[rocksndiamonds] 01/09: New upstream version 4.0.0.1+dfsg

Stephen Kitt skitt at moszumanska.debian.org
Tue Jan 17 21:58:12 UTC 2017


This is an automated email from the git hooks/post-receive script.

skitt pushed a commit to branch master
in repository rocksndiamonds.

commit a6b374cb96cefa7950d8ef40d77bf785e63ee834
Author: Stephen Kitt <steve at sk2.org>
Date:   Tue Jan 17 12:52:42 2017 +0100

    New upstream version 4.0.0.1+dfsg
---
 ChangeLog                                  |  673 ++-
 INSTALL                                    |   98 +-
 Makefile                                   |  112 +-
 README                                     |  340 --
 build-scripts/create_element_defs.pl       | 2645 +++++++++
 docs/elements/amoeba_dry.txt               |   12 +-
 docs/elements/amoeba_full.txt              |    8 +-
 docs/elements/amoeba_wet.txt               |   10 +-
 docs/elements/bd_amoeba.txt                |   14 +-
 docs/elements/bd_butterfly.txt             |   12 +-
 docs/elements/bd_firefly.txt               |    8 +-
 docs/elements/bd_magic_wall.txt            |   14 +-
 docs/elements/bd_wall.txt                  |   12 +-
 docs/elements/bug.txt                      |   10 +-
 docs/elements/char_space.txt               |    8 +-
 docs/elements/custom.txt                   |   12 +-
 docs/elements/dc_magic_wall.txt            |   16 +-
 docs/elements/dynabomb_increase_number.txt |   16 +-
 docs/elements/dynabomb_increase_power.txt  |   16 +-
 docs/elements/dynabomb_increase_size.txt   |   14 +-
 docs/elements/em_gate_1_gray.txt           |   14 +-
 docs/elements/em_gate_2_gray.txt           |   14 +-
 docs/elements/em_gate_3_gray.txt           |   14 +-
 docs/elements/em_gate_4_gray.txt           |   14 +-
 docs/elements/emc_gate_5_gray.txt          |   14 +-
 docs/elements/emc_gate_6_gray.txt          |   14 +-
 docs/elements/emc_gate_7_gray.txt          |   14 +-
 docs/elements/emc_gate_8_gray.txt          |   14 +-
 docs/elements/empty_space.txt              |    6 +-
 docs/elements/expandable_wall.txt          |   12 +-
 docs/elements/game_of_life.txt             |   18 +-
 docs/elements/invisible_sand.txt           |    6 +-
 docs/elements/invisible_steelwall.txt      |    8 +-
 docs/elements/invisible_wall.txt           |    6 +-
 docs/elements/magic_wall.txt               |   16 +-
 docs/elements/robot_wheel.txt              |   14 +-
 docs/elements/satellite.txt                |   12 +-
 docs/elements/shield_deadly.txt            |   14 +-
 docs/elements/sokoban_field_empty.txt      |   12 +-
 docs/elements/sokoban_field_full.txt       |   12 +-
 docs/elements/sokoban_field_player.txt     |   10 +-
 docs/elements/sp_base.txt                  |    6 +-
 docs/elements/spaceship.txt                |    8 +-
 docs/elements/switchgate_switch.txt        |    4 +-
 docs/elements/timegate_switch.txt          |    4 +-
 docs/elements/yamyam.txt                   |   16 +-
 rocksndiamonds.1                           |  245 -
 src/Makefile                               |  184 +-
 src/anim.c                                 | 1265 +++++
 src/anim.h                                 |   21 +
 src/cartoons.c                             |   95 -
 src/cartoons.h                             |   19 -
 src/conf_act.c                             |   22 +-
 src/conf_chr.c                             |  322 +-
 src/conf_chr.h                             |   22 +-
 src/conf_cus.c                             | 1046 ++--
 src/conf_cus.h                             |   22 +-
 src/conf_e2g.c                             |   22 +-
 src/conf_e2s.c                             |   22 +-
 src/conf_esg.c                             |   22 +-
 src/conf_fnt.c                             |   54 +-
 src/conf_g2m.c                             |   26 +-
 src/conf_g2s.c                             |   26 +-
 src/conf_gfx.c                             | 3563 ++++++++----
 src/conf_gfx.h                             |  499 +-
 src/conf_grp.c                             |  150 +-
 src/conf_grp.h                             |   22 +-
 src/conf_hlp.c                             |   22 +-
 src/conf_mus.c                             |   23 +-
 src/conf_mus.h                             |   73 +-
 src/conf_snd.c                             |   56 +-
 src/conf_snd.h                             |   89 +-
 src/conf_var.c                             | 8372 +++++++++++++++++++---------
 src/config.c                               |  116 +-
 src/config.h                               |   27 +-
 src/conftime.h                             |    1 +
 src/editor.c                               | 3266 ++++++-----
 src/editor.h                               |   22 +-
 src/engines.h                              |   37 +-
 src/events.c                               | 1536 +++--
 src/events.h                               |   34 +-
 src/files.c                                | 2812 ++++------
 src/files.h                                |   26 +-
 src/game.c                                 | 4025 ++++---------
 src/game.h                                 |  136 +-
 src/game_em/Makefile                       |   12 +-
 src/game_em/cave.c                         |   24 +-
 src/game_em/convert.c                      |  130 +-
 src/game_em/export.h                       |   14 +-
 src/game_em/game_em.h                      |   22 +-
 src/game_em/global.h                       |   11 +-
 src/game_em/graphics.c                     |  575 +-
 src/game_em/init.c                         |  298 +-
 src/game_em/input.c                        |   66 +-
 src/game_em/level.h                        |    6 -
 src/game_em/main_em.h                      |   57 +-
 src/game_em/sample.h                       |   12 +-
 src/game_em/sound.c                        |  511 --
 src/game_em/synchro_1.c                    |  218 +-
 src/game_em/synchro_2.c                    |  107 +-
 src/game_em/synchro_3.c                    |   18 -
 src/game_em/tab_generate.c                 |   76 +-
 src/game_em/ulaw_generate.c                |  129 -
 src/game_sp/BugsTerminals.c                |    6 +-
 src/game_sp/BugsTerminals.h                |    4 -
 src/game_sp/DDScrollBuffer.c               |  181 +-
 src/game_sp/DDScrollBuffer.h               |   16 +-
 src/game_sp/DDSpriteBuffer.c               |   10 +-
 src/game_sp/Display.c                      |    6 +-
 src/game_sp/Display.h                      |    6 +-
 src/game_sp/DoGameStuff.c                  |   18 +-
 src/game_sp/DoGameStuff.h                  |    5 -
 src/game_sp/Explosions.c                   |   28 +-
 src/game_sp/Globals.c                      |   52 +-
 src/game_sp/Globals.h                      |   23 +-
 src/game_sp/Infotrons.c                    |   11 -
 src/game_sp/MainForm.c                     |   45 +-
 src/game_sp/MainGameLoop.c                 |   24 -
 src/game_sp/Makefile                       |   16 +-
 src/game_sp/Murphy.c                       |  185 +-
 src/game_sp/SnikSnaks.c                    |    2 -
 src/game_sp/Zonk.c                         |    4 -
 src/game_sp/export.h                       |   28 +-
 src/game_sp/file.c                         |  126 +-
 src/game_sp/game_sp.h                      |   22 +-
 src/game_sp/init.c                         |  193 +-
 src/game_sp/main.c                         |   22 +-
 src/game_sp/main_sp.h                      |   41 +-
 src/game_sp/vb_lib.c                       |   16 +-
 src/game_sp/vb_lib.h                       |    6 +-
 src/init.c                                 | 1860 +++---
 src/init.h                                 |   27 +-
 src/libgame/Makefile                       |   17 +-
 src/libgame/android.h                      |   18 +
 src/libgame/gadgets.c                      |  229 +-
 src/libgame/gadgets.h                      |   94 +-
 src/libgame/hash.c                         |   22 +-
 src/libgame/hash.h                         |   22 +-
 src/libgame/image.c                        | 1006 +---
 src/libgame/image.h                        |  107 +-
 src/libgame/joystick.c                     |  109 +-
 src/libgame/joystick.h                     |   29 +-
 src/libgame/libgame.h                      |   24 +-
 src/libgame/macosx.h                       |   28 +-
 src/libgame/misc.c                         | 1837 ++++--
 src/libgame/misc.h                         |  180 +-
 src/libgame/msdos.c                        | 1002 ----
 src/libgame/msdos.h                        |  760 ---
 src/libgame/pcx.c                          |  316 --
 src/libgame/pcx.h                          |   37 -
 src/libgame/platform.h                     |   46 +-
 src/libgame/random.c                       |   44 +-
 src/libgame/random.h                       |   24 +-
 src/libgame/sdl.c                          | 1619 ++++--
 src/libgame/sdl.h                          |  182 +-
 src/libgame/setup.c                        |  978 ++--
 src/libgame/setup.h                        |   40 +-
 src/libgame/snapshot.c                     |  255 +-
 src/libgame/snapshot.h                     |   43 +-
 src/libgame/sound.c                        | 1388 +----
 src/libgame/sound.h                        |   57 +-
 src/libgame/system.c                       | 1095 ++--
 src/libgame/system.h                       |  517 +-
 src/libgame/text.c                         |  456 +-
 src/libgame/text.h                         |   66 +-
 src/libgame/toons.c                        |  425 --
 src/libgame/toons.h                        |   64 -
 src/libgame/types.h                        |   23 +-
 src/libgame/windows.h                      |   22 +-
 src/libgame/x11.c                          |  526 --
 src/libgame/x11.h                          |  356 --
 src/main.c                                 |  357 +-
 src/main.h                                 |  665 ++-
 src/netserv.c                              |  202 +-
 src/netserv.h                              |   25 +-
 src/network.c                              |  183 +-
 src/network.h                              |   22 +-
 src/screens.c                              | 3695 +++++++-----
 src/screens.h                              |   29 +-
 src/tape.c                                 | 1018 ++--
 src/tape.h                                 |  180 +-
 src/tools.c                                | 5320 +++++++++---------
 src/tools.h                                |   96 +-
 183 files changed, 33077 insertions(+), 30735 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index db17bdf..00eea69 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,530 @@
+2015-06-21
+	* extended automatic tape playing modes:
+	  - "autotest" to automatically test tapes (this was "autoplay" before)
+	  - "autoplay" to automatically play tapes (visibly)
+	  - "autoffwd" to automatically play tapes (visibly, with maximum speed)
+
+2015-06-16
+	* fixed and enhanced screen fading and background/border handling
+
+2015-05-31
+	* added setup option to enable/disable (now optional) snapshot buttons
+
+2015-04-22
+	* added lag prevention to door/request/envelope animations
+
+2015-04-15
+	* added option "program_icon_file" to run-time "special edition" support
+
+2015-04-14
+	* added run-time "special edition" support;
+	  this change is especially targeted to the "R'n'D jue" special edition
+	  of R'n'D, which changed some defaults at compile-time in previous
+	  versions, like:
+	  - using a different default artwork set (with fallback artwork for
+	    classic artwork not existing in the special edition),
+	  - using a different default level set,
+	  - using a different program name and user data directory,
+	  - starting with different default setup values and
+	  - using custom artwork even at a very early stage of startup
+	    (like initial fonts and initial loading/busy animation);
+	  these changes can now all be accomplished at run-time by using a new
+	  program-specific configuration file in the same location and with the
+	  same name as the game binary (minus a potential binary file extension
+	  ".exe", plus a configuration file extension ".conf", so a binary file
+	  "rnd_jue.exe" would be complemented by a new file "rnd_jue.conf" in
+	  the same directory);
+	  this config file can contain all options found in "setup.conf" plus
+	  the following new, internal "special edition" default settings:
+	  - program_title (like "R'n'D jue")
+	  - program_author (like "Juergen Bonhagen")
+	  - program_email (like "jue at artsoft.org")
+	  - program_website (like "http://jue.artsoft.org/")
+	  - program_copyright (like "(c) 2015 by jue")
+	  - program_company (like "A game by jue")
+	  - default_graphics_set (like "jue0")
+	  - default_sounds_set (like "jue0")
+	  - default_music_set (like "jue0")
+	  - fallback_graphics_file (like "fallback.png")
+	  - fallback_sounds_file (like "fallback.wav")
+	  - fallback_music_file (like "fallback.wav")
+	  - default_level_series (like "jue_start")
+	  - choose_from_top_leveldir ("true" or "false")
+	  where the "default" artwork set definitions are used to specify new
+	  default artwork that replaces the "classic" artwork sets, while the
+	  "fallback" settings specify artwork files used for all artwork files
+	  that would exist in the classic artwork sets, but are not defined or
+	  cannot be found in the new default artwork set; the program title is
+	  used for things like window title, title screens and user data folder
+	  name, and the entry point for choosing a level set can be changed
+	  from the current level set location to the topmost level tree node
+
+2015-04-07
+	* added sound definitions for pressing and releasing main menu buttons
+
+2015-03-31
+	* fixed slow tape quick-loading due to unneeded tape area update
+
+2015-03-30
+	* replaced stop/play buttons in game panel with save/load buttons
+
+2015-03-24
+	* added step-based engine snapshots to undo/redo single steps in game
+
+2015-03-19
+	* fixed (swapped) editor zoom directions for '-' and '+' (keypad) keys
+
+2015-03-18
+	* added dynamically configurable graphics and layout of editor gadgets
+
+2015-03-11
+	* fixed (swapped) editor zoom directions for left and right mouse button
+
+2015-03-10
+	* added main menu backlink to level set selection screen
+
+2015-03-07
+	* added support for gadget-like pressable menu buttons on main screen
+
+2015-03-02
+	* added classic graphics, sounds and music to git repository
+	* added classic level sets to git repository
+	* added element description files to git repository
+	* changed mouse cursor on title screens not being always invisible
+	* added manually edited non-preset audio volume values to select list
+	  (if sound, loops or music volume was manually edited in "setup.conf")
+
+2015-02-27
+	* fixed using "background.TOOLBOX", which was simply ignored before
+
+2015-02-23
+	* added key pad '-', '+' and '0' keys to zoom function in level editor
+	* changed editor key shortcut for undo/redo to 'u' and 'Shift-u'
+	* fixed using 'PageUp' and 'PageDown' keys for element list in editor
+
+2015-02-21
+	* added 1%, 2% and 5% to volume controls for sound and music settings
+
+2015-02-14
+	* fixed bug with editor border element not adjusted after resizing level
+	* changed unused playfield from "default" to "empty" after loading level
+	* increased number of undo/redo steps in level editor from 10 to 64
+
+2015-02-13
+	* added zoom functionality for playfield drawing area to level editor
+	  (use left, right and middle mouse buttons on new "zoom" toolbox button
+	  or use keys '-', '+' and '0' to zoom out, in or reset to default size)
+
+2015-02-11
+	* fixed bug not updating game panel values in visible warp forward mode
+
+2015-02-10
+	* changed position of CE/GE use/save template gadgets to be visually
+	  separated from other CE/GE gadgets (to prevent accidental use)
+	* fixed bug in editor when using undo after rotating level repeatedly
+	* added 'redo' functionality to editor (by pressing 'undo' with right
+	  mouse button or by using key shortcut "Shift-R")
+
+2015-02-04
+	* added configurability of editor control buttons (toolbox buttons)
+
+2015-02-03
+	* finished configurability of tape date and time display positions
+	* fixed bug with game buttons in tape area not properly redrawn
+	* fixed small graphical bug with default tape time display position
+	* added optionally configurable game frame counter to tape display
+
+2015-02-02
+	* fixed configurability of editor element palette (for columns != 4)
+
+2015-01-29
+	* improved configurability of tape date and time display positions
+	* added configurability of element properties button in editor
+	* added build dependency for auto-conf files
+
+2015-01-27
+	* added looking for editor element descriptions in level set directory
+	  (for example, in file "<my-level-folder>/docs/elements/custom_1.txt")
+
+2015-01-25
+	* moved "element properties" button in editor from toolbox to palette
+	* added "zoom level tile size" button in editor to toolbox (currently
+	  no function behind it; will be used to zoom level editor playfield)
+	* added key shortcuts '1' to '3' to view properties of drawing elements
+	* fixed gadget display bug in editor (door 1 area) after test playing
+	* fixed bugs when changing drawing area gadgets (like group elements)
+
+2015-01-19
+	* re-enabled editor palette element options in setup configuration file
+
+2014-12-13
+	* fixed loading custom PCX image files with default artwork file names
+	  (like "RocksDoor.pcx") which are not redefined in artwork config file
+	  (this is a special fix for Zelda 2 and probably some other existing
+	  level sets which use new graphics which are not defined in the file
+	  "graphicsinfo.conf", but use a file name of one of default graphics
+	  (like "RocksScreen.pcx"); this did not work anymore for PCX files
+	  since the default graphics files have been changed to PNG files, so
+	  different file names are checked now (like "RocksScreen.png"), so if
+	  the PNG files cannot be found, the old PCX files are also checked)
+
+2014-12-03
+	* added some more graphics customization options for the level editor:
+	  - editor.button.prev_level (position)
+	  - editor.button.next_level (position)
+	  - editor.input.level_number (position)
+	  - editor.palette.tile_size (tile size for palette elements)
+	  - editor.palette.element_left.tile_size (draw element tile size)
+	  - editor.palette.element_middle.tile_size (draw element tile size)
+	  - editor.palette.element_right.tile_size (draw element tile size)
+	  - editor.input.gfx.level_number (current level number input field)
+
+2014-11-22
+	* fixed menu display bugs caused by drawing outside menu area (again)
+
+2014-11-19
+	* fixed broken door animations when switching between custom graphics
+
+2014-11-06
+	* fixed layout for "level set info" to support custom playfield size
+	* fixed changing from title to info screen with custom playfield size
+
+2014-11-02
+	* fixed bug with not updating default bitmap pointer for scaled images
+	* fixed redraw/fade bugs when redefining the playfield size or position
+
+2014-10-27
+	* fixed some smaller issues with loading custom artwork
+
+2014-10-22
+	* added warnings when using undefined element and graphic names in
+	  custom artwork definitions (like ".crumbled_like" or ".clone_from")
+	* added setting default filenames for all cloned graphics in static
+	  graphics configuration on startup (to be able to fall back later)
+
+2014-10-20
+	* fixed using buttons on main screen with size other than 32x32 pixels
+	* fixed some initialization bugs for scrollbars and main screen buttons
+	* fixed bug when drawing non-element graphics (without separate in-game
+	  graphic/bitmap defined) while non-standard game tile size is defined
+
+2014-10-17
+	* removed some remaining unused X11 stuff
+	* fixed bug with potentially suppressed exit error message on startup
+
+2014-10-16
+	* fixed bug not loading tape when selecting level from level selection
+	  screen (thanks to filbo for finding this bug and supplying a patch)
+
+2014-10-15
+	* fixed menu display bugs (drawing outside menu area with draw offset)
+	* fixed menu key navigation bugs (when using smaller menu list size)
+
+2014-10-14
+	* added support for animated door parts during opening/closing movement
+
+2014-10-13
+	* added automatic detection of normal/steel character elements in level
+	  editor when drawing text (depending on currently selected element)
+
+2014-10-13
+	* eliminated historical ISO-8859-1 characters from source code files
+	  (but still using them internally for special character encodings)
+	* changed output of special character for level sketch brushes to UTF-8
+
+2014-10-08
+	* added handling of unselectable selectbox options and option headlines
+
+2014-10-07
+	* fixed bug when changing between graphic sets with different tile size
+	* cleanup of handling the various graphic sizes for different purposes
+	  (like 32x32, 16x16 etc.); this change was needed for the bugfix above
+
+2014-10-02
+	* added virtual keyboard on Android port when entering player name
+
+2014-10-01
+	* fixed "quick menu doors" and sounds for door and envelope requests
+
+2014-09-29
+	* fixed display bugs with certain custom menu definitions regarding the
+	  hall of fame (high scores) and setup screens that require scrolling
+	  (these display bugs showed up with custom menu graphics of R'n'D jue)
+
+2014-09-28
+	* fixed bug with animation frames per line with non-standard tile size
+	  (relevant for example for 64x64 sized frames continued on next row)
+
+2014-09-22
+	* removed checking of file identifier tokens for configuration files
+
+2014-09-19
+	* fixed bug where player actions were only mapped in team mode
+	  (this broke four tapes in automatic game engine unit test where
+	  old levels contained a non-yellow player, like rnd_abby_king, 011)
+
+2014-09-15
+	* removed large parts of the preprocessor hell of old and unused code
+
+2014-09-14
+	* updated source file headers (mainly author contact information)
+
+2014-09-11
+	* added key shortcuts for window scaling and toggling fullscreen mode:
+	  - Ctrl-'+', Ctrl-'-' and Ctrl-'0' for up/downscaling and normal size
+	  - "F11" key for toggling fullscreen mode (in addition to Alt-Enter)
+
+2014-09-10
+	* fixed some drawing bugs when scaling graphics due to "game.tile_size"
+	* added some performance improvements when handling SDL surface scaling
+
+2014-09-04
+	* added custom graphics property "game.tile_size" to define in-game tile
+	  size (this defines the tile size actually displayed on the playfield);
+	  tile graphics will either be scaled to the defined game tile size or
+	  have to be specified with the same image size (using ".tile_size")
+
+2014-09-01
+	* added custom graphics property ".tile_size" to define tile image size
+	  for game element graphics (like "custom_1.tile_size"); non-standard
+	  sized images will then be scaled accordingly to standard tile size
+
+2014-08-30
+	* fixed music still being played in Android version when in background
+
+2014-08-30
+	* added Android "menu" button to be treated as "yes" requester button
+	  (while the Android "back" button was already treated as "no" button)
+
+2014-08-28
+	* added command line options "--version" / "-V" to show program version
+	  (also shows SDL library versions when prefixed with "--debug" option)
+
+2014-08-27
+	* error file set to unbuffered to prevent truncation in case of crashes
+
+2014-08-19
+	* fixed bug causing wrong screen updates while playing (whole screen
+	  update from backbuffer instead of playfield buffer if REDRAW_ALL set)
+	* fixed nasty (typo) bug in native EM engine causing broken player
+	  graphics when using different (redefined) playfield size
+
+2014-08-18
+	* fixed bug causing EM/EMC graphics sets containing original 16x16 tiles
+	  to be displayed incorrectly (with broken scaling) when switching
+	  between small and normal game graphics (thanks a lot to filbo for
+	  analyzing and describing how to exactly reproduce this bug)
+
+2014-05-15
+	* removed MS-DOS support
+	* removed native X11 support (X11 now only supported via SDL/SDL2)
+
+2014-05-14
+	* cleanup of functions RedrawPlayfield() and BlitScreenToBitmap()
+
+2014-05-13
+	* fixed level redraw after quick-loading tape with small tile graphics
+
+2014-03-03
+	* added compatibility code for existing request door animation settings
+
+2014-03-01
+	* added ultra-generic, ultra-flexible request door animation handling
+
+2014-02-18
+	* fixed major bugs in handling single-player and multi-player tapes
+	  (for details, see http://www.artsoft.org/forum/viewtopic.php?t=2086)
+
+2014-02-13
+	* fixed various problems with playfield and requester/tape/editor doors
+	  defined to be at non-standard screen positions in artwork config file
+
+2014-01-28
+	* added envelope style requester dialog (alternative to door requester)
+
+2014-01-27
+	* fixed problems with window scaling and updating related setup value
+	* added setup option to select anti-aliasing quality of scaled windows
+
+2014-01-17
+	* improved speed of displaying progress when loading levels and artwork
+	* changed fullscreen and window scaling changes in setup menu to have
+	  immediate effect (instead of being effective after leaving setup menu)
+
+2014-01-15
+	* fixed toons stopping on continuous touch events on Mac OS X
+
+2014-01-14
+	* fixed bug when displaying game envelope with even sized playfield
+	* added graphic configuration options for request (dialog) buttons
+
+2014-01-13
+	* fixed some redraw bugs with window scaling under Mac OS X
+
+2014-01-10
+	* fixed problems with window scaling and updating related setup value
+
+2014-01-07
+	* fixed problems related to fullscreen switching and window scaling
+
+2014-01-06
+	* fixed inconsistent custom artwork constants numbering in src/main.h,
+	  src/screen.c and src/conf_gfx.c (this really should be cleaned up)
+	  (this bug caused custom artwork definition to set wrong variable)
+
+2014-01-05
+	* fixed using fullscreen mode on Android instead of pseudo-window mode
+	* fixed keeping desktop fullscreen mode when changing viewport size
+
+2014-01-04
+	* fixed remaining text input problems for non-ASCII keys with modifier
+	* added window scaling options to graphics setup menu
+
+2014-01-03
+	* fixed key code problems with certain keys for SDL2
+	  (keypad keys not being in numerical order; number of function keys)
+	* fixed text input problems for text characters using modifier keys
+
+2014-01-02
+	* fixed fullscreen option for SDL2 (using only desktop fullscreen now)
+
+2013-12-28
+	* fixed graphical bugs when using renderer/texture based graphics
+
+2013-12-23
+	* fixed playing certain sounds (menu navigation sound and counting
+	  score sound after solving a level) when "normal sounds" are disabled
+
+2013-12-16
+	* continued porting Rocks'n'Diamonds to Android (levels now playable)
+
+2013-12-12
+	* added SDL2 renderer/texture based graphics frame handling to allow for
+	  "desktop" style fullscreen mode and scaling of game screen/window
+
+2013-12-11
+	* removed limitation of artwork files to selected file types (this means
+	  that every file type supported by SDL_image and SDL_mixer can be used)
+	* changed default graphics from PCX to PNG (needed for Android version
+	  to prevent painfully slow image loading, although not compressing PCX
+	  files in the assets directory of the APK package might also work fine)
+	* fixed bug with SDL_BlitSurface creating garbage when source and target
+	  surface are the same (this bug also existed in versions of SDL 1.2.x)
+
+2013-12-07
+	* started porting Rocks'n'Diamonds to Android (already shows main menu)
+
+2013-12-03
+	* ported Rocks'n'Diamonds to SDL2 (first simple version that works)
+
+2013-12-01
+	* version number set to 3.3.1.3
+
+2013-11-24
+	* version 3.3.1.2 released
+
+2013-11-20
+	* improved error handling: display error message on screen (not only in
+	  the error file or on the console), and display path of the error file
+
+2013-11-13
+	* fixed problem with R'n'D restarting with same level set that may have
+	  caused a problem (and therefore failing again and again); after an
+	  error, the last level set is now deactivated in file "levelsetup.conf"
+	  to restart with default level set (which should work without error)
+
+2013-11-07
+	* fixed determining main game data directory on Mac OS X "Mavericks"
+
+2013-11-04
+	* version number set to 3.3.1.2
+
+2013-11-04
+	* version 3.3.1.1 released
+
+2013-11-03
+	* added scripts directory to distribution package to enable building
+	  element definitions after editing artwork config source code files
+
+2013-10-26
+	* added volume controls for sounds, loops and music to sound setup
+
+2013-10-24
+	* version number set to 3.3.1.1
+
+2013-10-23
+	* version 3.3.1.0 released
+
+2013-10-21
+	* version number set to 3.3.1.0
+
+2012-10-13
+	* fixed display of level time switching from ascending to descending
+	  when making use of the "time orb bug" (see element setting in editor)
+	  (see level 053 of set "rnd_equinox_tetrachloride_ii" for an example)
+	* fixed graphics performance problems (especially on Mac OS X) by using
+	  whole-playfield redraw on SDL target, while still using the previous
+	  single-tile redraw method on X11 target (using redraw tiles threshold)
+
+2011-10-07
+	* fixed code (esp. random/tape handling) when compiled on 64-bit systems
+	  (by replacing all "long" types by "int" types)
+
+2010-11-19
+	* fixed nasty bug (affecting crumbled graphics) after adding new special
+	  graphics suffix ".TAPE" (and messing some things up in src/main.c)
+
+2010-08-04
+	* fixed wrong argument order in DrawTextBuffer() in gadgets.c
+	  (this caused fonts in envelope config in level editor being invisible)
+
+2010-07-19
+	* fixed some problems with half tile size and even tile sized playfields
+
+2010-07-12
+	* added level selection screen (when clicking on main menu level number)
+	* added level tracing (played, solved) for use in level selection screen
+	  (to display already played or solved levels in different font color)
+
+2010-06-24
+	* added alternative game mode for playing with half size playfield tiles
+	* fixed another memory violation bug in the native Supaplex game engine
+	  (this potential memory bug was also in the original Megaplex code, but
+	  apparently only occured under rare conditions triggered by using the
+	  additional added preceding playfield memory area to make a few strange
+	  levels using dirty off-playfield tricks (bugs) like "12s033.sp" also
+	  solvable (this all worked fine in the classic DOS version, of course))
+
+2010-06-23
+	* added graphics performance optimization to native Supaplex game engine
+	* fixed bug with accidentally removing preceding buffer in SP engine
+	* moved some editor graphics from "RocksDoor.pcx" to "RocksMore.pcx"
+	  (to prevent compatibility mapping of these newer graphics to older
+	  (custom) versions of "RocksDoor.pcx" which did not contain them yet)
+
+2010-06-18
+	* added separately configurable game panel background to graphics config
+	* fixed displaying Supaplex time (now based on 35 fps instead of 50 fps)
+
+2010-06-16
+	* added tape panel graphics and screen positions to graphics config
+
+2010-06-15
+	* added compatibility stuff for redefined "global.door" (which affects
+	  all parts of that image that have their own graphics definition now)
+
+2010-06-14
+	* added sound button graphics to graphics config
+
+2010-06-13
+	* added tape button graphics and screen positions to graphics config
+
+2010-06-09
+	* improved single step mode in R'n'D, EM and SP engines
+
+2010-06-08
+	* version number set to 3.3.0.2
+
 2010-06-08
 	* version 3.3.0.1 released
 
@@ -1686,8 +2213,8 @@
 	* fixed bug with not resetting push delay under certain circumstances
 
 2004-04-27
-	* added option "handicap" for "levelinfo.conf" (thanks to Niko B�hm)
-	* added network multiplayer code for Windows (thanks to Niko B�hm)
+	* added option "handicap" for "levelinfo.conf" (thanks to Niko Böhm)
+	* added network multiplayer code for Windows (thanks to Niko Böhm)
 
 2004-04-25
 	* added option "reachable despite gravity" for gravity movement
@@ -1860,7 +2387,7 @@
 	  (reported by Simon Forsberg)
 
 	* fixed bug which could cause an array overflow in RelocatePlayer()
-	  (reported by Niko B�hm)
+	  (reported by Niko Böhm)
 
 	* changed Emerald Mine style "passable / over" elements to "protected"
 	  (fixing unsolvable level 10 of "Bondmine 9" with bug beside gate)
@@ -2251,24 +2778,59 @@
 2002-12-31
 	* pre-release version 2.2.0rc1 released
 
+2002-08-25	src/libgame/setup.c, src/libgame/sound.c
+	* Level series artwork now configurable via level series config file.
+	  "levelinfo.conf" may now contain directives "graphics_set",
+	  "sounds_set" and "music_set" to select artwork sets which are
+	  globally defined or which are included into other level series.
+
 2002-08-25
 	* version number set to 2.1.2
 
 2002-08-13
 	* version 2.1.1 released
 
+2002-08-10	src/libgame/system.h
+	* Default "snap" and "bomb" keys for Mac OS X set to left control key
+	  and keypad enter key -- Macs seem not to distinguish between left
+	  and right modifier keys (both generate scan code for left key). :-(
+
+2002-08-10	src/libgame/sound.c
+	* Fixed small NetBSD compilation bug.
+	  Thanks to Adam Ciarcinski for the bug report.
+
+2002-08-10	src/libgame/sound.c
+	* Added support for audio device "/dev/sound/dsp" (devfs).
+	  Thanks to Christoph Bauer for the corresponding report.
+
+2002-08-10	src/libgame/sound.c
+	* Bug fixed that caused regular crashes under SDL/Windows version.
+	  Mixer_InsertSound(): Always stop music before playing new music,
+	  else "mixer_active_channels" can get fucked up.
+	  Thanks to Keith Peterston for the bug report.
+
 2002-08-10
 	* version number set to 2.1.1
 
 2002-08-05
 	* version 2.1.0 released
-	
+
+2002-05-31	src/libgame/image.c
+	* Read_PCX_to_Pixmap(): Fixed bad memory leak by freeing "ximageinfo"
+	  and "image" after converting loaded PCX image file to X11 Pixmap.
+	  This really showed up when reloading custom artwork several times.
+
+2002-05-20	src/libgame/sound.c
+	* added support for 16 bit WAV sound files
+
 2002-05-19
 	* version number set to 2.1.0
 
 2002-04-03 to 2002-05-19	(various source files)
 	* graphics, sounds and music now fully configurable
 	* bug fixed that prevented walking through tubes when gravity on
+	* added support for TrueColor PCX graphics files
+	* enhanced sound system (especially regarding stereo and loop sounds)
 
 2002-04-02	src/events.c, src/editor.c
 	* Make Escape key less aggressive when playing or when editing level.
@@ -2288,6 +2850,16 @@
 	  automatically gets created by "src/Makefile" and contains an actual
 	  compile-time timestamp to identify development versions of the game).
 
+2002-04-01	src/libgame/misc.c
+	* Added (currently incomplete) function "getKeyFromKeyName()" simply
+	  for orthogonality. When really needed, this function must be
+	  extended accordingly (analog to "getKeyFromX11KeyName()").
+
+2002-04-01	src/libgame/setup.c
+	* Changed setup "TYPE_KEY" (internal, X11 style key symbol name) to
+	  "TYPE_KEY_X11" and added "TYPE_KEY" (human readable key symbol name).
+	  (This was needed for custom key setup handling in "src/screens.c".)
+
 2002-03-31	src/tape.c, src/events.c
 	* Added quick game/tape save/load functions to tape stuff which can be
 	  invoked by a keyboard shortcut. Default: "F1" saves game/tape, "F2"
@@ -2306,10 +2878,32 @@
 2002-03-30	src/cartoons.c
 	* Moved some stuff from cartoons.c to the new "src/libgame/toons.c".
 
+2002-03-30	src/libgame/toons.c
+	* New libgame source file "toons.c" for the program independant part
+	  of the toon stuff.
+
 2002-03-29	src/screen.c
 	* Changed setup screen stuff to be more generic (to make it easier
 	  to add more setup screens).
 
+2002-03-29	src/libgame/setup.c
+	* Changed "LoadLevelInfoFromLevelDir()" so that not only directories
+	  with level sub-directories are recognized, but also directories
+	  that directly contain level files.
+
+2002-03-29	src/libgame/sound.c
+	* Changed "boolean stereo = TRUE;" to "static boolean stereo = TRUE;".
+	  (This was a bug that showed up only when in mono audio mode.)
+
+2002-03-24	src/libgame/x11.c, src/libgame/sdl.c, src/libgame/image.c
+	* Changed image loading code to not exit on error, but set error by
+	  using "SetError()" accordingly. Image loading errors must now be
+	  catched by above layers (src/init.c for example).
+
+2002-03-24	src/libgame/misc.c
+	* New functions "SetError()" and "GetError()" to provide more
+	  flexible error handling.
+
 2002-03-23	src/main.c, src/main.h
 	* Various changes due to the introduction of the new libgame files
 	  "setup.c" and "joystick.c".
@@ -2322,6 +2916,18 @@
 	* File "src/joystick.c" moved to libgame source tree, with
 	  correspondig changes.
 
+2002-03-23	src/libgame/system.c, src/libgame/system.h
+	* Various changes due to the introduction of the new files "setup.c"
+	  and "joystick.c".
+
+2002-03-23	src/libgame/setup.c
+	* New libgame source file "setup.c" that contains now most setup and
+	  level directory stuff previously handled in "src/files.c".
+
+2002-03-23	src/libgame/joystick.c
+	* New libgame source file "joystick.c" that contains now all joystick
+	  stuff previously handled in "src/joystick.c" of "Rocks'n'Diamonds".
+
 2002-03-22	src/screens.c
 	* "HandleChooseLevel()": Another bug in level series navigation fixed.
 	  (Wrong level series information displayed when entering main group.)
@@ -2334,6 +2940,19 @@
 	  intuitive: When in "Element Properties" or "Level Info" mode,
 	  return to "Drawing Mode" instead of leaving the level editor.
 
+2002-03-22	src/libgame/misc.c, src/libgame/sound.c
+	* Added command line option "-s" / "--sounds" and "-m" / "--music"
+	  to specify alternative sound and music directories. (The former
+	  shortcut "-s" for "--serveronly" has changed accordingly.)
+
+2002-03-22	src/libgame/gadgets.c
+	* Added new gadget events for displaying gadget info texts:
+	  "GD_EVENT_INFO_ENTERING" and "GD_EVENT_INFO_LEAVING". Before,
+	  the info text callback function was only called when entering
+	  a gadget (implicit "GD_EVENT_INFO_ENTERING"). But the info text
+	  was never erased. This can now be done by checking the event type
+	  in the info callback function.
+
 2002-03-21	src/game.c, src/editor.c, src/files.c
 	* 2.0.1 introduced the corrected "Emerald Mine" style behaviour of
 	  gems (emeralds, diamonds, ...) slipping down from normal wall,
@@ -2362,12 +2981,29 @@
 	  compiling the SDL version on some systems.
 	  Thanks to the several people who pointed this out.
 
+2002-03-20	src/libgame/gadgets.c
+	* "va_arg(ap, boolean)" changed to "(boolean)va_arg(ap, int)";
+	  this caused problems especially on PowerPC architecture (although
+	  it is wrong on i386 and other architectures, too)
+
+2002-03-20	src/libgame/pcx.c, src/libgame/image.c
+	* Added support for loading and displaying true-color PCX files.
+
+2002-03-20	src/libgame/misc.c, src/libgame/x11.c
+	* Added command line option "-g" / "--graphics" to specify an
+	  alternative graphics directory.
+
 2002-03-19
 	* Version number set to 2.0.2.
 
 2002-03-19
 	* Version 2.0.1 released.
 
+2002-03-19	src/libgame/system.c, src/libgame/sdl.c [src/tools.c]
+	* Moved function "GetPixel()" from src/tools.c ("Mirror Magic" code)
+	  to libgame source files; needed for SDL fullscreen bug workaround
+	  to work correctly.
+
 2002-03-18	src/screens.c
 	* "HandleChooseLevel()": Small bug in level series navigation fixed.
 
@@ -2379,6 +3015,14 @@
 	  score files) according to suggestions of Debian users and mantainers.
 	  Thanks to Drew Parsons <dparsons at emerall.com> for the patch.
 
+2002-03-18	src/libgame/misc.c [src/files.c]
+	* Moved some common functions from src/files.c to src/libgame/misc.c.
+
+2002-03-18	src/libgame/misc.c [src/files.c]
+	* Changed permissions for new directories and saved files (especially
+	  score files) according to suggestions of Debian users and mantainers.
+	  Thanks to Drew Parsons <dparsons at emerall.com> for the patch.
+
 2002-03-17	src/files.c
 	* Changed "{Load|Save}{Level|Tape}()" to IFF style file format:
 	  Replaced "cookie" header string ("ROCKSNDIAMONDS_...\n") with
@@ -2392,11 +3036,27 @@
 	  file, and "file version" is a version number to distinguish files
 	  with different format, for example after adding new features).
 
+2002-03-17	src/libgame/sound.c
+	* Bug in "StopMusic()" fixed: SDL_mixer functions may be called
+	  even when sound not available.
+	  Thanks to Drew Parsons <dparsons at emerall.com> for the patch.
+
 2002-03-15	src/screen.c
 	* "DrawHallOfFame()": "FadeSounds()" when entering the hall of fame.
 	  (Before, you heard a mixture of the in-game music and the
 	  hall-of-fame music.)
 
+2002-03-15	src/libgame/sound.c, src/libgame/platform.h
+	* Added /dev/dsp (streaming audio) support for NetBSD (instead of the
+	  /dev/audio (ulaw) based Unix audio interface).
+	  Thanks to Krister Walfridsson <cato at df.lth.se> for the patches.
+
+2002-03-15	src/libgame/sdl.c
+	* Workaround for fullscreen bug in WIN32 version of SDL (at least
+	  in the currently actual version 1.2.3) by using "standard" screen
+	  resolutions like 800x600 and mapping all input (mouse events) and
+	  output (screen drawing) accordingly.
+
 2002-03-14	src/events.c
 	* Function "DumpTape()" (files.c) now available by pressing 't' from
 	  main menu (when in DEBUG mode).
@@ -2455,6 +3115,11 @@
 	* Fixed problem (introduced after 2.0.0 release) with penguins
 	  not getting killed by enemies
 
+2002-02-28	src/libgame/sound.c
+	* Fixed small problem with new SDL_Mixer 1.2.1:
+	  Mix_VolumeMusic() must be called _after_ Mix_PlayMusic(),
+	  or it has no effect.
+
 2002-02-24	src/game.c, src/main.h
 	* Added "player->is_moving"; now "player->last_move_dir" does
 	  not contain any information if the player is just moving at
diff --git a/INSTALL b/INSTALL
index d014b7a..bdca6cb 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,88 +1,36 @@
+===============================================================================
+Compiling and installing Rocks'n'Diamonds
+===============================================================================
 
-Installation instructions for Rocks'n'Diamonds
-==============================================
+To compile the game, you either need the new SDL2 library (recommended) or the
+old SDL 1.2 library. In addition, you also need the libraries SDL_image,
+SDL_mixer (including the SMPEG library if you want MP3 support) and SDL_net.
 
-Compilation
------------
+Please install these libraries before building Rocks'n'Diamonds.
 
-If your system supports Linux/i386/ELF/glibc executables (Linux package)
-or if you run DOS/Windows (DOS package), you can directly use the included
-precompiled binary.
 
-If you use a different system, just recompile the game:
+-------------------------------------------------------------------------------
+Linux and other Unix systems (including Mac OS X):
+-------------------------------------------------------------------------------
 
-If you use Linux with gcc or DOS or Windows 3.x with djgpp, just try 'make'
-which should work without problems.
+Just run "make" to build the game using either SDL2 or SDL (whatever being
+available).
 
-If you use SUN/Solaris with gcc and GNU make, try 'make solaris'.
+Run "make sdl" or "make sdl2" to explicitly use either SDL 1.2 or SDL2.
 
-To build the game with SDL support (needed for fullscreen and MOD support),
-type "make sdl". You need at least SDL version 1.1.x and the additional
-SDL libraries SDL_image and SDL_mixer. To get a recent version of the SDL
-library, see http://www.libsdl.org.
 
-If the above doesn't work, edit the Makefile in the top level directory.
-If it doesn't work either, edit the Makefile in the 'src' subdirectory.
+-------------------------------------------------------------------------------
+Windows with gcc (native or cross-compiling)
+-------------------------------------------------------------------------------
 
-If you had to modify any Makefile to compile it, please drop me a note
-about it to 'info at artsoft.org'. Thanks!
+To build the game natively, just proceed as described above for Unix systems.
 
+To cross-compile the game for Windows, run "cross-win32". You probably have to
+adjust the path to the Windows cross-compiler defined in "CROSS_PATH_WIN32" in
+the top-level Makefile.
 
-Customization
--------------
 
-The following configuration options in the top level Makefile help
-you to customize the game to your system and your environment:
+That's all!
 
-CC		Choose your favorite ANSI C compiler.
-		Default is 'gcc'.
-
-PLATFORM	Choose your platform, if auto detection fails.
-		Auto detection should work for Linux and DOS
-		(just type 'make'), on SUN/Solaris systems 'make solaris'
-		should work. Other systems may need additional editing
-		of 'src/Makefile' to set some additional compiler options.
-
-X11_PATH	Specify the path to your X11 installation. Include files
-		and libraries are searched for at $(X11_PATH)/include and
-		$(X11_PATH)/lib, if you set this variables. If you don't
-		set this variable, your compiler must be able to find X11
-		by itself, which works fine for Linux, for example.
-
-GAME_DIR	Specify the directory where the program looks for all the
-		graphics, sounds, levels and high scores. If you leave this
-		commented out, the current directory ('.') is used, which
-		lets you use the game without installing it somewhere in
-		your system (although you have to 'cd' to the game directory
-		each time you want to play it).
-
-JOYSTICK	Uncomment this line if your system does not support game
-		port hardware like joysticks (and has therefore no joystick
-		include file). Currently the game should work with joysticks
-		on Linux and FreeBSD.
-
-SOUNDS		Uncomment this line if your system does not support audio
-		hardware. Currently the game should work with sound support
-		on Linux, FreeBSD, SUN/Solaris, HP-UX and most Unix system
-		that support '/dev/dsp' or '/dev/audio' devices.
-
-SCORE_ENTRIES	Choose if you want to allow many entries in the high score
-		table for one player or exactly one entry. Systems with a
-		lot of users maybe want to limit high score entries to only
-		one entry for each player (and therefore set 'SCORE_ENTRIES'
-		to 'ONE_PER_NAME') where systems used by only one person
-		maybe want to use the default of 'MANY_PER_NAME' which is
-		automatically choosen if you leave everything commented out.
-
-Modifications of the Makefile in the directory 'src' are normally not needed.
-If the game fails to compile out of the box, you may have to modify some
-of the system variables there to get it to compile.
-
-SYSTEM		May need to be set to some system dependend values.
-
-INCL, LIBS	Maybe some more directories for include files and libraries
-		have to be added to this variables depending on your system.
-
-
-If you have any comments, additions or modifications to the Makefile(s),
-please send me mail: 'info at artsoft.org'. Thanks!
+If you have any comments, corrections or suggestions regarding the Makefiles,
+please let me know at "info at artsoft.org". Thanks!
diff --git a/Makefile b/Makefile
index 75fde6b..3e113fd 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,12 @@
 # =============================================================================
-# Rocks'n'Diamonds Makefile
+# Rocks'n'Diamonds - McDuffin Strikes Back!
 # -----------------------------------------------------------------------------
-# (c) 1995-2007 Holger Schemel <info at artsoft.org>
+# (c) 1995-2015 by Artsoft Entertainment
+#                  Holger Schemel
+#                  info at artsoft.org
+#                  http://www.artsoft.org/
+# -----------------------------------------------------------------------------
+# Makefile
 # =============================================================================
 
 # -----------------------------------------------------------------------------
@@ -16,18 +21,17 @@ CC = gcc
 # (this must be set to "gmake" for some systems)
 MAKE = make
 
-# path to X11 on your system
-X11_PATH = /usr/X11R6
-
 # directory for read-only game data (like graphics, sounds, levels)
+# (this directory is usually the game's installation directory)
 # default is '.' to be able to run program without installation
-# RO_GAME_DIR = /usr/games
+# RO_GAME_DIR = .
 # use the following setting for Debian / Ubuntu installations:
 # RO_GAME_DIR = /usr/share/games/rocksndiamonds
 
 # directory for writable game data (like highscore files)
+# (if no "scores" directory exists, scores are saved in user data directory)
 # default is '.' to be able to run program without installation
-# RW_GAME_DIR = /var/games
+# RW_GAME_DIR = .
 # use the following setting for Debian / Ubuntu installations:
 # RW_GAME_DIR = /var/games/rocksndiamonds
 
@@ -41,13 +45,9 @@ X11_PATH = /usr/X11R6
 # uncomment to install game in single-user environment (default)
 # SCORE_ENTRIES = MANY_PER_NAME
 
-# paths for cross-compiling (only needed for non-native MS-DOS and Win32 build)
-CROSS_PATH_MSDOS = /usr/local/cross-msdos/i386-msdosdjgpp
+# path for cross-compiling (only needed for non-native Windows build)
 CROSS_PATH_WIN32 = /usr/local/cross-tools/i386-mingw32msvc
 
-# compile special edition of R'n'D instead of the normal (classic) version
-# SPECIAL_EDITION = rnd_jue
-
 
 # -----------------------------------------------------------------------------
 # there should be no need to change anything below
@@ -58,50 +58,32 @@ CROSS_PATH_WIN32 = /usr/local/cross-tools/i386-mingw32msvc
 SRC_DIR = src
 MAKE_CMD = $(MAKE) -C $(SRC_DIR)
 
-# DEFAULT_TARGET = x11
-DEFAULT_TARGET = sdl
-
 
 # -----------------------------------------------------------------------------
 # build targets
 # -----------------------------------------------------------------------------
 
 all:
-	@$(MAKE_CMD) TARGET=$(DEFAULT_TARGET)
-
-x11:
-	@$(MAKE_CMD) TARGET=x11
+	@$(MAKE_CMD)
 
 sdl:
 	@$(MAKE_CMD) TARGET=sdl
 
-solaris:
-	@$(MAKE_CMD) PLATFORM=solaris TARGET=x11
-
-solaris-sdl:
-	@$(MAKE_CMD) PLATFORM=solaris TARGET=sdl
+sdl2:
+	@$(MAKE_CMD) TARGET=sdl2
 
 mac:
 	@$(MAKE_CMD) PLATFORM=macosx
 
-mac-static:
-	@$(MAKE_CMD) PLATFORM=macosx TARGET=sdl-static
-
-msdos:
-	@$(MAKE_CMD) PLATFORM=msdos
-
-os2:
-	@$(MAKE_CMD) PLATFORM=os2
-
-cross-msdos:
-	@PATH=$(CROSS_PATH_MSDOS)/bin:${PATH} $(MAKE_CMD) PLATFORM=cross-msdos
-
 cross-win32:
 	@PATH=$(CROSS_PATH_WIN32)/bin:${PATH} $(MAKE_CMD) PLATFORM=cross-win32
 
 clean:
 	@$(MAKE_CMD) clean
 
+clean-git:
+	@$(MAKE_CMD) clean-git
+
 
 # -----------------------------------------------------------------------------
 # development, test, distribution build and packaging targets
@@ -137,87 +119,47 @@ leveltest: all
 levelsketch_images: all
 	./Scripts/make_levelsketch_images.sh
 
-backup:
-	./Scripts/make_backup.sh src tar
-
-backup-net-copy:
-	./Scripts/make_backup.sh src scp
-
-backup-net: backup backup-net-copy
-
-backup_lev:
-	./Scripts/make_backup.sh lev
-
-backup_gfx:
-	./Scripts/make_backup.sh gfx
-
-# prerelease:
-#	./Scripts/make_prerelease.sh
-
-jue:
-	@$(MAKE) SPECIAL_EDITION=rnd_jue all
-
-jue-win:
-	@$(MAKE) SPECIAL_EDITION=rnd_jue cross-win32
-
 dist-clean:
 	@$(MAKE_CMD) dist-clean
 
 dist-build-unix:
-	@BUILD_DIST=TRUE $(MAKE) x11
-
-dist-build-msdos:
-	@BUILD_DIST=TRUE $(MAKE) cross-msdos
+	@BUILD_DIST=TRUE $(MAKE)
 
 dist-build-win32:
 	@BUILD_DIST=TRUE $(MAKE) cross-win32
 
 dist-build-macosx:
-	# (this is done by "dist-package-macosx" target)
+	@BUILD_DIST=TRUE $(MAKE)
 
 dist-package-unix:
-	./Scripts/make_dist.sh unix .
-
-dist-package-msdos:
-	./Scripts/make_dist.sh dos .
+	./Scripts/make_dist.sh package unix
 
 dist-package-win32:
-	./Scripts/make_dist.sh win .
+	./Scripts/make_dist.sh package win
 
 dist-package-macosx:
-	./Scripts/make_dist.sh mac . $(MAKE)
+	./Scripts/make_dist.sh package mac
 
 dist-upload-unix:
-	./Scripts/make_dist.sh unix . upload
-
-dist-upload-msdos:
-	./Scripts/make_dist.sh dos . upload
+	./Scripts/make_dist.sh upload unix
 
 dist-upload-win32:
-	./Scripts/make_dist.sh win . upload
+	./Scripts/make_dist.sh upload win
 
 dist-upload-macosx:
-	./Scripts/make_dist.sh mac . upload
-
-dist-build-all:
-	$(MAKE) clean
-	$(MAKE) dist-build-unix		; $(MAKE) dist-clean
-	$(MAKE) dist-build-win32	; $(MAKE) dist-clean
-#	$(MAKE) dist-build-msdos	; $(MAKE) dist-clean
+	./Scripts/make_dist.sh upload mac
 
 dist-package-all:
 	$(MAKE) dist-package-unix
 	$(MAKE) dist-package-win32
 	$(MAKE) dist-package-macosx
-#	$(MAKE) dist-package-msdos
 
 dist-upload-all:
 	$(MAKE) dist-upload-unix
 	$(MAKE) dist-upload-win32
 	$(MAKE) dist-upload-macosx
-#	$(MAKE) dist-upload-msdos
 
-dist-all: dist-build-all dist-package-all
+package-all: dist-package-all
 
 upload-all: dist-upload-all
 
diff --git a/README b/README
deleted file mode 100644
index 28572bf..0000000
--- a/README
+++ /dev/null
@@ -1,340 +0,0 @@
-
-Welcome to
-
-   R O C K S   ' N '   D I A M O N D S
-   -----------------------------------
-
-A game for Unix/X11, DOS and Windows by Holger Schemel.
-DOS port based on code by Guido Schulz.
-(c) 1995-2000 by Holger Schemel.
-
-Introduction
-============
-This is a nice little game with color graphics and sound for your
-Unix system with color X11, DOS or Windows. You need an 8-bit color
-display or better.
-It will not work on black&white systems, and maybe not on gray scale
-systems.
-
-If you know the game "Boulderdash" (Commodore C64) or "Emerald Mine"
-(Amiga) or "Supaplex" (PC), you know what "ROCKS'N'DIAMONDS" is about.
-
-
-Getting started
-===============
-Just 'cd' to the directory 'rocksndiamonds-*' (Unix, Windows) or 'rocks-*'
-(DOS) and type 'rocksndiamonds' (Linux, Windows) or 'rocks' (DOS)!
-This works only on Linux, DOS and Windows systems, because the included
-binary was compiled for Linux (i386/glibc) (if you have the Unix package)
-and DOS or Windows (if you have the DOS or Windows package).
-If you have another Unix system like HPUX, NetBSD or Solaris, you first have
-to type 'make' to compile it. See the file 'INSTALL' for details.
-This may be needed on Linux systems, too, depending on your kernel version,
-your libc version, your binary format, your processor, your karma, ...
-
-(The included Linux binary was compiled on a glibc 2.x system based on
-a 2.2.x Linux kernel and XFree86 4.0.x libraries.)
-
-
-The Menues
-==========
-You can see eight blue circles on the left side of the eight green menu
-texts; these are buttons to activate the menu commands by simply clicking
-on them with a mouse. The button will then change to red.
-(You can control the menues over the keyboard or joystick, too. Just use
-the arrow keys and the 'Return' or 'Enter' key or, if you use a joystick,
-the appropriate direction and the fire button.)
-
-The menu 'name' / 'team'
-------------------------
-When you start the game the first time, your login name will appear in
-the 'NAME:' field. If you want to use a different name for playing, for
-example a funny player name or a name for cheating, you can click on the
-button and enter a new name.
-
-This menu will show the text 'team' instead of 'name' if you activated
-the team (local multiplayer) mode in the setup menu. See below.
-
-The menu 'level'
------------------
-Choose any level from the current level series you want. The former
-'handicap' limitation in choosing levels has been removed because of
-beeing annoying.
-
-If the level number is red, you have choosen a 'ready' level series (which
-is read-only and cannot be modified by the level editor); if it is yellow
-you have choosen a 'user' level series (which is writable and can be changed
-by the builf-in level editor). See below for using the level editor.
-
-To choose new level series, click on the button on the left and choose
-the new level series. Scroll the page up and down with the blue arrow
-buttons if there are more level series than would fit on the screen.
-
-Hall of fame
-------------
-Click on this button to see a list of the best players of this level.
-Click again to go back to the main menu.
-
-Level creator
--------------
-This brings you to the level editor, if you have switched to a 'yellow'
-(writable) level series.
-
-Info screen
------------
-This screen shows you all elements which appear in the game and presents
-you the background music loops which you can listen to while playing the
-levels (not available on all systems).
-
-Start game
-----------
-This will start the game. The game will be automatically recorded 'on tape'
-if you have choosen this from the setup menu (see below). If you haven't
-choosen auto-recording level, but want to record this certain game, press
-the 'record' button on the level tape recorder to start game and recording.
-
-Setup
------
-To change some things in the game, use the setup menu.
-You can enable/disable "Sound" (enables/disables _all_ sounds in
-the game), "Sound loops" (only useful on Linux systems), "Game music"
-(can always be enabled on very fast systems [exception: you don't
-like it], on slower systems it will take some percent of CPU time
-which will slow things down a bit) and "Toons", which will forbid/
-permit the little animated toons.
-
-Forget about the setup options "Buffered Gfx" and "Fading" -- they
-have no effect at the moment and will probably disappear in future
-versions of the game. (Double-buffering is now always activated, because
-systems are fast enough now compared to 1995, when the last version of the
-game was released. Especially soft-scrolling needs the double-buffering.
-About fading from one screen to another with silly effects: Most players
-will probably deactivate it after a few minutes (see also "quick doors").)
-
-Enable "scroll delay" to avoid scrolling at each step, giving you an area
-where you can walk without scrolling until you get near enough to the screen
-border.
-
-Enable "soft scroll" for soft-scrolling. Looks nice, but may need a
-relatively fast graphics card. Systems from 1998 and later should be fast
-enough for enabling soft-scrolling.
-
-Enable "quick doors" if you are unpatient when switching between the
-several game screens where the doors have to be opened or closed. You will
-almost surely enable this if you design your own levels and therefore
-often switch between game and editor screens.
-
-Set "auto-record" to "on" if you want to automatically record each game
-by the built-in level tape recorder.
-
-For configuration of input devices like keyboard and joysticks, choose
-the sub-menu "input devices".
-
-"Exit" quits the setup menu without saving the changes, "Save and exit"
-will save and then return to the main menu.
-
-
-Input Devices (sub-menu of the setup menu)
-------------------------------------------
-
-"Player" lets you choose one of the four players.
-
-"Device" lets you choose the input device you want for this player;
-you can choose between the keyboard and one of the maximal four supported
-joysticks. (Normally you won't have more than two joysticks, but the Linux
-joystick driver supports more than two joysticks.)
-
-"Customize" / "Calibrate" lets you calibrate a joystick or customize the
-keyboard keys used for moving left, right, up and down, "snapping" fields
-without moving towards them and placing bombs. Just press the key you want
-to use for the specified action or press Return or Enter to stay with the
-already configured values.
-
-"Exit" brings you back to the setup screen.
-
-
-Quit
-----
-Exit the game.
-
-
-How To Play The Game
-====================
-When the game has started, you can see the playfield on the left side
-and a control field on the right side. The control field contains the
-following elements:
-
-Level indicator		Tells you which level you are playing.
-
-Emeralds		Shows you how many emeralds you still need
-			to win the current level.
-
-Dynamite		Shows you how many dynamite bombs you have.
-
-Keys			Shows you which keys you have in your inventory.
-
-Score			Shows the current score. In some levels there
-			are some extra items giving extra score points.
-
-Time			The seconds you have still left to play the level.
-
-Stop/Pause/Play		Game controls to stop the game, pause it and go on
-			playing. If the tape recorder is recording your
-			game, it is stopping/pausing/playing as well.
-
-Music buttons		The three music buttons can be used to control the
-			background music loop, the 'looping' sounds and
-			all other sounds. The little red light shows you
-			if it is enabled or disabled.
-
-About the game itself: Of course you know Boulderdash, so you will know
-how to play the game. :)
-If not: You can move your playing figure with the configured keys (which
-will normally and by default be the arrow keys) or with a joystick.
-To 'snap' a field near you without moving to it, you
-can use the left fire button on your joystick (hold it down, move the
-stick to 'snap' the field, release the button) or the key you have
-configured for this action (by default one of the left modifier keys like
-'Shift' or 'Control').
-To place a piece of dynamite, use the right fire button on your joystick or
-use the key you have configured for this (by default one of the right modifier
-keys, but you can change all this to what you like).
-After placing the dynamite, better see to move away from this field...).
-
-Just try the levels from the 'tutorial' level serie to see what most
-of the elements do or have a look at the info screen!
-
-
-The Level Editor
-================
-To create your own levels, it's a good idea to start with your personal
-level series, which has been created automatically the first time you
-started the game (together with some configuration files). These personal
-files are stored in '~/.rocksndiamonds' on Unix systems and in 'userdata'
-in the current playing directory (which normally is the game directory)
-on DOS/Windows systems.
-
-The levels that come with the game are normally read-only, to avoid
-problems on multi user systems, but you can set them to 'writable' in
-the file 'levelinfo.conf' ('lvlinfo.cnf' on DOS systems) in each level
-directory.
-
-To edit a level, you can use all three mouse buttons to draw in the
-level window. Click into the elements field with one of the three buttons
-to remap it to the new element. Use the scrollbars, arrow buttons or
-cursor keys to scroll around in the level. Use the drawing functions by
-selecting them from the toolbox field or pressing the corresponding key
-(the key shortcuts for each gadget are displayed in the status line at
-the bottom of the window when the mouse pointer is over the gadget).
-
-About the drawing functions: If you know the good old "Deluxe Paint" from
-the Amiga, you will have no problems with the drawing functions -- even
-the key shortcuts are mostly the same. If not, just try them out and you
-will see what happens. ;-)
-
-Some notes: Most drawing functions have different behaviour when different
-mouse buttons are pressed in the drawing area; normally, the left mouse
-button is the 'foreground button' and the middle and right buttons are
-some sort of 'background buttons', often with relation to the chosen
-element mappings on this buttons.
-
-The '?' button brings you to the 'Element settings' page, where you can
-see some information about the element and how many of them are included
-in the current level. The contents of elements with content (some amoeba
-and the Yam Yam (also know as cruncher) can have content) can be edited
-by 'sticking' the page with the corresponding button on their page.
-Yam Yam's can have up to eight content areas.
-
-The 'undo' button gives you the chance to undo up to 10 drawing operations.
-The 'info' button brings you to the 'Level/Editor settings' page.
-The 'save' button asks you to save the current level.
-The 'clear' button clears the drawing area without asking.
-The 'test' button lets you play your new level directly from the editor.
-The 'exit' button asks you to exit the editor (if there are unsaved changes).
-
-In the 'Editor settings' section, you can give your level a new name
-and type in your name which will be displayed as the level's author.
-(On Unix systems, your login name will be taken as default.)
-Then you can modify the level playfield size there, the available time
-(set this to zero to get unlimited time for this level), the score you
-get for each 10 seconds time that are left when reaching the exit, and
-last but not least you can enter the number of emeralds the player has
-to collect before the exit door opens.
-
-Another new button is the 'double speed' button that lets the player move
-twice as fast as normally from start; the effect is the same as collecting
-a speed pill during the game.
-
-In the 'Editor settings' section, you can make some modifications to the
-behaviour of the 'random element placement' button (the dice): Choose if
-the number you can enter means how many percent of the whole level are
-filled with the element chosen as the random element, or if it should mean
-the exact number of elements to be placed in the level field.
-With the 'restrict' button on the left side you can force the random function
-not to overwrite level elements other than the element chosen in the content
-field on the right side.
-
-
-The Tape Recorder
-=================
-You can use the tape recorder to record games and play tapes of previously
-played games. Just use them like a normal video recorder.
-
-Recording a game on tape:
--------------------------
-If you have enabled "auto-record", every game will automatically be recorded,
-so you just have to press "start game". Pressing the 'record' button on the
-tape recorder will start game and record it in any case.
-
-Saving a game tape:
--------------------
-To save a tape to the tape file corresponding to the level (that means
-that you can only save one tape file for each level), just press the
-'eject' button (the very left button). Then you will be prompted if
-you really want to replace the old tape (if an old tape exists).
-
-Playing a tape:
----------------
-Just press 'play' and then either 'play' or 'pause'.
-
-While recording or playing, you can press 'pause' to stop the recording
-or the playing of the tape and continue by pressing 'pause' again.
-You can use either the tape recorder buttons or the game control buttons
-for this purpose.
-
-If you want to continue a previously recorded game, press 'pause' while
-playing, then 'record' to switch from 'paused playing' to 'paused recording'
-and then continue the game by pressing 'record' or 'pause'. If you want
-to fast-forward the tape to get faster to the point where you want to
-continue playing, press 'play' again while already playing, therefore
-activating 'fast forward' playing mode. Press again the 'play' button
-to enter a special playing mode: 'pause before end' will stop a few seconds
-before the end of the tape (which will in most cases stop a few seconds
-before you get killed in the previous playing recorded on that tape) --
-after the automatic stop (which enters the 'pause' mode) you can continue
-the game as described above.
-
-
-And Now Have Fun!
-=================
-Have fun playing the game, building new levels and breaking all high
-scores! :-)
-
-If you have designed new levels, mail them to me to include them in the
-next version (which will be released much earlier than again after three
-years like this version... ;-)
-
-If you have any comments, problems, suggestions, donations, flames,
-send them to
-
-	info at artsoft.org
-
-or Snail Mail to
-
-	Holger Schemel
-	Detmolder Strasse 189
-	33604 Bielefeld
-	GERMANY
-
-Have fun,
-		Holger
diff --git a/build-scripts/create_element_defs.pl b/build-scripts/create_element_defs.pl
new file mode 100755
index 0000000..db4d42a
--- /dev/null
+++ b/build-scripts/create_element_defs.pl
@@ -0,0 +1,2645 @@
+#!/usr/bin/perl -w
+
+# =============================================================================
+# Rocks'n'Diamonds - McDuffin Strikes Back!
+# -----------------------------------------------------------------------------
+# (c) 1995-2014 by Artsoft Entertainment
+#                  Holger Schemel
+#                  info at artsoft.org
+#                  http://www.artsoft.org/
+# -----------------------------------------------------------------------------
+# create_element_defs.pl
+# =============================================================================
+
+use strict;
+
+
+# =============================================================================
+# C O N F I G U R A T I O N   S E C T I O N
+# =============================================================================
+
+my $base_path = ".";
+my $src_path = "$base_path/src";
+
+if (-d "../src")	# we're already inside "src" directory
+{
+    $src_path = ".";
+}
+
+
+# -----------------------------------------------------------------------------
+# global variables
+# -----------------------------------------------------------------------------
+
+my $filename_header_tmpl = "$src_path/header.tmpl";
+
+my $filename_conf_gfx_h = 'conf_gfx.h';
+my $filename_conf_snd_h = 'conf_snd.h';
+my $filename_conf_mus_h = 'conf_mus.h';
+my $filename_conf_chr_c = 'conf_chr.c';
+my $filename_conf_chr_h = 'conf_chr.h';
+my $filename_conf_cus_c = 'conf_cus.c';
+my $filename_conf_cus_h = 'conf_cus.h';
+my $filename_conf_grp_c = 'conf_grp.c';
+my $filename_conf_grp_h = 'conf_grp.h';
+my $filename_conf_e2g_c = 'conf_e2g.c';
+my $filename_conf_esg_c = 'conf_esg.c';
+my $filename_conf_e2s_c = 'conf_e2s.c';
+my $filename_conf_fnt_c = 'conf_fnt.c';
+my $filename_conf_g2s_c = 'conf_g2s.c';
+my $filename_conf_g2m_c = 'conf_g2m.c';
+my $filename_conf_var_c = 'conf_var.c';
+my $filename_conf_act_c = 'conf_act.c';
+
+my $text_auto = 'this file was automatically generated -- do not edit by hand';
+my $text_gfx_h = 'values for graphics configuration (normal elements)';
+my $text_snd_h = 'values for sounds configuration';
+my $text_mus_h = 'values for music configuration';
+my $text_chr_c = 'values for graphics configuration (character elements)';
+my $text_chr_h = 'values for elements configuration (character elements)';
+my $text_cus_c = 'values for graphics configuration (custom elements)';
+my $text_cus_h = 'values for elements configuration (custom elements)';
+my $text_grp_c = 'values for graphics configuration (group elements)';
+my $text_grp_h = 'values for elements configuration (group elements)';
+my $text_e2g_c = 'values for element/graphics mapping configuration (normal)';
+my $text_esg_c = 'values for element/graphics mapping configuration (special)';
+my $text_e2s_c = 'values for element/sounds mapping configuration';
+my $text_fnt_c = 'values for font/graphics mapping configuration';
+my $text_g2s_c = 'values for gamemode/sound mapping configuration';
+my $text_g2m_c = 'values for gamemode/music mapping configuration';
+my $text_var_c = 'values for image and layout parameter configuration';
+my $text_act_c = 'values for active states of elements and fonts';
+
+my $num_custom_elements = 256;
+my $num_group_elements = 32;
+
+my $char_skip = '---[SKIP]---';
+
+my @chars =
+    (
+     'SPACE',
+     'EXCLAM',
+     'QUOTEDBL',
+     'NUMBERSIGN',
+     'DOLLAR',
+     'PERCENT',
+     'AMPERSAND',
+     'APOSTROPHE',
+     'PARENLEFT',
+     'PARENRIGHT',
+     'ASTERISK',
+     'PLUS',
+     'COMMA',
+     'MINUS',
+     'PERIOD',
+     'SLASH',
+
+     '0',
+     '1',
+     '2',
+     '3',
+     '4',
+     '5',
+     '6',
+     '7',
+     '8',
+     '9',
+     'COLON',
+     'SEMICOLON',
+     'LESS',
+     'EQUAL',
+     'GREATER',
+     'QUESTION',
+
+     'AT',
+     'A',
+     'B',
+     'C',
+     'D',
+     'E',
+     'F',
+     'G',
+     'H',
+     'I',
+     'J',
+     'K',
+     'L',
+     'M',
+     'N',
+     'O',
+
+     'P',
+     'Q',
+     'R',
+     'S',
+     'T',
+     'U',
+     'V',
+     'W',
+     'X',
+     'Y',
+     'Z',
+     'BRACKETLEFT',
+     'BACKSLASH',
+     'BRACKETRIGHT',
+     'ASCIICIRCUM',
+     'UNDERSCORE',
+
+     'COPYRIGHT',
+     'AUMLAUT',
+     'OUMLAUT',
+     'UUMLAUT',
+     'DEGREE',
+     'TRADEMARK',
+     'CURSOR',
+     $char_skip,
+     $char_skip,
+     $char_skip,
+     $char_skip,
+     $char_skip,
+     $char_skip,
+     'BUTTON',
+     'UP',
+     'DOWN',
+     );
+
+
+# -----------------------------------------------------------------------------
+# start main program
+# -----------------------------------------------------------------------------
+
+main();
+exit 0;
+
+
+# =============================================================================
+# F U N C T I O N S
+# =============================================================================
+
+sub error
+{
+    my ($error_msg) = @_;
+
+    print STDERR "ERROR: ";
+    print STDERR "$error_msg\n";
+}
+
+sub fail
+{
+    my ($error_msg) = @_;
+
+    print STDERR "FATAL ";
+    error("$error_msg");
+
+    exit 1;
+}
+
+sub contains_image_file
+{
+    my ($line) = @_;
+
+    return ($line =~ /\".+\.png\"/ ||
+	    $line =~ /UNDEFINED_FILENAME/);
+}
+
+sub contains_sound_file
+{
+    my ($line) = @_;
+
+    return ($line =~ /\".+\.wav\"/ ||
+	    $line =~ /UNDEFINED_FILENAME/);
+}
+
+sub contains_music_file
+{
+    my ($line) = @_;
+
+    return ($line =~ /\".+\.wav\"/ ||
+	    $line =~ /\".+\.mod\"/ ||
+	    $line =~ /\".+\.mp3\"/ ||
+	    $line =~ /UNDEFINED_FILENAME/);
+}
+
+sub print_file_header
+{
+    my ($filename, $comment) = @_;
+    my $filename_tmpl = 'xxxxxxxx.x';
+    my $filename_text = $filename;
+    my $filename_def = uc($filename);
+    $filename_def =~ s/\./_/;
+
+    $filename_text .= ' ' x (length($filename_tmpl) - length($filename_text));
+
+    open(FILE, "$filename_header_tmpl") ||
+	fail("cannot open file '$filename_header_tmpl' for reading");
+
+    while (<FILE>)
+    {
+	s/$filename_tmpl/$filename_text/;
+
+	print;
+    }
+
+    close FILE;
+
+    print "\n";
+    print "/* ----- $text_auto ----- */\n";
+    print "\n";
+    print "#ifndef $filename_def\n";
+    print "#define $filename_def\n";
+    print "\n";
+    print "/* $comment */\n";
+    print "\n";
+}
+
+sub print_file_footer
+{
+    my ($filename) = @_;
+    my $filename_def = uc($filename);
+    $filename_def =~ s/\./_/;
+
+    print "\n";
+    print "#endif	/* $filename_def */\n";
+}
+
+sub get_tabs
+{
+    my ($text, $max_num_tabs) = @_;
+
+    my $num_tabs = $max_num_tabs - int(length($text) / 8);
+
+    if ($num_tabs < 1)	# at least one tab needed as separator
+    {
+	$num_tabs = 1;
+    }
+
+    return "\t" x $num_tabs;
+}
+
+sub print_graphics_list
+{
+    my $filename = "$src_path/conf_gfx.c";
+
+    print_file_header($filename_conf_gfx_h, $text_gfx_h);
+
+    open(FILE, "$filename") ||
+	fail("cannot open file '$filename' for reading");
+
+    my $max_num_tabs = 7;
+    my $i = 0;
+
+    while (<FILE>)
+    {
+	chomp;				# cut trailing newline
+
+	if (/^\#include "conf_chr.c"/)	# dump list of character elements
+	{
+	    foreach my $char (@chars)
+	    {
+		my $prefix = $char;
+
+		$prefix =~ s/^/#define IMG_CHAR_/;
+
+		my $tabs = get_tabs($prefix, $max_num_tabs);
+
+		if ($char ne $char_skip)
+		{
+		    print "$prefix$tabs$i\n";
+
+		    $i++;
+		}
+
+		if (lc($char) eq 'space')
+		{
+		    $prefix =~ s/$/_EDITOR/;
+
+		    my $tabs = get_tabs($prefix, $max_num_tabs);
+
+		    print "$prefix$tabs$i\n";
+
+		    $i++;
+		}
+	    }
+
+	    foreach my $char (@chars)
+	    {
+		my $prefix = $char;
+
+		$prefix =~ s/^/#define IMG_STEEL_CHAR_/;
+
+		my $tabs = get_tabs($prefix, $max_num_tabs);
+
+		if ($char ne $char_skip)
+		{
+		    print "$prefix$tabs$i\n";
+
+		    $i++;
+		}
+
+		if (lc($char) eq 'space')
+		{
+		    $prefix =~ s/$/_EDITOR/;
+
+		    my $tabs = get_tabs($prefix, $max_num_tabs);
+
+		    print "$prefix$tabs$i\n";
+
+		    $i++;
+		}
+	    }
+	}
+
+	if (/^\#include "conf_cus.c"/)	# dump list of custom elements
+	{
+	    for (my $nr = 0; $nr < $num_custom_elements; $nr++)
+	    {
+		my $line = sprintf("#define IMG_CUSTOM_%d", $nr + 1);
+
+		my $tabs = get_tabs($line, $max_num_tabs);
+
+		print "$line$tabs$i\n";
+
+		$i++;
+
+		$line = sprintf("#define IMG_CUSTOM_%d_EDITOR", $nr + 1);
+
+		$tabs = get_tabs($line, $max_num_tabs);
+
+		print "$line$tabs$i\n";
+
+		$i++;
+	    }
+	}
+
+	if (/^\#include "conf_grp.c"/)	# dump list of group elements
+	{
+	    for (my $nr = 0; $nr < $num_group_elements; $nr++)
+	    {
+		my $line = sprintf("#define IMG_GROUP_%d", $nr + 1);
+
+		my $tabs = get_tabs($line, $max_num_tabs);
+
+		print "$line$tabs$i\n";
+
+		$i++;
+
+		$line = sprintf("#define IMG_GROUP_%d_EDITOR", $nr + 1);
+
+		$tabs = get_tabs($line, $max_num_tabs);
+
+		print "$line$tabs$i\n";
+
+		$i++;
+	    }
+	}
+
+	if (!contains_image_file($_))	# skip all lines without image file
+	{
+	    next;
+	}
+
+	s/(.*)/uc($1)/eg;		# convert all characters to upper case
+	s/\./_/g;			# replace all '.' with '_'
+
+	s/^  \{ \"/#define IMG_/;	# convert line
+	s/\",.*$//;			# convert line
+
+	# dirty hack for making "ABC[DEF]" work as a "special" suffix
+	s/([^_])\[/$1_/;
+
+	# dirty hack for making "[default]" work as an element name
+	s/\[//;
+	s/\]//;
+
+	my $tabs = get_tabs($_, $max_num_tabs);
+
+	print "$_$tabs$i\n";
+
+	$i++;
+    }
+
+    my $summary = '#define NUM_IMAGE_FILES';
+    my $tabs = get_tabs($summary, $max_num_tabs);
+
+    print "\n$summary$tabs$i\n";
+
+    close FILE;
+
+    print_file_footer($filename_conf_gfx_h);
+}
+
+sub print_sounds_list
+{
+    my %known_element = get_known_element_definitions();
+
+    my $filename = "$src_path/conf_snd.c";
+
+    print_file_header($filename_conf_snd_h, $text_snd_h);
+
+    open(FILE, "$filename") ||
+	fail("cannot open file '$filename' for reading");
+
+    my $max_num_tabs = 7;
+    my $i = 0;
+
+    while (<FILE>)
+    {
+	chomp;				# cut trailing newline
+
+	if (!contains_sound_file($_))	# skip all lines without sound file
+	{
+	    next;
+	}
+
+	if (/\[not used\]/ ||
+	    / TEST / ||
+	    /wav[^\}]*$/)		# skip all lines without sound file
+	{
+	    next;
+	}
+
+	s/(.*)/uc($1)/eg;		# convert all characters to upper case
+	s/\./_/g;			# replace all '.' with '_'
+
+	s/^  \{ \"//;
+	s/\",.*$//;
+
+	my $sound = $_;
+
+	if ($sound =~ /^\[.+\]/)
+	{
+	    $sound =~ s/\[//;		# element class sound; begin ...
+	    $sound =~ s/\]//;		# ... and end of definition token
+	    $sound =~ s/^/CLASS_/;	# add class identifier
+ 	}
+
+	$sound = "SND_$sound";
+
+	my $define_text = "#define $sound";
+	my $tabs = get_tabs($define_text, $max_num_tabs);
+
+	print "$define_text$tabs$i\n";
+
+	$i++;
+    }
+
+    my $summary = '#define NUM_SOUND_FILES';
+    my $tabs = get_tabs($summary, $max_num_tabs);
+
+    print "\n$summary$tabs$i\n";
+
+    close FILE;
+
+    print_file_footer($filename_conf_snd_h);
+}
+
+sub print_music_list
+{
+    my %known_prefix = get_known_music_prefix_definitions();
+
+    my $filename = "$src_path/conf_mus.c";
+
+    print_file_header($filename_conf_mus_h, $text_mus_h);
+
+    open(FILE, "$filename") ||
+	fail("cannot open file '$filename' for reading");
+
+    my $max_num_tabs = 7;
+    my $i = 0;
+
+    while (<FILE>)
+    {
+	chomp;				# cut trailing newline
+
+	if (!contains_music_file($_))	# skip all lines without music file
+	{
+	    next;
+	}
+
+	if (/\[not used\]/ ||
+	    / TEST / ||
+	    /wav[^\}]*$/)		# skip all lines without music file
+	{
+	    next;
+	}
+
+	s/(.*)/uc($1)/eg;		# convert all characters to upper case
+	s/\./_/g;			# replace all '.' with '_'
+
+	s/^  \{ \"//;
+	s/\",.*$//;
+
+	my $music = $_;
+
+	$music = "MUS_$music";
+
+	my $define_text = "#define $music";
+	my $tabs = get_tabs($define_text, $max_num_tabs);
+
+	print "$define_text$tabs$i\n";
+
+	$i++;
+    }
+
+    my $summary = '#define NUM_MUSIC_FILES';
+    my $tabs = get_tabs($summary, $max_num_tabs);
+
+    print "\n$summary$tabs$i\n";
+
+    close FILE;
+
+    print_file_footer($filename_conf_mus_h);
+}
+
+sub print_chars_elements_list
+{
+    print_file_header($filename_conf_chr_h, $text_chr_h);
+
+    my $i = 0;
+
+    foreach my $char (@chars)
+    {
+	my $left = "#define EL_CHAR_$char";
+
+	my $tabs_left = get_tabs($left, 5);
+
+	my $right = sprintf("(EL_CHAR_ASCII0 + %d)", $i + 32);
+
+	if ($char ne $char_skip)
+	{
+	    print "$left$tabs_left$right\n";
+	}
+
+	$i++;
+    }
+
+    $i = 0;
+
+    foreach my $char (@chars)
+    {
+	my $left = "#define EL_STEEL_CHAR_$char";
+
+	my $tabs_left = get_tabs($left, 5);
+
+	my $right = sprintf("(EL_STEEL_CHAR_ASCII0 + %d)", $i + 32);
+
+	if ($char ne $char_skip)
+	{
+	    print "$left$tabs_left$right\n";
+	}
+
+	$i++;
+    }
+
+    print_file_footer($filename_conf_chr_c);
+}
+
+sub print_chars_graphics_list_line
+{
+    my ($token, $x, $y) = @_;
+
+    my @extensions =
+	(
+	 '',
+	 '.xpos',
+	 '.ypos',
+	 '.frames',
+	 );
+
+    my $basename = ($token =~ /^steel_char/ ? 'RocksFontDC' : 'RocksFontEM' );
+
+    foreach my $ext (@extensions)
+    {
+	my $left = "  \{ \"$token$ext\",";
+
+	my $tabs_left = get_tabs($left, 6);
+
+	my $right = ($ext eq '' ? $basename . '.png' :
+		     $ext eq '.frames' ? '1' : '0');
+
+	if ($ext eq '.xpos')
+	{
+	    $right = $x;
+	}
+	elsif ($ext eq '.ypos')
+	{
+	    $right = $y;
+	}
+
+	$right = "\"$right\"";
+
+	my $tabs_right = get_tabs($right, 3);
+
+	print "$left$tabs_left$right$tabs_right},\n";
+    }
+}
+
+sub print_chars_graphics_list
+{
+    print_file_header($filename_conf_chr_c, $text_chr_c);
+
+    my $i = 0;
+
+    foreach my $char (@chars)
+    {
+	if ($char ne $char_skip)
+	{
+	    my $x = $i % 16;
+	    my $y = int($i / 16);
+
+	    print_chars_graphics_list_line(lc("char_$char"), $x, $y);
+	}
+
+	if (lc($char) eq 'space')
+	{
+	    print_chars_graphics_list_line("char_space.EDITOR", 7, 4);
+	}
+
+	if ($char ne $char_skip)
+	{
+	    print "\n";
+	}
+
+	$i++;
+    }
+
+    $i = 0;
+
+    foreach my $char (@chars)
+    {
+	if ($char ne $char_skip)
+	{
+	    my $x = $i % 16;
+	    my $y = int($i / 16);
+
+	    print_chars_graphics_list_line(lc("steel_char_$char"), $x, $y);
+	}
+
+	if (lc($char) eq 'space')
+	{
+	    print_chars_graphics_list_line("steel_char_space.EDITOR", 7, 4);
+	}
+
+	if ($char ne $char_skip)
+	{
+	    print "\n";
+	}
+
+	$i++;
+    }
+
+    print_file_footer($filename_conf_chr_c);
+}
+
+sub print_custom_elements_list
+{
+    print_file_header($filename_conf_cus_h, $text_cus_h);
+
+    for (my $i = 0; $i < $num_custom_elements; $i++)
+    {
+	my $left = sprintf("#define EL_CUSTOM_%d", $i + 1);
+
+	my $tabs_left = get_tabs($left, 5);
+
+	my $right = "(EL_CUSTOM_START + $i)";
+
+	print "$left$tabs_left$right\n";
+    }
+
+    print_file_footer($filename_conf_cus_c);
+}
+
+sub print_group_elements_list
+{
+    print_file_header($filename_conf_grp_h, $text_grp_h);
+
+    for (my $i = 0; $i < $num_group_elements; $i++)
+    {
+	my $left = sprintf("#define EL_GROUP_%d", $i + 1);
+
+	my $tabs_left = get_tabs($left, 5);
+
+	my $right = "(EL_GROUP_START + $i)";
+
+	print "$left$tabs_left$right\n";
+    }
+
+    print_file_footer($filename_conf_grp_c);
+}
+
+sub print_custom_graphics_list
+{
+    my @extensions1 =
+	(
+	 '',
+	 '.xpos',
+	 '.ypos',
+	 '.frames',
+	 );
+    my @extensions2 =
+	(
+	 '',
+	 '.xpos',
+	 '.ypos',
+	 );
+
+    print_file_header($filename_conf_cus_c, $text_cus_c);
+
+    for (my $i = 0; $i < $num_custom_elements; $i++)
+    {
+	foreach my $ext (@extensions1)
+	{
+	    my $left = sprintf("  \{ \"custom_%d$ext\",", $i + 1);
+
+	    my $tabs_left = get_tabs($left, 6);
+
+	    # my $right = ($ext eq '' ? 'RocksElements.png' :
+	    my $right = ($ext eq '' ? 'RocksCE.png' :
+			 $ext eq '.frames' ? '1' : '0');
+
+	    if ($ext eq '.xpos')
+	    {
+		# $right = 7;
+		$right = int($i % 16);
+	    }
+	    elsif ($ext eq '.ypos')
+	    {
+		# $right = 9;
+		$right = int($i / 16);
+	    }
+
+	    $right = "\"$right\"";
+
+	    my $tabs_right = get_tabs($right, 3);
+
+	    print "$left$tabs_left$right$tabs_right},\n";
+	}
+
+	foreach my $ext (@extensions2)
+	{
+	    my $left = sprintf("  \{ \"custom_%d.EDITOR$ext\",", $i + 1);
+
+	    my $tabs_left = get_tabs($left, 6);
+
+	    # my $right = ($ext eq '' ? 'RocksElements.png' : '0');
+	    my $right = ($ext eq '' ? 'RocksCE.png' : '0');
+
+	    if ($ext eq '.xpos')
+	    {
+		# $right = 15;
+		$right = int($i % 16) + 16;
+	    }
+	    elsif ($ext eq '.ypos')
+	    {
+		# $right = 13;
+		$right = int($i / 16);
+	    }
+
+	    $right = "\"$right\"";
+
+	    my $tabs_right = get_tabs($right, 3);
+
+	    print "$left$tabs_left$right$tabs_right},\n";
+	}
+
+	print "\n";
+    }
+
+    print_file_footer($filename_conf_cus_c);
+}
+
+sub print_group_graphics_list
+{
+    my @extensions1 =
+	(
+	 '',
+	 '.xpos',
+	 '.ypos',
+	 '.frames',
+	 );
+    my @extensions2 =
+	(
+	 '',
+	 '.xpos',
+	 '.ypos',
+	 );
+
+    print_file_header($filename_conf_grp_c, $text_grp_c);
+
+    for (my $i = 0; $i < $num_group_elements; $i++)
+    {
+	foreach my $ext (@extensions1)
+	{
+	    my $left = sprintf("  \{ \"group_%d$ext\",", $i + 1);
+
+	    my $tabs_left = get_tabs($left, 6);
+
+	    # my $right = ($ext eq '' ? 'RocksDC.png' :
+	    my $right = ($ext eq '' ? 'RocksCE.png' :
+			 $ext eq '.frames' ? '1' : '0');
+
+	    if ($ext eq '.xpos')
+	    {
+		# $right = 4;
+		$right = int($i % 16);
+	    }
+	    elsif ($ext eq '.ypos')
+	    {
+		# $right = 15;
+		$right = int($i / 16) + int($num_custom_elements / 16);
+	    }
+
+	    $right = "\"$right\"";
+
+	    my $tabs_right = get_tabs($right, 3);
+
+	    print "$left$tabs_left$right$tabs_right},\n";
+	}
+
+	foreach my $ext (@extensions2)
+	{
+	    my $left = sprintf("  \{ \"group_%d.EDITOR$ext\",", $i + 1);
+
+	    my $tabs_left = get_tabs($left, 6);
+
+	    # my $right = ($ext eq '' ? 'RocksDC.png' : '0');
+	    my $right = ($ext eq '' ? 'RocksCE.png' : '0');
+
+	    if ($ext eq '.xpos')
+	    {
+		# $right = 14;
+		$right = int($i % 16) + 16;
+	    }
+	    elsif ($ext eq '.ypos')
+	    {
+		# $right = 15;
+		$right = int($i / 16) + int($num_custom_elements / 16);
+	    }
+
+	    $right = "\"$right\"";
+
+	    my $tabs_right = get_tabs($right, 3);
+
+	    print "$left$tabs_left$right$tabs_right},\n";
+	}
+
+	print "\n";
+    }
+
+    print_file_footer($filename_conf_grp_c);
+}
+
+sub get_known_element_definitions_ALTERNATIVE
+{
+    my %known_element = ();
+
+    my $filename = "$src_path/main.h";
+
+    open(FILE, "$filename") ||
+	fail("cannot open file '$filename' for reading");
+
+    while (<FILE>)
+    {
+	chomp;				# cut trailing newline
+
+	# process line with element definition
+	if (/^\#define (EL_[A-Z0-9_]+)\s/)
+	{
+	    $known_element{$1} = 1;
+
+	    # print STDERR "known_element: '$1'\n";
+	}
+    }
+
+    close FILE;
+
+    return %known_element;
+}
+
+sub get_known_element_definitions
+{
+    my %known_element = ();
+
+    my $filename = "$src_path/main.c";
+
+    open(FILE, "$filename") ||
+	fail("cannot open file '$filename' for reading");
+
+    my $element_name = '';
+    my $line_is_element_name = 0;
+    my $skip_line = 1;
+
+    while (<FILE>)
+    {
+	chomp;				# cut trailing newline
+
+	if (/ELEMENT_INFO_START/)	# keyword to start parsing file
+	{
+	    $skip_line = 0;
+	    next;
+	}
+	elsif (/ELEMENT_INFO_END/)	# keyword to stop parsing file
+	{
+	    last;
+	}
+	elsif ($skip_line)
+	{
+	    next;
+	}
+
+	if (/^\s+\{\s*$/)
+	{
+	    $line_is_element_name = 1;
+	}
+	elsif ($line_is_element_name)
+	{
+	    # process line with element name definition
+	    if (/^\s+\"(.+)\",?\s*$/)
+	    {
+		$element_name = 'EL_' . uc($1);
+
+		# dirty hack for making "[default]" work as an element name
+		$element_name =~ s/\[//;
+		$element_name =~ s/\]//;
+
+		# change '.' to '_' for elements like "dynamite.active"
+		$element_name =~ s/\./_/g;
+
+		$known_element{$element_name} = 1;
+
+		# printf STDERR "::: known element '$element_name'\n";
+	    }
+
+	    $line_is_element_name = 0;
+	}
+    }
+
+    close FILE;
+
+    return %known_element;
+}
+
+sub get_known_element_class_definitions
+{
+    my %known_element_class = ();
+
+    my $filename = "$src_path/main.c";
+
+    open(FILE, "$filename") ||
+	fail("cannot open file '$filename' for reading");
+
+    my $element_name = '';
+    my $element_class = '';
+    my $line_is_element_name = 0;
+    my $line_is_element_class = 0;
+    my $skip_line = 1;
+
+    while (<FILE>)
+    {
+	chomp;				# cut trailing newline
+
+	if (/ELEMENT_INFO_START/)	# keyword to start parsing file
+	{
+	    $skip_line = 0;
+	    next;
+	}
+	elsif (/ELEMENT_INFO_END/)	# keyword to stop parsing file
+	{
+	    last;
+	}
+	elsif ($skip_line)
+	{
+	    next;
+	}
+
+	if (/^\s+\{\s*$/)
+	{
+	    $line_is_element_name = 1;
+	}
+	elsif ($line_is_element_name)
+	{
+	    # process line with element name definition
+	    if (/^\s+\"(.+)\",?\s*$/)
+	    {
+		$element_name = 'EL_' . uc($1);
+
+		# dirty hack for making "[default]" work as an element name
+		$element_name =~ s/\[//;
+		$element_name =~ s/\]//;
+
+		# change '.' to '_' for elements like "dynamite.active"
+		$element_name =~ s/\./_/g;
+	    }
+
+	    $line_is_element_name = 0;
+	    $line_is_element_class = 1;
+	}
+	elsif ($line_is_element_class)
+	{
+	    # process line with element class definition
+	    if (/^\s+\"(.+)\",?\s*$/)
+	    {
+		$element_class = 'EL_CLASS_' . uc($1);
+
+		if (!defined($known_element_class{$element_class}))
+		{
+		    $known_element_class{$element_class} = $element_name;
+		}
+
+		$known_element_class{$element_name} = $element_class;
+
+		# print STDERR "known_element_class: '$element_name' => '$element_class'\n";
+	    }
+
+	    $line_is_element_class = 0;
+	}
+    }
+
+    close FILE;
+
+    return %known_element_class;
+}
+
+sub get_known_action_definitions
+{
+    my %known_action = ();
+
+    my $filename = "$src_path/main.h";
+
+    open(FILE, "$filename") ||
+	fail("cannot open file '$filename' for reading");
+
+    while (<FILE>)
+    {
+	chomp;				# cut trailing newline
+
+	# process line with action definition
+	if (/^\#define ACTION_([A-Z0-9_]+)\s/)
+	{
+	    $known_action{$1} = 1;
+
+	    # print STDERR "known_action: '$1'\n";
+	}
+    }
+
+    close FILE;
+
+    return %known_action;
+}
+
+sub get_known_special_arg_definitions
+{
+    my %known_special_arg = ();
+
+    my $filename = "$src_path/main.h";
+
+    open(FILE, "$filename") ||
+	fail("cannot open file '$filename' for reading");
+
+    while (<FILE>)
+    {
+	chomp;				# cut trailing newline
+
+	# process line with special arg definition
+	if (/^\#define GFX_SPECIAL_ARG_([A-Z0-9_]+)\s/)
+	{
+	    if ($1 eq 'CRUMBLED')
+	    {
+		next;
+	    }
+
+	    $known_special_arg{$1} = 1;
+
+	    # print STDERR "known_special_arg: '$1'\n";
+	}
+    }
+
+    close FILE;
+
+    return %known_special_arg;
+}
+
+sub get_known_button_definitions
+{
+    my %known_button = ();
+
+    my $filename = "$src_path/conf_gfx.h";
+
+    open(FILE, "$filename") ||
+	fail("cannot open file '$filename' for reading");
+
+    while (<FILE>)
+    {
+	chomp;				# cut trailing newline
+
+	# process line with button definition
+	if (/^\#define (IMG_MENU_BUTTON[A-Z0-9_]*)\s/)
+	{
+	    $known_button{$1} = 1;
+
+	    # print STDERR "known_button: '$1'\n";
+	}
+    }
+
+    close FILE;
+
+    return %known_button;
+}
+
+sub get_known_font_definitions
+{
+    my %known_font = ();
+
+    my $filename = "$src_path/main.h";
+
+    open(FILE, "$filename") ||
+	fail("cannot open file '$filename' for reading");
+
+    while (<FILE>)
+    {
+	chomp;				# cut trailing newline
+
+	# process line with font definition
+	if (/^\#define (FONT_[A-Z0-9_]+)\s/)
+	{
+	    $known_font{$1} = 1;
+
+	    # print STDERR "known_font: '$1'\n";
+	}
+    }
+
+    close FILE;
+
+    return %known_font;
+}
+
+sub get_known_sound_prefix_definitions
+{
+    my %known_sound_prefix = ( 'background'	=> 1 );
+
+    return %known_sound_prefix;
+}
+
+sub get_known_music_prefix_definitions
+{
+    my %known_music_prefix = ();
+
+    my $filename = "$src_path/main.c";
+
+    open(FILE, "$filename") ||
+	fail("cannot open file '$filename' for reading");
+
+    my $prefix_name = '';
+    my $skip_line = 1;
+
+    while (<FILE>)
+    {
+	chomp;				# cut trailing newline
+
+	if (/MusicPrefixInfo/)		# keyword to start parsing file
+	{
+	    $skip_line = 0;
+	    next;
+	}
+	elsif (/NULL/ && !$skip_line)	# keyword to stop parsing file
+	{
+	    last;
+	}
+	elsif ($skip_line)
+	{
+	    next;
+	}
+
+	if (/^\s+{\s+\"(.+)\"/)
+	{
+	    my $music_prefix = $1;
+
+	    $known_music_prefix{$music_prefix} = 1;
+
+	    # printf STDERR "::: known music prefix '$music_prefix'\n";
+	}
+    }
+
+    close FILE;
+
+    return %known_music_prefix;
+}
+
+sub print_element_to_graphic_entry
+{
+    my ($element, $action, $direction, $crumbled, $graphic) = @_;
+
+    my $num_tabs = 5 - int((length($element) + 4 + 1) / 8);
+    my $tabs = "\t" x $num_tabs;
+    if ($tabs eq '')
+    {
+	$tabs = ' ';
+    }
+
+    $crumbled = ($crumbled == 1 ? 'TRUE' : 'FALSE');
+
+    print "  {\n";
+    print "    $element,$tabs$action, $direction, $crumbled,\n";
+    print "    $graphic\n";
+    print "  },\n";
+}
+
+sub print_element_to_special_graphic_entry
+{
+    my ($element, $special, $graphic) = @_;
+
+    my $num_tabs = 6 - int((length($element) + 4 + 1) / 8);
+    my $tabs = "\t" x $num_tabs;
+    if ($tabs eq '')
+    {
+	$tabs = ' ';
+    }
+
+    print "  {\n";
+    print "    $element,$tabs$special,\n";
+    print "    $graphic\n";
+    print "  },\n";
+}
+
+sub print_font_to_graphic_entry
+{
+    my ($font, $special, $graphic) = @_;
+
+    my $num_tabs = 6 - int((length($font) + 4 + 1) / 8);
+    my $tabs = "\t" x $num_tabs;
+    if ($tabs eq '')
+    {
+	$tabs = ' ';
+    }
+
+    print "  {\n";
+    print "    $font,$tabs$special,\n";
+    print "    $graphic\n";
+    print "  },\n";
+}
+
+sub print_element_to_sound_entry
+{
+    my ($element, $is_class, $action, $sound) = @_;
+
+    my $element_plus_is_class = "$element, $is_class";
+
+    my $num_tabs = 6 - int((length($element_plus_is_class) + 4 + 1) / 8);
+    my $tabs = "\t" x $num_tabs;
+    if ($tabs eq '')
+    {
+	$tabs = ' ';
+    }
+
+    print "  {\n";
+    print "    $element_plus_is_class,$tabs$action,\n";
+    print "    $sound\n";
+    print "  },\n";
+}
+
+sub print_gamemode_to_sound_entry
+{
+    my ($gamemode, $sound) = @_;
+
+    print "  {\n";
+    print "    $gamemode,\n";
+    print "    $sound\n";
+    print "  },\n";
+}
+
+sub print_gamemode_to_music_entry
+{
+    my ($gamemode, $music) = @_;
+
+    print "  {\n";
+    print "    $gamemode,\n";
+    print "    $music\n";
+    print "  },\n";
+}
+
+sub print_image_config_var_entry
+{
+    my ($token, $var) = @_;
+
+    print "  {\n";
+    print "    $token,\n";
+    print "    $var\n";
+    print "  },\n";
+}
+
+sub print_active_state_entry
+{
+    my ($token, $token_active) = @_;
+
+    print "  {\n";
+    print "    $token,\n";
+    print "    $token_active\n";
+    print "  },\n";
+}
+
+sub print_element_to_graphic_list
+{
+    my %graphic_without_element =
+	(
+	 'IMG_FLAMES_1_LEFT'		=> 1,
+	 'IMG_FLAMES_2_LEFT'		=> 1,
+	 'IMG_FLAMES_3_LEFT'		=> 1,
+	 'IMG_FLAMES_1_RIGHT'		=> 1,
+	 'IMG_FLAMES_2_RIGHT'		=> 1,
+	 'IMG_FLAMES_3_RIGHT'		=> 1,
+	 'IMG_FLAMES_1_UP'		=> 1,
+	 'IMG_FLAMES_2_UP'		=> 1,
+	 'IMG_FLAMES_3_UP'		=> 1,
+	 'IMG_FLAMES_1_DOWN'		=> 1,
+	 'IMG_FLAMES_2_DOWN'		=> 1,
+	 'IMG_FLAMES_3_DOWN'		=> 1,
+	 'IMG_TWINKLE_BLUE'		=> 1,
+	 'IMG_TWINKLE_WHITE'		=> 1,
+	 );
+
+    my %additional_mappings =
+	(
+	 # file elements which are mapped to runtime elements when playing
+
+	 # 'EL_EM_KEY_1_FILE'		=> 'IMG_EM_KEY_1',
+	 # 'EL_EM_KEY_2_FILE'		=> 'IMG_EM_KEY_2',
+	 # 'EL_EM_KEY_3_FILE'		=> 'IMG_EM_KEY_3',
+	 # 'EL_EM_KEY_4_FILE'		=> 'IMG_EM_KEY_4',
+
+	 # new elements which still have no graphic
+	 # 'EL_DOOR_WHITE',		=> 'IMG_CHAR_QUESTION',
+	 # 'EL_DOOR_WHITE_GRAY',	=> 'IMG_CHAR_QUESTION',
+	 # 'EL_KEY_WHITE',		=> 'IMG_CHAR_QUESTION',
+	 # 'EL_SIGN_RADIOACTIVITY',	=> 'IMG_CHAR_QUESTION',
+	 # 'EL_SIGN_WHEELCHAIR',	=> 'IMG_CHAR_QUESTION',
+	 # 'EL_SIGN_PARKING',		=> 'IMG_CHAR_QUESTION',
+	 # 'EL_SIGN_ONEWAY',		=> 'IMG_CHAR_QUESTION',
+	 # 'EL_SIGN_HEART',		=> 'IMG_CHAR_QUESTION',
+	 # 'EL_SIGN_TRIANGLE',		=> 'IMG_CHAR_QUESTION',
+	 # 'EL_SIGN_ROUND',		=> 'IMG_CHAR_QUESTION',
+	 # 'EL_SIGN_EXIT',		=> 'IMG_CHAR_QUESTION',
+	 # 'EL_SIGN_YINYANG',		=> 'IMG_CHAR_QUESTION',
+	 # 'EL_SIGN_OTHER',		=> 'IMG_CHAR_QUESTION',
+	 'EL_SIGN_UNUSED_1',		=> 'IMG_CHAR_QUESTION',
+	 'EL_SIGN_UNUSED_2',		=> 'IMG_CHAR_QUESTION',
+	 'EL_DX_UNKNOWN_15',		=> 'IMG_CHAR_QUESTION',
+	 'EL_DX_UNKNOWN_42',		=> 'IMG_CHAR_QUESTION',
+
+	 # file elements with direction which is not defined
+	 'EL_BD_BUTTERFLY_LEFT'		=> 'IMG_BD_BUTTERFLY',
+	 'EL_BD_BUTTERFLY_RIGHT'	=> 'IMG_BD_BUTTERFLY',
+	 'EL_BD_BUTTERFLY_UP'		=> 'IMG_BD_BUTTERFLY',
+	 'EL_BD_BUTTERFLY_DOWN'		=> 'IMG_BD_BUTTERFLY',
+	 'EL_BD_FIREFLY_LEFT'		=> 'IMG_BD_FIREFLY',
+	 'EL_BD_FIREFLY_RIGHT'		=> 'IMG_BD_FIREFLY',
+	 'EL_BD_FIREFLY_UP'		=> 'IMG_BD_FIREFLY',
+	 'EL_BD_FIREFLY_DOWN'		=> 'IMG_BD_FIREFLY',
+	 );
+
+    my @unknown_graphics = ();
+    my %known_element     = get_known_element_definitions();
+    my %known_action      = get_known_action_definitions();
+    my %known_special_arg = get_known_special_arg_definitions();
+    my %known_direction =
+	(
+	 'LEFT'		=> 1,
+	 'RIGHT'	=> 1,
+	 'UP'		=> 1,
+	 'DOWN'		=> 1,
+	 'UPLEFT'	=> 1,
+	 'UPRIGHT'	=> 1,
+	 'DOWNLEFT'	=> 1,
+	 'DOWNRIGHT'	=> 1,
+	 );
+
+    # ---------- read graphic file definitions ----------
+
+    my $filename = "$src_path/conf_gfx.c";
+
+    print_file_header($filename_conf_e2g_c, $text_e2g_c);
+
+    open(FILE, "$filename") ||
+	fail("cannot open file '$filename' for reading");
+
+    print "static struct\n";
+    print "{\n";
+    print "  int element;\n";
+    print "  int action;\n";
+    print "  int direction;\n";
+    print "  boolean crumbled;\n";
+    print "\n";
+    print "  int graphic;\n";
+    print "}\n";
+    print "element_to_graphic[] =\n";
+    print "{\n";
+
+    while (<FILE>)
+    {
+	chomp;				# cut trailing newline
+
+	if (/NO_MORE_ELEMENT_IMAGES/)	# keyword to stop parsing file
+	{
+	    last;
+	}
+
+	if (!contains_image_file($_))	# skip all lines without image file
+	{
+	    next;
+	}
+
+	s/^  \{ \"//;			# cut all leading ...
+	s/\",.*$//;			# ... and trailing garbage
+
+	s/\[(\d+)\]/_$1/;		# convert "[1]" to "_1" etc.
+
+	s/\[//;				# dirty hack for making "[default]" ...
+	s/\]//;				# ... work as an element name
+
+	my $token = $_;
+
+	if ($token =~ /\.([^\.]+)$/ && defined($known_special_arg{$1}))
+	{
+	    next;			# skip all special definitions
+	}
+
+	$token = uc($token);		# convert all characters to upper case
+
+	my $gfx_action_default = '-1';
+	my $gfx_action = $gfx_action_default;
+
+	my $gfx_direction_default = '-1';
+	my $gfx_direction = $gfx_direction_default;
+
+	my $gfx_crumbled = '0';
+
+	my $object = $token;
+	my $action = '';
+	my $direction = '';
+	my $crumbled = '';
+
+	if ($object =~ /^(.*)\.([A-Z0-9]+)$/ && $2 eq 'CRUMBLED')
+	{
+	    $object = $1;
+	    $crumbled = $2;
+
+	    $gfx_crumbled = '1';
+	}
+
+	if ($object =~ /^(.*)\.([A-Z0-9]+)$/ && defined($known_direction{$2}))
+	{
+	    $object = $1;
+	    $direction = $2;
+
+	    $gfx_direction = "MV_BIT_$direction";
+	    $gfx_direction_default = $gfx_direction;
+	}
+
+	if ($object =~ /^(.*)\.([A-Z0-9_]+)$/ && defined($known_action{$2}))
+	{
+	    $object = $1;
+	    $action = $2;
+
+	    $gfx_action = "ACTION_$action";
+	    $gfx_action_default = $gfx_action;
+	}
+
+	$token =~ s/\./_/g;
+	$object =~ s/\./_/g;	# needed for "invisible_sand.active.digging"
+
+	# print STDERR "'$token' => '$object', '$action', '$direction'\n";
+
+	my $full_element = "EL_$token";
+	my $base_element = "EL_$object";
+
+	my $element = $base_element;
+	my $graphic = "IMG_$token";
+
+	my $element_without_crumbled = $full_element;
+	$element_without_crumbled =~ s/_$crumbled$//;
+
+	my $element_without_direction = $element_without_crumbled;
+	$element_without_direction =~ s/_$direction$//;
+
+	my $element_without_action = $element_without_direction;
+	$element_without_action =~ s/_$action$//;
+
+	if (defined($known_element{$full_element}))
+	{
+	    $element = $full_element;
+
+	    $gfx_action_default = '-1';
+	    $gfx_direction_default = '-1';
+	}
+
+	if ($element_without_action eq $element || $action eq '')
+	{
+	    $element_without_action = '';
+	}
+
+	if ($element_without_direction eq $element || $direction eq '')
+	{
+	    $element_without_direction = '';
+	}
+
+	if ($element_without_crumbled eq $element || $crumbled eq '')
+	{
+	    $element_without_crumbled = '';
+	}
+
+	if (defined($graphic_without_element{$graphic}))
+	{
+	    next;
+	}
+
+	if (!defined($known_element{$element}))
+	{
+	    # print STDERR "----- ERROR: unknown element '$element' -----\n";
+
+	    push @unknown_graphics, $graphic;
+
+	    next;
+	}
+
+	if (defined($known_element{$element}))
+	{
+	    print_element_to_graphic_entry($element,
+					   $gfx_action_default,
+					   $gfx_direction_default,
+					   $gfx_crumbled,
+					   $graphic);
+	}
+
+	if (defined($known_element{$element_without_action}))
+	{
+	    print_element_to_graphic_entry($element_without_action,
+					   $gfx_action,
+					   '-1',
+					   $gfx_crumbled,
+					   $graphic);
+	}
+
+	if (defined($known_element{$element_without_direction}))
+	{
+	    print_element_to_graphic_entry($element_without_direction,
+					   '-1',
+					   $gfx_direction,
+					   $gfx_crumbled,
+					   $graphic);
+	}
+
+	if (defined($known_element{$element_without_crumbled}))
+	{
+	    print_element_to_graphic_entry($element_without_crumbled,
+					   '-1',
+					   '-1',
+					   $gfx_crumbled,
+					   $graphic);
+	}
+    }
+
+    # dump list of additional elements
+    foreach my $element (sort keys %additional_mappings)
+    {
+	print_element_to_graphic_entry($element, '-1', '-1', '-1',
+				       $additional_mappings{$element});
+    }
+
+    # dump list of character elements
+    foreach my $char (@chars)
+    {
+	my $element = "EL_CHAR_$char";
+	my $graphic = "IMG_CHAR_$char";
+
+	if ($char ne $char_skip)
+	{
+	    print_element_to_graphic_entry($element, '-1', '-1', '-1',$graphic);
+	}
+    }
+    foreach my $char (@chars)
+    {
+	my $element = "EL_STEEL_CHAR_$char";
+	my $graphic = "IMG_STEEL_CHAR_$char";
+
+	if ($char ne $char_skip)
+	{
+	    print_element_to_graphic_entry($element, '-1', '-1', '-1',$graphic);
+	}
+    }
+
+    # dump list of custom elements
+    for (my $i = 0; $i < $num_custom_elements; $i++)
+    {
+	my $element = sprintf("EL_CUSTOM_%d", $i + 1);
+	my $graphic = sprintf("IMG_CUSTOM_%d", $i + 1);
+
+	print_element_to_graphic_entry($element, '-1', '-1', '-1', $graphic);
+    }
+
+    # dump list of group elements
+    for (my $i = 0; $i < $num_group_elements; $i++)
+    {
+	my $element = sprintf("EL_GROUP_%d", $i + 1);
+	my $graphic = sprintf("IMG_GROUP_%d", $i + 1);
+
+	print_element_to_graphic_entry($element, '-1', '-1', '-1', $graphic);
+    }
+
+    print_element_to_graphic_entry('-1', '-1', '-1', '-1', '-1');
+
+    print "};\n";
+
+    close FILE;
+
+    if (scalar(@unknown_graphics) > 0)
+    {
+	print STDERR "-" x 79 . "\n";
+	print STDERR "The following graphics cannot be associated with any element:\n";
+
+	foreach my $graphic (@unknown_graphics)
+	{
+	    print STDERR "- $graphic\n";
+	}
+
+	print STDERR "-" x 79 . "\n";
+    }
+
+    print_file_footer($filename_conf_e2g_c);
+}
+
+sub print_element_to_special_graphic_list
+{
+    my %graphic_without_element =
+	(
+	 'IMG_GLOBAL_DOOR'		=> 1,
+	 );
+
+    my %additional_mappings =
+	(
+	 # old elements which are mapped to other elements when playing
+	 #'EL_BUG'			=> 'IMG_BUG_RIGHT',
+	 #'EL_SPACESHIP'		=> 'IMG_SPACESHIP_RIGHT',
+	 #'EL_PACMAN'			=> 'IMG_PACMAN_RIGHT',
+	 );
+
+    my @elements_with_editor_graphic =
+	(
+	 'char_space'
+	 );
+
+    my @unknown_graphics = ();
+    my %known_element     = get_known_element_definitions();
+    my %known_special_arg = get_known_special_arg_definitions();
+
+    # ---------- read graphic file definitions ----------
+
+    my $filename = "$src_path/conf_gfx.c";
+
+    print_file_header($filename_conf_esg_c, $text_esg_c);
+
+    open(FILE, "$filename") ||
+	fail("cannot open file '$filename' for reading");
+
+    print "static struct\n";
+    print "{\n";
+    print "  int element;\n";
+    print "  int special;\n";
+    print "\n";
+    print "  int graphic;\n";
+    print "}\n";
+    print "element_to_special_graphic[] =\n";
+    print "{\n";
+
+    while (<FILE>)
+    {
+	chomp;				# cut trailing newline
+
+	if (/NO_MORE_ELEMENT_IMAGES/)	# keyword to stop parsing file
+	{
+	    last;
+	}
+
+	if (!contains_image_file($_))	# skip all lines without image file
+	{
+	    next;
+	}
+
+	s/^  \{ \"//;			# cut all leading ...
+	s/\",.*$//;			# ... and trailing garbage
+
+	my $token = $_;
+	my $object;
+	my $special;
+
+	if ($token =~ /^font\./)	# skip all font definitions
+	{
+	    next;
+	}
+
+	if ($token =~ /^background\./)	# skip all background image definitions
+	{
+	    next;
+	}
+
+	if ($token =~ /^(.*)\.([^\.]+)$/ &&
+	    defined($known_special_arg{$2}))
+	{
+	    $object = $1;
+	    $special = "GFX_SPECIAL_ARG_" . $2;
+	}
+	else
+	{
+	    next;			# skip all default definitions
+	}
+
+	$token  =~ s/(.*)/uc($1)/eg;	# convert all characters to upper case
+	$object =~ s/(.*)/uc($1)/eg;	# convert all characters to upper case
+
+	$token  =~ s/\./_/g;
+	$object =~ s/\./_/g;
+
+	# print STDERR "'$token' => '$object'\n";
+
+	my $element = "EL_$object";
+	my $graphic = "IMG_$token";
+
+	if (defined($graphic_without_element{$graphic}))
+	{
+	    next;
+	}
+
+	if (!defined($known_element{$element}))
+	{
+	    # print STDERR "----- ERROR: unknown element '$element' -----\n";
+
+	    push @unknown_graphics, $graphic;
+
+	    next;
+	}
+
+	print_element_to_special_graphic_entry($element,
+					       $special,
+					       $graphic);
+    }
+
+    # dump list of additional elements
+    foreach my $element (sort keys %additional_mappings)
+    {
+	print_element_to_special_graphic_entry($element,
+					       'GFX_SPECIAL_ARG_EDITOR',
+					       $additional_mappings{$element});
+	print_element_to_special_graphic_entry($element,
+					       'GFX_SPECIAL_ARG_PREVIEW',
+					       $additional_mappings{$element});
+    }
+
+    # dump list of custom element editor graphics
+    for (my $i = 0; $i < $num_custom_elements; $i++)
+    {
+	my $element = sprintf("EL_CUSTOM_%d", $i + 1);
+	my $graphic = sprintf("IMG_CUSTOM_%d_EDITOR", $i + 1);
+
+	print_element_to_special_graphic_entry($element,
+					       'GFX_SPECIAL_ARG_EDITOR',
+					       $graphic);
+    }
+
+    # dump list of group element editor graphics
+    for (my $i = 0; $i < $num_group_elements; $i++)
+    {
+	my $element = sprintf("EL_GROUP_%d", $i + 1);
+	my $graphic = sprintf("IMG_GROUP_%d_EDITOR", $i + 1);
+
+	print_element_to_special_graphic_entry($element,
+					       'GFX_SPECIAL_ARG_EDITOR',
+					       $graphic);
+    }
+
+    # dump other special editor graphics
+    foreach my $token (@elements_with_editor_graphic)
+    {
+	my $element = 'EL_'  . uc($token);
+	my $graphic = 'IMG_' . uc($token) . '_EDITOR';
+
+	print_element_to_special_graphic_entry($element,
+					       'GFX_SPECIAL_ARG_EDITOR',
+					       $graphic);
+    }
+
+    print_element_to_special_graphic_entry('-1', '-1', '-1');
+
+    print "};\n";
+
+    close FILE;
+
+    if (scalar(@unknown_graphics) > 0)
+    {
+	print STDERR "-" x 79 . "\n";
+	print STDERR "The following graphics cannot be associated with any element:\n";
+
+	foreach my $graphic (@unknown_graphics)
+	{
+	    print STDERR "- $graphic\n";
+	}
+
+	print STDERR "-" x 79 . "\n";
+    }
+
+    print_file_footer($filename_conf_esg_c);
+}
+
+sub print_element_to_sound_list
+{
+    my %sound_without_action =
+	(
+	 'SND_AMOEBA_TURNING_TO_GEM'		=> 1,
+	 'SND_AMOEBA_TURNING_TO_ROCK'		=> 1,
+	 'SND_BD_AMOEBA_TURNING_TO_GEM'		=> 1,
+	 'SND_BD_AMOEBA_TURNING_TO_ROCK'	=> 1,
+
+	 # no special case anymore after adding action ".splashing"
+	 # 'SND_ACID_SPLASHING'			=> 1,
+	 );
+
+    my @unknown_sounds = ();
+    my %known_element       = get_known_element_definitions();
+    my %known_element_class = get_known_element_class_definitions();
+    my %known_action        = get_known_action_definitions();
+
+    # ---------- read sound file definitions ----------
+
+    my $filename = "$src_path/conf_snd.c";
+
+    print_file_header($filename_conf_e2s_c, $text_e2s_c);
+
+    open(FILE, "$filename") ||
+	fail("cannot open file '$filename' for reading");
+
+    print "static struct\n";
+    print "{\n";
+    print "  int element;\n";
+    print "  boolean is_class;\n";
+    print "  int action;\n";
+    print "\n";
+    print "  int sound;\n";
+    print "}\n";
+    print "element_to_sound[] =\n";
+    print "{\n";
+
+    while (<FILE>)
+    {
+	chomp;				# cut trailing newline
+
+	if (/NO_MORE_ELEMENT_SOUNDS/)	# keyword to stop parsing file
+	{
+	    last;
+	}
+
+	if (!contains_sound_file($_))	# skip all lines without sound file
+	{
+	    next;
+	}
+
+	s/^  \{ \"//;			# cut all leading ...
+	s/\",.*$//;			# ... and trailing garbage
+
+	my $token = $_;
+
+	$token = uc($token);		# convert all characters to upper case
+
+	my $snd_action_default = '-1';
+	my $snd_action = $snd_action_default;
+
+	my $object = $token;
+	my $action = '';
+
+	if ($object =~ /^(.*)\.([A-Z0-9_]+)$/ && defined($known_action{$2}))
+	{
+	    $object = $1;
+	    $action = $2;
+
+	    $snd_action = "ACTION_$action";
+	    $snd_action_default = $snd_action;
+	}
+
+	$token =~ s/\./_/g;
+	$object =~ s/\./_/g;	# needed for "invisible_sand.active.digging"
+
+	if ($object =~ /^\[(.+)\]$/)
+	{
+	    $object = 'CLASS_' . $1;
+	}
+
+	# print STDERR "'$token' => '$object', '$action'\n";
+
+	my $full_element = "EL_$token";
+	my $base_element = "EL_$object";
+
+	my $element = $base_element;
+	my $sound = $token;
+
+	if ($sound =~ /^\[.+\]/)
+	{
+	    $sound =~ s/\[//;		# element class sound; begin ...
+	    $sound =~ s/\]//;		# ... and end of definition token
+	    $sound =~ s/^/CLASS_/;	# add class identifier
+ 	}
+
+	$sound = "SND_$sound";
+
+	my $element_without_action = $full_element;
+	$element_without_action =~ s/_$action$//;
+
+	my $element_class_without_action = $full_element;
+	$element_without_action =~ s/_$action$//;
+
+	if (defined($known_element_class{$full_element}))
+	{
+	    $element = $full_element;
+
+	    $snd_action_default = '-1';
+	}
+
+	if ($element_without_action eq $element || $action eq '')
+	{
+	    $element_without_action = '';
+	}
+
+	if (defined($sound_without_action{$sound}))
+	{
+	    next;
+	}
+
+	if (!defined($known_element{$element}) &&
+	    !defined($known_element_class{$element}))
+	{
+	    # print STDERR "----- ERROR: unknown element '$element' -----\n";
+
+	    push @unknown_sounds, $sound;
+
+	    next;
+	}
+
+	if (!($element =~ /_CLASS_/) &&
+	    defined($known_element{$element}))
+	{
+	    print_element_to_sound_entry($element, "FALSE",
+					 $snd_action_default,
+					 $sound);
+	}
+
+	if (!($element =~ /_CLASS_/) &&
+	    defined($known_element{$element_without_action}))
+	{
+	    print_element_to_sound_entry($element_without_action, "FALSE",
+					 $snd_action,
+					 $sound);
+	}
+
+	if ($element =~ /_CLASS_/ &&
+	    defined($known_element_class{$element}))
+	{
+	    my $class_element = $known_element_class{$element};
+
+	    print_element_to_sound_entry($class_element, "TRUE",
+					 $snd_action_default,
+					 $sound);
+	}
+
+	if ($element =~ /_CLASS_/ &&
+	    defined($known_element_class{$element_without_action}))
+	{
+	    my $class_element = $known_element_class{$element_without_action};
+
+	    print_element_to_sound_entry($class_element, "TRUE",
+					 $snd_action,
+					 $sound);
+	}
+    }
+
+    print_element_to_sound_entry('-1', '-1', '-1', '-1');
+
+    print "};\n";
+
+    close FILE;
+
+    if (scalar(@unknown_sounds) > 0)
+    {
+	print STDERR "-" x 79 . "\n";
+	print STDERR "The following sounds cannot be associated with any element or element class:\n";
+
+	foreach my $sound (@unknown_sounds)
+	{
+	    print STDERR "- $sound\n";
+	}
+
+	print STDERR "-" x 79 . "\n";
+    }
+
+    print_file_footer($filename_conf_e2s_c);
+}
+
+sub print_font_to_graphic_list
+{
+    my @unknown_graphics = ();
+    my %known_font        = get_known_font_definitions();
+    my %known_special_arg = get_known_special_arg_definitions();
+
+    # ---------- read graphic file definitions ----------
+
+    my $filename = "$src_path/conf_gfx.c";
+
+    print_file_header($filename_conf_fnt_c, $text_fnt_c);
+
+    open(FILE, "$filename") ||
+	fail("cannot open file '$filename' for reading");
+
+    print "static struct\n";
+    print "{\n";
+    print "  int font_nr;\n";
+    print "  int special;\n";
+    print "\n";
+    print "  int graphic;\n";
+    print "}\n";
+    print "font_to_graphic[] =\n";
+    print "{\n";
+
+    while (<FILE>)
+    {
+	chomp;				# cut trailing newline
+
+	if (!contains_image_file($_))	# skip all lines without image file
+	{
+	    next;
+	}
+
+	s/^  \{ \"//;			# cut all leading ...
+	s/\",.*$//;			# ... and trailing garbage
+
+	my $token = $_;
+	my $font;
+	my $special;
+	my $graphic;
+
+	if ($token =~ /^(font\..*)$/)
+	{
+	    $font = $token;
+	    $special = '-1';
+
+	    if ($token =~ /^(.*)\.([^\.]+)$/ &&
+		defined($known_special_arg{$2}))
+	    {
+		$font = $1;
+		$special = "GFX_SPECIAL_ARG_" . $2;
+	    }
+	}
+	else
+	{
+	    next;			# skip all non-font definitions
+	}
+
+	$token =~ s/(.*)/uc($1)/eg;	# convert all characters to upper case
+	$font  =~ s/(.*)/uc($1)/eg;	# convert all characters to upper case
+
+	$token =~ s/\./_/g;
+	$font  =~ s/\./_/g;
+
+	# print STDERR "'$token' => '$font'\n";
+
+	$graphic = "IMG_$token";
+
+	if (!defined($known_font{$font}))
+	{
+	    # print STDERR "----- ERROR: unknown font '$font' -----\n";
+
+	    push @unknown_graphics, $graphic;
+
+	    next;
+	}
+
+	print_font_to_graphic_entry($font,
+				    $special,
+				    $graphic);
+    }
+
+    print_font_to_graphic_entry('-1', '-1', '-1');
+
+    print "};\n";
+
+    close FILE;
+
+    if (scalar(@unknown_graphics) > 0)
+    {
+	print STDERR "-" x 79 . "\n";
+	print STDERR "The following graphics cannot be associated with any font:\n";
+
+	foreach my $graphic (@unknown_graphics)
+	{
+	    print STDERR "- $graphic\n";
+	}
+
+	print STDERR "-" x 79 . "\n";
+    }
+
+    print_file_footer($filename_conf_fnt_c);
+}
+
+sub print_gamemode_to_sound_list
+{
+    my %known_prefix = get_known_sound_prefix_definitions();
+    my %known_special_arg = get_known_special_arg_definitions();
+
+    # ---------- read music file definitions ----------
+
+    my $filename = "$src_path/conf_snd.c";
+
+    print_file_header($filename_conf_g2s_c, $text_g2s_c);
+
+    open(FILE, "$filename") ||
+	fail("cannot open file '$filename' for reading");
+
+    print "static struct\n";
+    print "{\n";
+    print "  int gamemode;\n";
+    print "\n";
+    print "  int sound;\n";
+    print "}\n";
+    print "gamemode_to_sound[] =\n";
+    print "{\n";
+
+    while (<FILE>)
+    {
+	chomp;				# cut trailing newline
+
+	if (!contains_sound_file($_))	# skip all lines without sound file
+	{
+	    next;
+	}
+
+	if (/\[not used\]/)
+	{
+	    next;
+	}
+
+	s/^  \{ \"//;			# cut all leading ...
+	s/\",.*$//;			# ... and trailing garbage
+
+	my $token = $_;
+	my $gamemode = -1;
+	# my $level = -1;		# ???
+
+	if (defined($known_prefix{$token}))
+	{
+	    # no special arg defined
+	}
+	elsif ($token =~ /^(.*)\.([^\.]+)$/ &&
+	       defined($known_prefix{$1}) &&
+	       defined($known_special_arg{$2}))
+	{
+	    $gamemode = "GFX_SPECIAL_ARG_" . $2;
+	}
+	else
+	{
+	    next;
+	}
+
+#	if ($token =~ /^(.*)\./ &&
+#	    !defined($known_prefix{$1}))
+#	{
+#	    next;
+#	}
+#
+#	if ($token =~ /^(.*)\.([^\.]+)$/ &&
+#	    defined($known_special_arg{$2}))
+#	{
+#	    $gamemode = "GFX_SPECIAL_ARG_" . $2;
+#	}
+
+	$token =~ s/(.*)/uc($1)/eg;	# convert all characters to upper case
+	$token =~ s/\./_/g;
+
+	my $sound = "SND_$token";
+
+	# print STDERR "'$token' => '$sound'\n";
+
+	print_gamemode_to_sound_entry($gamemode, $sound);
+    }
+
+    print_gamemode_to_sound_entry('-1', '-1');
+
+    print "};\n";
+
+    close FILE;
+
+    print_file_footer($filename_conf_g2s_c);
+}
+
+sub print_gamemode_to_music_list
+{
+    my %known_prefix = get_known_music_prefix_definitions();
+    my %known_special_arg = get_known_special_arg_definitions();
+
+    # ---------- read music file definitions ----------
+
+    my $filename = "$src_path/conf_mus.c";
+
+    print_file_header($filename_conf_g2m_c, $text_g2m_c);
+
+    open(FILE, "$filename") ||
+	fail("cannot open file '$filename' for reading");
+
+    print "static struct\n";
+    print "{\n";
+    print "  int gamemode;\n";
+    print "\n";
+    print "  int music;\n";
+    print "}\n";
+    print "gamemode_to_music[] =\n";
+    print "{\n";
+
+    while (<FILE>)
+    {
+	chomp;				# cut trailing newline
+
+	if (!contains_music_file($_))	# skip all lines without music file
+	{
+	    next;
+	}
+
+	s/^  \{ \"//;			# cut all leading ...
+	s/\",.*$//;			# ... and trailing garbage
+
+	my $token = $_;
+	my $gamemode = -1;
+
+	if (defined($known_prefix{$token}))
+	{
+	    # no special arg defined
+	}
+	elsif ($token =~ /^(.*)\.([^\.]+)$/ &&
+	       defined($known_prefix{$1}) &&
+	       defined($known_special_arg{$2}))
+	{
+	    $gamemode = "GFX_SPECIAL_ARG_" . $2;
+	}
+	else
+	{
+	    next;
+	}
+
+#	my $prefix = $token;
+#	$prefix =~ s/\..*$//;
+#
+##	if ($token =~ /^(.*)\./ &&
+##	    !defined($known_prefix{$1}))
+#	if (!defined($known_prefix{$prefix}))
+#	{
+#	    next;
+#	}
+#
+#	if ($token =~ /^(.*)\.([^\.]+)$/ &&
+#	    defined($known_special_arg{$2}))
+#	{
+#	    $gamemode = "GFX_SPECIAL_ARG_" . $2;
+#	}
+
+	$token =~ s/(.*)/uc($1)/eg;	# convert all characters to upper case
+	$token =~ s/\./_/g;
+
+	my $music = "MUS_$token";
+
+	# print STDERR "'$token' => '$music'\n";
+
+	print_gamemode_to_music_entry($gamemode, $music);
+    }
+
+    print_gamemode_to_music_entry('-1', '-1');
+
+    print "};\n";
+
+    close FILE;
+
+    print_file_footer($filename_conf_g2m_c);
+}
+
+sub print_image_config_vars
+{
+    # ---------- read graphic file definitions ----------
+
+    my $filename = "$src_path/conf_gfx.c";
+
+    print_file_header($filename_conf_var_c, $text_var_c);
+
+    open(FILE, "$filename") ||
+	fail("cannot open file '$filename' for reading");
+
+    print "struct TokenIntPtrInfo image_config_vars[] =\n";
+    print "{\n";
+
+    my $start_parsing = 0;
+
+    while (<FILE>)
+    {
+	chomp;				# cut trailing newline
+
+	if (/CONFIG_VARS_START/)	# keyword to start parsing file
+	{
+	    $start_parsing = 1;
+	}
+
+	if (!$start_parsing)
+	{
+	    next;
+	}
+
+	if (/^\s*\{\s*\"([^\"]+)\"/)	# config token found
+	{
+	    my $token = $1;
+	    my $var = $token;
+
+	    # --- some prefix replacements ---
+
+	    $var =~ s/^main\./menu.main./;
+	    $var =~ s/^\[player\]\./game.player_/;
+	    $var =~ s/^\[title_initial\]/title_initial_default/;
+	    $var =~ s/^\[title\]/title_default/;
+	    $var =~ s/^\[titlescreen_initial\]/titlescreen_initial_default/;
+	    $var =~ s/^\[titlescreen\]/titlescreen_default/;
+	    $var =~ s/^\[titlemessage_initial\]/titlemessage_initial_default/;
+	    $var =~ s/^\[titlemessage\]/titlemessage_default/;
+
+	    if ($var =~ /^titlescreen.*(\d)/ ||
+		$var =~ /^titlemessage.*(\d)/ ||
+		$var =~ /^game.panel.key_(\d)/ ||
+		$var =~ /^game.panel.inventory_first_(\d)/ ||
+		$var =~ /^game.panel.inventory_last_(\d)/ ||
+		$var =~ /^game.panel.conveyor_belt_(\d)\./ ||
+		$var =~ /^game.panel.element_(\d)\./ ||
+		$var =~ /^game.panel.graphic_(\d)\./ ||
+		$var =~ /^game.panel.ce_score_(\d)\./)
+	    {
+		my $number = $1;
+		my $array_pos = int($number) - 1;
+		$var =~ s/_$number/\[$array_pos\]/;
+	    }
+	    elsif ($var =~ /^game.panel.conveyor_belt_(\d)(_switch)/ ||
+		   $var =~ /^game.panel.element_(\d)(_count)/ ||
+		   $var =~ /^game.panel.ce_score_(\d)(_element)/)
+	    {
+		my $number = $1;
+		my $suffix = $2;
+		my $array_pos = int($number) - 1;
+		$var =~ s/_$number$suffix/$suffix\[$array_pos\]/;
+	    }
+
+	    # --- some suffix replacements ---
+
+	    $var =~ s/^(menu\.main\..*)\.chars$/$1.size/;
+	    $var =~ s/^(tape\.text\..*)\.chars$/$1.size/;
+	    $var =~ s/^(game\.panel\..*)\.chars$/$1.size/;
+	    $var =~ s/^(game\.panel\..*)\.tile_size$/$1.size/;
+	    $var =~ s/^(request\.button\..*)\.tile_size$/$1.size/;
+	    $var =~ s/\.digits$/.size/;
+	    $var =~ s/\.2nd_offset$/.offset2/;
+	    $var =~ s/\.2nd_xoffset$/.xoffset2/;
+	    $var =~ s/\.2nd_yoffset$/.yoffset2/;
+	    $var =~ s/\.element$/.id/;
+	    $var =~ s/\.draw_order$/.sort_priority/;
+
+	    $var =~ s/\.font_[a-z]+$/.font_alt/;
+	    $var =~ s/\.INFO\[([A-Z]+)\]$/_info\[GFX_SPECIAL_ARG_INFO_$1\]/;
+	    $var =~ s/\.SETUP\[([A-Z0-9_]+)\]$/_setup\[GFX_SPECIAL_ARG_SETUP_$1\]/;
+	    $var =~ s/\.([A-Z]+)$/\[GFX_SPECIAL_ARG_$1\]/;
+	    $var =~ s/\.([A-Z]+)\./\[GFX_SPECIAL_ARG_$1\]./;
+
+	    if ($var =~ /^(menu.(enter|leave|next)_screen)(.[a-z_]+)$/)
+	    {
+		$var = $1 . "[GFX_SPECIAL_ARG_DEFAULT]" . $3;
+	    }
+
+	    if ($var =~ /^menu.(draw_[xy]offset|list_size)$/)
+	    {
+		$var .= "[GFX_SPECIAL_ARG_DEFAULT]";
+	    }
+
+	    if ($var =~ /^(viewport.(window|playfield|door_[12]))(.[a-z_]+)$/)
+	    {
+		$var = $1 . "[GFX_SPECIAL_ARG_DEFAULT]" . $3;
+	    }
+
+	    print_image_config_var_entry("\"$token\"", "&$var");
+
+	    if ($var =~ /^(title)_default/ ||
+		$var =~ /^(title_initial)_default/ ||
+		$var =~ /^(titlescreen.*)\[\d\]/ ||
+		$var =~ /^(titlemessage.*)\[\d\]/)
+	    {
+		my $prefix = $1;
+		$var =~ s/^$prefix/${prefix}_first/;
+
+		print_image_config_var_entry("\"$token\"", "&$var");
+	    }
+	}
+    }
+
+    print_image_config_var_entry('NULL', 'NULL');
+
+    print "};\n";
+
+    close FILE;
+
+    print_file_footer($filename_conf_var_c);
+}
+
+sub print_active_states
+{
+    # ---------- read graphic file definitions ----------
+
+    my %known_element = get_known_element_definitions();
+    my %known_button  = get_known_button_definitions();
+    my %known_font    = get_known_font_definitions();
+
+    print_file_header($filename_conf_act_c, $text_act_c);
+
+    print "static struct\n";
+    print "{\n";
+    print "  int element;\n";
+    print "  int element_active;\n";
+    print "}\n";
+    print "element_with_active_state[] =\n";
+    print "{\n";
+
+    foreach my $element (sort keys %known_element)
+    {
+	my $element_active = $element . '_ACTIVE';
+
+	if (defined($known_element{$element_active}))
+	{
+	    print_active_state_entry($element, $element_active);
+	}
+    }
+
+    print_active_state_entry('-1', '-1');
+
+    print "};\n";
+
+    print "\n";
+    print "\n";
+    print "static struct\n";
+    print "{\n";
+    print "  int button;\n";
+    print "  int button_active;\n";
+    print "}\n";
+    print "button_with_active_state[] =\n";
+    print "{\n";
+
+    foreach my $button (sort keys %known_button)
+    {
+	my $button_active = $button . '_ACTIVE';
+
+	if (defined($known_button{$button_active}))
+	{
+	    print_active_state_entry($button, $button_active);
+	}
+    }
+
+    print_active_state_entry('-1', '-1');
+
+    print "};\n";
+
+    print "\n";
+    print "\n";
+    print "static struct\n";
+    print "{\n";
+    print "  int font_nr;\n";
+    print "  int font_nr_active;\n";
+    print "}\n";
+    print "font_with_active_state[] =\n";
+    print "{\n";
+
+    foreach my $font (sort keys %known_font)
+    {
+	my $font_active = $font . '_ACTIVE';
+
+	if (defined($known_font{$font_active}))
+	{
+	    print_active_state_entry($font, $font_active);
+	}
+    }
+
+    print_active_state_entry('-1', '-1');
+
+    print "};\n";
+
+    print_file_footer($filename_conf_act_c);
+}
+
+
+# =============================================================================
+# M A I N - P R O G R A M
+# =============================================================================
+
+sub main
+{
+    my $argc = scalar(@ARGV);
+
+    if ($argc == 0 || $ARGV[0] eq '-h' || $ARGV[0] eq '--help')
+    {
+	print "Usage: $0 <file>\n\n";
+	print "Choose <file> from the following list:\n";
+	print "- '$filename_conf_gfx_h'\n";
+	print "- '$filename_conf_snd_h'\n";
+	print "- '$filename_conf_mus_h'\n";
+	print "- '$filename_conf_chr_c'\n";
+	print "- '$filename_conf_chr_h'\n";
+	print "- '$filename_conf_cus_c'\n";
+	print "- '$filename_conf_cus_h'\n";
+	print "- '$filename_conf_grp_c'\n";
+	print "- '$filename_conf_grp_h'\n";
+	print "- '$filename_conf_e2g_c'\n";
+	print "- '$filename_conf_esg_c'\n";
+	print "- '$filename_conf_fnt_c'\n";
+	print "- '$filename_conf_g2s_c'\n";
+	print "- '$filename_conf_g2m_c'\n";
+	print "- '$filename_conf_var_c'\n";
+	print "- '$filename_conf_act_c'\n";
+
+	exit 1;
+    }
+
+    if ($ARGV[0] eq $filename_conf_gfx_h)
+    {
+	print_graphics_list();
+    }
+    elsif ($ARGV[0] eq $filename_conf_snd_h)
+    {
+	print_sounds_list();
+    }
+    elsif ($ARGV[0] eq $filename_conf_mus_h)
+    {
+	print_music_list();
+    }
+    elsif ($ARGV[0] eq $filename_conf_chr_c)
+    {
+	print_chars_graphics_list();
+    }
+    elsif ($ARGV[0] eq $filename_conf_chr_h)
+    {
+	print_chars_elements_list();
+    }
+    elsif ($ARGV[0] eq $filename_conf_cus_c)
+    {
+	print_custom_graphics_list();
+    }
+    elsif ($ARGV[0] eq $filename_conf_cus_h)
+    {
+	print_custom_elements_list();
+    }
+    elsif ($ARGV[0] eq $filename_conf_grp_c)
+    {
+	print_group_graphics_list();
+    }
+    elsif ($ARGV[0] eq $filename_conf_grp_h)
+    {
+	print_group_elements_list();
+    }
+    elsif ($ARGV[0] eq $filename_conf_e2g_c)
+    {
+	print_element_to_graphic_list();
+    }
+    elsif ($ARGV[0] eq $filename_conf_esg_c)
+    {
+	print_element_to_special_graphic_list();
+    }
+    elsif ($ARGV[0] eq $filename_conf_e2s_c)
+    {
+	print_element_to_sound_list();
+    }
+    elsif ($ARGV[0] eq $filename_conf_fnt_c)
+    {
+	print_font_to_graphic_list();
+    }
+    elsif ($ARGV[0] eq $filename_conf_g2s_c)
+    {
+	print_gamemode_to_sound_list();
+    }
+    elsif ($ARGV[0] eq $filename_conf_g2m_c)
+    {
+	print_gamemode_to_music_list();
+    }
+    elsif ($ARGV[0] eq $filename_conf_var_c)
+    {
+	print_image_config_vars();
+    }
+    elsif ($ARGV[0] eq $filename_conf_act_c)
+    {
+	print_active_states();
+    }
+    else
+    {
+	print "Unknown option '$ARGV[0]'.\n";
+
+	exit 1;
+    }
+
+    exit 0;
+}
diff --git a/docs/elements/amoeba_dry.txt b/docs/elements/amoeba_dry.txt
index 30c374e..49b67b4 100644
--- a/docs/elements/amoeba_dry.txt
+++ b/docs/elements/amoeba_dry.txt
@@ -1,6 +1,6 @@
-This is regular amoeba. If, when it attempt to grow, it is blocked in all
-directions by something other than the player, it will die. Amoeba will kill
-any bugs, flies, or spaceships that touch it.
-
-The amoeba growth value is the same for all types of amoeba.
-Amoeba will take between 0 and [25/(1-value)] seconds to attempt to grow.
+This is regular amoeba. If, when it attempt to grow, it is blocked in all
+directions by something other than the player, it will die. Amoeba will kill
+any bugs, flies, or spaceships that touch it.
+
+The amoeba growth value is the same for all types of amoeba.
+Amoeba will take between 0 and [25/(1-value)] seconds to attempt to grow.
diff --git a/docs/elements/amoeba_full.txt b/docs/elements/amoeba_full.txt
index 763c986..47cb8e4 100644
--- a/docs/elements/amoeba_full.txt
+++ b/docs/elements/amoeba_full.txt
@@ -1,4 +1,4 @@
-When this amoeba is completely surrounded, it gradually turns into the
-specified content.
-
-All amoeba types must share the same settings.
+When this amoeba is completely surrounded, it gradually turns into the
+specified content.
+
+All amoeba types must share the same settings.
diff --git a/docs/elements/amoeba_wet.txt b/docs/elements/amoeba_wet.txt
index 0b99b89..7b2275d 100644
--- a/docs/elements/amoeba_wet.txt
+++ b/docs/elements/amoeba_wet.txt
@@ -1,5 +1,5 @@
-Dripping amoeba will grow in drops, and will not die even if surrounded.
-Amoeba will kill any bugs, flies, or spaceships that touch it.
-
-The amoeba growth value is the same for all types of amoeba.
-Amoeba will take between 0 and [25/(1-value)] seconds to attempt to grow.
+Dripping amoeba will grow in drops, and will not die even if surrounded.
+Amoeba will kill any bugs, flies, or spaceships that touch it.
+
+The amoeba growth value is the same for all types of amoeba.
+Amoeba will take between 0 and [25/(1-value)] seconds to attempt to grow.
diff --git a/docs/elements/bd_amoeba.txt b/docs/elements/bd_amoeba.txt
index fb6e5a5..47016a6 100644
--- a/docs/elements/bd_amoeba.txt
+++ b/docs/elements/bd_amoeba.txt
@@ -1,7 +1,7 @@
-The BD style amoeba has some special properties: When it is completely
-surrounded, it instantly turns into the specified content. But if this
-cannot be achieved in a certain amount of time, this amoeba instantly
-turns to BD boulders instead. BD amoeba is the only amoeba that can be
-smothered by the player.
-
-All amoeba types must share the same settings.
+The BD style amoeba has some special properties: When it is completely
+surrounded, it instantly turns into the specified content. But if this
+cannot be achieved in a certain amount of time, this amoeba instantly
+turns to BD boulders instead. BD amoeba is the only amoeba that can be
+smothered by the player.
+
+All amoeba types must share the same settings.
diff --git a/docs/elements/bd_butterfly.txt b/docs/elements/bd_butterfly.txt
index 808f27c..ac23f35 100644
--- a/docs/elements/bd_butterfly.txt
+++ b/docs/elements/bd_butterfly.txt
@@ -1,6 +1,6 @@
-Butterflies always try to follow the right side of a wall or other elements.
-Touching them is deadly.
-
-They will explode in 9 BD style diamonds if smashed by a rock or BD style
-diamond. If dynabombed, they will become one BD style diamond.
-Other explosions simply destroy them.
+Butterflies always try to follow the right side of a wall or other elements.
+Touching them is deadly.
+
+They will explode in 9 BD style diamonds if smashed by a rock or BD style
+diamond. If dynabombed, they will become one BD style diamond.
+Other explosions simply destroy them.
diff --git a/docs/elements/bd_firefly.txt b/docs/elements/bd_firefly.txt
index 03f45ba..564dc2f 100644
--- a/docs/elements/bd_firefly.txt
+++ b/docs/elements/bd_firefly.txt
@@ -1,4 +1,4 @@
-Fireflies always try to follow the left side of a wall or other elements.
-Touching them is deadly.
-
-Fireflies can be smashed by BD style diamonds in addition to rocks.
+Fireflies always try to follow the left side of a wall or other elements.
+Touching them is deadly.
+
+Fireflies can be smashed by BD style diamonds in addition to rocks.
diff --git a/docs/elements/bd_magic_wall.txt b/docs/elements/bd_magic_wall.txt
index 06b519a..3800be9 100644
--- a/docs/elements/bd_magic_wall.txt
+++ b/docs/elements/bd_magic_wall.txt
@@ -1,7 +1,7 @@
-This is a (BD style) magic wall. It gets activated for about 10 seconds by
-rocks or gems that fall on it. Rocks that fall through it become BD style
-diamonds, and gems that fall through it become BD style rocks. After it has
-stopped running, it cannot be activated again.
-
-All BD magic walls run on the same timer; however, regular magic walls run
-on a seperate timer.
+This is a (BD style) magic wall. It gets activated for about 10 seconds by
+rocks or gems that fall on it. Rocks that fall through it become BD style
+diamonds, and gems that fall through it become BD style rocks. After it has
+stopped running, it cannot be activated again.
+
+All BD magic walls run on the same timer; however, regular magic walls run
+on a seperate timer.
diff --git a/docs/elements/bd_wall.txt b/docs/elements/bd_wall.txt
index a76fc18..3cb9ffa 100644
--- a/docs/elements/bd_wall.txt
+++ b/docs/elements/bd_wall.txt
@@ -1,6 +1,6 @@
-This is the BD style wall.
-
-Unlike most other walls, falling objects slip off this wall,
-although it does not look rounded or crumbled.
-
-It can be destroyed by explosions.
+This is the BD style wall.
+
+Unlike most other walls, falling objects slip off this wall,
+although it does not look rounded or crumbled.
+
+It can be destroyed by explosions.
diff --git a/docs/elements/bug.txt b/docs/elements/bug.txt
index e5ed4d9..c21a098 100644
--- a/docs/elements/bug.txt
+++ b/docs/elements/bug.txt
@@ -1,5 +1,5 @@
-Bugs always try to follow the right side of a wall
-or other elements. Touching them is deadly.
-
-Bugs will explode into a diamond surrounded by 8 emeralds,
-even when caught in other explosions!
+Bugs always try to follow the right side of a wall
+or other elements. Touching them is deadly.
+
+Bugs will explode into a diamond surrounded by 8 emeralds,
+even when caught in other explosions!
diff --git a/docs/elements/char_space.txt b/docs/elements/char_space.txt
index b3c93d2..e6c4678 100644
--- a/docs/elements/char_space.txt
+++ b/docs/elements/char_space.txt
@@ -1,4 +1,4 @@
-The space character is tricky. It's basically like an invisible normal wall,
-but it won't light up when a light switch is flicked on.
-
-Watch out for these in the editor; they can often be confused for empty space.
+The space character is tricky. It's basically like an invisible normal wall,
+but it won't light up when a light switch is flicked on.
+
+Watch out for these in the editor; they can often be confused for empty space.
diff --git a/docs/elements/custom.txt b/docs/elements/custom.txt
index 7b9782e..ec7571e 100644
--- a/docs/elements/custom.txt
+++ b/docs/elements/custom.txt
@@ -1,3 +1,9 @@
-Custom elements can be defined to do a ton of things, more than this humble
-space can describe. Just be aware that the code doesn't care from level to
-level in a set.
+Custom elements can be configured to have user-defined properties, to behave in
+their own special way, to interact with other elements, to change their
+behaviour on certain conditions (by changing into other custom elements with
+different properties) or to trigger actions that influence the game.
+
+Each level has its own set of custom elements. To use the same custom elements
+within one level set, use the "copy and paste" functions or use "save as
+template" and "use template" to use the same custom elements from a single level
+template for all levels of a set.
diff --git a/docs/elements/dc_magic_wall.txt b/docs/elements/dc_magic_wall.txt
index b7fc685..084d69d 100644
--- a/docs/elements/dc_magic_wall.txt
+++ b/docs/elements/dc_magic_wall.txt
@@ -1,8 +1,8 @@
-This is a (DC style) magic wall. It gets activated for a limited
-time by rocks or gems that fall on it. Objects falling though
-it will be changed to other objects. After it has stopped running,
-it cannot be activated again.
-
-The duration is expressed in seconds. A duration of zero will let the wall
-run forever. All regular magic walls run together; however, BD style magic
-walls have a separate counter.
+This is a (DC style) magic wall. It gets activated for a limited
+time by rocks or gems that fall on it. Objects falling though
+it will be changed to other objects. After it has stopped running,
+it cannot be activated again.
+
+The duration is expressed in seconds. A duration of zero will let the wall
+run forever. All regular magic walls run together; however, BD style magic
+walls have a separate counter.
diff --git a/docs/elements/dynabomb_increase_number.txt b/docs/elements/dynabomb_increase_number.txt
index a472025..527fbed 100644
--- a/docs/elements/dynabomb_increase_number.txt
+++ b/docs/elements/dynabomb_increase_number.txt
@@ -1,8 +1,8 @@
-Dynabombs are an infinite supply of bombs that the player can drop at any time
-he doesn't have anything else to drop. They explode in a cross shaped pattern,
-and may have strange results when they kill enemies. (For example, Yam Yams
-will only give off the center element of their pattern.)
-
-This pick-up will increase the number of Dynabombs the player can put on the
-field at one time. This number starts at zero, so the player must pick up one
-of these to use Dynabombs.
+Dynabombs are an infinite supply of bombs that the player can drop at any time
+he doesn't have anything else to drop. They explode in a cross shaped pattern,
+and may have strange results when they kill enemies. (For example, Yam Yams
+will only give off the center element of their pattern.)
+
+This pick-up will increase the number of Dynabombs the player can put on the
+field at one time. This number starts at zero, so the player must pick up one
+of these to use Dynabombs.
diff --git a/docs/elements/dynabomb_increase_power.txt b/docs/elements/dynabomb_increase_power.txt
index 3637505..73817a8 100644
--- a/docs/elements/dynabomb_increase_power.txt
+++ b/docs/elements/dynabomb_increase_power.txt
@@ -1,8 +1,8 @@
-Dynabombs are an infinite supply of bombs that the player can drop at any time
-he doesn't have anything else to drop. They explode in a cross shaped pattern,
-and may have strange results when they kill enemies. (For example, Yam Yams
-will only give off the center element of their pattern.)
-
-This pickup allows Dynabomb explosions to destroy brick walls, rather than
-stopping at the first wall. Picking up 2 of these will only get you extra
-points.
+Dynabombs are an infinite supply of bombs that the player can drop at any time
+he doesn't have anything else to drop. They explode in a cross shaped pattern,
+and may have strange results when they kill enemies. (For example, Yam Yams
+will only give off the center element of their pattern.)
+
+This pickup allows Dynabomb explosions to destroy brick walls, rather than
+stopping at the first wall. Picking up 2 of these will only get you extra
+points.
diff --git a/docs/elements/dynabomb_increase_size.txt b/docs/elements/dynabomb_increase_size.txt
index ac72227..e0d6497 100644
--- a/docs/elements/dynabomb_increase_size.txt
+++ b/docs/elements/dynabomb_increase_size.txt
@@ -1,7 +1,7 @@
-Dynabombs are an infinite supply of bombs that the player can drop at any time
-he doesn't have anything else to drop. They explode in a cross shaped pattern,
-and may have strange results when they kill enemies. (For example, Yam Yams
-will only give off the center element of their pattern.)
-
-This pickup increases the length of the explosion.
-At first, the explosion only reaches one square in each direction.
+Dynabombs are an infinite supply of bombs that the player can drop at any time
+he doesn't have anything else to drop. They explode in a cross shaped pattern,
+and may have strange results when they kill enemies. (For example, Yam Yams
+will only give off the center element of their pattern.)
+
+This pickup increases the length of the explosion.
+At first, the explosion only reaches one square in each direction.
diff --git a/docs/elements/em_gate_1_gray.txt b/docs/elements/em_gate_1_gray.txt
index 9104713..b715f45 100644
--- a/docs/elements/em_gate_1_gray.txt
+++ b/docs/elements/em_gate_1_gray.txt
@@ -1,7 +1,7 @@
-Emerald Mine doors will fling you to the other side of the door, rather than
-letting you stand on it. If there is *any* object on the other side, the
-player cannot pass through the door. Note that creators may allow players to
-pass to anything walkable under the player object's options.
-
-Gray doors' real colors are kept hidden to the player, making him/her guess
-which color key opens the door.
+Emerald Mine doors will fling you to the other side of the door, rather than
+letting you stand on it. If there is *any* object on the other side, the
+player cannot pass through the door. Note that creators may allow players to
+pass to anything walkable under the player object's options.
+
+Gray doors' real colors are kept hidden to the player, making him/her guess
+which color key opens the door.
diff --git a/docs/elements/em_gate_2_gray.txt b/docs/elements/em_gate_2_gray.txt
index 9104713..b715f45 100644
--- a/docs/elements/em_gate_2_gray.txt
+++ b/docs/elements/em_gate_2_gray.txt
@@ -1,7 +1,7 @@
-Emerald Mine doors will fling you to the other side of the door, rather than
-letting you stand on it. If there is *any* object on the other side, the
-player cannot pass through the door. Note that creators may allow players to
-pass to anything walkable under the player object's options.
-
-Gray doors' real colors are kept hidden to the player, making him/her guess
-which color key opens the door.
+Emerald Mine doors will fling you to the other side of the door, rather than
+letting you stand on it. If there is *any* object on the other side, the
+player cannot pass through the door. Note that creators may allow players to
+pass to anything walkable under the player object's options.
+
+Gray doors' real colors are kept hidden to the player, making him/her guess
+which color key opens the door.
diff --git a/docs/elements/em_gate_3_gray.txt b/docs/elements/em_gate_3_gray.txt
index 9104713..b715f45 100644
--- a/docs/elements/em_gate_3_gray.txt
+++ b/docs/elements/em_gate_3_gray.txt
@@ -1,7 +1,7 @@
-Emerald Mine doors will fling you to the other side of the door, rather than
-letting you stand on it. If there is *any* object on the other side, the
-player cannot pass through the door. Note that creators may allow players to
-pass to anything walkable under the player object's options.
-
-Gray doors' real colors are kept hidden to the player, making him/her guess
-which color key opens the door.
+Emerald Mine doors will fling you to the other side of the door, rather than
+letting you stand on it. If there is *any* object on the other side, the
+player cannot pass through the door. Note that creators may allow players to
+pass to anything walkable under the player object's options.
+
+Gray doors' real colors are kept hidden to the player, making him/her guess
+which color key opens the door.
diff --git a/docs/elements/em_gate_4_gray.txt b/docs/elements/em_gate_4_gray.txt
index 9104713..b715f45 100644
--- a/docs/elements/em_gate_4_gray.txt
+++ b/docs/elements/em_gate_4_gray.txt
@@ -1,7 +1,7 @@
-Emerald Mine doors will fling you to the other side of the door, rather than
-letting you stand on it. If there is *any* object on the other side, the
-player cannot pass through the door. Note that creators may allow players to
-pass to anything walkable under the player object's options.
-
-Gray doors' real colors are kept hidden to the player, making him/her guess
-which color key opens the door.
+Emerald Mine doors will fling you to the other side of the door, rather than
+letting you stand on it. If there is *any* object on the other side, the
+player cannot pass through the door. Note that creators may allow players to
+pass to anything walkable under the player object's options.
+
+Gray doors' real colors are kept hidden to the player, making him/her guess
+which color key opens the door.
diff --git a/docs/elements/emc_gate_5_gray.txt b/docs/elements/emc_gate_5_gray.txt
index 9104713..b715f45 100644
--- a/docs/elements/emc_gate_5_gray.txt
+++ b/docs/elements/emc_gate_5_gray.txt
@@ -1,7 +1,7 @@
-Emerald Mine doors will fling you to the other side of the door, rather than
-letting you stand on it. If there is *any* object on the other side, the
-player cannot pass through the door. Note that creators may allow players to
-pass to anything walkable under the player object's options.
-
-Gray doors' real colors are kept hidden to the player, making him/her guess
-which color key opens the door.
+Emerald Mine doors will fling you to the other side of the door, rather than
+letting you stand on it. If there is *any* object on the other side, the
+player cannot pass through the door. Note that creators may allow players to
+pass to anything walkable under the player object's options.
+
+Gray doors' real colors are kept hidden to the player, making him/her guess
+which color key opens the door.
diff --git a/docs/elements/emc_gate_6_gray.txt b/docs/elements/emc_gate_6_gray.txt
index 9104713..b715f45 100644
--- a/docs/elements/emc_gate_6_gray.txt
+++ b/docs/elements/emc_gate_6_gray.txt
@@ -1,7 +1,7 @@
-Emerald Mine doors will fling you to the other side of the door, rather than
-letting you stand on it. If there is *any* object on the other side, the
-player cannot pass through the door. Note that creators may allow players to
-pass to anything walkable under the player object's options.
-
-Gray doors' real colors are kept hidden to the player, making him/her guess
-which color key opens the door.
+Emerald Mine doors will fling you to the other side of the door, rather than
+letting you stand on it. If there is *any* object on the other side, the
+player cannot pass through the door. Note that creators may allow players to
+pass to anything walkable under the player object's options.
+
+Gray doors' real colors are kept hidden to the player, making him/her guess
+which color key opens the door.
diff --git a/docs/elements/emc_gate_7_gray.txt b/docs/elements/emc_gate_7_gray.txt
index 9104713..b715f45 100644
--- a/docs/elements/emc_gate_7_gray.txt
+++ b/docs/elements/emc_gate_7_gray.txt
@@ -1,7 +1,7 @@
-Emerald Mine doors will fling you to the other side of the door, rather than
-letting you stand on it. If there is *any* object on the other side, the
-player cannot pass through the door. Note that creators may allow players to
-pass to anything walkable under the player object's options.
-
-Gray doors' real colors are kept hidden to the player, making him/her guess
-which color key opens the door.
+Emerald Mine doors will fling you to the other side of the door, rather than
+letting you stand on it. If there is *any* object on the other side, the
+player cannot pass through the door. Note that creators may allow players to
+pass to anything walkable under the player object's options.
+
+Gray doors' real colors are kept hidden to the player, making him/her guess
+which color key opens the door.
diff --git a/docs/elements/emc_gate_8_gray.txt b/docs/elements/emc_gate_8_gray.txt
index 9104713..b715f45 100644
--- a/docs/elements/emc_gate_8_gray.txt
+++ b/docs/elements/emc_gate_8_gray.txt
@@ -1,7 +1,7 @@
-Emerald Mine doors will fling you to the other side of the door, rather than
-letting you stand on it. If there is *any* object on the other side, the
-player cannot pass through the door. Note that creators may allow players to
-pass to anything walkable under the player object's options.
-
-Gray doors' real colors are kept hidden to the player, making him/her guess
-which color key opens the door.
+Emerald Mine doors will fling you to the other side of the door, rather than
+letting you stand on it. If there is *any* object on the other side, the
+player cannot pass through the door. Note that creators may allow players to
+pass to anything walkable under the player object's options.
+
+Gray doors' real colors are kept hidden to the player, making him/her guess
+which color key opens the door.
diff --git a/docs/elements/empty_space.txt b/docs/elements/empty_space.txt
index bf36049..dd822fd 100644
--- a/docs/elements/empty_space.txt
+++ b/docs/elements/empty_space.txt
@@ -1,3 +1,3 @@
-Just empty space.
-
-Everything can walk, move or fall through it.
+Just empty space.
+
+Everything can walk, move or fall through it.
diff --git a/docs/elements/expandable_wall.txt b/docs/elements/expandable_wall.txt
index 86e7ea7..1f77835 100644
--- a/docs/elements/expandable_wall.txt
+++ b/docs/elements/expandable_wall.txt
@@ -1,6 +1,6 @@
-This wall will grow on either side that is open. It will stop
-growing on one side if it is blocked by a wall, even if said wall is later
-destroyed. Gems and others, however, will stop it only temporarily.
-
-This particular growing wall is the only one that is visibly different
-to the player from a normal wall, at least under the default graphics.
+This wall will grow on either side that is open. It will stop
+growing on one side if it is blocked by a wall, even if said wall is later
+destroyed. Gems and others, however, will stop it only temporarily.
+
+This particular growing wall is the only one that is visibly different
+to the player from a normal wall, at least under the default graphics.
diff --git a/docs/elements/game_of_life.txt b/docs/elements/game_of_life.txt
index 68224a4..db23325 100644
--- a/docs/elements/game_of_life.txt
+++ b/docs/elements/game_of_life.txt
@@ -1,9 +1,9 @@
-These walls behave like the well-known "Conway's Game of Life".
-They behave like normal walls; however, they may appear or disappear
-every half-second according to these rules:
-
-Cells that are surrounded by 2 or 3 cells are the only cells that survive.
-
-Space or dirt that is surrounded by exactly 3 cells grows into new cells.
-
-The player(s) is (are) counted as cells!
+These walls behave like the well-known "Conway's Game of Life".
+They behave like normal walls; however, they may appear or disappear
+every half-second according to these rules:
+
+Cells that are surrounded by 2 or 3 cells are the only cells that survive.
+
+Space or dirt that is surrounded by exactly 3 cells grows into new cells.
+
+The player(s) is (are) counted as cells!
diff --git a/docs/elements/invisible_sand.txt b/docs/elements/invisible_sand.txt
index d06a193..bfbe1f4 100644
--- a/docs/elements/invisible_sand.txt
+++ b/docs/elements/invisible_sand.txt
@@ -1,3 +1,3 @@
-Invisible sand behaves exactly like normal sand, but is invisible.
-
-It can be made visible for a short time by activating the light switch.
+Invisible sand behaves exactly like normal sand, but is invisible.
+
+It can be made visible for a short time by activating the light switch.
diff --git a/docs/elements/invisible_steelwall.txt b/docs/elements/invisible_steelwall.txt
index 2fc0c0b..0ef1132 100644
--- a/docs/elements/invisible_steelwall.txt
+++ b/docs/elements/invisible_steelwall.txt
@@ -1,4 +1,4 @@
-An invisible steel wall behaves exactly like a normal steel wall,
-but is invisible.
-
-It can be made visible for a short time by activating the light switch.
+An invisible steel wall behaves exactly like a normal steel wall,
+but is invisible.
+
+It can be made visible for a short time by activating the light switch.
diff --git a/docs/elements/invisible_wall.txt b/docs/elements/invisible_wall.txt
index 30fd93e..ecdbc9c 100644
--- a/docs/elements/invisible_wall.txt
+++ b/docs/elements/invisible_wall.txt
@@ -1,3 +1,3 @@
-An invisible wall behaves exactly like a normal wall, but is invisible.
-
-It can be made visible for a short time by activating the light switch.
+An invisible wall behaves exactly like a normal wall, but is invisible.
+
+It can be made visible for a short time by activating the light switch.
diff --git a/docs/elements/magic_wall.txt b/docs/elements/magic_wall.txt
index c02b36d..c17b45d 100644
--- a/docs/elements/magic_wall.txt
+++ b/docs/elements/magic_wall.txt
@@ -1,8 +1,8 @@
-This is a (EM style) magic wall. It gets activated for a limited
-time by rocks or gems that fall on it. Objects falling though
-it will be changed to other objects. After it has stopped running,
-it cannot be activated again.
-
-The duration is expressed in seconds. A duration of zero will let the wall
-run forever. All regular magic walls run together; however, BD style magic
-walls have a separate counter.
+This is a (EM style) magic wall. It gets activated for a limited
+time by rocks or gems that fall on it. Objects falling though
+it will be changed to other objects. After it has stopped running,
+it cannot be activated again.
+
+The duration is expressed in seconds. A duration of zero will let the wall
+run forever. All regular magic walls run together; however, BD style magic
+walls have a separate counter.
diff --git a/docs/elements/robot_wheel.txt b/docs/elements/robot_wheel.txt
index d6bf899..337ecd7 100644
--- a/docs/elements/robot_wheel.txt
+++ b/docs/elements/robot_wheel.txt
@@ -1,7 +1,7 @@
-Activating the magic wheel attracts the robots for a short time and
-keeps them away from the player. When it stops running, the robots
-will again turn towards the player.
-
-The magic wheel can be activated again after it stopped running.
-You can also activate other magic wheels while one is spinning;
-the robots will go towards the latest active wheel.
+Activating the magic wheel attracts the robots for a short time and
+keeps them away from the player. When it stops running, the robots
+will again turn towards the player.
+
+The magic wheel can be activated again after it stopped running.
+You can also activate other magic wheels while one is spinning;
+the robots will go towards the latest active wheel.
diff --git a/docs/elements/satellite.txt b/docs/elements/satellite.txt
index 72e7b92..b8b6a2e 100644
--- a/docs/elements/satellite.txt
+++ b/docs/elements/satellite.txt
@@ -1,6 +1,6 @@
-Satellites will follow the player as best they can, and the only way to outrun
-them is with double speed. Satellites are harmless, and they can be pushed,
-but in multiples or with strategically placed walls, they can easily trap the
-player. When crushed or caught in an explosion, satellites will explode.
-
-Satellites can be used as a sort of moving platform when gravity is on.
+Satellites will follow the player as best they can, and the only way to outrun
+them is with double speed. Satellites are harmless, and they can be pushed,
+but in multiples or with strategically placed walls, they can easily trap the
+player. When crushed or caught in an explosion, satellites will explode.
+
+Satellites can be used as a sort of moving platform when gravity is on.
diff --git a/docs/elements/shield_deadly.txt b/docs/elements/shield_deadly.txt
index 36113c6..ded410e 100644
--- a/docs/elements/shield_deadly.txt
+++ b/docs/elements/shield_deadly.txt
@@ -1,7 +1,7 @@
-This not only makes the player invincible, but also allows him to kill enemies
-just by pressing against them.
-
-Extra deadly shields will add more time without wasting any time already
-acquired. Picking up a deadly shield when you already have a normal shield
-(or vice versa) will not waste the normal shield; the player will use the
-normal shield when the deadly shield runs out.
+This not only makes the player invincible, but also allows him to kill enemies
+just by pressing against them.
+
+Extra deadly shields will add more time without wasting any time already
+acquired. Picking up a deadly shield when you already have a normal shield
+(or vice versa) will not waste the normal shield; the player will use the
+normal shield when the deadly shield runs out.
diff --git a/docs/elements/sokoban_field_empty.txt b/docs/elements/sokoban_field_empty.txt
index 298610e..65e9960 100644
--- a/docs/elements/sokoban_field_empty.txt
+++ b/docs/elements/sokoban_field_empty.txt
@@ -1,6 +1,6 @@
-This is an empty sokoban field. Only the player and sokoban objects can pass
-onto these fields. Watch out, the fields will be destroyed by explosions!
-
-Note that spare fields will prevent the exit from opening, but spare objects
-won't. Also, sometimes it is necessary to push sokoban objects off of fields
-to make room for other things.
+This is an empty sokoban field. Only the player and sokoban objects can pass
+onto these fields. Watch out, the fields will be destroyed by explosions!
+
+Note that spare fields will prevent the exit from opening, but spare objects
+won't. Also, sometimes it is necessary to push sokoban objects off of fields
+to make room for other things.
diff --git a/docs/elements/sokoban_field_full.txt b/docs/elements/sokoban_field_full.txt
index 0bd3d9d..a3170a7 100644
--- a/docs/elements/sokoban_field_full.txt
+++ b/docs/elements/sokoban_field_full.txt
@@ -1,6 +1,6 @@
-This is a sokoban field that already has a sokoban object.
-
-Note that it's safe to blow up a full sokoban field without affecting your
-ability to open the exit. Also, if the exit is already open, it will never
-close up. However, disrupting the puzzle in any other way will mess up your
-chances to win.
+This is a sokoban field that already has a sokoban object.
+
+Note that it's safe to blow up a full sokoban field without affecting your
+ability to open the exit. Also, if the exit is already open, it will never
+close up. However, disrupting the puzzle in any other way will mess up your
+chances to win.
diff --git a/docs/elements/sokoban_field_player.txt b/docs/elements/sokoban_field_player.txt
index 4c6076c..bef450a 100644
--- a/docs/elements/sokoban_field_player.txt
+++ b/docs/elements/sokoban_field_player.txt
@@ -1,5 +1,5 @@
-This is the player standing on a sokoban field.
-
-If a level contains *only* sokoban elements (those in the sokoban section,
-steel walls, and empty space), it will be completed as soon the sokoban puzzle
-is solved.
+This is the player standing on a sokoban field.
+
+If a level contains *only* sokoban elements (those in the sokoban section,
+steel walls, and empty space), it will be completed as soon the sokoban puzzle
+is solved.
diff --git a/docs/elements/sp_base.txt b/docs/elements/sp_base.txt
index 0ec5f97..ed2829a 100644
--- a/docs/elements/sp_base.txt
+++ b/docs/elements/sp_base.txt
@@ -1,3 +1,3 @@
-The base is the Supaplex equivalent of dirt.
-
-Bases will block Dark Yam Yams, but not amoeba.
+The base is the Supaplex equivalent of dirt.
+
+Bases will block Dark Yam Yams, but not amoeba.
diff --git a/docs/elements/spaceship.txt b/docs/elements/spaceship.txt
index 2df84cc..78bf1e0 100644
--- a/docs/elements/spaceship.txt
+++ b/docs/elements/spaceship.txt
@@ -1,4 +1,4 @@
-Spaceships always try to follow the left side of a wall
-or other elements. Touching them is deadly.
-
-Spaceships will not explode when caught in explosions.
+Spaceships always try to follow the left side of a wall
+or other elements. Touching them is deadly.
+
+Spaceships will not explode when caught in explosions.
diff --git a/docs/elements/switchgate_switch.txt b/docs/elements/switchgate_switch.txt
index 0ae2440..6e4a7dd 100644
--- a/docs/elements/switchgate_switch.txt
+++ b/docs/elements/switchgate_switch.txt
@@ -1,2 +1,2 @@
-This is the switch for switching the switch gates. When you switch the switch
-that controls the switching of the switch gates... okay, I'll stop. :-)
+This is the switch for switching the switch gates. When you switch the switch
+that controls the switching of the switch gates... okay, I'll stop. :-)
diff --git a/docs/elements/timegate_switch.txt b/docs/elements/timegate_switch.txt
index f267c3c..38da716 100644
--- a/docs/elements/timegate_switch.txt
+++ b/docs/elements/timegate_switch.txt
@@ -1,2 +1,2 @@
-As long as a single time gate switch is spinning, all time gates will be open.
-Each switch spins for a certain time when touched.
+As long as a single time gate switch is spinning, all time gates will be open.
+Each switch spins for a certain time when touched.
diff --git a/docs/elements/yamyam.txt b/docs/elements/yamyam.txt
index e25c979..6a1fa26 100644
--- a/docs/elements/yamyam.txt
+++ b/docs/elements/yamyam.txt
@@ -1,8 +1,8 @@
-The Yam Yam is one of the most exciting creatures. When it explodes
-(by dropping a rock on it, for example), it can turn to nine new
-elements. Further exploding Yam Yams can turn to other elements, up
-to eight different sets of new elements.
-
-Sometimes the last emerald you are looking for to finish the level
-is hidden in a Yam Yam! But be careful: Yam Yams will eat all diamonds
-in their way!
+The Yam Yam is one of the most exciting creatures. When it explodes
+(by dropping a rock on it, for example), it can turn to nine new
+elements. Further exploding Yam Yams can turn to other elements, up
+to eight different sets of new elements.
+
+Sometimes the last emerald you are looking for to finish the level
+is hidden in a Yam Yam! But be careful: Yam Yams will eat all diamonds
+in their way!
diff --git a/rocksndiamonds.1 b/rocksndiamonds.1
deleted file mode 100644
index 4c14c4b..0000000
--- a/rocksndiamonds.1
+++ /dev/null
@@ -1,245 +0,0 @@
-.TH ROCKSNDIAMONDS 1L "20 November 1995"
-
-.SH NAME
-Rocks'n'Diamonds \- A game for Unix/X11 
-.SH INTRODUCTION
-This is a nice little game with color graphics and sound for your
-Unix system with color X11. You need an 8-Bit color display or better.
-It is not recommended on black&white systems, and maybe not on gray
-scale systems.
-
-If you know the game "Boulderdash" (Commodore C64) or "Emerald Mine"
-(Amiga), you know what "ROCKS'N'DIAMONDS" is about.
-
-
-.SH The Menues
-
-You can see eight blue circles on the left side of the eight green menu
-texts; these are buttons to activate the menu commands by simply clicking
-on them with the left mouse button. The button will then change to red.
-(You can control the menues over the keyboard or joystick, too. Just use
-the arrow keys and the 'Return' or 'Enter' key or, if you use a joystick,
-the appropriate direction and the fire button.)
-
-.SH The menu 'name'
-
-When you start the game the first time, your login name will appear in
-the 'NAME:' field. If you want to use a different name for playing, for
-example a funny player name or a name for cheating, you can click on the
-button and enter a new name.
-
-If you choose a certain special name, you will be in a cheat mode where
-you can choose all levels without playing the lower levels before... :)
-
-.SH The menue 'level'
-
-If you have played some levels of this game, you can choose the already
-played levels at any time, but you cannot choose the higher levels. This
-means, you can choose levels from level 0 to the highest level that you
-have ever won. This is known as your 'handicap'.
-
-If the level number is red, you have choosen a 'ready' level, if it is
-yellow, you have choosen a 'user' level, which is blank and can be
-edited by yourself with the built-in level editor (see below).
-
-To choose new level series, click on the button on the left and choose
-the new level serie.
-
-.SH Hall of fame
-
-Click on this button to see a list of the best players of this level.
-Click again to go back to the main menu.
-
-.SH Level creator
-This brings you to the level editor, if you have switched to a 'yellow'
-level, which are empty and can be filled by yourself. See below.
-
-.SH Info screen
-This screen shows you all elements which appear in the game and presents
-you the background music loops which you can listen to while playing the
-levels (only available on Linux and FreeBSD systems).
-
-.SH Start game
-This will start the game.
-
-.SH Setup
-To change some things in the game, use the setup menu.
-You can enable/disable "Sound" (enables/disables _all_ sounds in
-the game), "Sound loops" (only allowed on Linux and FreeBSD systems with
-VoxWare[tm] sound driver; don't worry if you never heard of it --
-it's the name of the standard Linux sound driver), "Game music"
-(can always be enabled on very fast systems [exception: you don't
-like it], on slower systems it will take some percent of CPU time
-which will slow things down a bit) and "Toons", which will forbid/
-permit the little animated toons.
-
-"Buffered Gfx" can be set to "off" on slower systems, "Fading" gives
-a nice fading effect when displaying new screens, but unfortunately
-I haven't found a system which is fast enough to display it so far.
-(Maybe this works better on highly accelerated X servers.) Better set
-this to "off" if you have a normal system...
-
-Set "auto-record" to "on" if you want to automatically record each game
-to tape.
-
-If you have a Linux or FreeBSD system with a joystick, you can choose the "1st" or
-the "2nd" joystick port and use "Cal. Joystick" to calibrate it. Use
-"Save and exit" after calibration to save it for later playing sessions.
-
-"Exit" quits the setup menu without saving the changes, "Save and exit"
-will save and then return to the main menu.
-
-.SH Quit
-Exit the game.
-
-
-.SH How To Play The Game
-When the game has started, you can see the playfield on the left side
-and a control field on the right side. The control field contains the
-following elements:
-.TP
-.B Level indicator
-Tells you which level you are playing.
-.TP
-.B Emeralds
-Shows you how many emeralds you still need to win the current level.
-.TP
-.B Dynamite1
-Shows you how many dynamite bombs you have.
-.TP
-.B Keys
-Shows you which keys you have in your inventory.
-.TP
-.B Score
-Shows the current score. In some levels there
-are some extra items giving extra score points.
-.TP
-.B Time
-The seconds you have still left to play the level.
-.TP
-.B Stop/Pause/Play
-Game controls to stop the game, pause it and go on
-playing. If the tape recorder is recording your
-game, it is stopping/pausing/playing as well.
-.TP
-.B Music buttons
-The three music buttons can be used to control the
-background music loop, the 'looping' sounds and
-all other sounds. The little red light shows you
-if it is enabled or disabled. On slower systems
-(and a 486DX33 with Soundblaster _is_ a slower
-system) it increases the game speed to turn off
-background music. You can completely turn off all
-sound effects in the setup menu, although it is
-much more fun to have them enabled when it
-doesn't eats up to much speed.
-
-(A little note: The sound server currently needs
-about 10% CPU time on my 486DX/33/SBPro system
-when playing background music. I wonder if this
-would get better with a better soundcard, like
-Gravis Ultrasound, or if only pure CPU power
-helps in this case...)
-
-
-.SH About the game itself
- Of course you know Boulderdash, so you will know
-how to play the game. :)
-If not: You can move your playing figure (the smiley) with the arrow
-keys or with the joystick (if you have no joystick and even no arrow
-keys on your keyboard, you can use the keys 'i', 'j', 'k' and 'm' for
-the directions. To 'snap' a field near you without moving to it, you
-can use the left fire button on your joystick (hold it down, move the
-stick to 'snap' the field, release the button) or the keys 'e', 's',
-'d' and 'x'. To place a piece of dynamite, use the right fire button
-on your joystick or use the 'b' key (and, after placing the dynamite,
-better see to move away from this field...).
-
-Just try the levels from the 'tutorial' level serie to see what most
-of the elements do or have a look at the info screen!
-
-Note: It is *highly recommended* to use a joystick for playing this
-game! It is possible to play it with the keyboard, but it is *much
-more fun* to play with a joystick, and some levels are very difficult
-to solve with the keyboard. So, the best platform for this game is a
-Linux or a FreeBSD system (which gives you background music, too).
-
-.SH The Level Editor
-To build your own levels, just choose a 'yellow', empty level. If you
-cannot find any 'yellow' levels, choose a different level serie or
-choose the higher level numbers (if you have a small 'handicap' number,
-the higher levels will be skipped to reach the 'empty' levels.
-
-Another way is to create your own level series. Just add a line to the
-file 'levels/ROCKS.levelinfo' with the following entries:
-.br
-- the name of the level directory (create this directory under 'levels')
-.br
-- the name of the level serie (don't use any whitespaces within the name)
-.br
-- the 'ready' (red) levels (start with zero)
-.br
-- the 'empty' (yellow) levels (set this to some number of blank levels)
-.br
-
-To edit a level, you can use all three mouse buttons to draw in the
-level window. Click into the elements field with one of the three buttons
-to remap it to the new element. Use the arrow widgets to scroll around in
-the level. Use the 'flood fill' field to init exactly ony flood fill
-operation in the level field (you will be prompted). Click on 'control
-window' to switch to the control window.
-
-In the control window you can modify different parameters like the size
-of the level playfield, the name of the level, the scores for different
-elements and something like that. The four 3x3 field on the upper left
-can be edited like the level field and indicate the 'contents' of smashed
-crunchers (just try it out with some crunchers in one of your own levels).
-
-'Undo & Exit' leaves the level editor, throwing away all the changes you
-have done to the level.
-'Save & Exit' leveas the level editor and saves the new level (the old one
-will be deleted).
-
-
-.SH The Tape Recorder
-You can use the tape recorder to record games and play tapes of previously
-played games. Just use them like a normal video recorder.
-.TP
-.B Recording a game on tape:
-Just press the 'record' button (the one with the red point on it) and
-either press 'Start Game' or press on 'record' or 'pause' to end the
-pause mode and start playing and recording.
-
-If you have set "auto record" in the setup menu to "on", you just have
-to press 'Start Game' as usual.
-
-.TP
-.B Saving a game tape:
-To save a tape to the tape file corresponding to the level (that means
-that you can only save one tape file for each level), just press the
-'eject' button (the very left button). Then you will be prompted if
-you really want to replace the old tape (if an old tape exists).
-
-.TP
-.B Playing a tape:
-Just press 'play' and then either 'play' or 'pause'.
-
-While recording or playing, you can press 'pause' to stop the recording
-or the playing of the tape and continue by pressing 'pause' again.
-You can use either the tape recorder buttons or the game control buttons
-for this purpose.
-
-
-.SH And Now Have Fun!
-
-Have fun playing the game, building new levels and breaking all high
-scores! ;)
-
-.SH AUTHOR
-
-If you have any comments, problems, suggestions, donations, flames,
-send them to
-
-	info at artsoft.org
-
-Have fun!
diff --git a/src/Makefile b/src/Makefile
index 4bbbcca..bb33ce8 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,7 +1,12 @@
 # =============================================================================
-# Rocks'n'Diamonds Makefile (src)
+# Rocks'n'Diamonds - McDuffin Strikes Back!
 # -----------------------------------------------------------------------------
-# (c) 1995-2006 Holger Schemel <info at artsoft.org>
+# (c) 1995-2015 by Artsoft Entertainment
+#                  Holger Schemel
+#                  info at artsoft.org
+#                  http://www.artsoft.org/
+# -----------------------------------------------------------------------------
+# src/Makefile
 # =============================================================================
 
 # -----------------------------------------------------------------------------
@@ -10,35 +15,21 @@
 
 .EXPORT_ALL_VARIABLES:
 
-ifndef PLATFORM				# unknown platform -- try auto detection
-ifdef COMSPEC
-PLATFORM = msdos
-else
+ifndef PLATFORM				# unknown platform -- default to Unix
 PLATFORM = unix
 endif
-endif
-
-ifdef X11_PATH				# path to X11 from top level Makefile
-XINC_PATH = $(X11_PATH)/include
-XLIB_PATH = $(X11_PATH)/lib
-X11_INCL = -I$(XINC_PATH)
-X11_LIBS = -L$(XLIB_PATH) -lX11
-endif
 
 AR = ar
 RANLIB = ranlib
 ETAGS = etags
 RM = rm -f
 
-BMP2ICO = bmp2ico
+CONVERT = convert
 WINDRES = windres
 
-PROGBASE = rocksndiamonds
-
-ifdef SPECIAL_EDITION			# create special edition
-PROGBASE = $(SPECIAL_EDITION)
-endif
+CONVERT_ICON_ARGS = -transparent black -background transparent
 
+PROGBASE = rocksndiamonds
 PROGNAME = ../$(PROGBASE)
 
 
@@ -46,48 +37,18 @@ PROGNAME = ../$(PROGBASE)
 # configuring platform
 # -----------------------------------------------------------------------------
 
-ifeq ($(PLATFORM),solaris)		# native compiling to Solaris
-EXTRA_LDFLAGS = -lnsl -lsocket -R$(XLIB_PATH)
-PLATFORM = unix
-endif
-
-ifeq ($(PLATFORM),macosx)		# native compiling to Mac OS X
+ifeq ($(PLATFORM),macosx)		# compiling on Mac OS X
 EXTRA_LDFLAGS = -lstdc++
-PLATFORM = unix
-TARGET = sdl
-endif
-
-ifeq ($(PLATFORM),os2)			# native compiling to OS/2
-RANLIB = echo
-PROGNAME = ../$(PROGBASE).exe
-EXTRA_CFLAGS = -Zbin-files -D__ST_MT_ERRNO__ -Zmtd -fomit-frame-pointer
-EXTRA_LDFLAGS = -lsocket
-PLATFORM = unix
-TARGET = x11
+override PLATFORM = unix
 endif
 
-ifeq ($(PLATFORM),unix)			# native compiling to Unix (generic)
+ifeq ($(PLATFORM),unix)			# compiling on Unix/Linux (generic)
 PROFILING_FLAGS = -pg
 endif
 
 ifeq ($(PLATFORM),cross-win32)		# cross-compiling to Windows
 PROGNAME = ../$(PROGBASE).exe
 EXTRA_LDFLAGS = -lshfolder -lwsock32
-TARGET = sdl
-endif
-
-ifeq ($(PLATFORM),cross-msdos)		# cross-compiling to MS-DOS
-PROGBASE = rocks
-PROGNAME = ../$(PROGBASE).exe
-TARGET = allegro
-endif
-
-ifeq ($(PLATFORM),msdos)		# native compiling to MS-DOS
-PROGBASE = rocks
-PROGNAME = ../$(PROGBASE).exe
-SYS_CFLAGS = -DTARGET_X11
-SYS_LDFLAGS = -s -lalleg
-RM = del
 endif
 
 
@@ -95,26 +56,32 @@ endif
 # configuring target
 # -----------------------------------------------------------------------------
 
-ifeq ($(TARGET),x11)			# compiling for X11 target
-SYS_CFLAGS  = -DTARGET_X11 $(X11_INCL)
-SYS_LDFLAGS = $(X11_LIBS)
+ifndef TARGET				# auto-detect compiling for SDL or SDL2
+  SDL_VERSION := $(shell sdl2-config --version 2> /dev/null)
+  ifdef SDL_VERSION
+    TARGET = sdl2
+  else
+    SDL_VERSION := $(shell sdl-config --version 2> /dev/null)
+    ifdef SDL_VERSION
+      TARGET = sdl
+    else
+      $(error SDL/SDL2 library not found)
+    endif
+  endif
 endif
 
+# $(info Using SDL version $(SDL_VERSION) [TARGET == $(TARGET)])
+
 ifeq ($(TARGET),sdl)			# compiling for SDL target
-SYS_CFLAGS  = -DTARGET_SDL $(shell sdl-config --cflags)
-SDL_LIBS = -lSDL_image -lSDL_mixer -lSDL_net -lsmpeg
+SYS_CFLAGS = -DTARGET_SDL $(shell sdl-config --cflags)
+SDL_LIBS = -lSDL_image -lSDL_mixer -lSDL_net
 SYS_LDFLAGS = $(SDL_LIBS) $(shell sdl-config --libs)
 endif
 
-ifeq ($(TARGET),sdl-static)		# compiling for SDL target (static)
-SYS_CFLAGS  = -DTARGET_SDL $(shell sdl-config --cflags)
-SDL_LIBS = -lSDL_image -lSDL_mixer -lSDL_net -lsmpeg
-SYS_LDFLAGS = $(SDL_LIBS) $(shell sdl-config --static-libs)
-endif
-
-ifeq ($(TARGET),allegro)		# compiling for Allegro target
-SYS_CFLAGS = -DTARGET_ALLEGRO -I$(CROSS_PATH_MSDOS)/include
-SYS_LDFLAGS = -lalleg
+ifeq ($(TARGET),sdl2)			# compiling for SDL2 target
+SYS_CFLAGS = -DTARGET_SDL2 $(shell sdl2-config --cflags)
+SDL_LIBS = -lSDL2_image -lSDL2_mixer -lSDL2_net
+SYS_LDFLAGS = $(SDL_LIBS) $(shell sdl2-config --libs)
 endif
 
 
@@ -134,17 +101,11 @@ ifdef SCORE_ENTRIES			# number of score entries per player
 CONFIG_SCORE_ENTRIES = -D$(SCORE_ENTRIES)
 endif
 
-ifdef SPECIAL_EDITION
-ifeq ($(SPECIAL_EDITION),rnd_jue)	# create special edition
-CONFIG_SPECIAL = -DCREATE_SPECIAL_EDITION -DCREATE_SPECIAL_EDITION_RND_JUE
-endif
-endif
-
 CONFIG_GAME_DIR = $(CONFIG_RO_GAME_DIR) $(CONFIG_RW_GAME_DIR)
-CONFIG_GAME = $(CONFIG_GAME_DIR) $(CONFIG_SCORE_ENTRIES) $(CONFIG_SPECIAL)
+CONFIG_GAME = $(CONFIG_GAME_DIR) $(CONFIG_SCORE_ENTRIES)
 
 CONFIG = $(CONFIG_GAME) $(JOYSTICK)
-# DEBUG = -DDEBUG -g
+DEBUG = -DDEBUG -g
 # PROFILING = $(PROFILING_FLAGS)
 
 # OPTIONS = $(DEBUG) -Wall			# only for debugging purposes
@@ -154,9 +115,10 @@ OPTIONS = $(DEBUG) -Wall			# only for debugging purposes
 # OPTIONS = -O3 -Wall -ansi -pedantic
 # OPTIONS = -O3 -Wall
 # OPTIONS = -O3
-# OPTIONS = -DSYSV -Ae			# may be needed for HP-UX
 
 ifdef BUILD_DIST			# distribution build
+SYS_LDFLAGS := $(shell echo $(SYS_LDFLAGS) |	\
+		       sed -e "s%-rpath,[^ ]*%-rpath,'\$$ORIGIN/lib'%")
 OPTIONS = -O3 -Wall
 endif
 
@@ -178,7 +140,7 @@ SRCS =	main.c		\
 	editor.c	\
 	files.c		\
 	tape.c		\
-	cartoons.c	\
+	anim.c		\
 	network.c	\
 	netserv.c
 
@@ -196,7 +158,7 @@ OBJS =	main.o		\
 	editor.o	\
 	files.o		\
 	tape.o		\
-	cartoons.o	\
+	anim.o		\
 	network.o	\
 	netserv.o
 
@@ -218,9 +180,16 @@ CNFS =	conf_gfx.h	\
 	conf_var.c	\
 	conf_act.c
 
-CNFS_CMD = ../Scripts/create_element_defs.pl
+CNFS_CMD = ../build-scripts/create_element_defs.pl
 
 TIMESTAMP_FILE = conftime.h
+TIMESTAMP_FORMAT = %Y-%m-%d %H:%M
+
+# use SOURCE_DATE_EPOCH, or else last Git commit date, or else current date
+SOURCE_DATE_EPOCH ?= $(shell test -d ../.git && test `git ls-files -m | wc -l` -eq 0 && git show -s --format=%ct || date +%s)
+
+# get source date string from either GNU / Linux or BSD / Mac OS X style "date"
+SOURCE_DATE_STRING := $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "+$(TIMESTAMP_FORMAT)"  2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" "+$(TIMESTAMP_FORMAT)" 2>/dev/null || date -u "+$(TIMESTAMP_FORMAT)")
 
 LIBGAME_DIR = libgame
 LIBGAME = $(LIBGAME_DIR)/libgame.a
@@ -232,27 +201,30 @@ GAME_SP_DIR = game_sp
 GAME_SP = $(GAME_SP_DIR)/game_sp.a
 
 RNDLIBS = $(LIBGAME) $(GAME_EM) $(GAME_SP)
+AUTOCONF = conf_gfx.h conf_snd.h conf_mus.h
 
 ICONBASE = windows_icon
+ICON_BASEPATH = ../Special/Icons/windows_icons
+
 ifeq ($(PLATFORM),cross-win32)
-ifdef SPECIAL_EDITION
-ICONSUFFIX = 32x32_$(SPECIAL_EDITION)
-else
-ICONSUFFIX = 32x32
-endif
-ICON32X32 = ../graphics/$(ICONBASE)_$(ICONSUFFIX).bmp
+ICON_PATH = $(ICON_BASEPATH)/default
 ICON = $(ICONBASE).o
 endif
 
+GRAPHICS_DIR = ../graphics
+
 
 # -----------------------------------------------------------------------------
 # build targets
 # -----------------------------------------------------------------------------
 
-all: libgame_dir game_em_dir game_sp_dir $(PROGNAME)
+all: $(AUTOCONF) libgame_dir game_em_dir game_sp_dir $(PROGNAME) graphics_dir
 
 $(PROGNAME): $(RNDLIBS) $(TIMESTAMP_FILE) $(OBJS) $(ICON)
 	$(CC) $(PROFILING) $(OBJS) $(ICON) $(RNDLIBS) $(LDFLAGS) -o $(PROGNAME)
+ifdef BUILD_DIST
+	strip $(PROGNAME)
+endif
 
 libgame_dir:
 	@$(MAKE) -C $(LIBGAME_DIR)
@@ -275,35 +247,42 @@ auto-conf:
 		$(CNFS_CMD) $$i > $$i;		\
 	done
 
-conf_gfx.h: conf_gfx.c
+auto-conf-clean:
+	@for i in $(CNFS); do			\
+		echo "$(RM) $$i";		\
+		$(RM) $$i;			\
+	done
+
+conf_gfx.h: conf_gfx.c $(CNFS_CMD)
 	@$(MAKE) auto-conf
 
-conf_snd.h: conf_snd.c
+conf_snd.h: conf_snd.c $(CNFS_CMD)
 	@$(MAKE) auto-conf
 
-conf_mus.h: conf_mus.c
+conf_mus.h: conf_mus.c $(CNFS_CMD)
 	@$(MAKE) auto-conf
 
-$(TIMESTAMP_FILE): $(SRCS) $(LIBGAME) $(GAME_EM) $(GAME_SP)
-	@date '+"%Y-%m-%d %H:%M"' \
-	| sed -e 's/^/#define COMPILE_DATE_STRING /' \
+$(TIMESTAMP_FILE): $(SRCS) $(RNDLIBS)
+	@echo '#define SOURCE_DATE_STRING "$(SOURCE_DATE_STRING)"' \
 	> $(TIMESTAMP_FILE)
 
 $(ICON):
-	$(BMP2ICO) -transparent $(ICONBASE).ico $(ICON32X32)
+#	$(CONVERT) $(ICON32X32) $(CONVERT_ICON_ARGS) $(ICONBASE).ico
+	$(CONVERT) $(ICON_PATH)/*.png $(CONVERT_ICON_ARGS) $(ICONBASE).ico
 	echo "$(ICONBASE) ICON $(ICONBASE).ico" | $(WINDRES) -o $(ICON)
 
 .c.o:
 	$(CC) $(PROFILING) $(CFLAGS) -c $*.c
 
+graphics_dir:
+	@test -f $(GRAPHICS_DIR)/Makefile && $(MAKE) -C $(GRAPHICS_DIR) || true
+
 clean-obj:
 	$(MAKE) -C $(LIBGAME_DIR) clean
 	$(MAKE) -C $(GAME_EM_DIR) clean
 	$(MAKE) -C $(GAME_SP_DIR) clean
 	$(RM) $(OBJS)
-	$(RM) $(LIBGAME)
-	$(RM) $(GAME_EM)
-	$(RM) $(GAME_SP)
+	$(RM) $(RNDLIBS)
 
 clean-ico:
 	$(RM) $(ICONBASE).ico
@@ -315,18 +294,23 @@ clean-bin:
 
 clean: clean-obj clean-ico clean-bin
 
+clean-git: clean auto-conf-clean
+	@$(MAKE) -C $(GRAPHICS_DIR) clean
+
+dist-clean: clean-obj clean-ico
+
 
 # -----------------------------------------------------------------------------
 # run and test targets
 # -----------------------------------------------------------------------------
 
-run: all
+run:
 	cd .. && ./$(PROGBASE) --verbose
 
-gdb: all
+gdb:
 	cd .. && gdb -batch -x GDB_COMMANDS ./$(PROGBASE)
 
-valgrind: all
+valgrind:
 	cd .. && valgrind -v --leak-check=yes ./$(PROGBASE) 2> valgrind.out
 
 
@@ -334,8 +318,6 @@ valgrind: all
 # development only
 # -----------------------------------------------------------------------------
 
-dist-clean: clean-obj
-
 tags:
 	$(ETAGS) *.[ch] $(LIBGAME_DIR)/*.[ch] $(GAME_EM_DIR)/*.[ch] $(GAME_SP_DIR)/*.[ch]
 
diff --git a/src/anim.c b/src/anim.c
new file mode 100644
index 0000000..b9ea8be
--- /dev/null
+++ b/src/anim.c
@@ -0,0 +1,1265 @@
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// anim.c
+// ============================================================================
+
+#include "anim.h"
+#include "main.h"
+#include "tools.h"
+
+
+/* values for global toon animation definition */
+#define NUM_GLOBAL_TOON_ANIMS		1
+#define NUM_GLOBAL_TOON_PARTS		MAX_NUM_TOONS
+
+/* values for global animation definition (including toons) */
+#define NUM_GLOBAL_ANIMS_AND_TOONS	(NUM_GLOBAL_ANIMS +		\
+					 NUM_GLOBAL_TOON_ANIMS)
+#define NUM_GLOBAL_ANIM_PARTS_AND_TOONS	MAX(NUM_GLOBAL_ANIM_PARTS_ALL,	\
+					    NUM_GLOBAL_TOON_PARTS)
+
+#define ANIM_CLASS_BIT_TITLE_INITIAL	0
+#define ANIM_CLASS_BIT_TITLE		1
+#define ANIM_CLASS_BIT_MAIN		2
+#define ANIM_CLASS_BIT_SUBMENU		3
+#define ANIM_CLASS_BIT_MENU		4
+#define ANIM_CLASS_BIT_TOONS		5
+
+#define NUM_ANIM_CLASSES		6
+
+#define ANIM_CLASS_NONE			0
+#define ANIM_CLASS_TITLE_INITIAL	(1 << ANIM_CLASS_BIT_TITLE_INITIAL)
+#define ANIM_CLASS_TITLE		(1 << ANIM_CLASS_BIT_TITLE)
+#define ANIM_CLASS_MAIN			(1 << ANIM_CLASS_BIT_MAIN)
+#define ANIM_CLASS_SUBMENU		(1 << ANIM_CLASS_BIT_SUBMENU)
+#define ANIM_CLASS_MENU			(1 << ANIM_CLASS_BIT_MENU)
+#define ANIM_CLASS_TOONS		(1 << ANIM_CLASS_BIT_TOONS)
+
+#define ANIM_CLASS_TOONS_MENU_MAIN	(ANIM_CLASS_TOONS |	\
+					 ANIM_CLASS_MENU  |	\
+					 ANIM_CLASS_MAIN)
+
+#define ANIM_CLASS_TOONS_MENU_SUBMENU	(ANIM_CLASS_TOONS |	\
+					 ANIM_CLASS_MENU  |	\
+					 ANIM_CLASS_SUBMENU)
+
+/* values for global animation states */
+#define ANIM_STATE_INACTIVE		0
+#define ANIM_STATE_RESTART		(1 << 0)
+#define ANIM_STATE_WAITING		(1 << 1)
+#define ANIM_STATE_RUNNING		(1 << 2)
+
+/* values for global animation control */
+#define ANIM_NO_ACTION			0
+#define ANIM_START			1
+#define ANIM_CONTINUE			2
+#define ANIM_STOP			3
+
+
+struct GlobalAnimPartControlInfo
+{
+  int nr;
+  int anim_nr;
+  int mode_nr;
+
+  int sound;
+  int music;
+  int graphic;
+
+  struct GraphicInfo graphic_info;
+  struct GraphicInfo control_info;
+
+  int viewport_x;
+  int viewport_y;
+  int viewport_width;
+  int viewport_height;
+
+  int x, y;
+  int step_xoffset, step_yoffset;
+
+  unsigned int initial_anim_sync_frame;
+  unsigned int step_delay, step_delay_value;
+
+  int init_delay_counter;
+  int anim_delay_counter;
+  int post_delay_counter;
+
+  int drawing_stage;
+
+  int state;
+  int last_anim_status;
+};
+
+struct GlobalAnimMainControlInfo
+{
+  struct GlobalAnimPartControlInfo base;
+  struct GlobalAnimPartControlInfo part[NUM_GLOBAL_ANIM_PARTS_AND_TOONS];
+
+  int nr;
+  int mode_nr;
+
+  struct GraphicInfo control_info;
+
+  int num_parts;
+  int part_counter;
+  int active_part_nr;
+
+  boolean has_base;
+
+  int init_delay_counter;
+
+  int state;
+
+  int last_state, last_active_part_nr;
+};
+
+struct GlobalAnimControlInfo
+{
+  struct GlobalAnimMainControlInfo anim[NUM_GLOBAL_ANIMS_AND_TOONS];
+
+  int nr;
+  int num_anims;
+};
+
+struct GameModeAnimClass
+{
+  int game_mode;
+  int class;
+} game_mode_anim_classes_list[] =
+{
+  { GAME_MODE_TITLE_INITIAL_1,		ANIM_CLASS_TITLE_INITIAL	},
+  { GAME_MODE_TITLE_INITIAL_2,		ANIM_CLASS_TITLE_INITIAL	},
+  { GAME_MODE_TITLE_INITIAL_3,		ANIM_CLASS_TITLE_INITIAL	},
+  { GAME_MODE_TITLE_INITIAL_4,		ANIM_CLASS_TITLE_INITIAL	},
+  { GAME_MODE_TITLE_INITIAL_5,		ANIM_CLASS_TITLE_INITIAL	},
+  { GAME_MODE_TITLE_1,			ANIM_CLASS_TITLE		},
+  { GAME_MODE_TITLE_2,			ANIM_CLASS_TITLE		},
+  { GAME_MODE_TITLE_3,			ANIM_CLASS_TITLE		},
+  { GAME_MODE_TITLE_4,			ANIM_CLASS_TITLE		},
+  { GAME_MODE_TITLE_5,			ANIM_CLASS_TITLE		},
+  { GAME_MODE_LEVELS, 			ANIM_CLASS_TOONS_MENU_SUBMENU	},
+  { GAME_MODE_LEVELNR,			ANIM_CLASS_TOONS_MENU_SUBMENU	},
+  { GAME_MODE_INFO,			ANIM_CLASS_TOONS_MENU_SUBMENU	},
+  { GAME_MODE_SETUP,			ANIM_CLASS_TOONS_MENU_SUBMENU	},
+  { GAME_MODE_PSEUDO_MAINONLY,		ANIM_CLASS_TOONS_MENU_MAIN	},
+  { GAME_MODE_PSEUDO_TYPENAME,		ANIM_CLASS_TOONS_MENU_MAIN	},
+  { GAME_MODE_SCORES,			ANIM_CLASS_TOONS		},
+
+  { -1,					-1				}
+};
+
+struct AnimClassGameMode
+{
+  int class_bit;
+  int game_mode;
+} anim_class_game_modes_list[] =
+{
+  { ANIM_CLASS_BIT_TITLE_INITIAL,	GAME_MODE_TITLE_INITIAL		},
+  { ANIM_CLASS_BIT_TITLE,		GAME_MODE_TITLE			},
+  { ANIM_CLASS_BIT_MAIN,		GAME_MODE_MAIN			},
+  { ANIM_CLASS_BIT_SUBMENU,		GAME_MODE_PSEUDO_SUBMENU	},
+  { ANIM_CLASS_BIT_MENU,		GAME_MODE_PSEUDO_MENU		},
+  { ANIM_CLASS_BIT_TOONS,		GAME_MODE_PSEUDO_TOONS		},
+
+  { -1,					-1				}
+};
+
+/* forward declaration for internal use */
+static void HandleGlobalAnim(int, int);
+static void DoAnimationExt(void);
+
+static struct GlobalAnimControlInfo global_anim_ctrl[NUM_GAME_MODES];
+
+static unsigned int anim_sync_frame = 0;
+
+static int game_mode_anim_classes[NUM_GAME_MODES];
+static int anim_class_game_modes[NUM_ANIM_CLASSES];
+
+static int anim_status_last = GAME_MODE_DEFAULT;
+static int anim_classes_last = ANIM_CLASS_NONE;
+
+static boolean drawing_to_fading_buffer = FALSE;
+
+
+/* ========================================================================= */
+/* generic animation frame calculation                                       */
+/* ========================================================================= */
+
+int getAnimationFrame(int num_frames, int delay, int mode, int start_frame,
+		      int sync_frame)
+{
+  int frame = 0;
+
+  sync_frame += start_frame * delay;
+
+  if (mode & ANIM_LOOP)			/* looping animation */
+  {
+    frame = (sync_frame % (delay * num_frames)) / delay;
+  }
+  else if (mode & ANIM_LINEAR)		/* linear (non-looping) animation */
+  {
+    frame = sync_frame / delay;
+
+    if (frame > num_frames - 1)
+      frame = num_frames - 1;
+  }
+  else if (mode & ANIM_PINGPONG)	/* oscillate (border frames once) */
+  {
+    int max_anim_frames = (num_frames > 1 ? 2 * num_frames - 2 : 1);
+
+    frame = (sync_frame % (delay * max_anim_frames)) / delay;
+    frame = (frame < num_frames ? frame : max_anim_frames - frame);
+  }
+  else if (mode & ANIM_PINGPONG2)	/* oscillate (border frames twice) */
+  {
+    int max_anim_frames = 2 * num_frames;
+
+    frame = (sync_frame % (delay * max_anim_frames)) / delay;
+    frame = (frame < num_frames ? frame : max_anim_frames - frame - 1);
+  }
+  else if (mode & ANIM_RANDOM)		/* play frames in random order */
+  {
+    /* note: expect different frames for the same delay cycle! */
+
+    if (gfx.anim_random_frame < 0)
+      frame = GetSimpleRandom(num_frames);
+    else
+      frame = gfx.anim_random_frame % num_frames;
+  }
+  else if (mode & (ANIM_CE_VALUE | ANIM_CE_SCORE | ANIM_CE_DELAY))
+  {
+    frame = sync_frame % num_frames;
+  }
+
+  if (mode & ANIM_REVERSE)		/* use reverse animation direction */
+    frame = num_frames - frame - 1;
+
+  return frame;
+}
+
+
+/* ========================================================================= */
+/* global animation functions                                                */
+/* ========================================================================= */
+
+static int getGlobalAnimationPart(struct GlobalAnimMainControlInfo *anim)
+{
+  struct GraphicInfo *c = &anim->control_info;
+  int last_anim_random_frame = gfx.anim_random_frame;
+  int part_nr;
+
+  gfx.anim_random_frame = -1;	// (use simple, ad-hoc random numbers)
+
+  part_nr = getAnimationFrame(anim->num_parts, 1,
+			      c->anim_mode, c->anim_start_frame,
+			      anim->part_counter);
+
+  gfx.anim_random_frame = last_anim_random_frame;
+
+  return part_nr;
+}
+
+static int compareGlobalAnimPartControlInfo(const void *obj1, const void *obj2)
+{
+  const struct GlobalAnimPartControlInfo *o1 =
+    (struct GlobalAnimPartControlInfo *)obj1;
+  const struct GlobalAnimPartControlInfo *o2 =
+    (struct GlobalAnimPartControlInfo *)obj2;
+  int compare_result;
+
+  if (o1->control_info.draw_order != o2->control_info.draw_order)
+    compare_result = o1->control_info.draw_order - o2->control_info.draw_order;
+  else
+    compare_result = o1->nr - o2->nr;
+
+  return compare_result;
+}
+
+static int compareGlobalAnimMainControlInfo(const void *obj1, const void *obj2)
+{
+  const struct GlobalAnimMainControlInfo *o1 =
+    (struct GlobalAnimMainControlInfo *)obj1;
+  const struct GlobalAnimMainControlInfo *o2 =
+    (struct GlobalAnimMainControlInfo *)obj2;
+  int compare_result;
+
+  if (o1->control_info.draw_order != o2->control_info.draw_order)
+    compare_result = o1->control_info.draw_order - o2->control_info.draw_order;
+  else
+    compare_result = o1->nr - o2->nr;
+
+  return compare_result;
+}
+
+static void InitToonControls()
+{
+  int mode_nr_toons = GAME_MODE_PSEUDO_TOONS;
+  struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr_toons];
+  struct GlobalAnimMainControlInfo *anim = &ctrl->anim[ctrl->num_anims];
+  int mode_nr, anim_nr, part_nr;
+  int control = IMG_INTERNAL_GLOBAL_TOON_DEFAULT;
+  int num_toons = MAX_NUM_TOONS;
+  int i;
+
+  if (global.num_toons >= 0 && global.num_toons < MAX_NUM_TOONS)
+    num_toons = global.num_toons;
+
+  mode_nr = mode_nr_toons;
+  anim_nr = ctrl->num_anims;
+
+  anim->nr = anim_nr;
+  anim->mode_nr = mode_nr;
+  anim->control_info = graphic_info[control];
+
+  anim->num_parts = 0;
+  anim->part_counter = 0;
+  anim->active_part_nr = 0;
+
+  anim->has_base = FALSE;
+
+  anim->init_delay_counter = 0;
+
+  anim->state = ANIM_STATE_INACTIVE;
+
+  part_nr = 0;
+
+  for (i = 0; i < num_toons; i++)
+  {
+    struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
+    int sound = SND_UNDEFINED;
+    int music = MUS_UNDEFINED;
+    int graphic = IMG_TOON_1 + i;
+    int control = graphic;
+
+    part->nr = part_nr;
+    part->anim_nr = anim_nr;
+    part->mode_nr = mode_nr;
+    part->sound = sound;
+    part->music = music;
+    part->graphic = graphic;
+    part->graphic_info = graphic_info[graphic];
+    part->control_info = graphic_info[control];
+
+    part->graphic_info.anim_delay *= part->graphic_info.step_delay;
+
+    part->control_info.init_delay_fixed = 0;
+    part->control_info.init_delay_random = 150;
+
+    part->control_info.x = ARG_UNDEFINED_VALUE;
+    part->control_info.y = ARG_UNDEFINED_VALUE;
+
+    part->initial_anim_sync_frame = 0;
+
+    part->step_delay = 0;
+    part->step_delay_value = graphic_info[control].step_delay;
+
+    part->state = ANIM_STATE_INACTIVE;
+    part->last_anim_status = -1;
+
+    anim->num_parts++;
+    part_nr++;
+  }
+
+  ctrl->num_anims++;
+}
+
+void InitGlobalAnimControls()
+{
+  int i, m, a, p;
+  int mode_nr, anim_nr, part_nr;
+  int sound, music, graphic, control;
+
+  anim_sync_frame = 0;
+
+  for (m = 0; m < NUM_GAME_MODES; m++)
+  {
+    mode_nr = m;
+
+    struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr];
+
+    ctrl->nr = mode_nr;
+    ctrl->num_anims = 0;
+
+    anim_nr = 0;
+
+    for (a = 0; a < NUM_GLOBAL_ANIMS; a++)
+    {
+      struct GlobalAnimMainControlInfo *anim = &ctrl->anim[anim_nr];
+      int ctrl_id = GLOBAL_ANIM_ID_CONTROL_FIRST + a;
+
+      control = global_anim_info[ctrl_id].graphic[GLOBAL_ANIM_ID_PART_BASE][m];
+
+      // if no base animation parameters defined, use default values
+      if (control == IMG_UNDEFINED)
+	control = IMG_INTERNAL_GLOBAL_ANIM_DEFAULT;
+
+      anim->nr = anim_nr;
+      anim->mode_nr = mode_nr;
+      anim->control_info = graphic_info[control];
+
+      anim->num_parts = 0;
+      anim->part_counter = 0;
+      anim->active_part_nr = 0;
+
+      anim->has_base = FALSE;
+
+      anim->init_delay_counter = 0;
+
+      anim->state = ANIM_STATE_INACTIVE;
+
+      part_nr = 0;
+
+      for (p = 0; p < NUM_GLOBAL_ANIM_PARTS_ALL; p++)
+      {
+	struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
+
+	sound   = global_anim_info[a].sound[p][m];
+	music   = global_anim_info[a].music[p][m];
+	graphic = global_anim_info[a].graphic[p][m];
+	control = global_anim_info[ctrl_id].graphic[p][m];
+
+	if (graphic == IMG_UNDEFINED || graphic_info[graphic].bitmap == NULL ||
+	    control == IMG_UNDEFINED)
+	  continue;
+
+#if 0
+	printf("::: mode == %d, anim = %d, part = %d [%d, %d, %d] [%d]\n",
+	       m, a, p, mode_nr, anim_nr, part_nr, control);
+#endif
+
+#if 0
+	printf("::: mode == %d, anim = %d, part = %d [%d, %d, %d] [%d]\n",
+	       m, a, p, mode_nr, anim_nr, part_nr, sound);
+#endif
+
+	part->nr = part_nr;
+	part->anim_nr = anim_nr;
+	part->mode_nr = mode_nr;
+	part->sound = sound;
+	part->music = music;
+	part->graphic = graphic;
+	part->graphic_info = graphic_info[graphic];
+	part->control_info = graphic_info[control];
+
+	part->initial_anim_sync_frame = 0;
+
+	part->step_delay = 0;
+	part->step_delay_value = graphic_info[control].step_delay;
+
+	part->state = ANIM_STATE_INACTIVE;
+	part->last_anim_status = -1;
+
+	if (p < GLOBAL_ANIM_ID_PART_BASE)
+	{
+	  anim->num_parts++;
+	  part_nr++;
+	}
+	else
+	{
+	  anim->base = *part;
+	  anim->has_base = TRUE;
+	}
+      }
+
+      if (anim->num_parts > 0 || anim->has_base)
+      {
+	ctrl->num_anims++;
+	anim_nr++;
+      }
+    }
+  }
+
+  InitToonControls();
+
+  /* sort all animations according to draw_order and animation number */
+  for (m = 0; m < NUM_GAME_MODES; m++)
+  {
+    struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[m];
+
+    /* sort all main animations for this game mode */
+    qsort(ctrl->anim, ctrl->num_anims,
+	  sizeof(struct GlobalAnimMainControlInfo),
+	  compareGlobalAnimMainControlInfo);
+
+    for (a = 0; a < ctrl->num_anims; a++)
+    {
+      struct GlobalAnimMainControlInfo *anim = &ctrl->anim[a];
+
+      /* sort all animation parts for this main animation */
+      qsort(anim->part, anim->num_parts,
+	    sizeof(struct GlobalAnimPartControlInfo),
+	    compareGlobalAnimPartControlInfo);
+    }
+  }
+
+  for (i = 0; i < NUM_GAME_MODES; i++)
+    game_mode_anim_classes[i] = ANIM_CLASS_NONE;
+  for (i = 0; game_mode_anim_classes_list[i].game_mode != -1; i++)
+    game_mode_anim_classes[game_mode_anim_classes_list[i].game_mode] =
+      game_mode_anim_classes_list[i].class;
+
+  for (i = 0; i < NUM_ANIM_CLASSES; i++)
+    anim_class_game_modes[i] = GAME_MODE_DEFAULT;
+  for (i = 0; anim_class_game_modes_list[i].game_mode != -1; i++)
+    anim_class_game_modes[anim_class_game_modes_list[i].class_bit] =
+      anim_class_game_modes_list[i].game_mode;
+
+  anim_status_last = GAME_MODE_LOADING;
+  anim_classes_last = ANIM_CLASS_NONE;
+}
+
+void InitGlobalAnimations()
+{
+  InitGlobalAnimControls();
+}
+
+void DrawGlobalAnimationsExt(int drawing_target, int drawing_stage)
+{
+  Bitmap *fade_bitmap =
+    (drawing_target == DRAW_TO_FADE_SOURCE ? gfx.fade_bitmap_source :
+     drawing_target == DRAW_TO_FADE_TARGET ? gfx.fade_bitmap_target : NULL);
+  int game_mode_anim_action[NUM_GAME_MODES];
+  int mode_nr;
+
+  if (!setup.toons)
+    return;
+
+  if (drawing_stage == DRAW_GLOBAL_ANIM_STAGE_1 &&
+      drawing_target == DRAW_TO_SCREEN)
+    DoAnimationExt();
+
+  // always start with reliable default values (no animation actions)
+  for (mode_nr = 0; mode_nr < NUM_GAME_MODES; mode_nr++)
+    game_mode_anim_action[mode_nr] = ANIM_NO_ACTION;
+
+  if (global.anim_status != anim_status_last)
+  {
+    boolean before_fading = (global.anim_status == GAME_MODE_PSEUDO_FADING);
+    boolean after_fading  = (anim_status_last   == GAME_MODE_PSEUDO_FADING);
+    int anim_classes_next = game_mode_anim_classes[global.anim_status_next];
+    int i;
+
+    if (drawing_target == DRAW_TO_FADE_TARGET)
+      after_fading = TRUE;
+
+    // ---------- part 1 ------------------------------------------------------
+    // start or stop global animations by change of game mode
+    // (special handling of animations for "current screen" and "all screens")
+
+    // stop animations for last screen
+    game_mode_anim_action[anim_status_last] = ANIM_STOP;
+
+    // start animations for current screen
+    game_mode_anim_action[global.anim_status] = ANIM_START;
+
+    // start animations for all screens after loading new artwork set
+    if (anim_status_last == GAME_MODE_LOADING)
+      game_mode_anim_action[GAME_MODE_DEFAULT] = ANIM_START;
+
+    // ---------- part 2 ------------------------------------------------------
+    // start or stop global animations by change of animation class
+    // (generic handling of animations for "class of screens")
+
+    for (i = 0; i < NUM_ANIM_CLASSES; i++)
+    {
+      int anim_class_check = (1 << i);
+      int anim_class_game_mode = anim_class_game_modes[i];
+      int anim_class_last = anim_classes_last & anim_class_check;
+      int anim_class_next = anim_classes_next & anim_class_check;
+
+      // stop animations for changed screen class before fading to new screen
+      if (before_fading && anim_class_last && !anim_class_next)
+	game_mode_anim_action[anim_class_game_mode] = ANIM_STOP;
+
+      // start animations for changed screen class after fading to new screen
+      if (after_fading && !anim_class_last && anim_class_next)
+	game_mode_anim_action[anim_class_game_mode] = ANIM_START;
+    }
+
+    if (drawing_target == DRAW_TO_SCREEN)
+    {
+      if (after_fading)
+	anim_classes_last = anim_classes_next;
+
+      anim_status_last = global.anim_status;
+
+      // start or stop animations determined to be started or stopped above
+      for (mode_nr = 0; mode_nr < NUM_GAME_MODES; mode_nr++)
+	if (game_mode_anim_action[mode_nr] != ANIM_NO_ACTION)
+	  HandleGlobalAnim(game_mode_anim_action[mode_nr], mode_nr);
+    }
+    else if (drawing_target == DRAW_TO_FADE_TARGET)
+    {
+      drawing_to_fading_buffer = TRUE;
+
+      // start animations determined to be (temporary) started above
+      for (mode_nr = 0; mode_nr < NUM_GAME_MODES; mode_nr++)
+	if (game_mode_anim_action[mode_nr] == ANIM_START)
+	  HandleGlobalAnim(ANIM_START, mode_nr);
+    }
+  }
+
+  if (global.anim_status == GAME_MODE_LOADING)
+    return;
+
+  for (mode_nr = 0; mode_nr < NUM_GAME_MODES; mode_nr++)
+  {
+    struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr];
+    int anim_nr;
+
+    // when preparing source fading buffer, only draw animations to be stopped
+    if (drawing_target == DRAW_TO_FADE_SOURCE &&
+	game_mode_anim_action[mode_nr] != ANIM_STOP)
+      continue;
+
+    // when preparing target fading buffer, only draw animations to be started
+    if (drawing_target == DRAW_TO_FADE_TARGET &&
+	game_mode_anim_action[mode_nr] != ANIM_START)
+      continue;
+
+#if 0
+    if (mode_nr != GFX_SPECIAL_ARG_DEFAULT &&
+	mode_nr != game_status)
+      continue;
+#endif
+
+    for (anim_nr = 0; anim_nr < ctrl->num_anims; anim_nr++)
+    {
+      struct GlobalAnimMainControlInfo *anim = &ctrl->anim[anim_nr];
+      struct GraphicInfo *c = &anim->control_info;
+      int part_first, part_last;
+      int part_nr;
+
+      if (!(anim->state & ANIM_STATE_RUNNING))
+	continue;
+
+      part_first = part_last = anim->active_part_nr;
+
+      if (c->anim_mode & ANIM_ALL || anim->num_parts == 0)
+      {
+	int num_parts = anim->num_parts + (anim->has_base ? 1 : 0);
+
+	part_first = 0;
+	part_last = num_parts - 1;
+      }
+
+      for (part_nr = part_first; part_nr <= part_last; part_nr++)
+      {
+	struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
+	struct GraphicInfo *g = &part->graphic_info;
+	Bitmap *src_bitmap;
+	int src_x, src_y;
+	int width  = g->width;
+	int height = g->height;
+	int dst_x = part->x;
+	int dst_y = part->y;
+	int cut_x = 0;
+	int cut_y = 0;
+	int sync_frame;
+	int frame;
+
+	if (!(part->state & ANIM_STATE_RUNNING))
+	  continue;
+
+	if (part->drawing_stage != drawing_stage)
+	  continue;
+
+	if (part->x < 0)
+	{
+	  dst_x = 0;
+	  width += part->x;
+	  cut_x = -part->x;
+	}
+	else if (part->x > part->viewport_width - g->width)
+	  width -= (part->x - (part->viewport_width - g->width));
+
+	if (part->y < 0)
+	{
+	  dst_y = 0;
+	  height += part->y;
+	  cut_y = -part->y;
+	}
+	else if (part->y > part->viewport_height - g->height)
+	  height -= (part->y - (part->viewport_height - g->height));
+
+	if (width <= 0 || height <= 0)
+	  continue;
+
+	dst_x += part->viewport_x;
+	dst_y += part->viewport_y;
+
+	sync_frame = anim_sync_frame - part->initial_anim_sync_frame;
+	frame = getAnimationFrame(g->anim_frames, g->anim_delay,
+				  g->anim_mode, g->anim_start_frame,
+				  sync_frame);
+
+	getFixedGraphicSource(part->graphic, frame, &src_bitmap,
+			      &src_x, &src_y);
+
+	src_x += cut_x;
+	src_y += cut_y;
+
+	if (drawing_target == DRAW_TO_SCREEN)
+	  BlitToScreenMasked(src_bitmap, src_x, src_y, width, height,
+			     dst_x, dst_y);
+	else
+	  BlitBitmapMasked(src_bitmap, fade_bitmap, src_x, src_y, width, height,
+			   dst_x, dst_y);
+      }
+    }
+  }
+
+  if (drawing_target == DRAW_TO_FADE_TARGET)
+  {
+    // stop animations determined to be (temporary) started above
+    for (mode_nr = 0; mode_nr < NUM_GAME_MODES; mode_nr++)
+      if (game_mode_anim_action[mode_nr] == ANIM_START)
+	HandleGlobalAnim(ANIM_STOP, mode_nr);
+
+    drawing_to_fading_buffer = FALSE;
+  }
+}
+
+void DrawGlobalAnimations(int drawing_target, int drawing_stage)
+{
+  DrawGlobalAnimationsExt(drawing_target, drawing_stage);
+}
+
+boolean SetGlobalAnimPart_Viewport(struct GlobalAnimPartControlInfo *part)
+{
+  int viewport_x;
+  int viewport_y;
+  int viewport_width;
+  int viewport_height;
+  boolean changed = FALSE;
+
+  if (part->last_anim_status == global.anim_status)
+    return FALSE;
+
+  part->last_anim_status = global.anim_status;
+
+  part->drawing_stage = DRAW_GLOBAL_ANIM_STAGE_1;
+
+  if (part->control_info.class == get_hash_from_key("window") ||
+      part->control_info.class == get_hash_from_key("border"))
+  {
+    viewport_x = 0;
+    viewport_y = 0;
+    viewport_width  = WIN_XSIZE;
+    viewport_height = WIN_YSIZE;
+
+    part->drawing_stage = DRAW_GLOBAL_ANIM_STAGE_2;
+  }
+  else if (part->control_info.class == get_hash_from_key("door_1"))
+  {
+    viewport_x = DX;
+    viewport_y = DY;
+    viewport_width  = DXSIZE;
+    viewport_height = DYSIZE;
+  }
+  else if (part->control_info.class == get_hash_from_key("door_2"))
+  {
+    viewport_x = VX;
+    viewport_y = VY;
+    viewport_width  = VXSIZE;
+    viewport_height = VYSIZE;
+  }
+  else		// default: "playfield"
+  {
+    viewport_x = REAL_SX;
+    viewport_y = REAL_SY;
+    viewport_width  = FULL_SXSIZE;
+    viewport_height = FULL_SYSIZE;
+  }
+
+  if (viewport_x != part->viewport_x ||
+      viewport_y != part->viewport_y ||
+      viewport_width  != part->viewport_width ||
+      viewport_height != part->viewport_height)
+  {
+    part->viewport_x = viewport_x;
+    part->viewport_y = viewport_y;
+    part->viewport_width  = viewport_width;
+    part->viewport_height = viewport_height;
+
+    changed = TRUE;
+  }
+
+  return changed;
+}
+
+static void PlayGlobalAnimSound(struct GlobalAnimPartControlInfo *part)
+{
+  int sound = part->sound;
+
+  if (sound == SND_UNDEFINED)
+    return;
+
+  if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
+      (!setup.sound_loops && IS_LOOP_SOUND(sound)))
+    return;
+
+  // !!! TODO: ADD STEREO POSITION FOR MOVING ANIMATIONS !!!
+  if (IS_LOOP_SOUND(sound))
+    PlaySoundLoop(sound);
+  else
+    PlaySound(sound);
+
+#if 0
+  printf("::: PLAY SOUND %d.%d.%d: %d\n",
+	 part->anim_nr, part->nr, part->mode_nr, sound);
+#endif
+}
+
+static void StopGlobalAnimSound(struct GlobalAnimPartControlInfo *part)
+{
+  int sound = part->sound;
+
+  if (sound == SND_UNDEFINED)
+    return;
+
+  StopSound(sound);
+
+#if 0
+  printf("::: STOP SOUND %d.%d.%d: %d\n",
+	 part->anim_nr, part->nr, part->mode_nr, sound);
+#endif
+}
+
+static void PlayGlobalAnimMusic(struct GlobalAnimPartControlInfo *part)
+{
+  int music = part->music;
+
+  if (music == MUS_UNDEFINED)
+    return;
+
+  if (!setup.sound_music)
+    return;
+
+  PlayMusic(music);
+
+#if 0
+  printf("::: PLAY MUSIC %d.%d.%d: %d\n",
+	 part->anim_nr, part->nr, part->mode_nr, music);
+#endif
+}
+
+static void StopGlobalAnimMusic(struct GlobalAnimPartControlInfo *part)
+{
+  int music = part->music;
+
+  if (music == MUS_UNDEFINED)
+    return;
+
+  StopMusic();
+
+#if 0
+  printf("::: STOP MUSIC %d.%d.%d: %d\n",
+	 part->anim_nr, part->nr, part->mode_nr, music);
+#endif
+}
+
+static void PlayGlobalAnimSoundAndMusic(struct GlobalAnimPartControlInfo *part)
+{
+  // when drawing animations to fading buffer, do not play sounds or music
+  if (drawing_to_fading_buffer)
+    return;
+
+  PlayGlobalAnimSound(part);
+  PlayGlobalAnimMusic(part);
+}
+
+static void StopGlobalAnimSoundAndMusic(struct GlobalAnimPartControlInfo *part)
+{
+  StopGlobalAnimSound(part);
+  StopGlobalAnimMusic(part);
+}
+
+int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state)
+{
+  struct GraphicInfo *g = &part->graphic_info;
+  struct GraphicInfo *c = &part->control_info;
+  boolean viewport_changed = SetGlobalAnimPart_Viewport(part);
+
+  if (viewport_changed)
+    state |= ANIM_STATE_RESTART;
+
+  if (state & ANIM_STATE_RESTART)
+  {
+    // when drawing animations to fading buffer, only start fixed animations
+    if (drawing_to_fading_buffer && (c->x == ARG_UNDEFINED_VALUE ||
+				     c->y == ARG_UNDEFINED_VALUE))
+      return ANIM_STATE_INACTIVE;
+
+    ResetDelayCounterExt(&part->step_delay, anim_sync_frame);
+
+    part->init_delay_counter =
+      (c->init_delay_fixed + GetSimpleRandom(c->init_delay_random));
+
+    part->anim_delay_counter =
+      (c->anim_delay_fixed + GetSimpleRandom(c->anim_delay_random));
+
+    part->initial_anim_sync_frame =
+      (g->anim_global_sync ? 0 : anim_sync_frame + part->init_delay_counter);
+
+    if (c->direction & MV_HORIZONTAL)
+    {
+      int pos_bottom = part->viewport_height - g->height;
+
+      if (c->position == POS_TOP)
+	part->y = 0;
+      else if (c->position == POS_UPPER)
+	part->y = GetSimpleRandom(pos_bottom / 2);
+      else if (c->position == POS_MIDDLE)
+	part->y = pos_bottom / 2;
+      else if (c->position == POS_LOWER)
+	part->y = pos_bottom / 2 + GetSimpleRandom(pos_bottom / 2);
+      else if (c->position == POS_BOTTOM)
+	part->y = pos_bottom;
+      else
+	part->y = GetSimpleRandom(pos_bottom);
+
+      if (c->direction == MV_RIGHT)
+      {
+	part->step_xoffset = c->step_offset;
+	part->x = -g->width + part->step_xoffset;
+      }
+      else
+      {
+	part->step_xoffset = -c->step_offset;
+	part->x = part->viewport_width + part->step_xoffset;
+      }
+
+      part->step_yoffset = 0;
+    }
+    else if (c->direction & MV_VERTICAL)
+    {
+      int pos_right = part->viewport_width - g->width;
+
+      if (c->position == POS_LEFT)
+	part->x = 0;
+      else if (c->position == POS_RIGHT)
+	part->x = pos_right;
+      else
+	part->x = GetSimpleRandom(pos_right);
+
+      if (c->direction == MV_DOWN)
+      {
+	part->step_yoffset = c->step_offset;
+	part->y = -g->height + part->step_yoffset;
+      }
+      else
+      {
+	part->step_yoffset = -c->step_offset;
+	part->y = part->viewport_height + part->step_yoffset;
+      }
+
+      part->step_xoffset = 0;
+    }
+    else
+    {
+      part->x = 0;
+      part->y = 0;
+
+      part->step_xoffset = 0;
+      part->step_yoffset = 0;
+    }
+
+    if (c->x != ARG_UNDEFINED_VALUE)
+      part->x = c->x;
+    if (c->y != ARG_UNDEFINED_VALUE)
+      part->y = c->y;
+
+    if (c->step_xoffset != ARG_UNDEFINED_VALUE)
+      part->step_xoffset = c->step_xoffset;
+    if (c->step_yoffset != ARG_UNDEFINED_VALUE)
+      part->step_yoffset = c->step_yoffset;
+
+    if (part->init_delay_counter == 0)
+      PlayGlobalAnimSoundAndMusic(part);
+  }
+
+  if (part->init_delay_counter > 0)
+  {
+    part->init_delay_counter--;
+
+    if (part->init_delay_counter == 0)
+      PlayGlobalAnimSoundAndMusic(part);
+
+    return ANIM_STATE_WAITING;
+  }
+
+  // check if moving animation has left the visible screen area
+  if ((part->x <= -g->width              && part->step_xoffset <= 0) ||
+      (part->x >=  part->viewport_width  && part->step_xoffset >= 0) ||
+      (part->y <= -g->height             && part->step_yoffset <= 0) ||
+      (part->y >=  part->viewport_height && part->step_yoffset >= 0))
+  {
+    // do not stop animation before "anim" or "post" counter are finished
+    if (part->anim_delay_counter == 0 &&
+	part->post_delay_counter == 0)
+    {
+      StopGlobalAnimSoundAndMusic(part);
+
+      part->post_delay_counter =
+	(c->post_delay_fixed + GetSimpleRandom(c->post_delay_random));
+
+      if (part->post_delay_counter > 0)
+	return ANIM_STATE_RUNNING;
+
+      // drawing last frame not needed here -- animation not visible anymore
+      return ANIM_STATE_RESTART;
+    }
+  }
+
+  if (part->anim_delay_counter > 0)
+  {
+    part->anim_delay_counter--;
+
+    if (part->anim_delay_counter == 0)
+    {
+      StopGlobalAnimSoundAndMusic(part);
+
+      part->post_delay_counter =
+	(c->post_delay_fixed + GetSimpleRandom(c->post_delay_random));
+
+      if (part->post_delay_counter > 0)
+	return ANIM_STATE_RUNNING;
+
+      // additional state "RUNNING" required to not skip drawing last frame
+      return ANIM_STATE_RESTART | ANIM_STATE_RUNNING;
+    }
+  }
+
+  if (part->post_delay_counter > 0)
+  {
+    part->post_delay_counter--;
+
+    if (part->post_delay_counter == 0)
+      return ANIM_STATE_RESTART;
+
+    return ANIM_STATE_WAITING;
+  }
+
+  if (!DelayReachedExt(&part->step_delay, part->step_delay_value,
+		       anim_sync_frame))
+    return ANIM_STATE_RUNNING;
+
+#if 0
+  {
+    static unsigned int last_counter = -1;
+    unsigned int counter = Counter();
+
+    printf("::: NEXT ANIM PART [%d, %d]\n",
+	   anim_sync_frame, counter - last_counter);
+
+    last_counter = counter;
+  }
+#endif
+
+  part->x += part->step_xoffset;
+  part->y += part->step_yoffset;
+
+  return ANIM_STATE_RUNNING;
+}
+
+void HandleGlobalAnim_Main(struct GlobalAnimMainControlInfo *anim, int action)
+{
+  struct GlobalAnimPartControlInfo *part;
+  struct GraphicInfo *c = &anim->control_info;
+  int state, active_part_nr;
+
+#if 0
+  printf("::: HandleGlobalAnim_Main: %d, %d => %d\n",
+	 anim->mode_nr, anim->nr, anim->num_parts);
+  printf("::: %d, %d, %d\n", global.num_toons, setup.toons, num_toons);
+#endif
+
+#if 0
+  printf("::: %s(%d): %d, %d, %d [%d]\n",
+	 (action == ANIM_START ? "ANIM_START" :
+	  action == ANIM_CONTINUE ? "ANIM_CONTINUE" :
+	  action == ANIM_STOP ? "ANIM_STOP" : "(should not happen)"),
+	 anim->nr,
+	 anim->state & ANIM_STATE_RESTART,
+	 anim->state & ANIM_STATE_WAITING,
+	 anim->state & ANIM_STATE_RUNNING,
+	 anim->num_parts);
+#endif
+
+  switch (action)
+  {
+    case ANIM_START:
+      anim->state = anim->last_state = ANIM_STATE_RESTART;
+      anim->active_part_nr = anim->last_active_part_nr = 0;
+      anim->part_counter = 0;
+
+      break;
+
+    case ANIM_CONTINUE:
+      if (anim->state == ANIM_STATE_INACTIVE)
+	return;
+
+      anim->state = anim->last_state;
+      anim->active_part_nr = anim->last_active_part_nr;
+
+      break;
+
+    case ANIM_STOP:
+      anim->state = ANIM_STATE_INACTIVE;
+
+      {
+	int num_parts = anim->num_parts + (anim->has_base ? 1 : 0);
+	int i;
+
+	for (i = 0; i < num_parts; i++)
+	  StopGlobalAnimSoundAndMusic(&anim->part[i]);
+      }
+
+      return;
+
+    default:
+      break;
+  }
+
+  if (c->anim_mode & ANIM_ALL || anim->num_parts == 0)
+  {
+    int num_parts = anim->num_parts + (anim->has_base ? 1 : 0);
+    int i;
+
+#if 0
+    printf("::: HandleGlobalAnim_Main: %d, %d => %d\n",
+	   anim->mode_nr, anim->nr, num_parts);
+#endif
+
+    for (i = 0; i < num_parts; i++)
+    {
+      part = &anim->part[i];
+
+      switch (action)
+      {
+        case ANIM_START:
+	  anim->state = ANIM_STATE_RUNNING;
+	  part->state = ANIM_STATE_RESTART;
+
+	  break;
+
+        case ANIM_CONTINUE:
+	  if (part->state == ANIM_STATE_INACTIVE)
+	    continue;
+
+	  break;
+
+        case ANIM_STOP:
+	  part->state = ANIM_STATE_INACTIVE;
+
+	  continue;
+
+        default:
+	  break;
+      }
+
+      part->state = HandleGlobalAnim_Part(part, part->state);
+
+      // when animation mode is "once", stop after animation was played once
+      if (c->anim_mode & ANIM_ONCE &&
+	  part->state & ANIM_STATE_RESTART)
+	part->state = ANIM_STATE_INACTIVE;
+    }
+
+    anim->last_state = anim->state;
+    anim->last_active_part_nr = anim->active_part_nr;
+
+    return;
+  }
+
+  if (anim->state & ANIM_STATE_RESTART)		// directly after restart
+    anim->active_part_nr = getGlobalAnimationPart(anim);
+
+  part = &anim->part[anim->active_part_nr];
+
+  part->state = ANIM_STATE_RUNNING;
+
+  anim->state = HandleGlobalAnim_Part(part, anim->state);
+
+  if (anim->state & ANIM_STATE_RESTART)
+    anim->part_counter++;
+
+  // when animation mode is "once", stop after all animations were played once
+  if (c->anim_mode & ANIM_ONCE &&
+      anim->part_counter == anim->num_parts)
+    anim->state = ANIM_STATE_INACTIVE;
+
+  state = anim->state;
+  active_part_nr = anim->active_part_nr;
+
+  // while the animation parts are pausing (waiting or inactive), play the base
+  // (main) animation; this corresponds to the "boring player animation" logic
+  // (!!! KLUDGE WARNING: I THINK THIS IS A MESS THAT SHOULD BE CLEANED UP !!!)
+  if (anim->has_base)
+  {
+    if (anim->state == ANIM_STATE_WAITING ||
+	anim->state == ANIM_STATE_INACTIVE)
+    {
+      anim->active_part_nr = anim->num_parts;	// part nr of base animation
+      part = &anim->part[anim->active_part_nr];
+
+      if (anim->state != anim->last_state)
+	part->state = ANIM_STATE_RESTART;
+
+      anim->state = ANIM_STATE_RUNNING;
+      part->state = HandleGlobalAnim_Part(part, part->state);
+    }
+  }
+
+  anim->last_state = state;
+  anim->last_active_part_nr = active_part_nr;
+}
+
+void HandleGlobalAnim_Mode(struct GlobalAnimControlInfo *ctrl, int action)
+{
+  int i;
+
+#if 0
+  printf("::: HandleGlobalAnim_Mode: %d => %d\n",
+	 ctrl->nr, ctrl->num_anims);
+#endif
+
+  for (i = 0; i < ctrl->num_anims; i++)
+    HandleGlobalAnim_Main(&ctrl->anim[i], action);
+}
+
+static void HandleGlobalAnim(int action, int game_mode)
+{
+#if 0
+  printf("::: HandleGlobalAnim [mode == %d]\n", game_status);
+#endif
+
+  HandleGlobalAnim_Mode(&global_anim_ctrl[game_mode], action);
+}
+
+static void DoAnimationExt()
+{
+  int i;
+
+#if 0
+  printf("::: DoAnimation [%d, %d]\n", anim_sync_frame, Counter());
+#endif
+
+  // global animations now synchronized with frame delay of screen update
+  anim_sync_frame++;
+
+  for (i = 0; i < NUM_GAME_MODES; i++)
+    HandleGlobalAnim(ANIM_CONTINUE, i);
+
+#if 0
+  // force screen redraw in next frame to continue drawing global animations
+  redraw_mask = REDRAW_ALL;
+#endif
+}
diff --git a/src/anim.h b/src/anim.h
new file mode 100644
index 0000000..99de93e
--- /dev/null
+++ b/src/anim.h
@@ -0,0 +1,21 @@
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// anim.h
+// ============================================================================
+
+#ifndef ANIM_H
+#define ANIM_H
+
+
+int getAnimationFrame(int, int, int, int, int);
+
+void InitGlobalAnimations(void);
+void DrawGlobalAnimations(int, int);
+
+#endif
diff --git a/src/cartoons.c b/src/cartoons.c
deleted file mode 100644
index 8ca4bdd..0000000
--- a/src/cartoons.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* cartoons.c                                               *
-***********************************************************/
-
-#include "cartoons.h"
-#include "main.h"
-#include "tools.h"
-
-
-/* values for toon definition */
-#define MAX_NUM_TOONS			20
-
-static struct ToonInfo toons[MAX_NUM_TOONS];
-
-static void PrepareBackbuffer()
-{
-  if (game_status != GAME_MODE_PLAYING)
-    return;
-
-  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
-  {
-    BlitScreenToBitmap_EM(backbuffer);
-  }
-  else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
-  {
-    BlitScreenToBitmap_SP(backbuffer);
-  }
-  else if (setup.soft_scrolling)	/* GAME_ENGINE_TYPE_RND */
-  {
-    int fx = FX, fy = FY;
-
-    fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
-    fy += (ScreenMovDir & (MV_UP|MV_DOWN)    ? ScreenGfxPos : 0);
-
-    BlitBitmap(fieldbuffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
-  }
-}
-
-boolean ToonNeedsRedraw()
-{
-  return TRUE;
-}
-
-void InitToons()
-{
-  int num_toons = MAX_NUM_TOONS;
-  int i;
-
-  if (global.num_toons >= 0 && global.num_toons < MAX_NUM_TOONS)
-    num_toons = global.num_toons;
-
-  for (i = 0; i < num_toons; i++)
-  {
-    int graphic = IMG_TOON_1 + i;
-    struct FileInfo *image = getImageListEntryFromImageID(graphic);
-
-    toons[i].bitmap = graphic_info[graphic].bitmap;
-
-    toons[i].src_x = graphic_info[graphic].src_x;
-    toons[i].src_y = graphic_info[graphic].src_y;
-
-    toons[i].width  = graphic_info[graphic].width;
-    toons[i].height = graphic_info[graphic].height;
-
-    toons[i].anim_frames      = graphic_info[graphic].anim_frames;
-    toons[i].anim_delay       = graphic_info[graphic].anim_delay;
-    toons[i].anim_mode        = graphic_info[graphic].anim_mode;
-    toons[i].anim_start_frame = graphic_info[graphic].anim_start_frame;
-
-    toons[i].step_offset = graphic_info[graphic].step_offset;
-    toons[i].step_delay  = graphic_info[graphic].step_delay;
-
-    toons[i].direction = image->parameter[GFX_ARG_DIRECTION];
-    toons[i].position = image->parameter[GFX_ARG_POSITION];
-  }
-
-#if 1
-  InitToonScreen(bitmap_db_toons,
-#else
-  InitToonScreen(bitmap_db_door,
-#endif
-		 BackToFront, PrepareBackbuffer, ToonNeedsRedraw,
-		 toons, num_toons,
-		 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
-		 GAME_FRAME_DELAY);
-}
diff --git a/src/cartoons.h b/src/cartoons.h
deleted file mode 100644
index 073cc52..0000000
--- a/src/cartoons.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* cartoons.h                                               *
-***********************************************************/
-
-#ifndef CARTOONS_H
-#define CARTOONS_H
-
-void InitToons(void);
-
-#endif
diff --git a/src/conf_act.c b/src/conf_act.c
index 60c69b0..46db591 100644
--- a/src/conf_act.c
+++ b/src/conf_act.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_act.c                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                  Holger Schemel
+//                  info at artsoft.org
+//                  http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_act.c
+// ============================================================================
 
 /* ----- this file was automatically generated -- do not edit by hand ----- */
 
diff --git a/src/conf_chr.c b/src/conf_chr.c
index 3aa42ed..d8edb5a 100644
--- a/src/conf_chr.c
+++ b/src/conf_chr.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_chr.c                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                  Holger Schemel
+//                  info at artsoft.org
+//                  http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_chr.c
+// ============================================================================
 
 /* ----- this file was automatically generated -- do not edit by hand ----- */
 
@@ -18,750 +16,750 @@
 
 /* values for graphics configuration (character elements) */
 
-  { "char_space",				"RocksFontEM.pcx"	},
+  { "char_space",				"RocksFontEM.png"	},
   { "char_space.xpos",				"0"			},
   { "char_space.ypos",				"0"			},
   { "char_space.frames",			"1"			},
-  { "char_space.EDITOR",			"RocksFontEM.pcx"	},
+  { "char_space.EDITOR",			"RocksFontEM.png"	},
   { "char_space.EDITOR.xpos",			"7"			},
   { "char_space.EDITOR.ypos",			"4"			},
   { "char_space.EDITOR.frames",			"1"			},
 
-  { "char_exclam",				"RocksFontEM.pcx"	},
+  { "char_exclam",				"RocksFontEM.png"	},
   { "char_exclam.xpos",				"1"			},
   { "char_exclam.ypos",				"0"			},
   { "char_exclam.frames",			"1"			},
 
-  { "char_quotedbl",				"RocksFontEM.pcx"	},
+  { "char_quotedbl",				"RocksFontEM.png"	},
   { "char_quotedbl.xpos",			"2"			},
   { "char_quotedbl.ypos",			"0"			},
   { "char_quotedbl.frames",			"1"			},
 
-  { "char_numbersign",				"RocksFontEM.pcx"	},
+  { "char_numbersign",				"RocksFontEM.png"	},
   { "char_numbersign.xpos",			"3"			},
   { "char_numbersign.ypos",			"0"			},
   { "char_numbersign.frames",			"1"			},
 
-  { "char_dollar",				"RocksFontEM.pcx"	},
+  { "char_dollar",				"RocksFontEM.png"	},
   { "char_dollar.xpos",				"4"			},
   { "char_dollar.ypos",				"0"			},
   { "char_dollar.frames",			"1"			},
 
-  { "char_percent",				"RocksFontEM.pcx"	},
+  { "char_percent",				"RocksFontEM.png"	},
   { "char_percent.xpos",			"5"			},
   { "char_percent.ypos",			"0"			},
   { "char_percent.frames",			"1"			},
 
-  { "char_ampersand",				"RocksFontEM.pcx"	},
+  { "char_ampersand",				"RocksFontEM.png"	},
   { "char_ampersand.xpos",			"6"			},
   { "char_ampersand.ypos",			"0"			},
   { "char_ampersand.frames",			"1"			},
 
-  { "char_apostrophe",				"RocksFontEM.pcx"	},
+  { "char_apostrophe",				"RocksFontEM.png"	},
   { "char_apostrophe.xpos",			"7"			},
   { "char_apostrophe.ypos",			"0"			},
   { "char_apostrophe.frames",			"1"			},
 
-  { "char_parenleft",				"RocksFontEM.pcx"	},
+  { "char_parenleft",				"RocksFontEM.png"	},
   { "char_parenleft.xpos",			"8"			},
   { "char_parenleft.ypos",			"0"			},
   { "char_parenleft.frames",			"1"			},
 
-  { "char_parenright",				"RocksFontEM.pcx"	},
+  { "char_parenright",				"RocksFontEM.png"	},
   { "char_parenright.xpos",			"9"			},
   { "char_parenright.ypos",			"0"			},
   { "char_parenright.frames",			"1"			},
 
-  { "char_asterisk",				"RocksFontEM.pcx"	},
+  { "char_asterisk",				"RocksFontEM.png"	},
   { "char_asterisk.xpos",			"10"			},
   { "char_asterisk.ypos",			"0"			},
   { "char_asterisk.frames",			"1"			},
 
-  { "char_plus",				"RocksFontEM.pcx"	},
+  { "char_plus",				"RocksFontEM.png"	},
   { "char_plus.xpos",				"11"			},
   { "char_plus.ypos",				"0"			},
   { "char_plus.frames",				"1"			},
 
-  { "char_comma",				"RocksFontEM.pcx"	},
+  { "char_comma",				"RocksFontEM.png"	},
   { "char_comma.xpos",				"12"			},
   { "char_comma.ypos",				"0"			},
   { "char_comma.frames",			"1"			},
 
-  { "char_minus",				"RocksFontEM.pcx"	},
+  { "char_minus",				"RocksFontEM.png"	},
   { "char_minus.xpos",				"13"			},
   { "char_minus.ypos",				"0"			},
   { "char_minus.frames",			"1"			},
 
-  { "char_period",				"RocksFontEM.pcx"	},
+  { "char_period",				"RocksFontEM.png"	},
   { "char_period.xpos",				"14"			},
   { "char_period.ypos",				"0"			},
   { "char_period.frames",			"1"			},
 
-  { "char_slash",				"RocksFontEM.pcx"	},
+  { "char_slash",				"RocksFontEM.png"	},
   { "char_slash.xpos",				"15"			},
   { "char_slash.ypos",				"0"			},
   { "char_slash.frames",			"1"			},
 
-  { "char_0",					"RocksFontEM.pcx"	},
+  { "char_0",					"RocksFontEM.png"	},
   { "char_0.xpos",				"0"			},
   { "char_0.ypos",				"1"			},
   { "char_0.frames",				"1"			},
 
-  { "char_1",					"RocksFontEM.pcx"	},
+  { "char_1",					"RocksFontEM.png"	},
   { "char_1.xpos",				"1"			},
   { "char_1.ypos",				"1"			},
   { "char_1.frames",				"1"			},
 
-  { "char_2",					"RocksFontEM.pcx"	},
+  { "char_2",					"RocksFontEM.png"	},
   { "char_2.xpos",				"2"			},
   { "char_2.ypos",				"1"			},
   { "char_2.frames",				"1"			},
 
-  { "char_3",					"RocksFontEM.pcx"	},
+  { "char_3",					"RocksFontEM.png"	},
   { "char_3.xpos",				"3"			},
   { "char_3.ypos",				"1"			},
   { "char_3.frames",				"1"			},
 
-  { "char_4",					"RocksFontEM.pcx"	},
+  { "char_4",					"RocksFontEM.png"	},
   { "char_4.xpos",				"4"			},
   { "char_4.ypos",				"1"			},
   { "char_4.frames",				"1"			},
 
-  { "char_5",					"RocksFontEM.pcx"	},
+  { "char_5",					"RocksFontEM.png"	},
   { "char_5.xpos",				"5"			},
   { "char_5.ypos",				"1"			},
   { "char_5.frames",				"1"			},
 
-  { "char_6",					"RocksFontEM.pcx"	},
+  { "char_6",					"RocksFontEM.png"	},
   { "char_6.xpos",				"6"			},
   { "char_6.ypos",				"1"			},
   { "char_6.frames",				"1"			},
 
-  { "char_7",					"RocksFontEM.pcx"	},
+  { "char_7",					"RocksFontEM.png"	},
   { "char_7.xpos",				"7"			},
   { "char_7.ypos",				"1"			},
   { "char_7.frames",				"1"			},
 
-  { "char_8",					"RocksFontEM.pcx"	},
+  { "char_8",					"RocksFontEM.png"	},
   { "char_8.xpos",				"8"			},
   { "char_8.ypos",				"1"			},
   { "char_8.frames",				"1"			},
 
-  { "char_9",					"RocksFontEM.pcx"	},
+  { "char_9",					"RocksFontEM.png"	},
   { "char_9.xpos",				"9"			},
   { "char_9.ypos",				"1"			},
   { "char_9.frames",				"1"			},
 
-  { "char_colon",				"RocksFontEM.pcx"	},
+  { "char_colon",				"RocksFontEM.png"	},
   { "char_colon.xpos",				"10"			},
   { "char_colon.ypos",				"1"			},
   { "char_colon.frames",			"1"			},
 
-  { "char_semicolon",				"RocksFontEM.pcx"	},
+  { "char_semicolon",				"RocksFontEM.png"	},
   { "char_semicolon.xpos",			"11"			},
   { "char_semicolon.ypos",			"1"			},
   { "char_semicolon.frames",			"1"			},
 
-  { "char_less",				"RocksFontEM.pcx"	},
+  { "char_less",				"RocksFontEM.png"	},
   { "char_less.xpos",				"12"			},
   { "char_less.ypos",				"1"			},
   { "char_less.frames",				"1"			},
 
-  { "char_equal",				"RocksFontEM.pcx"	},
+  { "char_equal",				"RocksFontEM.png"	},
   { "char_equal.xpos",				"13"			},
   { "char_equal.ypos",				"1"			},
   { "char_equal.frames",			"1"			},
 
-  { "char_greater",				"RocksFontEM.pcx"	},
+  { "char_greater",				"RocksFontEM.png"	},
   { "char_greater.xpos",			"14"			},
   { "char_greater.ypos",			"1"			},
   { "char_greater.frames",			"1"			},
 
-  { "char_question",				"RocksFontEM.pcx"	},
+  { "char_question",				"RocksFontEM.png"	},
   { "char_question.xpos",			"15"			},
   { "char_question.ypos",			"1"			},
   { "char_question.frames",			"1"			},
 
-  { "char_at",					"RocksFontEM.pcx"	},
+  { "char_at",					"RocksFontEM.png"	},
   { "char_at.xpos",				"0"			},
   { "char_at.ypos",				"2"			},
   { "char_at.frames",				"1"			},
 
-  { "char_a",					"RocksFontEM.pcx"	},
+  { "char_a",					"RocksFontEM.png"	},
   { "char_a.xpos",				"1"			},
   { "char_a.ypos",				"2"			},
   { "char_a.frames",				"1"			},
 
-  { "char_b",					"RocksFontEM.pcx"	},
+  { "char_b",					"RocksFontEM.png"	},
   { "char_b.xpos",				"2"			},
   { "char_b.ypos",				"2"			},
   { "char_b.frames",				"1"			},
 
-  { "char_c",					"RocksFontEM.pcx"	},
+  { "char_c",					"RocksFontEM.png"	},
   { "char_c.xpos",				"3"			},
   { "char_c.ypos",				"2"			},
   { "char_c.frames",				"1"			},
 
-  { "char_d",					"RocksFontEM.pcx"	},
+  { "char_d",					"RocksFontEM.png"	},
   { "char_d.xpos",				"4"			},
   { "char_d.ypos",				"2"			},
   { "char_d.frames",				"1"			},
 
-  { "char_e",					"RocksFontEM.pcx"	},
+  { "char_e",					"RocksFontEM.png"	},
   { "char_e.xpos",				"5"			},
   { "char_e.ypos",				"2"			},
   { "char_e.frames",				"1"			},
 
-  { "char_f",					"RocksFontEM.pcx"	},
+  { "char_f",					"RocksFontEM.png"	},
   { "char_f.xpos",				"6"			},
   { "char_f.ypos",				"2"			},
   { "char_f.frames",				"1"			},
 
-  { "char_g",					"RocksFontEM.pcx"	},
+  { "char_g",					"RocksFontEM.png"	},
   { "char_g.xpos",				"7"			},
   { "char_g.ypos",				"2"			},
   { "char_g.frames",				"1"			},
 
-  { "char_h",					"RocksFontEM.pcx"	},
+  { "char_h",					"RocksFontEM.png"	},
   { "char_h.xpos",				"8"			},
   { "char_h.ypos",				"2"			},
   { "char_h.frames",				"1"			},
 
-  { "char_i",					"RocksFontEM.pcx"	},
+  { "char_i",					"RocksFontEM.png"	},
   { "char_i.xpos",				"9"			},
   { "char_i.ypos",				"2"			},
   { "char_i.frames",				"1"			},
 
-  { "char_j",					"RocksFontEM.pcx"	},
+  { "char_j",					"RocksFontEM.png"	},
   { "char_j.xpos",				"10"			},
   { "char_j.ypos",				"2"			},
   { "char_j.frames",				"1"			},
 
-  { "char_k",					"RocksFontEM.pcx"	},
+  { "char_k",					"RocksFontEM.png"	},
   { "char_k.xpos",				"11"			},
   { "char_k.ypos",				"2"			},
   { "char_k.frames",				"1"			},
 
-  { "char_l",					"RocksFontEM.pcx"	},
+  { "char_l",					"RocksFontEM.png"	},
   { "char_l.xpos",				"12"			},
   { "char_l.ypos",				"2"			},
   { "char_l.frames",				"1"			},
 
-  { "char_m",					"RocksFontEM.pcx"	},
+  { "char_m",					"RocksFontEM.png"	},
   { "char_m.xpos",				"13"			},
   { "char_m.ypos",				"2"			},
   { "char_m.frames",				"1"			},
 
-  { "char_n",					"RocksFontEM.pcx"	},
+  { "char_n",					"RocksFontEM.png"	},
   { "char_n.xpos",				"14"			},
   { "char_n.ypos",				"2"			},
   { "char_n.frames",				"1"			},
 
-  { "char_o",					"RocksFontEM.pcx"	},
+  { "char_o",					"RocksFontEM.png"	},
   { "char_o.xpos",				"15"			},
   { "char_o.ypos",				"2"			},
   { "char_o.frames",				"1"			},
 
-  { "char_p",					"RocksFontEM.pcx"	},
+  { "char_p",					"RocksFontEM.png"	},
   { "char_p.xpos",				"0"			},
   { "char_p.ypos",				"3"			},
   { "char_p.frames",				"1"			},
 
-  { "char_q",					"RocksFontEM.pcx"	},
+  { "char_q",					"RocksFontEM.png"	},
   { "char_q.xpos",				"1"			},
   { "char_q.ypos",				"3"			},
   { "char_q.frames",				"1"			},
 
-  { "char_r",					"RocksFontEM.pcx"	},
+  { "char_r",					"RocksFontEM.png"	},
   { "char_r.xpos",				"2"			},
   { "char_r.ypos",				"3"			},
   { "char_r.frames",				"1"			},
 
-  { "char_s",					"RocksFontEM.pcx"	},
+  { "char_s",					"RocksFontEM.png"	},
   { "char_s.xpos",				"3"			},
   { "char_s.ypos",				"3"			},
   { "char_s.frames",				"1"			},
 
-  { "char_t",					"RocksFontEM.pcx"	},
+  { "char_t",					"RocksFontEM.png"	},
   { "char_t.xpos",				"4"			},
   { "char_t.ypos",				"3"			},
   { "char_t.frames",				"1"			},
 
-  { "char_u",					"RocksFontEM.pcx"	},
+  { "char_u",					"RocksFontEM.png"	},
   { "char_u.xpos",				"5"			},
   { "char_u.ypos",				"3"			},
   { "char_u.frames",				"1"			},
 
-  { "char_v",					"RocksFontEM.pcx"	},
+  { "char_v",					"RocksFontEM.png"	},
   { "char_v.xpos",				"6"			},
   { "char_v.ypos",				"3"			},
   { "char_v.frames",				"1"			},
 
-  { "char_w",					"RocksFontEM.pcx"	},
+  { "char_w",					"RocksFontEM.png"	},
   { "char_w.xpos",				"7"			},
   { "char_w.ypos",				"3"			},
   { "char_w.frames",				"1"			},
 
-  { "char_x",					"RocksFontEM.pcx"	},
+  { "char_x",					"RocksFontEM.png"	},
   { "char_x.xpos",				"8"			},
   { "char_x.ypos",				"3"			},
   { "char_x.frames",				"1"			},
 
-  { "char_y",					"RocksFontEM.pcx"	},
+  { "char_y",					"RocksFontEM.png"	},
   { "char_y.xpos",				"9"			},
   { "char_y.ypos",				"3"			},
   { "char_y.frames",				"1"			},
 
-  { "char_z",					"RocksFontEM.pcx"	},
+  { "char_z",					"RocksFontEM.png"	},
   { "char_z.xpos",				"10"			},
   { "char_z.ypos",				"3"			},
   { "char_z.frames",				"1"			},
 
-  { "char_bracketleft",				"RocksFontEM.pcx"	},
+  { "char_bracketleft",				"RocksFontEM.png"	},
   { "char_bracketleft.xpos",			"11"			},
   { "char_bracketleft.ypos",			"3"			},
   { "char_bracketleft.frames",			"1"			},
 
-  { "char_backslash",				"RocksFontEM.pcx"	},
+  { "char_backslash",				"RocksFontEM.png"	},
   { "char_backslash.xpos",			"12"			},
   { "char_backslash.ypos",			"3"			},
   { "char_backslash.frames",			"1"			},
 
-  { "char_bracketright",			"RocksFontEM.pcx"	},
+  { "char_bracketright",			"RocksFontEM.png"	},
   { "char_bracketright.xpos",			"13"			},
   { "char_bracketright.ypos",			"3"			},
   { "char_bracketright.frames",			"1"			},
 
-  { "char_asciicircum",				"RocksFontEM.pcx"	},
+  { "char_asciicircum",				"RocksFontEM.png"	},
   { "char_asciicircum.xpos",			"14"			},
   { "char_asciicircum.ypos",			"3"			},
   { "char_asciicircum.frames",			"1"			},
 
-  { "char_underscore",				"RocksFontEM.pcx"	},
+  { "char_underscore",				"RocksFontEM.png"	},
   { "char_underscore.xpos",			"15"			},
   { "char_underscore.ypos",			"3"			},
   { "char_underscore.frames",			"1"			},
 
-  { "char_copyright",				"RocksFontEM.pcx"	},
+  { "char_copyright",				"RocksFontEM.png"	},
   { "char_copyright.xpos",			"0"			},
   { "char_copyright.ypos",			"4"			},
   { "char_copyright.frames",			"1"			},
 
-  { "char_aumlaut",				"RocksFontEM.pcx"	},
+  { "char_aumlaut",				"RocksFontEM.png"	},
   { "char_aumlaut.xpos",			"1"			},
   { "char_aumlaut.ypos",			"4"			},
   { "char_aumlaut.frames",			"1"			},
 
-  { "char_oumlaut",				"RocksFontEM.pcx"	},
+  { "char_oumlaut",				"RocksFontEM.png"	},
   { "char_oumlaut.xpos",			"2"			},
   { "char_oumlaut.ypos",			"4"			},
   { "char_oumlaut.frames",			"1"			},
 
-  { "char_uumlaut",				"RocksFontEM.pcx"	},
+  { "char_uumlaut",				"RocksFontEM.png"	},
   { "char_uumlaut.xpos",			"3"			},
   { "char_uumlaut.ypos",			"4"			},
   { "char_uumlaut.frames",			"1"			},
 
-  { "char_degree",				"RocksFontEM.pcx"	},
+  { "char_degree",				"RocksFontEM.png"	},
   { "char_degree.xpos",				"4"			},
   { "char_degree.ypos",				"4"			},
   { "char_degree.frames",			"1"			},
 
-  { "char_trademark",				"RocksFontEM.pcx"	},
+  { "char_trademark",				"RocksFontEM.png"	},
   { "char_trademark.xpos",			"5"			},
   { "char_trademark.ypos",			"4"			},
   { "char_trademark.frames",			"1"			},
 
-  { "char_cursor",				"RocksFontEM.pcx"	},
+  { "char_cursor",				"RocksFontEM.png"	},
   { "char_cursor.xpos",				"6"			},
   { "char_cursor.ypos",				"4"			},
   { "char_cursor.frames",			"1"			},
 
-  { "char_button",				"RocksFontEM.pcx"	},
+  { "char_button",				"RocksFontEM.png"	},
   { "char_button.xpos",				"13"			},
   { "char_button.ypos",				"4"			},
   { "char_button.frames",			"1"			},
 
-  { "char_up",					"RocksFontEM.pcx"	},
+  { "char_up",					"RocksFontEM.png"	},
   { "char_up.xpos",				"14"			},
   { "char_up.ypos",				"4"			},
   { "char_up.frames",				"1"			},
 
-  { "char_down",				"RocksFontEM.pcx"	},
+  { "char_down",				"RocksFontEM.png"	},
   { "char_down.xpos",				"15"			},
   { "char_down.ypos",				"4"			},
   { "char_down.frames",				"1"			},
 
-  { "steel_char_space",				"RocksFontDC.pcx"	},
+  { "steel_char_space",				"RocksFontDC.png"	},
   { "steel_char_space.xpos",			"0"			},
   { "steel_char_space.ypos",			"0"			},
   { "steel_char_space.frames",			"1"			},
-  { "steel_char_space.EDITOR",			"RocksFontDC.pcx"	},
+  { "steel_char_space.EDITOR",			"RocksFontDC.png"	},
   { "steel_char_space.EDITOR.xpos",		"7"			},
   { "steel_char_space.EDITOR.ypos",		"4"			},
   { "steel_char_space.EDITOR.frames",		"1"			},
 
-  { "steel_char_exclam",			"RocksFontDC.pcx"	},
+  { "steel_char_exclam",			"RocksFontDC.png"	},
   { "steel_char_exclam.xpos",			"1"			},
   { "steel_char_exclam.ypos",			"0"			},
   { "steel_char_exclam.frames",			"1"			},
 
-  { "steel_char_quotedbl",			"RocksFontDC.pcx"	},
+  { "steel_char_quotedbl",			"RocksFontDC.png"	},
   { "steel_char_quotedbl.xpos",			"2"			},
   { "steel_char_quotedbl.ypos",			"0"			},
   { "steel_char_quotedbl.frames",		"1"			},
 
-  { "steel_char_numbersign",			"RocksFontDC.pcx"	},
+  { "steel_char_numbersign",			"RocksFontDC.png"	},
   { "steel_char_numbersign.xpos",		"3"			},
   { "steel_char_numbersign.ypos",		"0"			},
   { "steel_char_numbersign.frames",		"1"			},
 
-  { "steel_char_dollar",			"RocksFontDC.pcx"	},
+  { "steel_char_dollar",			"RocksFontDC.png"	},
   { "steel_char_dollar.xpos",			"4"			},
   { "steel_char_dollar.ypos",			"0"			},
   { "steel_char_dollar.frames",			"1"			},
 
-  { "steel_char_percent",			"RocksFontDC.pcx"	},
+  { "steel_char_percent",			"RocksFontDC.png"	},
   { "steel_char_percent.xpos",			"5"			},
   { "steel_char_percent.ypos",			"0"			},
   { "steel_char_percent.frames",		"1"			},
 
-  { "steel_char_ampersand",			"RocksFontDC.pcx"	},
+  { "steel_char_ampersand",			"RocksFontDC.png"	},
   { "steel_char_ampersand.xpos",		"6"			},
   { "steel_char_ampersand.ypos",		"0"			},
   { "steel_char_ampersand.frames",		"1"			},
 
-  { "steel_char_apostrophe",			"RocksFontDC.pcx"	},
+  { "steel_char_apostrophe",			"RocksFontDC.png"	},
   { "steel_char_apostrophe.xpos",		"7"			},
   { "steel_char_apostrophe.ypos",		"0"			},
   { "steel_char_apostrophe.frames",		"1"			},
 
-  { "steel_char_parenleft",			"RocksFontDC.pcx"	},
+  { "steel_char_parenleft",			"RocksFontDC.png"	},
   { "steel_char_parenleft.xpos",		"8"			},
   { "steel_char_parenleft.ypos",		"0"			},
   { "steel_char_parenleft.frames",		"1"			},
 
-  { "steel_char_parenright",			"RocksFontDC.pcx"	},
+  { "steel_char_parenright",			"RocksFontDC.png"	},
   { "steel_char_parenright.xpos",		"9"			},
   { "steel_char_parenright.ypos",		"0"			},
   { "steel_char_parenright.frames",		"1"			},
 
-  { "steel_char_asterisk",			"RocksFontDC.pcx"	},
+  { "steel_char_asterisk",			"RocksFontDC.png"	},
   { "steel_char_asterisk.xpos",			"10"			},
   { "steel_char_asterisk.ypos",			"0"			},
   { "steel_char_asterisk.frames",		"1"			},
 
-  { "steel_char_plus",				"RocksFontDC.pcx"	},
+  { "steel_char_plus",				"RocksFontDC.png"	},
   { "steel_char_plus.xpos",			"11"			},
   { "steel_char_plus.ypos",			"0"			},
   { "steel_char_plus.frames",			"1"			},
 
-  { "steel_char_comma",				"RocksFontDC.pcx"	},
+  { "steel_char_comma",				"RocksFontDC.png"	},
   { "steel_char_comma.xpos",			"12"			},
   { "steel_char_comma.ypos",			"0"			},
   { "steel_char_comma.frames",			"1"			},
 
-  { "steel_char_minus",				"RocksFontDC.pcx"	},
+  { "steel_char_minus",				"RocksFontDC.png"	},
   { "steel_char_minus.xpos",			"13"			},
   { "steel_char_minus.ypos",			"0"			},
   { "steel_char_minus.frames",			"1"			},
 
-  { "steel_char_period",			"RocksFontDC.pcx"	},
+  { "steel_char_period",			"RocksFontDC.png"	},
   { "steel_char_period.xpos",			"14"			},
   { "steel_char_period.ypos",			"0"			},
   { "steel_char_period.frames",			"1"			},
 
-  { "steel_char_slash",				"RocksFontDC.pcx"	},
+  { "steel_char_slash",				"RocksFontDC.png"	},
   { "steel_char_slash.xpos",			"15"			},
   { "steel_char_slash.ypos",			"0"			},
   { "steel_char_slash.frames",			"1"			},
 
-  { "steel_char_0",				"RocksFontDC.pcx"	},
+  { "steel_char_0",				"RocksFontDC.png"	},
   { "steel_char_0.xpos",			"0"			},
   { "steel_char_0.ypos",			"1"			},
   { "steel_char_0.frames",			"1"			},
 
-  { "steel_char_1",				"RocksFontDC.pcx"	},
+  { "steel_char_1",				"RocksFontDC.png"	},
   { "steel_char_1.xpos",			"1"			},
   { "steel_char_1.ypos",			"1"			},
   { "steel_char_1.frames",			"1"			},
 
-  { "steel_char_2",				"RocksFontDC.pcx"	},
+  { "steel_char_2",				"RocksFontDC.png"	},
   { "steel_char_2.xpos",			"2"			},
   { "steel_char_2.ypos",			"1"			},
   { "steel_char_2.frames",			"1"			},
 
-  { "steel_char_3",				"RocksFontDC.pcx"	},
+  { "steel_char_3",				"RocksFontDC.png"	},
   { "steel_char_3.xpos",			"3"			},
   { "steel_char_3.ypos",			"1"			},
   { "steel_char_3.frames",			"1"			},
 
-  { "steel_char_4",				"RocksFontDC.pcx"	},
+  { "steel_char_4",				"RocksFontDC.png"	},
   { "steel_char_4.xpos",			"4"			},
   { "steel_char_4.ypos",			"1"			},
   { "steel_char_4.frames",			"1"			},
 
-  { "steel_char_5",				"RocksFontDC.pcx"	},
+  { "steel_char_5",				"RocksFontDC.png"	},
   { "steel_char_5.xpos",			"5"			},
   { "steel_char_5.ypos",			"1"			},
   { "steel_char_5.frames",			"1"			},
 
-  { "steel_char_6",				"RocksFontDC.pcx"	},
+  { "steel_char_6",				"RocksFontDC.png"	},
   { "steel_char_6.xpos",			"6"			},
   { "steel_char_6.ypos",			"1"			},
   { "steel_char_6.frames",			"1"			},
 
-  { "steel_char_7",				"RocksFontDC.pcx"	},
+  { "steel_char_7",				"RocksFontDC.png"	},
   { "steel_char_7.xpos",			"7"			},
   { "steel_char_7.ypos",			"1"			},
   { "steel_char_7.frames",			"1"			},
 
-  { "steel_char_8",				"RocksFontDC.pcx"	},
+  { "steel_char_8",				"RocksFontDC.png"	},
   { "steel_char_8.xpos",			"8"			},
   { "steel_char_8.ypos",			"1"			},
   { "steel_char_8.frames",			"1"			},
 
-  { "steel_char_9",				"RocksFontDC.pcx"	},
+  { "steel_char_9",				"RocksFontDC.png"	},
   { "steel_char_9.xpos",			"9"			},
   { "steel_char_9.ypos",			"1"			},
   { "steel_char_9.frames",			"1"			},
 
-  { "steel_char_colon",				"RocksFontDC.pcx"	},
+  { "steel_char_colon",				"RocksFontDC.png"	},
   { "steel_char_colon.xpos",			"10"			},
   { "steel_char_colon.ypos",			"1"			},
   { "steel_char_colon.frames",			"1"			},
 
-  { "steel_char_semicolon",			"RocksFontDC.pcx"	},
+  { "steel_char_semicolon",			"RocksFontDC.png"	},
   { "steel_char_semicolon.xpos",		"11"			},
   { "steel_char_semicolon.ypos",		"1"			},
   { "steel_char_semicolon.frames",		"1"			},
 
-  { "steel_char_less",				"RocksFontDC.pcx"	},
+  { "steel_char_less",				"RocksFontDC.png"	},
   { "steel_char_less.xpos",			"12"			},
   { "steel_char_less.ypos",			"1"			},
   { "steel_char_less.frames",			"1"			},
 
-  { "steel_char_equal",				"RocksFontDC.pcx"	},
+  { "steel_char_equal",				"RocksFontDC.png"	},
   { "steel_char_equal.xpos",			"13"			},
   { "steel_char_equal.ypos",			"1"			},
   { "steel_char_equal.frames",			"1"			},
 
-  { "steel_char_greater",			"RocksFontDC.pcx"	},
+  { "steel_char_greater",			"RocksFontDC.png"	},
   { "steel_char_greater.xpos",			"14"			},
   { "steel_char_greater.ypos",			"1"			},
   { "steel_char_greater.frames",		"1"			},
 
-  { "steel_char_question",			"RocksFontDC.pcx"	},
+  { "steel_char_question",			"RocksFontDC.png"	},
   { "steel_char_question.xpos",			"15"			},
   { "steel_char_question.ypos",			"1"			},
   { "steel_char_question.frames",		"1"			},
 
-  { "steel_char_at",				"RocksFontDC.pcx"	},
+  { "steel_char_at",				"RocksFontDC.png"	},
   { "steel_char_at.xpos",			"0"			},
   { "steel_char_at.ypos",			"2"			},
   { "steel_char_at.frames",			"1"			},
 
-  { "steel_char_a",				"RocksFontDC.pcx"	},
+  { "steel_char_a",				"RocksFontDC.png"	},
   { "steel_char_a.xpos",			"1"			},
   { "steel_char_a.ypos",			"2"			},
   { "steel_char_a.frames",			"1"			},
 
-  { "steel_char_b",				"RocksFontDC.pcx"	},
+  { "steel_char_b",				"RocksFontDC.png"	},
   { "steel_char_b.xpos",			"2"			},
   { "steel_char_b.ypos",			"2"			},
   { "steel_char_b.frames",			"1"			},
 
-  { "steel_char_c",				"RocksFontDC.pcx"	},
+  { "steel_char_c",				"RocksFontDC.png"	},
   { "steel_char_c.xpos",			"3"			},
   { "steel_char_c.ypos",			"2"			},
   { "steel_char_c.frames",			"1"			},
 
-  { "steel_char_d",				"RocksFontDC.pcx"	},
+  { "steel_char_d",				"RocksFontDC.png"	},
   { "steel_char_d.xpos",			"4"			},
   { "steel_char_d.ypos",			"2"			},
   { "steel_char_d.frames",			"1"			},
 
-  { "steel_char_e",				"RocksFontDC.pcx"	},
+  { "steel_char_e",				"RocksFontDC.png"	},
   { "steel_char_e.xpos",			"5"			},
   { "steel_char_e.ypos",			"2"			},
   { "steel_char_e.frames",			"1"			},
 
-  { "steel_char_f",				"RocksFontDC.pcx"	},
+  { "steel_char_f",				"RocksFontDC.png"	},
   { "steel_char_f.xpos",			"6"			},
   { "steel_char_f.ypos",			"2"			},
   { "steel_char_f.frames",			"1"			},
 
-  { "steel_char_g",				"RocksFontDC.pcx"	},
+  { "steel_char_g",				"RocksFontDC.png"	},
   { "steel_char_g.xpos",			"7"			},
   { "steel_char_g.ypos",			"2"			},
   { "steel_char_g.frames",			"1"			},
 
-  { "steel_char_h",				"RocksFontDC.pcx"	},
+  { "steel_char_h",				"RocksFontDC.png"	},
   { "steel_char_h.xpos",			"8"			},
   { "steel_char_h.ypos",			"2"			},
   { "steel_char_h.frames",			"1"			},
 
-  { "steel_char_i",				"RocksFontDC.pcx"	},
+  { "steel_char_i",				"RocksFontDC.png"	},
   { "steel_char_i.xpos",			"9"			},
   { "steel_char_i.ypos",			"2"			},
   { "steel_char_i.frames",			"1"			},
 
-  { "steel_char_j",				"RocksFontDC.pcx"	},
+  { "steel_char_j",				"RocksFontDC.png"	},
   { "steel_char_j.xpos",			"10"			},
   { "steel_char_j.ypos",			"2"			},
   { "steel_char_j.frames",			"1"			},
 
-  { "steel_char_k",				"RocksFontDC.pcx"	},
+  { "steel_char_k",				"RocksFontDC.png"	},
   { "steel_char_k.xpos",			"11"			},
   { "steel_char_k.ypos",			"2"			},
   { "steel_char_k.frames",			"1"			},
 
-  { "steel_char_l",				"RocksFontDC.pcx"	},
+  { "steel_char_l",				"RocksFontDC.png"	},
   { "steel_char_l.xpos",			"12"			},
   { "steel_char_l.ypos",			"2"			},
   { "steel_char_l.frames",			"1"			},
 
-  { "steel_char_m",				"RocksFontDC.pcx"	},
+  { "steel_char_m",				"RocksFontDC.png"	},
   { "steel_char_m.xpos",			"13"			},
   { "steel_char_m.ypos",			"2"			},
   { "steel_char_m.frames",			"1"			},
 
-  { "steel_char_n",				"RocksFontDC.pcx"	},
+  { "steel_char_n",				"RocksFontDC.png"	},
   { "steel_char_n.xpos",			"14"			},
   { "steel_char_n.ypos",			"2"			},
   { "steel_char_n.frames",			"1"			},
 
-  { "steel_char_o",				"RocksFontDC.pcx"	},
+  { "steel_char_o",				"RocksFontDC.png"	},
   { "steel_char_o.xpos",			"15"			},
   { "steel_char_o.ypos",			"2"			},
   { "steel_char_o.frames",			"1"			},
 
-  { "steel_char_p",				"RocksFontDC.pcx"	},
+  { "steel_char_p",				"RocksFontDC.png"	},
   { "steel_char_p.xpos",			"0"			},
   { "steel_char_p.ypos",			"3"			},
   { "steel_char_p.frames",			"1"			},
 
-  { "steel_char_q",				"RocksFontDC.pcx"	},
+  { "steel_char_q",				"RocksFontDC.png"	},
   { "steel_char_q.xpos",			"1"			},
   { "steel_char_q.ypos",			"3"			},
   { "steel_char_q.frames",			"1"			},
 
-  { "steel_char_r",				"RocksFontDC.pcx"	},
+  { "steel_char_r",				"RocksFontDC.png"	},
   { "steel_char_r.xpos",			"2"			},
   { "steel_char_r.ypos",			"3"			},
   { "steel_char_r.frames",			"1"			},
 
-  { "steel_char_s",				"RocksFontDC.pcx"	},
+  { "steel_char_s",				"RocksFontDC.png"	},
   { "steel_char_s.xpos",			"3"			},
   { "steel_char_s.ypos",			"3"			},
   { "steel_char_s.frames",			"1"			},
 
-  { "steel_char_t",				"RocksFontDC.pcx"	},
+  { "steel_char_t",				"RocksFontDC.png"	},
   { "steel_char_t.xpos",			"4"			},
   { "steel_char_t.ypos",			"3"			},
   { "steel_char_t.frames",			"1"			},
 
-  { "steel_char_u",				"RocksFontDC.pcx"	},
+  { "steel_char_u",				"RocksFontDC.png"	},
   { "steel_char_u.xpos",			"5"			},
   { "steel_char_u.ypos",			"3"			},
   { "steel_char_u.frames",			"1"			},
 
-  { "steel_char_v",				"RocksFontDC.pcx"	},
+  { "steel_char_v",				"RocksFontDC.png"	},
   { "steel_char_v.xpos",			"6"			},
   { "steel_char_v.ypos",			"3"			},
   { "steel_char_v.frames",			"1"			},
 
-  { "steel_char_w",				"RocksFontDC.pcx"	},
+  { "steel_char_w",				"RocksFontDC.png"	},
   { "steel_char_w.xpos",			"7"			},
   { "steel_char_w.ypos",			"3"			},
   { "steel_char_w.frames",			"1"			},
 
-  { "steel_char_x",				"RocksFontDC.pcx"	},
+  { "steel_char_x",				"RocksFontDC.png"	},
   { "steel_char_x.xpos",			"8"			},
   { "steel_char_x.ypos",			"3"			},
   { "steel_char_x.frames",			"1"			},
 
-  { "steel_char_y",				"RocksFontDC.pcx"	},
+  { "steel_char_y",				"RocksFontDC.png"	},
   { "steel_char_y.xpos",			"9"			},
   { "steel_char_y.ypos",			"3"			},
   { "steel_char_y.frames",			"1"			},
 
-  { "steel_char_z",				"RocksFontDC.pcx"	},
+  { "steel_char_z",				"RocksFontDC.png"	},
   { "steel_char_z.xpos",			"10"			},
   { "steel_char_z.ypos",			"3"			},
   { "steel_char_z.frames",			"1"			},
 
-  { "steel_char_bracketleft",			"RocksFontDC.pcx"	},
+  { "steel_char_bracketleft",			"RocksFontDC.png"	},
   { "steel_char_bracketleft.xpos",		"11"			},
   { "steel_char_bracketleft.ypos",		"3"			},
   { "steel_char_bracketleft.frames",		"1"			},
 
-  { "steel_char_backslash",			"RocksFontDC.pcx"	},
+  { "steel_char_backslash",			"RocksFontDC.png"	},
   { "steel_char_backslash.xpos",		"12"			},
   { "steel_char_backslash.ypos",		"3"			},
   { "steel_char_backslash.frames",		"1"			},
 
-  { "steel_char_bracketright",			"RocksFontDC.pcx"	},
+  { "steel_char_bracketright",			"RocksFontDC.png"	},
   { "steel_char_bracketright.xpos",		"13"			},
   { "steel_char_bracketright.ypos",		"3"			},
   { "steel_char_bracketright.frames",		"1"			},
 
-  { "steel_char_asciicircum",			"RocksFontDC.pcx"	},
+  { "steel_char_asciicircum",			"RocksFontDC.png"	},
   { "steel_char_asciicircum.xpos",		"14"			},
   { "steel_char_asciicircum.ypos",		"3"			},
   { "steel_char_asciicircum.frames",		"1"			},
 
-  { "steel_char_underscore",			"RocksFontDC.pcx"	},
+  { "steel_char_underscore",			"RocksFontDC.png"	},
   { "steel_char_underscore.xpos",		"15"			},
   { "steel_char_underscore.ypos",		"3"			},
   { "steel_char_underscore.frames",		"1"			},
 
-  { "steel_char_copyright",			"RocksFontDC.pcx"	},
+  { "steel_char_copyright",			"RocksFontDC.png"	},
   { "steel_char_copyright.xpos",		"0"			},
   { "steel_char_copyright.ypos",		"4"			},
   { "steel_char_copyright.frames",		"1"			},
 
-  { "steel_char_aumlaut",			"RocksFontDC.pcx"	},
+  { "steel_char_aumlaut",			"RocksFontDC.png"	},
   { "steel_char_aumlaut.xpos",			"1"			},
   { "steel_char_aumlaut.ypos",			"4"			},
   { "steel_char_aumlaut.frames",		"1"			},
 
-  { "steel_char_oumlaut",			"RocksFontDC.pcx"	},
+  { "steel_char_oumlaut",			"RocksFontDC.png"	},
   { "steel_char_oumlaut.xpos",			"2"			},
   { "steel_char_oumlaut.ypos",			"4"			},
   { "steel_char_oumlaut.frames",		"1"			},
 
-  { "steel_char_uumlaut",			"RocksFontDC.pcx"	},
+  { "steel_char_uumlaut",			"RocksFontDC.png"	},
   { "steel_char_uumlaut.xpos",			"3"			},
   { "steel_char_uumlaut.ypos",			"4"			},
   { "steel_char_uumlaut.frames",		"1"			},
 
-  { "steel_char_degree",			"RocksFontDC.pcx"	},
+  { "steel_char_degree",			"RocksFontDC.png"	},
   { "steel_char_degree.xpos",			"4"			},
   { "steel_char_degree.ypos",			"4"			},
   { "steel_char_degree.frames",			"1"			},
 
-  { "steel_char_trademark",			"RocksFontDC.pcx"	},
+  { "steel_char_trademark",			"RocksFontDC.png"	},
   { "steel_char_trademark.xpos",		"5"			},
   { "steel_char_trademark.ypos",		"4"			},
   { "steel_char_trademark.frames",		"1"			},
 
-  { "steel_char_cursor",			"RocksFontDC.pcx"	},
+  { "steel_char_cursor",			"RocksFontDC.png"	},
   { "steel_char_cursor.xpos",			"6"			},
   { "steel_char_cursor.ypos",			"4"			},
   { "steel_char_cursor.frames",			"1"			},
 
-  { "steel_char_button",			"RocksFontDC.pcx"	},
+  { "steel_char_button",			"RocksFontDC.png"	},
   { "steel_char_button.xpos",			"13"			},
   { "steel_char_button.ypos",			"4"			},
   { "steel_char_button.frames",			"1"			},
 
-  { "steel_char_up",				"RocksFontDC.pcx"	},
+  { "steel_char_up",				"RocksFontDC.png"	},
   { "steel_char_up.xpos",			"14"			},
   { "steel_char_up.ypos",			"4"			},
   { "steel_char_up.frames",			"1"			},
 
-  { "steel_char_down",				"RocksFontDC.pcx"	},
+  { "steel_char_down",				"RocksFontDC.png"	},
   { "steel_char_down.xpos",			"15"			},
   { "steel_char_down.ypos",			"4"			},
   { "steel_char_down.frames",			"1"			},
diff --git a/src/conf_chr.h b/src/conf_chr.h
index 41f01a2..56f9683 100644
--- a/src/conf_chr.h
+++ b/src/conf_chr.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_chr.h                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                  Holger Schemel
+//                  info at artsoft.org
+//                  http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_chr.h
+// ============================================================================
 
 /* ----- this file was automatically generated -- do not edit by hand ----- */
 
diff --git a/src/conf_cus.c b/src/conf_cus.c
index 50d7078..5e2c1e2 100644
--- a/src/conf_cus.c
+++ b/src/conf_cus.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_cus.c                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                  Holger Schemel
+//                  info at artsoft.org
+//                  http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_cus.c
+// ============================================================================
 
 /* ----- this file was automatically generated -- do not edit by hand ----- */
 
@@ -18,2051 +16,2051 @@
 
 /* values for graphics configuration (custom elements) */
 
-  { "custom_1",					"RocksCE.pcx"		},
+  { "custom_1",					"RocksCE.png"		},
   { "custom_1.xpos",				"0"			},
   { "custom_1.ypos",				"0"			},
   { "custom_1.frames",				"1"			},
-  { "custom_1.EDITOR",				"RocksCE.pcx"		},
+  { "custom_1.EDITOR",				"RocksCE.png"		},
   { "custom_1.EDITOR.xpos",			"16"			},
   { "custom_1.EDITOR.ypos",			"0"			},
 
-  { "custom_2",					"RocksCE.pcx"		},
+  { "custom_2",					"RocksCE.png"		},
   { "custom_2.xpos",				"1"			},
   { "custom_2.ypos",				"0"			},
   { "custom_2.frames",				"1"			},
-  { "custom_2.EDITOR",				"RocksCE.pcx"		},
+  { "custom_2.EDITOR",				"RocksCE.png"		},
   { "custom_2.EDITOR.xpos",			"17"			},
   { "custom_2.EDITOR.ypos",			"0"			},
 
-  { "custom_3",					"RocksCE.pcx"		},
+  { "custom_3",					"RocksCE.png"		},
   { "custom_3.xpos",				"2"			},
   { "custom_3.ypos",				"0"			},
   { "custom_3.frames",				"1"			},
-  { "custom_3.EDITOR",				"RocksCE.pcx"		},
+  { "custom_3.EDITOR",				"RocksCE.png"		},
   { "custom_3.EDITOR.xpos",			"18"			},
   { "custom_3.EDITOR.ypos",			"0"			},
 
-  { "custom_4",					"RocksCE.pcx"		},
+  { "custom_4",					"RocksCE.png"		},
   { "custom_4.xpos",				"3"			},
   { "custom_4.ypos",				"0"			},
   { "custom_4.frames",				"1"			},
-  { "custom_4.EDITOR",				"RocksCE.pcx"		},
+  { "custom_4.EDITOR",				"RocksCE.png"		},
   { "custom_4.EDITOR.xpos",			"19"			},
   { "custom_4.EDITOR.ypos",			"0"			},
 
-  { "custom_5",					"RocksCE.pcx"		},
+  { "custom_5",					"RocksCE.png"		},
   { "custom_5.xpos",				"4"			},
   { "custom_5.ypos",				"0"			},
   { "custom_5.frames",				"1"			},
-  { "custom_5.EDITOR",				"RocksCE.pcx"		},
+  { "custom_5.EDITOR",				"RocksCE.png"		},
   { "custom_5.EDITOR.xpos",			"20"			},
   { "custom_5.EDITOR.ypos",			"0"			},
 
-  { "custom_6",					"RocksCE.pcx"		},
+  { "custom_6",					"RocksCE.png"		},
   { "custom_6.xpos",				"5"			},
   { "custom_6.ypos",				"0"			},
   { "custom_6.frames",				"1"			},
-  { "custom_6.EDITOR",				"RocksCE.pcx"		},
+  { "custom_6.EDITOR",				"RocksCE.png"		},
   { "custom_6.EDITOR.xpos",			"21"			},
   { "custom_6.EDITOR.ypos",			"0"			},
 
-  { "custom_7",					"RocksCE.pcx"		},
+  { "custom_7",					"RocksCE.png"		},
   { "custom_7.xpos",				"6"			},
   { "custom_7.ypos",				"0"			},
   { "custom_7.frames",				"1"			},
-  { "custom_7.EDITOR",				"RocksCE.pcx"		},
+  { "custom_7.EDITOR",				"RocksCE.png"		},
   { "custom_7.EDITOR.xpos",			"22"			},
   { "custom_7.EDITOR.ypos",			"0"			},
 
-  { "custom_8",					"RocksCE.pcx"		},
+  { "custom_8",					"RocksCE.png"		},
   { "custom_8.xpos",				"7"			},
   { "custom_8.ypos",				"0"			},
   { "custom_8.frames",				"1"			},
-  { "custom_8.EDITOR",				"RocksCE.pcx"		},
+  { "custom_8.EDITOR",				"RocksCE.png"		},
   { "custom_8.EDITOR.xpos",			"23"			},
   { "custom_8.EDITOR.ypos",			"0"			},
 
-  { "custom_9",					"RocksCE.pcx"		},
+  { "custom_9",					"RocksCE.png"		},
   { "custom_9.xpos",				"8"			},
   { "custom_9.ypos",				"0"			},
   { "custom_9.frames",				"1"			},
-  { "custom_9.EDITOR",				"RocksCE.pcx"		},
+  { "custom_9.EDITOR",				"RocksCE.png"		},
   { "custom_9.EDITOR.xpos",			"24"			},
   { "custom_9.EDITOR.ypos",			"0"			},
 
-  { "custom_10",				"RocksCE.pcx"		},
+  { "custom_10",				"RocksCE.png"		},
   { "custom_10.xpos",				"9"			},
   { "custom_10.ypos",				"0"			},
   { "custom_10.frames",				"1"			},
-  { "custom_10.EDITOR",				"RocksCE.pcx"		},
+  { "custom_10.EDITOR",				"RocksCE.png"		},
   { "custom_10.EDITOR.xpos",			"25"			},
   { "custom_10.EDITOR.ypos",			"0"			},
 
-  { "custom_11",				"RocksCE.pcx"		},
+  { "custom_11",				"RocksCE.png"		},
   { "custom_11.xpos",				"10"			},
   { "custom_11.ypos",				"0"			},
   { "custom_11.frames",				"1"			},
-  { "custom_11.EDITOR",				"RocksCE.pcx"		},
+  { "custom_11.EDITOR",				"RocksCE.png"		},
   { "custom_11.EDITOR.xpos",			"26"			},
   { "custom_11.EDITOR.ypos",			"0"			},
 
-  { "custom_12",				"RocksCE.pcx"		},
+  { "custom_12",				"RocksCE.png"		},
   { "custom_12.xpos",				"11"			},
   { "custom_12.ypos",				"0"			},
   { "custom_12.frames",				"1"			},
-  { "custom_12.EDITOR",				"RocksCE.pcx"		},
+  { "custom_12.EDITOR",				"RocksCE.png"		},
   { "custom_12.EDITOR.xpos",			"27"			},
   { "custom_12.EDITOR.ypos",			"0"			},
 
-  { "custom_13",				"RocksCE.pcx"		},
+  { "custom_13",				"RocksCE.png"		},
   { "custom_13.xpos",				"12"			},
   { "custom_13.ypos",				"0"			},
   { "custom_13.frames",				"1"			},
-  { "custom_13.EDITOR",				"RocksCE.pcx"		},
+  { "custom_13.EDITOR",				"RocksCE.png"		},
   { "custom_13.EDITOR.xpos",			"28"			},
   { "custom_13.EDITOR.ypos",			"0"			},
 
-  { "custom_14",				"RocksCE.pcx"		},
+  { "custom_14",				"RocksCE.png"		},
   { "custom_14.xpos",				"13"			},
   { "custom_14.ypos",				"0"			},
   { "custom_14.frames",				"1"			},
-  { "custom_14.EDITOR",				"RocksCE.pcx"		},
+  { "custom_14.EDITOR",				"RocksCE.png"		},
   { "custom_14.EDITOR.xpos",			"29"			},
   { "custom_14.EDITOR.ypos",			"0"			},
 
-  { "custom_15",				"RocksCE.pcx"		},
+  { "custom_15",				"RocksCE.png"		},
   { "custom_15.xpos",				"14"			},
   { "custom_15.ypos",				"0"			},
   { "custom_15.frames",				"1"			},
-  { "custom_15.EDITOR",				"RocksCE.pcx"		},
+  { "custom_15.EDITOR",				"RocksCE.png"		},
   { "custom_15.EDITOR.xpos",			"30"			},
   { "custom_15.EDITOR.ypos",			"0"			},
 
-  { "custom_16",				"RocksCE.pcx"		},
+  { "custom_16",				"RocksCE.png"		},
   { "custom_16.xpos",				"15"			},
   { "custom_16.ypos",				"0"			},
   { "custom_16.frames",				"1"			},
-  { "custom_16.EDITOR",				"RocksCE.pcx"		},
+  { "custom_16.EDITOR",				"RocksCE.png"		},
   { "custom_16.EDITOR.xpos",			"31"			},
   { "custom_16.EDITOR.ypos",			"0"			},
 
-  { "custom_17",				"RocksCE.pcx"		},
+  { "custom_17",				"RocksCE.png"		},
   { "custom_17.xpos",				"0"			},
   { "custom_17.ypos",				"1"			},
   { "custom_17.frames",				"1"			},
-  { "custom_17.EDITOR",				"RocksCE.pcx"		},
+  { "custom_17.EDITOR",				"RocksCE.png"		},
   { "custom_17.EDITOR.xpos",			"16"			},
   { "custom_17.EDITOR.ypos",			"1"			},
 
-  { "custom_18",				"RocksCE.pcx"		},
+  { "custom_18",				"RocksCE.png"		},
   { "custom_18.xpos",				"1"			},
   { "custom_18.ypos",				"1"			},
   { "custom_18.frames",				"1"			},
-  { "custom_18.EDITOR",				"RocksCE.pcx"		},
+  { "custom_18.EDITOR",				"RocksCE.png"		},
   { "custom_18.EDITOR.xpos",			"17"			},
   { "custom_18.EDITOR.ypos",			"1"			},
 
-  { "custom_19",				"RocksCE.pcx"		},
+  { "custom_19",				"RocksCE.png"		},
   { "custom_19.xpos",				"2"			},
   { "custom_19.ypos",				"1"			},
   { "custom_19.frames",				"1"			},
-  { "custom_19.EDITOR",				"RocksCE.pcx"		},
+  { "custom_19.EDITOR",				"RocksCE.png"		},
   { "custom_19.EDITOR.xpos",			"18"			},
   { "custom_19.EDITOR.ypos",			"1"			},
 
-  { "custom_20",				"RocksCE.pcx"		},
+  { "custom_20",				"RocksCE.png"		},
   { "custom_20.xpos",				"3"			},
   { "custom_20.ypos",				"1"			},
   { "custom_20.frames",				"1"			},
-  { "custom_20.EDITOR",				"RocksCE.pcx"		},
+  { "custom_20.EDITOR",				"RocksCE.png"		},
   { "custom_20.EDITOR.xpos",			"19"			},
   { "custom_20.EDITOR.ypos",			"1"			},
 
-  { "custom_21",				"RocksCE.pcx"		},
+  { "custom_21",				"RocksCE.png"		},
   { "custom_21.xpos",				"4"			},
   { "custom_21.ypos",				"1"			},
   { "custom_21.frames",				"1"			},
-  { "custom_21.EDITOR",				"RocksCE.pcx"		},
+  { "custom_21.EDITOR",				"RocksCE.png"		},
   { "custom_21.EDITOR.xpos",			"20"			},
   { "custom_21.EDITOR.ypos",			"1"			},
 
-  { "custom_22",				"RocksCE.pcx"		},
+  { "custom_22",				"RocksCE.png"		},
   { "custom_22.xpos",				"5"			},
   { "custom_22.ypos",				"1"			},
   { "custom_22.frames",				"1"			},
-  { "custom_22.EDITOR",				"RocksCE.pcx"		},
+  { "custom_22.EDITOR",				"RocksCE.png"		},
   { "custom_22.EDITOR.xpos",			"21"			},
   { "custom_22.EDITOR.ypos",			"1"			},
 
-  { "custom_23",				"RocksCE.pcx"		},
+  { "custom_23",				"RocksCE.png"		},
   { "custom_23.xpos",				"6"			},
   { "custom_23.ypos",				"1"			},
   { "custom_23.frames",				"1"			},
-  { "custom_23.EDITOR",				"RocksCE.pcx"		},
+  { "custom_23.EDITOR",				"RocksCE.png"		},
   { "custom_23.EDITOR.xpos",			"22"			},
   { "custom_23.EDITOR.ypos",			"1"			},
 
-  { "custom_24",				"RocksCE.pcx"		},
+  { "custom_24",				"RocksCE.png"		},
   { "custom_24.xpos",				"7"			},
   { "custom_24.ypos",				"1"			},
   { "custom_24.frames",				"1"			},
-  { "custom_24.EDITOR",				"RocksCE.pcx"		},
+  { "custom_24.EDITOR",				"RocksCE.png"		},
   { "custom_24.EDITOR.xpos",			"23"			},
   { "custom_24.EDITOR.ypos",			"1"			},
 
-  { "custom_25",				"RocksCE.pcx"		},
+  { "custom_25",				"RocksCE.png"		},
   { "custom_25.xpos",				"8"			},
   { "custom_25.ypos",				"1"			},
   { "custom_25.frames",				"1"			},
-  { "custom_25.EDITOR",				"RocksCE.pcx"		},
+  { "custom_25.EDITOR",				"RocksCE.png"		},
   { "custom_25.EDITOR.xpos",			"24"			},
   { "custom_25.EDITOR.ypos",			"1"			},
 
-  { "custom_26",				"RocksCE.pcx"		},
+  { "custom_26",				"RocksCE.png"		},
   { "custom_26.xpos",				"9"			},
   { "custom_26.ypos",				"1"			},
   { "custom_26.frames",				"1"			},
-  { "custom_26.EDITOR",				"RocksCE.pcx"		},
+  { "custom_26.EDITOR",				"RocksCE.png"		},
   { "custom_26.EDITOR.xpos",			"25"			},
   { "custom_26.EDITOR.ypos",			"1"			},
 
-  { "custom_27",				"RocksCE.pcx"		},
+  { "custom_27",				"RocksCE.png"		},
   { "custom_27.xpos",				"10"			},
   { "custom_27.ypos",				"1"			},
   { "custom_27.frames",				"1"			},
-  { "custom_27.EDITOR",				"RocksCE.pcx"		},
+  { "custom_27.EDITOR",				"RocksCE.png"		},
   { "custom_27.EDITOR.xpos",			"26"			},
   { "custom_27.EDITOR.ypos",			"1"			},
 
-  { "custom_28",				"RocksCE.pcx"		},
+  { "custom_28",				"RocksCE.png"		},
   { "custom_28.xpos",				"11"			},
   { "custom_28.ypos",				"1"			},
   { "custom_28.frames",				"1"			},
-  { "custom_28.EDITOR",				"RocksCE.pcx"		},
+  { "custom_28.EDITOR",				"RocksCE.png"		},
   { "custom_28.EDITOR.xpos",			"27"			},
   { "custom_28.EDITOR.ypos",			"1"			},
 
-  { "custom_29",				"RocksCE.pcx"		},
+  { "custom_29",				"RocksCE.png"		},
   { "custom_29.xpos",				"12"			},
   { "custom_29.ypos",				"1"			},
   { "custom_29.frames",				"1"			},
-  { "custom_29.EDITOR",				"RocksCE.pcx"		},
+  { "custom_29.EDITOR",				"RocksCE.png"		},
   { "custom_29.EDITOR.xpos",			"28"			},
   { "custom_29.EDITOR.ypos",			"1"			},
 
-  { "custom_30",				"RocksCE.pcx"		},
+  { "custom_30",				"RocksCE.png"		},
   { "custom_30.xpos",				"13"			},
   { "custom_30.ypos",				"1"			},
   { "custom_30.frames",				"1"			},
-  { "custom_30.EDITOR",				"RocksCE.pcx"		},
+  { "custom_30.EDITOR",				"RocksCE.png"		},
   { "custom_30.EDITOR.xpos",			"29"			},
   { "custom_30.EDITOR.ypos",			"1"			},
 
-  { "custom_31",				"RocksCE.pcx"		},
+  { "custom_31",				"RocksCE.png"		},
   { "custom_31.xpos",				"14"			},
   { "custom_31.ypos",				"1"			},
   { "custom_31.frames",				"1"			},
-  { "custom_31.EDITOR",				"RocksCE.pcx"		},
+  { "custom_31.EDITOR",				"RocksCE.png"		},
   { "custom_31.EDITOR.xpos",			"30"			},
   { "custom_31.EDITOR.ypos",			"1"			},
 
-  { "custom_32",				"RocksCE.pcx"		},
+  { "custom_32",				"RocksCE.png"		},
   { "custom_32.xpos",				"15"			},
   { "custom_32.ypos",				"1"			},
   { "custom_32.frames",				"1"			},
-  { "custom_32.EDITOR",				"RocksCE.pcx"		},
+  { "custom_32.EDITOR",				"RocksCE.png"		},
   { "custom_32.EDITOR.xpos",			"31"			},
   { "custom_32.EDITOR.ypos",			"1"			},
 
-  { "custom_33",				"RocksCE.pcx"		},
+  { "custom_33",				"RocksCE.png"		},
   { "custom_33.xpos",				"0"			},
   { "custom_33.ypos",				"2"			},
   { "custom_33.frames",				"1"			},
-  { "custom_33.EDITOR",				"RocksCE.pcx"		},
+  { "custom_33.EDITOR",				"RocksCE.png"		},
   { "custom_33.EDITOR.xpos",			"16"			},
   { "custom_33.EDITOR.ypos",			"2"			},
 
-  { "custom_34",				"RocksCE.pcx"		},
+  { "custom_34",				"RocksCE.png"		},
   { "custom_34.xpos",				"1"			},
   { "custom_34.ypos",				"2"			},
   { "custom_34.frames",				"1"			},
-  { "custom_34.EDITOR",				"RocksCE.pcx"		},
+  { "custom_34.EDITOR",				"RocksCE.png"		},
   { "custom_34.EDITOR.xpos",			"17"			},
   { "custom_34.EDITOR.ypos",			"2"			},
 
-  { "custom_35",				"RocksCE.pcx"		},
+  { "custom_35",				"RocksCE.png"		},
   { "custom_35.xpos",				"2"			},
   { "custom_35.ypos",				"2"			},
   { "custom_35.frames",				"1"			},
-  { "custom_35.EDITOR",				"RocksCE.pcx"		},
+  { "custom_35.EDITOR",				"RocksCE.png"		},
   { "custom_35.EDITOR.xpos",			"18"			},
   { "custom_35.EDITOR.ypos",			"2"			},
 
-  { "custom_36",				"RocksCE.pcx"		},
+  { "custom_36",				"RocksCE.png"		},
   { "custom_36.xpos",				"3"			},
   { "custom_36.ypos",				"2"			},
   { "custom_36.frames",				"1"			},
-  { "custom_36.EDITOR",				"RocksCE.pcx"		},
+  { "custom_36.EDITOR",				"RocksCE.png"		},
   { "custom_36.EDITOR.xpos",			"19"			},
   { "custom_36.EDITOR.ypos",			"2"			},
 
-  { "custom_37",				"RocksCE.pcx"		},
+  { "custom_37",				"RocksCE.png"		},
   { "custom_37.xpos",				"4"			},
   { "custom_37.ypos",				"2"			},
   { "custom_37.frames",				"1"			},
-  { "custom_37.EDITOR",				"RocksCE.pcx"		},
+  { "custom_37.EDITOR",				"RocksCE.png"		},
   { "custom_37.EDITOR.xpos",			"20"			},
   { "custom_37.EDITOR.ypos",			"2"			},
 
-  { "custom_38",				"RocksCE.pcx"		},
+  { "custom_38",				"RocksCE.png"		},
   { "custom_38.xpos",				"5"			},
   { "custom_38.ypos",				"2"			},
   { "custom_38.frames",				"1"			},
-  { "custom_38.EDITOR",				"RocksCE.pcx"		},
+  { "custom_38.EDITOR",				"RocksCE.png"		},
   { "custom_38.EDITOR.xpos",			"21"			},
   { "custom_38.EDITOR.ypos",			"2"			},
 
-  { "custom_39",				"RocksCE.pcx"		},
+  { "custom_39",				"RocksCE.png"		},
   { "custom_39.xpos",				"6"			},
   { "custom_39.ypos",				"2"			},
   { "custom_39.frames",				"1"			},
-  { "custom_39.EDITOR",				"RocksCE.pcx"		},
+  { "custom_39.EDITOR",				"RocksCE.png"		},
   { "custom_39.EDITOR.xpos",			"22"			},
   { "custom_39.EDITOR.ypos",			"2"			},
 
-  { "custom_40",				"RocksCE.pcx"		},
+  { "custom_40",				"RocksCE.png"		},
   { "custom_40.xpos",				"7"			},
   { "custom_40.ypos",				"2"			},
   { "custom_40.frames",				"1"			},
-  { "custom_40.EDITOR",				"RocksCE.pcx"		},
+  { "custom_40.EDITOR",				"RocksCE.png"		},
   { "custom_40.EDITOR.xpos",			"23"			},
   { "custom_40.EDITOR.ypos",			"2"			},
 
-  { "custom_41",				"RocksCE.pcx"		},
+  { "custom_41",				"RocksCE.png"		},
   { "custom_41.xpos",				"8"			},
   { "custom_41.ypos",				"2"			},
   { "custom_41.frames",				"1"			},
-  { "custom_41.EDITOR",				"RocksCE.pcx"		},
+  { "custom_41.EDITOR",				"RocksCE.png"		},
   { "custom_41.EDITOR.xpos",			"24"			},
   { "custom_41.EDITOR.ypos",			"2"			},
 
-  { "custom_42",				"RocksCE.pcx"		},
+  { "custom_42",				"RocksCE.png"		},
   { "custom_42.xpos",				"9"			},
   { "custom_42.ypos",				"2"			},
   { "custom_42.frames",				"1"			},
-  { "custom_42.EDITOR",				"RocksCE.pcx"		},
+  { "custom_42.EDITOR",				"RocksCE.png"		},
   { "custom_42.EDITOR.xpos",			"25"			},
   { "custom_42.EDITOR.ypos",			"2"			},
 
-  { "custom_43",				"RocksCE.pcx"		},
+  { "custom_43",				"RocksCE.png"		},
   { "custom_43.xpos",				"10"			},
   { "custom_43.ypos",				"2"			},
   { "custom_43.frames",				"1"			},
-  { "custom_43.EDITOR",				"RocksCE.pcx"		},
+  { "custom_43.EDITOR",				"RocksCE.png"		},
   { "custom_43.EDITOR.xpos",			"26"			},
   { "custom_43.EDITOR.ypos",			"2"			},
 
-  { "custom_44",				"RocksCE.pcx"		},
+  { "custom_44",				"RocksCE.png"		},
   { "custom_44.xpos",				"11"			},
   { "custom_44.ypos",				"2"			},
   { "custom_44.frames",				"1"			},
-  { "custom_44.EDITOR",				"RocksCE.pcx"		},
+  { "custom_44.EDITOR",				"RocksCE.png"		},
   { "custom_44.EDITOR.xpos",			"27"			},
   { "custom_44.EDITOR.ypos",			"2"			},
 
-  { "custom_45",				"RocksCE.pcx"		},
+  { "custom_45",				"RocksCE.png"		},
   { "custom_45.xpos",				"12"			},
   { "custom_45.ypos",				"2"			},
   { "custom_45.frames",				"1"			},
-  { "custom_45.EDITOR",				"RocksCE.pcx"		},
+  { "custom_45.EDITOR",				"RocksCE.png"		},
   { "custom_45.EDITOR.xpos",			"28"			},
   { "custom_45.EDITOR.ypos",			"2"			},
 
-  { "custom_46",				"RocksCE.pcx"		},
+  { "custom_46",				"RocksCE.png"		},
   { "custom_46.xpos",				"13"			},
   { "custom_46.ypos",				"2"			},
   { "custom_46.frames",				"1"			},
-  { "custom_46.EDITOR",				"RocksCE.pcx"		},
+  { "custom_46.EDITOR",				"RocksCE.png"		},
   { "custom_46.EDITOR.xpos",			"29"			},
   { "custom_46.EDITOR.ypos",			"2"			},
 
-  { "custom_47",				"RocksCE.pcx"		},
+  { "custom_47",				"RocksCE.png"		},
   { "custom_47.xpos",				"14"			},
   { "custom_47.ypos",				"2"			},
   { "custom_47.frames",				"1"			},
-  { "custom_47.EDITOR",				"RocksCE.pcx"		},
+  { "custom_47.EDITOR",				"RocksCE.png"		},
   { "custom_47.EDITOR.xpos",			"30"			},
   { "custom_47.EDITOR.ypos",			"2"			},
 
-  { "custom_48",				"RocksCE.pcx"		},
+  { "custom_48",				"RocksCE.png"		},
   { "custom_48.xpos",				"15"			},
   { "custom_48.ypos",				"2"			},
   { "custom_48.frames",				"1"			},
-  { "custom_48.EDITOR",				"RocksCE.pcx"		},
+  { "custom_48.EDITOR",				"RocksCE.png"		},
   { "custom_48.EDITOR.xpos",			"31"			},
   { "custom_48.EDITOR.ypos",			"2"			},
 
-  { "custom_49",				"RocksCE.pcx"		},
+  { "custom_49",				"RocksCE.png"		},
   { "custom_49.xpos",				"0"			},
   { "custom_49.ypos",				"3"			},
   { "custom_49.frames",				"1"			},
-  { "custom_49.EDITOR",				"RocksCE.pcx"		},
+  { "custom_49.EDITOR",				"RocksCE.png"		},
   { "custom_49.EDITOR.xpos",			"16"			},
   { "custom_49.EDITOR.ypos",			"3"			},
 
-  { "custom_50",				"RocksCE.pcx"		},
+  { "custom_50",				"RocksCE.png"		},
   { "custom_50.xpos",				"1"			},
   { "custom_50.ypos",				"3"			},
   { "custom_50.frames",				"1"			},
-  { "custom_50.EDITOR",				"RocksCE.pcx"		},
+  { "custom_50.EDITOR",				"RocksCE.png"		},
   { "custom_50.EDITOR.xpos",			"17"			},
   { "custom_50.EDITOR.ypos",			"3"			},
 
-  { "custom_51",				"RocksCE.pcx"		},
+  { "custom_51",				"RocksCE.png"		},
   { "custom_51.xpos",				"2"			},
   { "custom_51.ypos",				"3"			},
   { "custom_51.frames",				"1"			},
-  { "custom_51.EDITOR",				"RocksCE.pcx"		},
+  { "custom_51.EDITOR",				"RocksCE.png"		},
   { "custom_51.EDITOR.xpos",			"18"			},
   { "custom_51.EDITOR.ypos",			"3"			},
 
-  { "custom_52",				"RocksCE.pcx"		},
+  { "custom_52",				"RocksCE.png"		},
   { "custom_52.xpos",				"3"			},
   { "custom_52.ypos",				"3"			},
   { "custom_52.frames",				"1"			},
-  { "custom_52.EDITOR",				"RocksCE.pcx"		},
+  { "custom_52.EDITOR",				"RocksCE.png"		},
   { "custom_52.EDITOR.xpos",			"19"			},
   { "custom_52.EDITOR.ypos",			"3"			},
 
-  { "custom_53",				"RocksCE.pcx"		},
+  { "custom_53",				"RocksCE.png"		},
   { "custom_53.xpos",				"4"			},
   { "custom_53.ypos",				"3"			},
   { "custom_53.frames",				"1"			},
-  { "custom_53.EDITOR",				"RocksCE.pcx"		},
+  { "custom_53.EDITOR",				"RocksCE.png"		},
   { "custom_53.EDITOR.xpos",			"20"			},
   { "custom_53.EDITOR.ypos",			"3"			},
 
-  { "custom_54",				"RocksCE.pcx"		},
+  { "custom_54",				"RocksCE.png"		},
   { "custom_54.xpos",				"5"			},
   { "custom_54.ypos",				"3"			},
   { "custom_54.frames",				"1"			},
-  { "custom_54.EDITOR",				"RocksCE.pcx"		},
+  { "custom_54.EDITOR",				"RocksCE.png"		},
   { "custom_54.EDITOR.xpos",			"21"			},
   { "custom_54.EDITOR.ypos",			"3"			},
 
-  { "custom_55",				"RocksCE.pcx"		},
+  { "custom_55",				"RocksCE.png"		},
   { "custom_55.xpos",				"6"			},
   { "custom_55.ypos",				"3"			},
   { "custom_55.frames",				"1"			},
-  { "custom_55.EDITOR",				"RocksCE.pcx"		},
+  { "custom_55.EDITOR",				"RocksCE.png"		},
   { "custom_55.EDITOR.xpos",			"22"			},
   { "custom_55.EDITOR.ypos",			"3"			},
 
-  { "custom_56",				"RocksCE.pcx"		},
+  { "custom_56",				"RocksCE.png"		},
   { "custom_56.xpos",				"7"			},
   { "custom_56.ypos",				"3"			},
   { "custom_56.frames",				"1"			},
-  { "custom_56.EDITOR",				"RocksCE.pcx"		},
+  { "custom_56.EDITOR",				"RocksCE.png"		},
   { "custom_56.EDITOR.xpos",			"23"			},
   { "custom_56.EDITOR.ypos",			"3"			},
 
-  { "custom_57",				"RocksCE.pcx"		},
+  { "custom_57",				"RocksCE.png"		},
   { "custom_57.xpos",				"8"			},
   { "custom_57.ypos",				"3"			},
   { "custom_57.frames",				"1"			},
-  { "custom_57.EDITOR",				"RocksCE.pcx"		},
+  { "custom_57.EDITOR",				"RocksCE.png"		},
   { "custom_57.EDITOR.xpos",			"24"			},
   { "custom_57.EDITOR.ypos",			"3"			},
 
-  { "custom_58",				"RocksCE.pcx"		},
+  { "custom_58",				"RocksCE.png"		},
   { "custom_58.xpos",				"9"			},
   { "custom_58.ypos",				"3"			},
   { "custom_58.frames",				"1"			},
-  { "custom_58.EDITOR",				"RocksCE.pcx"		},
+  { "custom_58.EDITOR",				"RocksCE.png"		},
   { "custom_58.EDITOR.xpos",			"25"			},
   { "custom_58.EDITOR.ypos",			"3"			},
 
-  { "custom_59",				"RocksCE.pcx"		},
+  { "custom_59",				"RocksCE.png"		},
   { "custom_59.xpos",				"10"			},
   { "custom_59.ypos",				"3"			},
   { "custom_59.frames",				"1"			},
-  { "custom_59.EDITOR",				"RocksCE.pcx"		},
+  { "custom_59.EDITOR",				"RocksCE.png"		},
   { "custom_59.EDITOR.xpos",			"26"			},
   { "custom_59.EDITOR.ypos",			"3"			},
 
-  { "custom_60",				"RocksCE.pcx"		},
+  { "custom_60",				"RocksCE.png"		},
   { "custom_60.xpos",				"11"			},
   { "custom_60.ypos",				"3"			},
   { "custom_60.frames",				"1"			},
-  { "custom_60.EDITOR",				"RocksCE.pcx"		},
+  { "custom_60.EDITOR",				"RocksCE.png"		},
   { "custom_60.EDITOR.xpos",			"27"			},
   { "custom_60.EDITOR.ypos",			"3"			},
 
-  { "custom_61",				"RocksCE.pcx"		},
+  { "custom_61",				"RocksCE.png"		},
   { "custom_61.xpos",				"12"			},
   { "custom_61.ypos",				"3"			},
   { "custom_61.frames",				"1"			},
-  { "custom_61.EDITOR",				"RocksCE.pcx"		},
+  { "custom_61.EDITOR",				"RocksCE.png"		},
   { "custom_61.EDITOR.xpos",			"28"			},
   { "custom_61.EDITOR.ypos",			"3"			},
 
-  { "custom_62",				"RocksCE.pcx"		},
+  { "custom_62",				"RocksCE.png"		},
   { "custom_62.xpos",				"13"			},
   { "custom_62.ypos",				"3"			},
   { "custom_62.frames",				"1"			},
-  { "custom_62.EDITOR",				"RocksCE.pcx"		},
+  { "custom_62.EDITOR",				"RocksCE.png"		},
   { "custom_62.EDITOR.xpos",			"29"			},
   { "custom_62.EDITOR.ypos",			"3"			},
 
-  { "custom_63",				"RocksCE.pcx"		},
+  { "custom_63",				"RocksCE.png"		},
   { "custom_63.xpos",				"14"			},
   { "custom_63.ypos",				"3"			},
   { "custom_63.frames",				"1"			},
-  { "custom_63.EDITOR",				"RocksCE.pcx"		},
+  { "custom_63.EDITOR",				"RocksCE.png"		},
   { "custom_63.EDITOR.xpos",			"30"			},
   { "custom_63.EDITOR.ypos",			"3"			},
 
-  { "custom_64",				"RocksCE.pcx"		},
+  { "custom_64",				"RocksCE.png"		},
   { "custom_64.xpos",				"15"			},
   { "custom_64.ypos",				"3"			},
   { "custom_64.frames",				"1"			},
-  { "custom_64.EDITOR",				"RocksCE.pcx"		},
+  { "custom_64.EDITOR",				"RocksCE.png"		},
   { "custom_64.EDITOR.xpos",			"31"			},
   { "custom_64.EDITOR.ypos",			"3"			},
 
-  { "custom_65",				"RocksCE.pcx"		},
+  { "custom_65",				"RocksCE.png"		},
   { "custom_65.xpos",				"0"			},
   { "custom_65.ypos",				"4"			},
   { "custom_65.frames",				"1"			},
-  { "custom_65.EDITOR",				"RocksCE.pcx"		},
+  { "custom_65.EDITOR",				"RocksCE.png"		},
   { "custom_65.EDITOR.xpos",			"16"			},
   { "custom_65.EDITOR.ypos",			"4"			},
 
-  { "custom_66",				"RocksCE.pcx"		},
+  { "custom_66",				"RocksCE.png"		},
   { "custom_66.xpos",				"1"			},
   { "custom_66.ypos",				"4"			},
   { "custom_66.frames",				"1"			},
-  { "custom_66.EDITOR",				"RocksCE.pcx"		},
+  { "custom_66.EDITOR",				"RocksCE.png"		},
   { "custom_66.EDITOR.xpos",			"17"			},
   { "custom_66.EDITOR.ypos",			"4"			},
 
-  { "custom_67",				"RocksCE.pcx"		},
+  { "custom_67",				"RocksCE.png"		},
   { "custom_67.xpos",				"2"			},
   { "custom_67.ypos",				"4"			},
   { "custom_67.frames",				"1"			},
-  { "custom_67.EDITOR",				"RocksCE.pcx"		},
+  { "custom_67.EDITOR",				"RocksCE.png"		},
   { "custom_67.EDITOR.xpos",			"18"			},
   { "custom_67.EDITOR.ypos",			"4"			},
 
-  { "custom_68",				"RocksCE.pcx"		},
+  { "custom_68",				"RocksCE.png"		},
   { "custom_68.xpos",				"3"			},
   { "custom_68.ypos",				"4"			},
   { "custom_68.frames",				"1"			},
-  { "custom_68.EDITOR",				"RocksCE.pcx"		},
+  { "custom_68.EDITOR",				"RocksCE.png"		},
   { "custom_68.EDITOR.xpos",			"19"			},
   { "custom_68.EDITOR.ypos",			"4"			},
 
-  { "custom_69",				"RocksCE.pcx"		},
+  { "custom_69",				"RocksCE.png"		},
   { "custom_69.xpos",				"4"			},
   { "custom_69.ypos",				"4"			},
   { "custom_69.frames",				"1"			},
-  { "custom_69.EDITOR",				"RocksCE.pcx"		},
+  { "custom_69.EDITOR",				"RocksCE.png"		},
   { "custom_69.EDITOR.xpos",			"20"			},
   { "custom_69.EDITOR.ypos",			"4"			},
 
-  { "custom_70",				"RocksCE.pcx"		},
+  { "custom_70",				"RocksCE.png"		},
   { "custom_70.xpos",				"5"			},
   { "custom_70.ypos",				"4"			},
   { "custom_70.frames",				"1"			},
-  { "custom_70.EDITOR",				"RocksCE.pcx"		},
+  { "custom_70.EDITOR",				"RocksCE.png"		},
   { "custom_70.EDITOR.xpos",			"21"			},
   { "custom_70.EDITOR.ypos",			"4"			},
 
-  { "custom_71",				"RocksCE.pcx"		},
+  { "custom_71",				"RocksCE.png"		},
   { "custom_71.xpos",				"6"			},
   { "custom_71.ypos",				"4"			},
   { "custom_71.frames",				"1"			},
-  { "custom_71.EDITOR",				"RocksCE.pcx"		},
+  { "custom_71.EDITOR",				"RocksCE.png"		},
   { "custom_71.EDITOR.xpos",			"22"			},
   { "custom_71.EDITOR.ypos",			"4"			},
 
-  { "custom_72",				"RocksCE.pcx"		},
+  { "custom_72",				"RocksCE.png"		},
   { "custom_72.xpos",				"7"			},
   { "custom_72.ypos",				"4"			},
   { "custom_72.frames",				"1"			},
-  { "custom_72.EDITOR",				"RocksCE.pcx"		},
+  { "custom_72.EDITOR",				"RocksCE.png"		},
   { "custom_72.EDITOR.xpos",			"23"			},
   { "custom_72.EDITOR.ypos",			"4"			},
 
-  { "custom_73",				"RocksCE.pcx"		},
+  { "custom_73",				"RocksCE.png"		},
   { "custom_73.xpos",				"8"			},
   { "custom_73.ypos",				"4"			},
   { "custom_73.frames",				"1"			},
-  { "custom_73.EDITOR",				"RocksCE.pcx"		},
+  { "custom_73.EDITOR",				"RocksCE.png"		},
   { "custom_73.EDITOR.xpos",			"24"			},
   { "custom_73.EDITOR.ypos",			"4"			},
 
-  { "custom_74",				"RocksCE.pcx"		},
+  { "custom_74",				"RocksCE.png"		},
   { "custom_74.xpos",				"9"			},
   { "custom_74.ypos",				"4"			},
   { "custom_74.frames",				"1"			},
-  { "custom_74.EDITOR",				"RocksCE.pcx"		},
+  { "custom_74.EDITOR",				"RocksCE.png"		},
   { "custom_74.EDITOR.xpos",			"25"			},
   { "custom_74.EDITOR.ypos",			"4"			},
 
-  { "custom_75",				"RocksCE.pcx"		},
+  { "custom_75",				"RocksCE.png"		},
   { "custom_75.xpos",				"10"			},
   { "custom_75.ypos",				"4"			},
   { "custom_75.frames",				"1"			},
-  { "custom_75.EDITOR",				"RocksCE.pcx"		},
+  { "custom_75.EDITOR",				"RocksCE.png"		},
   { "custom_75.EDITOR.xpos",			"26"			},
   { "custom_75.EDITOR.ypos",			"4"			},
 
-  { "custom_76",				"RocksCE.pcx"		},
+  { "custom_76",				"RocksCE.png"		},
   { "custom_76.xpos",				"11"			},
   { "custom_76.ypos",				"4"			},
   { "custom_76.frames",				"1"			},
-  { "custom_76.EDITOR",				"RocksCE.pcx"		},
+  { "custom_76.EDITOR",				"RocksCE.png"		},
   { "custom_76.EDITOR.xpos",			"27"			},
   { "custom_76.EDITOR.ypos",			"4"			},
 
-  { "custom_77",				"RocksCE.pcx"		},
+  { "custom_77",				"RocksCE.png"		},
   { "custom_77.xpos",				"12"			},
   { "custom_77.ypos",				"4"			},
   { "custom_77.frames",				"1"			},
-  { "custom_77.EDITOR",				"RocksCE.pcx"		},
+  { "custom_77.EDITOR",				"RocksCE.png"		},
   { "custom_77.EDITOR.xpos",			"28"			},
   { "custom_77.EDITOR.ypos",			"4"			},
 
-  { "custom_78",				"RocksCE.pcx"		},
+  { "custom_78",				"RocksCE.png"		},
   { "custom_78.xpos",				"13"			},
   { "custom_78.ypos",				"4"			},
   { "custom_78.frames",				"1"			},
-  { "custom_78.EDITOR",				"RocksCE.pcx"		},
+  { "custom_78.EDITOR",				"RocksCE.png"		},
   { "custom_78.EDITOR.xpos",			"29"			},
   { "custom_78.EDITOR.ypos",			"4"			},
 
-  { "custom_79",				"RocksCE.pcx"		},
+  { "custom_79",				"RocksCE.png"		},
   { "custom_79.xpos",				"14"			},
   { "custom_79.ypos",				"4"			},
   { "custom_79.frames",				"1"			},
-  { "custom_79.EDITOR",				"RocksCE.pcx"		},
+  { "custom_79.EDITOR",				"RocksCE.png"		},
   { "custom_79.EDITOR.xpos",			"30"			},
   { "custom_79.EDITOR.ypos",			"4"			},
 
-  { "custom_80",				"RocksCE.pcx"		},
+  { "custom_80",				"RocksCE.png"		},
   { "custom_80.xpos",				"15"			},
   { "custom_80.ypos",				"4"			},
   { "custom_80.frames",				"1"			},
-  { "custom_80.EDITOR",				"RocksCE.pcx"		},
+  { "custom_80.EDITOR",				"RocksCE.png"		},
   { "custom_80.EDITOR.xpos",			"31"			},
   { "custom_80.EDITOR.ypos",			"4"			},
 
-  { "custom_81",				"RocksCE.pcx"		},
+  { "custom_81",				"RocksCE.png"		},
   { "custom_81.xpos",				"0"			},
   { "custom_81.ypos",				"5"			},
   { "custom_81.frames",				"1"			},
-  { "custom_81.EDITOR",				"RocksCE.pcx"		},
+  { "custom_81.EDITOR",				"RocksCE.png"		},
   { "custom_81.EDITOR.xpos",			"16"			},
   { "custom_81.EDITOR.ypos",			"5"			},
 
-  { "custom_82",				"RocksCE.pcx"		},
+  { "custom_82",				"RocksCE.png"		},
   { "custom_82.xpos",				"1"			},
   { "custom_82.ypos",				"5"			},
   { "custom_82.frames",				"1"			},
-  { "custom_82.EDITOR",				"RocksCE.pcx"		},
+  { "custom_82.EDITOR",				"RocksCE.png"		},
   { "custom_82.EDITOR.xpos",			"17"			},
   { "custom_82.EDITOR.ypos",			"5"			},
 
-  { "custom_83",				"RocksCE.pcx"		},
+  { "custom_83",				"RocksCE.png"		},
   { "custom_83.xpos",				"2"			},
   { "custom_83.ypos",				"5"			},
   { "custom_83.frames",				"1"			},
-  { "custom_83.EDITOR",				"RocksCE.pcx"		},
+  { "custom_83.EDITOR",				"RocksCE.png"		},
   { "custom_83.EDITOR.xpos",			"18"			},
   { "custom_83.EDITOR.ypos",			"5"			},
 
-  { "custom_84",				"RocksCE.pcx"		},
+  { "custom_84",				"RocksCE.png"		},
   { "custom_84.xpos",				"3"			},
   { "custom_84.ypos",				"5"			},
   { "custom_84.frames",				"1"			},
-  { "custom_84.EDITOR",				"RocksCE.pcx"		},
+  { "custom_84.EDITOR",				"RocksCE.png"		},
   { "custom_84.EDITOR.xpos",			"19"			},
   { "custom_84.EDITOR.ypos",			"5"			},
 
-  { "custom_85",				"RocksCE.pcx"		},
+  { "custom_85",				"RocksCE.png"		},
   { "custom_85.xpos",				"4"			},
   { "custom_85.ypos",				"5"			},
   { "custom_85.frames",				"1"			},
-  { "custom_85.EDITOR",				"RocksCE.pcx"		},
+  { "custom_85.EDITOR",				"RocksCE.png"		},
   { "custom_85.EDITOR.xpos",			"20"			},
   { "custom_85.EDITOR.ypos",			"5"			},
 
-  { "custom_86",				"RocksCE.pcx"		},
+  { "custom_86",				"RocksCE.png"		},
   { "custom_86.xpos",				"5"			},
   { "custom_86.ypos",				"5"			},
   { "custom_86.frames",				"1"			},
-  { "custom_86.EDITOR",				"RocksCE.pcx"		},
+  { "custom_86.EDITOR",				"RocksCE.png"		},
   { "custom_86.EDITOR.xpos",			"21"			},
   { "custom_86.EDITOR.ypos",			"5"			},
 
-  { "custom_87",				"RocksCE.pcx"		},
+  { "custom_87",				"RocksCE.png"		},
   { "custom_87.xpos",				"6"			},
   { "custom_87.ypos",				"5"			},
   { "custom_87.frames",				"1"			},
-  { "custom_87.EDITOR",				"RocksCE.pcx"		},
+  { "custom_87.EDITOR",				"RocksCE.png"		},
   { "custom_87.EDITOR.xpos",			"22"			},
   { "custom_87.EDITOR.ypos",			"5"			},
 
-  { "custom_88",				"RocksCE.pcx"		},
+  { "custom_88",				"RocksCE.png"		},
   { "custom_88.xpos",				"7"			},
   { "custom_88.ypos",				"5"			},
   { "custom_88.frames",				"1"			},
-  { "custom_88.EDITOR",				"RocksCE.pcx"		},
+  { "custom_88.EDITOR",				"RocksCE.png"		},
   { "custom_88.EDITOR.xpos",			"23"			},
   { "custom_88.EDITOR.ypos",			"5"			},
 
-  { "custom_89",				"RocksCE.pcx"		},
+  { "custom_89",				"RocksCE.png"		},
   { "custom_89.xpos",				"8"			},
   { "custom_89.ypos",				"5"			},
   { "custom_89.frames",				"1"			},
-  { "custom_89.EDITOR",				"RocksCE.pcx"		},
+  { "custom_89.EDITOR",				"RocksCE.png"		},
   { "custom_89.EDITOR.xpos",			"24"			},
   { "custom_89.EDITOR.ypos",			"5"			},
 
-  { "custom_90",				"RocksCE.pcx"		},
+  { "custom_90",				"RocksCE.png"		},
   { "custom_90.xpos",				"9"			},
   { "custom_90.ypos",				"5"			},
   { "custom_90.frames",				"1"			},
-  { "custom_90.EDITOR",				"RocksCE.pcx"		},
+  { "custom_90.EDITOR",				"RocksCE.png"		},
   { "custom_90.EDITOR.xpos",			"25"			},
   { "custom_90.EDITOR.ypos",			"5"			},
 
-  { "custom_91",				"RocksCE.pcx"		},
+  { "custom_91",				"RocksCE.png"		},
   { "custom_91.xpos",				"10"			},
   { "custom_91.ypos",				"5"			},
   { "custom_91.frames",				"1"			},
-  { "custom_91.EDITOR",				"RocksCE.pcx"		},
+  { "custom_91.EDITOR",				"RocksCE.png"		},
   { "custom_91.EDITOR.xpos",			"26"			},
   { "custom_91.EDITOR.ypos",			"5"			},
 
-  { "custom_92",				"RocksCE.pcx"		},
+  { "custom_92",				"RocksCE.png"		},
   { "custom_92.xpos",				"11"			},
   { "custom_92.ypos",				"5"			},
   { "custom_92.frames",				"1"			},
-  { "custom_92.EDITOR",				"RocksCE.pcx"		},
+  { "custom_92.EDITOR",				"RocksCE.png"		},
   { "custom_92.EDITOR.xpos",			"27"			},
   { "custom_92.EDITOR.ypos",			"5"			},
 
-  { "custom_93",				"RocksCE.pcx"		},
+  { "custom_93",				"RocksCE.png"		},
   { "custom_93.xpos",				"12"			},
   { "custom_93.ypos",				"5"			},
   { "custom_93.frames",				"1"			},
-  { "custom_93.EDITOR",				"RocksCE.pcx"		},
+  { "custom_93.EDITOR",				"RocksCE.png"		},
   { "custom_93.EDITOR.xpos",			"28"			},
   { "custom_93.EDITOR.ypos",			"5"			},
 
-  { "custom_94",				"RocksCE.pcx"		},
+  { "custom_94",				"RocksCE.png"		},
   { "custom_94.xpos",				"13"			},
   { "custom_94.ypos",				"5"			},
   { "custom_94.frames",				"1"			},
-  { "custom_94.EDITOR",				"RocksCE.pcx"		},
+  { "custom_94.EDITOR",				"RocksCE.png"		},
   { "custom_94.EDITOR.xpos",			"29"			},
   { "custom_94.EDITOR.ypos",			"5"			},
 
-  { "custom_95",				"RocksCE.pcx"		},
+  { "custom_95",				"RocksCE.png"		},
   { "custom_95.xpos",				"14"			},
   { "custom_95.ypos",				"5"			},
   { "custom_95.frames",				"1"			},
-  { "custom_95.EDITOR",				"RocksCE.pcx"		},
+  { "custom_95.EDITOR",				"RocksCE.png"		},
   { "custom_95.EDITOR.xpos",			"30"			},
   { "custom_95.EDITOR.ypos",			"5"			},
 
-  { "custom_96",				"RocksCE.pcx"		},
+  { "custom_96",				"RocksCE.png"		},
   { "custom_96.xpos",				"15"			},
   { "custom_96.ypos",				"5"			},
   { "custom_96.frames",				"1"			},
-  { "custom_96.EDITOR",				"RocksCE.pcx"		},
+  { "custom_96.EDITOR",				"RocksCE.png"		},
   { "custom_96.EDITOR.xpos",			"31"			},
   { "custom_96.EDITOR.ypos",			"5"			},
 
-  { "custom_97",				"RocksCE.pcx"		},
+  { "custom_97",				"RocksCE.png"		},
   { "custom_97.xpos",				"0"			},
   { "custom_97.ypos",				"6"			},
   { "custom_97.frames",				"1"			},
-  { "custom_97.EDITOR",				"RocksCE.pcx"		},
+  { "custom_97.EDITOR",				"RocksCE.png"		},
   { "custom_97.EDITOR.xpos",			"16"			},
   { "custom_97.EDITOR.ypos",			"6"			},
 
-  { "custom_98",				"RocksCE.pcx"		},
+  { "custom_98",				"RocksCE.png"		},
   { "custom_98.xpos",				"1"			},
   { "custom_98.ypos",				"6"			},
   { "custom_98.frames",				"1"			},
-  { "custom_98.EDITOR",				"RocksCE.pcx"		},
+  { "custom_98.EDITOR",				"RocksCE.png"		},
   { "custom_98.EDITOR.xpos",			"17"			},
   { "custom_98.EDITOR.ypos",			"6"			},
 
-  { "custom_99",				"RocksCE.pcx"		},
+  { "custom_99",				"RocksCE.png"		},
   { "custom_99.xpos",				"2"			},
   { "custom_99.ypos",				"6"			},
   { "custom_99.frames",				"1"			},
-  { "custom_99.EDITOR",				"RocksCE.pcx"		},
+  { "custom_99.EDITOR",				"RocksCE.png"		},
   { "custom_99.EDITOR.xpos",			"18"			},
   { "custom_99.EDITOR.ypos",			"6"			},
 
-  { "custom_100",				"RocksCE.pcx"		},
+  { "custom_100",				"RocksCE.png"		},
   { "custom_100.xpos",				"3"			},
   { "custom_100.ypos",				"6"			},
   { "custom_100.frames",			"1"			},
-  { "custom_100.EDITOR",			"RocksCE.pcx"		},
+  { "custom_100.EDITOR",			"RocksCE.png"		},
   { "custom_100.EDITOR.xpos",			"19"			},
   { "custom_100.EDITOR.ypos",			"6"			},
 
-  { "custom_101",				"RocksCE.pcx"		},
+  { "custom_101",				"RocksCE.png"		},
   { "custom_101.xpos",				"4"			},
   { "custom_101.ypos",				"6"			},
   { "custom_101.frames",			"1"			},
-  { "custom_101.EDITOR",			"RocksCE.pcx"		},
+  { "custom_101.EDITOR",			"RocksCE.png"		},
   { "custom_101.EDITOR.xpos",			"20"			},
   { "custom_101.EDITOR.ypos",			"6"			},
 
-  { "custom_102",				"RocksCE.pcx"		},
+  { "custom_102",				"RocksCE.png"		},
   { "custom_102.xpos",				"5"			},
   { "custom_102.ypos",				"6"			},
   { "custom_102.frames",			"1"			},
-  { "custom_102.EDITOR",			"RocksCE.pcx"		},
+  { "custom_102.EDITOR",			"RocksCE.png"		},
   { "custom_102.EDITOR.xpos",			"21"			},
   { "custom_102.EDITOR.ypos",			"6"			},
 
-  { "custom_103",				"RocksCE.pcx"		},
+  { "custom_103",				"RocksCE.png"		},
   { "custom_103.xpos",				"6"			},
   { "custom_103.ypos",				"6"			},
   { "custom_103.frames",			"1"			},
-  { "custom_103.EDITOR",			"RocksCE.pcx"		},
+  { "custom_103.EDITOR",			"RocksCE.png"		},
   { "custom_103.EDITOR.xpos",			"22"			},
   { "custom_103.EDITOR.ypos",			"6"			},
 
-  { "custom_104",				"RocksCE.pcx"		},
+  { "custom_104",				"RocksCE.png"		},
   { "custom_104.xpos",				"7"			},
   { "custom_104.ypos",				"6"			},
   { "custom_104.frames",			"1"			},
-  { "custom_104.EDITOR",			"RocksCE.pcx"		},
+  { "custom_104.EDITOR",			"RocksCE.png"		},
   { "custom_104.EDITOR.xpos",			"23"			},
   { "custom_104.EDITOR.ypos",			"6"			},
 
-  { "custom_105",				"RocksCE.pcx"		},
+  { "custom_105",				"RocksCE.png"		},
   { "custom_105.xpos",				"8"			},
   { "custom_105.ypos",				"6"			},
   { "custom_105.frames",			"1"			},
-  { "custom_105.EDITOR",			"RocksCE.pcx"		},
+  { "custom_105.EDITOR",			"RocksCE.png"		},
   { "custom_105.EDITOR.xpos",			"24"			},
   { "custom_105.EDITOR.ypos",			"6"			},
 
-  { "custom_106",				"RocksCE.pcx"		},
+  { "custom_106",				"RocksCE.png"		},
   { "custom_106.xpos",				"9"			},
   { "custom_106.ypos",				"6"			},
   { "custom_106.frames",			"1"			},
-  { "custom_106.EDITOR",			"RocksCE.pcx"		},
+  { "custom_106.EDITOR",			"RocksCE.png"		},
   { "custom_106.EDITOR.xpos",			"25"			},
   { "custom_106.EDITOR.ypos",			"6"			},
 
-  { "custom_107",				"RocksCE.pcx"		},
+  { "custom_107",				"RocksCE.png"		},
   { "custom_107.xpos",				"10"			},
   { "custom_107.ypos",				"6"			},
   { "custom_107.frames",			"1"			},
-  { "custom_107.EDITOR",			"RocksCE.pcx"		},
+  { "custom_107.EDITOR",			"RocksCE.png"		},
   { "custom_107.EDITOR.xpos",			"26"			},
   { "custom_107.EDITOR.ypos",			"6"			},
 
-  { "custom_108",				"RocksCE.pcx"		},
+  { "custom_108",				"RocksCE.png"		},
   { "custom_108.xpos",				"11"			},
   { "custom_108.ypos",				"6"			},
   { "custom_108.frames",			"1"			},
-  { "custom_108.EDITOR",			"RocksCE.pcx"		},
+  { "custom_108.EDITOR",			"RocksCE.png"		},
   { "custom_108.EDITOR.xpos",			"27"			},
   { "custom_108.EDITOR.ypos",			"6"			},
 
-  { "custom_109",				"RocksCE.pcx"		},
+  { "custom_109",				"RocksCE.png"		},
   { "custom_109.xpos",				"12"			},
   { "custom_109.ypos",				"6"			},
   { "custom_109.frames",			"1"			},
-  { "custom_109.EDITOR",			"RocksCE.pcx"		},
+  { "custom_109.EDITOR",			"RocksCE.png"		},
   { "custom_109.EDITOR.xpos",			"28"			},
   { "custom_109.EDITOR.ypos",			"6"			},
 
-  { "custom_110",				"RocksCE.pcx"		},
+  { "custom_110",				"RocksCE.png"		},
   { "custom_110.xpos",				"13"			},
   { "custom_110.ypos",				"6"			},
   { "custom_110.frames",			"1"			},
-  { "custom_110.EDITOR",			"RocksCE.pcx"		},
+  { "custom_110.EDITOR",			"RocksCE.png"		},
   { "custom_110.EDITOR.xpos",			"29"			},
   { "custom_110.EDITOR.ypos",			"6"			},
 
-  { "custom_111",				"RocksCE.pcx"		},
+  { "custom_111",				"RocksCE.png"		},
   { "custom_111.xpos",				"14"			},
   { "custom_111.ypos",				"6"			},
   { "custom_111.frames",			"1"			},
-  { "custom_111.EDITOR",			"RocksCE.pcx"		},
+  { "custom_111.EDITOR",			"RocksCE.png"		},
   { "custom_111.EDITOR.xpos",			"30"			},
   { "custom_111.EDITOR.ypos",			"6"			},
 
-  { "custom_112",				"RocksCE.pcx"		},
+  { "custom_112",				"RocksCE.png"		},
   { "custom_112.xpos",				"15"			},
   { "custom_112.ypos",				"6"			},
   { "custom_112.frames",			"1"			},
-  { "custom_112.EDITOR",			"RocksCE.pcx"		},
+  { "custom_112.EDITOR",			"RocksCE.png"		},
   { "custom_112.EDITOR.xpos",			"31"			},
   { "custom_112.EDITOR.ypos",			"6"			},
 
-  { "custom_113",				"RocksCE.pcx"		},
+  { "custom_113",				"RocksCE.png"		},
   { "custom_113.xpos",				"0"			},
   { "custom_113.ypos",				"7"			},
   { "custom_113.frames",			"1"			},
-  { "custom_113.EDITOR",			"RocksCE.pcx"		},
+  { "custom_113.EDITOR",			"RocksCE.png"		},
   { "custom_113.EDITOR.xpos",			"16"			},
   { "custom_113.EDITOR.ypos",			"7"			},
 
-  { "custom_114",				"RocksCE.pcx"		},
+  { "custom_114",				"RocksCE.png"		},
   { "custom_114.xpos",				"1"			},
   { "custom_114.ypos",				"7"			},
   { "custom_114.frames",			"1"			},
-  { "custom_114.EDITOR",			"RocksCE.pcx"		},
+  { "custom_114.EDITOR",			"RocksCE.png"		},
   { "custom_114.EDITOR.xpos",			"17"			},
   { "custom_114.EDITOR.ypos",			"7"			},
 
-  { "custom_115",				"RocksCE.pcx"		},
+  { "custom_115",				"RocksCE.png"		},
   { "custom_115.xpos",				"2"			},
   { "custom_115.ypos",				"7"			},
   { "custom_115.frames",			"1"			},
-  { "custom_115.EDITOR",			"RocksCE.pcx"		},
+  { "custom_115.EDITOR",			"RocksCE.png"		},
   { "custom_115.EDITOR.xpos",			"18"			},
   { "custom_115.EDITOR.ypos",			"7"			},
 
-  { "custom_116",				"RocksCE.pcx"		},
+  { "custom_116",				"RocksCE.png"		},
   { "custom_116.xpos",				"3"			},
   { "custom_116.ypos",				"7"			},
   { "custom_116.frames",			"1"			},
-  { "custom_116.EDITOR",			"RocksCE.pcx"		},
+  { "custom_116.EDITOR",			"RocksCE.png"		},
   { "custom_116.EDITOR.xpos",			"19"			},
   { "custom_116.EDITOR.ypos",			"7"			},
 
-  { "custom_117",				"RocksCE.pcx"		},
+  { "custom_117",				"RocksCE.png"		},
   { "custom_117.xpos",				"4"			},
   { "custom_117.ypos",				"7"			},
   { "custom_117.frames",			"1"			},
-  { "custom_117.EDITOR",			"RocksCE.pcx"		},
+  { "custom_117.EDITOR",			"RocksCE.png"		},
   { "custom_117.EDITOR.xpos",			"20"			},
   { "custom_117.EDITOR.ypos",			"7"			},
 
-  { "custom_118",				"RocksCE.pcx"		},
+  { "custom_118",				"RocksCE.png"		},
   { "custom_118.xpos",				"5"			},
   { "custom_118.ypos",				"7"			},
   { "custom_118.frames",			"1"			},
-  { "custom_118.EDITOR",			"RocksCE.pcx"		},
+  { "custom_118.EDITOR",			"RocksCE.png"		},
   { "custom_118.EDITOR.xpos",			"21"			},
   { "custom_118.EDITOR.ypos",			"7"			},
 
-  { "custom_119",				"RocksCE.pcx"		},
+  { "custom_119",				"RocksCE.png"		},
   { "custom_119.xpos",				"6"			},
   { "custom_119.ypos",				"7"			},
   { "custom_119.frames",			"1"			},
-  { "custom_119.EDITOR",			"RocksCE.pcx"		},
+  { "custom_119.EDITOR",			"RocksCE.png"		},
   { "custom_119.EDITOR.xpos",			"22"			},
   { "custom_119.EDITOR.ypos",			"7"			},
 
-  { "custom_120",				"RocksCE.pcx"		},
+  { "custom_120",				"RocksCE.png"		},
   { "custom_120.xpos",				"7"			},
   { "custom_120.ypos",				"7"			},
   { "custom_120.frames",			"1"			},
-  { "custom_120.EDITOR",			"RocksCE.pcx"		},
+  { "custom_120.EDITOR",			"RocksCE.png"		},
   { "custom_120.EDITOR.xpos",			"23"			},
   { "custom_120.EDITOR.ypos",			"7"			},
 
-  { "custom_121",				"RocksCE.pcx"		},
+  { "custom_121",				"RocksCE.png"		},
   { "custom_121.xpos",				"8"			},
   { "custom_121.ypos",				"7"			},
   { "custom_121.frames",			"1"			},
-  { "custom_121.EDITOR",			"RocksCE.pcx"		},
+  { "custom_121.EDITOR",			"RocksCE.png"		},
   { "custom_121.EDITOR.xpos",			"24"			},
   { "custom_121.EDITOR.ypos",			"7"			},
 
-  { "custom_122",				"RocksCE.pcx"		},
+  { "custom_122",				"RocksCE.png"		},
   { "custom_122.xpos",				"9"			},
   { "custom_122.ypos",				"7"			},
   { "custom_122.frames",			"1"			},
-  { "custom_122.EDITOR",			"RocksCE.pcx"		},
+  { "custom_122.EDITOR",			"RocksCE.png"		},
   { "custom_122.EDITOR.xpos",			"25"			},
   { "custom_122.EDITOR.ypos",			"7"			},
 
-  { "custom_123",				"RocksCE.pcx"		},
+  { "custom_123",				"RocksCE.png"		},
   { "custom_123.xpos",				"10"			},
   { "custom_123.ypos",				"7"			},
   { "custom_123.frames",			"1"			},
-  { "custom_123.EDITOR",			"RocksCE.pcx"		},
+  { "custom_123.EDITOR",			"RocksCE.png"		},
   { "custom_123.EDITOR.xpos",			"26"			},
   { "custom_123.EDITOR.ypos",			"7"			},
 
-  { "custom_124",				"RocksCE.pcx"		},
+  { "custom_124",				"RocksCE.png"		},
   { "custom_124.xpos",				"11"			},
   { "custom_124.ypos",				"7"			},
   { "custom_124.frames",			"1"			},
-  { "custom_124.EDITOR",			"RocksCE.pcx"		},
+  { "custom_124.EDITOR",			"RocksCE.png"		},
   { "custom_124.EDITOR.xpos",			"27"			},
   { "custom_124.EDITOR.ypos",			"7"			},
 
-  { "custom_125",				"RocksCE.pcx"		},
+  { "custom_125",				"RocksCE.png"		},
   { "custom_125.xpos",				"12"			},
   { "custom_125.ypos",				"7"			},
   { "custom_125.frames",			"1"			},
-  { "custom_125.EDITOR",			"RocksCE.pcx"		},
+  { "custom_125.EDITOR",			"RocksCE.png"		},
   { "custom_125.EDITOR.xpos",			"28"			},
   { "custom_125.EDITOR.ypos",			"7"			},
 
-  { "custom_126",				"RocksCE.pcx"		},
+  { "custom_126",				"RocksCE.png"		},
   { "custom_126.xpos",				"13"			},
   { "custom_126.ypos",				"7"			},
   { "custom_126.frames",			"1"			},
-  { "custom_126.EDITOR",			"RocksCE.pcx"		},
+  { "custom_126.EDITOR",			"RocksCE.png"		},
   { "custom_126.EDITOR.xpos",			"29"			},
   { "custom_126.EDITOR.ypos",			"7"			},
 
-  { "custom_127",				"RocksCE.pcx"		},
+  { "custom_127",				"RocksCE.png"		},
   { "custom_127.xpos",				"14"			},
   { "custom_127.ypos",				"7"			},
   { "custom_127.frames",			"1"			},
-  { "custom_127.EDITOR",			"RocksCE.pcx"		},
+  { "custom_127.EDITOR",			"RocksCE.png"		},
   { "custom_127.EDITOR.xpos",			"30"			},
   { "custom_127.EDITOR.ypos",			"7"			},
 
-  { "custom_128",				"RocksCE.pcx"		},
+  { "custom_128",				"RocksCE.png"		},
   { "custom_128.xpos",				"15"			},
   { "custom_128.ypos",				"7"			},
   { "custom_128.frames",			"1"			},
-  { "custom_128.EDITOR",			"RocksCE.pcx"		},
+  { "custom_128.EDITOR",			"RocksCE.png"		},
   { "custom_128.EDITOR.xpos",			"31"			},
   { "custom_128.EDITOR.ypos",			"7"			},
 
-  { "custom_129",				"RocksCE.pcx"		},
+  { "custom_129",				"RocksCE.png"		},
   { "custom_129.xpos",				"0"			},
   { "custom_129.ypos",				"8"			},
   { "custom_129.frames",			"1"			},
-  { "custom_129.EDITOR",			"RocksCE.pcx"		},
+  { "custom_129.EDITOR",			"RocksCE.png"		},
   { "custom_129.EDITOR.xpos",			"16"			},
   { "custom_129.EDITOR.ypos",			"8"			},
 
-  { "custom_130",				"RocksCE.pcx"		},
+  { "custom_130",				"RocksCE.png"		},
   { "custom_130.xpos",				"1"			},
   { "custom_130.ypos",				"8"			},
   { "custom_130.frames",			"1"			},
-  { "custom_130.EDITOR",			"RocksCE.pcx"		},
+  { "custom_130.EDITOR",			"RocksCE.png"		},
   { "custom_130.EDITOR.xpos",			"17"			},
   { "custom_130.EDITOR.ypos",			"8"			},
 
-  { "custom_131",				"RocksCE.pcx"		},
+  { "custom_131",				"RocksCE.png"		},
   { "custom_131.xpos",				"2"			},
   { "custom_131.ypos",				"8"			},
   { "custom_131.frames",			"1"			},
-  { "custom_131.EDITOR",			"RocksCE.pcx"		},
+  { "custom_131.EDITOR",			"RocksCE.png"		},
   { "custom_131.EDITOR.xpos",			"18"			},
   { "custom_131.EDITOR.ypos",			"8"			},
 
-  { "custom_132",				"RocksCE.pcx"		},
+  { "custom_132",				"RocksCE.png"		},
   { "custom_132.xpos",				"3"			},
   { "custom_132.ypos",				"8"			},
   { "custom_132.frames",			"1"			},
-  { "custom_132.EDITOR",			"RocksCE.pcx"		},
+  { "custom_132.EDITOR",			"RocksCE.png"		},
   { "custom_132.EDITOR.xpos",			"19"			},
   { "custom_132.EDITOR.ypos",			"8"			},
 
-  { "custom_133",				"RocksCE.pcx"		},
+  { "custom_133",				"RocksCE.png"		},
   { "custom_133.xpos",				"4"			},
   { "custom_133.ypos",				"8"			},
   { "custom_133.frames",			"1"			},
-  { "custom_133.EDITOR",			"RocksCE.pcx"		},
+  { "custom_133.EDITOR",			"RocksCE.png"		},
   { "custom_133.EDITOR.xpos",			"20"			},
   { "custom_133.EDITOR.ypos",			"8"			},
 
-  { "custom_134",				"RocksCE.pcx"		},
+  { "custom_134",				"RocksCE.png"		},
   { "custom_134.xpos",				"5"			},
   { "custom_134.ypos",				"8"			},
   { "custom_134.frames",			"1"			},
-  { "custom_134.EDITOR",			"RocksCE.pcx"		},
+  { "custom_134.EDITOR",			"RocksCE.png"		},
   { "custom_134.EDITOR.xpos",			"21"			},
   { "custom_134.EDITOR.ypos",			"8"			},
 
-  { "custom_135",				"RocksCE.pcx"		},
+  { "custom_135",				"RocksCE.png"		},
   { "custom_135.xpos",				"6"			},
   { "custom_135.ypos",				"8"			},
   { "custom_135.frames",			"1"			},
-  { "custom_135.EDITOR",			"RocksCE.pcx"		},
+  { "custom_135.EDITOR",			"RocksCE.png"		},
   { "custom_135.EDITOR.xpos",			"22"			},
   { "custom_135.EDITOR.ypos",			"8"			},
 
-  { "custom_136",				"RocksCE.pcx"		},
+  { "custom_136",				"RocksCE.png"		},
   { "custom_136.xpos",				"7"			},
   { "custom_136.ypos",				"8"			},
   { "custom_136.frames",			"1"			},
-  { "custom_136.EDITOR",			"RocksCE.pcx"		},
+  { "custom_136.EDITOR",			"RocksCE.png"		},
   { "custom_136.EDITOR.xpos",			"23"			},
   { "custom_136.EDITOR.ypos",			"8"			},
 
-  { "custom_137",				"RocksCE.pcx"		},
+  { "custom_137",				"RocksCE.png"		},
   { "custom_137.xpos",				"8"			},
   { "custom_137.ypos",				"8"			},
   { "custom_137.frames",			"1"			},
-  { "custom_137.EDITOR",			"RocksCE.pcx"		},
+  { "custom_137.EDITOR",			"RocksCE.png"		},
   { "custom_137.EDITOR.xpos",			"24"			},
   { "custom_137.EDITOR.ypos",			"8"			},
 
-  { "custom_138",				"RocksCE.pcx"		},
+  { "custom_138",				"RocksCE.png"		},
   { "custom_138.xpos",				"9"			},
   { "custom_138.ypos",				"8"			},
   { "custom_138.frames",			"1"			},
-  { "custom_138.EDITOR",			"RocksCE.pcx"		},
+  { "custom_138.EDITOR",			"RocksCE.png"		},
   { "custom_138.EDITOR.xpos",			"25"			},
   { "custom_138.EDITOR.ypos",			"8"			},
 
-  { "custom_139",				"RocksCE.pcx"		},
+  { "custom_139",				"RocksCE.png"		},
   { "custom_139.xpos",				"10"			},
   { "custom_139.ypos",				"8"			},
   { "custom_139.frames",			"1"			},
-  { "custom_139.EDITOR",			"RocksCE.pcx"		},
+  { "custom_139.EDITOR",			"RocksCE.png"		},
   { "custom_139.EDITOR.xpos",			"26"			},
   { "custom_139.EDITOR.ypos",			"8"			},
 
-  { "custom_140",				"RocksCE.pcx"		},
+  { "custom_140",				"RocksCE.png"		},
   { "custom_140.xpos",				"11"			},
   { "custom_140.ypos",				"8"			},
   { "custom_140.frames",			"1"			},
-  { "custom_140.EDITOR",			"RocksCE.pcx"		},
+  { "custom_140.EDITOR",			"RocksCE.png"		},
   { "custom_140.EDITOR.xpos",			"27"			},
   { "custom_140.EDITOR.ypos",			"8"			},
 
-  { "custom_141",				"RocksCE.pcx"		},
+  { "custom_141",				"RocksCE.png"		},
   { "custom_141.xpos",				"12"			},
   { "custom_141.ypos",				"8"			},
   { "custom_141.frames",			"1"			},
-  { "custom_141.EDITOR",			"RocksCE.pcx"		},
+  { "custom_141.EDITOR",			"RocksCE.png"		},
   { "custom_141.EDITOR.xpos",			"28"			},
   { "custom_141.EDITOR.ypos",			"8"			},
 
-  { "custom_142",				"RocksCE.pcx"		},
+  { "custom_142",				"RocksCE.png"		},
   { "custom_142.xpos",				"13"			},
   { "custom_142.ypos",				"8"			},
   { "custom_142.frames",			"1"			},
-  { "custom_142.EDITOR",			"RocksCE.pcx"		},
+  { "custom_142.EDITOR",			"RocksCE.png"		},
   { "custom_142.EDITOR.xpos",			"29"			},
   { "custom_142.EDITOR.ypos",			"8"			},
 
-  { "custom_143",				"RocksCE.pcx"		},
+  { "custom_143",				"RocksCE.png"		},
   { "custom_143.xpos",				"14"			},
   { "custom_143.ypos",				"8"			},
   { "custom_143.frames",			"1"			},
-  { "custom_143.EDITOR",			"RocksCE.pcx"		},
+  { "custom_143.EDITOR",			"RocksCE.png"		},
   { "custom_143.EDITOR.xpos",			"30"			},
   { "custom_143.EDITOR.ypos",			"8"			},
 
-  { "custom_144",				"RocksCE.pcx"		},
+  { "custom_144",				"RocksCE.png"		},
   { "custom_144.xpos",				"15"			},
   { "custom_144.ypos",				"8"			},
   { "custom_144.frames",			"1"			},
-  { "custom_144.EDITOR",			"RocksCE.pcx"		},
+  { "custom_144.EDITOR",			"RocksCE.png"		},
   { "custom_144.EDITOR.xpos",			"31"			},
   { "custom_144.EDITOR.ypos",			"8"			},
 
-  { "custom_145",				"RocksCE.pcx"		},
+  { "custom_145",				"RocksCE.png"		},
   { "custom_145.xpos",				"0"			},
   { "custom_145.ypos",				"9"			},
   { "custom_145.frames",			"1"			},
-  { "custom_145.EDITOR",			"RocksCE.pcx"		},
+  { "custom_145.EDITOR",			"RocksCE.png"		},
   { "custom_145.EDITOR.xpos",			"16"			},
   { "custom_145.EDITOR.ypos",			"9"			},
 
-  { "custom_146",				"RocksCE.pcx"		},
+  { "custom_146",				"RocksCE.png"		},
   { "custom_146.xpos",				"1"			},
   { "custom_146.ypos",				"9"			},
   { "custom_146.frames",			"1"			},
-  { "custom_146.EDITOR",			"RocksCE.pcx"		},
+  { "custom_146.EDITOR",			"RocksCE.png"		},
   { "custom_146.EDITOR.xpos",			"17"			},
   { "custom_146.EDITOR.ypos",			"9"			},
 
-  { "custom_147",				"RocksCE.pcx"		},
+  { "custom_147",				"RocksCE.png"		},
   { "custom_147.xpos",				"2"			},
   { "custom_147.ypos",				"9"			},
   { "custom_147.frames",			"1"			},
-  { "custom_147.EDITOR",			"RocksCE.pcx"		},
+  { "custom_147.EDITOR",			"RocksCE.png"		},
   { "custom_147.EDITOR.xpos",			"18"			},
   { "custom_147.EDITOR.ypos",			"9"			},
 
-  { "custom_148",				"RocksCE.pcx"		},
+  { "custom_148",				"RocksCE.png"		},
   { "custom_148.xpos",				"3"			},
   { "custom_148.ypos",				"9"			},
   { "custom_148.frames",			"1"			},
-  { "custom_148.EDITOR",			"RocksCE.pcx"		},
+  { "custom_148.EDITOR",			"RocksCE.png"		},
   { "custom_148.EDITOR.xpos",			"19"			},
   { "custom_148.EDITOR.ypos",			"9"			},
 
-  { "custom_149",				"RocksCE.pcx"		},
+  { "custom_149",				"RocksCE.png"		},
   { "custom_149.xpos",				"4"			},
   { "custom_149.ypos",				"9"			},
   { "custom_149.frames",			"1"			},
-  { "custom_149.EDITOR",			"RocksCE.pcx"		},
+  { "custom_149.EDITOR",			"RocksCE.png"		},
   { "custom_149.EDITOR.xpos",			"20"			},
   { "custom_149.EDITOR.ypos",			"9"			},
 
-  { "custom_150",				"RocksCE.pcx"		},
+  { "custom_150",				"RocksCE.png"		},
   { "custom_150.xpos",				"5"			},
   { "custom_150.ypos",				"9"			},
   { "custom_150.frames",			"1"			},
-  { "custom_150.EDITOR",			"RocksCE.pcx"		},
+  { "custom_150.EDITOR",			"RocksCE.png"		},
   { "custom_150.EDITOR.xpos",			"21"			},
   { "custom_150.EDITOR.ypos",			"9"			},
 
-  { "custom_151",				"RocksCE.pcx"		},
+  { "custom_151",				"RocksCE.png"		},
   { "custom_151.xpos",				"6"			},
   { "custom_151.ypos",				"9"			},
   { "custom_151.frames",			"1"			},
-  { "custom_151.EDITOR",			"RocksCE.pcx"		},
+  { "custom_151.EDITOR",			"RocksCE.png"		},
   { "custom_151.EDITOR.xpos",			"22"			},
   { "custom_151.EDITOR.ypos",			"9"			},
 
-  { "custom_152",				"RocksCE.pcx"		},
+  { "custom_152",				"RocksCE.png"		},
   { "custom_152.xpos",				"7"			},
   { "custom_152.ypos",				"9"			},
   { "custom_152.frames",			"1"			},
-  { "custom_152.EDITOR",			"RocksCE.pcx"		},
+  { "custom_152.EDITOR",			"RocksCE.png"		},
   { "custom_152.EDITOR.xpos",			"23"			},
   { "custom_152.EDITOR.ypos",			"9"			},
 
-  { "custom_153",				"RocksCE.pcx"		},
+  { "custom_153",				"RocksCE.png"		},
   { "custom_153.xpos",				"8"			},
   { "custom_153.ypos",				"9"			},
   { "custom_153.frames",			"1"			},
-  { "custom_153.EDITOR",			"RocksCE.pcx"		},
+  { "custom_153.EDITOR",			"RocksCE.png"		},
   { "custom_153.EDITOR.xpos",			"24"			},
   { "custom_153.EDITOR.ypos",			"9"			},
 
-  { "custom_154",				"RocksCE.pcx"		},
+  { "custom_154",				"RocksCE.png"		},
   { "custom_154.xpos",				"9"			},
   { "custom_154.ypos",				"9"			},
   { "custom_154.frames",			"1"			},
-  { "custom_154.EDITOR",			"RocksCE.pcx"		},
+  { "custom_154.EDITOR",			"RocksCE.png"		},
   { "custom_154.EDITOR.xpos",			"25"			},
   { "custom_154.EDITOR.ypos",			"9"			},
 
-  { "custom_155",				"RocksCE.pcx"		},
+  { "custom_155",				"RocksCE.png"		},
   { "custom_155.xpos",				"10"			},
   { "custom_155.ypos",				"9"			},
   { "custom_155.frames",			"1"			},
-  { "custom_155.EDITOR",			"RocksCE.pcx"		},
+  { "custom_155.EDITOR",			"RocksCE.png"		},
   { "custom_155.EDITOR.xpos",			"26"			},
   { "custom_155.EDITOR.ypos",			"9"			},
 
-  { "custom_156",				"RocksCE.pcx"		},
+  { "custom_156",				"RocksCE.png"		},
   { "custom_156.xpos",				"11"			},
   { "custom_156.ypos",				"9"			},
   { "custom_156.frames",			"1"			},
-  { "custom_156.EDITOR",			"RocksCE.pcx"		},
+  { "custom_156.EDITOR",			"RocksCE.png"		},
   { "custom_156.EDITOR.xpos",			"27"			},
   { "custom_156.EDITOR.ypos",			"9"			},
 
-  { "custom_157",				"RocksCE.pcx"		},
+  { "custom_157",				"RocksCE.png"		},
   { "custom_157.xpos",				"12"			},
   { "custom_157.ypos",				"9"			},
   { "custom_157.frames",			"1"			},
-  { "custom_157.EDITOR",			"RocksCE.pcx"		},
+  { "custom_157.EDITOR",			"RocksCE.png"		},
   { "custom_157.EDITOR.xpos",			"28"			},
   { "custom_157.EDITOR.ypos",			"9"			},
 
-  { "custom_158",				"RocksCE.pcx"		},
+  { "custom_158",				"RocksCE.png"		},
   { "custom_158.xpos",				"13"			},
   { "custom_158.ypos",				"9"			},
   { "custom_158.frames",			"1"			},
-  { "custom_158.EDITOR",			"RocksCE.pcx"		},
+  { "custom_158.EDITOR",			"RocksCE.png"		},
   { "custom_158.EDITOR.xpos",			"29"			},
   { "custom_158.EDITOR.ypos",			"9"			},
 
-  { "custom_159",				"RocksCE.pcx"		},
+  { "custom_159",				"RocksCE.png"		},
   { "custom_159.xpos",				"14"			},
   { "custom_159.ypos",				"9"			},
   { "custom_159.frames",			"1"			},
-  { "custom_159.EDITOR",			"RocksCE.pcx"		},
+  { "custom_159.EDITOR",			"RocksCE.png"		},
   { "custom_159.EDITOR.xpos",			"30"			},
   { "custom_159.EDITOR.ypos",			"9"			},
 
-  { "custom_160",				"RocksCE.pcx"		},
+  { "custom_160",				"RocksCE.png"		},
   { "custom_160.xpos",				"15"			},
   { "custom_160.ypos",				"9"			},
   { "custom_160.frames",			"1"			},
-  { "custom_160.EDITOR",			"RocksCE.pcx"		},
+  { "custom_160.EDITOR",			"RocksCE.png"		},
   { "custom_160.EDITOR.xpos",			"31"			},
   { "custom_160.EDITOR.ypos",			"9"			},
 
-  { "custom_161",				"RocksCE.pcx"		},
+  { "custom_161",				"RocksCE.png"		},
   { "custom_161.xpos",				"0"			},
   { "custom_161.ypos",				"10"			},
   { "custom_161.frames",			"1"			},
-  { "custom_161.EDITOR",			"RocksCE.pcx"		},
+  { "custom_161.EDITOR",			"RocksCE.png"		},
   { "custom_161.EDITOR.xpos",			"16"			},
   { "custom_161.EDITOR.ypos",			"10"			},
 
-  { "custom_162",				"RocksCE.pcx"		},
+  { "custom_162",				"RocksCE.png"		},
   { "custom_162.xpos",				"1"			},
   { "custom_162.ypos",				"10"			},
   { "custom_162.frames",			"1"			},
-  { "custom_162.EDITOR",			"RocksCE.pcx"		},
+  { "custom_162.EDITOR",			"RocksCE.png"		},
   { "custom_162.EDITOR.xpos",			"17"			},
   { "custom_162.EDITOR.ypos",			"10"			},
 
-  { "custom_163",				"RocksCE.pcx"		},
+  { "custom_163",				"RocksCE.png"		},
   { "custom_163.xpos",				"2"			},
   { "custom_163.ypos",				"10"			},
   { "custom_163.frames",			"1"			},
-  { "custom_163.EDITOR",			"RocksCE.pcx"		},
+  { "custom_163.EDITOR",			"RocksCE.png"		},
   { "custom_163.EDITOR.xpos",			"18"			},
   { "custom_163.EDITOR.ypos",			"10"			},
 
-  { "custom_164",				"RocksCE.pcx"		},
+  { "custom_164",				"RocksCE.png"		},
   { "custom_164.xpos",				"3"			},
   { "custom_164.ypos",				"10"			},
   { "custom_164.frames",			"1"			},
-  { "custom_164.EDITOR",			"RocksCE.pcx"		},
+  { "custom_164.EDITOR",			"RocksCE.png"		},
   { "custom_164.EDITOR.xpos",			"19"			},
   { "custom_164.EDITOR.ypos",			"10"			},
 
-  { "custom_165",				"RocksCE.pcx"		},
+  { "custom_165",				"RocksCE.png"		},
   { "custom_165.xpos",				"4"			},
   { "custom_165.ypos",				"10"			},
   { "custom_165.frames",			"1"			},
-  { "custom_165.EDITOR",			"RocksCE.pcx"		},
+  { "custom_165.EDITOR",			"RocksCE.png"		},
   { "custom_165.EDITOR.xpos",			"20"			},
   { "custom_165.EDITOR.ypos",			"10"			},
 
-  { "custom_166",				"RocksCE.pcx"		},
+  { "custom_166",				"RocksCE.png"		},
   { "custom_166.xpos",				"5"			},
   { "custom_166.ypos",				"10"			},
   { "custom_166.frames",			"1"			},
-  { "custom_166.EDITOR",			"RocksCE.pcx"		},
+  { "custom_166.EDITOR",			"RocksCE.png"		},
   { "custom_166.EDITOR.xpos",			"21"			},
   { "custom_166.EDITOR.ypos",			"10"			},
 
-  { "custom_167",				"RocksCE.pcx"		},
+  { "custom_167",				"RocksCE.png"		},
   { "custom_167.xpos",				"6"			},
   { "custom_167.ypos",				"10"			},
   { "custom_167.frames",			"1"			},
-  { "custom_167.EDITOR",			"RocksCE.pcx"		},
+  { "custom_167.EDITOR",			"RocksCE.png"		},
   { "custom_167.EDITOR.xpos",			"22"			},
   { "custom_167.EDITOR.ypos",			"10"			},
 
-  { "custom_168",				"RocksCE.pcx"		},
+  { "custom_168",				"RocksCE.png"		},
   { "custom_168.xpos",				"7"			},
   { "custom_168.ypos",				"10"			},
   { "custom_168.frames",			"1"			},
-  { "custom_168.EDITOR",			"RocksCE.pcx"		},
+  { "custom_168.EDITOR",			"RocksCE.png"		},
   { "custom_168.EDITOR.xpos",			"23"			},
   { "custom_168.EDITOR.ypos",			"10"			},
 
-  { "custom_169",				"RocksCE.pcx"		},
+  { "custom_169",				"RocksCE.png"		},
   { "custom_169.xpos",				"8"			},
   { "custom_169.ypos",				"10"			},
   { "custom_169.frames",			"1"			},
-  { "custom_169.EDITOR",			"RocksCE.pcx"		},
+  { "custom_169.EDITOR",			"RocksCE.png"		},
   { "custom_169.EDITOR.xpos",			"24"			},
   { "custom_169.EDITOR.ypos",			"10"			},
 
-  { "custom_170",				"RocksCE.pcx"		},
+  { "custom_170",				"RocksCE.png"		},
   { "custom_170.xpos",				"9"			},
   { "custom_170.ypos",				"10"			},
   { "custom_170.frames",			"1"			},
-  { "custom_170.EDITOR",			"RocksCE.pcx"		},
+  { "custom_170.EDITOR",			"RocksCE.png"		},
   { "custom_170.EDITOR.xpos",			"25"			},
   { "custom_170.EDITOR.ypos",			"10"			},
 
-  { "custom_171",				"RocksCE.pcx"		},
+  { "custom_171",				"RocksCE.png"		},
   { "custom_171.xpos",				"10"			},
   { "custom_171.ypos",				"10"			},
   { "custom_171.frames",			"1"			},
-  { "custom_171.EDITOR",			"RocksCE.pcx"		},
+  { "custom_171.EDITOR",			"RocksCE.png"		},
   { "custom_171.EDITOR.xpos",			"26"			},
   { "custom_171.EDITOR.ypos",			"10"			},
 
-  { "custom_172",				"RocksCE.pcx"		},
+  { "custom_172",				"RocksCE.png"		},
   { "custom_172.xpos",				"11"			},
   { "custom_172.ypos",				"10"			},
   { "custom_172.frames",			"1"			},
-  { "custom_172.EDITOR",			"RocksCE.pcx"		},
+  { "custom_172.EDITOR",			"RocksCE.png"		},
   { "custom_172.EDITOR.xpos",			"27"			},
   { "custom_172.EDITOR.ypos",			"10"			},
 
-  { "custom_173",				"RocksCE.pcx"		},
+  { "custom_173",				"RocksCE.png"		},
   { "custom_173.xpos",				"12"			},
   { "custom_173.ypos",				"10"			},
   { "custom_173.frames",			"1"			},
-  { "custom_173.EDITOR",			"RocksCE.pcx"		},
+  { "custom_173.EDITOR",			"RocksCE.png"		},
   { "custom_173.EDITOR.xpos",			"28"			},
   { "custom_173.EDITOR.ypos",			"10"			},
 
-  { "custom_174",				"RocksCE.pcx"		},
+  { "custom_174",				"RocksCE.png"		},
   { "custom_174.xpos",				"13"			},
   { "custom_174.ypos",				"10"			},
   { "custom_174.frames",			"1"			},
-  { "custom_174.EDITOR",			"RocksCE.pcx"		},
+  { "custom_174.EDITOR",			"RocksCE.png"		},
   { "custom_174.EDITOR.xpos",			"29"			},
   { "custom_174.EDITOR.ypos",			"10"			},
 
-  { "custom_175",				"RocksCE.pcx"		},
+  { "custom_175",				"RocksCE.png"		},
   { "custom_175.xpos",				"14"			},
   { "custom_175.ypos",				"10"			},
   { "custom_175.frames",			"1"			},
-  { "custom_175.EDITOR",			"RocksCE.pcx"		},
+  { "custom_175.EDITOR",			"RocksCE.png"		},
   { "custom_175.EDITOR.xpos",			"30"			},
   { "custom_175.EDITOR.ypos",			"10"			},
 
-  { "custom_176",				"RocksCE.pcx"		},
+  { "custom_176",				"RocksCE.png"		},
   { "custom_176.xpos",				"15"			},
   { "custom_176.ypos",				"10"			},
   { "custom_176.frames",			"1"			},
-  { "custom_176.EDITOR",			"RocksCE.pcx"		},
+  { "custom_176.EDITOR",			"RocksCE.png"		},
   { "custom_176.EDITOR.xpos",			"31"			},
   { "custom_176.EDITOR.ypos",			"10"			},
 
-  { "custom_177",				"RocksCE.pcx"		},
+  { "custom_177",				"RocksCE.png"		},
   { "custom_177.xpos",				"0"			},
   { "custom_177.ypos",				"11"			},
   { "custom_177.frames",			"1"			},
-  { "custom_177.EDITOR",			"RocksCE.pcx"		},
+  { "custom_177.EDITOR",			"RocksCE.png"		},
   { "custom_177.EDITOR.xpos",			"16"			},
   { "custom_177.EDITOR.ypos",			"11"			},
 
-  { "custom_178",				"RocksCE.pcx"		},
+  { "custom_178",				"RocksCE.png"		},
   { "custom_178.xpos",				"1"			},
   { "custom_178.ypos",				"11"			},
   { "custom_178.frames",			"1"			},
-  { "custom_178.EDITOR",			"RocksCE.pcx"		},
+  { "custom_178.EDITOR",			"RocksCE.png"		},
   { "custom_178.EDITOR.xpos",			"17"			},
   { "custom_178.EDITOR.ypos",			"11"			},
 
-  { "custom_179",				"RocksCE.pcx"		},
+  { "custom_179",				"RocksCE.png"		},
   { "custom_179.xpos",				"2"			},
   { "custom_179.ypos",				"11"			},
   { "custom_179.frames",			"1"			},
-  { "custom_179.EDITOR",			"RocksCE.pcx"		},
+  { "custom_179.EDITOR",			"RocksCE.png"		},
   { "custom_179.EDITOR.xpos",			"18"			},
   { "custom_179.EDITOR.ypos",			"11"			},
 
-  { "custom_180",				"RocksCE.pcx"		},
+  { "custom_180",				"RocksCE.png"		},
   { "custom_180.xpos",				"3"			},
   { "custom_180.ypos",				"11"			},
   { "custom_180.frames",			"1"			},
-  { "custom_180.EDITOR",			"RocksCE.pcx"		},
+  { "custom_180.EDITOR",			"RocksCE.png"		},
   { "custom_180.EDITOR.xpos",			"19"			},
   { "custom_180.EDITOR.ypos",			"11"			},
 
-  { "custom_181",				"RocksCE.pcx"		},
+  { "custom_181",				"RocksCE.png"		},
   { "custom_181.xpos",				"4"			},
   { "custom_181.ypos",				"11"			},
   { "custom_181.frames",			"1"			},
-  { "custom_181.EDITOR",			"RocksCE.pcx"		},
+  { "custom_181.EDITOR",			"RocksCE.png"		},
   { "custom_181.EDITOR.xpos",			"20"			},
   { "custom_181.EDITOR.ypos",			"11"			},
 
-  { "custom_182",				"RocksCE.pcx"		},
+  { "custom_182",				"RocksCE.png"		},
   { "custom_182.xpos",				"5"			},
   { "custom_182.ypos",				"11"			},
   { "custom_182.frames",			"1"			},
-  { "custom_182.EDITOR",			"RocksCE.pcx"		},
+  { "custom_182.EDITOR",			"RocksCE.png"		},
   { "custom_182.EDITOR.xpos",			"21"			},
   { "custom_182.EDITOR.ypos",			"11"			},
 
-  { "custom_183",				"RocksCE.pcx"		},
+  { "custom_183",				"RocksCE.png"		},
   { "custom_183.xpos",				"6"			},
   { "custom_183.ypos",				"11"			},
   { "custom_183.frames",			"1"			},
-  { "custom_183.EDITOR",			"RocksCE.pcx"		},
+  { "custom_183.EDITOR",			"RocksCE.png"		},
   { "custom_183.EDITOR.xpos",			"22"			},
   { "custom_183.EDITOR.ypos",			"11"			},
 
-  { "custom_184",				"RocksCE.pcx"		},
+  { "custom_184",				"RocksCE.png"		},
   { "custom_184.xpos",				"7"			},
   { "custom_184.ypos",				"11"			},
   { "custom_184.frames",			"1"			},
-  { "custom_184.EDITOR",			"RocksCE.pcx"		},
+  { "custom_184.EDITOR",			"RocksCE.png"		},
   { "custom_184.EDITOR.xpos",			"23"			},
   { "custom_184.EDITOR.ypos",			"11"			},
 
-  { "custom_185",				"RocksCE.pcx"		},
+  { "custom_185",				"RocksCE.png"		},
   { "custom_185.xpos",				"8"			},
   { "custom_185.ypos",				"11"			},
   { "custom_185.frames",			"1"			},
-  { "custom_185.EDITOR",			"RocksCE.pcx"		},
+  { "custom_185.EDITOR",			"RocksCE.png"		},
   { "custom_185.EDITOR.xpos",			"24"			},
   { "custom_185.EDITOR.ypos",			"11"			},
 
-  { "custom_186",				"RocksCE.pcx"		},
+  { "custom_186",				"RocksCE.png"		},
   { "custom_186.xpos",				"9"			},
   { "custom_186.ypos",				"11"			},
   { "custom_186.frames",			"1"			},
-  { "custom_186.EDITOR",			"RocksCE.pcx"		},
+  { "custom_186.EDITOR",			"RocksCE.png"		},
   { "custom_186.EDITOR.xpos",			"25"			},
   { "custom_186.EDITOR.ypos",			"11"			},
 
-  { "custom_187",				"RocksCE.pcx"		},
+  { "custom_187",				"RocksCE.png"		},
   { "custom_187.xpos",				"10"			},
   { "custom_187.ypos",				"11"			},
   { "custom_187.frames",			"1"			},
-  { "custom_187.EDITOR",			"RocksCE.pcx"		},
+  { "custom_187.EDITOR",			"RocksCE.png"		},
   { "custom_187.EDITOR.xpos",			"26"			},
   { "custom_187.EDITOR.ypos",			"11"			},
 
-  { "custom_188",				"RocksCE.pcx"		},
+  { "custom_188",				"RocksCE.png"		},
   { "custom_188.xpos",				"11"			},
   { "custom_188.ypos",				"11"			},
   { "custom_188.frames",			"1"			},
-  { "custom_188.EDITOR",			"RocksCE.pcx"		},
+  { "custom_188.EDITOR",			"RocksCE.png"		},
   { "custom_188.EDITOR.xpos",			"27"			},
   { "custom_188.EDITOR.ypos",			"11"			},
 
-  { "custom_189",				"RocksCE.pcx"		},
+  { "custom_189",				"RocksCE.png"		},
   { "custom_189.xpos",				"12"			},
   { "custom_189.ypos",				"11"			},
   { "custom_189.frames",			"1"			},
-  { "custom_189.EDITOR",			"RocksCE.pcx"		},
+  { "custom_189.EDITOR",			"RocksCE.png"		},
   { "custom_189.EDITOR.xpos",			"28"			},
   { "custom_189.EDITOR.ypos",			"11"			},
 
-  { "custom_190",				"RocksCE.pcx"		},
+  { "custom_190",				"RocksCE.png"		},
   { "custom_190.xpos",				"13"			},
   { "custom_190.ypos",				"11"			},
   { "custom_190.frames",			"1"			},
-  { "custom_190.EDITOR",			"RocksCE.pcx"		},
+  { "custom_190.EDITOR",			"RocksCE.png"		},
   { "custom_190.EDITOR.xpos",			"29"			},
   { "custom_190.EDITOR.ypos",			"11"			},
 
-  { "custom_191",				"RocksCE.pcx"		},
+  { "custom_191",				"RocksCE.png"		},
   { "custom_191.xpos",				"14"			},
   { "custom_191.ypos",				"11"			},
   { "custom_191.frames",			"1"			},
-  { "custom_191.EDITOR",			"RocksCE.pcx"		},
+  { "custom_191.EDITOR",			"RocksCE.png"		},
   { "custom_191.EDITOR.xpos",			"30"			},
   { "custom_191.EDITOR.ypos",			"11"			},
 
-  { "custom_192",				"RocksCE.pcx"		},
+  { "custom_192",				"RocksCE.png"		},
   { "custom_192.xpos",				"15"			},
   { "custom_192.ypos",				"11"			},
   { "custom_192.frames",			"1"			},
-  { "custom_192.EDITOR",			"RocksCE.pcx"		},
+  { "custom_192.EDITOR",			"RocksCE.png"		},
   { "custom_192.EDITOR.xpos",			"31"			},
   { "custom_192.EDITOR.ypos",			"11"			},
 
-  { "custom_193",				"RocksCE.pcx"		},
+  { "custom_193",				"RocksCE.png"		},
   { "custom_193.xpos",				"0"			},
   { "custom_193.ypos",				"12"			},
   { "custom_193.frames",			"1"			},
-  { "custom_193.EDITOR",			"RocksCE.pcx"		},
+  { "custom_193.EDITOR",			"RocksCE.png"		},
   { "custom_193.EDITOR.xpos",			"16"			},
   { "custom_193.EDITOR.ypos",			"12"			},
 
-  { "custom_194",				"RocksCE.pcx"		},
+  { "custom_194",				"RocksCE.png"		},
   { "custom_194.xpos",				"1"			},
   { "custom_194.ypos",				"12"			},
   { "custom_194.frames",			"1"			},
-  { "custom_194.EDITOR",			"RocksCE.pcx"		},
+  { "custom_194.EDITOR",			"RocksCE.png"		},
   { "custom_194.EDITOR.xpos",			"17"			},
   { "custom_194.EDITOR.ypos",			"12"			},
 
-  { "custom_195",				"RocksCE.pcx"		},
+  { "custom_195",				"RocksCE.png"		},
   { "custom_195.xpos",				"2"			},
   { "custom_195.ypos",				"12"			},
   { "custom_195.frames",			"1"			},
-  { "custom_195.EDITOR",			"RocksCE.pcx"		},
+  { "custom_195.EDITOR",			"RocksCE.png"		},
   { "custom_195.EDITOR.xpos",			"18"			},
   { "custom_195.EDITOR.ypos",			"12"			},
 
-  { "custom_196",				"RocksCE.pcx"		},
+  { "custom_196",				"RocksCE.png"		},
   { "custom_196.xpos",				"3"			},
   { "custom_196.ypos",				"12"			},
   { "custom_196.frames",			"1"			},
-  { "custom_196.EDITOR",			"RocksCE.pcx"		},
+  { "custom_196.EDITOR",			"RocksCE.png"		},
   { "custom_196.EDITOR.xpos",			"19"			},
   { "custom_196.EDITOR.ypos",			"12"			},
 
-  { "custom_197",				"RocksCE.pcx"		},
+  { "custom_197",				"RocksCE.png"		},
   { "custom_197.xpos",				"4"			},
   { "custom_197.ypos",				"12"			},
   { "custom_197.frames",			"1"			},
-  { "custom_197.EDITOR",			"RocksCE.pcx"		},
+  { "custom_197.EDITOR",			"RocksCE.png"		},
   { "custom_197.EDITOR.xpos",			"20"			},
   { "custom_197.EDITOR.ypos",			"12"			},
 
-  { "custom_198",				"RocksCE.pcx"		},
+  { "custom_198",				"RocksCE.png"		},
   { "custom_198.xpos",				"5"			},
   { "custom_198.ypos",				"12"			},
   { "custom_198.frames",			"1"			},
-  { "custom_198.EDITOR",			"RocksCE.pcx"		},
+  { "custom_198.EDITOR",			"RocksCE.png"		},
   { "custom_198.EDITOR.xpos",			"21"			},
   { "custom_198.EDITOR.ypos",			"12"			},
 
-  { "custom_199",				"RocksCE.pcx"		},
+  { "custom_199",				"RocksCE.png"		},
   { "custom_199.xpos",				"6"			},
   { "custom_199.ypos",				"12"			},
   { "custom_199.frames",			"1"			},
-  { "custom_199.EDITOR",			"RocksCE.pcx"		},
+  { "custom_199.EDITOR",			"RocksCE.png"		},
   { "custom_199.EDITOR.xpos",			"22"			},
   { "custom_199.EDITOR.ypos",			"12"			},
 
-  { "custom_200",				"RocksCE.pcx"		},
+  { "custom_200",				"RocksCE.png"		},
   { "custom_200.xpos",				"7"			},
   { "custom_200.ypos",				"12"			},
   { "custom_200.frames",			"1"			},
-  { "custom_200.EDITOR",			"RocksCE.pcx"		},
+  { "custom_200.EDITOR",			"RocksCE.png"		},
   { "custom_200.EDITOR.xpos",			"23"			},
   { "custom_200.EDITOR.ypos",			"12"			},
 
-  { "custom_201",				"RocksCE.pcx"		},
+  { "custom_201",				"RocksCE.png"		},
   { "custom_201.xpos",				"8"			},
   { "custom_201.ypos",				"12"			},
   { "custom_201.frames",			"1"			},
-  { "custom_201.EDITOR",			"RocksCE.pcx"		},
+  { "custom_201.EDITOR",			"RocksCE.png"		},
   { "custom_201.EDITOR.xpos",			"24"			},
   { "custom_201.EDITOR.ypos",			"12"			},
 
-  { "custom_202",				"RocksCE.pcx"		},
+  { "custom_202",				"RocksCE.png"		},
   { "custom_202.xpos",				"9"			},
   { "custom_202.ypos",				"12"			},
   { "custom_202.frames",			"1"			},
-  { "custom_202.EDITOR",			"RocksCE.pcx"		},
+  { "custom_202.EDITOR",			"RocksCE.png"		},
   { "custom_202.EDITOR.xpos",			"25"			},
   { "custom_202.EDITOR.ypos",			"12"			},
 
-  { "custom_203",				"RocksCE.pcx"		},
+  { "custom_203",				"RocksCE.png"		},
   { "custom_203.xpos",				"10"			},
   { "custom_203.ypos",				"12"			},
   { "custom_203.frames",			"1"			},
-  { "custom_203.EDITOR",			"RocksCE.pcx"		},
+  { "custom_203.EDITOR",			"RocksCE.png"		},
   { "custom_203.EDITOR.xpos",			"26"			},
   { "custom_203.EDITOR.ypos",			"12"			},
 
-  { "custom_204",				"RocksCE.pcx"		},
+  { "custom_204",				"RocksCE.png"		},
   { "custom_204.xpos",				"11"			},
   { "custom_204.ypos",				"12"			},
   { "custom_204.frames",			"1"			},
-  { "custom_204.EDITOR",			"RocksCE.pcx"		},
+  { "custom_204.EDITOR",			"RocksCE.png"		},
   { "custom_204.EDITOR.xpos",			"27"			},
   { "custom_204.EDITOR.ypos",			"12"			},
 
-  { "custom_205",				"RocksCE.pcx"		},
+  { "custom_205",				"RocksCE.png"		},
   { "custom_205.xpos",				"12"			},
   { "custom_205.ypos",				"12"			},
   { "custom_205.frames",			"1"			},
-  { "custom_205.EDITOR",			"RocksCE.pcx"		},
+  { "custom_205.EDITOR",			"RocksCE.png"		},
   { "custom_205.EDITOR.xpos",			"28"			},
   { "custom_205.EDITOR.ypos",			"12"			},
 
-  { "custom_206",				"RocksCE.pcx"		},
+  { "custom_206",				"RocksCE.png"		},
   { "custom_206.xpos",				"13"			},
   { "custom_206.ypos",				"12"			},
   { "custom_206.frames",			"1"			},
-  { "custom_206.EDITOR",			"RocksCE.pcx"		},
+  { "custom_206.EDITOR",			"RocksCE.png"		},
   { "custom_206.EDITOR.xpos",			"29"			},
   { "custom_206.EDITOR.ypos",			"12"			},
 
-  { "custom_207",				"RocksCE.pcx"		},
+  { "custom_207",				"RocksCE.png"		},
   { "custom_207.xpos",				"14"			},
   { "custom_207.ypos",				"12"			},
   { "custom_207.frames",			"1"			},
-  { "custom_207.EDITOR",			"RocksCE.pcx"		},
+  { "custom_207.EDITOR",			"RocksCE.png"		},
   { "custom_207.EDITOR.xpos",			"30"			},
   { "custom_207.EDITOR.ypos",			"12"			},
 
-  { "custom_208",				"RocksCE.pcx"		},
+  { "custom_208",				"RocksCE.png"		},
   { "custom_208.xpos",				"15"			},
   { "custom_208.ypos",				"12"			},
   { "custom_208.frames",			"1"			},
-  { "custom_208.EDITOR",			"RocksCE.pcx"		},
+  { "custom_208.EDITOR",			"RocksCE.png"		},
   { "custom_208.EDITOR.xpos",			"31"			},
   { "custom_208.EDITOR.ypos",			"12"			},
 
-  { "custom_209",				"RocksCE.pcx"		},
+  { "custom_209",				"RocksCE.png"		},
   { "custom_209.xpos",				"0"			},
   { "custom_209.ypos",				"13"			},
   { "custom_209.frames",			"1"			},
-  { "custom_209.EDITOR",			"RocksCE.pcx"		},
+  { "custom_209.EDITOR",			"RocksCE.png"		},
   { "custom_209.EDITOR.xpos",			"16"			},
   { "custom_209.EDITOR.ypos",			"13"			},
 
-  { "custom_210",				"RocksCE.pcx"		},
+  { "custom_210",				"RocksCE.png"		},
   { "custom_210.xpos",				"1"			},
   { "custom_210.ypos",				"13"			},
   { "custom_210.frames",			"1"			},
-  { "custom_210.EDITOR",			"RocksCE.pcx"		},
+  { "custom_210.EDITOR",			"RocksCE.png"		},
   { "custom_210.EDITOR.xpos",			"17"			},
   { "custom_210.EDITOR.ypos",			"13"			},
 
-  { "custom_211",				"RocksCE.pcx"		},
+  { "custom_211",				"RocksCE.png"		},
   { "custom_211.xpos",				"2"			},
   { "custom_211.ypos",				"13"			},
   { "custom_211.frames",			"1"			},
-  { "custom_211.EDITOR",			"RocksCE.pcx"		},
+  { "custom_211.EDITOR",			"RocksCE.png"		},
   { "custom_211.EDITOR.xpos",			"18"			},
   { "custom_211.EDITOR.ypos",			"13"			},
 
-  { "custom_212",				"RocksCE.pcx"		},
+  { "custom_212",				"RocksCE.png"		},
   { "custom_212.xpos",				"3"			},
   { "custom_212.ypos",				"13"			},
   { "custom_212.frames",			"1"			},
-  { "custom_212.EDITOR",			"RocksCE.pcx"		},
+  { "custom_212.EDITOR",			"RocksCE.png"		},
   { "custom_212.EDITOR.xpos",			"19"			},
   { "custom_212.EDITOR.ypos",			"13"			},
 
-  { "custom_213",				"RocksCE.pcx"		},
+  { "custom_213",				"RocksCE.png"		},
   { "custom_213.xpos",				"4"			},
   { "custom_213.ypos",				"13"			},
   { "custom_213.frames",			"1"			},
-  { "custom_213.EDITOR",			"RocksCE.pcx"		},
+  { "custom_213.EDITOR",			"RocksCE.png"		},
   { "custom_213.EDITOR.xpos",			"20"			},
   { "custom_213.EDITOR.ypos",			"13"			},
 
-  { "custom_214",				"RocksCE.pcx"		},
+  { "custom_214",				"RocksCE.png"		},
   { "custom_214.xpos",				"5"			},
   { "custom_214.ypos",				"13"			},
   { "custom_214.frames",			"1"			},
-  { "custom_214.EDITOR",			"RocksCE.pcx"		},
+  { "custom_214.EDITOR",			"RocksCE.png"		},
   { "custom_214.EDITOR.xpos",			"21"			},
   { "custom_214.EDITOR.ypos",			"13"			},
 
-  { "custom_215",				"RocksCE.pcx"		},
+  { "custom_215",				"RocksCE.png"		},
   { "custom_215.xpos",				"6"			},
   { "custom_215.ypos",				"13"			},
   { "custom_215.frames",			"1"			},
-  { "custom_215.EDITOR",			"RocksCE.pcx"		},
+  { "custom_215.EDITOR",			"RocksCE.png"		},
   { "custom_215.EDITOR.xpos",			"22"			},
   { "custom_215.EDITOR.ypos",			"13"			},
 
-  { "custom_216",				"RocksCE.pcx"		},
+  { "custom_216",				"RocksCE.png"		},
   { "custom_216.xpos",				"7"			},
   { "custom_216.ypos",				"13"			},
   { "custom_216.frames",			"1"			},
-  { "custom_216.EDITOR",			"RocksCE.pcx"		},
+  { "custom_216.EDITOR",			"RocksCE.png"		},
   { "custom_216.EDITOR.xpos",			"23"			},
   { "custom_216.EDITOR.ypos",			"13"			},
 
-  { "custom_217",				"RocksCE.pcx"		},
+  { "custom_217",				"RocksCE.png"		},
   { "custom_217.xpos",				"8"			},
   { "custom_217.ypos",				"13"			},
   { "custom_217.frames",			"1"			},
-  { "custom_217.EDITOR",			"RocksCE.pcx"		},
+  { "custom_217.EDITOR",			"RocksCE.png"		},
   { "custom_217.EDITOR.xpos",			"24"			},
   { "custom_217.EDITOR.ypos",			"13"			},
 
-  { "custom_218",				"RocksCE.pcx"		},
+  { "custom_218",				"RocksCE.png"		},
   { "custom_218.xpos",				"9"			},
   { "custom_218.ypos",				"13"			},
   { "custom_218.frames",			"1"			},
-  { "custom_218.EDITOR",			"RocksCE.pcx"		},
+  { "custom_218.EDITOR",			"RocksCE.png"		},
   { "custom_218.EDITOR.xpos",			"25"			},
   { "custom_218.EDITOR.ypos",			"13"			},
 
-  { "custom_219",				"RocksCE.pcx"		},
+  { "custom_219",				"RocksCE.png"		},
   { "custom_219.xpos",				"10"			},
   { "custom_219.ypos",				"13"			},
   { "custom_219.frames",			"1"			},
-  { "custom_219.EDITOR",			"RocksCE.pcx"		},
+  { "custom_219.EDITOR",			"RocksCE.png"		},
   { "custom_219.EDITOR.xpos",			"26"			},
   { "custom_219.EDITOR.ypos",			"13"			},
 
-  { "custom_220",				"RocksCE.pcx"		},
+  { "custom_220",				"RocksCE.png"		},
   { "custom_220.xpos",				"11"			},
   { "custom_220.ypos",				"13"			},
   { "custom_220.frames",			"1"			},
-  { "custom_220.EDITOR",			"RocksCE.pcx"		},
+  { "custom_220.EDITOR",			"RocksCE.png"		},
   { "custom_220.EDITOR.xpos",			"27"			},
   { "custom_220.EDITOR.ypos",			"13"			},
 
-  { "custom_221",				"RocksCE.pcx"		},
+  { "custom_221",				"RocksCE.png"		},
   { "custom_221.xpos",				"12"			},
   { "custom_221.ypos",				"13"			},
   { "custom_221.frames",			"1"			},
-  { "custom_221.EDITOR",			"RocksCE.pcx"		},
+  { "custom_221.EDITOR",			"RocksCE.png"		},
   { "custom_221.EDITOR.xpos",			"28"			},
   { "custom_221.EDITOR.ypos",			"13"			},
 
-  { "custom_222",				"RocksCE.pcx"		},
+  { "custom_222",				"RocksCE.png"		},
   { "custom_222.xpos",				"13"			},
   { "custom_222.ypos",				"13"			},
   { "custom_222.frames",			"1"			},
-  { "custom_222.EDITOR",			"RocksCE.pcx"		},
+  { "custom_222.EDITOR",			"RocksCE.png"		},
   { "custom_222.EDITOR.xpos",			"29"			},
   { "custom_222.EDITOR.ypos",			"13"			},
 
-  { "custom_223",				"RocksCE.pcx"		},
+  { "custom_223",				"RocksCE.png"		},
   { "custom_223.xpos",				"14"			},
   { "custom_223.ypos",				"13"			},
   { "custom_223.frames",			"1"			},
-  { "custom_223.EDITOR",			"RocksCE.pcx"		},
+  { "custom_223.EDITOR",			"RocksCE.png"		},
   { "custom_223.EDITOR.xpos",			"30"			},
   { "custom_223.EDITOR.ypos",			"13"			},
 
-  { "custom_224",				"RocksCE.pcx"		},
+  { "custom_224",				"RocksCE.png"		},
   { "custom_224.xpos",				"15"			},
   { "custom_224.ypos",				"13"			},
   { "custom_224.frames",			"1"			},
-  { "custom_224.EDITOR",			"RocksCE.pcx"		},
+  { "custom_224.EDITOR",			"RocksCE.png"		},
   { "custom_224.EDITOR.xpos",			"31"			},
   { "custom_224.EDITOR.ypos",			"13"			},
 
-  { "custom_225",				"RocksCE.pcx"		},
+  { "custom_225",				"RocksCE.png"		},
   { "custom_225.xpos",				"0"			},
   { "custom_225.ypos",				"14"			},
   { "custom_225.frames",			"1"			},
-  { "custom_225.EDITOR",			"RocksCE.pcx"		},
+  { "custom_225.EDITOR",			"RocksCE.png"		},
   { "custom_225.EDITOR.xpos",			"16"			},
   { "custom_225.EDITOR.ypos",			"14"			},
 
-  { "custom_226",				"RocksCE.pcx"		},
+  { "custom_226",				"RocksCE.png"		},
   { "custom_226.xpos",				"1"			},
   { "custom_226.ypos",				"14"			},
   { "custom_226.frames",			"1"			},
-  { "custom_226.EDITOR",			"RocksCE.pcx"		},
+  { "custom_226.EDITOR",			"RocksCE.png"		},
   { "custom_226.EDITOR.xpos",			"17"			},
   { "custom_226.EDITOR.ypos",			"14"			},
 
-  { "custom_227",				"RocksCE.pcx"		},
+  { "custom_227",				"RocksCE.png"		},
   { "custom_227.xpos",				"2"			},
   { "custom_227.ypos",				"14"			},
   { "custom_227.frames",			"1"			},
-  { "custom_227.EDITOR",			"RocksCE.pcx"		},
+  { "custom_227.EDITOR",			"RocksCE.png"		},
   { "custom_227.EDITOR.xpos",			"18"			},
   { "custom_227.EDITOR.ypos",			"14"			},
 
-  { "custom_228",				"RocksCE.pcx"		},
+  { "custom_228",				"RocksCE.png"		},
   { "custom_228.xpos",				"3"			},
   { "custom_228.ypos",				"14"			},
   { "custom_228.frames",			"1"			},
-  { "custom_228.EDITOR",			"RocksCE.pcx"		},
+  { "custom_228.EDITOR",			"RocksCE.png"		},
   { "custom_228.EDITOR.xpos",			"19"			},
   { "custom_228.EDITOR.ypos",			"14"			},
 
-  { "custom_229",				"RocksCE.pcx"		},
+  { "custom_229",				"RocksCE.png"		},
   { "custom_229.xpos",				"4"			},
   { "custom_229.ypos",				"14"			},
   { "custom_229.frames",			"1"			},
-  { "custom_229.EDITOR",			"RocksCE.pcx"		},
+  { "custom_229.EDITOR",			"RocksCE.png"		},
   { "custom_229.EDITOR.xpos",			"20"			},
   { "custom_229.EDITOR.ypos",			"14"			},
 
-  { "custom_230",				"RocksCE.pcx"		},
+  { "custom_230",				"RocksCE.png"		},
   { "custom_230.xpos",				"5"			},
   { "custom_230.ypos",				"14"			},
   { "custom_230.frames",			"1"			},
-  { "custom_230.EDITOR",			"RocksCE.pcx"		},
+  { "custom_230.EDITOR",			"RocksCE.png"		},
   { "custom_230.EDITOR.xpos",			"21"			},
   { "custom_230.EDITOR.ypos",			"14"			},
 
-  { "custom_231",				"RocksCE.pcx"		},
+  { "custom_231",				"RocksCE.png"		},
   { "custom_231.xpos",				"6"			},
   { "custom_231.ypos",				"14"			},
   { "custom_231.frames",			"1"			},
-  { "custom_231.EDITOR",			"RocksCE.pcx"		},
+  { "custom_231.EDITOR",			"RocksCE.png"		},
   { "custom_231.EDITOR.xpos",			"22"			},
   { "custom_231.EDITOR.ypos",			"14"			},
 
-  { "custom_232",				"RocksCE.pcx"		},
+  { "custom_232",				"RocksCE.png"		},
   { "custom_232.xpos",				"7"			},
   { "custom_232.ypos",				"14"			},
   { "custom_232.frames",			"1"			},
-  { "custom_232.EDITOR",			"RocksCE.pcx"		},
+  { "custom_232.EDITOR",			"RocksCE.png"		},
   { "custom_232.EDITOR.xpos",			"23"			},
   { "custom_232.EDITOR.ypos",			"14"			},
 
-  { "custom_233",				"RocksCE.pcx"		},
+  { "custom_233",				"RocksCE.png"		},
   { "custom_233.xpos",				"8"			},
   { "custom_233.ypos",				"14"			},
   { "custom_233.frames",			"1"			},
-  { "custom_233.EDITOR",			"RocksCE.pcx"		},
+  { "custom_233.EDITOR",			"RocksCE.png"		},
   { "custom_233.EDITOR.xpos",			"24"			},
   { "custom_233.EDITOR.ypos",			"14"			},
 
-  { "custom_234",				"RocksCE.pcx"		},
+  { "custom_234",				"RocksCE.png"		},
   { "custom_234.xpos",				"9"			},
   { "custom_234.ypos",				"14"			},
   { "custom_234.frames",			"1"			},
-  { "custom_234.EDITOR",			"RocksCE.pcx"		},
+  { "custom_234.EDITOR",			"RocksCE.png"		},
   { "custom_234.EDITOR.xpos",			"25"			},
   { "custom_234.EDITOR.ypos",			"14"			},
 
-  { "custom_235",				"RocksCE.pcx"		},
+  { "custom_235",				"RocksCE.png"		},
   { "custom_235.xpos",				"10"			},
   { "custom_235.ypos",				"14"			},
   { "custom_235.frames",			"1"			},
-  { "custom_235.EDITOR",			"RocksCE.pcx"		},
+  { "custom_235.EDITOR",			"RocksCE.png"		},
   { "custom_235.EDITOR.xpos",			"26"			},
   { "custom_235.EDITOR.ypos",			"14"			},
 
-  { "custom_236",				"RocksCE.pcx"		},
+  { "custom_236",				"RocksCE.png"		},
   { "custom_236.xpos",				"11"			},
   { "custom_236.ypos",				"14"			},
   { "custom_236.frames",			"1"			},
-  { "custom_236.EDITOR",			"RocksCE.pcx"		},
+  { "custom_236.EDITOR",			"RocksCE.png"		},
   { "custom_236.EDITOR.xpos",			"27"			},
   { "custom_236.EDITOR.ypos",			"14"			},
 
-  { "custom_237",				"RocksCE.pcx"		},
+  { "custom_237",				"RocksCE.png"		},
   { "custom_237.xpos",				"12"			},
   { "custom_237.ypos",				"14"			},
   { "custom_237.frames",			"1"			},
-  { "custom_237.EDITOR",			"RocksCE.pcx"		},
+  { "custom_237.EDITOR",			"RocksCE.png"		},
   { "custom_237.EDITOR.xpos",			"28"			},
   { "custom_237.EDITOR.ypos",			"14"			},
 
-  { "custom_238",				"RocksCE.pcx"		},
+  { "custom_238",				"RocksCE.png"		},
   { "custom_238.xpos",				"13"			},
   { "custom_238.ypos",				"14"			},
   { "custom_238.frames",			"1"			},
-  { "custom_238.EDITOR",			"RocksCE.pcx"		},
+  { "custom_238.EDITOR",			"RocksCE.png"		},
   { "custom_238.EDITOR.xpos",			"29"			},
   { "custom_238.EDITOR.ypos",			"14"			},
 
-  { "custom_239",				"RocksCE.pcx"		},
+  { "custom_239",				"RocksCE.png"		},
   { "custom_239.xpos",				"14"			},
   { "custom_239.ypos",				"14"			},
   { "custom_239.frames",			"1"			},
-  { "custom_239.EDITOR",			"RocksCE.pcx"		},
+  { "custom_239.EDITOR",			"RocksCE.png"		},
   { "custom_239.EDITOR.xpos",			"30"			},
   { "custom_239.EDITOR.ypos",			"14"			},
 
-  { "custom_240",				"RocksCE.pcx"		},
+  { "custom_240",				"RocksCE.png"		},
   { "custom_240.xpos",				"15"			},
   { "custom_240.ypos",				"14"			},
   { "custom_240.frames",			"1"			},
-  { "custom_240.EDITOR",			"RocksCE.pcx"		},
+  { "custom_240.EDITOR",			"RocksCE.png"		},
   { "custom_240.EDITOR.xpos",			"31"			},
   { "custom_240.EDITOR.ypos",			"14"			},
 
-  { "custom_241",				"RocksCE.pcx"		},
+  { "custom_241",				"RocksCE.png"		},
   { "custom_241.xpos",				"0"			},
   { "custom_241.ypos",				"15"			},
   { "custom_241.frames",			"1"			},
-  { "custom_241.EDITOR",			"RocksCE.pcx"		},
+  { "custom_241.EDITOR",			"RocksCE.png"		},
   { "custom_241.EDITOR.xpos",			"16"			},
   { "custom_241.EDITOR.ypos",			"15"			},
 
-  { "custom_242",				"RocksCE.pcx"		},
+  { "custom_242",				"RocksCE.png"		},
   { "custom_242.xpos",				"1"			},
   { "custom_242.ypos",				"15"			},
   { "custom_242.frames",			"1"			},
-  { "custom_242.EDITOR",			"RocksCE.pcx"		},
+  { "custom_242.EDITOR",			"RocksCE.png"		},
   { "custom_242.EDITOR.xpos",			"17"			},
   { "custom_242.EDITOR.ypos",			"15"			},
 
-  { "custom_243",				"RocksCE.pcx"		},
+  { "custom_243",				"RocksCE.png"		},
   { "custom_243.xpos",				"2"			},
   { "custom_243.ypos",				"15"			},
   { "custom_243.frames",			"1"			},
-  { "custom_243.EDITOR",			"RocksCE.pcx"		},
+  { "custom_243.EDITOR",			"RocksCE.png"		},
   { "custom_243.EDITOR.xpos",			"18"			},
   { "custom_243.EDITOR.ypos",			"15"			},
 
-  { "custom_244",				"RocksCE.pcx"		},
+  { "custom_244",				"RocksCE.png"		},
   { "custom_244.xpos",				"3"			},
   { "custom_244.ypos",				"15"			},
   { "custom_244.frames",			"1"			},
-  { "custom_244.EDITOR",			"RocksCE.pcx"		},
+  { "custom_244.EDITOR",			"RocksCE.png"		},
   { "custom_244.EDITOR.xpos",			"19"			},
   { "custom_244.EDITOR.ypos",			"15"			},
 
-  { "custom_245",				"RocksCE.pcx"		},
+  { "custom_245",				"RocksCE.png"		},
   { "custom_245.xpos",				"4"			},
   { "custom_245.ypos",				"15"			},
   { "custom_245.frames",			"1"			},
-  { "custom_245.EDITOR",			"RocksCE.pcx"		},
+  { "custom_245.EDITOR",			"RocksCE.png"		},
   { "custom_245.EDITOR.xpos",			"20"			},
   { "custom_245.EDITOR.ypos",			"15"			},
 
-  { "custom_246",				"RocksCE.pcx"		},
+  { "custom_246",				"RocksCE.png"		},
   { "custom_246.xpos",				"5"			},
   { "custom_246.ypos",				"15"			},
   { "custom_246.frames",			"1"			},
-  { "custom_246.EDITOR",			"RocksCE.pcx"		},
+  { "custom_246.EDITOR",			"RocksCE.png"		},
   { "custom_246.EDITOR.xpos",			"21"			},
   { "custom_246.EDITOR.ypos",			"15"			},
 
-  { "custom_247",				"RocksCE.pcx"		},
+  { "custom_247",				"RocksCE.png"		},
   { "custom_247.xpos",				"6"			},
   { "custom_247.ypos",				"15"			},
   { "custom_247.frames",			"1"			},
-  { "custom_247.EDITOR",			"RocksCE.pcx"		},
+  { "custom_247.EDITOR",			"RocksCE.png"		},
   { "custom_247.EDITOR.xpos",			"22"			},
   { "custom_247.EDITOR.ypos",			"15"			},
 
-  { "custom_248",				"RocksCE.pcx"		},
+  { "custom_248",				"RocksCE.png"		},
   { "custom_248.xpos",				"7"			},
   { "custom_248.ypos",				"15"			},
   { "custom_248.frames",			"1"			},
-  { "custom_248.EDITOR",			"RocksCE.pcx"		},
+  { "custom_248.EDITOR",			"RocksCE.png"		},
   { "custom_248.EDITOR.xpos",			"23"			},
   { "custom_248.EDITOR.ypos",			"15"			},
 
-  { "custom_249",				"RocksCE.pcx"		},
+  { "custom_249",				"RocksCE.png"		},
   { "custom_249.xpos",				"8"			},
   { "custom_249.ypos",				"15"			},
   { "custom_249.frames",			"1"			},
-  { "custom_249.EDITOR",			"RocksCE.pcx"		},
+  { "custom_249.EDITOR",			"RocksCE.png"		},
   { "custom_249.EDITOR.xpos",			"24"			},
   { "custom_249.EDITOR.ypos",			"15"			},
 
-  { "custom_250",				"RocksCE.pcx"		},
+  { "custom_250",				"RocksCE.png"		},
   { "custom_250.xpos",				"9"			},
   { "custom_250.ypos",				"15"			},
   { "custom_250.frames",			"1"			},
-  { "custom_250.EDITOR",			"RocksCE.pcx"		},
+  { "custom_250.EDITOR",			"RocksCE.png"		},
   { "custom_250.EDITOR.xpos",			"25"			},
   { "custom_250.EDITOR.ypos",			"15"			},
 
-  { "custom_251",				"RocksCE.pcx"		},
+  { "custom_251",				"RocksCE.png"		},
   { "custom_251.xpos",				"10"			},
   { "custom_251.ypos",				"15"			},
   { "custom_251.frames",			"1"			},
-  { "custom_251.EDITOR",			"RocksCE.pcx"		},
+  { "custom_251.EDITOR",			"RocksCE.png"		},
   { "custom_251.EDITOR.xpos",			"26"			},
   { "custom_251.EDITOR.ypos",			"15"			},
 
-  { "custom_252",				"RocksCE.pcx"		},
+  { "custom_252",				"RocksCE.png"		},
   { "custom_252.xpos",				"11"			},
   { "custom_252.ypos",				"15"			},
   { "custom_252.frames",			"1"			},
-  { "custom_252.EDITOR",			"RocksCE.pcx"		},
+  { "custom_252.EDITOR",			"RocksCE.png"		},
   { "custom_252.EDITOR.xpos",			"27"			},
   { "custom_252.EDITOR.ypos",			"15"			},
 
-  { "custom_253",				"RocksCE.pcx"		},
+  { "custom_253",				"RocksCE.png"		},
   { "custom_253.xpos",				"12"			},
   { "custom_253.ypos",				"15"			},
   { "custom_253.frames",			"1"			},
-  { "custom_253.EDITOR",			"RocksCE.pcx"		},
+  { "custom_253.EDITOR",			"RocksCE.png"		},
   { "custom_253.EDITOR.xpos",			"28"			},
   { "custom_253.EDITOR.ypos",			"15"			},
 
-  { "custom_254",				"RocksCE.pcx"		},
+  { "custom_254",				"RocksCE.png"		},
   { "custom_254.xpos",				"13"			},
   { "custom_254.ypos",				"15"			},
   { "custom_254.frames",			"1"			},
-  { "custom_254.EDITOR",			"RocksCE.pcx"		},
+  { "custom_254.EDITOR",			"RocksCE.png"		},
   { "custom_254.EDITOR.xpos",			"29"			},
   { "custom_254.EDITOR.ypos",			"15"			},
 
-  { "custom_255",				"RocksCE.pcx"		},
+  { "custom_255",				"RocksCE.png"		},
   { "custom_255.xpos",				"14"			},
   { "custom_255.ypos",				"15"			},
   { "custom_255.frames",			"1"			},
-  { "custom_255.EDITOR",			"RocksCE.pcx"		},
+  { "custom_255.EDITOR",			"RocksCE.png"		},
   { "custom_255.EDITOR.xpos",			"30"			},
   { "custom_255.EDITOR.ypos",			"15"			},
 
-  { "custom_256",				"RocksCE.pcx"		},
+  { "custom_256",				"RocksCE.png"		},
   { "custom_256.xpos",				"15"			},
   { "custom_256.ypos",				"15"			},
   { "custom_256.frames",			"1"			},
-  { "custom_256.EDITOR",			"RocksCE.pcx"		},
+  { "custom_256.EDITOR",			"RocksCE.png"		},
   { "custom_256.EDITOR.xpos",			"31"			},
   { "custom_256.EDITOR.ypos",			"15"			},
 
diff --git a/src/conf_cus.h b/src/conf_cus.h
index dfc8e51..adb554d 100644
--- a/src/conf_cus.h
+++ b/src/conf_cus.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_cus.h                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                  Holger Schemel
+//                  info at artsoft.org
+//                  http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_cus.h
+// ============================================================================
 
 /* ----- this file was automatically generated -- do not edit by hand ----- */
 
diff --git a/src/conf_e2g.c b/src/conf_e2g.c
index 6b15419..f2e2390 100644
--- a/src/conf_e2g.c
+++ b/src/conf_e2g.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_e2g.c                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                  Holger Schemel
+//                  info at artsoft.org
+//                  http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_e2g.c
+// ============================================================================
 
 /* ----- this file was automatically generated -- do not edit by hand ----- */
 
diff --git a/src/conf_e2s.c b/src/conf_e2s.c
index bdcb6ac..8d12b5d 100644
--- a/src/conf_e2s.c
+++ b/src/conf_e2s.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_e2s.c                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                  Holger Schemel
+//                  info at artsoft.org
+//                  http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_e2s.c
+// ============================================================================
 
 /* ----- this file was automatically generated -- do not edit by hand ----- */
 
diff --git a/src/conf_esg.c b/src/conf_esg.c
index 9b97510..74e1b41 100644
--- a/src/conf_esg.c
+++ b/src/conf_esg.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_esg.c                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                  Holger Schemel
+//                  info at artsoft.org
+//                  http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_esg.c
+// ============================================================================
 
 /* ----- this file was automatically generated -- do not edit by hand ----- */
 
diff --git a/src/conf_fnt.c b/src/conf_fnt.c
index f23bd99..233a48a 100644
--- a/src/conf_fnt.c
+++ b/src/conf_fnt.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_fnt.c                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                  Holger Schemel
+//                  info at artsoft.org
+//                  http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_fnt.c
+// ============================================================================
 
 /* ----- this file was automatically generated -- do not edit by hand ----- */
 
@@ -84,6 +82,10 @@ font_to_graphic[] =
     IMG_FONT_TEXT_1_LEVELS
   },
   {
+    FONT_TEXT_1,				GFX_SPECIAL_ARG_LEVELNR,
+    IMG_FONT_TEXT_1_LEVELNR
+  },
+  {
     FONT_TEXT_1,				GFX_SPECIAL_ARG_SETUP,
     IMG_FONT_TEXT_1_SETUP
   },
@@ -120,6 +122,10 @@ font_to_graphic[] =
     IMG_FONT_TEXT_2_LEVELS
   },
   {
+    FONT_TEXT_2,				GFX_SPECIAL_ARG_LEVELNR,
+    IMG_FONT_TEXT_2_LEVELNR
+  },
+  {
     FONT_TEXT_2,				GFX_SPECIAL_ARG_SETUP,
     IMG_FONT_TEXT_2_SETUP
   },
@@ -144,6 +150,10 @@ font_to_graphic[] =
     IMG_FONT_TEXT_3_LEVELS
   },
   {
+    FONT_TEXT_3,				GFX_SPECIAL_ARG_LEVELNR,
+    IMG_FONT_TEXT_3_LEVELNR
+  },
+  {
     FONT_TEXT_3,				GFX_SPECIAL_ARG_SETUP,
     IMG_FONT_TEXT_3_SETUP
   },
@@ -172,6 +182,10 @@ font_to_graphic[] =
     IMG_FONT_TEXT_4_LEVELS
   },
   {
+    FONT_TEXT_4,				GFX_SPECIAL_ARG_LEVELNR,
+    IMG_FONT_TEXT_4_LEVELNR
+  },
+  {
     FONT_TEXT_4,				GFX_SPECIAL_ARG_SETUP,
     IMG_FONT_TEXT_4_SETUP
   },
@@ -200,6 +214,10 @@ font_to_graphic[] =
     IMG_FONT_ENVELOPE_4
   },
   {
+    FONT_REQUEST,				-1,
+    IMG_FONT_REQUEST
+  },
+  {
     FONT_INPUT_1,				-1,
     IMG_FONT_INPUT_1
   },
@@ -232,10 +250,18 @@ font_to_graphic[] =
     IMG_FONT_OPTION_OFF
   },
   {
+    FONT_OPTION_OFF_NARROW,			-1,
+    IMG_FONT_OPTION_OFF_NARROW
+  },
+  {
     FONT_OPTION_ON,				-1,
     IMG_FONT_OPTION_ON
   },
   {
+    FONT_OPTION_ON_NARROW,			-1,
+    IMG_FONT_OPTION_ON_NARROW
+  },
+  {
     FONT_VALUE_1,				-1,
     IMG_FONT_VALUE_1
   },
@@ -248,6 +274,10 @@ font_to_graphic[] =
     IMG_FONT_VALUE_OLD
   },
   {
+    FONT_VALUE_NARROW,				-1,
+    IMG_FONT_VALUE_NARROW
+  },
+  {
     FONT_LEVEL_NUMBER,				-1,
     IMG_FONT_LEVEL_NUMBER
   },
diff --git a/src/conf_g2m.c b/src/conf_g2m.c
index 207525e..5f9134b 100644
--- a/src/conf_g2m.c
+++ b/src/conf_g2m.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_g2m.c                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                  Holger Schemel
+//                  info at artsoft.org
+//                  http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_g2m.c
+// ============================================================================
 
 /* ----- this file was automatically generated -- do not edit by hand ----- */
 
@@ -47,6 +45,10 @@ gamemode_to_music[] =
     MUS_BACKGROUND_LEVELS
   },
   {
+    GFX_SPECIAL_ARG_LEVELNR,
+    MUS_BACKGROUND_LEVELNR
+  },
+  {
     GFX_SPECIAL_ARG_SCORES,
     MUS_BACKGROUND_SCORES
   },
diff --git a/src/conf_g2s.c b/src/conf_g2s.c
index ec9ea42..f98fed0 100644
--- a/src/conf_g2s.c
+++ b/src/conf_g2s.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_g2s.c                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                  Holger Schemel
+//                  info at artsoft.org
+//                  http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_g2s.c
+// ============================================================================
 
 /* ----- this file was automatically generated -- do not edit by hand ----- */
 
@@ -43,6 +41,10 @@ gamemode_to_sound[] =
     SND_BACKGROUND_LEVELS
   },
   {
+    GFX_SPECIAL_ARG_LEVELNR,
+    SND_BACKGROUND_LEVELNR
+  },
+  {
     GFX_SPECIAL_ARG_SCORES,
     SND_BACKGROUND_SCORES
   },
diff --git a/src/conf_gfx.c b/src/conf_gfx.c
index f8a5ae3..9693b1f 100644
--- a/src/conf_gfx.c
+++ b/src/conf_gfx.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_gfx.c                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_gfx.c
+// ============================================================================
 
 #include "libgame/libgame.h"
 #include "main.h"
@@ -47,18 +45,24 @@ struct ConfigTypeInfo image_config_suffix[] =
   { ".diggable_like",			ARG_UNDEFINED,	TYPE_ELEMENT	},
   { ".border_size",			ARG_UNDEFINED,	TYPE_INTEGER	},
   { ".step_offset",			"4",		TYPE_INTEGER	},
+  { ".step_xoffset",			ARG_UNDEFINED,	TYPE_INTEGER	},
+  { ".step_yoffset",			ARG_UNDEFINED,	TYPE_INTEGER	},
   { ".step_delay",			"1",		TYPE_INTEGER	},
   { ".direction",			ARG_UNDEFINED,	TYPE_STRING	},
   { ".position",			ARG_UNDEFINED,	TYPE_STRING	},
   { ".draw_xoffset",			"0",		TYPE_INTEGER	},
   { ".draw_yoffset",			"0",		TYPE_INTEGER	},
   { ".draw_masked",			"false",	TYPE_BOOLEAN	},
+  { ".draw_order",			ARG_UNDEFINED,	TYPE_INTEGER	},
+  { ".init_delay_fixed",		ARG_UNDEFINED,	TYPE_INTEGER	},
+  { ".init_delay_random",		ARG_UNDEFINED,	TYPE_INTEGER	},
   { ".anim_delay_fixed",		ARG_UNDEFINED,	TYPE_INTEGER	},
   { ".anim_delay_random",		ARG_UNDEFINED,	TYPE_INTEGER	},
   { ".post_delay_fixed",		ARG_UNDEFINED,	TYPE_INTEGER	},
   { ".post_delay_random",		ARG_UNDEFINED,	TYPE_INTEGER	},
   { ".name",				ARG_UNDEFINED,	TYPE_STRING	},
   { ".scale_up_factor",			ARG_UNDEFINED,	TYPE_INTEGER	},
+  { ".tile_size",			ARG_UNDEFINED,	TYPE_INTEGER	},
   { ".clone_from",			ARG_UNDEFINED,	TYPE_GRAPHIC	},
   { ".fade_mode",			ARG_UNDEFINED,	TYPE_INTEGER	},
   { ".fade_delay",			ARG_UNDEFINED,	TYPE_INTEGER	},
@@ -69,342 +73,350 @@ struct ConfigTypeInfo image_config_suffix[] =
   { ".sort_priority",			ARG_UNDEFINED,	TYPE_INTEGER	},
   { ".class",				ARG_UNDEFINED,	TYPE_STRING	},
   { ".style",				ARG_UNDEFINED,	TYPE_STRING	},
+  { ".active_xoffset",			"0",		TYPE_INTEGER	},
+  { ".active_yoffset",			"0",		TYPE_INTEGER	},
+  { ".pressed_xoffset",			"0",		TYPE_INTEGER	},
+  { ".pressed_yoffset",			"0",		TYPE_INTEGER	},
 
   { NULL,				NULL,		0		}
 };
 
 struct ConfigInfo image_config[] =
 {
+  // ==========================================================================
+  // image definitions for game elements (for in-game and editor graphics)
+  // ==========================================================================
+
   /* images for Boulder Dash style elements and actions */
 
-  { "bd_wall",					"RocksDC.pcx"		},
+  { "bd_wall",					"RocksDC.png"		},
   { "bd_wall.xpos",				"12"			},
   { "bd_wall.ypos",				"9"			},
   { "bd_wall.frames",				"1"			},
-  { "bd_wall.EDITOR",				"RocksDC.pcx"		},
+  { "bd_wall.EDITOR",				"RocksDC.png"		},
   { "bd_wall.EDITOR.xpos",			"14"			},
   { "bd_wall.EDITOR.ypos",			"13"			},
 
-  { "bd_rock",					"RocksDC.pcx"		},
+  { "bd_rock",					"RocksDC.png"		},
   { "bd_rock.xpos",				"12"			},
   { "bd_rock.ypos",				"10"			},
   { "bd_rock.frames",				"1"			},
-  { "bd_rock.EDITOR",				"RocksDC.pcx"		},
+  { "bd_rock.EDITOR",				"RocksDC.png"		},
   { "bd_rock.EDITOR.xpos",			"14"			},
   { "bd_rock.EDITOR.ypos",			"14"			},
-  { "bd_rock.moving.left",			"RocksDC.pcx"		},
+  { "bd_rock.moving.left",			"RocksDC.png"		},
   { "bd_rock.moving.left.xpos",			"12"			},
   { "bd_rock.moving.left.ypos",			"10"			},
   { "bd_rock.moving.left.frames",		"4"			},
   { "bd_rock.moving.left.delay",		"2"			},
   { "bd_rock.moving.left.anim_mode",		"reverse"		},
-  { "bd_rock.moving.right",			"RocksDC.pcx"		},
+  { "bd_rock.moving.right",			"RocksDC.png"		},
   { "bd_rock.moving.right.xpos",		"12"			},
   { "bd_rock.moving.right.ypos",		"10"			},
   { "bd_rock.moving.right.frames",		"4"			},
   { "bd_rock.moving.right.start_frame",		"1"			},
   { "bd_rock.moving.right.delay",		"2"			},
-  { "bd_rock.pushing.left",			"RocksDC.pcx"		},
+  { "bd_rock.pushing.left",			"RocksDC.png"		},
   { "bd_rock.pushing.left.xpos",		"12"			},
   { "bd_rock.pushing.left.ypos",		"10"			},
   { "bd_rock.pushing.left.frames",		"4"			},
   { "bd_rock.pushing.left.delay",		"2"			},
   { "bd_rock.pushing.left.anim_mode",		"reverse"		},
-  { "bd_rock.pushing.right",			"RocksDC.pcx"		},
+  { "bd_rock.pushing.right",			"RocksDC.png"		},
   { "bd_rock.pushing.right.xpos",		"12"			},
   { "bd_rock.pushing.right.ypos",		"10"			},
   { "bd_rock.pushing.right.frames",		"4"			},
   { "bd_rock.pushing.right.start_frame",	"1"			},
   { "bd_rock.pushing.right.delay",		"2"			},
 
-  { "bd_diamond",				"RocksElements.pcx"	},
+  { "bd_diamond",				"RocksElements.png"	},
   { "bd_diamond.xpos",				"0"			},
   { "bd_diamond.ypos",				"10"			},
   { "bd_diamond.frames",			"4"			},
   { "bd_diamond.delay",				"4"			},
   { "bd_diamond.anim_mode",			"reverse"		},
-  { "bd_diamond.moving",			"RocksElements.pcx"	},
+  { "bd_diamond.moving",			"RocksElements.png"	},
   { "bd_diamond.moving.xpos",			"3"			},
   { "bd_diamond.moving.ypos",			"10"			},
   { "bd_diamond.moving.frames",			"2"			},
   { "bd_diamond.moving.delay",			"4"			},
-  { "bd_diamond.falling",			"RocksElements.pcx"	},
+  { "bd_diamond.falling",			"RocksElements.png"	},
   { "bd_diamond.falling.xpos",			"3"			},
   { "bd_diamond.falling.ypos",			"10"			},
   { "bd_diamond.falling.frames",		"2"			},
   { "bd_diamond.falling.delay",			"4"			},
 
-  { "bd_magic_wall",				"RocksElements.pcx"	},
+  { "bd_magic_wall",				"RocksElements.png"	},
   { "bd_magic_wall.xpos",			"12"			},
   { "bd_magic_wall.ypos",			"10"			},
   { "bd_magic_wall.frames",			"1"			},
-  { "bd_magic_wall.active",			"RocksElements.pcx"	},
+  { "bd_magic_wall.active",			"RocksElements.png"	},
   { "bd_magic_wall.active.xpos",		"12"			},
   { "bd_magic_wall.active.ypos",		"10"			},
   { "bd_magic_wall.active.frames",		"4"			},
   { "bd_magic_wall.active.anim_mode",		"reverse"		},
   { "bd_magic_wall.active.delay",		"4"			},
   { "bd_magic_wall.active.global_sync",		"true"			},
-  { "bd_magic_wall.filling",			"RocksElements.pcx"	},
+  { "bd_magic_wall.filling",			"RocksElements.png"	},
   { "bd_magic_wall.filling.xpos",		"12"			},
   { "bd_magic_wall.filling.ypos",		"10"			},
   { "bd_magic_wall.filling.frames",		"4"			},
   { "bd_magic_wall.filling.anim_mode",		"reverse"		},
   { "bd_magic_wall.filling.delay",		"4"			},
   { "bd_magic_wall.filling.global_sync",	"true"			},
-  { "bd_magic_wall_full",			"RocksElements.pcx"	},
+  { "bd_magic_wall_full",			"RocksElements.png"	},
   { "bd_magic_wall_full.xpos",			"12"			},
   { "bd_magic_wall_full.ypos",			"10"			},
   { "bd_magic_wall_full.frames",		"4"			},
   { "bd_magic_wall_full.anim_mode",		"reverse"		},
   { "bd_magic_wall_full.delay",			"4"			},
   { "bd_magic_wall_full.global_sync",		"true"			},
-  { "bd_magic_wall.emptying",			"RocksElements.pcx"	},
+  { "bd_magic_wall.emptying",			"RocksElements.png"	},
   { "bd_magic_wall.emptying.xpos",		"12"			},
   { "bd_magic_wall.emptying.ypos",		"10"			},
   { "bd_magic_wall.emptying.frames",		"4"			},
   { "bd_magic_wall.emptying.anim_mode",		"reverse"		},
   { "bd_magic_wall.emptying.delay",		"4"			},
   { "bd_magic_wall.emptying.global_sync",	"true"			},
-  { "bd_magic_wall_dead",			"RocksElements.pcx"	},
+  { "bd_magic_wall_dead",			"RocksElements.png"	},
   { "bd_magic_wall_dead.xpos",			"12"			},
   { "bd_magic_wall_dead.ypos",			"10"			},
   { "bd_magic_wall_dead.frames",		"1"			},
 
-  { "bd_amoeba",				"RocksElements.pcx"	},
+  { "bd_amoeba",				"RocksElements.png"	},
   { "bd_amoeba.xpos",				"8"			},
   { "bd_amoeba.ypos",				"6"			},
   { "bd_amoeba.frames",				"4"			},
   { "bd_amoeba.delay",				"1000000"		},
   { "bd_amoeba.anim_mode",			"random"		},
-  { "bd_amoeba.EDITOR",				"RocksElements.pcx"	},
+  { "bd_amoeba.EDITOR",				"RocksElements.png"	},
   { "bd_amoeba.EDITOR.xpos",			"8"			},
   { "bd_amoeba.EDITOR.ypos",			"7"			},
 
-  { "bd_butterfly",				"RocksElements.pcx"	},
+  { "bd_butterfly",				"RocksElements.png"	},
   { "bd_butterfly.xpos",			"4"			},
   { "bd_butterfly.ypos",			"12"			},
   { "bd_butterfly.frames",			"2"			},
   { "bd_butterfly.anim_mode",			"pingpong"		},
   { "bd_butterfly.delay",			"4"			},
   { "bd_butterfly.global_sync",			"true"			},
-  { "bd_butterfly.right",			"RocksElements.pcx"	},
+  { "bd_butterfly.right",			"RocksElements.png"	},
   { "bd_butterfly.right.xpos",			"4"			},
   { "bd_butterfly.right.ypos",			"12"			},
   { "bd_butterfly.right.frames",		"2"			},
   { "bd_butterfly.right.anim_mode",		"pingpong"		},
   { "bd_butterfly.right.delay",			"4"			},
   { "bd_butterfly.right.global_sync",		"true"			},
-  { "bd_butterfly.right.EDITOR",		"RocksElements.pcx"	},
+  { "bd_butterfly.right.EDITOR",		"RocksElements.png"	},
   { "bd_butterfly.right.EDITOR.xpos",		"8"			},
   { "bd_butterfly.right.EDITOR.ypos",		"12"			},
-  { "bd_butterfly.up",				"RocksElements.pcx"	},
+  { "bd_butterfly.up",				"RocksElements.png"	},
   { "bd_butterfly.up.xpos",			"4"			},
   { "bd_butterfly.up.ypos",			"12"			},
   { "bd_butterfly.up.frames",			"2"			},
   { "bd_butterfly.up.anim_mode",		"pingpong"		},
   { "bd_butterfly.up.delay",			"4"			},
   { "bd_butterfly.up.global_sync",		"true"			},
-  { "bd_butterfly.up.EDITOR",			"RocksElements.pcx"	},
+  { "bd_butterfly.up.EDITOR",			"RocksElements.png"	},
   { "bd_butterfly.up.EDITOR.xpos",		"9"			},
   { "bd_butterfly.up.EDITOR.ypos",		"12"			},
-  { "bd_butterfly.left",			"RocksElements.pcx"	},
+  { "bd_butterfly.left",			"RocksElements.png"	},
   { "bd_butterfly.left.xpos",			"4"			},
   { "bd_butterfly.left.ypos",			"12"			},
   { "bd_butterfly.left.frames",			"2"			},
   { "bd_butterfly.left.anim_mode",		"pingpong"		},
   { "bd_butterfly.left.delay",			"4"			},
   { "bd_butterfly.left.global_sync",		"true"			},
-  { "bd_butterfly.left.EDITOR",			"RocksElements.pcx"	},
+  { "bd_butterfly.left.EDITOR",			"RocksElements.png"	},
   { "bd_butterfly.left.EDITOR.xpos",		"10"			},
   { "bd_butterfly.left.EDITOR.ypos",		"12"			},
-  { "bd_butterfly.down",			"RocksElements.pcx"	},
+  { "bd_butterfly.down",			"RocksElements.png"	},
   { "bd_butterfly.down.xpos",			"4"			},
   { "bd_butterfly.down.ypos",			"12"			},
   { "bd_butterfly.down.frames",			"2"			},
   { "bd_butterfly.down.anim_mode",		"pingpong"		},
   { "bd_butterfly.down.delay",			"4"			},
   { "bd_butterfly.down.global_sync",		"true"			},
-  { "bd_butterfly.down.EDITOR",			"RocksElements.pcx"	},
+  { "bd_butterfly.down.EDITOR",			"RocksElements.png"	},
   { "bd_butterfly.down.EDITOR.xpos",		"11"			},
   { "bd_butterfly.down.EDITOR.ypos",		"12"			},
 
-  { "bd_firefly",				"RocksElements.pcx"	},
+  { "bd_firefly",				"RocksElements.png"	},
   { "bd_firefly.xpos",				"6"			},
   { "bd_firefly.ypos",				"12"			},
   { "bd_firefly.frames",			"2"			},
   { "bd_firefly.anim_mode",			"pingpong"		},
   { "bd_firefly.delay",				"4"			},
   { "bd_firefly.global_sync",			"true"			},
-  { "bd_firefly.right",				"RocksElements.pcx"	},
+  { "bd_firefly.right",				"RocksElements.png"	},
   { "bd_firefly.right.xpos",			"6"			},
   { "bd_firefly.right.ypos",			"12"			},
   { "bd_firefly.right.frames",			"2"			},
   { "bd_firefly.right.anim_mode",		"pingpong"		},
   { "bd_firefly.right.delay",			"4"			},
   { "bd_firefly.right.global_sync",		"true"			},
-  { "bd_firefly.right.EDITOR",			"RocksElements.pcx"	},
+  { "bd_firefly.right.EDITOR",			"RocksElements.png"	},
   { "bd_firefly.right.EDITOR.xpos",		"12"			},
   { "bd_firefly.right.EDITOR.ypos",		"12"			},
-  { "bd_firefly.up",				"RocksElements.pcx"	},
+  { "bd_firefly.up",				"RocksElements.png"	},
   { "bd_firefly.up.xpos",			"6"			},
   { "bd_firefly.up.ypos",			"12"			},
   { "bd_firefly.up.frames",			"2"			},
   { "bd_firefly.up.anim_mode",			"pingpong"		},
   { "bd_firefly.up.delay",			"4"			},
   { "bd_firefly.up.global_sync",		"true"			},
-  { "bd_firefly.up.EDITOR",			"RocksElements.pcx"	},
+  { "bd_firefly.up.EDITOR",			"RocksElements.png"	},
   { "bd_firefly.up.EDITOR.xpos",		"13"			},
   { "bd_firefly.up.EDITOR.ypos",		"12"			},
-  { "bd_firefly.left",				"RocksElements.pcx"	},
+  { "bd_firefly.left",				"RocksElements.png"	},
   { "bd_firefly.left.xpos",			"6"			},
   { "bd_firefly.left.ypos",			"12"			},
   { "bd_firefly.left.frames",			"2"			},
   { "bd_firefly.left.anim_mode",		"pingpong"		},
   { "bd_firefly.left.delay",			"4"			},
   { "bd_firefly.left.global_sync",		"true"			},
-  { "bd_firefly.left.EDITOR",			"RocksElements.pcx"	},
+  { "bd_firefly.left.EDITOR",			"RocksElements.png"	},
   { "bd_firefly.left.EDITOR.xpos",		"14"			},
   { "bd_firefly.left.EDITOR.ypos",		"12"			},
-  { "bd_firefly.down",				"RocksElements.pcx"	},
+  { "bd_firefly.down",				"RocksElements.png"	},
   { "bd_firefly.down.xpos",			"6"			},
   { "bd_firefly.down.ypos",			"12"			},
   { "bd_firefly.down.frames",			"2"			},
   { "bd_firefly.down.anim_mode",		"pingpong"		},
   { "bd_firefly.down.delay",			"4"			},
   { "bd_firefly.down.global_sync",		"true"			},
-  { "bd_firefly.down.EDITOR",			"RocksElements.pcx"	},
+  { "bd_firefly.down.EDITOR",			"RocksElements.png"	},
   { "bd_firefly.down.EDITOR.xpos",		"15"			},
   { "bd_firefly.down.EDITOR.ypos",		"12"			},
 
   /* images for Supaplex style elements and actions */
 
-  { "[sp_default].exploding",			"RocksSP.pcx"		},
+  { "[sp_default].exploding",			"RocksSP.png"		},
   { "[sp_default].exploding.xpos",		"8"			},
   { "[sp_default].exploding.ypos",		"3"			},
   { "[sp_default].exploding.frames",		"8"			},
   { "[sp_default].exploding.delay",		"4"			},
   { "[sp_default].exploding.anim_mode",		"linear"		},
 
-  { "sp_zonk",					"RocksSP.pcx"		},
+  { "sp_zonk",					"RocksSP.png"		},
   { "sp_zonk.xpos",				"1"			},
   { "sp_zonk.ypos",				"0"			},
   { "sp_zonk.frames",				"1"			},
-  { "sp_zonk.moving.left",			"RocksSP.pcx"		},
+  { "sp_zonk.moving.left",			"RocksSP.png"		},
   { "sp_zonk.moving.left.xpos",			"0"			},
   { "sp_zonk.moving.left.ypos",			"6"			},
   { "sp_zonk.moving.left.frames",		"4"			},
   { "sp_zonk.moving.left.delay",		"1"			},
   { "sp_zonk.moving.left.anim_mode",		"reverse"		},
-  { "sp_zonk.moving.right",			"RocksSP.pcx"		},
+  { "sp_zonk.moving.right",			"RocksSP.png"		},
   { "sp_zonk.moving.right.xpos",		"0"			},
   { "sp_zonk.moving.right.ypos",		"6"			},
   { "sp_zonk.moving.right.frames",		"4"			},
   { "sp_zonk.moving.right.start_frame",		"1"			},
   { "sp_zonk.moving.right.delay",		"1"			},
-  { "sp_zonk.pushing.left",			"RocksSP.pcx"		},
+  { "sp_zonk.pushing.left",			"RocksSP.png"		},
   { "sp_zonk.pushing.left.xpos",		"0"			},
   { "sp_zonk.pushing.left.ypos",		"6"			},
   { "sp_zonk.pushing.left.frames",		"4"			},
   { "sp_zonk.pushing.left.delay",		"1"			},
   { "sp_zonk.pushing.left.anim_mode",		"reverse"		},
-  { "sp_zonk.pushing.right",			"RocksSP.pcx"		},
+  { "sp_zonk.pushing.right",			"RocksSP.png"		},
   { "sp_zonk.pushing.right.xpos",		"0"			},
   { "sp_zonk.pushing.right.ypos",		"6"			},
   { "sp_zonk.pushing.right.frames",		"4"			},
   { "sp_zonk.pushing.right.start_frame",	"1"			},
   { "sp_zonk.pushing.right.delay",		"1"			},
 
-  { "sp_base",					"RocksSP.pcx"		},
+  { "sp_base",					"RocksSP.png"		},
   { "sp_base.xpos",				"2"			},
   { "sp_base.ypos",				"0"			},
   { "sp_base.frames",				"1"			},
-  { "sp_base.digging",				"RocksSP.pcx"		},
+  { "sp_base.digging",				"RocksSP.png"		},
   { "sp_base.digging.xpos",			"2"			},
   { "sp_base.digging.ypos",			"0"			},
   { "sp_base.digging.frames",			"1"			},
   { "sp_base.digging.anim_mode",		"opaque_player"		},
-  { "sp_base.snapping",				"RocksSP.pcx"		},
+  { "sp_base.snapping",				"RocksSP.png"		},
   { "sp_base.snapping.xpos",			"8"			},
   { "sp_base.snapping.ypos",			"2"			},
   { "sp_base.snapping.frames",			"7"			},
   { "sp_base.snapping.anim_mode",		"linear"		},
 
-  { "sp_murphy",				"RocksSP.pcx"		},
+  { "sp_murphy",				"RocksSP.png"		},
   { "sp_murphy.xpos",				"3"			},
   { "sp_murphy.ypos",				"0"			},
   { "sp_murphy.frames",				"1"			},
-  { "sp_murphy.moving.left",			"RocksSP.pcx"		},
+  { "sp_murphy.moving.left",			"RocksSP.png"		},
   { "sp_murphy.moving.left.xpos",		"8"			},
   { "sp_murphy.moving.left.ypos",		"0"			},
   { "sp_murphy.moving.left.frames",		"3"			},
   { "sp_murphy.moving.left.anim_mode",		"pingpong"		},
   { "sp_murphy.moving.left.delay",		"2"			},
   { "sp_murphy.moving.left.start_frame",	"1"			},
-  { "sp_murphy.moving.right",			"RocksSP.pcx"		},
+  { "sp_murphy.moving.right",			"RocksSP.png"		},
   { "sp_murphy.moving.right.xpos",		"11"			},
   { "sp_murphy.moving.right.ypos",		"0"			},
   { "sp_murphy.moving.right.frames",		"3"			},
   { "sp_murphy.moving.right.anim_mode",		"pingpong"		},
   { "sp_murphy.moving.right.delay",		"2"			},
   { "sp_murphy.moving.right.start_frame",	"1"			},
-  { "sp_murphy.digging.left",			"RocksSP.pcx"		},
+  { "sp_murphy.digging.left",			"RocksSP.png"		},
   { "sp_murphy.digging.left.xpos",		"8"			},
   { "sp_murphy.digging.left.ypos",		"0"			},
   { "sp_murphy.digging.left.frames",		"3"			},
   { "sp_murphy.digging.left.anim_mode",		"pingpong"		},
   { "sp_murphy.digging.left.delay",		"2"			},
   { "sp_murphy.digging.left.start_frame",	"1"			},
-  { "sp_murphy.digging.right",			"RocksSP.pcx"		},
+  { "sp_murphy.digging.right",			"RocksSP.png"		},
   { "sp_murphy.digging.right.xpos",		"11"			},
   { "sp_murphy.digging.right.ypos",		"0"			},
   { "sp_murphy.digging.right.frames",		"3"			},
   { "sp_murphy.digging.right.anim_mode",	"pingpong"		},
   { "sp_murphy.digging.right.delay",		"2"			},
   { "sp_murphy.digging.right.start_frame",	"1"			},
-  { "sp_murphy.collecting.left",		"RocksSP.pcx"		},
+  { "sp_murphy.collecting.left",		"RocksSP.png"		},
   { "sp_murphy.collecting.left.xpos",		"8"			},
   { "sp_murphy.collecting.left.ypos",		"0"			},
   { "sp_murphy.collecting.left.frames",		"3"			},
   { "sp_murphy.collecting.left.anim_mode",	"pingpong"		},
   { "sp_murphy.collecting.left.delay",		"2"			},
   { "sp_murphy.collecting.left.start_frame",	"1"			},
-  { "sp_murphy.collecting.right",		"RocksSP.pcx"		},
+  { "sp_murphy.collecting.right",		"RocksSP.png"		},
   { "sp_murphy.collecting.right.xpos",		"11"			},
   { "sp_murphy.collecting.right.ypos",		"0"			},
   { "sp_murphy.collecting.right.frames",	"3"			},
   { "sp_murphy.collecting.right.anim_mode",	"pingpong"		},
   { "sp_murphy.collecting.right.delay",		"2"			},
   { "sp_murphy.collecting.right.start_frame",	"1"			},
-  { "sp_murphy.pushing.left",			"RocksSP.pcx"		},
+  { "sp_murphy.pushing.left",			"RocksSP.png"		},
   { "sp_murphy.pushing.left.xpos",		"11"			},
   { "sp_murphy.pushing.left.ypos",		"1"			},
   { "sp_murphy.pushing.left.frames",		"1"			},
-  { "sp_murphy.pushing.right",			"RocksSP.pcx"		},
+  { "sp_murphy.pushing.right",			"RocksSP.png"		},
   { "sp_murphy.pushing.right.xpos",		"10"			},
   { "sp_murphy.pushing.right.ypos",		"1"			},
   { "sp_murphy.pushing.right.frames",		"1"			},
-  { "sp_murphy.snapping.left",			"RocksSP.pcx"		},
+  { "sp_murphy.snapping.left",			"RocksSP.png"		},
   { "sp_murphy.snapping.left.xpos",		"9"			},
   { "sp_murphy.snapping.left.ypos",		"1"			},
   { "sp_murphy.snapping.left.frames",		"1"			},
-  { "sp_murphy.snapping.right",			"RocksSP.pcx"		},
+  { "sp_murphy.snapping.right",			"RocksSP.png"		},
   { "sp_murphy.snapping.right.xpos",		"8"			},
   { "sp_murphy.snapping.right.ypos",		"1"			},
   { "sp_murphy.snapping.right.frames",		"1"			},
-  { "sp_murphy.snapping.up",			"RocksSP.pcx"		},
+  { "sp_murphy.snapping.up",			"RocksSP.png"		},
   { "sp_murphy.snapping.up.xpos",		"14"			},
   { "sp_murphy.snapping.up.ypos",		"0"			},
   { "sp_murphy.snapping.up.frames",		"1"			},
-  { "sp_murphy.snapping.down",			"RocksSP.pcx"		},
+  { "sp_murphy.snapping.down",			"RocksSP.png"		},
   { "sp_murphy.snapping.down.xpos",		"15"			},
   { "sp_murphy.snapping.down.ypos",		"0"			},
   { "sp_murphy.snapping.down.frames",		"1"			},
-  { "sp_murphy.boring",				"RocksSP.pcx"		},
+  { "sp_murphy.boring",				"RocksSP.png"		},
   { "sp_murphy.boring.xpos",			"11"			},
   { "sp_murphy.boring.ypos",			"12"			},
   { "sp_murphy.boring.frames",			"1"			},
-  { "sp_murphy.boring[1]",			"RocksSP.pcx"		},
+  { "sp_murphy.boring[1]",			"RocksSP.png"		},
   { "sp_murphy.boring[1].xpos",			"0"			},
   { "sp_murphy.boring[1].ypos",			"12"			},
   { "sp_murphy.boring[1].frames",		"12"			},
@@ -414,327 +426,327 @@ struct ConfigInfo image_config[] =
   { "sp_murphy.boring[1].anim_delay_random",	"0"			},
   { "sp_murphy.boring[1].post_delay_fixed",	"500"			},
   { "sp_murphy.boring[1].post_delay_random",	"500"			},
-  { "sp_murphy.sleeping.left",			"RocksSP.pcx"		},
+  { "sp_murphy.sleeping.left",			"RocksSP.png"		},
   { "sp_murphy.sleeping.left.xpos",		"4"			},
   { "sp_murphy.sleeping.left.ypos",		"9"			},
   { "sp_murphy.sleeping.left.frames",		"3"			},
   { "sp_murphy.sleeping.left.delay",		"100"			},
   { "sp_murphy.sleeping.left.anim_mode",	"linear,reverse"	},
-  { "sp_murphy.sleeping.right",			"RocksSP.pcx"		},
+  { "sp_murphy.sleeping.right",			"RocksSP.png"		},
   { "sp_murphy.sleeping.right.xpos",		"13"			},
   { "sp_murphy.sleeping.right.ypos",		"12"			},
   { "sp_murphy.sleeping.right.frames",		"3"			},
   { "sp_murphy.sleeping.right.delay",		"100"			},
   { "sp_murphy.sleeping.right.anim_mode",	"linear"		},
-  { "sp_murphy.dropping",			"RocksSP.pcx"		},
+  { "sp_murphy.dropping",			"RocksSP.png"		},
   { "sp_murphy.dropping.xpos",			"11"			},
   { "sp_murphy.dropping.ypos",			"12"			},
   { "sp_murphy.dropping.frames",		"1"			},
-  { "sp_murphy.shrinking",			"RocksSP.pcx"		},
+  { "sp_murphy.shrinking",			"RocksSP.png"		},
   { "sp_murphy.shrinking.xpos",			"8"			},
   { "sp_murphy.shrinking.ypos",			"14"			},
   { "sp_murphy.shrinking.frames",		"8"			},
   { "sp_murphy.shrinking.delay",		"4"			},
   { "sp_murphy.shrinking.anim_mode",		"linear"		},
 
-  { "sp_murphy_clone",				"RocksSP.pcx"		},
+  { "sp_murphy_clone",				"RocksSP.png"		},
   { "sp_murphy_clone.xpos",			"3"			},
   { "sp_murphy_clone.ypos",			"0"			},
   { "sp_murphy_clone.frames",			"1"			},
 
-  { "sp_infotron",				"RocksSP.pcx"		},
+  { "sp_infotron",				"RocksSP.png"		},
   { "sp_infotron.xpos",				"4"			},
   { "sp_infotron.ypos",				"0"			},
   { "sp_infotron.frames",			"1"			},
-  { "sp_infotron.EDITOR",			"RocksSP.pcx"		},
+  { "sp_infotron.EDITOR",			"RocksSP.png"		},
   { "sp_infotron.EDITOR.xpos",			"8"			},
   { "sp_infotron.EDITOR.ypos",			"11"			},
-  { "sp_infotron.moving.left",			"RocksSP.pcx"		},
+  { "sp_infotron.moving.left",			"RocksSP.png"		},
   { "sp_infotron.moving.left.xpos",		"8"			},
   { "sp_infotron.moving.left.ypos",		"13"			},
   { "sp_infotron.moving.left.frames",		"8"			},
-  { "sp_infotron.moving.right",			"RocksSP.pcx"		},
+  { "sp_infotron.moving.right",			"RocksSP.png"		},
   { "sp_infotron.moving.right.xpos",		"8"			},
   { "sp_infotron.moving.right.ypos",		"13"			},
   { "sp_infotron.moving.right.frames",		"8"			},
   { "sp_infotron.moving.right.start_frame",	"6"			},
   { "sp_infotron.moving.right.anim_mode",	"reverse"		},
-  { "sp_infotron.collecting",			"RocksSP.pcx"		},
+  { "sp_infotron.collecting",			"RocksSP.png"		},
   { "sp_infotron.collecting.xpos",		"8"			},
   { "sp_infotron.collecting.ypos",		"7"			},
   { "sp_infotron.collecting.frames",		"8"			},
   { "sp_infotron.collecting.anim_mode",		"linear"		},
 
-  { "sp_chip_single",				"RocksSP.pcx"		},
+  { "sp_chip_single",				"RocksSP.png"		},
   { "sp_chip_single.xpos",			"5"			},
   { "sp_chip_single.ypos",			"0"			},
   { "sp_chip_single.frames",			"1"			},
-  { "sp_chip_left",				"RocksSP.pcx"		},
+  { "sp_chip_left",				"RocksSP.png"		},
   { "sp_chip_left.xpos",			"2"			},
   { "sp_chip_left.ypos",			"3"			},
   { "sp_chip_left.frames",			"1"			},
-  { "sp_chip_right",				"RocksSP.pcx"		},
+  { "sp_chip_right",				"RocksSP.png"		},
   { "sp_chip_right.xpos",			"3"			},
   { "sp_chip_right.ypos",			"3"			},
   { "sp_chip_right.frames",			"1"			},
-  { "sp_chip_top",				"RocksSP.pcx"		},
+  { "sp_chip_top",				"RocksSP.png"		},
   { "sp_chip_top.xpos",				"6"			},
   { "sp_chip_top.ypos",				"4"			},
   { "sp_chip_top.frames",			"1"			},
-  { "sp_chip_bottom",				"RocksSP.pcx"		},
+  { "sp_chip_bottom",				"RocksSP.png"		},
   { "sp_chip_bottom.xpos",			"7"			},
   { "sp_chip_bottom.ypos",			"4"			},
   { "sp_chip_bottom.frames",			"1"			},
 
-  { "sp_hardware_gray",				"RocksSP.pcx"		},
+  { "sp_hardware_gray",				"RocksSP.png"		},
   { "sp_hardware_gray.xpos",			"6"			},
   { "sp_hardware_gray.ypos",			"0"			},
   { "sp_hardware_gray.frames",			"1"			},
-  { "sp_hardware_green",			"RocksSP.pcx"		},
+  { "sp_hardware_green",			"RocksSP.png"		},
   { "sp_hardware_green.xpos",			"5"			},
   { "sp_hardware_green.ypos",			"3"			},
   { "sp_hardware_green.frames",			"1"			},
-  { "sp_hardware_blue",				"RocksSP.pcx"		},
+  { "sp_hardware_blue",				"RocksSP.png"		},
   { "sp_hardware_blue.xpos",			"6"			},
   { "sp_hardware_blue.ypos",			"3"			},
   { "sp_hardware_blue.frames",			"1"			},
-  { "sp_hardware_red",				"RocksSP.pcx"		},
+  { "sp_hardware_red",				"RocksSP.png"		},
   { "sp_hardware_red.xpos",			"7"			},
   { "sp_hardware_red.ypos",			"3"			},
   { "sp_hardware_red.frames",			"1"			},
-  { "sp_hardware_yellow",			"RocksSP.pcx"		},
+  { "sp_hardware_yellow",			"RocksSP.png"		},
   { "sp_hardware_yellow.xpos",			"0"			},
   { "sp_hardware_yellow.ypos",			"4"			},
   { "sp_hardware_yellow.frames",		"1"			},
 
-  { "sp_exit_closed",				"RocksSP.pcx"		},
+  { "sp_exit_closed",				"RocksSP.png"		},
   { "sp_exit_closed.xpos",			"7"			},
   { "sp_exit_closed.ypos",			"0"			},
   { "sp_exit_closed.frames",			"1"			},
-  { "sp_exit.opening",				"RocksSP.pcx"		},
+  { "sp_exit.opening",				"RocksSP.png"		},
   { "sp_exit.opening.xpos",			"7"			},
   { "sp_exit.opening.ypos",			"0"			},
   { "sp_exit.opening.frames",			"1"			},
-  { "sp_exit_open",				"RocksSP.pcx"		},
+  { "sp_exit_open",				"RocksSP.png"		},
   { "sp_exit_open.xpos",			"7"			},
   { "sp_exit_open.ypos",			"0"			},
   { "sp_exit_open.frames",			"1"			},
-  { "sp_exit.closing",				"RocksSP.pcx"		},
+  { "sp_exit.closing",				"RocksSP.png"		},
   { "sp_exit.closing.xpos",			"7"			},
   { "sp_exit.closing.ypos",			"0"			},
   { "sp_exit.closing.frames",			"1"			},
 
-  { "sp_disk_orange",				"RocksSP.pcx"		},
+  { "sp_disk_orange",				"RocksSP.png"		},
   { "sp_disk_orange.xpos",			"0"			},
   { "sp_disk_orange.ypos",			"1"			},
   { "sp_disk_orange.frames",			"1"			},
 
-  { "sp_disk_yellow",				"RocksSP.pcx"		},
+  { "sp_disk_yellow",				"RocksSP.png"		},
   { "sp_disk_yellow.xpos",			"2"			},
   { "sp_disk_yellow.ypos",			"2"			},
   { "sp_disk_yellow.frames",			"1"			},
 
-  { "sp_disk_red",				"RocksSP.pcx"		},
+  { "sp_disk_red",				"RocksSP.png"		},
   { "sp_disk_red.xpos",				"4"			},
   { "sp_disk_red.ypos",				"2"			},
   { "sp_disk_red.frames",			"1"			},
-  { "sp_disk_red.collecting",			"RocksSP.pcx"		},
+  { "sp_disk_red.collecting",			"RocksSP.png"		},
   { "sp_disk_red.collecting.xpos",		"9"			},
   { "sp_disk_red.collecting.ypos",		"5"			},
   { "sp_disk_red.collecting.frames",		"7"			},
   { "sp_disk_red.collecting.anim_mode",		"linear"		},
-  { "sp_disk_red.active",			"RocksSP.pcx"		},
+  { "sp_disk_red.active",			"RocksSP.png"		},
   { "sp_disk_red.active.xpos",			"4"			},
   { "sp_disk_red.active.ypos",			"2"			},
   { "sp_disk_red.active.frames",		"1"			},
 
-  { "sp_port_right",				"RocksSP.pcx"		},
+  { "sp_port_right",				"RocksSP.png"		},
   { "sp_port_right.xpos",			"1"			},
   { "sp_port_right.ypos",			"1"			},
   { "sp_port_right.frames",			"1"			},
-  { "sp_port_down",				"RocksSP.pcx"		},
+  { "sp_port_down",				"RocksSP.png"		},
   { "sp_port_down.xpos",			"2"			},
   { "sp_port_down.ypos",			"1"			},
   { "sp_port_down.frames",			"1"			},
-  { "sp_port_left",				"RocksSP.pcx"		},
+  { "sp_port_left",				"RocksSP.png"		},
   { "sp_port_left.xpos",			"3"			},
   { "sp_port_left.ypos",			"1"			},
   { "sp_port_left.frames",			"1"			},
-  { "sp_port_up",				"RocksSP.pcx"		},
+  { "sp_port_up",				"RocksSP.png"		},
   { "sp_port_up.xpos",				"4"			},
   { "sp_port_up.ypos",				"1"			},
   { "sp_port_up.frames",			"1"			},
-  { "sp_port_horizontal",			"RocksSP.pcx"		},
+  { "sp_port_horizontal",			"RocksSP.png"		},
   { "sp_port_horizontal.xpos",			"6"			},
   { "sp_port_horizontal.ypos",			"2"			},
   { "sp_port_horizontal.frames",		"1"			},
-  { "sp_port_vertical",				"RocksSP.pcx"		},
+  { "sp_port_vertical",				"RocksSP.png"		},
   { "sp_port_vertical.xpos",			"5"			},
   { "sp_port_vertical.ypos",			"2"			},
   { "sp_port_vertical.frames",			"1"			},
-  { "sp_port_any",				"RocksSP.pcx"		},
+  { "sp_port_any",				"RocksSP.png"		},
   { "sp_port_any.xpos",				"7"			},
   { "sp_port_any.ypos",				"2"			},
   { "sp_port_any.frames",			"1"			},
-  { "sp_gravity_port_right",			"RocksSP.pcx"		},
+  { "sp_gravity_port_right",			"RocksSP.png"		},
   { "sp_gravity_port_right.xpos",		"1"			},
   { "sp_gravity_port_right.ypos",		"1"			},
   { "sp_gravity_port_right.frames",		"1"			},
-  { "sp_gravity_port_right.EDITOR",		"RocksSP.pcx"		},
+  { "sp_gravity_port_right.EDITOR",		"RocksSP.png"		},
   { "sp_gravity_port_right.EDITOR.xpos",	"0"			},
   { "sp_gravity_port_right.EDITOR.ypos",	"14"			},
-  { "sp_gravity_port_down",			"RocksSP.pcx"		},
+  { "sp_gravity_port_down",			"RocksSP.png"		},
   { "sp_gravity_port_down.xpos",		"2"			},
   { "sp_gravity_port_down.ypos",		"1"			},
   { "sp_gravity_port_down.frames",		"1"			},
-  { "sp_gravity_port_down.EDITOR",		"RocksSP.pcx"		},
+  { "sp_gravity_port_down.EDITOR",		"RocksSP.png"		},
   { "sp_gravity_port_down.EDITOR.xpos",		"1"			},
   { "sp_gravity_port_down.EDITOR.ypos",		"14"			},
-  { "sp_gravity_port_left",			"RocksSP.pcx"		},
+  { "sp_gravity_port_left",			"RocksSP.png"		},
   { "sp_gravity_port_left.xpos",		"3"			},
   { "sp_gravity_port_left.ypos",		"1"			},
   { "sp_gravity_port_left.frames",		"1"			},
-  { "sp_gravity_port_left.EDITOR",		"RocksSP.pcx"		},
+  { "sp_gravity_port_left.EDITOR",		"RocksSP.png"		},
   { "sp_gravity_port_left.EDITOR.xpos",		"2"			},
   { "sp_gravity_port_left.EDITOR.ypos",		"14"			},
-  { "sp_gravity_port_up",			"RocksSP.pcx"		},
+  { "sp_gravity_port_up",			"RocksSP.png"		},
   { "sp_gravity_port_up.xpos",			"4"			},
   { "sp_gravity_port_up.ypos",			"1"			},
   { "sp_gravity_port_up.frames",		"1"			},
-  { "sp_gravity_port_up.EDITOR",		"RocksSP.pcx"		},
+  { "sp_gravity_port_up.EDITOR",		"RocksSP.png"		},
   { "sp_gravity_port_up.EDITOR.xpos",		"3"			},
   { "sp_gravity_port_up.EDITOR.ypos",		"14"			},
-  { "sp_gravity_on_port_right",			"RocksSP.pcx"		},
+  { "sp_gravity_on_port_right",			"RocksSP.png"		},
   { "sp_gravity_on_port_right.xpos",		"1"			},
   { "sp_gravity_on_port_right.ypos",		"1"			},
   { "sp_gravity_on_port_right.frames",		"1"			},
-  { "sp_gravity_on_port_right.EDITOR",		"RocksSP.pcx"		},
+  { "sp_gravity_on_port_right.EDITOR",		"RocksSP.png"		},
   { "sp_gravity_on_port_right.EDITOR.xpos",	"0"			},
   { "sp_gravity_on_port_right.EDITOR.ypos",	"13"			},
-  { "sp_gravity_on_port_down",			"RocksSP.pcx"		},
+  { "sp_gravity_on_port_down",			"RocksSP.png"		},
   { "sp_gravity_on_port_down.xpos",		"2"			},
   { "sp_gravity_on_port_down.ypos",		"1"			},
   { "sp_gravity_on_port_down.frames",		"1"			},
-  { "sp_gravity_on_port_down.EDITOR",		"RocksSP.pcx"		},
+  { "sp_gravity_on_port_down.EDITOR",		"RocksSP.png"		},
   { "sp_gravity_on_port_down.EDITOR.xpos",	"1"			},
   { "sp_gravity_on_port_down.EDITOR.ypos",	"13"			},
-  { "sp_gravity_on_port_left",			"RocksSP.pcx"		},
+  { "sp_gravity_on_port_left",			"RocksSP.png"		},
   { "sp_gravity_on_port_left.xpos",		"3"			},
   { "sp_gravity_on_port_left.ypos",		"1"			},
   { "sp_gravity_on_port_left.frames",		"1"			},
-  { "sp_gravity_on_port_left.EDITOR",		"RocksSP.pcx"		},
+  { "sp_gravity_on_port_left.EDITOR",		"RocksSP.png"		},
   { "sp_gravity_on_port_left.EDITOR.xpos",	"2"			},
   { "sp_gravity_on_port_left.EDITOR.ypos",	"13"			},
-  { "sp_gravity_on_port_up",			"RocksSP.pcx"		},
+  { "sp_gravity_on_port_up",			"RocksSP.png"		},
   { "sp_gravity_on_port_up.xpos",		"4"			},
   { "sp_gravity_on_port_up.ypos",		"1"			},
   { "sp_gravity_on_port_up.frames",		"1"			},
-  { "sp_gravity_on_port_up.EDITOR",		"RocksSP.pcx"		},
+  { "sp_gravity_on_port_up.EDITOR",		"RocksSP.png"		},
   { "sp_gravity_on_port_up.EDITOR.xpos",	"3"			},
   { "sp_gravity_on_port_up.EDITOR.ypos",	"13"			},
-  { "sp_gravity_off_port_right",		"RocksSP.pcx"		},
+  { "sp_gravity_off_port_right",		"RocksSP.png"		},
   { "sp_gravity_off_port_right.xpos",		"1"			},
   { "sp_gravity_off_port_right.ypos",		"1"			},
   { "sp_gravity_off_port_right.frames",		"1"			},
-  { "sp_gravity_off_port_right.EDITOR",		"RocksSP.pcx"		},
+  { "sp_gravity_off_port_right.EDITOR",		"RocksSP.png"		},
   { "sp_gravity_off_port_right.EDITOR.xpos",	"4"			},
   { "sp_gravity_off_port_right.EDITOR.ypos",	"13"			},
-  { "sp_gravity_off_port_down",			"RocksSP.pcx"		},
+  { "sp_gravity_off_port_down",			"RocksSP.png"		},
   { "sp_gravity_off_port_down.xpos",		"2"			},
   { "sp_gravity_off_port_down.ypos",		"1"			},
   { "sp_gravity_off_port_down.frames",		"1"			},
-  { "sp_gravity_off_port_down.EDITOR",		"RocksSP.pcx"		},
+  { "sp_gravity_off_port_down.EDITOR",		"RocksSP.png"		},
   { "sp_gravity_off_port_down.EDITOR.xpos",	"5"			},
   { "sp_gravity_off_port_down.EDITOR.ypos",	"13"			},
-  { "sp_gravity_off_port_left",			"RocksSP.pcx"		},
+  { "sp_gravity_off_port_left",			"RocksSP.png"		},
   { "sp_gravity_off_port_left.xpos",		"3"			},
   { "sp_gravity_off_port_left.ypos",		"1"			},
   { "sp_gravity_off_port_left.frames",		"1"			},
-  { "sp_gravity_off_port_left.EDITOR",		"RocksSP.pcx"		},
+  { "sp_gravity_off_port_left.EDITOR",		"RocksSP.png"		},
   { "sp_gravity_off_port_left.EDITOR.xpos",	"6"			},
   { "sp_gravity_off_port_left.EDITOR.ypos",	"13"			},
-  { "sp_gravity_off_port_up",			"RocksSP.pcx"		},
+  { "sp_gravity_off_port_up",			"RocksSP.png"		},
   { "sp_gravity_off_port_up.xpos",		"4"			},
   { "sp_gravity_off_port_up.ypos",		"1"			},
   { "sp_gravity_off_port_up.frames",		"1"			},
-  { "sp_gravity_off_port_up.EDITOR",		"RocksSP.pcx"		},
+  { "sp_gravity_off_port_up.EDITOR",		"RocksSP.png"		},
   { "sp_gravity_off_port_up.EDITOR.xpos",	"7"			},
   { "sp_gravity_off_port_up.EDITOR.ypos",	"13"			},
 
-  { "sp_sniksnak",				"RocksSP.pcx"		},
+  { "sp_sniksnak",				"RocksSP.png"		},
   { "sp_sniksnak.xpos",				"1"			},
   { "sp_sniksnak.ypos",				"2"			},
   { "sp_sniksnak.frames",			"1"			},
-  { "sp_sniksnak.left",				"RocksSP.pcx"		},
+  { "sp_sniksnak.left",				"RocksSP.png"		},
   { "sp_sniksnak.left.xpos",			"8"			},
   { "sp_sniksnak.left.ypos",			"8"			},
   { "sp_sniksnak.left.frames",			"4"			},
   { "sp_sniksnak.left.anim_mode",		"pingpong2"		},
-  { "sp_sniksnak.right",			"RocksSP.pcx"		},
+  { "sp_sniksnak.right",			"RocksSP.png"		},
   { "sp_sniksnak.right.xpos",			"12"			},
   { "sp_sniksnak.right.ypos",			"8"			},
   { "sp_sniksnak.right.frames",			"4"			},
   { "sp_sniksnak.right.anim_mode",		"pingpong2"		},
-  { "sp_sniksnak.up",				"RocksSP.pcx"		},
+  { "sp_sniksnak.up",				"RocksSP.png"		},
   { "sp_sniksnak.up.xpos",			"8"			},
   { "sp_sniksnak.up.ypos",			"9"			},
   { "sp_sniksnak.up.frames",			"4"			},
   { "sp_sniksnak.up.anim_mode",			"pingpong2"		},
-  { "sp_sniksnak.down",				"RocksSP.pcx"		},
+  { "sp_sniksnak.down",				"RocksSP.png"		},
   { "sp_sniksnak.down.xpos",			"12"			},
   { "sp_sniksnak.down.ypos",			"9"			},
   { "sp_sniksnak.down.frames",			"4"			},
   { "sp_sniksnak.down.anim_mode",		"pingpong2"		},
-  { "sp_sniksnak.turning_from_left.up",		"RocksSP.pcx"		},
+  { "sp_sniksnak.turning_from_left.up",		"RocksSP.png"		},
   { "sp_sniksnak.turning_from_left.up.xpos",	"12"			},
   { "sp_sniksnak.turning_from_left.up.ypos",	"6"			},
   { "sp_sniksnak.turning_from_left.up.frames",	"2"			},
   { "sp_sniksnak.turning_from_left.up.delay",	"4"			},
   { "sp_sniksnak.turning_from_left.up.offset",	"1408"			},
   { "sp_sniksnak.turning_from_left.up.anim_mode","linear"		},
-  { "sp_sniksnak.turning_from_left.down",	"RocksSP.pcx"		},
+  { "sp_sniksnak.turning_from_left.down",	"RocksSP.png"		},
   { "sp_sniksnak.turning_from_left.down.xpos",	"13"			},
   { "sp_sniksnak.turning_from_left.down.ypos",	"6"			},
   { "sp_sniksnak.turning_from_left.down.frames","2"			},
   { "sp_sniksnak.turning_from_left.down.delay",	"4"			},
   { "sp_sniksnak.turning_from_left.down.offset","1504"			},
   { "sp_sniksnak.turning_from_left.down.anim_mode","linear"		},
-  { "sp_sniksnak.turning_from_right.up",	"RocksSP.pcx"		},
+  { "sp_sniksnak.turning_from_right.up",	"RocksSP.png"		},
   { "sp_sniksnak.turning_from_right.up.xpos",	"15"			},
   { "sp_sniksnak.turning_from_right.up.ypos",	"6"			},
   { "sp_sniksnak.turning_from_right.up.frames",	"2"			},
   { "sp_sniksnak.turning_from_right.up.delay",	"4"			},
   { "sp_sniksnak.turning_from_right.up.offset",	"1312"			},
   { "sp_sniksnak.turning_from_right.up.anim_mode","linear"		},
-  { "sp_sniksnak.turning_from_right.down",	"RocksSP.pcx"		},
+  { "sp_sniksnak.turning_from_right.down",	"RocksSP.png"		},
   { "sp_sniksnak.turning_from_right.down.xpos",	"14"			},
   { "sp_sniksnak.turning_from_right.down.ypos",	"6"			},
   { "sp_sniksnak.turning_from_right.down.frames","2"			},
   { "sp_sniksnak.turning_from_right.down.delay","4"			},
   { "sp_sniksnak.turning_from_right.down.offset","1472"			},
   { "sp_sniksnak.turning_from_right.down.anim_mode","linear"		},
-  { "sp_sniksnak.turning_from_up.left",		"RocksSP.pcx"		},
+  { "sp_sniksnak.turning_from_up.left",		"RocksSP.png"		},
   { "sp_sniksnak.turning_from_up.left.xpos",	"12"			},
   { "sp_sniksnak.turning_from_up.left.ypos",	"6"			},
   { "sp_sniksnak.turning_from_up.left.frames",	"2"			},
   { "sp_sniksnak.turning_from_up.left.delay",	"4"			},
   { "sp_sniksnak.turning_from_up.left.offset",	"896"			},
   { "sp_sniksnak.turning_from_up.left.anim_mode","linear"		},
-  { "sp_sniksnak.turning_from_up.right",	"RocksSP.pcx"		},
+  { "sp_sniksnak.turning_from_up.right",	"RocksSP.png"		},
   { "sp_sniksnak.turning_from_up.right.xpos",	"15"			},
   { "sp_sniksnak.turning_from_up.right.ypos",	"6"			},
   { "sp_sniksnak.turning_from_up.right.frames",	"2"			},
   { "sp_sniksnak.turning_from_up.right.delay",	"4"			},
   { "sp_sniksnak.turning_from_up.right.offset",	"928"			},
   { "sp_sniksnak.turning_from_up.right.anim_mode","linear"		},
-  { "sp_sniksnak.turning_from_down.left",	"RocksSP.pcx"		},
+  { "sp_sniksnak.turning_from_down.left",	"RocksSP.png"		},
   { "sp_sniksnak.turning_from_down.left.xpos",	"13"			},
   { "sp_sniksnak.turning_from_down.left.ypos",	"6"			},
   { "sp_sniksnak.turning_from_down.left.frames","2"			},
   { "sp_sniksnak.turning_from_down.left.delay",	"4"			},
   { "sp_sniksnak.turning_from_down.left.offset","864"			},
   { "sp_sniksnak.turning_from_down.left.anim_mode","linear"		},
-  { "sp_sniksnak.turning_from_down.right",	"RocksSP.pcx"		},
+  { "sp_sniksnak.turning_from_down.right",	"RocksSP.png"		},
   { "sp_sniksnak.turning_from_down.right.xpos",	"14"			},
   { "sp_sniksnak.turning_from_down.right.ypos",	"6"			},
   { "sp_sniksnak.turning_from_down.right.frames","2"			},
@@ -742,966 +754,966 @@ struct ConfigInfo image_config[] =
   { "sp_sniksnak.turning_from_down.right.offset","960"			},
   { "sp_sniksnak.turning_from_down.right.anim_mode","linear"		},
 
-  { "sp_electron",				"RocksSP.pcx"		},
+  { "sp_electron",				"RocksSP.png"		},
   { "sp_electron.xpos",				"8"			},
   { "sp_electron.ypos",				"10"			},
   { "sp_electron.frames",			"8"			},
   { "sp_electron.delay",			"4"			},
   { "sp_electron.global_sync",			"true"			},
-  { "sp_electron.EDITOR",			"RocksSP.pcx"		},
+  { "sp_electron.EDITOR",			"RocksSP.png"		},
   { "sp_electron.EDITOR.xpos",			"10"			},
   { "sp_electron.EDITOR.ypos",			"11"			},
-  { "sp_electron.exploding",			"RocksSP.pcx"		},
+  { "sp_electron.exploding",			"RocksSP.png"		},
   { "sp_electron.exploding.xpos",		"8"			},
   { "sp_electron.exploding.ypos",		"4"			},
   { "sp_electron.exploding.frames",		"8"			},
   { "sp_electron.exploding.delay",		"4"			},
   { "sp_electron.exploding.anim_mode",		"linear"		},
 
-  { "sp_terminal",				"RocksSP.pcx"		},
+  { "sp_terminal",				"RocksSP.png"		},
   { "sp_terminal.xpos",				"0"			},
   { "sp_terminal.ypos",				"10"			},
   { "sp_terminal.frames",			"7"			},
   { "sp_terminal.delay",			"12"			},
-  { "sp_terminal.EDITOR",			"RocksSP.pcx"		},
+  { "sp_terminal.EDITOR",			"RocksSP.png"		},
   { "sp_terminal.EDITOR.xpos",			"9"			},
   { "sp_terminal.EDITOR.ypos",			"11"			},
-  { "sp_terminal.active",			"RocksSP.pcx"		},
+  { "sp_terminal.active",			"RocksSP.png"		},
   { "sp_terminal.active.xpos",			"0"			},
   { "sp_terminal.active.ypos",			"11"			},
   { "sp_terminal.active.frames",		"7"			},
   { "sp_terminal.active.delay",			"4"			},
 
-  { "sp_buggy_base",				"RocksSP.pcx"		},
+  { "sp_buggy_base",				"RocksSP.png"		},
   { "sp_buggy_base.xpos",			"1"			},
   { "sp_buggy_base.ypos",			"3"			},
   { "sp_buggy_base.frames",			"1"			},
-  { "sp_buggy_base.EDITOR",			"RocksSP.pcx"		},
+  { "sp_buggy_base.EDITOR",			"RocksSP.png"		},
   { "sp_buggy_base.EDITOR.xpos",		"9"			},
   { "sp_buggy_base.EDITOR.ypos",		"6"			},
-  { "sp_buggy_base.activating",			"RocksSP.pcx"		},
+  { "sp_buggy_base.activating",			"RocksSP.png"		},
   { "sp_buggy_base.activating.xpos",		"15"			},
   { "sp_buggy_base.activating.ypos",		"2"			},
   { "sp_buggy_base.activating.frames",		"1"			},
-  { "sp_buggy_base.active",			"RocksSP.pcx"		},
+  { "sp_buggy_base.active",			"RocksSP.png"		},
   { "sp_buggy_base.active.xpos",		"8"			},
   { "sp_buggy_base.active.ypos",		"6"			},
   { "sp_buggy_base.active.frames",		"4"			},
   { "sp_buggy_base.active.delay",		"4"			},
   { "sp_buggy_base.active.anim_mode",		"pingpong"		},
 
-  { "sp_hardware_base_1",			"RocksSP.pcx"		},
+  { "sp_hardware_base_1",			"RocksSP.png"		},
   { "sp_hardware_base_1.xpos",			"4"			},
   { "sp_hardware_base_1.ypos",			"3"			},
   { "sp_hardware_base_1.frames",		"1"			},
-  { "sp_hardware_base_2",			"RocksSP.pcx"		},
+  { "sp_hardware_base_2",			"RocksSP.png"		},
   { "sp_hardware_base_2.xpos",			"1"			},
   { "sp_hardware_base_2.ypos",			"4"			},
   { "sp_hardware_base_2.frames",		"1"			},
-  { "sp_hardware_base_3",			"RocksSP.pcx"		},
+  { "sp_hardware_base_3",			"RocksSP.png"		},
   { "sp_hardware_base_3.xpos",			"2"			},
   { "sp_hardware_base_3.ypos",			"4"			},
   { "sp_hardware_base_3.frames",		"1"			},
-  { "sp_hardware_base_4",			"RocksSP.pcx"		},
+  { "sp_hardware_base_4",			"RocksSP.png"		},
   { "sp_hardware_base_4.xpos",			"3"			},
   { "sp_hardware_base_4.ypos",			"4"			},
   { "sp_hardware_base_4.frames",		"1"			},
-  { "sp_hardware_base_5",			"RocksSP.pcx"		},
+  { "sp_hardware_base_5",			"RocksSP.png"		},
   { "sp_hardware_base_5.xpos",			"4"			},
   { "sp_hardware_base_5.ypos",			"4"			},
   { "sp_hardware_base_5.frames",		"1"			},
-  { "sp_hardware_base_6",			"RocksSP.pcx"		},
+  { "sp_hardware_base_6",			"RocksSP.png"		},
   { "sp_hardware_base_6.xpos",			"5"			},
   { "sp_hardware_base_6.ypos",			"4"			},
   { "sp_hardware_base_6.frames",		"1"			},
 
   /* images for Sokoban style elements and actions */
 
-  { "sokoban_object",				"RocksElements.pcx"	},
+  { "sokoban_object",				"RocksElements.png"	},
   { "sokoban_object.xpos",			"9"			},
   { "sokoban_object.ypos",			"7"			},
   { "sokoban_object.frames",			"1"			},
-  { "sokoban_object.EDITOR",			"RocksElements.pcx"	},
+  { "sokoban_object.EDITOR",			"RocksElements.png"	},
   { "sokoban_object.EDITOR.xpos",		"2"			},
   { "sokoban_object.EDITOR.ypos",		"14"			},
 
-  { "sokoban_field_empty",			"RocksElements.pcx"	},
+  { "sokoban_field_empty",			"RocksElements.png"	},
   { "sokoban_field_empty.xpos",			"10"			},
   { "sokoban_field_empty.ypos",			"7"			},
   { "sokoban_field_empty.frames",		"1"			},
 
-  { "sokoban_field_full",			"RocksElements.pcx"	},
+  { "sokoban_field_full",			"RocksElements.png"	},
   { "sokoban_field_full.xpos",			"11"			},
   { "sokoban_field_full.ypos",			"7"			},
   { "sokoban_field_full.frames",		"1"			},
 
-  { "sokoban_field_player",			"RocksHeroes.pcx"	},
+  { "sokoban_field_player",			"RocksHeroes.png"	},
   { "sokoban_field_player.xpos",		"0"			},
   { "sokoban_field_player.ypos",		"15"			},
   { "sokoban_field_player.frames",		"1"			},
-  { "sokoban_field_player.EDITOR",		"RocksHeroes.pcx"	},
+  { "sokoban_field_player.EDITOR",		"RocksHeroes.png"	},
   { "sokoban_field_player.EDITOR.xpos",		"1"			},
   { "sokoban_field_player.EDITOR.ypos",		"15"			},
 
   /* images for Emerald Mine style elements and actions */
 
-  { "empty_space",				"RocksSP.pcx"		},
+  { "empty_space",				"RocksSP.png"		},
   { "empty_space.xpos",				"0"			},
   { "empty_space.ypos",				"0"			},
   { "empty_space.frames",			"1"			},
 
-  { "sand",					"RocksElements.pcx"	},
+  { "sand",					"RocksElements.png"	},
   { "sand.xpos",				"0"			},
   { "sand.ypos",				"0"			},
   { "sand.frames",				"1"			},
-  { "sand.CRUMBLED",				"RocksElements.pcx"	},
+  { "sand.CRUMBLED",				"RocksElements.png"	},
   { "sand.CRUMBLED.xpos",			"1"			},
   { "sand.CRUMBLED.ypos",			"0"			},
   { "sand.CRUMBLED.frames",			"1"			},
-  { "sand.digging.left",			"RocksMore.pcx"		},
+  { "sand.digging.left",			"RocksMore.png"		},
   { "sand.digging.left.xpos",			"6"			},
   { "sand.digging.left.ypos",			"3"			},
   { "sand.digging.left.frames",			"3"			},
   { "sand.digging.left.delay",			"2"			},
   { "sand.digging.left.anim_mode",		"linear"		},
-  { "sand.digging.right",			"RocksMore.pcx"		},
+  { "sand.digging.right",			"RocksMore.png"		},
   { "sand.digging.right.xpos",			"9"			},
   { "sand.digging.right.ypos",			"3"			},
   { "sand.digging.right.frames",		"3"			},
   { "sand.digging.right.delay",			"2"			},
   { "sand.digging.right.anim_mode",		"linear"		},
-  { "sand.digging.up",				"RocksMore.pcx"		},
+  { "sand.digging.up",				"RocksMore.png"		},
   { "sand.digging.up.xpos",			"0"			},
   { "sand.digging.up.ypos",			"3"			},
   { "sand.digging.up.frames",			"3"			},
   { "sand.digging.up.delay",			"2"			},
   { "sand.digging.up.anim_mode",		"linear"		},
-  { "sand.digging.down",			"RocksMore.pcx"		},
+  { "sand.digging.down",			"RocksMore.png"		},
   { "sand.digging.down.xpos",			"3"			},
   { "sand.digging.down.ypos",			"3"			},
   { "sand.digging.down.frames",			"3"			},
   { "sand.digging.down.delay",			"2"			},
   { "sand.digging.down.anim_mode",		"linear"		},
-  { "sand.digging.left.CRUMBLED",		"RocksMore.pcx"		},
+  { "sand.digging.left.CRUMBLED",		"RocksMore.png"		},
   { "sand.digging.left.CRUMBLED.xpos",		"6"			},
   { "sand.digging.left.CRUMBLED.ypos",		"0"			},
   { "sand.digging.left.CRUMBLED.frames",	"3"			},
   { "sand.digging.left.CRUMBLED.delay",		"2"			},
   { "sand.digging.left.CRUMBLED.anim_mode",	"linear"		},
-  { "sand.digging.right.CRUMBLED",		"RocksMore.pcx"		},
+  { "sand.digging.right.CRUMBLED",		"RocksMore.png"		},
   { "sand.digging.right.CRUMBLED.xpos",		"9"			},
   { "sand.digging.right.CRUMBLED.ypos",		"0"			},
   { "sand.digging.right.CRUMBLED.frames",	"3"			},
   { "sand.digging.right.CRUMBLED.delay",	"2"			},
   { "sand.digging.right.CRUMBLED.anim_mode",	"linear"		},
-  { "sand.digging.up.CRUMBLED",			"RocksMore.pcx"		},
+  { "sand.digging.up.CRUMBLED",			"RocksMore.png"		},
   { "sand.digging.up.CRUMBLED.xpos",		"0"			},
   { "sand.digging.up.CRUMBLED.ypos",		"0"			},
   { "sand.digging.up.CRUMBLED.frames",		"3"			},
   { "sand.digging.up.CRUMBLED.delay",		"2"			},
   { "sand.digging.up.CRUMBLED.anim_mode",	"linear"		},
-  { "sand.digging.down.CRUMBLED",		"RocksMore.pcx"		},
+  { "sand.digging.down.CRUMBLED",		"RocksMore.png"		},
   { "sand.digging.down.CRUMBLED.xpos",		"3"			},
   { "sand.digging.down.CRUMBLED.ypos",		"0"			},
   { "sand.digging.down.CRUMBLED.frames",	"3"			},
   { "sand.digging.down.CRUMBLED.delay",		"2"			},
   { "sand.digging.down.CRUMBLED.anim_mode",	"linear"		},
 
-  { "wall",					"RocksElements.pcx"	},
+  { "wall",					"RocksElements.png"	},
   { "wall.xpos",				"5"			},
   { "wall.ypos",				"0"			},
   { "wall.frames",				"1"			},
 
-  { "wall_slippery",				"RocksElements.pcx"	},
+  { "wall_slippery",				"RocksElements.png"	},
   { "wall_slippery.xpos",			"6"			},
   { "wall_slippery.ypos",			"0"			},
   { "wall_slippery.frames",			"1"			},
 
-  { "steelwall",				"RocksElements.pcx"	},
+  { "steelwall",				"RocksElements.png"	},
   { "steelwall.xpos",				"4"			},
   { "steelwall.ypos",				"0"			},
   { "steelwall.frames",				"1"			},
 
-  { "rock",					"RocksElements.pcx"	},
+  { "rock",					"RocksElements.png"	},
   { "rock.xpos",				"12"			},
   { "rock.ypos",				"0"			},
   { "rock.frames",				"1"			},
-  { "rock.moving.left",				"RocksElements.pcx"	},
+  { "rock.moving.left",				"RocksElements.png"	},
   { "rock.moving.left.xpos",			"12"			},
   { "rock.moving.left.ypos",			"0"			},
   { "rock.moving.left.frames",			"4"			},
   { "rock.moving.left.delay",			"2"			},
   { "rock.moving.left.anim_mode",		"reverse"		},
-  { "rock.moving.right",			"RocksElements.pcx"	},
+  { "rock.moving.right",			"RocksElements.png"	},
   { "rock.moving.right.xpos",			"12"			},
   { "rock.moving.right.ypos",			"0"			},
   { "rock.moving.right.frames",			"4"			},
   { "rock.moving.right.start_frame",		"1"			},
   { "rock.moving.right.delay",			"2"			},
-  { "rock.pushing.left",			"RocksElements.pcx"	},
+  { "rock.pushing.left",			"RocksElements.png"	},
   { "rock.pushing.left.xpos",			"12"			},
   { "rock.pushing.left.ypos",			"0"			},
   { "rock.pushing.left.frames",			"4"			},
   { "rock.pushing.left.delay",			"2"			},
   { "rock.pushing.left.anim_mode",		"reverse"		},
-  { "rock.pushing.right",			"RocksElements.pcx"	},
+  { "rock.pushing.right",			"RocksElements.png"	},
   { "rock.pushing.right.xpos",			"12"			},
   { "rock.pushing.right.ypos",			"0"			},
   { "rock.pushing.right.frames",		"4"			},
   { "rock.pushing.right.start_frame",		"1"			},
   { "rock.pushing.right.delay",			"2"			},
 
-  { "emerald",					"RocksElements.pcx"	},
+  { "emerald",					"RocksElements.png"	},
   { "emerald.xpos",				"8"			},
   { "emerald.ypos",				"0"			},
   { "emerald.frames",				"1"			},
-  { "emerald.moving",				"RocksElements.pcx"	},
+  { "emerald.moving",				"RocksElements.png"	},
   { "emerald.moving.xpos",			"8"			},
   { "emerald.moving.ypos",			"0"			},
   { "emerald.moving.frames",			"2"			},
   { "emerald.moving.delay",			"4"			},
-  { "emerald.falling",				"RocksElements.pcx"	},
+  { "emerald.falling",				"RocksElements.png"	},
   { "emerald.falling.xpos",			"8"			},
   { "emerald.falling.ypos",			"0"			},
   { "emerald.falling.frames",			"2"			},
   { "emerald.falling.delay",			"4"			},
-  { "emerald.collecting",			"RocksMore.pcx"		},
+  { "emerald.collecting",			"RocksMore.png"		},
   { "emerald.collecting.xpos",			"3"			},
   { "emerald.collecting.ypos",			"2"			},
   { "emerald.collecting.frames",		"3"			},
   { "emerald.collecting.delay",			"2"			},
   { "emerald.collecting.anim_mode",		"linear"		},
 
-  { "diamond",					"RocksElements.pcx"	},
+  { "diamond",					"RocksElements.png"	},
   { "diamond.xpos",				"10"			},
   { "diamond.ypos",				"0"			},
   { "diamond.frames",				"1"			},
-  { "diamond.moving",				"RocksElements.pcx"	},
+  { "diamond.moving",				"RocksElements.png"	},
   { "diamond.moving.xpos",			"10"			},
   { "diamond.moving.ypos",			"0"			},
   { "diamond.moving.frames",			"2"			},
   { "diamond.moving.delay",			"4"			},
-  { "diamond.falling",				"RocksElements.pcx"	},
+  { "diamond.falling",				"RocksElements.png"	},
   { "diamond.falling.xpos",			"10"			},
   { "diamond.falling.ypos",			"0"			},
   { "diamond.falling.frames",			"2"			},
   { "diamond.falling.delay",			"4"			},
-  { "diamond.collecting",			"RocksMore.pcx"		},
+  { "diamond.collecting",			"RocksMore.png"		},
   { "diamond.collecting.xpos",			"7"			},
   { "diamond.collecting.ypos",			"2"			},
   { "diamond.collecting.frames",		"3"			},
   { "diamond.collecting.delay",			"2"			},
   { "diamond.collecting.anim_mode",		"linear"		},
 
-  { "bomb",					"RocksElements.pcx"	},
+  { "bomb",					"RocksElements.png"	},
   { "bomb.xpos",				"11"			},
   { "bomb.ypos",				"1"			},
   { "bomb.frames",				"1"			},
 
-  { "nut",					"RocksElements.pcx"	},
+  { "nut",					"RocksElements.png"	},
   { "nut.xpos",					"12"			},
   { "nut.ypos",					"1"			},
   { "nut.frames",				"1"			},
-  { "nut.breaking",				"RocksElements.pcx"	},
+  { "nut.breaking",				"RocksElements.png"	},
   { "nut.breaking.xpos",			"13"			},
   { "nut.breaking.ypos",			"1"			},
   { "nut.breaking.frames",			"3"			},
   { "nut.breaking.delay",			"2"			},
   { "nut.breaking.anim_mode",			"linear"		},
 
-  { "dynamite",					"RocksElements.pcx"	},
+  { "dynamite",					"RocksElements.png"	},
   { "dynamite.xpos",				"0"			},
   { "dynamite.ypos",				"3"			},
   { "dynamite.frames",				"1"			},
-  { "dynamite.EDITOR",				"RocksElements.pcx"	},
+  { "dynamite.EDITOR",				"RocksElements.png"	},
   { "dynamite.EDITOR.xpos",			"0"			},
   { "dynamite.EDITOR.ypos",			"14"			},
-  { "dynamite.active",				"RocksElements.pcx"	},
+  { "dynamite.active",				"RocksElements.png"	},
   { "dynamite.active.xpos",			"1"			},
   { "dynamite.active.ypos",			"3"			},
   { "dynamite.active.frames",			"7"			},
   { "dynamite.active.delay",			"12"			},
   { "dynamite.active.anim_mode",		"linear"		},
-  { "dynamite.active.EDITOR",			"RocksElements.pcx"	},
+  { "dynamite.active.EDITOR",			"RocksElements.png"	},
   { "dynamite.active.EDITOR.xpos",		"1"			},
   { "dynamite.active.EDITOR.ypos",		"14"			},
 
-  { "em_dynamite",				"RocksEMC.pcx"		},
+  { "em_dynamite",				"RocksEMC.png"		},
   { "em_dynamite.xpos",				"0"			},
   { "em_dynamite.ypos",				"15"			},
   { "em_dynamite.frames",			"1"			},
-  { "em_dynamite.active",			"RocksEMC.pcx"		},
+  { "em_dynamite.active",			"RocksEMC.png"		},
   { "em_dynamite.active.xpos",			"1"			},
   { "em_dynamite.active.ypos",			"15"			},
   { "em_dynamite.active.frames",		"4"			},
   { "em_dynamite.active.delay",			"8"			},
   { "em_dynamite.active.anim_mode",		"linear"		},
-  { "em_dynamite.active.EDITOR",		"RocksEMC.pcx"		},
+  { "em_dynamite.active.EDITOR",		"RocksEMC.png"		},
   { "em_dynamite.active.EDITOR.xpos",		"2"			},
   { "em_dynamite.active.EDITOR.ypos",		"15"			},
 
-  { "wall_emerald",				"RocksElements.pcx"	},
+  { "wall_emerald",				"RocksElements.png"	},
   { "wall_emerald.xpos",			"4"			},
   { "wall_emerald.ypos",			"8"			},
   { "wall_emerald.frames",			"1"			},
 
-  { "wall_diamond",				"RocksElements.pcx"	},
+  { "wall_diamond",				"RocksElements.png"	},
   { "wall_diamond.xpos",			"5"			},
   { "wall_diamond.ypos",			"8"			},
   { "wall_diamond.frames",			"1"			},
 
-  { "bug",					"RocksElements.pcx"	},
+  { "bug",					"RocksElements.png"	},
   { "bug.xpos",					"8"			},
   { "bug.ypos",					"4"			},
   { "bug.frames",				"4"			},
   { "bug.delay",				"8"			},
-  { "bug.right",				"RocksElements.pcx"	},
+  { "bug.right",				"RocksElements.png"	},
   { "bug.right.xpos",				"8"			},
   { "bug.right.ypos",				"4"			},
   { "bug.right.frames",				"1"			},
-  { "bug.up",					"RocksElements.pcx"	},
+  { "bug.up",					"RocksElements.png"	},
   { "bug.up.xpos",				"9"			},
   { "bug.up.ypos",				"4"			},
   { "bug.up.frames",				"1"			},
-  { "bug.left",					"RocksElements.pcx"	},
+  { "bug.left",					"RocksElements.png"	},
   { "bug.left.xpos",				"10"			},
   { "bug.left.ypos",				"4"			},
   { "bug.left.frames",				"1"			},
-  { "bug.down",					"RocksElements.pcx"	},
+  { "bug.down",					"RocksElements.png"	},
   { "bug.down.xpos",				"11"			},
   { "bug.down.ypos",				"4"			},
   { "bug.down.frames",				"1"			},
-  { "bug.moving.right",				"RocksElements.pcx"	},
+  { "bug.moving.right",				"RocksElements.png"	},
   { "bug.moving.right.xpos",			"8"			},
   { "bug.moving.right.ypos",			"4"			},
   { "bug.moving.right.frames",			"2"			},
   { "bug.moving.right.delay",			"4"			},
   { "bug.moving.right.offset",			"128"			},
-  { "bug.moving.up",				"RocksElements.pcx"	},
+  { "bug.moving.up",				"RocksElements.png"	},
   { "bug.moving.up.xpos",			"9"			},
   { "bug.moving.up.ypos",			"4"			},
   { "bug.moving.up.frames",			"2"			},
   { "bug.moving.up.delay",			"4"			},
   { "bug.moving.up.offset",			"128"			},
-  { "bug.moving.left",				"RocksElements.pcx"	},
+  { "bug.moving.left",				"RocksElements.png"	},
   { "bug.moving.left.xpos",			"10"			},
   { "bug.moving.left.ypos",			"4"			},
   { "bug.moving.left.frames",			"2"			},
   { "bug.moving.left.delay",			"4"			},
   { "bug.moving.left.offset",			"128"			},
-  { "bug.moving.down",				"RocksElements.pcx"	},
+  { "bug.moving.down",				"RocksElements.png"	},
   { "bug.moving.down.xpos",			"11"			},
   { "bug.moving.down.ypos",			"4"			},
   { "bug.moving.down.frames",			"2"			},
   { "bug.moving.down.delay",			"4"			},
   { "bug.moving.down.offset",			"128"			},
-  { "bug.turning_from_right.up",		"RocksMore.pcx"		},
+  { "bug.turning_from_right.up",		"RocksMore.png"		},
   { "bug.turning_from_right.up.xpos",		"0"			},
   { "bug.turning_from_right.up.ypos",		"6"			},
   { "bug.turning_from_right.up.frames",		"4"			},
   { "bug.turning_from_right.up.delay",		"2"			},
   { "bug.turning_from_right.up.anim_mode",	"linear,reverse"	},
-  { "bug.turning_from_up.left",			"RocksMore.pcx"		},
+  { "bug.turning_from_up.left",			"RocksMore.png"		},
   { "bug.turning_from_up.left.xpos",		"12"			},
   { "bug.turning_from_up.left.ypos",		"6"			},
   { "bug.turning_from_up.left.frames",		"4"			},
   { "bug.turning_from_up.left.delay",		"2"			},
   { "bug.turning_from_up.left.anim_mode",	"linear,reverse"	},
-  { "bug.turning_from_left.down",		"RocksMore.pcx"		},
+  { "bug.turning_from_left.down",		"RocksMore.png"		},
   { "bug.turning_from_left.down.xpos",		"8"			},
   { "bug.turning_from_left.down.ypos",		"6"			},
   { "bug.turning_from_left.down.frames",	"4"			},
   { "bug.turning_from_left.down.delay",		"2"			},
   { "bug.turning_from_left.down.anim_mode",	"linear,reverse"	},
-  { "bug.turning_from_down.right",		"RocksMore.pcx"		},
+  { "bug.turning_from_down.right",		"RocksMore.png"		},
   { "bug.turning_from_down.right.xpos",		"4"			},
   { "bug.turning_from_down.right.ypos",		"6"			},
   { "bug.turning_from_down.right.frames",	"4"			},
   { "bug.turning_from_down.right.delay",	"2"			},
   { "bug.turning_from_down.right.anim_mode",	"linear,reverse"	},
-  { "bug.turning_from_right.down",		"RocksMore.pcx"		},
+  { "bug.turning_from_right.down",		"RocksMore.png"		},
   { "bug.turning_from_right.down.xpos",		"5"			},
   { "bug.turning_from_right.down.ypos",		"6"			},
   { "bug.turning_from_right.down.frames",	"4"			},
   { "bug.turning_from_right.down.delay",	"2"			},
   { "bug.turning_from_right.down.anim_mode",	"linear"		},
-  { "bug.turning_from_up.right",		"RocksMore.pcx"		},
+  { "bug.turning_from_up.right",		"RocksMore.png"		},
   { "bug.turning_from_up.right.xpos",		"1"			},
   { "bug.turning_from_up.right.ypos",		"6"			},
   { "bug.turning_from_up.right.frames",		"4"			},
   { "bug.turning_from_up.right.delay",		"2"			},
   { "bug.turning_from_up.right.anim_mode",	"linear"		},
-  { "bug.turning_from_left.up",			"RocksMore.pcx"		},
+  { "bug.turning_from_left.up",			"RocksMore.png"		},
   { "bug.turning_from_left.up.xpos",		"13"			},
   { "bug.turning_from_left.up.ypos",		"6"			},
   { "bug.turning_from_left.up.frames",		"4"			},
   { "bug.turning_from_left.up.delay",		"2"			},
   { "bug.turning_from_left.up.anim_mode",	"linear"		},
-  { "bug.turning_from_down.left",		"RocksMore.pcx"		},
+  { "bug.turning_from_down.left",		"RocksMore.png"		},
   { "bug.turning_from_down.left.xpos",		"9"			},
   { "bug.turning_from_down.left.ypos",		"6"			},
   { "bug.turning_from_down.left.frames",	"4"			},
   { "bug.turning_from_down.left.delay",		"2"			},
   { "bug.turning_from_down.left.anim_mode",	"linear"		},
 
-  { "spaceship",				"RocksElements.pcx"	},
+  { "spaceship",				"RocksElements.png"	},
   { "spaceship.xpos",				"8"			},
   { "spaceship.ypos",				"3"			},
   { "spaceship.frames",				"4"			},
   { "spaceship.delay",				"8"			},
-  { "spaceship.right",				"RocksElements.pcx"	},
+  { "spaceship.right",				"RocksElements.png"	},
   { "spaceship.right.xpos",			"8"			},
   { "spaceship.right.ypos",			"3"			},
   { "spaceship.right.frames",			"1"			},
-  { "spaceship.up",				"RocksElements.pcx"	},
+  { "spaceship.up",				"RocksElements.png"	},
   { "spaceship.up.xpos",			"9"			},
   { "spaceship.up.ypos",			"3"			},
   { "spaceship.up.frames",			"1"			},
-  { "spaceship.left",				"RocksElements.pcx"	},
+  { "spaceship.left",				"RocksElements.png"	},
   { "spaceship.left.xpos",			"10"			},
   { "spaceship.left.ypos",			"3"			},
   { "spaceship.left.frames",			"1"			},
-  { "spaceship.down",				"RocksElements.pcx"	},
+  { "spaceship.down",				"RocksElements.png"	},
   { "spaceship.down.xpos",			"11"			},
   { "spaceship.down.ypos",			"3"			},
   { "spaceship.down.frames",			"1"			},
-  { "spaceship.moving.right",			"RocksElements.pcx"	},
+  { "spaceship.moving.right",			"RocksElements.png"	},
   { "spaceship.moving.right.xpos",		"8"			},
   { "spaceship.moving.right.ypos",		"3"			},
   { "spaceship.moving.right.frames",		"2"			},
   { "spaceship.moving.right.delay",		"4"			},
   { "spaceship.moving.right.offset",		"128"			},
-  { "spaceship.moving.up",			"RocksElements.pcx"	},
+  { "spaceship.moving.up",			"RocksElements.png"	},
   { "spaceship.moving.up.xpos",			"9"			},
   { "spaceship.moving.up.ypos",			"3"			},
   { "spaceship.moving.up.frames",		"2"			},
   { "spaceship.moving.up.delay",		"4"			},
   { "spaceship.moving.up.offset",		"128"			},
-  { "spaceship.moving.left",			"RocksElements.pcx"	},
+  { "spaceship.moving.left",			"RocksElements.png"	},
   { "spaceship.moving.left.xpos",		"10"			},
   { "spaceship.moving.left.ypos",		"3"			},
   { "spaceship.moving.left.frames",		"2"			},
   { "spaceship.moving.left.delay",		"4"			},
   { "spaceship.moving.left.offset",		"128"			},
-  { "spaceship.moving.down",			"RocksElements.pcx"	},
+  { "spaceship.moving.down",			"RocksElements.png"	},
   { "spaceship.moving.down.xpos",		"11"			},
   { "spaceship.moving.down.ypos",		"3"			},
   { "spaceship.moving.down.frames",		"2"			},
   { "spaceship.moving.down.delay",		"4"			},
   { "spaceship.moving.down.offset",		"128"			},
-  { "spaceship.turning_from_right.up",		"RocksMore.pcx"		},
+  { "spaceship.turning_from_right.up",		"RocksMore.png"		},
   { "spaceship.turning_from_right.up.xpos",	"0"			},
   { "spaceship.turning_from_right.up.ypos",	"5"			},
   { "spaceship.turning_from_right.up.frames",	"4"			},
   { "spaceship.turning_from_right.up.delay",	"2"			},
   { "spaceship.turning_from_right.up.anim_mode","linear,reverse"	},
-  { "spaceship.turning_from_up.left",		"RocksMore.pcx"		},
+  { "spaceship.turning_from_up.left",		"RocksMore.png"		},
   { "spaceship.turning_from_up.left.xpos",	"12"			},
   { "spaceship.turning_from_up.left.ypos",	"5"			},
   { "spaceship.turning_from_up.left.frames",	"4"			},
   { "spaceship.turning_from_up.left.delay",	"2"			},
   { "spaceship.turning_from_up.left.anim_mode",	"linear,reverse"	},
-  { "spaceship.turning_from_left.down",		"RocksMore.pcx"		},
+  { "spaceship.turning_from_left.down",		"RocksMore.png"		},
   { "spaceship.turning_from_left.down.xpos",	"8"			},
   { "spaceship.turning_from_left.down.ypos",	"5"			},
   { "spaceship.turning_from_left.down.frames",	"4"			},
   { "spaceship.turning_from_left.down.delay",	"2"			},
   { "spaceship.turning_from_left.down.anim_mode","linear,reverse"	},
-  { "spaceship.turning_from_down.right",	"RocksMore.pcx"		},
+  { "spaceship.turning_from_down.right",	"RocksMore.png"		},
   { "spaceship.turning_from_down.right.xpos",	"4"			},
   { "spaceship.turning_from_down.right.ypos",	"5"			},
   { "spaceship.turning_from_down.right.frames",	"4"			},
   { "spaceship.turning_from_down.right.delay",	"2"			},
   { "spaceship.turning_from_down.right.anim_mode","linear,reverse"	},
-  { "spaceship.turning_from_right.down",	"RocksMore.pcx"		},
+  { "spaceship.turning_from_right.down",	"RocksMore.png"		},
   { "spaceship.turning_from_right.down.xpos",	"5"			},
   { "spaceship.turning_from_right.down.ypos",	"5"			},
   { "spaceship.turning_from_right.down.frames",	"4"			},
   { "spaceship.turning_from_right.down.delay",	"2"			},
   { "spaceship.turning_from_right.down.anim_mode","linear"		},
-  { "spaceship.turning_from_up.right",		"RocksMore.pcx"		},
+  { "spaceship.turning_from_up.right",		"RocksMore.png"		},
   { "spaceship.turning_from_up.right.xpos",	"1"			},
   { "spaceship.turning_from_up.right.ypos",	"5"			},
   { "spaceship.turning_from_up.right.frames",	"4"			},
   { "spaceship.turning_from_up.right.delay",	"2"			},
   { "spaceship.turning_from_up.right.anim_mode","linear"		},
-  { "spaceship.turning_from_left.up",		"RocksMore.pcx"		},
+  { "spaceship.turning_from_left.up",		"RocksMore.png"		},
   { "spaceship.turning_from_left.up.xpos",	"13"			},
   { "spaceship.turning_from_left.up.ypos",	"5"			},
   { "spaceship.turning_from_left.up.frames",	"4"			},
   { "spaceship.turning_from_left.up.delay",	"2"			},
   { "spaceship.turning_from_left.up.anim_mode",	"linear"		},
-  { "spaceship.turning_from_down.left",		"RocksMore.pcx"		},
+  { "spaceship.turning_from_down.left",		"RocksMore.png"		},
   { "spaceship.turning_from_down.left.xpos",	"9"			},
   { "spaceship.turning_from_down.left.ypos",	"5"			},
   { "spaceship.turning_from_down.left.frames",	"4"			},
   { "spaceship.turning_from_down.left.delay",	"2"			},
   { "spaceship.turning_from_down.left.anim_mode","linear"		},
 
-  { "yamyam",					"RocksElements.pcx"	},
+  { "yamyam",					"RocksElements.png"	},
   { "yamyam.xpos",				"0"			},
   { "yamyam.ypos",				"5"			},
   { "yamyam.frames",				"4"			},
   { "yamyam.anim_mode",				"pingpong2"		},
-  { "yamyam.left",				"RocksElements.pcx"	},
+  { "yamyam.left",				"RocksElements.png"	},
   { "yamyam.left.xpos",				"0"			},
   { "yamyam.left.ypos",				"5"			},
   { "yamyam.left.frames",			"4"			},
   { "yamyam.left.anim_mode",			"pingpong2"		},
-  { "yamyam.left.EDITOR",			"RocksEMC.pcx"		},
+  { "yamyam.left.EDITOR",			"RocksEMC.png"		},
   { "yamyam.left.EDITOR.xpos",			"7"			},
   { "yamyam.left.EDITOR.ypos",			"15"			},
-  { "yamyam.right",				"RocksElements.pcx"	},
+  { "yamyam.right",				"RocksElements.png"	},
   { "yamyam.right.xpos",			"0"			},
   { "yamyam.right.ypos",			"5"			},
   { "yamyam.right.frames",			"4"			},
   { "yamyam.right.anim_mode",			"pingpong2"		},
-  { "yamyam.right.EDITOR",			"RocksEMC.pcx"		},
+  { "yamyam.right.EDITOR",			"RocksEMC.png"		},
   { "yamyam.right.EDITOR.xpos",			"8"			},
   { "yamyam.right.EDITOR.ypos",			"15"			},
-  { "yamyam.up",				"RocksElements.pcx"	},
+  { "yamyam.up",				"RocksElements.png"	},
   { "yamyam.up.xpos",				"0"			},
   { "yamyam.up.ypos",				"5"			},
   { "yamyam.up.frames",				"4"			},
   { "yamyam.up.anim_mode",			"pingpong2"		},
-  { "yamyam.up.EDITOR",				"RocksEMC.pcx"		},
+  { "yamyam.up.EDITOR",				"RocksEMC.png"		},
   { "yamyam.up.EDITOR.xpos",			"5"			},
   { "yamyam.up.EDITOR.ypos",			"15"			},
-  { "yamyam.down",				"RocksElements.pcx"	},
+  { "yamyam.down",				"RocksElements.png"	},
   { "yamyam.down.xpos",				"0"			},
   { "yamyam.down.ypos",				"5"			},
   { "yamyam.down.frames",			"4"			},
   { "yamyam.down.anim_mode",			"pingpong2"		},
-  { "yamyam.down.EDITOR",			"RocksEMC.pcx"		},
+  { "yamyam.down.EDITOR",			"RocksEMC.png"		},
   { "yamyam.down.EDITOR.xpos",			"6"			},
   { "yamyam.down.EDITOR.ypos",			"15"			},
-  { "yamyam.moving",				"RocksElements.pcx"	},
+  { "yamyam.moving",				"RocksElements.png"	},
   { "yamyam.moving.xpos",			"0"			},
   { "yamyam.moving.ypos",			"5"			},
   { "yamyam.moving.frames",			"1"			},
 
-  { "robot",					"RocksElements.pcx"	},
+  { "robot",					"RocksElements.png"	},
   { "robot.xpos",				"4"			},
   { "robot.ypos",				"5"			},
   { "robot.frames",				"4"			},
   { "robot.anim_mode",				"pingpong2"		},
-  { "robot.moving",				"RocksElements.pcx"	},
+  { "robot.moving",				"RocksElements.png"	},
   { "robot.moving.xpos",			"4"			},
   { "robot.moving.ypos",			"5"			},
   { "robot.moving.frames",			"1"			},
 
-  { "robot_wheel",				"RocksElements.pcx"	},
+  { "robot_wheel",				"RocksElements.png"	},
   { "robot_wheel.xpos",				"0"			},
   { "robot_wheel.ypos",				"6"			},
   { "robot_wheel.frames",			"1"			},
-  { "robot_wheel.active",			"RocksElements.pcx"	},
+  { "robot_wheel.active",			"RocksElements.png"	},
   { "robot_wheel.active.xpos",			"0"			},
   { "robot_wheel.active.ypos",			"6"			},
   { "robot_wheel.active.frames",		"4"			},
 
-  { "magic_wall",				"RocksElements.pcx"	},
+  { "magic_wall",				"RocksElements.png"	},
   { "magic_wall.xpos",				"0"			},
   { "magic_wall.ypos",				"8"			},
   { "magic_wall.frames",			"1"			},
-  { "magic_wall.active",			"RocksElements.pcx"	},
+  { "magic_wall.active",			"RocksElements.png"	},
   { "magic_wall.active.xpos",			"0"			},
   { "magic_wall.active.ypos",			"8"			},
   { "magic_wall.active.frames",			"4"			},
   { "magic_wall.active.anim_mode",		"reverse"		},
   { "magic_wall.active.delay",			"4"			},
   { "magic_wall.active.global_sync",		"true"			},
-  { "magic_wall.filling",			"RocksElements.pcx"	},
+  { "magic_wall.filling",			"RocksElements.png"	},
   { "magic_wall.filling.xpos",			"0"			},
   { "magic_wall.filling.ypos",			"8"			},
   { "magic_wall.filling.frames",		"4"			},
   { "magic_wall.filling.anim_mode",		"reverse"		},
   { "magic_wall.filling.delay",			"4"			},
   { "magic_wall.filling.global_sync",		"true"			},
-  { "magic_wall_full",				"RocksElements.pcx"	},
+  { "magic_wall_full",				"RocksElements.png"	},
   { "magic_wall_full.xpos",			"0"			},
   { "magic_wall_full.ypos",			"8"			},
   { "magic_wall_full.frames",			"4"			},
   { "magic_wall_full.anim_mode",		"reverse"		},
   { "magic_wall_full.delay",			"4"			},
   { "magic_wall_full.global_sync",		"true"			},
-  { "magic_wall.emptying",			"RocksElements.pcx"	},
+  { "magic_wall.emptying",			"RocksElements.png"	},
   { "magic_wall.emptying.xpos",			"0"			},
   { "magic_wall.emptying.ypos",			"8"			},
   { "magic_wall.emptying.frames",		"4"			},
   { "magic_wall.emptying.anim_mode",		"reverse"		},
   { "magic_wall.emptying.delay",		"4"			},
   { "magic_wall.emptying.global_sync",		"true"			},
-  { "magic_wall_dead",				"RocksElements.pcx"	},
+  { "magic_wall_dead",				"RocksElements.png"	},
   { "magic_wall_dead.xpos",			"0"			},
   { "magic_wall_dead.ypos",			"8"			},
   { "magic_wall_dead.frames",			"1"			},
 
-  { "dc_magic_wall",				"RocksDC2.pcx"		},
+  { "dc_magic_wall",				"RocksDC2.png"		},
   { "dc_magic_wall.xpos",			"0"			},
   { "dc_magic_wall.ypos",			"3"			},
   { "dc_magic_wall.frames",			"1"			},
-  { "dc_magic_wall.active",			"RocksDC2.pcx"		},
+  { "dc_magic_wall.active",			"RocksDC2.png"		},
   { "dc_magic_wall.active.xpos",		"0"			},
   { "dc_magic_wall.active.ypos",		"3"			},
   { "dc_magic_wall.active.frames",		"4"			},
   { "dc_magic_wall.active.anim_mode",		"reverse"		},
   { "dc_magic_wall.active.delay",		"4"			},
   { "dc_magic_wall.active.global_sync",		"true"			},
-  { "dc_magic_wall.filling",			"RocksDC2.pcx"		},
+  { "dc_magic_wall.filling",			"RocksDC2.png"		},
   { "dc_magic_wall.filling.xpos",		"0"			},
   { "dc_magic_wall.filling.ypos",		"3"			},
   { "dc_magic_wall.filling.frames",		"4"			},
   { "dc_magic_wall.filling.anim_mode",		"reverse"		},
   { "dc_magic_wall.filling.delay",		"4"			},
   { "dc_magic_wall.filling.global_sync",	"true"			},
-  { "dc_magic_wall_full",			"RocksDC2.pcx"		},
+  { "dc_magic_wall_full",			"RocksDC2.png"		},
   { "dc_magic_wall_full.xpos",			"0"			},
   { "dc_magic_wall_full.ypos",			"3"			},
   { "dc_magic_wall_full.frames",		"4"			},
   { "dc_magic_wall_full.anim_mode",		"reverse"		},
   { "dc_magic_wall_full.delay",			"4"			},
   { "dc_magic_wall_full.global_sync",		"true"			},
-  { "dc_magic_wall.emptying",			"RocksDC2.pcx"		},
+  { "dc_magic_wall.emptying",			"RocksDC2.png"		},
   { "dc_magic_wall.emptying.xpos",		"0"			},
   { "dc_magic_wall.emptying.ypos",		"3"			},
   { "dc_magic_wall.emptying.frames",		"4"			},
   { "dc_magic_wall.emptying.anim_mode",		"reverse"		},
   { "dc_magic_wall.emptying.delay",		"4"			},
   { "dc_magic_wall.emptying.global_sync",	"true"			},
-  { "dc_magic_wall_dead",			"RocksDC2.pcx"		},
+  { "dc_magic_wall_dead",			"RocksDC2.png"		},
   { "dc_magic_wall_dead.xpos",			"0"			},
   { "dc_magic_wall_dead.ypos",			"3"			},
   { "dc_magic_wall_dead.frames",		"1"			},
 
-  { "quicksand_empty",				"RocksElements.pcx"	},
+  { "quicksand_empty",				"RocksElements.png"	},
   { "quicksand_empty.xpos",			"2"			},
   { "quicksand_empty.ypos",			"0"			},
   { "quicksand_empty.frames",			"1"			},
-  { "quicksand.filling",			"RocksElements.pcx"	},
+  { "quicksand.filling",			"RocksElements.png"	},
   { "quicksand.filling.xpos",			"3"			},
   { "quicksand.filling.ypos",			"0"			},
   { "quicksand.filling.frames",			"1"			},
-  { "quicksand_full",				"RocksElements.pcx"	},
+  { "quicksand_full",				"RocksElements.png"	},
   { "quicksand_full.xpos",			"3"			},
   { "quicksand_full.ypos",			"0"			},
   { "quicksand_full.frames",			"1"			},
-  { "quicksand_full.EDITOR",			"RocksElements.pcx"	},
+  { "quicksand_full.EDITOR",			"RocksElements.png"	},
   { "quicksand_full.EDITOR.xpos",		"3"			},
   { "quicksand_full.EDITOR.ypos",		"14"			},
-  { "quicksand.emptying",			"RocksElements.pcx"	},
+  { "quicksand.emptying",			"RocksElements.png"	},
   { "quicksand.emptying.xpos",			"3"			},
   { "quicksand.emptying.ypos",			"0"			},
   { "quicksand.emptying.frames",		"1"			},
 
-  { "quicksand_fast_empty",			"RocksDC2.pcx"		},
+  { "quicksand_fast_empty",			"RocksDC2.png"		},
   { "quicksand_fast_empty.xpos",		"4"			},
   { "quicksand_fast_empty.ypos",		"3"			},
   { "quicksand_fast_empty.frames",		"1"			},
-  { "quicksand_fast.filling",			"RocksDC2.pcx"		},
+  { "quicksand_fast.filling",			"RocksDC2.png"		},
   { "quicksand_fast.filling.xpos",		"4"			},
   { "quicksand_fast.filling.ypos",		"3"			},
   { "quicksand_fast.filling.frames",		"1"			},
-  { "quicksand_fast_full",			"RocksDC2.pcx"		},
+  { "quicksand_fast_full",			"RocksDC2.png"		},
   { "quicksand_fast_full.xpos",			"4"			},
   { "quicksand_fast_full.ypos",			"3"			},
   { "quicksand_fast_full.frames",		"1"			},
-  { "quicksand_fast_full.EDITOR",		"RocksDC2.pcx"		},
+  { "quicksand_fast_full.EDITOR",		"RocksDC2.png"		},
   { "quicksand_fast_full.EDITOR.xpos",		"5"			},
   { "quicksand_fast_full.EDITOR.ypos",		"3"			},
-  { "quicksand_fast.emptying",			"RocksDC2.pcx"		},
+  { "quicksand_fast.emptying",			"RocksDC2.png"		},
   { "quicksand_fast.emptying.xpos",		"4"			},
   { "quicksand_fast.emptying.ypos",		"3"			},
   { "quicksand_fast.emptying.frames",		"1"			},
 
-  { "acid_pool_topleft",			"RocksElements.pcx"	},
+  { "acid_pool_topleft",			"RocksElements.png"	},
   { "acid_pool_topleft.xpos",			"0"			},
   { "acid_pool_topleft.ypos",			"1"			},
   { "acid_pool_topleft.frames",			"1"			},
-  { "acid_pool_topright",			"RocksElements.pcx"	},
+  { "acid_pool_topright",			"RocksElements.png"	},
   { "acid_pool_topright.xpos",			"2"			},
   { "acid_pool_topright.ypos",			"1"			},
   { "acid_pool_topright.frames",		"1"			},
-  { "acid_pool_bottomleft",			"RocksElements.pcx"	},
+  { "acid_pool_bottomleft",			"RocksElements.png"	},
   { "acid_pool_bottomleft.xpos",		"0"			},
   { "acid_pool_bottomleft.ypos",		"2"			},
   { "acid_pool_bottomleft.frames",		"1"			},
-  { "acid_pool_bottom",				"RocksElements.pcx"	},
+  { "acid_pool_bottom",				"RocksElements.png"	},
   { "acid_pool_bottom.xpos",			"1"			},
   { "acid_pool_bottom.ypos",			"2"			},
   { "acid_pool_bottom.frames",			"1"			},
-  { "acid_pool_bottomright",			"RocksElements.pcx"	},
+  { "acid_pool_bottomright",			"RocksElements.png"	},
   { "acid_pool_bottomright.xpos",		"2"			},
   { "acid_pool_bottomright.ypos",		"2"			},
   { "acid_pool_bottomright.frames",		"1"			},
 
-  { "acid",					"RocksElements.pcx"	},
+  { "acid",					"RocksElements.png"	},
   { "acid.xpos",				"12"			},
   { "acid.ypos",				"7"			},
   { "acid.frames",				"4"			},
   { "acid.delay",				"10"			},
   { "acid.global_sync",				"true"			},
 
-  { "acid_splash_left",				"RocksHeroes.pcx"	},
+  { "acid_splash_left",				"RocksHeroes.png"	},
   { "acid_splash_left.xpos",			"8"			},
   { "acid_splash_left.ypos",			"10"			},
   { "acid_splash_left.frames",			"4"			},
   { "acid_splash_left.delay",			"2"			},
   { "acid_splash_left.anim_mode",		"linear"		},
-  { "acid_splash_right",			"RocksHeroes.pcx"	},
+  { "acid_splash_right",			"RocksHeroes.png"	},
   { "acid_splash_right.xpos",			"12"			},
   { "acid_splash_right.ypos",			"10"			},
   { "acid_splash_right.frames",			"4"			},
   { "acid_splash_right.delay",			"2"			},
   { "acid_splash_right.anim_mode",		"linear"		},
 
-  { "amoeba_drop",				"RocksElements.pcx"	},
+  { "amoeba_drop",				"RocksElements.png"	},
   { "amoeba_drop.xpos",				"5"			},
   { "amoeba_drop.ypos",				"6"			},
   { "amoeba_drop.frames",			"1"			},
-  { "amoeba.growing",				"RocksElements.pcx"	},
+  { "amoeba.growing",				"RocksElements.png"	},
   { "amoeba.growing.xpos",			"5"			},
   { "amoeba.growing.ypos",			"6"			},
   { "amoeba.growing.frames",			"3"			},
   { "amoeba.growing.delay",			"2"			},
   { "amoeba.growing.anim_mode",			"linear"		},
-  { "amoeba.shrinking",				"RocksElements.pcx"	},
+  { "amoeba.shrinking",				"RocksElements.png"	},
   { "amoeba.shrinking.xpos",			"5"			},
   { "amoeba.shrinking.ypos",			"6"			},
   { "amoeba.shrinking.frames",			"3"			},
   { "amoeba.shrinking.delay",			"2"			},
   { "amoeba.shrinking.anim_mode",		"linear,reverse"	},
-  { "amoeba_wet",				"RocksElements.pcx"	},
+  { "amoeba_wet",				"RocksElements.png"	},
   { "amoeba_wet.xpos",				"8"			},
   { "amoeba_wet.ypos",				"6"			},
   { "amoeba_wet.frames",			"4"			},
   { "amoeba_wet.delay",				"1000000"		},
   { "amoeba_wet.anim_mode",			"random"		},
-  { "amoeba_wet.EDITOR",			"RocksElements.pcx"	},
+  { "amoeba_wet.EDITOR",			"RocksElements.png"	},
   { "amoeba_wet.EDITOR.xpos",			"4"			},
   { "amoeba_wet.EDITOR.ypos",			"6"			},
-  { "amoeba.dropping",				"RocksElements.pcx"	},
+  { "amoeba.dropping",				"RocksElements.png"	},
   { "amoeba.dropping.xpos",			"8"			},
   { "amoeba.dropping.ypos",			"6"			},
   { "amoeba.dropping.frames",			"4"			},
   { "amoeba.dropping.delay",			"1000000"		},
   { "amoeba.dropping.anim_mode",		"random"		},
-  { "amoeba_dry",				"RocksElements.pcx"	},
+  { "amoeba_dry",				"RocksElements.png"	},
   { "amoeba_dry.xpos",				"8"			},
   { "amoeba_dry.ypos",				"6"			},
   { "amoeba_dry.frames",			"4"			},
   { "amoeba_dry.delay",				"1000000"		},
   { "amoeba_dry.anim_mode",			"random"		},
-  { "amoeba_full",				"RocksElements.pcx"	},
+  { "amoeba_full",				"RocksElements.png"	},
   { "amoeba_full.xpos",				"8"			},
   { "amoeba_full.ypos",				"6"			},
   { "amoeba_full.frames",			"4"			},
   { "amoeba_full.delay",			"1000000"		},
   { "amoeba_full.anim_mode",			"random"		},
-  { "amoeba_full.EDITOR",			"RocksElements.pcx"	},
+  { "amoeba_full.EDITOR",			"RocksElements.png"	},
   { "amoeba_full.EDITOR.xpos",			"8"			},
   { "amoeba_full.EDITOR.ypos",			"7"			},
-  { "amoeba_dead",				"RocksElements.pcx"	},
+  { "amoeba_dead",				"RocksElements.png"	},
   { "amoeba_dead.xpos",				"12"			},
   { "amoeba_dead.ypos",				"6"			},
   { "amoeba_dead.frames",			"4"			},
   { "amoeba_dead.delay",			"1000000"		},
   { "amoeba_dead.anim_mode",			"random"		},
-  { "amoeba_dead.EDITOR",			"RocksElements.pcx"	},
+  { "amoeba_dead.EDITOR",			"RocksElements.png"	},
   { "amoeba_dead.EDITOR.xpos",			"12"			},
   { "amoeba_dead.EDITOR.ypos",			"6"			},
 
-  { "em_key_1",					"RocksSP.pcx"		},
+  { "em_key_1",					"RocksSP.png"		},
   { "em_key_1.xpos",				"4"			},
   { "em_key_1.ypos",				"6"			},
   { "em_key_1.frames",				"1"			},
-  { "em_key_2",					"RocksSP.pcx"		},
+  { "em_key_2",					"RocksSP.png"		},
   { "em_key_2.xpos",				"5"			},
   { "em_key_2.ypos",				"6"			},
   { "em_key_2.frames",				"1"			},
-  { "em_key_3",					"RocksSP.pcx"		},
+  { "em_key_3",					"RocksSP.png"		},
   { "em_key_3.xpos",				"6"			},
   { "em_key_3.ypos",				"6"			},
   { "em_key_3.frames",				"1"			},
-  { "em_key_4",					"RocksSP.pcx"		},
+  { "em_key_4",					"RocksSP.png"		},
   { "em_key_4.xpos",				"7"			},
   { "em_key_4.ypos",				"6"			},
   { "em_key_4.frames",				"1"			},
 
-  { "dc_key_white",				"RocksSP.pcx"		},
+  { "dc_key_white",				"RocksSP.png"		},
   { "dc_key_white.xpos",			"13"			},
   { "dc_key_white.ypos",			"1"			},
   { "dc_key_white.frames",			"1"			},
 
-  { "em_gate_1",				"RocksSP.pcx"		},
+  { "em_gate_1",				"RocksSP.png"		},
   { "em_gate_1.xpos",				"0"			},
   { "em_gate_1.ypos",				"7"			},
   { "em_gate_1.frames",				"1"			},
-  { "em_gate_2",				"RocksSP.pcx"		},
+  { "em_gate_2",				"RocksSP.png"		},
   { "em_gate_2.xpos",				"1"			},
   { "em_gate_2.ypos",				"7"			},
   { "em_gate_2.frames",				"1"			},
-  { "em_gate_3",				"RocksSP.pcx"		},
+  { "em_gate_3",				"RocksSP.png"		},
   { "em_gate_3.xpos",				"2"			},
   { "em_gate_3.ypos",				"7"			},
   { "em_gate_3.frames",				"1"			},
-  { "em_gate_4",				"RocksSP.pcx"		},
+  { "em_gate_4",				"RocksSP.png"		},
   { "em_gate_4.xpos",				"3"			},
   { "em_gate_4.ypos",				"7"			},
   { "em_gate_4.frames",				"1"			},
 
-  { "dc_gate_white",				"RocksSP.pcx"		},
+  { "dc_gate_white",				"RocksSP.png"		},
   { "dc_gate_white.xpos",			"14"			},
   { "dc_gate_white.ypos",			"1"			},
   { "dc_gate_white.frames",			"1"			},
 
-  { "em_gate_1_gray",				"RocksSP.pcx"		},
+  { "em_gate_1_gray",				"RocksSP.png"		},
   { "em_gate_1_gray.xpos",			"4"			},
   { "em_gate_1_gray.ypos",			"7"			},
   { "em_gate_1_gray.frames",			"1"			},
-  { "em_gate_1_gray.EDITOR",			"RocksSP.pcx"		},
+  { "em_gate_1_gray.EDITOR",			"RocksSP.png"		},
   { "em_gate_1_gray.EDITOR.xpos",		"12"			},
   { "em_gate_1_gray.EDITOR.ypos",		"11"			},
-  { "em_gate_1_gray.active",			"RocksSP.pcx"		},
+  { "em_gate_1_gray.active",			"RocksSP.png"		},
   { "em_gate_1_gray.active.xpos",		"0"			},
   { "em_gate_1_gray.active.ypos",		"7"			},
   { "em_gate_1_gray.active.frames",		"1"			},
-  { "em_gate_2_gray",				"RocksSP.pcx"		},
+  { "em_gate_2_gray",				"RocksSP.png"		},
   { "em_gate_2_gray.xpos",			"5"			},
   { "em_gate_2_gray.ypos",			"7"			},
   { "em_gate_2_gray.frames",			"1"			},
-  { "em_gate_2_gray.EDITOR",			"RocksSP.pcx"		},
+  { "em_gate_2_gray.EDITOR",			"RocksSP.png"		},
   { "em_gate_2_gray.EDITOR.xpos",		"13"			},
   { "em_gate_2_gray.EDITOR.ypos",		"11"			},
-  { "em_gate_2_gray.active",			"RocksSP.pcx"		},
+  { "em_gate_2_gray.active",			"RocksSP.png"		},
   { "em_gate_2_gray.active.xpos",		"1"			},
   { "em_gate_2_gray.active.ypos",		"7"			},
   { "em_gate_2_gray.active.frames",		"1"			},
-  { "em_gate_3_gray",				"RocksSP.pcx"		},
+  { "em_gate_3_gray",				"RocksSP.png"		},
   { "em_gate_3_gray.xpos",			"6"			},
   { "em_gate_3_gray.ypos",			"7"			},
   { "em_gate_3_gray.frames",			"1"			},
-  { "em_gate_3_gray.EDITOR",			"RocksSP.pcx"		},
+  { "em_gate_3_gray.EDITOR",			"RocksSP.png"		},
   { "em_gate_3_gray.EDITOR.xpos",		"14"			},
   { "em_gate_3_gray.EDITOR.ypos",		"11"			},
-  { "em_gate_3_gray.active",			"RocksSP.pcx"		},
+  { "em_gate_3_gray.active",			"RocksSP.png"		},
   { "em_gate_3_gray.active.xpos",		"2"			},
   { "em_gate_3_gray.active.ypos",		"7"			},
   { "em_gate_3_gray.active.frames",		"1"			},
-  { "em_gate_4_gray",				"RocksSP.pcx"		},
+  { "em_gate_4_gray",				"RocksSP.png"		},
   { "em_gate_4_gray.xpos",			"7"			},
   { "em_gate_4_gray.ypos",			"7"			},
   { "em_gate_4_gray.frames",			"1"			},
-  { "em_gate_4_gray.EDITOR",			"RocksSP.pcx"		},
+  { "em_gate_4_gray.EDITOR",			"RocksSP.png"		},
   { "em_gate_4_gray.EDITOR.xpos",		"15"			},
   { "em_gate_4_gray.EDITOR.ypos",		"11"			},
-  { "em_gate_4_gray.active",			"RocksSP.pcx"		},
+  { "em_gate_4_gray.active",			"RocksSP.png"		},
   { "em_gate_4_gray.active.xpos",		"3"			},
   { "em_gate_4_gray.active.ypos",		"7"			},
   { "em_gate_4_gray.active.frames",		"1"			},
 
-  { "dc_gate_white_gray",			"RocksSP.pcx"		},
+  { "dc_gate_white_gray",			"RocksSP.png"		},
   { "dc_gate_white_gray.xpos",			"7"			},
   { "dc_gate_white_gray.ypos",			"7"			},
   { "dc_gate_white_gray.frames",		"1"			},
-  { "dc_gate_white_gray.EDITOR",		"RocksSP.pcx"		},
+  { "dc_gate_white_gray.EDITOR",		"RocksSP.png"		},
   { "dc_gate_white_gray.EDITOR.xpos",		"15"			},
   { "dc_gate_white_gray.EDITOR.ypos",		"1"			},
-  { "dc_gate_white_gray.active",		"RocksSP.pcx"		},
+  { "dc_gate_white_gray.active",		"RocksSP.png"		},
   { "dc_gate_white_gray.active.xpos",		"14"			},
   { "dc_gate_white_gray.active.ypos",		"1"			},
   { "dc_gate_white_gray.active.frames",		"1"			},
 
-  { "dc_gate_fake_gray",			"RocksSP.pcx"		},
+  { "dc_gate_fake_gray",			"RocksSP.png"		},
   { "dc_gate_fake_gray.xpos",			"7"			},
   { "dc_gate_fake_gray.ypos",			"7"			},
   { "dc_gate_fake_gray.frames",			"1"			},
 
-  { "exit_closed",				"RocksElements.pcx"	},
+  { "exit_closed",				"RocksElements.png"	},
   { "exit_closed.xpos",				"0"			},
   { "exit_closed.ypos",				"11"			},
   { "exit_closed.frames",			"1"			},
-  { "exit.opening",				"RocksElements.pcx"	},
+  { "exit.opening",				"RocksElements.png"	},
   { "exit.opening.xpos",			"0"			},
   { "exit.opening.ypos",			"11"			},
   { "exit.opening.frames",			"5"			},
   { "exit.opening.delay",			"6"			},
   { "exit.opening.anim_mode",			"linear"		},
-  { "exit_open",				"RocksElements.pcx"	},
+  { "exit_open",				"RocksElements.png"	},
   { "exit_open.xpos",				"4"			},
   { "exit_open.ypos",				"11"			},
   { "exit_open.frames",				"4"			},
   { "exit_open.delay",				"4"			},
   { "exit_open.anim_mode",			"pingpong"		},
-  { "exit.closing",				"RocksElements.pcx"	},
+  { "exit.closing",				"RocksElements.png"	},
   { "exit.closing.xpos",			"0"			},
   { "exit.closing.ypos",			"11"			},
   { "exit.closing.frames",			"5"			},
   { "exit.closing.delay",			"6"			},
   { "exit.closing.anim_mode",			"linear,reverse"	},
 
-  { "steel_exit_closed",			"RocksDC2.pcx"	},
+  { "steel_exit_closed",			"RocksDC2.png"	},
   { "steel_exit_closed.xpos",			"8"			},
   { "steel_exit_closed.ypos",			"0"			},
   { "steel_exit_closed.frames",			"1"			},
-  { "steel_exit.opening",			"RocksDC2.pcx"	},
+  { "steel_exit.opening",			"RocksDC2.png"	},
   { "steel_exit.opening.xpos",			"8"			},
   { "steel_exit.opening.ypos",			"0"			},
   { "steel_exit.opening.frames",		"5"			},
   { "steel_exit.opening.delay",			"6"			},
   { "steel_exit.opening.anim_mode",		"linear"		},
-  { "steel_exit_open",				"RocksDC2.pcx"	},
+  { "steel_exit_open",				"RocksDC2.png"	},
   { "steel_exit_open.xpos",			"12"			},
   { "steel_exit_open.ypos",			"0"			},
   { "steel_exit_open.frames",			"4"			},
   { "steel_exit_open.delay",			"4"			},
   { "steel_exit_open.anim_mode",		"pingpong"		},
-  { "steel_exit.closing",			"RocksDC2.pcx"	},
+  { "steel_exit.closing",			"RocksDC2.png"	},
   { "steel_exit.closing.xpos",			"8"			},
   { "steel_exit.closing.ypos",			"0"			},
   { "steel_exit.closing.frames",		"5"			},
   { "steel_exit.closing.delay",			"6"			},
   { "steel_exit.closing.anim_mode",		"linear,reverse"	},
 
-  { "em_exit_closed",				"RocksDC2.pcx"	},
+  { "em_exit_closed",				"RocksDC2.png"	},
   { "em_exit_closed.xpos",			"0"			},
   { "em_exit_closed.ypos",			"4"			},
   { "em_exit_closed.frames",			"1"			},
-  { "em_exit.opening",				"RocksDC2.pcx"	},
+  { "em_exit.opening",				"RocksDC2.png"	},
   { "em_exit.opening.xpos",			"0"			},
   { "em_exit.opening.ypos",			"4"			},
   { "em_exit.opening.frames",			"5"			},
   { "em_exit.opening.delay",			"6"			},
   { "em_exit.opening.anim_mode",		"linear"		},
-  { "em_exit_open",				"RocksDC2.pcx"	},
+  { "em_exit_open",				"RocksDC2.png"	},
   { "em_exit_open.xpos",			"4"			},
   { "em_exit_open.ypos",			"4"			},
   { "em_exit_open.frames",			"4"			},
   { "em_exit_open.delay",			"4"			},
   { "em_exit_open.anim_mode",			"pingpong"		},
-  { "em_exit.closing",				"RocksDC2.pcx"	},
+  { "em_exit.closing",				"RocksDC2.png"	},
   { "em_exit.closing.xpos",			"0"			},
   { "em_exit.closing.ypos",			"6"			},
   { "em_exit.closing.frames",			"5"			},
   { "em_exit.closing.delay",			"6"			},
   { "em_exit.closing.anim_mode",		"linear"		},
 
-  { "em_steel_exit_closed",			"RocksDC2.pcx"	},
+  { "em_steel_exit_closed",			"RocksDC2.png"	},
   { "em_steel_exit_closed.xpos",		"0"			},
   { "em_steel_exit_closed.ypos",		"5"			},
   { "em_steel_exit_closed.frames",		"1"			},
-  { "em_steel_exit.opening",			"RocksDC2.pcx"	},
+  { "em_steel_exit.opening",			"RocksDC2.png"	},
   { "em_steel_exit.opening.xpos",		"0"			},
   { "em_steel_exit.opening.ypos",		"5"			},
   { "em_steel_exit.opening.frames",		"5"			},
   { "em_steel_exit.opening.delay",		"6"			},
   { "em_steel_exit.opening.anim_mode",		"linear"		},
-  { "em_steel_exit_open",			"RocksDC2.pcx"	},
+  { "em_steel_exit_open",			"RocksDC2.png"	},
   { "em_steel_exit_open.xpos",			"4"			},
   { "em_steel_exit_open.ypos",			"5"			},
   { "em_steel_exit_open.frames",		"4"			},
   { "em_steel_exit_open.delay",			"4"			},
   { "em_steel_exit_open.anim_mode",		"pingpong"		},
-  { "em_steel_exit.closing",			"RocksDC2.pcx"	},
+  { "em_steel_exit.closing",			"RocksDC2.png"	},
   { "em_steel_exit.closing.xpos",		"0"			},
   { "em_steel_exit.closing.ypos",		"7"			},
   { "em_steel_exit.closing.frames",		"5"			},
@@ -1710,805 +1722,805 @@ struct ConfigInfo image_config[] =
 
   /* images for Emerald Mine Club style elements and actions */
 
-  { "balloon",					"RocksDC.pcx"		},
+  { "balloon",					"RocksDC.png"		},
   { "balloon.xpos",				"12"			},
   { "balloon.ypos",				"7"			},
   { "balloon.frames",				"1"			},
-  { "balloon.moving",				"RocksDC.pcx"		},
+  { "balloon.moving",				"RocksDC.png"		},
   { "balloon.moving.xpos",			"12"			},
   { "balloon.moving.ypos",			"7"			},
   { "balloon.moving.frames",			"4"			},
   { "balloon.moving.anim_mode",			"pingpong"		},
   { "balloon.moving.delay",			"2"			},
-  { "balloon.pushing",				"RocksDC.pcx"		},
+  { "balloon.pushing",				"RocksDC.png"		},
   { "balloon.pushing.xpos",			"12"			},
   { "balloon.pushing.ypos",			"7"			},
   { "balloon.pushing.frames",			"4"			},
   { "balloon.pushing.anim_mode",		"pingpong"		},
   { "balloon.pushing.delay",			"2"			},
-  { "balloon_switch_left",			"RocksDC.pcx"		},
+  { "balloon_switch_left",			"RocksDC.png"		},
   { "balloon_switch_left.xpos",			"8"			},
   { "balloon_switch_left.ypos",			"7"			},
   { "balloon_switch_left.frames",		"1"			},
-  { "balloon_switch_right",			"RocksDC.pcx"		},
+  { "balloon_switch_right",			"RocksDC.png"		},
   { "balloon_switch_right.xpos",		"9"			},
   { "balloon_switch_right.ypos",		"7"			},
   { "balloon_switch_right.frames",		"1"			},
-  { "balloon_switch_up",			"RocksDC.pcx"		},
+  { "balloon_switch_up",			"RocksDC.png"		},
   { "balloon_switch_up.xpos",			"10"			},
   { "balloon_switch_up.ypos",			"7"			},
   { "balloon_switch_up.frames",			"1"			},
-  { "balloon_switch_down",			"RocksDC.pcx"		},
+  { "balloon_switch_down",			"RocksDC.png"		},
   { "balloon_switch_down.xpos",			"11"			},
   { "balloon_switch_down.ypos",			"7"			},
   { "balloon_switch_down.frames",		"1"			},
-  { "balloon_switch_any",			"RocksDC.pcx"		},
+  { "balloon_switch_any",			"RocksDC.png"		},
   { "balloon_switch_any.xpos",			"15"			},
   { "balloon_switch_any.ypos",			"0"			},
   { "balloon_switch_any.frames",		"1"			},
-  { "balloon_switch_none",			"RocksDC.pcx"		},
+  { "balloon_switch_none",			"RocksDC.png"		},
   { "balloon_switch_none.xpos",			"13"			},
   { "balloon_switch_none.ypos",			"5"			},
   { "balloon_switch_none.frames",		"1"			},
 
-  { "spring",					"RocksDC.pcx"		},
+  { "spring",					"RocksDC.png"		},
   { "spring.xpos",				"8"			},
   { "spring.ypos",				"13"			},
   { "spring.frames",				"1"			},
 
-  { "emc_steelwall_1",				"RocksDC.pcx"		},
+  { "emc_steelwall_1",				"RocksDC.png"		},
   { "emc_steelwall_1.xpos",			"14"			},
   { "emc_steelwall_1.ypos",			"0"			},
   { "emc_steelwall_1.frames",			"1"			},
-  { "emc_steelwall_2",				"RocksEMC.pcx"		},
+  { "emc_steelwall_2",				"RocksEMC.png"		},
   { "emc_steelwall_2.xpos",			"9"			},
   { "emc_steelwall_2.ypos",			"8"			},
   { "emc_steelwall_2.frames",			"1"			},
-  { "emc_steelwall_3",				"RocksEMC.pcx"		},
+  { "emc_steelwall_3",				"RocksEMC.png"		},
   { "emc_steelwall_3.xpos",			"9"			},
   { "emc_steelwall_3.ypos",			"9"			},
   { "emc_steelwall_3.frames",			"1"			},
-  { "emc_steelwall_4",				"RocksEMC.pcx"		},
+  { "emc_steelwall_4",				"RocksEMC.png"		},
   { "emc_steelwall_4.xpos",			"9"			},
   { "emc_steelwall_4.ypos",			"10"			},
   { "emc_steelwall_4.frames",			"1"			},
 
-  { "emc_wall_1",				"RocksDC.pcx"		},
+  { "emc_wall_1",				"RocksDC.png"		},
   { "emc_wall_1.xpos",				"13"			},
   { "emc_wall_1.ypos",				"6"			},
   { "emc_wall_1.frames",			"1"			},
-  { "emc_wall_2",				"RocksDC.pcx"		},
+  { "emc_wall_2",				"RocksDC.png"		},
   { "emc_wall_2.xpos",				"14"			},
   { "emc_wall_2.ypos",				"6"			},
   { "emc_wall_2.frames",			"1"			},
-  { "emc_wall_3",				"RocksDC.pcx"		},
+  { "emc_wall_3",				"RocksDC.png"		},
   { "emc_wall_3.xpos",				"15"			},
   { "emc_wall_3.ypos",				"6"			},
   { "emc_wall_3.frames",			"1"			},
-  { "emc_wall_4",				"RocksDC.pcx"		},
+  { "emc_wall_4",				"RocksDC.png"		},
   { "emc_wall_4.xpos",				"14"			},
   { "emc_wall_4.ypos",				"1"			},
   { "emc_wall_4.frames",			"1"			},
-  { "emc_wall_5",				"RocksDC.pcx"		},
+  { "emc_wall_5",				"RocksDC.png"		},
   { "emc_wall_5.xpos",				"15"			},
   { "emc_wall_5.ypos",				"1"			},
   { "emc_wall_5.frames",			"1"			},
-  { "emc_wall_6",				"RocksDC.pcx"		},
+  { "emc_wall_6",				"RocksDC.png"		},
   { "emc_wall_6.xpos",				"14"			},
   { "emc_wall_6.ypos",				"2"			},
   { "emc_wall_6.frames",			"1"			},
-  { "emc_wall_7",				"RocksDC.pcx"		},
+  { "emc_wall_7",				"RocksDC.png"		},
   { "emc_wall_7.xpos",				"15"			},
   { "emc_wall_7.ypos",				"2"			},
   { "emc_wall_7.frames",			"1"			},
-  { "emc_wall_8",				"RocksEMC.pcx"		},
+  { "emc_wall_8",				"RocksEMC.png"		},
   { "emc_wall_8.xpos",				"8"			},
   { "emc_wall_8.ypos",				"7"			},
   { "emc_wall_8.frames",			"1"			},
 
   /* images for Diamond Caves style elements and actions */
 
-  { "invisible_steelwall",			"RocksSP.pcx"		},
+  { "invisible_steelwall",			"RocksSP.png"		},
   { "invisible_steelwall.xpos",			"3"			},
   { "invisible_steelwall.ypos",			"5"			},
   { "invisible_steelwall.frames",		"1"			},
-  { "invisible_steelwall.EDITOR",		"RocksSP.pcx"		},
+  { "invisible_steelwall.EDITOR",		"RocksSP.png"		},
   { "invisible_steelwall.EDITOR.xpos",		"1"			},
   { "invisible_steelwall.EDITOR.ypos",		"5"			},
-  { "invisible_steelwall.active",		"RocksSP.pcx"		},
+  { "invisible_steelwall.active",		"RocksSP.png"		},
   { "invisible_steelwall.active.xpos",		"1"			},
   { "invisible_steelwall.active.ypos",		"5"			},
   { "invisible_steelwall.active.frames",	"1"			},
 
-  { "invisible_wall",				"RocksSP.pcx"		},
+  { "invisible_wall",				"RocksSP.png"		},
   { "invisible_wall.xpos",			"7"			},
   { "invisible_wall.ypos",			"5"			},
   { "invisible_wall.frames",			"1"			},
-  { "invisible_wall.EDITOR",			"RocksSP.pcx"		},
+  { "invisible_wall.EDITOR",			"RocksSP.png"		},
   { "invisible_wall.EDITOR.xpos",		"5"			},
   { "invisible_wall.EDITOR.ypos",		"5"			},
-  { "invisible_wall.active",			"RocksSP.pcx"		},
+  { "invisible_wall.active",			"RocksSP.png"		},
   { "invisible_wall.active.xpos",		"5"			},
   { "invisible_wall.active.ypos",		"5"			},
   { "invisible_wall.active.frames",		"1"			},
 
-  { "invisible_sand",				"RocksSP.pcx"		},
+  { "invisible_sand",				"RocksSP.png"		},
   { "invisible_sand.xpos",			"0"			},
   { "invisible_sand.ypos",			"0"			},
   { "invisible_sand.frames",			"1"			},
-  { "invisible_sand.EDITOR",			"RocksEMC.pcx"		},
+  { "invisible_sand.EDITOR",			"RocksEMC.png"		},
   { "invisible_sand.EDITOR.xpos",		"2"			},
   { "invisible_sand.EDITOR.ypos",		"4"			},
-  { "invisible_sand.active",			"RocksEMC.pcx"		},
+  { "invisible_sand.active",			"RocksEMC.png"		},
   { "invisible_sand.active.xpos",		"2"			},
   { "invisible_sand.active.ypos",		"4"			},
   { "invisible_sand.active.frames",		"1"			},
-  { "invisible_sand.active.CRUMBLED",		"RocksEMC.pcx"		},
+  { "invisible_sand.active.CRUMBLED",		"RocksEMC.png"		},
   { "invisible_sand.active.CRUMBLED.xpos",	"3"			},
   { "invisible_sand.active.CRUMBLED.ypos",	"4"			},
   { "invisible_sand.active.CRUMBLED.frames",	"1"			},
-  { "invisible_sand.active.digging.left",	"RocksEMC.pcx"		},
+  { "invisible_sand.active.digging.left",	"RocksEMC.png"		},
   { "invisible_sand.active.digging.left.xpos",	"6"			},
   { "invisible_sand.active.digging.left.ypos",	"2"			},
   { "invisible_sand.active.digging.left.frames","3"			},
   { "invisible_sand.active.digging.left.delay",	"2"			},
   { "invisible_sand.active.digging.left.anim_mode","linear"		},
-  { "invisible_sand.active.digging.right",	"RocksEMC.pcx"		},
+  { "invisible_sand.active.digging.right",	"RocksEMC.png"		},
   { "invisible_sand.active.digging.right.xpos",	"9"			},
   { "invisible_sand.active.digging.right.ypos",	"2"			},
   { "invisible_sand.active.digging.right.frames","3"			},
   { "invisible_sand.active.digging.right.delay","2"			},
   { "invisible_sand.active.digging.right.anim_mode","linear"		},
-  { "invisible_sand.active.digging.up",		"RocksEMC.pcx"		},
+  { "invisible_sand.active.digging.up",		"RocksEMC.png"		},
   { "invisible_sand.active.digging.up.xpos",	"0"			},
   { "invisible_sand.active.digging.up.ypos",	"2"			},
   { "invisible_sand.active.digging.up.frames",	"3"			},
   { "invisible_sand.active.digging.up.delay",	"2"			},
   { "invisible_sand.active.digging.up.anim_mode","linear"		},
-  { "invisible_sand.active.digging.down",	"RocksEMC.pcx"		},
+  { "invisible_sand.active.digging.down",	"RocksEMC.png"		},
   { "invisible_sand.active.digging.down.xpos",	"3"			},
   { "invisible_sand.active.digging.down.ypos",	"2"			},
   { "invisible_sand.active.digging.down.frames","3"			},
   { "invisible_sand.active.digging.down.delay",	"2"			},
   { "invisible_sand.active.digging.down.anim_mode","linear"		},
-  { "invisible_sand.active.digging.left.CRUMBLED",	"RocksEMC.pcx"	},
+  { "invisible_sand.active.digging.left.CRUMBLED",	"RocksEMC.png"	},
   { "invisible_sand.active.digging.left.CRUMBLED.xpos",	"6"		},
   { "invisible_sand.active.digging.left.CRUMBLED.ypos",	"3"		},
   { "invisible_sand.active.digging.left.CRUMBLED.frames","3"		},
   { "invisible_sand.active.digging.left.CRUMBLED.delay","2"		},
   { "invisible_sand.active.digging.left.CRUMBLED.anim_mode","linear"	},
-  { "invisible_sand.active.digging.right.CRUMBLED",	"RocksEMC.pcx"	},
+  { "invisible_sand.active.digging.right.CRUMBLED",	"RocksEMC.png"	},
   { "invisible_sand.active.digging.right.CRUMBLED.xpos","9"		},
   { "invisible_sand.active.digging.right.CRUMBLED.ypos","3"		},
   { "invisible_sand.active.digging.right.CRUMBLED.frames","3"		},
   { "invisible_sand.active.digging.right.CRUMBLED.delay","2"		},
   { "invisible_sand.active.digging.right.CRUMBLED.anim_mode","linear"	},
-  { "invisible_sand.active.digging.up.CRUMBLED",	"RocksEMC.pcx"	},
+  { "invisible_sand.active.digging.up.CRUMBLED",	"RocksEMC.png"	},
   { "invisible_sand.active.digging.up.CRUMBLED.xpos",	"0"		},
   { "invisible_sand.active.digging.up.CRUMBLED.ypos",	"3"		},
   { "invisible_sand.active.digging.up.CRUMBLED.frames",	"3"		},
   { "invisible_sand.active.digging.up.CRUMBLED.delay",	"2"		},
   { "invisible_sand.active.digging.up.CRUMBLED.anim_mode","linear"	},
-  { "invisible_sand.active.digging.down.CRUMBLED",	"RocksEMC.pcx"	},
+  { "invisible_sand.active.digging.down.CRUMBLED",	"RocksEMC.png"	},
   { "invisible_sand.active.digging.down.CRUMBLED.xpos",	"3"		},
   { "invisible_sand.active.digging.down.CRUMBLED.ypos",	"3"		},
   { "invisible_sand.active.digging.down.CRUMBLED.frames","3"		},
   { "invisible_sand.active.digging.down.CRUMBLED.delay","2"		},
   { "invisible_sand.active.digging.down.CRUMBLED.anim_mode","linear"	},
 
-  { "conveyor_belt_1_middle",			"RocksDC.pcx"		},
+  { "conveyor_belt_1_middle",			"RocksDC.png"		},
   { "conveyor_belt_1_middle.xpos",		"0"			},
   { "conveyor_belt_1_middle.ypos",		"0"			},
   { "conveyor_belt_1_middle.frames",		"1"			},
-  { "conveyor_belt_1_middle.active",		"RocksDC.pcx"		},
+  { "conveyor_belt_1_middle.active",		"RocksDC.png"		},
   { "conveyor_belt_1_middle.active.xpos",	"0"			},
   { "conveyor_belt_1_middle.active.ypos",	"0"			},
   { "conveyor_belt_1_middle.active.frames",	"8"			},
   { "conveyor_belt_1_middle.active.delay",	"2"			},
-  { "conveyor_belt_1_left",			"RocksDC.pcx"		},
+  { "conveyor_belt_1_left",			"RocksDC.png"		},
   { "conveyor_belt_1_left.xpos",		"0"			},
   { "conveyor_belt_1_left.ypos",		"1"			},
   { "conveyor_belt_1_left.frames",		"1"			},
-  { "conveyor_belt_1_left.active",		"RocksDC.pcx"		},
+  { "conveyor_belt_1_left.active",		"RocksDC.png"		},
   { "conveyor_belt_1_left.active.xpos",		"0"			},
   { "conveyor_belt_1_left.active.ypos",		"1"			},
   { "conveyor_belt_1_left.active.frames",	"8"			},
   { "conveyor_belt_1_left.active.delay",	"2"			},
-  { "conveyor_belt_1_right",			"RocksDC.pcx"		},
+  { "conveyor_belt_1_right",			"RocksDC.png"		},
   { "conveyor_belt_1_right.xpos",		"0"			},
   { "conveyor_belt_1_right.ypos",		"2"			},
   { "conveyor_belt_1_right.frames",		"1"			},
-  { "conveyor_belt_1_right.active",		"RocksDC.pcx"		},
+  { "conveyor_belt_1_right.active",		"RocksDC.png"		},
   { "conveyor_belt_1_right.active.xpos",	"0"			},
   { "conveyor_belt_1_right.active.ypos",	"2"			},
   { "conveyor_belt_1_right.active.frames",	"8"			},
   { "conveyor_belt_1_right.active.delay",	"2"			},
-  { "conveyor_belt_1_switch_left",		"RocksDC.pcx"		},
+  { "conveyor_belt_1_switch_left",		"RocksDC.png"		},
   { "conveyor_belt_1_switch_left.xpos",		"0"			},
   { "conveyor_belt_1_switch_left.ypos",		"12"			},
   { "conveyor_belt_1_switch_left.frames",	"1"			},
-  { "conveyor_belt_1_switch_middle",		"RocksDC.pcx"		},
+  { "conveyor_belt_1_switch_middle",		"RocksDC.png"		},
   { "conveyor_belt_1_switch_middle.xpos",	"0"			},
   { "conveyor_belt_1_switch_middle.ypos",	"13"			},
   { "conveyor_belt_1_switch_middle.frames",	"1"			},
-  { "conveyor_belt_1_switch_right",		"RocksDC.pcx"		},
+  { "conveyor_belt_1_switch_right",		"RocksDC.png"		},
   { "conveyor_belt_1_switch_right.xpos",	"0"			},
   { "conveyor_belt_1_switch_right.ypos",	"14"			},
   { "conveyor_belt_1_switch_right.frames",	"1"			},
 
-  { "conveyor_belt_2_middle",			"RocksDC.pcx"		},
+  { "conveyor_belt_2_middle",			"RocksDC.png"		},
   { "conveyor_belt_2_middle.xpos",		"0"			},
   { "conveyor_belt_2_middle.ypos",		"3"			},
   { "conveyor_belt_2_middle.frames",		"1"			},
-  { "conveyor_belt_2_middle.active",		"RocksDC.pcx"		},
+  { "conveyor_belt_2_middle.active",		"RocksDC.png"		},
   { "conveyor_belt_2_middle.active.xpos",	"0"			},
   { "conveyor_belt_2_middle.active.ypos",	"3"			},
   { "conveyor_belt_2_middle.active.frames",	"8"			},
   { "conveyor_belt_2_middle.active.delay",	"2"			},
-  { "conveyor_belt_2_left",			"RocksDC.pcx"		},
+  { "conveyor_belt_2_left",			"RocksDC.png"		},
   { "conveyor_belt_2_left.xpos",		"0"			},
   { "conveyor_belt_2_left.ypos",		"4"			},
   { "conveyor_belt_2_left.frames",		"1"			},
-  { "conveyor_belt_2_left.active",		"RocksDC.pcx"		},
+  { "conveyor_belt_2_left.active",		"RocksDC.png"		},
   { "conveyor_belt_2_left.active.xpos",		"0"			},
   { "conveyor_belt_2_left.active.ypos",		"4"			},
   { "conveyor_belt_2_left.active.frames",	"8"			},
   { "conveyor_belt_2_left.active.delay",	"2"			},
-  { "conveyor_belt_2_right",			"RocksDC.pcx"		},
+  { "conveyor_belt_2_right",			"RocksDC.png"		},
   { "conveyor_belt_2_right.xpos",		"0"			},
   { "conveyor_belt_2_right.ypos",		"5"			},
   { "conveyor_belt_2_right.frames",		"1"			},
-  { "conveyor_belt_2_right.active",		"RocksDC.pcx"		},
+  { "conveyor_belt_2_right.active",		"RocksDC.png"		},
   { "conveyor_belt_2_right.active.xpos",	"0"			},
   { "conveyor_belt_2_right.active.ypos",	"5"			},
   { "conveyor_belt_2_right.active.frames",	"8"			},
   { "conveyor_belt_2_right.active.delay",	"2"			},
-  { "conveyor_belt_2_switch_left",		"RocksDC.pcx"		},
+  { "conveyor_belt_2_switch_left",		"RocksDC.png"		},
   { "conveyor_belt_2_switch_left.xpos",		"1"			},
   { "conveyor_belt_2_switch_left.ypos",		"12"			},
   { "conveyor_belt_2_switch_left.frames",	"1"			},
-  { "conveyor_belt_2_switch_middle",		"RocksDC.pcx"		},
+  { "conveyor_belt_2_switch_middle",		"RocksDC.png"		},
   { "conveyor_belt_2_switch_middle.xpos",	"1"			},
   { "conveyor_belt_2_switch_middle.ypos",	"13"			},
   { "conveyor_belt_2_switch_middle.frames",	"1"			},
-  { "conveyor_belt_2_switch_right",		"RocksDC.pcx"		},
+  { "conveyor_belt_2_switch_right",		"RocksDC.png"		},
   { "conveyor_belt_2_switch_right.xpos",	"1"			},
   { "conveyor_belt_2_switch_right.ypos",	"14"			},
   { "conveyor_belt_2_switch_right.frames",	"1"			},
 
-  { "conveyor_belt_3_middle",			"RocksDC.pcx"		},
+  { "conveyor_belt_3_middle",			"RocksDC.png"		},
   { "conveyor_belt_3_middle.xpos",		"0"			},
   { "conveyor_belt_3_middle.ypos",		"6"			},
   { "conveyor_belt_3_middle.frames",		"1"			},
-  { "conveyor_belt_3_middle.active",		"RocksDC.pcx"		},
+  { "conveyor_belt_3_middle.active",		"RocksDC.png"		},
   { "conveyor_belt_3_middle.active.xpos",	"0"			},
   { "conveyor_belt_3_middle.active.ypos",	"6"			},
   { "conveyor_belt_3_middle.active.frames",	"8"			},
   { "conveyor_belt_3_middle.active.delay",	"2"			},
-  { "conveyor_belt_3_left",			"RocksDC.pcx"		},
+  { "conveyor_belt_3_left",			"RocksDC.png"		},
   { "conveyor_belt_3_left.xpos",		"0"			},
   { "conveyor_belt_3_left.ypos",		"7"			},
   { "conveyor_belt_3_left.frames",		"1"			},
-  { "conveyor_belt_3_left.active",		"RocksDC.pcx"		},
+  { "conveyor_belt_3_left.active",		"RocksDC.png"		},
   { "conveyor_belt_3_left.active.xpos",		"0"			},
   { "conveyor_belt_3_left.active.ypos",		"7"			},
   { "conveyor_belt_3_left.active.frames",	"8"			},
   { "conveyor_belt_3_left.active.delay",	"2"			},
-  { "conveyor_belt_3_right",			"RocksDC.pcx"		},
+  { "conveyor_belt_3_right",			"RocksDC.png"		},
   { "conveyor_belt_3_right.xpos",		"0"			},
   { "conveyor_belt_3_right.ypos",		"8"			},
   { "conveyor_belt_3_right.frames",		"1"			},
-  { "conveyor_belt_3_right.active",		"RocksDC.pcx"		},
+  { "conveyor_belt_3_right.active",		"RocksDC.png"		},
   { "conveyor_belt_3_right.active.xpos",	"0"			},
   { "conveyor_belt_3_right.active.ypos",	"8"			},
   { "conveyor_belt_3_right.active.frames",	"8"			},
   { "conveyor_belt_3_right.active.delay",	"2"			},
-  { "conveyor_belt_3_switch_left",		"RocksDC.pcx"		},
+  { "conveyor_belt_3_switch_left",		"RocksDC.png"		},
   { "conveyor_belt_3_switch_left.xpos",		"2"			},
   { "conveyor_belt_3_switch_left.ypos",		"12"			},
   { "conveyor_belt_3_switch_left.frames",	"1"			},
-  { "conveyor_belt_3_switch_middle",		"RocksDC.pcx"		},
+  { "conveyor_belt_3_switch_middle",		"RocksDC.png"		},
   { "conveyor_belt_3_switch_middle.xpos",	"2"			},
   { "conveyor_belt_3_switch_middle.ypos",	"13"			},
   { "conveyor_belt_3_switch_middle.frames",	"1"			},
-  { "conveyor_belt_3_switch_right",		"RocksDC.pcx"		},
+  { "conveyor_belt_3_switch_right",		"RocksDC.png"		},
   { "conveyor_belt_3_switch_right.xpos",	"2"			},
   { "conveyor_belt_3_switch_right.ypos",	"14"			},
   { "conveyor_belt_3_switch_right.frames",	"1"			},
 
-  { "conveyor_belt_4_middle",			"RocksDC.pcx"		},
+  { "conveyor_belt_4_middle",			"RocksDC.png"		},
   { "conveyor_belt_4_middle.xpos",		"0"			},
   { "conveyor_belt_4_middle.ypos",		"9"			},
   { "conveyor_belt_4_middle.frames",		"1"			},
-  { "conveyor_belt_4_middle.active",		"RocksDC.pcx"		},
+  { "conveyor_belt_4_middle.active",		"RocksDC.png"		},
   { "conveyor_belt_4_middle.active.xpos",	"0"			},
   { "conveyor_belt_4_middle.active.ypos",	"9"			},
   { "conveyor_belt_4_middle.active.frames",	"8"			},
   { "conveyor_belt_4_middle.active.delay",	"2"			},
-  { "conveyor_belt_4_left",			"RocksDC.pcx"		},
+  { "conveyor_belt_4_left",			"RocksDC.png"		},
   { "conveyor_belt_4_left.xpos",		"0"			},
   { "conveyor_belt_4_left.ypos",		"10"			},
   { "conveyor_belt_4_left.frames",		"1"			},
-  { "conveyor_belt_4_left.active",		"RocksDC.pcx"		},
+  { "conveyor_belt_4_left.active",		"RocksDC.png"		},
   { "conveyor_belt_4_left.active.xpos",		"0"			},
   { "conveyor_belt_4_left.active.ypos",		"10"			},
   { "conveyor_belt_4_left.active.frames",	"8"			},
   { "conveyor_belt_4_left.active.delay",	"2"			},
-  { "conveyor_belt_4_right",			"RocksDC.pcx"		},
+  { "conveyor_belt_4_right",			"RocksDC.png"		},
   { "conveyor_belt_4_right.xpos",		"0"			},
   { "conveyor_belt_4_right.ypos",		"11"			},
   { "conveyor_belt_4_right.frames",		"1"			},
-  { "conveyor_belt_4_right.active",		"RocksDC.pcx"		},
+  { "conveyor_belt_4_right.active",		"RocksDC.png"		},
   { "conveyor_belt_4_right.active.xpos",	"0"			},
   { "conveyor_belt_4_right.active.ypos",	"11"			},
   { "conveyor_belt_4_right.active.frames",	"8"			},
   { "conveyor_belt_4_right.active.delay",	"2"			},
-  { "conveyor_belt_4_switch_left",		"RocksDC.pcx"		},
+  { "conveyor_belt_4_switch_left",		"RocksDC.png"		},
   { "conveyor_belt_4_switch_left.xpos",		"3"			},
   { "conveyor_belt_4_switch_left.ypos",		"12"			},
   { "conveyor_belt_4_switch_left.frames",	"1"			},
-  { "conveyor_belt_4_switch_middle",		"RocksDC.pcx"		},
+  { "conveyor_belt_4_switch_middle",		"RocksDC.png"		},
   { "conveyor_belt_4_switch_middle.xpos",	"3"			},
   { "conveyor_belt_4_switch_middle.ypos",	"13"			},
   { "conveyor_belt_4_switch_middle.frames",	"1"			},
-  { "conveyor_belt_4_switch_right",		"RocksDC.pcx"		},
+  { "conveyor_belt_4_switch_right",		"RocksDC.png"		},
   { "conveyor_belt_4_switch_right.xpos",	"3"			},
   { "conveyor_belt_4_switch_right.ypos",	"14"			},
   { "conveyor_belt_4_switch_right.frames",	"1"			},
 
-  { "switchgate_switch_up",			"RocksDC.pcx"		},
+  { "switchgate_switch_up",			"RocksDC.png"		},
   { "switchgate_switch_up.xpos",		"4"			},
   { "switchgate_switch_up.ypos",		"12"			},
   { "switchgate_switch_up.frames",		"1"			},
-  { "switchgate_switch_down",			"RocksDC.pcx"		},
+  { "switchgate_switch_down",			"RocksDC.png"		},
   { "switchgate_switch_down.xpos",		"5"			},
   { "switchgate_switch_down.ypos",		"12"			},
   { "switchgate_switch_down.frames",		"1"			},
 
-  { "dc_switchgate_switch_up",			"RocksDC2.pcx"		},
+  { "dc_switchgate_switch_up",			"RocksDC2.png"		},
   { "dc_switchgate_switch_up.xpos",		"10"			},
   { "dc_switchgate_switch_up.ypos",		"1"			},
   { "dc_switchgate_switch_up.frames",		"1"			},
-  { "dc_switchgate_switch_down",		"RocksDC2.pcx"		},
+  { "dc_switchgate_switch_down",		"RocksDC2.png"		},
   { "dc_switchgate_switch_down.xpos",		"11"			},
   { "dc_switchgate_switch_down.ypos",		"1"			},
   { "dc_switchgate_switch_down.frames",		"1"			},
 
-  { "light_switch",				"RocksDC.pcx"		},
+  { "light_switch",				"RocksDC.png"		},
   { "light_switch.xpos",			"6"			},
   { "light_switch.ypos",			"12"			},
   { "light_switch.frames",			"1"			},
-  { "light_switch.active",			"RocksDC.pcx"		},
+  { "light_switch.active",			"RocksDC.png"		},
   { "light_switch.active.xpos",			"7"			},
   { "light_switch.active.ypos",			"12"			},
   { "light_switch.active.frames",		"1"			},
 
-  { "timegate_switch",				"RocksDC.pcx"		},
+  { "timegate_switch",				"RocksDC.png"		},
   { "timegate_switch.xpos",			"0"			},
   { "timegate_switch.ypos",			"15"			},
   { "timegate_switch.frames",			"1"			},
-  { "timegate_switch.active",			"RocksDC.pcx"		},
+  { "timegate_switch.active",			"RocksDC.png"		},
   { "timegate_switch.active.xpos",		"0"			},
   { "timegate_switch.active.ypos",		"15"			},
   { "timegate_switch.active.frames",		"4"			},
 
-  { "dc_timegate_switch",			"RocksDC2.pcx"		},
+  { "dc_timegate_switch",			"RocksDC2.png"		},
   { "dc_timegate_switch.xpos",			"12"			},
   { "dc_timegate_switch.ypos",			"1"			},
   { "dc_timegate_switch.frames",		"1"			},
-  { "dc_timegate_switch.active",		"RocksDC2.pcx"		},
+  { "dc_timegate_switch.active",		"RocksDC2.png"		},
   { "dc_timegate_switch.active.xpos",		"12"			},
   { "dc_timegate_switch.active.ypos",		"1"			},
   { "dc_timegate_switch.active.frames",		"4"			},
 
-  { "envelope_1",				"RocksMore.pcx"		},
+  { "envelope_1",				"RocksMore.png"		},
   { "envelope_1.xpos",				"0"			},
   { "envelope_1.ypos",				"4"			},
   { "envelope_1.frames",			"1"			},
-  { "envelope_1.collecting",			"RocksMore.pcx"		},
+  { "envelope_1.collecting",			"RocksMore.png"		},
   { "envelope_1.collecting.xpos",		"5"			},
   { "envelope_1.collecting.ypos",		"4"			},
   { "envelope_1.collecting.frames",		"3"			},
   { "envelope_1.collecting.delay",		"2"			},
   { "envelope_1.collecting.anim_mode",		"linear"		},
-  { "envelope_2",				"RocksMore.pcx"		},
+  { "envelope_2",				"RocksMore.png"		},
   { "envelope_2.xpos",				"1"			},
   { "envelope_2.ypos",				"4"			},
   { "envelope_2.frames",			"1"			},
-  { "envelope_2.collecting",			"RocksMore.pcx"		},
+  { "envelope_2.collecting",			"RocksMore.png"		},
   { "envelope_2.collecting.xpos",		"5"			},
   { "envelope_2.collecting.ypos",		"4"			},
   { "envelope_2.collecting.frames",		"3"			},
   { "envelope_2.collecting.delay",		"2"			},
   { "envelope_2.collecting.anim_mode",		"linear"		},
-  { "envelope_3",				"RocksMore.pcx"		},
+  { "envelope_3",				"RocksMore.png"		},
   { "envelope_3.xpos",				"2"			},
   { "envelope_3.ypos",				"4"			},
   { "envelope_3.frames",			"1"			},
-  { "envelope_3.collecting",			"RocksMore.pcx"		},
+  { "envelope_3.collecting",			"RocksMore.png"		},
   { "envelope_3.collecting.xpos",		"5"			},
   { "envelope_3.collecting.ypos",		"4"			},
   { "envelope_3.collecting.frames",		"3"			},
   { "envelope_3.collecting.delay",		"2"			},
   { "envelope_3.collecting.anim_mode",		"linear"		},
-  { "envelope_4",				"RocksMore.pcx"		},
+  { "envelope_4",				"RocksMore.png"		},
   { "envelope_4.xpos",				"3"			},
   { "envelope_4.ypos",				"4"			},
   { "envelope_4.frames",			"1"			},
-  { "envelope_4.collecting",			"RocksMore.pcx"		},
+  { "envelope_4.collecting",			"RocksMore.png"		},
   { "envelope_4.collecting.xpos",		"5"			},
   { "envelope_4.collecting.ypos",		"4"			},
   { "envelope_4.collecting.frames",		"3"			},
   { "envelope_4.collecting.delay",		"2"			},
   { "envelope_4.collecting.anim_mode",		"linear"		},
 
-  { "sign_radioactivity",			"RocksDC.pcx"		},
+  { "sign_radioactivity",			"RocksDC.png"		},
   { "sign_radioactivity.xpos",			"4"			},
   { "sign_radioactivity.ypos",			"13"			},
   { "sign_radioactivity.frames",		"1"			},
 
-  { "sign_give_way",				"RocksDC.pcx"		},
+  { "sign_give_way",				"RocksDC.png"		},
   { "sign_give_way.xpos",			"5"			},
   { "sign_give_way.ypos",			"13"			},
   { "sign_give_way.frames",			"1"			},
 
-  { "sign_no_entry",				"RocksDC.pcx"		},
+  { "sign_no_entry",				"RocksDC.png"		},
   { "sign_no_entry.xpos",			"6"			},
   { "sign_no_entry.ypos",			"13"			},
   { "sign_no_entry.frames",			"1"			},
 
-  { "sign_emergency_exit",			"RocksDC.pcx"		},
+  { "sign_emergency_exit",			"RocksDC.png"		},
   { "sign_emergency_exit.xpos",			"7"			},
   { "sign_emergency_exit.ypos",			"13"			},
   { "sign_emergency_exit.frames",		"1"			},
 
-  { "sign_yin_yang",				"RocksDC.pcx"		},
+  { "sign_yin_yang",				"RocksDC.png"		},
   { "sign_yin_yang.xpos",			"4"			},
   { "sign_yin_yang.ypos",			"14"			},
   { "sign_yin_yang.frames",			"1"			},
 
-  { "sign_exclamation",				"RocksDC.pcx"		},
+  { "sign_exclamation",				"RocksDC.png"		},
   { "sign_exclamation.xpos",			"5"			},
   { "sign_exclamation.ypos",			"14"			},
   { "sign_exclamation.frames",			"1"			},
 
-  { "sign_stop",				"RocksDC.pcx"		},
+  { "sign_stop",				"RocksDC.png"		},
   { "sign_stop.xpos",				"6"			},
   { "sign_stop.ypos",				"14"			},
   { "sign_stop.frames",				"1"			},
 
-  { "sign_parking",				"RocksDC.pcx"		},
+  { "sign_parking",				"RocksDC.png"		},
   { "sign_parking.xpos",			"6"			},
   { "sign_parking.ypos",			"15"			},
   { "sign_parking.frames",			"1"			},
 
-  { "sign_wheelchair",				"RocksDC.pcx"		},
+  { "sign_wheelchair",				"RocksDC.png"		},
   { "sign_wheelchair.xpos",			"7"			},
   { "sign_wheelchair.ypos",			"15"			},
   { "sign_wheelchair.frames",			"1"			},
 
-  { "sign_entry_forbidden",			"RocksDC.pcx"		},
+  { "sign_entry_forbidden",			"RocksDC.png"		},
   { "sign_entry_forbidden.xpos",		"12"			},
   { "sign_entry_forbidden.ypos",		"15"			},
   { "sign_entry_forbidden.frames",		"1"			},
 
-  { "sperms",					"RocksDC2.pcx"		},
+  { "sperms",					"RocksDC2.png"		},
   { "sperms.xpos",				"11"			},
   { "sperms.ypos",				"3"			},
   { "sperms.frames",				"1"			},
 
-  { "bullet",					"RocksDC2.pcx"		},
+  { "bullet",					"RocksDC2.png"		},
   { "bullet.xpos",				"12"			},
   { "bullet.ypos",				"3"			},
   { "bullet.frames",				"1"			},
 
-  { "heart",					"RocksDC2.pcx"		},
+  { "heart",					"RocksDC2.png"		},
   { "heart.xpos",				"13"			},
   { "heart.ypos",				"3"			},
   { "heart.frames",				"1"			},
 
-  { "cross",					"RocksDC2.pcx"		},
+  { "cross",					"RocksDC2.png"		},
   { "cross.xpos",				"14"			},
   { "cross.ypos",				"3"			},
   { "cross.frames",				"1"			},
 
-  { "frankie",					"RocksDC2.pcx"		},
+  { "frankie",					"RocksDC2.png"		},
   { "frankie.xpos",				"15"			},
   { "frankie.ypos",				"3"			},
   { "frankie.frames",				"1"			},
 
-  { "sign_sperms",				"RocksDC2.pcx"		},
+  { "sign_sperms",				"RocksDC2.png"		},
   { "sign_sperms.xpos",				"11"			},
   { "sign_sperms.ypos",				"2"			},
   { "sign_sperms.frames",			"1"			},
 
-  { "sign_bullet",				"RocksDC2.pcx"		},
+  { "sign_bullet",				"RocksDC2.png"		},
   { "sign_bullet.xpos",				"12"			},
   { "sign_bullet.ypos",				"2"			},
   { "sign_bullet.frames",			"1"			},
 
-  { "sign_heart",				"RocksDC2.pcx"		},
+  { "sign_heart",				"RocksDC2.png"		},
   { "sign_heart.xpos",				"13"			},
   { "sign_heart.ypos",				"2"			},
   { "sign_heart.frames",			"1"			},
 
-  { "sign_cross",				"RocksDC2.pcx"		},
+  { "sign_cross",				"RocksDC2.png"		},
   { "sign_cross.xpos",				"14"			},
   { "sign_cross.ypos",				"2"			},
   { "sign_cross.frames",			"1"			},
 
-  { "sign_frankie",				"RocksDC2.pcx"		},
+  { "sign_frankie",				"RocksDC2.png"		},
   { "sign_frankie.xpos",			"15"			},
   { "sign_frankie.ypos",			"2"			},
   { "sign_frankie.frames",			"1"			},
 
-  { "landmine",					"RocksDC.pcx"		},
+  { "landmine",					"RocksDC.png"		},
   { "landmine.xpos",				"7"			},
   { "landmine.ypos",				"14"			},
   { "landmine.frames",				"1"			},
   { "landmine.crumbled_like",			"sand"			},
 
-  { "dc_landmine",				"RocksDC.pcx"		},
+  { "dc_landmine",				"RocksDC.png"		},
   { "dc_landmine.xpos",				"14"			},
   { "dc_landmine.ypos",				"5"			},
   { "dc_landmine.frames",			"1"			},
   { "dc_landmine.crumbled_like",		"sand"			},
 
-  { "steelwall_slippery",			"RocksDC.pcx"		},
+  { "steelwall_slippery",			"RocksDC.png"		},
   { "steelwall_slippery.xpos",			"5"			},
   { "steelwall_slippery.ypos",			"15"			},
   { "steelwall_slippery.frames",		"1"			},
 
-  { "extra_time",				"RocksDC.pcx"		},
+  { "extra_time",				"RocksDC.png"		},
   { "extra_time.xpos",				"8"			},
   { "extra_time.ypos",				"0"			},
   { "extra_time.frames",			"6"			},
   { "extra_time.delay",				"4"			},
 
-  { "shield_normal",				"RocksDC.pcx"		},
+  { "shield_normal",				"RocksDC.png"		},
   { "shield_normal.xpos",			"8"			},
   { "shield_normal.ypos",			"2"			},
   { "shield_normal.frames",			"6"			},
   { "shield_normal.delay",			"4"			},
-  { "shield_normal.active",			"RocksHeroes.pcx"	},
+  { "shield_normal.active",			"RocksHeroes.png"	},
   { "shield_normal.active.xpos",		"1"			},
   { "shield_normal.active.ypos",		"13"			},
   { "shield_normal.active.frames",		"3"			},
   { "shield_normal.active.delay",		"8"			},
   { "shield_normal.active.anim_mode",		"pingpong"		},
 
-  { "shield_deadly",				"RocksDC.pcx"		},
+  { "shield_deadly",				"RocksDC.png"		},
   { "shield_deadly.xpos",			"8"			},
   { "shield_deadly.ypos",			"1"			},
   { "shield_deadly.frames",			"6"			},
   { "shield_deadly.delay",			"4"			},
-  { "shield_deadly.active",			"RocksHeroes.pcx"	},
+  { "shield_deadly.active",			"RocksHeroes.png"	},
   { "shield_deadly.active.xpos",		"5"			},
   { "shield_deadly.active.ypos",		"13"			},
   { "shield_deadly.active.frames",		"3"			},
   { "shield_deadly.active.delay",		"8"			},
   { "shield_deadly.active.anim_mode",		"pingpong"		},
 
-  { "switchgate_closed",			"RocksDC.pcx"		},
+  { "switchgate_closed",			"RocksDC.png"		},
   { "switchgate_closed.xpos",			"8"			},
   { "switchgate_closed.ypos",			"5"			},
   { "switchgate_closed.frames",			"1"			},
-  { "switchgate.opening",			"RocksDC.pcx"		},
+  { "switchgate.opening",			"RocksDC.png"		},
   { "switchgate.opening.xpos",			"8"			},
   { "switchgate.opening.ypos",			"5"			},
   { "switchgate.opening.frames",		"5"			},
   { "switchgate.opening.delay",			"6"			},
-  { "switchgate_open",				"RocksDC.pcx"		},
+  { "switchgate_open",				"RocksDC.png"		},
   { "switchgate_open.xpos",			"12"			},
   { "switchgate_open.ypos",			"5"			},
   { "switchgate_open.frames",			"1"			},
-  { "switchgate.closing",			"RocksDC.pcx"		},
+  { "switchgate.closing",			"RocksDC.png"		},
   { "switchgate.closing.xpos",			"8"			},
   { "switchgate.closing.ypos",			"5"			},
   { "switchgate.closing.frames",		"5"			},
   { "switchgate.closing.delay",			"6"			},
   { "switchgate.closing.anim_mode",		"reverse"		},
 
-  { "timegate_closed",				"RocksDC.pcx"		},
+  { "timegate_closed",				"RocksDC.png"		},
   { "timegate_closed.xpos",			"8"			},
   { "timegate_closed.ypos",			"6"			},
   { "timegate_closed.frames",			"1"			},
-  { "timegate.opening",				"RocksDC.pcx"		},
+  { "timegate.opening",				"RocksDC.png"		},
   { "timegate.opening.xpos",			"8"			},
   { "timegate.opening.ypos",			"6"			},
   { "timegate.opening.frames",			"5"			},
   { "timegate.opening.delay",			"6"			},
-  { "timegate_open",				"RocksDC.pcx"		},
+  { "timegate_open",				"RocksDC.png"		},
   { "timegate_open.xpos",			"12"			},
   { "timegate_open.ypos",			"6"			},
   { "timegate_open.frames",			"1"			},
-  { "timegate.closing",				"RocksDC.pcx"		},
+  { "timegate.closing",				"RocksDC.png"		},
   { "timegate.closing.xpos",			"8"			},
   { "timegate.closing.ypos",			"6"			},
   { "timegate.closing.frames",			"5"			},
   { "timegate.closing.delay",			"6"			},
   { "timegate.closing.anim_mode",		"reverse"		},
 
-  { "pearl",					"RocksDC.pcx"		},
+  { "pearl",					"RocksDC.png"		},
   { "pearl.xpos",				"8"			},
   { "pearl.ypos",				"11"			},
   { "pearl.frames",				"1"			},
-  { "pearl.breaking",				"RocksDC.pcx"		},
+  { "pearl.breaking",				"RocksDC.png"		},
   { "pearl.breaking.xpos",			"8"			},
   { "pearl.breaking.ypos",			"12"			},
   { "pearl.breaking.frames",			"4"			},
   { "pearl.breaking.delay",			"2"			},
   { "pearl.breaking.anim_mode",			"linear"		},
 
-  { "crystal",					"RocksDC.pcx"		},
+  { "crystal",					"RocksDC.png"		},
   { "crystal.xpos",				"9"			},
   { "crystal.ypos",				"11"			},
   { "crystal.frames",				"1"			},
 
-  { "wall_pearl",				"RocksDC.pcx"		},
+  { "wall_pearl",				"RocksDC.png"		},
   { "wall_pearl.xpos",				"10"			},
   { "wall_pearl.ypos",				"11"			},
   { "wall_pearl.frames",			"1"			},
 
-  { "wall_crystal",				"RocksDC.pcx"		},
+  { "wall_crystal",				"RocksDC.png"		},
   { "wall_crystal.xpos",			"11"			},
   { "wall_crystal.ypos",			"11"			},
   { "wall_crystal.frames",			"1"			},
 
-  { "dc_steelwall_1_left",			"RocksDC2.pcx"		},
+  { "dc_steelwall_1_left",			"RocksDC2.png"		},
   { "dc_steelwall_1_left.xpos",			"5"			},
   { "dc_steelwall_1_left.ypos",			"1"			},
   { "dc_steelwall_1_left.frames",		"1"			},
-  { "dc_steelwall_1_right",			"RocksDC2.pcx"		},
+  { "dc_steelwall_1_right",			"RocksDC2.png"		},
   { "dc_steelwall_1_right.xpos",		"3"			},
   { "dc_steelwall_1_right.ypos",		"1"			},
   { "dc_steelwall_1_right.frames",		"1"			},
-  { "dc_steelwall_1_top",			"RocksDC2.pcx"		},
+  { "dc_steelwall_1_top",			"RocksDC2.png"		},
   { "dc_steelwall_1_top.xpos",			"4"			},
   { "dc_steelwall_1_top.ypos",			"2"			},
   { "dc_steelwall_1_top.frames",		"1"			},
-  { "dc_steelwall_1_bottom",			"RocksDC2.pcx"		},
+  { "dc_steelwall_1_bottom",			"RocksDC2.png"		},
   { "dc_steelwall_1_bottom.xpos",		"4"			},
   { "dc_steelwall_1_bottom.ypos",		"0"			},
   { "dc_steelwall_1_bottom.frames",		"1"			},
-  { "dc_steelwall_1_horizontal",		"RocksDC2.pcx"		},
+  { "dc_steelwall_1_horizontal",		"RocksDC2.png"		},
   { "dc_steelwall_1_horizontal.xpos",		"1"			},
   { "dc_steelwall_1_horizontal.ypos",		"0"			},
   { "dc_steelwall_1_horizontal.frames",		"1"			},
-  { "dc_steelwall_1_vertical",			"RocksDC2.pcx"		},
+  { "dc_steelwall_1_vertical",			"RocksDC2.png"		},
   { "dc_steelwall_1_vertical.xpos",		"0"			},
   { "dc_steelwall_1_vertical.ypos",		"1"			},
   { "dc_steelwall_1_vertical.frames",		"1"			},
-  { "dc_steelwall_1_topleft",			"RocksDC2.pcx"		},
+  { "dc_steelwall_1_topleft",			"RocksDC2.png"		},
   { "dc_steelwall_1_topleft.xpos",		"0"			},
   { "dc_steelwall_1_topleft.ypos",		"0"			},
   { "dc_steelwall_1_topleft.frames",		"1"			},
-  { "dc_steelwall_1_topright",			"RocksDC2.pcx"		},
+  { "dc_steelwall_1_topright",			"RocksDC2.png"		},
   { "dc_steelwall_1_topright.xpos",		"2"			},
   { "dc_steelwall_1_topright.ypos",		"0"			},
   { "dc_steelwall_1_topright.frames",		"1"			},
-  { "dc_steelwall_1_bottomleft",		"RocksDC2.pcx"		},
+  { "dc_steelwall_1_bottomleft",		"RocksDC2.png"		},
   { "dc_steelwall_1_bottomleft.xpos",		"0"			},
   { "dc_steelwall_1_bottomleft.ypos",		"2"			},
   { "dc_steelwall_1_bottomleft.frames",		"1"			},
-  { "dc_steelwall_1_bottomright",		"RocksDC2.pcx"		},
+  { "dc_steelwall_1_bottomright",		"RocksDC2.png"		},
   { "dc_steelwall_1_bottomright.xpos",		"2"			},
   { "dc_steelwall_1_bottomright.ypos",		"2"			},
   { "dc_steelwall_1_bottomright.frames",	"1"			},
-  { "dc_steelwall_1_topleft_2",			"RocksDC2.pcx"		},
+  { "dc_steelwall_1_topleft_2",			"RocksDC2.png"		},
   { "dc_steelwall_1_topleft_2.xpos",		"5"			},
   { "dc_steelwall_1_topleft_2.ypos",		"2"			},
   { "dc_steelwall_1_topleft_2.frames",		"1"			},
-  { "dc_steelwall_1_topright_2",		"RocksDC2.pcx"		},
+  { "dc_steelwall_1_topright_2",		"RocksDC2.png"		},
   { "dc_steelwall_1_topright_2.xpos",		"3"			},
   { "dc_steelwall_1_topright_2.ypos",		"2"			},
   { "dc_steelwall_1_topright_2.frames",		"1"			},
-  { "dc_steelwall_1_bottomleft_2",		"RocksDC2.pcx"		},
+  { "dc_steelwall_1_bottomleft_2",		"RocksDC2.png"		},
   { "dc_steelwall_1_bottomleft_2.xpos",		"5"			},
   { "dc_steelwall_1_bottomleft_2.ypos",		"0"			},
   { "dc_steelwall_1_bottomleft_2.frames",	"1"			},
-  { "dc_steelwall_1_bottomright_2",		"RocksDC2.pcx"		},
+  { "dc_steelwall_1_bottomright_2",		"RocksDC2.png"		},
   { "dc_steelwall_1_bottomright_2.xpos",	"3"			},
   { "dc_steelwall_1_bottomright_2.ypos",	"0"			},
   { "dc_steelwall_1_bottomright_2.frames",	"1"			},
 
-  { "dc_steelwall_2_left",			"RocksDC2.pcx"		},
+  { "dc_steelwall_2_left",			"RocksDC2.png"		},
   { "dc_steelwall_2_left.xpos",			"6"			},
   { "dc_steelwall_2_left.ypos",			"1"			},
   { "dc_steelwall_2_left.frames",		"1"			},
-  { "dc_steelwall_2_right",			"RocksDC2.pcx"		},
+  { "dc_steelwall_2_right",			"RocksDC2.png"		},
   { "dc_steelwall_2_right.xpos",		"9"			},
   { "dc_steelwall_2_right.ypos",		"1"			},
   { "dc_steelwall_2_right.frames",		"1"			},
-  { "dc_steelwall_2_top",			"RocksDC2.pcx"		},
+  { "dc_steelwall_2_top",			"RocksDC2.png"		},
   { "dc_steelwall_2_top.xpos",			"7"			},
   { "dc_steelwall_2_top.ypos",			"0"			},
   { "dc_steelwall_2_top.frames",		"1"			},
-  { "dc_steelwall_2_bottom",			"RocksDC2.pcx"		},
+  { "dc_steelwall_2_bottom",			"RocksDC2.png"		},
   { "dc_steelwall_2_bottom.xpos",		"7"			},
   { "dc_steelwall_2_bottom.ypos",		"3"			},
   { "dc_steelwall_2_bottom.frames",		"1"			},
-  { "dc_steelwall_2_horizontal",		"RocksDC2.pcx"		},
+  { "dc_steelwall_2_horizontal",		"RocksDC2.png"		},
   { "dc_steelwall_2_horizontal.xpos",		"8"			},
   { "dc_steelwall_2_horizontal.ypos",		"1"			},
   { "dc_steelwall_2_horizontal.frames",		"1"			},
-  { "dc_steelwall_2_vertical",			"RocksDC2.pcx"		},
+  { "dc_steelwall_2_vertical",			"RocksDC2.png"		},
   { "dc_steelwall_2_vertical.xpos",		"7"			},
   { "dc_steelwall_2_vertical.ypos",		"2"			},
   { "dc_steelwall_2_vertical.frames",		"1"			},
-  { "dc_steelwall_2_middle",			"RocksDC2.pcx"		},
+  { "dc_steelwall_2_middle",			"RocksDC2.png"		},
   { "dc_steelwall_2_middle.xpos",		"7"			},
   { "dc_steelwall_2_middle.ypos",		"1"			},
   { "dc_steelwall_2_middle.frames",		"1"			},
-  { "dc_steelwall_2_single",			"RocksDC2.pcx"		},
+  { "dc_steelwall_2_single",			"RocksDC2.png"		},
   { "dc_steelwall_2_single.xpos",		"6"			},
   { "dc_steelwall_2_single.ypos",		"0"			},
   { "dc_steelwall_2_single.frames",		"1"			},
 
   /* images for DX Boulderdash style elements and actions */
 
-  { "tube_right_down",				"RocksDC.pcx"		},
+  { "tube_right_down",				"RocksDC.png"		},
   { "tube_right_down.xpos",			"9"			},
   { "tube_right_down.ypos",			"13"			},
   { "tube_right_down.frames",			"1"			},
 
-  { "tube_horizontal_down",			"RocksDC.pcx"		},
+  { "tube_horizontal_down",			"RocksDC.png"		},
   { "tube_horizontal_down.xpos",		"10"			},
   { "tube_horizontal_down.ypos",		"13"			},
   { "tube_horizontal_down.frames",		"1"			},
 
-  { "tube_left_down",				"RocksDC.pcx"		},
+  { "tube_left_down",				"RocksDC.png"		},
   { "tube_left_down.xpos",			"11"			},
   { "tube_left_down.ypos",			"13"			},
   { "tube_left_down.frames",			"1"			},
 
-  { "tube_horizontal",				"RocksDC.pcx"		},
+  { "tube_horizontal",				"RocksDC.png"		},
   { "tube_horizontal.xpos",			"8"			},
   { "tube_horizontal.ypos",			"14"			},
   { "tube_horizontal.frames",			"1"			},
 
-  { "tube_vertical_right",			"RocksDC.pcx"		},
+  { "tube_vertical_right",			"RocksDC.png"		},
   { "tube_vertical_right.xpos",			"9"			},
   { "tube_vertical_right.ypos",			"14"			},
   { "tube_vertical_right.frames",		"1"			},
 
-  { "tube_any",					"RocksDC.pcx"		},
+  { "tube_any",					"RocksDC.png"		},
   { "tube_any.xpos",				"10"			},
   { "tube_any.ypos",				"14"			},
   { "tube_any.frames",				"1"			},
 
-  { "tube_vertical_left",			"RocksDC.pcx"		},
+  { "tube_vertical_left",			"RocksDC.png"		},
   { "tube_vertical_left.xpos",			"11"			},
   { "tube_vertical_left.ypos",			"14"			},
   { "tube_vertical_left.frames",		"1"			},
 
-  { "tube_vertical",				"RocksDC.pcx"		},
+  { "tube_vertical",				"RocksDC.png"		},
   { "tube_vertical.xpos",			"8"			},
   { "tube_vertical.ypos",			"15"			},
   { "tube_vertical.frames",			"1"			},
 
-  { "tube_right_up",				"RocksDC.pcx"		},
+  { "tube_right_up",				"RocksDC.png"		},
   { "tube_right_up.xpos",			"9"			},
   { "tube_right_up.ypos",			"15"			},
   { "tube_right_up.frames",			"1"			},
 
-  { "tube_horizontal_up",			"RocksDC.pcx"		},
+  { "tube_horizontal_up",			"RocksDC.png"		},
   { "tube_horizontal_up.xpos",			"10"			},
   { "tube_horizontal_up.ypos",			"15"			},
   { "tube_horizontal_up.frames",		"1"			},
 
-  { "tube_left_up",				"RocksDC.pcx"		},
+  { "tube_left_up",				"RocksDC.png"		},
   { "tube_left_up.xpos",			"11"			},
   { "tube_left_up.ypos",			"15"			},
   { "tube_left_up.frames",			"1"			},
 
-  { "trap",					"RocksDC.pcx"		},
+  { "trap",					"RocksDC.png"		},
   { "trap.xpos",				"12"			},
   { "trap.ypos",				"8"			},
   { "trap.frames",				"1"			},
   { "trap.crumbled_like",			"sand"			},
   { "trap.diggable_like",			"sand"			},
-  { "trap.active",				"RocksDC.pcx"		},
+  { "trap.active",				"RocksDC.png"		},
   { "trap.active.xpos",				"12"			},
   { "trap.active.ypos",				"8"			},
   { "trap.active.frames",			"4"			},
@@ -2516,1268 +2528,1268 @@ struct ConfigInfo image_config[] =
   { "trap.active.anim_mode",			"pingpong2"		},
   { "trap.active.crumbled_like",		"sand"			},
 
-  { "dx_supabomb",				"RocksDC.pcx"		},
+  { "dx_supabomb",				"RocksDC.png"		},
   { "dx_supabomb.xpos",				"15"			},
   { "dx_supabomb.ypos",				"9"			},
   { "dx_supabomb.frames",			"1"			},
 
   /* images for Rocks'n'Diamonds style elements and actions */
 
-  { "key_1",					"RocksElements.pcx"	},
+  { "key_1",					"RocksElements.png"	},
   { "key_1.xpos",				"4"			},
   { "key_1.ypos",				"1"			},
   { "key_1.frames",				"1"			},
-  { "key_1.EDITOR",				"RocksElements.pcx"	},
+  { "key_1.EDITOR",				"RocksElements.png"	},
   { "key_1.EDITOR.xpos",			"4"			},
   { "key_1.EDITOR.ypos",			"14"			},
-  { "key_2",					"RocksElements.pcx"	},
+  { "key_2",					"RocksElements.png"	},
   { "key_2.xpos",				"5"			},
   { "key_2.ypos",				"1"			},
   { "key_2.frames",				"1"			},
-  { "key_2.EDITOR",				"RocksElements.pcx"	},
+  { "key_2.EDITOR",				"RocksElements.png"	},
   { "key_2.EDITOR.xpos",			"5"			},
   { "key_2.EDITOR.ypos",			"14"			},
-  { "key_3",					"RocksElements.pcx"	},
+  { "key_3",					"RocksElements.png"	},
   { "key_3.xpos",				"6"			},
   { "key_3.ypos",				"1"			},
   { "key_3.frames",				"1"			},
-  { "key_3.EDITOR",				"RocksElements.pcx"	},
+  { "key_3.EDITOR",				"RocksElements.png"	},
   { "key_3.EDITOR.xpos",			"6"			},
   { "key_3.EDITOR.ypos",			"14"			},
-  { "key_4",					"RocksElements.pcx"	},
+  { "key_4",					"RocksElements.png"	},
   { "key_4.xpos",				"7"			},
   { "key_4.ypos",				"1"			},
   { "key_4.frames",				"1"			},
-  { "key_4.EDITOR",				"RocksElements.pcx"	},
+  { "key_4.EDITOR",				"RocksElements.png"	},
   { "key_4.EDITOR.xpos",			"7"			},
   { "key_4.EDITOR.ypos",			"14"			},
 
-  { "gate_1",					"RocksElements.pcx"	},
+  { "gate_1",					"RocksElements.png"	},
   { "gate_1.xpos",				"4"			},
   { "gate_1.ypos",				"2"			},
   { "gate_1.frames",				"1"			},
-  { "gate_2",					"RocksElements.pcx"	},
+  { "gate_2",					"RocksElements.png"	},
   { "gate_2.xpos",				"5"			},
   { "gate_2.ypos",				"2"			},
   { "gate_2.frames",				"1"			},
-  { "gate_3",					"RocksElements.pcx"	},
+  { "gate_3",					"RocksElements.png"	},
   { "gate_3.xpos",				"6"			},
   { "gate_3.ypos",				"2"			},
   { "gate_3.frames",				"1"			},
-  { "gate_4",					"RocksElements.pcx"	},
+  { "gate_4",					"RocksElements.png"	},
   { "gate_4.xpos",				"7"			},
   { "gate_4.ypos",				"2"			},
   { "gate_4.frames",				"1"			},
-  { "gate_1_gray",				"RocksElements.pcx"	},
+  { "gate_1_gray",				"RocksElements.png"	},
   { "gate_1_gray.xpos",				"8"			},
   { "gate_1_gray.ypos",				"2"			},
   { "gate_1_gray.frames",			"1"			},
-  { "gate_1_gray.EDITOR",			"RocksElements.pcx"	},
+  { "gate_1_gray.EDITOR",			"RocksElements.png"	},
   { "gate_1_gray.EDITOR.xpos",			"8"			},
   { "gate_1_gray.EDITOR.ypos",			"14"			},
-  { "gate_1_gray.active",			"RocksElements.pcx"	},
+  { "gate_1_gray.active",			"RocksElements.png"	},
   { "gate_1_gray.active.xpos",			"4"			},
   { "gate_1_gray.active.ypos",			"2"			},
   { "gate_1_gray.active.frames",		"1"			},
-  { "gate_2_gray",				"RocksElements.pcx"	},
+  { "gate_2_gray",				"RocksElements.png"	},
   { "gate_2_gray.xpos",				"9"			},
   { "gate_2_gray.ypos",				"2"			},
   { "gate_2_gray.frames",			"1"			},
-  { "gate_2_gray.EDITOR",			"RocksElements.pcx"	},
+  { "gate_2_gray.EDITOR",			"RocksElements.png"	},
   { "gate_2_gray.EDITOR.xpos",			"9"			},
   { "gate_2_gray.EDITOR.ypos",			"14"			},
-  { "gate_2_gray.active",			"RocksElements.pcx"	},
+  { "gate_2_gray.active",			"RocksElements.png"	},
   { "gate_2_gray.active.xpos",			"5"			},
   { "gate_2_gray.active.ypos",			"2"			},
   { "gate_2_gray.active.frames",		"1"			},
-  { "gate_3_gray",				"RocksElements.pcx"	},
+  { "gate_3_gray",				"RocksElements.png"	},
   { "gate_3_gray.xpos",				"10"			},
   { "gate_3_gray.ypos",				"2"			},
   { "gate_3_gray.frames",			"1"			},
-  { "gate_3_gray.EDITOR",			"RocksElements.pcx"	},
+  { "gate_3_gray.EDITOR",			"RocksElements.png"	},
   { "gate_3_gray.EDITOR.xpos",			"10"			},
   { "gate_3_gray.EDITOR.ypos",			"14"			},
-  { "gate_3_gray.active",			"RocksElements.pcx"	},
+  { "gate_3_gray.active",			"RocksElements.png"	},
   { "gate_3_gray.active.xpos",			"6"			},
   { "gate_3_gray.active.ypos",			"2"			},
   { "gate_3_gray.active.frames",		"1"			},
-  { "gate_4_gray",				"RocksElements.pcx"	},
+  { "gate_4_gray",				"RocksElements.png"	},
   { "gate_4_gray.xpos",				"11"			},
   { "gate_4_gray.ypos",				"2"			},
   { "gate_4_gray.frames",			"1"			},
-  { "gate_4_gray.EDITOR",			"RocksElements.pcx"	},
+  { "gate_4_gray.EDITOR",			"RocksElements.png"	},
   { "gate_4_gray.EDITOR.xpos",			"11"			},
   { "gate_4_gray.EDITOR.ypos",			"14"			},
-  { "gate_4_gray.active",			"RocksElements.pcx"	},
+  { "gate_4_gray.active",			"RocksElements.png"	},
   { "gate_4_gray.active.xpos",			"7"			},
   { "gate_4_gray.active.ypos",			"2"			},
   { "gate_4_gray.active.frames",		"1"			},
 
-  { "game_of_life",				"RocksElements.pcx"	},
+  { "game_of_life",				"RocksElements.png"	},
   { "game_of_life.xpos",			"8"			},
   { "game_of_life.ypos",			"1"			},
   { "game_of_life.frames",			"1"			},
 
-  { "biomaze",					"RocksElements.pcx"	},
+  { "biomaze",					"RocksElements.png"	},
   { "biomaze.xpos",				"9"			},
   { "biomaze.ypos",				"1"			},
   { "biomaze.frames",				"1"			},
 
-  { "pacman",					"RocksElements.pcx"	},
+  { "pacman",					"RocksElements.png"	},
   { "pacman.xpos",				"8"			},
   { "pacman.ypos",				"5"			},
   { "pacman.frames",				"1"			},
-  { "pacman.right",				"RocksElements.pcx"	},
+  { "pacman.right",				"RocksElements.png"	},
   { "pacman.right.xpos",			"8"			},
   { "pacman.right.ypos",			"5"			},
   { "pacman.right.frames",			"2"			},
   { "pacman.right.delay",			"4"			},
   { "pacman.right.offset",			"128"			},
-  { "pacman.up",				"RocksElements.pcx"	},
+  { "pacman.up",				"RocksElements.png"	},
   { "pacman.up.xpos",				"9"			},
   { "pacman.up.ypos",				"5"			},
   { "pacman.up.frames",				"2"			},
   { "pacman.up.delay",				"4"			},
   { "pacman.up.offset",				"128"			},
-  { "pacman.left",				"RocksElements.pcx"	},
+  { "pacman.left",				"RocksElements.png"	},
   { "pacman.left.xpos",				"10"			},
   { "pacman.left.ypos",				"5"			},
   { "pacman.left.frames",			"2"			},
   { "pacman.left.delay",			"4"			},
   { "pacman.left.offset",			"128"			},
-  { "pacman.down",				"RocksElements.pcx"	},
+  { "pacman.down",				"RocksElements.png"	},
   { "pacman.down.xpos",				"11"			},
   { "pacman.down.ypos",				"5"			},
   { "pacman.down.frames",			"2"			},
   { "pacman.down.delay",			"4"			},
   { "pacman.down.offset",			"128"			},
-  { "pacman.turning_from_right",		"RocksElements.pcx"	},
+  { "pacman.turning_from_right",		"RocksElements.png"	},
   { "pacman.turning_from_right.xpos",		"12"			},
   { "pacman.turning_from_right.ypos",		"5"			},
   { "pacman.turning_from_right.frames",		"1"			},
-  { "pacman.turning_from_up",			"RocksElements.pcx"	},
+  { "pacman.turning_from_up",			"RocksElements.png"	},
   { "pacman.turning_from_up.xpos",		"13"			},
   { "pacman.turning_from_up.ypos",		"5"			},
   { "pacman.turning_from_up.frames",		"1"			},
-  { "pacman.turning_from_left",			"RocksElements.pcx"	},
+  { "pacman.turning_from_left",			"RocksElements.png"	},
   { "pacman.turning_from_left.xpos",		"14"			},
   { "pacman.turning_from_left.ypos",		"5"			},
   { "pacman.turning_from_left.frames",		"1"			},
-  { "pacman.turning_from_down",			"RocksElements.pcx"	},
+  { "pacman.turning_from_down",			"RocksElements.png"	},
   { "pacman.turning_from_down.xpos",		"15"			},
   { "pacman.turning_from_down.ypos",		"5"			},
   { "pacman.turning_from_down.frames",		"1"			},
 
-  { "lamp",					"RocksElements.pcx"	},
+  { "lamp",					"RocksElements.png"	},
   { "lamp.xpos",				"0"			},
   { "lamp.ypos",				"7"			},
   { "lamp.frames",				"1"			},
-  { "lamp.EDITOR",				"RocksElements.pcx"	},
+  { "lamp.EDITOR",				"RocksElements.png"	},
   { "lamp.EDITOR.xpos",				"2"			},
   { "lamp.EDITOR.ypos",				"14"			},
-  { "lamp.active",				"RocksElements.pcx"	},
+  { "lamp.active",				"RocksElements.png"	},
   { "lamp.active.xpos",				"1"			},
   { "lamp.active.ypos",				"7"			},
   { "lamp.active.frames",			"1"			},
 
-  { "time_orb_full",				"RocksElements.pcx"	},
+  { "time_orb_full",				"RocksElements.png"	},
   { "time_orb_full.xpos",			"2"			},
   { "time_orb_full.ypos",			"7"			},
   { "time_orb_full.frames",			"1"			},
-  { "time_orb_empty",				"RocksElements.pcx"	},
+  { "time_orb_empty",				"RocksElements.png"	},
   { "time_orb_empty.xpos",			"3"			},
   { "time_orb_empty.ypos",			"7"			},
   { "time_orb_empty.frames",			"1"			},
 
-  { "emerald_yellow",				"RocksElements.pcx"	},
+  { "emerald_yellow",				"RocksElements.png"	},
   { "emerald_yellow.xpos",			"10"			},
   { "emerald_yellow.ypos",			"8"			},
   { "emerald_yellow.frames",			"1"			},
-  { "emerald_yellow.moving",			"RocksElements.pcx"	},
+  { "emerald_yellow.moving",			"RocksElements.png"	},
   { "emerald_yellow.moving.xpos",		"10"			},
   { "emerald_yellow.moving.ypos",		"8"			},
   { "emerald_yellow.moving.frames",		"2"			},
   { "emerald_yellow.moving.delay",		"4"			},
-  { "emerald_yellow.falling",			"RocksElements.pcx"	},
+  { "emerald_yellow.falling",			"RocksElements.png"	},
   { "emerald_yellow.falling.xpos",		"10"			},
   { "emerald_yellow.falling.ypos",		"8"			},
   { "emerald_yellow.falling.frames",		"2"			},
   { "emerald_yellow.falling.delay",		"4"			},
-  { "emerald_red",				"RocksElements.pcx"	},
+  { "emerald_red",				"RocksElements.png"	},
   { "emerald_red.xpos",				"8"			},
   { "emerald_red.ypos",				"9"			},
   { "emerald_red.frames",			"1"			},
-  { "emerald_red.moving",			"RocksElements.pcx"	},
+  { "emerald_red.moving",			"RocksElements.png"	},
   { "emerald_red.moving.xpos",			"8"			},
   { "emerald_red.moving.ypos",			"9"			},
   { "emerald_red.moving.frames",		"2"			},
   { "emerald_red.moving.delay",			"4"			},
-  { "emerald_red.falling",			"RocksElements.pcx"	},
+  { "emerald_red.falling",			"RocksElements.png"	},
   { "emerald_red.falling.xpos",			"8"			},
   { "emerald_red.falling.ypos",			"9"			},
   { "emerald_red.falling.frames",		"2"			},
   { "emerald_red.falling.delay",		"4"			},
-  { "emerald_purple",				"RocksElements.pcx"	},
+  { "emerald_purple",				"RocksElements.png"	},
   { "emerald_purple.xpos",			"10"			},
   { "emerald_purple.ypos",			"9"			},
   { "emerald_purple.frames",			"1"			},
-  { "emerald_purple.moving",			"RocksElements.pcx"	},
+  { "emerald_purple.moving",			"RocksElements.png"	},
   { "emerald_purple.moving.xpos",		"10"			},
   { "emerald_purple.moving.ypos",		"9"			},
   { "emerald_purple.moving.frames",		"2"			},
   { "emerald_purple.moving.delay",		"4"			},
-  { "emerald_purple.falling",			"RocksElements.pcx"	},
+  { "emerald_purple.falling",			"RocksElements.png"	},
   { "emerald_purple.falling.xpos",		"10"			},
   { "emerald_purple.falling.ypos",		"9"			},
   { "emerald_purple.falling.frames",		"2"			},
   { "emerald_purple.falling.delay",		"4"			},
 
-  { "wall_emerald_yellow",			"RocksElements.pcx"	},
+  { "wall_emerald_yellow",			"RocksElements.png"	},
   { "wall_emerald_yellow.xpos",			"8"			},
   { "wall_emerald_yellow.ypos",			"8"			},
   { "wall_emerald_yellow.frames",		"1"			},
-  { "wall_emerald_red",				"RocksElements.pcx"	},
+  { "wall_emerald_red",				"RocksElements.png"	},
   { "wall_emerald_red.xpos",			"6"			},
   { "wall_emerald_red.ypos",			"8"			},
   { "wall_emerald_red.frames",			"1"			},
-  { "wall_emerald_purple",			"RocksElements.pcx"	},
+  { "wall_emerald_purple",			"RocksElements.png"	},
   { "wall_emerald_purple.xpos",			"7"			},
   { "wall_emerald_purple.ypos",			"8"			},
   { "wall_emerald_purple.frames",		"1"			},
-  { "wall_bd_diamond",				"RocksElements.pcx"	},
+  { "wall_bd_diamond",				"RocksElements.png"	},
   { "wall_bd_diamond.xpos",			"9"			},
   { "wall_bd_diamond.ypos",			"8"			},
   { "wall_bd_diamond.frames",			"1"			},
 
-  { "expandable_wall",				"RocksElements.pcx"	},
+  { "expandable_wall",				"RocksElements.png"	},
   { "expandable_wall.xpos",			"11"			},
   { "expandable_wall.ypos",			"10"			},
   { "expandable_wall.frames",			"1"			},
-  { "expandable_wall_horizontal",		"RocksElements.pcx"	},
+  { "expandable_wall_horizontal",		"RocksElements.png"	},
   { "expandable_wall_horizontal.xpos",		"5"			},
   { "expandable_wall_horizontal.ypos",		"9"			},
   { "expandable_wall_horizontal.frames",	"1"			},
-  { "expandable_wall_horizontal.EDITOR",	"RocksElements.pcx"	},
+  { "expandable_wall_horizontal.EDITOR",	"RocksElements.png"	},
   { "expandable_wall_horizontal.EDITOR.xpos",	"13"			},
   { "expandable_wall_horizontal.EDITOR.ypos",	"13"			},
-  { "expandable_wall_vertical",			"RocksElements.pcx"	},
+  { "expandable_wall_vertical",			"RocksElements.png"	},
   { "expandable_wall_vertical.xpos",		"6"			},
   { "expandable_wall_vertical.ypos",		"9"			},
   { "expandable_wall_vertical.frames",		"1"			},
-  { "expandable_wall_vertical.EDITOR",		"RocksElements.pcx"	},
+  { "expandable_wall_vertical.EDITOR",		"RocksElements.png"	},
   { "expandable_wall_vertical.EDITOR.xpos",	"14"			},
   { "expandable_wall_vertical.EDITOR.ypos",	"13"			},
-  { "expandable_wall_any",			"RocksElements.pcx"	},
+  { "expandable_wall_any",			"RocksElements.png"	},
   { "expandable_wall_any.xpos",			"4"			},
   { "expandable_wall_any.ypos",			"9"			},
   { "expandable_wall_any.frames",		"1"			},
-  { "expandable_wall_any.EDITOR",		"RocksElements.pcx"	},
+  { "expandable_wall_any.EDITOR",		"RocksElements.png"	},
   { "expandable_wall_any.EDITOR.xpos",		"12"			},
   { "expandable_wall_any.EDITOR.ypos",		"13"			},
 
-  { "expandable_steelwall_horizontal",		"RocksDC2.pcx"		},
+  { "expandable_steelwall_horizontal",		"RocksDC2.png"		},
   { "expandable_steelwall_horizontal.xpos",	"6"			},
   { "expandable_steelwall_horizontal.ypos",	"2"			},
   { "expandable_steelwall_horizontal.frames",	"1"			},
-  { "expandable_steelwall_horizontal.EDITOR",	"RocksDC2.pcx"		},
+  { "expandable_steelwall_horizontal.EDITOR",	"RocksDC2.png"		},
   { "expandable_steelwall_horizontal.EDITOR.xpos","9"			},
   { "expandable_steelwall_horizontal.EDITOR.ypos","2"			},
-  { "expandable_steelwall_vertical",		"RocksDC2.pcx"		},
+  { "expandable_steelwall_vertical",		"RocksDC2.png"		},
   { "expandable_steelwall_vertical.xpos",	"6"			},
   { "expandable_steelwall_vertical.ypos",	"2"			},
   { "expandable_steelwall_vertical.frames",	"1"			},
-  { "expandable_steelwall_vertical.EDITOR",	"RocksDC2.pcx"		},
+  { "expandable_steelwall_vertical.EDITOR",	"RocksDC2.png"		},
   { "expandable_steelwall_vertical.EDITOR.xpos","10"			},
   { "expandable_steelwall_vertical.EDITOR.ypos","2"			},
-  { "expandable_steelwall_any",			"RocksDC2.pcx"		},
+  { "expandable_steelwall_any",			"RocksDC2.png"		},
   { "expandable_steelwall_any.xpos",		"6"			},
   { "expandable_steelwall_any.ypos",		"2"			},
   { "expandable_steelwall_any.frames",		"1"			},
-  { "expandable_steelwall_any.EDITOR",		"RocksDC2.pcx"		},
+  { "expandable_steelwall_any.EDITOR",		"RocksDC2.png"		},
   { "expandable_steelwall_any.EDITOR.xpos",	"8"			},
   { "expandable_steelwall_any.EDITOR.ypos",	"2"			},
 
-  { "bd_expandable_wall",			"RocksElements.pcx"	},
+  { "bd_expandable_wall",			"RocksElements.png"	},
   { "bd_expandable_wall.xpos",			"5"			},
   { "bd_expandable_wall.ypos",			"9"			},
   { "bd_expandable_wall.frames",		"1"			},
-  { "bd_expandable_wall.EDITOR",		"RocksDC.pcx"		},
+  { "bd_expandable_wall.EDITOR",		"RocksDC.png"		},
   { "bd_expandable_wall.EDITOR.xpos",		"15"			},
   { "bd_expandable_wall.EDITOR.ypos",		"15"			},
 
-  { "expandable_wall.growing.left",		"RocksElements.pcx"	},
+  { "expandable_wall.growing.left",		"RocksElements.png"	},
   { "expandable_wall.growing.left.xpos",	"8"			},
   { "expandable_wall.growing.left.ypos",	"10"			},
   { "expandable_wall.growing.left.frames",	"3"			},
   { "expandable_wall.growing.left.delay",	"6"			},
   { "expandable_wall.growing.left.anim_mode",	"linear"		},
-  { "expandable_wall.growing.right",		"RocksElements.pcx"	},
+  { "expandable_wall.growing.right",		"RocksElements.png"	},
   { "expandable_wall.growing.right.xpos",	"5"			},
   { "expandable_wall.growing.right.ypos",	"10"			},
   { "expandable_wall.growing.right.frames",	"3"			},
   { "expandable_wall.growing.right.delay",	"6"			},
   { "expandable_wall.growing.right.anim_mode",	"linear"		},
-  { "expandable_wall.growing.up",		"RocksHeroes.pcx"	},
+  { "expandable_wall.growing.up",		"RocksHeroes.png"	},
   { "expandable_wall.growing.up.xpos",		"3"			},
   { "expandable_wall.growing.up.ypos",		"12"			},
   { "expandable_wall.growing.up.frames",	"3"			},
   { "expandable_wall.growing.up.delay",		"6"			},
   { "expandable_wall.growing.up.anim_mode",	"linear"		},
-  { "expandable_wall.growing.down",		"RocksHeroes.pcx"	},
+  { "expandable_wall.growing.down",		"RocksHeroes.png"	},
   { "expandable_wall.growing.down.xpos",	"0"			},
   { "expandable_wall.growing.down.ypos",	"12"			},
   { "expandable_wall.growing.down.frames",	"3"			},
   { "expandable_wall.growing.down.delay",	"6"			},
   { "expandable_wall.growing.down.anim_mode",	"linear"		},
 
-  { "expandable_steelwall.growing.left",	"RocksDC2.pcx"		},
+  { "expandable_steelwall.growing.left",	"RocksDC2.png"		},
   { "expandable_steelwall.growing.left.xpos",	"8"			},
   { "expandable_steelwall.growing.left.ypos",	"4"			},
   { "expandable_steelwall.growing.left.frames",	"4"			},
   { "expandable_steelwall.growing.left.delay",	"4"			},
   { "expandable_steelwall.growing.left.anim_mode","linear"		},
-  { "expandable_steelwall.growing.right",	"RocksDC2.pcx"		},
+  { "expandable_steelwall.growing.right",	"RocksDC2.png"		},
   { "expandable_steelwall.growing.right.xpos",	"12"			},
   { "expandable_steelwall.growing.right.ypos",	"4"			},
   { "expandable_steelwall.growing.right.frames","4"			},
   { "expandable_steelwall.growing.right.delay",	"4"			},
   { "expandable_steelwall.growing.right.anim_mode","linear"		},
-  { "expandable_steelwall.growing.up",		"RocksDC2.pcx"		},
+  { "expandable_steelwall.growing.up",		"RocksDC2.png"		},
   { "expandable_steelwall.growing.up.xpos",	"8"			},
   { "expandable_steelwall.growing.up.ypos",	"5"			},
   { "expandable_steelwall.growing.up.frames",	"4"			},
   { "expandable_steelwall.growing.up.delay",	"4"			},
   { "expandable_steelwall.growing.up.anim_mode","linear"		},
-  { "expandable_steelwall.growing.down",	"RocksDC2.pcx"		},
+  { "expandable_steelwall.growing.down",	"RocksDC2.png"		},
   { "expandable_steelwall.growing.down.xpos",	"12"			},
   { "expandable_steelwall.growing.down.ypos",	"5"			},
   { "expandable_steelwall.growing.down.frames",	"4"			},
   { "expandable_steelwall.growing.down.delay",	"4"			},
   { "expandable_steelwall.growing.down.anim_mode","linear"		},
 
-  { "black_orb",				"RocksElements.pcx"	},
+  { "black_orb",				"RocksElements.png"	},
   { "black_orb.xpos",				"13"			},
   { "black_orb.ypos",				"9"			},
   { "black_orb.frames",				"1"			},
 
-  { "speed_pill",				"RocksElements.pcx"	},
+  { "speed_pill",				"RocksElements.png"	},
   { "speed_pill.xpos",				"14"			},
   { "speed_pill.ypos",				"9"			},
   { "speed_pill.frames",			"1"			},
 
-  { "dark_yamyam",				"RocksElements.pcx"	},
+  { "dark_yamyam",				"RocksElements.png"	},
   { "dark_yamyam.xpos",				"8"			},
   { "dark_yamyam.ypos",				"11"			},
   { "dark_yamyam.frames",			"4"			},
   { "dark_yamyam.anim_mode",			"pingpong2"		},
 
-  { "dynabomb",					"RocksElements.pcx"	},
+  { "dynabomb",					"RocksElements.png"	},
   { "dynabomb.xpos",				"12"			},
   { "dynabomb.ypos",				"11"			},
   { "dynabomb.frames",				"1"			},
-  { "dynabomb.active",				"RocksElements.pcx"	},
+  { "dynabomb.active",				"RocksElements.png"	},
   { "dynabomb.active.xpos",			"12"			},
   { "dynabomb.active.ypos",			"11"			},
   { "dynabomb.active.frames",			"4"			},
   { "dynabomb.active.delay",			"6"			},
   { "dynabomb.active.anim_mode",		"pingpong"		},
-  { "dynabomb_player_1",			"RocksElements.pcx"	},
+  { "dynabomb_player_1",			"RocksElements.png"	},
   { "dynabomb_player_1.xpos",			"12"			},
   { "dynabomb_player_1.ypos",			"11"			},
   { "dynabomb_player_1.frames",			"1"			},
-  { "dynabomb_player_1.active",			"RocksElements.pcx"	},
+  { "dynabomb_player_1.active",			"RocksElements.png"	},
   { "dynabomb_player_1.active.xpos",		"12"			},
   { "dynabomb_player_1.active.ypos",		"11"			},
   { "dynabomb_player_1.active.frames",		"4"			},
   { "dynabomb_player_1.active.delay",		"6"			},
   { "dynabomb_player_1.active.anim_mode",	"pingpong"		},
-  { "dynabomb_player_2",			"RocksElements.pcx"	},
+  { "dynabomb_player_2",			"RocksElements.png"	},
   { "dynabomb_player_2.xpos",			"12"			},
   { "dynabomb_player_2.ypos",			"11"			},
   { "dynabomb_player_2.frames",			"1"			},
-  { "dynabomb_player_2.active",			"RocksElements.pcx"	},
+  { "dynabomb_player_2.active",			"RocksElements.png"	},
   { "dynabomb_player_2.active.xpos",		"12"			},
   { "dynabomb_player_2.active.ypos",		"11"			},
   { "dynabomb_player_2.active.frames",		"4"			},
   { "dynabomb_player_2.active.delay",		"6"			},
   { "dynabomb_player_2.active.anim_mode",	"pingpong"		},
-  { "dynabomb_player_3",			"RocksElements.pcx"	},
+  { "dynabomb_player_3",			"RocksElements.png"	},
   { "dynabomb_player_3.xpos",			"12"			},
   { "dynabomb_player_3.ypos",			"11"			},
   { "dynabomb_player_3.frames",			"1"			},
-  { "dynabomb_player_3.active",			"RocksElements.pcx"	},
+  { "dynabomb_player_3.active",			"RocksElements.png"	},
   { "dynabomb_player_3.active.xpos",		"12"			},
   { "dynabomb_player_3.active.ypos",		"11"			},
   { "dynabomb_player_3.active.frames",		"4"			},
   { "dynabomb_player_3.active.delay",		"6"			},
   { "dynabomb_player_3.active.anim_mode",	"pingpong"		},
-  { "dynabomb_player_4",			"RocksElements.pcx"	},
+  { "dynabomb_player_4",			"RocksElements.png"	},
   { "dynabomb_player_4.xpos",			"12"			},
   { "dynabomb_player_4.ypos",			"11"			},
   { "dynabomb_player_4.frames",			"1"			},
-  { "dynabomb_player_4.active",			"RocksElements.pcx"	},
+  { "dynabomb_player_4.active",			"RocksElements.png"	},
   { "dynabomb_player_4.active.xpos",		"12"			},
   { "dynabomb_player_4.active.ypos",		"11"			},
   { "dynabomb_player_4.active.frames",		"4"			},
   { "dynabomb_player_4.active.delay",		"6"			},
   { "dynabomb_player_4.active.anim_mode",	"pingpong"		},
-  { "dynabomb_increase_number",			"RocksElements.pcx"	},
+  { "dynabomb_increase_number",			"RocksElements.png"	},
   { "dynabomb_increase_number.xpos",		"12"			},
   { "dynabomb_increase_number.ypos",		"11"			},
   { "dynabomb_increase_number.frames",		"1"			},
-  { "dynabomb_increase_size",			"RocksElements.pcx"	},
+  { "dynabomb_increase_size",			"RocksElements.png"	},
   { "dynabomb_increase_size.xpos",		"15"			},
   { "dynabomb_increase_size.ypos",		"11"			},
   { "dynabomb_increase_size.frames",		"1"			},
-  { "dynabomb_increase_power",			"RocksElements.pcx"	},
+  { "dynabomb_increase_power",			"RocksElements.png"	},
   { "dynabomb_increase_power.xpos",		"12"			},
   { "dynabomb_increase_power.ypos",		"9"			},
   { "dynabomb_increase_power.frames",		"1"			},
 
-  { "pig",					"RocksHeroes.pcx"	},
+  { "pig",					"RocksHeroes.png"	},
   { "pig.xpos",					"8"			},
   { "pig.ypos",					"0"			},
   { "pig.frames",				"1"			},
-  { "pig.down",					"RocksHeroes.pcx"	},
+  { "pig.down",					"RocksHeroes.png"	},
   { "pig.down.xpos",				"8"			},
   { "pig.down.ypos",				"0"			},
   { "pig.down.frames",				"1"			},
-  { "pig.up",					"RocksHeroes.pcx"	},
+  { "pig.up",					"RocksHeroes.png"	},
   { "pig.up.xpos",				"12"			},
   { "pig.up.ypos",				"0"			},
   { "pig.up.frames",				"1"			},
-  { "pig.left",					"RocksHeroes.pcx"	},
+  { "pig.left",					"RocksHeroes.png"	},
   { "pig.left.xpos",				"8"			},
   { "pig.left.ypos",				"1"			},
   { "pig.left.frames",				"1"			},
-  { "pig.right",				"RocksHeroes.pcx"	},
+  { "pig.right",				"RocksHeroes.png"	},
   { "pig.right.xpos",				"12"			},
   { "pig.right.ypos",				"1"			},
   { "pig.right.frames",				"1"			},
-  { "pig.moving.down",				"RocksHeroes.pcx"	},
+  { "pig.moving.down",				"RocksHeroes.png"	},
   { "pig.moving.down.xpos",			"8"			},
   { "pig.moving.down.ypos",			"0"			},
   { "pig.moving.down.frames",			"4"			},
   { "pig.moving.down.delay",			"2"			},
-  { "pig.moving.up",				"RocksHeroes.pcx"	},
+  { "pig.moving.up",				"RocksHeroes.png"	},
   { "pig.moving.up.xpos",			"12"			},
   { "pig.moving.up.ypos",			"0"			},
   { "pig.moving.up.frames",			"4"			},
   { "pig.moving.up.delay",			"2"			},
-  { "pig.moving.left",				"RocksHeroes.pcx"	},
+  { "pig.moving.left",				"RocksHeroes.png"	},
   { "pig.moving.left.xpos",			"8"			},
   { "pig.moving.left.ypos",			"1"			},
   { "pig.moving.left.frames",			"4"			},
   { "pig.moving.left.delay",			"2"			},
-  { "pig.moving.right",				"RocksHeroes.pcx"	},
+  { "pig.moving.right",				"RocksHeroes.png"	},
   { "pig.moving.right.xpos",			"12"			},
   { "pig.moving.right.ypos",			"1"			},
   { "pig.moving.right.frames",			"4"			},
   { "pig.moving.right.delay",			"2"			},
-  { "pig.digging.down",				"RocksHeroes.pcx"	},
+  { "pig.digging.down",				"RocksHeroes.png"	},
   { "pig.digging.down.xpos",			"8"			},
   { "pig.digging.down.ypos",			"0"			},
   { "pig.digging.down.frames",			"4"			},
   { "pig.digging.down.delay",			"2"			},
-  { "pig.digging.up",				"RocksHeroes.pcx"	},
+  { "pig.digging.up",				"RocksHeroes.png"	},
   { "pig.digging.up.xpos",			"12"			},
   { "pig.digging.up.ypos",			"0"			},
   { "pig.digging.up.frames",			"4"			},
   { "pig.digging.up.delay",			"2"			},
-  { "pig.digging.left",				"RocksHeroes.pcx"	},
+  { "pig.digging.left",				"RocksHeroes.png"	},
   { "pig.digging.left.xpos",			"8"			},
   { "pig.digging.left.ypos",			"1"			},
   { "pig.digging.left.frames",			"4"			},
   { "pig.digging.left.delay",			"2"			},
-  { "pig.digging.right",			"RocksHeroes.pcx"	},
+  { "pig.digging.right",			"RocksHeroes.png"	},
   { "pig.digging.right.xpos",			"12"			},
   { "pig.digging.right.ypos",			"1"			},
   { "pig.digging.right.frames",			"4"			},
   { "pig.digging.right.delay",			"2"			},
 
-  { "dragon",					"RocksHeroes.pcx"	},
+  { "dragon",					"RocksHeroes.png"	},
   { "dragon.xpos",				"8"			},
   { "dragon.ypos",				"2"			},
   { "dragon.frames",				"1"			},
-  { "dragon.down",				"RocksHeroes.pcx"	},
+  { "dragon.down",				"RocksHeroes.png"	},
   { "dragon.down.xpos",				"8"			},
   { "dragon.down.ypos",				"2"			},
   { "dragon.down.frames",			"1"			},
-  { "dragon.up",				"RocksHeroes.pcx"	},
+  { "dragon.up",				"RocksHeroes.png"	},
   { "dragon.up.xpos",				"12"			},
   { "dragon.up.ypos",				"2"			},
   { "dragon.up.frames",				"1"			},
-  { "dragon.left",				"RocksHeroes.pcx"	},
+  { "dragon.left",				"RocksHeroes.png"	},
   { "dragon.left.xpos",				"8"			},
   { "dragon.left.ypos",				"3"			},
   { "dragon.left.frames",			"1"			},
-  { "dragon.right",				"RocksHeroes.pcx"	},
+  { "dragon.right",				"RocksHeroes.png"	},
   { "dragon.right.xpos",			"12"			},
   { "dragon.right.ypos",			"3"			},
   { "dragon.right.frames",			"1"			},
-  { "dragon.moving.down",			"RocksHeroes.pcx"	},
+  { "dragon.moving.down",			"RocksHeroes.png"	},
   { "dragon.moving.down.xpos",			"8"			},
   { "dragon.moving.down.ypos",			"2"			},
   { "dragon.moving.down.frames",		"4"			},
   { "dragon.moving.down.delay",			"2"			},
-  { "dragon.moving.up",				"RocksHeroes.pcx"	},
+  { "dragon.moving.up",				"RocksHeroes.png"	},
   { "dragon.moving.up.xpos",			"12"			},
   { "dragon.moving.up.ypos",			"2"			},
   { "dragon.moving.up.frames",			"4"			},
   { "dragon.moving.up.delay",			"2"			},
-  { "dragon.moving.left",			"RocksHeroes.pcx"	},
+  { "dragon.moving.left",			"RocksHeroes.png"	},
   { "dragon.moving.left.xpos",			"8"			},
   { "dragon.moving.left.ypos",			"3"			},
   { "dragon.moving.left.frames",		"4"			},
   { "dragon.moving.left.delay",			"2"			},
-  { "dragon.moving.right",			"RocksHeroes.pcx"	},
+  { "dragon.moving.right",			"RocksHeroes.png"	},
   { "dragon.moving.right.xpos",			"12"			},
   { "dragon.moving.right.ypos",			"3"			},
   { "dragon.moving.right.frames",		"4"			},
   { "dragon.moving.right.delay",		"2"			},
-  { "dragon.attacking.down",			"RocksHeroes.pcx"	},
+  { "dragon.attacking.down",			"RocksHeroes.png"	},
   { "dragon.attacking.down.xpos",		"8"			},
   { "dragon.attacking.down.ypos",		"2"			},
   { "dragon.attacking.down.frames",		"1"			},
-  { "dragon.attacking.up",			"RocksHeroes.pcx"	},
+  { "dragon.attacking.up",			"RocksHeroes.png"	},
   { "dragon.attacking.up.xpos",			"12"			},
   { "dragon.attacking.up.ypos",			"2"			},
   { "dragon.attacking.up.frames",		"1"			},
-  { "dragon.attacking.left",			"RocksHeroes.pcx"	},
+  { "dragon.attacking.left",			"RocksHeroes.png"	},
   { "dragon.attacking.left.xpos",		"8"			},
   { "dragon.attacking.left.ypos",		"3"			},
   { "dragon.attacking.left.frames",		"1"			},
-  { "dragon.attacking.right",			"RocksHeroes.pcx"	},
+  { "dragon.attacking.right",			"RocksHeroes.png"	},
   { "dragon.attacking.right.xpos",		"12"			},
   { "dragon.attacking.right.ypos",		"3"			},
   { "dragon.attacking.right.frames",		"1"			},
 
-  { "mole",					"RocksHeroes.pcx"	},
+  { "mole",					"RocksHeroes.png"	},
   { "mole.xpos",				"8"			},
   { "mole.ypos",				"4"			},
   { "mole.frames",				"1"			},
-  { "mole.down",				"RocksHeroes.pcx"	},
+  { "mole.down",				"RocksHeroes.png"	},
   { "mole.down.xpos",				"8"			},
   { "mole.down.ypos",				"4"			},
   { "mole.down.frames",				"1"			},
-  { "mole.up",					"RocksHeroes.pcx"	},
+  { "mole.up",					"RocksHeroes.png"	},
   { "mole.up.xpos",				"12"			},
   { "mole.up.ypos",				"4"			},
   { "mole.up.frames",				"1"			},
-  { "mole.left",				"RocksHeroes.pcx"	},
+  { "mole.left",				"RocksHeroes.png"	},
   { "mole.left.xpos",				"8"			},
   { "mole.left.ypos",				"5"			},
   { "mole.left.frames",				"1"			},
-  { "mole.right",				"RocksHeroes.pcx"	},
+  { "mole.right",				"RocksHeroes.png"	},
   { "mole.right.xpos",				"12"			},
   { "mole.right.ypos",				"5"			},
   { "mole.right.frames",			"1"			},
-  { "mole.moving.down",				"RocksHeroes.pcx"	},
+  { "mole.moving.down",				"RocksHeroes.png"	},
   { "mole.moving.down.xpos",			"8"			},
   { "mole.moving.down.ypos",			"4"			},
   { "mole.moving.down.frames",			"4"			},
   { "mole.moving.down.delay",			"2"			},
-  { "mole.moving.up",				"RocksHeroes.pcx"	},
+  { "mole.moving.up",				"RocksHeroes.png"	},
   { "mole.moving.up.xpos",			"12"			},
   { "mole.moving.up.ypos",			"4"			},
   { "mole.moving.up.frames",			"4"			},
   { "mole.moving.up.delay",			"2"			},
-  { "mole.moving.left",				"RocksHeroes.pcx"	},
+  { "mole.moving.left",				"RocksHeroes.png"	},
   { "mole.moving.left.xpos",			"8"			},
   { "mole.moving.left.ypos",			"5"			},
   { "mole.moving.left.frames",			"4"			},
   { "mole.moving.left.delay",			"2"			},
-  { "mole.moving.right",			"RocksHeroes.pcx"	},
+  { "mole.moving.right",			"RocksHeroes.png"	},
   { "mole.moving.right.xpos",			"12"			},
   { "mole.moving.right.ypos",			"5"			},
   { "mole.moving.right.frames",			"4"			},
   { "mole.moving.right.delay",			"2"			},
-  { "mole.digging.down",			"RocksHeroes.pcx"	},
+  { "mole.digging.down",			"RocksHeroes.png"	},
   { "mole.digging.down.xpos",			"8"			},
   { "mole.digging.down.ypos",			"4"			},
   { "mole.digging.down.frames",			"4"			},
   { "mole.digging.down.delay",			"2"			},
-  { "mole.digging.up",				"RocksHeroes.pcx"	},
+  { "mole.digging.up",				"RocksHeroes.png"	},
   { "mole.digging.up.xpos",			"12"			},
   { "mole.digging.up.ypos",			"4"			},
   { "mole.digging.up.frames",			"4"			},
   { "mole.digging.up.delay",			"2"			},
-  { "mole.digging.left",			"RocksHeroes.pcx"	},
+  { "mole.digging.left",			"RocksHeroes.png"	},
   { "mole.digging.left.xpos",			"8"			},
   { "mole.digging.left.ypos",			"5"			},
   { "mole.digging.left.frames",			"4"			},
   { "mole.digging.left.delay",			"2"			},
-  { "mole.digging.right",			"RocksHeroes.pcx"	},
+  { "mole.digging.right",			"RocksHeroes.png"	},
   { "mole.digging.right.xpos",			"12"			},
   { "mole.digging.right.ypos",			"5"			},
   { "mole.digging.right.frames",		"4"			},
   { "mole.digging.right.delay",			"2"			},
 
-  { "penguin",					"RocksHeroes.pcx"	},
+  { "penguin",					"RocksHeroes.png"	},
   { "penguin.xpos",				"8"			},
   { "penguin.ypos",				"6"			},
   { "penguin.frames",				"1"			},
-  { "penguin.EDITOR",				"RocksElements.pcx"	},
+  { "penguin.EDITOR",				"RocksElements.png"	},
   { "penguin.EDITOR.xpos",			"12"			},
   { "penguin.EDITOR.ypos",			"14"			},
-  { "penguin.down",				"RocksHeroes.pcx"	},
+  { "penguin.down",				"RocksHeroes.png"	},
   { "penguin.down.xpos",			"8"			},
   { "penguin.down.ypos",			"6"			},
   { "penguin.down.frames",			"1"			},
-  { "penguin.up",				"RocksHeroes.pcx"	},
+  { "penguin.up",				"RocksHeroes.png"	},
   { "penguin.up.xpos",				"12"			},
   { "penguin.up.ypos",				"6"			},
   { "penguin.up.frames",			"1"			},
-  { "penguin.left",				"RocksHeroes.pcx"	},
+  { "penguin.left",				"RocksHeroes.png"	},
   { "penguin.left.xpos",			"8"			},
   { "penguin.left.ypos",			"7"			},
   { "penguin.left.frames",			"1"			},
-  { "penguin.right",				"RocksHeroes.pcx"	},
+  { "penguin.right",				"RocksHeroes.png"	},
   { "penguin.right.xpos",			"12"			},
   { "penguin.right.ypos",			"7"			},
   { "penguin.right.frames",			"1"			},
-  { "penguin.moving.down",			"RocksHeroes.pcx"	},
+  { "penguin.moving.down",			"RocksHeroes.png"	},
   { "penguin.moving.down.xpos",			"8"			},
   { "penguin.moving.down.ypos",			"6"			},
   { "penguin.moving.down.frames",		"4"			},
   { "penguin.moving.down.delay",		"2"			},
-  { "penguin.moving.up",			"RocksHeroes.pcx"	},
+  { "penguin.moving.up",			"RocksHeroes.png"	},
   { "penguin.moving.up.xpos",			"12"			},
   { "penguin.moving.up.ypos",			"6"			},
   { "penguin.moving.up.frames",			"4"			},
   { "penguin.moving.up.delay",			"2"			},
-  { "penguin.moving.left",			"RocksHeroes.pcx"	},
+  { "penguin.moving.left",			"RocksHeroes.png"	},
   { "penguin.moving.left.xpos",			"8"			},
   { "penguin.moving.left.ypos",			"7"			},
   { "penguin.moving.left.frames",		"4"			},
   { "penguin.moving.left.delay",		"2"			},
-  { "penguin.moving.right",			"RocksHeroes.pcx"	},
+  { "penguin.moving.right",			"RocksHeroes.png"	},
   { "penguin.moving.right.xpos",		"12"			},
   { "penguin.moving.right.ypos",		"7"			},
   { "penguin.moving.right.frames",		"4"			},
   { "penguin.moving.right.delay",		"2"			},
 
-  { "satellite",				"RocksHeroes.pcx"	},
+  { "satellite",				"RocksHeroes.png"	},
   { "satellite.xpos",				"8"			},
   { "satellite.ypos",				"9"			},
   { "satellite.frames",				"8"			},
   { "satellite.delay",				"2"			},
   { "satellite.global_sync",			"true"			},
 
-  { "flames_1_left",				"RocksHeroes.pcx"	},
+  { "flames_1_left",				"RocksHeroes.png"	},
   { "flames_1_left.xpos",			"8"			},
   { "flames_1_left.ypos",			"12"			},
   { "flames_1_left.frames",			"2"			},
   { "flames_1_left.offset",			"96"			},
-  { "flames_2_left",				"RocksHeroes.pcx"	},
+  { "flames_2_left",				"RocksHeroes.png"	},
   { "flames_2_left.xpos",			"9"			},
   { "flames_2_left.ypos",			"12"			},
   { "flames_2_left.frames",			"2"			},
   { "flames_2_left.offset",			"96"			},
-  { "flames_3_left",				"RocksHeroes.pcx"	},
+  { "flames_3_left",				"RocksHeroes.png"	},
   { "flames_3_left.xpos",			"10"			},
   { "flames_3_left.ypos",			"12"			},
   { "flames_3_left.frames",			"2"			},
   { "flames_3_left.offset",			"96"			},
 
-  { "flames_1_right",				"RocksHeroes.pcx"	},
+  { "flames_1_right",				"RocksHeroes.png"	},
   { "flames_1_right.xpos",			"8"			},
   { "flames_1_right.ypos",			"13"			},
   { "flames_1_right.frames",			"2"			},
   { "flames_1_right.offset",			"96"			},
-  { "flames_2_right",				"RocksHeroes.pcx"	},
+  { "flames_2_right",				"RocksHeroes.png"	},
   { "flames_2_right.xpos",			"9"			},
   { "flames_2_right.ypos",			"13"			},
   { "flames_2_right.frames",			"2"			},
   { "flames_2_right.offset",			"96"			},
-  { "flames_3_right",				"RocksHeroes.pcx"	},
+  { "flames_3_right",				"RocksHeroes.png"	},
   { "flames_3_right.xpos",			"10"			},
   { "flames_3_right.ypos",			"13"			},
   { "flames_3_right.frames",			"2"			},
   { "flames_3_right.offset",			"96"			},
 
-  { "flames_1_up",				"RocksHeroes.pcx"	},
+  { "flames_1_up",				"RocksHeroes.png"	},
   { "flames_1_up.xpos",				"8"			},
   { "flames_1_up.ypos",				"14"			},
   { "flames_1_up.frames",			"2"			},
   { "flames_1_up.offset",			"96"			},
-  { "flames_2_up",				"RocksHeroes.pcx"	},
+  { "flames_2_up",				"RocksHeroes.png"	},
   { "flames_2_up.xpos",				"9"			},
   { "flames_2_up.ypos",				"14"			},
   { "flames_2_up.frames",			"2"			},
   { "flames_2_up.offset",			"96"			},
-  { "flames_3_up",				"RocksHeroes.pcx"	},
+  { "flames_3_up",				"RocksHeroes.png"	},
   { "flames_3_up.xpos",				"10"			},
   { "flames_3_up.ypos",				"14"			},
   { "flames_3_up.frames",			"2"			},
   { "flames_3_up.offset",			"96"			},
 
-  { "flames_1_down",				"RocksHeroes.pcx"	},
+  { "flames_1_down",				"RocksHeroes.png"	},
   { "flames_1_down.xpos",			"8"			},
   { "flames_1_down.ypos",			"15"			},
   { "flames_1_down.frames",			"2"			},
   { "flames_1_down.offset",			"96"			},
-  { "flames_2_down",				"RocksHeroes.pcx"	},
+  { "flames_2_down",				"RocksHeroes.png"	},
   { "flames_2_down.xpos",			"9"			},
   { "flames_2_down.ypos",			"15"			},
   { "flames_2_down.frames",			"2"			},
   { "flames_2_down.offset",			"96"			},
-  { "flames_3_down",				"RocksHeroes.pcx"	},
+  { "flames_3_down",				"RocksHeroes.png"	},
   { "flames_3_down.xpos",			"10"			},
   { "flames_3_down.ypos",			"15"			},
   { "flames_3_down.frames",			"2"			},
   { "flames_3_down.offset",			"96"			},
 
-  { "stoneblock",				"RocksElements.pcx"	},
+  { "stoneblock",				"RocksElements.png"	},
   { "stoneblock.xpos",				"10"			},
   { "stoneblock.ypos",				"1"			},
   { "stoneblock.frames",			"1"			},
 
   /* images for other elements and actions */
 
-  { "player_1",					"RocksHeroes.pcx"	},
+  { "player_1",					"RocksHeroes.png"	},
   { "player_1.xpos",				"0"			},
   { "player_1.ypos",				"0"			},
   { "player_1.frames",				"1"			},
-  { "player_1.EDITOR",				"RocksElements.pcx"	},
+  { "player_1.EDITOR",				"RocksElements.png"	},
   { "player_1.EDITOR.xpos",			"4"			},
   { "player_1.EDITOR.ypos",			"7"			},
-  { "player_1.down",				"RocksHeroes.pcx"	},
+  { "player_1.down",				"RocksHeroes.png"	},
   { "player_1.down.xpos",			"0"			},
   { "player_1.down.ypos",			"0"			},
   { "player_1.down.frames",			"1"			},
-  { "player_1.up",				"RocksHeroes.pcx"	},
+  { "player_1.up",				"RocksHeroes.png"	},
   { "player_1.up.xpos",				"4"			},
   { "player_1.up.ypos",				"0"			},
   { "player_1.up.frames",			"1"			},
-  { "player_1.left",				"RocksHeroes.pcx"	},
+  { "player_1.left",				"RocksHeroes.png"	},
   { "player_1.left.xpos",			"0"			},
   { "player_1.left.ypos",			"1"			},
   { "player_1.left.frames",			"1"			},
-  { "player_1.right",				"RocksHeroes.pcx"	},
+  { "player_1.right",				"RocksHeroes.png"	},
   { "player_1.right.xpos",			"4"			},
   { "player_1.right.ypos",			"1"			},
   { "player_1.right.frames",			"1"			},
-  { "player_1.moving.down",			"RocksHeroes.pcx"	},
+  { "player_1.moving.down",			"RocksHeroes.png"	},
   { "player_1.moving.down.xpos",		"0"			},
   { "player_1.moving.down.ypos",		"0"			},
   { "player_1.moving.down.frames",		"4"			},
   { "player_1.moving.down.start_frame",		"1"			},
   { "player_1.moving.down.delay",		"4"			},
-  { "player_1.moving.up",			"RocksHeroes.pcx"	},
+  { "player_1.moving.up",			"RocksHeroes.png"	},
   { "player_1.moving.up.xpos",			"4"			},
   { "player_1.moving.up.ypos",			"0"			},
   { "player_1.moving.up.frames",		"4"			},
   { "player_1.moving.up.start_frame",		"1"			},
   { "player_1.moving.up.delay",			"4"			},
-  { "player_1.moving.left",			"RocksHeroes.pcx"	},
+  { "player_1.moving.left",			"RocksHeroes.png"	},
   { "player_1.moving.left.xpos",		"0"			},
   { "player_1.moving.left.ypos",		"1"			},
   { "player_1.moving.left.frames",		"4"			},
   { "player_1.moving.left.start_frame",		"1"			},
   { "player_1.moving.left.delay",		"4"			},
-  { "player_1.moving.right",			"RocksHeroes.pcx"	},
+  { "player_1.moving.right",			"RocksHeroes.png"	},
   { "player_1.moving.right.xpos",		"4"			},
   { "player_1.moving.right.ypos",		"1"			},
   { "player_1.moving.right.frames",		"4"			},
   { "player_1.moving.right.start_frame",	"1"			},
   { "player_1.moving.right.delay",		"4"			},
-  { "player_1.digging.down",			"RocksHeroes.pcx"	},
+  { "player_1.digging.down",			"RocksHeroes.png"	},
   { "player_1.digging.down.xpos",		"0"			},
   { "player_1.digging.down.ypos",		"0"			},
   { "player_1.digging.down.frames",		"4"			},
   { "player_1.digging.down.start_frame",	"1"			},
   { "player_1.digging.down.delay",		"4"			},
-  { "player_1.digging.up",			"RocksHeroes.pcx"	},
+  { "player_1.digging.up",			"RocksHeroes.png"	},
   { "player_1.digging.up.xpos",			"4"			},
   { "player_1.digging.up.ypos",			"0"			},
   { "player_1.digging.up.frames",		"4"			},
   { "player_1.digging.up.start_frame",		"1"			},
   { "player_1.digging.up.delay",		"4"			},
-  { "player_1.digging.left",			"RocksHeroes.pcx"	},
+  { "player_1.digging.left",			"RocksHeroes.png"	},
   { "player_1.digging.left.xpos",		"0"			},
   { "player_1.digging.left.ypos",		"1"			},
   { "player_1.digging.left.frames",		"4"			},
   { "player_1.digging.left.start_frame",	"1"			},
   { "player_1.digging.left.delay",		"4"			},
-  { "player_1.digging.right",			"RocksHeroes.pcx"	},
+  { "player_1.digging.right",			"RocksHeroes.png"	},
   { "player_1.digging.right.xpos",		"4"			},
   { "player_1.digging.right.ypos",		"1"			},
   { "player_1.digging.right.frames",		"4"			},
   { "player_1.digging.right.start_frame",	"1"			},
   { "player_1.digging.right.delay",		"4"			},
-  { "player_1.collecting.down",			"RocksHeroes.pcx"	},
+  { "player_1.collecting.down",			"RocksHeroes.png"	},
   { "player_1.collecting.down.xpos",		"0"			},
   { "player_1.collecting.down.ypos",		"0"			},
   { "player_1.collecting.down.frames",		"4"			},
   { "player_1.collecting.down.start_frame",	"1"			},
   { "player_1.collecting.down.delay",		"4"			},
-  { "player_1.collecting.up",			"RocksHeroes.pcx"	},
+  { "player_1.collecting.up",			"RocksHeroes.png"	},
   { "player_1.collecting.up.xpos",		"4"			},
   { "player_1.collecting.up.ypos",		"0"			},
   { "player_1.collecting.up.frames",		"4"			},
   { "player_1.collecting.up.start_frame",	"1"			},
   { "player_1.collecting.up.delay",		"4"			},
-  { "player_1.collecting.left",			"RocksHeroes.pcx"	},
+  { "player_1.collecting.left",			"RocksHeroes.png"	},
   { "player_1.collecting.left.xpos",		"0"			},
   { "player_1.collecting.left.ypos",		"1"			},
   { "player_1.collecting.left.frames",		"4"			},
   { "player_1.collecting.left.start_frame",	"1"			},
   { "player_1.collecting.left.delay",		"4"			},
-  { "player_1.collecting.right",		"RocksHeroes.pcx"	},
+  { "player_1.collecting.right",		"RocksHeroes.png"	},
   { "player_1.collecting.right.xpos",		"4"			},
   { "player_1.collecting.right.ypos",		"1"			},
   { "player_1.collecting.right.frames",		"4"			},
   { "player_1.collecting.right.start_frame",	"1"			},
   { "player_1.collecting.right.delay",		"4"			},
-  { "player_1.pushing.down",			"RocksHeroes.pcx"	},
+  { "player_1.pushing.down",			"RocksHeroes.png"	},
   { "player_1.pushing.down.xpos",		"0"			},
   { "player_1.pushing.down.ypos",		"0"			},
   { "player_1.pushing.down.frames",		"4"			},
   { "player_1.pushing.down.delay",		"4"			},
-  { "player_1.pushing.up",			"RocksHeroes.pcx"	},
+  { "player_1.pushing.up",			"RocksHeroes.png"	},
   { "player_1.pushing.up.xpos",			"4"			},
   { "player_1.pushing.up.ypos",			"0"			},
   { "player_1.pushing.up.frames",		"4"			},
   { "player_1.pushing.up.delay",		"4"			},
-  { "player_1.pushing.left",			"RocksHeroes.pcx"	},
+  { "player_1.pushing.left",			"RocksHeroes.png"	},
   { "player_1.pushing.left.xpos",		"4"			},
   { "player_1.pushing.left.ypos",		"2"			},
   { "player_1.pushing.left.frames",		"4"			},
   { "player_1.pushing.left.delay",		"4"			},
-  { "player_1.pushing.right",			"RocksHeroes.pcx"	},
+  { "player_1.pushing.right",			"RocksHeroes.png"	},
   { "player_1.pushing.right.xpos",		"0"			},
   { "player_1.pushing.right.ypos",		"2"			},
   { "player_1.pushing.right.frames",		"4"			},
   { "player_1.pushing.right.delay",		"4"			},
-  { "player_1.snapping.down",			"RocksHeroes.pcx"	},
+  { "player_1.snapping.down",			"RocksHeroes.png"	},
   { "player_1.snapping.down.xpos",		"0"			},
   { "player_1.snapping.down.ypos",		"0"			},
   { "player_1.snapping.down.frames",		"1"			},
-  { "player_1.snapping.up",			"RocksHeroes.pcx"	},
+  { "player_1.snapping.up",			"RocksHeroes.png"	},
   { "player_1.snapping.up.xpos",		"4"			},
   { "player_1.snapping.up.ypos",		"0"			},
   { "player_1.snapping.up.frames",		"1"			},
-  { "player_1.snapping.left",			"RocksHeroes.pcx"	},
+  { "player_1.snapping.left",			"RocksHeroes.png"	},
   { "player_1.snapping.left.xpos",		"0"			},
   { "player_1.snapping.left.ypos",		"1"			},
   { "player_1.snapping.left.frames",		"1"			},
-  { "player_1.snapping.right",			"RocksHeroes.pcx"	},
+  { "player_1.snapping.right",			"RocksHeroes.png"	},
   { "player_1.snapping.right.xpos",		"4"			},
   { "player_1.snapping.right.ypos",		"1"			},
   { "player_1.snapping.right.frames",		"1"			},
 
-  { "player_2",					"RocksHeroes.pcx"	},
+  { "player_2",					"RocksHeroes.png"	},
   { "player_2.xpos",				"0"			},
   { "player_2.ypos",				"3"			},
   { "player_2.frames",				"1"			},
-  { "player_2.EDITOR",				"RocksElements.pcx"	},
+  { "player_2.EDITOR",				"RocksElements.png"	},
   { "player_2.EDITOR.xpos",			"5"			},
   { "player_2.EDITOR.ypos",			"7"			},
-  { "player_2.down",				"RocksHeroes.pcx"	},
+  { "player_2.down",				"RocksHeroes.png"	},
   { "player_2.down.xpos",			"0"			},
   { "player_2.down.ypos",			"3"			},
   { "player_2.down.frames",			"1"			},
-  { "player_2.up",				"RocksHeroes.pcx"	},
+  { "player_2.up",				"RocksHeroes.png"	},
   { "player_2.up.xpos",				"4"			},
   { "player_2.up.ypos",				"3"			},
   { "player_2.up.frames",			"1"			},
-  { "player_2.left",				"RocksHeroes.pcx"	},
+  { "player_2.left",				"RocksHeroes.png"	},
   { "player_2.left.xpos",			"0"			},
   { "player_2.left.ypos",			"4"			},
   { "player_2.left.frames",			"1"			},
-  { "player_2.right",				"RocksHeroes.pcx"	},
+  { "player_2.right",				"RocksHeroes.png"	},
   { "player_2.right.xpos",			"4"			},
   { "player_2.right.ypos",			"4"			},
   { "player_2.right.frames",			"1"			},
-  { "player_2.moving.down",			"RocksHeroes.pcx"	},
+  { "player_2.moving.down",			"RocksHeroes.png"	},
   { "player_2.moving.down.xpos",		"0"			},
   { "player_2.moving.down.ypos",		"3"			},
   { "player_2.moving.down.frames",		"4"			},
   { "player_2.moving.down.start_frame",		"1"			},
   { "player_2.moving.down.delay",		"4"			},
-  { "player_2.moving.up",			"RocksHeroes.pcx"	},
+  { "player_2.moving.up",			"RocksHeroes.png"	},
   { "player_2.moving.up.xpos",			"4"			},
   { "player_2.moving.up.ypos",			"3"			},
   { "player_2.moving.up.frames",		"4"			},
   { "player_2.moving.up.start_frame",		"1"			},
   { "player_2.moving.up.delay",			"4"			},
-  { "player_2.moving.left",			"RocksHeroes.pcx"	},
+  { "player_2.moving.left",			"RocksHeroes.png"	},
   { "player_2.moving.left.xpos",		"0"			},
   { "player_2.moving.left.ypos",		"4"			},
   { "player_2.moving.left.frames",		"4"			},
   { "player_2.moving.left.start_frame",		"1"			},
   { "player_2.moving.left.delay",		"4"			},
-  { "player_2.moving.right",			"RocksHeroes.pcx"	},
+  { "player_2.moving.right",			"RocksHeroes.png"	},
   { "player_2.moving.right.xpos",		"4"			},
   { "player_2.moving.right.ypos",		"4"			},
   { "player_2.moving.right.frames",		"4"			},
   { "player_2.moving.right.start_frame",	"1"			},
   { "player_2.moving.right.delay",		"4"			},
-  { "player_2.digging.down",			"RocksHeroes.pcx"	},
+  { "player_2.digging.down",			"RocksHeroes.png"	},
   { "player_2.digging.down.xpos",		"0"			},
   { "player_2.digging.down.ypos",		"3"			},
   { "player_2.digging.down.frames",		"4"			},
   { "player_2.digging.down.start_frame",	"1"			},
   { "player_2.digging.down.delay",		"4"			},
-  { "player_2.digging.up",			"RocksHeroes.pcx"	},
+  { "player_2.digging.up",			"RocksHeroes.png"	},
   { "player_2.digging.up.xpos",			"4"			},
   { "player_2.digging.up.ypos",			"3"			},
   { "player_2.digging.up.frames",		"4"			},
   { "player_2.digging.up.start_frame",		"1"			},
   { "player_2.digging.up.delay",		"4"			},
-  { "player_2.digging.left",			"RocksHeroes.pcx"	},
+  { "player_2.digging.left",			"RocksHeroes.png"	},
   { "player_2.digging.left.xpos",		"0"			},
   { "player_2.digging.left.ypos",		"4"			},
   { "player_2.digging.left.frames",		"4"			},
   { "player_2.digging.left.start_frame",	"1"			},
   { "player_2.digging.left.delay",		"4"			},
-  { "player_2.digging.right",			"RocksHeroes.pcx"	},
+  { "player_2.digging.right",			"RocksHeroes.png"	},
   { "player_2.digging.right.xpos",		"4"			},
   { "player_2.digging.right.ypos",		"4"			},
   { "player_2.digging.right.frames",		"4"			},
   { "player_2.digging.right.start_frame",	"1"			},
   { "player_2.digging.right.delay",		"4"			},
-  { "player_2.collecting.down",			"RocksHeroes.pcx"	},
+  { "player_2.collecting.down",			"RocksHeroes.png"	},
   { "player_2.collecting.down.xpos",		"0"			},
   { "player_2.collecting.down.ypos",		"3"			},
   { "player_2.collecting.down.frames",		"4"			},
   { "player_2.collecting.down.start_frame",	"1"			},
   { "player_2.collecting.down.delay",		"4"			},
-  { "player_2.collecting.up",			"RocksHeroes.pcx"	},
+  { "player_2.collecting.up",			"RocksHeroes.png"	},
   { "player_2.collecting.up.xpos",		"4"			},
   { "player_2.collecting.up.ypos",		"3"			},
   { "player_2.collecting.up.frames",		"4"			},
   { "player_2.collecting.up.start_frame",	"1"			},
   { "player_2.collecting.up.delay",		"4"			},
-  { "player_2.collecting.left",			"RocksHeroes.pcx"	},
+  { "player_2.collecting.left",			"RocksHeroes.png"	},
   { "player_2.collecting.left.xpos",		"0"			},
   { "player_2.collecting.left.ypos",		"4"			},
   { "player_2.collecting.left.frames",		"4"			},
   { "player_2.collecting.left.start_frame",	"1"			},
   { "player_2.collecting.left.delay",		"4"			},
-  { "player_2.collecting.right",		"RocksHeroes.pcx"	},
+  { "player_2.collecting.right",		"RocksHeroes.png"	},
   { "player_2.collecting.right.xpos",		"4"			},
   { "player_2.collecting.right.ypos",		"4"			},
   { "player_2.collecting.right.frames",		"4"			},
   { "player_2.collecting.right.start_frame",	"1"			},
   { "player_2.collecting.right.delay",		"4"			},
-  { "player_2.pushing.down",			"RocksHeroes.pcx"	},
+  { "player_2.pushing.down",			"RocksHeroes.png"	},
   { "player_2.pushing.down.xpos",		"0"			},
   { "player_2.pushing.down.ypos",		"3"			},
   { "player_2.pushing.down.frames",		"4"			},
   { "player_2.pushing.down.delay",		"4"			},
-  { "player_2.pushing.up",			"RocksHeroes.pcx"	},
+  { "player_2.pushing.up",			"RocksHeroes.png"	},
   { "player_2.pushing.up.xpos",			"4"			},
   { "player_2.pushing.up.ypos",			"3"			},
   { "player_2.pushing.up.frames",		"4"			},
   { "player_2.pushing.up.delay",		"4"			},
-  { "player_2.pushing.left",			"RocksHeroes.pcx"	},
+  { "player_2.pushing.left",			"RocksHeroes.png"	},
   { "player_2.pushing.left.xpos",		"4"			},
   { "player_2.pushing.left.ypos",		"5"			},
   { "player_2.pushing.left.frames",		"4"			},
   { "player_2.pushing.left.delay",		"4"			},
-  { "player_2.pushing.right",			"RocksHeroes.pcx"	},
+  { "player_2.pushing.right",			"RocksHeroes.png"	},
   { "player_2.pushing.right.xpos",		"0"			},
   { "player_2.pushing.right.ypos",		"5"			},
   { "player_2.pushing.right.frames",		"4"			},
   { "player_2.pushing.right.delay",		"4"			},
-  { "player_2.snapping.down",			"RocksHeroes.pcx"	},
+  { "player_2.snapping.down",			"RocksHeroes.png"	},
   { "player_2.snapping.down.xpos",		"0"			},
   { "player_2.snapping.down.ypos",		"3"			},
   { "player_2.snapping.down.frames",		"1"			},
-  { "player_2.snapping.up",			"RocksHeroes.pcx"	},
+  { "player_2.snapping.up",			"RocksHeroes.png"	},
   { "player_2.snapping.up.xpos",		"4"			},
   { "player_2.snapping.up.ypos",		"3"			},
   { "player_2.snapping.up.frames",		"1"			},
-  { "player_2.snapping.left",			"RocksHeroes.pcx"	},
+  { "player_2.snapping.left",			"RocksHeroes.png"	},
   { "player_2.snapping.left.xpos",		"0"			},
   { "player_2.snapping.left.ypos",		"4"			},
   { "player_2.snapping.left.frames",		"1"			},
-  { "player_2.snapping.right",			"RocksHeroes.pcx"	},
+  { "player_2.snapping.right",			"RocksHeroes.png"	},
   { "player_2.snapping.right.xpos",		"4"			},
   { "player_2.snapping.right.ypos",		"4"			},
   { "player_2.snapping.right.frames",		"1"			},
 
-  { "player_3",					"RocksHeroes.pcx"	},
+  { "player_3",					"RocksHeroes.png"	},
   { "player_3.xpos",				"0"			},
   { "player_3.ypos",				"6"			},
   { "player_3.frames",				"1"			},
-  { "player_3.EDITOR",				"RocksElements.pcx"	},
+  { "player_3.EDITOR",				"RocksElements.png"	},
   { "player_3.EDITOR.xpos",			"6"			},
   { "player_3.EDITOR.ypos",			"7"			},
-  { "player_3.down",				"RocksHeroes.pcx"	},
+  { "player_3.down",				"RocksHeroes.png"	},
   { "player_3.down.xpos",			"0"			},
   { "player_3.down.ypos",			"6"			},
   { "player_3.down.frames",			"1"			},
-  { "player_3.up",				"RocksHeroes.pcx"	},
+  { "player_3.up",				"RocksHeroes.png"	},
   { "player_3.up.xpos",				"4"			},
   { "player_3.up.ypos",				"6"			},
   { "player_3.up.frames",			"1"			},
-  { "player_3.left",				"RocksHeroes.pcx"	},
+  { "player_3.left",				"RocksHeroes.png"	},
   { "player_3.left.xpos",			"0"			},
   { "player_3.left.ypos",			"7"			},
   { "player_3.left.frames",			"1"			},
-  { "player_3.right",				"RocksHeroes.pcx"	},
+  { "player_3.right",				"RocksHeroes.png"	},
   { "player_3.right.xpos",			"4"			},
   { "player_3.right.ypos",			"7"			},
   { "player_3.right.frames",			"1"			},
-  { "player_3.moving.down",			"RocksHeroes.pcx"	},
+  { "player_3.moving.down",			"RocksHeroes.png"	},
   { "player_3.moving.down.xpos",		"0"			},
   { "player_3.moving.down.ypos",		"6"			},
   { "player_3.moving.down.frames",		"4"			},
   { "player_3.moving.down.start_frame",		"1"			},
   { "player_3.moving.down.delay",		"4"			},
-  { "player_3.moving.up",			"RocksHeroes.pcx"	},
+  { "player_3.moving.up",			"RocksHeroes.png"	},
   { "player_3.moving.up.xpos",			"4"			},
   { "player_3.moving.up.ypos",			"6"			},
   { "player_3.moving.up.frames",		"4"			},
   { "player_3.moving.up.start_frame",		"1"			},
   { "player_3.moving.up.delay",			"4"			},
-  { "player_3.moving.left",			"RocksHeroes.pcx"	},
+  { "player_3.moving.left",			"RocksHeroes.png"	},
   { "player_3.moving.left.xpos",		"0"			},
   { "player_3.moving.left.ypos",		"7"			},
   { "player_3.moving.left.frames",		"4"			},
   { "player_3.moving.left.start_frame",		"1"			},
   { "player_3.moving.left.delay",		"4"			},
-  { "player_3.moving.right",			"RocksHeroes.pcx"	},
+  { "player_3.moving.right",			"RocksHeroes.png"	},
   { "player_3.moving.right.xpos",		"4"			},
   { "player_3.moving.right.ypos",		"7"			},
   { "player_3.moving.right.frames",		"4"			},
   { "player_3.moving.right.start_frame",	"1"			},
   { "player_3.moving.right.delay",		"4"			},
-  { "player_3.digging.down",			"RocksHeroes.pcx"	},
+  { "player_3.digging.down",			"RocksHeroes.png"	},
   { "player_3.digging.down.xpos",		"0"			},
   { "player_3.digging.down.ypos",		"6"			},
   { "player_3.digging.down.frames",		"4"			},
   { "player_3.digging.down.start_frame",	"1"			},
   { "player_3.digging.down.delay",		"4"			},
-  { "player_3.digging.up",			"RocksHeroes.pcx"	},
+  { "player_3.digging.up",			"RocksHeroes.png"	},
   { "player_3.digging.up.xpos",			"4"			},
   { "player_3.digging.up.ypos",			"6"			},
   { "player_3.digging.up.frames",		"4"			},
   { "player_3.digging.up.start_frame",		"1"			},
   { "player_3.digging.up.delay",		"4"			},
-  { "player_3.digging.left",			"RocksHeroes.pcx"	},
+  { "player_3.digging.left",			"RocksHeroes.png"	},
   { "player_3.digging.left.xpos",		"0"			},
   { "player_3.digging.left.ypos",		"7"			},
   { "player_3.digging.left.frames",		"4"			},
   { "player_3.digging.left.start_frame",	"1"			},
   { "player_3.digging.left.delay",		"4"			},
-  { "player_3.digging.right",			"RocksHeroes.pcx"	},
+  { "player_3.digging.right",			"RocksHeroes.png"	},
   { "player_3.digging.right.xpos",		"4"			},
   { "player_3.digging.right.ypos",		"7"			},
   { "player_3.digging.right.frames",		"4"			},
   { "player_3.digging.right.start_frame",	"1"			},
   { "player_3.digging.right.delay",		"4"			},
-  { "player_3.collecting.down",			"RocksHeroes.pcx"	},
+  { "player_3.collecting.down",			"RocksHeroes.png"	},
   { "player_3.collecting.down.xpos",		"0"			},
   { "player_3.collecting.down.ypos",		"6"			},
   { "player_3.collecting.down.frames",		"4"			},
   { "player_3.collecting.down.start_frame",	"1"			},
   { "player_3.collecting.down.delay",		"4"			},
-  { "player_3.collecting.up",			"RocksHeroes.pcx"	},
+  { "player_3.collecting.up",			"RocksHeroes.png"	},
   { "player_3.collecting.up.xpos",		"4"			},
   { "player_3.collecting.up.ypos",		"6"			},
   { "player_3.collecting.up.frames",		"4"			},
   { "player_3.collecting.up.start_frame",	"1"			},
   { "player_3.collecting.up.delay",		"4"			},
-  { "player_3.collecting.left",			"RocksHeroes.pcx"	},
+  { "player_3.collecting.left",			"RocksHeroes.png"	},
   { "player_3.collecting.left.xpos",		"0"			},
   { "player_3.collecting.left.ypos",		"7"			},
   { "player_3.collecting.left.frames",		"4"			},
   { "player_3.collecting.left.start_frame",	"1"			},
   { "player_3.collecting.left.delay",		"4"			},
-  { "player_3.collecting.right",		"RocksHeroes.pcx"	},
+  { "player_3.collecting.right",		"RocksHeroes.png"	},
   { "player_3.collecting.right.xpos",		"4"			},
   { "player_3.collecting.right.ypos",		"7"			},
   { "player_3.collecting.right.frames",		"4"			},
   { "player_3.collecting.right.start_frame",	"1"			},
   { "player_3.collecting.right.delay",		"4"			},
-  { "player_3.pushing.down",			"RocksHeroes.pcx"	},
+  { "player_3.pushing.down",			"RocksHeroes.png"	},
   { "player_3.pushing.down.xpos",		"0"			},
   { "player_3.pushing.down.ypos",		"6"			},
   { "player_3.pushing.down.frames",		"4"			},
   { "player_3.pushing.down.delay",		"4"			},
-  { "player_3.pushing.up",			"RocksHeroes.pcx"	},
+  { "player_3.pushing.up",			"RocksHeroes.png"	},
   { "player_3.pushing.up.xpos",			"4"			},
   { "player_3.pushing.up.ypos",			"6"			},
   { "player_3.pushing.up.frames",		"4"			},
   { "player_3.pushing.up.delay",		"4"			},
-  { "player_3.pushing.left",			"RocksHeroes.pcx"	},
+  { "player_3.pushing.left",			"RocksHeroes.png"	},
   { "player_3.pushing.left.xpos",		"4"			},
   { "player_3.pushing.left.ypos",		"8"			},
   { "player_3.pushing.left.frames",		"4"			},
   { "player_3.pushing.left.delay",		"4"			},
-  { "player_3.pushing.right",			"RocksHeroes.pcx"	},
+  { "player_3.pushing.right",			"RocksHeroes.png"	},
   { "player_3.pushing.right.xpos",		"0"			},
   { "player_3.pushing.right.ypos",		"8"			},
   { "player_3.pushing.right.frames",		"4"			},
   { "player_3.pushing.right.delay",		"4"			},
-  { "player_3.snapping.down",			"RocksHeroes.pcx"	},
+  { "player_3.snapping.down",			"RocksHeroes.png"	},
   { "player_3.snapping.down.xpos",		"0"			},
   { "player_3.snapping.down.ypos",		"6"			},
   { "player_3.snapping.down.frames",		"1"			},
-  { "player_3.snapping.up",			"RocksHeroes.pcx"	},
+  { "player_3.snapping.up",			"RocksHeroes.png"	},
   { "player_3.snapping.up.xpos",		"4"			},
   { "player_3.snapping.up.ypos",		"6"			},
   { "player_3.snapping.up.frames",		"1"			},
-  { "player_3.snapping.left",			"RocksHeroes.pcx"	},
+  { "player_3.snapping.left",			"RocksHeroes.png"	},
   { "player_3.snapping.left.xpos",		"0"			},
   { "player_3.snapping.left.ypos",		"7"			},
   { "player_3.snapping.left.frames",		"1"			},
-  { "player_3.snapping.right",			"RocksHeroes.pcx"	},
+  { "player_3.snapping.right",			"RocksHeroes.png"	},
   { "player_3.snapping.right.xpos",		"4"			},
   { "player_3.snapping.right.ypos",		"7"			},
   { "player_3.snapping.right.frames",		"1"			},
 
-  { "player_4",					"RocksHeroes.pcx"	},
+  { "player_4",					"RocksHeroes.png"	},
   { "player_4.xpos",				"0"			},
   { "player_4.ypos",				"9"			},
   { "player_4.frames",				"1"			},
-  { "player_4.EDITOR",				"RocksElements.pcx"	},
+  { "player_4.EDITOR",				"RocksElements.png"	},
   { "player_4.EDITOR.xpos",			"7"			},
   { "player_4.EDITOR.ypos",			"7"			},
-  { "player_4.down",				"RocksHeroes.pcx"	},
+  { "player_4.down",				"RocksHeroes.png"	},
   { "player_4.down.xpos",			"0"			},
   { "player_4.down.ypos",			"9"			},
   { "player_4.down.frames",			"1"			},
-  { "player_4.up",				"RocksHeroes.pcx"	},
+  { "player_4.up",				"RocksHeroes.png"	},
   { "player_4.up.xpos",				"4"			},
   { "player_4.up.ypos",				"9"			},
   { "player_4.up.frames",			"1"			},
-  { "player_4.left",				"RocksHeroes.pcx"	},
+  { "player_4.left",				"RocksHeroes.png"	},
   { "player_4.left.xpos",			"0"			},
   { "player_4.left.ypos",			"10"			},
   { "player_4.left.frames",			"1"			},
-  { "player_4.right",				"RocksHeroes.pcx"	},
+  { "player_4.right",				"RocksHeroes.png"	},
   { "player_4.right.xpos",			"4"			},
   { "player_4.right.ypos",			"10"			},
   { "player_4.right.frames",			"1"			},
-  { "player_4.moving.down",			"RocksHeroes.pcx"	},
+  { "player_4.moving.down",			"RocksHeroes.png"	},
   { "player_4.moving.down.xpos",		"0"			},
   { "player_4.moving.down.ypos",		"9"			},
   { "player_4.moving.down.frames",		"4"			},
   { "player_4.moving.down.start_frame",		"1"			},
   { "player_4.moving.down.delay",		"4"			},
-  { "player_4.moving.up",			"RocksHeroes.pcx"	},
+  { "player_4.moving.up",			"RocksHeroes.png"	},
   { "player_4.moving.up.xpos",			"4"			},
   { "player_4.moving.up.ypos",			"9"			},
   { "player_4.moving.up.frames",		"4"			},
   { "player_4.moving.up.start_frame",		"1"			},
   { "player_4.moving.up.delay",			"4"			},
-  { "player_4.moving.left",			"RocksHeroes.pcx"	},
+  { "player_4.moving.left",			"RocksHeroes.png"	},
   { "player_4.moving.left.xpos",		"0"			},
   { "player_4.moving.left.ypos",		"10"			},
   { "player_4.moving.left.frames",		"4"			},
   { "player_4.moving.left.start_frame",		"1"			},
   { "player_4.moving.left.delay",		"4"			},
-  { "player_4.moving.right",			"RocksHeroes.pcx"	},
+  { "player_4.moving.right",			"RocksHeroes.png"	},
   { "player_4.moving.right.xpos",		"4"			},
   { "player_4.moving.right.ypos",		"10"			},
   { "player_4.moving.right.frames",		"4"			},
   { "player_4.moving.right.start_frame",	"1"			},
   { "player_4.moving.right.delay",		"4"			},
-  { "player_4.digging.down",			"RocksHeroes.pcx"	},
+  { "player_4.digging.down",			"RocksHeroes.png"	},
   { "player_4.digging.down.xpos",		"0"			},
   { "player_4.digging.down.ypos",		"9"			},
   { "player_4.digging.down.frames",		"4"			},
   { "player_4.digging.down.start_frame",	"1"			},
   { "player_4.digging.down.delay",		"4"			},
-  { "player_4.digging.up",			"RocksHeroes.pcx"	},
+  { "player_4.digging.up",			"RocksHeroes.png"	},
   { "player_4.digging.up.xpos",			"4"			},
   { "player_4.digging.up.ypos",			"9"			},
   { "player_4.digging.up.frames",		"4"			},
   { "player_4.digging.up.start_frame",		"1"			},
   { "player_4.digging.up.delay",		"4"			},
-  { "player_4.digging.left",			"RocksHeroes.pcx"	},
+  { "player_4.digging.left",			"RocksHeroes.png"	},
   { "player_4.digging.left.xpos",		"0"			},
   { "player_4.digging.left.ypos",		"10"			},
   { "player_4.digging.left.frames",		"4"			},
   { "player_4.digging.left.start_frame",	"1"			},
   { "player_4.digging.left.delay",		"4"			},
-  { "player_4.digging.right",			"RocksHeroes.pcx"	},
+  { "player_4.digging.right",			"RocksHeroes.png"	},
   { "player_4.digging.right.xpos",		"4"			},
   { "player_4.digging.right.ypos",		"10"			},
   { "player_4.digging.right.frames",		"4"			},
   { "player_4.digging.right.start_frame",	"1"			},
   { "player_4.digging.right.delay",		"4"			},
-  { "player_4.collecting.down",			"RocksHeroes.pcx"	},
+  { "player_4.collecting.down",			"RocksHeroes.png"	},
   { "player_4.collecting.down.xpos",		"0"			},
   { "player_4.collecting.down.ypos",		"9"			},
   { "player_4.collecting.down.frames",		"4"			},
   { "player_4.collecting.down.start_frame",	"1"			},
   { "player_4.collecting.down.delay",		"4"			},
-  { "player_4.collecting.up",			"RocksHeroes.pcx"	},
+  { "player_4.collecting.up",			"RocksHeroes.png"	},
   { "player_4.collecting.up.xpos",		"4"			},
   { "player_4.collecting.up.ypos",		"9"			},
   { "player_4.collecting.up.frames",		"4"			},
   { "player_4.collecting.up.start_frame",	"1"			},
   { "player_4.collecting.up.delay",		"4"			},
-  { "player_4.collecting.left",			"RocksHeroes.pcx"	},
+  { "player_4.collecting.left",			"RocksHeroes.png"	},
   { "player_4.collecting.left.xpos",		"0"			},
   { "player_4.collecting.left.ypos",		"10"			},
   { "player_4.collecting.left.frames",		"4"			},
   { "player_4.collecting.left.start_frame",	"1"			},
   { "player_4.collecting.left.delay",		"4"			},
-  { "player_4.collecting.right",		"RocksHeroes.pcx"	},
+  { "player_4.collecting.right",		"RocksHeroes.png"	},
   { "player_4.collecting.right.xpos",		"4"			},
   { "player_4.collecting.right.ypos",		"10"			},
   { "player_4.collecting.right.frames",		"4"			},
   { "player_4.collecting.right.start_frame",	"1"			},
   { "player_4.collecting.right.delay",		"4"			},
-  { "player_4.pushing.down",			"RocksHeroes.pcx"	},
+  { "player_4.pushing.down",			"RocksHeroes.png"	},
   { "player_4.pushing.down.xpos",		"0"			},
   { "player_4.pushing.down.ypos",		"9"			},
   { "player_4.pushing.down.frames",		"4"			},
   { "player_4.pushing.down.delay",		"4"			},
-  { "player_4.pushing.up",			"RocksHeroes.pcx"	},
+  { "player_4.pushing.up",			"RocksHeroes.png"	},
   { "player_4.pushing.up.xpos",			"4"			},
   { "player_4.pushing.up.ypos",			"9"			},
   { "player_4.pushing.up.frames",		"4"			},
   { "player_4.pushing.up.delay",		"4"			},
-  { "player_4.pushing.left",			"RocksHeroes.pcx"	},
+  { "player_4.pushing.left",			"RocksHeroes.png"	},
   { "player_4.pushing.left.xpos",		"4"			},
   { "player_4.pushing.left.ypos",		"11"			},
   { "player_4.pushing.left.frames",		"4"			},
   { "player_4.pushing.left.delay",		"4"			},
-  { "player_4.pushing.right",			"RocksHeroes.pcx"	},
+  { "player_4.pushing.right",			"RocksHeroes.png"	},
   { "player_4.pushing.right.xpos",		"0"			},
   { "player_4.pushing.right.ypos",		"11"			},
   { "player_4.pushing.right.frames",		"4"			},
   { "player_4.pushing.right.delay",		"4"			},
-  { "player_4.snapping.down",			"RocksHeroes.pcx"	},
+  { "player_4.snapping.down",			"RocksHeroes.png"	},
   { "player_4.snapping.down.xpos",		"0"			},
   { "player_4.snapping.down.ypos",		"9"			},
   { "player_4.snapping.down.frames",		"1"			},
-  { "player_4.snapping.up",			"RocksHeroes.pcx"	},
+  { "player_4.snapping.up",			"RocksHeroes.png"	},
   { "player_4.snapping.up.xpos",		"4"			},
   { "player_4.snapping.up.ypos",		"9"			},
   { "player_4.snapping.up.frames",		"1"			},
-  { "player_4.snapping.left",			"RocksHeroes.pcx"	},
+  { "player_4.snapping.left",			"RocksHeroes.png"	},
   { "player_4.snapping.left.xpos",		"0"			},
   { "player_4.snapping.left.ypos",		"10"			},
   { "player_4.snapping.left.frames",		"1"			},
-  { "player_4.snapping.right",			"RocksHeroes.pcx"	},
+  { "player_4.snapping.right",			"RocksHeroes.png"	},
   { "player_4.snapping.right.xpos",		"4"			},
   { "player_4.snapping.right.ypos",		"10"			},
   { "player_4.snapping.right.frames",		"1"			},
 
-  { "[default].exploding",			"RocksElements.pcx"	},
+  { "[default].exploding",			"RocksElements.png"	},
   { "[default].exploding.xpos",			"0"			},
   { "[default].exploding.ypos",			"4"			},
   { "[default].exploding.frames",		"8"			},
   { "[default].exploding.delay",		"2"			},
   { "[default].exploding.anim_mode",		"linear"		},
 
-  { "twinkle_blue",				"RocksHeroes.pcx"	},
+  { "twinkle_blue",				"RocksHeroes.png"	},
   { "twinkle_blue.xpos",			"9"			},
   { "twinkle_blue.ypos",			"11"			},
   { "twinkle_blue.frames",			"3"			},
   { "twinkle_blue.delay",			"2"			},
   { "twinkle_blue.anim_mode",			"pingpong"		},
   { "twinkle_blue.global_sync",			"false"			},
-  { "twinkle_white",				"RocksHeroes.pcx"	},
+  { "twinkle_white",				"RocksHeroes.png"	},
   { "twinkle_white.xpos",			"13"			},
   { "twinkle_white.ypos",			"11"			},
   { "twinkle_white.frames",			"3"			},
@@ -3785,565 +3797,565 @@ struct ConfigInfo image_config[] =
   { "twinkle_white.anim_mode",			"pingpong"		},
   { "twinkle_white.global_sync",		"false"			},
 
-  { "steelwall_topleft",			"RocksElements.pcx"	},
+  { "steelwall_topleft",			"RocksElements.png"	},
   { "steelwall_topleft.xpos",			"4"			},
   { "steelwall_topleft.ypos",			"0"			},
   { "steelwall_topleft.frames",			"1"			},
-  { "steelwall_topright",			"RocksElements.pcx"	},
+  { "steelwall_topright",			"RocksElements.png"	},
   { "steelwall_topright.xpos",			"4"			},
   { "steelwall_topright.ypos",			"0"			},
   { "steelwall_topright.frames",		"1"			},
-  { "steelwall_bottomleft",			"RocksElements.pcx"	},
+  { "steelwall_bottomleft",			"RocksElements.png"	},
   { "steelwall_bottomleft.xpos",		"4"			},
   { "steelwall_bottomleft.ypos",		"0"			},
   { "steelwall_bottomleft.frames",		"1"			},
-  { "steelwall_bottomright",			"RocksElements.pcx"	},
+  { "steelwall_bottomright",			"RocksElements.png"	},
   { "steelwall_bottomright.xpos",		"4"			},
   { "steelwall_bottomright.ypos",		"0"			},
   { "steelwall_bottomright.frames",		"1"			},
-  { "steelwall_horizontal",			"RocksElements.pcx"	},
+  { "steelwall_horizontal",			"RocksElements.png"	},
   { "steelwall_horizontal.xpos",		"4"			},
   { "steelwall_horizontal.ypos",		"0"			},
   { "steelwall_horizontal.frames",		"1"			},
-  { "steelwall_vertical",			"RocksElements.pcx"	},
+  { "steelwall_vertical",			"RocksElements.png"	},
   { "steelwall_vertical.xpos",			"4"			},
   { "steelwall_vertical.ypos",			"0"			},
   { "steelwall_vertical.frames",		"1"			},
 
-  { "steelwall_topleft.EDITOR",			"RocksElements.pcx"	},
+  { "steelwall_topleft.EDITOR",			"RocksElements.png"	},
   { "steelwall_topleft.EDITOR.xpos",		"0"			},
   { "steelwall_topleft.EDITOR.ypos",		"13"			},
-  { "steelwall_topright.EDITOR",		"RocksElements.pcx"	},
+  { "steelwall_topright.EDITOR",		"RocksElements.png"	},
   { "steelwall_topright.EDITOR.xpos",		"1"			},
   { "steelwall_topright.EDITOR.ypos",		"13"			},
-  { "steelwall_bottomleft.EDITOR",		"RocksElements.pcx"	},
+  { "steelwall_bottomleft.EDITOR",		"RocksElements.png"	},
   { "steelwall_bottomleft.EDITOR.xpos",		"2"			},
   { "steelwall_bottomleft.EDITOR.ypos",		"13"			},
-  { "steelwall_bottomright.EDITOR",		"RocksElements.pcx"	},
+  { "steelwall_bottomright.EDITOR",		"RocksElements.png"	},
   { "steelwall_bottomright.EDITOR.xpos",	"3"			},
   { "steelwall_bottomright.EDITOR.ypos",	"13"			},
-  { "steelwall_horizontal.EDITOR",		"RocksElements.pcx"	},
+  { "steelwall_horizontal.EDITOR",		"RocksElements.png"	},
   { "steelwall_horizontal.EDITOR.xpos",		"4"			},
   { "steelwall_horizontal.EDITOR.ypos",		"13"			},
-  { "steelwall_vertical.EDITOR",		"RocksElements.pcx"	},
+  { "steelwall_vertical.EDITOR",		"RocksElements.png"	},
   { "steelwall_vertical.EDITOR.xpos",		"5"			},
   { "steelwall_vertical.EDITOR.ypos",		"13"			},
 
-  { "invisible_steelwall_topleft",		"RocksSP.pcx"		},
+  { "invisible_steelwall_topleft",		"RocksSP.png"		},
   { "invisible_steelwall_topleft.xpos",		"0"			},
   { "invisible_steelwall_topleft.ypos",		"0"			},
   { "invisible_steelwall_topleft.frames",	"1"			},
-  { "invisible_steelwall_topright",		"RocksSP.pcx"		},
+  { "invisible_steelwall_topright",		"RocksSP.png"		},
   { "invisible_steelwall_topright.xpos",	"0"			},
   { "invisible_steelwall_topright.ypos",	"0"			},
   { "invisible_steelwall_topright.frames",	"1"			},
-  { "invisible_steelwall_bottomleft",		"RocksSP.pcx"		},
+  { "invisible_steelwall_bottomleft",		"RocksSP.png"		},
   { "invisible_steelwall_bottomleft.xpos",	"0"			},
   { "invisible_steelwall_bottomleft.ypos",	"0"			},
   { "invisible_steelwall_bottomleft.frames",	"1"			},
-  { "invisible_steelwall_bottomright",		"RocksSP.pcx"		},
+  { "invisible_steelwall_bottomright",		"RocksSP.png"		},
   { "invisible_steelwall_bottomright.xpos",	"0"			},
   { "invisible_steelwall_bottomright.ypos",	"0"			},
   { "invisible_steelwall_bottomright.frames",	"1"			},
-  { "invisible_steelwall_horizontal",		"RocksSP.pcx"		},
+  { "invisible_steelwall_horizontal",		"RocksSP.png"		},
   { "invisible_steelwall_horizontal.xpos",	"0"			},
   { "invisible_steelwall_horizontal.ypos",	"0"			},
   { "invisible_steelwall_horizontal.frames",	"1"			},
-  { "invisible_steelwall_vertical",		"RocksSP.pcx"		},
+  { "invisible_steelwall_vertical",		"RocksSP.png"		},
   { "invisible_steelwall_vertical.xpos",	"0"			},
   { "invisible_steelwall_vertical.ypos",	"0"			},
   { "invisible_steelwall_vertical.frames",	"1"			},
 
-  { "invisible_steelwall_topleft.EDITOR",	"RocksElements.pcx"	},
+  { "invisible_steelwall_topleft.EDITOR",	"RocksElements.png"	},
   { "invisible_steelwall_topleft.EDITOR.xpos",	"6"			},
   { "invisible_steelwall_topleft.EDITOR.ypos",	"13"			},
-  { "invisible_steelwall_topright.EDITOR",	"RocksElements.pcx"	},
+  { "invisible_steelwall_topright.EDITOR",	"RocksElements.png"	},
   { "invisible_steelwall_topright.EDITOR.xpos",	"7"			},
   { "invisible_steelwall_topright.EDITOR.ypos",	"13"			},
-  { "invisible_steelwall_bottomleft.EDITOR",	"RocksElements.pcx"	},
+  { "invisible_steelwall_bottomleft.EDITOR",	"RocksElements.png"	},
   { "invisible_steelwall_bottomleft.EDITOR.xpos","8"			},
   { "invisible_steelwall_bottomleft.EDITOR.ypos","13"			},
-  { "invisible_steelwall_bottomright.EDITOR",	"RocksElements.pcx"	},
+  { "invisible_steelwall_bottomright.EDITOR",	"RocksElements.png"	},
   { "invisible_steelwall_bottomright.EDITOR.xpos","9"			},
   { "invisible_steelwall_bottomright.EDITOR.ypos","13"			},
-  { "invisible_steelwall_horizontal.EDITOR",	"RocksElements.pcx"	},
+  { "invisible_steelwall_horizontal.EDITOR",	"RocksElements.png"	},
   { "invisible_steelwall_horizontal.EDITOR.xpos","10"			},
   { "invisible_steelwall_horizontal.EDITOR.ypos","13"			},
-  { "invisible_steelwall_vertical.EDITOR",	"RocksElements.pcx"	},
+  { "invisible_steelwall_vertical.EDITOR",	"RocksElements.png"	},
   { "invisible_steelwall_vertical.EDITOR.xpos",	"11"			},
   { "invisible_steelwall_vertical.EDITOR.ypos",	"13"			},
 
-  { "arrow_left",				"RocksDC.pcx"		},
+  { "arrow_left",				"RocksDC.png"		},
   { "arrow_left.xpos",				"8"			},
   { "arrow_left.ypos",				"8"			},
   { "arrow_left.frames",			"1"			},
-  { "arrow_right",				"RocksDC.pcx"		},
+  { "arrow_right",				"RocksDC.png"		},
   { "arrow_right.xpos",				"9"			},
   { "arrow_right.ypos",				"8"			},
   { "arrow_right.frames",			"1"			},
-  { "arrow_up",					"RocksDC.pcx"		},
+  { "arrow_up",					"RocksDC.png"		},
   { "arrow_up.xpos",				"10"			},
   { "arrow_up.ypos",				"8"			},
   { "arrow_up.frames",				"1"			},
-  { "arrow_down",				"RocksDC.pcx"		},
+  { "arrow_down",				"RocksDC.png"		},
   { "arrow_down.xpos",				"11"			},
   { "arrow_down.ypos",				"8"			},
   { "arrow_down.frames",			"1"			},
 
-  { "unknown",					"RocksFontEM.pcx"	},
+  { "unknown",					"RocksFontEM.png"	},
   { "unknown.xpos",				"15"			},
   { "unknown.ypos",				"1"			},
   { "unknown.frames",				"1"			},
 
-  { "trigger_element",				"RocksDC.pcx"		},
+  { "trigger_element",				"RocksDC.png"		},
   { "trigger_element.xpos",			"15"			},
   { "trigger_element.ypos",			"14"			},
   { "trigger_element.frames",			"1"			},
 
-  { "trigger_player",				"RocksDC.pcx"		},
+  { "trigger_player",				"RocksDC.png"		},
   { "trigger_player.xpos",			"15"			},
   { "trigger_player.ypos",			"13"			},
   { "trigger_player.frames",			"1"			},
 
-  { "trigger_ce_value",				"RocksDC.pcx"		},
+  { "trigger_ce_value",				"RocksDC.png"		},
   { "trigger_ce_value.xpos",			"15"			},
   { "trigger_ce_value.ypos",			"11"			},
   { "trigger_ce_value.frames",			"1"			},
 
-  { "trigger_ce_score",				"RocksDC.pcx"		},
+  { "trigger_ce_score",				"RocksDC.png"		},
   { "trigger_ce_score.xpos",			"15"			},
   { "trigger_ce_score.ypos",			"12"			},
   { "trigger_ce_score.frames",			"1"			},
 
-  { "current_ce_value",				"RocksDC.pcx"		},
+  { "current_ce_value",				"RocksDC.png"		},
   { "current_ce_value.xpos",			"14"			},
   { "current_ce_value.ypos",			"11"			},
   { "current_ce_value.frames",			"1"			},
 
-  { "current_ce_score",				"RocksDC.pcx"		},
+  { "current_ce_score",				"RocksDC.png"		},
   { "current_ce_score.xpos",			"14"			},
   { "current_ce_score.ypos",			"12"			},
   { "current_ce_score.frames",			"1"			},
 
-  { "prev_ce_1",				"RocksMore.pcx"		},
+  { "prev_ce_1",				"RocksMore.png"		},
   { "prev_ce_1.xpos",				"0"			},
   { "prev_ce_1.ypos",				"7"			},
   { "prev_ce_1.frames",				"1"			},
 
-  { "prev_ce_2",				"RocksMore.pcx"		},
+  { "prev_ce_2",				"RocksMore.png"		},
   { "prev_ce_2.xpos",				"1"			},
   { "prev_ce_2.ypos",				"7"			},
   { "prev_ce_2.frames",				"1"			},
 
-  { "prev_ce_3",				"RocksMore.pcx"		},
+  { "prev_ce_3",				"RocksMore.png"		},
   { "prev_ce_3.xpos",				"2"			},
   { "prev_ce_3.ypos",				"7"			},
   { "prev_ce_3.frames",				"1"			},
 
-  { "prev_ce_4",				"RocksMore.pcx"		},
+  { "prev_ce_4",				"RocksMore.png"		},
   { "prev_ce_4.xpos",				"3"			},
   { "prev_ce_4.ypos",				"7"			},
   { "prev_ce_4.frames",				"1"			},
 
-  { "prev_ce_5",				"RocksMore.pcx"		},
+  { "prev_ce_5",				"RocksMore.png"		},
   { "prev_ce_5.xpos",				"4"			},
   { "prev_ce_5.ypos",				"7"			},
   { "prev_ce_5.frames",				"1"			},
 
-  { "prev_ce_6",				"RocksMore.pcx"		},
+  { "prev_ce_6",				"RocksMore.png"		},
   { "prev_ce_6.xpos",				"5"			},
   { "prev_ce_6.ypos",				"7"			},
   { "prev_ce_6.frames",				"1"			},
 
-  { "prev_ce_7",				"RocksMore.pcx"		},
+  { "prev_ce_7",				"RocksMore.png"		},
   { "prev_ce_7.xpos",				"6"			},
   { "prev_ce_7.ypos",				"7"			},
   { "prev_ce_7.frames",				"1"			},
 
-  { "prev_ce_8",				"RocksMore.pcx"		},
+  { "prev_ce_8",				"RocksMore.png"		},
   { "prev_ce_8.xpos",				"7"			},
   { "prev_ce_8.ypos",				"7"			},
   { "prev_ce_8.frames",				"1"			},
 
-  { "next_ce_1",				"RocksMore.pcx"		},
+  { "next_ce_1",				"RocksMore.png"		},
   { "next_ce_1.xpos",				"0"			},
   { "next_ce_1.ypos",				"8"			},
   { "next_ce_1.frames",				"1"			},
 
-  { "next_ce_2",				"RocksMore.pcx"		},
+  { "next_ce_2",				"RocksMore.png"		},
   { "next_ce_2.xpos",				"1"			},
   { "next_ce_2.ypos",				"8"			},
   { "next_ce_2.frames",				"1"			},
 
-  { "next_ce_3",				"RocksMore.pcx"		},
+  { "next_ce_3",				"RocksMore.png"		},
   { "next_ce_3.xpos",				"2"			},
   { "next_ce_3.ypos",				"8"			},
   { "next_ce_3.frames",				"1"			},
 
-  { "next_ce_4",				"RocksMore.pcx"		},
+  { "next_ce_4",				"RocksMore.png"		},
   { "next_ce_4.xpos",				"3"			},
   { "next_ce_4.ypos",				"8"			},
   { "next_ce_4.frames",				"1"			},
 
-  { "next_ce_5",				"RocksMore.pcx"		},
+  { "next_ce_5",				"RocksMore.png"		},
   { "next_ce_5.xpos",				"4"			},
   { "next_ce_5.ypos",				"8"			},
   { "next_ce_5.frames",				"1"			},
 
-  { "next_ce_6",				"RocksMore.pcx"		},
+  { "next_ce_6",				"RocksMore.png"		},
   { "next_ce_6.xpos",				"5"			},
   { "next_ce_6.ypos",				"8"			},
   { "next_ce_6.frames",				"1"			},
 
-  { "next_ce_7",				"RocksMore.pcx"		},
+  { "next_ce_7",				"RocksMore.png"		},
   { "next_ce_7.xpos",				"6"			},
   { "next_ce_7.ypos",				"8"			},
   { "next_ce_7.frames",				"1"			},
 
-  { "next_ce_8",				"RocksMore.pcx"		},
+  { "next_ce_8",				"RocksMore.png"		},
   { "next_ce_8.xpos",				"7"			},
   { "next_ce_8.ypos",				"8"			},
   { "next_ce_8.frames",				"1"			},
 
-  { "self",					"RocksMore.pcx"		},
+  { "self",					"RocksMore.png"		},
   { "self.xpos",				"8"			},
   { "self.ypos",				"7"			},
   { "self.frames",				"1"			},
 
-  { "any_element",				"RocksMore.pcx"		},
+  { "any_element",				"RocksMore.png"		},
   { "any_element.xpos",				"9"			},
   { "any_element.ypos",				"7"			},
   { "any_element.frames",			"1"			},
 
-  { "emc_key_5",				"RocksEMC.pcx"		},
+  { "emc_key_5",				"RocksEMC.png"		},
   { "emc_key_5.xpos",				"0"			},
   { "emc_key_5.ypos",				"5"			},
   { "emc_key_5.frames",				"1"			},
-  { "emc_key_6",				"RocksEMC.pcx"		},
+  { "emc_key_6",				"RocksEMC.png"		},
   { "emc_key_6.xpos",				"1"			},
   { "emc_key_6.ypos",				"5"			},
   { "emc_key_6.frames",				"1"			},
-  { "emc_key_7",				"RocksEMC.pcx"		},
+  { "emc_key_7",				"RocksEMC.png"		},
   { "emc_key_7.xpos",				"2"			},
   { "emc_key_7.ypos",				"5"			},
   { "emc_key_7.frames",				"1"			},
-  { "emc_key_8",				"RocksEMC.pcx"		},
+  { "emc_key_8",				"RocksEMC.png"		},
   { "emc_key_8.xpos",				"3"			},
   { "emc_key_8.ypos",				"5"			},
   { "emc_key_8.frames",				"1"			},
 
-  { "emc_gate_5",				"RocksEMC.pcx"		},
+  { "emc_gate_5",				"RocksEMC.png"		},
   { "emc_gate_5.xpos",				"0"			},
   { "emc_gate_5.ypos",				"6"			},
   { "emc_gate_5.frames",			"1"			},
-  { "emc_gate_6",				"RocksEMC.pcx"		},
+  { "emc_gate_6",				"RocksEMC.png"		},
   { "emc_gate_6.xpos",				"1"			},
   { "emc_gate_6.ypos",				"6"			},
   { "emc_gate_6.frames",			"1"			},
-  { "emc_gate_7",				"RocksEMC.pcx"		},
+  { "emc_gate_7",				"RocksEMC.png"		},
   { "emc_gate_7.xpos",				"2"			},
   { "emc_gate_7.ypos",				"6"			},
   { "emc_gate_7.frames",			"1"			},
-  { "emc_gate_8",				"RocksEMC.pcx"		},
+  { "emc_gate_8",				"RocksEMC.png"		},
   { "emc_gate_8.xpos",				"3"			},
   { "emc_gate_8.ypos",				"6"			},
   { "emc_gate_8.frames",			"1"			},
-  { "emc_gate_5_gray",				"RocksEMC.pcx"		},
+  { "emc_gate_5_gray",				"RocksEMC.png"		},
   { "emc_gate_5_gray.xpos",			"4"			},
   { "emc_gate_5_gray.ypos",			"7"			},
   { "emc_gate_5_gray.frames",			"1"			},
-  { "emc_gate_5_gray.EDITOR",			"RocksEMC.pcx"		},
+  { "emc_gate_5_gray.EDITOR",			"RocksEMC.png"		},
   { "emc_gate_5_gray.EDITOR.xpos",		"0"			},
   { "emc_gate_5_gray.EDITOR.ypos",		"7"			},
-  { "emc_gate_5_gray.active",			"RocksEMC.pcx"		},
+  { "emc_gate_5_gray.active",			"RocksEMC.png"		},
   { "emc_gate_5_gray.active.xpos",		"0"			},
   { "emc_gate_5_gray.active.ypos",		"6"			},
   { "emc_gate_5_gray.active.frames",		"1"			},
-  { "emc_gate_6_gray",				"RocksEMC.pcx"		},
+  { "emc_gate_6_gray",				"RocksEMC.png"		},
   { "emc_gate_6_gray.xpos",			"4"			},
   { "emc_gate_6_gray.ypos",			"7"			},
   { "emc_gate_6_gray.frames",			"1"			},
-  { "emc_gate_6_gray.EDITOR",			"RocksEMC.pcx"		},
+  { "emc_gate_6_gray.EDITOR",			"RocksEMC.png"		},
   { "emc_gate_6_gray.EDITOR.xpos",		"1"			},
   { "emc_gate_6_gray.EDITOR.ypos",		"7"			},
-  { "emc_gate_6_gray.active",			"RocksEMC.pcx"		},
+  { "emc_gate_6_gray.active",			"RocksEMC.png"		},
   { "emc_gate_6_gray.active.xpos",		"1"			},
   { "emc_gate_6_gray.active.ypos",		"6"			},
   { "emc_gate_6_gray.active.frames",		"1"			},
-  { "emc_gate_7_gray",				"RocksEMC.pcx"		},
+  { "emc_gate_7_gray",				"RocksEMC.png"		},
   { "emc_gate_7_gray.xpos",			"4"			},
   { "emc_gate_7_gray.ypos",			"7"			},
   { "emc_gate_7_gray.frames",			"1"			},
-  { "emc_gate_7_gray.EDITOR",			"RocksEMC.pcx"		},
+  { "emc_gate_7_gray.EDITOR",			"RocksEMC.png"		},
   { "emc_gate_7_gray.EDITOR.xpos",		"2"			},
   { "emc_gate_7_gray.EDITOR.ypos",		"7"			},
-  { "emc_gate_7_gray.active",			"RocksEMC.pcx"		},
+  { "emc_gate_7_gray.active",			"RocksEMC.png"		},
   { "emc_gate_7_gray.active.xpos",		"2"			},
   { "emc_gate_7_gray.active.ypos",		"6"			},
   { "emc_gate_7_gray.active.frames",		"1"			},
-  { "emc_gate_8_gray",				"RocksEMC.pcx"		},
+  { "emc_gate_8_gray",				"RocksEMC.png"		},
   { "emc_gate_8_gray.xpos",			"4"			},
   { "emc_gate_8_gray.ypos",			"7"			},
   { "emc_gate_8_gray.frames",			"1"			},
-  { "emc_gate_8_gray.EDITOR",			"RocksEMC.pcx"		},
+  { "emc_gate_8_gray.EDITOR",			"RocksEMC.png"		},
   { "emc_gate_8_gray.EDITOR.xpos",		"3"			},
   { "emc_gate_8_gray.EDITOR.ypos",		"7"			},
-  { "emc_gate_8_gray.active",			"RocksEMC.pcx"		},
+  { "emc_gate_8_gray.active",			"RocksEMC.png"		},
   { "emc_gate_8_gray.active.xpos",		"3"			},
   { "emc_gate_8_gray.active.ypos",		"6"			},
   { "emc_gate_8_gray.active.frames",		"1"			},
 
-  { "emc_android",				"RocksEMC.pcx"		},
+  { "emc_android",				"RocksEMC.png"		},
   { "emc_android.xpos",				"0"			},
   { "emc_android.ypos",				"8"			},
   { "emc_android.frames",			"8"			},
   { "emc_android.delay",			"2"			},
 
-  { "emc_android.shrinking.upleft",		"RocksEMC.pcx"		},
+  { "emc_android.shrinking.upleft",		"RocksEMC.png"		},
   { "emc_android.shrinking.upleft.xpos",	"1"			},
   { "emc_android.shrinking.upleft.ypos",	"11"			},
   { "emc_android.shrinking.upleft.frames",	"8"			},
   { "emc_android.shrinking.upleft.anim_mode",	"linear"		},
 
-  { "emc_android.growing.downright",		"RocksEMC.pcx"		},
+  { "emc_android.growing.downright",		"RocksEMC.png"		},
   { "emc_android.growing.downright.xpos",	"0"			},
   { "emc_android.growing.downright.ypos",	"11"			},
   { "emc_android.growing.downright.frames",	"8"			},
   { "emc_android.growing.downright.anim_mode",	"linear,reverse"	},
 
-  { "emc_android.shrinking.downleft",		"RocksEMC.pcx"		},
+  { "emc_android.shrinking.downleft",		"RocksEMC.png"		},
   { "emc_android.shrinking.downleft.xpos",	"1"			},
   { "emc_android.shrinking.downleft.ypos",	"12"			},
   { "emc_android.shrinking.downleft.frames",	"8"			},
   { "emc_android.shrinking.downleft.anim_mode",	"linear"		},
 
-  { "emc_android.growing.upright",		"RocksEMC.pcx"		},
+  { "emc_android.growing.upright",		"RocksEMC.png"		},
   { "emc_android.growing.upright.xpos",		"0"			},
   { "emc_android.growing.upright.ypos",		"12"			},
   { "emc_android.growing.upright.frames",	"8"			},
   { "emc_android.growing.upright.anim_mode",	"linear,reverse"	},
 
-  { "emc_android.shrinking.upright",		"RocksEMC.pcx"		},
+  { "emc_android.shrinking.upright",		"RocksEMC.png"		},
   { "emc_android.shrinking.upright.xpos",	"1"			},
   { "emc_android.shrinking.upright.ypos",	"13"			},
   { "emc_android.shrinking.upright.frames",	"8"			},
   { "emc_android.shrinking.upright.anim_mode",	"linear"		},
 
-  { "emc_android.growing.downleft",		"RocksEMC.pcx"		},
+  { "emc_android.growing.downleft",		"RocksEMC.png"		},
   { "emc_android.growing.downleft.xpos",	"0"			},
   { "emc_android.growing.downleft.ypos",	"13"			},
   { "emc_android.growing.downleft.frames",	"8"			},
   { "emc_android.growing.downleft.anim_mode",	"linear,reverse"	},
 
-  { "emc_android.shrinking.downright",		"RocksEMC.pcx"		},
+  { "emc_android.shrinking.downright",		"RocksEMC.png"		},
   { "emc_android.shrinking.downright.xpos",	"1"			},
   { "emc_android.shrinking.downright.ypos",	"14"			},
   { "emc_android.shrinking.downright.frames",	"8"			},
   { "emc_android.shrinking.downright.anim_mode","linear"		},
 
-  { "emc_android.growing.upleft",		"RocksEMC.pcx"		},
+  { "emc_android.growing.upleft",		"RocksEMC.png"		},
   { "emc_android.growing.upleft.xpos",		"0"			},
   { "emc_android.growing.upleft.ypos",		"14"			},
   { "emc_android.growing.upleft.frames",	"8"			},
   { "emc_android.growing.upleft.anim_mode",	"linear,reverse"	},
 
-  { "emc_grass",				"RocksEMC.pcx"		},
+  { "emc_grass",				"RocksEMC.png"		},
   { "emc_grass.xpos",				"0"			},
   { "emc_grass.ypos",				"4"			},
   { "emc_grass.frames",				"1"			},
-  { "emc_grass.CRUMBLED",			"RocksEMC.pcx"		},
+  { "emc_grass.CRUMBLED",			"RocksEMC.png"		},
   { "emc_grass.CRUMBLED.xpos",			"1"			},
   { "emc_grass.CRUMBLED.ypos",			"4"			},
   { "emc_grass.CRUMBLED.frames",		"1"			},
-  { "emc_grass.digging.left",			"RocksEMC.pcx"		},
+  { "emc_grass.digging.left",			"RocksEMC.png"		},
   { "emc_grass.digging.left.xpos",		"6"			},
   { "emc_grass.digging.left.ypos",		"0"			},
   { "emc_grass.digging.left.frames",		"3"			},
   { "emc_grass.digging.left.delay",		"2"			},
   { "emc_grass.digging.left.anim_mode",		"linear"		},
-  { "emc_grass.digging.right",			"RocksEMC.pcx"		},
+  { "emc_grass.digging.right",			"RocksEMC.png"		},
   { "emc_grass.digging.right.xpos",		"9"			},
   { "emc_grass.digging.right.ypos",		"0"			},
   { "emc_grass.digging.right.frames",		"3"			},
   { "emc_grass.digging.right.delay",		"2"			},
   { "emc_grass.digging.right.anim_mode",	"linear"		},
-  { "emc_grass.digging.up",			"RocksEMC.pcx"		},
+  { "emc_grass.digging.up",			"RocksEMC.png"		},
   { "emc_grass.digging.up.xpos",		"0"			},
   { "emc_grass.digging.up.ypos",		"0"			},
   { "emc_grass.digging.up.frames",		"3"			},
   { "emc_grass.digging.up.delay",		"2"			},
   { "emc_grass.digging.up.anim_mode",		"linear"		},
-  { "emc_grass.digging.down",			"RocksEMC.pcx"		},
+  { "emc_grass.digging.down",			"RocksEMC.png"		},
   { "emc_grass.digging.down.xpos",		"3"			},
   { "emc_grass.digging.down.ypos",		"0"			},
   { "emc_grass.digging.down.frames",		"3"			},
   { "emc_grass.digging.down.delay",		"2"			},
   { "emc_grass.digging.down.anim_mode",		"linear"		},
-  { "emc_grass.digging.left.CRUMBLED",		"RocksEMC.pcx"		},
+  { "emc_grass.digging.left.CRUMBLED",		"RocksEMC.png"		},
   { "emc_grass.digging.left.CRUMBLED.xpos",	"6"			},
   { "emc_grass.digging.left.CRUMBLED.ypos",	"1"			},
   { "emc_grass.digging.left.CRUMBLED.frames",	"3"			},
   { "emc_grass.digging.left.CRUMBLED.delay",	"2"			},
   { "emc_grass.digging.left.CRUMBLED.anim_mode","linear"		},
-  { "emc_grass.digging.right.CRUMBLED",		"RocksEMC.pcx"		},
+  { "emc_grass.digging.right.CRUMBLED",		"RocksEMC.png"		},
   { "emc_grass.digging.right.CRUMBLED.xpos",	"9"			},
   { "emc_grass.digging.right.CRUMBLED.ypos",	"1"			},
   { "emc_grass.digging.right.CRUMBLED.frames",	"3"			},
   { "emc_grass.digging.right.CRUMBLED.delay",	"2"			},
   { "emc_grass.digging.right.CRUMBLED.anim_mode","linear"		},
-  { "emc_grass.digging.up.CRUMBLED",		"RocksEMC.pcx"		},
+  { "emc_grass.digging.up.CRUMBLED",		"RocksEMC.png"		},
   { "emc_grass.digging.up.CRUMBLED.xpos",	"0"			},
   { "emc_grass.digging.up.CRUMBLED.ypos",	"1"			},
   { "emc_grass.digging.up.CRUMBLED.frames",	"3"			},
   { "emc_grass.digging.up.CRUMBLED.delay",	"2"			},
   { "emc_grass.digging.up.CRUMBLED.anim_mode",	"linear"		},
-  { "emc_grass.digging.down.CRUMBLED",		"RocksEMC.pcx"		},
+  { "emc_grass.digging.down.CRUMBLED",		"RocksEMC.png"		},
   { "emc_grass.digging.down.CRUMBLED.xpos",	"3"			},
   { "emc_grass.digging.down.CRUMBLED.ypos",	"1"			},
   { "emc_grass.digging.down.CRUMBLED.frames",	"3"			},
   { "emc_grass.digging.down.CRUMBLED.delay",	"2"			},
   { "emc_grass.digging.down.CRUMBLED.anim_mode","linear"		},
 
-  { "emc_magic_ball",				"RocksEMC.pcx"		},
+  { "emc_magic_ball",				"RocksEMC.png"		},
   { "emc_magic_ball.xpos",			"0"			},
   { "emc_magic_ball.ypos",			"9"			},
   { "emc_magic_ball.frames",			"1"			},
-  { "emc_magic_ball.active",			"RocksEMC.pcx"		},
+  { "emc_magic_ball.active",			"RocksEMC.png"		},
   { "emc_magic_ball.active.xpos",		"0"			},
   { "emc_magic_ball.active.ypos",		"9"			},
   { "emc_magic_ball.active.frames",		"16"			},
   { "emc_magic_ball.active.frames_per_line",	"8"			},
-  { "emc_magic_ball.dropping",			"RocksElements.pcx"	},
+  { "emc_magic_ball.dropping",			"RocksElements.png"	},
   { "emc_magic_ball.dropping.xpos",		"0"			},
   { "emc_magic_ball.dropping.ypos",		"4"			},
   { "emc_magic_ball.dropping.frames",		"8"			},
   { "emc_magic_ball.dropping.anim_mode",	"linear"		},
 
-  { "emc_magic_ball_switch",			"RocksEMC.pcx"		},
+  { "emc_magic_ball_switch",			"RocksEMC.png"		},
   { "emc_magic_ball_switch.xpos",		"8"			},
   { "emc_magic_ball_switch.ypos",		"10"			},
   { "emc_magic_ball_switch.frames",		"1"			},
-  { "emc_magic_ball_switch.active",		"RocksEMC.pcx"		},
+  { "emc_magic_ball_switch.active",		"RocksEMC.png"		},
   { "emc_magic_ball_switch.active.xpos",	"8"			},
   { "emc_magic_ball_switch.active.ypos",	"9"			},
   { "emc_magic_ball_switch.active.frames",	"1"			},
 
-  { "emc_spring_bumper",			"RocksEMC.pcx"		},
+  { "emc_spring_bumper",			"RocksEMC.png"		},
   { "emc_spring_bumper.xpos",			"8"			},
   { "emc_spring_bumper.ypos",			"4"			},
   { "emc_spring_bumper.frames",			"1"			},
 
-  { "emc_spring_bumper.active",			"RocksEMC.pcx"		},
+  { "emc_spring_bumper.active",			"RocksEMC.png"		},
   { "emc_spring_bumper.active.xpos",		"8"			},
   { "emc_spring_bumper.active.ypos",		"4"			},
   { "emc_spring_bumper.active.frames",		"4"			},
   { "emc_spring_bumper.active.anim_mode",	"pingpong2"		},
 
-  { "emc_plant",				"RocksEMC.pcx"		},
+  { "emc_plant",				"RocksEMC.png"		},
   { "emc_plant.xpos",				"4"			},
   { "emc_plant.ypos",				"4"			},
   { "emc_plant.frames",				"1"			},
-  { "emc_plant.CRUMBLED",			"RocksEMC.pcx"		},
+  { "emc_plant.CRUMBLED",			"RocksEMC.png"		},
   { "emc_plant.CRUMBLED.xpos",			"5"			},
   { "emc_plant.CRUMBLED.ypos",			"4"			},
   { "emc_plant.CRUMBLED.frames",		"1"			},
 
-  { "emc_lenses",				"RocksEMC.pcx"		},
+  { "emc_lenses",				"RocksEMC.png"		},
   { "emc_lenses.xpos",				"6"			},
   { "emc_lenses.ypos",				"4"			},
   { "emc_lenses.frames",			"1"			},
 
-  { "emc_magnifier",				"RocksEMC.pcx"		},
+  { "emc_magnifier",				"RocksEMC.png"		},
   { "emc_magnifier.xpos",			"7"			},
   { "emc_magnifier.ypos",			"4"			},
   { "emc_magnifier.frames",			"1"			},
 
-  { "emc_wall_9",				"RocksEMC.pcx"		},
+  { "emc_wall_9",				"RocksEMC.png"		},
   { "emc_wall_9.xpos",				"10"			},
   { "emc_wall_9.ypos",				"5"			},
   { "emc_wall_9.frames",			"1"			},
-  { "emc_wall_10",				"RocksEMC.pcx"		},
+  { "emc_wall_10",				"RocksEMC.png"		},
   { "emc_wall_10.xpos",				"10"			},
   { "emc_wall_10.ypos",				"6"			},
   { "emc_wall_10.frames",			"1"			},
-  { "emc_wall_11",				"RocksEMC.pcx"		},
+  { "emc_wall_11",				"RocksEMC.png"		},
   { "emc_wall_11.xpos",				"11"			},
   { "emc_wall_11.ypos",				"5"			},
   { "emc_wall_11.frames",			"1"			},
-  { "emc_wall_12",				"RocksEMC.pcx"		},
+  { "emc_wall_12",				"RocksEMC.png"		},
   { "emc_wall_12.xpos",				"11"			},
   { "emc_wall_12.ypos",				"6"			},
   { "emc_wall_12.frames",			"1"			},
-  { "emc_wall_13",				"RocksEMC.pcx"		},
+  { "emc_wall_13",				"RocksEMC.png"		},
   { "emc_wall_13.xpos",				"10"			},
   { "emc_wall_13.ypos",				"7"			},
   { "emc_wall_13.frames",			"1"			},
-  { "emc_wall_14",				"RocksEMC.pcx"		},
+  { "emc_wall_14",				"RocksEMC.png"		},
   { "emc_wall_14.xpos",				"10"			},
   { "emc_wall_14.ypos",				"8"			},
   { "emc_wall_14.frames",			"1"			},
-  { "emc_wall_15",				"RocksEMC.pcx"		},
+  { "emc_wall_15",				"RocksEMC.png"		},
   { "emc_wall_15.xpos",				"10"			},
   { "emc_wall_15.ypos",				"9"			},
   { "emc_wall_15.frames",			"1"			},
-  { "emc_wall_16",				"RocksEMC.pcx"		},
+  { "emc_wall_16",				"RocksEMC.png"		},
   { "emc_wall_16.xpos",				"10"			},
   { "emc_wall_16.ypos",				"10"			},
   { "emc_wall_16.frames",			"1"			},
 
-  { "emc_wall_slippery_1",			"RocksEMC.pcx"		},
+  { "emc_wall_slippery_1",			"RocksEMC.png"		},
   { "emc_wall_slippery_1.xpos",			"11"			},
   { "emc_wall_slippery_1.ypos",			"7"			},
   { "emc_wall_slippery_1.frames",		"1"			},
-  { "emc_wall_slippery_2",			"RocksEMC.pcx"		},
+  { "emc_wall_slippery_2",			"RocksEMC.png"		},
   { "emc_wall_slippery_2.xpos",			"11"			},
   { "emc_wall_slippery_2.ypos",			"8"			},
   { "emc_wall_slippery_2.frames",		"1"			},
-  { "emc_wall_slippery_3",			"RocksEMC.pcx"		},
+  { "emc_wall_slippery_3",			"RocksEMC.png"		},
   { "emc_wall_slippery_3.xpos",			"11"			},
   { "emc_wall_slippery_3.ypos",			"9"			},
   { "emc_wall_slippery_3.frames",		"1"			},
-  { "emc_wall_slippery_4",			"RocksEMC.pcx"		},
+  { "emc_wall_slippery_4",			"RocksEMC.png"		},
   { "emc_wall_slippery_4.xpos",			"11"			},
   { "emc_wall_slippery_4.ypos",			"10"			},
   { "emc_wall_slippery_4.frames",		"1"			},
 
-  { "emc_fake_grass",				"RocksEMC.pcx"		},
+  { "emc_fake_grass",				"RocksEMC.png"		},
   { "emc_fake_grass.xpos",			"0"			},
   { "emc_fake_grass.ypos",			"4"			},
   { "emc_fake_grass.frames",			"1"			},
-  { "emc_fake_grass.CRUMBLED",			"RocksEMC.pcx"		},
+  { "emc_fake_grass.CRUMBLED",			"RocksEMC.png"		},
   { "emc_fake_grass.CRUMBLED.xpos",		"1"			},
   { "emc_fake_grass.CRUMBLED.ypos",		"4"			},
   { "emc_fake_grass.CRUMBLED.frames",		"1"			},
-  { "emc_fake_grass.active",			"RocksEMC.pcx"		},
+  { "emc_fake_grass.active",			"RocksEMC.png"		},
   { "emc_fake_grass.active.xpos",		"2"			},
   { "emc_fake_grass.active.ypos",		"4"			},
   { "emc_fake_grass.active.frames",		"1"			},
-  { "emc_fake_grass.active.CRUMBLED",		"RocksEMC.pcx"		},
+  { "emc_fake_grass.active.CRUMBLED",		"RocksEMC.png"		},
   { "emc_fake_grass.active.CRUMBLED.xpos",	"3"			},
   { "emc_fake_grass.active.CRUMBLED.ypos",	"4"			},
   { "emc_fake_grass.active.CRUMBLED.frames",	"1"			},
-  { "emc_fake_grass.EDITOR",			"RocksEMC.pcx"		},
+  { "emc_fake_grass.EDITOR",			"RocksEMC.png"		},
   { "emc_fake_grass.EDITOR.xpos",		"2"			},
   { "emc_fake_grass.EDITOR.ypos",		"4"			},
   { "emc_fake_grass.EDITOR.frames",		"1"			},
 
-  { "emc_fake_acid",				"RocksElements.pcx"	},
+  { "emc_fake_acid",				"RocksElements.png"	},
   { "emc_fake_acid.xpos",			"12"			},
   { "emc_fake_acid.ypos",			"7"			},
   { "emc_fake_acid.frames",			"4"			},
   { "emc_fake_acid.delay",			"10"			},
   { "emc_fake_acid.global_sync",		"true"			},
 
-  { "emc_dripper",				"RocksSP.pcx"		},
+  { "emc_dripper",				"RocksSP.png"		},
   { "emc_dripper.xpos",				"0"			},
   { "emc_dripper.ypos",				"0"			},
   { "emc_dripper.frames",			"1"			},
-  { "emc_dripper.EDITOR",			"RocksEMC.pcx"		},
+  { "emc_dripper.EDITOR",			"RocksEMC.png"		},
   { "emc_dripper.EDITOR.xpos",			"8"			},
   { "emc_dripper.EDITOR.ypos",			"8"			},
-  { "emc_dripper.active",			"RocksEMC.pcx"		},
+  { "emc_dripper.active",			"RocksEMC.png"		},
   { "emc_dripper.active.xpos",			"8"			},
   { "emc_dripper.active.ypos",			"8"			},
   { "emc_dripper.active.frames",		"1"			},
@@ -4362,36 +4374,40 @@ struct ConfigInfo image_config[] =
 #include "conf_cus.c"	/* include auto-generated data structure definitions */
 #include "conf_grp.c"	/* include auto-generated data structure definitions */
 
-  /* images not associated to game elements (used for menu screens etc.) */
+
+  // ==========================================================================
+  // image definitions not associated with game elements (menu screens etc.)
+  // ==========================================================================
+
   /* keyword to stop parser: "NO_MORE_ELEMENT_IMAGES" <-- do not change! */
 
 #if 1
   /* !!! TEMPORARILY STORED HERE -- PROBABLY TO BE CHANGED !!! */
 
-  /* (for testing, change filename back to "emc_objects dot pcx") */
-  { "emc_object",				"RocksEMC.pcx"		},
+  /* (for testing, change filename back to "emc_objects dot png") */
+  { "emc_object",				"RocksEMC.png"		},
 #if 0
   { "emc_object.scale_up_factor",		"2"			},
 #endif
 
-  /* (for testing, change filename back to "emc_players dot pcx") */
-  { "emc_sprite",				"RocksEMC.pcx"		},
+  /* (for testing, change filename back to "emc_players dot png") */
+  { "emc_sprite",				"RocksEMC.png"		},
 #if 0
   { "emc_sprite.scale_up_factor",		"2"			},
 #endif
 #endif
 
-  { "sp_frame_horizontal",			"RocksSP.pcx"		},
+  { "sp_frame_horizontal",			"RocksSP.png"		},
   { "sp_frame_horizontal.xpos",			"7"			},
   { "sp_frame_horizontal.ypos",			"14"			},
-  { "sp_frame_vertical",			"RocksSP.pcx"		},
+  { "sp_frame_vertical",			"RocksSP.png"		},
   { "sp_frame_vertical.xpos",			"6"			},
   { "sp_frame_vertical.ypos",			"14"			},
-  { "sp_frame_corner",				"RocksSP.pcx"		},
+  { "sp_frame_corner",				"RocksSP.png"		},
   { "sp_frame_corner.xpos",			"5"			},
   { "sp_frame_corner.ypos",			"14"			},
 
-  { "toon_1",					"RocksToons.pcx"	},
+  { "toon_1",					"RocksToons.png"	},
   { "toon_1.x",					"2"			},
   { "toon_1.y",					"72"			},
   { "toon_1.width",				"40"			},
@@ -4403,7 +4419,7 @@ struct ConfigInfo image_config[] =
   { "toon_1.direction",				"right"			},
   { "toon_1.position",				"bottom"		},
 
-  { "toon_2",					"RocksToons.pcx"	},
+  { "toon_2",					"RocksToons.png"	},
   { "toon_2.x",					"2"			},
   { "toon_2.y",					"186"			},
   { "toon_2.width",				"40"			},
@@ -4415,7 +4431,7 @@ struct ConfigInfo image_config[] =
   { "toon_2.direction",				"left"			},
   { "toon_2.position",				"bottom"		},
 
-  { "toon_3",					"RocksToons.pcx"	},
+  { "toon_3",					"RocksToons.png"	},
   { "toon_3.x",					"2"			},
   { "toon_3.y",					"125"			},
   { "toon_3.width",				"48"			},
@@ -4427,7 +4443,7 @@ struct ConfigInfo image_config[] =
   { "toon_3.direction",				"right"			},
   { "toon_3.position",				"bottom"		},
 
-  { "toon_4",					"RocksToons.pcx"	},
+  { "toon_4",					"RocksToons.png"	},
   { "toon_4.x",					"327"			},
   { "toon_4.y",					"10"			},
   { "toon_4.width",				"80"			},
@@ -4439,7 +4455,7 @@ struct ConfigInfo image_config[] =
   { "toon_4.direction",				"up"			},
   { "toon_4.position",				"any"			},
 
-  { "toon_5",					"RocksToons.pcx"	},
+  { "toon_5",					"RocksToons.png"	},
   { "toon_5.x",					"2"			},
   { "toon_5.y",					"2"			},
   { "toon_5.width",				"32"			},
@@ -4452,7 +4468,7 @@ struct ConfigInfo image_config[] =
   { "toon_5.direction",				"right"			},
   { "toon_5.position",				"upper"			},
 
-  { "toon_6",					"RocksToons.pcx"	},
+  { "toon_6",					"RocksToons.png"	},
   { "toon_6.x",					"2"			},
   { "toon_6.y",					"37"			},
   { "toon_6.width",				"32"			},
@@ -4465,7 +4481,7 @@ struct ConfigInfo image_config[] =
   { "toon_6.direction",				"left"			},
   { "toon_6.position",				"upper"			},
 
-  { "toon_7",					"RocksMore.pcx"		},
+  { "toon_7",					"RocksMore.png"		},
   { "toon_7.xpos",				"0"			},
   { "toon_7.ypos",				"6"			},
   { "toon_7.frames",				"16"			},
@@ -4473,7 +4489,7 @@ struct ConfigInfo image_config[] =
   { "toon_7.direction",				"down"			},
   { "toon_7.position",				"any"			},
 
-  { "toon_8",					"RocksHeroes.pcx"	},
+  { "toon_8",					"RocksHeroes.png"	},
   { "toon_8.xpos",				"4"			},
   { "toon_8.ypos",				"1"			},
   { "toon_8.frames",				"4"			},
@@ -4481,7 +4497,7 @@ struct ConfigInfo image_config[] =
   { "toon_8.direction",				"right"			},
   { "toon_8.position",				"bottom"		},
 
-  { "toon_9",					"RocksHeroes.pcx"	},
+  { "toon_9",					"RocksHeroes.png"	},
   { "toon_9.xpos",				"8"			},
   { "toon_9.ypos",				"7"			},
   { "toon_9.frames",				"4"			},
@@ -4489,7 +4505,7 @@ struct ConfigInfo image_config[] =
   { "toon_9.direction",				"left"			},
   { "toon_9.position",				"bottom"		},
 
-  { "toon_10",					"RocksHeroes.pcx"	},
+  { "toon_10",					"RocksHeroes.png"	},
   { "toon_10.xpos",				"12"			},
   { "toon_10.ypos",				"7"			},
   { "toon_10.frames",				"4"			},
@@ -4497,7 +4513,7 @@ struct ConfigInfo image_config[] =
   { "toon_10.direction",			"right"			},
   { "toon_10.position",				"bottom"		},
 
-  { "toon_11",					"RocksHeroes.pcx"	},
+  { "toon_11",					"RocksHeroes.png"	},
   { "toon_11.xpos",				"8"			},
   { "toon_11.ypos",				"5"			},
   { "toon_11.frames",				"4"			},
@@ -4505,7 +4521,7 @@ struct ConfigInfo image_config[] =
   { "toon_11.direction",			"left"			},
   { "toon_11.position",				"bottom"		},
 
-  { "toon_12",					"RocksHeroes.pcx"	},
+  { "toon_12",					"RocksHeroes.png"	},
   { "toon_12.xpos",				"12"			},
   { "toon_12.ypos",				"5"			},
   { "toon_12.frames",				"4"			},
@@ -4513,7 +4529,7 @@ struct ConfigInfo image_config[] =
   { "toon_12.direction",			"right"			},
   { "toon_12.position",				"bottom"		},
 
-  { "toon_13",					"RocksHeroes.pcx"	},
+  { "toon_13",					"RocksHeroes.png"	},
   { "toon_13.xpos",				"8"			},
   { "toon_13.ypos",				"1"			},
   { "toon_13.frames",				"4"			},
@@ -4521,7 +4537,7 @@ struct ConfigInfo image_config[] =
   { "toon_13.direction",			"left"			},
   { "toon_13.position",				"bottom"		},
 
-  { "toon_14",					"RocksHeroes.pcx"	},
+  { "toon_14",					"RocksHeroes.png"	},
   { "toon_14.xpos",				"12"			},
   { "toon_14.ypos",				"1"			},
   { "toon_14.frames",				"4"			},
@@ -4529,7 +4545,7 @@ struct ConfigInfo image_config[] =
   { "toon_14.direction",			"right"			},
   { "toon_14.position",				"bottom"		},
 
-  { "toon_15",					"RocksHeroes.pcx"	},
+  { "toon_15",					"RocksHeroes.png"	},
   { "toon_15.xpos",				"8"			},
   { "toon_15.ypos",				"3"			},
   { "toon_15.frames",				"4"			},
@@ -4537,7 +4553,7 @@ struct ConfigInfo image_config[] =
   { "toon_15.direction",			"left"			},
   { "toon_15.position",				"bottom"		},
 
-  { "toon_16",					"RocksHeroes.pcx"	},
+  { "toon_16",					"RocksHeroes.png"	},
   { "toon_16.xpos",				"12"			},
   { "toon_16.ypos",				"3"			},
   { "toon_16.frames",				"4"			},
@@ -4545,7 +4561,7 @@ struct ConfigInfo image_config[] =
   { "toon_16.direction",			"right"			},
   { "toon_16.position",				"bottom"		},
 
-  { "toon_17",					"RocksHeroes.pcx"	},
+  { "toon_17",					"RocksHeroes.png"	},
   { "toon_17.xpos",				"8"			},
   { "toon_17.ypos",				"9"			},
   { "toon_17.frames",				"8"			},
@@ -4553,7 +4569,7 @@ struct ConfigInfo image_config[] =
   { "toon_17.direction",			"left"			},
   { "toon_17.position",				"any"			},
 
-  { "toon_18",					"RocksHeroes.pcx"	},
+  { "toon_18",					"RocksHeroes.png"	},
   { "toon_18.xpos",				"8"			},
   { "toon_18.ypos",				"9"			},
   { "toon_18.frames",				"8"			},
@@ -4561,7 +4577,7 @@ struct ConfigInfo image_config[] =
   { "toon_18.direction",			"right"			},
   { "toon_18.position",				"any"			},
 
-  { "toon_19",					"RocksElements.pcx"	},
+  { "toon_19",					"RocksElements.png"	},
   { "toon_19.xpos",				"8"			},
   { "toon_19.ypos",				"0"			},
   { "toon_19.frames",				"2"			},
@@ -4569,7 +4585,7 @@ struct ConfigInfo image_config[] =
   { "toon_19.direction",			"down"			},
   { "toon_19.position",				"any"			},
 
-  { "toon_20",					"RocksElements.pcx"	},
+  { "toon_20",					"RocksElements.png"	},
   { "toon_20.xpos",				"10"			},
   { "toon_20.ypos",				"0"			},
   { "toon_20.frames",				"2"			},
@@ -4577,57 +4593,80 @@ struct ConfigInfo image_config[] =
   { "toon_20.direction",			"down"			},
   { "toon_20.position",				"any"			},
 
-  { "menu.calibrate_red",			"RocksElements.pcx"	},
+  { "gfx.global.anim_1",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_2",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_3",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_4",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_5",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_6",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_7",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_8",			UNDEFINED_FILENAME	},
+
+  { "global.anim_1",				UNDEFINED_FILENAME	},
+  { "global.anim_2",				UNDEFINED_FILENAME	},
+  { "global.anim_3",				UNDEFINED_FILENAME	},
+  { "global.anim_4",				UNDEFINED_FILENAME	},
+  { "global.anim_5",				UNDEFINED_FILENAME	},
+  { "global.anim_6",				UNDEFINED_FILENAME	},
+  { "global.anim_7",				UNDEFINED_FILENAME	},
+  { "global.anim_8",				UNDEFINED_FILENAME	},
+
+  { "internal.global.toon_default",		UNDEFINED_FILENAME	},
+  { "internal.global.toon_default.anim_mode",	"random"		},
+
+  { "internal.global.anim_default",		UNDEFINED_FILENAME	},
+
+  { "menu.calibrate_red",			"RocksElements.png"	},
   { "menu.calibrate_red.xpos",			"12"			},
   { "menu.calibrate_red.ypos",			"8"			},
   { "menu.calibrate_red.frames",		"1"			},
-  { "menu.calibrate_blue",			"RocksElements.pcx"	},
+  { "menu.calibrate_blue",			"RocksElements.png"	},
   { "menu.calibrate_blue.xpos",			"13"			},
   { "menu.calibrate_blue.ypos",			"8"			},
   { "menu.calibrate_blue.frames",		"1"			},
-  { "menu.calibrate_yellow",			"RocksElements.pcx"	},
+  { "menu.calibrate_yellow",			"RocksElements.png"	},
   { "menu.calibrate_yellow.xpos",		"14"			},
   { "menu.calibrate_yellow.ypos",		"8"			},
   { "menu.calibrate_yellow.frames",		"1"			},
 
-  { "menu.button",				"RocksElements.pcx"	},
+  { "menu.button",				"RocksElements.png"	},
   { "menu.button.xpos",				"13"			},
   { "menu.button.ypos",				"8"			},
   { "menu.button.frames",			"1"			},
-  { "menu.button.active",			"RocksElements.pcx"	},
+  { "menu.button.active",			"RocksElements.png"	},
   { "menu.button.active.xpos",			"12"			},
   { "menu.button.active.ypos",			"8"			},
   { "menu.button.active.frames",		"1"			},
 
-  { "menu.button_left",				"RocksDC.pcx"		},
+  { "menu.button_left",				"RocksDC.png"		},
   { "menu.button_left.xpos",			"8"			},
   { "menu.button_left.ypos",			"8"			},
   { "menu.button_left.frames",			"1"			},
-  { "menu.button_left.active",			"RocksDC.pcx"		},
+  { "menu.button_left.active",			"RocksDC.png"		},
   { "menu.button_left.active.xpos",		"8"			},
   { "menu.button_left.active.ypos",		"9"			},
   { "menu.button_left.active.frames",		"1"			},
-  { "menu.button_right",			"RocksDC.pcx"		},
+  { "menu.button_right",			"RocksDC.png"		},
   { "menu.button_right.xpos",			"9"			},
   { "menu.button_right.ypos",			"8"			},
   { "menu.button_right.frames",			"1"			},
-  { "menu.button_right.active",			"RocksDC.pcx"		},
+  { "menu.button_right.active",			"RocksDC.png"		},
   { "menu.button_right.active.xpos",		"9"			},
   { "menu.button_right.active.ypos",		"9"			},
   { "menu.button_right.active.frames",		"1"			},
-  { "menu.button_up",				"RocksDC.pcx"		},
+  { "menu.button_up",				"RocksDC.png"		},
   { "menu.button_up.xpos",			"10"			},
   { "menu.button_up.ypos",			"8"			},
   { "menu.button_up.frames",			"1"			},
-  { "menu.button_up.active",			"RocksDC.pcx"		},
+  { "menu.button_up.active",			"RocksDC.png"		},
   { "menu.button_up.active.xpos",		"10"			},
   { "menu.button_up.active.ypos",		"9"			},
   { "menu.button_up.active.frames",		"1"			},
-  { "menu.button_down",				"RocksDC.pcx"		},
+  { "menu.button_down",				"RocksDC.png"		},
   { "menu.button_down.xpos",			"11"			},
   { "menu.button_down.ypos",			"8"			},
   { "menu.button_down.frames",			"1"			},
-  { "menu.button_down.active",			"RocksDC.pcx"		},
+  { "menu.button_down.active",			"RocksDC.png"		},
   { "menu.button_down.active.xpos",		"11"			},
   { "menu.button_down.active.ypos",		"9"			},
   { "menu.button_down.active.frames",		"1"			},
@@ -4683,42 +4722,277 @@ struct ConfigInfo image_config[] =
   { "menu.button_quit.active",			UNDEFINED_FILENAME	},
   { "menu.button_quit.active.clone_from",	"menu.button.active"	},
 
-  { "menu.scrollbar",				"RocksDC.pcx"		},
+  { "menu.scrollbar",				"RocksDC.png"		},
   { "menu.scrollbar.xpos",			"8"			},
   { "menu.scrollbar.ypos",			"10"			},
   { "menu.scrollbar.frames",			"1"			},
-  { "menu.scrollbar.active",			"RocksDC.pcx"		},
+  { "menu.scrollbar.active",			"RocksDC.png"		},
   { "menu.scrollbar.active.xpos",		"9"			},
   { "menu.scrollbar.active.ypos",		"10"			},
   { "menu.scrollbar.active.frames",		"1"			},
 
-  { "font.initial_1",				"RocksFontSmall.pcx"	},
+  { "gfx.game.button.stop",			"RocksDoor.png"		},
+  { "gfx.game.button.stop.x",			"305"			},
+  { "gfx.game.button.stop.y",			"185"			},
+  { "gfx.game.button.stop.width",		"30"			},
+  { "gfx.game.button.stop.height",		"30"			},
+  { "gfx.game.button.stop.pressed_xoffset",	"-100"			},
+  { "gfx.game.button.pause",			"RocksDoor.png"		},
+  { "gfx.game.button.pause.x",			"335"			},
+  { "gfx.game.button.pause.y",			"185"			},
+  { "gfx.game.button.pause.width",		"30"			},
+  { "gfx.game.button.pause.height",		"30"			},
+  { "gfx.game.button.pause.pressed_xoffset",	"-100"			},
+  { "gfx.game.button.play",			"RocksDoor.png"		},
+  { "gfx.game.button.play.x",			"365"			},
+  { "gfx.game.button.play.y",			"185"			},
+  { "gfx.game.button.play.width",		"30"			},
+  { "gfx.game.button.play.height",		"30"			},
+  { "gfx.game.button.play.pressed_xoffset",	"-100"			},
+
+  { "gfx.game.button.undo",			"RocksDoor2.png"	},
+  { "gfx.game.button.undo.x",			"105"			},
+  { "gfx.game.button.undo.y",			"20"			},
+  { "gfx.game.button.undo.width",		"30"			},
+  { "gfx.game.button.undo.height",		"30"			},
+  { "gfx.game.button.undo.pressed_xoffset",	"-100"			},
+  { "gfx.game.button.redo",			"RocksDoor2.png"	},
+  { "gfx.game.button.redo.x",			"165"			},
+  { "gfx.game.button.redo.y",			"20"			},
+  { "gfx.game.button.redo.width",		"30"			},
+  { "gfx.game.button.redo.height",		"30"			},
+  { "gfx.game.button.redo.pressed_xoffset",	"-100"			},
+
+  { "gfx.game.button.save",			"RocksDoor2.png"	},
+  { "gfx.game.button.save.x",			"105"			},
+  { "gfx.game.button.save.y",			"50"			},
+  { "gfx.game.button.save.width",		"30"			},
+  { "gfx.game.button.save.height",		"30"			},
+  { "gfx.game.button.save.pressed_xoffset",	"-100"			},
+  { "gfx.game.button.pause2",			"RocksDoor2.png"	},
+  { "gfx.game.button.pause2.x",			"135"			},
+  { "gfx.game.button.pause2.y",			"50"			},
+  { "gfx.game.button.pause2.width",		"30"			},
+  { "gfx.game.button.pause2.height",		"30"			},
+  { "gfx.game.button.pause2.pressed_xoffset",	"-100"			},
+  { "gfx.game.button.pause2.active_yoffset",	"-30"			},
+  { "gfx.game.button.load",			"RocksDoor2.png"	},
+  { "gfx.game.button.load.x",			"165"			},
+  { "gfx.game.button.load.y",			"50"			},
+  { "gfx.game.button.load.width",		"30"			},
+  { "gfx.game.button.load.height",		"30"			},
+  { "gfx.game.button.load.pressed_xoffset",	"-100"			},
+
+  { "gfx.game.button.sound_music",		"RocksDoor.png"		},
+  { "gfx.game.button.sound_music.x",		"305"			},
+  { "gfx.game.button.sound_music.y",		"245"			},
+  { "gfx.game.button.sound_music.width",	"30"			},
+  { "gfx.game.button.sound_music.height",	"30"			},
+  { "gfx.game.button.sound_music.pressed_xoffset", "-100"		},
+  { "gfx.game.button.sound_music.active_yoffset", "-30"			},
+  { "gfx.game.button.sound_loops",		"RocksDoor.png"		},
+  { "gfx.game.button.sound_loops.x",		"335"			},
+  { "gfx.game.button.sound_loops.y",		"245"			},
+  { "gfx.game.button.sound_loops.width",	"30"			},
+  { "gfx.game.button.sound_loops.height",	"30"			},
+  { "gfx.game.button.sound_loops.pressed_xoffset", "-100"		},
+  { "gfx.game.button.sound_loops.active_yoffset", "-30"			},
+  { "gfx.game.button.sound_simple",		"RocksDoor.png"		},
+  { "gfx.game.button.sound_simple.x",		"365"			},
+  { "gfx.game.button.sound_simple.y",		"245"			},
+  { "gfx.game.button.sound_simple.width",	"30"			},
+  { "gfx.game.button.sound_simple.height",	"30"			},
+  { "gfx.game.button.sound_simple.pressed_xoffset", "-100"		},
+  { "gfx.game.button.sound_simple.active_yoffset", "-30"		},
+
+  { "gfx.tape.button.eject",			"RocksDoor.png"		},
+  { "gfx.tape.button.eject.x",			"305"			},
+  { "gfx.tape.button.eject.y",			"357"			},
+  { "gfx.tape.button.eject.width",		"18"			},
+  { "gfx.tape.button.eject.height",		"18"			},
+  { "gfx.tape.button.eject.pressed_xoffset",	"-100"			},
+  { "gfx.tape.button.extra",			"RocksDoor.png"		},
+  { "gfx.tape.button.extra.x",			"505"			},
+  { "gfx.tape.button.extra.y",			"357"			},
+  { "gfx.tape.button.extra.width",		"18"			},
+  { "gfx.tape.button.extra.height",		"18"			},
+  { "gfx.tape.button.extra.pressed_xoffset",	"-100"			},
+  { "gfx.tape.button.stop",			"RocksDoor.png"		},
+  { "gfx.tape.button.stop.x",			"323"			},
+  { "gfx.tape.button.stop.y",			"357"			},
+  { "gfx.tape.button.stop.width",		"18"			},
+  { "gfx.tape.button.stop.height",		"18"			},
+  { "gfx.tape.button.stop.pressed_xoffset",	"-100"			},
+  { "gfx.tape.button.pause",			"RocksDoor.png"		},
+  { "gfx.tape.button.pause.x",			"341"			},
+  { "gfx.tape.button.pause.y",			"357"			},
+  { "gfx.tape.button.pause.width",		"18"			},
+  { "gfx.tape.button.pause.height",		"18"			},
+  { "gfx.tape.button.pause.pressed_xoffset",	"-100"			},
+  { "gfx.tape.button.record",			"RocksDoor.png"		},
+  { "gfx.tape.button.record.x",			"359"			},
+  { "gfx.tape.button.record.y",			"357"			},
+  { "gfx.tape.button.record.width",		"18"			},
+  { "gfx.tape.button.record.height",		"18"			},
+  { "gfx.tape.button.record.pressed_xoffset",	"-100"			},
+  { "gfx.tape.button.play",			"RocksDoor.png"		},
+  { "gfx.tape.button.play.x",			"377"			},
+  { "gfx.tape.button.play.y",			"357"			},
+  { "gfx.tape.button.play.width",		"18"			},
+  { "gfx.tape.button.play.height",		"18"			},
+  { "gfx.tape.button.play.pressed_xoffset",	"-100"			},
+
+  { "gfx.tape.symbol.eject",			UNDEFINED_FILENAME	},
+  { "gfx.tape.symbol.stop",			UNDEFINED_FILENAME	},
+  { "gfx.tape.symbol.pause",			"RocksDoor.png"		},
+  { "gfx.tape.symbol.pause.x",			"340"			},
+  { "gfx.tape.symbol.pause.y",			"321"			},
+  { "gfx.tape.symbol.pause.width",		"17"			},
+  { "gfx.tape.symbol.pause.height",		"13"			},
+  { "gfx.tape.symbol.record",			"RocksDoor.png"		},
+  { "gfx.tape.symbol.record.x",			"325"			},
+  { "gfx.tape.symbol.record.y",			"321"			},
+  { "gfx.tape.symbol.record.width",		"16"			},
+  { "gfx.tape.symbol.record.height",		"16"			},
+  { "gfx.tape.symbol.play",			"RocksDoor.png"		},
+  { "gfx.tape.symbol.play.x",			"357"			},
+  { "gfx.tape.symbol.play.y",			"321"			},
+  { "gfx.tape.symbol.play.width",		"11"			},
+  { "gfx.tape.symbol.play.height",		"13"			},
+  { "gfx.tape.symbol.fast_forward",		"RocksDoor.png"		},
+  { "gfx.tape.symbol.fast_forward.x",		"539"			},
+  { "gfx.tape.symbol.fast_forward.y",		"193"			},
+  { "gfx.tape.symbol.fast_forward.width",	"27"			},
+  { "gfx.tape.symbol.fast_forward.height",	"13"			},
+  { "gfx.tape.symbol.warp_forward",		"RocksDoor.png"		},
+  { "gfx.tape.symbol.warp_forward.x",		"539"			},
+  { "gfx.tape.symbol.warp_forward.y",		"152"			},
+  { "gfx.tape.symbol.warp_forward.width",	"27"			},
+  { "gfx.tape.symbol.warp_forward.height",	"13"			},
+  { "gfx.tape.symbol.warp_forward_blind",	"RocksDoor.png"		},
+  { "gfx.tape.symbol.warp_forward_blind.x",	"539"			},
+  { "gfx.tape.symbol.warp_forward_blind.y",	"165"			},
+  { "gfx.tape.symbol.warp_forward_blind.width",	"27"			},
+  { "gfx.tape.symbol.warp_forward_blind.height","13"			},
+  { "gfx.tape.symbol.pause_before_end",		"RocksDoor.png"		},
+  { "gfx.tape.symbol.pause_before_end.x",	"539"			},
+  { "gfx.tape.symbol.pause_before_end.y",	"221"			},
+  { "gfx.tape.symbol.pause_before_end.width",	"27"			},
+  { "gfx.tape.symbol.pause_before_end.height",	"13"			},
+  { "gfx.tape.symbol.single_step",		UNDEFINED_FILENAME	},
+
+  { "gfx.tape.label.eject",			UNDEFINED_FILENAME	},
+  { "gfx.tape.label.stop",			UNDEFINED_FILENAME	},
+  { "gfx.tape.label.pause",			"RocksDoor.png"		},
+  { "gfx.tape.label.pause.x",			"305"			},
+  { "gfx.tape.label.pause.y",			"341"			},
+  { "gfx.tape.label.pause.width",		"35"			},
+  { "gfx.tape.label.pause.height",		"8"			},
+  { "gfx.tape.label.record",			"RocksDoor.png"		},
+  { "gfx.tape.label.record.x",			"305"			},
+  { "gfx.tape.label.record.y",			"321"			},
+  { "gfx.tape.label.record.width",		"20"			},
+  { "gfx.tape.label.record.height",		"12"			},
+  { "gfx.tape.label.play",			"RocksDoor.png"		},
+  { "gfx.tape.label.play.x",			"370"			},
+  { "gfx.tape.label.play.y",			"321"			},
+  { "gfx.tape.label.play.width",		"22"			},
+  { "gfx.tape.label.play.height",		"12"			},
+  { "gfx.tape.label.fast_forward",		"RocksDoor.png"		},
+  { "gfx.tape.label.fast_forward.x",		"505"			},
+  { "gfx.tape.label.fast_forward.y",		"193"			},
+  { "gfx.tape.label.fast_forward.width",	"40"			},
+  { "gfx.tape.label.fast_forward.height",	"28"			},
+  { "gfx.tape.label.warp_forward",		"RocksDoor.png"		},
+  { "gfx.tape.label.warp_forward.x",		"505"			},
+  { "gfx.tape.label.warp_forward.y",		"165"			},
+  { "gfx.tape.label.warp_forward.width",	"40"			},
+  { "gfx.tape.label.warp_forward.height",	"28"			},
+  { "gfx.tape.label.warp_forward_blind",	"RocksDoor.png"		},
+  { "gfx.tape.label.warp_forward_blind.x",	"505"			},
+  { "gfx.tape.label.warp_forward_blind.y",	"165"			},
+  { "gfx.tape.label.warp_forward_blind.width",	"40"			},
+  { "gfx.tape.label.warp_forward_blind.height",	"28"			},
+  { "gfx.tape.label.pause_before_end",		"RocksDoor.png"		},
+  { "gfx.tape.label.pause_before_end.x",	"505"			},
+  { "gfx.tape.label.pause_before_end.y",	"221"			},
+  { "gfx.tape.label.pause_before_end.width",	"40"			},
+  { "gfx.tape.label.pause_before_end.height",	"28"			},
+  { "gfx.tape.label.single_step",		"RocksDoor.png"		},
+  { "gfx.tape.label.single_step.x",		"557"			},
+  { "gfx.tape.label.single_step.y",		"139"			},
+  { "gfx.tape.label.single_step.width",		"38"			},
+  { "gfx.tape.label.single_step.height",	"13"			},
+
+  { "gfx.tape.label.date",			"RocksDoor.png"		},
+  { "gfx.tape.label.date.x",			"305"			},
+  { "gfx.tape.label.date.y",			"285"			},
+  { "gfx.tape.label.date.width",		"90"			},
+  { "gfx.tape.label.date.height",		"31"			},
+  { "gfx.tape.label.time",			"RocksDoor.png"		},
+  { "gfx.tape.label.time.x",			"346"			},
+  { "gfx.tape.label.time.y",			"335"			},
+  { "gfx.tape.label.time.width",		"45"			},
+  { "gfx.tape.label.time.height",		"13"			},
+
+  { "gfx.request.button.yes",			"RocksDoor.png"		},
+  { "gfx.request.button.yes.x",			"302"			},
+  { "gfx.request.button.yes.y",			"0"			},
+  { "gfx.request.button.yes.width",		"46"			},
+  { "gfx.request.button.yes.height",		"28"			},
+  { "gfx.request.button.yes.pressed_xoffset",	"-100"			},
+  { "gfx.request.button.no",			"RocksDoor.png"		},
+  { "gfx.request.button.no.x",			"352"			},
+  { "gfx.request.button.no.y",			"0"			},
+  { "gfx.request.button.no.width",		"46"			},
+  { "gfx.request.button.no.height",		"28"			},
+  { "gfx.request.button.no.pressed_xoffset",	"-100"			},
+  { "gfx.request.button.confirm",		"RocksDoor.png"		},
+  { "gfx.request.button.confirm.x",		"302"			},
+  { "gfx.request.button.confirm.y",		"30"			},
+  { "gfx.request.button.confirm.width",		"96"			},
+  { "gfx.request.button.confirm.height",	"28"			},
+  { "gfx.request.button.confirm.pressed_xoffset", "-100"		},
+  { "gfx.request.button.player_1",		"RocksDoor.png"		},
+  { "gfx.request.button.player_1.x",		"305"			},
+  { "gfx.request.button.player_1.y",		"185"			},
+  { "gfx.request.button.player_1.width",	"30"			},
+  { "gfx.request.button.player_1.height",	"30"			},
+  { "gfx.request.button.player_1.pressed_xoffset", "-100"		},
+  { "gfx.request.button.player_2",		UNDEFINED_FILENAME	},
+  { "gfx.request.button.player_2.clone_from",	"gfx.request.button.player_1" },
+  { "gfx.request.button.player_3",		UNDEFINED_FILENAME	},
+  { "gfx.request.button.player_3.clone_from",	"gfx.request.button.player_1" },
+  { "gfx.request.button.player_4",		UNDEFINED_FILENAME	},
+  { "gfx.request.button.player_4.clone_from",	"gfx.request.button.player_1" },
+
+  { "font.initial_1",				"RocksFontSmall.png"	},
   { "font.initial_1.x",				"0"			},
   { "font.initial_1.y",				"0"			},
   { "font.initial_1.width",			"14"			},
   { "font.initial_1.height",			"14"			},
-  { "font.initial_2",				"RocksFontSmall.pcx"	},
+  { "font.initial_2",				"RocksFontSmall.png"	},
   { "font.initial_2.x",				"0"			},
   { "font.initial_2.y",				"70"			},
   { "font.initial_2.width",			"14"			},
   { "font.initial_2.height",			"14"			},
-  { "font.initial_3",				"RocksFontSmall.pcx"	},
+  { "font.initial_3",				"RocksFontSmall.png"	},
   { "font.initial_3.x",				"0"			},
   { "font.initial_3.y",				"140"			},
   { "font.initial_3.width",			"14"			},
   { "font.initial_3.height",			"14"			},
-  { "font.initial_4",				"RocksFontSmall.pcx"	},
+  { "font.initial_4",				"RocksFontSmall.png"	},
   { "font.initial_4.x",				"0"			},
   { "font.initial_4.y",				"210"			},
   { "font.initial_4.width",			"14"			},
   { "font.initial_4.height",			"14"			},
 
-  { "font.title_1",				"RocksFontBig.pcx"	},
+  { "font.title_1",				"RocksFontBig.png"	},
   { "font.title_1.x",				"0"			},
   { "font.title_1.y",				"480"			},
   { "font.title_1.width",			"32"			},
   { "font.title_1.height",			"32"			},
-  { "font.title_2",				"RocksFontSmall.pcx"	},
+  { "font.title_2",				"RocksFontSmall.png"	},
   { "font.title_2.x",				"0"			},
   { "font.title_2.y",				"0"			},
   { "font.title_2.width",			"14"			},
@@ -4726,52 +5000,54 @@ struct ConfigInfo image_config[] =
   { "font.title_2.SETUP",			UNDEFINED_FILENAME	},
   { "font.title_2.SETUP.clone_from",		"font.text_4"		},
 
-  { "font.menu_1",				"RocksFontBig.pcx"	},
+  { "font.menu_1",				"RocksFontBig.png"	},
   { "font.menu_1.x",				"0"			},
   { "font.menu_1.y",				"320"			},
   { "font.menu_1.width",			"32"			},
   { "font.menu_1.height",			"32"			},
-  { "font.menu_1.active",			"RocksFontBig.pcx"	},
+  { "font.menu_1.active",			"RocksFontBig.png"	},
   { "font.menu_1.active.x",			"0"			},
   { "font.menu_1.active.y",			"480"			},
   { "font.menu_1.active.width",			"32"			},
   { "font.menu_1.active.height",		"32"			},
-  { "font.menu_2",				"RocksFontMedium.pcx"	},
+  { "font.menu_2",				"RocksFontMedium.png"	},
   { "font.menu_2.x",				"0"			},
   { "font.menu_2.y",				"320"			},
   { "font.menu_2.width",			"16"			},
   { "font.menu_2.height",			"32"			},
-  { "font.menu_2.active",			"RocksFontMedium.pcx"	},
+  { "font.menu_2.active",			"RocksFontMedium.png"	},
   { "font.menu_2.active.x",			"0"			},
   { "font.menu_2.active.y",			"480"			},
   { "font.menu_2.active.width",			"16"			},
   { "font.menu_2.active.height",		"32"			},
 
-  { "font.text_1",				"RocksFontSmall.pcx"	},
+  { "font.text_1",				"RocksFontSmall.png"	},
   { "font.text_1.x",				"0"			},
   { "font.text_1.y",				"140"			},
   { "font.text_1.width",			"14"			},
   { "font.text_1.height",			"14"			},
   { "font.text_1.MAIN",				UNDEFINED_FILENAME	},
   { "font.text_1.MAIN.clone_from",		"font.text_1.PREVIEW"	},
-  { "font.text_1.LEVELS",			"RocksFontMedium.pcx"	},
+  { "font.text_1.LEVELS",			"RocksFontMedium.png"	},
   { "font.text_1.LEVELS.x",			"0"			},
   { "font.text_1.LEVELS.y",			"0"			},
   { "font.text_1.LEVELS.width",			"16"			},
   { "font.text_1.LEVELS.height",		"32"			},
+  { "font.text_1.LEVELNR",			UNDEFINED_FILENAME	},
+  { "font.text_1.LEVELNR.clone_from",		"font.text_1.LEVELS"	},
   { "font.text_1.SETUP",			UNDEFINED_FILENAME	},
   { "font.text_1.SETUP.clone_from",		"font.text_1.LEVELS"	},
-  { "font.text_1.PREVIEW",			"RocksFontEM.pcx"	},
+  { "font.text_1.PREVIEW",			"RocksFontEM.png"	},
   { "font.text_1.PREVIEW.x",			"0"			},
   { "font.text_1.PREVIEW.y",			"160"			},
   { "font.text_1.PREVIEW.width",		"16"			},
   { "font.text_1.PREVIEW.height",		"16"			},
-  { "font.text_1.SCORES",			"RocksFontMedium.pcx"	},
+  { "font.text_1.SCORES",			"RocksFontMedium.png"	},
   { "font.text_1.SCORES.x",			"0"			},
   { "font.text_1.SCORES.y",			"480"			},
   { "font.text_1.SCORES.width",			"16"			},
   { "font.text_1.SCORES.height",		"32"			},
-  { "font.text_1.active.SCORES",		"RocksFontMedium.pcx"	},
+  { "font.text_1.active.SCORES",		"RocksFontMedium.png"	},
   { "font.text_1.active.SCORES.x",		"0"			},
   { "font.text_1.active.SCORES.y",		"0"			},
   { "font.text_1.active.SCORES.width",		"16"			},
@@ -4780,172 +5056,190 @@ struct ConfigInfo image_config[] =
   { "font.text_1.PANEL.clone_from",		"font.level_number"	},
   { "font.text_1.DOOR",				UNDEFINED_FILENAME	},
   { "font.text_1.DOOR.clone_from",		"font.level_number"	},
-  { "font.text_2",				"RocksFontSmall.pcx"	},
+  { "font.text_2",				"RocksFontSmall.png"	},
   { "font.text_2.x",				"0"			},
   { "font.text_2.y",				"210"			},
   { "font.text_2.width",			"14"			},
   { "font.text_2.height",			"14"			},
   { "font.text_2.MAIN",				UNDEFINED_FILENAME	},
   { "font.text_2.MAIN.clone_from",		"font.text_2.PREVIEW"	},
-  { "font.text_2.LEVELS",			"RocksFontMedium.pcx"	},
+  { "font.text_2.LEVELS",			"RocksFontMedium.png"	},
   { "font.text_2.LEVELS.x",			"0"			},
   { "font.text_2.LEVELS.y",			"160"			},
   { "font.text_2.LEVELS.width",			"16"			},
   { "font.text_2.LEVELS.height",		"32"			},
+  { "font.text_2.LEVELNR",			UNDEFINED_FILENAME	},
+  { "font.text_2.LEVELNR.clone_from",		"font.text_2.LEVELS"	},
   { "font.text_2.SETUP",			UNDEFINED_FILENAME	},
   { "font.text_2.SETUP.clone_from",		"font.text_2.LEVELS"	},
-  { "font.text_2.PREVIEW",			"RocksFontEM.pcx"	},
+  { "font.text_2.PREVIEW",			"RocksFontEM.png"	},
   { "font.text_2.PREVIEW.x",			"0"			},
   { "font.text_2.PREVIEW.y",			"160"			},
   { "font.text_2.PREVIEW.width",		"16"			},
   { "font.text_2.PREVIEW.height",		"16"			},
-  { "font.text_2.SCORES",			"RocksFontBig.pcx"	},
+  { "font.text_2.SCORES",			"RocksFontBig.png"	},
   { "font.text_2.SCORES.x",			"0"			},
   { "font.text_2.SCORES.y",			"320"			},
   { "font.text_2.SCORES.width",			"32"			},
   { "font.text_2.SCORES.height",		"32"			},
-  { "font.text_2.active.SCORES",		"RocksFontBig.pcx"	},
+  { "font.text_2.active.SCORES",		"RocksFontBig.png"	},
   { "font.text_2.active.SCORES.x",		"0"			},
   { "font.text_2.active.SCORES.y",		"0"			},
   { "font.text_2.active.SCORES.width",		"32"			},
   { "font.text_2.active.SCORES.height",		"32"			},
-  { "font.text_3",				"RocksFontSmall.pcx"	},
+  { "font.text_3",				"RocksFontSmall.png"	},
   { "font.text_3.x",				"0"			},
   { "font.text_3.y",				"0"			},
   { "font.text_3.width",			"14"			},
   { "font.text_3.height",			"14"			},
-  { "font.text_3.LEVELS",			"RocksFontMedium.pcx"	},
+  { "font.text_3.LEVELS",			"RocksFontMedium.png"	},
   { "font.text_3.LEVELS.x",			"0"			},
   { "font.text_3.LEVELS.y",			"320"			},
   { "font.text_3.LEVELS.width",			"16"			},
   { "font.text_3.LEVELS.height",		"32"			},
+  { "font.text_3.LEVELNR",			UNDEFINED_FILENAME	},
+  { "font.text_3.LEVELNR.clone_from",		"font.text_3.LEVELS"	},
   { "font.text_3.SETUP",			UNDEFINED_FILENAME	},
   { "font.text_3.SETUP.clone_from",		"font.text_3.LEVELS"	},
-  { "font.text_3.PREVIEW",			"RocksFontEM.pcx"	},
+  { "font.text_3.PREVIEW",			"RocksFontEM.png"	},
   { "font.text_3.PREVIEW.x",			"0"			},
   { "font.text_3.PREVIEW.y",			"160"			},
   { "font.text_3.PREVIEW.width",		"16"			},
   { "font.text_3.PREVIEW.height",		"16"			},
-  { "font.text_3.SCORES",			"RocksFontMedium.pcx"	},
+  { "font.text_3.SCORES",			"RocksFontMedium.png"	},
   { "font.text_3.SCORES.x",			"0"			},
   { "font.text_3.SCORES.y",			"480"			},
   { "font.text_3.SCORES.width",			"16"			},
   { "font.text_3.SCORES.height",		"32"			},
-  { "font.text_3.active.SCORES",		"RocksFontMedium.pcx"	},
+  { "font.text_3.active.SCORES",		"RocksFontMedium.png"	},
   { "font.text_3.active.SCORES.x",		"0"			},
   { "font.text_3.active.SCORES.y",		"0"			},
   { "font.text_3.active.SCORES.width",		"16"			},
   { "font.text_3.active.SCORES.height",		"32"			},
-  { "font.text_4",				"RocksFontSmall.pcx"	},
+  { "font.text_4",				"RocksFontSmall.png"	},
   { "font.text_4.x",				"0"			},
   { "font.text_4.y",				"70"			},
   { "font.text_4.width",			"14"			},
   { "font.text_4.height",			"14"			},
   { "font.text_4.MAIN",				UNDEFINED_FILENAME	},
   { "font.text_4.MAIN.clone_from",		"font.text_3.PREVIEW"	},
-  { "font.text_4.LEVELS",			"RocksFontMedium.pcx"	},
+  { "font.text_4.LEVELS",			"RocksFontMedium.png"	},
   { "font.text_4.LEVELS.x",			"0"			},
   { "font.text_4.LEVELS.y",			"480"			},
   { "font.text_4.LEVELS.width",			"16"			},
   { "font.text_4.LEVELS.height",		"32"			},
+  { "font.text_4.LEVELNR",			UNDEFINED_FILENAME	},
+  { "font.text_4.LEVELNR.clone_from",		"font.text_4.LEVELS"	},
   { "font.text_4.SETUP",			UNDEFINED_FILENAME	},
   { "font.text_4.SETUP.clone_from",		"font.text_4.LEVELS"	},
-  { "font.text_4.SCORES",			"RocksFontMedium.pcx"	},
+  { "font.text_4.SCORES",			"RocksFontMedium.png"	},
   { "font.text_4.SCORES.x",			"0"			},
   { "font.text_4.SCORES.y",			"480"			},
   { "font.text_4.SCORES.width",			"16"			},
   { "font.text_4.SCORES.height",		"32"			},
-  { "font.text_4.active.SCORES",		"RocksFontMedium.pcx"	},
+  { "font.text_4.active.SCORES",		"RocksFontMedium.png"	},
   { "font.text_4.active.SCORES.x",		"0"			},
   { "font.text_4.active.SCORES.y",		"0"			},
   { "font.text_4.active.SCORES.width",		"16"			},
   { "font.text_4.active.SCORES.height",		"32"			},
 
-  { "font.envelope_1",				"RocksFontEM.pcx"	},
+  { "font.envelope_1",				"RocksFontEM.png"	},
   { "font.envelope_1.x",			"0"			},
   { "font.envelope_1.y",			"160"			},
   { "font.envelope_1.width",			"16"			},
   { "font.envelope_1.height",			"16"			},
-  { "font.envelope_2",				"RocksFontEM.pcx"	},
+  { "font.envelope_2",				"RocksFontEM.png"	},
   { "font.envelope_2.x",			"0"			},
   { "font.envelope_2.y",			"160"			},
   { "font.envelope_2.width",			"16"			},
   { "font.envelope_2.height",			"16"			},
-  { "font.envelope_3",				"RocksFontEM.pcx"	},
+  { "font.envelope_3",				"RocksFontEM.png"	},
   { "font.envelope_3.x",			"0"			},
   { "font.envelope_3.y",			"160"			},
   { "font.envelope_3.width",			"16"			},
   { "font.envelope_3.height",			"16"			},
-  { "font.envelope_4",				"RocksFontEM.pcx"	},
+  { "font.envelope_4",				"RocksFontEM.png"	},
   { "font.envelope_4.x",			"0"			},
   { "font.envelope_4.y",			"160"			},
   { "font.envelope_4.width",			"16"			},
   { "font.envelope_4.height",			"16"			},
 
-  { "font.input_1",				"RocksFontSmall.pcx"	},
+  { "font.request",				"RocksFontSmall.png"	},
+  { "font.request.x",				"0"			},
+  { "font.request.y",				"210"			},
+  { "font.request.width",			"14"			},
+  { "font.request.height",			"14"			},
+
+  { "font.input_1",				"RocksFontSmall.png"	},
   { "font.input_1.x",				"0"			},
   { "font.input_1.y",				"210"			},
   { "font.input_1.width",			"14"			},
   { "font.input_1.height",			"14"			},
-  { "font.input_1.MAIN",			"RocksFontBig.pcx"	},
+  { "font.input_1.MAIN",			"RocksFontBig.png"	},
   { "font.input_1.MAIN.x",			"0"			},
   { "font.input_1.MAIN.y",			"0"			},
   { "font.input_1.MAIN.width",			"32"			},
   { "font.input_1.MAIN.height",			"32"			},
-  { "font.input_1.active",			"RocksFontSmall.pcx"	},
+  { "font.input_1.active",			"RocksFontSmall.png"	},
   { "font.input_1.active.x",			"0"			},
   { "font.input_1.active.y",			"210"			},
   { "font.input_1.active.width",		"14"			},
   { "font.input_1.active.height",		"14"			},
-  { "font.input_1.active.MAIN",			"RocksFontBig.pcx"	},
+  { "font.input_1.active.MAIN",			"RocksFontBig.png"	},
   { "font.input_1.active.MAIN.x",		"0"			},
   { "font.input_1.active.MAIN.y",		"480"			},
   { "font.input_1.active.MAIN.width",		"32"			},
   { "font.input_1.active.MAIN.height",		"32"			},
-  { "font.input_1.active.SETUP",		"RocksFontBig.pcx"	},
+  { "font.input_1.active.SETUP",		"RocksFontBig.png"	},
   { "font.input_1.active.SETUP.x",		"0"			},
   { "font.input_1.active.SETUP.y",		"0"			},
   { "font.input_1.active.SETUP.width",		"32"			},
   { "font.input_1.active.SETUP.height",		"32"			},
-  { "font.input_2",				"RocksFontSmall.pcx"	},
+  { "font.input_2",				"RocksFontSmall.png"	},
   { "font.input_2.x",				"0"			},
   { "font.input_2.y",				"210"			},
   { "font.input_2.width",			"14"			},
   { "font.input_2.height",			"14"			},
-  { "font.input_2.active",			"RocksFontSmall.pcx"	},
+  { "font.input_2.active",			"RocksFontSmall.png"	},
   { "font.input_2.active.x",			"0"			},
   { "font.input_2.active.y",			"210"			},
   { "font.input_2.active.width",		"14"			},
   { "font.input_2.active.height",		"14"			},
 
-  { "font.option_off",				"RocksFontBig.pcx"	},
+  { "font.option_off",				"RocksFontBig.png"	},
   { "font.option_off.x",			"0"			},
   { "font.option_off.y",			"160"			},
   { "font.option_off.width",			"32"			},
   { "font.option_off.height",			"32"			},
-  { "font.option_on",				"RocksFontBig.pcx"	},
+  { "font.option_off_narrow",			UNDEFINED_FILENAME	},
+  { "font.option_off_narrow.clone_from",	"font.text_2.LEVELS"	},
+  { "font.option_on",				"RocksFontBig.png"	},
   { "font.option_on.x",				"0"			},
   { "font.option_on.y",				"480"			},
   { "font.option_on.width",			"32"			},
   { "font.option_on.height",			"32"			},
+  { "font.option_on_narrow",			UNDEFINED_FILENAME	},
+  { "font.option_on_narrow.clone_from",		"font.text_4.LEVELS"	},
 
-  { "font.value_1",				"RocksFontBig.pcx"	},
+  { "font.value_1",				"RocksFontBig.png"	},
   { "font.value_1.x",				"0"			},
   { "font.value_1.y",				"480"			},
   { "font.value_1.width",			"32"			},
   { "font.value_1.height",			"32"			},
-  { "font.value_2",				"RocksFontMedium.pcx"	},
+  { "font.value_2",				"RocksFontMedium.png"	},
   { "font.value_2.x",				"0"			},
   { "font.value_2.y",				"480"			},
   { "font.value_2.width",			"16"			},
   { "font.value_2.height",			"32"			},
-  { "font.value_old",				"RocksFontBig.pcx"	},
+  { "font.value_old",				"RocksFontBig.png"	},
   { "font.value_old.x",				"0"			},
   { "font.value_old.y",				"160"			},
   { "font.value_old.width",			"32"			},
   { "font.value_old.height",			"32"			},
+  { "font.value_narrow",			UNDEFINED_FILENAME	},
+  { "font.value_narrow.clone_from",		"font.text_4.LEVELS"	},
 
-  { "font.level_number",			"RocksFontSmall.pcx"	},
+  { "font.level_number",			"RocksFontSmall.png"	},
   { "font.level_number.x",			"0"			},
   { "font.level_number.y",			"350"			},
   { "font.level_number.width",			"10"			},
@@ -4953,13 +5247,13 @@ struct ConfigInfo image_config[] =
   { "font.level_number.active",			UNDEFINED_FILENAME	},
   { "font.level_number.active.clone_from",	"font.level_number"	},
 
-  { "font.tape_recorder",			"RocksFontSmall.pcx"	},
+  { "font.tape_recorder",			"RocksFontSmall.png"	},
   { "font.tape_recorder.x",			"0"			},
   { "font.tape_recorder.y",			"280"			},
   { "font.tape_recorder.width",			"11"			},
   { "font.tape_recorder.height",		"14"			},
 
-  { "font.game_info",				"RocksFontEM.pcx"	},
+  { "font.game_info",				"RocksFontEM.png"	},
   { "font.game_info.xpos",			"0"			},
   { "font.game_info.ypos",			"0"			},
   { "font.game_info.delay",			"10"			},
@@ -4970,10 +5264,470 @@ struct ConfigInfo image_config[] =
   { "font.info.levelset",			UNDEFINED_FILENAME	},
   { "font.info.levelset.clone_from",		"font.level_number"	},
 
-  { "global.border",				"RocksScreen.pcx"	},
-  { "global.door",				"RocksDoor.pcx"		},
+  { "editor.element_border",			"RocksMore.png"		},
+  { "editor.element_border.xpos",		"0"			},
+  { "editor.element_border.ypos",		"2"			},
+  { "editor.element_border.border_size",	"8"			},
+
+  { "editor.element_border_input",		"RocksMore.png"		},
+  { "editor.element_border_input.xpos",		"10"			},
+  { "editor.element_border_input.ypos",		"7"			},
+  { "editor.element_border_input.border_size",	"4"			},
+
+  { "editor.counter.down",			"RocksDoor.png"		},
+  { "editor.counter.down.x",			"302"			},
+  { "editor.counter.down.y",			"60"			},
+  { "editor.counter.down.width",		"20"			},
+  { "editor.counter.down.height",		"20"			},
+  { "editor.counter.down.pressed_xoffset",	"-100"			},
+
+  { "editor.counter.up",			"RocksDoor.png"		},
+  { "editor.counter.up.x",			"378"			},
+  { "editor.counter.up.y",			"60"			},
+  { "editor.counter.up.width",			"20"			},
+  { "editor.counter.up.height",			"20"			},
+  { "editor.counter.up.pressed_xoffset",	"-100"			},
+
+  { "editor.counter.input",			"RocksDoor.png"		},
+  { "editor.counter.input.x",			"324"			},
+  { "editor.counter.input.y",			"60"			},
+  { "editor.counter.input.width",		"52"			},
+  { "editor.counter.input.height",		"20"			},
+  { "editor.counter.input.active_xoffset",	"-100"			},
+  { "editor.counter.input.border_size",		"3"			},
+
+  { "editor.selectbox.input",			"RocksDoor.png"		},
+  { "editor.selectbox.input.x",			"324"			},
+  { "editor.selectbox.input.y",			"82"			},
+  { "editor.selectbox.input.width",		"52"			},
+  { "editor.selectbox.input.height",		"20"			},
+  { "editor.selectbox.input.active_xoffset",	"-100"			},
+  { "editor.selectbox.input.border_size",	"3"			},
+
+  { "editor.selectbox.button",			UNDEFINED_FILENAME	},
+  { "editor.selectbox.button.width",		"14"			},
+
+  { "editor.checkbox",				"RocksDoor.png"		},
+  { "editor.checkbox.x",			"302"			},
+  { "editor.checkbox.y",			"82"			},
+  { "editor.checkbox.width",			"20"			},
+  { "editor.checkbox.height",			"20"			},
+  { "editor.checkbox.pressed_xoffset",		"-100"			},
+  { "editor.checkbox.active_xoffset",		"76"			},
+
+  { "editor.radiobutton",			"RocksDoor.png"		},
+  { "editor.radiobutton.x",			"302"			},
+  { "editor.radiobutton.y",			"104"			},
+  { "editor.radiobutton.width",			"20"			},
+  { "editor.radiobutton.height",		"20"			},
+  { "editor.radiobutton.pressed_xoffset",	"-100"			},
+  { "editor.radiobutton.active_xoffset",	"76"			},
+
+  { "editor.stickybutton",			"RocksDoor.png"		},
+  { "editor.stickybutton.x",			"302"			},
+  { "editor.stickybutton.y",			"126"			},
+  { "editor.stickybutton.width",		"20"			},
+  { "editor.stickybutton.height",		"20"			},
+  { "editor.stickybutton.pressed_xoffset",	"-100"			},
+  { "editor.stickybutton.active_xoffset",	"76"			},
+
+  { "editor.tabbutton",				"RocksDoor.png"		},
+  { "editor.tabbutton.x",			"324"			},
+  { "editor.tabbutton.y",			"104"			},
+  { "editor.tabbutton.width",			"52"			},
+  { "editor.tabbutton.height",			"20"			},
+  { "editor.tabbutton.pressed_xoffset",		"-100"			},
+  { "editor.tabbutton.active_yoffset",		"22"			},
+  { "editor.tabbutton.border_size",		"3"			},
+  { "editor.tabbutton.draw_xoffset",		"2"			},
+
+  { "editor.textbutton",			"RocksDoor.png"		},
+  { "editor.textbutton.x",			"324"			},
+  { "editor.textbutton.y",			"148"			},
+  { "editor.textbutton.width",			"52"			},
+  { "editor.textbutton.height",			"20"			},
+  { "editor.textbutton.pressed_xoffset",	"-100"			},
+  { "editor.textbutton.border_size",		"3"			},
+  { "editor.textbutton.draw_xoffset",		"2"			},
+
+  { "editor.input.text",			"RocksDoor.png"		},
+  { "editor.input.text.x",			"324"			},
+  { "editor.input.text.y",			"60"			},
+  { "editor.input.text.width",			"52"			},
+  { "editor.input.text.height",			"20"			},
+  { "editor.input.text.active_xoffset",		"-100"			},
+  { "editor.input.text.border_size",		"3"			},
+
+  { "editor.input.textarea",			"RocksDoor.png"		},
+  { "editor.input.textarea.x",			"324"			},
+  { "editor.input.textarea.y",			"60"			},
+  { "editor.input.textarea.width",		"52"			},
+  { "editor.input.textarea.height",		"20"			},
+  { "editor.input.textarea.active_xoffset",	"-100"			},
+  { "editor.input.textarea.border_size",	"3"			},
+
+  { "editor.cascade_list",			"RocksMore.png"		},
+  { "editor.cascade_list.xpos",			"9"			},
+  { "editor.cascade_list.ypos",			"8"			},
+  { "editor.cascade_list.frames",		"1"			},
+  { "editor.cascade_list.active",		"RocksMore.png"		},
+  { "editor.cascade_list.active.xpos",		"10"			},
+  { "editor.cascade_list.active.ypos",		"8"			},
+  { "editor.cascade_list.active.frames",	"1"			},
 
-  { "global.busy",				"RocksBusy.pcx"		},
+  { "editor.palette.button",			"RocksDoor.png"		},
+  { "editor.palette.button.x",			"525"			},
+  { "editor.palette.button.y",			"30"			},
+  { "editor.palette.button.width",		"20"			},
+  { "editor.palette.button.height",		"20"			},
+  { "editor.palette.button.pressed_xoffset",	"-20"			},
+
+  { "editor.palette.scroll_up",			"RocksDoor.png"		},
+  { "editor.palette.scroll_up.x",		"750"			},
+  { "editor.palette.scroll_up.y",		"0"			},
+  { "editor.palette.scroll_up.width",		"10"			},
+  { "editor.palette.scroll_up.height",		"10"			},
+  { "editor.palette.scroll_up.pressed_xoffset",	"-10"			},
+
+  { "editor.palette.scroll_down",		"RocksDoor.png"		},
+  { "editor.palette.scroll_down.x",		"750"			},
+  { "editor.palette.scroll_down.y",		"10"			},
+  { "editor.palette.scroll_down.width",		"10"			},
+  { "editor.palette.scroll_down.height",	"10"			},
+  { "editor.palette.scroll_down.pressed_xoffset", "-10"			},
+
+  { "editor.palette.scrollbar",			"RocksDoor.png"		},
+  { "editor.palette.scrollbar.x",		"750"			},
+  { "editor.palette.scrollbar.y",		"20"			},
+  { "editor.palette.scrollbar.width",		"10"			},
+  { "editor.palette.scrollbar.height",		"10"			},
+  { "editor.palette.scrollbar.pressed_xoffset",	"-10"			},
+  { "editor.palette.scrollbar.border_size",	"3"			},
+
+  { "editor.playfield.scroll_up",		"RocksDoor.png"		},
+  { "editor.playfield.scroll_up.x",		"724"			},
+  { "editor.playfield.scroll_up.y",		"0"			},
+  { "editor.playfield.scroll_up.width",		"16"			},
+  { "editor.playfield.scroll_up.height",	"16"			},
+  { "editor.playfield.scroll_up.pressed_xoffset", "-16"			},
+
+  { "editor.playfield.scroll_down",		"RocksDoor.png"		},
+  { "editor.playfield.scroll_down.x",		"724"			},
+  { "editor.playfield.scroll_down.y",		"16"			},
+  { "editor.playfield.scroll_down.width",	"16"			},
+  { "editor.playfield.scroll_down.height",	"16"			},
+  { "editor.playfield.scroll_down.pressed_xoffset", "-16"		},
+
+  { "editor.playfield.scroll_left",		"RocksDoor.png"		},
+  { "editor.playfield.scroll_left.x",		"724"			},
+  { "editor.playfield.scroll_left.y",		"32"			},
+  { "editor.playfield.scroll_left.width",	"16"			},
+  { "editor.playfield.scroll_left.height",	"16"			},
+  { "editor.playfield.scroll_left.pressed_xoffset", "-16"		},
+
+  { "editor.playfield.scroll_right",		"RocksDoor.png"		},
+  { "editor.playfield.scroll_right.x",		"724"			},
+  { "editor.playfield.scroll_right.y",		"48"			},
+  { "editor.playfield.scroll_right.width",	"16"			},
+  { "editor.playfield.scroll_right.height",	"16"			},
+  { "editor.playfield.scroll_right.pressed_xoffset", "-16"		},
+
+  { "editor.playfield.scrollbar",		"RocksDoor.png"		},
+  { "editor.playfield.scrollbar.x",		"724"			},
+  { "editor.playfield.scrollbar.y",		"64"			},
+  { "editor.playfield.scrollbar.width",		"16"			},
+  { "editor.playfield.scrollbar.height",	"16"			},
+  { "editor.playfield.scrollbar.pressed_xoffset", "-16"			},
+  { "editor.playfield.scrollbar.border_size",	"3"			},
+
+  { "gfx.editor.button.prev_level",		"RocksDoor.png"		},
+  { "gfx.editor.button.prev_level.x",		"724"			},
+  { "gfx.editor.button.prev_level.y",		"32"			},
+  { "gfx.editor.button.prev_level.width",	"16"			},
+  { "gfx.editor.button.prev_level.height",	"16"			},
+  { "gfx.editor.button.prev_level.pressed_xoffset", "-16"		},
+
+  { "gfx.editor.button.next_level",		"RocksDoor.png"		},
+  { "gfx.editor.button.next_level.x",		"724"			},
+  { "gfx.editor.button.next_level.y",		"48"			},
+  { "gfx.editor.button.next_level.width",	"16"			},
+  { "gfx.editor.button.next_level.height",	"16"			},
+  { "gfx.editor.button.next_level.pressed_xoffset", "-16"		},
+
+  { "gfx.editor.button.properties",		"RocksDoor2.png"	},
+  { "gfx.editor.button.properties.x",		"105"			},
+  { "gfx.editor.button.properties.y",		"0"			},
+  { "gfx.editor.button.properties.width",	"90"			},
+  { "gfx.editor.button.properties.height",	"20"			},
+  { "gfx.editor.button.properties.pressed_xoffset", "-100"		},
+
+  { "gfx.editor.button.element_left",		"RocksDoor2.png"	},
+  { "gfx.editor.button.element_left.x",		"368"			},
+  { "gfx.editor.button.element_left.y",		"48"			},
+  { "gfx.editor.button.element_left.width",	"16"			},
+  { "gfx.editor.button.element_left.height",	"16"			},
+  { "gfx.editor.button.element_left.pressed_xoffset", "0"		},
+
+  { "gfx.editor.button.element_middle",		"RocksDoor2.png"	},
+  { "gfx.editor.button.element_middle.x",	"368"			},
+  { "gfx.editor.button.element_middle.y",	"48"			},
+  { "gfx.editor.button.element_middle.width",	"16"			},
+  { "gfx.editor.button.element_middle.height",	"16"			},
+  { "gfx.editor.button.element_middle.pressed_xoffset", "0"		},
+
+  { "gfx.editor.button.element_right",		"RocksDoor2.png"	},
+  { "gfx.editor.button.element_right.x",	"368"			},
+  { "gfx.editor.button.element_right.y",	"48"			},
+  { "gfx.editor.button.element_right.width",	"16"			},
+  { "gfx.editor.button.element_right.height",	"16"			},
+  { "gfx.editor.button.element_right.pressed_xoffset", "0"		},
+
+  { "gfx.editor.button.palette",		UNDEFINED_FILENAME	},
+
+  { "editor.no_toolbox_button",			"RocksDoor.png"		},
+  { "editor.no_toolbox_button.x",		"506"			},
+  { "editor.no_toolbox_button.y",		"286"			},
+  { "editor.no_toolbox_button.width",		"22"			},
+  { "editor.no_toolbox_button.height",		"22"			},
+
+  { "gfx.editor.button.draw_single",		"RocksDoor.png"		},
+  { "gfx.editor.button.draw_single.x",		"706"			},
+  { "gfx.editor.button.draw_single.y",		"242"			},
+  { "gfx.editor.button.draw_single.width",	"22"			},
+  { "gfx.editor.button.draw_single.height",	"22"			},
+  { "gfx.editor.button.draw_single.pressed_xoffset", "-100"		},
+  { "gfx.editor.button.draw_single.active_yoffset",  "-94"		},
+
+  { "gfx.editor.button.draw_connected",		"RocksDoor.png"		},
+  { "gfx.editor.button.draw_connected.x",	"728"			},
+  { "gfx.editor.button.draw_connected.y",	"242"			},
+  { "gfx.editor.button.draw_connected.width",	"22"			},
+  { "gfx.editor.button.draw_connected.height",	"22"			},
+  { "gfx.editor.button.draw_connected.pressed_xoffset", "-100"		},
+  { "gfx.editor.button.draw_connected.active_yoffset",  "-94"		},
+
+  { "gfx.editor.button.draw_line",		"RocksDoor.png"		},
+  { "gfx.editor.button.draw_line.x",		"750"			},
+  { "gfx.editor.button.draw_line.y",		"242"			},
+  { "gfx.editor.button.draw_line.width",	"22"			},
+  { "gfx.editor.button.draw_line.height",	"22"			},
+  { "gfx.editor.button.draw_line.pressed_xoffset", "-100"		},
+  { "gfx.editor.button.draw_line.active_yoffset",  "-94"		},
+
+  { "gfx.editor.button.draw_arc",		"RocksDoor.png"		},
+  { "gfx.editor.button.draw_arc.x",		"772"			},
+  { "gfx.editor.button.draw_arc.y",		"242"			},
+  { "gfx.editor.button.draw_arc.width",		"22"			},
+  { "gfx.editor.button.draw_arc.height",	"22"			},
+  { "gfx.editor.button.draw_arc.pressed_xoffset", "-100"		},
+  { "gfx.editor.button.draw_arc.active_yoffset",  "-94"			},
+
+  { "gfx.editor.button.draw_rectangle",		"RocksDoor.png"		},
+  { "gfx.editor.button.draw_rectangle.x",	"706"			},
+  { "gfx.editor.button.draw_rectangle.y",	"264"			},
+  { "gfx.editor.button.draw_rectangle.width",	"22"			},
+  { "gfx.editor.button.draw_rectangle.height",	"22"			},
+  { "gfx.editor.button.draw_rectangle.pressed_xoffset", "-100"		},
+  { "gfx.editor.button.draw_rectangle.active_yoffset",  "-94"		},
+
+  { "gfx.editor.button.draw_filled_box",	"RocksDoor.png"		},
+  { "gfx.editor.button.draw_filled_box.x",	"728"			},
+  { "gfx.editor.button.draw_filled_box.y",	"264"			},
+  { "gfx.editor.button.draw_filled_box.width",	"22"			},
+  { "gfx.editor.button.draw_filled_box.height",	"22"			},
+  { "gfx.editor.button.draw_filled_box.pressed_xoffset", "-100"		},
+  { "gfx.editor.button.draw_filled_box.active_yoffset",  "-94"		},
+
+  { "gfx.editor.button.rotate_up",		"RocksDoor.png"		},
+  { "gfx.editor.button.rotate_up.x",		"750"			},
+  { "gfx.editor.button.rotate_up.y",		"264"			},
+  { "gfx.editor.button.rotate_up.width",	"22"			},
+  { "gfx.editor.button.rotate_up.height",	"22"			},
+  { "gfx.editor.button.rotate_up.pressed_xoffset", "-100"		},
+  { "gfx.editor.button.rotate_up.active_yoffset",  "-94"		},
+
+  { "gfx.editor.button.draw_text",		"RocksDoor.png"		},
+  { "gfx.editor.button.draw_text.x",		"772"			},
+  { "gfx.editor.button.draw_text.y",		"264"			},
+  { "gfx.editor.button.draw_text.width",	"22"			},
+  { "gfx.editor.button.draw_text.height",	"22"			},
+  { "gfx.editor.button.draw_text.pressed_xoffset", "-100"		},
+  { "gfx.editor.button.draw_text.active_yoffset",  "-94"		},
+
+  { "gfx.editor.button.flood_fill",		"RocksDoor.png"		},
+  { "gfx.editor.button.flood_fill.x",		"706"			},
+  { "gfx.editor.button.flood_fill.y",		"286"			},
+  { "gfx.editor.button.flood_fill.width",	"22"			},
+  { "gfx.editor.button.flood_fill.height",	"22"			},
+  { "gfx.editor.button.flood_fill.pressed_xoffset", "-100"		},
+  { "gfx.editor.button.flood_fill.active_yoffset",  "-94"		},
+
+  { "gfx.editor.button.rotate_left",		"RocksDoor.png"		},
+  { "gfx.editor.button.rotate_left.x",		"728"			},
+  { "gfx.editor.button.rotate_left.y",		"286"			},
+  { "gfx.editor.button.rotate_left.width",	"22"			},
+  { "gfx.editor.button.rotate_left.height",	"22"			},
+  { "gfx.editor.button.rotate_left.pressed_xoffset", "-100"		},
+  { "gfx.editor.button.rotate_left.active_yoffset",  "-94"		},
+
+  { "gfx.editor.button.zoom_level",		"RocksDoor2.png"	},
+  { "gfx.editor.button.zoom_level.x",		"350"			},
+  { "gfx.editor.button.zoom_level.y",		"22"			},
+  { "gfx.editor.button.zoom_level.width",	"22"			},
+  { "gfx.editor.button.zoom_level.height",	"22"			},
+  { "gfx.editor.button.zoom_level.pressed_xoffset", "-100"		},
+  { "gfx.editor.button.zoom_level.active_yoffset",  "-22"		},
+
+  { "gfx.editor.button.rotate_right",		"RocksDoor.png"		},
+  { "gfx.editor.button.rotate_right.x",		"772"			},
+  { "gfx.editor.button.rotate_right.y",		"286"			},
+  { "gfx.editor.button.rotate_right.width",	"22"			},
+  { "gfx.editor.button.rotate_right.height",	"22"			},
+  { "gfx.editor.button.rotate_right.pressed_xoffset", "-100"		},
+  { "gfx.editor.button.rotate_right.active_yoffset",  "-94"		},
+
+  { "gfx.editor.button.draw_random",		"RocksDoor.png"		},
+  { "gfx.editor.button.draw_random.x",		"706"			},
+  { "gfx.editor.button.draw_random.y",		"308"			},
+  { "gfx.editor.button.draw_random.width",	"22"			},
+  { "gfx.editor.button.draw_random.height",	"22"			},
+  { "gfx.editor.button.draw_random.pressed_xoffset", "-100"		},
+  { "gfx.editor.button.draw_random.active_yoffset",  "-94"		},
+
+  { "gfx.editor.button.grab_brush",		"RocksDoor.png"		},
+  { "gfx.editor.button.grab_brush.x",		"728"			},
+  { "gfx.editor.button.grab_brush.y",		"308"			},
+  { "gfx.editor.button.grab_brush.width",	"22"			},
+  { "gfx.editor.button.grab_brush.height",	"22"			},
+  { "gfx.editor.button.grab_brush.pressed_xoffset", "-100"		},
+  { "gfx.editor.button.grab_brush.active_yoffset",  "-94"		},
+
+  { "gfx.editor.button.rotate_down",		"RocksDoor.png"		},
+  { "gfx.editor.button.rotate_down.x",		"750"			},
+  { "gfx.editor.button.rotate_down.y",		"308"			},
+  { "gfx.editor.button.rotate_down.width",	"22"			},
+  { "gfx.editor.button.rotate_down.height",	"22"			},
+  { "gfx.editor.button.rotate_down.pressed_xoffset", "-100"		},
+  { "gfx.editor.button.rotate_down.active_yoffset",  "-94"		},
+
+  { "gfx.editor.button.pick_element",		"RocksDoor.png"		},
+  { "gfx.editor.button.pick_element.x",		"772"			},
+  { "gfx.editor.button.pick_element.y",		"308"			},
+  { "gfx.editor.button.pick_element.width",	"22"			},
+  { "gfx.editor.button.pick_element.height",	"22"			},
+  { "gfx.editor.button.pick_element.pressed_xoffset", "-100"		},
+  { "gfx.editor.button.pick_element.active_yoffset",  "-94"		},
+
+  { "gfx.editor.button.ce_copy_from",		"RocksDoor.png"		},
+  { "gfx.editor.button.ce_copy_from.x",		"528"			},
+  { "gfx.editor.button.ce_copy_from.y",		"330"			},
+  { "gfx.editor.button.ce_copy_from.width",	"22"			},
+  { "gfx.editor.button.ce_copy_from.height",	"22"			},
+  { "gfx.editor.button.ce_copy_from.pressed_xoffset", "-100"		},
+  { "gfx.editor.button.ce_copy_from.active_yoffset",  "-22"		},
+
+  { "gfx.editor.button.ce_copy_to",		"RocksDoor.png"		},
+  { "gfx.editor.button.ce_copy_to.x",		"550"			},
+  { "gfx.editor.button.ce_copy_to.y",		"330"			},
+  { "gfx.editor.button.ce_copy_to.width",	"22"			},
+  { "gfx.editor.button.ce_copy_to.height",	"22"			},
+  { "gfx.editor.button.ce_copy_to.pressed_xoffset", "-100"		},
+  { "gfx.editor.button.ce_copy_to.active_yoffset",  "-22"		},
+
+  { "gfx.editor.button.ce_swap",		"RocksDoor.png"		},
+  { "gfx.editor.button.ce_swap.x",		"572"			},
+  { "gfx.editor.button.ce_swap.y",		"330"			},
+  { "gfx.editor.button.ce_swap.width",		"22"			},
+  { "gfx.editor.button.ce_swap.height",		"22"			},
+  { "gfx.editor.button.ce_swap.pressed_xoffset", "-100"			},
+  { "gfx.editor.button.ce_swap.active_yoffset",  "-22"			},
+
+  { "gfx.editor.button.ce_copy",		"RocksDoor.png"		},
+  { "gfx.editor.button.ce_copy.x",		"550"			},
+  { "gfx.editor.button.ce_copy.y",		"286"			},
+  { "gfx.editor.button.ce_copy.width",		"22"			},
+  { "gfx.editor.button.ce_copy.height",		"22"			},
+  { "gfx.editor.button.ce_copy.pressed_xoffset", "-100"			},
+
+  { "gfx.editor.button.ce_paste",		"RocksDoor.png"		},
+  { "gfx.editor.button.ce_paste.x",		"572"			},
+  { "gfx.editor.button.ce_paste.y",		"286"			},
+  { "gfx.editor.button.ce_paste.width",		"22"			},
+  { "gfx.editor.button.ce_paste.height",	"22"			},
+  { "gfx.editor.button.ce_paste.pressed_xoffset", "-100"		},
+
+  { "gfx.editor.button.cp_copy",		"RocksDoor.png"		},
+  { "gfx.editor.button.cp_copy.x",		"525"			},
+  { "gfx.editor.button.cp_copy.y",		"50"			},
+  { "gfx.editor.button.cp_copy.width",		"20"			},
+  { "gfx.editor.button.cp_copy.height",		"20"			},
+  { "gfx.editor.button.cp_copy.pressed_xoffset", "-20"			},
+
+  { "gfx.editor.button.cp_paste",		"RocksDoor.png"		},
+  { "gfx.editor.button.cp_paste.x",		"525"			},
+  { "gfx.editor.button.cp_paste.y",		"70"			},
+  { "gfx.editor.button.cp_paste.width",		"20"			},
+  { "gfx.editor.button.cp_paste.height",	"20"			},
+  { "gfx.editor.button.cp_paste.pressed_xoffset", "-20"			},
+
+  { "gfx.editor.button.undo",			"RocksDoor.png"		},
+  { "gfx.editor.button.undo.x",			"705"			},
+  { "gfx.editor.button.undo.y",			"335"			},
+  { "gfx.editor.button.undo.width",		"30"			},
+  { "gfx.editor.button.undo.height",		"20"			},
+  { "gfx.editor.button.undo.pressed_xoffset",	"-100"			},
+
+  { "gfx.editor.button.conf",			"RocksDoor.png"		},
+  { "gfx.editor.button.conf.x",			"735"			},
+  { "gfx.editor.button.conf.y",			"335"			},
+  { "gfx.editor.button.conf.width",		"30"			},
+  { "gfx.editor.button.conf.height",		"20"			},
+  { "gfx.editor.button.conf.pressed_xoffset",	"-100"			},
+
+  { "gfx.editor.button.save",			"RocksDoor.png"		},
+  { "gfx.editor.button.save.x",			"765"			},
+  { "gfx.editor.button.save.y",			"335"			},
+  { "gfx.editor.button.save.width",		"30"			},
+  { "gfx.editor.button.save.height",		"20"			},
+  { "gfx.editor.button.save.pressed_xoffset",	"-100"			},
+
+  { "gfx.editor.button.clear",			"RocksDoor.png"		},
+  { "gfx.editor.button.clear.x",		"705"			},
+  { "gfx.editor.button.clear.y",		"355"			},
+  { "gfx.editor.button.clear.width",		"30"			},
+  { "gfx.editor.button.clear.height",		"20"			},
+  { "gfx.editor.button.clear.pressed_xoffset",	"-100"			},
+
+  { "gfx.editor.button.test",			"RocksDoor.png"		},
+  { "gfx.editor.button.test.x",			"735"			},
+  { "gfx.editor.button.test.y",			"355"			},
+  { "gfx.editor.button.test.width",		"30"			},
+  { "gfx.editor.button.test.height",		"20"			},
+  { "gfx.editor.button.test.pressed_xoffset",	"-100"			},
+
+  { "gfx.editor.button.exit",			"RocksDoor.png"		},
+  { "gfx.editor.button.exit.x",			"765"			},
+  { "gfx.editor.button.exit.y",			"355"			},
+  { "gfx.editor.button.exit.width",		"30"			},
+  { "gfx.editor.button.exit.height",		"20"			},
+  { "gfx.editor.button.exit.pressed_xoffset",	"-100"			},
+
+  { "gfx.editor.input.level_number",		"RocksDoor.png"		},
+  { "gfx.editor.input.level_number.x",		"529"			},
+  { "gfx.editor.input.level_number.y",		"5"			},
+  { "gfx.editor.input.level_number.width",	"42"			},
+  { "gfx.editor.input.level_number.height",	"16"			},
+  { "gfx.editor.input.level_number.border_size","1"			},
+
+  { "global.border",				"RocksScreen.png"	},
+  { "global.border.MAIN",			UNDEFINED_FILENAME	},
+  { "global.border.SCORES",			UNDEFINED_FILENAME	},
+  { "global.border.EDITOR",			UNDEFINED_FILENAME	},
+  { "global.border.PLAYING",			UNDEFINED_FILENAME	},
+
+  { "global.door",				"RocksDoor.png"		},
+
+  { "global.busy",				"RocksBusy.png"		},
   { "global.busy.x",				"0"			},
   { "global.busy.y",				"0"			},
   { "global.busy.width",			"32"			},
@@ -4982,28 +5736,12 @@ struct ConfigInfo image_config[] =
   { "global.busy.frames_per_line",		"7"			},
   { "global.busy.delay",			"2"			},
 
-  { "editor.element_border",			"RocksElements.pcx"	},
-  { "editor.element_border.x",			"0"			},
-  { "editor.element_border.y",			"0"			},
-
-  { "editor.element_border_input",		"RocksDoor.pcx"		},
-  { "editor.element_border_input.x",		"740"			},
-  { "editor.element_border_input.y",		"48"			},
-
-  { "editor.cascade_list",			"RocksDoor.pcx"		},
-  { "editor.cascade_list.x",			"708"			},
-  { "editor.cascade_list.y",			"80"			},
-  { "editor.cascade_list.frames",		"1"			},
-  { "editor.cascade_list.active",		"RocksDoor.pcx"		},
-  { "editor.cascade_list.active.x",		"740"			},
-  { "editor.cascade_list.active.y",		"80"			},
-  { "editor.cascade_list.active.frames",	"1"			},
-
   { "background",				UNDEFINED_FILENAME	},
   { "background.TITLE_INITIAL",			UNDEFINED_FILENAME	},
   { "background.TITLE",				UNDEFINED_FILENAME	},
   { "background.MAIN",				UNDEFINED_FILENAME	},
   { "background.LEVELS",			UNDEFINED_FILENAME	},
+  { "background.LEVELNR",			UNDEFINED_FILENAME	},
   { "background.SCORES",			UNDEFINED_FILENAME	},
   { "background.EDITOR",			UNDEFINED_FILENAME	},
   { "background.INFO",				UNDEFINED_FILENAME	},
@@ -5016,6 +5754,26 @@ struct ConfigInfo image_config[] =
   { "background.SETUP",				UNDEFINED_FILENAME	},
   { "background.PLAYING",			UNDEFINED_FILENAME	},
   { "background.DOOR",				UNDEFINED_FILENAME	},
+  { "background.TAPE",				"RocksDoor.png"		},
+  { "background.TAPE.x",			"200"			},
+  { "background.TAPE.y",			"280"			},
+  { "background.TAPE.width",			"100"			},
+  { "background.TAPE.height",			"100"			},
+  { "background.PANEL",				"RocksDoor.png"		},
+  { "background.PANEL.x",			"400"			},
+  { "background.PANEL.y",			"0"			},
+  { "background.PANEL.width",			"100"			},
+  { "background.PANEL.height",			"280"			},
+  { "background.PALETTE",			"RocksDoor.png"		},
+  { "background.PALETTE.x",			"500"			},
+  { "background.PALETTE.y",			"0"			},
+  { "background.PALETTE.width",			"100"			},
+  { "background.PALETTE.height",		"280"			},
+  { "background.TOOLBOX",			"RocksDoor.png"		},
+  { "background.TOOLBOX.x",			"700"			},
+  { "background.TOOLBOX.y",			"236"			},
+  { "background.TOOLBOX.width",			"100"			},
+  { "background.TOOLBOX.height",		"144"			},
 
   { "background.titlescreen_initial_1",		UNDEFINED_FILENAME	},
   { "background.titlescreen_initial_2",		UNDEFINED_FILENAME	},
@@ -5038,28 +5796,28 @@ struct ConfigInfo image_config[] =
   { "background.titlemessage_4",		UNDEFINED_FILENAME	},
   { "background.titlemessage_5",		UNDEFINED_FILENAME	},
 
-  { "background.envelope_1",			"RocksScreen.pcx"	},
+  { "background.envelope_1",			"RocksScreen.png"	},
   { "background.envelope_1.x",			"0"			},
   { "background.envelope_1.y",			"0"			},
   { "background.envelope_1.width",		"560"			},
   { "background.envelope_1.height",		"560"			},
   { "background.envelope_1.anim_mode",		"default"		},
   { "background.envelope_1.draw_masked",	"false"			},
-  { "background.envelope_2",			"RocksScreen.pcx"	},
+  { "background.envelope_2",			"RocksScreen.png"	},
   { "background.envelope_2.x",			"0"			},
   { "background.envelope_2.y",			"0"			},
   { "background.envelope_2.width",		"560"			},
   { "background.envelope_2.height",		"560"			},
   { "background.envelope_2.anim_mode",		"default"		},
   { "background.envelope_2.draw_masked",	"false"			},
-  { "background.envelope_3",			"RocksScreen.pcx"	},
+  { "background.envelope_3",			"RocksScreen.png"	},
   { "background.envelope_3.x",			"0"			},
   { "background.envelope_3.y",			"0"			},
   { "background.envelope_3.width",		"560"			},
   { "background.envelope_3.height",		"560"			},
   { "background.envelope_3.anim_mode",		"default"		},
   { "background.envelope_3.draw_masked",	"false"			},
-  { "background.envelope_4",			"RocksScreen.pcx"	},
+  { "background.envelope_4",			"RocksScreen.png"	},
   { "background.envelope_4.x",			"0"			},
   { "background.envelope_4.y",			"0"			},
   { "background.envelope_4.width",		"560"			},
@@ -5067,6 +5825,14 @@ struct ConfigInfo image_config[] =
   { "background.envelope_4.anim_mode",		"default"		},
   { "background.envelope_4.draw_masked",	"false"			},
 
+  { "background.request",			"RocksScreen.png"	},
+  { "background.request.x",			"562"			},
+  { "background.request.y",			"56"			},
+  { "background.request.width",			"108"			},
+  { "background.request.height",		"288"			},
+  { "background.request.anim_mode",		"default"		},
+  { "background.request.draw_masked",		"false"			},
+
   { "titlescreen_initial_1",			UNDEFINED_FILENAME	},
   { "titlescreen_initial_2",			UNDEFINED_FILENAME	},
   { "titlescreen_initial_3",			UNDEFINED_FILENAME	},
@@ -5078,6 +5844,99 @@ struct ConfigInfo image_config[] =
   { "titlescreen_4",				UNDEFINED_FILENAME	},
   { "titlescreen_5",				UNDEFINED_FILENAME	},
 
+  { "gfx.door_1.part_1",			"RocksDoor.png"		},
+  { "gfx.door_1.part_1.x",			"0"			},
+  { "gfx.door_1.part_1.y",			"0"			},
+  { "gfx.door_1.part_1.width",			"100"			},
+  { "gfx.door_1.part_1.height",			"77"			},
+  { "gfx.door_1.part_1.frames",			"1"			},
+  { "gfx.door_1.part_2",			"RocksDoor.png"		},
+  { "gfx.door_1.part_2.x",			"0"			},
+  { "gfx.door_1.part_2.y",			"77"			},
+  { "gfx.door_1.part_2.width",			"100"			},
+  { "gfx.door_1.part_2.height",			"63"			},
+  { "gfx.door_1.part_2.frames",			"1"			},
+  { "gfx.door_1.part_3",			"RocksDoor.png"		},
+  { "gfx.door_1.part_3.x",			"0"			},
+  { "gfx.door_1.part_3.y",			"140"			},
+  { "gfx.door_1.part_3.width",			"100"			},
+  { "gfx.door_1.part_3.height",			"63"			},
+  { "gfx.door_1.part_3.frames",			"1"			},
+  { "gfx.door_1.part_4",			"RocksDoor.png"		},
+  { "gfx.door_1.part_4.x",			"0"			},
+  { "gfx.door_1.part_4.y",			"203"			},
+  { "gfx.door_1.part_4.width",			"100"			},
+  { "gfx.door_1.part_4.height",			"77"			},
+  { "gfx.door_1.part_4.frames",			"1"			},
+  { "gfx.door_1.part_5",			"RocksDoor.png"		},
+  { "gfx.door_1.part_5.x",			"100"			},
+  { "gfx.door_1.part_5.y",			"0"			},
+  { "gfx.door_1.part_5.width",			"100"			},
+  { "gfx.door_1.part_5.height",			"77"			},
+  { "gfx.door_1.part_5.frames",			"1"			},
+  { "gfx.door_1.part_6",			"RocksDoor.png"		},
+  { "gfx.door_1.part_6.x",			"100"			},
+  { "gfx.door_1.part_6.y",			"77"			},
+  { "gfx.door_1.part_6.width",			"100"			},
+  { "gfx.door_1.part_6.height",			"63"			},
+  { "gfx.door_1.part_6.frames",			"1"			},
+  { "gfx.door_1.part_7",			"RocksDoor.png"		},
+  { "gfx.door_1.part_7.x",			"100"			},
+  { "gfx.door_1.part_7.y",			"140"			},
+  { "gfx.door_1.part_7.width",			"100"			},
+  { "gfx.door_1.part_7.height",			"63"			},
+  { "gfx.door_1.part_7.frames",			"1"			},
+  { "gfx.door_1.part_8",			"RocksDoor.png"		},
+  { "gfx.door_1.part_8.x",			"100"			},
+  { "gfx.door_1.part_8.y",			"203"			},
+  { "gfx.door_1.part_8.width",			"100"			},
+  { "gfx.door_1.part_8.height",			"77"			},
+  { "gfx.door_1.part_8.frames",			"1"			},
+
+  { "gfx.door_2.part_1",			"RocksDoor.png"		},
+  { "gfx.door_2.part_1.x",			"0"			},
+  { "gfx.door_2.part_1.y",			"280"			},
+  { "gfx.door_2.part_1.width",			"100"			},
+  { "gfx.door_2.part_1.height",			"50"			},
+  { "gfx.door_2.part_1.frames",			"1"			},
+  { "gfx.door_2.part_2",			"RocksDoor.png"		},
+  { "gfx.door_2.part_2.x",			"0"			},
+  { "gfx.door_2.part_2.y",			"330"			},
+  { "gfx.door_2.part_2.width",			"100"			},
+  { "gfx.door_2.part_2.height",			"50"			},
+  { "gfx.door_2.part_2.frames",			"1"			},
+  { "gfx.door_2.part_3",			"RocksDoor.png"		},
+  { "gfx.door_2.part_3.x",			"100"			},
+  { "gfx.door_2.part_3.y",			"280"			},
+  { "gfx.door_2.part_3.width",			"100"			},
+  { "gfx.door_2.part_3.height",			"50"			},
+  { "gfx.door_2.part_3.frames",			"1"			},
+  { "gfx.door_2.part_4",			"RocksDoor.png"		},
+  { "gfx.door_2.part_4.x",			"100"			},
+  { "gfx.door_2.part_4.y",			"330"			},
+  { "gfx.door_2.part_4.width",			"100"			},
+  { "gfx.door_2.part_4.height",			"50"			},
+  { "gfx.door_2.part_4.frames",			"1"			},
+  { "gfx.door_2.part_5",			UNDEFINED_FILENAME	},
+  { "gfx.door_2.part_6",			UNDEFINED_FILENAME	},
+  { "gfx.door_2.part_7",			UNDEFINED_FILENAME	},
+  { "gfx.door_2.part_8",			UNDEFINED_FILENAME	},
+
+  { "door_2.top_border_correction",		"RocksDoor.png"		},
+  { "door_2.top_border_correction.x",		"600"			},
+  { "door_2.top_border_correction.y",		"0"			},
+  { "door_2.top_border_correction.width",	"108"			},
+  { "door_2.top_border_correction.height",	"8"			},
+
+  /* the last image entry apparently gets overwritten by very last entry
+     of "image_config[]"; so far this bug could not be found and fixed */
+  { "last_image_entry_bug",			UNDEFINED_FILENAME	},
+
+
+  // ==========================================================================
+  // non-image definitions
+  // ==========================================================================
+
   /* the following directives are not associated with an image, but
      probably make sense to be defined in "graphicsinfo.conf", too */
 
@@ -5092,10 +5951,72 @@ struct ConfigInfo image_config[] =
   { "[title].post_delay",			"250"			},
   { "[title].auto_delay",			"-1"			},
 
-  { "[titlemessage_initial].x",			"336"			},
-  { "[titlemessage_initial].y",			"280"			},
-  { "[titlemessage_initial].width",		"640"			},
-  { "[titlemessage_initial].height",		"512"			},
+  { "[titlescreen_initial].sort_priority",	"0"			},
+  { "[titlescreen_initial].fade_mode",		ARG_DEFAULT		},
+  { "[titlescreen_initial].fade_delay",		ARG_DEFAULT		},
+  { "[titlescreen_initial].post_delay",		ARG_DEFAULT		},
+  { "[titlescreen_initial].auto_delay",		ARG_DEFAULT		},
+  { "[titlescreen].sort_priority",		"0"			},
+  { "[titlescreen].fade_mode",			ARG_DEFAULT		},
+  { "[titlescreen].fade_delay",			ARG_DEFAULT		},
+  { "[titlescreen].post_delay",			ARG_DEFAULT		},
+  { "[titlescreen].auto_delay",			ARG_DEFAULT		},
+
+  { "titlescreen_initial_1.sort_priority",	ARG_DEFAULT		},
+  { "titlescreen_initial_1.fade_mode",		ARG_DEFAULT		},
+  { "titlescreen_initial_1.fade_delay",		ARG_DEFAULT		},
+  { "titlescreen_initial_1.post_delay",		ARG_DEFAULT		},
+  { "titlescreen_initial_1.auto_delay",		ARG_DEFAULT		},
+  { "titlescreen_initial_2.sort_priority",	ARG_DEFAULT		},
+  { "titlescreen_initial_2.fade_mode",		ARG_DEFAULT		},
+  { "titlescreen_initial_2.fade_delay",		ARG_DEFAULT		},
+  { "titlescreen_initial_2.post_delay",		ARG_DEFAULT		},
+  { "titlescreen_initial_2.auto_delay",		ARG_DEFAULT		},
+  { "titlescreen_initial_3.sort_priority",	ARG_DEFAULT		},
+  { "titlescreen_initial_3.fade_mode",		ARG_DEFAULT		},
+  { "titlescreen_initial_3.fade_delay",		ARG_DEFAULT		},
+  { "titlescreen_initial_3.post_delay",		ARG_DEFAULT		},
+  { "titlescreen_initial_3.auto_delay",		ARG_DEFAULT		},
+  { "titlescreen_initial_4.sort_priority",	ARG_DEFAULT		},
+  { "titlescreen_initial_4.fade_mode",		ARG_DEFAULT		},
+  { "titlescreen_initial_4.fade_delay",		ARG_DEFAULT		},
+  { "titlescreen_initial_4.post_delay",		ARG_DEFAULT		},
+  { "titlescreen_initial_4.auto_delay",		ARG_DEFAULT		},
+  { "titlescreen_initial_5.sort_priority",	ARG_DEFAULT		},
+  { "titlescreen_initial_5.fade_mode",		ARG_DEFAULT		},
+  { "titlescreen_initial_5.fade_delay",		ARG_DEFAULT		},
+  { "titlescreen_initial_5.post_delay",		ARG_DEFAULT		},
+  { "titlescreen_initial_5.auto_delay",		ARG_DEFAULT		},
+  { "titlescreen_1.sort_priority",		ARG_DEFAULT		},
+  { "titlescreen_1.fade_mode",			ARG_DEFAULT		},
+  { "titlescreen_1.fade_delay",			ARG_DEFAULT		},
+  { "titlescreen_1.post_delay",			ARG_DEFAULT		},
+  { "titlescreen_1.auto_delay",			ARG_DEFAULT		},
+  { "titlescreen_2.sort_priority",		ARG_DEFAULT		},
+  { "titlescreen_2.fade_mode",			ARG_DEFAULT		},
+  { "titlescreen_2.fade_delay",			ARG_DEFAULT		},
+  { "titlescreen_2.post_delay",			ARG_DEFAULT		},
+  { "titlescreen_2.auto_delay",			ARG_DEFAULT		},
+  { "titlescreen_3.sort_priority",		ARG_DEFAULT		},
+  { "titlescreen_3.fade_mode",			ARG_DEFAULT		},
+  { "titlescreen_3.fade_delay",			ARG_DEFAULT		},
+  { "titlescreen_3.post_delay",			ARG_DEFAULT		},
+  { "titlescreen_3.auto_delay",			ARG_DEFAULT		},
+  { "titlescreen_4.sort_priority",		ARG_DEFAULT		},
+  { "titlescreen_4.fade_mode",			ARG_DEFAULT		},
+  { "titlescreen_4.fade_delay",			ARG_DEFAULT		},
+  { "titlescreen_4.post_delay",			ARG_DEFAULT		},
+  { "titlescreen_4.auto_delay",			ARG_DEFAULT		},
+  { "titlescreen_5.sort_priority",		ARG_DEFAULT		},
+  { "titlescreen_5.fade_mode",			ARG_DEFAULT		},
+  { "titlescreen_5.fade_delay",			ARG_DEFAULT		},
+  { "titlescreen_5.post_delay",			ARG_DEFAULT		},
+  { "titlescreen_5.auto_delay",			ARG_DEFAULT		},
+
+  { "[titlemessage_initial].x",			"-1"			},
+  { "[titlemessage_initial].y",			"-1"			},
+  { "[titlemessage_initial].width",		"-1"			},
+  { "[titlemessage_initial].height",		"-1"			},
   { "[titlemessage_initial].chars",		"-1"			},
   { "[titlemessage_initial].lines",		"-1"			},
   { "[titlemessage_initial].align",		"center"		},
@@ -5109,10 +6030,10 @@ struct ConfigInfo image_config[] =
   { "[titlemessage_initial].fade_delay",	ARG_DEFAULT		},
   { "[titlemessage_initial].post_delay",	ARG_DEFAULT		},
   { "[titlemessage_initial].auto_delay",	ARG_DEFAULT		},
-  { "[titlemessage].x",				"336"			},
-  { "[titlemessage].y",				"280"			},
-  { "[titlemessage].width",			"640"			},
-  { "[titlemessage].height",			"512"			},
+  { "[titlemessage].x",				"-1"			},
+  { "[titlemessage].y",				"-1"			},
+  { "[titlemessage].width",			"-1"			},
+  { "[titlemessage].height",			"-1"			},
   { "[titlemessage].chars",			"-1"			},
   { "[titlemessage].lines",			"-1"			},
   { "[titlemessage].align",			"center"		},
@@ -5298,10 +6219,10 @@ struct ConfigInfo image_config[] =
   { "titlemessage_5.post_delay",		ARG_DEFAULT		},
   { "titlemessage_5.auto_delay",		ARG_DEFAULT		},
 
-  { "readme.x",					"272"			},
-  { "readme.y",					"150"			},
-  { "readme.width",				"480"			},
-  { "readme.height",				"364"			},
+  { "readme.x",					"-1"			},
+  { "readme.y",					"-1"			},
+  { "readme.width",				"-1"			},
+  { "readme.height",				"-1"			},
   { "readme.chars",				"-1"			},
   { "readme.lines",				"-1"			},
   { "readme.align",				"center"		},
@@ -5317,6 +6238,7 @@ struct ConfigInfo image_config[] =
   { "border.draw_masked.TITLE",			"false"			},
   { "border.draw_masked.MAIN",			"false"			},
   { "border.draw_masked.LEVELS",		"false"			},
+  { "border.draw_masked.LEVELNR",		"false"			},
   { "border.draw_masked.SCORES",		"false"			},
   { "border.draw_masked.EDITOR",		"false"			},
   { "border.draw_masked.INFO",			"false"			},
@@ -5326,8 +6248,8 @@ struct ConfigInfo image_config[] =
 
   { "border.draw_masked_when_fading",		"true"			},
 
-  { "init.busy.x",				"336"			},
-  { "init.busy.y",				"280"			},
+  { "init.busy.x",				"-1"			},
+  { "init.busy.y",				"-1"			},
   { "init.busy.align",				"center"		},
   { "init.busy.valign",				"middle"		},
 
@@ -5340,12 +6262,16 @@ struct ConfigInfo image_config[] =
   { "menu.enter_screen.fade_mode",		"fade"			},
   { "menu.enter_screen.fade_delay",		"250"			},
   { "menu.enter_screen.post_delay",		"125"			},
-  { "menu.next_screen.fade_mode",		"crossfade"		},
-  { "menu.next_screen.fade_delay",		"250"			},
-  { "menu.next_screen.post_delay",		"125"			},
   { "menu.leave_screen.fade_mode",		"fade"			},
   { "menu.leave_screen.fade_delay",		"250"			},
   { "menu.leave_screen.post_delay",		"125"			},
+  { "menu.next_screen.fade_mode",		"crossfade"		},
+  { "menu.next_screen.fade_delay",		"250"			},
+  { "menu.next_screen.post_delay",		"125"			},
+  { "menu.enter_screen.TITLE.fade_mode",	"fade"			},
+  { "menu.enter_screen.TITLE.fade_delay",	"500"			},
+  { "menu.enter_screen.TITLE.post_delay",	"250"			},
+  { "menu.enter_screen.TITLE.auto_delay",	"-1"			},
   { "menu.enter_screen.SCORES.fade_mode",	ARG_DEFAULT		},
   { "menu.enter_screen.SCORES.fade_delay",	ARG_DEFAULT		},
   { "menu.enter_screen.SCORES.post_delay",	ARG_DEFAULT		},
@@ -5358,6 +6284,10 @@ struct ConfigInfo image_config[] =
   { "menu.enter_screen.PLAYING.fade_mode",	ARG_DEFAULT		},
   { "menu.enter_screen.PLAYING.fade_delay",	ARG_DEFAULT		},
   { "menu.enter_screen.PLAYING.post_delay",	ARG_DEFAULT		},
+  { "menu.leave_screen.TITLE.fade_mode",	"fade"			},
+  { "menu.leave_screen.TITLE.fade_delay",	"500"			},
+  { "menu.leave_screen.TITLE.post_delay",	"250"			},
+  { "menu.leave_screen.TITLE.auto_delay",	"-1"			},
   { "menu.leave_screen.SCORES.fade_mode",	ARG_DEFAULT		},
   { "menu.leave_screen.SCORES.fade_delay",	ARG_DEFAULT		},
   { "menu.leave_screen.SCORES.post_delay",	ARG_DEFAULT		},
@@ -5370,6 +6300,13 @@ struct ConfigInfo image_config[] =
   { "menu.leave_screen.PLAYING.fade_mode",	ARG_DEFAULT		},
   { "menu.leave_screen.PLAYING.fade_delay",	ARG_DEFAULT		},
   { "menu.leave_screen.PLAYING.post_delay",	ARG_DEFAULT		},
+  { "menu.next_screen.TITLE.fade_mode",		"fade"			},
+  { "menu.next_screen.TITLE.fade_delay",	"500"			},
+  { "menu.next_screen.TITLE.post_delay",	"250"			},
+  { "menu.next_screen.TITLE.auto_delay",	"-1"			},
+  { "menu.next_screen.INFO.fade_mode",		ARG_DEFAULT		},
+  { "menu.next_screen.INFO.fade_delay",		ARG_DEFAULT		},
+  { "menu.next_screen.INFO.post_delay",		ARG_DEFAULT		},
 
   { "menu.draw_xoffset",			"0"			},
   { "menu.draw_yoffset",			"0"			},
@@ -5377,6 +6314,8 @@ struct ConfigInfo image_config[] =
   { "menu.draw_yoffset.MAIN",			"0"			},
   { "menu.draw_xoffset.LEVELS",			"0"			},
   { "menu.draw_yoffset.LEVELS",			"0"			},
+  { "menu.draw_xoffset.LEVELNR",		"0"			},
+  { "menu.draw_yoffset.LEVELNR",		"0"			},
   { "menu.draw_xoffset.SCORES",			"0"			},
   { "menu.draw_yoffset.SCORES",			"0"			},
   { "menu.draw_xoffset.EDITOR",			"0"			},
@@ -5409,6 +6348,8 @@ struct ConfigInfo image_config[] =
   { "menu.draw_yoffset.SETUP[ARTWORK]",		"0"			},
   { "menu.draw_xoffset.SETUP[INPUT]",		"0"			},
   { "menu.draw_yoffset.SETUP[INPUT]",		"0"			},
+  { "menu.draw_xoffset.SETUP[TOUCH]",		"0"			},
+  { "menu.draw_yoffset.SETUP[TOUCH]",		"0"			},
   { "menu.draw_xoffset.SETUP[SHORTCUTS]",	"0"			},
   { "menu.draw_yoffset.SETUP[SHORTCUTS]",	"0"			},
   { "menu.draw_xoffset.SETUP[SHORTCUTS_1]",	"0"			},
@@ -5419,6 +6360,8 @@ struct ConfigInfo image_config[] =
   { "menu.draw_yoffset.SETUP[SHORTCUTS_3]",	"0"			},
   { "menu.draw_xoffset.SETUP[SHORTCUTS_4]",	"0"			},
   { "menu.draw_yoffset.SETUP[SHORTCUTS_4]",	"0"			},
+  { "menu.draw_xoffset.SETUP[SHORTCUTS_5]",	"0"			},
+  { "menu.draw_yoffset.SETUP[SHORTCUTS_5]",	"0"			},
   { "menu.draw_xoffset.SETUP[CHOOSE_ARTWORK]",	"0"			},
   { "menu.draw_yoffset.SETUP[CHOOSE_ARTWORK]",	"0"			},
   { "menu.draw_xoffset.SETUP[CHOOSE_OTHER]",	"0"			},
@@ -5428,8 +6371,10 @@ struct ConfigInfo image_config[] =
 
   { "menu.list_size",				"-1"			},
   { "menu.list_size.LEVELS",			"-1"			},
+  { "menu.list_size.LEVELNR",			"-1"			},
   { "menu.list_size.SCORES",			"-1"			},
   { "menu.list_size.INFO",			"-1"			},
+  { "menu.list_size.INFO[ELEMENTS]",		"-1"			},
   { "menu.list_size.SETUP",			"-1"			},
 
   { "main.button.name.x",			"0"			},
@@ -5613,6 +6558,190 @@ struct ConfigInfo image_config[] =
   { "preview.step_delay",			"50"			},
   { "preview.anim_mode",			"default"		},
 
+  { "door_1.part_1.x",				"0"			},
+  { "door_1.part_1.y",				"0"			},
+  { "door_1.part_1.step_xoffset",		"3"			},
+  { "door_1.part_1.step_yoffset",		"1"			},
+  { "door_1.part_1.step_delay",			"10"			},
+  { "door_1.part_1.start_step",			"0"			},
+  { "door_1.part_1.start_step_opening",		"0"			},
+  { "door_1.part_1.start_step_closing",		"0"			},
+  { "door_1.part_1.draw_masked",		"true"			},
+  { "door_1.part_1.draw_order",			"3"			},
+  { "door_1.part_2.x",				"0"			},
+  { "door_1.part_2.y",				"77"			},
+  { "door_1.part_2.step_xoffset",		"3"			},
+  { "door_1.part_2.step_yoffset",		"1"			},
+  { "door_1.part_2.step_delay",			"10"			},
+  { "door_1.part_2.start_step",			"0"			},
+  { "door_1.part_2.start_step_opening",		"0"			},
+  { "door_1.part_2.start_step_closing",		"0"			},
+  { "door_1.part_2.draw_masked",		"true"			},
+  { "door_1.part_2.draw_order",			"5"			},
+  { "door_1.part_3.x",				"0"			},
+  { "door_1.part_3.y",				"140"			},
+  { "door_1.part_3.step_xoffset",		"3"			},
+  { "door_1.part_3.step_yoffset",		"1"			},
+  { "door_1.part_3.step_delay",			"10"			},
+  { "door_1.part_3.start_step",			"0"			},
+  { "door_1.part_3.start_step_opening",		"0"			},
+  { "door_1.part_3.start_step_closing",		"0"			},
+  { "door_1.part_3.draw_masked",		"true"			},
+  { "door_1.part_3.draw_order",			"4"			},
+  { "door_1.part_4.x",				"0"			},
+  { "door_1.part_4.y",				"203"			},
+  { "door_1.part_4.step_xoffset",		"3"			},
+  { "door_1.part_4.step_yoffset",		"1"			},
+  { "door_1.part_4.step_delay",			"10"			},
+  { "door_1.part_4.start_step",			"0"			},
+  { "door_1.part_4.start_step_opening",		"0"			},
+  { "door_1.part_4.start_step_closing",		"0"			},
+  { "door_1.part_4.draw_masked",		"true"			},
+  { "door_1.part_4.draw_order",			"6"			},
+  { "door_1.part_5.x",				"0"			},
+  { "door_1.part_5.y",				"0"			},
+  { "door_1.part_5.step_xoffset",		"-3"			},
+  { "door_1.part_5.step_yoffset",		"-1"			},
+  { "door_1.part_5.step_delay",			"10"			},
+  { "door_1.part_5.start_step",			"0"			},
+  { "door_1.part_5.start_step_opening",		"0"			},
+  { "door_1.part_5.start_step_closing",		"0"			},
+  { "door_1.part_5.draw_masked",		"true"			},
+  { "door_1.part_5.draw_order",			"1"			},
+  { "door_1.part_6.x",				"0"			},
+  { "door_1.part_6.y",				"77"			},
+  { "door_1.part_6.step_xoffset",		"-3"			},
+  { "door_1.part_6.step_yoffset",		"-1"			},
+  { "door_1.part_6.step_delay",			"10"			},
+  { "door_1.part_6.start_step",			"0"			},
+  { "door_1.part_6.start_step_opening",		"0"			},
+  { "door_1.part_6.start_step_closing",		"0"			},
+  { "door_1.part_6.draw_masked",		"true"			},
+  { "door_1.part_6.draw_order",			"7"			},
+  { "door_1.part_7.x",				"0"			},
+  { "door_1.part_7.y",				"140"			},
+  { "door_1.part_7.step_xoffset",		"-3"			},
+  { "door_1.part_7.step_yoffset",		"-1"			},
+  { "door_1.part_7.step_delay",			"10"			},
+  { "door_1.part_7.start_step",			"0"			},
+  { "door_1.part_7.start_step_opening",		"0"			},
+  { "door_1.part_7.start_step_closing",		"0"			},
+  { "door_1.part_7.draw_masked",		"true"			},
+  { "door_1.part_7.draw_order",			"2"			},
+  { "door_1.part_8.x",				"0"			},
+  { "door_1.part_8.y",				"203"			},
+  { "door_1.part_8.step_xoffset",		"-3"			},
+  { "door_1.part_8.step_yoffset",		"-1"			},
+  { "door_1.part_8.step_delay",			"10"			},
+  { "door_1.part_8.start_step",			"0"			},
+  { "door_1.part_8.start_step_opening",		"0"			},
+  { "door_1.part_8.start_step_closing",		"0"			},
+  { "door_1.part_8.draw_masked",		"true"			},
+  { "door_1.part_8.draw_order",			"8"			},
+
+  { "door_2.part_1.x",				"0"			},
+  { "door_2.part_1.y",				"0"			},
+  { "door_2.part_1.step_xoffset",		"3"			},
+  { "door_2.part_1.step_yoffset",		"1"			},
+  { "door_2.part_1.step_delay",			"10"			},
+  { "door_2.part_1.start_step",			"0"			},
+  { "door_2.part_1.start_step_opening",		"0"			},
+  { "door_2.part_1.start_step_closing",		"0"			},
+  { "door_2.part_1.draw_masked",		"true"			},
+  { "door_2.part_1.draw_order",			"2"			},
+  { "door_2.part_2.x",				"0"			},
+  { "door_2.part_2.y",				"50"			},
+  { "door_2.part_2.step_xoffset",		"3"			},
+  { "door_2.part_2.step_yoffset",		"1"			},
+  { "door_2.part_2.step_delay",			"10"			},
+  { "door_2.part_2.start_step",			"0"			},
+  { "door_2.part_2.start_step_opening",		"0"			},
+  { "door_2.part_2.start_step_closing",		"0"			},
+  { "door_2.part_2.draw_masked",		"true"			},
+  { "door_2.part_2.draw_order",			"3"			},
+  { "door_2.part_3.x",				"0"			},
+  { "door_2.part_3.y",				"0"			},
+  { "door_2.part_3.step_xoffset",		"-3"			},
+  { "door_2.part_3.step_yoffset",		"-1"			},
+  { "door_2.part_3.step_delay",			"10"			},
+  { "door_2.part_3.start_step",			"0"			},
+  { "door_2.part_3.start_step_opening",		"0"			},
+  { "door_2.part_3.start_step_closing",		"0"			},
+  { "door_2.part_3.draw_masked",		"true"			},
+  { "door_2.part_3.draw_order",			"1"			},
+  { "door_2.part_4.x",				"0"			},
+  { "door_2.part_4.y",				"50"			},
+  { "door_2.part_4.step_xoffset",		"-3"			},
+  { "door_2.part_4.step_yoffset",		"-1"			},
+  { "door_2.part_4.step_delay",			"10"			},
+  { "door_2.part_4.start_step",			"0"			},
+  { "door_2.part_4.start_step_opening",		"0"			},
+  { "door_2.part_4.start_step_closing",		"0"			},
+  { "door_2.part_4.draw_masked",		"true"			},
+  { "door_2.part_4.draw_order",			"4"			},
+  { "door_2.part_5.x",				"-1"			},
+  { "door_2.part_5.y",				"-1"			},
+  { "door_2.part_5.step_xoffset",		"0"			},
+  { "door_2.part_5.step_yoffset",		"0"			},
+  { "door_2.part_5.step_delay",			"0"			},
+  { "door_2.part_5.start_step",			"0"			},
+  { "door_2.part_5.start_step_opening",		"0"			},
+  { "door_2.part_5.start_step_closing",		"0"			},
+  { "door_2.part_5.draw_masked",		"true"			},
+  { "door_2.part_5.draw_order",			"0"			},
+  { "door_2.part_6.x",				"-1"			},
+  { "door_2.part_6.y",				"-1"			},
+  { "door_2.part_6.step_xoffset",		"0"			},
+  { "door_2.part_6.step_yoffset",		"0"			},
+  { "door_2.part_6.step_delay",			"0"			},
+  { "door_2.part_6.start_step",			"0"			},
+  { "door_2.part_6.start_step_opening",		"0"			},
+  { "door_2.part_6.start_step_closing",		"0"			},
+  { "door_2.part_6.draw_masked",		"true"			},
+  { "door_2.part_6.draw_order",			"0"			},
+  { "door_2.part_7.x",				"-1"			},
+  { "door_2.part_7.y",				"-1"			},
+  { "door_2.part_7.step_xoffset",		"0"			},
+  { "door_2.part_7.step_yoffset",		"0"			},
+  { "door_2.part_7.step_delay",			"0"			},
+  { "door_2.part_7.start_step",			"0"			},
+  { "door_2.part_7.start_step_opening",		"0"			},
+  { "door_2.part_7.start_step_closing",		"0"			},
+  { "door_2.part_7.draw_masked",		"true"			},
+  { "door_2.part_7.draw_order",			"0"			},
+  { "door_2.part_8.x",				"-1"			},
+  { "door_2.part_8.y",				"-1"			},
+  { "door_2.part_8.step_xoffset",		"0"			},
+  { "door_2.part_8.step_yoffset",		"0"			},
+  { "door_2.part_8.step_delay",			"0"			},
+  { "door_2.part_8.start_step",			"0"			},
+  { "door_2.part_8.start_step_opening",		"0"			},
+  { "door_2.part_8.start_step_closing",		"0"			},
+  { "door_2.part_8.draw_masked",		"true"			},
+  { "door_2.part_8.draw_order",			"0"			},
+
+  { "door_1.panel.x",				"0"			},
+  { "door_1.panel.y",				"0"			},
+  { "door_1.panel.step_xoffset",		"0"			},
+  { "door_1.panel.step_yoffset",		"1"			},
+  { "door_1.panel.step_delay",			"10"			},
+  { "door_1.panel.start_step",			"246"			},
+  { "door_1.panel.start_step_opening",		"0"			},
+  { "door_1.panel.start_step_closing",		"0"			},
+  { "door_1.panel.draw_masked",			"false"			},
+  { "door_1.panel.draw_order",			"0"			},
+
+  { "door_2.panel.x",				"0"			},
+  { "door_2.panel.y",				"0"			},
+  { "door_2.panel.step_xoffset",		"0"			},
+  { "door_2.panel.step_yoffset",		"1"			},
+  { "door_2.panel.step_delay",			"10"			},
+  { "door_2.panel.start_step",			"66"			},
+  { "door_2.panel.start_step_opening",		"0"			},
+  { "door_2.panel.start_step_closing",		"0"			},
+  { "door_2.panel.draw_masked",			"false"			},
+  { "door_2.panel.draw_order",			"0"			},
+
   { "door_1.width",				"-1"			},
   { "door_1.height",				"-1"			},
   { "door_1.step_offset",			"2"			},
@@ -6389,6 +7518,16 @@ struct ConfigInfo image_config[] =
   { "game.button.pause.y",			"215"			},
   { "game.button.play.x",			"65"			},
   { "game.button.play.y",			"215"			},
+  { "game.button.undo.x",			"-1"			},
+  { "game.button.undo.y",			"-1"			},
+  { "game.button.redo.x",			"-1"			},
+  { "game.button.redo.y",			"-1"			},
+  { "game.button.save.x",			"-1"			},
+  { "game.button.save.y",			"-1"			},
+  { "game.button.pause2.x",			"-1"			},
+  { "game.button.pause2.y",			"-1"			},
+  { "game.button.load.x",			"-1"			},
+  { "game.button.load.y",			"-1"			},
   { "game.button.sound_music.x",		"5"			},
   { "game.button.sound_music.y",		"245"			},
   { "game.button.sound_loops.x",		"35"			},
@@ -6396,10 +7535,318 @@ struct ConfigInfo image_config[] =
   { "game.button.sound_simple.x",		"65"			},
   { "game.button.sound_simple.y",		"245"			},
 
+  { "tape.button.eject.x",			"5"			},
+  { "tape.button.eject.y",			"77"			},
+  { "tape.button.stop.x",			"23"			},
+  { "tape.button.stop.y",			"77"			},
+  { "tape.button.pause.x",			"41"			},
+  { "tape.button.pause.y",			"77"			},
+  { "tape.button.record.x",			"59"			},
+  { "tape.button.record.y",			"77"			},
+  { "tape.button.play.x",			"77"			},
+  { "tape.button.play.y",			"77"			},
+
+  { "tape.symbol.eject.x",			"-1"			},
+  { "tape.symbol.eject.y",			"-1"			},
+  { "tape.symbol.stop.x",			"-1"			},
+  { "tape.symbol.stop.y",			"-1"			},
+  { "tape.symbol.pause.x",			"40"			},
+  { "tape.symbol.pause.y",			"41"			},
+  { "tape.symbol.record.x",			"25"			},
+  { "tape.symbol.record.y",			"41"			},
+  { "tape.symbol.play.x",			"57"			},
+  { "tape.symbol.play.y",			"41"			},
+  { "tape.symbol.fast_forward.x",		"39"			},
+  { "tape.symbol.fast_forward.y",		"42"			},
+  { "tape.symbol.warp_forward.x",		"39"			},
+  { "tape.symbol.warp_forward.y",		"42"			},
+  { "tape.symbol.warp_forward_blind.x",		"39"			},
+  { "tape.symbol.warp_forward_blind.y",		"42"			},
+  { "tape.symbol.pause_before_end.x",		"-1"			},
+  { "tape.symbol.pause_before_end.y",		"-1"			},
+  { "tape.symbol.single_step.x",		"-1"			},
+  { "tape.symbol.single_step.y",		"-1"			},
+
+  { "tape.label.eject.x",			"-1"			},
+  { "tape.label.eject.y",			"-1"			},
+  { "tape.label.stop.x",			"-1"			},
+  { "tape.label.stop.y",			"-1"			},
+  { "tape.label.pause.x",			"5"			},
+  { "tape.label.pause.y",			"61"			},
+  { "tape.label.record.x",			"5"			},
+  { "tape.label.record.y",			"41"			},
+  { "tape.label.play.x",			"70"			},
+  { "tape.label.play.y",			"41"			},
+  { "tape.label.fast_forward.x",		"5"			},
+  { "tape.label.fast_forward.y",		"42"			},
+  { "tape.label.warp_forward.x",		"5"			},
+  { "tape.label.warp_forward.y",		"42"			},
+  { "tape.label.warp_forward_blind.x",		"5"			},
+  { "tape.label.warp_forward_blind.y",		"42"			},
+  { "tape.label.pause_before_end.x",		"5"			},
+  { "tape.label.pause_before_end.y",		"42"			},
+  { "tape.label.single_step.x",			"57"			},
+  { "tape.label.single_step.y",			"42"			},
+
+  { "tape.label.date.x",			"5"			},
+  { "tape.label.date.y",			"5"			},
+  { "tape.label.time.x",			"46"			},
+  { "tape.label.time.y",			"55"			},
+
+  { "tape.text.date.x",				"7"			},
+  { "tape.text.date.y",				"19"			},
+  { "tape.text.date.align",			"left"			},
+  { "tape.text.date.valign",			"top"			},
+  { "tape.text.date.digits",			"-1"			},
+  { "tape.text.date.xoffset",			"27"			},
+  { "tape.text.date.2nd_xoffset",		"64"			},
+  { "tape.text.date.font",			"font.tape_recorder"	},
+  { "tape.text.date.draw_masked",		"false"			},
+
+  { "tape.text.date_yyyy.x",			"-1"			},
+  { "tape.text.date_yyyy.y",			"-1"			},
+  { "tape.text.date_yyyy.align",		"left"			},
+  { "tape.text.date_yyyy.valign",		"top"			},
+  { "tape.text.date_yyyy.digits",		"4"			},
+  { "tape.text.date_yyyy.font",			"font.tape_recorder"	},
+  { "tape.text.date_yyyy.draw_masked",		"false"			},
+  { "tape.text.date_yy.x",			"-1"			},
+  { "tape.text.date_yy.y",			"-1"			},
+  { "tape.text.date_yy.align",			"left"			},
+  { "tape.text.date_yy.valign",			"top"			},
+  { "tape.text.date_yy.digits",			"2"			},
+  { "tape.text.date_yy.font",			"font.tape_recorder"	},
+  { "tape.text.date_yy.draw_masked",		"false"			},
+  { "tape.text.date_mon.x",			"-1"			},
+  { "tape.text.date_mon.y",			"-1"			},
+  { "tape.text.date_mon.align",			"left"			},
+  { "tape.text.date_mon.valign",		"top"			},
+  { "tape.text.date_mon.chars",			"3"			},
+  { "tape.text.date_mon.font",			"font.tape_recorder"	},
+  { "tape.text.date_mon.draw_masked",		"false"			},
+  { "tape.text.date_mm.x",			"-1"			},
+  { "tape.text.date_mm.y",			"-1"			},
+  { "tape.text.date_mm.align",			"left"			},
+  { "tape.text.date_mm.valign",			"top"			},
+  { "tape.text.date_mm.digits",			"2"			},
+  { "tape.text.date_mm.font",			"font.tape_recorder"	},
+  { "tape.text.date_mm.draw_masked",		"false"			},
+  { "tape.text.date_dd.x",			"-1"			},
+  { "tape.text.date_dd.y",			"-1"			},
+  { "tape.text.date_dd.align",			"left"			},
+  { "tape.text.date_dd.valign",			"top"			},
+  { "tape.text.date_dd.digits",			"2"			},
+  { "tape.text.date_dd.font",			"font.tape_recorder"	},
+  { "tape.text.date_dd.draw_masked",		"false"			},
+
+  { "tape.text.time.x",				"44"			},
+  { "tape.text.time.y",				"55"			},
+  { "tape.text.time.align",			"left"			},
+  { "tape.text.time.valign",			"top"			},
+  { "tape.text.time.digits",			"-1"			},
+  { "tape.text.time.xoffset",			"27"			},
+  { "tape.text.time.font",			"font.tape_recorder"	},
+  { "tape.text.time.draw_masked",		"false"			},
+
+  { "tape.text.time_hh.x",			"-1"			},
+  { "tape.text.time_hh.y",			"-1"			},
+  { "tape.text.time_hh.align",			"left"			},
+  { "tape.text.time_hh.valign",			"top"			},
+  { "tape.text.time_hh.digits",			"2"			},
+  { "tape.text.time_hh.font",			"font.tape_recorder"	},
+  { "tape.text.time_hh.draw_masked",		"false"			},
+  { "tape.text.time_mm.x",			"-1"			},
+  { "tape.text.time_mm.y",			"-1"			},
+  { "tape.text.time_mm.align",			"left"			},
+  { "tape.text.time_mm.valign",			"top"			},
+  { "tape.text.time_mm.digits",			"2"			},
+  { "tape.text.time_mm.font",			"font.tape_recorder"	},
+  { "tape.text.time_mm.draw_masked",		"false"			},
+  { "tape.text.time_ss.x",			"-1"			},
+  { "tape.text.time_ss.y",			"-1"			},
+  { "tape.text.time_ss.align",			"left"			},
+  { "tape.text.time_ss.valign",			"top"			},
+  { "tape.text.time_ss.digits",			"2"			},
+  { "tape.text.time_ss.font",			"font.tape_recorder"	},
+  { "tape.text.time_ss.draw_masked",		"false"			},
+
+  { "tape.text.frame.x",			"-1"			},
+  { "tape.text.frame.y",			"-1"			},
+  { "tape.text.frame.align",			"left"			},
+  { "tape.text.frame.valign",			"top"			},
+  { "tape.text.frame.digits",			"-1"			},
+  { "tape.text.frame.font",			"font.tape_recorder"	},
+  { "tape.text.frame.draw_masked",		"false"			},
+
+  { "tape.show_game_buttons",			"false"			},
+
+  { "editor.button.prev_level.x",		"5"			},
+  { "editor.button.prev_level.y",		"5"			},
+  { "editor.button.next_level.x",		"79"			},
+  { "editor.button.next_level.y",		"5"			},
+
+  { "editor.button.properties.x",		"5"			},
+  { "editor.button.properties.y",		"230"			},
+
+  { "editor.button.element_left.x",		"-1"			},
+  { "editor.button.element_left.y",		"-1"			},
+  { "editor.button.element_left.tile_size",	"-1"			},
+  { "editor.button.element_middle.x",		"-1"			},
+  { "editor.button.element_middle.y",		"-1"			},
+  { "editor.button.element_middle.tile_size",	"-1"			},
+  { "editor.button.element_right.x",		"-1"			},
+  { "editor.button.element_right.y",		"-1"			},
+  { "editor.button.element_right.tile_size",	"-1"			},
+
+  { "editor.button.palette.x",			"-1"			},
+  { "editor.button.palette.y",			"-1"			},
+
+  { "editor.button.draw_single.x",		"6"			},
+  { "editor.button.draw_single.y",		"6"			},
+  { "editor.button.draw_connected.x",		"28"			},
+  { "editor.button.draw_connected.y",		"6"			},
+  { "editor.button.draw_line.x",		"50"			},
+  { "editor.button.draw_line.y",		"6"			},
+  { "editor.button.draw_arc.x",			"72"			},
+  { "editor.button.draw_arc.y",			"6"			},
+  { "editor.button.draw_rectangle.x",		"6"			},
+  { "editor.button.draw_rectangle.y",		"28"			},
+  { "editor.button.draw_filled_box.x",		"28"			},
+  { "editor.button.draw_filled_box.y",		"28"			},
+  { "editor.button.rotate_up.x",		"50"			},
+  { "editor.button.rotate_up.y",		"28"			},
+  { "editor.button.draw_text.x",		"72"			},
+  { "editor.button.draw_text.y",		"28"			},
+  { "editor.button.flood_fill.x",		"6"			},
+  { "editor.button.flood_fill.y",		"50"			},
+  { "editor.button.rotate_left.x",		"28"			},
+  { "editor.button.rotate_left.y",		"50"			},
+  { "editor.button.zoom_level.x",		"50"			},
+  { "editor.button.zoom_level.y",		"50"			},
+  { "editor.button.rotate_right.x",		"72"			},
+  { "editor.button.rotate_right.y",		"50"			},
+  { "editor.button.draw_random.x",		"6"			},
+  { "editor.button.draw_random.y",		"72"			},
+  { "editor.button.grab_brush.x",		"28"			},
+  { "editor.button.grab_brush.y",		"72"			},
+  { "editor.button.rotate_down.x",		"50"			},
+  { "editor.button.rotate_down.y",		"72"			},
+  { "editor.button.pick_element.x",		"72"			},
+  { "editor.button.pick_element.y",		"72"			},
+
+  { "editor.button.ce_copy_from.x",		"28"			},
+  { "editor.button.ce_copy_from.y",		"6"			},
+  { "editor.button.ce_copy_to.x",		"50"			},
+  { "editor.button.ce_copy_to.y",		"6"			},
+  { "editor.button.ce_swap.x",			"72"			},
+  { "editor.button.ce_swap.y",			"6"			},
+  { "editor.button.ce_copy.x",			"6"			},
+  { "editor.button.ce_copy.y",			"72"			},
+  { "editor.button.ce_paste.x",			"28"			},
+  { "editor.button.ce_paste.y",			"72"			},
+
+  { "editor.button.undo.x",			"5"			},
+  { "editor.button.undo.y",			"99"			},
+  { "editor.button.conf.x",			"35"			},
+  { "editor.button.conf.y",			"99"			},
+  { "editor.button.save.x",			"65"			},
+  { "editor.button.save.y",			"99"			},
+  { "editor.button.clear.x",			"5"			},
+  { "editor.button.clear.y",			"119"			},
+  { "editor.button.test.x",			"35"			},
+  { "editor.button.test.y",			"119"			},
+  { "editor.button.exit.x",			"65"			},
+  { "editor.button.exit.y",			"119"			},
+
+  { "editor.input.level_number.x",		"29"			},
+  { "editor.input.level_number.y",		"5"			},
+
+  { "editor.palette.x",				"5"			},
+  { "editor.palette.y",				"30"			},
+  { "editor.palette.cols",			"4"			},
+  { "editor.palette.rows",			"10"			},
+  { "editor.palette.tile_size",			"16"			},
+  { "editor.palette.show_as_separate_screen",	"false"			},
+  { "editor.palette.show_on_element_buttons",	"false"			},
+
+  { "editor.palette.element_left.x",		"6"			},
+  { "editor.palette.element_left.y",		"258"			},
+  { "editor.palette.element_left.tile_size",	"16"			},
+  { "editor.palette.element_middle.x",		"42"			},
+  { "editor.palette.element_middle.y",		"258"			},
+  { "editor.palette.element_middle.tile_size",	"16"			},
+  { "editor.palette.element_right.x",		"78"			},
+  { "editor.palette.element_right.y",		"258"			},
+  { "editor.palette.element_right.tile_size",	"16"			},
+
+  { "editor.drawingarea.tile_size",		"16"			},
+
+  { "editor.settings.headline.x",		"272"			},
+  { "editor.settings.headline.y",		"16"			},
+  { "editor.settings.headline.align",		"center"		},
+  { "editor.settings.element_graphic.x",	"24"			},
+  { "editor.settings.element_graphic.y",	"64"			},
+  { "editor.settings.element_name.x",		"-1"			},
+  { "editor.settings.element_name.y",		"-1"			},
+  { "editor.settings.tabs.x",			"24"			},
+  { "editor.settings.tabs.y",			"64"			},
+  { "editor.settings.tabs.2nd_yoffset",		"64"			},
+  { "editor.settings.tabs.draw_xoffset",	"0"			},
+  { "editor.settings.tabs.draw_yoffset",	"8"			},
+
+  { "editor.gadget.normal_spacing",		"4"			},
+  { "editor.gadget.small_spacing",		"2"			},
+  { "editor.gadget.tiny_spacing",		"1"			},
+  { "editor.gadget.line_spacing",		"4"			},
+  { "editor.gadget.text_spacing",		"4"			},
+  { "editor.gadget.separator_line.height",	"2"			},
+
+  { "request.button.yes.x",			"2"			},
+  { "request.button.yes.y",			"250"			},
+  { "request.button.no.x",			"52"			},
+  { "request.button.no.y",			"250"			},
+  { "request.button.confirm.x",			"2"			},
+  { "request.button.confirm.y",			"250"			},
+  { "request.button.player_1.x",		"20"			},
+  { "request.button.player_1.y",		"200"			},
+  { "request.button.player_1.draw_player",	"true"			},
+  { "request.button.player_1.tile_size",	"16"			},
+  { "request.button.player_2.x",		"50"			},
+  { "request.button.player_2.y",		"200"			},
+  { "request.button.player_2.draw_player",	"true"			},
+  { "request.button.player_2.tile_size",	"16"			},
+  { "request.button.player_3.x",		"20"			},
+  { "request.button.player_3.y",		"230"			},
+  { "request.button.player_3.draw_player",	"true"			},
+  { "request.button.player_3.tile_size",	"16"			},
+  { "request.button.player_4.x",		"50"			},
+  { "request.button.player_4.y",		"230"			},
+  { "request.button.player_4.draw_player",	"true"			},
+  { "request.button.player_4.tile_size",	"16"			},
+
+  { "request.x",				"-1"			},
+  { "request.y",				"-1"			},
+  { "request.width",				"120"			},
+  { "request.height",				"300"			},
+  { "request.border_size",			"10"			},
+  { "request.line_spacing",			"2"			},
+  { "request.step_offset",			"10"			},
+  { "request.step_delay",			"20"			},
+  { "request.anim_mode",			"default"		},
+  { "request.align",				"center"		},
+  { "request.valign",				"middle"		},
+  { "request.autowrap",				"false"			},
+  { "request.centered",				"true"			},
+  { "request.wrap_single_words",		"true"			},
+
+  { "global.use_envelope_request",		"false"			},
+
+  { "game.graphics_engine_version",		"-1"			},
   { "game.forced_scroll_delay_value",		"-1"			},
   { "game.use_native_emc_graphics_engine",	"false"			},
   { "game.use_native_sp_graphics_engine",	"true"			},
   { "game.use_masked_pushing",			"false"			},
+  { "game.tile_size",				"32"			},
 
   { "[player].boring_delay_fixed",		"1000"			},
   { "[player].boring_delay_random",		"1000"			},
@@ -6408,6 +7855,9 @@ struct ConfigInfo image_config[] =
 
   { "viewport.window.width",			"672"			},
   { "viewport.window.height",			"560"			},
+  { "viewport.window.TITLE.width",		ARG_DEFAULT		},
+  { "viewport.window.TITLE.height",		ARG_DEFAULT		},
+
   { "viewport.playfield.x",			"6"			},
   { "viewport.playfield.y",			"6"			},
   { "viewport.playfield.width",			"548"			},
@@ -6418,32 +7868,73 @@ struct ConfigInfo image_config[] =
   { "viewport.playfield.MAIN.width",		ARG_DEFAULT		},
   { "viewport.playfield.MAIN.height",		ARG_DEFAULT		},
   { "viewport.playfield.MAIN.border_size",	ARG_DEFAULT		},
-  { "viewport.playfield.PLAYING.x",		ARG_DEFAULT		},
-  { "viewport.playfield.PLAYING.y",		ARG_DEFAULT		},
-  { "viewport.playfield.PLAYING.width",		ARG_DEFAULT		},
-  { "viewport.playfield.PLAYING.height",	ARG_DEFAULT		},
-  { "viewport.playfield.PLAYING.border_size",	ARG_DEFAULT		},
+  { "viewport.playfield.SCORES.x",		ARG_DEFAULT		},
+  { "viewport.playfield.SCORES.y",		ARG_DEFAULT		},
+  { "viewport.playfield.SCORES.width",		ARG_DEFAULT		},
+  { "viewport.playfield.SCORES.height",		ARG_DEFAULT		},
+  { "viewport.playfield.SCORES.border_size",	ARG_DEFAULT		},
   { "viewport.playfield.EDITOR.x",		ARG_DEFAULT		},
   { "viewport.playfield.EDITOR.y",		ARG_DEFAULT		},
   { "viewport.playfield.EDITOR.width",		ARG_DEFAULT		},
   { "viewport.playfield.EDITOR.height",		ARG_DEFAULT		},
   { "viewport.playfield.EDITOR.border_size",	ARG_DEFAULT		},
+  { "viewport.playfield.PLAYING.x",		ARG_DEFAULT		},
+  { "viewport.playfield.PLAYING.y",		ARG_DEFAULT		},
+  { "viewport.playfield.PLAYING.width",		ARG_DEFAULT		},
+  { "viewport.playfield.PLAYING.height",	ARG_DEFAULT		},
+  { "viewport.playfield.PLAYING.border_size",	ARG_DEFAULT		},
+
   { "viewport.door_1.x",			"566"			},
   { "viewport.door_1.y",			"60"			},
+  { "viewport.door_1.width",			"100"			},
+  { "viewport.door_1.height",			"280"			},
+  { "viewport.door_1.border_size",		"4"			},
   { "viewport.door_1.MAIN.x",			ARG_DEFAULT		},
   { "viewport.door_1.MAIN.y",			ARG_DEFAULT		},
-  { "viewport.door_1.PLAYING.x",		ARG_DEFAULT		},
-  { "viewport.door_1.PLAYING.y",		ARG_DEFAULT		},
+  { "viewport.door_1.MAIN.width",		ARG_DEFAULT		},
+  { "viewport.door_1.MAIN.height",		ARG_DEFAULT		},
+  { "viewport.door_1.MAIN.border_size",		ARG_DEFAULT		},
+  { "viewport.door_1.SCORES.x",			ARG_DEFAULT		},
+  { "viewport.door_1.SCORES.y",			ARG_DEFAULT		},
+  { "viewport.door_1.SCORES.width",		ARG_DEFAULT		},
+  { "viewport.door_1.SCORES.height",		ARG_DEFAULT		},
+  { "viewport.door_1.SCORES.border_size",	ARG_DEFAULT		},
   { "viewport.door_1.EDITOR.x",			ARG_DEFAULT		},
   { "viewport.door_1.EDITOR.y",			ARG_DEFAULT		},
+  { "viewport.door_1.EDITOR.width",		ARG_DEFAULT		},
+  { "viewport.door_1.EDITOR.height",		ARG_DEFAULT		},
+  { "viewport.door_1.EDITOR.border_size",	ARG_DEFAULT		},
+  { "viewport.door_1.PLAYING.x",		ARG_DEFAULT		},
+  { "viewport.door_1.PLAYING.y",		ARG_DEFAULT		},
+  { "viewport.door_1.PLAYING.width",		ARG_DEFAULT		},
+  { "viewport.door_1.PLAYING.height",		ARG_DEFAULT		},
+  { "viewport.door_1.PLAYING.border_size",	ARG_DEFAULT		},
+
   { "viewport.door_2.x",			"566"			},
   { "viewport.door_2.y",			"400"			},
+  { "viewport.door_2.width",			"100"			},
+  { "viewport.door_2.height",			"100"			},
+  { "viewport.door_2.border_size",		"4"			},
   { "viewport.door_2.MAIN.x",			ARG_DEFAULT		},
   { "viewport.door_2.MAIN.y",			ARG_DEFAULT		},
-  { "viewport.door_2.PLAYING.x",		ARG_DEFAULT		},
-  { "viewport.door_2.PLAYING.y",		ARG_DEFAULT		},
+  { "viewport.door_2.MAIN.width",		ARG_DEFAULT		},
+  { "viewport.door_2.MAIN.height",		ARG_DEFAULT		},
+  { "viewport.door_2.MAIN.border_size",		ARG_DEFAULT		},
+  { "viewport.door_2.SCORES.x",			ARG_DEFAULT		},
+  { "viewport.door_2.SCORES.y",			ARG_DEFAULT		},
+  { "viewport.door_2.SCORES.width",		ARG_DEFAULT		},
+  { "viewport.door_2.SCORES.height",		ARG_DEFAULT		},
+  { "viewport.door_2.SCORES.border_size",	ARG_DEFAULT		},
   { "viewport.door_2.EDITOR.x",			"566"			},
   { "viewport.door_2.EDITOR.y",			"356"			},
+  { "viewport.door_2.EDITOR.width",		"100"			},
+  { "viewport.door_2.EDITOR.height",		"144"			},
+  { "viewport.door_2.EDITOR.border_size",	"4"			},
+  { "viewport.door_2.PLAYING.x",		ARG_DEFAULT		},
+  { "viewport.door_2.PLAYING.y",		ARG_DEFAULT		},
+  { "viewport.door_2.PLAYING.width",		ARG_DEFAULT		},
+  { "viewport.door_2.PLAYING.height",		ARG_DEFAULT		},
+  { "viewport.door_2.PLAYING.border_size",	ARG_DEFAULT		},
 
   { NULL,					NULL			}
 };
diff --git a/src/conf_gfx.h b/src/conf_gfx.h
index a8557b0..a69bc9b 100644
--- a/src/conf_gfx.h
+++ b/src/conf_gfx.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_gfx.h                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                  Holger Schemel
+//                  info at artsoft.org
+//                  http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_gfx.h
+// ============================================================================
 
 /* ----- this file was automatically generated -- do not edit by hand ----- */
 
@@ -1660,165 +1658,324 @@
 #define IMG_TOON_18					1639
 #define IMG_TOON_19					1640
 #define IMG_TOON_20					1641
-#define IMG_MENU_CALIBRATE_RED				1642
-#define IMG_MENU_CALIBRATE_BLUE				1643
-#define IMG_MENU_CALIBRATE_YELLOW			1644
-#define IMG_MENU_BUTTON					1645
-#define IMG_MENU_BUTTON_ACTIVE				1646
-#define IMG_MENU_BUTTON_LEFT				1647
-#define IMG_MENU_BUTTON_LEFT_ACTIVE			1648
-#define IMG_MENU_BUTTON_RIGHT				1649
-#define IMG_MENU_BUTTON_RIGHT_ACTIVE			1650
-#define IMG_MENU_BUTTON_UP				1651
-#define IMG_MENU_BUTTON_UP_ACTIVE			1652
-#define IMG_MENU_BUTTON_DOWN				1653
-#define IMG_MENU_BUTTON_DOWN_ACTIVE			1654
-#define IMG_MENU_BUTTON_ENTER_MENU			1655
-#define IMG_MENU_BUTTON_ENTER_MENU_ACTIVE		1656
-#define IMG_MENU_BUTTON_LEAVE_MENU			1657
-#define IMG_MENU_BUTTON_LEAVE_MENU_ACTIVE		1658
-#define IMG_MENU_BUTTON_NEXT_LEVEL			1659
-#define IMG_MENU_BUTTON_NEXT_LEVEL_ACTIVE		1660
-#define IMG_MENU_BUTTON_PREV_LEVEL			1661
-#define IMG_MENU_BUTTON_PREV_LEVEL_ACTIVE		1662
-#define IMG_MENU_BUTTON_NAME				1663
-#define IMG_MENU_BUTTON_NAME_ACTIVE			1664
-#define IMG_MENU_BUTTON_LEVELS				1665
-#define IMG_MENU_BUTTON_LEVELS_ACTIVE			1666
-#define IMG_MENU_BUTTON_SCORES				1667
-#define IMG_MENU_BUTTON_SCORES_ACTIVE			1668
-#define IMG_MENU_BUTTON_EDITOR				1669
-#define IMG_MENU_BUTTON_EDITOR_ACTIVE			1670
-#define IMG_MENU_BUTTON_INFO				1671
-#define IMG_MENU_BUTTON_INFO_ACTIVE			1672
-#define IMG_MENU_BUTTON_GAME				1673
-#define IMG_MENU_BUTTON_GAME_ACTIVE			1674
-#define IMG_MENU_BUTTON_SETUP				1675
-#define IMG_MENU_BUTTON_SETUP_ACTIVE			1676
-#define IMG_MENU_BUTTON_QUIT				1677
-#define IMG_MENU_BUTTON_QUIT_ACTIVE			1678
-#define IMG_MENU_SCROLLBAR				1679
-#define IMG_MENU_SCROLLBAR_ACTIVE			1680
-#define IMG_FONT_INITIAL_1				1681
-#define IMG_FONT_INITIAL_2				1682
-#define IMG_FONT_INITIAL_3				1683
-#define IMG_FONT_INITIAL_4				1684
-#define IMG_FONT_TITLE_1				1685
-#define IMG_FONT_TITLE_2				1686
-#define IMG_FONT_TITLE_2_SETUP				1687
-#define IMG_FONT_MENU_1					1688
-#define IMG_FONT_MENU_1_ACTIVE				1689
-#define IMG_FONT_MENU_2					1690
-#define IMG_FONT_MENU_2_ACTIVE				1691
-#define IMG_FONT_TEXT_1					1692
-#define IMG_FONT_TEXT_1_MAIN				1693
-#define IMG_FONT_TEXT_1_LEVELS				1694
-#define IMG_FONT_TEXT_1_SETUP				1695
-#define IMG_FONT_TEXT_1_PREVIEW				1696
-#define IMG_FONT_TEXT_1_SCORES				1697
-#define IMG_FONT_TEXT_1_ACTIVE_SCORES			1698
-#define IMG_FONT_TEXT_1_PANEL				1699
-#define IMG_FONT_TEXT_1_DOOR				1700
-#define IMG_FONT_TEXT_2					1701
-#define IMG_FONT_TEXT_2_MAIN				1702
-#define IMG_FONT_TEXT_2_LEVELS				1703
-#define IMG_FONT_TEXT_2_SETUP				1704
-#define IMG_FONT_TEXT_2_PREVIEW				1705
-#define IMG_FONT_TEXT_2_SCORES				1706
-#define IMG_FONT_TEXT_2_ACTIVE_SCORES			1707
-#define IMG_FONT_TEXT_3					1708
-#define IMG_FONT_TEXT_3_LEVELS				1709
-#define IMG_FONT_TEXT_3_SETUP				1710
-#define IMG_FONT_TEXT_3_PREVIEW				1711
-#define IMG_FONT_TEXT_3_SCORES				1712
-#define IMG_FONT_TEXT_3_ACTIVE_SCORES			1713
-#define IMG_FONT_TEXT_4					1714
-#define IMG_FONT_TEXT_4_MAIN				1715
-#define IMG_FONT_TEXT_4_LEVELS				1716
-#define IMG_FONT_TEXT_4_SETUP				1717
-#define IMG_FONT_TEXT_4_SCORES				1718
-#define IMG_FONT_TEXT_4_ACTIVE_SCORES			1719
-#define IMG_FONT_ENVELOPE_1				1720
-#define IMG_FONT_ENVELOPE_2				1721
-#define IMG_FONT_ENVELOPE_3				1722
-#define IMG_FONT_ENVELOPE_4				1723
-#define IMG_FONT_INPUT_1				1724
-#define IMG_FONT_INPUT_1_MAIN				1725
-#define IMG_FONT_INPUT_1_ACTIVE				1726
-#define IMG_FONT_INPUT_1_ACTIVE_MAIN			1727
-#define IMG_FONT_INPUT_1_ACTIVE_SETUP			1728
-#define IMG_FONT_INPUT_2				1729
-#define IMG_FONT_INPUT_2_ACTIVE				1730
-#define IMG_FONT_OPTION_OFF				1731
-#define IMG_FONT_OPTION_ON				1732
-#define IMG_FONT_VALUE_1				1733
-#define IMG_FONT_VALUE_2				1734
-#define IMG_FONT_VALUE_OLD				1735
-#define IMG_FONT_LEVEL_NUMBER				1736
-#define IMG_FONT_LEVEL_NUMBER_ACTIVE			1737
-#define IMG_FONT_TAPE_RECORDER				1738
-#define IMG_FONT_GAME_INFO				1739
-#define IMG_FONT_INFO_ELEMENTS				1740
-#define IMG_FONT_INFO_LEVELSET				1741
-#define IMG_GLOBAL_BORDER				1742
-#define IMG_GLOBAL_DOOR					1743
-#define IMG_GLOBAL_BUSY					1744
-#define IMG_EDITOR_ELEMENT_BORDER			1745
-#define IMG_EDITOR_ELEMENT_BORDER_INPUT			1746
-#define IMG_EDITOR_CASCADE_LIST				1747
-#define IMG_EDITOR_CASCADE_LIST_ACTIVE			1748
-#define IMG_BACKGROUND					1749
-#define IMG_BACKGROUND_TITLE_INITIAL			1750
-#define IMG_BACKGROUND_TITLE				1751
-#define IMG_BACKGROUND_MAIN				1752
-#define IMG_BACKGROUND_LEVELS				1753
-#define IMG_BACKGROUND_SCORES				1754
-#define IMG_BACKGROUND_EDITOR				1755
-#define IMG_BACKGROUND_INFO				1756
-#define IMG_BACKGROUND_INFO_ELEMENTS			1757
-#define IMG_BACKGROUND_INFO_MUSIC			1758
-#define IMG_BACKGROUND_INFO_CREDITS			1759
-#define IMG_BACKGROUND_INFO_PROGRAM			1760
-#define IMG_BACKGROUND_INFO_VERSION			1761
-#define IMG_BACKGROUND_INFO_LEVELSET			1762
-#define IMG_BACKGROUND_SETUP				1763
-#define IMG_BACKGROUND_PLAYING				1764
-#define IMG_BACKGROUND_DOOR				1765
-#define IMG_BACKGROUND_TITLESCREEN_INITIAL_1		1766
-#define IMG_BACKGROUND_TITLESCREEN_INITIAL_2		1767
-#define IMG_BACKGROUND_TITLESCREEN_INITIAL_3		1768
-#define IMG_BACKGROUND_TITLESCREEN_INITIAL_4		1769
-#define IMG_BACKGROUND_TITLESCREEN_INITIAL_5		1770
-#define IMG_BACKGROUND_TITLESCREEN_1			1771
-#define IMG_BACKGROUND_TITLESCREEN_2			1772
-#define IMG_BACKGROUND_TITLESCREEN_3			1773
-#define IMG_BACKGROUND_TITLESCREEN_4			1774
-#define IMG_BACKGROUND_TITLESCREEN_5			1775
-#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_1		1776
-#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_2		1777
-#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_3		1778
-#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_4		1779
-#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_5		1780
-#define IMG_BACKGROUND_TITLEMESSAGE_1			1781
-#define IMG_BACKGROUND_TITLEMESSAGE_2			1782
-#define IMG_BACKGROUND_TITLEMESSAGE_3			1783
-#define IMG_BACKGROUND_TITLEMESSAGE_4			1784
-#define IMG_BACKGROUND_TITLEMESSAGE_5			1785
-#define IMG_BACKGROUND_ENVELOPE_1			1786
-#define IMG_BACKGROUND_ENVELOPE_2			1787
-#define IMG_BACKGROUND_ENVELOPE_3			1788
-#define IMG_BACKGROUND_ENVELOPE_4			1789
-#define IMG_TITLESCREEN_INITIAL_1			1790
-#define IMG_TITLESCREEN_INITIAL_2			1791
-#define IMG_TITLESCREEN_INITIAL_3			1792
-#define IMG_TITLESCREEN_INITIAL_4			1793
-#define IMG_TITLESCREEN_INITIAL_5			1794
-#define IMG_TITLESCREEN_1				1795
-#define IMG_TITLESCREEN_2				1796
-#define IMG_TITLESCREEN_3				1797
-#define IMG_TITLESCREEN_4				1798
-#define IMG_TITLESCREEN_5				1799
+#define IMG_GFX_GLOBAL_ANIM_1				1642
+#define IMG_GFX_GLOBAL_ANIM_2				1643
+#define IMG_GFX_GLOBAL_ANIM_3				1644
+#define IMG_GFX_GLOBAL_ANIM_4				1645
+#define IMG_GFX_GLOBAL_ANIM_5				1646
+#define IMG_GFX_GLOBAL_ANIM_6				1647
+#define IMG_GFX_GLOBAL_ANIM_7				1648
+#define IMG_GFX_GLOBAL_ANIM_8				1649
+#define IMG_GLOBAL_ANIM_1				1650
+#define IMG_GLOBAL_ANIM_2				1651
+#define IMG_GLOBAL_ANIM_3				1652
+#define IMG_GLOBAL_ANIM_4				1653
+#define IMG_GLOBAL_ANIM_5				1654
+#define IMG_GLOBAL_ANIM_6				1655
+#define IMG_GLOBAL_ANIM_7				1656
+#define IMG_GLOBAL_ANIM_8				1657
+#define IMG_INTERNAL_GLOBAL_TOON_DEFAULT		1658
+#define IMG_INTERNAL_GLOBAL_ANIM_DEFAULT		1659
+#define IMG_MENU_CALIBRATE_RED				1660
+#define IMG_MENU_CALIBRATE_BLUE				1661
+#define IMG_MENU_CALIBRATE_YELLOW			1662
+#define IMG_MENU_BUTTON					1663
+#define IMG_MENU_BUTTON_ACTIVE				1664
+#define IMG_MENU_BUTTON_LEFT				1665
+#define IMG_MENU_BUTTON_LEFT_ACTIVE			1666
+#define IMG_MENU_BUTTON_RIGHT				1667
+#define IMG_MENU_BUTTON_RIGHT_ACTIVE			1668
+#define IMG_MENU_BUTTON_UP				1669
+#define IMG_MENU_BUTTON_UP_ACTIVE			1670
+#define IMG_MENU_BUTTON_DOWN				1671
+#define IMG_MENU_BUTTON_DOWN_ACTIVE			1672
+#define IMG_MENU_BUTTON_ENTER_MENU			1673
+#define IMG_MENU_BUTTON_ENTER_MENU_ACTIVE		1674
+#define IMG_MENU_BUTTON_LEAVE_MENU			1675
+#define IMG_MENU_BUTTON_LEAVE_MENU_ACTIVE		1676
+#define IMG_MENU_BUTTON_NEXT_LEVEL			1677
+#define IMG_MENU_BUTTON_NEXT_LEVEL_ACTIVE		1678
+#define IMG_MENU_BUTTON_PREV_LEVEL			1679
+#define IMG_MENU_BUTTON_PREV_LEVEL_ACTIVE		1680
+#define IMG_MENU_BUTTON_NAME				1681
+#define IMG_MENU_BUTTON_NAME_ACTIVE			1682
+#define IMG_MENU_BUTTON_LEVELS				1683
+#define IMG_MENU_BUTTON_LEVELS_ACTIVE			1684
+#define IMG_MENU_BUTTON_SCORES				1685
+#define IMG_MENU_BUTTON_SCORES_ACTIVE			1686
+#define IMG_MENU_BUTTON_EDITOR				1687
+#define IMG_MENU_BUTTON_EDITOR_ACTIVE			1688
+#define IMG_MENU_BUTTON_INFO				1689
+#define IMG_MENU_BUTTON_INFO_ACTIVE			1690
+#define IMG_MENU_BUTTON_GAME				1691
+#define IMG_MENU_BUTTON_GAME_ACTIVE			1692
+#define IMG_MENU_BUTTON_SETUP				1693
+#define IMG_MENU_BUTTON_SETUP_ACTIVE			1694
+#define IMG_MENU_BUTTON_QUIT				1695
+#define IMG_MENU_BUTTON_QUIT_ACTIVE			1696
+#define IMG_MENU_SCROLLBAR				1697
+#define IMG_MENU_SCROLLBAR_ACTIVE			1698
+#define IMG_GFX_GAME_BUTTON_STOP			1699
+#define IMG_GFX_GAME_BUTTON_PAUSE			1700
+#define IMG_GFX_GAME_BUTTON_PLAY			1701
+#define IMG_GFX_GAME_BUTTON_UNDO			1702
+#define IMG_GFX_GAME_BUTTON_REDO			1703
+#define IMG_GFX_GAME_BUTTON_SAVE			1704
+#define IMG_GFX_GAME_BUTTON_PAUSE2			1705
+#define IMG_GFX_GAME_BUTTON_LOAD			1706
+#define IMG_GFX_GAME_BUTTON_SOUND_MUSIC			1707
+#define IMG_GFX_GAME_BUTTON_SOUND_LOOPS			1708
+#define IMG_GFX_GAME_BUTTON_SOUND_SIMPLE		1709
+#define IMG_GFX_TAPE_BUTTON_EJECT			1710
+#define IMG_GFX_TAPE_BUTTON_EXTRA			1711
+#define IMG_GFX_TAPE_BUTTON_STOP			1712
+#define IMG_GFX_TAPE_BUTTON_PAUSE			1713
+#define IMG_GFX_TAPE_BUTTON_RECORD			1714
+#define IMG_GFX_TAPE_BUTTON_PLAY			1715
+#define IMG_GFX_TAPE_SYMBOL_EJECT			1716
+#define IMG_GFX_TAPE_SYMBOL_STOP			1717
+#define IMG_GFX_TAPE_SYMBOL_PAUSE			1718
+#define IMG_GFX_TAPE_SYMBOL_RECORD			1719
+#define IMG_GFX_TAPE_SYMBOL_PLAY			1720
+#define IMG_GFX_TAPE_SYMBOL_FAST_FORWARD		1721
+#define IMG_GFX_TAPE_SYMBOL_WARP_FORWARD		1722
+#define IMG_GFX_TAPE_SYMBOL_WARP_FORWARD_BLIND		1723
+#define IMG_GFX_TAPE_SYMBOL_PAUSE_BEFORE_END		1724
+#define IMG_GFX_TAPE_SYMBOL_SINGLE_STEP			1725
+#define IMG_GFX_TAPE_LABEL_EJECT			1726
+#define IMG_GFX_TAPE_LABEL_STOP				1727
+#define IMG_GFX_TAPE_LABEL_PAUSE			1728
+#define IMG_GFX_TAPE_LABEL_RECORD			1729
+#define IMG_GFX_TAPE_LABEL_PLAY				1730
+#define IMG_GFX_TAPE_LABEL_FAST_FORWARD			1731
+#define IMG_GFX_TAPE_LABEL_WARP_FORWARD			1732
+#define IMG_GFX_TAPE_LABEL_WARP_FORWARD_BLIND		1733
+#define IMG_GFX_TAPE_LABEL_PAUSE_BEFORE_END		1734
+#define IMG_GFX_TAPE_LABEL_SINGLE_STEP			1735
+#define IMG_GFX_TAPE_LABEL_DATE				1736
+#define IMG_GFX_TAPE_LABEL_TIME				1737
+#define IMG_GFX_REQUEST_BUTTON_YES			1738
+#define IMG_GFX_REQUEST_BUTTON_NO			1739
+#define IMG_GFX_REQUEST_BUTTON_CONFIRM			1740
+#define IMG_GFX_REQUEST_BUTTON_PLAYER_1			1741
+#define IMG_GFX_REQUEST_BUTTON_PLAYER_2			1742
+#define IMG_GFX_REQUEST_BUTTON_PLAYER_3			1743
+#define IMG_GFX_REQUEST_BUTTON_PLAYER_4			1744
+#define IMG_FONT_INITIAL_1				1745
+#define IMG_FONT_INITIAL_2				1746
+#define IMG_FONT_INITIAL_3				1747
+#define IMG_FONT_INITIAL_4				1748
+#define IMG_FONT_TITLE_1				1749
+#define IMG_FONT_TITLE_2				1750
+#define IMG_FONT_TITLE_2_SETUP				1751
+#define IMG_FONT_MENU_1					1752
+#define IMG_FONT_MENU_1_ACTIVE				1753
+#define IMG_FONT_MENU_2					1754
+#define IMG_FONT_MENU_2_ACTIVE				1755
+#define IMG_FONT_TEXT_1					1756
+#define IMG_FONT_TEXT_1_MAIN				1757
+#define IMG_FONT_TEXT_1_LEVELS				1758
+#define IMG_FONT_TEXT_1_LEVELNR				1759
+#define IMG_FONT_TEXT_1_SETUP				1760
+#define IMG_FONT_TEXT_1_PREVIEW				1761
+#define IMG_FONT_TEXT_1_SCORES				1762
+#define IMG_FONT_TEXT_1_ACTIVE_SCORES			1763
+#define IMG_FONT_TEXT_1_PANEL				1764
+#define IMG_FONT_TEXT_1_DOOR				1765
+#define IMG_FONT_TEXT_2					1766
+#define IMG_FONT_TEXT_2_MAIN				1767
+#define IMG_FONT_TEXT_2_LEVELS				1768
+#define IMG_FONT_TEXT_2_LEVELNR				1769
+#define IMG_FONT_TEXT_2_SETUP				1770
+#define IMG_FONT_TEXT_2_PREVIEW				1771
+#define IMG_FONT_TEXT_2_SCORES				1772
+#define IMG_FONT_TEXT_2_ACTIVE_SCORES			1773
+#define IMG_FONT_TEXT_3					1774
+#define IMG_FONT_TEXT_3_LEVELS				1775
+#define IMG_FONT_TEXT_3_LEVELNR				1776
+#define IMG_FONT_TEXT_3_SETUP				1777
+#define IMG_FONT_TEXT_3_PREVIEW				1778
+#define IMG_FONT_TEXT_3_SCORES				1779
+#define IMG_FONT_TEXT_3_ACTIVE_SCORES			1780
+#define IMG_FONT_TEXT_4					1781
+#define IMG_FONT_TEXT_4_MAIN				1782
+#define IMG_FONT_TEXT_4_LEVELS				1783
+#define IMG_FONT_TEXT_4_LEVELNR				1784
+#define IMG_FONT_TEXT_4_SETUP				1785
+#define IMG_FONT_TEXT_4_SCORES				1786
+#define IMG_FONT_TEXT_4_ACTIVE_SCORES			1787
+#define IMG_FONT_ENVELOPE_1				1788
+#define IMG_FONT_ENVELOPE_2				1789
+#define IMG_FONT_ENVELOPE_3				1790
+#define IMG_FONT_ENVELOPE_4				1791
+#define IMG_FONT_REQUEST				1792
+#define IMG_FONT_INPUT_1				1793
+#define IMG_FONT_INPUT_1_MAIN				1794
+#define IMG_FONT_INPUT_1_ACTIVE				1795
+#define IMG_FONT_INPUT_1_ACTIVE_MAIN			1796
+#define IMG_FONT_INPUT_1_ACTIVE_SETUP			1797
+#define IMG_FONT_INPUT_2				1798
+#define IMG_FONT_INPUT_2_ACTIVE				1799
+#define IMG_FONT_OPTION_OFF				1800
+#define IMG_FONT_OPTION_OFF_NARROW			1801
+#define IMG_FONT_OPTION_ON				1802
+#define IMG_FONT_OPTION_ON_NARROW			1803
+#define IMG_FONT_VALUE_1				1804
+#define IMG_FONT_VALUE_2				1805
+#define IMG_FONT_VALUE_OLD				1806
+#define IMG_FONT_VALUE_NARROW				1807
+#define IMG_FONT_LEVEL_NUMBER				1808
+#define IMG_FONT_LEVEL_NUMBER_ACTIVE			1809
+#define IMG_FONT_TAPE_RECORDER				1810
+#define IMG_FONT_GAME_INFO				1811
+#define IMG_FONT_INFO_ELEMENTS				1812
+#define IMG_FONT_INFO_LEVELSET				1813
+#define IMG_EDITOR_ELEMENT_BORDER			1814
+#define IMG_EDITOR_ELEMENT_BORDER_INPUT			1815
+#define IMG_EDITOR_COUNTER_DOWN				1816
+#define IMG_EDITOR_COUNTER_UP				1817
+#define IMG_EDITOR_COUNTER_INPUT			1818
+#define IMG_EDITOR_SELECTBOX_INPUT			1819
+#define IMG_EDITOR_SELECTBOX_BUTTON			1820
+#define IMG_EDITOR_CHECKBOX				1821
+#define IMG_EDITOR_RADIOBUTTON				1822
+#define IMG_EDITOR_STICKYBUTTON				1823
+#define IMG_EDITOR_TABBUTTON				1824
+#define IMG_EDITOR_TEXTBUTTON				1825
+#define IMG_EDITOR_INPUT_TEXT				1826
+#define IMG_EDITOR_INPUT_TEXTAREA			1827
+#define IMG_EDITOR_CASCADE_LIST				1828
+#define IMG_EDITOR_CASCADE_LIST_ACTIVE			1829
+#define IMG_EDITOR_PALETTE_BUTTON			1830
+#define IMG_EDITOR_PALETTE_SCROLL_UP			1831
+#define IMG_EDITOR_PALETTE_SCROLL_DOWN			1832
+#define IMG_EDITOR_PALETTE_SCROLLBAR			1833
+#define IMG_EDITOR_PLAYFIELD_SCROLL_UP			1834
+#define IMG_EDITOR_PLAYFIELD_SCROLL_DOWN		1835
+#define IMG_EDITOR_PLAYFIELD_SCROLL_LEFT		1836
+#define IMG_EDITOR_PLAYFIELD_SCROLL_RIGHT		1837
+#define IMG_EDITOR_PLAYFIELD_SCROLLBAR			1838
+#define IMG_GFX_EDITOR_BUTTON_PREV_LEVEL		1839
+#define IMG_GFX_EDITOR_BUTTON_NEXT_LEVEL		1840
+#define IMG_GFX_EDITOR_BUTTON_PROPERTIES		1841
+#define IMG_GFX_EDITOR_BUTTON_ELEMENT_LEFT		1842
+#define IMG_GFX_EDITOR_BUTTON_ELEMENT_MIDDLE		1843
+#define IMG_GFX_EDITOR_BUTTON_ELEMENT_RIGHT		1844
+#define IMG_GFX_EDITOR_BUTTON_PALETTE			1845
+#define IMG_EDITOR_NO_TOOLBOX_BUTTON			1846
+#define IMG_GFX_EDITOR_BUTTON_DRAW_SINGLE		1847
+#define IMG_GFX_EDITOR_BUTTON_DRAW_CONNECTED		1848
+#define IMG_GFX_EDITOR_BUTTON_DRAW_LINE			1849
+#define IMG_GFX_EDITOR_BUTTON_DRAW_ARC			1850
+#define IMG_GFX_EDITOR_BUTTON_DRAW_RECTANGLE		1851
+#define IMG_GFX_EDITOR_BUTTON_DRAW_FILLED_BOX		1852
+#define IMG_GFX_EDITOR_BUTTON_ROTATE_UP			1853
+#define IMG_GFX_EDITOR_BUTTON_DRAW_TEXT			1854
+#define IMG_GFX_EDITOR_BUTTON_FLOOD_FILL		1855
+#define IMG_GFX_EDITOR_BUTTON_ROTATE_LEFT		1856
+#define IMG_GFX_EDITOR_BUTTON_ZOOM_LEVEL		1857
+#define IMG_GFX_EDITOR_BUTTON_ROTATE_RIGHT		1858
+#define IMG_GFX_EDITOR_BUTTON_DRAW_RANDOM		1859
+#define IMG_GFX_EDITOR_BUTTON_GRAB_BRUSH		1860
+#define IMG_GFX_EDITOR_BUTTON_ROTATE_DOWN		1861
+#define IMG_GFX_EDITOR_BUTTON_PICK_ELEMENT		1862
+#define IMG_GFX_EDITOR_BUTTON_CE_COPY_FROM		1863
+#define IMG_GFX_EDITOR_BUTTON_CE_COPY_TO		1864
+#define IMG_GFX_EDITOR_BUTTON_CE_SWAP			1865
+#define IMG_GFX_EDITOR_BUTTON_CE_COPY			1866
+#define IMG_GFX_EDITOR_BUTTON_CE_PASTE			1867
+#define IMG_GFX_EDITOR_BUTTON_CP_COPY			1868
+#define IMG_GFX_EDITOR_BUTTON_CP_PASTE			1869
+#define IMG_GFX_EDITOR_BUTTON_UNDO			1870
+#define IMG_GFX_EDITOR_BUTTON_CONF			1871
+#define IMG_GFX_EDITOR_BUTTON_SAVE			1872
+#define IMG_GFX_EDITOR_BUTTON_CLEAR			1873
+#define IMG_GFX_EDITOR_BUTTON_TEST			1874
+#define IMG_GFX_EDITOR_BUTTON_EXIT			1875
+#define IMG_GFX_EDITOR_INPUT_LEVEL_NUMBER		1876
+#define IMG_GLOBAL_BORDER				1877
+#define IMG_GLOBAL_BORDER_MAIN				1878
+#define IMG_GLOBAL_BORDER_SCORES			1879
+#define IMG_GLOBAL_BORDER_EDITOR			1880
+#define IMG_GLOBAL_BORDER_PLAYING			1881
+#define IMG_GLOBAL_DOOR					1882
+#define IMG_GLOBAL_BUSY					1883
+#define IMG_BACKGROUND					1884
+#define IMG_BACKGROUND_TITLE_INITIAL			1885
+#define IMG_BACKGROUND_TITLE				1886
+#define IMG_BACKGROUND_MAIN				1887
+#define IMG_BACKGROUND_LEVELS				1888
+#define IMG_BACKGROUND_LEVELNR				1889
+#define IMG_BACKGROUND_SCORES				1890
+#define IMG_BACKGROUND_EDITOR				1891
+#define IMG_BACKGROUND_INFO				1892
+#define IMG_BACKGROUND_INFO_ELEMENTS			1893
+#define IMG_BACKGROUND_INFO_MUSIC			1894
+#define IMG_BACKGROUND_INFO_CREDITS			1895
+#define IMG_BACKGROUND_INFO_PROGRAM			1896
+#define IMG_BACKGROUND_INFO_VERSION			1897
+#define IMG_BACKGROUND_INFO_LEVELSET			1898
+#define IMG_BACKGROUND_SETUP				1899
+#define IMG_BACKGROUND_PLAYING				1900
+#define IMG_BACKGROUND_DOOR				1901
+#define IMG_BACKGROUND_TAPE				1902
+#define IMG_BACKGROUND_PANEL				1903
+#define IMG_BACKGROUND_PALETTE				1904
+#define IMG_BACKGROUND_TOOLBOX				1905
+#define IMG_BACKGROUND_TITLESCREEN_INITIAL_1		1906
+#define IMG_BACKGROUND_TITLESCREEN_INITIAL_2		1907
+#define IMG_BACKGROUND_TITLESCREEN_INITIAL_3		1908
+#define IMG_BACKGROUND_TITLESCREEN_INITIAL_4		1909
+#define IMG_BACKGROUND_TITLESCREEN_INITIAL_5		1910
+#define IMG_BACKGROUND_TITLESCREEN_1			1911
+#define IMG_BACKGROUND_TITLESCREEN_2			1912
+#define IMG_BACKGROUND_TITLESCREEN_3			1913
+#define IMG_BACKGROUND_TITLESCREEN_4			1914
+#define IMG_BACKGROUND_TITLESCREEN_5			1915
+#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_1		1916
+#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_2		1917
+#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_3		1918
+#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_4		1919
+#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_5		1920
+#define IMG_BACKGROUND_TITLEMESSAGE_1			1921
+#define IMG_BACKGROUND_TITLEMESSAGE_2			1922
+#define IMG_BACKGROUND_TITLEMESSAGE_3			1923
+#define IMG_BACKGROUND_TITLEMESSAGE_4			1924
+#define IMG_BACKGROUND_TITLEMESSAGE_5			1925
+#define IMG_BACKGROUND_ENVELOPE_1			1926
+#define IMG_BACKGROUND_ENVELOPE_2			1927
+#define IMG_BACKGROUND_ENVELOPE_3			1928
+#define IMG_BACKGROUND_ENVELOPE_4			1929
+#define IMG_BACKGROUND_REQUEST				1930
+#define IMG_TITLESCREEN_INITIAL_1			1931
+#define IMG_TITLESCREEN_INITIAL_2			1932
+#define IMG_TITLESCREEN_INITIAL_3			1933
+#define IMG_TITLESCREEN_INITIAL_4			1934
+#define IMG_TITLESCREEN_INITIAL_5			1935
+#define IMG_TITLESCREEN_1				1936
+#define IMG_TITLESCREEN_2				1937
+#define IMG_TITLESCREEN_3				1938
+#define IMG_TITLESCREEN_4				1939
+#define IMG_TITLESCREEN_5				1940
+#define IMG_GFX_DOOR_1_PART_1				1941
+#define IMG_GFX_DOOR_1_PART_2				1942
+#define IMG_GFX_DOOR_1_PART_3				1943
+#define IMG_GFX_DOOR_1_PART_4				1944
+#define IMG_GFX_DOOR_1_PART_5				1945
+#define IMG_GFX_DOOR_1_PART_6				1946
+#define IMG_GFX_DOOR_1_PART_7				1947
+#define IMG_GFX_DOOR_1_PART_8				1948
+#define IMG_GFX_DOOR_2_PART_1				1949
+#define IMG_GFX_DOOR_2_PART_2				1950
+#define IMG_GFX_DOOR_2_PART_3				1951
+#define IMG_GFX_DOOR_2_PART_4				1952
+#define IMG_GFX_DOOR_2_PART_5				1953
+#define IMG_GFX_DOOR_2_PART_6				1954
+#define IMG_GFX_DOOR_2_PART_7				1955
+#define IMG_GFX_DOOR_2_PART_8				1956
+#define IMG_DOOR_2_TOP_BORDER_CORRECTION		1957
+#define IMG_LAST_IMAGE_ENTRY_BUG			1958
 
-#define NUM_IMAGE_FILES					1800
+#define NUM_IMAGE_FILES					1959
 
 #endif	/* CONF_GFX_H */
diff --git a/src/conf_grp.c b/src/conf_grp.c
index 7c89bca..aa4d194 100644
--- a/src/conf_grp.c
+++ b/src/conf_grp.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_grp.c                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                  Holger Schemel
+//                  info at artsoft.org
+//                  http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_grp.c
+// ============================================================================
 
 /* ----- this file was automatically generated -- do not edit by hand ----- */
 
@@ -18,259 +16,259 @@
 
 /* values for graphics configuration (group elements) */
 
-  { "group_1",					"RocksCE.pcx"		},
+  { "group_1",					"RocksCE.png"		},
   { "group_1.xpos",				"0"			},
   { "group_1.ypos",				"16"			},
   { "group_1.frames",				"1"			},
-  { "group_1.EDITOR",				"RocksCE.pcx"		},
+  { "group_1.EDITOR",				"RocksCE.png"		},
   { "group_1.EDITOR.xpos",			"16"			},
   { "group_1.EDITOR.ypos",			"16"			},
 
-  { "group_2",					"RocksCE.pcx"		},
+  { "group_2",					"RocksCE.png"		},
   { "group_2.xpos",				"1"			},
   { "group_2.ypos",				"16"			},
   { "group_2.frames",				"1"			},
-  { "group_2.EDITOR",				"RocksCE.pcx"		},
+  { "group_2.EDITOR",				"RocksCE.png"		},
   { "group_2.EDITOR.xpos",			"17"			},
   { "group_2.EDITOR.ypos",			"16"			},
 
-  { "group_3",					"RocksCE.pcx"		},
+  { "group_3",					"RocksCE.png"		},
   { "group_3.xpos",				"2"			},
   { "group_3.ypos",				"16"			},
   { "group_3.frames",				"1"			},
-  { "group_3.EDITOR",				"RocksCE.pcx"		},
+  { "group_3.EDITOR",				"RocksCE.png"		},
   { "group_3.EDITOR.xpos",			"18"			},
   { "group_3.EDITOR.ypos",			"16"			},
 
-  { "group_4",					"RocksCE.pcx"		},
+  { "group_4",					"RocksCE.png"		},
   { "group_4.xpos",				"3"			},
   { "group_4.ypos",				"16"			},
   { "group_4.frames",				"1"			},
-  { "group_4.EDITOR",				"RocksCE.pcx"		},
+  { "group_4.EDITOR",				"RocksCE.png"		},
   { "group_4.EDITOR.xpos",			"19"			},
   { "group_4.EDITOR.ypos",			"16"			},
 
-  { "group_5",					"RocksCE.pcx"		},
+  { "group_5",					"RocksCE.png"		},
   { "group_5.xpos",				"4"			},
   { "group_5.ypos",				"16"			},
   { "group_5.frames",				"1"			},
-  { "group_5.EDITOR",				"RocksCE.pcx"		},
+  { "group_5.EDITOR",				"RocksCE.png"		},
   { "group_5.EDITOR.xpos",			"20"			},
   { "group_5.EDITOR.ypos",			"16"			},
 
-  { "group_6",					"RocksCE.pcx"		},
+  { "group_6",					"RocksCE.png"		},
   { "group_6.xpos",				"5"			},
   { "group_6.ypos",				"16"			},
   { "group_6.frames",				"1"			},
-  { "group_6.EDITOR",				"RocksCE.pcx"		},
+  { "group_6.EDITOR",				"RocksCE.png"		},
   { "group_6.EDITOR.xpos",			"21"			},
   { "group_6.EDITOR.ypos",			"16"			},
 
-  { "group_7",					"RocksCE.pcx"		},
+  { "group_7",					"RocksCE.png"		},
   { "group_7.xpos",				"6"			},
   { "group_7.ypos",				"16"			},
   { "group_7.frames",				"1"			},
-  { "group_7.EDITOR",				"RocksCE.pcx"		},
+  { "group_7.EDITOR",				"RocksCE.png"		},
   { "group_7.EDITOR.xpos",			"22"			},
   { "group_7.EDITOR.ypos",			"16"			},
 
-  { "group_8",					"RocksCE.pcx"		},
+  { "group_8",					"RocksCE.png"		},
   { "group_8.xpos",				"7"			},
   { "group_8.ypos",				"16"			},
   { "group_8.frames",				"1"			},
-  { "group_8.EDITOR",				"RocksCE.pcx"		},
+  { "group_8.EDITOR",				"RocksCE.png"		},
   { "group_8.EDITOR.xpos",			"23"			},
   { "group_8.EDITOR.ypos",			"16"			},
 
-  { "group_9",					"RocksCE.pcx"		},
+  { "group_9",					"RocksCE.png"		},
   { "group_9.xpos",				"8"			},
   { "group_9.ypos",				"16"			},
   { "group_9.frames",				"1"			},
-  { "group_9.EDITOR",				"RocksCE.pcx"		},
+  { "group_9.EDITOR",				"RocksCE.png"		},
   { "group_9.EDITOR.xpos",			"24"			},
   { "group_9.EDITOR.ypos",			"16"			},
 
-  { "group_10",					"RocksCE.pcx"		},
+  { "group_10",					"RocksCE.png"		},
   { "group_10.xpos",				"9"			},
   { "group_10.ypos",				"16"			},
   { "group_10.frames",				"1"			},
-  { "group_10.EDITOR",				"RocksCE.pcx"		},
+  { "group_10.EDITOR",				"RocksCE.png"		},
   { "group_10.EDITOR.xpos",			"25"			},
   { "group_10.EDITOR.ypos",			"16"			},
 
-  { "group_11",					"RocksCE.pcx"		},
+  { "group_11",					"RocksCE.png"		},
   { "group_11.xpos",				"10"			},
   { "group_11.ypos",				"16"			},
   { "group_11.frames",				"1"			},
-  { "group_11.EDITOR",				"RocksCE.pcx"		},
+  { "group_11.EDITOR",				"RocksCE.png"		},
   { "group_11.EDITOR.xpos",			"26"			},
   { "group_11.EDITOR.ypos",			"16"			},
 
-  { "group_12",					"RocksCE.pcx"		},
+  { "group_12",					"RocksCE.png"		},
   { "group_12.xpos",				"11"			},
   { "group_12.ypos",				"16"			},
   { "group_12.frames",				"1"			},
-  { "group_12.EDITOR",				"RocksCE.pcx"		},
+  { "group_12.EDITOR",				"RocksCE.png"		},
   { "group_12.EDITOR.xpos",			"27"			},
   { "group_12.EDITOR.ypos",			"16"			},
 
-  { "group_13",					"RocksCE.pcx"		},
+  { "group_13",					"RocksCE.png"		},
   { "group_13.xpos",				"12"			},
   { "group_13.ypos",				"16"			},
   { "group_13.frames",				"1"			},
-  { "group_13.EDITOR",				"RocksCE.pcx"		},
+  { "group_13.EDITOR",				"RocksCE.png"		},
   { "group_13.EDITOR.xpos",			"28"			},
   { "group_13.EDITOR.ypos",			"16"			},
 
-  { "group_14",					"RocksCE.pcx"		},
+  { "group_14",					"RocksCE.png"		},
   { "group_14.xpos",				"13"			},
   { "group_14.ypos",				"16"			},
   { "group_14.frames",				"1"			},
-  { "group_14.EDITOR",				"RocksCE.pcx"		},
+  { "group_14.EDITOR",				"RocksCE.png"		},
   { "group_14.EDITOR.xpos",			"29"			},
   { "group_14.EDITOR.ypos",			"16"			},
 
-  { "group_15",					"RocksCE.pcx"		},
+  { "group_15",					"RocksCE.png"		},
   { "group_15.xpos",				"14"			},
   { "group_15.ypos",				"16"			},
   { "group_15.frames",				"1"			},
-  { "group_15.EDITOR",				"RocksCE.pcx"		},
+  { "group_15.EDITOR",				"RocksCE.png"		},
   { "group_15.EDITOR.xpos",			"30"			},
   { "group_15.EDITOR.ypos",			"16"			},
 
-  { "group_16",					"RocksCE.pcx"		},
+  { "group_16",					"RocksCE.png"		},
   { "group_16.xpos",				"15"			},
   { "group_16.ypos",				"16"			},
   { "group_16.frames",				"1"			},
-  { "group_16.EDITOR",				"RocksCE.pcx"		},
+  { "group_16.EDITOR",				"RocksCE.png"		},
   { "group_16.EDITOR.xpos",			"31"			},
   { "group_16.EDITOR.ypos",			"16"			},
 
-  { "group_17",					"RocksCE.pcx"		},
+  { "group_17",					"RocksCE.png"		},
   { "group_17.xpos",				"0"			},
   { "group_17.ypos",				"17"			},
   { "group_17.frames",				"1"			},
-  { "group_17.EDITOR",				"RocksCE.pcx"		},
+  { "group_17.EDITOR",				"RocksCE.png"		},
   { "group_17.EDITOR.xpos",			"16"			},
   { "group_17.EDITOR.ypos",			"17"			},
 
-  { "group_18",					"RocksCE.pcx"		},
+  { "group_18",					"RocksCE.png"		},
   { "group_18.xpos",				"1"			},
   { "group_18.ypos",				"17"			},
   { "group_18.frames",				"1"			},
-  { "group_18.EDITOR",				"RocksCE.pcx"		},
+  { "group_18.EDITOR",				"RocksCE.png"		},
   { "group_18.EDITOR.xpos",			"17"			},
   { "group_18.EDITOR.ypos",			"17"			},
 
-  { "group_19",					"RocksCE.pcx"		},
+  { "group_19",					"RocksCE.png"		},
   { "group_19.xpos",				"2"			},
   { "group_19.ypos",				"17"			},
   { "group_19.frames",				"1"			},
-  { "group_19.EDITOR",				"RocksCE.pcx"		},
+  { "group_19.EDITOR",				"RocksCE.png"		},
   { "group_19.EDITOR.xpos",			"18"			},
   { "group_19.EDITOR.ypos",			"17"			},
 
-  { "group_20",					"RocksCE.pcx"		},
+  { "group_20",					"RocksCE.png"		},
   { "group_20.xpos",				"3"			},
   { "group_20.ypos",				"17"			},
   { "group_20.frames",				"1"			},
-  { "group_20.EDITOR",				"RocksCE.pcx"		},
+  { "group_20.EDITOR",				"RocksCE.png"		},
   { "group_20.EDITOR.xpos",			"19"			},
   { "group_20.EDITOR.ypos",			"17"			},
 
-  { "group_21",					"RocksCE.pcx"		},
+  { "group_21",					"RocksCE.png"		},
   { "group_21.xpos",				"4"			},
   { "group_21.ypos",				"17"			},
   { "group_21.frames",				"1"			},
-  { "group_21.EDITOR",				"RocksCE.pcx"		},
+  { "group_21.EDITOR",				"RocksCE.png"		},
   { "group_21.EDITOR.xpos",			"20"			},
   { "group_21.EDITOR.ypos",			"17"			},
 
-  { "group_22",					"RocksCE.pcx"		},
+  { "group_22",					"RocksCE.png"		},
   { "group_22.xpos",				"5"			},
   { "group_22.ypos",				"17"			},
   { "group_22.frames",				"1"			},
-  { "group_22.EDITOR",				"RocksCE.pcx"		},
+  { "group_22.EDITOR",				"RocksCE.png"		},
   { "group_22.EDITOR.xpos",			"21"			},
   { "group_22.EDITOR.ypos",			"17"			},
 
-  { "group_23",					"RocksCE.pcx"		},
+  { "group_23",					"RocksCE.png"		},
   { "group_23.xpos",				"6"			},
   { "group_23.ypos",				"17"			},
   { "group_23.frames",				"1"			},
-  { "group_23.EDITOR",				"RocksCE.pcx"		},
+  { "group_23.EDITOR",				"RocksCE.png"		},
   { "group_23.EDITOR.xpos",			"22"			},
   { "group_23.EDITOR.ypos",			"17"			},
 
-  { "group_24",					"RocksCE.pcx"		},
+  { "group_24",					"RocksCE.png"		},
   { "group_24.xpos",				"7"			},
   { "group_24.ypos",				"17"			},
   { "group_24.frames",				"1"			},
-  { "group_24.EDITOR",				"RocksCE.pcx"		},
+  { "group_24.EDITOR",				"RocksCE.png"		},
   { "group_24.EDITOR.xpos",			"23"			},
   { "group_24.EDITOR.ypos",			"17"			},
 
-  { "group_25",					"RocksCE.pcx"		},
+  { "group_25",					"RocksCE.png"		},
   { "group_25.xpos",				"8"			},
   { "group_25.ypos",				"17"			},
   { "group_25.frames",				"1"			},
-  { "group_25.EDITOR",				"RocksCE.pcx"		},
+  { "group_25.EDITOR",				"RocksCE.png"		},
   { "group_25.EDITOR.xpos",			"24"			},
   { "group_25.EDITOR.ypos",			"17"			},
 
-  { "group_26",					"RocksCE.pcx"		},
+  { "group_26",					"RocksCE.png"		},
   { "group_26.xpos",				"9"			},
   { "group_26.ypos",				"17"			},
   { "group_26.frames",				"1"			},
-  { "group_26.EDITOR",				"RocksCE.pcx"		},
+  { "group_26.EDITOR",				"RocksCE.png"		},
   { "group_26.EDITOR.xpos",			"25"			},
   { "group_26.EDITOR.ypos",			"17"			},
 
-  { "group_27",					"RocksCE.pcx"		},
+  { "group_27",					"RocksCE.png"		},
   { "group_27.xpos",				"10"			},
   { "group_27.ypos",				"17"			},
   { "group_27.frames",				"1"			},
-  { "group_27.EDITOR",				"RocksCE.pcx"		},
+  { "group_27.EDITOR",				"RocksCE.png"		},
   { "group_27.EDITOR.xpos",			"26"			},
   { "group_27.EDITOR.ypos",			"17"			},
 
-  { "group_28",					"RocksCE.pcx"		},
+  { "group_28",					"RocksCE.png"		},
   { "group_28.xpos",				"11"			},
   { "group_28.ypos",				"17"			},
   { "group_28.frames",				"1"			},
-  { "group_28.EDITOR",				"RocksCE.pcx"		},
+  { "group_28.EDITOR",				"RocksCE.png"		},
   { "group_28.EDITOR.xpos",			"27"			},
   { "group_28.EDITOR.ypos",			"17"			},
 
-  { "group_29",					"RocksCE.pcx"		},
+  { "group_29",					"RocksCE.png"		},
   { "group_29.xpos",				"12"			},
   { "group_29.ypos",				"17"			},
   { "group_29.frames",				"1"			},
-  { "group_29.EDITOR",				"RocksCE.pcx"		},
+  { "group_29.EDITOR",				"RocksCE.png"		},
   { "group_29.EDITOR.xpos",			"28"			},
   { "group_29.EDITOR.ypos",			"17"			},
 
-  { "group_30",					"RocksCE.pcx"		},
+  { "group_30",					"RocksCE.png"		},
   { "group_30.xpos",				"13"			},
   { "group_30.ypos",				"17"			},
   { "group_30.frames",				"1"			},
-  { "group_30.EDITOR",				"RocksCE.pcx"		},
+  { "group_30.EDITOR",				"RocksCE.png"		},
   { "group_30.EDITOR.xpos",			"29"			},
   { "group_30.EDITOR.ypos",			"17"			},
 
-  { "group_31",					"RocksCE.pcx"		},
+  { "group_31",					"RocksCE.png"		},
   { "group_31.xpos",				"14"			},
   { "group_31.ypos",				"17"			},
   { "group_31.frames",				"1"			},
-  { "group_31.EDITOR",				"RocksCE.pcx"		},
+  { "group_31.EDITOR",				"RocksCE.png"		},
   { "group_31.EDITOR.xpos",			"30"			},
   { "group_31.EDITOR.ypos",			"17"			},
 
-  { "group_32",					"RocksCE.pcx"		},
+  { "group_32",					"RocksCE.png"		},
   { "group_32.xpos",				"15"			},
   { "group_32.ypos",				"17"			},
   { "group_32.frames",				"1"			},
-  { "group_32.EDITOR",				"RocksCE.pcx"		},
+  { "group_32.EDITOR",				"RocksCE.png"		},
   { "group_32.EDITOR.xpos",			"31"			},
   { "group_32.EDITOR.ypos",			"17"			},
 
diff --git a/src/conf_grp.h b/src/conf_grp.h
index 564b5fb..4c7113f 100644
--- a/src/conf_grp.h
+++ b/src/conf_grp.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_grp.h                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                  Holger Schemel
+//                  info at artsoft.org
+//                  http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_grp.h
+// ============================================================================
 
 /* ----- this file was automatically generated -- do not edit by hand ----- */
 
diff --git a/src/conf_hlp.c b/src/conf_hlp.c
index 0733cb7..c8422e9 100644
--- a/src/conf_hlp.c
+++ b/src/conf_hlp.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_hlp.c                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_hlp.c
+// ============================================================================
 
 #include "libgame/libgame.h"
 #include "main.h"
diff --git a/src/conf_mus.c b/src/conf_mus.c
index 934fd82..5ecd077 100644
--- a/src/conf_mus.c
+++ b/src/conf_mus.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_mus.c                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_mus.c
+// ============================================================================
 
 #include "libgame/libgame.h"
 #include "main.h"
@@ -33,6 +31,7 @@ struct ConfigInfo music_config[] =
   { "background.TITLE",			UNDEFINED_FILENAME		},
   { "background.MAIN",			UNDEFINED_FILENAME		},
   { "background.LEVELS",		UNDEFINED_FILENAME		},
+  { "background.LEVELNR",		UNDEFINED_FILENAME		},
   { "background.SCORES",		UNDEFINED_FILENAME		},
   { "background.EDITOR",		UNDEFINED_FILENAME		},
   { "background.INFO",			"rhythmloop.wav"		},
diff --git a/src/conf_mus.h b/src/conf_mus.h
index 1c3c553..03e8a83 100644
--- a/src/conf_mus.h
+++ b/src/conf_mus.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_mus.h                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                  Holger Schemel
+//                  info at artsoft.org
+//                  http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_mus.h
+// ============================================================================
 
 /* ----- this file was automatically generated -- do not edit by hand ----- */
 
@@ -23,31 +21,32 @@
 #define MUS_BACKGROUND_TITLE				2
 #define MUS_BACKGROUND_MAIN				3
 #define MUS_BACKGROUND_LEVELS				4
-#define MUS_BACKGROUND_SCORES				5
-#define MUS_BACKGROUND_EDITOR				6
-#define MUS_BACKGROUND_INFO				7
-#define MUS_BACKGROUND_SETUP				8
-#define MUS_BACKGROUND_TITLESCREEN_INITIAL_1		9
-#define MUS_BACKGROUND_TITLESCREEN_INITIAL_2		10
-#define MUS_BACKGROUND_TITLESCREEN_INITIAL_3		11
-#define MUS_BACKGROUND_TITLESCREEN_INITIAL_4		12
-#define MUS_BACKGROUND_TITLESCREEN_INITIAL_5		13
-#define MUS_BACKGROUND_TITLESCREEN_1			14
-#define MUS_BACKGROUND_TITLESCREEN_2			15
-#define MUS_BACKGROUND_TITLESCREEN_3			16
-#define MUS_BACKGROUND_TITLESCREEN_4			17
-#define MUS_BACKGROUND_TITLESCREEN_5			18
-#define MUS_BACKGROUND_TITLEMESSAGE_INITIAL_1		19
-#define MUS_BACKGROUND_TITLEMESSAGE_INITIAL_2		20
-#define MUS_BACKGROUND_TITLEMESSAGE_INITIAL_3		21
-#define MUS_BACKGROUND_TITLEMESSAGE_INITIAL_4		22
-#define MUS_BACKGROUND_TITLEMESSAGE_INITIAL_5		23
-#define MUS_BACKGROUND_TITLEMESSAGE_1			24
-#define MUS_BACKGROUND_TITLEMESSAGE_2			25
-#define MUS_BACKGROUND_TITLEMESSAGE_3			26
-#define MUS_BACKGROUND_TITLEMESSAGE_4			27
-#define MUS_BACKGROUND_TITLEMESSAGE_5			28
+#define MUS_BACKGROUND_LEVELNR				5
+#define MUS_BACKGROUND_SCORES				6
+#define MUS_BACKGROUND_EDITOR				7
+#define MUS_BACKGROUND_INFO				8
+#define MUS_BACKGROUND_SETUP				9
+#define MUS_BACKGROUND_TITLESCREEN_INITIAL_1		10
+#define MUS_BACKGROUND_TITLESCREEN_INITIAL_2		11
+#define MUS_BACKGROUND_TITLESCREEN_INITIAL_3		12
+#define MUS_BACKGROUND_TITLESCREEN_INITIAL_4		13
+#define MUS_BACKGROUND_TITLESCREEN_INITIAL_5		14
+#define MUS_BACKGROUND_TITLESCREEN_1			15
+#define MUS_BACKGROUND_TITLESCREEN_2			16
+#define MUS_BACKGROUND_TITLESCREEN_3			17
+#define MUS_BACKGROUND_TITLESCREEN_4			18
+#define MUS_BACKGROUND_TITLESCREEN_5			19
+#define MUS_BACKGROUND_TITLEMESSAGE_INITIAL_1		20
+#define MUS_BACKGROUND_TITLEMESSAGE_INITIAL_2		21
+#define MUS_BACKGROUND_TITLEMESSAGE_INITIAL_3		22
+#define MUS_BACKGROUND_TITLEMESSAGE_INITIAL_4		23
+#define MUS_BACKGROUND_TITLEMESSAGE_INITIAL_5		24
+#define MUS_BACKGROUND_TITLEMESSAGE_1			25
+#define MUS_BACKGROUND_TITLEMESSAGE_2			26
+#define MUS_BACKGROUND_TITLEMESSAGE_3			27
+#define MUS_BACKGROUND_TITLEMESSAGE_4			28
+#define MUS_BACKGROUND_TITLEMESSAGE_5			29
 
-#define NUM_MUSIC_FILES					29
+#define NUM_MUSIC_FILES					30
 
 #endif	/* CONF_MUS_H */
diff --git a/src/conf_snd.c b/src/conf_snd.c
index 763f31d..e2d7a53 100644
--- a/src/conf_snd.c
+++ b/src/conf_snd.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_snd.c                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_snd.c
+// ============================================================================
 
 #include "libgame/libgame.h"
 #include "main.h"
@@ -249,17 +247,24 @@ struct ConfigInfo sound_config[] =
   { "game.sokoban_solving",		"buing.wav"			},
 
   /* sounds for other non-game actions */
-  { "door.opening",			"oeffnen.wav"			},
-  { "door.closing",			"oeffnen.wav"			},
+  { "door.opening",			"door.wav"			},
+  { "door.closing",			"door.wav"			},
+
+  { "request.opening",			UNDEFINED_FILENAME		},
+  { "request.closing",			UNDEFINED_FILENAME		},
 
   /* sounds for menu actions */
   { "menu.item.activating",		"empty.wav"			},
   { "menu.item.selecting",		"base.wav"			},
 
+  { "menu.button.pressing",		UNDEFINED_FILENAME		},
+  { "menu.button.releasing",		UNDEFINED_FILENAME		},
+
   { "background.TITLE_INITIAL",		UNDEFINED_FILENAME		},
   { "background.TITLE",			UNDEFINED_FILENAME		},
   { "background.MAIN",			UNDEFINED_FILENAME		},
   { "background.LEVELS",		UNDEFINED_FILENAME		},
+  { "background.LEVELNR",		UNDEFINED_FILENAME		},
   { "background.SCORES",		"halloffame.wav"		},
   { "background.SCORES.mode_loop",	"false"				},
   { "background.EDITOR",		UNDEFINED_FILENAME		},
@@ -287,28 +292,5 @@ struct ConfigInfo sound_config[] =
   { "background.titlemessage_4",	UNDEFINED_FILENAME		},
   { "background.titlemessage_5",	UNDEFINED_FILENAME		},
 
-#if 0
-  { "[not used]",			"antigrav.wav"			},
-  { "[not used]",			"bong.wav"			},
-  { "[not used]",		 	"fuel.wav"			},
-  { "[not used]",			"holz.wav"			},
-  { "[not used]",			"hui.wav"			},
-  { "[not used]",			"kabumm.wav"			},
-  { "[not used]",			"kink.wav"			},
-  { "[not used]",			"kling.wav"			},
-  { "[not used]",			"krach.wav"			},
-  { "[not used]",			"laser.wav"			},
-  { "[not used]",			"quiek.wav"			},
-  { "[not used]",			"rumms.wav"			},
-  { "[not used]",			"schlopp.wav"			},
-  { "[not used]",			"schrff.wav"			},
-  { "[not used]",			"schwirr.wav"			},
-  { "[not used]",			"slurp.wav"			},
-  { "[not used]",			"sproing.wav"			},
-  { "[not used]",			"warnton.wav"			},
-  { "[not used]",			"whoosh.wav"			},
-  { "[not used]",			"boom.wav"			},
-#endif
-
   { NULL,				NULL				}
 };
diff --git a/src/conf_snd.h b/src/conf_snd.h
index 08fe1a9..632599d 100644
--- a/src/conf_snd.h
+++ b/src/conf_snd.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_snd.h                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                  Holger Schemel
+//                  info at artsoft.org
+//                  http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_snd.h
+// ============================================================================
 
 /* ----- this file was automatically generated -- do not edit by hand ----- */
 
@@ -212,37 +210,42 @@
 #define SND_GAME_SOKOBAN_SOLVING			191
 #define SND_DOOR_OPENING				192
 #define SND_DOOR_CLOSING				193
-#define SND_MENU_ITEM_ACTIVATING			194
-#define SND_MENU_ITEM_SELECTING				195
-#define SND_BACKGROUND_TITLE_INITIAL			196
-#define SND_BACKGROUND_TITLE				197
-#define SND_BACKGROUND_MAIN				198
-#define SND_BACKGROUND_LEVELS				199
-#define SND_BACKGROUND_SCORES				200
-#define SND_BACKGROUND_EDITOR				201
-#define SND_BACKGROUND_INFO				202
-#define SND_BACKGROUND_SETUP				203
-#define SND_BACKGROUND_TITLESCREEN_INITIAL_1		204
-#define SND_BACKGROUND_TITLESCREEN_INITIAL_2		205
-#define SND_BACKGROUND_TITLESCREEN_INITIAL_3		206
-#define SND_BACKGROUND_TITLESCREEN_INITIAL_4		207
-#define SND_BACKGROUND_TITLESCREEN_INITIAL_5		208
-#define SND_BACKGROUND_TITLESCREEN_1			209
-#define SND_BACKGROUND_TITLESCREEN_2			210
-#define SND_BACKGROUND_TITLESCREEN_3			211
-#define SND_BACKGROUND_TITLESCREEN_4			212
-#define SND_BACKGROUND_TITLESCREEN_5			213
-#define SND_BACKGROUND_TITLEMESSAGE_INITIAL_1		214
-#define SND_BACKGROUND_TITLEMESSAGE_INITIAL_2		215
-#define SND_BACKGROUND_TITLEMESSAGE_INITIAL_3		216
-#define SND_BACKGROUND_TITLEMESSAGE_INITIAL_4		217
-#define SND_BACKGROUND_TITLEMESSAGE_INITIAL_5		218
-#define SND_BACKGROUND_TITLEMESSAGE_1			219
-#define SND_BACKGROUND_TITLEMESSAGE_2			220
-#define SND_BACKGROUND_TITLEMESSAGE_3			221
-#define SND_BACKGROUND_TITLEMESSAGE_4			222
-#define SND_BACKGROUND_TITLEMESSAGE_5			223
+#define SND_REQUEST_OPENING				194
+#define SND_REQUEST_CLOSING				195
+#define SND_MENU_ITEM_ACTIVATING			196
+#define SND_MENU_ITEM_SELECTING				197
+#define SND_MENU_BUTTON_PRESSING			198
+#define SND_MENU_BUTTON_RELEASING			199
+#define SND_BACKGROUND_TITLE_INITIAL			200
+#define SND_BACKGROUND_TITLE				201
+#define SND_BACKGROUND_MAIN				202
+#define SND_BACKGROUND_LEVELS				203
+#define SND_BACKGROUND_LEVELNR				204
+#define SND_BACKGROUND_SCORES				205
+#define SND_BACKGROUND_EDITOR				206
+#define SND_BACKGROUND_INFO				207
+#define SND_BACKGROUND_SETUP				208
+#define SND_BACKGROUND_TITLESCREEN_INITIAL_1		209
+#define SND_BACKGROUND_TITLESCREEN_INITIAL_2		210
+#define SND_BACKGROUND_TITLESCREEN_INITIAL_3		211
+#define SND_BACKGROUND_TITLESCREEN_INITIAL_4		212
+#define SND_BACKGROUND_TITLESCREEN_INITIAL_5		213
+#define SND_BACKGROUND_TITLESCREEN_1			214
+#define SND_BACKGROUND_TITLESCREEN_2			215
+#define SND_BACKGROUND_TITLESCREEN_3			216
+#define SND_BACKGROUND_TITLESCREEN_4			217
+#define SND_BACKGROUND_TITLESCREEN_5			218
+#define SND_BACKGROUND_TITLEMESSAGE_INITIAL_1		219
+#define SND_BACKGROUND_TITLEMESSAGE_INITIAL_2		220
+#define SND_BACKGROUND_TITLEMESSAGE_INITIAL_3		221
+#define SND_BACKGROUND_TITLEMESSAGE_INITIAL_4		222
+#define SND_BACKGROUND_TITLEMESSAGE_INITIAL_5		223
+#define SND_BACKGROUND_TITLEMESSAGE_1			224
+#define SND_BACKGROUND_TITLEMESSAGE_2			225
+#define SND_BACKGROUND_TITLEMESSAGE_3			226
+#define SND_BACKGROUND_TITLEMESSAGE_4			227
+#define SND_BACKGROUND_TITLEMESSAGE_5			228
 
-#define NUM_SOUND_FILES					224
+#define NUM_SOUND_FILES					229
 
 #endif	/* CONF_SND_H */
diff --git a/src/conf_var.c b/src/conf_var.c
index e12f001..9d4b354 100644
--- a/src/conf_var.c
+++ b/src/conf_var.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* conf_var.c                                               *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                  Holger Schemel
+//                  info at artsoft.org
+//                  http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// conf_var.c
+// ============================================================================
 
 /* ----- this file was automatically generated -- do not edit by hand ----- */
 
@@ -25,5040 +23,8172 @@ struct TokenIntPtrInfo image_config_vars[] =
     &title_initial_default.fade_mode
   },
   {
+    "[title_initial].fade_mode",
+    &title_initial_first_default.fade_mode
+  },
+  {
     "[title_initial].fade_delay",
     &title_initial_default.fade_delay
   },
   {
+    "[title_initial].fade_delay",
+    &title_initial_first_default.fade_delay
+  },
+  {
     "[title_initial].post_delay",
     &title_initial_default.post_delay
   },
   {
+    "[title_initial].post_delay",
+    &title_initial_first_default.post_delay
+  },
+  {
     "[title_initial].auto_delay",
     &title_initial_default.auto_delay
   },
   {
+    "[title_initial].auto_delay",
+    &title_initial_first_default.auto_delay
+  },
+  {
     "[title].fade_mode",
     &title_default.fade_mode
   },
   {
+    "[title].fade_mode",
+    &title_first_default.fade_mode
+  },
+  {
     "[title].fade_delay",
     &title_default.fade_delay
   },
   {
+    "[title].fade_delay",
+    &title_first_default.fade_delay
+  },
+  {
     "[title].post_delay",
     &title_default.post_delay
   },
   {
+    "[title].post_delay",
+    &title_first_default.post_delay
+  },
+  {
     "[title].auto_delay",
     &title_default.auto_delay
   },
   {
-    "[titlemessage_initial].x",
-    &titlemessage_initial_default.x
+    "[title].auto_delay",
+    &title_first_default.auto_delay
   },
   {
-    "[titlemessage_initial].y",
-    &titlemessage_initial_default.y
+    "[titlescreen_initial].sort_priority",
+    &titlescreen_initial_default.sort_priority
   },
   {
-    "[titlemessage_initial].width",
-    &titlemessage_initial_default.width
+    "[titlescreen_initial].fade_mode",
+    &titlescreen_initial_default.fade_mode
   },
   {
-    "[titlemessage_initial].height",
-    &titlemessage_initial_default.height
+    "[titlescreen_initial].fade_delay",
+    &titlescreen_initial_default.fade_delay
   },
   {
-    "[titlemessage_initial].chars",
-    &titlemessage_initial_default.chars
+    "[titlescreen_initial].post_delay",
+    &titlescreen_initial_default.post_delay
   },
   {
-    "[titlemessage_initial].lines",
-    &titlemessage_initial_default.lines
+    "[titlescreen_initial].auto_delay",
+    &titlescreen_initial_default.auto_delay
   },
   {
-    "[titlemessage_initial].align",
-    &titlemessage_initial_default.align
+    "[titlescreen].sort_priority",
+    &titlescreen_default.sort_priority
   },
   {
-    "[titlemessage_initial].valign",
-    &titlemessage_initial_default.valign
+    "[titlescreen].fade_mode",
+    &titlescreen_default.fade_mode
   },
   {
-    "[titlemessage_initial].font",
-    &titlemessage_initial_default.font
+    "[titlescreen].fade_delay",
+    &titlescreen_default.fade_delay
   },
   {
-    "[titlemessage_initial].autowrap",
-    &titlemessage_initial_default.autowrap
+    "[titlescreen].post_delay",
+    &titlescreen_default.post_delay
   },
   {
-    "[titlemessage_initial].centered",
-    &titlemessage_initial_default.centered
+    "[titlescreen].auto_delay",
+    &titlescreen_default.auto_delay
   },
   {
-    "[titlemessage_initial].parse_comments",
-    &titlemessage_initial_default.parse_comments
+    "titlescreen_initial_1.sort_priority",
+    &titlescreen_initial[0].sort_priority
   },
   {
-    "[titlemessage_initial].sort_priority",
-    &titlemessage_initial_default.sort_priority
+    "titlescreen_initial_1.sort_priority",
+    &titlescreen_initial_first[0].sort_priority
   },
   {
-    "[titlemessage_initial].fade_mode",
-    &titlemessage_initial_default.fade_mode
+    "titlescreen_initial_1.fade_mode",
+    &titlescreen_initial[0].fade_mode
   },
   {
-    "[titlemessage_initial].fade_delay",
-    &titlemessage_initial_default.fade_delay
+    "titlescreen_initial_1.fade_mode",
+    &titlescreen_initial_first[0].fade_mode
   },
   {
-    "[titlemessage_initial].post_delay",
-    &titlemessage_initial_default.post_delay
+    "titlescreen_initial_1.fade_delay",
+    &titlescreen_initial[0].fade_delay
   },
   {
-    "[titlemessage_initial].auto_delay",
-    &titlemessage_initial_default.auto_delay
+    "titlescreen_initial_1.fade_delay",
+    &titlescreen_initial_first[0].fade_delay
   },
   {
-    "[titlemessage].x",
-    &titlemessage_default.x
+    "titlescreen_initial_1.post_delay",
+    &titlescreen_initial[0].post_delay
   },
   {
-    "[titlemessage].y",
-    &titlemessage_default.y
+    "titlescreen_initial_1.post_delay",
+    &titlescreen_initial_first[0].post_delay
   },
   {
-    "[titlemessage].width",
-    &titlemessage_default.width
+    "titlescreen_initial_1.auto_delay",
+    &titlescreen_initial[0].auto_delay
   },
   {
-    "[titlemessage].height",
-    &titlemessage_default.height
+    "titlescreen_initial_1.auto_delay",
+    &titlescreen_initial_first[0].auto_delay
   },
   {
-    "[titlemessage].chars",
-    &titlemessage_default.chars
+    "titlescreen_initial_2.sort_priority",
+    &titlescreen_initial[1].sort_priority
   },
   {
-    "[titlemessage].lines",
-    &titlemessage_default.lines
+    "titlescreen_initial_2.sort_priority",
+    &titlescreen_initial_first[1].sort_priority
   },
   {
-    "[titlemessage].align",
-    &titlemessage_default.align
+    "titlescreen_initial_2.fade_mode",
+    &titlescreen_initial[1].fade_mode
   },
   {
-    "[titlemessage].valign",
-    &titlemessage_default.valign
+    "titlescreen_initial_2.fade_mode",
+    &titlescreen_initial_first[1].fade_mode
   },
   {
-    "[titlemessage].font",
-    &titlemessage_default.font
+    "titlescreen_initial_2.fade_delay",
+    &titlescreen_initial[1].fade_delay
   },
   {
-    "[titlemessage].autowrap",
-    &titlemessage_default.autowrap
+    "titlescreen_initial_2.fade_delay",
+    &titlescreen_initial_first[1].fade_delay
   },
   {
-    "[titlemessage].centered",
-    &titlemessage_default.centered
+    "titlescreen_initial_2.post_delay",
+    &titlescreen_initial[1].post_delay
   },
   {
-    "[titlemessage].parse_comments",
-    &titlemessage_default.parse_comments
+    "titlescreen_initial_2.post_delay",
+    &titlescreen_initial_first[1].post_delay
   },
   {
-    "[titlemessage].sort_priority",
-    &titlemessage_default.sort_priority
+    "titlescreen_initial_2.auto_delay",
+    &titlescreen_initial[1].auto_delay
   },
   {
-    "[titlemessage].fade_mode",
-    &titlemessage_default.fade_mode
+    "titlescreen_initial_2.auto_delay",
+    &titlescreen_initial_first[1].auto_delay
   },
   {
-    "[titlemessage].fade_delay",
-    &titlemessage_default.fade_delay
+    "titlescreen_initial_3.sort_priority",
+    &titlescreen_initial[2].sort_priority
   },
   {
-    "[titlemessage].post_delay",
-    &titlemessage_default.post_delay
+    "titlescreen_initial_3.sort_priority",
+    &titlescreen_initial_first[2].sort_priority
   },
   {
-    "[titlemessage].auto_delay",
-    &titlemessage_default.auto_delay
+    "titlescreen_initial_3.fade_mode",
+    &titlescreen_initial[2].fade_mode
   },
   {
-    "titlemessage_initial_1.x",
-    &titlemessage_initial[0].x
+    "titlescreen_initial_3.fade_mode",
+    &titlescreen_initial_first[2].fade_mode
   },
   {
-    "titlemessage_initial_1.y",
-    &titlemessage_initial[0].y
+    "titlescreen_initial_3.fade_delay",
+    &titlescreen_initial[2].fade_delay
   },
   {
-    "titlemessage_initial_1.width",
-    &titlemessage_initial[0].width
+    "titlescreen_initial_3.fade_delay",
+    &titlescreen_initial_first[2].fade_delay
   },
   {
-    "titlemessage_initial_1.height",
-    &titlemessage_initial[0].height
+    "titlescreen_initial_3.post_delay",
+    &titlescreen_initial[2].post_delay
   },
   {
-    "titlemessage_initial_1.chars",
-    &titlemessage_initial[0].chars
+    "titlescreen_initial_3.post_delay",
+    &titlescreen_initial_first[2].post_delay
   },
   {
-    "titlemessage_initial_1.lines",
-    &titlemessage_initial[0].lines
+    "titlescreen_initial_3.auto_delay",
+    &titlescreen_initial[2].auto_delay
   },
   {
-    "titlemessage_initial_1.align",
-    &titlemessage_initial[0].align
+    "titlescreen_initial_3.auto_delay",
+    &titlescreen_initial_first[2].auto_delay
   },
   {
-    "titlemessage_initial_1.valign",
-    &titlemessage_initial[0].valign
+    "titlescreen_initial_4.sort_priority",
+    &titlescreen_initial[3].sort_priority
   },
   {
-    "titlemessage_initial_1.font",
-    &titlemessage_initial[0].font
+    "titlescreen_initial_4.sort_priority",
+    &titlescreen_initial_first[3].sort_priority
   },
   {
-    "titlemessage_initial_1.autowrap",
-    &titlemessage_initial[0].autowrap
+    "titlescreen_initial_4.fade_mode",
+    &titlescreen_initial[3].fade_mode
   },
   {
-    "titlemessage_initial_1.centered",
-    &titlemessage_initial[0].centered
+    "titlescreen_initial_4.fade_mode",
+    &titlescreen_initial_first[3].fade_mode
   },
   {
-    "titlemessage_initial_1.parse_comments",
-    &titlemessage_initial[0].parse_comments
+    "titlescreen_initial_4.fade_delay",
+    &titlescreen_initial[3].fade_delay
   },
   {
-    "titlemessage_initial_1.sort_priority",
-    &titlemessage_initial[0].sort_priority
+    "titlescreen_initial_4.fade_delay",
+    &titlescreen_initial_first[3].fade_delay
   },
   {
-    "titlemessage_initial_1.fade_mode",
-    &titlemessage_initial[0].fade_mode
+    "titlescreen_initial_4.post_delay",
+    &titlescreen_initial[3].post_delay
   },
   {
-    "titlemessage_initial_1.fade_delay",
-    &titlemessage_initial[0].fade_delay
+    "titlescreen_initial_4.post_delay",
+    &titlescreen_initial_first[3].post_delay
   },
   {
-    "titlemessage_initial_1.post_delay",
-    &titlemessage_initial[0].post_delay
+    "titlescreen_initial_4.auto_delay",
+    &titlescreen_initial[3].auto_delay
   },
   {
-    "titlemessage_initial_1.auto_delay",
-    &titlemessage_initial[0].auto_delay
+    "titlescreen_initial_4.auto_delay",
+    &titlescreen_initial_first[3].auto_delay
   },
   {
-    "titlemessage_initial_2.x",
-    &titlemessage_initial[1].x
+    "titlescreen_initial_5.sort_priority",
+    &titlescreen_initial[4].sort_priority
   },
   {
-    "titlemessage_initial_2.y",
-    &titlemessage_initial[1].y
+    "titlescreen_initial_5.sort_priority",
+    &titlescreen_initial_first[4].sort_priority
   },
   {
-    "titlemessage_initial_2.width",
-    &titlemessage_initial[1].width
+    "titlescreen_initial_5.fade_mode",
+    &titlescreen_initial[4].fade_mode
   },
   {
-    "titlemessage_initial_2.height",
-    &titlemessage_initial[1].height
+    "titlescreen_initial_5.fade_mode",
+    &titlescreen_initial_first[4].fade_mode
   },
   {
-    "titlemessage_initial_2.chars",
-    &titlemessage_initial[1].chars
+    "titlescreen_initial_5.fade_delay",
+    &titlescreen_initial[4].fade_delay
   },
   {
-    "titlemessage_initial_2.lines",
-    &titlemessage_initial[1].lines
+    "titlescreen_initial_5.fade_delay",
+    &titlescreen_initial_first[4].fade_delay
   },
   {
-    "titlemessage_initial_2.align",
-    &titlemessage_initial[1].align
+    "titlescreen_initial_5.post_delay",
+    &titlescreen_initial[4].post_delay
   },
   {
-    "titlemessage_initial_2.valign",
-    &titlemessage_initial[1].valign
+    "titlescreen_initial_5.post_delay",
+    &titlescreen_initial_first[4].post_delay
   },
   {
-    "titlemessage_initial_2.font",
-    &titlemessage_initial[1].font
+    "titlescreen_initial_5.auto_delay",
+    &titlescreen_initial[4].auto_delay
   },
   {
-    "titlemessage_initial_2.autowrap",
-    &titlemessage_initial[1].autowrap
+    "titlescreen_initial_5.auto_delay",
+    &titlescreen_initial_first[4].auto_delay
   },
   {
-    "titlemessage_initial_2.centered",
-    &titlemessage_initial[1].centered
+    "titlescreen_1.sort_priority",
+    &titlescreen[0].sort_priority
   },
   {
-    "titlemessage_initial_2.parse_comments",
-    &titlemessage_initial[1].parse_comments
+    "titlescreen_1.sort_priority",
+    &titlescreen_first[0].sort_priority
   },
   {
-    "titlemessage_initial_2.sort_priority",
-    &titlemessage_initial[1].sort_priority
+    "titlescreen_1.fade_mode",
+    &titlescreen[0].fade_mode
   },
   {
-    "titlemessage_initial_2.fade_mode",
-    &titlemessage_initial[1].fade_mode
+    "titlescreen_1.fade_mode",
+    &titlescreen_first[0].fade_mode
   },
   {
-    "titlemessage_initial_2.fade_delay",
-    &titlemessage_initial[1].fade_delay
+    "titlescreen_1.fade_delay",
+    &titlescreen[0].fade_delay
   },
   {
-    "titlemessage_initial_2.post_delay",
-    &titlemessage_initial[1].post_delay
+    "titlescreen_1.fade_delay",
+    &titlescreen_first[0].fade_delay
   },
   {
-    "titlemessage_initial_2.auto_delay",
-    &titlemessage_initial[1].auto_delay
+    "titlescreen_1.post_delay",
+    &titlescreen[0].post_delay
   },
   {
-    "titlemessage_initial_3.x",
-    &titlemessage_initial[2].x
+    "titlescreen_1.post_delay",
+    &titlescreen_first[0].post_delay
   },
   {
-    "titlemessage_initial_3.y",
-    &titlemessage_initial[2].y
+    "titlescreen_1.auto_delay",
+    &titlescreen[0].auto_delay
   },
   {
-    "titlemessage_initial_3.width",
-    &titlemessage_initial[2].width
+    "titlescreen_1.auto_delay",
+    &titlescreen_first[0].auto_delay
   },
   {
-    "titlemessage_initial_3.height",
-    &titlemessage_initial[2].height
+    "titlescreen_2.sort_priority",
+    &titlescreen[1].sort_priority
   },
   {
-    "titlemessage_initial_3.chars",
-    &titlemessage_initial[2].chars
+    "titlescreen_2.sort_priority",
+    &titlescreen_first[1].sort_priority
   },
   {
-    "titlemessage_initial_3.lines",
-    &titlemessage_initial[2].lines
+    "titlescreen_2.fade_mode",
+    &titlescreen[1].fade_mode
   },
   {
-    "titlemessage_initial_3.align",
-    &titlemessage_initial[2].align
+    "titlescreen_2.fade_mode",
+    &titlescreen_first[1].fade_mode
   },
   {
-    "titlemessage_initial_3.valign",
-    &titlemessage_initial[2].valign
+    "titlescreen_2.fade_delay",
+    &titlescreen[1].fade_delay
   },
   {
-    "titlemessage_initial_3.font",
-    &titlemessage_initial[2].font
+    "titlescreen_2.fade_delay",
+    &titlescreen_first[1].fade_delay
   },
   {
-    "titlemessage_initial_3.autowrap",
-    &titlemessage_initial[2].autowrap
+    "titlescreen_2.post_delay",
+    &titlescreen[1].post_delay
   },
   {
-    "titlemessage_initial_3.centered",
-    &titlemessage_initial[2].centered
+    "titlescreen_2.post_delay",
+    &titlescreen_first[1].post_delay
   },
   {
-    "titlemessage_initial_3.parse_comments",
-    &titlemessage_initial[2].parse_comments
+    "titlescreen_2.auto_delay",
+    &titlescreen[1].auto_delay
   },
   {
-    "titlemessage_initial_3.sort_priority",
-    &titlemessage_initial[2].sort_priority
+    "titlescreen_2.auto_delay",
+    &titlescreen_first[1].auto_delay
   },
   {
-    "titlemessage_initial_3.fade_mode",
-    &titlemessage_initial[2].fade_mode
+    "titlescreen_3.sort_priority",
+    &titlescreen[2].sort_priority
   },
   {
-    "titlemessage_initial_3.fade_delay",
-    &titlemessage_initial[2].fade_delay
+    "titlescreen_3.sort_priority",
+    &titlescreen_first[2].sort_priority
   },
   {
-    "titlemessage_initial_3.post_delay",
-    &titlemessage_initial[2].post_delay
+    "titlescreen_3.fade_mode",
+    &titlescreen[2].fade_mode
   },
   {
-    "titlemessage_initial_3.auto_delay",
-    &titlemessage_initial[2].auto_delay
+    "titlescreen_3.fade_mode",
+    &titlescreen_first[2].fade_mode
   },
   {
-    "titlemessage_initial_4.x",
-    &titlemessage_initial[3].x
+    "titlescreen_3.fade_delay",
+    &titlescreen[2].fade_delay
   },
   {
-    "titlemessage_initial_4.y",
-    &titlemessage_initial[3].y
+    "titlescreen_3.fade_delay",
+    &titlescreen_first[2].fade_delay
   },
   {
-    "titlemessage_initial_4.width",
-    &titlemessage_initial[3].width
+    "titlescreen_3.post_delay",
+    &titlescreen[2].post_delay
   },
   {
-    "titlemessage_initial_4.height",
-    &titlemessage_initial[3].height
+    "titlescreen_3.post_delay",
+    &titlescreen_first[2].post_delay
   },
   {
-    "titlemessage_initial_4.chars",
-    &titlemessage_initial[3].chars
+    "titlescreen_3.auto_delay",
+    &titlescreen[2].auto_delay
   },
   {
-    "titlemessage_initial_4.lines",
-    &titlemessage_initial[3].lines
+    "titlescreen_3.auto_delay",
+    &titlescreen_first[2].auto_delay
   },
   {
-    "titlemessage_initial_4.align",
-    &titlemessage_initial[3].align
+    "titlescreen_4.sort_priority",
+    &titlescreen[3].sort_priority
   },
   {
-    "titlemessage_initial_4.valign",
-    &titlemessage_initial[3].valign
+    "titlescreen_4.sort_priority",
+    &titlescreen_first[3].sort_priority
   },
   {
-    "titlemessage_initial_4.font",
-    &titlemessage_initial[3].font
+    "titlescreen_4.fade_mode",
+    &titlescreen[3].fade_mode
   },
   {
-    "titlemessage_initial_4.autowrap",
-    &titlemessage_initial[3].autowrap
+    "titlescreen_4.fade_mode",
+    &titlescreen_first[3].fade_mode
   },
   {
-    "titlemessage_initial_4.centered",
-    &titlemessage_initial[3].centered
+    "titlescreen_4.fade_delay",
+    &titlescreen[3].fade_delay
   },
   {
-    "titlemessage_initial_4.parse_comments",
-    &titlemessage_initial[3].parse_comments
+    "titlescreen_4.fade_delay",
+    &titlescreen_first[3].fade_delay
   },
   {
-    "titlemessage_initial_4.sort_priority",
-    &titlemessage_initial[3].sort_priority
+    "titlescreen_4.post_delay",
+    &titlescreen[3].post_delay
   },
   {
-    "titlemessage_initial_4.fade_mode",
-    &titlemessage_initial[3].fade_mode
+    "titlescreen_4.post_delay",
+    &titlescreen_first[3].post_delay
   },
   {
-    "titlemessage_initial_4.fade_delay",
-    &titlemessage_initial[3].fade_delay
+    "titlescreen_4.auto_delay",
+    &titlescreen[3].auto_delay
   },
   {
-    "titlemessage_initial_4.post_delay",
-    &titlemessage_initial[3].post_delay
+    "titlescreen_4.auto_delay",
+    &titlescreen_first[3].auto_delay
   },
   {
-    "titlemessage_initial_4.auto_delay",
-    &titlemessage_initial[3].auto_delay
+    "titlescreen_5.sort_priority",
+    &titlescreen[4].sort_priority
   },
   {
-    "titlemessage_initial_5.x",
-    &titlemessage_initial[4].x
+    "titlescreen_5.sort_priority",
+    &titlescreen_first[4].sort_priority
   },
   {
-    "titlemessage_initial_5.y",
-    &titlemessage_initial[4].y
+    "titlescreen_5.fade_mode",
+    &titlescreen[4].fade_mode
   },
   {
-    "titlemessage_initial_5.width",
-    &titlemessage_initial[4].width
+    "titlescreen_5.fade_mode",
+    &titlescreen_first[4].fade_mode
   },
   {
-    "titlemessage_initial_5.height",
-    &titlemessage_initial[4].height
+    "titlescreen_5.fade_delay",
+    &titlescreen[4].fade_delay
   },
   {
-    "titlemessage_initial_5.chars",
-    &titlemessage_initial[4].chars
+    "titlescreen_5.fade_delay",
+    &titlescreen_first[4].fade_delay
   },
   {
-    "titlemessage_initial_5.lines",
-    &titlemessage_initial[4].lines
+    "titlescreen_5.post_delay",
+    &titlescreen[4].post_delay
   },
   {
-    "titlemessage_initial_5.align",
-    &titlemessage_initial[4].align
+    "titlescreen_5.post_delay",
+    &titlescreen_first[4].post_delay
   },
   {
-    "titlemessage_initial_5.valign",
-    &titlemessage_initial[4].valign
+    "titlescreen_5.auto_delay",
+    &titlescreen[4].auto_delay
   },
   {
-    "titlemessage_initial_5.font",
-    &titlemessage_initial[4].font
+    "titlescreen_5.auto_delay",
+    &titlescreen_first[4].auto_delay
   },
   {
-    "titlemessage_initial_5.autowrap",
-    &titlemessage_initial[4].autowrap
+    "[titlemessage_initial].x",
+    &titlemessage_initial_default.x
   },
   {
-    "titlemessage_initial_5.centered",
-    &titlemessage_initial[4].centered
+    "[titlemessage_initial].y",
+    &titlemessage_initial_default.y
   },
   {
-    "titlemessage_initial_5.parse_comments",
-    &titlemessage_initial[4].parse_comments
+    "[titlemessage_initial].width",
+    &titlemessage_initial_default.width
   },
   {
-    "titlemessage_initial_5.sort_priority",
-    &titlemessage_initial[4].sort_priority
+    "[titlemessage_initial].height",
+    &titlemessage_initial_default.height
   },
   {
-    "titlemessage_initial_5.fade_mode",
-    &titlemessage_initial[4].fade_mode
+    "[titlemessage_initial].chars",
+    &titlemessage_initial_default.chars
   },
   {
-    "titlemessage_initial_5.fade_delay",
-    &titlemessage_initial[4].fade_delay
+    "[titlemessage_initial].lines",
+    &titlemessage_initial_default.lines
   },
   {
-    "titlemessage_initial_5.post_delay",
-    &titlemessage_initial[4].post_delay
+    "[titlemessage_initial].align",
+    &titlemessage_initial_default.align
   },
   {
-    "titlemessage_initial_5.auto_delay",
-    &titlemessage_initial[4].auto_delay
+    "[titlemessage_initial].valign",
+    &titlemessage_initial_default.valign
   },
   {
-    "titlemessage_1.x",
-    &titlemessage[0].x
+    "[titlemessage_initial].font",
+    &titlemessage_initial_default.font
   },
   {
-    "titlemessage_1.y",
-    &titlemessage[0].y
+    "[titlemessage_initial].autowrap",
+    &titlemessage_initial_default.autowrap
   },
   {
-    "titlemessage_1.width",
-    &titlemessage[0].width
+    "[titlemessage_initial].centered",
+    &titlemessage_initial_default.centered
   },
   {
-    "titlemessage_1.height",
-    &titlemessage[0].height
+    "[titlemessage_initial].parse_comments",
+    &titlemessage_initial_default.parse_comments
   },
   {
-    "titlemessage_1.chars",
-    &titlemessage[0].chars
+    "[titlemessage_initial].sort_priority",
+    &titlemessage_initial_default.sort_priority
   },
   {
-    "titlemessage_1.lines",
-    &titlemessage[0].lines
+    "[titlemessage_initial].fade_mode",
+    &titlemessage_initial_default.fade_mode
   },
   {
-    "titlemessage_1.align",
-    &titlemessage[0].align
+    "[titlemessage_initial].fade_delay",
+    &titlemessage_initial_default.fade_delay
   },
   {
-    "titlemessage_1.valign",
-    &titlemessage[0].valign
+    "[titlemessage_initial].post_delay",
+    &titlemessage_initial_default.post_delay
   },
   {
-    "titlemessage_1.font",
-    &titlemessage[0].font
+    "[titlemessage_initial].auto_delay",
+    &titlemessage_initial_default.auto_delay
   },
   {
-    "titlemessage_1.autowrap",
-    &titlemessage[0].autowrap
+    "[titlemessage].x",
+    &titlemessage_default.x
   },
   {
-    "titlemessage_1.centered",
-    &titlemessage[0].centered
+    "[titlemessage].y",
+    &titlemessage_default.y
   },
   {
-    "titlemessage_1.parse_comments",
-    &titlemessage[0].parse_comments
+    "[titlemessage].width",
+    &titlemessage_default.width
   },
   {
-    "titlemessage_1.sort_priority",
-    &titlemessage[0].sort_priority
+    "[titlemessage].height",
+    &titlemessage_default.height
   },
   {
-    "titlemessage_1.fade_mode",
-    &titlemessage[0].fade_mode
+    "[titlemessage].chars",
+    &titlemessage_default.chars
   },
   {
-    "titlemessage_1.fade_delay",
-    &titlemessage[0].fade_delay
+    "[titlemessage].lines",
+    &titlemessage_default.lines
   },
   {
-    "titlemessage_1.post_delay",
-    &titlemessage[0].post_delay
+    "[titlemessage].align",
+    &titlemessage_default.align
   },
   {
-    "titlemessage_1.auto_delay",
-    &titlemessage[0].auto_delay
+    "[titlemessage].valign",
+    &titlemessage_default.valign
   },
   {
-    "titlemessage_2.x",
-    &titlemessage[1].x
+    "[titlemessage].font",
+    &titlemessage_default.font
   },
   {
-    "titlemessage_2.y",
-    &titlemessage[1].y
+    "[titlemessage].autowrap",
+    &titlemessage_default.autowrap
   },
   {
-    "titlemessage_2.width",
-    &titlemessage[1].width
+    "[titlemessage].centered",
+    &titlemessage_default.centered
   },
   {
-    "titlemessage_2.height",
-    &titlemessage[1].height
+    "[titlemessage].parse_comments",
+    &titlemessage_default.parse_comments
   },
   {
-    "titlemessage_2.chars",
-    &titlemessage[1].chars
+    "[titlemessage].sort_priority",
+    &titlemessage_default.sort_priority
   },
   {
-    "titlemessage_2.lines",
-    &titlemessage[1].lines
+    "[titlemessage].fade_mode",
+    &titlemessage_default.fade_mode
   },
   {
-    "titlemessage_2.align",
-    &titlemessage[1].align
+    "[titlemessage].fade_delay",
+    &titlemessage_default.fade_delay
   },
   {
-    "titlemessage_2.valign",
-    &titlemessage[1].valign
+    "[titlemessage].post_delay",
+    &titlemessage_default.post_delay
   },
   {
-    "titlemessage_2.font",
-    &titlemessage[1].font
+    "[titlemessage].auto_delay",
+    &titlemessage_default.auto_delay
   },
   {
-    "titlemessage_2.autowrap",
-    &titlemessage[1].autowrap
+    "titlemessage_initial_1.x",
+    &titlemessage_initial[0].x
   },
   {
-    "titlemessage_2.centered",
-    &titlemessage[1].centered
+    "titlemessage_initial_1.x",
+    &titlemessage_initial_first[0].x
   },
   {
-    "titlemessage_2.parse_comments",
-    &titlemessage[1].parse_comments
+    "titlemessage_initial_1.y",
+    &titlemessage_initial[0].y
   },
   {
-    "titlemessage_2.sort_priority",
-    &titlemessage[1].sort_priority
+    "titlemessage_initial_1.y",
+    &titlemessage_initial_first[0].y
   },
   {
-    "titlemessage_2.fade_mode",
-    &titlemessage[1].fade_mode
+    "titlemessage_initial_1.width",
+    &titlemessage_initial[0].width
   },
   {
-    "titlemessage_2.fade_delay",
-    &titlemessage[1].fade_delay
+    "titlemessage_initial_1.width",
+    &titlemessage_initial_first[0].width
   },
   {
-    "titlemessage_2.post_delay",
-    &titlemessage[1].post_delay
+    "titlemessage_initial_1.height",
+    &titlemessage_initial[0].height
   },
   {
-    "titlemessage_2.auto_delay",
-    &titlemessage[1].auto_delay
+    "titlemessage_initial_1.height",
+    &titlemessage_initial_first[0].height
   },
   {
-    "titlemessage_3.x",
-    &titlemessage[2].x
+    "titlemessage_initial_1.chars",
+    &titlemessage_initial[0].chars
   },
   {
-    "titlemessage_3.y",
-    &titlemessage[2].y
+    "titlemessage_initial_1.chars",
+    &titlemessage_initial_first[0].chars
   },
   {
-    "titlemessage_3.width",
-    &titlemessage[2].width
+    "titlemessage_initial_1.lines",
+    &titlemessage_initial[0].lines
   },
   {
-    "titlemessage_3.height",
-    &titlemessage[2].height
+    "titlemessage_initial_1.lines",
+    &titlemessage_initial_first[0].lines
   },
   {
-    "titlemessage_3.chars",
-    &titlemessage[2].chars
+    "titlemessage_initial_1.align",
+    &titlemessage_initial[0].align
   },
   {
-    "titlemessage_3.lines",
-    &titlemessage[2].lines
+    "titlemessage_initial_1.align",
+    &titlemessage_initial_first[0].align
   },
   {
-    "titlemessage_3.align",
-    &titlemessage[2].align
+    "titlemessage_initial_1.valign",
+    &titlemessage_initial[0].valign
   },
   {
-    "titlemessage_3.valign",
-    &titlemessage[2].valign
+    "titlemessage_initial_1.valign",
+    &titlemessage_initial_first[0].valign
   },
   {
-    "titlemessage_3.font",
-    &titlemessage[2].font
+    "titlemessage_initial_1.font",
+    &titlemessage_initial[0].font
   },
   {
-    "titlemessage_3.autowrap",
-    &titlemessage[2].autowrap
+    "titlemessage_initial_1.font",
+    &titlemessage_initial_first[0].font
   },
   {
-    "titlemessage_3.centered",
-    &titlemessage[2].centered
+    "titlemessage_initial_1.autowrap",
+    &titlemessage_initial[0].autowrap
   },
   {
-    "titlemessage_3.parse_comments",
-    &titlemessage[2].parse_comments
+    "titlemessage_initial_1.autowrap",
+    &titlemessage_initial_first[0].autowrap
   },
   {
-    "titlemessage_3.sort_priority",
-    &titlemessage[2].sort_priority
+    "titlemessage_initial_1.centered",
+    &titlemessage_initial[0].centered
   },
   {
-    "titlemessage_3.fade_mode",
-    &titlemessage[2].fade_mode
+    "titlemessage_initial_1.centered",
+    &titlemessage_initial_first[0].centered
   },
   {
-    "titlemessage_3.fade_delay",
-    &titlemessage[2].fade_delay
+    "titlemessage_initial_1.parse_comments",
+    &titlemessage_initial[0].parse_comments
   },
   {
-    "titlemessage_3.post_delay",
-    &titlemessage[2].post_delay
+    "titlemessage_initial_1.parse_comments",
+    &titlemessage_initial_first[0].parse_comments
   },
   {
-    "titlemessage_3.auto_delay",
-    &titlemessage[2].auto_delay
+    "titlemessage_initial_1.sort_priority",
+    &titlemessage_initial[0].sort_priority
   },
   {
-    "titlemessage_4.x",
-    &titlemessage[3].x
+    "titlemessage_initial_1.sort_priority",
+    &titlemessage_initial_first[0].sort_priority
   },
   {
-    "titlemessage_4.y",
-    &titlemessage[3].y
+    "titlemessage_initial_1.fade_mode",
+    &titlemessage_initial[0].fade_mode
   },
   {
-    "titlemessage_4.width",
-    &titlemessage[3].width
+    "titlemessage_initial_1.fade_mode",
+    &titlemessage_initial_first[0].fade_mode
   },
   {
-    "titlemessage_4.height",
-    &titlemessage[3].height
+    "titlemessage_initial_1.fade_delay",
+    &titlemessage_initial[0].fade_delay
   },
   {
-    "titlemessage_4.chars",
-    &titlemessage[3].chars
+    "titlemessage_initial_1.fade_delay",
+    &titlemessage_initial_first[0].fade_delay
   },
   {
-    "titlemessage_4.lines",
-    &titlemessage[3].lines
+    "titlemessage_initial_1.post_delay",
+    &titlemessage_initial[0].post_delay
   },
   {
-    "titlemessage_4.align",
-    &titlemessage[3].align
+    "titlemessage_initial_1.post_delay",
+    &titlemessage_initial_first[0].post_delay
   },
   {
-    "titlemessage_4.valign",
-    &titlemessage[3].valign
+    "titlemessage_initial_1.auto_delay",
+    &titlemessage_initial[0].auto_delay
   },
   {
-    "titlemessage_4.font",
-    &titlemessage[3].font
+    "titlemessage_initial_1.auto_delay",
+    &titlemessage_initial_first[0].auto_delay
   },
   {
-    "titlemessage_4.autowrap",
-    &titlemessage[3].autowrap
+    "titlemessage_initial_2.x",
+    &titlemessage_initial[1].x
   },
   {
-    "titlemessage_4.centered",
-    &titlemessage[3].centered
+    "titlemessage_initial_2.x",
+    &titlemessage_initial_first[1].x
   },
   {
-    "titlemessage_4.parse_comments",
-    &titlemessage[3].parse_comments
+    "titlemessage_initial_2.y",
+    &titlemessage_initial[1].y
   },
   {
-    "titlemessage_4.sort_priority",
-    &titlemessage[3].sort_priority
+    "titlemessage_initial_2.y",
+    &titlemessage_initial_first[1].y
   },
   {
-    "titlemessage_4.fade_mode",
-    &titlemessage[3].fade_mode
+    "titlemessage_initial_2.width",
+    &titlemessage_initial[1].width
   },
   {
-    "titlemessage_4.fade_delay",
-    &titlemessage[3].fade_delay
+    "titlemessage_initial_2.width",
+    &titlemessage_initial_first[1].width
   },
   {
-    "titlemessage_4.post_delay",
-    &titlemessage[3].post_delay
+    "titlemessage_initial_2.height",
+    &titlemessage_initial[1].height
   },
   {
-    "titlemessage_4.auto_delay",
-    &titlemessage[3].auto_delay
+    "titlemessage_initial_2.height",
+    &titlemessage_initial_first[1].height
   },
   {
-    "titlemessage_5.x",
-    &titlemessage[4].x
+    "titlemessage_initial_2.chars",
+    &titlemessage_initial[1].chars
   },
   {
-    "titlemessage_5.y",
-    &titlemessage[4].y
+    "titlemessage_initial_2.chars",
+    &titlemessage_initial_first[1].chars
   },
   {
-    "titlemessage_5.width",
-    &titlemessage[4].width
+    "titlemessage_initial_2.lines",
+    &titlemessage_initial[1].lines
   },
   {
-    "titlemessage_5.height",
-    &titlemessage[4].height
+    "titlemessage_initial_2.lines",
+    &titlemessage_initial_first[1].lines
   },
   {
-    "titlemessage_5.chars",
-    &titlemessage[4].chars
+    "titlemessage_initial_2.align",
+    &titlemessage_initial[1].align
   },
   {
-    "titlemessage_5.lines",
-    &titlemessage[4].lines
+    "titlemessage_initial_2.align",
+    &titlemessage_initial_first[1].align
   },
   {
-    "titlemessage_5.align",
-    &titlemessage[4].align
+    "titlemessage_initial_2.valign",
+    &titlemessage_initial[1].valign
   },
   {
-    "titlemessage_5.valign",
-    &titlemessage[4].valign
+    "titlemessage_initial_2.valign",
+    &titlemessage_initial_first[1].valign
   },
   {
-    "titlemessage_5.font",
-    &titlemessage[4].font
+    "titlemessage_initial_2.font",
+    &titlemessage_initial[1].font
   },
   {
-    "titlemessage_5.autowrap",
-    &titlemessage[4].autowrap
+    "titlemessage_initial_2.font",
+    &titlemessage_initial_first[1].font
   },
   {
-    "titlemessage_5.centered",
-    &titlemessage[4].centered
+    "titlemessage_initial_2.autowrap",
+    &titlemessage_initial[1].autowrap
   },
   {
-    "titlemessage_5.parse_comments",
-    &titlemessage[4].parse_comments
+    "titlemessage_initial_2.autowrap",
+    &titlemessage_initial_first[1].autowrap
   },
   {
-    "titlemessage_5.sort_priority",
-    &titlemessage[4].sort_priority
+    "titlemessage_initial_2.centered",
+    &titlemessage_initial[1].centered
   },
   {
-    "titlemessage_5.fade_mode",
-    &titlemessage[4].fade_mode
+    "titlemessage_initial_2.centered",
+    &titlemessage_initial_first[1].centered
   },
   {
-    "titlemessage_5.fade_delay",
-    &titlemessage[4].fade_delay
+    "titlemessage_initial_2.parse_comments",
+    &titlemessage_initial[1].parse_comments
   },
   {
-    "titlemessage_5.post_delay",
-    &titlemessage[4].post_delay
+    "titlemessage_initial_2.parse_comments",
+    &titlemessage_initial_first[1].parse_comments
   },
   {
-    "titlemessage_5.auto_delay",
-    &titlemessage[4].auto_delay
+    "titlemessage_initial_2.sort_priority",
+    &titlemessage_initial[1].sort_priority
   },
   {
-    "readme.x",
-    &readme.x
+    "titlemessage_initial_2.sort_priority",
+    &titlemessage_initial_first[1].sort_priority
   },
   {
-    "readme.y",
-    &readme.y
+    "titlemessage_initial_2.fade_mode",
+    &titlemessage_initial[1].fade_mode
   },
   {
-    "readme.width",
-    &readme.width
+    "titlemessage_initial_2.fade_mode",
+    &titlemessage_initial_first[1].fade_mode
   },
   {
-    "readme.height",
-    &readme.height
+    "titlemessage_initial_2.fade_delay",
+    &titlemessage_initial[1].fade_delay
   },
   {
-    "readme.chars",
-    &readme.chars
+    "titlemessage_initial_2.fade_delay",
+    &titlemessage_initial_first[1].fade_delay
   },
   {
-    "readme.lines",
-    &readme.lines
+    "titlemessage_initial_2.post_delay",
+    &titlemessage_initial[1].post_delay
   },
   {
-    "readme.align",
-    &readme.align
+    "titlemessage_initial_2.post_delay",
+    &titlemessage_initial_first[1].post_delay
   },
   {
-    "readme.valign",
-    &readme.valign
+    "titlemessage_initial_2.auto_delay",
+    &titlemessage_initial[1].auto_delay
   },
   {
-    "readme.font",
-    &readme.font
+    "titlemessage_initial_2.auto_delay",
+    &titlemessage_initial_first[1].auto_delay
   },
   {
-    "readme.autowrap",
-    &readme.autowrap
+    "titlemessage_initial_3.x",
+    &titlemessage_initial[2].x
   },
   {
-    "readme.centered",
-    &readme.centered
+    "titlemessage_initial_3.x",
+    &titlemessage_initial_first[2].x
   },
   {
-    "readme.parse_comments",
-    &readme.parse_comments
+    "titlemessage_initial_3.y",
+    &titlemessage_initial[2].y
   },
   {
-    "readme.sort_priority",
-    &readme.sort_priority
+    "titlemessage_initial_3.y",
+    &titlemessage_initial_first[2].y
   },
   {
-    "global.num_toons",
-    &global.num_toons
+    "titlemessage_initial_3.width",
+    &titlemessage_initial[2].width
   },
   {
-    "border.draw_masked.TITLE",
-    &border.draw_masked[GFX_SPECIAL_ARG_TITLE]
+    "titlemessage_initial_3.width",
+    &titlemessage_initial_first[2].width
   },
   {
-    "border.draw_masked.MAIN",
-    &border.draw_masked[GFX_SPECIAL_ARG_MAIN]
+    "titlemessage_initial_3.height",
+    &titlemessage_initial[2].height
   },
   {
-    "border.draw_masked.LEVELS",
-    &border.draw_masked[GFX_SPECIAL_ARG_LEVELS]
+    "titlemessage_initial_3.height",
+    &titlemessage_initial_first[2].height
   },
   {
-    "border.draw_masked.SCORES",
-    &border.draw_masked[GFX_SPECIAL_ARG_SCORES]
+    "titlemessage_initial_3.chars",
+    &titlemessage_initial[2].chars
   },
   {
-    "border.draw_masked.EDITOR",
-    &border.draw_masked[GFX_SPECIAL_ARG_EDITOR]
+    "titlemessage_initial_3.chars",
+    &titlemessage_initial_first[2].chars
   },
   {
-    "border.draw_masked.INFO",
-    &border.draw_masked[GFX_SPECIAL_ARG_INFO]
+    "titlemessage_initial_3.lines",
+    &titlemessage_initial[2].lines
   },
   {
-    "border.draw_masked.SETUP",
-    &border.draw_masked[GFX_SPECIAL_ARG_SETUP]
+    "titlemessage_initial_3.lines",
+    &titlemessage_initial_first[2].lines
   },
   {
-    "border.draw_masked.PLAYING",
-    &border.draw_masked[GFX_SPECIAL_ARG_PLAYING]
+    "titlemessage_initial_3.align",
+    &titlemessage_initial[2].align
   },
   {
-    "border.draw_masked.DOOR",
-    &border.draw_masked[GFX_SPECIAL_ARG_DOOR]
+    "titlemessage_initial_3.align",
+    &titlemessage_initial_first[2].align
   },
   {
-    "border.draw_masked_when_fading",
-    &border.draw_masked_when_fading
+    "titlemessage_initial_3.valign",
+    &titlemessage_initial[2].valign
   },
   {
-    "init.busy.x",
-    &init.busy.x
+    "titlemessage_initial_3.valign",
+    &titlemessage_initial_first[2].valign
   },
   {
-    "init.busy.y",
-    &init.busy.y
+    "titlemessage_initial_3.font",
+    &titlemessage_initial[2].font
   },
   {
-    "init.busy.align",
-    &init.busy.align
+    "titlemessage_initial_3.font",
+    &titlemessage_initial_first[2].font
   },
   {
-    "init.busy.valign",
-    &init.busy.valign
+    "titlemessage_initial_3.autowrap",
+    &titlemessage_initial[2].autowrap
   },
   {
-    "menu.enter_menu.fade_mode",
-    &menu.enter_menu.fade_mode
+    "titlemessage_initial_3.autowrap",
+    &titlemessage_initial_first[2].autowrap
   },
   {
-    "menu.enter_menu.fade_delay",
-    &menu.enter_menu.fade_delay
+    "titlemessage_initial_3.centered",
+    &titlemessage_initial[2].centered
   },
   {
-    "menu.enter_menu.post_delay",
-    &menu.enter_menu.post_delay
+    "titlemessage_initial_3.centered",
+    &titlemessage_initial_first[2].centered
   },
   {
-    "menu.leave_menu.fade_mode",
-    &menu.leave_menu.fade_mode
+    "titlemessage_initial_3.parse_comments",
+    &titlemessage_initial[2].parse_comments
   },
   {
-    "menu.leave_menu.fade_delay",
-    &menu.leave_menu.fade_delay
+    "titlemessage_initial_3.parse_comments",
+    &titlemessage_initial_first[2].parse_comments
   },
   {
-    "menu.leave_menu.post_delay",
-    &menu.leave_menu.post_delay
+    "titlemessage_initial_3.sort_priority",
+    &titlemessage_initial[2].sort_priority
   },
   {
-    "menu.enter_screen.fade_mode",
-    &menu.enter_screen[GFX_SPECIAL_ARG_DEFAULT].fade_mode
+    "titlemessage_initial_3.sort_priority",
+    &titlemessage_initial_first[2].sort_priority
   },
   {
-    "menu.enter_screen.fade_delay",
-    &menu.enter_screen[GFX_SPECIAL_ARG_DEFAULT].fade_delay
+    "titlemessage_initial_3.fade_mode",
+    &titlemessage_initial[2].fade_mode
   },
   {
-    "menu.enter_screen.post_delay",
-    &menu.enter_screen[GFX_SPECIAL_ARG_DEFAULT].post_delay
+    "titlemessage_initial_3.fade_mode",
+    &titlemessage_initial_first[2].fade_mode
   },
   {
-    "menu.next_screen.fade_mode",
-    &menu.next_screen.fade_mode
+    "titlemessage_initial_3.fade_delay",
+    &titlemessage_initial[2].fade_delay
   },
   {
-    "menu.next_screen.fade_delay",
-    &menu.next_screen.fade_delay
+    "titlemessage_initial_3.fade_delay",
+    &titlemessage_initial_first[2].fade_delay
   },
   {
-    "menu.next_screen.post_delay",
-    &menu.next_screen.post_delay
+    "titlemessage_initial_3.post_delay",
+    &titlemessage_initial[2].post_delay
   },
   {
-    "menu.leave_screen.fade_mode",
-    &menu.leave_screen[GFX_SPECIAL_ARG_DEFAULT].fade_mode
+    "titlemessage_initial_3.post_delay",
+    &titlemessage_initial_first[2].post_delay
   },
   {
-    "menu.leave_screen.fade_delay",
-    &menu.leave_screen[GFX_SPECIAL_ARG_DEFAULT].fade_delay
+    "titlemessage_initial_3.auto_delay",
+    &titlemessage_initial[2].auto_delay
   },
   {
-    "menu.leave_screen.post_delay",
-    &menu.leave_screen[GFX_SPECIAL_ARG_DEFAULT].post_delay
+    "titlemessage_initial_3.auto_delay",
+    &titlemessage_initial_first[2].auto_delay
   },
   {
-    "menu.enter_screen.SCORES.fade_mode",
-    &menu.enter_screen[GFX_SPECIAL_ARG_SCORES].fade_mode
+    "titlemessage_initial_4.x",
+    &titlemessage_initial[3].x
   },
   {
-    "menu.enter_screen.SCORES.fade_delay",
-    &menu.enter_screen[GFX_SPECIAL_ARG_SCORES].fade_delay
+    "titlemessage_initial_4.x",
+    &titlemessage_initial_first[3].x
   },
   {
-    "menu.enter_screen.SCORES.post_delay",
-    &menu.enter_screen[GFX_SPECIAL_ARG_SCORES].post_delay
+    "titlemessage_initial_4.y",
+    &titlemessage_initial[3].y
   },
   {
-    "menu.enter_screen.EDITOR.fade_mode",
-    &menu.enter_screen[GFX_SPECIAL_ARG_EDITOR].fade_mode
+    "titlemessage_initial_4.y",
+    &titlemessage_initial_first[3].y
   },
   {
-    "menu.enter_screen.EDITOR.fade_delay",
-    &menu.enter_screen[GFX_SPECIAL_ARG_EDITOR].fade_delay
+    "titlemessage_initial_4.width",
+    &titlemessage_initial[3].width
   },
   {
-    "menu.enter_screen.EDITOR.post_delay",
-    &menu.enter_screen[GFX_SPECIAL_ARG_EDITOR].post_delay
+    "titlemessage_initial_4.width",
+    &titlemessage_initial_first[3].width
   },
   {
-    "menu.enter_screen.INFO.fade_mode",
-    &menu.enter_screen[GFX_SPECIAL_ARG_INFO].fade_mode
+    "titlemessage_initial_4.height",
+    &titlemessage_initial[3].height
   },
   {
-    "menu.enter_screen.INFO.fade_delay",
-    &menu.enter_screen[GFX_SPECIAL_ARG_INFO].fade_delay
+    "titlemessage_initial_4.height",
+    &titlemessage_initial_first[3].height
   },
   {
-    "menu.enter_screen.INFO.post_delay",
-    &menu.enter_screen[GFX_SPECIAL_ARG_INFO].post_delay
+    "titlemessage_initial_4.chars",
+    &titlemessage_initial[3].chars
   },
   {
-    "menu.enter_screen.PLAYING.fade_mode",
-    &menu.enter_screen[GFX_SPECIAL_ARG_PLAYING].fade_mode
+    "titlemessage_initial_4.chars",
+    &titlemessage_initial_first[3].chars
   },
   {
-    "menu.enter_screen.PLAYING.fade_delay",
-    &menu.enter_screen[GFX_SPECIAL_ARG_PLAYING].fade_delay
+    "titlemessage_initial_4.lines",
+    &titlemessage_initial[3].lines
   },
   {
-    "menu.enter_screen.PLAYING.post_delay",
-    &menu.enter_screen[GFX_SPECIAL_ARG_PLAYING].post_delay
+    "titlemessage_initial_4.lines",
+    &titlemessage_initial_first[3].lines
   },
   {
-    "menu.leave_screen.SCORES.fade_mode",
-    &menu.leave_screen[GFX_SPECIAL_ARG_SCORES].fade_mode
+    "titlemessage_initial_4.align",
+    &titlemessage_initial[3].align
   },
   {
-    "menu.leave_screen.SCORES.fade_delay",
-    &menu.leave_screen[GFX_SPECIAL_ARG_SCORES].fade_delay
+    "titlemessage_initial_4.align",
+    &titlemessage_initial_first[3].align
   },
   {
-    "menu.leave_screen.SCORES.post_delay",
-    &menu.leave_screen[GFX_SPECIAL_ARG_SCORES].post_delay
+    "titlemessage_initial_4.valign",
+    &titlemessage_initial[3].valign
   },
   {
-    "menu.leave_screen.EDITOR.fade_mode",
-    &menu.leave_screen[GFX_SPECIAL_ARG_EDITOR].fade_mode
+    "titlemessage_initial_4.valign",
+    &titlemessage_initial_first[3].valign
   },
   {
-    "menu.leave_screen.EDITOR.fade_delay",
-    &menu.leave_screen[GFX_SPECIAL_ARG_EDITOR].fade_delay
+    "titlemessage_initial_4.font",
+    &titlemessage_initial[3].font
   },
   {
-    "menu.leave_screen.EDITOR.post_delay",
-    &menu.leave_screen[GFX_SPECIAL_ARG_EDITOR].post_delay
+    "titlemessage_initial_4.font",
+    &titlemessage_initial_first[3].font
   },
   {
-    "menu.leave_screen.INFO.fade_mode",
-    &menu.leave_screen[GFX_SPECIAL_ARG_INFO].fade_mode
+    "titlemessage_initial_4.autowrap",
+    &titlemessage_initial[3].autowrap
   },
   {
-    "menu.leave_screen.INFO.fade_delay",
-    &menu.leave_screen[GFX_SPECIAL_ARG_INFO].fade_delay
+    "titlemessage_initial_4.autowrap",
+    &titlemessage_initial_first[3].autowrap
   },
   {
-    "menu.leave_screen.INFO.post_delay",
-    &menu.leave_screen[GFX_SPECIAL_ARG_INFO].post_delay
+    "titlemessage_initial_4.centered",
+    &titlemessage_initial[3].centered
   },
   {
-    "menu.leave_screen.PLAYING.fade_mode",
-    &menu.leave_screen[GFX_SPECIAL_ARG_PLAYING].fade_mode
+    "titlemessage_initial_4.centered",
+    &titlemessage_initial_first[3].centered
   },
   {
-    "menu.leave_screen.PLAYING.fade_delay",
-    &menu.leave_screen[GFX_SPECIAL_ARG_PLAYING].fade_delay
+    "titlemessage_initial_4.parse_comments",
+    &titlemessage_initial[3].parse_comments
   },
   {
-    "menu.leave_screen.PLAYING.post_delay",
-    &menu.leave_screen[GFX_SPECIAL_ARG_PLAYING].post_delay
+    "titlemessage_initial_4.parse_comments",
+    &titlemessage_initial_first[3].parse_comments
   },
   {
-    "menu.draw_xoffset",
-    &menu.draw_xoffset[GFX_SPECIAL_ARG_DEFAULT]
+    "titlemessage_initial_4.sort_priority",
+    &titlemessage_initial[3].sort_priority
   },
   {
-    "menu.draw_yoffset",
-    &menu.draw_yoffset[GFX_SPECIAL_ARG_DEFAULT]
+    "titlemessage_initial_4.sort_priority",
+    &titlemessage_initial_first[3].sort_priority
   },
   {
-    "menu.draw_xoffset.MAIN",
-    &menu.draw_xoffset[GFX_SPECIAL_ARG_MAIN]
+    "titlemessage_initial_4.fade_mode",
+    &titlemessage_initial[3].fade_mode
   },
   {
-    "menu.draw_yoffset.MAIN",
-    &menu.draw_yoffset[GFX_SPECIAL_ARG_MAIN]
+    "titlemessage_initial_4.fade_mode",
+    &titlemessage_initial_first[3].fade_mode
   },
   {
-    "menu.draw_xoffset.LEVELS",
-    &menu.draw_xoffset[GFX_SPECIAL_ARG_LEVELS]
+    "titlemessage_initial_4.fade_delay",
+    &titlemessage_initial[3].fade_delay
   },
   {
-    "menu.draw_yoffset.LEVELS",
-    &menu.draw_yoffset[GFX_SPECIAL_ARG_LEVELS]
+    "titlemessage_initial_4.fade_delay",
+    &titlemessage_initial_first[3].fade_delay
   },
   {
-    "menu.draw_xoffset.SCORES",
-    &menu.draw_xoffset[GFX_SPECIAL_ARG_SCORES]
+    "titlemessage_initial_4.post_delay",
+    &titlemessage_initial[3].post_delay
   },
   {
-    "menu.draw_yoffset.SCORES",
-    &menu.draw_yoffset[GFX_SPECIAL_ARG_SCORES]
+    "titlemessage_initial_4.post_delay",
+    &titlemessage_initial_first[3].post_delay
   },
   {
-    "menu.draw_xoffset.EDITOR",
-    &menu.draw_xoffset[GFX_SPECIAL_ARG_EDITOR]
+    "titlemessage_initial_4.auto_delay",
+    &titlemessage_initial[3].auto_delay
   },
   {
-    "menu.draw_yoffset.EDITOR",
-    &menu.draw_yoffset[GFX_SPECIAL_ARG_EDITOR]
+    "titlemessage_initial_4.auto_delay",
+    &titlemessage_initial_first[3].auto_delay
   },
   {
-    "menu.draw_xoffset.INFO",
-    &menu.draw_xoffset[GFX_SPECIAL_ARG_INFO]
+    "titlemessage_initial_5.x",
+    &titlemessage_initial[4].x
   },
   {
-    "menu.draw_yoffset.INFO",
-    &menu.draw_yoffset[GFX_SPECIAL_ARG_INFO]
+    "titlemessage_initial_5.x",
+    &titlemessage_initial_first[4].x
   },
   {
-    "menu.draw_xoffset.INFO[ELEMENTS]",
-    &menu.draw_xoffset_info[GFX_SPECIAL_ARG_INFO_ELEMENTS]
+    "titlemessage_initial_5.y",
+    &titlemessage_initial[4].y
   },
   {
-    "menu.draw_yoffset.INFO[ELEMENTS]",
-    &menu.draw_yoffset_info[GFX_SPECIAL_ARG_INFO_ELEMENTS]
+    "titlemessage_initial_5.y",
+    &titlemessage_initial_first[4].y
   },
   {
-    "menu.draw_xoffset.INFO[MUSIC]",
-    &menu.draw_xoffset_info[GFX_SPECIAL_ARG_INFO_MUSIC]
+    "titlemessage_initial_5.width",
+    &titlemessage_initial[4].width
   },
   {
-    "menu.draw_yoffset.INFO[MUSIC]",
-    &menu.draw_yoffset_info[GFX_SPECIAL_ARG_INFO_MUSIC]
+    "titlemessage_initial_5.width",
+    &titlemessage_initial_first[4].width
   },
   {
-    "menu.draw_xoffset.INFO[CREDITS]",
-    &menu.draw_xoffset_info[GFX_SPECIAL_ARG_INFO_CREDITS]
+    "titlemessage_initial_5.height",
+    &titlemessage_initial[4].height
   },
   {
-    "menu.draw_yoffset.INFO[CREDITS]",
-    &menu.draw_yoffset_info[GFX_SPECIAL_ARG_INFO_CREDITS]
+    "titlemessage_initial_5.height",
+    &titlemessage_initial_first[4].height
   },
   {
-    "menu.draw_xoffset.INFO[PROGRAM]",
-    &menu.draw_xoffset_info[GFX_SPECIAL_ARG_INFO_PROGRAM]
+    "titlemessage_initial_5.chars",
+    &titlemessage_initial[4].chars
   },
   {
-    "menu.draw_yoffset.INFO[PROGRAM]",
-    &menu.draw_yoffset_info[GFX_SPECIAL_ARG_INFO_PROGRAM]
+    "titlemessage_initial_5.chars",
+    &titlemessage_initial_first[4].chars
   },
   {
-    "menu.draw_xoffset.INFO[VERSION]",
-    &menu.draw_xoffset_info[GFX_SPECIAL_ARG_INFO_VERSION]
+    "titlemessage_initial_5.lines",
+    &titlemessage_initial[4].lines
   },
   {
-    "menu.draw_yoffset.INFO[VERSION]",
-    &menu.draw_yoffset_info[GFX_SPECIAL_ARG_INFO_VERSION]
+    "titlemessage_initial_5.lines",
+    &titlemessage_initial_first[4].lines
   },
   {
-    "menu.draw_xoffset.INFO[LEVELSET]",
-    &menu.draw_xoffset_info[GFX_SPECIAL_ARG_INFO_LEVELSET]
+    "titlemessage_initial_5.align",
+    &titlemessage_initial[4].align
   },
   {
-    "menu.draw_yoffset.INFO[LEVELSET]",
-    &menu.draw_yoffset_info[GFX_SPECIAL_ARG_INFO_LEVELSET]
+    "titlemessage_initial_5.align",
+    &titlemessage_initial_first[4].align
   },
   {
-    "menu.draw_xoffset.SETUP",
-    &menu.draw_xoffset[GFX_SPECIAL_ARG_SETUP]
+    "titlemessage_initial_5.valign",
+    &titlemessage_initial[4].valign
   },
   {
-    "menu.draw_yoffset.SETUP",
-    &menu.draw_yoffset[GFX_SPECIAL_ARG_SETUP]
+    "titlemessage_initial_5.valign",
+    &titlemessage_initial_first[4].valign
   },
   {
-    "menu.draw_xoffset.SETUP[GAME]",
-    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_GAME]
+    "titlemessage_initial_5.font",
+    &titlemessage_initial[4].font
   },
   {
-    "menu.draw_yoffset.SETUP[GAME]",
-    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_GAME]
+    "titlemessage_initial_5.font",
+    &titlemessage_initial_first[4].font
   },
   {
-    "menu.draw_xoffset.SETUP[EDITOR]",
-    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_EDITOR]
+    "titlemessage_initial_5.autowrap",
+    &titlemessage_initial[4].autowrap
   },
   {
-    "menu.draw_yoffset.SETUP[EDITOR]",
-    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_EDITOR]
+    "titlemessage_initial_5.autowrap",
+    &titlemessage_initial_first[4].autowrap
   },
   {
-    "menu.draw_xoffset.SETUP[GRAPHICS]",
-    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_GRAPHICS]
+    "titlemessage_initial_5.centered",
+    &titlemessage_initial[4].centered
   },
   {
-    "menu.draw_yoffset.SETUP[GRAPHICS]",
-    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_GRAPHICS]
+    "titlemessage_initial_5.centered",
+    &titlemessage_initial_first[4].centered
   },
   {
-    "menu.draw_xoffset.SETUP[SOUND]",
-    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SOUND]
+    "titlemessage_initial_5.parse_comments",
+    &titlemessage_initial[4].parse_comments
   },
   {
-    "menu.draw_yoffset.SETUP[SOUND]",
-    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SOUND]
+    "titlemessage_initial_5.parse_comments",
+    &titlemessage_initial_first[4].parse_comments
   },
   {
-    "menu.draw_xoffset.SETUP[ARTWORK]",
-    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_ARTWORK]
+    "titlemessage_initial_5.sort_priority",
+    &titlemessage_initial[4].sort_priority
   },
   {
-    "menu.draw_yoffset.SETUP[ARTWORK]",
-    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_ARTWORK]
+    "titlemessage_initial_5.sort_priority",
+    &titlemessage_initial_first[4].sort_priority
   },
   {
-    "menu.draw_xoffset.SETUP[INPUT]",
-    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_INPUT]
+    "titlemessage_initial_5.fade_mode",
+    &titlemessage_initial[4].fade_mode
   },
   {
-    "menu.draw_yoffset.SETUP[INPUT]",
-    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_INPUT]
+    "titlemessage_initial_5.fade_mode",
+    &titlemessage_initial_first[4].fade_mode
   },
   {
-    "menu.draw_xoffset.SETUP[SHORTCUTS]",
-    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS]
+    "titlemessage_initial_5.fade_delay",
+    &titlemessage_initial[4].fade_delay
   },
   {
-    "menu.draw_yoffset.SETUP[SHORTCUTS]",
-    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS]
+    "titlemessage_initial_5.fade_delay",
+    &titlemessage_initial_first[4].fade_delay
   },
   {
-    "menu.draw_xoffset.SETUP[SHORTCUTS_1]",
-    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_1]
+    "titlemessage_initial_5.post_delay",
+    &titlemessage_initial[4].post_delay
   },
   {
-    "menu.draw_yoffset.SETUP[SHORTCUTS_1]",
-    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_1]
+    "titlemessage_initial_5.post_delay",
+    &titlemessage_initial_first[4].post_delay
   },
   {
-    "menu.draw_xoffset.SETUP[SHORTCUTS_2]",
-    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_2]
+    "titlemessage_initial_5.auto_delay",
+    &titlemessage_initial[4].auto_delay
   },
   {
-    "menu.draw_yoffset.SETUP[SHORTCUTS_2]",
-    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_2]
+    "titlemessage_initial_5.auto_delay",
+    &titlemessage_initial_first[4].auto_delay
   },
   {
-    "menu.draw_xoffset.SETUP[SHORTCUTS_3]",
-    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_3]
+    "titlemessage_1.x",
+    &titlemessage[0].x
   },
   {
-    "menu.draw_yoffset.SETUP[SHORTCUTS_3]",
-    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_3]
+    "titlemessage_1.x",
+    &titlemessage_first[0].x
   },
   {
-    "menu.draw_xoffset.SETUP[SHORTCUTS_4]",
-    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_4]
+    "titlemessage_1.y",
+    &titlemessage[0].y
   },
   {
-    "menu.draw_yoffset.SETUP[SHORTCUTS_4]",
-    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_4]
+    "titlemessage_1.y",
+    &titlemessage_first[0].y
   },
   {
-    "menu.draw_xoffset.SETUP[CHOOSE_ARTWORK]",
-    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_CHOOSE_ARTWORK]
+    "titlemessage_1.width",
+    &titlemessage[0].width
   },
   {
-    "menu.draw_yoffset.SETUP[CHOOSE_ARTWORK]",
-    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_CHOOSE_ARTWORK]
+    "titlemessage_1.width",
+    &titlemessage_first[0].width
   },
   {
-    "menu.draw_xoffset.SETUP[CHOOSE_OTHER]",
-    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_CHOOSE_OTHER]
+    "titlemessage_1.height",
+    &titlemessage[0].height
   },
   {
-    "menu.draw_yoffset.SETUP[CHOOSE_OTHER]",
-    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_CHOOSE_OTHER]
+    "titlemessage_1.height",
+    &titlemessage_first[0].height
   },
   {
-    "menu.scrollbar_xoffset",
-    &menu.scrollbar_xoffset
+    "titlemessage_1.chars",
+    &titlemessage[0].chars
   },
   {
-    "menu.list_size",
-    &menu.list_size[GFX_SPECIAL_ARG_DEFAULT]
+    "titlemessage_1.chars",
+    &titlemessage_first[0].chars
   },
   {
-    "menu.list_size.LEVELS",
-    &menu.list_size[GFX_SPECIAL_ARG_LEVELS]
+    "titlemessage_1.lines",
+    &titlemessage[0].lines
   },
   {
-    "menu.list_size.SCORES",
-    &menu.list_size[GFX_SPECIAL_ARG_SCORES]
+    "titlemessage_1.lines",
+    &titlemessage_first[0].lines
   },
   {
-    "menu.list_size.INFO",
-    &menu.list_size[GFX_SPECIAL_ARG_INFO]
+    "titlemessage_1.align",
+    &titlemessage[0].align
   },
   {
-    "menu.list_size.SETUP",
-    &menu.list_size[GFX_SPECIAL_ARG_SETUP]
+    "titlemessage_1.align",
+    &titlemessage_first[0].align
   },
   {
-    "main.button.name.x",
-    &menu.main.button.name.x
-  },
+    "titlemessage_1.valign",
+    &titlemessage[0].valign
+  },
   {
-    "main.button.name.y",
-    &menu.main.button.name.y
+    "titlemessage_1.valign",
+    &titlemessage_first[0].valign
   },
   {
-    "main.button.levels.x",
-    &menu.main.button.levels.x
+    "titlemessage_1.font",
+    &titlemessage[0].font
   },
   {
-    "main.button.levels.y",
-    &menu.main.button.levels.y
+    "titlemessage_1.font",
+    &titlemessage_first[0].font
   },
   {
-    "main.button.scores.x",
-    &menu.main.button.scores.x
+    "titlemessage_1.autowrap",
+    &titlemessage[0].autowrap
   },
   {
-    "main.button.scores.y",
-    &menu.main.button.scores.y
+    "titlemessage_1.autowrap",
+    &titlemessage_first[0].autowrap
   },
   {
-    "main.button.editor.x",
-    &menu.main.button.editor.x
+    "titlemessage_1.centered",
+    &titlemessage[0].centered
   },
   {
-    "main.button.editor.y",
-    &menu.main.button.editor.y
+    "titlemessage_1.centered",
+    &titlemessage_first[0].centered
   },
   {
-    "main.button.info.x",
-    &menu.main.button.info.x
+    "titlemessage_1.parse_comments",
+    &titlemessage[0].parse_comments
   },
   {
-    "main.button.info.y",
-    &menu.main.button.info.y
+    "titlemessage_1.parse_comments",
+    &titlemessage_first[0].parse_comments
   },
   {
-    "main.button.game.x",
-    &menu.main.button.game.x
+    "titlemessage_1.sort_priority",
+    &titlemessage[0].sort_priority
   },
   {
-    "main.button.game.y",
-    &menu.main.button.game.y
+    "titlemessage_1.sort_priority",
+    &titlemessage_first[0].sort_priority
   },
   {
-    "main.button.setup.x",
-    &menu.main.button.setup.x
+    "titlemessage_1.fade_mode",
+    &titlemessage[0].fade_mode
   },
   {
-    "main.button.setup.y",
-    &menu.main.button.setup.y
+    "titlemessage_1.fade_mode",
+    &titlemessage_first[0].fade_mode
   },
   {
-    "main.button.quit.x",
-    &menu.main.button.quit.x
+    "titlemessage_1.fade_delay",
+    &titlemessage[0].fade_delay
   },
   {
-    "main.button.quit.y",
-    &menu.main.button.quit.y
+    "titlemessage_1.fade_delay",
+    &titlemessage_first[0].fade_delay
   },
   {
-    "main.button.prev_level.x",
-    &menu.main.button.prev_level.x
+    "titlemessage_1.post_delay",
+    &titlemessage[0].post_delay
   },
   {
-    "main.button.prev_level.y",
-    &menu.main.button.prev_level.y
+    "titlemessage_1.post_delay",
+    &titlemessage_first[0].post_delay
   },
   {
-    "main.button.next_level.x",
-    &menu.main.button.next_level.x
+    "titlemessage_1.auto_delay",
+    &titlemessage[0].auto_delay
   },
   {
-    "main.button.next_level.y",
-    &menu.main.button.next_level.y
+    "titlemessage_1.auto_delay",
+    &titlemessage_first[0].auto_delay
   },
   {
-    "main.text.name.x",
-    &menu.main.text.name.x
+    "titlemessage_2.x",
+    &titlemessage[1].x
   },
   {
-    "main.text.name.y",
-    &menu.main.text.name.y
+    "titlemessage_2.x",
+    &titlemessage_first[1].x
   },
   {
-    "main.text.name.width",
-    &menu.main.text.name.width
+    "titlemessage_2.y",
+    &titlemessage[1].y
   },
   {
-    "main.text.name.height",
-    &menu.main.text.name.height
+    "titlemessage_2.y",
+    &titlemessage_first[1].y
   },
   {
-    "main.text.name.align",
-    &menu.main.text.name.align
+    "titlemessage_2.width",
+    &titlemessage[1].width
   },
   {
-    "main.text.name.valign",
-    &menu.main.text.name.valign
+    "titlemessage_2.width",
+    &titlemessage_first[1].width
   },
   {
-    "main.text.name.font",
-    &menu.main.text.name.font
+    "titlemessage_2.height",
+    &titlemessage[1].height
   },
   {
-    "main.text.levels.x",
-    &menu.main.text.levels.x
+    "titlemessage_2.height",
+    &titlemessage_first[1].height
   },
   {
-    "main.text.levels.y",
-    &menu.main.text.levels.y
+    "titlemessage_2.chars",
+    &titlemessage[1].chars
   },
   {
-    "main.text.levels.width",
-    &menu.main.text.levels.width
+    "titlemessage_2.chars",
+    &titlemessage_first[1].chars
   },
   {
-    "main.text.levels.height",
-    &menu.main.text.levels.height
+    "titlemessage_2.lines",
+    &titlemessage[1].lines
   },
   {
-    "main.text.levels.align",
-    &menu.main.text.levels.align
+    "titlemessage_2.lines",
+    &titlemessage_first[1].lines
   },
   {
-    "main.text.levels.valign",
-    &menu.main.text.levels.valign
+    "titlemessage_2.align",
+    &titlemessage[1].align
   },
   {
-    "main.text.levels.font",
-    &menu.main.text.levels.font
+    "titlemessage_2.align",
+    &titlemessage_first[1].align
   },
   {
-    "main.text.scores.x",
-    &menu.main.text.scores.x
+    "titlemessage_2.valign",
+    &titlemessage[1].valign
   },
   {
-    "main.text.scores.y",
-    &menu.main.text.scores.y
+    "titlemessage_2.valign",
+    &titlemessage_first[1].valign
   },
   {
-    "main.text.scores.width",
-    &menu.main.text.scores.width
+    "titlemessage_2.font",
+    &titlemessage[1].font
   },
   {
-    "main.text.scores.height",
-    &menu.main.text.scores.height
+    "titlemessage_2.font",
+    &titlemessage_first[1].font
   },
   {
-    "main.text.scores.align",
-    &menu.main.text.scores.align
+    "titlemessage_2.autowrap",
+    &titlemessage[1].autowrap
   },
   {
-    "main.text.scores.valign",
-    &menu.main.text.scores.valign
+    "titlemessage_2.autowrap",
+    &titlemessage_first[1].autowrap
   },
   {
-    "main.text.scores.font",
-    &menu.main.text.scores.font
+    "titlemessage_2.centered",
+    &titlemessage[1].centered
   },
   {
-    "main.text.editor.x",
-    &menu.main.text.editor.x
+    "titlemessage_2.centered",
+    &titlemessage_first[1].centered
   },
   {
-    "main.text.editor.y",
-    &menu.main.text.editor.y
+    "titlemessage_2.parse_comments",
+    &titlemessage[1].parse_comments
   },
   {
-    "main.text.editor.width",
-    &menu.main.text.editor.width
+    "titlemessage_2.parse_comments",
+    &titlemessage_first[1].parse_comments
   },
   {
-    "main.text.editor.height",
-    &menu.main.text.editor.height
+    "titlemessage_2.sort_priority",
+    &titlemessage[1].sort_priority
   },
   {
-    "main.text.editor.align",
-    &menu.main.text.editor.align
+    "titlemessage_2.sort_priority",
+    &titlemessage_first[1].sort_priority
   },
   {
-    "main.text.editor.valign",
-    &menu.main.text.editor.valign
+    "titlemessage_2.fade_mode",
+    &titlemessage[1].fade_mode
   },
   {
-    "main.text.editor.font",
-    &menu.main.text.editor.font
+    "titlemessage_2.fade_mode",
+    &titlemessage_first[1].fade_mode
   },
   {
-    "main.text.info.x",
-    &menu.main.text.info.x
+    "titlemessage_2.fade_delay",
+    &titlemessage[1].fade_delay
   },
   {
-    "main.text.info.y",
-    &menu.main.text.info.y
+    "titlemessage_2.fade_delay",
+    &titlemessage_first[1].fade_delay
   },
   {
-    "main.text.info.width",
-    &menu.main.text.info.width
+    "titlemessage_2.post_delay",
+    &titlemessage[1].post_delay
   },
   {
-    "main.text.info.height",
-    &menu.main.text.info.height
+    "titlemessage_2.post_delay",
+    &titlemessage_first[1].post_delay
   },
   {
-    "main.text.info.align",
-    &menu.main.text.info.align
+    "titlemessage_2.auto_delay",
+    &titlemessage[1].auto_delay
   },
   {
-    "main.text.info.valign",
-    &menu.main.text.info.valign
+    "titlemessage_2.auto_delay",
+    &titlemessage_first[1].auto_delay
   },
   {
-    "main.text.info.font",
-    &menu.main.text.info.font
+    "titlemessage_3.x",
+    &titlemessage[2].x
   },
   {
-    "main.text.game.x",
-    &menu.main.text.game.x
+    "titlemessage_3.x",
+    &titlemessage_first[2].x
   },
   {
-    "main.text.game.y",
-    &menu.main.text.game.y
+    "titlemessage_3.y",
+    &titlemessage[2].y
   },
   {
-    "main.text.game.width",
-    &menu.main.text.game.width
+    "titlemessage_3.y",
+    &titlemessage_first[2].y
   },
   {
-    "main.text.game.height",
-    &menu.main.text.game.height
+    "titlemessage_3.width",
+    &titlemessage[2].width
   },
   {
-    "main.text.game.align",
-    &menu.main.text.game.align
+    "titlemessage_3.width",
+    &titlemessage_first[2].width
   },
   {
-    "main.text.game.valign",
-    &menu.main.text.game.valign
+    "titlemessage_3.height",
+    &titlemessage[2].height
   },
   {
-    "main.text.game.font",
-    &menu.main.text.game.font
+    "titlemessage_3.height",
+    &titlemessage_first[2].height
   },
   {
-    "main.text.setup.x",
-    &menu.main.text.setup.x
+    "titlemessage_3.chars",
+    &titlemessage[2].chars
   },
   {
-    "main.text.setup.y",
-    &menu.main.text.setup.y
+    "titlemessage_3.chars",
+    &titlemessage_first[2].chars
   },
   {
-    "main.text.setup.width",
-    &menu.main.text.setup.width
+    "titlemessage_3.lines",
+    &titlemessage[2].lines
   },
   {
-    "main.text.setup.height",
-    &menu.main.text.setup.height
+    "titlemessage_3.lines",
+    &titlemessage_first[2].lines
   },
   {
-    "main.text.setup.align",
-    &menu.main.text.setup.align
+    "titlemessage_3.align",
+    &titlemessage[2].align
   },
   {
-    "main.text.setup.valign",
-    &menu.main.text.setup.valign
+    "titlemessage_3.align",
+    &titlemessage_first[2].align
   },
   {
-    "main.text.setup.font",
-    &menu.main.text.setup.font
+    "titlemessage_3.valign",
+    &titlemessage[2].valign
   },
   {
-    "main.text.quit.x",
-    &menu.main.text.quit.x
+    "titlemessage_3.valign",
+    &titlemessage_first[2].valign
   },
   {
-    "main.text.quit.y",
-    &menu.main.text.quit.y
+    "titlemessage_3.font",
+    &titlemessage[2].font
   },
   {
-    "main.text.quit.width",
-    &menu.main.text.quit.width
+    "titlemessage_3.font",
+    &titlemessage_first[2].font
   },
   {
-    "main.text.quit.height",
-    &menu.main.text.quit.height
+    "titlemessage_3.autowrap",
+    &titlemessage[2].autowrap
   },
   {
-    "main.text.quit.align",
-    &menu.main.text.quit.align
+    "titlemessage_3.autowrap",
+    &titlemessage_first[2].autowrap
   },
   {
-    "main.text.quit.valign",
-    &menu.main.text.quit.valign
+    "titlemessage_3.centered",
+    &titlemessage[2].centered
   },
   {
-    "main.text.quit.font",
-    &menu.main.text.quit.font
+    "titlemessage_3.centered",
+    &titlemessage_first[2].centered
   },
   {
-    "main.text.first_level.x",
-    &menu.main.text.first_level.x
+    "titlemessage_3.parse_comments",
+    &titlemessage[2].parse_comments
   },
   {
-    "main.text.first_level.y",
-    &menu.main.text.first_level.y
+    "titlemessage_3.parse_comments",
+    &titlemessage_first[2].parse_comments
   },
   {
-    "main.text.first_level.align",
-    &menu.main.text.first_level.align
+    "titlemessage_3.sort_priority",
+    &titlemessage[2].sort_priority
   },
   {
-    "main.text.first_level.valign",
-    &menu.main.text.first_level.valign
+    "titlemessage_3.sort_priority",
+    &titlemessage_first[2].sort_priority
   },
   {
-    "main.text.first_level.digits",
-    &menu.main.text.first_level.size
+    "titlemessage_3.fade_mode",
+    &titlemessage[2].fade_mode
   },
   {
-    "main.text.first_level.font",
-    &menu.main.text.first_level.font
+    "titlemessage_3.fade_mode",
+    &titlemessage_first[2].fade_mode
   },
   {
-    "main.text.last_level.x",
-    &menu.main.text.last_level.x
+    "titlemessage_3.fade_delay",
+    &titlemessage[2].fade_delay
   },
   {
-    "main.text.last_level.y",
-    &menu.main.text.last_level.y
+    "titlemessage_3.fade_delay",
+    &titlemessage_first[2].fade_delay
   },
   {
-    "main.text.last_level.align",
-    &menu.main.text.last_level.align
+    "titlemessage_3.post_delay",
+    &titlemessage[2].post_delay
   },
   {
-    "main.text.last_level.valign",
-    &menu.main.text.last_level.valign
+    "titlemessage_3.post_delay",
+    &titlemessage_first[2].post_delay
   },
   {
-    "main.text.last_level.digits",
-    &menu.main.text.last_level.size
+    "titlemessage_3.auto_delay",
+    &titlemessage[2].auto_delay
   },
   {
-    "main.text.last_level.font",
-    &menu.main.text.last_level.font
+    "titlemessage_3.auto_delay",
+    &titlemessage_first[2].auto_delay
   },
   {
-    "main.text.level_number.x",
-    &menu.main.text.level_number.x
+    "titlemessage_4.x",
+    &titlemessage[3].x
   },
   {
-    "main.text.level_number.y",
-    &menu.main.text.level_number.y
+    "titlemessage_4.x",
+    &titlemessage_first[3].x
   },
   {
-    "main.text.level_number.align",
-    &menu.main.text.level_number.align
+    "titlemessage_4.y",
+    &titlemessage[3].y
   },
   {
-    "main.text.level_number.valign",
-    &menu.main.text.level_number.valign
+    "titlemessage_4.y",
+    &titlemessage_first[3].y
   },
   {
-    "main.text.level_number.digits",
-    &menu.main.text.level_number.size
+    "titlemessage_4.width",
+    &titlemessage[3].width
   },
   {
-    "main.text.level_number.font",
-    &menu.main.text.level_number.font
+    "titlemessage_4.width",
+    &titlemessage_first[3].width
   },
   {
-    "main.text.level_info_1.x",
-    &menu.main.text.level_info_1.x
+    "titlemessage_4.height",
+    &titlemessage[3].height
   },
   {
-    "main.text.level_info_1.y",
-    &menu.main.text.level_info_1.y
+    "titlemessage_4.height",
+    &titlemessage_first[3].height
   },
   {
-    "main.text.level_info_1.align",
-    &menu.main.text.level_info_1.align
+    "titlemessage_4.chars",
+    &titlemessage[3].chars
   },
   {
-    "main.text.level_info_1.valign",
-    &menu.main.text.level_info_1.valign
+    "titlemessage_4.chars",
+    &titlemessage_first[3].chars
   },
   {
-    "main.text.level_info_1.chars",
-    &menu.main.text.level_info_1.size
+    "titlemessage_4.lines",
+    &titlemessage[3].lines
   },
   {
-    "main.text.level_info_1.font",
-    &menu.main.text.level_info_1.font
+    "titlemessage_4.lines",
+    &titlemessage_first[3].lines
   },
   {
-    "main.text.level_info_2.x",
-    &menu.main.text.level_info_2.x
+    "titlemessage_4.align",
+    &titlemessage[3].align
   },
   {
-    "main.text.level_info_2.y",
-    &menu.main.text.level_info_2.y
+    "titlemessage_4.align",
+    &titlemessage_first[3].align
   },
   {
-    "main.text.level_info_2.align",
-    &menu.main.text.level_info_2.align
+    "titlemessage_4.valign",
+    &titlemessage[3].valign
   },
   {
-    "main.text.level_info_2.valign",
-    &menu.main.text.level_info_2.valign
+    "titlemessage_4.valign",
+    &titlemessage_first[3].valign
   },
   {
-    "main.text.level_info_2.chars",
-    &menu.main.text.level_info_2.size
+    "titlemessage_4.font",
+    &titlemessage[3].font
   },
   {
-    "main.text.level_info_2.font",
-    &menu.main.text.level_info_2.font
+    "titlemessage_4.font",
+    &titlemessage_first[3].font
   },
   {
-    "main.text.level_info_2.font_header",
-    &menu.main.text.level_info_2.font_alt
+    "titlemessage_4.autowrap",
+    &titlemessage[3].autowrap
   },
   {
-    "main.text.level_name.x",
-    &menu.main.text.level_name.x
+    "titlemessage_4.autowrap",
+    &titlemessage_first[3].autowrap
   },
   {
-    "main.text.level_name.y",
-    &menu.main.text.level_name.y
+    "titlemessage_4.centered",
+    &titlemessage[3].centered
   },
   {
-    "main.text.level_name.align",
-    &menu.main.text.level_name.align
+    "titlemessage_4.centered",
+    &titlemessage_first[3].centered
   },
   {
-    "main.text.level_name.valign",
-    &menu.main.text.level_name.valign
+    "titlemessage_4.parse_comments",
+    &titlemessage[3].parse_comments
   },
   {
-    "main.text.level_name.chars",
-    &menu.main.text.level_name.size
+    "titlemessage_4.parse_comments",
+    &titlemessage_first[3].parse_comments
   },
   {
-    "main.text.level_name.font",
-    &menu.main.text.level_name.font
+    "titlemessage_4.sort_priority",
+    &titlemessage[3].sort_priority
   },
   {
-    "main.text.level_author.x",
-    &menu.main.text.level_author.x
+    "titlemessage_4.sort_priority",
+    &titlemessage_first[3].sort_priority
   },
   {
-    "main.text.level_author.y",
-    &menu.main.text.level_author.y
+    "titlemessage_4.fade_mode",
+    &titlemessage[3].fade_mode
   },
   {
-    "main.text.level_author.align",
-    &menu.main.text.level_author.align
+    "titlemessage_4.fade_mode",
+    &titlemessage_first[3].fade_mode
   },
   {
-    "main.text.level_author.valign",
-    &menu.main.text.level_author.valign
+    "titlemessage_4.fade_delay",
+    &titlemessage[3].fade_delay
   },
   {
-    "main.text.level_author.chars",
-    &menu.main.text.level_author.size
+    "titlemessage_4.fade_delay",
+    &titlemessage_first[3].fade_delay
   },
   {
-    "main.text.level_author.font",
-    &menu.main.text.level_author.font
+    "titlemessage_4.post_delay",
+    &titlemessage[3].post_delay
   },
   {
-    "main.text.level_year.x",
-    &menu.main.text.level_year.x
+    "titlemessage_4.post_delay",
+    &titlemessage_first[3].post_delay
   },
   {
-    "main.text.level_year.y",
-    &menu.main.text.level_year.y
+    "titlemessage_4.auto_delay",
+    &titlemessage[3].auto_delay
   },
   {
-    "main.text.level_year.align",
-    &menu.main.text.level_year.align
+    "titlemessage_4.auto_delay",
+    &titlemessage_first[3].auto_delay
   },
   {
-    "main.text.level_year.valign",
-    &menu.main.text.level_year.valign
+    "titlemessage_5.x",
+    &titlemessage[4].x
   },
   {
-    "main.text.level_year.digits",
-    &menu.main.text.level_year.size
+    "titlemessage_5.x",
+    &titlemessage_first[4].x
   },
   {
-    "main.text.level_year.font",
-    &menu.main.text.level_year.font
+    "titlemessage_5.y",
+    &titlemessage[4].y
   },
   {
-    "main.text.level_imported_from.x",
-    &menu.main.text.level_imported_from.x
+    "titlemessage_5.y",
+    &titlemessage_first[4].y
   },
   {
-    "main.text.level_imported_from.y",
-    &menu.main.text.level_imported_from.y
+    "titlemessage_5.width",
+    &titlemessage[4].width
   },
   {
-    "main.text.level_imported_from.align",
-    &menu.main.text.level_imported_from.align
+    "titlemessage_5.width",
+    &titlemessage_first[4].width
   },
   {
-    "main.text.level_imported_from.valign",
-    &menu.main.text.level_imported_from.valign
+    "titlemessage_5.height",
+    &titlemessage[4].height
   },
   {
-    "main.text.level_imported_from.chars",
-    &menu.main.text.level_imported_from.size
+    "titlemessage_5.height",
+    &titlemessage_first[4].height
   },
   {
-    "main.text.level_imported_from.font",
-    &menu.main.text.level_imported_from.font
+    "titlemessage_5.chars",
+    &titlemessage[4].chars
   },
   {
-    "main.text.level_imported_by.x",
-    &menu.main.text.level_imported_by.x
+    "titlemessage_5.chars",
+    &titlemessage_first[4].chars
   },
   {
-    "main.text.level_imported_by.y",
-    &menu.main.text.level_imported_by.y
+    "titlemessage_5.lines",
+    &titlemessage[4].lines
   },
   {
-    "main.text.level_imported_by.align",
-    &menu.main.text.level_imported_by.align
+    "titlemessage_5.lines",
+    &titlemessage_first[4].lines
   },
   {
-    "main.text.level_imported_by.valign",
-    &menu.main.text.level_imported_by.valign
+    "titlemessage_5.align",
+    &titlemessage[4].align
   },
   {
-    "main.text.level_imported_by.chars",
-    &menu.main.text.level_imported_by.size
+    "titlemessage_5.align",
+    &titlemessage_first[4].align
   },
   {
-    "main.text.level_imported_by.font",
-    &menu.main.text.level_imported_by.font
+    "titlemessage_5.valign",
+    &titlemessage[4].valign
   },
   {
-    "main.text.level_tested_by.x",
-    &menu.main.text.level_tested_by.x
+    "titlemessage_5.valign",
+    &titlemessage_first[4].valign
   },
   {
-    "main.text.level_tested_by.y",
-    &menu.main.text.level_tested_by.y
+    "titlemessage_5.font",
+    &titlemessage[4].font
   },
   {
-    "main.text.level_tested_by.align",
-    &menu.main.text.level_tested_by.align
+    "titlemessage_5.font",
+    &titlemessage_first[4].font
   },
   {
-    "main.text.level_tested_by.valign",
-    &menu.main.text.level_tested_by.valign
+    "titlemessage_5.autowrap",
+    &titlemessage[4].autowrap
   },
   {
-    "main.text.level_tested_by.chars",
-    &menu.main.text.level_tested_by.size
+    "titlemessage_5.autowrap",
+    &titlemessage_first[4].autowrap
   },
   {
-    "main.text.level_tested_by.font",
-    &menu.main.text.level_tested_by.font
+    "titlemessage_5.centered",
+    &titlemessage[4].centered
   },
   {
-    "main.text.title_1.x",
-    &menu.main.text.title_1.x
+    "titlemessage_5.centered",
+    &titlemessage_first[4].centered
   },
   {
-    "main.text.title_1.y",
-    &menu.main.text.title_1.y
+    "titlemessage_5.parse_comments",
+    &titlemessage[4].parse_comments
   },
   {
-    "main.text.title_1.align",
-    &menu.main.text.title_1.align
+    "titlemessage_5.parse_comments",
+    &titlemessage_first[4].parse_comments
   },
   {
-    "main.text.title_1.valign",
-    &menu.main.text.title_1.valign
+    "titlemessage_5.sort_priority",
+    &titlemessage[4].sort_priority
   },
   {
-    "main.text.title_1.font",
-    &menu.main.text.title_1.font
+    "titlemessage_5.sort_priority",
+    &titlemessage_first[4].sort_priority
   },
   {
-    "main.text.title_2.x",
-    &menu.main.text.title_2.x
+    "titlemessage_5.fade_mode",
+    &titlemessage[4].fade_mode
   },
   {
-    "main.text.title_2.y",
-    &menu.main.text.title_2.y
+    "titlemessage_5.fade_mode",
+    &titlemessage_first[4].fade_mode
   },
   {
-    "main.text.title_2.align",
-    &menu.main.text.title_2.align
+    "titlemessage_5.fade_delay",
+    &titlemessage[4].fade_delay
   },
   {
-    "main.text.title_2.valign",
-    &menu.main.text.title_2.valign
+    "titlemessage_5.fade_delay",
+    &titlemessage_first[4].fade_delay
   },
   {
-    "main.text.title_2.font",
-    &menu.main.text.title_2.font
+    "titlemessage_5.post_delay",
+    &titlemessage[4].post_delay
   },
   {
-    "main.text.title_3.x",
-    &menu.main.text.title_3.x
+    "titlemessage_5.post_delay",
+    &titlemessage_first[4].post_delay
   },
   {
-    "main.text.title_3.y",
-    &menu.main.text.title_3.y
+    "titlemessage_5.auto_delay",
+    &titlemessage[4].auto_delay
   },
   {
-    "main.text.title_3.align",
-    &menu.main.text.title_3.align
+    "titlemessage_5.auto_delay",
+    &titlemessage_first[4].auto_delay
   },
   {
-    "main.text.title_3.valign",
-    &menu.main.text.title_3.valign
+    "readme.x",
+    &readme.x
   },
   {
-    "main.text.title_3.font",
-    &menu.main.text.title_3.font
+    "readme.y",
+    &readme.y
   },
   {
-    "main.input.name.x",
-    &menu.main.input.name.x
+    "readme.width",
+    &readme.width
   },
   {
-    "main.input.name.y",
-    &menu.main.input.name.y
+    "readme.height",
+    &readme.height
   },
   {
-    "main.input.name.align",
-    &menu.main.input.name.align
+    "readme.chars",
+    &readme.chars
   },
   {
-    "main.input.name.valign",
-    &menu.main.input.name.valign
+    "readme.lines",
+    &readme.lines
   },
   {
-    "main.input.name.font",
-    &menu.main.input.name.font
+    "readme.align",
+    &readme.align
   },
   {
-    "preview.x",
-    &preview.x
+    "readme.valign",
+    &readme.valign
   },
   {
-    "preview.y",
-    &preview.y
+    "readme.font",
+    &readme.font
   },
   {
-    "preview.align",
-    &preview.align
+    "readme.autowrap",
+    &readme.autowrap
   },
   {
-    "preview.valign",
-    &preview.valign
+    "readme.centered",
+    &readme.centered
   },
   {
-    "preview.xsize",
-    &preview.xsize
+    "readme.parse_comments",
+    &readme.parse_comments
   },
   {
-    "preview.ysize",
-    &preview.ysize
+    "readme.sort_priority",
+    &readme.sort_priority
   },
   {
-    "preview.xoffset",
-    &preview.xoffset
+    "global.num_toons",
+    &global.num_toons
   },
   {
-    "preview.yoffset",
-    &preview.yoffset
+    "border.draw_masked.TITLE",
+    &border.draw_masked[GFX_SPECIAL_ARG_TITLE]
   },
   {
-    "preview.tile_size",
-    &preview.tile_size
+    "border.draw_masked.MAIN",
+    &border.draw_masked[GFX_SPECIAL_ARG_MAIN]
   },
   {
-    "preview.step_offset",
-    &preview.step_offset
+    "border.draw_masked.LEVELS",
+    &border.draw_masked[GFX_SPECIAL_ARG_LEVELS]
   },
   {
-    "preview.step_delay",
-    &preview.step_delay
+    "border.draw_masked.LEVELNR",
+    &border.draw_masked[GFX_SPECIAL_ARG_LEVELNR]
   },
   {
-    "preview.anim_mode",
-    &preview.anim_mode
+    "border.draw_masked.SCORES",
+    &border.draw_masked[GFX_SPECIAL_ARG_SCORES]
   },
   {
-    "door_1.width",
-    &door_1.width
+    "border.draw_masked.EDITOR",
+    &border.draw_masked[GFX_SPECIAL_ARG_EDITOR]
   },
   {
-    "door_1.height",
-    &door_1.height
+    "border.draw_masked.INFO",
+    &border.draw_masked[GFX_SPECIAL_ARG_INFO]
   },
   {
-    "door_1.step_offset",
-    &door_1.step_offset
+    "border.draw_masked.SETUP",
+    &border.draw_masked[GFX_SPECIAL_ARG_SETUP]
   },
   {
-    "door_1.step_delay",
-    &door_1.step_delay
+    "border.draw_masked.PLAYING",
+    &border.draw_masked[GFX_SPECIAL_ARG_PLAYING]
   },
   {
-    "door_1.anim_mode",
-    &door_1.anim_mode
+    "border.draw_masked.DOOR",
+    &border.draw_masked[GFX_SPECIAL_ARG_DOOR]
   },
   {
-    "door_2.width",
-    &door_2.width
+    "border.draw_masked_when_fading",
+    &border.draw_masked_when_fading
   },
   {
-    "door_2.height",
-    &door_2.height
+    "init.busy.x",
+    &init.busy.x
   },
   {
-    "door_2.step_offset",
-    &door_2.step_offset
+    "init.busy.y",
+    &init.busy.y
   },
   {
-    "door_2.step_delay",
-    &door_2.step_delay
+    "init.busy.align",
+    &init.busy.align
   },
   {
-    "door_2.anim_mode",
-    &door_2.anim_mode
+    "init.busy.valign",
+    &init.busy.valign
   },
   {
-    "game.panel.level_number.x",
-    &game.panel.level_number.x
+    "menu.enter_menu.fade_mode",
+    &menu.enter_menu.fade_mode
   },
   {
-    "game.panel.level_number.y",
-    &game.panel.level_number.y
+    "menu.enter_menu.fade_delay",
+    &menu.enter_menu.fade_delay
   },
   {
-    "game.panel.level_number.align",
-    &game.panel.level_number.align
+    "menu.enter_menu.post_delay",
+    &menu.enter_menu.post_delay
   },
   {
-    "game.panel.level_number.valign",
-    &game.panel.level_number.valign
+    "menu.leave_menu.fade_mode",
+    &menu.leave_menu.fade_mode
   },
   {
-    "game.panel.level_number.digits",
-    &game.panel.level_number.size
+    "menu.leave_menu.fade_delay",
+    &menu.leave_menu.fade_delay
   },
   {
-    "game.panel.level_number.font",
-    &game.panel.level_number.font
+    "menu.leave_menu.post_delay",
+    &menu.leave_menu.post_delay
   },
   {
-    "game.panel.level_number.font_narrow",
-    &game.panel.level_number.font_alt
+    "menu.enter_screen.fade_mode",
+    &menu.enter_screen[GFX_SPECIAL_ARG_DEFAULT].fade_mode
   },
   {
-    "game.panel.level_number.draw_masked",
-    &game.panel.level_number.draw_masked
+    "menu.enter_screen.fade_delay",
+    &menu.enter_screen[GFX_SPECIAL_ARG_DEFAULT].fade_delay
   },
   {
-    "game.panel.level_number.draw_order",
-    &game.panel.level_number.sort_priority
+    "menu.enter_screen.post_delay",
+    &menu.enter_screen[GFX_SPECIAL_ARG_DEFAULT].post_delay
   },
   {
-    "game.panel.gems.x",
-    &game.panel.gems.x
+    "menu.leave_screen.fade_mode",
+    &menu.leave_screen[GFX_SPECIAL_ARG_DEFAULT].fade_mode
   },
   {
-    "game.panel.gems.y",
-    &game.panel.gems.y
+    "menu.leave_screen.fade_delay",
+    &menu.leave_screen[GFX_SPECIAL_ARG_DEFAULT].fade_delay
   },
   {
-    "game.panel.gems.align",
-    &game.panel.gems.align
+    "menu.leave_screen.post_delay",
+    &menu.leave_screen[GFX_SPECIAL_ARG_DEFAULT].post_delay
   },
   {
-    "game.panel.gems.valign",
-    &game.panel.gems.valign
+    "menu.next_screen.fade_mode",
+    &menu.next_screen[GFX_SPECIAL_ARG_DEFAULT].fade_mode
   },
   {
-    "game.panel.gems.digits",
-    &game.panel.gems.size
+    "menu.next_screen.fade_delay",
+    &menu.next_screen[GFX_SPECIAL_ARG_DEFAULT].fade_delay
   },
   {
-    "game.panel.gems.font",
-    &game.panel.gems.font
+    "menu.next_screen.post_delay",
+    &menu.next_screen[GFX_SPECIAL_ARG_DEFAULT].post_delay
   },
   {
-    "game.panel.gems.draw_masked",
-    &game.panel.gems.draw_masked
+    "menu.enter_screen.TITLE.fade_mode",
+    &menu.enter_screen[GFX_SPECIAL_ARG_TITLE].fade_mode
   },
   {
-    "game.panel.gems.draw_order",
-    &game.panel.gems.sort_priority
+    "menu.enter_screen.TITLE.fade_delay",
+    &menu.enter_screen[GFX_SPECIAL_ARG_TITLE].fade_delay
   },
   {
-    "game.panel.inventory_count.x",
-    &game.panel.inventory_count.x
+    "menu.enter_screen.TITLE.post_delay",
+    &menu.enter_screen[GFX_SPECIAL_ARG_TITLE].post_delay
   },
   {
-    "game.panel.inventory_count.y",
-    &game.panel.inventory_count.y
+    "menu.enter_screen.TITLE.auto_delay",
+    &menu.enter_screen[GFX_SPECIAL_ARG_TITLE].auto_delay
   },
   {
-    "game.panel.inventory_count.align",
-    &game.panel.inventory_count.align
+    "menu.enter_screen.SCORES.fade_mode",
+    &menu.enter_screen[GFX_SPECIAL_ARG_SCORES].fade_mode
   },
   {
-    "game.panel.inventory_count.valign",
-    &game.panel.inventory_count.valign
+    "menu.enter_screen.SCORES.fade_delay",
+    &menu.enter_screen[GFX_SPECIAL_ARG_SCORES].fade_delay
   },
   {
-    "game.panel.inventory_count.digits",
-    &game.panel.inventory_count.size
+    "menu.enter_screen.SCORES.post_delay",
+    &menu.enter_screen[GFX_SPECIAL_ARG_SCORES].post_delay
   },
   {
-    "game.panel.inventory_count.font",
-    &game.panel.inventory_count.font
+    "menu.enter_screen.EDITOR.fade_mode",
+    &menu.enter_screen[GFX_SPECIAL_ARG_EDITOR].fade_mode
   },
   {
-    "game.panel.inventory_count.draw_masked",
-    &game.panel.inventory_count.draw_masked
+    "menu.enter_screen.EDITOR.fade_delay",
+    &menu.enter_screen[GFX_SPECIAL_ARG_EDITOR].fade_delay
   },
   {
-    "game.panel.inventory_count.draw_order",
-    &game.panel.inventory_count.sort_priority
+    "menu.enter_screen.EDITOR.post_delay",
+    &menu.enter_screen[GFX_SPECIAL_ARG_EDITOR].post_delay
   },
   {
-    "game.panel.inventory_first_1.x",
-    &game.panel.inventory_first[0].x
+    "menu.enter_screen.INFO.fade_mode",
+    &menu.enter_screen[GFX_SPECIAL_ARG_INFO].fade_mode
   },
   {
-    "game.panel.inventory_first_1.y",
-    &game.panel.inventory_first[0].y
+    "menu.enter_screen.INFO.fade_delay",
+    &menu.enter_screen[GFX_SPECIAL_ARG_INFO].fade_delay
   },
   {
-    "game.panel.inventory_first_1.tile_size",
-    &game.panel.inventory_first[0].size
+    "menu.enter_screen.INFO.post_delay",
+    &menu.enter_screen[GFX_SPECIAL_ARG_INFO].post_delay
   },
   {
-    "game.panel.inventory_first_1.draw_masked",
-    &game.panel.inventory_first[0].draw_masked
+    "menu.enter_screen.PLAYING.fade_mode",
+    &menu.enter_screen[GFX_SPECIAL_ARG_PLAYING].fade_mode
   },
   {
-    "game.panel.inventory_first_1.draw_order",
-    &game.panel.inventory_first[0].sort_priority
+    "menu.enter_screen.PLAYING.fade_delay",
+    &menu.enter_screen[GFX_SPECIAL_ARG_PLAYING].fade_delay
   },
   {
-    "game.panel.inventory_first_2.x",
-    &game.panel.inventory_first[1].x
+    "menu.enter_screen.PLAYING.post_delay",
+    &menu.enter_screen[GFX_SPECIAL_ARG_PLAYING].post_delay
   },
   {
-    "game.panel.inventory_first_2.y",
-    &game.panel.inventory_first[1].y
+    "menu.leave_screen.TITLE.fade_mode",
+    &menu.leave_screen[GFX_SPECIAL_ARG_TITLE].fade_mode
   },
   {
-    "game.panel.inventory_first_2.tile_size",
-    &game.panel.inventory_first[1].size
+    "menu.leave_screen.TITLE.fade_delay",
+    &menu.leave_screen[GFX_SPECIAL_ARG_TITLE].fade_delay
   },
   {
-    "game.panel.inventory_first_2.draw_masked",
-    &game.panel.inventory_first[1].draw_masked
+    "menu.leave_screen.TITLE.post_delay",
+    &menu.leave_screen[GFX_SPECIAL_ARG_TITLE].post_delay
   },
   {
-    "game.panel.inventory_first_2.draw_order",
-    &game.panel.inventory_first[1].sort_priority
+    "menu.leave_screen.TITLE.auto_delay",
+    &menu.leave_screen[GFX_SPECIAL_ARG_TITLE].auto_delay
   },
   {
-    "game.panel.inventory_first_3.x",
-    &game.panel.inventory_first[2].x
+    "menu.leave_screen.SCORES.fade_mode",
+    &menu.leave_screen[GFX_SPECIAL_ARG_SCORES].fade_mode
   },
   {
-    "game.panel.inventory_first_3.y",
-    &game.panel.inventory_first[2].y
+    "menu.leave_screen.SCORES.fade_delay",
+    &menu.leave_screen[GFX_SPECIAL_ARG_SCORES].fade_delay
   },
   {
-    "game.panel.inventory_first_3.tile_size",
-    &game.panel.inventory_first[2].size
+    "menu.leave_screen.SCORES.post_delay",
+    &menu.leave_screen[GFX_SPECIAL_ARG_SCORES].post_delay
   },
   {
-    "game.panel.inventory_first_3.draw_masked",
-    &game.panel.inventory_first[2].draw_masked
+    "menu.leave_screen.EDITOR.fade_mode",
+    &menu.leave_screen[GFX_SPECIAL_ARG_EDITOR].fade_mode
   },
   {
-    "game.panel.inventory_first_3.draw_order",
-    &game.panel.inventory_first[2].sort_priority
+    "menu.leave_screen.EDITOR.fade_delay",
+    &menu.leave_screen[GFX_SPECIAL_ARG_EDITOR].fade_delay
   },
   {
-    "game.panel.inventory_first_4.x",
-    &game.panel.inventory_first[3].x
+    "menu.leave_screen.EDITOR.post_delay",
+    &menu.leave_screen[GFX_SPECIAL_ARG_EDITOR].post_delay
   },
   {
-    "game.panel.inventory_first_4.y",
-    &game.panel.inventory_first[3].y
+    "menu.leave_screen.INFO.fade_mode",
+    &menu.leave_screen[GFX_SPECIAL_ARG_INFO].fade_mode
   },
   {
-    "game.panel.inventory_first_4.tile_size",
-    &game.panel.inventory_first[3].size
+    "menu.leave_screen.INFO.fade_delay",
+    &menu.leave_screen[GFX_SPECIAL_ARG_INFO].fade_delay
   },
   {
-    "game.panel.inventory_first_4.draw_masked",
-    &game.panel.inventory_first[3].draw_masked
+    "menu.leave_screen.INFO.post_delay",
+    &menu.leave_screen[GFX_SPECIAL_ARG_INFO].post_delay
   },
   {
-    "game.panel.inventory_first_4.draw_order",
-    &game.panel.inventory_first[3].sort_priority
+    "menu.leave_screen.PLAYING.fade_mode",
+    &menu.leave_screen[GFX_SPECIAL_ARG_PLAYING].fade_mode
   },
   {
-    "game.panel.inventory_first_5.x",
-    &game.panel.inventory_first[4].x
+    "menu.leave_screen.PLAYING.fade_delay",
+    &menu.leave_screen[GFX_SPECIAL_ARG_PLAYING].fade_delay
   },
   {
-    "game.panel.inventory_first_5.y",
-    &game.panel.inventory_first[4].y
+    "menu.leave_screen.PLAYING.post_delay",
+    &menu.leave_screen[GFX_SPECIAL_ARG_PLAYING].post_delay
   },
   {
-    "game.panel.inventory_first_5.tile_size",
-    &game.panel.inventory_first[4].size
+    "menu.next_screen.TITLE.fade_mode",
+    &menu.next_screen[GFX_SPECIAL_ARG_TITLE].fade_mode
   },
   {
-    "game.panel.inventory_first_5.draw_masked",
-    &game.panel.inventory_first[4].draw_masked
+    "menu.next_screen.TITLE.fade_delay",
+    &menu.next_screen[GFX_SPECIAL_ARG_TITLE].fade_delay
   },
   {
-    "game.panel.inventory_first_5.draw_order",
-    &game.panel.inventory_first[4].sort_priority
+    "menu.next_screen.TITLE.post_delay",
+    &menu.next_screen[GFX_SPECIAL_ARG_TITLE].post_delay
   },
   {
-    "game.panel.inventory_first_6.x",
-    &game.panel.inventory_first[5].x
+    "menu.next_screen.TITLE.auto_delay",
+    &menu.next_screen[GFX_SPECIAL_ARG_TITLE].auto_delay
   },
   {
-    "game.panel.inventory_first_6.y",
-    &game.panel.inventory_first[5].y
+    "menu.next_screen.INFO.fade_mode",
+    &menu.next_screen[GFX_SPECIAL_ARG_INFO].fade_mode
   },
   {
-    "game.panel.inventory_first_6.tile_size",
-    &game.panel.inventory_first[5].size
+    "menu.next_screen.INFO.fade_delay",
+    &menu.next_screen[GFX_SPECIAL_ARG_INFO].fade_delay
   },
   {
-    "game.panel.inventory_first_6.draw_masked",
-    &game.panel.inventory_first[5].draw_masked
+    "menu.next_screen.INFO.post_delay",
+    &menu.next_screen[GFX_SPECIAL_ARG_INFO].post_delay
   },
   {
-    "game.panel.inventory_first_6.draw_order",
-    &game.panel.inventory_first[5].sort_priority
+    "menu.draw_xoffset",
+    &menu.draw_xoffset[GFX_SPECIAL_ARG_DEFAULT]
   },
   {
-    "game.panel.inventory_first_7.x",
-    &game.panel.inventory_first[6].x
+    "menu.draw_yoffset",
+    &menu.draw_yoffset[GFX_SPECIAL_ARG_DEFAULT]
   },
   {
-    "game.panel.inventory_first_7.y",
-    &game.panel.inventory_first[6].y
+    "menu.draw_xoffset.MAIN",
+    &menu.draw_xoffset[GFX_SPECIAL_ARG_MAIN]
   },
   {
-    "game.panel.inventory_first_7.tile_size",
-    &game.panel.inventory_first[6].size
+    "menu.draw_yoffset.MAIN",
+    &menu.draw_yoffset[GFX_SPECIAL_ARG_MAIN]
   },
   {
-    "game.panel.inventory_first_7.draw_masked",
-    &game.panel.inventory_first[6].draw_masked
+    "menu.draw_xoffset.LEVELS",
+    &menu.draw_xoffset[GFX_SPECIAL_ARG_LEVELS]
   },
   {
-    "game.panel.inventory_first_7.draw_order",
-    &game.panel.inventory_first[6].sort_priority
+    "menu.draw_yoffset.LEVELS",
+    &menu.draw_yoffset[GFX_SPECIAL_ARG_LEVELS]
   },
   {
-    "game.panel.inventory_first_8.x",
-    &game.panel.inventory_first[7].x
+    "menu.draw_xoffset.LEVELNR",
+    &menu.draw_xoffset[GFX_SPECIAL_ARG_LEVELNR]
   },
   {
-    "game.panel.inventory_first_8.y",
-    &game.panel.inventory_first[7].y
+    "menu.draw_yoffset.LEVELNR",
+    &menu.draw_yoffset[GFX_SPECIAL_ARG_LEVELNR]
   },
   {
-    "game.panel.inventory_first_8.tile_size",
-    &game.panel.inventory_first[7].size
+    "menu.draw_xoffset.SCORES",
+    &menu.draw_xoffset[GFX_SPECIAL_ARG_SCORES]
   },
   {
-    "game.panel.inventory_first_8.draw_masked",
-    &game.panel.inventory_first[7].draw_masked
+    "menu.draw_yoffset.SCORES",
+    &menu.draw_yoffset[GFX_SPECIAL_ARG_SCORES]
   },
   {
-    "game.panel.inventory_first_8.draw_order",
-    &game.panel.inventory_first[7].sort_priority
+    "menu.draw_xoffset.EDITOR",
+    &menu.draw_xoffset[GFX_SPECIAL_ARG_EDITOR]
   },
   {
-    "game.panel.inventory_last_1.x",
-    &game.panel.inventory_last[0].x
+    "menu.draw_yoffset.EDITOR",
+    &menu.draw_yoffset[GFX_SPECIAL_ARG_EDITOR]
   },
   {
-    "game.panel.inventory_last_1.y",
-    &game.panel.inventory_last[0].y
+    "menu.draw_xoffset.INFO",
+    &menu.draw_xoffset[GFX_SPECIAL_ARG_INFO]
   },
   {
-    "game.panel.inventory_last_1.tile_size",
-    &game.panel.inventory_last[0].size
+    "menu.draw_yoffset.INFO",
+    &menu.draw_yoffset[GFX_SPECIAL_ARG_INFO]
   },
   {
-    "game.panel.inventory_last_1.draw_masked",
-    &game.panel.inventory_last[0].draw_masked
+    "menu.draw_xoffset.INFO[ELEMENTS]",
+    &menu.draw_xoffset_info[GFX_SPECIAL_ARG_INFO_ELEMENTS]
   },
   {
-    "game.panel.inventory_last_1.draw_order",
-    &game.panel.inventory_last[0].sort_priority
+    "menu.draw_yoffset.INFO[ELEMENTS]",
+    &menu.draw_yoffset_info[GFX_SPECIAL_ARG_INFO_ELEMENTS]
   },
   {
-    "game.panel.inventory_last_2.x",
-    &game.panel.inventory_last[1].x
+    "menu.draw_xoffset.INFO[MUSIC]",
+    &menu.draw_xoffset_info[GFX_SPECIAL_ARG_INFO_MUSIC]
   },
   {
-    "game.panel.inventory_last_2.y",
-    &game.panel.inventory_last[1].y
+    "menu.draw_yoffset.INFO[MUSIC]",
+    &menu.draw_yoffset_info[GFX_SPECIAL_ARG_INFO_MUSIC]
   },
   {
-    "game.panel.inventory_last_2.tile_size",
-    &game.panel.inventory_last[1].size
+    "menu.draw_xoffset.INFO[CREDITS]",
+    &menu.draw_xoffset_info[GFX_SPECIAL_ARG_INFO_CREDITS]
   },
   {
-    "game.panel.inventory_last_2.draw_masked",
-    &game.panel.inventory_last[1].draw_masked
+    "menu.draw_yoffset.INFO[CREDITS]",
+    &menu.draw_yoffset_info[GFX_SPECIAL_ARG_INFO_CREDITS]
   },
   {
-    "game.panel.inventory_last_2.draw_order",
-    &game.panel.inventory_last[1].sort_priority
+    "menu.draw_xoffset.INFO[PROGRAM]",
+    &menu.draw_xoffset_info[GFX_SPECIAL_ARG_INFO_PROGRAM]
   },
   {
-    "game.panel.inventory_last_3.x",
-    &game.panel.inventory_last[2].x
+    "menu.draw_yoffset.INFO[PROGRAM]",
+    &menu.draw_yoffset_info[GFX_SPECIAL_ARG_INFO_PROGRAM]
   },
   {
-    "game.panel.inventory_last_3.y",
-    &game.panel.inventory_last[2].y
+    "menu.draw_xoffset.INFO[VERSION]",
+    &menu.draw_xoffset_info[GFX_SPECIAL_ARG_INFO_VERSION]
   },
   {
-    "game.panel.inventory_last_3.tile_size",
-    &game.panel.inventory_last[2].size
+    "menu.draw_yoffset.INFO[VERSION]",
+    &menu.draw_yoffset_info[GFX_SPECIAL_ARG_INFO_VERSION]
   },
   {
-    "game.panel.inventory_last_3.draw_masked",
-    &game.panel.inventory_last[2].draw_masked
+    "menu.draw_xoffset.INFO[LEVELSET]",
+    &menu.draw_xoffset_info[GFX_SPECIAL_ARG_INFO_LEVELSET]
   },
   {
-    "game.panel.inventory_last_3.draw_order",
-    &game.panel.inventory_last[2].sort_priority
+    "menu.draw_yoffset.INFO[LEVELSET]",
+    &menu.draw_yoffset_info[GFX_SPECIAL_ARG_INFO_LEVELSET]
   },
   {
-    "game.panel.inventory_last_4.x",
-    &game.panel.inventory_last[3].x
+    "menu.draw_xoffset.SETUP",
+    &menu.draw_xoffset[GFX_SPECIAL_ARG_SETUP]
   },
   {
-    "game.panel.inventory_last_4.y",
-    &game.panel.inventory_last[3].y
+    "menu.draw_yoffset.SETUP",
+    &menu.draw_yoffset[GFX_SPECIAL_ARG_SETUP]
   },
   {
-    "game.panel.inventory_last_4.tile_size",
-    &game.panel.inventory_last[3].size
+    "menu.draw_xoffset.SETUP[GAME]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_GAME]
   },
   {
-    "game.panel.inventory_last_4.draw_masked",
-    &game.panel.inventory_last[3].draw_masked
+    "menu.draw_yoffset.SETUP[GAME]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_GAME]
   },
   {
-    "game.panel.inventory_last_4.draw_order",
-    &game.panel.inventory_last[3].sort_priority
+    "menu.draw_xoffset.SETUP[EDITOR]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_EDITOR]
   },
   {
-    "game.panel.inventory_last_5.x",
-    &game.panel.inventory_last[4].x
+    "menu.draw_yoffset.SETUP[EDITOR]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_EDITOR]
   },
   {
-    "game.panel.inventory_last_5.y",
-    &game.panel.inventory_last[4].y
+    "menu.draw_xoffset.SETUP[GRAPHICS]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_GRAPHICS]
   },
   {
-    "game.panel.inventory_last_5.tile_size",
-    &game.panel.inventory_last[4].size
+    "menu.draw_yoffset.SETUP[GRAPHICS]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_GRAPHICS]
   },
   {
-    "game.panel.inventory_last_5.draw_masked",
-    &game.panel.inventory_last[4].draw_masked
+    "menu.draw_xoffset.SETUP[SOUND]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SOUND]
   },
   {
-    "game.panel.inventory_last_5.draw_order",
-    &game.panel.inventory_last[4].sort_priority
+    "menu.draw_yoffset.SETUP[SOUND]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SOUND]
   },
   {
-    "game.panel.inventory_last_6.x",
-    &game.panel.inventory_last[5].x
+    "menu.draw_xoffset.SETUP[ARTWORK]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_ARTWORK]
   },
   {
-    "game.panel.inventory_last_6.y",
-    &game.panel.inventory_last[5].y
+    "menu.draw_yoffset.SETUP[ARTWORK]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_ARTWORK]
   },
   {
-    "game.panel.inventory_last_6.tile_size",
-    &game.panel.inventory_last[5].size
+    "menu.draw_xoffset.SETUP[INPUT]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_INPUT]
   },
   {
-    "game.panel.inventory_last_6.draw_masked",
-    &game.panel.inventory_last[5].draw_masked
+    "menu.draw_yoffset.SETUP[INPUT]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_INPUT]
   },
   {
-    "game.panel.inventory_last_6.draw_order",
-    &game.panel.inventory_last[5].sort_priority
+    "menu.draw_xoffset.SETUP[TOUCH]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_TOUCH]
   },
   {
-    "game.panel.inventory_last_7.x",
-    &game.panel.inventory_last[6].x
+    "menu.draw_yoffset.SETUP[TOUCH]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_TOUCH]
   },
   {
-    "game.panel.inventory_last_7.y",
-    &game.panel.inventory_last[6].y
+    "menu.draw_xoffset.SETUP[SHORTCUTS]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS]
   },
   {
-    "game.panel.inventory_last_7.tile_size",
-    &game.panel.inventory_last[6].size
+    "menu.draw_yoffset.SETUP[SHORTCUTS]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS]
   },
   {
-    "game.panel.inventory_last_7.draw_masked",
-    &game.panel.inventory_last[6].draw_masked
+    "menu.draw_xoffset.SETUP[SHORTCUTS_1]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_1]
   },
   {
-    "game.panel.inventory_last_7.draw_order",
-    &game.panel.inventory_last[6].sort_priority
+    "menu.draw_yoffset.SETUP[SHORTCUTS_1]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_1]
   },
   {
-    "game.panel.inventory_last_8.x",
-    &game.panel.inventory_last[7].x
+    "menu.draw_xoffset.SETUP[SHORTCUTS_2]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_2]
   },
   {
-    "game.panel.inventory_last_8.y",
-    &game.panel.inventory_last[7].y
+    "menu.draw_yoffset.SETUP[SHORTCUTS_2]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_2]
   },
   {
-    "game.panel.inventory_last_8.tile_size",
-    &game.panel.inventory_last[7].size
+    "menu.draw_xoffset.SETUP[SHORTCUTS_3]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_3]
   },
   {
-    "game.panel.inventory_last_8.draw_masked",
-    &game.panel.inventory_last[7].draw_masked
+    "menu.draw_yoffset.SETUP[SHORTCUTS_3]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_3]
   },
   {
-    "game.panel.inventory_last_8.draw_order",
-    &game.panel.inventory_last[7].sort_priority
+    "menu.draw_xoffset.SETUP[SHORTCUTS_4]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_4]
   },
   {
-    "game.panel.key_1.x",
-    &game.panel.key[0].x
+    "menu.draw_yoffset.SETUP[SHORTCUTS_4]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_4]
   },
   {
-    "game.panel.key_1.y",
-    &game.panel.key[0].y
+    "menu.draw_xoffset.SETUP[SHORTCUTS_5]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_5]
   },
   {
-    "game.panel.key_1.tile_size",
-    &game.panel.key[0].size
+    "menu.draw_yoffset.SETUP[SHORTCUTS_5]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_5]
   },
   {
-    "game.panel.key_1.draw_masked",
-    &game.panel.key[0].draw_masked
+    "menu.draw_xoffset.SETUP[CHOOSE_ARTWORK]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_CHOOSE_ARTWORK]
   },
   {
-    "game.panel.key_1.draw_order",
-    &game.panel.key[0].sort_priority
+    "menu.draw_yoffset.SETUP[CHOOSE_ARTWORK]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_CHOOSE_ARTWORK]
   },
   {
-    "game.panel.key_2.x",
-    &game.panel.key[1].x
+    "menu.draw_xoffset.SETUP[CHOOSE_OTHER]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_CHOOSE_OTHER]
   },
   {
-    "game.panel.key_2.y",
-    &game.panel.key[1].y
+    "menu.draw_yoffset.SETUP[CHOOSE_OTHER]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_CHOOSE_OTHER]
   },
   {
-    "game.panel.key_2.tile_size",
-    &game.panel.key[1].size
+    "menu.scrollbar_xoffset",
+    &menu.scrollbar_xoffset
   },
   {
-    "game.panel.key_2.draw_masked",
-    &game.panel.key[1].draw_masked
+    "menu.list_size",
+    &menu.list_size[GFX_SPECIAL_ARG_DEFAULT]
   },
   {
-    "game.panel.key_2.draw_order",
-    &game.panel.key[1].sort_priority
+    "menu.list_size.LEVELS",
+    &menu.list_size[GFX_SPECIAL_ARG_LEVELS]
   },
   {
-    "game.panel.key_3.x",
-    &game.panel.key[2].x
+    "menu.list_size.LEVELNR",
+    &menu.list_size[GFX_SPECIAL_ARG_LEVELNR]
   },
   {
-    "game.panel.key_3.y",
-    &game.panel.key[2].y
+    "menu.list_size.SCORES",
+    &menu.list_size[GFX_SPECIAL_ARG_SCORES]
   },
   {
-    "game.panel.key_3.tile_size",
-    &game.panel.key[2].size
+    "menu.list_size.INFO",
+    &menu.list_size[GFX_SPECIAL_ARG_INFO]
   },
   {
-    "game.panel.key_3.draw_masked",
-    &game.panel.key[2].draw_masked
+    "menu.list_size.INFO[ELEMENTS]",
+    &menu.list_size_info[GFX_SPECIAL_ARG_INFO_ELEMENTS]
   },
   {
-    "game.panel.key_3.draw_order",
-    &game.panel.key[2].sort_priority
+    "menu.list_size.SETUP",
+    &menu.list_size[GFX_SPECIAL_ARG_SETUP]
   },
   {
-    "game.panel.key_4.x",
-    &game.panel.key[3].x
+    "main.button.name.x",
+    &menu.main.button.name.x
   },
   {
-    "game.panel.key_4.y",
-    &game.panel.key[3].y
+    "main.button.name.y",
+    &menu.main.button.name.y
   },
   {
-    "game.panel.key_4.tile_size",
-    &game.panel.key[3].size
+    "main.button.levels.x",
+    &menu.main.button.levels.x
   },
   {
-    "game.panel.key_4.draw_masked",
-    &game.panel.key[3].draw_masked
+    "main.button.levels.y",
+    &menu.main.button.levels.y
   },
   {
-    "game.panel.key_4.draw_order",
-    &game.panel.key[3].sort_priority
+    "main.button.scores.x",
+    &menu.main.button.scores.x
   },
   {
-    "game.panel.key_5.x",
-    &game.panel.key[4].x
+    "main.button.scores.y",
+    &menu.main.button.scores.y
   },
   {
-    "game.panel.key_5.y",
-    &game.panel.key[4].y
+    "main.button.editor.x",
+    &menu.main.button.editor.x
   },
   {
-    "game.panel.key_5.tile_size",
-    &game.panel.key[4].size
+    "main.button.editor.y",
+    &menu.main.button.editor.y
   },
   {
-    "game.panel.key_5.draw_masked",
-    &game.panel.key[4].draw_masked
+    "main.button.info.x",
+    &menu.main.button.info.x
   },
   {
-    "game.panel.key_5.draw_order",
-    &game.panel.key[4].sort_priority
+    "main.button.info.y",
+    &menu.main.button.info.y
   },
   {
-    "game.panel.key_6.x",
-    &game.panel.key[5].x
+    "main.button.game.x",
+    &menu.main.button.game.x
   },
   {
-    "game.panel.key_6.y",
-    &game.panel.key[5].y
+    "main.button.game.y",
+    &menu.main.button.game.y
   },
   {
-    "game.panel.key_6.tile_size",
-    &game.panel.key[5].size
+    "main.button.setup.x",
+    &menu.main.button.setup.x
   },
   {
-    "game.panel.key_6.draw_masked",
-    &game.panel.key[5].draw_masked
+    "main.button.setup.y",
+    &menu.main.button.setup.y
   },
   {
-    "game.panel.key_6.draw_order",
-    &game.panel.key[5].sort_priority
+    "main.button.quit.x",
+    &menu.main.button.quit.x
   },
   {
-    "game.panel.key_7.x",
-    &game.panel.key[6].x
+    "main.button.quit.y",
+    &menu.main.button.quit.y
   },
   {
-    "game.panel.key_7.y",
-    &game.panel.key[6].y
+    "main.button.prev_level.x",
+    &menu.main.button.prev_level.x
   },
   {
-    "game.panel.key_7.tile_size",
-    &game.panel.key[6].size
+    "main.button.prev_level.y",
+    &menu.main.button.prev_level.y
   },
   {
-    "game.panel.key_7.draw_masked",
-    &game.panel.key[6].draw_masked
+    "main.button.next_level.x",
+    &menu.main.button.next_level.x
   },
   {
-    "game.panel.key_7.draw_order",
-    &game.panel.key[6].sort_priority
+    "main.button.next_level.y",
+    &menu.main.button.next_level.y
   },
   {
-    "game.panel.key_8.x",
-    &game.panel.key[7].x
+    "main.text.name.x",
+    &menu.main.text.name.x
   },
   {
-    "game.panel.key_8.y",
-    &game.panel.key[7].y
+    "main.text.name.y",
+    &menu.main.text.name.y
   },
   {
-    "game.panel.key_8.tile_size",
-    &game.panel.key[7].size
+    "main.text.name.width",
+    &menu.main.text.name.width
   },
   {
-    "game.panel.key_8.draw_masked",
-    &game.panel.key[7].draw_masked
+    "main.text.name.height",
+    &menu.main.text.name.height
   },
   {
-    "game.panel.key_8.draw_order",
-    &game.panel.key[7].sort_priority
+    "main.text.name.align",
+    &menu.main.text.name.align
   },
   {
-    "game.panel.key_white.x",
-    &game.panel.key_white.x
+    "main.text.name.valign",
+    &menu.main.text.name.valign
   },
   {
-    "game.panel.key_white.y",
-    &game.panel.key_white.y
+    "main.text.name.font",
+    &menu.main.text.name.font
   },
   {
-    "game.panel.key_white.tile_size",
-    &game.panel.key_white.size
+    "main.text.levels.x",
+    &menu.main.text.levels.x
   },
   {
-    "game.panel.key_white.draw_masked",
-    &game.panel.key_white.draw_masked
+    "main.text.levels.y",
+    &menu.main.text.levels.y
   },
   {
-    "game.panel.key_white.draw_order",
-    &game.panel.key_white.sort_priority
+    "main.text.levels.width",
+    &menu.main.text.levels.width
   },
   {
-    "game.panel.key_white_count.x",
-    &game.panel.key_white_count.x
+    "main.text.levels.height",
+    &menu.main.text.levels.height
   },
   {
-    "game.panel.key_white_count.y",
-    &game.panel.key_white_count.y
+    "main.text.levels.align",
+    &menu.main.text.levels.align
   },
   {
-    "game.panel.key_white_count.align",
-    &game.panel.key_white_count.align
+    "main.text.levels.valign",
+    &menu.main.text.levels.valign
   },
   {
-    "game.panel.key_white_count.valign",
-    &game.panel.key_white_count.valign
+    "main.text.levels.font",
+    &menu.main.text.levels.font
   },
   {
-    "game.panel.key_white_count.digits",
-    &game.panel.key_white_count.size
+    "main.text.scores.x",
+    &menu.main.text.scores.x
   },
   {
-    "game.panel.key_white_count.font",
-    &game.panel.key_white_count.font
+    "main.text.scores.y",
+    &menu.main.text.scores.y
   },
   {
-    "game.panel.key_white_count.draw_masked",
-    &game.panel.key_white_count.draw_masked
+    "main.text.scores.width",
+    &menu.main.text.scores.width
   },
   {
-    "game.panel.key_white_count.draw_order",
-    &game.panel.key_white_count.sort_priority
+    "main.text.scores.height",
+    &menu.main.text.scores.height
   },
   {
-    "game.panel.score.x",
-    &game.panel.score.x
+    "main.text.scores.align",
+    &menu.main.text.scores.align
   },
   {
-    "game.panel.score.y",
-    &game.panel.score.y
+    "main.text.scores.valign",
+    &menu.main.text.scores.valign
   },
   {
-    "game.panel.score.align",
-    &game.panel.score.align
+    "main.text.scores.font",
+    &menu.main.text.scores.font
   },
   {
-    "game.panel.score.valign",
-    &game.panel.score.valign
+    "main.text.editor.x",
+    &menu.main.text.editor.x
   },
   {
-    "game.panel.score.digits",
-    &game.panel.score.size
+    "main.text.editor.y",
+    &menu.main.text.editor.y
   },
   {
-    "game.panel.score.font",
-    &game.panel.score.font
+    "main.text.editor.width",
+    &menu.main.text.editor.width
   },
   {
-    "game.panel.score.draw_masked",
-    &game.panel.score.draw_masked
+    "main.text.editor.height",
+    &menu.main.text.editor.height
   },
   {
-    "game.panel.score.draw_order",
-    &game.panel.score.sort_priority
+    "main.text.editor.align",
+    &menu.main.text.editor.align
   },
   {
-    "game.panel.highscore.x",
-    &game.panel.highscore.x
+    "main.text.editor.valign",
+    &menu.main.text.editor.valign
   },
   {
-    "game.panel.highscore.y",
-    &game.panel.highscore.y
+    "main.text.editor.font",
+    &menu.main.text.editor.font
+  },
+  {
+    "main.text.info.x",
+    &menu.main.text.info.x
+  },
+  {
+    "main.text.info.y",
+    &menu.main.text.info.y
+  },
+  {
+    "main.text.info.width",
+    &menu.main.text.info.width
+  },
+  {
+    "main.text.info.height",
+    &menu.main.text.info.height
+  },
+  {
+    "main.text.info.align",
+    &menu.main.text.info.align
+  },
+  {
+    "main.text.info.valign",
+    &menu.main.text.info.valign
+  },
+  {
+    "main.text.info.font",
+    &menu.main.text.info.font
+  },
+  {
+    "main.text.game.x",
+    &menu.main.text.game.x
+  },
+  {
+    "main.text.game.y",
+    &menu.main.text.game.y
+  },
+  {
+    "main.text.game.width",
+    &menu.main.text.game.width
+  },
+  {
+    "main.text.game.height",
+    &menu.main.text.game.height
+  },
+  {
+    "main.text.game.align",
+    &menu.main.text.game.align
+  },
+  {
+    "main.text.game.valign",
+    &menu.main.text.game.valign
+  },
+  {
+    "main.text.game.font",
+    &menu.main.text.game.font
+  },
+  {
+    "main.text.setup.x",
+    &menu.main.text.setup.x
+  },
+  {
+    "main.text.setup.y",
+    &menu.main.text.setup.y
+  },
+  {
+    "main.text.setup.width",
+    &menu.main.text.setup.width
+  },
+  {
+    "main.text.setup.height",
+    &menu.main.text.setup.height
+  },
+  {
+    "main.text.setup.align",
+    &menu.main.text.setup.align
+  },
+  {
+    "main.text.setup.valign",
+    &menu.main.text.setup.valign
+  },
+  {
+    "main.text.setup.font",
+    &menu.main.text.setup.font
+  },
+  {
+    "main.text.quit.x",
+    &menu.main.text.quit.x
+  },
+  {
+    "main.text.quit.y",
+    &menu.main.text.quit.y
+  },
+  {
+    "main.text.quit.width",
+    &menu.main.text.quit.width
+  },
+  {
+    "main.text.quit.height",
+    &menu.main.text.quit.height
+  },
+  {
+    "main.text.quit.align",
+    &menu.main.text.quit.align
+  },
+  {
+    "main.text.quit.valign",
+    &menu.main.text.quit.valign
+  },
+  {
+    "main.text.quit.font",
+    &menu.main.text.quit.font
+  },
+  {
+    "main.text.first_level.x",
+    &menu.main.text.first_level.x
+  },
+  {
+    "main.text.first_level.y",
+    &menu.main.text.first_level.y
+  },
+  {
+    "main.text.first_level.align",
+    &menu.main.text.first_level.align
+  },
+  {
+    "main.text.first_level.valign",
+    &menu.main.text.first_level.valign
+  },
+  {
+    "main.text.first_level.digits",
+    &menu.main.text.first_level.size
+  },
+  {
+    "main.text.first_level.font",
+    &menu.main.text.first_level.font
+  },
+  {
+    "main.text.last_level.x",
+    &menu.main.text.last_level.x
+  },
+  {
+    "main.text.last_level.y",
+    &menu.main.text.last_level.y
+  },
+  {
+    "main.text.last_level.align",
+    &menu.main.text.last_level.align
+  },
+  {
+    "main.text.last_level.valign",
+    &menu.main.text.last_level.valign
+  },
+  {
+    "main.text.last_level.digits",
+    &menu.main.text.last_level.size
+  },
+  {
+    "main.text.last_level.font",
+    &menu.main.text.last_level.font
+  },
+  {
+    "main.text.level_number.x",
+    &menu.main.text.level_number.x
+  },
+  {
+    "main.text.level_number.y",
+    &menu.main.text.level_number.y
+  },
+  {
+    "main.text.level_number.align",
+    &menu.main.text.level_number.align
+  },
+  {
+    "main.text.level_number.valign",
+    &menu.main.text.level_number.valign
+  },
+  {
+    "main.text.level_number.digits",
+    &menu.main.text.level_number.size
+  },
+  {
+    "main.text.level_number.font",
+    &menu.main.text.level_number.font
+  },
+  {
+    "main.text.level_info_1.x",
+    &menu.main.text.level_info_1.x
+  },
+  {
+    "main.text.level_info_1.y",
+    &menu.main.text.level_info_1.y
+  },
+  {
+    "main.text.level_info_1.align",
+    &menu.main.text.level_info_1.align
+  },
+  {
+    "main.text.level_info_1.valign",
+    &menu.main.text.level_info_1.valign
+  },
+  {
+    "main.text.level_info_1.chars",
+    &menu.main.text.level_info_1.size
+  },
+  {
+    "main.text.level_info_1.font",
+    &menu.main.text.level_info_1.font
+  },
+  {
+    "main.text.level_info_2.x",
+    &menu.main.text.level_info_2.x
+  },
+  {
+    "main.text.level_info_2.y",
+    &menu.main.text.level_info_2.y
+  },
+  {
+    "main.text.level_info_2.align",
+    &menu.main.text.level_info_2.align
+  },
+  {
+    "main.text.level_info_2.valign",
+    &menu.main.text.level_info_2.valign
+  },
+  {
+    "main.text.level_info_2.chars",
+    &menu.main.text.level_info_2.size
+  },
+  {
+    "main.text.level_info_2.font",
+    &menu.main.text.level_info_2.font
+  },
+  {
+    "main.text.level_info_2.font_header",
+    &menu.main.text.level_info_2.font_alt
+  },
+  {
+    "main.text.level_name.x",
+    &menu.main.text.level_name.x
+  },
+  {
+    "main.text.level_name.y",
+    &menu.main.text.level_name.y
+  },
+  {
+    "main.text.level_name.align",
+    &menu.main.text.level_name.align
+  },
+  {
+    "main.text.level_name.valign",
+    &menu.main.text.level_name.valign
+  },
+  {
+    "main.text.level_name.chars",
+    &menu.main.text.level_name.size
+  },
+  {
+    "main.text.level_name.font",
+    &menu.main.text.level_name.font
+  },
+  {
+    "main.text.level_author.x",
+    &menu.main.text.level_author.x
+  },
+  {
+    "main.text.level_author.y",
+    &menu.main.text.level_author.y
+  },
+  {
+    "main.text.level_author.align",
+    &menu.main.text.level_author.align
+  },
+  {
+    "main.text.level_author.valign",
+    &menu.main.text.level_author.valign
+  },
+  {
+    "main.text.level_author.chars",
+    &menu.main.text.level_author.size
+  },
+  {
+    "main.text.level_author.font",
+    &menu.main.text.level_author.font
+  },
+  {
+    "main.text.level_year.x",
+    &menu.main.text.level_year.x
+  },
+  {
+    "main.text.level_year.y",
+    &menu.main.text.level_year.y
+  },
+  {
+    "main.text.level_year.align",
+    &menu.main.text.level_year.align
+  },
+  {
+    "main.text.level_year.valign",
+    &menu.main.text.level_year.valign
+  },
+  {
+    "main.text.level_year.digits",
+    &menu.main.text.level_year.size
+  },
+  {
+    "main.text.level_year.font",
+    &menu.main.text.level_year.font
+  },
+  {
+    "main.text.level_imported_from.x",
+    &menu.main.text.level_imported_from.x
+  },
+  {
+    "main.text.level_imported_from.y",
+    &menu.main.text.level_imported_from.y
+  },
+  {
+    "main.text.level_imported_from.align",
+    &menu.main.text.level_imported_from.align
+  },
+  {
+    "main.text.level_imported_from.valign",
+    &menu.main.text.level_imported_from.valign
+  },
+  {
+    "main.text.level_imported_from.chars",
+    &menu.main.text.level_imported_from.size
+  },
+  {
+    "main.text.level_imported_from.font",
+    &menu.main.text.level_imported_from.font
+  },
+  {
+    "main.text.level_imported_by.x",
+    &menu.main.text.level_imported_by.x
+  },
+  {
+    "main.text.level_imported_by.y",
+    &menu.main.text.level_imported_by.y
+  },
+  {
+    "main.text.level_imported_by.align",
+    &menu.main.text.level_imported_by.align
+  },
+  {
+    "main.text.level_imported_by.valign",
+    &menu.main.text.level_imported_by.valign
+  },
+  {
+    "main.text.level_imported_by.chars",
+    &menu.main.text.level_imported_by.size
+  },
+  {
+    "main.text.level_imported_by.font",
+    &menu.main.text.level_imported_by.font
+  },
+  {
+    "main.text.level_tested_by.x",
+    &menu.main.text.level_tested_by.x
+  },
+  {
+    "main.text.level_tested_by.y",
+    &menu.main.text.level_tested_by.y
+  },
+  {
+    "main.text.level_tested_by.align",
+    &menu.main.text.level_tested_by.align
+  },
+  {
+    "main.text.level_tested_by.valign",
+    &menu.main.text.level_tested_by.valign
+  },
+  {
+    "main.text.level_tested_by.chars",
+    &menu.main.text.level_tested_by.size
+  },
+  {
+    "main.text.level_tested_by.font",
+    &menu.main.text.level_tested_by.font
+  },
+  {
+    "main.text.title_1.x",
+    &menu.main.text.title_1.x
+  },
+  {
+    "main.text.title_1.y",
+    &menu.main.text.title_1.y
+  },
+  {
+    "main.text.title_1.align",
+    &menu.main.text.title_1.align
+  },
+  {
+    "main.text.title_1.valign",
+    &menu.main.text.title_1.valign
+  },
+  {
+    "main.text.title_1.font",
+    &menu.main.text.title_1.font
+  },
+  {
+    "main.text.title_2.x",
+    &menu.main.text.title_2.x
+  },
+  {
+    "main.text.title_2.y",
+    &menu.main.text.title_2.y
+  },
+  {
+    "main.text.title_2.align",
+    &menu.main.text.title_2.align
+  },
+  {
+    "main.text.title_2.valign",
+    &menu.main.text.title_2.valign
+  },
+  {
+    "main.text.title_2.font",
+    &menu.main.text.title_2.font
+  },
+  {
+    "main.text.title_3.x",
+    &menu.main.text.title_3.x
+  },
+  {
+    "main.text.title_3.y",
+    &menu.main.text.title_3.y
+  },
+  {
+    "main.text.title_3.align",
+    &menu.main.text.title_3.align
+  },
+  {
+    "main.text.title_3.valign",
+    &menu.main.text.title_3.valign
+  },
+  {
+    "main.text.title_3.font",
+    &menu.main.text.title_3.font
+  },
+  {
+    "main.input.name.x",
+    &menu.main.input.name.x
+  },
+  {
+    "main.input.name.y",
+    &menu.main.input.name.y
+  },
+  {
+    "main.input.name.align",
+    &menu.main.input.name.align
+  },
+  {
+    "main.input.name.valign",
+    &menu.main.input.name.valign
+  },
+  {
+    "main.input.name.font",
+    &menu.main.input.name.font
+  },
+  {
+    "preview.x",
+    &preview.x
+  },
+  {
+    "preview.y",
+    &preview.y
+  },
+  {
+    "preview.align",
+    &preview.align
+  },
+  {
+    "preview.valign",
+    &preview.valign
+  },
+  {
+    "preview.xsize",
+    &preview.xsize
+  },
+  {
+    "preview.ysize",
+    &preview.ysize
+  },
+  {
+    "preview.xoffset",
+    &preview.xoffset
+  },
+  {
+    "preview.yoffset",
+    &preview.yoffset
+  },
+  {
+    "preview.tile_size",
+    &preview.tile_size
+  },
+  {
+    "preview.step_offset",
+    &preview.step_offset
+  },
+  {
+    "preview.step_delay",
+    &preview.step_delay
+  },
+  {
+    "preview.anim_mode",
+    &preview.anim_mode
+  },
+  {
+    "door_1.part_1.x",
+    &door_1.part_1.x
+  },
+  {
+    "door_1.part_1.y",
+    &door_1.part_1.y
+  },
+  {
+    "door_1.part_1.step_xoffset",
+    &door_1.part_1.step_xoffset
+  },
+  {
+    "door_1.part_1.step_yoffset",
+    &door_1.part_1.step_yoffset
+  },
+  {
+    "door_1.part_1.step_delay",
+    &door_1.part_1.step_delay
+  },
+  {
+    "door_1.part_1.start_step",
+    &door_1.part_1.start_step
+  },
+  {
+    "door_1.part_1.start_step_opening",
+    &door_1.part_1.start_step_opening
+  },
+  {
+    "door_1.part_1.start_step_closing",
+    &door_1.part_1.start_step_closing
+  },
+  {
+    "door_1.part_1.draw_masked",
+    &door_1.part_1.draw_masked
+  },
+  {
+    "door_1.part_1.draw_order",
+    &door_1.part_1.sort_priority
+  },
+  {
+    "door_1.part_2.x",
+    &door_1.part_2.x
+  },
+  {
+    "door_1.part_2.y",
+    &door_1.part_2.y
+  },
+  {
+    "door_1.part_2.step_xoffset",
+    &door_1.part_2.step_xoffset
+  },
+  {
+    "door_1.part_2.step_yoffset",
+    &door_1.part_2.step_yoffset
+  },
+  {
+    "door_1.part_2.step_delay",
+    &door_1.part_2.step_delay
+  },
+  {
+    "door_1.part_2.start_step",
+    &door_1.part_2.start_step
+  },
+  {
+    "door_1.part_2.start_step_opening",
+    &door_1.part_2.start_step_opening
+  },
+  {
+    "door_1.part_2.start_step_closing",
+    &door_1.part_2.start_step_closing
+  },
+  {
+    "door_1.part_2.draw_masked",
+    &door_1.part_2.draw_masked
+  },
+  {
+    "door_1.part_2.draw_order",
+    &door_1.part_2.sort_priority
+  },
+  {
+    "door_1.part_3.x",
+    &door_1.part_3.x
+  },
+  {
+    "door_1.part_3.y",
+    &door_1.part_3.y
+  },
+  {
+    "door_1.part_3.step_xoffset",
+    &door_1.part_3.step_xoffset
+  },
+  {
+    "door_1.part_3.step_yoffset",
+    &door_1.part_3.step_yoffset
+  },
+  {
+    "door_1.part_3.step_delay",
+    &door_1.part_3.step_delay
+  },
+  {
+    "door_1.part_3.start_step",
+    &door_1.part_3.start_step
+  },
+  {
+    "door_1.part_3.start_step_opening",
+    &door_1.part_3.start_step_opening
+  },
+  {
+    "door_1.part_3.start_step_closing",
+    &door_1.part_3.start_step_closing
+  },
+  {
+    "door_1.part_3.draw_masked",
+    &door_1.part_3.draw_masked
+  },
+  {
+    "door_1.part_3.draw_order",
+    &door_1.part_3.sort_priority
+  },
+  {
+    "door_1.part_4.x",
+    &door_1.part_4.x
+  },
+  {
+    "door_1.part_4.y",
+    &door_1.part_4.y
+  },
+  {
+    "door_1.part_4.step_xoffset",
+    &door_1.part_4.step_xoffset
+  },
+  {
+    "door_1.part_4.step_yoffset",
+    &door_1.part_4.step_yoffset
+  },
+  {
+    "door_1.part_4.step_delay",
+    &door_1.part_4.step_delay
+  },
+  {
+    "door_1.part_4.start_step",
+    &door_1.part_4.start_step
+  },
+  {
+    "door_1.part_4.start_step_opening",
+    &door_1.part_4.start_step_opening
+  },
+  {
+    "door_1.part_4.start_step_closing",
+    &door_1.part_4.start_step_closing
+  },
+  {
+    "door_1.part_4.draw_masked",
+    &door_1.part_4.draw_masked
+  },
+  {
+    "door_1.part_4.draw_order",
+    &door_1.part_4.sort_priority
+  },
+  {
+    "door_1.part_5.x",
+    &door_1.part_5.x
+  },
+  {
+    "door_1.part_5.y",
+    &door_1.part_5.y
+  },
+  {
+    "door_1.part_5.step_xoffset",
+    &door_1.part_5.step_xoffset
+  },
+  {
+    "door_1.part_5.step_yoffset",
+    &door_1.part_5.step_yoffset
+  },
+  {
+    "door_1.part_5.step_delay",
+    &door_1.part_5.step_delay
+  },
+  {
+    "door_1.part_5.start_step",
+    &door_1.part_5.start_step
+  },
+  {
+    "door_1.part_5.start_step_opening",
+    &door_1.part_5.start_step_opening
+  },
+  {
+    "door_1.part_5.start_step_closing",
+    &door_1.part_5.start_step_closing
+  },
+  {
+    "door_1.part_5.draw_masked",
+    &door_1.part_5.draw_masked
+  },
+  {
+    "door_1.part_5.draw_order",
+    &door_1.part_5.sort_priority
+  },
+  {
+    "door_1.part_6.x",
+    &door_1.part_6.x
+  },
+  {
+    "door_1.part_6.y",
+    &door_1.part_6.y
+  },
+  {
+    "door_1.part_6.step_xoffset",
+    &door_1.part_6.step_xoffset
+  },
+  {
+    "door_1.part_6.step_yoffset",
+    &door_1.part_6.step_yoffset
+  },
+  {
+    "door_1.part_6.step_delay",
+    &door_1.part_6.step_delay
+  },
+  {
+    "door_1.part_6.start_step",
+    &door_1.part_6.start_step
+  },
+  {
+    "door_1.part_6.start_step_opening",
+    &door_1.part_6.start_step_opening
+  },
+  {
+    "door_1.part_6.start_step_closing",
+    &door_1.part_6.start_step_closing
+  },
+  {
+    "door_1.part_6.draw_masked",
+    &door_1.part_6.draw_masked
+  },
+  {
+    "door_1.part_6.draw_order",
+    &door_1.part_6.sort_priority
+  },
+  {
+    "door_1.part_7.x",
+    &door_1.part_7.x
+  },
+  {
+    "door_1.part_7.y",
+    &door_1.part_7.y
+  },
+  {
+    "door_1.part_7.step_xoffset",
+    &door_1.part_7.step_xoffset
+  },
+  {
+    "door_1.part_7.step_yoffset",
+    &door_1.part_7.step_yoffset
+  },
+  {
+    "door_1.part_7.step_delay",
+    &door_1.part_7.step_delay
+  },
+  {
+    "door_1.part_7.start_step",
+    &door_1.part_7.start_step
+  },
+  {
+    "door_1.part_7.start_step_opening",
+    &door_1.part_7.start_step_opening
+  },
+  {
+    "door_1.part_7.start_step_closing",
+    &door_1.part_7.start_step_closing
+  },
+  {
+    "door_1.part_7.draw_masked",
+    &door_1.part_7.draw_masked
+  },
+  {
+    "door_1.part_7.draw_order",
+    &door_1.part_7.sort_priority
+  },
+  {
+    "door_1.part_8.x",
+    &door_1.part_8.x
+  },
+  {
+    "door_1.part_8.y",
+    &door_1.part_8.y
+  },
+  {
+    "door_1.part_8.step_xoffset",
+    &door_1.part_8.step_xoffset
+  },
+  {
+    "door_1.part_8.step_yoffset",
+    &door_1.part_8.step_yoffset
+  },
+  {
+    "door_1.part_8.step_delay",
+    &door_1.part_8.step_delay
+  },
+  {
+    "door_1.part_8.start_step",
+    &door_1.part_8.start_step
+  },
+  {
+    "door_1.part_8.start_step_opening",
+    &door_1.part_8.start_step_opening
+  },
+  {
+    "door_1.part_8.start_step_closing",
+    &door_1.part_8.start_step_closing
+  },
+  {
+    "door_1.part_8.draw_masked",
+    &door_1.part_8.draw_masked
+  },
+  {
+    "door_1.part_8.draw_order",
+    &door_1.part_8.sort_priority
+  },
+  {
+    "door_2.part_1.x",
+    &door_2.part_1.x
+  },
+  {
+    "door_2.part_1.y",
+    &door_2.part_1.y
+  },
+  {
+    "door_2.part_1.step_xoffset",
+    &door_2.part_1.step_xoffset
+  },
+  {
+    "door_2.part_1.step_yoffset",
+    &door_2.part_1.step_yoffset
+  },
+  {
+    "door_2.part_1.step_delay",
+    &door_2.part_1.step_delay
+  },
+  {
+    "door_2.part_1.start_step",
+    &door_2.part_1.start_step
+  },
+  {
+    "door_2.part_1.start_step_opening",
+    &door_2.part_1.start_step_opening
+  },
+  {
+    "door_2.part_1.start_step_closing",
+    &door_2.part_1.start_step_closing
+  },
+  {
+    "door_2.part_1.draw_masked",
+    &door_2.part_1.draw_masked
+  },
+  {
+    "door_2.part_1.draw_order",
+    &door_2.part_1.sort_priority
+  },
+  {
+    "door_2.part_2.x",
+    &door_2.part_2.x
+  },
+  {
+    "door_2.part_2.y",
+    &door_2.part_2.y
+  },
+  {
+    "door_2.part_2.step_xoffset",
+    &door_2.part_2.step_xoffset
+  },
+  {
+    "door_2.part_2.step_yoffset",
+    &door_2.part_2.step_yoffset
+  },
+  {
+    "door_2.part_2.step_delay",
+    &door_2.part_2.step_delay
+  },
+  {
+    "door_2.part_2.start_step",
+    &door_2.part_2.start_step
+  },
+  {
+    "door_2.part_2.start_step_opening",
+    &door_2.part_2.start_step_opening
+  },
+  {
+    "door_2.part_2.start_step_closing",
+    &door_2.part_2.start_step_closing
+  },
+  {
+    "door_2.part_2.draw_masked",
+    &door_2.part_2.draw_masked
+  },
+  {
+    "door_2.part_2.draw_order",
+    &door_2.part_2.sort_priority
+  },
+  {
+    "door_2.part_3.x",
+    &door_2.part_3.x
+  },
+  {
+    "door_2.part_3.y",
+    &door_2.part_3.y
+  },
+  {
+    "door_2.part_3.step_xoffset",
+    &door_2.part_3.step_xoffset
+  },
+  {
+    "door_2.part_3.step_yoffset",
+    &door_2.part_3.step_yoffset
+  },
+  {
+    "door_2.part_3.step_delay",
+    &door_2.part_3.step_delay
+  },
+  {
+    "door_2.part_3.start_step",
+    &door_2.part_3.start_step
+  },
+  {
+    "door_2.part_3.start_step_opening",
+    &door_2.part_3.start_step_opening
+  },
+  {
+    "door_2.part_3.start_step_closing",
+    &door_2.part_3.start_step_closing
+  },
+  {
+    "door_2.part_3.draw_masked",
+    &door_2.part_3.draw_masked
+  },
+  {
+    "door_2.part_3.draw_order",
+    &door_2.part_3.sort_priority
+  },
+  {
+    "door_2.part_4.x",
+    &door_2.part_4.x
+  },
+  {
+    "door_2.part_4.y",
+    &door_2.part_4.y
+  },
+  {
+    "door_2.part_4.step_xoffset",
+    &door_2.part_4.step_xoffset
+  },
+  {
+    "door_2.part_4.step_yoffset",
+    &door_2.part_4.step_yoffset
+  },
+  {
+    "door_2.part_4.step_delay",
+    &door_2.part_4.step_delay
+  },
+  {
+    "door_2.part_4.start_step",
+    &door_2.part_4.start_step
+  },
+  {
+    "door_2.part_4.start_step_opening",
+    &door_2.part_4.start_step_opening
+  },
+  {
+    "door_2.part_4.start_step_closing",
+    &door_2.part_4.start_step_closing
+  },
+  {
+    "door_2.part_4.draw_masked",
+    &door_2.part_4.draw_masked
+  },
+  {
+    "door_2.part_4.draw_order",
+    &door_2.part_4.sort_priority
+  },
+  {
+    "door_2.part_5.x",
+    &door_2.part_5.x
+  },
+  {
+    "door_2.part_5.y",
+    &door_2.part_5.y
+  },
+  {
+    "door_2.part_5.step_xoffset",
+    &door_2.part_5.step_xoffset
+  },
+  {
+    "door_2.part_5.step_yoffset",
+    &door_2.part_5.step_yoffset
+  },
+  {
+    "door_2.part_5.step_delay",
+    &door_2.part_5.step_delay
+  },
+  {
+    "door_2.part_5.start_step",
+    &door_2.part_5.start_step
+  },
+  {
+    "door_2.part_5.start_step_opening",
+    &door_2.part_5.start_step_opening
+  },
+  {
+    "door_2.part_5.start_step_closing",
+    &door_2.part_5.start_step_closing
+  },
+  {
+    "door_2.part_5.draw_masked",
+    &door_2.part_5.draw_masked
+  },
+  {
+    "door_2.part_5.draw_order",
+    &door_2.part_5.sort_priority
+  },
+  {
+    "door_2.part_6.x",
+    &door_2.part_6.x
+  },
+  {
+    "door_2.part_6.y",
+    &door_2.part_6.y
+  },
+  {
+    "door_2.part_6.step_xoffset",
+    &door_2.part_6.step_xoffset
+  },
+  {
+    "door_2.part_6.step_yoffset",
+    &door_2.part_6.step_yoffset
+  },
+  {
+    "door_2.part_6.step_delay",
+    &door_2.part_6.step_delay
+  },
+  {
+    "door_2.part_6.start_step",
+    &door_2.part_6.start_step
+  },
+  {
+    "door_2.part_6.start_step_opening",
+    &door_2.part_6.start_step_opening
+  },
+  {
+    "door_2.part_6.start_step_closing",
+    &door_2.part_6.start_step_closing
+  },
+  {
+    "door_2.part_6.draw_masked",
+    &door_2.part_6.draw_masked
+  },
+  {
+    "door_2.part_6.draw_order",
+    &door_2.part_6.sort_priority
+  },
+  {
+    "door_2.part_7.x",
+    &door_2.part_7.x
+  },
+  {
+    "door_2.part_7.y",
+    &door_2.part_7.y
+  },
+  {
+    "door_2.part_7.step_xoffset",
+    &door_2.part_7.step_xoffset
+  },
+  {
+    "door_2.part_7.step_yoffset",
+    &door_2.part_7.step_yoffset
+  },
+  {
+    "door_2.part_7.step_delay",
+    &door_2.part_7.step_delay
+  },
+  {
+    "door_2.part_7.start_step",
+    &door_2.part_7.start_step
+  },
+  {
+    "door_2.part_7.start_step_opening",
+    &door_2.part_7.start_step_opening
+  },
+  {
+    "door_2.part_7.start_step_closing",
+    &door_2.part_7.start_step_closing
+  },
+  {
+    "door_2.part_7.draw_masked",
+    &door_2.part_7.draw_masked
+  },
+  {
+    "door_2.part_7.draw_order",
+    &door_2.part_7.sort_priority
+  },
+  {
+    "door_2.part_8.x",
+    &door_2.part_8.x
+  },
+  {
+    "door_2.part_8.y",
+    &door_2.part_8.y
+  },
+  {
+    "door_2.part_8.step_xoffset",
+    &door_2.part_8.step_xoffset
+  },
+  {
+    "door_2.part_8.step_yoffset",
+    &door_2.part_8.step_yoffset
+  },
+  {
+    "door_2.part_8.step_delay",
+    &door_2.part_8.step_delay
+  },
+  {
+    "door_2.part_8.start_step",
+    &door_2.part_8.start_step
+  },
+  {
+    "door_2.part_8.start_step_opening",
+    &door_2.part_8.start_step_opening
+  },
+  {
+    "door_2.part_8.start_step_closing",
+    &door_2.part_8.start_step_closing
+  },
+  {
+    "door_2.part_8.draw_masked",
+    &door_2.part_8.draw_masked
+  },
+  {
+    "door_2.part_8.draw_order",
+    &door_2.part_8.sort_priority
+  },
+  {
+    "door_1.panel.x",
+    &door_1.panel.x
+  },
+  {
+    "door_1.panel.y",
+    &door_1.panel.y
+  },
+  {
+    "door_1.panel.step_xoffset",
+    &door_1.panel.step_xoffset
+  },
+  {
+    "door_1.panel.step_yoffset",
+    &door_1.panel.step_yoffset
+  },
+  {
+    "door_1.panel.step_delay",
+    &door_1.panel.step_delay
+  },
+  {
+    "door_1.panel.start_step",
+    &door_1.panel.start_step
+  },
+  {
+    "door_1.panel.start_step_opening",
+    &door_1.panel.start_step_opening
+  },
+  {
+    "door_1.panel.start_step_closing",
+    &door_1.panel.start_step_closing
+  },
+  {
+    "door_1.panel.draw_masked",
+    &door_1.panel.draw_masked
+  },
+  {
+    "door_1.panel.draw_order",
+    &door_1.panel.sort_priority
+  },
+  {
+    "door_2.panel.x",
+    &door_2.panel.x
+  },
+  {
+    "door_2.panel.y",
+    &door_2.panel.y
+  },
+  {
+    "door_2.panel.step_xoffset",
+    &door_2.panel.step_xoffset
+  },
+  {
+    "door_2.panel.step_yoffset",
+    &door_2.panel.step_yoffset
+  },
+  {
+    "door_2.panel.step_delay",
+    &door_2.panel.step_delay
+  },
+  {
+    "door_2.panel.start_step",
+    &door_2.panel.start_step
+  },
+  {
+    "door_2.panel.start_step_opening",
+    &door_2.panel.start_step_opening
+  },
+  {
+    "door_2.panel.start_step_closing",
+    &door_2.panel.start_step_closing
+  },
+  {
+    "door_2.panel.draw_masked",
+    &door_2.panel.draw_masked
+  },
+  {
+    "door_2.panel.draw_order",
+    &door_2.panel.sort_priority
+  },
+  {
+    "door_1.width",
+    &door_1.width
+  },
+  {
+    "door_1.height",
+    &door_1.height
+  },
+  {
+    "door_1.step_offset",
+    &door_1.step_offset
+  },
+  {
+    "door_1.step_delay",
+    &door_1.step_delay
+  },
+  {
+    "door_1.anim_mode",
+    &door_1.anim_mode
+  },
+  {
+    "door_2.width",
+    &door_2.width
+  },
+  {
+    "door_2.height",
+    &door_2.height
+  },
+  {
+    "door_2.step_offset",
+    &door_2.step_offset
+  },
+  {
+    "door_2.step_delay",
+    &door_2.step_delay
+  },
+  {
+    "door_2.anim_mode",
+    &door_2.anim_mode
+  },
+  {
+    "game.panel.level_number.x",
+    &game.panel.level_number.x
+  },
+  {
+    "game.panel.level_number.y",
+    &game.panel.level_number.y
+  },
+  {
+    "game.panel.level_number.align",
+    &game.panel.level_number.align
+  },
+  {
+    "game.panel.level_number.valign",
+    &game.panel.level_number.valign
+  },
+  {
+    "game.panel.level_number.digits",
+    &game.panel.level_number.size
+  },
+  {
+    "game.panel.level_number.font",
+    &game.panel.level_number.font
+  },
+  {
+    "game.panel.level_number.font_narrow",
+    &game.panel.level_number.font_alt
+  },
+  {
+    "game.panel.level_number.draw_masked",
+    &game.panel.level_number.draw_masked
+  },
+  {
+    "game.panel.level_number.draw_order",
+    &game.panel.level_number.sort_priority
+  },
+  {
+    "game.panel.gems.x",
+    &game.panel.gems.x
+  },
+  {
+    "game.panel.gems.y",
+    &game.panel.gems.y
+  },
+  {
+    "game.panel.gems.align",
+    &game.panel.gems.align
+  },
+  {
+    "game.panel.gems.valign",
+    &game.panel.gems.valign
+  },
+  {
+    "game.panel.gems.digits",
+    &game.panel.gems.size
+  },
+  {
+    "game.panel.gems.font",
+    &game.panel.gems.font
+  },
+  {
+    "game.panel.gems.draw_masked",
+    &game.panel.gems.draw_masked
+  },
+  {
+    "game.panel.gems.draw_order",
+    &game.panel.gems.sort_priority
+  },
+  {
+    "game.panel.inventory_count.x",
+    &game.panel.inventory_count.x
+  },
+  {
+    "game.panel.inventory_count.y",
+    &game.panel.inventory_count.y
+  },
+  {
+    "game.panel.inventory_count.align",
+    &game.panel.inventory_count.align
+  },
+  {
+    "game.panel.inventory_count.valign",
+    &game.panel.inventory_count.valign
+  },
+  {
+    "game.panel.inventory_count.digits",
+    &game.panel.inventory_count.size
+  },
+  {
+    "game.panel.inventory_count.font",
+    &game.panel.inventory_count.font
+  },
+  {
+    "game.panel.inventory_count.draw_masked",
+    &game.panel.inventory_count.draw_masked
+  },
+  {
+    "game.panel.inventory_count.draw_order",
+    &game.panel.inventory_count.sort_priority
+  },
+  {
+    "game.panel.inventory_first_1.x",
+    &game.panel.inventory_first[0].x
+  },
+  {
+    "game.panel.inventory_first_1.y",
+    &game.panel.inventory_first[0].y
+  },
+  {
+    "game.panel.inventory_first_1.tile_size",
+    &game.panel.inventory_first[0].size
+  },
+  {
+    "game.panel.inventory_first_1.draw_masked",
+    &game.panel.inventory_first[0].draw_masked
+  },
+  {
+    "game.panel.inventory_first_1.draw_order",
+    &game.panel.inventory_first[0].sort_priority
+  },
+  {
+    "game.panel.inventory_first_2.x",
+    &game.panel.inventory_first[1].x
+  },
+  {
+    "game.panel.inventory_first_2.y",
+    &game.panel.inventory_first[1].y
+  },
+  {
+    "game.panel.inventory_first_2.tile_size",
+    &game.panel.inventory_first[1].size
+  },
+  {
+    "game.panel.inventory_first_2.draw_masked",
+    &game.panel.inventory_first[1].draw_masked
+  },
+  {
+    "game.panel.inventory_first_2.draw_order",
+    &game.panel.inventory_first[1].sort_priority
+  },
+  {
+    "game.panel.inventory_first_3.x",
+    &game.panel.inventory_first[2].x
+  },
+  {
+    "game.panel.inventory_first_3.y",
+    &game.panel.inventory_first[2].y
+  },
+  {
+    "game.panel.inventory_first_3.tile_size",
+    &game.panel.inventory_first[2].size
+  },
+  {
+    "game.panel.inventory_first_3.draw_masked",
+    &game.panel.inventory_first[2].draw_masked
+  },
+  {
+    "game.panel.inventory_first_3.draw_order",
+    &game.panel.inventory_first[2].sort_priority
+  },
+  {
+    "game.panel.inventory_first_4.x",
+    &game.panel.inventory_first[3].x
+  },
+  {
+    "game.panel.inventory_first_4.y",
+    &game.panel.inventory_first[3].y
+  },
+  {
+    "game.panel.inventory_first_4.tile_size",
+    &game.panel.inventory_first[3].size
+  },
+  {
+    "game.panel.inventory_first_4.draw_masked",
+    &game.panel.inventory_first[3].draw_masked
+  },
+  {
+    "game.panel.inventory_first_4.draw_order",
+    &game.panel.inventory_first[3].sort_priority
+  },
+  {
+    "game.panel.inventory_first_5.x",
+    &game.panel.inventory_first[4].x
+  },
+  {
+    "game.panel.inventory_first_5.y",
+    &game.panel.inventory_first[4].y
+  },
+  {
+    "game.panel.inventory_first_5.tile_size",
+    &game.panel.inventory_first[4].size
+  },
+  {
+    "game.panel.inventory_first_5.draw_masked",
+    &game.panel.inventory_first[4].draw_masked
+  },
+  {
+    "game.panel.inventory_first_5.draw_order",
+    &game.panel.inventory_first[4].sort_priority
+  },
+  {
+    "game.panel.inventory_first_6.x",
+    &game.panel.inventory_first[5].x
+  },
+  {
+    "game.panel.inventory_first_6.y",
+    &game.panel.inventory_first[5].y
+  },
+  {
+    "game.panel.inventory_first_6.tile_size",
+    &game.panel.inventory_first[5].size
+  },
+  {
+    "game.panel.inventory_first_6.draw_masked",
+    &game.panel.inventory_first[5].draw_masked
+  },
+  {
+    "game.panel.inventory_first_6.draw_order",
+    &game.panel.inventory_first[5].sort_priority
+  },
+  {
+    "game.panel.inventory_first_7.x",
+    &game.panel.inventory_first[6].x
+  },
+  {
+    "game.panel.inventory_first_7.y",
+    &game.panel.inventory_first[6].y
+  },
+  {
+    "game.panel.inventory_first_7.tile_size",
+    &game.panel.inventory_first[6].size
+  },
+  {
+    "game.panel.inventory_first_7.draw_masked",
+    &game.panel.inventory_first[6].draw_masked
+  },
+  {
+    "game.panel.inventory_first_7.draw_order",
+    &game.panel.inventory_first[6].sort_priority
+  },
+  {
+    "game.panel.inventory_first_8.x",
+    &game.panel.inventory_first[7].x
+  },
+  {
+    "game.panel.inventory_first_8.y",
+    &game.panel.inventory_first[7].y
+  },
+  {
+    "game.panel.inventory_first_8.tile_size",
+    &game.panel.inventory_first[7].size
+  },
+  {
+    "game.panel.inventory_first_8.draw_masked",
+    &game.panel.inventory_first[7].draw_masked
+  },
+  {
+    "game.panel.inventory_first_8.draw_order",
+    &game.panel.inventory_first[7].sort_priority
+  },
+  {
+    "game.panel.inventory_last_1.x",
+    &game.panel.inventory_last[0].x
+  },
+  {
+    "game.panel.inventory_last_1.y",
+    &game.panel.inventory_last[0].y
+  },
+  {
+    "game.panel.inventory_last_1.tile_size",
+    &game.panel.inventory_last[0].size
+  },
+  {
+    "game.panel.inventory_last_1.draw_masked",
+    &game.panel.inventory_last[0].draw_masked
+  },
+  {
+    "game.panel.inventory_last_1.draw_order",
+    &game.panel.inventory_last[0].sort_priority
+  },
+  {
+    "game.panel.inventory_last_2.x",
+    &game.panel.inventory_last[1].x
+  },
+  {
+    "game.panel.inventory_last_2.y",
+    &game.panel.inventory_last[1].y
+  },
+  {
+    "game.panel.inventory_last_2.tile_size",
+    &game.panel.inventory_last[1].size
+  },
+  {
+    "game.panel.inventory_last_2.draw_masked",
+    &game.panel.inventory_last[1].draw_masked
+  },
+  {
+    "game.panel.inventory_last_2.draw_order",
+    &game.panel.inventory_last[1].sort_priority
+  },
+  {
+    "game.panel.inventory_last_3.x",
+    &game.panel.inventory_last[2].x
+  },
+  {
+    "game.panel.inventory_last_3.y",
+    &game.panel.inventory_last[2].y
+  },
+  {
+    "game.panel.inventory_last_3.tile_size",
+    &game.panel.inventory_last[2].size
+  },
+  {
+    "game.panel.inventory_last_3.draw_masked",
+    &game.panel.inventory_last[2].draw_masked
+  },
+  {
+    "game.panel.inventory_last_3.draw_order",
+    &game.panel.inventory_last[2].sort_priority
+  },
+  {
+    "game.panel.inventory_last_4.x",
+    &game.panel.inventory_last[3].x
+  },
+  {
+    "game.panel.inventory_last_4.y",
+    &game.panel.inventory_last[3].y
+  },
+  {
+    "game.panel.inventory_last_4.tile_size",
+    &game.panel.inventory_last[3].size
+  },
+  {
+    "game.panel.inventory_last_4.draw_masked",
+    &game.panel.inventory_last[3].draw_masked
+  },
+  {
+    "game.panel.inventory_last_4.draw_order",
+    &game.panel.inventory_last[3].sort_priority
+  },
+  {
+    "game.panel.inventory_last_5.x",
+    &game.panel.inventory_last[4].x
+  },
+  {
+    "game.panel.inventory_last_5.y",
+    &game.panel.inventory_last[4].y
+  },
+  {
+    "game.panel.inventory_last_5.tile_size",
+    &game.panel.inventory_last[4].size
+  },
+  {
+    "game.panel.inventory_last_5.draw_masked",
+    &game.panel.inventory_last[4].draw_masked
+  },
+  {
+    "game.panel.inventory_last_5.draw_order",
+    &game.panel.inventory_last[4].sort_priority
+  },
+  {
+    "game.panel.inventory_last_6.x",
+    &game.panel.inventory_last[5].x
+  },
+  {
+    "game.panel.inventory_last_6.y",
+    &game.panel.inventory_last[5].y
+  },
+  {
+    "game.panel.inventory_last_6.tile_size",
+    &game.panel.inventory_last[5].size
+  },
+  {
+    "game.panel.inventory_last_6.draw_masked",
+    &game.panel.inventory_last[5].draw_masked
+  },
+  {
+    "game.panel.inventory_last_6.draw_order",
+    &game.panel.inventory_last[5].sort_priority
+  },
+  {
+    "game.panel.inventory_last_7.x",
+    &game.panel.inventory_last[6].x
+  },
+  {
+    "game.panel.inventory_last_7.y",
+    &game.panel.inventory_last[6].y
+  },
+  {
+    "game.panel.inventory_last_7.tile_size",
+    &game.panel.inventory_last[6].size
+  },
+  {
+    "game.panel.inventory_last_7.draw_masked",
+    &game.panel.inventory_last[6].draw_masked
+  },
+  {
+    "game.panel.inventory_last_7.draw_order",
+    &game.panel.inventory_last[6].sort_priority
+  },
+  {
+    "game.panel.inventory_last_8.x",
+    &game.panel.inventory_last[7].x
+  },
+  {
+    "game.panel.inventory_last_8.y",
+    &game.panel.inventory_last[7].y
+  },
+  {
+    "game.panel.inventory_last_8.tile_size",
+    &game.panel.inventory_last[7].size
+  },
+  {
+    "game.panel.inventory_last_8.draw_masked",
+    &game.panel.inventory_last[7].draw_masked
+  },
+  {
+    "game.panel.inventory_last_8.draw_order",
+    &game.panel.inventory_last[7].sort_priority
+  },
+  {
+    "game.panel.key_1.x",
+    &game.panel.key[0].x
+  },
+  {
+    "game.panel.key_1.y",
+    &game.panel.key[0].y
+  },
+  {
+    "game.panel.key_1.tile_size",
+    &game.panel.key[0].size
+  },
+  {
+    "game.panel.key_1.draw_masked",
+    &game.panel.key[0].draw_masked
+  },
+  {
+    "game.panel.key_1.draw_order",
+    &game.panel.key[0].sort_priority
+  },
+  {
+    "game.panel.key_2.x",
+    &game.panel.key[1].x
+  },
+  {
+    "game.panel.key_2.y",
+    &game.panel.key[1].y
+  },
+  {
+    "game.panel.key_2.tile_size",
+    &game.panel.key[1].size
+  },
+  {
+    "game.panel.key_2.draw_masked",
+    &game.panel.key[1].draw_masked
+  },
+  {
+    "game.panel.key_2.draw_order",
+    &game.panel.key[1].sort_priority
+  },
+  {
+    "game.panel.key_3.x",
+    &game.panel.key[2].x
+  },
+  {
+    "game.panel.key_3.y",
+    &game.panel.key[2].y
+  },
+  {
+    "game.panel.key_3.tile_size",
+    &game.panel.key[2].size
+  },
+  {
+    "game.panel.key_3.draw_masked",
+    &game.panel.key[2].draw_masked
+  },
+  {
+    "game.panel.key_3.draw_order",
+    &game.panel.key[2].sort_priority
+  },
+  {
+    "game.panel.key_4.x",
+    &game.panel.key[3].x
+  },
+  {
+    "game.panel.key_4.y",
+    &game.panel.key[3].y
+  },
+  {
+    "game.panel.key_4.tile_size",
+    &game.panel.key[3].size
+  },
+  {
+    "game.panel.key_4.draw_masked",
+    &game.panel.key[3].draw_masked
+  },
+  {
+    "game.panel.key_4.draw_order",
+    &game.panel.key[3].sort_priority
+  },
+  {
+    "game.panel.key_5.x",
+    &game.panel.key[4].x
+  },
+  {
+    "game.panel.key_5.y",
+    &game.panel.key[4].y
+  },
+  {
+    "game.panel.key_5.tile_size",
+    &game.panel.key[4].size
+  },
+  {
+    "game.panel.key_5.draw_masked",
+    &game.panel.key[4].draw_masked
+  },
+  {
+    "game.panel.key_5.draw_order",
+    &game.panel.key[4].sort_priority
+  },
+  {
+    "game.panel.key_6.x",
+    &game.panel.key[5].x
+  },
+  {
+    "game.panel.key_6.y",
+    &game.panel.key[5].y
+  },
+  {
+    "game.panel.key_6.tile_size",
+    &game.panel.key[5].size
+  },
+  {
+    "game.panel.key_6.draw_masked",
+    &game.panel.key[5].draw_masked
+  },
+  {
+    "game.panel.key_6.draw_order",
+    &game.panel.key[5].sort_priority
+  },
+  {
+    "game.panel.key_7.x",
+    &game.panel.key[6].x
+  },
+  {
+    "game.panel.key_7.y",
+    &game.panel.key[6].y
+  },
+  {
+    "game.panel.key_7.tile_size",
+    &game.panel.key[6].size
+  },
+  {
+    "game.panel.key_7.draw_masked",
+    &game.panel.key[6].draw_masked
+  },
+  {
+    "game.panel.key_7.draw_order",
+    &game.panel.key[6].sort_priority
+  },
+  {
+    "game.panel.key_8.x",
+    &game.panel.key[7].x
+  },
+  {
+    "game.panel.key_8.y",
+    &game.panel.key[7].y
+  },
+  {
+    "game.panel.key_8.tile_size",
+    &game.panel.key[7].size
+  },
+  {
+    "game.panel.key_8.draw_masked",
+    &game.panel.key[7].draw_masked
+  },
+  {
+    "game.panel.key_8.draw_order",
+    &game.panel.key[7].sort_priority
+  },
+  {
+    "game.panel.key_white.x",
+    &game.panel.key_white.x
+  },
+  {
+    "game.panel.key_white.y",
+    &game.panel.key_white.y
+  },
+  {
+    "game.panel.key_white.tile_size",
+    &game.panel.key_white.size
+  },
+  {
+    "game.panel.key_white.draw_masked",
+    &game.panel.key_white.draw_masked
+  },
+  {
+    "game.panel.key_white.draw_order",
+    &game.panel.key_white.sort_priority
+  },
+  {
+    "game.panel.key_white_count.x",
+    &game.panel.key_white_count.x
+  },
+  {
+    "game.panel.key_white_count.y",
+    &game.panel.key_white_count.y
+  },
+  {
+    "game.panel.key_white_count.align",
+    &game.panel.key_white_count.align
+  },
+  {
+    "game.panel.key_white_count.valign",
+    &game.panel.key_white_count.valign
+  },
+  {
+    "game.panel.key_white_count.digits",
+    &game.panel.key_white_count.size
+  },
+  {
+    "game.panel.key_white_count.font",
+    &game.panel.key_white_count.font
+  },
+  {
+    "game.panel.key_white_count.draw_masked",
+    &game.panel.key_white_count.draw_masked
+  },
+  {
+    "game.panel.key_white_count.draw_order",
+    &game.panel.key_white_count.sort_priority
+  },
+  {
+    "game.panel.score.x",
+    &game.panel.score.x
+  },
+  {
+    "game.panel.score.y",
+    &game.panel.score.y
+  },
+  {
+    "game.panel.score.align",
+    &game.panel.score.align
+  },
+  {
+    "game.panel.score.valign",
+    &game.panel.score.valign
+  },
+  {
+    "game.panel.score.digits",
+    &game.panel.score.size
+  },
+  {
+    "game.panel.score.font",
+    &game.panel.score.font
+  },
+  {
+    "game.panel.score.draw_masked",
+    &game.panel.score.draw_masked
+  },
+  {
+    "game.panel.score.draw_order",
+    &game.panel.score.sort_priority
+  },
+  {
+    "game.panel.highscore.x",
+    &game.panel.highscore.x
+  },
+  {
+    "game.panel.highscore.y",
+    &game.panel.highscore.y
+  },
+  {
+    "game.panel.highscore.align",
+    &game.panel.highscore.align
+  },
+  {
+    "game.panel.highscore.valign",
+    &game.panel.highscore.valign
+  },
+  {
+    "game.panel.highscore.digits",
+    &game.panel.highscore.size
+  },
+  {
+    "game.panel.highscore.font",
+    &game.panel.highscore.font
+  },
+  {
+    "game.panel.highscore.draw_masked",
+    &game.panel.highscore.draw_masked
+  },
+  {
+    "game.panel.highscore.draw_order",
+    &game.panel.highscore.sort_priority
+  },
+  {
+    "game.panel.time.x",
+    &game.panel.time.x
+  },
+  {
+    "game.panel.time.y",
+    &game.panel.time.y
+  },
+  {
+    "game.panel.time.align",
+    &game.panel.time.align
+  },
+  {
+    "game.panel.time.valign",
+    &game.panel.time.valign
+  },
+  {
+    "game.panel.time.digits",
+    &game.panel.time.size
+  },
+  {
+    "game.panel.time.font",
+    &game.panel.time.font
+  },
+  {
+    "game.panel.time.font_narrow",
+    &game.panel.time.font_alt
+  },
+  {
+    "game.panel.time.draw_masked",
+    &game.panel.time.draw_masked
+  },
+  {
+    "game.panel.time.draw_order",
+    &game.panel.time.sort_priority
+  },
+  {
+    "game.panel.time_hh.x",
+    &game.panel.time_hh.x
+  },
+  {
+    "game.panel.time_hh.y",
+    &game.panel.time_hh.y
+  },
+  {
+    "game.panel.time_hh.align",
+    &game.panel.time_hh.align
+  },
+  {
+    "game.panel.time_hh.valign",
+    &game.panel.time_hh.valign
+  },
+  {
+    "game.panel.time_hh.digits",
+    &game.panel.time_hh.size
+  },
+  {
+    "game.panel.time_hh.font",
+    &game.panel.time_hh.font
+  },
+  {
+    "game.panel.time_hh.draw_masked",
+    &game.panel.time_hh.draw_masked
+  },
+  {
+    "game.panel.time_hh.draw_order",
+    &game.panel.time_hh.sort_priority
+  },
+  {
+    "game.panel.time_mm.x",
+    &game.panel.time_mm.x
+  },
+  {
+    "game.panel.time_mm.y",
+    &game.panel.time_mm.y
+  },
+  {
+    "game.panel.time_mm.align",
+    &game.panel.time_mm.align
+  },
+  {
+    "game.panel.time_mm.valign",
+    &game.panel.time_mm.valign
+  },
+  {
+    "game.panel.time_mm.digits",
+    &game.panel.time_mm.size
+  },
+  {
+    "game.panel.time_mm.font",
+    &game.panel.time_mm.font
+  },
+  {
+    "game.panel.time_mm.draw_masked",
+    &game.panel.time_mm.draw_masked
+  },
+  {
+    "game.panel.time_mm.draw_order",
+    &game.panel.time_mm.sort_priority
+  },
+  {
+    "game.panel.time_ss.x",
+    &game.panel.time_ss.x
+  },
+  {
+    "game.panel.time_ss.y",
+    &game.panel.time_ss.y
+  },
+  {
+    "game.panel.time_ss.align",
+    &game.panel.time_ss.align
+  },
+  {
+    "game.panel.time_ss.valign",
+    &game.panel.time_ss.valign
+  },
+  {
+    "game.panel.time_ss.digits",
+    &game.panel.time_ss.size
+  },
+  {
+    "game.panel.time_ss.font",
+    &game.panel.time_ss.font
+  },
+  {
+    "game.panel.time_ss.draw_masked",
+    &game.panel.time_ss.draw_masked
+  },
+  {
+    "game.panel.time_ss.draw_order",
+    &game.panel.time_ss.sort_priority
+  },
+  {
+    "game.panel.frame.x",
+    &game.panel.frame.x
+  },
+  {
+    "game.panel.frame.y",
+    &game.panel.frame.y
+  },
+  {
+    "game.panel.frame.align",
+    &game.panel.frame.align
+  },
+  {
+    "game.panel.frame.valign",
+    &game.panel.frame.valign
+  },
+  {
+    "game.panel.frame.digits",
+    &game.panel.frame.size
+  },
+  {
+    "game.panel.frame.font",
+    &game.panel.frame.font
+  },
+  {
+    "game.panel.frame.draw_masked",
+    &game.panel.frame.draw_masked
+  },
+  {
+    "game.panel.frame.draw_order",
+    &game.panel.frame.sort_priority
+  },
+  {
+    "game.panel.shield_normal.x",
+    &game.panel.shield_normal.x
+  },
+  {
+    "game.panel.shield_normal.y",
+    &game.panel.shield_normal.y
+  },
+  {
+    "game.panel.shield_normal.tile_size",
+    &game.panel.shield_normal.size
+  },
+  {
+    "game.panel.shield_normal.draw_masked",
+    &game.panel.shield_normal.draw_masked
+  },
+  {
+    "game.panel.shield_normal.draw_order",
+    &game.panel.shield_normal.sort_priority
+  },
+  {
+    "game.panel.shield_normal_time.x",
+    &game.panel.shield_normal_time.x
+  },
+  {
+    "game.panel.shield_normal_time.y",
+    &game.panel.shield_normal_time.y
+  },
+  {
+    "game.panel.shield_normal_time.align",
+    &game.panel.shield_normal_time.align
+  },
+  {
+    "game.panel.shield_normal_time.valign",
+    &game.panel.shield_normal_time.valign
+  },
+  {
+    "game.panel.shield_normal_time.digits",
+    &game.panel.shield_normal_time.size
+  },
+  {
+    "game.panel.shield_normal_time.font",
+    &game.panel.shield_normal_time.font
+  },
+  {
+    "game.panel.shield_normal_time.draw_masked",
+    &game.panel.shield_normal_time.draw_masked
+  },
+  {
+    "game.panel.shield_normal_time.draw_order",
+    &game.panel.shield_normal_time.sort_priority
+  },
+  {
+    "game.panel.shield_deadly.x",
+    &game.panel.shield_deadly.x
+  },
+  {
+    "game.panel.shield_deadly.y",
+    &game.panel.shield_deadly.y
+  },
+  {
+    "game.panel.shield_deadly.tile_size",
+    &game.panel.shield_deadly.size
+  },
+  {
+    "game.panel.shield_deadly.draw_masked",
+    &game.panel.shield_deadly.draw_masked
+  },
+  {
+    "game.panel.shield_deadly.draw_order",
+    &game.panel.shield_deadly.sort_priority
+  },
+  {
+    "game.panel.shield_deadly_time.x",
+    &game.panel.shield_deadly_time.x
+  },
+  {
+    "game.panel.shield_deadly_time.y",
+    &game.panel.shield_deadly_time.y
+  },
+  {
+    "game.panel.shield_deadly_time.align",
+    &game.panel.shield_deadly_time.align
+  },
+  {
+    "game.panel.shield_deadly_time.valign",
+    &game.panel.shield_deadly_time.valign
+  },
+  {
+    "game.panel.shield_deadly_time.digits",
+    &game.panel.shield_deadly_time.size
+  },
+  {
+    "game.panel.shield_deadly_time.font",
+    &game.panel.shield_deadly_time.font
+  },
+  {
+    "game.panel.shield_deadly_time.draw_masked",
+    &game.panel.shield_deadly_time.draw_masked
+  },
+  {
+    "game.panel.shield_deadly_time.draw_order",
+    &game.panel.shield_deadly_time.sort_priority
+  },
+  {
+    "game.panel.exit.x",
+    &game.panel.exit.x
+  },
+  {
+    "game.panel.exit.y",
+    &game.panel.exit.y
+  },
+  {
+    "game.panel.exit.tile_size",
+    &game.panel.exit.size
+  },
+  {
+    "game.panel.exit.draw_masked",
+    &game.panel.exit.draw_masked
+  },
+  {
+    "game.panel.exit.draw_order",
+    &game.panel.exit.sort_priority
+  },
+  {
+    "game.panel.emc_magic_ball.x",
+    &game.panel.emc_magic_ball.x
+  },
+  {
+    "game.panel.emc_magic_ball.y",
+    &game.panel.emc_magic_ball.y
+  },
+  {
+    "game.panel.emc_magic_ball.tile_size",
+    &game.panel.emc_magic_ball.size
+  },
+  {
+    "game.panel.emc_magic_ball.draw_masked",
+    &game.panel.emc_magic_ball.draw_masked
+  },
+  {
+    "game.panel.emc_magic_ball.draw_order",
+    &game.panel.emc_magic_ball.sort_priority
+  },
+  {
+    "game.panel.emc_magic_ball_switch.x",
+    &game.panel.emc_magic_ball_switch.x
+  },
+  {
+    "game.panel.emc_magic_ball_switch.y",
+    &game.panel.emc_magic_ball_switch.y
+  },
+  {
+    "game.panel.emc_magic_ball_switch.tile_size",
+    &game.panel.emc_magic_ball_switch.size
+  },
+  {
+    "game.panel.emc_magic_ball_switch.draw_masked",
+    &game.panel.emc_magic_ball_switch.draw_masked
+  },
+  {
+    "game.panel.emc_magic_ball_switch.draw_order",
+    &game.panel.emc_magic_ball_switch.sort_priority
+  },
+  {
+    "game.panel.light_switch.x",
+    &game.panel.light_switch.x
+  },
+  {
+    "game.panel.light_switch.y",
+    &game.panel.light_switch.y
+  },
+  {
+    "game.panel.light_switch.tile_size",
+    &game.panel.light_switch.size
+  },
+  {
+    "game.panel.light_switch.draw_masked",
+    &game.panel.light_switch.draw_masked
+  },
+  {
+    "game.panel.light_switch.draw_order",
+    &game.panel.light_switch.sort_priority
+  },
+  {
+    "game.panel.light_switch_time.x",
+    &game.panel.light_switch_time.x
+  },
+  {
+    "game.panel.light_switch_time.y",
+    &game.panel.light_switch_time.y
+  },
+  {
+    "game.panel.light_switch_time.align",
+    &game.panel.light_switch_time.align
+  },
+  {
+    "game.panel.light_switch_time.valign",
+    &game.panel.light_switch_time.valign
+  },
+  {
+    "game.panel.light_switch_time.digits",
+    &game.panel.light_switch_time.size
+  },
+  {
+    "game.panel.light_switch_time.font",
+    &game.panel.light_switch_time.font
+  },
+  {
+    "game.panel.light_switch_time.draw_masked",
+    &game.panel.light_switch_time.draw_masked
+  },
+  {
+    "game.panel.light_switch_time.draw_order",
+    &game.panel.light_switch_time.sort_priority
+  },
+  {
+    "game.panel.timegate_switch.x",
+    &game.panel.timegate_switch.x
+  },
+  {
+    "game.panel.timegate_switch.y",
+    &game.panel.timegate_switch.y
+  },
+  {
+    "game.panel.timegate_switch.tile_size",
+    &game.panel.timegate_switch.size
+  },
+  {
+    "game.panel.timegate_switch.draw_masked",
+    &game.panel.timegate_switch.draw_masked
+  },
+  {
+    "game.panel.timegate_switch.draw_order",
+    &game.panel.timegate_switch.sort_priority
+  },
+  {
+    "game.panel.timegate_switch_time.x",
+    &game.panel.timegate_switch_time.x
+  },
+  {
+    "game.panel.timegate_switch_time.y",
+    &game.panel.timegate_switch_time.y
+  },
+  {
+    "game.panel.timegate_switch_time.align",
+    &game.panel.timegate_switch_time.align
+  },
+  {
+    "game.panel.timegate_switch_time.valign",
+    &game.panel.timegate_switch_time.valign
+  },
+  {
+    "game.panel.timegate_switch_time.digits",
+    &game.panel.timegate_switch_time.size
+  },
+  {
+    "game.panel.timegate_switch_time.font",
+    &game.panel.timegate_switch_time.font
+  },
+  {
+    "game.panel.timegate_switch_time.draw_masked",
+    &game.panel.timegate_switch_time.draw_masked
+  },
+  {
+    "game.panel.timegate_switch_time.draw_order",
+    &game.panel.timegate_switch_time.sort_priority
+  },
+  {
+    "game.panel.switchgate_switch.x",
+    &game.panel.switchgate_switch.x
+  },
+  {
+    "game.panel.switchgate_switch.y",
+    &game.panel.switchgate_switch.y
+  },
+  {
+    "game.panel.switchgate_switch.tile_size",
+    &game.panel.switchgate_switch.size
+  },
+  {
+    "game.panel.switchgate_switch.draw_masked",
+    &game.panel.switchgate_switch.draw_masked
+  },
+  {
+    "game.panel.switchgate_switch.draw_order",
+    &game.panel.switchgate_switch.sort_priority
+  },
+  {
+    "game.panel.emc_lenses.x",
+    &game.panel.emc_lenses.x
+  },
+  {
+    "game.panel.emc_lenses.y",
+    &game.panel.emc_lenses.y
+  },
+  {
+    "game.panel.emc_lenses.tile_size",
+    &game.panel.emc_lenses.size
+  },
+  {
+    "game.panel.emc_lenses.draw_masked",
+    &game.panel.emc_lenses.draw_masked
+  },
+  {
+    "game.panel.emc_lenses.draw_order",
+    &game.panel.emc_lenses.sort_priority
+  },
+  {
+    "game.panel.emc_lenses_time.x",
+    &game.panel.emc_lenses_time.x
+  },
+  {
+    "game.panel.emc_lenses_time.y",
+    &game.panel.emc_lenses_time.y
+  },
+  {
+    "game.panel.emc_lenses_time.align",
+    &game.panel.emc_lenses_time.align
+  },
+  {
+    "game.panel.emc_lenses_time.valign",
+    &game.panel.emc_lenses_time.valign
+  },
+  {
+    "game.panel.emc_lenses_time.digits",
+    &game.panel.emc_lenses_time.size
+  },
+  {
+    "game.panel.emc_lenses_time.font",
+    &game.panel.emc_lenses_time.font
+  },
+  {
+    "game.panel.emc_lenses_time.draw_masked",
+    &game.panel.emc_lenses_time.draw_masked
+  },
+  {
+    "game.panel.emc_lenses_time.draw_order",
+    &game.panel.emc_lenses_time.sort_priority
+  },
+  {
+    "game.panel.emc_magnifier.x",
+    &game.panel.emc_magnifier.x
+  },
+  {
+    "game.panel.emc_magnifier.y",
+    &game.panel.emc_magnifier.y
+  },
+  {
+    "game.panel.emc_magnifier.tile_size",
+    &game.panel.emc_magnifier.size
+  },
+  {
+    "game.panel.emc_magnifier.draw_masked",
+    &game.panel.emc_magnifier.draw_masked
+  },
+  {
+    "game.panel.emc_magnifier.draw_order",
+    &game.panel.emc_magnifier.sort_priority
+  },
+  {
+    "game.panel.emc_magnifier_time.x",
+    &game.panel.emc_magnifier_time.x
+  },
+  {
+    "game.panel.emc_magnifier_time.y",
+    &game.panel.emc_magnifier_time.y
+  },
+  {
+    "game.panel.emc_magnifier_time.align",
+    &game.panel.emc_magnifier_time.align
+  },
+  {
+    "game.panel.emc_magnifier_time.valign",
+    &game.panel.emc_magnifier_time.valign
+  },
+  {
+    "game.panel.emc_magnifier_time.digits",
+    &game.panel.emc_magnifier_time.size
+  },
+  {
+    "game.panel.emc_magnifier_time.font",
+    &game.panel.emc_magnifier_time.font
+  },
+  {
+    "game.panel.emc_magnifier_time.draw_masked",
+    &game.panel.emc_magnifier_time.draw_masked
+  },
+  {
+    "game.panel.emc_magnifier_time.draw_order",
+    &game.panel.emc_magnifier_time.sort_priority
+  },
+  {
+    "game.panel.balloon_switch.x",
+    &game.panel.balloon_switch.x
+  },
+  {
+    "game.panel.balloon_switch.y",
+    &game.panel.balloon_switch.y
+  },
+  {
+    "game.panel.balloon_switch.tile_size",
+    &game.panel.balloon_switch.size
+  },
+  {
+    "game.panel.balloon_switch.draw_masked",
+    &game.panel.balloon_switch.draw_masked
+  },
+  {
+    "game.panel.balloon_switch.draw_order",
+    &game.panel.balloon_switch.sort_priority
+  },
+  {
+    "game.panel.dynabomb_number.x",
+    &game.panel.dynabomb_number.x
+  },
+  {
+    "game.panel.dynabomb_number.y",
+    &game.panel.dynabomb_number.y
+  },
+  {
+    "game.panel.dynabomb_number.align",
+    &game.panel.dynabomb_number.align
+  },
+  {
+    "game.panel.dynabomb_number.valign",
+    &game.panel.dynabomb_number.valign
+  },
+  {
+    "game.panel.dynabomb_number.digits",
+    &game.panel.dynabomb_number.size
+  },
+  {
+    "game.panel.dynabomb_number.font",
+    &game.panel.dynabomb_number.font
+  },
+  {
+    "game.panel.dynabomb_number.draw_masked",
+    &game.panel.dynabomb_number.draw_masked
+  },
+  {
+    "game.panel.dynabomb_number.draw_order",
+    &game.panel.dynabomb_number.sort_priority
+  },
+  {
+    "game.panel.dynabomb_size.x",
+    &game.panel.dynabomb_size.x
+  },
+  {
+    "game.panel.dynabomb_size.y",
+    &game.panel.dynabomb_size.y
+  },
+  {
+    "game.panel.dynabomb_size.align",
+    &game.panel.dynabomb_size.align
+  },
+  {
+    "game.panel.dynabomb_size.valign",
+    &game.panel.dynabomb_size.valign
+  },
+  {
+    "game.panel.dynabomb_size.digits",
+    &game.panel.dynabomb_size.size
+  },
+  {
+    "game.panel.dynabomb_size.font",
+    &game.panel.dynabomb_size.font
+  },
+  {
+    "game.panel.dynabomb_size.draw_masked",
+    &game.panel.dynabomb_size.draw_masked
+  },
+  {
+    "game.panel.dynabomb_size.draw_order",
+    &game.panel.dynabomb_size.sort_priority
+  },
+  {
+    "game.panel.dynabomb_power.x",
+    &game.panel.dynabomb_power.x
+  },
+  {
+    "game.panel.dynabomb_power.y",
+    &game.panel.dynabomb_power.y
+  },
+  {
+    "game.panel.dynabomb_power.tile_size",
+    &game.panel.dynabomb_power.size
+  },
+  {
+    "game.panel.dynabomb_power.draw_masked",
+    &game.panel.dynabomb_power.draw_masked
+  },
+  {
+    "game.panel.dynabomb_power.draw_order",
+    &game.panel.dynabomb_power.sort_priority
+  },
+  {
+    "game.panel.penguins.x",
+    &game.panel.penguins.x
+  },
+  {
+    "game.panel.penguins.y",
+    &game.panel.penguins.y
+  },
+  {
+    "game.panel.penguins.align",
+    &game.panel.penguins.align
+  },
+  {
+    "game.panel.penguins.valign",
+    &game.panel.penguins.valign
+  },
+  {
+    "game.panel.penguins.digits",
+    &game.panel.penguins.size
+  },
+  {
+    "game.panel.penguins.font",
+    &game.panel.penguins.font
+  },
+  {
+    "game.panel.penguins.draw_masked",
+    &game.panel.penguins.draw_masked
+  },
+  {
+    "game.panel.penguins.draw_order",
+    &game.panel.penguins.sort_priority
+  },
+  {
+    "game.panel.sokoban_objects.x",
+    &game.panel.sokoban_objects.x
+  },
+  {
+    "game.panel.sokoban_objects.y",
+    &game.panel.sokoban_objects.y
+  },
+  {
+    "game.panel.sokoban_objects.align",
+    &game.panel.sokoban_objects.align
+  },
+  {
+    "game.panel.sokoban_objects.valign",
+    &game.panel.sokoban_objects.valign
+  },
+  {
+    "game.panel.sokoban_objects.digits",
+    &game.panel.sokoban_objects.size
+  },
+  {
+    "game.panel.sokoban_objects.font",
+    &game.panel.sokoban_objects.font
+  },
+  {
+    "game.panel.sokoban_objects.draw_masked",
+    &game.panel.sokoban_objects.draw_masked
+  },
+  {
+    "game.panel.sokoban_objects.draw_order",
+    &game.panel.sokoban_objects.sort_priority
+  },
+  {
+    "game.panel.sokoban_fields.x",
+    &game.panel.sokoban_fields.x
+  },
+  {
+    "game.panel.sokoban_fields.y",
+    &game.panel.sokoban_fields.y
+  },
+  {
+    "game.panel.sokoban_fields.align",
+    &game.panel.sokoban_fields.align
+  },
+  {
+    "game.panel.sokoban_fields.valign",
+    &game.panel.sokoban_fields.valign
+  },
+  {
+    "game.panel.sokoban_fields.digits",
+    &game.panel.sokoban_fields.size
+  },
+  {
+    "game.panel.sokoban_fields.font",
+    &game.panel.sokoban_fields.font
+  },
+  {
+    "game.panel.sokoban_fields.draw_masked",
+    &game.panel.sokoban_fields.draw_masked
+  },
+  {
+    "game.panel.sokoban_fields.draw_order",
+    &game.panel.sokoban_fields.sort_priority
+  },
+  {
+    "game.panel.robot_wheel.x",
+    &game.panel.robot_wheel.x
+  },
+  {
+    "game.panel.robot_wheel.y",
+    &game.panel.robot_wheel.y
+  },
+  {
+    "game.panel.robot_wheel.tile_size",
+    &game.panel.robot_wheel.size
+  },
+  {
+    "game.panel.robot_wheel.draw_masked",
+    &game.panel.robot_wheel.draw_masked
+  },
+  {
+    "game.panel.robot_wheel.draw_order",
+    &game.panel.robot_wheel.sort_priority
+  },
+  {
+    "game.panel.conveyor_belt_1.x",
+    &game.panel.conveyor_belt[0].x
+  },
+  {
+    "game.panel.conveyor_belt_1.y",
+    &game.panel.conveyor_belt[0].y
+  },
+  {
+    "game.panel.conveyor_belt_1.tile_size",
+    &game.panel.conveyor_belt[0].size
+  },
+  {
+    "game.panel.conveyor_belt_1.draw_masked",
+    &game.panel.conveyor_belt[0].draw_masked
+  },
+  {
+    "game.panel.conveyor_belt_1.draw_order",
+    &game.panel.conveyor_belt[0].sort_priority
+  },
+  {
+    "game.panel.conveyor_belt_1_switch.x",
+    &game.panel.conveyor_belt_switch[0].x
+  },
+  {
+    "game.panel.conveyor_belt_1_switch.y",
+    &game.panel.conveyor_belt_switch[0].y
+  },
+  {
+    "game.panel.conveyor_belt_1_switch.tile_size",
+    &game.panel.conveyor_belt_switch[0].size
+  },
+  {
+    "game.panel.conveyor_belt_1_switch.draw_masked",
+    &game.panel.conveyor_belt_switch[0].draw_masked
+  },
+  {
+    "game.panel.conveyor_belt_1_switch.draw_order",
+    &game.panel.conveyor_belt_switch[0].sort_priority
+  },
+  {
+    "game.panel.conveyor_belt_2.x",
+    &game.panel.conveyor_belt[1].x
+  },
+  {
+    "game.panel.conveyor_belt_2.y",
+    &game.panel.conveyor_belt[1].y
+  },
+  {
+    "game.panel.conveyor_belt_2.tile_size",
+    &game.panel.conveyor_belt[1].size
+  },
+  {
+    "game.panel.conveyor_belt_2.draw_masked",
+    &game.panel.conveyor_belt[1].draw_masked
+  },
+  {
+    "game.panel.conveyor_belt_2.draw_order",
+    &game.panel.conveyor_belt[1].sort_priority
+  },
+  {
+    "game.panel.conveyor_belt_2_switch.x",
+    &game.panel.conveyor_belt_switch[1].x
+  },
+  {
+    "game.panel.conveyor_belt_2_switch.y",
+    &game.panel.conveyor_belt_switch[1].y
+  },
+  {
+    "game.panel.conveyor_belt_2_switch.tile_size",
+    &game.panel.conveyor_belt_switch[1].size
+  },
+  {
+    "game.panel.conveyor_belt_2_switch.draw_masked",
+    &game.panel.conveyor_belt_switch[1].draw_masked
+  },
+  {
+    "game.panel.conveyor_belt_2_switch.draw_order",
+    &game.panel.conveyor_belt_switch[1].sort_priority
+  },
+  {
+    "game.panel.conveyor_belt_3.x",
+    &game.panel.conveyor_belt[2].x
+  },
+  {
+    "game.panel.conveyor_belt_3.y",
+    &game.panel.conveyor_belt[2].y
+  },
+  {
+    "game.panel.conveyor_belt_3.tile_size",
+    &game.panel.conveyor_belt[2].size
+  },
+  {
+    "game.panel.conveyor_belt_3.draw_masked",
+    &game.panel.conveyor_belt[2].draw_masked
+  },
+  {
+    "game.panel.conveyor_belt_3.draw_order",
+    &game.panel.conveyor_belt[2].sort_priority
+  },
+  {
+    "game.panel.conveyor_belt_3_switch.x",
+    &game.panel.conveyor_belt_switch[2].x
+  },
+  {
+    "game.panel.conveyor_belt_3_switch.y",
+    &game.panel.conveyor_belt_switch[2].y
+  },
+  {
+    "game.panel.conveyor_belt_3_switch.tile_size",
+    &game.panel.conveyor_belt_switch[2].size
+  },
+  {
+    "game.panel.conveyor_belt_3_switch.draw_masked",
+    &game.panel.conveyor_belt_switch[2].draw_masked
+  },
+  {
+    "game.panel.conveyor_belt_3_switch.draw_order",
+    &game.panel.conveyor_belt_switch[2].sort_priority
+  },
+  {
+    "game.panel.conveyor_belt_4.x",
+    &game.panel.conveyor_belt[3].x
+  },
+  {
+    "game.panel.conveyor_belt_4.y",
+    &game.panel.conveyor_belt[3].y
+  },
+  {
+    "game.panel.conveyor_belt_4.tile_size",
+    &game.panel.conveyor_belt[3].size
+  },
+  {
+    "game.panel.conveyor_belt_4.draw_masked",
+    &game.panel.conveyor_belt[3].draw_masked
   },
   {
-    "game.panel.highscore.align",
-    &game.panel.highscore.align
+    "game.panel.conveyor_belt_4.draw_order",
+    &game.panel.conveyor_belt[3].sort_priority
   },
   {
-    "game.panel.highscore.valign",
-    &game.panel.highscore.valign
+    "game.panel.conveyor_belt_4_switch.x",
+    &game.panel.conveyor_belt_switch[3].x
   },
   {
-    "game.panel.highscore.digits",
-    &game.panel.highscore.size
+    "game.panel.conveyor_belt_4_switch.y",
+    &game.panel.conveyor_belt_switch[3].y
   },
   {
-    "game.panel.highscore.font",
-    &game.panel.highscore.font
+    "game.panel.conveyor_belt_4_switch.tile_size",
+    &game.panel.conveyor_belt_switch[3].size
   },
   {
-    "game.panel.highscore.draw_masked",
-    &game.panel.highscore.draw_masked
+    "game.panel.conveyor_belt_4_switch.draw_masked",
+    &game.panel.conveyor_belt_switch[3].draw_masked
   },
   {
-    "game.panel.highscore.draw_order",
-    &game.panel.highscore.sort_priority
+    "game.panel.conveyor_belt_4_switch.draw_order",
+    &game.panel.conveyor_belt_switch[3].sort_priority
   },
   {
-    "game.panel.time.x",
-    &game.panel.time.x
+    "game.panel.magic_wall.x",
+    &game.panel.magic_wall.x
+  },
+  {
+    "game.panel.magic_wall.y",
+    &game.panel.magic_wall.y
+  },
+  {
+    "game.panel.magic_wall.tile_size",
+    &game.panel.magic_wall.size
+  },
+  {
+    "game.panel.magic_wall.draw_masked",
+    &game.panel.magic_wall.draw_masked
+  },
+  {
+    "game.panel.magic_wall.draw_order",
+    &game.panel.magic_wall.sort_priority
+  },
+  {
+    "game.panel.magic_wall_time.x",
+    &game.panel.magic_wall_time.x
+  },
+  {
+    "game.panel.magic_wall_time.y",
+    &game.panel.magic_wall_time.y
+  },
+  {
+    "game.panel.magic_wall_time.align",
+    &game.panel.magic_wall_time.align
+  },
+  {
+    "game.panel.magic_wall_time.valign",
+    &game.panel.magic_wall_time.valign
+  },
+  {
+    "game.panel.magic_wall_time.digits",
+    &game.panel.magic_wall_time.size
+  },
+  {
+    "game.panel.magic_wall_time.font",
+    &game.panel.magic_wall_time.font
+  },
+  {
+    "game.panel.magic_wall_time.draw_masked",
+    &game.panel.magic_wall_time.draw_masked
+  },
+  {
+    "game.panel.magic_wall_time.draw_order",
+    &game.panel.magic_wall_time.sort_priority
+  },
+  {
+    "game.panel.gravity_state.x",
+    &game.panel.gravity_state.x
+  },
+  {
+    "game.panel.gravity_state.y",
+    &game.panel.gravity_state.y
+  },
+  {
+    "game.panel.gravity_state.align",
+    &game.panel.gravity_state.align
+  },
+  {
+    "game.panel.gravity_state.valign",
+    &game.panel.gravity_state.valign
+  },
+  {
+    "game.panel.gravity_state.chars",
+    &game.panel.gravity_state.size
+  },
+  {
+    "game.panel.gravity_state.font",
+    &game.panel.gravity_state.font
+  },
+  {
+    "game.panel.gravity_state.font_active",
+    &game.panel.gravity_state.font_alt
+  },
+  {
+    "game.panel.gravity_state.draw_masked",
+    &game.panel.gravity_state.draw_masked
+  },
+  {
+    "game.panel.gravity_state.draw_order",
+    &game.panel.gravity_state.sort_priority
+  },
+  {
+    "game.panel.graphic_1.x",
+    &game.panel.graphic[0].x
+  },
+  {
+    "game.panel.graphic_1.y",
+    &game.panel.graphic[0].y
+  },
+  {
+    "game.panel.graphic_1.draw_masked",
+    &game.panel.graphic[0].draw_masked
+  },
+  {
+    "game.panel.graphic_1.draw_order",
+    &game.panel.graphic[0].sort_priority
+  },
+  {
+    "game.panel.graphic_2.x",
+    &game.panel.graphic[1].x
+  },
+  {
+    "game.panel.graphic_2.y",
+    &game.panel.graphic[1].y
+  },
+  {
+    "game.panel.graphic_2.draw_masked",
+    &game.panel.graphic[1].draw_masked
+  },
+  {
+    "game.panel.graphic_2.draw_order",
+    &game.panel.graphic[1].sort_priority
+  },
+  {
+    "game.panel.graphic_3.x",
+    &game.panel.graphic[2].x
+  },
+  {
+    "game.panel.graphic_3.y",
+    &game.panel.graphic[2].y
+  },
+  {
+    "game.panel.graphic_3.draw_masked",
+    &game.panel.graphic[2].draw_masked
+  },
+  {
+    "game.panel.graphic_3.draw_order",
+    &game.panel.graphic[2].sort_priority
+  },
+  {
+    "game.panel.graphic_4.x",
+    &game.panel.graphic[3].x
+  },
+  {
+    "game.panel.graphic_4.y",
+    &game.panel.graphic[3].y
+  },
+  {
+    "game.panel.graphic_4.draw_masked",
+    &game.panel.graphic[3].draw_masked
+  },
+  {
+    "game.panel.graphic_4.draw_order",
+    &game.panel.graphic[3].sort_priority
+  },
+  {
+    "game.panel.graphic_5.x",
+    &game.panel.graphic[4].x
+  },
+  {
+    "game.panel.graphic_5.y",
+    &game.panel.graphic[4].y
+  },
+  {
+    "game.panel.graphic_5.draw_masked",
+    &game.panel.graphic[4].draw_masked
+  },
+  {
+    "game.panel.graphic_5.draw_order",
+    &game.panel.graphic[4].sort_priority
+  },
+  {
+    "game.panel.graphic_6.x",
+    &game.panel.graphic[5].x
+  },
+  {
+    "game.panel.graphic_6.y",
+    &game.panel.graphic[5].y
+  },
+  {
+    "game.panel.graphic_6.draw_masked",
+    &game.panel.graphic[5].draw_masked
+  },
+  {
+    "game.panel.graphic_6.draw_order",
+    &game.panel.graphic[5].sort_priority
+  },
+  {
+    "game.panel.graphic_7.x",
+    &game.panel.graphic[6].x
+  },
+  {
+    "game.panel.graphic_7.y",
+    &game.panel.graphic[6].y
+  },
+  {
+    "game.panel.graphic_7.draw_masked",
+    &game.panel.graphic[6].draw_masked
+  },
+  {
+    "game.panel.graphic_7.draw_order",
+    &game.panel.graphic[6].sort_priority
+  },
+  {
+    "game.panel.graphic_8.x",
+    &game.panel.graphic[7].x
+  },
+  {
+    "game.panel.graphic_8.y",
+    &game.panel.graphic[7].y
+  },
+  {
+    "game.panel.graphic_8.draw_masked",
+    &game.panel.graphic[7].draw_masked
+  },
+  {
+    "game.panel.graphic_8.draw_order",
+    &game.panel.graphic[7].sort_priority
+  },
+  {
+    "game.panel.element_1.x",
+    &game.panel.element[0].x
+  },
+  {
+    "game.panel.element_1.y",
+    &game.panel.element[0].y
+  },
+  {
+    "game.panel.element_1.tile_size",
+    &game.panel.element[0].size
+  },
+  {
+    "game.panel.element_1.element",
+    &game.panel.element[0].id
   },
   {
-    "game.panel.time.y",
-    &game.panel.time.y
+    "game.panel.element_1.draw_masked",
+    &game.panel.element[0].draw_masked
   },
   {
-    "game.panel.time.align",
-    &game.panel.time.align
+    "game.panel.element_1.draw_order",
+    &game.panel.element[0].sort_priority
   },
   {
-    "game.panel.time.valign",
-    &game.panel.time.valign
+    "game.panel.element_1_count.x",
+    &game.panel.element_count[0].x
   },
   {
-    "game.panel.time.digits",
-    &game.panel.time.size
+    "game.panel.element_1_count.y",
+    &game.panel.element_count[0].y
   },
   {
-    "game.panel.time.font",
-    &game.panel.time.font
+    "game.panel.element_1_count.align",
+    &game.panel.element_count[0].align
   },
   {
-    "game.panel.time.font_narrow",
-    &game.panel.time.font_alt
+    "game.panel.element_1_count.valign",
+    &game.panel.element_count[0].valign
   },
   {
-    "game.panel.time.draw_masked",
-    &game.panel.time.draw_masked
+    "game.panel.element_1_count.digits",
+    &game.panel.element_count[0].size
   },
   {
-    "game.panel.time.draw_order",
-    &game.panel.time.sort_priority
+    "game.panel.element_1_count.font",
+    &game.panel.element_count[0].font
   },
   {
-    "game.panel.time_hh.x",
-    &game.panel.time_hh.x
+    "game.panel.element_1_count.element",
+    &game.panel.element_count[0].id
   },
   {
-    "game.panel.time_hh.y",
-    &game.panel.time_hh.y
+    "game.panel.element_1_count.draw_masked",
+    &game.panel.element_count[0].draw_masked
   },
   {
-    "game.panel.time_hh.align",
-    &game.panel.time_hh.align
+    "game.panel.element_1_count.draw_order",
+    &game.panel.element_count[0].sort_priority
   },
   {
-    "game.panel.time_hh.valign",
-    &game.panel.time_hh.valign
+    "game.panel.element_2.x",
+    &game.panel.element[1].x
   },
   {
-    "game.panel.time_hh.digits",
-    &game.panel.time_hh.size
+    "game.panel.element_2.y",
+    &game.panel.element[1].y
   },
   {
-    "game.panel.time_hh.font",
-    &game.panel.time_hh.font
+    "game.panel.element_2.tile_size",
+    &game.panel.element[1].size
   },
   {
-    "game.panel.time_hh.draw_masked",
-    &game.panel.time_hh.draw_masked
+    "game.panel.element_2.element",
+    &game.panel.element[1].id
   },
   {
-    "game.panel.time_hh.draw_order",
-    &game.panel.time_hh.sort_priority
+    "game.panel.element_2.draw_masked",
+    &game.panel.element[1].draw_masked
   },
   {
-    "game.panel.time_mm.x",
-    &game.panel.time_mm.x
+    "game.panel.element_2.draw_order",
+    &game.panel.element[1].sort_priority
   },
   {
-    "game.panel.time_mm.y",
-    &game.panel.time_mm.y
+    "game.panel.element_2_count.x",
+    &game.panel.element_count[1].x
   },
   {
-    "game.panel.time_mm.align",
-    &game.panel.time_mm.align
+    "game.panel.element_2_count.y",
+    &game.panel.element_count[1].y
   },
   {
-    "game.panel.time_mm.valign",
-    &game.panel.time_mm.valign
+    "game.panel.element_2_count.align",
+    &game.panel.element_count[1].align
   },
   {
-    "game.panel.time_mm.digits",
-    &game.panel.time_mm.size
+    "game.panel.element_2_count.valign",
+    &game.panel.element_count[1].valign
   },
   {
-    "game.panel.time_mm.font",
-    &game.panel.time_mm.font
+    "game.panel.element_2_count.digits",
+    &game.panel.element_count[1].size
   },
   {
-    "game.panel.time_mm.draw_masked",
-    &game.panel.time_mm.draw_masked
+    "game.panel.element_2_count.font",
+    &game.panel.element_count[1].font
   },
   {
-    "game.panel.time_mm.draw_order",
-    &game.panel.time_mm.sort_priority
+    "game.panel.element_2_count.element",
+    &game.panel.element_count[1].id
   },
   {
-    "game.panel.time_ss.x",
-    &game.panel.time_ss.x
+    "game.panel.element_2_count.draw_masked",
+    &game.panel.element_count[1].draw_masked
   },
   {
-    "game.panel.time_ss.y",
-    &game.panel.time_ss.y
+    "game.panel.element_2_count.draw_order",
+    &game.panel.element_count[1].sort_priority
   },
   {
-    "game.panel.time_ss.align",
-    &game.panel.time_ss.align
+    "game.panel.element_3.x",
+    &game.panel.element[2].x
   },
   {
-    "game.panel.time_ss.valign",
-    &game.panel.time_ss.valign
+    "game.panel.element_3.y",
+    &game.panel.element[2].y
   },
   {
-    "game.panel.time_ss.digits",
-    &game.panel.time_ss.size
+    "game.panel.element_3.tile_size",
+    &game.panel.element[2].size
   },
   {
-    "game.panel.time_ss.font",
-    &game.panel.time_ss.font
+    "game.panel.element_3.element",
+    &game.panel.element[2].id
   },
   {
-    "game.panel.time_ss.draw_masked",
-    &game.panel.time_ss.draw_masked
+    "game.panel.element_3.draw_masked",
+    &game.panel.element[2].draw_masked
   },
   {
-    "game.panel.time_ss.draw_order",
-    &game.panel.time_ss.sort_priority
+    "game.panel.element_3.draw_order",
+    &game.panel.element[2].sort_priority
   },
   {
-    "game.panel.frame.x",
-    &game.panel.frame.x
+    "game.panel.element_3_count.x",
+    &game.panel.element_count[2].x
   },
   {
-    "game.panel.frame.y",
-    &game.panel.frame.y
+    "game.panel.element_3_count.y",
+    &game.panel.element_count[2].y
   },
   {
-    "game.panel.frame.align",
-    &game.panel.frame.align
+    "game.panel.element_3_count.align",
+    &game.panel.element_count[2].align
   },
   {
-    "game.panel.frame.valign",
-    &game.panel.frame.valign
+    "game.panel.element_3_count.valign",
+    &game.panel.element_count[2].valign
   },
   {
-    "game.panel.frame.digits",
-    &game.panel.frame.size
+    "game.panel.element_3_count.digits",
+    &game.panel.element_count[2].size
   },
   {
-    "game.panel.frame.font",
-    &game.panel.frame.font
+    "game.panel.element_3_count.font",
+    &game.panel.element_count[2].font
   },
   {
-    "game.panel.frame.draw_masked",
-    &game.panel.frame.draw_masked
+    "game.panel.element_3_count.element",
+    &game.panel.element_count[2].id
   },
   {
-    "game.panel.frame.draw_order",
-    &game.panel.frame.sort_priority
+    "game.panel.element_3_count.draw_masked",
+    &game.panel.element_count[2].draw_masked
   },
   {
-    "game.panel.shield_normal.x",
-    &game.panel.shield_normal.x
+    "game.panel.element_3_count.draw_order",
+    &game.panel.element_count[2].sort_priority
   },
   {
-    "game.panel.shield_normal.y",
-    &game.panel.shield_normal.y
+    "game.panel.element_4.x",
+    &game.panel.element[3].x
   },
   {
-    "game.panel.shield_normal.tile_size",
-    &game.panel.shield_normal.size
+    "game.panel.element_4.y",
+    &game.panel.element[3].y
   },
   {
-    "game.panel.shield_normal.draw_masked",
-    &game.panel.shield_normal.draw_masked
+    "game.panel.element_4.tile_size",
+    &game.panel.element[3].size
   },
   {
-    "game.panel.shield_normal.draw_order",
-    &game.panel.shield_normal.sort_priority
+    "game.panel.element_4.element",
+    &game.panel.element[3].id
   },
   {
-    "game.panel.shield_normal_time.x",
-    &game.panel.shield_normal_time.x
+    "game.panel.element_4.draw_masked",
+    &game.panel.element[3].draw_masked
   },
   {
-    "game.panel.shield_normal_time.y",
-    &game.panel.shield_normal_time.y
+    "game.panel.element_4.draw_order",
+    &game.panel.element[3].sort_priority
   },
   {
-    "game.panel.shield_normal_time.align",
-    &game.panel.shield_normal_time.align
+    "game.panel.element_4_count.x",
+    &game.panel.element_count[3].x
   },
   {
-    "game.panel.shield_normal_time.valign",
-    &game.panel.shield_normal_time.valign
+    "game.panel.element_4_count.y",
+    &game.panel.element_count[3].y
   },
   {
-    "game.panel.shield_normal_time.digits",
-    &game.panel.shield_normal_time.size
+    "game.panel.element_4_count.align",
+    &game.panel.element_count[3].align
   },
   {
-    "game.panel.shield_normal_time.font",
-    &game.panel.shield_normal_time.font
+    "game.panel.element_4_count.valign",
+    &game.panel.element_count[3].valign
   },
   {
-    "game.panel.shield_normal_time.draw_masked",
-    &game.panel.shield_normal_time.draw_masked
+    "game.panel.element_4_count.digits",
+    &game.panel.element_count[3].size
   },
   {
-    "game.panel.shield_normal_time.draw_order",
-    &game.panel.shield_normal_time.sort_priority
+    "game.panel.element_4_count.font",
+    &game.panel.element_count[3].font
   },
   {
-    "game.panel.shield_deadly.x",
-    &game.panel.shield_deadly.x
+    "game.panel.element_4_count.element",
+    &game.panel.element_count[3].id
   },
   {
-    "game.panel.shield_deadly.y",
-    &game.panel.shield_deadly.y
+    "game.panel.element_4_count.draw_masked",
+    &game.panel.element_count[3].draw_masked
   },
   {
-    "game.panel.shield_deadly.tile_size",
-    &game.panel.shield_deadly.size
+    "game.panel.element_4_count.draw_order",
+    &game.panel.element_count[3].sort_priority
   },
   {
-    "game.panel.shield_deadly.draw_masked",
-    &game.panel.shield_deadly.draw_masked
+    "game.panel.element_5.x",
+    &game.panel.element[4].x
   },
   {
-    "game.panel.shield_deadly.draw_order",
-    &game.panel.shield_deadly.sort_priority
+    "game.panel.element_5.y",
+    &game.panel.element[4].y
   },
   {
-    "game.panel.shield_deadly_time.x",
-    &game.panel.shield_deadly_time.x
+    "game.panel.element_5.tile_size",
+    &game.panel.element[4].size
   },
   {
-    "game.panel.shield_deadly_time.y",
-    &game.panel.shield_deadly_time.y
+    "game.panel.element_5.element",
+    &game.panel.element[4].id
   },
   {
-    "game.panel.shield_deadly_time.align",
-    &game.panel.shield_deadly_time.align
+    "game.panel.element_5.draw_masked",
+    &game.panel.element[4].draw_masked
   },
   {
-    "game.panel.shield_deadly_time.valign",
-    &game.panel.shield_deadly_time.valign
+    "game.panel.element_5.draw_order",
+    &game.panel.element[4].sort_priority
   },
   {
-    "game.panel.shield_deadly_time.digits",
-    &game.panel.shield_deadly_time.size
+    "game.panel.element_5_count.x",
+    &game.panel.element_count[4].x
   },
   {
-    "game.panel.shield_deadly_time.font",
-    &game.panel.shield_deadly_time.font
+    "game.panel.element_5_count.y",
+    &game.panel.element_count[4].y
   },
   {
-    "game.panel.shield_deadly_time.draw_masked",
-    &game.panel.shield_deadly_time.draw_masked
+    "game.panel.element_5_count.align",
+    &game.panel.element_count[4].align
   },
   {
-    "game.panel.shield_deadly_time.draw_order",
-    &game.panel.shield_deadly_time.sort_priority
+    "game.panel.element_5_count.valign",
+    &game.panel.element_count[4].valign
   },
   {
-    "game.panel.exit.x",
-    &game.panel.exit.x
+    "game.panel.element_5_count.digits",
+    &game.panel.element_count[4].size
   },
   {
-    "game.panel.exit.y",
-    &game.panel.exit.y
+    "game.panel.element_5_count.font",
+    &game.panel.element_count[4].font
   },
   {
-    "game.panel.exit.tile_size",
-    &game.panel.exit.size
+    "game.panel.element_5_count.element",
+    &game.panel.element_count[4].id
   },
   {
-    "game.panel.exit.draw_masked",
-    &game.panel.exit.draw_masked
+    "game.panel.element_5_count.draw_masked",
+    &game.panel.element_count[4].draw_masked
   },
   {
-    "game.panel.exit.draw_order",
-    &game.panel.exit.sort_priority
+    "game.panel.element_5_count.draw_order",
+    &game.panel.element_count[4].sort_priority
   },
   {
-    "game.panel.emc_magic_ball.x",
-    &game.panel.emc_magic_ball.x
+    "game.panel.element_6.x",
+    &game.panel.element[5].x
   },
   {
-    "game.panel.emc_magic_ball.y",
-    &game.panel.emc_magic_ball.y
+    "game.panel.element_6.y",
+    &game.panel.element[5].y
   },
   {
-    "game.panel.emc_magic_ball.tile_size",
-    &game.panel.emc_magic_ball.size
+    "game.panel.element_6.tile_size",
+    &game.panel.element[5].size
   },
   {
-    "game.panel.emc_magic_ball.draw_masked",
-    &game.panel.emc_magic_ball.draw_masked
+    "game.panel.element_6.element",
+    &game.panel.element[5].id
   },
   {
-    "game.panel.emc_magic_ball.draw_order",
-    &game.panel.emc_magic_ball.sort_priority
+    "game.panel.element_6.draw_masked",
+    &game.panel.element[5].draw_masked
   },
   {
-    "game.panel.emc_magic_ball_switch.x",
-    &game.panel.emc_magic_ball_switch.x
+    "game.panel.element_6.draw_order",
+    &game.panel.element[5].sort_priority
   },
   {
-    "game.panel.emc_magic_ball_switch.y",
-    &game.panel.emc_magic_ball_switch.y
+    "game.panel.element_6_count.x",
+    &game.panel.element_count[5].x
   },
   {
-    "game.panel.emc_magic_ball_switch.tile_size",
-    &game.panel.emc_magic_ball_switch.size
+    "game.panel.element_6_count.y",
+    &game.panel.element_count[5].y
   },
   {
-    "game.panel.emc_magic_ball_switch.draw_masked",
-    &game.panel.emc_magic_ball_switch.draw_masked
+    "game.panel.element_6_count.align",
+    &game.panel.element_count[5].align
   },
   {
-    "game.panel.emc_magic_ball_switch.draw_order",
-    &game.panel.emc_magic_ball_switch.sort_priority
+    "game.panel.element_6_count.valign",
+    &game.panel.element_count[5].valign
   },
   {
-    "game.panel.light_switch.x",
-    &game.panel.light_switch.x
+    "game.panel.element_6_count.digits",
+    &game.panel.element_count[5].size
   },
   {
-    "game.panel.light_switch.y",
-    &game.panel.light_switch.y
+    "game.panel.element_6_count.font",
+    &game.panel.element_count[5].font
   },
   {
-    "game.panel.light_switch.tile_size",
-    &game.panel.light_switch.size
+    "game.panel.element_6_count.element",
+    &game.panel.element_count[5].id
   },
   {
-    "game.panel.light_switch.draw_masked",
-    &game.panel.light_switch.draw_masked
+    "game.panel.element_6_count.draw_masked",
+    &game.panel.element_count[5].draw_masked
   },
   {
-    "game.panel.light_switch.draw_order",
-    &game.panel.light_switch.sort_priority
+    "game.panel.element_6_count.draw_order",
+    &game.panel.element_count[5].sort_priority
   },
   {
-    "game.panel.light_switch_time.x",
-    &game.panel.light_switch_time.x
+    "game.panel.element_7.x",
+    &game.panel.element[6].x
   },
   {
-    "game.panel.light_switch_time.y",
-    &game.panel.light_switch_time.y
+    "game.panel.element_7.y",
+    &game.panel.element[6].y
   },
   {
-    "game.panel.light_switch_time.align",
-    &game.panel.light_switch_time.align
+    "game.panel.element_7.tile_size",
+    &game.panel.element[6].size
   },
   {
-    "game.panel.light_switch_time.valign",
-    &game.panel.light_switch_time.valign
+    "game.panel.element_7.element",
+    &game.panel.element[6].id
   },
   {
-    "game.panel.light_switch_time.digits",
-    &game.panel.light_switch_time.size
+    "game.panel.element_7.draw_masked",
+    &game.panel.element[6].draw_masked
   },
   {
-    "game.panel.light_switch_time.font",
-    &game.panel.light_switch_time.font
+    "game.panel.element_7.draw_order",
+    &game.panel.element[6].sort_priority
   },
   {
-    "game.panel.light_switch_time.draw_masked",
-    &game.panel.light_switch_time.draw_masked
+    "game.panel.element_7_count.x",
+    &game.panel.element_count[6].x
   },
   {
-    "game.panel.light_switch_time.draw_order",
-    &game.panel.light_switch_time.sort_priority
+    "game.panel.element_7_count.y",
+    &game.panel.element_count[6].y
   },
   {
-    "game.panel.timegate_switch.x",
-    &game.panel.timegate_switch.x
+    "game.panel.element_7_count.align",
+    &game.panel.element_count[6].align
   },
   {
-    "game.panel.timegate_switch.y",
-    &game.panel.timegate_switch.y
+    "game.panel.element_7_count.valign",
+    &game.panel.element_count[6].valign
   },
   {
-    "game.panel.timegate_switch.tile_size",
-    &game.panel.timegate_switch.size
+    "game.panel.element_7_count.digits",
+    &game.panel.element_count[6].size
   },
   {
-    "game.panel.timegate_switch.draw_masked",
-    &game.panel.timegate_switch.draw_masked
+    "game.panel.element_7_count.font",
+    &game.panel.element_count[6].font
   },
   {
-    "game.panel.timegate_switch.draw_order",
-    &game.panel.timegate_switch.sort_priority
+    "game.panel.element_7_count.element",
+    &game.panel.element_count[6].id
   },
   {
-    "game.panel.timegate_switch_time.x",
-    &game.panel.timegate_switch_time.x
+    "game.panel.element_7_count.draw_masked",
+    &game.panel.element_count[6].draw_masked
   },
   {
-    "game.panel.timegate_switch_time.y",
-    &game.panel.timegate_switch_time.y
+    "game.panel.element_7_count.draw_order",
+    &game.panel.element_count[6].sort_priority
   },
   {
-    "game.panel.timegate_switch_time.align",
-    &game.panel.timegate_switch_time.align
+    "game.panel.element_8.x",
+    &game.panel.element[7].x
   },
   {
-    "game.panel.timegate_switch_time.valign",
-    &game.panel.timegate_switch_time.valign
+    "game.panel.element_8.y",
+    &game.panel.element[7].y
   },
   {
-    "game.panel.timegate_switch_time.digits",
-    &game.panel.timegate_switch_time.size
+    "game.panel.element_8.tile_size",
+    &game.panel.element[7].size
   },
   {
-    "game.panel.timegate_switch_time.font",
-    &game.panel.timegate_switch_time.font
+    "game.panel.element_8.element",
+    &game.panel.element[7].id
   },
   {
-    "game.panel.timegate_switch_time.draw_masked",
-    &game.panel.timegate_switch_time.draw_masked
+    "game.panel.element_8.draw_masked",
+    &game.panel.element[7].draw_masked
   },
   {
-    "game.panel.timegate_switch_time.draw_order",
-    &game.panel.timegate_switch_time.sort_priority
+    "game.panel.element_8.draw_order",
+    &game.panel.element[7].sort_priority
   },
   {
-    "game.panel.switchgate_switch.x",
-    &game.panel.switchgate_switch.x
+    "game.panel.element_8_count.x",
+    &game.panel.element_count[7].x
   },
   {
-    "game.panel.switchgate_switch.y",
-    &game.panel.switchgate_switch.y
+    "game.panel.element_8_count.y",
+    &game.panel.element_count[7].y
   },
   {
-    "game.panel.switchgate_switch.tile_size",
-    &game.panel.switchgate_switch.size
+    "game.panel.element_8_count.align",
+    &game.panel.element_count[7].align
   },
   {
-    "game.panel.switchgate_switch.draw_masked",
-    &game.panel.switchgate_switch.draw_masked
+    "game.panel.element_8_count.valign",
+    &game.panel.element_count[7].valign
   },
   {
-    "game.panel.switchgate_switch.draw_order",
-    &game.panel.switchgate_switch.sort_priority
+    "game.panel.element_8_count.digits",
+    &game.panel.element_count[7].size
   },
   {
-    "game.panel.emc_lenses.x",
-    &game.panel.emc_lenses.x
+    "game.panel.element_8_count.font",
+    &game.panel.element_count[7].font
   },
   {
-    "game.panel.emc_lenses.y",
-    &game.panel.emc_lenses.y
+    "game.panel.element_8_count.element",
+    &game.panel.element_count[7].id
   },
   {
-    "game.panel.emc_lenses.tile_size",
-    &game.panel.emc_lenses.size
+    "game.panel.element_8_count.draw_masked",
+    &game.panel.element_count[7].draw_masked
   },
   {
-    "game.panel.emc_lenses.draw_masked",
-    &game.panel.emc_lenses.draw_masked
+    "game.panel.element_8_count.draw_order",
+    &game.panel.element_count[7].sort_priority
   },
   {
-    "game.panel.emc_lenses.draw_order",
-    &game.panel.emc_lenses.sort_priority
+    "game.panel.ce_score_1.x",
+    &game.panel.ce_score[0].x
   },
   {
-    "game.panel.emc_lenses_time.x",
-    &game.panel.emc_lenses_time.x
+    "game.panel.ce_score_1.y",
+    &game.panel.ce_score[0].y
   },
   {
-    "game.panel.emc_lenses_time.y",
-    &game.panel.emc_lenses_time.y
+    "game.panel.ce_score_1.align",
+    &game.panel.ce_score[0].align
   },
   {
-    "game.panel.emc_lenses_time.align",
-    &game.panel.emc_lenses_time.align
+    "game.panel.ce_score_1.valign",
+    &game.panel.ce_score[0].valign
   },
   {
-    "game.panel.emc_lenses_time.valign",
-    &game.panel.emc_lenses_time.valign
+    "game.panel.ce_score_1.digits",
+    &game.panel.ce_score[0].size
   },
   {
-    "game.panel.emc_lenses_time.digits",
-    &game.panel.emc_lenses_time.size
+    "game.panel.ce_score_1.font",
+    &game.panel.ce_score[0].font
   },
   {
-    "game.panel.emc_lenses_time.font",
-    &game.panel.emc_lenses_time.font
+    "game.panel.ce_score_1.element",
+    &game.panel.ce_score[0].id
   },
   {
-    "game.panel.emc_lenses_time.draw_masked",
-    &game.panel.emc_lenses_time.draw_masked
+    "game.panel.ce_score_1.draw_masked",
+    &game.panel.ce_score[0].draw_masked
   },
   {
-    "game.panel.emc_lenses_time.draw_order",
-    &game.panel.emc_lenses_time.sort_priority
+    "game.panel.ce_score_1.draw_order",
+    &game.panel.ce_score[0].sort_priority
   },
   {
-    "game.panel.emc_magnifier.x",
-    &game.panel.emc_magnifier.x
+    "game.panel.ce_score_1_element.x",
+    &game.panel.ce_score_element[0].x
   },
   {
-    "game.panel.emc_magnifier.y",
-    &game.panel.emc_magnifier.y
+    "game.panel.ce_score_1_element.y",
+    &game.panel.ce_score_element[0].y
   },
   {
-    "game.panel.emc_magnifier.tile_size",
-    &game.panel.emc_magnifier.size
+    "game.panel.ce_score_1_element.tile_size",
+    &game.panel.ce_score_element[0].size
   },
   {
-    "game.panel.emc_magnifier.draw_masked",
-    &game.panel.emc_magnifier.draw_masked
+    "game.panel.ce_score_1_element.element",
+    &game.panel.ce_score_element[0].id
   },
   {
-    "game.panel.emc_magnifier.draw_order",
-    &game.panel.emc_magnifier.sort_priority
+    "game.panel.ce_score_1_element.draw_masked",
+    &game.panel.ce_score_element[0].draw_masked
   },
   {
-    "game.panel.emc_magnifier_time.x",
-    &game.panel.emc_magnifier_time.x
+    "game.panel.ce_score_1_element.draw_order",
+    &game.panel.ce_score_element[0].sort_priority
   },
   {
-    "game.panel.emc_magnifier_time.y",
-    &game.panel.emc_magnifier_time.y
+    "game.panel.ce_score_2.x",
+    &game.panel.ce_score[1].x
   },
   {
-    "game.panel.emc_magnifier_time.align",
-    &game.panel.emc_magnifier_time.align
+    "game.panel.ce_score_2.y",
+    &game.panel.ce_score[1].y
   },
   {
-    "game.panel.emc_magnifier_time.valign",
-    &game.panel.emc_magnifier_time.valign
+    "game.panel.ce_score_2.align",
+    &game.panel.ce_score[1].align
   },
   {
-    "game.panel.emc_magnifier_time.digits",
-    &game.panel.emc_magnifier_time.size
+    "game.panel.ce_score_2.valign",
+    &game.panel.ce_score[1].valign
   },
   {
-    "game.panel.emc_magnifier_time.font",
-    &game.panel.emc_magnifier_time.font
+    "game.panel.ce_score_2.digits",
+    &game.panel.ce_score[1].size
   },
   {
-    "game.panel.emc_magnifier_time.draw_masked",
-    &game.panel.emc_magnifier_time.draw_masked
+    "game.panel.ce_score_2.font",
+    &game.panel.ce_score[1].font
   },
   {
-    "game.panel.emc_magnifier_time.draw_order",
-    &game.panel.emc_magnifier_time.sort_priority
+    "game.panel.ce_score_2.element",
+    &game.panel.ce_score[1].id
   },
   {
-    "game.panel.balloon_switch.x",
-    &game.panel.balloon_switch.x
+    "game.panel.ce_score_2.draw_masked",
+    &game.panel.ce_score[1].draw_masked
   },
   {
-    "game.panel.balloon_switch.y",
-    &game.panel.balloon_switch.y
+    "game.panel.ce_score_2.draw_order",
+    &game.panel.ce_score[1].sort_priority
   },
   {
-    "game.panel.balloon_switch.tile_size",
-    &game.panel.balloon_switch.size
+    "game.panel.ce_score_2_element.x",
+    &game.panel.ce_score_element[1].x
   },
   {
-    "game.panel.balloon_switch.draw_masked",
-    &game.panel.balloon_switch.draw_masked
+    "game.panel.ce_score_2_element.y",
+    &game.panel.ce_score_element[1].y
   },
   {
-    "game.panel.balloon_switch.draw_order",
-    &game.panel.balloon_switch.sort_priority
+    "game.panel.ce_score_2_element.tile_size",
+    &game.panel.ce_score_element[1].size
   },
   {
-    "game.panel.dynabomb_number.x",
-    &game.panel.dynabomb_number.x
+    "game.panel.ce_score_2_element.element",
+    &game.panel.ce_score_element[1].id
   },
   {
-    "game.panel.dynabomb_number.y",
-    &game.panel.dynabomb_number.y
+    "game.panel.ce_score_2_element.draw_masked",
+    &game.panel.ce_score_element[1].draw_masked
   },
   {
-    "game.panel.dynabomb_number.align",
-    &game.panel.dynabomb_number.align
+    "game.panel.ce_score_2_element.draw_order",
+    &game.panel.ce_score_element[1].sort_priority
   },
   {
-    "game.panel.dynabomb_number.valign",
-    &game.panel.dynabomb_number.valign
+    "game.panel.ce_score_3.x",
+    &game.panel.ce_score[2].x
   },
   {
-    "game.panel.dynabomb_number.digits",
-    &game.panel.dynabomb_number.size
+    "game.panel.ce_score_3.y",
+    &game.panel.ce_score[2].y
   },
   {
-    "game.panel.dynabomb_number.font",
-    &game.panel.dynabomb_number.font
+    "game.panel.ce_score_3.align",
+    &game.panel.ce_score[2].align
   },
   {
-    "game.panel.dynabomb_number.draw_masked",
-    &game.panel.dynabomb_number.draw_masked
+    "game.panel.ce_score_3.valign",
+    &game.panel.ce_score[2].valign
   },
   {
-    "game.panel.dynabomb_number.draw_order",
-    &game.panel.dynabomb_number.sort_priority
+    "game.panel.ce_score_3.digits",
+    &game.panel.ce_score[2].size
   },
   {
-    "game.panel.dynabomb_size.x",
-    &game.panel.dynabomb_size.x
+    "game.panel.ce_score_3.font",
+    &game.panel.ce_score[2].font
   },
   {
-    "game.panel.dynabomb_size.y",
-    &game.panel.dynabomb_size.y
+    "game.panel.ce_score_3.element",
+    &game.panel.ce_score[2].id
   },
   {
-    "game.panel.dynabomb_size.align",
-    &game.panel.dynabomb_size.align
+    "game.panel.ce_score_3.draw_masked",
+    &game.panel.ce_score[2].draw_masked
   },
   {
-    "game.panel.dynabomb_size.valign",
-    &game.panel.dynabomb_size.valign
+    "game.panel.ce_score_3.draw_order",
+    &game.panel.ce_score[2].sort_priority
   },
   {
-    "game.panel.dynabomb_size.digits",
-    &game.panel.dynabomb_size.size
+    "game.panel.ce_score_3_element.x",
+    &game.panel.ce_score_element[2].x
   },
   {
-    "game.panel.dynabomb_size.font",
-    &game.panel.dynabomb_size.font
+    "game.panel.ce_score_3_element.y",
+    &game.panel.ce_score_element[2].y
   },
   {
-    "game.panel.dynabomb_size.draw_masked",
-    &game.panel.dynabomb_size.draw_masked
+    "game.panel.ce_score_3_element.tile_size",
+    &game.panel.ce_score_element[2].size
   },
   {
-    "game.panel.dynabomb_size.draw_order",
-    &game.panel.dynabomb_size.sort_priority
+    "game.panel.ce_score_3_element.element",
+    &game.panel.ce_score_element[2].id
   },
   {
-    "game.panel.dynabomb_power.x",
-    &game.panel.dynabomb_power.x
+    "game.panel.ce_score_3_element.draw_masked",
+    &game.panel.ce_score_element[2].draw_masked
   },
   {
-    "game.panel.dynabomb_power.y",
-    &game.panel.dynabomb_power.y
+    "game.panel.ce_score_3_element.draw_order",
+    &game.panel.ce_score_element[2].sort_priority
   },
   {
-    "game.panel.dynabomb_power.tile_size",
-    &game.panel.dynabomb_power.size
+    "game.panel.ce_score_4.x",
+    &game.panel.ce_score[3].x
   },
   {
-    "game.panel.dynabomb_power.draw_masked",
-    &game.panel.dynabomb_power.draw_masked
+    "game.panel.ce_score_4.y",
+    &game.panel.ce_score[3].y
   },
   {
-    "game.panel.dynabomb_power.draw_order",
-    &game.panel.dynabomb_power.sort_priority
+    "game.panel.ce_score_4.align",
+    &game.panel.ce_score[3].align
   },
   {
-    "game.panel.penguins.x",
-    &game.panel.penguins.x
+    "game.panel.ce_score_4.valign",
+    &game.panel.ce_score[3].valign
   },
   {
-    "game.panel.penguins.y",
-    &game.panel.penguins.y
+    "game.panel.ce_score_4.digits",
+    &game.panel.ce_score[3].size
   },
   {
-    "game.panel.penguins.align",
-    &game.panel.penguins.align
+    "game.panel.ce_score_4.font",
+    &game.panel.ce_score[3].font
   },
   {
-    "game.panel.penguins.valign",
-    &game.panel.penguins.valign
+    "game.panel.ce_score_4.element",
+    &game.panel.ce_score[3].id
   },
   {
-    "game.panel.penguins.digits",
-    &game.panel.penguins.size
+    "game.panel.ce_score_4.draw_masked",
+    &game.panel.ce_score[3].draw_masked
   },
   {
-    "game.panel.penguins.font",
-    &game.panel.penguins.font
+    "game.panel.ce_score_4.draw_order",
+    &game.panel.ce_score[3].sort_priority
   },
   {
-    "game.panel.penguins.draw_masked",
-    &game.panel.penguins.draw_masked
+    "game.panel.ce_score_4_element.x",
+    &game.panel.ce_score_element[3].x
   },
   {
-    "game.panel.penguins.draw_order",
-    &game.panel.penguins.sort_priority
+    "game.panel.ce_score_4_element.y",
+    &game.panel.ce_score_element[3].y
   },
   {
-    "game.panel.sokoban_objects.x",
-    &game.panel.sokoban_objects.x
+    "game.panel.ce_score_4_element.tile_size",
+    &game.panel.ce_score_element[3].size
   },
   {
-    "game.panel.sokoban_objects.y",
-    &game.panel.sokoban_objects.y
+    "game.panel.ce_score_4_element.element",
+    &game.panel.ce_score_element[3].id
   },
   {
-    "game.panel.sokoban_objects.align",
-    &game.panel.sokoban_objects.align
+    "game.panel.ce_score_4_element.draw_masked",
+    &game.panel.ce_score_element[3].draw_masked
   },
   {
-    "game.panel.sokoban_objects.valign",
-    &game.panel.sokoban_objects.valign
+    "game.panel.ce_score_4_element.draw_order",
+    &game.panel.ce_score_element[3].sort_priority
   },
   {
-    "game.panel.sokoban_objects.digits",
-    &game.panel.sokoban_objects.size
+    "game.panel.ce_score_5.x",
+    &game.panel.ce_score[4].x
   },
   {
-    "game.panel.sokoban_objects.font",
-    &game.panel.sokoban_objects.font
+    "game.panel.ce_score_5.y",
+    &game.panel.ce_score[4].y
   },
   {
-    "game.panel.sokoban_objects.draw_masked",
-    &game.panel.sokoban_objects.draw_masked
+    "game.panel.ce_score_5.align",
+    &game.panel.ce_score[4].align
   },
   {
-    "game.panel.sokoban_objects.draw_order",
-    &game.panel.sokoban_objects.sort_priority
+    "game.panel.ce_score_5.valign",
+    &game.panel.ce_score[4].valign
   },
   {
-    "game.panel.sokoban_fields.x",
-    &game.panel.sokoban_fields.x
+    "game.panel.ce_score_5.digits",
+    &game.panel.ce_score[4].size
   },
   {
-    "game.panel.sokoban_fields.y",
-    &game.panel.sokoban_fields.y
+    "game.panel.ce_score_5.font",
+    &game.panel.ce_score[4].font
   },
   {
-    "game.panel.sokoban_fields.align",
-    &game.panel.sokoban_fields.align
+    "game.panel.ce_score_5.element",
+    &game.panel.ce_score[4].id
   },
   {
-    "game.panel.sokoban_fields.valign",
-    &game.panel.sokoban_fields.valign
+    "game.panel.ce_score_5.draw_masked",
+    &game.panel.ce_score[4].draw_masked
   },
   {
-    "game.panel.sokoban_fields.digits",
-    &game.panel.sokoban_fields.size
+    "game.panel.ce_score_5.draw_order",
+    &game.panel.ce_score[4].sort_priority
   },
   {
-    "game.panel.sokoban_fields.font",
-    &game.panel.sokoban_fields.font
+    "game.panel.ce_score_5_element.x",
+    &game.panel.ce_score_element[4].x
   },
   {
-    "game.panel.sokoban_fields.draw_masked",
-    &game.panel.sokoban_fields.draw_masked
+    "game.panel.ce_score_5_element.y",
+    &game.panel.ce_score_element[4].y
   },
   {
-    "game.panel.sokoban_fields.draw_order",
-    &game.panel.sokoban_fields.sort_priority
+    "game.panel.ce_score_5_element.tile_size",
+    &game.panel.ce_score_element[4].size
   },
   {
-    "game.panel.robot_wheel.x",
-    &game.panel.robot_wheel.x
+    "game.panel.ce_score_5_element.element",
+    &game.panel.ce_score_element[4].id
   },
   {
-    "game.panel.robot_wheel.y",
-    &game.panel.robot_wheel.y
+    "game.panel.ce_score_5_element.draw_masked",
+    &game.panel.ce_score_element[4].draw_masked
   },
   {
-    "game.panel.robot_wheel.tile_size",
-    &game.panel.robot_wheel.size
+    "game.panel.ce_score_5_element.draw_order",
+    &game.panel.ce_score_element[4].sort_priority
   },
   {
-    "game.panel.robot_wheel.draw_masked",
-    &game.panel.robot_wheel.draw_masked
+    "game.panel.ce_score_6.x",
+    &game.panel.ce_score[5].x
   },
   {
-    "game.panel.robot_wheel.draw_order",
-    &game.panel.robot_wheel.sort_priority
+    "game.panel.ce_score_6.y",
+    &game.panel.ce_score[5].y
   },
   {
-    "game.panel.conveyor_belt_1.x",
-    &game.panel.conveyor_belt[0].x
+    "game.panel.ce_score_6.align",
+    &game.panel.ce_score[5].align
   },
   {
-    "game.panel.conveyor_belt_1.y",
-    &game.panel.conveyor_belt[0].y
+    "game.panel.ce_score_6.valign",
+    &game.panel.ce_score[5].valign
   },
   {
-    "game.panel.conveyor_belt_1.tile_size",
-    &game.panel.conveyor_belt[0].size
+    "game.panel.ce_score_6.digits",
+    &game.panel.ce_score[5].size
   },
   {
-    "game.panel.conveyor_belt_1.draw_masked",
-    &game.panel.conveyor_belt[0].draw_masked
+    "game.panel.ce_score_6.font",
+    &game.panel.ce_score[5].font
   },
   {
-    "game.panel.conveyor_belt_1.draw_order",
-    &game.panel.conveyor_belt[0].sort_priority
+    "game.panel.ce_score_6.element",
+    &game.panel.ce_score[5].id
   },
   {
-    "game.panel.conveyor_belt_1_switch.x",
-    &game.panel.conveyor_belt_switch[0].x
+    "game.panel.ce_score_6.draw_masked",
+    &game.panel.ce_score[5].draw_masked
   },
   {
-    "game.panel.conveyor_belt_1_switch.y",
-    &game.panel.conveyor_belt_switch[0].y
+    "game.panel.ce_score_6.draw_order",
+    &game.panel.ce_score[5].sort_priority
   },
   {
-    "game.panel.conveyor_belt_1_switch.tile_size",
-    &game.panel.conveyor_belt_switch[0].size
+    "game.panel.ce_score_6_element.x",
+    &game.panel.ce_score_element[5].x
   },
   {
-    "game.panel.conveyor_belt_1_switch.draw_masked",
-    &game.panel.conveyor_belt_switch[0].draw_masked
+    "game.panel.ce_score_6_element.y",
+    &game.panel.ce_score_element[5].y
   },
   {
-    "game.panel.conveyor_belt_1_switch.draw_order",
-    &game.panel.conveyor_belt_switch[0].sort_priority
+    "game.panel.ce_score_6_element.tile_size",
+    &game.panel.ce_score_element[5].size
   },
   {
-    "game.panel.conveyor_belt_2.x",
-    &game.panel.conveyor_belt[1].x
+    "game.panel.ce_score_6_element.element",
+    &game.panel.ce_score_element[5].id
   },
   {
-    "game.panel.conveyor_belt_2.y",
-    &game.panel.conveyor_belt[1].y
+    "game.panel.ce_score_6_element.draw_masked",
+    &game.panel.ce_score_element[5].draw_masked
   },
   {
-    "game.panel.conveyor_belt_2.tile_size",
-    &game.panel.conveyor_belt[1].size
+    "game.panel.ce_score_6_element.draw_order",
+    &game.panel.ce_score_element[5].sort_priority
   },
   {
-    "game.panel.conveyor_belt_2.draw_masked",
-    &game.panel.conveyor_belt[1].draw_masked
+    "game.panel.ce_score_7.x",
+    &game.panel.ce_score[6].x
   },
   {
-    "game.panel.conveyor_belt_2.draw_order",
-    &game.panel.conveyor_belt[1].sort_priority
+    "game.panel.ce_score_7.y",
+    &game.panel.ce_score[6].y
   },
   {
-    "game.panel.conveyor_belt_2_switch.x",
-    &game.panel.conveyor_belt_switch[1].x
+    "game.panel.ce_score_7.align",
+    &game.panel.ce_score[6].align
   },
   {
-    "game.panel.conveyor_belt_2_switch.y",
-    &game.panel.conveyor_belt_switch[1].y
+    "game.panel.ce_score_7.valign",
+    &game.panel.ce_score[6].valign
   },
   {
-    "game.panel.conveyor_belt_2_switch.tile_size",
-    &game.panel.conveyor_belt_switch[1].size
+    "game.panel.ce_score_7.digits",
+    &game.panel.ce_score[6].size
   },
   {
-    "game.panel.conveyor_belt_2_switch.draw_masked",
-    &game.panel.conveyor_belt_switch[1].draw_masked
+    "game.panel.ce_score_7.font",
+    &game.panel.ce_score[6].font
   },
   {
-    "game.panel.conveyor_belt_2_switch.draw_order",
-    &game.panel.conveyor_belt_switch[1].sort_priority
+    "game.panel.ce_score_7.element",
+    &game.panel.ce_score[6].id
   },
   {
-    "game.panel.conveyor_belt_3.x",
-    &game.panel.conveyor_belt[2].x
+    "game.panel.ce_score_7.draw_masked",
+    &game.panel.ce_score[6].draw_masked
   },
   {
-    "game.panel.conveyor_belt_3.y",
-    &game.panel.conveyor_belt[2].y
+    "game.panel.ce_score_7.draw_order",
+    &game.panel.ce_score[6].sort_priority
   },
   {
-    "game.panel.conveyor_belt_3.tile_size",
-    &game.panel.conveyor_belt[2].size
+    "game.panel.ce_score_7_element.x",
+    &game.panel.ce_score_element[6].x
   },
   {
-    "game.panel.conveyor_belt_3.draw_masked",
-    &game.panel.conveyor_belt[2].draw_masked
+    "game.panel.ce_score_7_element.y",
+    &game.panel.ce_score_element[6].y
   },
   {
-    "game.panel.conveyor_belt_3.draw_order",
-    &game.panel.conveyor_belt[2].sort_priority
+    "game.panel.ce_score_7_element.tile_size",
+    &game.panel.ce_score_element[6].size
   },
   {
-    "game.panel.conveyor_belt_3_switch.x",
-    &game.panel.conveyor_belt_switch[2].x
+    "game.panel.ce_score_7_element.element",
+    &game.panel.ce_score_element[6].id
   },
   {
-    "game.panel.conveyor_belt_3_switch.y",
-    &game.panel.conveyor_belt_switch[2].y
+    "game.panel.ce_score_7_element.draw_masked",
+    &game.panel.ce_score_element[6].draw_masked
   },
   {
-    "game.panel.conveyor_belt_3_switch.tile_size",
-    &game.panel.conveyor_belt_switch[2].size
+    "game.panel.ce_score_7_element.draw_order",
+    &game.panel.ce_score_element[6].sort_priority
   },
   {
-    "game.panel.conveyor_belt_3_switch.draw_masked",
-    &game.panel.conveyor_belt_switch[2].draw_masked
+    "game.panel.ce_score_8.x",
+    &game.panel.ce_score[7].x
   },
   {
-    "game.panel.conveyor_belt_3_switch.draw_order",
-    &game.panel.conveyor_belt_switch[2].sort_priority
+    "game.panel.ce_score_8.y",
+    &game.panel.ce_score[7].y
   },
   {
-    "game.panel.conveyor_belt_4.x",
-    &game.panel.conveyor_belt[3].x
+    "game.panel.ce_score_8.align",
+    &game.panel.ce_score[7].align
   },
   {
-    "game.panel.conveyor_belt_4.y",
-    &game.panel.conveyor_belt[3].y
+    "game.panel.ce_score_8.valign",
+    &game.panel.ce_score[7].valign
   },
   {
-    "game.panel.conveyor_belt_4.tile_size",
-    &game.panel.conveyor_belt[3].size
+    "game.panel.ce_score_8.digits",
+    &game.panel.ce_score[7].size
   },
   {
-    "game.panel.conveyor_belt_4.draw_masked",
-    &game.panel.conveyor_belt[3].draw_masked
+    "game.panel.ce_score_8.font",
+    &game.panel.ce_score[7].font
   },
   {
-    "game.panel.conveyor_belt_4.draw_order",
-    &game.panel.conveyor_belt[3].sort_priority
+    "game.panel.ce_score_8.element",
+    &game.panel.ce_score[7].id
   },
   {
-    "game.panel.conveyor_belt_4_switch.x",
-    &game.panel.conveyor_belt_switch[3].x
+    "game.panel.ce_score_8.draw_masked",
+    &game.panel.ce_score[7].draw_masked
   },
   {
-    "game.panel.conveyor_belt_4_switch.y",
-    &game.panel.conveyor_belt_switch[3].y
+    "game.panel.ce_score_8.draw_order",
+    &game.panel.ce_score[7].sort_priority
   },
   {
-    "game.panel.conveyor_belt_4_switch.tile_size",
-    &game.panel.conveyor_belt_switch[3].size
+    "game.panel.ce_score_8_element.x",
+    &game.panel.ce_score_element[7].x
   },
   {
-    "game.panel.conveyor_belt_4_switch.draw_masked",
-    &game.panel.conveyor_belt_switch[3].draw_masked
+    "game.panel.ce_score_8_element.y",
+    &game.panel.ce_score_element[7].y
   },
   {
-    "game.panel.conveyor_belt_4_switch.draw_order",
-    &game.panel.conveyor_belt_switch[3].sort_priority
+    "game.panel.ce_score_8_element.tile_size",
+    &game.panel.ce_score_element[7].size
   },
   {
-    "game.panel.magic_wall.x",
-    &game.panel.magic_wall.x
+    "game.panel.ce_score_8_element.element",
+    &game.panel.ce_score_element[7].id
   },
   {
-    "game.panel.magic_wall.y",
-    &game.panel.magic_wall.y
+    "game.panel.ce_score_8_element.draw_masked",
+    &game.panel.ce_score_element[7].draw_masked
   },
   {
-    "game.panel.magic_wall.tile_size",
-    &game.panel.magic_wall.size
+    "game.panel.ce_score_8_element.draw_order",
+    &game.panel.ce_score_element[7].sort_priority
   },
   {
-    "game.panel.magic_wall.draw_masked",
-    &game.panel.magic_wall.draw_masked
+    "game.panel.player_name.x",
+    &game.panel.player_name.x
   },
   {
-    "game.panel.magic_wall.draw_order",
-    &game.panel.magic_wall.sort_priority
+    "game.panel.player_name.y",
+    &game.panel.player_name.y
   },
   {
-    "game.panel.magic_wall_time.x",
-    &game.panel.magic_wall_time.x
+    "game.panel.player_name.align",
+    &game.panel.player_name.align
   },
   {
-    "game.panel.magic_wall_time.y",
-    &game.panel.magic_wall_time.y
+    "game.panel.player_name.valign",
+    &game.panel.player_name.valign
   },
   {
-    "game.panel.magic_wall_time.align",
-    &game.panel.magic_wall_time.align
+    "game.panel.player_name.chars",
+    &game.panel.player_name.size
   },
   {
-    "game.panel.magic_wall_time.valign",
-    &game.panel.magic_wall_time.valign
+    "game.panel.player_name.font",
+    &game.panel.player_name.font
   },
   {
-    "game.panel.magic_wall_time.digits",
-    &game.panel.magic_wall_time.size
+    "game.panel.player_name.draw_masked",
+    &game.panel.player_name.draw_masked
   },
   {
-    "game.panel.magic_wall_time.font",
-    &game.panel.magic_wall_time.font
+    "game.panel.player_name.draw_order",
+    &game.panel.player_name.sort_priority
   },
   {
-    "game.panel.magic_wall_time.draw_masked",
-    &game.panel.magic_wall_time.draw_masked
+    "game.panel.level_name.x",
+    &game.panel.level_name.x
   },
   {
-    "game.panel.magic_wall_time.draw_order",
-    &game.panel.magic_wall_time.sort_priority
+    "game.panel.level_name.y",
+    &game.panel.level_name.y
   },
   {
-    "game.panel.gravity_state.x",
-    &game.panel.gravity_state.x
+    "game.panel.level_name.align",
+    &game.panel.level_name.align
   },
   {
-    "game.panel.gravity_state.y",
-    &game.panel.gravity_state.y
+    "game.panel.level_name.valign",
+    &game.panel.level_name.valign
   },
   {
-    "game.panel.gravity_state.align",
-    &game.panel.gravity_state.align
+    "game.panel.level_name.chars",
+    &game.panel.level_name.size
   },
   {
-    "game.panel.gravity_state.valign",
-    &game.panel.gravity_state.valign
+    "game.panel.level_name.font",
+    &game.panel.level_name.font
   },
   {
-    "game.panel.gravity_state.chars",
-    &game.panel.gravity_state.size
+    "game.panel.level_name.draw_masked",
+    &game.panel.level_name.draw_masked
   },
   {
-    "game.panel.gravity_state.font",
-    &game.panel.gravity_state.font
+    "game.panel.level_name.draw_order",
+    &game.panel.level_name.sort_priority
   },
   {
-    "game.panel.gravity_state.font_active",
-    &game.panel.gravity_state.font_alt
+    "game.panel.level_author.x",
+    &game.panel.level_author.x
   },
   {
-    "game.panel.gravity_state.draw_masked",
-    &game.panel.gravity_state.draw_masked
+    "game.panel.level_author.y",
+    &game.panel.level_author.y
   },
   {
-    "game.panel.gravity_state.draw_order",
-    &game.panel.gravity_state.sort_priority
+    "game.panel.level_author.align",
+    &game.panel.level_author.align
   },
   {
-    "game.panel.graphic_1.x",
-    &game.panel.graphic[0].x
+    "game.panel.level_author.valign",
+    &game.panel.level_author.valign
   },
   {
-    "game.panel.graphic_1.y",
-    &game.panel.graphic[0].y
+    "game.panel.level_author.chars",
+    &game.panel.level_author.size
   },
   {
-    "game.panel.graphic_1.draw_masked",
-    &game.panel.graphic[0].draw_masked
+    "game.panel.level_author.font",
+    &game.panel.level_author.font
   },
   {
-    "game.panel.graphic_1.draw_order",
-    &game.panel.graphic[0].sort_priority
+    "game.panel.level_author.draw_masked",
+    &game.panel.level_author.draw_masked
   },
   {
-    "game.panel.graphic_2.x",
-    &game.panel.graphic[1].x
+    "game.panel.level_author.draw_order",
+    &game.panel.level_author.sort_priority
   },
   {
-    "game.panel.graphic_2.y",
-    &game.panel.graphic[1].y
+    "game.button.stop.x",
+    &game.button.stop.x
   },
   {
-    "game.panel.graphic_2.draw_masked",
-    &game.panel.graphic[1].draw_masked
+    "game.button.stop.y",
+    &game.button.stop.y
   },
   {
-    "game.panel.graphic_2.draw_order",
-    &game.panel.graphic[1].sort_priority
+    "game.button.pause.x",
+    &game.button.pause.x
   },
   {
-    "game.panel.graphic_3.x",
-    &game.panel.graphic[2].x
+    "game.button.pause.y",
+    &game.button.pause.y
   },
   {
-    "game.panel.graphic_3.y",
-    &game.panel.graphic[2].y
+    "game.button.play.x",
+    &game.button.play.x
   },
   {
-    "game.panel.graphic_3.draw_masked",
-    &game.panel.graphic[2].draw_masked
+    "game.button.play.y",
+    &game.button.play.y
   },
   {
-    "game.panel.graphic_3.draw_order",
-    &game.panel.graphic[2].sort_priority
+    "game.button.undo.x",
+    &game.button.undo.x
   },
   {
-    "game.panel.graphic_4.x",
-    &game.panel.graphic[3].x
+    "game.button.undo.y",
+    &game.button.undo.y
   },
   {
-    "game.panel.graphic_4.y",
-    &game.panel.graphic[3].y
+    "game.button.redo.x",
+    &game.button.redo.x
   },
   {
-    "game.panel.graphic_4.draw_masked",
-    &game.panel.graphic[3].draw_masked
+    "game.button.redo.y",
+    &game.button.redo.y
   },
   {
-    "game.panel.graphic_4.draw_order",
-    &game.panel.graphic[3].sort_priority
+    "game.button.save.x",
+    &game.button.save.x
   },
   {
-    "game.panel.graphic_5.x",
-    &game.panel.graphic[4].x
+    "game.button.save.y",
+    &game.button.save.y
   },
   {
-    "game.panel.graphic_5.y",
-    &game.panel.graphic[4].y
+    "game.button.pause2.x",
+    &game.button.pause2.x
   },
   {
-    "game.panel.graphic_5.draw_masked",
-    &game.panel.graphic[4].draw_masked
+    "game.button.pause2.y",
+    &game.button.pause2.y
   },
   {
-    "game.panel.graphic_5.draw_order",
-    &game.panel.graphic[4].sort_priority
+    "game.button.load.x",
+    &game.button.load.x
   },
   {
-    "game.panel.graphic_6.x",
-    &game.panel.graphic[5].x
+    "game.button.load.y",
+    &game.button.load.y
   },
   {
-    "game.panel.graphic_6.y",
-    &game.panel.graphic[5].y
+    "game.button.sound_music.x",
+    &game.button.sound_music.x
   },
   {
-    "game.panel.graphic_6.draw_masked",
-    &game.panel.graphic[5].draw_masked
+    "game.button.sound_music.y",
+    &game.button.sound_music.y
   },
   {
-    "game.panel.graphic_6.draw_order",
-    &game.panel.graphic[5].sort_priority
+    "game.button.sound_loops.x",
+    &game.button.sound_loops.x
   },
   {
-    "game.panel.graphic_7.x",
-    &game.panel.graphic[6].x
+    "game.button.sound_loops.y",
+    &game.button.sound_loops.y
   },
   {
-    "game.panel.graphic_7.y",
-    &game.panel.graphic[6].y
+    "game.button.sound_simple.x",
+    &game.button.sound_simple.x
   },
   {
-    "game.panel.graphic_7.draw_masked",
-    &game.panel.graphic[6].draw_masked
+    "game.button.sound_simple.y",
+    &game.button.sound_simple.y
   },
   {
-    "game.panel.graphic_7.draw_order",
-    &game.panel.graphic[6].sort_priority
+    "tape.button.eject.x",
+    &tape.button.eject.x
   },
   {
-    "game.panel.graphic_8.x",
-    &game.panel.graphic[7].x
+    "tape.button.eject.y",
+    &tape.button.eject.y
   },
   {
-    "game.panel.graphic_8.y",
-    &game.panel.graphic[7].y
+    "tape.button.stop.x",
+    &tape.button.stop.x
   },
   {
-    "game.panel.graphic_8.draw_masked",
-    &game.panel.graphic[7].draw_masked
+    "tape.button.stop.y",
+    &tape.button.stop.y
   },
   {
-    "game.panel.graphic_8.draw_order",
-    &game.panel.graphic[7].sort_priority
+    "tape.button.pause.x",
+    &tape.button.pause.x
   },
   {
-    "game.panel.element_1.x",
-    &game.panel.element[0].x
+    "tape.button.pause.y",
+    &tape.button.pause.y
   },
   {
-    "game.panel.element_1.y",
-    &game.panel.element[0].y
+    "tape.button.record.x",
+    &tape.button.record.x
   },
   {
-    "game.panel.element_1.tile_size",
-    &game.panel.element[0].size
+    "tape.button.record.y",
+    &tape.button.record.y
   },
   {
-    "game.panel.element_1.element",
-    &game.panel.element[0].id
+    "tape.button.play.x",
+    &tape.button.play.x
   },
   {
-    "game.panel.element_1.draw_masked",
-    &game.panel.element[0].draw_masked
+    "tape.button.play.y",
+    &tape.button.play.y
   },
   {
-    "game.panel.element_1.draw_order",
-    &game.panel.element[0].sort_priority
+    "tape.symbol.eject.x",
+    &tape.symbol.eject.x
   },
   {
-    "game.panel.element_1_count.x",
-    &game.panel.element_count[0].x
+    "tape.symbol.eject.y",
+    &tape.symbol.eject.y
   },
   {
-    "game.panel.element_1_count.y",
-    &game.panel.element_count[0].y
+    "tape.symbol.stop.x",
+    &tape.symbol.stop.x
   },
   {
-    "game.panel.element_1_count.align",
-    &game.panel.element_count[0].align
+    "tape.symbol.stop.y",
+    &tape.symbol.stop.y
   },
   {
-    "game.panel.element_1_count.valign",
-    &game.panel.element_count[0].valign
+    "tape.symbol.pause.x",
+    &tape.symbol.pause.x
   },
   {
-    "game.panel.element_1_count.digits",
-    &game.panel.element_count[0].size
+    "tape.symbol.pause.y",
+    &tape.symbol.pause.y
   },
   {
-    "game.panel.element_1_count.font",
-    &game.panel.element_count[0].font
+    "tape.symbol.record.x",
+    &tape.symbol.record.x
   },
   {
-    "game.panel.element_1_count.element",
-    &game.panel.element_count[0].id
+    "tape.symbol.record.y",
+    &tape.symbol.record.y
   },
   {
-    "game.panel.element_1_count.draw_masked",
-    &game.panel.element_count[0].draw_masked
+    "tape.symbol.play.x",
+    &tape.symbol.play.x
   },
   {
-    "game.panel.element_1_count.draw_order",
-    &game.panel.element_count[0].sort_priority
+    "tape.symbol.play.y",
+    &tape.symbol.play.y
   },
   {
-    "game.panel.element_2.x",
-    &game.panel.element[1].x
+    "tape.symbol.fast_forward.x",
+    &tape.symbol.fast_forward.x
   },
   {
-    "game.panel.element_2.y",
-    &game.panel.element[1].y
+    "tape.symbol.fast_forward.y",
+    &tape.symbol.fast_forward.y
   },
   {
-    "game.panel.element_2.tile_size",
-    &game.panel.element[1].size
+    "tape.symbol.warp_forward.x",
+    &tape.symbol.warp_forward.x
   },
   {
-    "game.panel.element_2.element",
-    &game.panel.element[1].id
+    "tape.symbol.warp_forward.y",
+    &tape.symbol.warp_forward.y
   },
   {
-    "game.panel.element_2.draw_masked",
-    &game.panel.element[1].draw_masked
+    "tape.symbol.warp_forward_blind.x",
+    &tape.symbol.warp_forward_blind.x
   },
   {
-    "game.panel.element_2.draw_order",
-    &game.panel.element[1].sort_priority
+    "tape.symbol.warp_forward_blind.y",
+    &tape.symbol.warp_forward_blind.y
   },
   {
-    "game.panel.element_2_count.x",
-    &game.panel.element_count[1].x
+    "tape.symbol.pause_before_end.x",
+    &tape.symbol.pause_before_end.x
   },
   {
-    "game.panel.element_2_count.y",
-    &game.panel.element_count[1].y
+    "tape.symbol.pause_before_end.y",
+    &tape.symbol.pause_before_end.y
   },
   {
-    "game.panel.element_2_count.align",
-    &game.panel.element_count[1].align
+    "tape.symbol.single_step.x",
+    &tape.symbol.single_step.x
   },
   {
-    "game.panel.element_2_count.valign",
-    &game.panel.element_count[1].valign
+    "tape.symbol.single_step.y",
+    &tape.symbol.single_step.y
   },
   {
-    "game.panel.element_2_count.digits",
-    &game.panel.element_count[1].size
+    "tape.label.eject.x",
+    &tape.label.eject.x
   },
   {
-    "game.panel.element_2_count.font",
-    &game.panel.element_count[1].font
+    "tape.label.eject.y",
+    &tape.label.eject.y
   },
   {
-    "game.panel.element_2_count.element",
-    &game.panel.element_count[1].id
+    "tape.label.stop.x",
+    &tape.label.stop.x
   },
   {
-    "game.panel.element_2_count.draw_masked",
-    &game.panel.element_count[1].draw_masked
+    "tape.label.stop.y",
+    &tape.label.stop.y
   },
   {
-    "game.panel.element_2_count.draw_order",
-    &game.panel.element_count[1].sort_priority
+    "tape.label.pause.x",
+    &tape.label.pause.x
   },
   {
-    "game.panel.element_3.x",
-    &game.panel.element[2].x
+    "tape.label.pause.y",
+    &tape.label.pause.y
   },
   {
-    "game.panel.element_3.y",
-    &game.panel.element[2].y
+    "tape.label.record.x",
+    &tape.label.record.x
   },
   {
-    "game.panel.element_3.tile_size",
-    &game.panel.element[2].size
+    "tape.label.record.y",
+    &tape.label.record.y
   },
   {
-    "game.panel.element_3.element",
-    &game.panel.element[2].id
+    "tape.label.play.x",
+    &tape.label.play.x
   },
   {
-    "game.panel.element_3.draw_masked",
-    &game.panel.element[2].draw_masked
+    "tape.label.play.y",
+    &tape.label.play.y
   },
   {
-    "game.panel.element_3.draw_order",
-    &game.panel.element[2].sort_priority
+    "tape.label.fast_forward.x",
+    &tape.label.fast_forward.x
   },
   {
-    "game.panel.element_3_count.x",
-    &game.panel.element_count[2].x
+    "tape.label.fast_forward.y",
+    &tape.label.fast_forward.y
   },
   {
-    "game.panel.element_3_count.y",
-    &game.panel.element_count[2].y
+    "tape.label.warp_forward.x",
+    &tape.label.warp_forward.x
   },
   {
-    "game.panel.element_3_count.align",
-    &game.panel.element_count[2].align
+    "tape.label.warp_forward.y",
+    &tape.label.warp_forward.y
   },
   {
-    "game.panel.element_3_count.valign",
-    &game.panel.element_count[2].valign
+    "tape.label.warp_forward_blind.x",
+    &tape.label.warp_forward_blind.x
   },
   {
-    "game.panel.element_3_count.digits",
-    &game.panel.element_count[2].size
+    "tape.label.warp_forward_blind.y",
+    &tape.label.warp_forward_blind.y
   },
   {
-    "game.panel.element_3_count.font",
-    &game.panel.element_count[2].font
+    "tape.label.pause_before_end.x",
+    &tape.label.pause_before_end.x
   },
   {
-    "game.panel.element_3_count.element",
-    &game.panel.element_count[2].id
+    "tape.label.pause_before_end.y",
+    &tape.label.pause_before_end.y
   },
   {
-    "game.panel.element_3_count.draw_masked",
-    &game.panel.element_count[2].draw_masked
+    "tape.label.single_step.x",
+    &tape.label.single_step.x
   },
   {
-    "game.panel.element_3_count.draw_order",
-    &game.panel.element_count[2].sort_priority
+    "tape.label.single_step.y",
+    &tape.label.single_step.y
   },
   {
-    "game.panel.element_4.x",
-    &game.panel.element[3].x
+    "tape.label.date.x",
+    &tape.label.date.x
   },
   {
-    "game.panel.element_4.y",
-    &game.panel.element[3].y
+    "tape.label.date.y",
+    &tape.label.date.y
   },
   {
-    "game.panel.element_4.tile_size",
-    &game.panel.element[3].size
+    "tape.label.time.x",
+    &tape.label.time.x
   },
   {
-    "game.panel.element_4.element",
-    &game.panel.element[3].id
+    "tape.label.time.y",
+    &tape.label.time.y
   },
   {
-    "game.panel.element_4.draw_masked",
-    &game.panel.element[3].draw_masked
+    "tape.text.date.x",
+    &tape.text.date.x
   },
   {
-    "game.panel.element_4.draw_order",
-    &game.panel.element[3].sort_priority
+    "tape.text.date.y",
+    &tape.text.date.y
   },
   {
-    "game.panel.element_4_count.x",
-    &game.panel.element_count[3].x
+    "tape.text.date.align",
+    &tape.text.date.align
   },
   {
-    "game.panel.element_4_count.y",
-    &game.panel.element_count[3].y
+    "tape.text.date.valign",
+    &tape.text.date.valign
   },
   {
-    "game.panel.element_4_count.align",
-    &game.panel.element_count[3].align
+    "tape.text.date.digits",
+    &tape.text.date.size
   },
   {
-    "game.panel.element_4_count.valign",
-    &game.panel.element_count[3].valign
+    "tape.text.date.xoffset",
+    &tape.text.date.xoffset
   },
   {
-    "game.panel.element_4_count.digits",
-    &game.panel.element_count[3].size
+    "tape.text.date.2nd_xoffset",
+    &tape.text.date.xoffset2
   },
   {
-    "game.panel.element_4_count.font",
-    &game.panel.element_count[3].font
+    "tape.text.date.font",
+    &tape.text.date.font
   },
   {
-    "game.panel.element_4_count.element",
-    &game.panel.element_count[3].id
+    "tape.text.date.draw_masked",
+    &tape.text.date.draw_masked
   },
   {
-    "game.panel.element_4_count.draw_masked",
-    &game.panel.element_count[3].draw_masked
+    "tape.text.date_yyyy.x",
+    &tape.text.date_yyyy.x
   },
   {
-    "game.panel.element_4_count.draw_order",
-    &game.panel.element_count[3].sort_priority
+    "tape.text.date_yyyy.y",
+    &tape.text.date_yyyy.y
   },
   {
-    "game.panel.element_5.x",
-    &game.panel.element[4].x
+    "tape.text.date_yyyy.align",
+    &tape.text.date_yyyy.align
   },
   {
-    "game.panel.element_5.y",
-    &game.panel.element[4].y
+    "tape.text.date_yyyy.valign",
+    &tape.text.date_yyyy.valign
   },
   {
-    "game.panel.element_5.tile_size",
-    &game.panel.element[4].size
+    "tape.text.date_yyyy.digits",
+    &tape.text.date_yyyy.size
   },
   {
-    "game.panel.element_5.element",
-    &game.panel.element[4].id
+    "tape.text.date_yyyy.font",
+    &tape.text.date_yyyy.font
   },
   {
-    "game.panel.element_5.draw_masked",
-    &game.panel.element[4].draw_masked
+    "tape.text.date_yyyy.draw_masked",
+    &tape.text.date_yyyy.draw_masked
   },
   {
-    "game.panel.element_5.draw_order",
-    &game.panel.element[4].sort_priority
+    "tape.text.date_yy.x",
+    &tape.text.date_yy.x
   },
   {
-    "game.panel.element_5_count.x",
-    &game.panel.element_count[4].x
+    "tape.text.date_yy.y",
+    &tape.text.date_yy.y
   },
   {
-    "game.panel.element_5_count.y",
-    &game.panel.element_count[4].y
+    "tape.text.date_yy.align",
+    &tape.text.date_yy.align
   },
   {
-    "game.panel.element_5_count.align",
-    &game.panel.element_count[4].align
+    "tape.text.date_yy.valign",
+    &tape.text.date_yy.valign
   },
   {
-    "game.panel.element_5_count.valign",
-    &game.panel.element_count[4].valign
+    "tape.text.date_yy.digits",
+    &tape.text.date_yy.size
   },
   {
-    "game.panel.element_5_count.digits",
-    &game.panel.element_count[4].size
+    "tape.text.date_yy.font",
+    &tape.text.date_yy.font
   },
   {
-    "game.panel.element_5_count.font",
-    &game.panel.element_count[4].font
+    "tape.text.date_yy.draw_masked",
+    &tape.text.date_yy.draw_masked
   },
   {
-    "game.panel.element_5_count.element",
-    &game.panel.element_count[4].id
+    "tape.text.date_mon.x",
+    &tape.text.date_mon.x
   },
   {
-    "game.panel.element_5_count.draw_masked",
-    &game.panel.element_count[4].draw_masked
+    "tape.text.date_mon.y",
+    &tape.text.date_mon.y
   },
   {
-    "game.panel.element_5_count.draw_order",
-    &game.panel.element_count[4].sort_priority
+    "tape.text.date_mon.align",
+    &tape.text.date_mon.align
   },
   {
-    "game.panel.element_6.x",
-    &game.panel.element[5].x
+    "tape.text.date_mon.valign",
+    &tape.text.date_mon.valign
   },
   {
-    "game.panel.element_6.y",
-    &game.panel.element[5].y
+    "tape.text.date_mon.chars",
+    &tape.text.date_mon.size
   },
   {
-    "game.panel.element_6.tile_size",
-    &game.panel.element[5].size
+    "tape.text.date_mon.font",
+    &tape.text.date_mon.font
   },
   {
-    "game.panel.element_6.element",
-    &game.panel.element[5].id
+    "tape.text.date_mon.draw_masked",
+    &tape.text.date_mon.draw_masked
   },
   {
-    "game.panel.element_6.draw_masked",
-    &game.panel.element[5].draw_masked
+    "tape.text.date_mm.x",
+    &tape.text.date_mm.x
   },
   {
-    "game.panel.element_6.draw_order",
-    &game.panel.element[5].sort_priority
+    "tape.text.date_mm.y",
+    &tape.text.date_mm.y
   },
   {
-    "game.panel.element_6_count.x",
-    &game.panel.element_count[5].x
+    "tape.text.date_mm.align",
+    &tape.text.date_mm.align
   },
   {
-    "game.panel.element_6_count.y",
-    &game.panel.element_count[5].y
+    "tape.text.date_mm.valign",
+    &tape.text.date_mm.valign
   },
   {
-    "game.panel.element_6_count.align",
-    &game.panel.element_count[5].align
+    "tape.text.date_mm.digits",
+    &tape.text.date_mm.size
   },
   {
-    "game.panel.element_6_count.valign",
-    &game.panel.element_count[5].valign
+    "tape.text.date_mm.font",
+    &tape.text.date_mm.font
   },
   {
-    "game.panel.element_6_count.digits",
-    &game.panel.element_count[5].size
+    "tape.text.date_mm.draw_masked",
+    &tape.text.date_mm.draw_masked
   },
   {
-    "game.panel.element_6_count.font",
-    &game.panel.element_count[5].font
+    "tape.text.date_dd.x",
+    &tape.text.date_dd.x
   },
   {
-    "game.panel.element_6_count.element",
-    &game.panel.element_count[5].id
+    "tape.text.date_dd.y",
+    &tape.text.date_dd.y
   },
   {
-    "game.panel.element_6_count.draw_masked",
-    &game.panel.element_count[5].draw_masked
+    "tape.text.date_dd.align",
+    &tape.text.date_dd.align
   },
   {
-    "game.panel.element_6_count.draw_order",
-    &game.panel.element_count[5].sort_priority
+    "tape.text.date_dd.valign",
+    &tape.text.date_dd.valign
   },
   {
-    "game.panel.element_7.x",
-    &game.panel.element[6].x
+    "tape.text.date_dd.digits",
+    &tape.text.date_dd.size
   },
   {
-    "game.panel.element_7.y",
-    &game.panel.element[6].y
+    "tape.text.date_dd.font",
+    &tape.text.date_dd.font
   },
   {
-    "game.panel.element_7.tile_size",
-    &game.panel.element[6].size
+    "tape.text.date_dd.draw_masked",
+    &tape.text.date_dd.draw_masked
   },
   {
-    "game.panel.element_7.element",
-    &game.panel.element[6].id
+    "tape.text.time.x",
+    &tape.text.time.x
   },
   {
-    "game.panel.element_7.draw_masked",
-    &game.panel.element[6].draw_masked
+    "tape.text.time.y",
+    &tape.text.time.y
   },
   {
-    "game.panel.element_7.draw_order",
-    &game.panel.element[6].sort_priority
+    "tape.text.time.align",
+    &tape.text.time.align
   },
   {
-    "game.panel.element_7_count.x",
-    &game.panel.element_count[6].x
+    "tape.text.time.valign",
+    &tape.text.time.valign
   },
   {
-    "game.panel.element_7_count.y",
-    &game.panel.element_count[6].y
+    "tape.text.time.digits",
+    &tape.text.time.size
   },
   {
-    "game.panel.element_7_count.align",
-    &game.panel.element_count[6].align
+    "tape.text.time.xoffset",
+    &tape.text.time.xoffset
   },
   {
-    "game.panel.element_7_count.valign",
-    &game.panel.element_count[6].valign
+    "tape.text.time.font",
+    &tape.text.time.font
   },
   {
-    "game.panel.element_7_count.digits",
-    &game.panel.element_count[6].size
+    "tape.text.time.draw_masked",
+    &tape.text.time.draw_masked
   },
   {
-    "game.panel.element_7_count.font",
-    &game.panel.element_count[6].font
+    "tape.text.time_hh.x",
+    &tape.text.time_hh.x
   },
   {
-    "game.panel.element_7_count.element",
-    &game.panel.element_count[6].id
+    "tape.text.time_hh.y",
+    &tape.text.time_hh.y
   },
   {
-    "game.panel.element_7_count.draw_masked",
-    &game.panel.element_count[6].draw_masked
+    "tape.text.time_hh.align",
+    &tape.text.time_hh.align
   },
   {
-    "game.panel.element_7_count.draw_order",
-    &game.panel.element_count[6].sort_priority
+    "tape.text.time_hh.valign",
+    &tape.text.time_hh.valign
   },
   {
-    "game.panel.element_8.x",
-    &game.panel.element[7].x
+    "tape.text.time_hh.digits",
+    &tape.text.time_hh.size
   },
   {
-    "game.panel.element_8.y",
-    &game.panel.element[7].y
+    "tape.text.time_hh.font",
+    &tape.text.time_hh.font
   },
   {
-    "game.panel.element_8.tile_size",
-    &game.panel.element[7].size
+    "tape.text.time_hh.draw_masked",
+    &tape.text.time_hh.draw_masked
   },
   {
-    "game.panel.element_8.element",
-    &game.panel.element[7].id
+    "tape.text.time_mm.x",
+    &tape.text.time_mm.x
   },
   {
-    "game.panel.element_8.draw_masked",
-    &game.panel.element[7].draw_masked
+    "tape.text.time_mm.y",
+    &tape.text.time_mm.y
   },
   {
-    "game.panel.element_8.draw_order",
-    &game.panel.element[7].sort_priority
+    "tape.text.time_mm.align",
+    &tape.text.time_mm.align
   },
   {
-    "game.panel.element_8_count.x",
-    &game.panel.element_count[7].x
+    "tape.text.time_mm.valign",
+    &tape.text.time_mm.valign
   },
   {
-    "game.panel.element_8_count.y",
-    &game.panel.element_count[7].y
+    "tape.text.time_mm.digits",
+    &tape.text.time_mm.size
   },
   {
-    "game.panel.element_8_count.align",
-    &game.panel.element_count[7].align
+    "tape.text.time_mm.font",
+    &tape.text.time_mm.font
   },
   {
-    "game.panel.element_8_count.valign",
-    &game.panel.element_count[7].valign
+    "tape.text.time_mm.draw_masked",
+    &tape.text.time_mm.draw_masked
   },
   {
-    "game.panel.element_8_count.digits",
-    &game.panel.element_count[7].size
+    "tape.text.time_ss.x",
+    &tape.text.time_ss.x
   },
   {
-    "game.panel.element_8_count.font",
-    &game.panel.element_count[7].font
+    "tape.text.time_ss.y",
+    &tape.text.time_ss.y
   },
   {
-    "game.panel.element_8_count.element",
-    &game.panel.element_count[7].id
+    "tape.text.time_ss.align",
+    &tape.text.time_ss.align
   },
   {
-    "game.panel.element_8_count.draw_masked",
-    &game.panel.element_count[7].draw_masked
+    "tape.text.time_ss.valign",
+    &tape.text.time_ss.valign
   },
   {
-    "game.panel.element_8_count.draw_order",
-    &game.panel.element_count[7].sort_priority
+    "tape.text.time_ss.digits",
+    &tape.text.time_ss.size
   },
   {
-    "game.panel.ce_score_1.x",
-    &game.panel.ce_score[0].x
+    "tape.text.time_ss.font",
+    &tape.text.time_ss.font
   },
   {
-    "game.panel.ce_score_1.y",
-    &game.panel.ce_score[0].y
+    "tape.text.time_ss.draw_masked",
+    &tape.text.time_ss.draw_masked
   },
   {
-    "game.panel.ce_score_1.align",
-    &game.panel.ce_score[0].align
+    "tape.text.frame.x",
+    &tape.text.frame.x
   },
   {
-    "game.panel.ce_score_1.valign",
-    &game.panel.ce_score[0].valign
+    "tape.text.frame.y",
+    &tape.text.frame.y
   },
   {
-    "game.panel.ce_score_1.digits",
-    &game.panel.ce_score[0].size
+    "tape.text.frame.align",
+    &tape.text.frame.align
   },
   {
-    "game.panel.ce_score_1.font",
-    &game.panel.ce_score[0].font
+    "tape.text.frame.valign",
+    &tape.text.frame.valign
   },
   {
-    "game.panel.ce_score_1.element",
-    &game.panel.ce_score[0].id
+    "tape.text.frame.digits",
+    &tape.text.frame.size
   },
   {
-    "game.panel.ce_score_1.draw_masked",
-    &game.panel.ce_score[0].draw_masked
+    "tape.text.frame.font",
+    &tape.text.frame.font
   },
   {
-    "game.panel.ce_score_1.draw_order",
-    &game.panel.ce_score[0].sort_priority
+    "tape.text.frame.draw_masked",
+    &tape.text.frame.draw_masked
   },
   {
-    "game.panel.ce_score_1_element.x",
-    &game.panel.ce_score_element[0].x
+    "tape.show_game_buttons",
+    &tape.show_game_buttons
   },
   {
-    "game.panel.ce_score_1_element.y",
-    &game.panel.ce_score_element[0].y
+    "editor.button.prev_level.x",
+    &editor.button.prev_level.x
   },
   {
-    "game.panel.ce_score_1_element.tile_size",
-    &game.panel.ce_score_element[0].size
+    "editor.button.prev_level.y",
+    &editor.button.prev_level.y
   },
   {
-    "game.panel.ce_score_1_element.element",
-    &game.panel.ce_score_element[0].id
+    "editor.button.next_level.x",
+    &editor.button.next_level.x
   },
   {
-    "game.panel.ce_score_1_element.draw_masked",
-    &game.panel.ce_score_element[0].draw_masked
+    "editor.button.next_level.y",
+    &editor.button.next_level.y
   },
   {
-    "game.panel.ce_score_1_element.draw_order",
-    &game.panel.ce_score_element[0].sort_priority
+    "editor.button.properties.x",
+    &editor.button.properties.x
   },
   {
-    "game.panel.ce_score_2.x",
-    &game.panel.ce_score[1].x
+    "editor.button.properties.y",
+    &editor.button.properties.y
   },
   {
-    "game.panel.ce_score_2.y",
-    &game.panel.ce_score[1].y
+    "editor.button.element_left.x",
+    &editor.button.element_left.x
   },
   {
-    "game.panel.ce_score_2.align",
-    &game.panel.ce_score[1].align
+    "editor.button.element_left.y",
+    &editor.button.element_left.y
   },
   {
-    "game.panel.ce_score_2.valign",
-    &game.panel.ce_score[1].valign
+    "editor.button.element_left.tile_size",
+    &editor.button.element_left.tile_size
   },
   {
-    "game.panel.ce_score_2.digits",
-    &game.panel.ce_score[1].size
+    "editor.button.element_middle.x",
+    &editor.button.element_middle.x
   },
   {
-    "game.panel.ce_score_2.font",
-    &game.panel.ce_score[1].font
+    "editor.button.element_middle.y",
+    &editor.button.element_middle.y
   },
   {
-    "game.panel.ce_score_2.element",
-    &game.panel.ce_score[1].id
+    "editor.button.element_middle.tile_size",
+    &editor.button.element_middle.tile_size
   },
   {
-    "game.panel.ce_score_2.draw_masked",
-    &game.panel.ce_score[1].draw_masked
+    "editor.button.element_right.x",
+    &editor.button.element_right.x
   },
   {
-    "game.panel.ce_score_2.draw_order",
-    &game.panel.ce_score[1].sort_priority
+    "editor.button.element_right.y",
+    &editor.button.element_right.y
   },
   {
-    "game.panel.ce_score_2_element.x",
-    &game.panel.ce_score_element[1].x
+    "editor.button.element_right.tile_size",
+    &editor.button.element_right.tile_size
   },
   {
-    "game.panel.ce_score_2_element.y",
-    &game.panel.ce_score_element[1].y
+    "editor.button.palette.x",
+    &editor.button.palette.x
   },
   {
-    "game.panel.ce_score_2_element.tile_size",
-    &game.panel.ce_score_element[1].size
+    "editor.button.palette.y",
+    &editor.button.palette.y
   },
   {
-    "game.panel.ce_score_2_element.element",
-    &game.panel.ce_score_element[1].id
+    "editor.button.draw_single.x",
+    &editor.button.draw_single.x
   },
   {
-    "game.panel.ce_score_2_element.draw_masked",
-    &game.panel.ce_score_element[1].draw_masked
+    "editor.button.draw_single.y",
+    &editor.button.draw_single.y
   },
   {
-    "game.panel.ce_score_2_element.draw_order",
-    &game.panel.ce_score_element[1].sort_priority
+    "editor.button.draw_connected.x",
+    &editor.button.draw_connected.x
   },
   {
-    "game.panel.ce_score_3.x",
-    &game.panel.ce_score[2].x
+    "editor.button.draw_connected.y",
+    &editor.button.draw_connected.y
   },
   {
-    "game.panel.ce_score_3.y",
-    &game.panel.ce_score[2].y
+    "editor.button.draw_line.x",
+    &editor.button.draw_line.x
   },
   {
-    "game.panel.ce_score_3.align",
-    &game.panel.ce_score[2].align
+    "editor.button.draw_line.y",
+    &editor.button.draw_line.y
   },
   {
-    "game.panel.ce_score_3.valign",
-    &game.panel.ce_score[2].valign
+    "editor.button.draw_arc.x",
+    &editor.button.draw_arc.x
   },
   {
-    "game.panel.ce_score_3.digits",
-    &game.panel.ce_score[2].size
+    "editor.button.draw_arc.y",
+    &editor.button.draw_arc.y
   },
   {
-    "game.panel.ce_score_3.font",
-    &game.panel.ce_score[2].font
+    "editor.button.draw_rectangle.x",
+    &editor.button.draw_rectangle.x
   },
   {
-    "game.panel.ce_score_3.element",
-    &game.panel.ce_score[2].id
+    "editor.button.draw_rectangle.y",
+    &editor.button.draw_rectangle.y
   },
   {
-    "game.panel.ce_score_3.draw_masked",
-    &game.panel.ce_score[2].draw_masked
+    "editor.button.draw_filled_box.x",
+    &editor.button.draw_filled_box.x
   },
   {
-    "game.panel.ce_score_3.draw_order",
-    &game.panel.ce_score[2].sort_priority
+    "editor.button.draw_filled_box.y",
+    &editor.button.draw_filled_box.y
   },
   {
-    "game.panel.ce_score_3_element.x",
-    &game.panel.ce_score_element[2].x
+    "editor.button.rotate_up.x",
+    &editor.button.rotate_up.x
   },
   {
-    "game.panel.ce_score_3_element.y",
-    &game.panel.ce_score_element[2].y
+    "editor.button.rotate_up.y",
+    &editor.button.rotate_up.y
   },
   {
-    "game.panel.ce_score_3_element.tile_size",
-    &game.panel.ce_score_element[2].size
+    "editor.button.draw_text.x",
+    &editor.button.draw_text.x
   },
   {
-    "game.panel.ce_score_3_element.element",
-    &game.panel.ce_score_element[2].id
+    "editor.button.draw_text.y",
+    &editor.button.draw_text.y
   },
   {
-    "game.panel.ce_score_3_element.draw_masked",
-    &game.panel.ce_score_element[2].draw_masked
+    "editor.button.flood_fill.x",
+    &editor.button.flood_fill.x
   },
   {
-    "game.panel.ce_score_3_element.draw_order",
-    &game.panel.ce_score_element[2].sort_priority
+    "editor.button.flood_fill.y",
+    &editor.button.flood_fill.y
   },
   {
-    "game.panel.ce_score_4.x",
-    &game.panel.ce_score[3].x
+    "editor.button.rotate_left.x",
+    &editor.button.rotate_left.x
   },
   {
-    "game.panel.ce_score_4.y",
-    &game.panel.ce_score[3].y
+    "editor.button.rotate_left.y",
+    &editor.button.rotate_left.y
   },
   {
-    "game.panel.ce_score_4.align",
-    &game.panel.ce_score[3].align
+    "editor.button.zoom_level.x",
+    &editor.button.zoom_level.x
   },
   {
-    "game.panel.ce_score_4.valign",
-    &game.panel.ce_score[3].valign
+    "editor.button.zoom_level.y",
+    &editor.button.zoom_level.y
   },
   {
-    "game.panel.ce_score_4.digits",
-    &game.panel.ce_score[3].size
+    "editor.button.rotate_right.x",
+    &editor.button.rotate_right.x
   },
   {
-    "game.panel.ce_score_4.font",
-    &game.panel.ce_score[3].font
+    "editor.button.rotate_right.y",
+    &editor.button.rotate_right.y
   },
   {
-    "game.panel.ce_score_4.element",
-    &game.panel.ce_score[3].id
+    "editor.button.draw_random.x",
+    &editor.button.draw_random.x
   },
   {
-    "game.panel.ce_score_4.draw_masked",
-    &game.panel.ce_score[3].draw_masked
+    "editor.button.draw_random.y",
+    &editor.button.draw_random.y
   },
   {
-    "game.panel.ce_score_4.draw_order",
-    &game.panel.ce_score[3].sort_priority
+    "editor.button.grab_brush.x",
+    &editor.button.grab_brush.x
   },
   {
-    "game.panel.ce_score_4_element.x",
-    &game.panel.ce_score_element[3].x
+    "editor.button.grab_brush.y",
+    &editor.button.grab_brush.y
   },
   {
-    "game.panel.ce_score_4_element.y",
-    &game.panel.ce_score_element[3].y
+    "editor.button.rotate_down.x",
+    &editor.button.rotate_down.x
   },
   {
-    "game.panel.ce_score_4_element.tile_size",
-    &game.panel.ce_score_element[3].size
+    "editor.button.rotate_down.y",
+    &editor.button.rotate_down.y
   },
   {
-    "game.panel.ce_score_4_element.element",
-    &game.panel.ce_score_element[3].id
+    "editor.button.pick_element.x",
+    &editor.button.pick_element.x
   },
   {
-    "game.panel.ce_score_4_element.draw_masked",
-    &game.panel.ce_score_element[3].draw_masked
+    "editor.button.pick_element.y",
+    &editor.button.pick_element.y
   },
   {
-    "game.panel.ce_score_4_element.draw_order",
-    &game.panel.ce_score_element[3].sort_priority
+    "editor.button.ce_copy_from.x",
+    &editor.button.ce_copy_from.x
   },
   {
-    "game.panel.ce_score_5.x",
-    &game.panel.ce_score[4].x
+    "editor.button.ce_copy_from.y",
+    &editor.button.ce_copy_from.y
   },
   {
-    "game.panel.ce_score_5.y",
-    &game.panel.ce_score[4].y
+    "editor.button.ce_copy_to.x",
+    &editor.button.ce_copy_to.x
   },
   {
-    "game.panel.ce_score_5.align",
-    &game.panel.ce_score[4].align
+    "editor.button.ce_copy_to.y",
+    &editor.button.ce_copy_to.y
   },
   {
-    "game.panel.ce_score_5.valign",
-    &game.panel.ce_score[4].valign
+    "editor.button.ce_swap.x",
+    &editor.button.ce_swap.x
   },
   {
-    "game.panel.ce_score_5.digits",
-    &game.panel.ce_score[4].size
+    "editor.button.ce_swap.y",
+    &editor.button.ce_swap.y
   },
   {
-    "game.panel.ce_score_5.font",
-    &game.panel.ce_score[4].font
+    "editor.button.ce_copy.x",
+    &editor.button.ce_copy.x
   },
   {
-    "game.panel.ce_score_5.element",
-    &game.panel.ce_score[4].id
+    "editor.button.ce_copy.y",
+    &editor.button.ce_copy.y
   },
   {
-    "game.panel.ce_score_5.draw_masked",
-    &game.panel.ce_score[4].draw_masked
+    "editor.button.ce_paste.x",
+    &editor.button.ce_paste.x
   },
   {
-    "game.panel.ce_score_5.draw_order",
-    &game.panel.ce_score[4].sort_priority
+    "editor.button.ce_paste.y",
+    &editor.button.ce_paste.y
   },
   {
-    "game.panel.ce_score_5_element.x",
-    &game.panel.ce_score_element[4].x
+    "editor.button.undo.x",
+    &editor.button.undo.x
   },
   {
-    "game.panel.ce_score_5_element.y",
-    &game.panel.ce_score_element[4].y
+    "editor.button.undo.y",
+    &editor.button.undo.y
   },
   {
-    "game.panel.ce_score_5_element.tile_size",
-    &game.panel.ce_score_element[4].size
+    "editor.button.conf.x",
+    &editor.button.conf.x
   },
   {
-    "game.panel.ce_score_5_element.element",
-    &game.panel.ce_score_element[4].id
+    "editor.button.conf.y",
+    &editor.button.conf.y
   },
   {
-    "game.panel.ce_score_5_element.draw_masked",
-    &game.panel.ce_score_element[4].draw_masked
+    "editor.button.save.x",
+    &editor.button.save.x
   },
   {
-    "game.panel.ce_score_5_element.draw_order",
-    &game.panel.ce_score_element[4].sort_priority
+    "editor.button.save.y",
+    &editor.button.save.y
   },
   {
-    "game.panel.ce_score_6.x",
-    &game.panel.ce_score[5].x
+    "editor.button.clear.x",
+    &editor.button.clear.x
   },
   {
-    "game.panel.ce_score_6.y",
-    &game.panel.ce_score[5].y
+    "editor.button.clear.y",
+    &editor.button.clear.y
   },
   {
-    "game.panel.ce_score_6.align",
-    &game.panel.ce_score[5].align
+    "editor.button.test.x",
+    &editor.button.test.x
   },
   {
-    "game.panel.ce_score_6.valign",
-    &game.panel.ce_score[5].valign
+    "editor.button.test.y",
+    &editor.button.test.y
   },
   {
-    "game.panel.ce_score_6.digits",
-    &game.panel.ce_score[5].size
+    "editor.button.exit.x",
+    &editor.button.exit.x
   },
   {
-    "game.panel.ce_score_6.font",
-    &game.panel.ce_score[5].font
+    "editor.button.exit.y",
+    &editor.button.exit.y
   },
   {
-    "game.panel.ce_score_6.element",
-    &game.panel.ce_score[5].id
+    "editor.input.level_number.x",
+    &editor.input.level_number.x
   },
   {
-    "game.panel.ce_score_6.draw_masked",
-    &game.panel.ce_score[5].draw_masked
+    "editor.input.level_number.y",
+    &editor.input.level_number.y
   },
   {
-    "game.panel.ce_score_6.draw_order",
-    &game.panel.ce_score[5].sort_priority
+    "editor.palette.x",
+    &editor.palette.x
   },
   {
-    "game.panel.ce_score_6_element.x",
-    &game.panel.ce_score_element[5].x
+    "editor.palette.y",
+    &editor.palette.y
   },
   {
-    "game.panel.ce_score_6_element.y",
-    &game.panel.ce_score_element[5].y
+    "editor.palette.cols",
+    &editor.palette.cols
   },
   {
-    "game.panel.ce_score_6_element.tile_size",
-    &game.panel.ce_score_element[5].size
+    "editor.palette.rows",
+    &editor.palette.rows
   },
   {
-    "game.panel.ce_score_6_element.element",
-    &game.panel.ce_score_element[5].id
+    "editor.palette.tile_size",
+    &editor.palette.tile_size
   },
   {
-    "game.panel.ce_score_6_element.draw_masked",
-    &game.panel.ce_score_element[5].draw_masked
+    "editor.palette.show_as_separate_screen",
+    &editor.palette.show_as_separate_screen
   },
   {
-    "game.panel.ce_score_6_element.draw_order",
-    &game.panel.ce_score_element[5].sort_priority
+    "editor.palette.show_on_element_buttons",
+    &editor.palette.show_on_element_buttons
   },
   {
-    "game.panel.ce_score_7.x",
-    &game.panel.ce_score[6].x
+    "editor.palette.element_left.x",
+    &editor.palette.element_left.x
   },
   {
-    "game.panel.ce_score_7.y",
-    &game.panel.ce_score[6].y
+    "editor.palette.element_left.y",
+    &editor.palette.element_left.y
   },
   {
-    "game.panel.ce_score_7.align",
-    &game.panel.ce_score[6].align
+    "editor.palette.element_left.tile_size",
+    &editor.palette.element_left.tile_size
   },
   {
-    "game.panel.ce_score_7.valign",
-    &game.panel.ce_score[6].valign
+    "editor.palette.element_middle.x",
+    &editor.palette.element_middle.x
   },
   {
-    "game.panel.ce_score_7.digits",
-    &game.panel.ce_score[6].size
+    "editor.palette.element_middle.y",
+    &editor.palette.element_middle.y
   },
   {
-    "game.panel.ce_score_7.font",
-    &game.panel.ce_score[6].font
+    "editor.palette.element_middle.tile_size",
+    &editor.palette.element_middle.tile_size
   },
   {
-    "game.panel.ce_score_7.element",
-    &game.panel.ce_score[6].id
+    "editor.palette.element_right.x",
+    &editor.palette.element_right.x
   },
   {
-    "game.panel.ce_score_7.draw_masked",
-    &game.panel.ce_score[6].draw_masked
+    "editor.palette.element_right.y",
+    &editor.palette.element_right.y
   },
   {
-    "game.panel.ce_score_7.draw_order",
-    &game.panel.ce_score[6].sort_priority
+    "editor.palette.element_right.tile_size",
+    &editor.palette.element_right.tile_size
   },
   {
-    "game.panel.ce_score_7_element.x",
-    &game.panel.ce_score_element[6].x
+    "editor.drawingarea.tile_size",
+    &editor.drawingarea.tile_size
   },
   {
-    "game.panel.ce_score_7_element.y",
-    &game.panel.ce_score_element[6].y
+    "editor.settings.headline.x",
+    &editor.settings.headline.x
   },
   {
-    "game.panel.ce_score_7_element.tile_size",
-    &game.panel.ce_score_element[6].size
+    "editor.settings.headline.y",
+    &editor.settings.headline.y
   },
   {
-    "game.panel.ce_score_7_element.element",
-    &game.panel.ce_score_element[6].id
+    "editor.settings.headline.align",
+    &editor.settings.headline.align
   },
   {
-    "game.panel.ce_score_7_element.draw_masked",
-    &game.panel.ce_score_element[6].draw_masked
+    "editor.settings.element_graphic.x",
+    &editor.settings.element_graphic.x
   },
   {
-    "game.panel.ce_score_7_element.draw_order",
-    &game.panel.ce_score_element[6].sort_priority
+    "editor.settings.element_graphic.y",
+    &editor.settings.element_graphic.y
   },
   {
-    "game.panel.ce_score_8.x",
-    &game.panel.ce_score[7].x
+    "editor.settings.element_name.x",
+    &editor.settings.element_name.x
   },
   {
-    "game.panel.ce_score_8.y",
-    &game.panel.ce_score[7].y
+    "editor.settings.element_name.y",
+    &editor.settings.element_name.y
   },
   {
-    "game.panel.ce_score_8.align",
-    &game.panel.ce_score[7].align
+    "editor.settings.tabs.x",
+    &editor.settings.tabs.x
   },
   {
-    "game.panel.ce_score_8.valign",
-    &game.panel.ce_score[7].valign
+    "editor.settings.tabs.y",
+    &editor.settings.tabs.y
   },
   {
-    "game.panel.ce_score_8.digits",
-    &game.panel.ce_score[7].size
+    "editor.settings.tabs.2nd_yoffset",
+    &editor.settings.tabs.yoffset2
   },
   {
-    "game.panel.ce_score_8.font",
-    &game.panel.ce_score[7].font
+    "editor.settings.tabs.draw_xoffset",
+    &editor.settings.tabs.draw_xoffset
   },
   {
-    "game.panel.ce_score_8.element",
-    &game.panel.ce_score[7].id
+    "editor.settings.tabs.draw_yoffset",
+    &editor.settings.tabs.draw_yoffset
   },
   {
-    "game.panel.ce_score_8.draw_masked",
-    &game.panel.ce_score[7].draw_masked
+    "editor.gadget.normal_spacing",
+    &editor.gadget.normal_spacing
   },
   {
-    "game.panel.ce_score_8.draw_order",
-    &game.panel.ce_score[7].sort_priority
+    "editor.gadget.small_spacing",
+    &editor.gadget.small_spacing
   },
   {
-    "game.panel.ce_score_8_element.x",
-    &game.panel.ce_score_element[7].x
+    "editor.gadget.tiny_spacing",
+    &editor.gadget.tiny_spacing
   },
   {
-    "game.panel.ce_score_8_element.y",
-    &game.panel.ce_score_element[7].y
+    "editor.gadget.line_spacing",
+    &editor.gadget.line_spacing
   },
   {
-    "game.panel.ce_score_8_element.tile_size",
-    &game.panel.ce_score_element[7].size
+    "editor.gadget.text_spacing",
+    &editor.gadget.text_spacing
   },
   {
-    "game.panel.ce_score_8_element.element",
-    &game.panel.ce_score_element[7].id
+    "editor.gadget.separator_line.height",
+    &editor.gadget.separator_line.height
   },
   {
-    "game.panel.ce_score_8_element.draw_masked",
-    &game.panel.ce_score_element[7].draw_masked
+    "request.button.yes.x",
+    &request.button.yes.x
   },
   {
-    "game.panel.ce_score_8_element.draw_order",
-    &game.panel.ce_score_element[7].sort_priority
+    "request.button.yes.y",
+    &request.button.yes.y
   },
   {
-    "game.panel.player_name.x",
-    &game.panel.player_name.x
+    "request.button.no.x",
+    &request.button.no.x
   },
   {
-    "game.panel.player_name.y",
-    &game.panel.player_name.y
+    "request.button.no.y",
+    &request.button.no.y
   },
   {
-    "game.panel.player_name.align",
-    &game.panel.player_name.align
+    "request.button.confirm.x",
+    &request.button.confirm.x
   },
   {
-    "game.panel.player_name.valign",
-    &game.panel.player_name.valign
+    "request.button.confirm.y",
+    &request.button.confirm.y
   },
   {
-    "game.panel.player_name.chars",
-    &game.panel.player_name.size
+    "request.button.player_1.x",
+    &request.button.player_1.x
   },
   {
-    "game.panel.player_name.font",
-    &game.panel.player_name.font
+    "request.button.player_1.y",
+    &request.button.player_1.y
   },
   {
-    "game.panel.player_name.draw_masked",
-    &game.panel.player_name.draw_masked
+    "request.button.player_1.draw_player",
+    &request.button.player_1.draw_player
   },
   {
-    "game.panel.player_name.draw_order",
-    &game.panel.player_name.sort_priority
+    "request.button.player_1.tile_size",
+    &request.button.player_1.size
   },
   {
-    "game.panel.level_name.x",
-    &game.panel.level_name.x
+    "request.button.player_2.x",
+    &request.button.player_2.x
   },
   {
-    "game.panel.level_name.y",
-    &game.panel.level_name.y
+    "request.button.player_2.y",
+    &request.button.player_2.y
   },
   {
-    "game.panel.level_name.align",
-    &game.panel.level_name.align
+    "request.button.player_2.draw_player",
+    &request.button.player_2.draw_player
   },
   {
-    "game.panel.level_name.valign",
-    &game.panel.level_name.valign
+    "request.button.player_2.tile_size",
+    &request.button.player_2.size
   },
   {
-    "game.panel.level_name.chars",
-    &game.panel.level_name.size
+    "request.button.player_3.x",
+    &request.button.player_3.x
   },
   {
-    "game.panel.level_name.font",
-    &game.panel.level_name.font
+    "request.button.player_3.y",
+    &request.button.player_3.y
   },
   {
-    "game.panel.level_name.draw_masked",
-    &game.panel.level_name.draw_masked
+    "request.button.player_3.draw_player",
+    &request.button.player_3.draw_player
   },
   {
-    "game.panel.level_name.draw_order",
-    &game.panel.level_name.sort_priority
+    "request.button.player_3.tile_size",
+    &request.button.player_3.size
   },
   {
-    "game.panel.level_author.x",
-    &game.panel.level_author.x
+    "request.button.player_4.x",
+    &request.button.player_4.x
   },
   {
-    "game.panel.level_author.y",
-    &game.panel.level_author.y
+    "request.button.player_4.y",
+    &request.button.player_4.y
   },
   {
-    "game.panel.level_author.align",
-    &game.panel.level_author.align
+    "request.button.player_4.draw_player",
+    &request.button.player_4.draw_player
   },
   {
-    "game.panel.level_author.valign",
-    &game.panel.level_author.valign
+    "request.button.player_4.tile_size",
+    &request.button.player_4.size
   },
   {
-    "game.panel.level_author.chars",
-    &game.panel.level_author.size
+    "request.x",
+    &request.x
   },
   {
-    "game.panel.level_author.font",
-    &game.panel.level_author.font
+    "request.y",
+    &request.y
   },
   {
-    "game.panel.level_author.draw_masked",
-    &game.panel.level_author.draw_masked
+    "request.width",
+    &request.width
   },
   {
-    "game.panel.level_author.draw_order",
-    &game.panel.level_author.sort_priority
+    "request.height",
+    &request.height
   },
   {
-    "game.button.stop.x",
-    &game.button.stop.x
+    "request.border_size",
+    &request.border_size
   },
   {
-    "game.button.stop.y",
-    &game.button.stop.y
+    "request.line_spacing",
+    &request.line_spacing
   },
   {
-    "game.button.pause.x",
-    &game.button.pause.x
+    "request.step_offset",
+    &request.step_offset
   },
   {
-    "game.button.pause.y",
-    &game.button.pause.y
+    "request.step_delay",
+    &request.step_delay
   },
   {
-    "game.button.play.x",
-    &game.button.play.x
+    "request.anim_mode",
+    &request.anim_mode
   },
   {
-    "game.button.play.y",
-    &game.button.play.y
+    "request.align",
+    &request.align
   },
   {
-    "game.button.sound_music.x",
-    &game.button.sound_music.x
+    "request.valign",
+    &request.valign
   },
   {
-    "game.button.sound_music.y",
-    &game.button.sound_music.y
+    "request.autowrap",
+    &request.autowrap
   },
   {
-    "game.button.sound_loops.x",
-    &game.button.sound_loops.x
+    "request.centered",
+    &request.centered
   },
   {
-    "game.button.sound_loops.y",
-    &game.button.sound_loops.y
+    "request.wrap_single_words",
+    &request.wrap_single_words
   },
   {
-    "game.button.sound_simple.x",
-    &game.button.sound_simple.x
+    "global.use_envelope_request",
+    &global.use_envelope_request
   },
   {
-    "game.button.sound_simple.y",
-    &game.button.sound_simple.y
+    "game.graphics_engine_version",
+    &game.graphics_engine_version
   },
   {
     "game.forced_scroll_delay_value",
@@ -5077,6 +8207,10 @@ struct TokenIntPtrInfo image_config_vars[] =
     &game.use_masked_pushing
   },
   {
+    "game.tile_size",
+    &game.tile_size
+  },
+  {
     "[player].boring_delay_fixed",
     &game.player_boring_delay_fixed
   },
@@ -5094,11 +8228,19 @@ struct TokenIntPtrInfo image_config_vars[] =
   },
   {
     "viewport.window.width",
-    &viewport.window.width
+    &viewport.window[GFX_SPECIAL_ARG_DEFAULT].width
   },
   {
     "viewport.window.height",
-    &viewport.window.height
+    &viewport.window[GFX_SPECIAL_ARG_DEFAULT].height
+  },
+  {
+    "viewport.window.TITLE.width",
+    &viewport.window[GFX_SPECIAL_ARG_TITLE].width
+  },
+  {
+    "viewport.window.TITLE.height",
+    &viewport.window[GFX_SPECIAL_ARG_TITLE].height
   },
   {
     "viewport.playfield.x",
@@ -5141,24 +8283,24 @@ struct TokenIntPtrInfo image_config_vars[] =
     &viewport.playfield[GFX_SPECIAL_ARG_MAIN].border_size
   },
   {
-    "viewport.playfield.PLAYING.x",
-    &viewport.playfield[GFX_SPECIAL_ARG_PLAYING].x
+    "viewport.playfield.SCORES.x",
+    &viewport.playfield[GFX_SPECIAL_ARG_SCORES].x
   },
   {
-    "viewport.playfield.PLAYING.y",
-    &viewport.playfield[GFX_SPECIAL_ARG_PLAYING].y
+    "viewport.playfield.SCORES.y",
+    &viewport.playfield[GFX_SPECIAL_ARG_SCORES].y
   },
   {
-    "viewport.playfield.PLAYING.width",
-    &viewport.playfield[GFX_SPECIAL_ARG_PLAYING].width
+    "viewport.playfield.SCORES.width",
+    &viewport.playfield[GFX_SPECIAL_ARG_SCORES].width
   },
   {
-    "viewport.playfield.PLAYING.height",
-    &viewport.playfield[GFX_SPECIAL_ARG_PLAYING].height
+    "viewport.playfield.SCORES.height",
+    &viewport.playfield[GFX_SPECIAL_ARG_SCORES].height
   },
   {
-    "viewport.playfield.PLAYING.border_size",
-    &viewport.playfield[GFX_SPECIAL_ARG_PLAYING].border_size
+    "viewport.playfield.SCORES.border_size",
+    &viewport.playfield[GFX_SPECIAL_ARG_SCORES].border_size
   },
   {
     "viewport.playfield.EDITOR.x",
@@ -5181,6 +8323,26 @@ struct TokenIntPtrInfo image_config_vars[] =
     &viewport.playfield[GFX_SPECIAL_ARG_EDITOR].border_size
   },
   {
+    "viewport.playfield.PLAYING.x",
+    &viewport.playfield[GFX_SPECIAL_ARG_PLAYING].x
+  },
+  {
+    "viewport.playfield.PLAYING.y",
+    &viewport.playfield[GFX_SPECIAL_ARG_PLAYING].y
+  },
+  {
+    "viewport.playfield.PLAYING.width",
+    &viewport.playfield[GFX_SPECIAL_ARG_PLAYING].width
+  },
+  {
+    "viewport.playfield.PLAYING.height",
+    &viewport.playfield[GFX_SPECIAL_ARG_PLAYING].height
+  },
+  {
+    "viewport.playfield.PLAYING.border_size",
+    &viewport.playfield[GFX_SPECIAL_ARG_PLAYING].border_size
+  },
+  {
     "viewport.door_1.x",
     &viewport.door_1[GFX_SPECIAL_ARG_DEFAULT].x
   },
@@ -5189,6 +8351,18 @@ struct TokenIntPtrInfo image_config_vars[] =
     &viewport.door_1[GFX_SPECIAL_ARG_DEFAULT].y
   },
   {
+    "viewport.door_1.width",
+    &viewport.door_1[GFX_SPECIAL_ARG_DEFAULT].width
+  },
+  {
+    "viewport.door_1.height",
+    &viewport.door_1[GFX_SPECIAL_ARG_DEFAULT].height
+  },
+  {
+    "viewport.door_1.border_size",
+    &viewport.door_1[GFX_SPECIAL_ARG_DEFAULT].border_size
+  },
+  {
     "viewport.door_1.MAIN.x",
     &viewport.door_1[GFX_SPECIAL_ARG_MAIN].x
   },
@@ -5197,12 +8371,36 @@ struct TokenIntPtrInfo image_config_vars[] =
     &viewport.door_1[GFX_SPECIAL_ARG_MAIN].y
   },
   {
-    "viewport.door_1.PLAYING.x",
-    &viewport.door_1[GFX_SPECIAL_ARG_PLAYING].x
+    "viewport.door_1.MAIN.width",
+    &viewport.door_1[GFX_SPECIAL_ARG_MAIN].width
   },
   {
-    "viewport.door_1.PLAYING.y",
-    &viewport.door_1[GFX_SPECIAL_ARG_PLAYING].y
+    "viewport.door_1.MAIN.height",
+    &viewport.door_1[GFX_SPECIAL_ARG_MAIN].height
+  },
+  {
+    "viewport.door_1.MAIN.border_size",
+    &viewport.door_1[GFX_SPECIAL_ARG_MAIN].border_size
+  },
+  {
+    "viewport.door_1.SCORES.x",
+    &viewport.door_1[GFX_SPECIAL_ARG_SCORES].x
+  },
+  {
+    "viewport.door_1.SCORES.y",
+    &viewport.door_1[GFX_SPECIAL_ARG_SCORES].y
+  },
+  {
+    "viewport.door_1.SCORES.width",
+    &viewport.door_1[GFX_SPECIAL_ARG_SCORES].width
+  },
+  {
+    "viewport.door_1.SCORES.height",
+    &viewport.door_1[GFX_SPECIAL_ARG_SCORES].height
+  },
+  {
+    "viewport.door_1.SCORES.border_size",
+    &viewport.door_1[GFX_SPECIAL_ARG_SCORES].border_size
   },
   {
     "viewport.door_1.EDITOR.x",
@@ -5213,6 +8411,38 @@ struct TokenIntPtrInfo image_config_vars[] =
     &viewport.door_1[GFX_SPECIAL_ARG_EDITOR].y
   },
   {
+    "viewport.door_1.EDITOR.width",
+    &viewport.door_1[GFX_SPECIAL_ARG_EDITOR].width
+  },
+  {
+    "viewport.door_1.EDITOR.height",
+    &viewport.door_1[GFX_SPECIAL_ARG_EDITOR].height
+  },
+  {
+    "viewport.door_1.EDITOR.border_size",
+    &viewport.door_1[GFX_SPECIAL_ARG_EDITOR].border_size
+  },
+  {
+    "viewport.door_1.PLAYING.x",
+    &viewport.door_1[GFX_SPECIAL_ARG_PLAYING].x
+  },
+  {
+    "viewport.door_1.PLAYING.y",
+    &viewport.door_1[GFX_SPECIAL_ARG_PLAYING].y
+  },
+  {
+    "viewport.door_1.PLAYING.width",
+    &viewport.door_1[GFX_SPECIAL_ARG_PLAYING].width
+  },
+  {
+    "viewport.door_1.PLAYING.height",
+    &viewport.door_1[GFX_SPECIAL_ARG_PLAYING].height
+  },
+  {
+    "viewport.door_1.PLAYING.border_size",
+    &viewport.door_1[GFX_SPECIAL_ARG_PLAYING].border_size
+  },
+  {
     "viewport.door_2.x",
     &viewport.door_2[GFX_SPECIAL_ARG_DEFAULT].x
   },
@@ -5221,6 +8451,18 @@ struct TokenIntPtrInfo image_config_vars[] =
     &viewport.door_2[GFX_SPECIAL_ARG_DEFAULT].y
   },
   {
+    "viewport.door_2.width",
+    &viewport.door_2[GFX_SPECIAL_ARG_DEFAULT].width
+  },
+  {
+    "viewport.door_2.height",
+    &viewport.door_2[GFX_SPECIAL_ARG_DEFAULT].height
+  },
+  {
+    "viewport.door_2.border_size",
+    &viewport.door_2[GFX_SPECIAL_ARG_DEFAULT].border_size
+  },
+  {
     "viewport.door_2.MAIN.x",
     &viewport.door_2[GFX_SPECIAL_ARG_MAIN].x
   },
@@ -5229,12 +8471,36 @@ struct TokenIntPtrInfo image_config_vars[] =
     &viewport.door_2[GFX_SPECIAL_ARG_MAIN].y
   },
   {
-    "viewport.door_2.PLAYING.x",
-    &viewport.door_2[GFX_SPECIAL_ARG_PLAYING].x
+    "viewport.door_2.MAIN.width",
+    &viewport.door_2[GFX_SPECIAL_ARG_MAIN].width
   },
   {
-    "viewport.door_2.PLAYING.y",
-    &viewport.door_2[GFX_SPECIAL_ARG_PLAYING].y
+    "viewport.door_2.MAIN.height",
+    &viewport.door_2[GFX_SPECIAL_ARG_MAIN].height
+  },
+  {
+    "viewport.door_2.MAIN.border_size",
+    &viewport.door_2[GFX_SPECIAL_ARG_MAIN].border_size
+  },
+  {
+    "viewport.door_2.SCORES.x",
+    &viewport.door_2[GFX_SPECIAL_ARG_SCORES].x
+  },
+  {
+    "viewport.door_2.SCORES.y",
+    &viewport.door_2[GFX_SPECIAL_ARG_SCORES].y
+  },
+  {
+    "viewport.door_2.SCORES.width",
+    &viewport.door_2[GFX_SPECIAL_ARG_SCORES].width
+  },
+  {
+    "viewport.door_2.SCORES.height",
+    &viewport.door_2[GFX_SPECIAL_ARG_SCORES].height
+  },
+  {
+    "viewport.door_2.SCORES.border_size",
+    &viewport.door_2[GFX_SPECIAL_ARG_SCORES].border_size
   },
   {
     "viewport.door_2.EDITOR.x",
@@ -5245,6 +8511,38 @@ struct TokenIntPtrInfo image_config_vars[] =
     &viewport.door_2[GFX_SPECIAL_ARG_EDITOR].y
   },
   {
+    "viewport.door_2.EDITOR.width",
+    &viewport.door_2[GFX_SPECIAL_ARG_EDITOR].width
+  },
+  {
+    "viewport.door_2.EDITOR.height",
+    &viewport.door_2[GFX_SPECIAL_ARG_EDITOR].height
+  },
+  {
+    "viewport.door_2.EDITOR.border_size",
+    &viewport.door_2[GFX_SPECIAL_ARG_EDITOR].border_size
+  },
+  {
+    "viewport.door_2.PLAYING.x",
+    &viewport.door_2[GFX_SPECIAL_ARG_PLAYING].x
+  },
+  {
+    "viewport.door_2.PLAYING.y",
+    &viewport.door_2[GFX_SPECIAL_ARG_PLAYING].y
+  },
+  {
+    "viewport.door_2.PLAYING.width",
+    &viewport.door_2[GFX_SPECIAL_ARG_PLAYING].width
+  },
+  {
+    "viewport.door_2.PLAYING.height",
+    &viewport.door_2[GFX_SPECIAL_ARG_PLAYING].height
+  },
+  {
+    "viewport.door_2.PLAYING.border_size",
+    &viewport.door_2[GFX_SPECIAL_ARG_PLAYING].border_size
+  },
+  {
     NULL,
     NULL
   },
diff --git a/src/config.c b/src/config.c
index c812adf..608b066 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* config.c                                                 *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// config.c
+// ============================================================================
 
 #include "libgame/libgame.h"
 
@@ -17,68 +15,38 @@
 #include "conftime.h"
 
 
-#define USE_EXTENDED_VERSION	1
-
-
-char *getCompileDateString()
+char *getSourceDateString()
 {
-  return COMPILE_DATE_STRING;
+  return SOURCE_DATE_STRING;
 }
 
-char *getProgramReleaseVersionString()
+char *getProgramTitleString()
 {
-  static char program_version_string[32];
-
-#if USE_EXTENDED_VERSION
-  sprintf(program_version_string, "%d.%d.%d.%d",
-	  PROGRAM_VERSION_MAJOR, PROGRAM_VERSION_MINOR, PROGRAM_VERSION_PATCH,
-	  PROGRAM_VERSION_BUILD);
-#else
-  sprintf(program_version_string, "%d.%d.%d",
-	  PROGRAM_VERSION_MAJOR, PROGRAM_VERSION_MINOR, PROGRAM_VERSION_PATCH);
-#endif
-
-  return program_version_string;
+  return program.program_title;
 }
 
-char *getProgramFullVersionString()
+char *getProgramVersionString()
 {
   static char program_version_string[32];
 
-#if USE_EXTENDED_VERSION
-  sprintf(program_version_string, "%d.%d.%d.%d",
+  sprintf(program_version_string, "%d.%d.%d.%d%s",
 	  PROGRAM_VERSION_MAJOR, PROGRAM_VERSION_MINOR, PROGRAM_VERSION_PATCH,
-	  PROGRAM_VERSION_BUILD);
-#else
-  sprintf(program_version_string, "%d.%d.%d-%d",
-	  PROGRAM_VERSION_MAJOR, PROGRAM_VERSION_MINOR, PROGRAM_VERSION_PATCH,
-	  PROGRAM_VERSION_BUILD);
-#endif
+	  PROGRAM_VERSION_BUILD, PROGRAM_VERSION_EXTRA);
 
   return program_version_string;
 }
 
-char *getProgramVersionString()
-{
-#ifdef DEBUG
-  return getProgramFullVersionString();
-#else
-  return getProgramReleaseVersionString();
-#endif
-}
-
 char *getProgramInitString()
 {
   static char *program_init_string = NULL;
 
   if (program_init_string == NULL)
   {
-    program_init_string = checked_malloc(strlen(PROGRAM_TITLE_STRING) + 1 +
-					 strlen(getProgramVersionString()) +1 +
-					 strlen(TARGET_STRING) + 1);
+    program_init_string = checked_malloc(strlen(getProgramTitleString()) + 1 +
+					 strlen(getProgramVersionString()) + 1);
 
-    sprintf(program_init_string, "%s %s %s",
-	    PROGRAM_TITLE_STRING, getProgramVersionString(), TARGET_STRING);
+    sprintf(program_init_string, "%s %s",
+	    getProgramTitleString(), getProgramVersionString());
   }
 
   return program_init_string;
@@ -86,20 +54,42 @@ char *getProgramInitString()
 
 char *getWindowTitleString()
 {
-#ifdef DEBUG
   static char *window_title_string = NULL;
 
-  if (window_title_string == NULL)
-  {
-    window_title_string = checked_malloc(strlen(getProgramInitString()) + 1 +
-					 strlen(getCompileDateString()) + 2 +1);
+  checked_free(window_title_string);
 
-    sprintf(window_title_string, "%s [%s]",
-	    getProgramInitString(), getCompileDateString());
-  }
+#if defined(TARGET_SDL2)
 
-  return window_title_string;
+#ifdef DEBUG
+  window_title_string = checked_malloc(strlen(getProgramInitString()) + 20 +
+				       strlen(getSourceDateString()) + 2 + 1);
+
+  sprintf(window_title_string, "%s (%d %%) [%s]",
+	  getProgramInitString(), video.window_scaling_percent,
+	  getSourceDateString());
 #else
-  return getProgramInitString();
+  window_title_string = checked_malloc(strlen(getProgramInitString()) + 20);
+
+  sprintf(window_title_string, "%s (%d %%)",
+	  getProgramInitString(), video.window_scaling_percent);
 #endif
+
+#else
+
+#ifdef DEBUG
+  window_title_string = checked_malloc(strlen(getProgramInitString()) + 1 +
+				       strlen(getSourceDateString()) + 2 + 1);
+
+  sprintf(window_title_string, "%s [%s]",
+	  getProgramInitString(), getSourceDateString());
+#else
+  window_title_string = checked_malloc(strlen(getProgramInitString()) + 1);
+
+  sprintf(window_title_string, "%s",
+	  getProgramInitString());
+#endif
+
+#endif
+
+  return window_title_string;
 }
diff --git a/src/config.h b/src/config.h
index ac24bb1..ba401a5 100644
--- a/src/config.h
+++ b/src/config.h
@@ -1,24 +1,21 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* config.h                                                 *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// config.h
+// ============================================================================
 
 #ifndef CONFIG_H
 #define CONFIG_H
 
 #include "main.h"
 
-char *getCompileDateString(void);
-char *getProgramReleaseVersionString(void);
-char *getProgramFullVersionString(void);
+char *getSourceDateString(void);
+char *getProgramTitleString(void);
 char *getProgramVersionString(void);
 char *getProgramInitString(void);
 char *getWindowTitleString(void);
diff --git a/src/conftime.h b/src/conftime.h
new file mode 100644
index 0000000..af3e285
--- /dev/null
+++ b/src/conftime.h
@@ -0,0 +1 @@
+#define SOURCE_DATE_STRING "2017-01-10 23:06"
diff --git a/src/editor.c b/src/editor.c
index 5752d74..3518185 100644
--- a/src/editor.c
+++ b/src/editor.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* editor.c                                                 *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// editor.c
+// ============================================================================
 
 #include <math.h>
 
@@ -33,157 +31,234 @@
   -----------------------------------------------------------------------------
 */
 
-/* positions in the level editor */
-#define ED_WIN_MB_LEFT_XPOS		6
-#define ED_WIN_MB_LEFT_YPOS		258
-#define ED_WIN_MB_MIDDLE_XPOS		42
-#define ED_WIN_MB_MIDDLE_YPOS		ED_WIN_MB_LEFT_YPOS
-#define ED_WIN_MB_RIGHT_XPOS		78
-#define ED_WIN_MB_RIGHT_YPOS		ED_WIN_MB_LEFT_YPOS
-
 /* values for the control window */
-#define ED_CTRL_NO_BUTTONS_GFX_XPOS 	6
-#define ED_CTRL_NO_BUTTONS_GFX_YPOS 	286
-#define ED_CTRL1_BUTTONS_GFX_YPOS 	236
-#define ED_CTRL2_BUTTONS_GFX_YPOS 	236
-#define ED_CTRL3_BUTTONS_GFX_YPOS 	324
-#define ED_CTRL4_BUTTONS_GFX_XPOS 	44
-#define ED_CTRL4_BUTTONS_GFX_YPOS 	214
-#define ED_CTRL1_BUTTONS_ALT_GFX_YPOS 	142
-#define ED_CTRL3_BUTTONS_ALT_GFX_YPOS 	302
-
-#define ED_CTRL1_BUTTON_XSIZE		22
-#define ED_CTRL1_BUTTON_YSIZE		22
-#define ED_CTRL1_BUTTONS_XPOS		6
-#define ED_CTRL1_BUTTONS_YPOS		6
-#define ED_CTRL2_BUTTON_XSIZE		30
-#define ED_CTRL2_BUTTON_YSIZE		20
-#define ED_CTRL2_BUTTONS_XPOS		5
-#define ED_CTRL2_BUTTONS_YPOS		99
-#define ED_CTRL3_BUTTON_XSIZE		22
-#define ED_CTRL3_BUTTON_YSIZE		22
-#define ED_CTRL3_BUTTONS_XPOS		6
-#define ED_CTRL3_BUTTONS_YPOS		6
-#define ED_CTRL4_BUTTON_XSIZE		22
-#define ED_CTRL4_BUTTON_YSIZE		22
-#define ED_CTRL4_BUTTONS_XPOS		6
-#define ED_CTRL4_BUTTONS_YPOS		6
-
-#define ED_CTRL1_BUTTONS_HORIZ		4
+#define ED_CTRL1_BUTTONS_HORIZ		4	/* toolbox */
 #define ED_CTRL1_BUTTONS_VERT		4
-#define ED_CTRL2_BUTTONS_HORIZ		3
+#define ED_CTRL2_BUTTONS_HORIZ		3	/* level */
 #define ED_CTRL2_BUTTONS_VERT		2
-#define ED_CTRL3_BUTTONS_HORIZ		3
+#define ED_CTRL3_BUTTONS_HORIZ		3	/* CE and GE */
 #define ED_CTRL3_BUTTONS_VERT		1
-#define ED_CTRL4_BUTTONS_HORIZ		2
+#define ED_CTRL4_BUTTONS_HORIZ		2	/* CE and GE */
 #define ED_CTRL4_BUTTONS_VERT		1
+#define ED_CTRL5_BUTTONS_HORIZ		1	/* properties */
+#define ED_CTRL5_BUTTONS_VERT		1
+#define ED_CTRL6_BUTTONS_HORIZ		3	/* properties */
+#define ED_CTRL6_BUTTONS_VERT		1
+#define ED_CTRL7_BUTTONS_HORIZ		1	/* palette */
+#define ED_CTRL7_BUTTONS_VERT		1
 
 #define ED_NUM_CTRL1_BUTTONS   (ED_CTRL1_BUTTONS_HORIZ * ED_CTRL1_BUTTONS_VERT)
 #define ED_NUM_CTRL2_BUTTONS   (ED_CTRL2_BUTTONS_HORIZ * ED_CTRL2_BUTTONS_VERT)
 #define ED_NUM_CTRL3_BUTTONS   (ED_CTRL3_BUTTONS_HORIZ * ED_CTRL3_BUTTONS_VERT)
 #define ED_NUM_CTRL4_BUTTONS   (ED_CTRL4_BUTTONS_HORIZ * ED_CTRL4_BUTTONS_VERT)
+#define ED_NUM_CTRL5_BUTTONS   (ED_CTRL5_BUTTONS_HORIZ * ED_CTRL5_BUTTONS_VERT)
+#define ED_NUM_CTRL6_BUTTONS   (ED_CTRL6_BUTTONS_HORIZ * ED_CTRL6_BUTTONS_VERT)
+#define ED_NUM_CTRL7_BUTTONS   (ED_CTRL7_BUTTONS_HORIZ * ED_CTRL7_BUTTONS_VERT)
 #define ED_NUM_CTRL1_2_BUTTONS (ED_NUM_CTRL1_BUTTONS   + ED_NUM_CTRL2_BUTTONS)
 #define ED_NUM_CTRL1_3_BUTTONS (ED_NUM_CTRL1_2_BUTTONS + ED_NUM_CTRL3_BUTTONS)
-#define ED_NUM_CTRL_BUTTONS    (ED_NUM_CTRL1_BUTTONS +	\
-				ED_NUM_CTRL2_BUTTONS +	\
-				ED_NUM_CTRL3_BUTTONS +	\
-				ED_NUM_CTRL4_BUTTONS)
+#define ED_NUM_CTRL1_4_BUTTONS (ED_NUM_CTRL1_3_BUTTONS + ED_NUM_CTRL4_BUTTONS)
+#define ED_NUM_CTRL1_5_BUTTONS (ED_NUM_CTRL1_4_BUTTONS + ED_NUM_CTRL5_BUTTONS)
+#define ED_NUM_CTRL1_6_BUTTONS (ED_NUM_CTRL1_5_BUTTONS + ED_NUM_CTRL6_BUTTONS)
+#define ED_NUM_CTRL1_7_BUTTONS (ED_NUM_CTRL1_6_BUTTONS + ED_NUM_CTRL7_BUTTONS)
+#define ED_NUM_CTRL_BUTTONS    ED_NUM_CTRL1_7_BUTTONS
 
 /* values for the element list */
-#define ED_ELEMENTLIST_XPOS		5
-#define ED_ELEMENTLIST_YPOS		30
-#define ED_ELEMENTLIST_XSIZE		20
-#define ED_ELEMENTLIST_YSIZE		20
-#define ED_ELEMENTLIST_BUTTONS_HORIZ	4
-#define ED_ELEMENTLIST_BUTTONS_VERT	11
+#define ED_ELEMENTLIST_XPOS		(editor.palette.x)
+#define ED_ELEMENTLIST_YPOS		(editor.palette.y)
+#define ED_ELEMENTLIST_XSIZE		(graphic_info[IMG_EDITOR_PALETTE_BUTTON].width)
+#define ED_ELEMENTLIST_YSIZE		(graphic_info[IMG_EDITOR_PALETTE_BUTTON].height)
+#define ED_ELEMENTLIST_BUTTONS_HORIZ	(editor.palette.cols)
+#define ED_ELEMENTLIST_BUTTONS_VERT	(editor.palette.rows)
 #define ED_NUM_ELEMENTLIST_BUTTONS	(ED_ELEMENTLIST_BUTTONS_HORIZ *	\
 					 ED_ELEMENTLIST_BUTTONS_VERT)
 
 /* standard distances */
-#define ED_BORDER_SIZE			3
-#define ED_BORDER_TEXT_XSIZE		5
-#define ED_BORDER_AREA_YSIZE		1
-
-#define ED_GADGET_DISTANCE		2
-#define ED_GADGET_TEXT_DISTANCE		(2 * ED_GADGET_DISTANCE)
+#define ED_GADGET_NORMAL_DISTANCE	(editor.gadget.normal_spacing)
+#define ED_GADGET_SMALL_DISTANCE	(editor.gadget.small_spacing)
+#define ED_GADGET_TINY_DISTANCE		(editor.gadget.tiny_spacing)
+#define ED_GADGET_LINE_DISTANCE		(editor.gadget.line_spacing)
+#define ED_GADGET_TEXT_DISTANCE		(editor.gadget.text_spacing)
+#define ED_TAB_BAR_HEIGHT		(editor.gadget.separator_line.height)
 #define ED_DRAWINGAREA_TEXT_DISTANCE	(ED_GADGET_TEXT_DISTANCE +	\
-					 MINI_TILEX / 2)
-
-/* values for the settings windows */
-#define ED_LEVEL_SETTINGS_XSTART	(3 * MINI_TILEX / 2)
-#define ED_LEVEL_SETTINGS_YSTART	(7 * MINI_TILEY)
-
-#define ED_ELEMENT_SETTINGS_XSTART	(3 * MINI_TILEX / 2)
-#define ED_ELEMENT_SETTINGS_YSTART	(10 * MINI_TILEY)
+					 ED_DRAWINGAREA_BORDER_SIZE)
+#define ED_GADGET_SPACE_DISTANCE	(getFontWidth(FONT_TEXT_1))
 
-#define ED_XOFFSET_CHECKBOX		(ED_CHECKBUTTON_XSIZE +		\
-					 2 * ED_GADGET_DISTANCE)
+/* values for drawingarea gadgets */
+#define IMG_BORDER_1			IMG_EDITOR_ELEMENT_BORDER
+#define IMG_BORDER_2			IMG_EDITOR_ELEMENT_BORDER_INPUT
+#define ED_ELEMENT_BORDER		(graphic_info[IMG_BORDER_1].border_size)
+#define ED_DRAWINGAREA_BORDER_SIZE	(graphic_info[IMG_BORDER_2].border_size)
+#define ED_DRAWINGAREA_TILE_SIZE	(editor.drawingarea.tile_size)
 
-#define ED_SETTINGS_XOFFSET		ED_XOFFSET_CHECKBOX
-#define ED_SETTINGS_YOFFSET		(3 * MINI_TILEY / 2)
-#define ED_SETTINGS_TAB_XOFFSET		124
-
-#define ED_LEVEL_SETTINGS_XPOS(n)	(ED_LEVEL_SETTINGS_XSTART +	\
-	 				 (n) * ED_SETTINGS_XOFFSET)
-#define ED_LEVEL_SETTINGS_YPOS(n)	(ED_LEVEL_SETTINGS_YSTART +	\
+/* values for checkbutton gadgets */
+#define ED_CHECKBUTTON_XSIZE	     (graphic_info[IMG_EDITOR_CHECKBOX].width)
+#define ED_CHECKBUTTON_YSIZE	     (graphic_info[IMG_EDITOR_CHECKBOX].height)
+
+#define ED_TABBUTTON_XSIZE	     (graphic_info[IMG_EDITOR_TABBUTTON].width)
+#define ED_TABBUTTON_YSIZE	     (graphic_info[IMG_EDITOR_TABBUTTON].height)
+
+#define ED_LEVEL_SETTINGS_TABS_X	(editor.settings.tabs.x)
+#define ED_LEVEL_SETTINGS_TABS_Y	(editor.settings.tabs.y)
+#define ED_ELEMENT_SETTINGS_TABS_X	(editor.settings.tabs.x)
+#define ED_ELEMENT_SETTINGS_TABS_Y	(editor.settings.tabs.y +	\
+					 editor.settings.tabs.yoffset2)
+
+#define ED_SETTINGS_TABS_XOFFSET	(editor.settings.tabs.draw_xoffset)
+#define ED_SETTINGS_TABS_YOFFSET	(editor.settings.tabs.draw_yoffset)
+
+#define ED_LEVEL_SETTINGS_XSTART	(ED_LEVEL_SETTINGS_TABS_X +	\
+					 ED_SETTINGS_TABS_XOFFSET)
+#define ED_LEVEL_SETTINGS_YSTART	(ED_LEVEL_SETTINGS_TABS_Y +	\
+					 ED_TABBUTTON_YSIZE +		\
+					 ED_GADGET_TINY_DISTANCE +	\
+					 ED_TAB_BAR_HEIGHT +		\
+					 ED_SETTINGS_TABS_YOFFSET +	\
+					 getFontHeight(FONT_TEXT_1) +	\
+					 ED_GADGET_TEXT_DISTANCE)
+#define ED_ELEMENT_SETTINGS_XSTART	(ED_ELEMENT_SETTINGS_TABS_X +	\
+					 ED_SETTINGS_TABS_XOFFSET)
+#define ED_ELEMENT_SETTINGS_YSTART	(ED_ELEMENT_SETTINGS_TABS_Y +	\
+					 ED_TABBUTTON_YSIZE +		\
+					 ED_GADGET_TINY_DISTANCE +	\
+					 ED_TAB_BAR_HEIGHT +		\
+					 ED_SETTINGS_TABS_YOFFSET)
+
+#define ED_SETTINGS_XOFFSET		(ED_CHECKBUTTON_XSIZE +		\
+					 ED_GADGET_TEXT_DISTANCE)
+#define ED_SETTINGS_YOFFSET		(ED_CHECKBUTTON_YSIZE +		\
+					 ED_GADGET_LINE_DISTANCE)
+
+#define ED_POS_LEVEL_SETTINGS_RANGE	(10000)
+#define ED_POS_LEVEL_SETTINGS_FIRST	(1 * ED_POS_LEVEL_SETTINGS_RANGE)
+#define ED_POS_LEVEL_SETTINGS_LAST	(2 * ED_POS_LEVEL_SETTINGS_RANGE - 1)
+#define ED_POS_ELEMENT_SETTINGS_FIRST	(2 * ED_POS_LEVEL_SETTINGS_RANGE)
+#define ED_POS_ELEMENT_SETTINGS_LAST	(3 * ED_POS_LEVEL_SETTINGS_RANGE - 1)
+
+#define ED_LEVEL_SETTINGS_XPOS(n)	(ED_POS_LEVEL_SETTINGS_FIRST + (n))
+#define ED_LEVEL_SETTINGS_YPOS(n)	(ED_POS_LEVEL_SETTINGS_FIRST + (n))
+
+#define ED_ELEMENT_SETTINGS_XPOS(n)	(ED_POS_ELEMENT_SETTINGS_FIRST + (n))
+#define ED_ELEMENT_SETTINGS_YPOS(n)	(ED_POS_ELEMENT_SETTINGS_FIRST + (n))
+
+#define IS_POS_LEVEL_SETTINGS(n)      ((n) >= ED_POS_LEVEL_SETTINGS_FIRST && \
+				       (n) <= ED_POS_LEVEL_SETTINGS_LAST)
+#define IS_POS_ELEMENT_SETTINGS(n)    ((n) >= ED_POS_ELEMENT_SETTINGS_FIRST && \
+				       (n) <= ED_POS_ELEMENT_SETTINGS_LAST)
+
+#define ED_LEVEL_SETTINGS_LINE(n)	((n) - ED_POS_LEVEL_SETTINGS_FIRST)
+#define ED_ELEMENT_SETTINGS_LINE(n)	((n) - ED_POS_ELEMENT_SETTINGS_FIRST)
+
+#define ED_LEVEL_SETTINGS_X(n)		(ED_LEVEL_SETTINGS_XSTART +	\
+					 (n) * ED_SETTINGS_XOFFSET)
+#define ED_LEVEL_SETTINGS_Y(n)		(ED_LEVEL_SETTINGS_YSTART +	\
 					 (n) * ED_SETTINGS_YOFFSET)
 
-#define ED_ELEMENT_SETTINGS_XPOS(n)	(ED_ELEMENT_SETTINGS_XSTART +	\
-	 				 (n) * ED_SETTINGS_XOFFSET)
-#define ED_ELEMENT_SETTINGS_YPOS(n)	(ED_ELEMENT_SETTINGS_YSTART +	\
+#define ED_ELEMENT_SETTINGS_X(n)	(ED_ELEMENT_SETTINGS_XSTART +	\
+					 (n) * ED_SETTINGS_XOFFSET)
+#define ED_ELEMENT_SETTINGS_Y(n)	(ED_ELEMENT_SETTINGS_YSTART +	\
 					 (n) * ED_SETTINGS_YOFFSET)
 
-#define ED_LEVEL_SETTINGS_TABS_XPOS(n)	(ED_LEVEL_SETTINGS_XPOS(0) +	\
-	 				(n) * ED_SETTINGS_TAB_XOFFSET)
-#define ED_LEVEL_SETTINGS_TABS_YPOS(n)	(ED_LEVEL_SETTINGS_YSTART -	\
-					 3 * MINI_TILEY)
+#define ED_POS_TO_LEVEL_SETTINGS_X(n)	\
+  (ED_LEVEL_SETTINGS_X(ED_LEVEL_SETTINGS_LINE(n)))
+#define ED_POS_TO_LEVEL_SETTINGS_Y(n)	\
+  (ED_LEVEL_SETTINGS_Y(ED_LEVEL_SETTINGS_LINE(n)))
+
+#define ED_POS_TO_ELEMENT_SETTINGS_X(n)	\
+  (ED_ELEMENT_SETTINGS_X(ED_ELEMENT_SETTINGS_LINE(n)))
+#define ED_POS_TO_ELEMENT_SETTINGS_Y(n)	\
+  (ED_ELEMENT_SETTINGS_Y(ED_ELEMENT_SETTINGS_LINE(n)))
+
+#define ED_SETTINGS_X(n)		(IS_POS_LEVEL_SETTINGS(n) ?	\
+					 ED_POS_TO_LEVEL_SETTINGS_X(n) : \
+					 IS_POS_ELEMENT_SETTINGS(n) ?	\
+					 ED_POS_TO_ELEMENT_SETTINGS_X(n) : (n))
+#define ED_SETTINGS_Y(n)		(IS_POS_LEVEL_SETTINGS(n) ?	\
+					 ED_POS_TO_LEVEL_SETTINGS_Y(n) : \
+					 IS_POS_ELEMENT_SETTINGS(n) ?	\
+					 ED_POS_TO_ELEMENT_SETTINGS_Y(n) : (n))
+
+#define ED_TAB_SETTINGS_X(n)		(IS_POS_LEVEL_SETTINGS(n) ?	\
+					 ED_LEVEL_SETTINGS_TABS_X :	\
+					 ED_ELEMENT_SETTINGS_TABS_X)
+#define ED_TAB_SETTINGS_Y(n)		(IS_POS_LEVEL_SETTINGS(n) ?	\
+					 ED_LEVEL_SETTINGS_TABS_Y :	\
+					 ED_ELEMENT_SETTINGS_TABS_Y)
+
+#define ED_SETTINGS_XOFF(n)		(5 * ((n) % 4) *		\
+					 ED_DRAWINGAREA_TILE_SIZE)
+#define ED_SETTINGS_YOFF(n)		(5 * ((n) / 4) *		\
+					 ED_DRAWINGAREA_TILE_SIZE)
+
+#define ED_AREA_XOFFSET_1(n)		((n) != 0 ?			\
+					 ED_DRAWINGAREA_BORDER_SIZE : 0)
+#define ED_AREA_YOFFSET_1(n)		((n) != 0 ?			\
+					 (ED_CHECKBUTTON_YSIZE -	\
+					  ED_DRAWINGAREA_TILE_SIZE) / 2 : 0)
+
+#define ED_AREA_XOFFSET_2(n)	  (0)
+#define ED_AREA_YOFFSET_2(n)	  ((n) == 3 ?			\
+				   ((n) - 1) * ED_DRAWINGAREA_TILE_SIZE / 2 : 0)
+
+#define ED_AREA_SETTINGS_X(i)	   (ED_SETTINGS_X((i).x) +		\
+				    ED_SETTINGS_XOFF((i).xoffset) +	\
+				    ED_AREA_XOFFSET_1((i).x) -		\
+				    ED_AREA_XOFFSET_2((i).area_xsize))
+#define ED_AREA_SETTINGS_Y(i)	   (ED_SETTINGS_Y((i).y) +		\
+				    ED_SETTINGS_YOFF((i).yoffset) +	\
+				    ED_AREA_YOFFSET_1((i).y) -		\
+				    ED_AREA_YOFFSET_2((i).area_ysize))
 
-#define ED_ELEMENT_SETTINGS_TABS_XPOS(n) (ED_ELEMENT_SETTINGS_XPOS(0) +	\
-	 				 (n) * ED_SETTINGS_TAB_XOFFSET)
-#define ED_ELEMENT_SETTINGS_TABS_YPOS(n) (ED_ELEMENT_SETTINGS_YSTART -	\
-					 2 * MINI_TILEY)
-
-#define ED_SETTINGS1_YPOS		MINI_TILEY
-#define ED_SETTINGS2_XPOS		MINI_TILEX
-#define ED_SETTINGS2_YPOS		(ED_SETTINGS1_YPOS + 12 * TILEY - 2)
+/* values for element content drawing areas */
+#define ED_AREA_1X1_LSETTINGS_XPOS(n)	ED_LEVEL_SETTINGS_XPOS(n)
+#define ED_AREA_1X1_LSETTINGS_YPOS(n)	ED_LEVEL_SETTINGS_YPOS(n)
+#define ED_AREA_1X1_LSETTINGS_XOFF	(0)
+#define ED_AREA_1X1_LSETTINGS_YOFF	(0)
 
-/* values for counter gadgets */
-#define ED_COUNTER_YSTART		(ED_SETTINGS1_YPOS + 2 * TILEY)
-#define ED_COUNTER_YDISTANCE		(3 * MINI_TILEY)
-#define ED_COUNTER_YPOS(n)		(ED_COUNTER_YSTART +		\
-					 (n) * ED_COUNTER_YDISTANCE)
-#define ED_COUNTER2_YPOS(n)		(ED_COUNTER_YSTART +		\
-					 (n) * ED_COUNTER_YDISTANCE - 2)
+#define ED_AREA_1X1_SETTINGS_XPOS(n)	ED_ELEMENT_SETTINGS_XPOS(n)
+#define ED_AREA_1X1_SETTINGS_YPOS(n)	ED_ELEMENT_SETTINGS_YPOS(n)
+#define ED_AREA_1X1_SETTINGS_XOFF	(0)
+#define ED_AREA_1X1_SETTINGS_YOFF	(0)
 
-/* values for element content drawing areas */
-#define ED_AREA_1X1_SETTINGS_XPOS(n)	(ED_ELEMENT_SETTINGS_XPOS(n))
-#define ED_AREA_1X1_SETTINGS_YPOS(n)	(ED_ELEMENT_SETTINGS_YPOS(n) +	\
-					 ED_GADGET_DISTANCE)
+#define ED_AREA_3X3_SETTINGS_XPOS(n)	ED_ELEMENT_SETTINGS_XPOS(n)
+#define ED_AREA_3X3_SETTINGS_YPOS(n)	ED_ELEMENT_SETTINGS_YPOS(n)
+#define ED_AREA_3X3_SETTINGS_XOFF	(0)
+#define ED_AREA_3X3_SETTINGS_YOFF	(0)
 
-#define ED_AREA_3X3_SETTINGS_XPOS(n)	(ED_ELEMENT_SETTINGS_XPOS(n))
-#define ED_AREA_3X3_SETTINGS_YPOS(n)	(ED_ELEMENT_SETTINGS_YPOS(n) +	\
-					 ED_GADGET_DISTANCE - MINI_TILEY)
+/* element content */
+#define ED_AREA_ELEMENT_CONTENT_XOFF(n)	(n)
+#define ED_AREA_ELEMENT_CONTENT_YOFF(n)	(n)
 
 /* yamyam content */
-#define ED_AREA_YAMYAM_CONTENT_XPOS(n)	(2 * MINI_TILEX +		\
-					 5 * ((n) % 4) * MINI_TILEX)
-#define ED_AREA_YAMYAM_CONTENT_YPOS(n)	(11 * ED_SETTINGS_YOFFSET +	\
-					 6 * ((n) / 4) * MINI_TILEY)
+#define ED_XPOS_YAM			0
+#define ED_YPOS_YAM			5
+#define ED_AREA_YAMYAM_CONTENT_XPOS	ED_ELEMENT_SETTINGS_XPOS(ED_XPOS_YAM)
+#define ED_AREA_YAMYAM_CONTENT_YPOS	ED_ELEMENT_SETTINGS_YPOS(ED_YPOS_YAM)
+#define ED_AREA_YAMYAM_CONTENT_XOFF(n)	ED_AREA_ELEMENT_CONTENT_XOFF(n)
+#define ED_AREA_YAMYAM_CONTENT_YOFF(n)	ED_AREA_ELEMENT_CONTENT_YOFF(n)
+#define ED_AREA_YAMYAM_CONTENT_X(n)	(ED_ELEMENT_SETTINGS_X(ED_XPOS_YAM) + \
+					 ED_SETTINGS_XOFF(n))
+#define ED_AREA_YAMYAM_CONTENT_Y(n)	(ED_ELEMENT_SETTINGS_Y(ED_YPOS_YAM) + \
+					 ED_SETTINGS_YOFF(n) +		\
+					 ED_AREA_YOFFSET_1(ED_YPOS_YAM) - \
+					 ED_AREA_YOFFSET_2(3))
 
 /* magic ball content */
-#define ED_AREA_MAGIC_BALL_CONTENT_XPOS(n) (2 * MINI_TILEX +		\
-					    5 * ((n) % 4) * MINI_TILEX)
-#define ED_AREA_MAGIC_BALL_CONTENT_YPOS(n) (12 * ED_SETTINGS_YOFFSET +	\
-					    6 * ((n) / 4) * MINI_TILEY)
+#define ED_XPOS_BALL			0
+#define ED_YPOS_BALL			6
+#define ED_AREA_MAGIC_BALL_CONTENT_XPOS	ED_ELEMENT_SETTINGS_XPOS(ED_XPOS_BALL)
+#define ED_AREA_MAGIC_BALL_CONTENT_YPOS	ED_ELEMENT_SETTINGS_YPOS(ED_YPOS_BALL)
+#define ED_AREA_MAGIC_BALL_CONTENT_XOFF(n) ED_AREA_ELEMENT_CONTENT_XOFF(n)
+#define ED_AREA_MAGIC_BALL_CONTENT_YOFF(n) ED_AREA_ELEMENT_CONTENT_YOFF(n)
+#define ED_AREA_MAGIC_BALL_CONTENT_X(n)	(ED_ELEMENT_SETTINGS_X(ED_XPOS_BALL) + \
+					 ED_SETTINGS_XOFF(n))
+#define ED_AREA_MAGIC_BALL_CONTENT_Y(n)	(ED_ELEMENT_SETTINGS_Y(ED_YPOS_BALL) + \
+					 ED_SETTINGS_YOFF(n) +		\
+					 ED_AREA_YOFFSET_1(ED_YPOS_BALL) - \
+					 ED_AREA_YOFFSET_2(3))
 
 /* values for scrolling gadgets for drawing area */
-#define ED_SCROLLBUTTON_XPOS		24
-#define ED_SCROLLBUTTON_YPOS		0
-#define ED_SCROLLBAR_XPOS		24
-#define ED_SCROLLBAR_YPOS		64
-
-#define ED_SCROLLBUTTON_XSIZE		16
-#define ED_SCROLLBUTTON_YSIZE		16
+#define ED_SCROLLBUTTON_XSIZE		(graphic_info[IMG_EDITOR_PLAYFIELD_SCROLLBAR].width)
+#define ED_SCROLLBUTTON_YSIZE		(graphic_info[IMG_EDITOR_PLAYFIELD_SCROLLBAR].height)
 
 #define ED_SCROLL_UP_XPOS		(SXSIZE - ED_SCROLLBUTTON_XSIZE)
 #define ED_SCROLL_UP_YPOS		(0)
@@ -205,16 +280,13 @@
 #define ED_SCROLL_VERTICAL_YSIZE	(SYSIZE - 4 * ED_SCROLLBUTTON_YSIZE)
 
 /* values for scrolling gadgets for element list */
-#define ED_SCROLLBUTTON2_XPOS		50
-#define ED_SCROLLBUTTON2_YPOS		0
-#define ED_SCROLLBAR2_XPOS		50
-#define ED_SCROLLBAR2_YPOS		20
-
-#define ED_SCROLLBUTTON2_XSIZE		10
-#define ED_SCROLLBUTTON2_YSIZE		10
+#define ED_SCROLLBUTTON2_XSIZE		(graphic_info[IMG_EDITOR_PALETTE_SCROLL_UP].width)
+#define ED_SCROLLBUTTON2_YSIZE		(graphic_info[IMG_EDITOR_PALETTE_SCROLL_UP].height)
 
-#define ED_SCROLL2_UP_XPOS		85
-#define ED_SCROLL2_UP_YPOS		30
+#define ED_SCROLL2_UP_XPOS		(ED_ELEMENTLIST_XPOS +		\
+					 ED_ELEMENTLIST_BUTTONS_HORIZ *	\
+					 ED_ELEMENTLIST_XSIZE)
+#define ED_SCROLL2_UP_YPOS		ED_ELEMENTLIST_YPOS
 #define ED_SCROLL2_DOWN_XPOS		ED_SCROLL2_UP_XPOS
 #define ED_SCROLL2_DOWN_YPOS		(ED_SCROLL2_UP_YPOS +		\
 					 ED_ELEMENTLIST_BUTTONS_VERT *	\
@@ -228,71 +300,13 @@
 					 ED_ELEMENTLIST_YSIZE -		\
 					 2 * ED_SCROLLBUTTON2_YSIZE)
 
-/* values for checkbutton gadgets */
-#define ED_CHECKBUTTON_XSIZE		ED_BUTTON_COUNT_XSIZE
-#define ED_CHECKBUTTON_YSIZE		ED_BUTTON_COUNT_YSIZE
-#define ED_CHECKBUTTON_UNCHECKED_XPOS	ED_BUTTON_MINUS_XPOS
-#define ED_CHECKBUTTON_CHECKED_XPOS	ED_BUTTON_PLUS_XPOS
-#define ED_CHECKBUTTON_YPOS		(ED_BUTTON_MINUS_YPOS + 22)
-#define ED_RADIOBUTTON_YPOS		(ED_BUTTON_MINUS_YPOS + 44)
-#define ED_STICKYBUTTON_YPOS		(ED_BUTTON_MINUS_YPOS + 66)
-
-/* values for some special graphic buttons */
-#define ED_COPY_CHANGE_PAGE_XPOS	25
-#define ED_COPY_CHANGE_PAGE_YPOS	50
-#define ED_PASTE_CHANGE_PAGE_XPOS	25
-#define ED_PASTE_CHANGE_PAGE_YPOS	70
-
-/* some values for text input, selectbox and counter gadgets */
-#define ED_BUTTON_COUNT_YPOS		60
-#define ED_BUTTON_COUNT_XSIZE		20
-#define ED_BUTTON_COUNT_YSIZE		20
-#define ED_WIN_COUNT_XPOS		(2 + ED_BUTTON_COUNT_XSIZE + 2)
-#define ED_WIN_COUNT_YPOS		ED_BUTTON_COUNT_YPOS
-#define ED_WIN_COUNT_XSIZE		52
-#define ED_WIN_COUNT_YSIZE		ED_BUTTON_COUNT_YSIZE
-#define ED_WIN_COUNT2_XPOS		27
-#define ED_WIN_COUNT2_YPOS		3
-#define ED_WIN_COUNT2_XSIZE		46
-#define ED_WIN_COUNT2_YSIZE		ED_BUTTON_COUNT_YSIZE
-
-#define ED_BUTTON_MINUS_XPOS		2
-#define ED_BUTTON_MINUS_YPOS		ED_BUTTON_COUNT_YPOS
-#define ED_BUTTON_MINUS_XSIZE		ED_BUTTON_COUNT_XSIZE
-#define ED_BUTTON_MINUS_YSIZE		ED_BUTTON_COUNT_YSIZE
-#define ED_BUTTON_PLUS_XPOS		(ED_WIN_COUNT_XPOS +		\
-	 				 ED_WIN_COUNT_XSIZE + 2)
-#define ED_BUTTON_PLUS_YPOS		ED_BUTTON_COUNT_YPOS
-#define ED_BUTTON_PLUS_XSIZE		ED_BUTTON_COUNT_XSIZE
-#define ED_BUTTON_PLUS_YSIZE		ED_BUTTON_COUNT_YSIZE
-
-#define ED_SELECTBOX_XPOS		ED_WIN_COUNT_XPOS
-#define ED_SELECTBOX_YPOS		(ED_WIN_COUNT_YPOS +		\
-					 2 + ED_WIN_COUNT_YSIZE)
-#define ED_SELECTBOX_XSIZE		ED_WIN_COUNT_XSIZE
-#define ED_SELECTBOX_YSIZE		ED_WIN_COUNT_YSIZE
-
-#define ED_SELECTBOX_BUTTON_XSIZE	14
-
-#define ED_TEXTBUTTON_XPOS		ED_WIN_COUNT_XPOS
-#define ED_TEXTBUTTON_YPOS		(ED_WIN_COUNT_YPOS +		\
-					 4 * (2 + ED_WIN_COUNT_YSIZE))
-#define ED_TEXTBUTTON_INACTIVE_YPOS	ED_TEXTBUTTON_YPOS
-
-#define ED_TEXTBUTTON_TAB_XPOS		ED_WIN_COUNT_XPOS
-#define ED_TEXTBUTTON_TAB_YPOS		(ED_WIN_COUNT_YPOS +		\
-					 2 * (2 + ED_WIN_COUNT_YSIZE))
-#define ED_TEXTBUTTON_TAB_INACTIVE_YPOS	(ED_WIN_COUNT_YPOS +		\
-					 3 * (2 + ED_WIN_COUNT_YSIZE))
-
-#define ED_TEXTBUTTON_XSIZE		ED_WIN_COUNT_XSIZE
-#define ED_TEXTBUTTON_YSIZE		ED_WIN_COUNT_YSIZE
-
 /* values for ClearEditorGadgetInfoText() and HandleEditorGadgetInfoText() */
-#define INFOTEXT_XPOS			SX
-#define INFOTEXT_YPOS			(SY + SYSIZE - MINI_TILEX + 2)
-#define INFOTEXT_XSIZE			SXSIZE
-#define INFOTEXT_YSIZE			MINI_TILEX
+#define INFOTEXT_FONT		FONT_TEXT_2
+#define INFOTEXT_XSIZE		SXSIZE
+#define INFOTEXT_YSIZE		getFontHeight(INFOTEXT_FONT)
+#define INFOTEXT_YSIZE_FULL	(INFOTEXT_YSIZE + ED_GADGET_SMALL_DISTANCE)
+#define INFOTEXT_XPOS		SX
+#define INFOTEXT_YPOS		(SY + SYSIZE - INFOTEXT_YSIZE)
 
 
 /*
@@ -315,7 +329,7 @@
 #define GADGET_ID_TEXT			(GADGET_ID_TOOLBOX_FIRST + 7)
 #define GADGET_ID_FLOOD_FILL		(GADGET_ID_TOOLBOX_FIRST + 8)
 #define GADGET_ID_WRAP_LEFT		(GADGET_ID_TOOLBOX_FIRST + 9)
-#define GADGET_ID_PROPERTIES		(GADGET_ID_TOOLBOX_FIRST + 10)
+#define GADGET_ID_ZOOM			(GADGET_ID_TOOLBOX_FIRST + 10)
 #define GADGET_ID_WRAP_RIGHT		(GADGET_ID_TOOLBOX_FIRST + 11)
 #define GADGET_ID_RANDOM_PLACEMENT	(GADGET_ID_TOOLBOX_FIRST + 12)
 #define GADGET_ID_GRAB_BRUSH		(GADGET_ID_TOOLBOX_FIRST + 13)
@@ -335,8 +349,14 @@
 #define GADGET_ID_CUSTOM_COPY		(GADGET_ID_TOOLBOX_FIRST + 25)
 #define GADGET_ID_CUSTOM_PASTE		(GADGET_ID_TOOLBOX_FIRST + 26)
 
+#define GADGET_ID_PROPERTIES		(GADGET_ID_TOOLBOX_FIRST + 27)
+#define GADGET_ID_ELEMENT_LEFT		(GADGET_ID_TOOLBOX_FIRST + 28)
+#define GADGET_ID_ELEMENT_MIDDLE	(GADGET_ID_TOOLBOX_FIRST + 29)
+#define GADGET_ID_ELEMENT_RIGHT		(GADGET_ID_TOOLBOX_FIRST + 30)
+#define GADGET_ID_PALETTE		(GADGET_ID_TOOLBOX_FIRST + 31)
+
 /* counter gadget identifiers */
-#define GADGET_ID_COUNTER_FIRST		(GADGET_ID_TOOLBOX_FIRST + 27)
+#define GADGET_ID_COUNTER_FIRST		(GADGET_ID_TOOLBOX_FIRST + 32)
 
 #define GADGET_ID_SELECT_LEVEL_DOWN	(GADGET_ID_COUNTER_FIRST + 0)
 #define GADGET_ID_SELECT_LEVEL_TEXT	(GADGET_ID_COUNTER_FIRST + 1)
@@ -583,45 +603,46 @@
 #define GADGET_ID_SP_BLOCK_LAST_FIELD	(GADGET_ID_CHECKBUTTON_FIRST + 15)
 #define GADGET_ID_INSTANT_RELOCATION	(GADGET_ID_CHECKBUTTON_FIRST + 16)
 #define GADGET_ID_SHIFTED_RELOCATION	(GADGET_ID_CHECKBUTTON_FIRST + 17)
-#define GADGET_ID_USE_START_ELEMENT	(GADGET_ID_CHECKBUTTON_FIRST + 18)
-#define GADGET_ID_USE_ARTWORK_ELEMENT	(GADGET_ID_CHECKBUTTON_FIRST + 19)
-#define GADGET_ID_USE_EXPLOSION_ELEMENT	(GADGET_ID_CHECKBUTTON_FIRST + 20)
-#define GADGET_ID_INITIAL_GRAVITY	(GADGET_ID_CHECKBUTTON_FIRST + 21)
-#define GADGET_ID_USE_INITIAL_INVENTORY	(GADGET_ID_CHECKBUTTON_FIRST + 22)
-#define GADGET_ID_CAN_PASS_TO_WALKABLE	(GADGET_ID_CHECKBUTTON_FIRST + 23)
-#define GADGET_ID_CAN_FALL_INTO_ACID	(GADGET_ID_CHECKBUTTON_FIRST + 24)
-#define GADGET_ID_CAN_MOVE_INTO_ACID	(GADGET_ID_CHECKBUTTON_FIRST + 25)
-#define GADGET_ID_DONT_COLLIDE_WITH	(GADGET_ID_CHECKBUTTON_FIRST + 26)
-#define GADGET_ID_ENVELOPE_AUTOWRAP	(GADGET_ID_CHECKBUTTON_FIRST + 27)
-#define GADGET_ID_ENVELOPE_CENTERED	(GADGET_ID_CHECKBUTTON_FIRST + 28)
-#define GADGET_ID_CUSTOM_INDESTRUCTIBLE	(GADGET_ID_CHECKBUTTON_FIRST + 29)
-#define GADGET_ID_CUSTOM_CAN_EXPLODE	(GADGET_ID_CHECKBUTTON_FIRST + 30)
-#define GADGET_ID_CUSTOM_EXPLODE_FIRE	(GADGET_ID_CHECKBUTTON_FIRST + 31)
-#define GADGET_ID_CUSTOM_EXPLODE_SMASH	(GADGET_ID_CHECKBUTTON_FIRST + 32)
-#define GADGET_ID_CUSTOM_EXPLODE_IMPACT	(GADGET_ID_CHECKBUTTON_FIRST + 33)
-#define GADGET_ID_CUSTOM_WALK_TO_OBJECT	(GADGET_ID_CHECKBUTTON_FIRST + 34)
-#define GADGET_ID_CUSTOM_DEADLY		(GADGET_ID_CHECKBUTTON_FIRST + 35)
-#define GADGET_ID_CUSTOM_CAN_MOVE	(GADGET_ID_CHECKBUTTON_FIRST + 36)
-#define GADGET_ID_CUSTOM_CAN_FALL	(GADGET_ID_CHECKBUTTON_FIRST + 37)
-#define GADGET_ID_CUSTOM_CAN_SMASH	(GADGET_ID_CHECKBUTTON_FIRST + 38)
-#define GADGET_ID_CUSTOM_SLIPPERY	(GADGET_ID_CHECKBUTTON_FIRST + 39)
-#define GADGET_ID_CUSTOM_ACCESSIBLE	(GADGET_ID_CHECKBUTTON_FIRST + 40)
-#define GADGET_ID_CUSTOM_GRAV_REACHABLE	(GADGET_ID_CHECKBUTTON_FIRST + 41)
-#define GADGET_ID_CUSTOM_USE_LAST_VALUE	(GADGET_ID_CHECKBUTTON_FIRST + 42)
-#define GADGET_ID_CUSTOM_USE_GRAPHIC	(GADGET_ID_CHECKBUTTON_FIRST + 43)
-#define GADGET_ID_CUSTOM_USE_TEMPLATE	(GADGET_ID_CHECKBUTTON_FIRST + 44)
-#define GADGET_ID_CUSTOM_CAN_CHANGE	(GADGET_ID_CHECKBUTTON_FIRST + 45)
-#define GADGET_ID_CHANGE_USE_CONTENT	(GADGET_ID_CHECKBUTTON_FIRST + 46)
-#define GADGET_ID_CHANGE_USE_EXPLOSION	(GADGET_ID_CHECKBUTTON_FIRST + 47)
-#define GADGET_ID_CHANGE_ONLY_COMPLETE	(GADGET_ID_CHECKBUTTON_FIRST + 48)
-#define GADGET_ID_CHANGE_USE_RANDOM	(GADGET_ID_CHECKBUTTON_FIRST + 49)
-#define GADGET_ID_CHANGE_HAS_ACTION	(GADGET_ID_CHECKBUTTON_FIRST + 50)
-#define GADGET_ID_CHANGE_DELAY		(GADGET_ID_CHECKBUTTON_FIRST + 51)
-#define GADGET_ID_CHANGE_BY_DIRECT_ACT	(GADGET_ID_CHECKBUTTON_FIRST + 52)
-#define GADGET_ID_CHANGE_BY_OTHER_ACT	(GADGET_ID_CHECKBUTTON_FIRST + 53)
+#define GADGET_ID_LAZY_RELOCATION	(GADGET_ID_CHECKBUTTON_FIRST + 18)
+#define GADGET_ID_USE_START_ELEMENT	(GADGET_ID_CHECKBUTTON_FIRST + 19)
+#define GADGET_ID_USE_ARTWORK_ELEMENT	(GADGET_ID_CHECKBUTTON_FIRST + 20)
+#define GADGET_ID_USE_EXPLOSION_ELEMENT	(GADGET_ID_CHECKBUTTON_FIRST + 21)
+#define GADGET_ID_INITIAL_GRAVITY	(GADGET_ID_CHECKBUTTON_FIRST + 22)
+#define GADGET_ID_USE_INITIAL_INVENTORY	(GADGET_ID_CHECKBUTTON_FIRST + 23)
+#define GADGET_ID_CAN_PASS_TO_WALKABLE	(GADGET_ID_CHECKBUTTON_FIRST + 24)
+#define GADGET_ID_CAN_FALL_INTO_ACID	(GADGET_ID_CHECKBUTTON_FIRST + 25)
+#define GADGET_ID_CAN_MOVE_INTO_ACID	(GADGET_ID_CHECKBUTTON_FIRST + 26)
+#define GADGET_ID_DONT_COLLIDE_WITH	(GADGET_ID_CHECKBUTTON_FIRST + 27)
+#define GADGET_ID_ENVELOPE_AUTOWRAP	(GADGET_ID_CHECKBUTTON_FIRST + 28)
+#define GADGET_ID_ENVELOPE_CENTERED	(GADGET_ID_CHECKBUTTON_FIRST + 29)
+#define GADGET_ID_CUSTOM_INDESTRUCTIBLE	(GADGET_ID_CHECKBUTTON_FIRST + 30)
+#define GADGET_ID_CUSTOM_CAN_EXPLODE	(GADGET_ID_CHECKBUTTON_FIRST + 31)
+#define GADGET_ID_CUSTOM_EXPLODE_FIRE	(GADGET_ID_CHECKBUTTON_FIRST + 32)
+#define GADGET_ID_CUSTOM_EXPLODE_SMASH	(GADGET_ID_CHECKBUTTON_FIRST + 33)
+#define GADGET_ID_CUSTOM_EXPLODE_IMPACT	(GADGET_ID_CHECKBUTTON_FIRST + 34)
+#define GADGET_ID_CUSTOM_WALK_TO_OBJECT	(GADGET_ID_CHECKBUTTON_FIRST + 35)
+#define GADGET_ID_CUSTOM_DEADLY		(GADGET_ID_CHECKBUTTON_FIRST + 36)
+#define GADGET_ID_CUSTOM_CAN_MOVE	(GADGET_ID_CHECKBUTTON_FIRST + 37)
+#define GADGET_ID_CUSTOM_CAN_FALL	(GADGET_ID_CHECKBUTTON_FIRST + 38)
+#define GADGET_ID_CUSTOM_CAN_SMASH	(GADGET_ID_CHECKBUTTON_FIRST + 39)
+#define GADGET_ID_CUSTOM_SLIPPERY	(GADGET_ID_CHECKBUTTON_FIRST + 40)
+#define GADGET_ID_CUSTOM_ACCESSIBLE	(GADGET_ID_CHECKBUTTON_FIRST + 41)
+#define GADGET_ID_CUSTOM_GRAV_REACHABLE	(GADGET_ID_CHECKBUTTON_FIRST + 42)
+#define GADGET_ID_CUSTOM_USE_LAST_VALUE	(GADGET_ID_CHECKBUTTON_FIRST + 43)
+#define GADGET_ID_CUSTOM_USE_GRAPHIC	(GADGET_ID_CHECKBUTTON_FIRST + 44)
+#define GADGET_ID_CUSTOM_USE_TEMPLATE	(GADGET_ID_CHECKBUTTON_FIRST + 45)
+#define GADGET_ID_CUSTOM_CAN_CHANGE	(GADGET_ID_CHECKBUTTON_FIRST + 46)
+#define GADGET_ID_CHANGE_USE_CONTENT	(GADGET_ID_CHECKBUTTON_FIRST + 47)
+#define GADGET_ID_CHANGE_USE_EXPLOSION	(GADGET_ID_CHECKBUTTON_FIRST + 48)
+#define GADGET_ID_CHANGE_ONLY_COMPLETE	(GADGET_ID_CHECKBUTTON_FIRST + 49)
+#define GADGET_ID_CHANGE_USE_RANDOM	(GADGET_ID_CHECKBUTTON_FIRST + 50)
+#define GADGET_ID_CHANGE_HAS_ACTION	(GADGET_ID_CHECKBUTTON_FIRST + 51)
+#define GADGET_ID_CHANGE_DELAY		(GADGET_ID_CHECKBUTTON_FIRST + 52)
+#define GADGET_ID_CHANGE_BY_DIRECT_ACT	(GADGET_ID_CHECKBUTTON_FIRST + 53)
+#define GADGET_ID_CHANGE_BY_OTHER_ACT	(GADGET_ID_CHECKBUTTON_FIRST + 54)
 
 /* gadgets for buttons in element list */
-#define GADGET_ID_ELEMENTLIST_FIRST	(GADGET_ID_CHECKBUTTON_FIRST + 54)
+#define GADGET_ID_ELEMENTLIST_FIRST	(GADGET_ID_CHECKBUTTON_FIRST + 55)
 #define GADGET_ID_ELEMENTLIST_LAST	(GADGET_ID_ELEMENTLIST_FIRST +	\
 	 				ED_NUM_ELEMENTLIST_BUTTONS - 1)
 
@@ -823,44 +844,45 @@
 #define ED_CHECKBUTTON_ID_SP_BLOCK_LAST_FIELD	13
 #define ED_CHECKBUTTON_ID_INSTANT_RELOCATION	14
 #define ED_CHECKBUTTON_ID_SHIFTED_RELOCATION	15
-#define ED_CHECKBUTTON_ID_USE_START_ELEMENT	16
-#define ED_CHECKBUTTON_ID_USE_ARTWORK_ELEMENT	17
-#define ED_CHECKBUTTON_ID_USE_EXPLOSION_ELEMENT	18
-#define ED_CHECKBUTTON_ID_INITIAL_GRAVITY	19
-#define ED_CHECKBUTTON_ID_USE_INITIAL_INVENTORY	20
-#define ED_CHECKBUTTON_ID_CAN_PASS_TO_WALKABLE	21
-#define ED_CHECKBUTTON_ID_CAN_FALL_INTO_ACID	22
-#define ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID	23
-#define ED_CHECKBUTTON_ID_DONT_COLLIDE_WITH	24
-#define ED_CHECKBUTTON_ID_ENVELOPE_AUTOWRAP	25
-#define ED_CHECKBUTTON_ID_ENVELOPE_CENTERED	26
-#define ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC	27
-#define ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE	28
-#define ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE	29
-#define ED_CHECKBUTTON_ID_CUSTOM_GRAV_REACHABLE	30
-#define ED_CHECKBUTTON_ID_CUSTOM_USE_LAST_VALUE	31
-#define ED_CHECKBUTTON_ID_CUSTOM_WALK_TO_OBJECT	32
-#define ED_CHECKBUTTON_ID_CUSTOM_INDESTRUCTIBLE	33
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_MOVE	34
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_FALL	35
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_SMASH	36
-#define ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY	37
-#define ED_CHECKBUTTON_ID_CUSTOM_DEADLY		38
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_EXPLODE	39
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_FIRE	40
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_SMASH	41
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT	42
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE	43
-#define ED_CHECKBUTTON_ID_CHANGE_DELAY		44
-#define ED_CHECKBUTTON_ID_CHANGE_BY_DIRECT_ACT	45
-#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER_ACT	46
-#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION	47
-#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT	48
-#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE	49
-#define ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM	50
-#define ED_CHECKBUTTON_ID_CHANGE_HAS_ACTION	51
-
-#define ED_NUM_CHECKBUTTONS			52
+#define ED_CHECKBUTTON_ID_LAZY_RELOCATION	16
+#define ED_CHECKBUTTON_ID_USE_START_ELEMENT	17
+#define ED_CHECKBUTTON_ID_USE_ARTWORK_ELEMENT	18
+#define ED_CHECKBUTTON_ID_USE_EXPLOSION_ELEMENT	19
+#define ED_CHECKBUTTON_ID_INITIAL_GRAVITY	20
+#define ED_CHECKBUTTON_ID_USE_INITIAL_INVENTORY	21
+#define ED_CHECKBUTTON_ID_CAN_PASS_TO_WALKABLE	22
+#define ED_CHECKBUTTON_ID_CAN_FALL_INTO_ACID	23
+#define ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID	24
+#define ED_CHECKBUTTON_ID_DONT_COLLIDE_WITH	25
+#define ED_CHECKBUTTON_ID_ENVELOPE_AUTOWRAP	26
+#define ED_CHECKBUTTON_ID_ENVELOPE_CENTERED	27
+#define ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC	28
+#define ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE	29
+#define ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE	30
+#define ED_CHECKBUTTON_ID_CUSTOM_GRAV_REACHABLE	31
+#define ED_CHECKBUTTON_ID_CUSTOM_USE_LAST_VALUE	32
+#define ED_CHECKBUTTON_ID_CUSTOM_WALK_TO_OBJECT	33
+#define ED_CHECKBUTTON_ID_CUSTOM_INDESTRUCTIBLE	34
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_MOVE	35
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_FALL	36
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_SMASH	37
+#define ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY	38
+#define ED_CHECKBUTTON_ID_CUSTOM_DEADLY		39
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_EXPLODE	40
+#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_FIRE	41
+#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_SMASH	42
+#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT	43
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE	44
+#define ED_CHECKBUTTON_ID_CHANGE_DELAY		45
+#define ED_CHECKBUTTON_ID_CHANGE_BY_DIRECT_ACT	46
+#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER_ACT	47
+#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION	48
+#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT	49
+#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE	50
+#define ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM	51
+#define ED_CHECKBUTTON_ID_CHANGE_HAS_ACTION	52
+
+#define ED_NUM_CHECKBUTTONS			53
 
 #define ED_CHECKBUTTON_ID_EDITOR_FIRST	ED_CHECKBUTTON_ID_RANDOM_RESTRICTED
 #define ED_CHECKBUTTON_ID_EDITOR_LAST	ED_CHECKBUTTON_ID_RANDOM_RESTRICTED
@@ -943,6 +965,7 @@
 #define ED_MODE_DRAWING			0
 #define ED_MODE_INFO			1
 #define ED_MODE_PROPERTIES		2
+#define ED_MODE_PALETTE			3
 
 /* sub-screens in the global settings section */
 #define ED_MODE_LEVELINFO_LEVEL		ED_TEXTBUTTON_ID_LEVELINFO_LEVEL
@@ -956,7 +979,7 @@
 #define ED_MODE_PROPERTIES_CHANGE	ED_TEXTBUTTON_ID_PROPERTIES_CHANGE
 
 /* how many steps can be cancelled */
-#define NUM_UNDO_STEPS			(10 + 1)
+#define NUM_UNDO_STEPS			(64 + 1)
 
 /* values for elements with score for certain actions */
 #define MIN_SCORE			0
@@ -970,9 +993,8 @@
 #define RANDOM_USE_PERCENTAGE		0
 #define RANDOM_USE_QUANTITY		1
 
-/* maximal size of level editor drawing area */
-#define MAX_ED_FIELDX		(2 * SCR_FIELDX)
-#define MAX_ED_FIELDY		(2 * SCR_FIELDY - 1)
+/* default value for element tile size in drawing area */
+#define DEFAULT_EDITOR_TILESIZE		MINI_TILESIZE
 
 
 /*
@@ -983,43 +1005,188 @@
 
 static struct
 {
+  int graphic;
+  int gadget_id;
+  struct XYTileSize *pos;
+  int gadget_type;
+  char *infotext;
   char shortcut;
-  char *text;
-} control_info[ED_NUM_CTRL_BUTTONS] =
+} controlbutton_info[ED_NUM_CTRL_BUTTONS] =
 {
   /* note: some additional characters are already reserved for "cheat mode"
      shortcuts (":XYZ" style) -- for details, see "events.c" */
 
-  { 's',	"draw single items"			},
-  { 'd',	"draw connected items"			},
-  { 'l',	"draw lines"				},
-  { 'a',	"draw arcs"				},
-  { 'r',	"draw outline rectangles"		},
-  { 'R',	"draw filled rectangles"		},
-  { '\0',	"wrap (rotate) level up"		},
-  { 't',	"enter text elements"			},
-  { 'f',	"flood fill"				},
-  { '\0',	"wrap (rotate) level left"		},
-  { '?',	"properties of drawing element"		},
-  { '\0',	"wrap (rotate) level right"		},
-  { '\0',	"random element placement"		},
-  { 'b',	"grab brush"				},
-  { '\0',	"wrap (rotate) level down"		},
-  { ',',	"pick drawing element"			},
-
-  { 'U',	"undo last operation"			},
-  { 'I',	"properties of level"			},
-  { 'S',	"save level"				},
-  { 'C',	"clear level"				},
-  { 'T',	"test level"				},
-  { 'E',	"exit level editor"			},
-
-  { '\0',	"copy settings from other element"	},
-  { '\0',	"copy settings to other element"	},
-  { '\0',	"exchange element with other element"	},
-
-  { '\0',	"copy settings from this element"	},
-  { '\0',	"paste settings to this element"	},
+  /* ---------- toolbox control buttons ------------------------------------ */
+
+  {
+    IMG_GFX_EDITOR_BUTTON_DRAW_SINGLE,		GADGET_ID_SINGLE_ITEMS,
+    &editor.button.draw_single,			GD_TYPE_RADIO_BUTTON,
+    "draw single items",			's'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_DRAW_CONNECTED,	GADGET_ID_CONNECTED_ITEMS,
+    &editor.button.draw_connected,		GD_TYPE_RADIO_BUTTON,
+    "draw connected items",			'd'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_DRAW_LINE,		GADGET_ID_LINE,
+    &editor.button.draw_line,			GD_TYPE_RADIO_BUTTON,
+    "draw lines",				'l'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_DRAW_ARC,		GADGET_ID_ARC,
+    &editor.button.draw_arc,			GD_TYPE_RADIO_BUTTON,
+    "draw arcs",				'a'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_DRAW_RECTANGLE,	GADGET_ID_RECTANGLE,
+    &editor.button.draw_rectangle,		GD_TYPE_RADIO_BUTTON,
+    "draw outline rectangles",			'r'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_DRAW_FILLED_BOX,	GADGET_ID_FILLED_BOX,
+    &editor.button.draw_filled_box,		GD_TYPE_RADIO_BUTTON,
+    "draw filled rectangles",			'R'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_ROTATE_UP,		GADGET_ID_WRAP_UP,
+    &editor.button.rotate_up,			GD_TYPE_NORMAL_BUTTON,
+    "wrap (rotate) level up",			0
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_DRAW_TEXT,		GADGET_ID_TEXT,
+    &editor.button.draw_text,			GD_TYPE_RADIO_BUTTON,
+    "enter text elements",			't'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_FLOOD_FILL,		GADGET_ID_FLOOD_FILL,
+    &editor.button.flood_fill,			GD_TYPE_RADIO_BUTTON,
+    "flood fill",				'f'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_ROTATE_LEFT,		GADGET_ID_WRAP_LEFT,
+    &editor.button.rotate_left,			GD_TYPE_NORMAL_BUTTON,
+    "wrap (rotate) level left",			0
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_ZOOM_LEVEL,		GADGET_ID_ZOOM,
+    &editor.button.zoom_level,			GD_TYPE_NORMAL_BUTTON,
+    "zoom level tile size",			'+'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_ROTATE_RIGHT,		GADGET_ID_WRAP_RIGHT,
+    &editor.button.rotate_right,		GD_TYPE_NORMAL_BUTTON,
+    "wrap (rotate) level right",		0
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_DRAW_RANDOM,		GADGET_ID_RANDOM_PLACEMENT,
+    &editor.button.draw_random,			GD_TYPE_NORMAL_BUTTON,
+    "random element placement",			0
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_GRAB_BRUSH,		GADGET_ID_GRAB_BRUSH,
+    &editor.button.grab_brush,			GD_TYPE_RADIO_BUTTON,
+    "grab brush",				'b'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_ROTATE_DOWN,		GADGET_ID_WRAP_DOWN,
+    &editor.button.rotate_down,			GD_TYPE_NORMAL_BUTTON,
+    "wrap (rotate) level down",			0
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_PICK_ELEMENT,		GADGET_ID_PICK_ELEMENT,
+    &editor.button.pick_element,		GD_TYPE_RADIO_BUTTON,
+    "pick drawing element",			','
+  },
+
+  /* ---------- level control buttons -------------------------------------- */
+
+  {
+    IMG_GFX_EDITOR_BUTTON_UNDO,			GADGET_ID_UNDO,
+    &editor.button.undo,			GD_TYPE_NORMAL_BUTTON,
+    "undo/redo last operation",			'u'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_CONF,			GADGET_ID_INFO,
+    &editor.button.conf,			GD_TYPE_NORMAL_BUTTON,
+    "properties of level",			'I'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_SAVE,			GADGET_ID_SAVE,
+    &editor.button.save,			GD_TYPE_NORMAL_BUTTON,
+    "save level",				'S'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_CLEAR,		GADGET_ID_CLEAR,
+    &editor.button.clear,			GD_TYPE_NORMAL_BUTTON,
+    "clear level",				'C'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_TEST,			GADGET_ID_TEST,
+    &editor.button.test,			GD_TYPE_NORMAL_BUTTON,
+    "test level",				'T'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_EXIT,			GADGET_ID_EXIT,
+    &editor.button.exit,			GD_TYPE_NORMAL_BUTTON,
+    "exit level editor",			'E'
+  },
+
+  /* ---------- CE and GE control buttons ---------------------------------- */
+
+  {
+    IMG_GFX_EDITOR_BUTTON_CE_COPY_FROM,		GADGET_ID_CUSTOM_COPY_FROM,
+    &editor.button.ce_copy_from,		GD_TYPE_RADIO_BUTTON,
+    "copy settings from other element",		0
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_CE_COPY_TO,		GADGET_ID_CUSTOM_COPY_TO,
+    &editor.button.ce_copy_to,			GD_TYPE_RADIO_BUTTON,
+    "copy settings to other element",		0
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_CE_SWAP,		GADGET_ID_CUSTOM_EXCHANGE,
+    &editor.button.ce_swap,			GD_TYPE_RADIO_BUTTON,
+    "exchange element with other element",	0
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_CE_COPY,		GADGET_ID_CUSTOM_COPY,
+    &editor.button.ce_copy,			GD_TYPE_NORMAL_BUTTON,
+    "copy settings from this element",		0
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_CE_PASTE,		GADGET_ID_CUSTOM_PASTE,
+    &editor.button.ce_paste,			GD_TYPE_NORMAL_BUTTON,
+    "paste settings to this element",		0
+  },
+
+  /* ---------- palette control buttons ------------------------------------ */
+
+  {
+    IMG_GFX_EDITOR_BUTTON_PROPERTIES,		GADGET_ID_PROPERTIES,
+    &editor.button.properties,			GD_TYPE_NORMAL_BUTTON,
+    "properties of drawing element",		'p'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_ELEMENT_LEFT,		GADGET_ID_ELEMENT_LEFT,
+    &editor.button.element_left,		GD_TYPE_NORMAL_BUTTON,
+    "properties of drawing element 1",		'1'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_ELEMENT_MIDDLE,	GADGET_ID_ELEMENT_MIDDLE,
+    &editor.button.element_middle,		GD_TYPE_NORMAL_BUTTON,
+    "properties of drawing element 2",		'2'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_ELEMENT_RIGHT,	GADGET_ID_ELEMENT_RIGHT,
+    &editor.button.element_right,		GD_TYPE_NORMAL_BUTTON,
+    "properties of drawing element 3",		'3'
+  },
+  {
+    IMG_GFX_EDITOR_BUTTON_PALETTE,		GADGET_ID_PALETTE,
+    &editor.button.palette,			GD_TYPE_NORMAL_BUTTON,
+    "show list of elements",			'e'
+  }
 };
 
 static int random_placement_value = 10;
@@ -1047,11 +1214,7 @@ static struct
   /* ---------- current level number --------------------------------------- */
 
   {
-#if 1
     -1, -1,	/* these values are not constant, but can change at runtime */
-#else
-    DX + 5 - SX,			DY + 3 - SY,
-#endif
     1,					100,
     GADGET_ID_SELECT_LEVEL_DOWN,	GADGET_ID_SELECT_LEVEL_UP,
     GADGET_ID_SELECT_LEVEL_TEXT,	GADGET_ID_NONE,
@@ -1204,7 +1367,7 @@ static struct
   /* ---------- element settings: configure 1 (custom elements) ------------ */
 
   {
-    ED_ELEMENT_SETTINGS_XPOS(1),	ED_ELEMENT_SETTINGS_YPOS(6),
+    ED_ELEMENT_SETTINGS_XPOS(1),	ED_ELEMENT_SETTINGS_YPOS(5),
     MIN_SCORE,				MAX_SCORE,
     GADGET_ID_CUSTOM_SCORE_DOWN,	GADGET_ID_CUSTOM_SCORE_UP,
     GADGET_ID_CUSTOM_SCORE_TEXT,	GADGET_ID_NONE,
@@ -1212,7 +1375,7 @@ static struct
     NULL,				"CE score", " "
   },
   {
-    -1,					ED_ELEMENT_SETTINGS_YPOS(6),
+    -1,					ED_ELEMENT_SETTINGS_YPOS(5),
     MIN_COLLECT_COUNT,			MAX_COLLECT_COUNT,
     GADGET_ID_CUSTOM_GEMCOUNT_DOWN,	GADGET_ID_CUSTOM_GEMCOUNT_UP,
     GADGET_ID_CUSTOM_GEMCOUNT_TEXT,	GADGET_ID_CUSTOM_SCORE_UP,
@@ -1220,7 +1383,7 @@ static struct
     NULL,				"CE count", NULL
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(12),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(10),
     0,					9999,
     GADGET_ID_CUSTOM_VALUE_FIX_DOWN,	GADGET_ID_CUSTOM_VALUE_FIX_UP,
     GADGET_ID_CUSTOM_VALUE_FIX_TEXT,	GADGET_ID_NONE,
@@ -1228,7 +1391,7 @@ static struct
     NULL,				"CE value", NULL
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(12),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(10),
     0,					9999,
     GADGET_ID_CUSTOM_VALUE_RND_DOWN,	GADGET_ID_CUSTOM_VALUE_RND_UP,
     GADGET_ID_CUSTOM_VALUE_RND_TEXT,	GADGET_ID_CUSTOM_VALUE_FIX_UP,
@@ -1236,7 +1399,7 @@ static struct
     NULL,				"+random", NULL
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(1),	ED_ELEMENT_SETTINGS_YPOS(7),
+    ED_ELEMENT_SETTINGS_XPOS(1),	ED_ELEMENT_SETTINGS_YPOS(6),
     0,					999,
     GADGET_ID_PUSH_DELAY_FIX_DOWN,	GADGET_ID_PUSH_DELAY_FIX_UP,
     GADGET_ID_PUSH_DELAY_FIX_TEXT,	GADGET_ID_NONE,
@@ -1244,7 +1407,7 @@ static struct
     NULL,				"push delay", NULL
   },
   {
-    -1,					ED_ELEMENT_SETTINGS_YPOS(7),
+    -1,					ED_ELEMENT_SETTINGS_YPOS(6),
     0,					999,
     GADGET_ID_PUSH_DELAY_RND_DOWN,	GADGET_ID_PUSH_DELAY_RND_UP,
     GADGET_ID_PUSH_DELAY_RND_TEXT,	GADGET_ID_PUSH_DELAY_FIX_UP,
@@ -1252,7 +1415,7 @@ static struct
     NULL,				"+random", NULL
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(1),	ED_ELEMENT_SETTINGS_YPOS(8),
+    ED_ELEMENT_SETTINGS_XPOS(1),	ED_ELEMENT_SETTINGS_YPOS(7),
     0,					999,
     GADGET_ID_DROP_DELAY_FIX_DOWN,	GADGET_ID_DROP_DELAY_FIX_UP,
     GADGET_ID_DROP_DELAY_FIX_TEXT,	GADGET_ID_NONE,
@@ -1260,7 +1423,7 @@ static struct
     NULL,				"drop delay", NULL
   },
   {
-    -1,					ED_ELEMENT_SETTINGS_YPOS(8),
+    -1,					ED_ELEMENT_SETTINGS_YPOS(7),
     0,					999,
     GADGET_ID_DROP_DELAY_RND_DOWN,	GADGET_ID_DROP_DELAY_RND_UP,
     GADGET_ID_DROP_DELAY_RND_TEXT,	GADGET_ID_DROP_DELAY_FIX_UP,
@@ -1306,7 +1469,7 @@ static struct
   /* ---------- element settings: configure (group elements) --------------- */
 
   {
-    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(5),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(3),
     MIN_ELEMENTS_IN_GROUP,		MAX_ELEMENTS_IN_GROUP,
     GADGET_ID_GROUP_CONTENT_DOWN,	GADGET_ID_GROUP_CONTENT_UP,
     GADGET_ID_GROUP_CONTENT_TEXT,	GADGET_ID_NONE,
@@ -1366,7 +1529,7 @@ static struct
     "Author:", "Author"
   },
   {
-    5 * MINI_TILEX - 2,			5 * MINI_TILEY - ED_BORDER_SIZE + 1,
+    -1, -1,	/* these values are not constant, but can change at runtime */
     GADGET_ID_ELEMENT_NAME,
     MAX_ELEMENT_NAME_LEN - 2,		/* currently 2 chars less editable */
     custom_element.description,
@@ -2135,7 +2298,7 @@ static struct
   /* ---------- element settings: configure (several elements) ------------- */
 
   {
-    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(6),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(7),
     GADGET_ID_PLAYER_SPEED,		GADGET_ID_NONE,
     -1,
     options_player_speed,
@@ -2146,7 +2309,7 @@ static struct
   /* ---------- element settings: configure 1 (custom elements) ------------ */
 
   {
-    ED_ELEMENT_SETTINGS_XPOS(1),	ED_ELEMENT_SETTINGS_YPOS(3),
+    ED_ELEMENT_SETTINGS_XPOS(1),	ED_ELEMENT_SETTINGS_YPOS(2),
     GADGET_ID_CUSTOM_ACCESS_TYPE,	GADGET_ID_NONE,
     -1,
     options_access_type,
@@ -2154,7 +2317,7 @@ static struct
     NULL, NULL,				"type of access to this field"
   },
   {
-    -1,					ED_ELEMENT_SETTINGS_YPOS(3),
+    -1,					ED_ELEMENT_SETTINGS_YPOS(2),
     GADGET_ID_CUSTOM_ACCESS_LAYER,	GADGET_ID_CUSTOM_ACCESS_TYPE,
     -1,
     options_access_layer,
@@ -2162,7 +2325,7 @@ static struct
     NULL, NULL,				"layer of access for this field"
   },
   {
-    -1,					ED_ELEMENT_SETTINGS_YPOS(3),
+    -1,					ED_ELEMENT_SETTINGS_YPOS(2),
     GADGET_ID_CUSTOM_ACCESS_PROTECTED,	GADGET_ID_CUSTOM_ACCESS_LAYER,
     -1,
     options_access_protected,
@@ -2170,7 +2333,7 @@ static struct
     NULL, NULL,				"protected access for this field"
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(1),	ED_ELEMENT_SETTINGS_YPOS(4),
+    ED_ELEMENT_SETTINGS_XPOS(1),	ED_ELEMENT_SETTINGS_YPOS(3),
     GADGET_ID_CUSTOM_ACCESS_DIRECTION,	GADGET_ID_NONE,
     -1,
     options_access_direction,
@@ -2178,7 +2341,7 @@ static struct
     "from", NULL,			"access direction for this field"
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(1),	ED_ELEMENT_SETTINGS_YPOS(5),
+    ED_ELEMENT_SETTINGS_XPOS(1),	ED_ELEMENT_SETTINGS_YPOS(4),
     GADGET_ID_CUSTOM_WALK_TO_ACTION,	GADGET_ID_NONE,
     -1,
     options_walk_to_action,
@@ -2218,7 +2381,10 @@ static struct
     -1,
     options_move_leave_type,
     &custom_element.move_leave_type,
-    "can dig:    can", ":",		"leave behind or change element"
+    // left text with leading spaces to place gadget next to "can dig" gadget
+    // (needed because drawing area gadgets created after selectbox gadgets)
+    // "can dig:    can", ":",		"leave behind or change element"
+    "            can", ":",		"leave behind or change element"
   },
   {
     -1,					ED_ELEMENT_SETTINGS_YPOS(7),
@@ -2347,7 +2513,7 @@ static struct
   /* ---------- element settings: configure (group elements) --------------- */
 
   {
-    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(6),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(4),
     GADGET_ID_GROUP_CHOICE_MODE,	GADGET_ID_NONE,
     -1,
     options_group_choice_mode,
@@ -2367,61 +2533,61 @@ static struct
 } textbutton_info[ED_NUM_TEXTBUTTONS] =
 {
   {
-    ED_LEVEL_SETTINGS_TABS_XPOS(0),	ED_LEVEL_SETTINGS_TABS_YPOS(0),
+    ED_LEVEL_SETTINGS_XPOS(0),		ED_LEVEL_SETTINGS_YPOS(0),
     GADGET_ID_LEVELINFO_LEVEL,		GADGET_ID_NONE,
     8,					"Level",			
     NULL, NULL,				"Configure level properties"
   },
   {
-    ED_LEVEL_SETTINGS_TABS_XPOS(1),	ED_LEVEL_SETTINGS_TABS_YPOS(0),
-    GADGET_ID_LEVELINFO_EDITOR,		GADGET_ID_NONE,
+    -1,					-1,
+    GADGET_ID_LEVELINFO_EDITOR,		GADGET_ID_LEVELINFO_LEVEL,
     8,					"Editor",			
     NULL, NULL,				"Configure editor properties"
   },
   {
-    ED_ELEMENT_SETTINGS_TABS_XPOS(0),	ED_ELEMENT_SETTINGS_TABS_YPOS(0),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(0),
     GADGET_ID_PROPERTIES_INFO,		GADGET_ID_NONE,
     8,					"Info",			
     NULL, NULL,				"Show information about element"
   },
   {
-    ED_ELEMENT_SETTINGS_TABS_XPOS(1),	ED_ELEMENT_SETTINGS_TABS_YPOS(0),
-    GADGET_ID_PROPERTIES_CONFIG,	GADGET_ID_NONE,
+    -1,					-1,
+    GADGET_ID_PROPERTIES_CONFIG,	GADGET_ID_PROPERTIES_INFO,
     8,					"Config",
     NULL, NULL,				"Configure element properties"
   },
   {
-    ED_ELEMENT_SETTINGS_TABS_XPOS(1),	ED_ELEMENT_SETTINGS_TABS_YPOS(0),
-    GADGET_ID_PROPERTIES_CONFIG_1,	GADGET_ID_NONE,
+    -1,					-1,
+    GADGET_ID_PROPERTIES_CONFIG_1,	GADGET_ID_PROPERTIES_INFO,
     8,					"Config 1",
     NULL, NULL,				"Configure element properties, part 1"
   },
   {
-    ED_ELEMENT_SETTINGS_TABS_XPOS(2),	ED_ELEMENT_SETTINGS_TABS_YPOS(0),
-    GADGET_ID_PROPERTIES_CONFIG_2,	GADGET_ID_NONE,
+    -1,					-1,
+    GADGET_ID_PROPERTIES_CONFIG_2,	GADGET_ID_PROPERTIES_CONFIG_1,
     8,					"Config 2",
     NULL, NULL,				"Configure element properties, part 2"
   },
   {
-    ED_ELEMENT_SETTINGS_TABS_XPOS(3),	ED_ELEMENT_SETTINGS_TABS_YPOS(0),
-    GADGET_ID_PROPERTIES_CHANGE,	GADGET_ID_NONE,
+    -1,					-1,
+    GADGET_ID_PROPERTIES_CHANGE,	GADGET_ID_PROPERTIES_CONFIG_2,
     8,					"Change",
     NULL, NULL,				"Configure custom element change pages"
   },
   {
-    -1,					ED_ELEMENT_SETTINGS_YPOS(2),
+    -1,					-1,
     GADGET_ID_SAVE_AS_TEMPLATE,		GADGET_ID_CUSTOM_USE_TEMPLATE,
     -1,					"Save",
     " ", "As Template",			"Save current settings as new template"
   },
   {
-    -1,					ED_ELEMENT_SETTINGS_YPOS(14),
+    -1,					-1,
     GADGET_ID_ADD_CHANGE_PAGE,		GADGET_ID_PASTE_CHANGE_PAGE,
     -1,					"New",
     NULL, NULL,				"Add new change page"
   },
   {
-    -1,					ED_ELEMENT_SETTINGS_YPOS(14),
+    -1,					-1,
     GADGET_ID_DEL_CHANGE_PAGE,		GADGET_ID_ADD_CHANGE_PAGE,
     -1,					"Delete",
     NULL, NULL,				"Delete current change page"
@@ -2430,39 +2596,34 @@ static struct
 
 static struct
 {
-  int gd_x, gd_y;
+  int graphic;
   int x, y;
-  int width, height;
   int gadget_id;
   int gadget_id_align;
   char *text_left, *text_right, *infotext;
 } graphicbutton_info[ED_NUM_GRAPHICBUTTONS] =
 {
   {
-    ED_BUTTON_MINUS_XPOS,		ED_BUTTON_COUNT_YPOS,
+    IMG_EDITOR_COUNTER_DOWN,
     ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(14),
-    ED_BUTTON_COUNT_XSIZE,		ED_BUTTON_COUNT_YSIZE,
     GADGET_ID_PREV_CHANGE_PAGE,		GADGET_ID_NONE,
     NULL, NULL,				"select previous change page"
   },
   {
-    ED_BUTTON_PLUS_XPOS,		ED_BUTTON_COUNT_YPOS,
+    IMG_EDITOR_COUNTER_UP,
     -1,					ED_ELEMENT_SETTINGS_YPOS(14),
-    ED_BUTTON_COUNT_XSIZE,		ED_BUTTON_COUNT_YSIZE,
     GADGET_ID_NEXT_CHANGE_PAGE,		GADGET_ID_SELECT_CHANGE_PAGE,
     NULL, "change page",		"select next change page"
   },
   {
-    ED_COPY_CHANGE_PAGE_XPOS,		ED_COPY_CHANGE_PAGE_YPOS,
+    IMG_GFX_EDITOR_BUTTON_CP_COPY,
     -1,					ED_ELEMENT_SETTINGS_YPOS(14),
-    ED_BUTTON_COUNT_XSIZE,		ED_BUTTON_COUNT_YSIZE,
     GADGET_ID_COPY_CHANGE_PAGE,		GADGET_ID_NEXT_CHANGE_PAGE,
     " ", NULL,				"copy settings from this change page"
   },
   {
-    ED_PASTE_CHANGE_PAGE_XPOS,		ED_PASTE_CHANGE_PAGE_YPOS,
+    IMG_GFX_EDITOR_BUTTON_CP_PASTE,
     -1,					ED_ELEMENT_SETTINGS_YPOS(14),
-    ED_BUTTON_COUNT_XSIZE,		ED_BUTTON_COUNT_YSIZE,
     GADGET_ID_PASTE_CHANGE_PAGE,	GADGET_ID_COPY_CHANGE_PAGE,
     NULL, NULL,				"paste settings to this change page"
   },
@@ -2470,61 +2631,43 @@ static struct
 
 static struct
 {
-  int gd_x, gd_y;
   int x, y;
+} scrollbutton_pos[ED_NUM_SCROLLBUTTONS];
+
+static struct
+{
+  int graphic;
   int gadget_id;
   char *infotext;
 } scrollbutton_info[ED_NUM_SCROLLBUTTONS] =
 {
   {
-    ED_SCROLLBUTTON_XPOS,   ED_SCROLLBUTTON_YPOS + 0 * ED_SCROLLBUTTON_YSIZE,
-#if 1
-    -1, -1,	/* these values are not constant, but can change at runtime */
-#else
-    ED_SCROLL_UP_XPOS,      ED_SCROLL_UP_YPOS,
-#endif
+    IMG_EDITOR_PLAYFIELD_SCROLL_UP,
     GADGET_ID_SCROLL_UP,
     "scroll level editing area up"
   },
   {
-    ED_SCROLLBUTTON_XPOS,   ED_SCROLLBUTTON_YPOS + 1 * ED_SCROLLBUTTON_YSIZE,
-#if 1
-    -1, -1,	/* these values are not constant, but can change at runtime */
-#else
-    ED_SCROLL_DOWN_XPOS,    ED_SCROLL_DOWN_YPOS,
-#endif
+    IMG_EDITOR_PLAYFIELD_SCROLL_DOWN,
     GADGET_ID_SCROLL_DOWN,
     "scroll level editing area down"
   },
   {
-    ED_SCROLLBUTTON_XPOS,   ED_SCROLLBUTTON_YPOS + 2 * ED_SCROLLBUTTON_YSIZE,
-#if 1
-    -1, -1,	/* these values are not constant, but can change at runtime */
-#else
-    ED_SCROLL_LEFT_XPOS,    ED_SCROLL_LEFT_YPOS,
-#endif
+    IMG_EDITOR_PLAYFIELD_SCROLL_LEFT,
     GADGET_ID_SCROLL_LEFT,
     "scroll level editing area left"
   },
   {
-    ED_SCROLLBUTTON_XPOS,   ED_SCROLLBUTTON_YPOS + 3 * ED_SCROLLBUTTON_YSIZE,
-#if 1
-    -1, -1,	/* these values are not constant, but can change at runtime */
-#else
-    ED_SCROLL_RIGHT_XPOS,   ED_SCROLL_RIGHT_YPOS,
-#endif
+    IMG_EDITOR_PLAYFIELD_SCROLL_RIGHT,
     GADGET_ID_SCROLL_RIGHT,
     "scroll level editing area right"
   },
   {
-    ED_SCROLLBUTTON2_XPOS,  ED_SCROLLBUTTON2_YPOS + 0 * ED_SCROLLBUTTON2_YSIZE,
-    ED_SCROLL2_UP_XPOS,     ED_SCROLL2_UP_YPOS,
+    IMG_EDITOR_PALETTE_SCROLL_UP,
     GADGET_ID_SCROLL_LIST_UP,
     "scroll element list up ('Page Up')"
   },
   {
-    ED_SCROLLBUTTON2_XPOS,  ED_SCROLLBUTTON2_YPOS + 1 * ED_SCROLLBUTTON2_YSIZE,
-    ED_SCROLL2_DOWN_XPOS,   ED_SCROLL2_DOWN_YPOS,
+    IMG_EDITOR_PALETTE_SCROLL_DOWN,
     GADGET_ID_SCROLL_LIST_DOWN,
     "scroll element list down ('Page Down')"
   },
@@ -2532,68 +2675,41 @@ static struct
 
 static struct
 {
-  int gd_x, gd_y;
   int x, y;
   int width, height;
   int wheel_x, wheel_y;
   int wheel_width, wheel_height;
+} scrollbar_pos[ED_NUM_SCROLLBARS];
+
+static struct
+{
+  int graphic;
   int type;
   int gadget_id;
   char *infotext;
 } scrollbar_info[ED_NUM_SCROLLBARS] =
 {
   {
-    ED_SCROLLBAR_XPOS,			ED_SCROLLBAR_YPOS,
-#if 1
-    -1, -1,	/* these values are not constant, but can change at runtime */
-    -1, -1,	/* these values are not constant, but can change at runtime */
-    -1, -1,	/* these values are not constant, but can change at runtime */
-    -1, -1,	/* these values are not constant, but can change at runtime */
-#else
-    SX + ED_SCROLL_HORIZONTAL_XPOS,	SY + ED_SCROLL_HORIZONTAL_YPOS,
-    ED_SCROLL_HORIZONTAL_XSIZE,		ED_SCROLL_HORIZONTAL_YSIZE,
-    SX,					SY,
-    SXSIZE,				SYSIZE,
-#endif
+    IMG_EDITOR_PLAYFIELD_SCROLLBAR,
     GD_TYPE_SCROLLBAR_HORIZONTAL,
     GADGET_ID_SCROLL_HORIZONTAL,
     "scroll level editing area horizontally"
   },
   {
-    ED_SCROLLBAR_XPOS,			ED_SCROLLBAR_YPOS,
-#if 1
-    -1, -1,	/* these values are not constant, but can change at runtime */
-    -1, -1,	/* these values are not constant, but can change at runtime */
-    -1, -1,	/* these values are not constant, but can change at runtime */
-    -1, -1,	/* these values are not constant, but can change at runtime */
-#else
-    SX + ED_SCROLL_VERTICAL_XPOS,	SY + ED_SCROLL_VERTICAL_YPOS,
-    ED_SCROLL_VERTICAL_XSIZE,		ED_SCROLL_VERTICAL_YSIZE,
-    SX,					SY,
-    SXSIZE,				SYSIZE,
-#endif
+    IMG_EDITOR_PLAYFIELD_SCROLLBAR,
     GD_TYPE_SCROLLBAR_VERTICAL,
     GADGET_ID_SCROLL_VERTICAL,
     "scroll level editing area vertically"
   },
   {
-    ED_SCROLLBAR2_XPOS,			ED_SCROLLBAR2_YPOS,
-#if 1
-    -1, -1,	/* these values are not constant, but can change at runtime */
-    ED_SCROLL2_VERTICAL_XSIZE,		ED_SCROLL2_VERTICAL_YSIZE,
-    -1, -1,	/* these values are not constant, but can change at runtime */
-#else
-    DX + ED_SCROLL2_VERTICAL_XPOS,	DY + ED_SCROLL2_VERTICAL_YPOS,
-    ED_SCROLL2_VERTICAL_XSIZE,		ED_SCROLL2_VERTICAL_YSIZE,
-    DX,					DY,
-#endif
-    DXSIZE,				DYSIZE,
+    IMG_EDITOR_PALETTE_SCROLLBAR,
     GD_TYPE_SCROLLBAR_VERTICAL,
     GADGET_ID_SCROLL_LIST_VERTICAL,
     "scroll element list vertically"
   }
 };
 
+
 static struct
 {
   int x, y;
@@ -2706,14 +2822,14 @@ static struct
     "exit level if all fields solved",	"automatically finish Sokoban levels"
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(8),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(9),
     GADGET_ID_CONTINUOUS_SNAPPING,	GADGET_ID_NONE,
     &level.continuous_snapping,
     NULL,
-    "continuos snapping",		"use snapping without releasing key"
+    "continuous snapping",		"use snapping without releasing key"
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(7),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(8),
     GADGET_ID_BLOCK_SNAP_FIELD,		GADGET_ID_NONE,
     &level.block_snap_field,
     NULL,
@@ -2748,28 +2864,35 @@ static struct
     "no centering when relocating",	"level not centered after relocation"
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(9),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(5),
+    GADGET_ID_LAZY_RELOCATION,		GADGET_ID_NONE,
+    &level.lazy_relocation,
+    NULL,
+    "only redraw off-screen relocation","no redraw if relocation target visible"
+  },
+  {
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(10),
     GADGET_ID_USE_START_ELEMENT,	GADGET_ID_NONE,
     &level.use_start_element[0],
     NULL,
     "use level start element:",	       "start level at this element's position"
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(10),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(11),
     GADGET_ID_USE_ARTWORK_ELEMENT,	GADGET_ID_NONE,
     &level.use_artwork_element[0],
     NULL,
     "use artwork from element:",	"use player artwork from other element"
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(11),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(12),
     GADGET_ID_USE_EXPLOSION_ELEMENT,	GADGET_ID_NONE,
     &level.use_explosion_element[0],
     NULL,
     "use explosion from element:",	"use explosion properties from element"
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(12),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(13),
     GADGET_ID_INITIAL_GRAVITY,		GADGET_ID_NONE,
     &level.initial_player_gravity[0],
     NULL,
@@ -2783,7 +2906,7 @@ static struct
     "use initial inventory:",		"use collected elements on level start"
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(5),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(6),
     GADGET_ID_CAN_PASS_TO_WALKABLE,	GADGET_ID_NONE,
     &level.can_pass_to_walkable,
     NULL,
@@ -2831,53 +2954,46 @@ static struct
     ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(1),
     GADGET_ID_CUSTOM_USE_GRAPHIC,	GADGET_ID_NONE,
     &custom_element.use_gfx_element,
-
-    /* !!! add separate "use existing element sound" !!! */
-#if 0
-    NULL,
-    "use graphic/sound of element:",	"use existing graphic and sound"
-#else
     NULL,
     "use graphic of element:",		"use existing element graphic"
-#endif
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(2),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(14),
     GADGET_ID_CUSTOM_USE_TEMPLATE,	GADGET_ID_NONE,
     &level.use_custom_template,
     NULL,
     "use template",			"use template for custom properties"
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(3),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(2),
     GADGET_ID_CUSTOM_ACCESSIBLE,	GADGET_ID_NONE,
     &custom_element_properties[EP_ACCESSIBLE],
     NULL,
     NULL,				"player can walk to or pass this field"
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(10),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(9),
     GADGET_ID_CUSTOM_GRAV_REACHABLE,	GADGET_ID_NONE,
     &custom_element_properties[EP_GRAVITY_REACHABLE],
     NULL,
     "reachable despite gravity",	"player can walk/dig despite gravity"
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(13),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(11),
     GADGET_ID_CUSTOM_USE_LAST_VALUE,	GADGET_ID_NONE,
     &custom_element.use_last_ce_value,
     NULL,
     "use last CE value after change",	"use last CE value after change"
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(5),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(4),
     GADGET_ID_CUSTOM_WALK_TO_OBJECT,	GADGET_ID_NONE,
     &custom_element_properties[EP_WALK_TO_OBJECT],
     NULL,
     NULL,				"player can dig/collect/push element"
   },
   {
-    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(9),
+    ED_ELEMENT_SETTINGS_XPOS(0),	ED_ELEMENT_SETTINGS_YPOS(8),
     GADGET_ID_CUSTOM_INDESTRUCTIBLE,	GADGET_ID_NONE,
     &custom_element_properties[EP_INDESTRUCTIBLE],
     NULL,
@@ -3020,6 +3136,7 @@ static struct
 static struct
 {
   int x, y;
+  int xoffset, yoffset;
   int gadget_id;
   int gadget_id_align;
   int *value;
@@ -3031,62 +3148,67 @@ static struct
 
   {
     0,					0,
+    0,					0,
     GADGET_ID_DRAWING_LEVEL,		GADGET_ID_NONE,
     NULL,
-#if 1
     -1, -1,	/* these values are not constant, but can change at runtime */
-#else
-    MAX_ED_FIELDX, MAX_ED_FIELDY,
-#endif
     NULL, NULL, NULL,			NULL
   },
 
   /* ---------- yam yam content -------------------------------------------- */
 
   {
-    ED_AREA_YAMYAM_CONTENT_XPOS(0),	ED_AREA_YAMYAM_CONTENT_YPOS(0),
+    ED_AREA_YAMYAM_CONTENT_XPOS,	ED_AREA_YAMYAM_CONTENT_YPOS,
+    ED_AREA_YAMYAM_CONTENT_XOFF(0),	ED_AREA_YAMYAM_CONTENT_YOFF(0),
     GADGET_ID_YAMYAM_CONTENT_0,		GADGET_ID_NONE,
     &level.yamyam_content[0].e[0][0],	3, 3,
     NULL, NULL, "1",			NULL
   },
   {
-    ED_AREA_YAMYAM_CONTENT_XPOS(1),	ED_AREA_YAMYAM_CONTENT_YPOS(1),
+    ED_AREA_YAMYAM_CONTENT_XPOS,	ED_AREA_YAMYAM_CONTENT_YPOS,
+    ED_AREA_YAMYAM_CONTENT_XOFF(1),	ED_AREA_YAMYAM_CONTENT_YOFF(1),
     GADGET_ID_YAMYAM_CONTENT_1,		GADGET_ID_NONE,
     &level.yamyam_content[1].e[0][0],	3, 3,
     NULL, NULL, "2",			NULL
   },
   {
-    ED_AREA_YAMYAM_CONTENT_XPOS(2),	ED_AREA_YAMYAM_CONTENT_YPOS(2),
+    ED_AREA_YAMYAM_CONTENT_XPOS,	ED_AREA_YAMYAM_CONTENT_YPOS,
+    ED_AREA_YAMYAM_CONTENT_XOFF(2),	ED_AREA_YAMYAM_CONTENT_YOFF(2),
     GADGET_ID_YAMYAM_CONTENT_2,		GADGET_ID_NONE,
     &level.yamyam_content[2].e[0][0],	3, 3,
     NULL, NULL, "3",			NULL
   },
   {
-    ED_AREA_YAMYAM_CONTENT_XPOS(3),	ED_AREA_YAMYAM_CONTENT_YPOS(3),
+    ED_AREA_YAMYAM_CONTENT_XPOS,	ED_AREA_YAMYAM_CONTENT_YPOS,
+    ED_AREA_YAMYAM_CONTENT_XOFF(3),	ED_AREA_YAMYAM_CONTENT_YOFF(3),
     GADGET_ID_YAMYAM_CONTENT_3,		GADGET_ID_NONE,
     &level.yamyam_content[3].e[0][0],	3, 3,
     NULL, NULL, "4",			NULL
   },
   {
-    ED_AREA_YAMYAM_CONTENT_XPOS(4),	ED_AREA_YAMYAM_CONTENT_YPOS(4),
+    ED_AREA_YAMYAM_CONTENT_XPOS,	ED_AREA_YAMYAM_CONTENT_YPOS,
+    ED_AREA_YAMYAM_CONTENT_XOFF(4),	ED_AREA_YAMYAM_CONTENT_YOFF(4),
     GADGET_ID_YAMYAM_CONTENT_4,		GADGET_ID_NONE,
     &level.yamyam_content[4].e[0][0],	3, 3,
     NULL, NULL, "5",			NULL
   },
   {
-    ED_AREA_YAMYAM_CONTENT_XPOS(5),	ED_AREA_YAMYAM_CONTENT_YPOS(5),
+    ED_AREA_YAMYAM_CONTENT_XPOS,	ED_AREA_YAMYAM_CONTENT_YPOS,
+    ED_AREA_YAMYAM_CONTENT_XOFF(5),	ED_AREA_YAMYAM_CONTENT_YOFF(5),
     GADGET_ID_YAMYAM_CONTENT_5,		GADGET_ID_NONE,
     &level.yamyam_content[5].e[0][0],	3, 3,
     NULL, NULL, "6",			NULL
   },
   {
-    ED_AREA_YAMYAM_CONTENT_XPOS(6),	ED_AREA_YAMYAM_CONTENT_YPOS(6),
+    ED_AREA_YAMYAM_CONTENT_XPOS,	ED_AREA_YAMYAM_CONTENT_YPOS,
+    ED_AREA_YAMYAM_CONTENT_XOFF(6),	ED_AREA_YAMYAM_CONTENT_YOFF(6),
     GADGET_ID_YAMYAM_CONTENT_6,		GADGET_ID_NONE,
     &level.yamyam_content[6].e[0][0],	3, 3,
     NULL, NULL, "7",			NULL
   },
   {
-    ED_AREA_YAMYAM_CONTENT_XPOS(7),	ED_AREA_YAMYAM_CONTENT_YPOS(7),
+    ED_AREA_YAMYAM_CONTENT_XPOS,	ED_AREA_YAMYAM_CONTENT_YPOS,
+    ED_AREA_YAMYAM_CONTENT_XOFF(7),	ED_AREA_YAMYAM_CONTENT_YOFF(7),
     GADGET_ID_YAMYAM_CONTENT_7,		GADGET_ID_NONE,
     &level.yamyam_content[7].e[0][0],	3, 3,
     NULL, NULL, "8",			NULL
@@ -3095,49 +3217,57 @@ static struct
   /* ---------- magic ball content ----------------------------------------- */
 
   {
-    ED_AREA_MAGIC_BALL_CONTENT_XPOS(0),	ED_AREA_MAGIC_BALL_CONTENT_YPOS(0),
+    ED_AREA_MAGIC_BALL_CONTENT_XPOS,	ED_AREA_MAGIC_BALL_CONTENT_YPOS,
+    ED_AREA_MAGIC_BALL_CONTENT_XOFF(0),	ED_AREA_MAGIC_BALL_CONTENT_YOFF(0),
     GADGET_ID_MAGIC_BALL_CONTENT_0,	GADGET_ID_NONE,
     &level.ball_content[0].e[0][0],	3, 3,
     NULL, NULL, "1",			NULL
   },
   {
-    ED_AREA_MAGIC_BALL_CONTENT_XPOS(1),	ED_AREA_MAGIC_BALL_CONTENT_YPOS(1),
+    ED_AREA_MAGIC_BALL_CONTENT_XPOS,	ED_AREA_MAGIC_BALL_CONTENT_YPOS,
+    ED_AREA_MAGIC_BALL_CONTENT_XOFF(1),	ED_AREA_MAGIC_BALL_CONTENT_YOFF(1),
     GADGET_ID_MAGIC_BALL_CONTENT_1,	GADGET_ID_NONE,
     &level.ball_content[1].e[0][0],	3, 3,
     NULL, NULL, "2",			NULL
   },
   {
-    ED_AREA_MAGIC_BALL_CONTENT_XPOS(2),	ED_AREA_MAGIC_BALL_CONTENT_YPOS(2),
+    ED_AREA_MAGIC_BALL_CONTENT_XPOS,	ED_AREA_MAGIC_BALL_CONTENT_YPOS,
+    ED_AREA_MAGIC_BALL_CONTENT_XOFF(2),	ED_AREA_MAGIC_BALL_CONTENT_YOFF(2),
     GADGET_ID_MAGIC_BALL_CONTENT_2,	GADGET_ID_NONE,
     &level.ball_content[2].e[0][0],	3, 3,
     NULL, NULL, "3",			NULL
   },
   {
-    ED_AREA_MAGIC_BALL_CONTENT_XPOS(3),	ED_AREA_MAGIC_BALL_CONTENT_YPOS(3),
+    ED_AREA_MAGIC_BALL_CONTENT_XPOS,	ED_AREA_MAGIC_BALL_CONTENT_YPOS,
+    ED_AREA_MAGIC_BALL_CONTENT_XOFF(3),	ED_AREA_MAGIC_BALL_CONTENT_YOFF(3),
     GADGET_ID_MAGIC_BALL_CONTENT_3,	GADGET_ID_NONE,
     &level.ball_content[3].e[0][0],	3, 3,
     NULL, NULL, "4",			NULL
   },
   {
-    ED_AREA_MAGIC_BALL_CONTENT_XPOS(4),	ED_AREA_MAGIC_BALL_CONTENT_YPOS(4),
+    ED_AREA_MAGIC_BALL_CONTENT_XPOS,	ED_AREA_MAGIC_BALL_CONTENT_YPOS,
+    ED_AREA_MAGIC_BALL_CONTENT_XOFF(4),	ED_AREA_MAGIC_BALL_CONTENT_YOFF(4),
     GADGET_ID_MAGIC_BALL_CONTENT_4,	GADGET_ID_NONE,
     &level.ball_content[4].e[0][0],	3, 3,
     NULL, NULL, "5",			NULL
   },
   {
-    ED_AREA_MAGIC_BALL_CONTENT_XPOS(5),	ED_AREA_MAGIC_BALL_CONTENT_YPOS(5),
+    ED_AREA_MAGIC_BALL_CONTENT_XPOS,	ED_AREA_MAGIC_BALL_CONTENT_YPOS,
+    ED_AREA_MAGIC_BALL_CONTENT_XOFF(5),	ED_AREA_MAGIC_BALL_CONTENT_YOFF(5),
     GADGET_ID_MAGIC_BALL_CONTENT_5,	GADGET_ID_NONE,
     &level.ball_content[5].e[0][0],	3, 3,
     NULL, NULL, "6",			NULL
   },
   {
-    ED_AREA_MAGIC_BALL_CONTENT_XPOS(6),	ED_AREA_MAGIC_BALL_CONTENT_YPOS(6),
+    ED_AREA_MAGIC_BALL_CONTENT_XPOS,	ED_AREA_MAGIC_BALL_CONTENT_YPOS,
+    ED_AREA_MAGIC_BALL_CONTENT_XOFF(6),	ED_AREA_MAGIC_BALL_CONTENT_YOFF(6),
     GADGET_ID_MAGIC_BALL_CONTENT_6,	GADGET_ID_NONE,
     &level.ball_content[6].e[0][0],	3, 3,
     NULL, NULL, "7",			NULL
   },
   {
-    ED_AREA_MAGIC_BALL_CONTENT_XPOS(7),	ED_AREA_MAGIC_BALL_CONTENT_YPOS(7),
+    ED_AREA_MAGIC_BALL_CONTENT_XPOS,	ED_AREA_MAGIC_BALL_CONTENT_YPOS,
+    ED_AREA_MAGIC_BALL_CONTENT_XOFF(7),	ED_AREA_MAGIC_BALL_CONTENT_YOFF(7),
     GADGET_ID_MAGIC_BALL_CONTENT_7,	GADGET_ID_NONE,
     &level.ball_content[7].e[0][0],	3, 3,
     NULL, NULL, "8",			NULL
@@ -3147,6 +3277,7 @@ static struct
 
   {
     ED_AREA_1X1_SETTINGS_XPOS(0),	ED_AREA_1X1_SETTINGS_YPOS(5),
+    ED_AREA_1X1_SETTINGS_XOFF,		ED_AREA_1X1_SETTINGS_YOFF,
     GADGET_ID_ANDROID_CONTENT,		GADGET_ID_NONE,
     &level.android_clone_element[0],	MAX_ANDROID_ELEMENTS, 1,
     "elements:", NULL, NULL,		"elements android can clone"
@@ -3156,6 +3287,7 @@ static struct
 
   {
     ED_AREA_1X1_SETTINGS_XPOS(0),	ED_AREA_1X1_SETTINGS_YPOS(3),
+    ED_AREA_1X1_SETTINGS_XOFF,		ED_AREA_1X1_SETTINGS_YOFF,
     GADGET_ID_AMOEBA_CONTENT,		GADGET_ID_NONE,
     &level.amoeba_content,		1, 1,
     "content:", NULL, NULL,		"amoeba content"
@@ -3164,7 +3296,8 @@ static struct
   /* ---------- level start element ---------------------------------------- */
 
   {
-    -1,					ED_AREA_1X1_SETTINGS_YPOS(9),
+    -1,					ED_AREA_1X1_SETTINGS_YPOS(10),
+    0,					ED_AREA_1X1_SETTINGS_YOFF,
     GADGET_ID_START_ELEMENT,		GADGET_ID_USE_START_ELEMENT,
     &level.start_element[0],		1, 1,
     NULL, NULL, NULL,			"level start element"
@@ -3173,7 +3306,8 @@ static struct
   /* ---------- player artwork element ------------------------------------- */
 
   {
-    -1,					ED_AREA_1X1_SETTINGS_YPOS(10),
+    -1,					ED_AREA_1X1_SETTINGS_YPOS(11),
+    0,					ED_AREA_1X1_SETTINGS_YOFF,
     GADGET_ID_ARTWORK_ELEMENT,		GADGET_ID_USE_ARTWORK_ELEMENT,
     &level.artwork_element[0],		1, 1,
     NULL, NULL, NULL,			"element for player artwork"
@@ -3182,7 +3316,8 @@ static struct
   /* ---------- player explosion element ----------------------------------- */
 
   {
-    -1,					ED_AREA_1X1_SETTINGS_YPOS(11),
+    -1,					ED_AREA_1X1_SETTINGS_YPOS(12),
+    0,					ED_AREA_1X1_SETTINGS_YOFF,
     GADGET_ID_EXPLOSION_ELEMENT,	GADGET_ID_USE_EXPLOSION_ELEMENT,
     &level.explosion_element[0],	1, 1,
     NULL, NULL, NULL,			"element for player explosion"
@@ -3192,6 +3327,7 @@ static struct
 
   {
     -1,					ED_AREA_1X1_SETTINGS_YPOS(1),
+    0,					ED_AREA_1X1_SETTINGS_YOFF,
     GADGET_ID_INVENTORY_CONTENT,	GADGET_ID_USE_INITIAL_INVENTORY,
     &level.initial_inventory_content[0][0], MAX_INITIAL_INVENTORY_SIZE, 1,
     NULL, NULL, NULL,			"content for initial inventory"
@@ -3203,6 +3339,7 @@ static struct
 
   {
     -1,					ED_AREA_1X1_SETTINGS_YPOS(1),
+    0,					ED_AREA_1X1_SETTINGS_YOFF,
     GADGET_ID_CUSTOM_GRAPHIC,		GADGET_ID_CUSTOM_USE_GRAPHIC,
     &custom_element.gfx_element_initial,1, 1,
     NULL, NULL, NULL,			"custom graphic element"
@@ -3214,6 +3351,7 @@ static struct
 
   {
     -1,					ED_AREA_3X3_SETTINGS_YPOS(10),
+    0,					ED_AREA_3X3_SETTINGS_YOFF,
     GADGET_ID_CUSTOM_CONTENT,		GADGET_ID_NONE,	/* align three rows */
     &custom_element.content.e[0][0],	3, 3,
     "content:", NULL, NULL,		NULL
@@ -3223,12 +3361,14 @@ static struct
 
   {
     ED_AREA_1X1_SETTINGS_XPOS(1),	ED_AREA_1X1_SETTINGS_YPOS(3),
+    ED_AREA_1X1_SETTINGS_XOFF,		ED_AREA_1X1_SETTINGS_YOFF,
     GADGET_ID_CUSTOM_MOVE_ENTER,	GADGET_ID_NONE,
     &custom_element.move_enter_element,	1, 1,
     "can dig:", " ", NULL,		"element that can be digged/collected"
   },
   {
     -1,					ED_AREA_1X1_SETTINGS_YPOS(3),
+    0,					ED_AREA_1X1_SETTINGS_YOFF,
     GADGET_ID_CUSTOM_MOVE_LEAVE,	GADGET_ID_CUSTOM_MOVE_LEAVE_TYPE,
     &custom_element.move_leave_element,	1, 1,
     NULL, NULL, NULL,			"element that will be left behind"
@@ -3240,6 +3380,7 @@ static struct
 
   {
     -1,					ED_AREA_1X1_SETTINGS_YPOS(1),
+    0,					ED_AREA_1X1_SETTINGS_YOFF,
     GADGET_ID_CUSTOM_CHANGE_TARGET,	GADGET_ID_CUSTOM_CAN_CHANGE,
     &custom_element_change.target_element, 1, 1,
     NULL, "after/when:", NULL,		"new target element after change"
@@ -3249,6 +3390,7 @@ static struct
 
   {
     -1,					ED_AREA_3X3_SETTINGS_YPOS(9),
+    0,					ED_AREA_3X3_SETTINGS_YOFF,
     GADGET_ID_CUSTOM_CHANGE_CONTENT,	GADGET_ID_NONE,	/* align three rows */
     &custom_element_change.target_content.e[0][0], 3, 3,
     NULL, NULL, NULL,			"new extended elements after change"
@@ -3258,6 +3400,7 @@ static struct
 
   {
     -1,					ED_AREA_1X1_SETTINGS_YPOS(5),
+    0,					ED_AREA_1X1_SETTINGS_YOFF,
     GADGET_ID_CUSTOM_CHANGE_TRIGGER,	GADGET_ID_CHANGE_OTHER_ACTION,
     &custom_element_change.initial_trigger_element, 1, 1,
     NULL, NULL, NULL,			"other element triggering change"
@@ -3267,6 +3410,7 @@ static struct
 
   {
     -1,					ED_AREA_1X1_SETTINGS_YPOS(13),
+    0,					ED_AREA_1X1_SETTINGS_YOFF,
     GADGET_ID_CUSTOM_CHANGE_ACTION,	GADGET_ID_ACTION_ARG,
     &custom_element_change.action_element, 1, 1,
     NULL, NULL, NULL,			"element used as action parameter"
@@ -3275,7 +3419,8 @@ static struct
   /* ---------- group element content -------------------------------------- */
 
   {
-    ED_AREA_1X1_SETTINGS_XPOS(0),	ED_AREA_1X1_SETTINGS_YPOS(4),
+    ED_AREA_1X1_SETTINGS_XPOS(0),	ED_AREA_1X1_SETTINGS_YPOS(2),
+    ED_AREA_1X1_SETTINGS_XOFF,		ED_AREA_1X1_SETTINGS_YOFF,
     GADGET_ID_GROUP_CONTENT,		GADGET_ID_NONE,
     &group_element_info.element[0],	MAX_ELEMENTS_IN_GROUP, 1,
     "content:", NULL, NULL,		NULL
@@ -3284,7 +3429,8 @@ static struct
   /* ---------- random background (for random painting) -------------------- */
 
   {
-    -1,					ED_AREA_1X1_SETTINGS_YPOS(-1),
+    -1,					ED_AREA_1X1_LSETTINGS_YPOS(1),
+    0,					ED_AREA_1X1_LSETTINGS_YOFF,
     GADGET_ID_RANDOM_BACKGROUND,	GADGET_ID_RANDOM_RESTRICTED,
     &random_placement_background_element, 1, 1,
     NULL, NULL, NULL,			"random placement background"
@@ -3298,21 +3444,19 @@ static struct
   -----------------------------------------------------------------------------
 */
 
+/* maximal size of level editor drawing area */
+static int MAX_ED_FIELDX, MAX_ED_FIELDY;
+
 /* actual size of level editor drawing area */
-#if 1
 static int ed_fieldx, ed_fieldy;
-#else
-static int ed_fieldx = MAX_ED_FIELDX - 1, ed_fieldy = MAX_ED_FIELDY - 1;
-#endif
 
 /* actual position of level editor drawing area in level playfield */
 static int level_xpos = -1, level_ypos = -1;
 
-#if 1
+/* actual tile size used to display playfield drawing area */
+static int ed_tilesize = DEFAULT_EDITOR_TILESIZE;
+
 #define IN_ED_FIELD(x,y)	IN_FIELD(x, y, ed_fieldx, ed_fieldy)
-#else
-#define IN_ED_FIELD(x,y)  ((x)>=0 && (x)<ed_fieldx && (y)>=0 &&(y)<ed_fieldy)
-#endif
 
 /* drawing elements on the three mouse buttons */
 static int new_element1 = EL_WALL;
@@ -3323,7 +3467,15 @@ static int new_element3 = EL_SAND;
 #define BUTTON_ELEMENT(button) ((button) == 1 ? new_element1 : \
 				(button) == 2 ? new_element2 : \
 				(button) == 3 ? new_element3 : EL_EMPTY)
-#define BUTTON_STEPSIZE(button) ((button) == 1 ? 1 : (button) == 2 ? 5 : 10)
+
+#define BUTTON_TILE_SIZE(x)	((x) >= TILESIZE ? TILESIZE : MINI_TILESIZE)
+
+static int use_permanent_palette = TRUE;
+
+#define PX		(use_permanent_palette ? DX : SX)
+#define PY		(use_permanent_palette ? DY : SY)
+#define PXSIZE		(use_permanent_palette ? DXSIZE : SXSIZE)
+#define PYSIZE		(use_permanent_palette ? DYSIZE : SYSIZE)
 
 /* forward declaration for internal use */
 static void ModifyEditorCounterValue(int, int);
@@ -3337,6 +3489,7 @@ static void RedrawDrawingElements();
 static void DrawDrawingWindow();
 static void DrawLevelInfoWindow();
 static void DrawPropertiesWindow();
+static void DrawPaletteWindow();
 static void UpdateCustomElementGraphicGadgets();
 static boolean checkPropertiesConfig(int);
 static void CopyLevelToUndoBuffer(int);
@@ -3353,8 +3506,10 @@ static void HandleControlButtons(struct GadgetInfo *);
 static void HandleDrawingAreaInfo(struct GadgetInfo *);
 static void PrintEditorGadgetInfoText(struct GadgetInfo *);
 
-static struct GadgetInfo *level_editor_gadget[NUM_EDITOR_GADGETS];
-static int right_gadget_border[NUM_EDITOR_GADGETS];
+static int num_editor_gadgets = 0;	/* dynamically determined */
+
+static struct GadgetInfo **level_editor_gadget = NULL;
+static int *right_gadget_border = NULL;
 
 static int drawing_function = GADGET_ID_SINGLE_ITEMS;
 static int last_drawing_function = GADGET_ID_SINGLE_ITEMS;
@@ -3366,6 +3521,7 @@ static short UndoBuffer[NUM_UNDO_STEPS][MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 static short IntelliDrawBuffer[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 static int undo_buffer_position = 0;
 static int undo_buffer_steps = 0;
+static int redo_buffer_steps = 0;
 
 static int edit_mode;
 static int edit_mode_levelinfo;
@@ -4065,13 +4221,13 @@ static int editor_el_chars[] =
   EL_CHAR('^'),
   EL_CHAR('_'),
 
-  EL_CHAR('�'),
-  EL_CHAR('�'),
-  EL_CHAR('�'),
-  EL_CHAR('�'),
+  EL_CHAR(CHAR_BYTE_COPYRIGHT),
+  EL_CHAR(CHAR_BYTE_UMLAUT_A),
+  EL_CHAR(CHAR_BYTE_UMLAUT_O),
+  EL_CHAR(CHAR_BYTE_UMLAUT_U),
 
-  EL_CHAR('�'),
-  EL_CHAR('�'),
+  EL_CHAR(CHAR_BYTE_DEGREE),
+  EL_CHAR(CHAR_BYTE_REGISTERED),
   EL_CHAR(FONT_ASCII_CURSOR),
   EL_CHAR(FONT_ASCII_BUTTON),
 
@@ -4175,13 +4331,13 @@ static int editor_el_steel_chars[] =
   EL_STEEL_CHAR('^'),
   EL_STEEL_CHAR('_'),
 
-  EL_STEEL_CHAR('�'),
-  EL_STEEL_CHAR('�'),
-  EL_STEEL_CHAR('�'),
-  EL_STEEL_CHAR('�'),
+  EL_STEEL_CHAR(CHAR_BYTE_COPYRIGHT),
+  EL_STEEL_CHAR(CHAR_BYTE_UMLAUT_A),
+  EL_STEEL_CHAR(CHAR_BYTE_UMLAUT_O),
+  EL_STEEL_CHAR(CHAR_BYTE_UMLAUT_U),
 
-  EL_STEEL_CHAR('�'),
-  EL_STEEL_CHAR('�'),
+  EL_STEEL_CHAR(CHAR_BYTE_DEGREE),
+  EL_STEEL_CHAR(CHAR_BYTE_REGISTERED),
   EL_STEEL_CHAR(FONT_ASCII_CURSOR),
   EL_STEEL_CHAR(FONT_ASCII_BUTTON),
 
@@ -4656,11 +4812,11 @@ static int *editor_el_dynamic_ptr = NULL;
 static int num_editor_hl_dynamic = SIZEOF_ARRAY_INT(editor_hl_dynamic);
 static int num_editor_el_dynamic = 0;
 
-static int editor_hl_empty[] = { };
-static int editor_el_empty[ED_NUM_ELEMENTLIST_BUTTONS];
+static int editor_hl_empty[] = { EL_EMPTY };
+static int *editor_el_empty = NULL;	/* dynamically allocated */
 
 static int *editor_hl_empty_ptr = editor_hl_empty;
-static int *editor_el_empty_ptr = editor_el_empty;
+static int *editor_el_empty_ptr = NULL;
 static int num_editor_hl_empty = 0;
 static int num_editor_el_empty = 0;	/* dynamically determined, if needed */
 
@@ -4810,7 +4966,7 @@ editor_elements_info[] =
 
 static int getMaxInfoTextLength()
 {
-  return (SXSIZE / getFontWidth(FONT_TEXT_2));
+  return (SXSIZE / getFontWidth(INFOTEXT_FONT));
 }
 
 static int getTextWidthForGadget(char *text)
@@ -4854,27 +5010,47 @@ static char *getElementInfoText(int element)
   return info_text;
 }
 
-char *getElementDescriptionFilename(int element)
+static char *getElementDescriptionFilenameExt(char *basename)
 {
-  char *docs_dir = options.docs_directory;
   char *elements_subdir = "elements";
+  static char *elements_subdir2 = NULL;
   static char *filename = NULL;
-  char basename[MAX_FILENAME_LEN];
+
+  if (elements_subdir2 == NULL)
+    elements_subdir2 = getPath2(DOCS_DIRECTORY, elements_subdir);
 
   checked_free(filename);
 
-  /* 1st try: look for element description file for exactly this element */
-  sprintf(basename, "%s.txt", element_info[element].token_name);
-  filename = getPath3(docs_dir, elements_subdir, basename);
+  /* 1st try: look for element description in current level set directory */
+  filename = getPath3(getCurrentLevelDir(), elements_subdir2, basename);
   if (fileExists(filename))
     return filename;
 
   free(filename);
 
+  /* 2nd try: look for element description in the game's base directory */
+  filename = getPath3(options.docs_directory, elements_subdir, basename);
+  if (fileExists(filename))
+    return filename;
+
+  return NULL;
+}
+
+char *getElementDescriptionFilename(int element)
+{
+  char basename[MAX_FILENAME_LEN];
+  char *filename;
+
+  /* 1st try: look for element description file for exactly this element */
+  sprintf(basename, "%s.txt", element_info[element].token_name);
+  filename = getElementDescriptionFilenameExt(basename);
+  if (filename != NULL)
+    return filename;
+
   /* 2nd try: look for element description file for this element's class */
   sprintf(basename, "%s.txt", element_info[element].class_name);
-  filename = getPath3(docs_dir, elements_subdir, basename);
-  if (fileExists(filename))
+  filename = getElementDescriptionFilenameExt(basename);
+  if (filename != NULL)
     return filename;
 
   return NULL;
@@ -4993,7 +5169,9 @@ static void ReinitializeElementList()
     {
       if (setup.editor.el_headlines)
       {
-	num_editor_elements += *editor_elements_info[i].headline_list_size;
+	// required for correct padding of palette headline buttons
+	if (*editor_elements_info[i].headline_list_size > 0)
+	  num_editor_elements += editor.palette.cols;
 
 	for (j = 0; j < *editor_elements_info[i].headline_list_size; j++)
 	{
@@ -5007,7 +5185,13 @@ static void ReinitializeElementList()
       if (found_inactive_cascade)
 	continue;
 
-      num_editor_elements += *editor_elements_info[i].element_list_size;
+      // required for correct padding of palette element buttons
+      int element_list_size = *editor_elements_info[i].element_list_size;
+      int element_rows =
+	(element_list_size + editor.palette.cols - 1) / editor.palette.cols;
+      int element_buttons = editor.palette.cols * element_rows;
+
+      num_editor_elements += element_buttons;
     }
   }
 
@@ -5031,9 +5215,16 @@ static void ReinitializeElementList()
     {
       if (setup.editor.el_headlines)
       {
-	for (j = 0; j < *editor_elements_info[i].headline_list_size; j++)
+	// required for correct padding of palette headline buttons
+	int headline_size = (*editor_elements_info[i].headline_list_size > 0 ?
+			     editor.palette.cols : 0);
+
+	for (j = 0; j < headline_size; j++)
 	{
-	  int element = (*editor_elements_info[i].headline_list)[j];
+	  // use empty elements for padding of palette headline buttons
+	  int element = (j < *editor_elements_info[i].headline_list_size ?
+			 (*editor_elements_info[i].headline_list)[j] :
+			 editor_el_empty[0]);
 
 	  editor_elements[pos++] = element;
 
@@ -5045,8 +5236,19 @@ static void ReinitializeElementList()
       if (found_inactive_cascade)
 	continue;
 
-      for (j = 0; j < *editor_elements_info[i].element_list_size; j++)
+      // required for correct padding of palette element buttons
+      int element_list_size = *editor_elements_info[i].element_list_size;
+      int element_rows =
+	(element_list_size + editor.palette.cols - 1) / editor.palette.cols;
+      int element_buttons = editor.palette.cols * element_rows;
+
+      // copy all elements from element list
+      for (j = 0; j < element_list_size; j++)
 	editor_elements[pos++] = (*editor_elements_info[i].element_list)[j];
+
+      // use empty elements for padding of palette element buttons
+      for (j = 0; j < element_buttons - element_list_size; j++)
+	editor_elements[pos++] = editor_el_empty[0];
     }
   }
 
@@ -5068,9 +5270,9 @@ void PrintEditorElementList()
       int cascade_element_show = EL_CASCADE_INACTIVE(cascade_element);
       char *headline = element_info[cascade_element_show].editor_description;
 
-      printf_line_with_prefix("# ", "-", 77);
-      printf("# %s\n", headline);
-      printf_line_with_prefix("# ", "-", 77);
+      PrintLineWithPrefix("# ", "-", 77);
+      Print("# %s\n", headline);
+      PrintLineWithPrefix("# ", "-", 77);
     }
 
     for (j = 0; j < *editor_elements_info[i].headline_list_size; j++)
@@ -5080,21 +5282,21 @@ void PrintEditorElementList()
       if (IS_EDITOR_CASCADE(element))
 	element = EL_CHAR_MINUS;
 
-      printf("# %s\n", element_info[element].token_name);
+      Print("# %s\n", element_info[element].token_name);
     }
 
     if (j > 0)
-      printf("#\n");
+      Print("#\n");
 
     for (j = 0; j < *editor_elements_info[i].element_list_size; j++)
     {
       int element = (*editor_elements_info[i].element_list)[j];
 
-      printf("# %s\n", element_info[element].token_name);
+      Print("# %s\n", element_info[element].token_name);
     }
 
     if (j > 0)
-      printf("#\n");
+      Print("#\n");
   }
 }
 
@@ -5135,44 +5337,67 @@ static void DrawElementBorder(int dest_x, int dest_y, int width, int height,
 {
   int border_graphic =
     (input ? IMG_EDITOR_ELEMENT_BORDER_INPUT : IMG_EDITOR_ELEMENT_BORDER);
-  Bitmap *src_bitmap;
-  int src_x, src_y;
-  int bx = (input ? 4 : 8);
-  int by = (input ? 4 : 8);
-  int bx2 = TILEX - bx;
-  int by2 = TILEY - by;
+  struct GraphicInfo *g = &graphic_info[border_graphic];
+  Bitmap *src_bitmap = g->bitmap;
+  int src_x = g->src_x;
+  int src_y = g->src_y;
+  int border_size = g->border_size;
+  int border_xpos = g->width  - border_size;
+  int border_ypos = g->height - border_size;
+  int tilesize = ED_DRAWINGAREA_TILE_SIZE;
   int i;
 
-  getGraphicSource(border_graphic, 0, &src_bitmap, &src_x, &src_y);
-
   BlitBitmap(src_bitmap, drawto, src_x, src_y,
-	     bx, by, dest_x - bx, dest_y - by);
-  BlitBitmap(src_bitmap, drawto, src_x + bx2, src_y,
-	     bx, by, dest_x + width, dest_y - by);
-  BlitBitmap(src_bitmap, drawto, src_x, src_y + by2,
-	     bx, by, dest_x - bx, dest_y + height);
-  BlitBitmap(src_bitmap, drawto, src_x + bx2, src_y + by2,
-	     bx, by, dest_x + width, dest_y + height);
-
-  for (i = 0; i < width / MINI_TILEX; i++)
-  {
-    BlitBitmap(src_bitmap, drawto, src_x + bx, src_y, MINI_TILEX, by,
-	       dest_x + i * MINI_TILEX, dest_y - by);
-    BlitBitmap(src_bitmap, drawto, src_x + bx, src_y + by2, MINI_TILEX, by,
-	       dest_x + i * MINI_TILEX, dest_y + height);
-  }
-
-  for (i = 0; i < height / MINI_TILEY; i++)
-  {
-    BlitBitmap(src_bitmap, drawto, src_x, src_y + by, bx, MINI_TILEY,
-	       dest_x - bx, dest_y + i * MINI_TILEY);
-    BlitBitmap(src_bitmap, drawto, src_x + bx2, src_y + by, bx, MINI_TILEY,
-	       dest_x + width, dest_y + i * MINI_TILEY);
+	     border_size, border_size,
+	     dest_x - border_size, dest_y - border_size);
+  BlitBitmap(src_bitmap, drawto, src_x + border_xpos, src_y,
+	     border_size, border_size,
+	     dest_x + width, dest_y - border_size);
+  BlitBitmap(src_bitmap, drawto, src_x, src_y + border_ypos,
+	     border_size, border_size,
+	     dest_x - border_size, dest_y + height);
+  BlitBitmap(src_bitmap, drawto, src_x + border_xpos, src_y + border_ypos,
+	     border_size, border_size,
+	     dest_x + width, dest_y + height);
+
+  for (i = 0; i < width / tilesize; i++)
+  {
+    BlitBitmap(src_bitmap, drawto, src_x + border_size, src_y,
+	       tilesize, border_size,
+	       dest_x + i * tilesize, dest_y - border_size);
+    BlitBitmap(src_bitmap, drawto, src_x + border_size, src_y + border_ypos,
+	       tilesize, border_size,
+	       dest_x + i * tilesize, dest_y + height);
+  }
+
+  for (i = 0; i < height / tilesize; i++)
+  {
+    BlitBitmap(src_bitmap, drawto, src_x, src_y + border_size,
+	       border_size, tilesize,
+	       dest_x - border_size, dest_y + i * tilesize);
+    BlitBitmap(src_bitmap, drawto, src_x + border_xpos, src_y + border_size,
+	       border_size, tilesize,
+	       dest_x + width, dest_y + i * tilesize);
   }
 
   ClearRectangle(drawto, dest_x - 1, dest_y - 1, width + 2, height + 2);
 }
 
+static void DrawEditorElement(int x, int y, int element)
+{
+  DrawSizedElement(x, y, element, ed_tilesize);
+}
+
+static void DrawEditorElementOrWall(int x, int y, int scroll_x, int scroll_y)
+{
+  DrawSizedElementOrWall(x, y, scroll_x, scroll_y, ed_tilesize);
+}
+
+static void DrawEditorLevel(int size_x, int size_y, int scroll_x, int scroll_y)
+{
+  DrawSizedLevel(size_x, size_y, scroll_x, scroll_y, ed_tilesize);
+}
+
 static void DrawDrawingArea(int id)
 {
   struct GadgetInfo *gi = level_editor_gadget[drawingarea_info[id].gadget_id];
@@ -5181,89 +5406,94 @@ static void DrawDrawingArea(int id)
   int *value = drawingarea_info[id].value;
   int area_xsize = drawingarea_info[id].area_xsize;
   int area_ysize = drawingarea_info[id].area_ysize;
+  int tilesize = ED_DRAWINGAREA_TILE_SIZE;
 
   for (x = 0; x < area_xsize; x++)
     for (y = 0; y < area_ysize; y++)
-      DrawMiniGraphicExt(drawto,
-			 gi->x + x * MINI_TILEX,
-			 gi->y + y * MINI_TILEY,
-			 el2edimg(value[x * area_ysize + y]));
+      DrawSizedGraphicExt(drawto,
+			  gi->x + x * tilesize,
+			  gi->y + y * tilesize,
+			  el2edimg(value[x * area_ysize + y]), 0, tilesize);
 }
 
-static void ScrollMiniLevel(int from_x, int from_y, int scroll)
+static void ScrollEditorLevel(int from_x, int from_y, int scroll)
 {
   int x, y;
   int dx = (scroll == ED_SCROLL_LEFT ? -1 : scroll == ED_SCROLL_RIGHT ? 1 : 0);
   int dy = (scroll == ED_SCROLL_UP   ? -1 : scroll == ED_SCROLL_DOWN  ? 1 : 0);
 
   BlitBitmap(drawto, drawto,
-	     SX + (dx == -1 ? MINI_TILEX : 0),
-	     SY + (dy == -1 ? MINI_TILEY : 0),
-	     (ed_fieldx * MINI_TILEX) - (dx != 0 ? MINI_TILEX : 0),
-	     (ed_fieldy * MINI_TILEY) - (dy != 0 ? MINI_TILEY : 0),
-	     SX + (dx == +1 ? MINI_TILEX : 0),
-	     SY + (dy == +1 ? MINI_TILEY : 0));
+	     SX + (dx == -1 ? ed_tilesize : 0),
+	     SY + (dy == -1 ? ed_tilesize : 0),
+	     (ed_fieldx * ed_tilesize) - (dx != 0 ? ed_tilesize : 0),
+	     (ed_fieldy * ed_tilesize) - (dy != 0 ? ed_tilesize : 0),
+	     SX + (dx == +1 ? ed_tilesize : 0),
+	     SY + (dy == +1 ? ed_tilesize : 0));
 
   if (dx)
   {
     x = (dx == 1 ? 0 : ed_fieldx - 1);
     for (y = 0; y < ed_fieldy; y++)
-      DrawMiniElementOrWall(x, y, from_x, from_y);
+      DrawEditorElementOrWall(x, y, from_x, from_y);
   }
   else if (dy)
   {
     y = (dy == 1 ? 0 : ed_fieldy - 1);
     for (x = 0; x < ed_fieldx; x++)
-      DrawMiniElementOrWall(x, y, from_x, from_y);
+      DrawEditorElementOrWall(x, y, from_x, from_y);
   }
 
   redraw_mask |= REDRAW_FIELD;
   BackToFront();
 }
 
+void getEditorGraphicSource(int element, int tile_size, Bitmap **bitmap,
+			    int *x, int *y)
+{
+  getSizedGraphicSource(el2edimg(element), 0, tile_size, bitmap, x, y);
+}
+
 static void CreateControlButtons()
 {
-  Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
   struct GadgetInfo *gi;
-  unsigned long event_mask;
   int i;
 
   /* create toolbox buttons */
   for (i = 0; i < ED_NUM_CTRL_BUTTONS; i++)
   {
-    int id = i;
-    int width, height;
-    int gd_xoffset, gd_yoffset;
-    int gd_x1, gd_x2, gd_y1, gd_y2;
-    int button_type;
-    int radio_button_nr;
-    boolean checked;
-
-    if (id == GADGET_ID_SINGLE_ITEMS ||
-	id == GADGET_ID_CONNECTED_ITEMS ||
-	id == GADGET_ID_LINE ||
-	id == GADGET_ID_ARC ||
-	id == GADGET_ID_TEXT ||
-	id == GADGET_ID_RECTANGLE ||
-	id == GADGET_ID_FILLED_BOX ||
-	id == GADGET_ID_FLOOD_FILL ||
-	id == GADGET_ID_GRAB_BRUSH ||
-	id == GADGET_ID_PICK_ELEMENT ||
-	id == GADGET_ID_CUSTOM_COPY_FROM ||
-	id == GADGET_ID_CUSTOM_COPY_TO ||
-	id == GADGET_ID_CUSTOM_EXCHANGE)
+    int id = controlbutton_info[i].gadget_id;
+    int type = controlbutton_info[i].gadget_type;
+    int graphic = controlbutton_info[i].graphic;
+    struct XYTileSize *pos = controlbutton_info[i].pos;
+    struct GraphicInfo *gd = &graphic_info[graphic];
+    Bitmap *deco_bitmap = NULL;
+    int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
+    int tile_size = 0, deco_shift = 0;
+    boolean deco_masked = FALSE;
+    int gd_x1 = gd->src_x;
+    int gd_y1 = gd->src_y;
+    int gd_x2 = gd->src_x + gd->pressed_xoffset;
+    int gd_y2 = gd->src_y + gd->pressed_yoffset;
+    int gd_x1a = gd->src_x + gd->active_xoffset;
+    int gd_y1a = gd->src_y + gd->active_yoffset;
+    int gd_x2a = gd->src_x + gd->active_xoffset + gd->pressed_xoffset;
+    int gd_y2a = gd->src_y + gd->active_yoffset + gd->pressed_yoffset;
+    int x = pos->x;
+    int y = pos->y;
+    unsigned int event_mask;
+    int radio_button_nr = RADIO_NR_NONE;
+    boolean checked = FALSE;
+
+    if (type == GD_TYPE_RADIO_BUTTON)
     {
-      button_type = GD_TYPE_RADIO_BUTTON;
-      radio_button_nr = RADIO_NR_DRAWING_TOOLBOX;
-      checked = (id == drawing_function ? TRUE : FALSE);
       event_mask = GD_EVENT_PRESSED;
+      radio_button_nr = RADIO_NR_DRAWING_TOOLBOX;
+
+      if (id == drawing_function)
+	checked = TRUE;
     }
     else
     {
-      button_type = GD_TYPE_NORMAL_BUTTON;
-      radio_button_nr = RADIO_NR_NONE;
-      checked = FALSE;
-
       if (id == GADGET_ID_WRAP_LEFT ||
 	  id == GADGET_ID_WRAP_RIGHT ||
 	  id == GADGET_ID_WRAP_UP ||
@@ -5273,82 +5503,66 @@ static void CreateControlButtons()
 	event_mask = GD_EVENT_RELEASED;
     }
 
-    if (id < ED_NUM_CTRL1_BUTTONS)
+    if (id == GADGET_ID_PROPERTIES ||
+	id == GADGET_ID_PALETTE)
     {
-      int x = i % ED_CTRL1_BUTTONS_HORIZ;
-      int y = i / ED_CTRL1_BUTTONS_HORIZ;
-
-      gd_xoffset = ED_CTRL1_BUTTONS_XPOS + x * ED_CTRL1_BUTTON_XSIZE;
-      gd_yoffset = ED_CTRL1_BUTTONS_YPOS + y * ED_CTRL1_BUTTON_YSIZE;
-      width  = ED_CTRL1_BUTTON_XSIZE;
-      height = ED_CTRL1_BUTTON_YSIZE;
-
-      gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
-      gd_x2 = DOOR_GFX_PAGEX7 + gd_xoffset;
-      gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL1_BUTTONS_GFX_YPOS     + gd_yoffset;
-      gd_y2 = DOOR_GFX_PAGEY1 + ED_CTRL1_BUTTONS_ALT_GFX_YPOS + gd_yoffset;
+      x += DX;
+      y += DY;
     }
-    else if (id < ED_NUM_CTRL1_2_BUTTONS)
+    else if (id == GADGET_ID_ELEMENT_LEFT ||
+	     id == GADGET_ID_ELEMENT_MIDDLE ||
+	     id == GADGET_ID_ELEMENT_RIGHT)
     {
-      int x = (i - ED_NUM_CTRL1_BUTTONS) % ED_CTRL2_BUTTONS_HORIZ;
-      int y = (i - ED_NUM_CTRL1_BUTTONS) / ED_CTRL2_BUTTONS_HORIZ;
-
-      gd_xoffset = ED_CTRL2_BUTTONS_XPOS + x * ED_CTRL2_BUTTON_XSIZE;
-      gd_yoffset = ED_CTRL2_BUTTONS_YPOS + y * ED_CTRL2_BUTTON_YSIZE;
-      width  = ED_CTRL2_BUTTON_XSIZE;
-      height = ED_CTRL2_BUTTON_YSIZE;
-
-      gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
-      gd_x2 = DOOR_GFX_PAGEX7 + gd_xoffset;
-      gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL2_BUTTONS_GFX_YPOS + gd_yoffset;
-      gd_y2 = 0;	/* no alternative graphic for these buttons */
-    }
-    else if (id < ED_NUM_CTRL1_3_BUTTONS)
-    {
-      int x = (i - ED_NUM_CTRL1_2_BUTTONS) % ED_CTRL3_BUTTONS_HORIZ + 1;
-      int y = (i - ED_NUM_CTRL1_2_BUTTONS) / ED_CTRL3_BUTTONS_HORIZ;
-
-      gd_xoffset = ED_CTRL3_BUTTONS_XPOS + x * ED_CTRL3_BUTTON_XSIZE;
-      gd_yoffset = ED_CTRL3_BUTTONS_YPOS + y * ED_CTRL3_BUTTON_YSIZE;
-      width  = ED_CTRL3_BUTTON_XSIZE;
-      height = ED_CTRL3_BUTTON_YSIZE;
-
-      gd_x1 = DOOR_GFX_PAGEX6 + gd_xoffset;
-      gd_x2 = DOOR_GFX_PAGEX5 + gd_xoffset;
-      gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL3_BUTTONS_GFX_YPOS     + gd_yoffset;
-      gd_y2 = DOOR_GFX_PAGEY1 + ED_CTRL3_BUTTONS_ALT_GFX_YPOS + gd_yoffset;
+      x += DX;
+      y += DY;
+
+      int element = (id == GADGET_ID_ELEMENT_LEFT   ? new_element1 :
+		     id == GADGET_ID_ELEMENT_MIDDLE ? new_element2 :
+		     id == GADGET_ID_ELEMENT_RIGHT  ? new_element3 : EL_EMPTY);
+
+      tile_size = BUTTON_TILE_SIZE(id == GADGET_ID_ELEMENT_LEFT ?
+				   editor.button.element_left.tile_size :
+				   id == GADGET_ID_ELEMENT_MIDDLE ?
+				   editor.button.element_middle.tile_size :
+				   id == GADGET_ID_ELEMENT_RIGHT ?
+				   editor.button.element_right.tile_size : 0);
+
+      // make sure that decoration does not overlap gadget border
+      tile_size = MIN(tile_size, MIN(gd->width, gd->height));
+
+      getEditorGraphicSource(element, tile_size, &deco_bitmap, &deco_x,&deco_y);
+
+      deco_xpos = (gd->width  - tile_size) / 2;
+      deco_ypos = (gd->height - tile_size) / 2;
+      deco_shift = 1;
+      deco_masked = gd->draw_masked;
     }
     else
     {
-      int x = (i - ED_NUM_CTRL1_3_BUTTONS) % ED_CTRL4_BUTTONS_HORIZ;
-      int y = (i - ED_NUM_CTRL1_3_BUTTONS) / ED_CTRL4_BUTTONS_HORIZ + 3;
-
-      gd_xoffset = ED_CTRL4_BUTTONS_XPOS + x * ED_CTRL4_BUTTON_XSIZE;
-      gd_yoffset = ED_CTRL4_BUTTONS_YPOS + y * ED_CTRL4_BUTTON_YSIZE;
-      width  = ED_CTRL4_BUTTON_XSIZE;
-      height = ED_CTRL4_BUTTON_YSIZE;
-
-      gd_x1 = DOOR_GFX_PAGEX6 + ED_CTRL4_BUTTONS_GFX_XPOS + gd_xoffset;
-      gd_x2 = DOOR_GFX_PAGEX5 + ED_CTRL4_BUTTONS_GFX_XPOS + gd_xoffset;
-      gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL4_BUTTONS_GFX_YPOS + gd_yoffset;
-      gd_y2 = 0;	/* no alternative graphic for these buttons */
+      x += EX;
+      y += EY;
     }
 
     gi = CreateGadget(GDI_CUSTOM_ID, id,
 		      GDI_CUSTOM_TYPE_ID, i,
-		      GDI_INFO_TEXT, control_info[i].text,
-		      GDI_X, EX + gd_xoffset,
-		      GDI_Y, EY + gd_yoffset,
-		      GDI_WIDTH, width,
-		      GDI_HEIGHT, height,
-		      GDI_TYPE, button_type,
+		      GDI_INFO_TEXT, controlbutton_info[i].infotext,
+		      GDI_X, x,
+		      GDI_Y, y,
+		      GDI_WIDTH, gd->width,
+		      GDI_HEIGHT, gd->height,
+		      GDI_TYPE, type,
 		      GDI_STATE, GD_BUTTON_UNPRESSED,
 		      GDI_RADIO_NR, radio_button_nr,
 		      GDI_CHECKED, checked,
-		      GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y1,
-		      GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y1,
-		      GDI_ALT_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y2,
-		      GDI_ALT_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y2,
+		      GDI_DESIGN_UNPRESSED, gd->bitmap, gd_x1, gd_y1,
+		      GDI_DESIGN_PRESSED, gd->bitmap, gd_x2, gd_y2,
+		      GDI_ALT_DESIGN_UNPRESSED, gd->bitmap, gd_x1a, gd_y1a,
+		      GDI_ALT_DESIGN_PRESSED, gd->bitmap, gd_x2a, gd_y2a,
+		      GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
+		      GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
+		      GDI_DECORATION_SIZE, tile_size, tile_size,
+		      GDI_DECORATION_SHIFTING, deco_shift, deco_shift,
+		      GDI_DECORATION_MASKED, deco_masked,
 		      GDI_EVENT_MASK, event_mask,
 		      GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
 		      GDI_CALLBACK_ACTION, HandleControlButtons,
@@ -5361,49 +5575,46 @@ static void CreateControlButtons()
   }
 
   /* these values are not constant, but can change at runtime */
-  scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_UP].x    = ED_SCROLL_UP_XPOS;
-  scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_UP].y    = ED_SCROLL_UP_YPOS;
-  scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_DOWN].x  = ED_SCROLL_DOWN_XPOS;
-  scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_DOWN].y  = ED_SCROLL_DOWN_YPOS;
-  scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_LEFT].x  = ED_SCROLL_LEFT_XPOS;
-  scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_LEFT].y  = ED_SCROLL_LEFT_YPOS;
-  scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_RIGHT].x = ED_SCROLL_RIGHT_XPOS;
-  scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_RIGHT].y = ED_SCROLL_RIGHT_YPOS;
+  scrollbutton_pos[ED_SCROLLBUTTON_ID_AREA_UP].x    = ED_SCROLL_UP_XPOS;
+  scrollbutton_pos[ED_SCROLLBUTTON_ID_AREA_UP].y    = ED_SCROLL_UP_YPOS;
+  scrollbutton_pos[ED_SCROLLBUTTON_ID_AREA_DOWN].x  = ED_SCROLL_DOWN_XPOS;
+  scrollbutton_pos[ED_SCROLLBUTTON_ID_AREA_DOWN].y  = ED_SCROLL_DOWN_YPOS;
+  scrollbutton_pos[ED_SCROLLBUTTON_ID_AREA_LEFT].x  = ED_SCROLL_LEFT_XPOS;
+  scrollbutton_pos[ED_SCROLLBUTTON_ID_AREA_LEFT].y  = ED_SCROLL_LEFT_YPOS;
+  scrollbutton_pos[ED_SCROLLBUTTON_ID_AREA_RIGHT].x = ED_SCROLL_RIGHT_XPOS;
+  scrollbutton_pos[ED_SCROLLBUTTON_ID_AREA_RIGHT].y = ED_SCROLL_RIGHT_YPOS;
+  scrollbutton_pos[ED_SCROLLBUTTON_ID_LIST_UP].x    = ED_SCROLL2_UP_XPOS;
+  scrollbutton_pos[ED_SCROLLBUTTON_ID_LIST_UP].y    = ED_SCROLL2_UP_YPOS;
+  scrollbutton_pos[ED_SCROLLBUTTON_ID_LIST_DOWN].x  = ED_SCROLL2_DOWN_XPOS;
+  scrollbutton_pos[ED_SCROLLBUTTON_ID_LIST_DOWN].y  = ED_SCROLL2_DOWN_YPOS;
 
   /* create buttons for scrolling of drawing area and element list */
   for (i = 0; i < ED_NUM_SCROLLBUTTONS; i++)
   {
     int id = scrollbutton_info[i].gadget_id;
-    int x, y, width, height;
-    int gd_x1, gd_x2, gd_y1, gd_y2;
-
-    x = scrollbutton_info[i].x;
-    y = scrollbutton_info[i].y;
-
-    event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
+    int graphic = scrollbutton_info[i].graphic;
+    struct GraphicInfo *gd = &graphic_info[graphic];
+    Bitmap *gd_bitmap = gd->bitmap;
+    int gd_x1 = gd->src_x;
+    int gd_y1 = gd->src_y;
+    int gd_x2 = gd->src_x + gd->pressed_xoffset;
+    int gd_y2 = gd->src_y + gd->pressed_yoffset;
+    int width  = gd->width;
+    int height = gd->height;
+    int x = scrollbutton_pos[i].x;
+    int y = scrollbutton_pos[i].y;
+    unsigned int event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
 
     if (id == GADGET_ID_SCROLL_LIST_UP ||
 	id == GADGET_ID_SCROLL_LIST_DOWN)
     {
-      x += DX;
-      y += DY;
-      width = ED_SCROLLBUTTON2_XSIZE;
-      height = ED_SCROLLBUTTON2_YSIZE;
-      gd_x1 = DOOR_GFX_PAGEX8 + scrollbutton_info[i].gd_x;
-      gd_y1 = DOOR_GFX_PAGEY1 + scrollbutton_info[i].gd_y;
-      gd_x2 = gd_x1 - ED_SCROLLBUTTON2_XSIZE;
-      gd_y2 = gd_y1;
+      x += PX;
+      y += PY;
     }
     else
     {
       x += SX;
       y += SY;
-      width = ED_SCROLLBUTTON_XSIZE;
-      height = ED_SCROLLBUTTON_YSIZE;
-      gd_x1 = DOOR_GFX_PAGEX8 + scrollbutton_info[i].gd_x;
-      gd_y1 = DOOR_GFX_PAGEY1 + scrollbutton_info[i].gd_y;
-      gd_x2 = gd_x1 - ED_SCROLLBUTTON_XSIZE;
-      gd_y2 = gd_y1;
     }
 
     gi = CreateGadget(GDI_CUSTOM_ID, id,
@@ -5431,42 +5642,43 @@ static void CreateControlButtons()
   /* create buttons for element list */
   for (i = 0; i < ED_NUM_ELEMENTLIST_BUTTONS; i++)
   {
+    int id = GADGET_ID_ELEMENTLIST_FIRST + i;
+    int graphic = IMG_EDITOR_PALETTE_BUTTON;
+    struct GraphicInfo *gd = &graphic_info[graphic];
+    Bitmap *gd_bitmap = gd->bitmap;
     Bitmap *deco_bitmap;
     int deco_x, deco_y, deco_xpos, deco_ypos;
-    int gd_xoffset, gd_yoffset;
-    int gd_x1, gd_x2, gd_y;
-    int x = i % ED_ELEMENTLIST_BUTTONS_HORIZ;
-    int y = i / ED_ELEMENTLIST_BUTTONS_HORIZ;
-    int id = GADGET_ID_ELEMENTLIST_FIRST + i;
+    int gd_x1 = gd->src_x;
+    int gd_y1 = gd->src_y;
+    int gd_x2 = gd->src_x + gd->pressed_xoffset;
+    int gd_y2 = gd->src_y + gd->pressed_yoffset;
+    int xx = i % ED_ELEMENTLIST_BUTTONS_HORIZ;
+    int yy = i / ED_ELEMENTLIST_BUTTONS_HORIZ;
+    int x = PX + ED_ELEMENTLIST_XPOS + xx * gd->width;
+    int y = PY + ED_ELEMENTLIST_YPOS + yy * gd->height;
     int element = editor_elements[i];
+    int tile_size = BUTTON_TILE_SIZE(editor.palette.tile_size);
+    unsigned int event_mask = GD_EVENT_RELEASED;
 
-    event_mask = GD_EVENT_RELEASED;
-
-    gd_xoffset = ED_ELEMENTLIST_XPOS + x * ED_ELEMENTLIST_XSIZE;
-    gd_yoffset = ED_ELEMENTLIST_YPOS + y * ED_ELEMENTLIST_YSIZE;
-
-    gd_x1 = DOOR_GFX_PAGEX6 + ED_ELEMENTLIST_XPOS + ED_ELEMENTLIST_XSIZE;
-    gd_x2 = DOOR_GFX_PAGEX6 + ED_ELEMENTLIST_XPOS;
-    gd_y  = DOOR_GFX_PAGEY1 + ED_ELEMENTLIST_YPOS;
+    getEditorGraphicSource(element, tile_size, &deco_bitmap, &deco_x, &deco_y);
 
-    getMiniGraphicSource(el2edimg(element), &deco_bitmap, &deco_x, &deco_y);
-    deco_xpos = (ED_ELEMENTLIST_XSIZE - MINI_TILEX) / 2;
-    deco_ypos = (ED_ELEMENTLIST_YSIZE - MINI_TILEY) / 2;
+    deco_xpos = (gd->width  - tile_size) / 2;
+    deco_ypos = (gd->height - tile_size) / 2;
 
     gi = CreateGadget(GDI_CUSTOM_ID, id,
 		      GDI_CUSTOM_TYPE_ID, i,
 		      GDI_INFO_TEXT, getElementInfoText(element),
-		      GDI_X, DX + gd_xoffset,
-		      GDI_Y, DY + gd_yoffset,
-		      GDI_WIDTH, ED_ELEMENTLIST_XSIZE,
-		      GDI_HEIGHT, ED_ELEMENTLIST_YSIZE,
+		      GDI_X, x,
+		      GDI_Y, y,
+		      GDI_WIDTH, gd->width,
+		      GDI_HEIGHT, gd->height,
 		      GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
 		      GDI_STATE, GD_BUTTON_UNPRESSED,
-		      GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
-		      GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
+		      GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y1,
+		      GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y2,
 		      GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
 		      GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
-		      GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
+		      GDI_DECORATION_SIZE, tile_size, tile_size,
 		      GDI_DECORATION_SHIFTING, 1, 1,
 		      GDI_EVENT_MASK, event_mask,
 		      GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
@@ -5485,15 +5697,11 @@ static void CreateCounterButtons()
   int max_infotext_len = getMaxInfoTextLength();
   int i;
 
-  /* these values are not constant, but can change at runtime */
-  counterbutton_info[ED_COUNTER_ID_SELECT_LEVEL].x = DX + 5 - SX;
-  counterbutton_info[ED_COUNTER_ID_SELECT_LEVEL].y = DY + 3 - SY;
-
   for (i = 0; i < ED_NUM_COUNTERBUTTONS; i++)
   {
     int j;
-    int x = SX + counterbutton_info[i].x;	/* down count button */
-    int y = SY + counterbutton_info[i].y;
+    int x = SX + ED_SETTINGS_X(counterbutton_info[i].x); /* down count button */
+    int y = SY + ED_SETTINGS_Y(counterbutton_info[i].y);
 
     /* determine horizontal position to the right of specified gadget */
     if (counterbutton_info[i].gadget_id_align != GADGET_ID_NONE)
@@ -5506,47 +5714,51 @@ static void CreateCounterButtons()
 
     for (j = 0; j < 2; j++)
     {
-      Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
       struct GadgetInfo *gi;
       int id = (j == 0 ?
 		counterbutton_info[i].gadget_id_down :
 		counterbutton_info[i].gadget_id_up);
-      int gd_xoffset;
-      int gd_x, gd_x1, gd_x2, gd_y;
-      int x_size, y_size;
-      unsigned long event_mask;
+      int graphic;
+      struct GraphicInfo *gd;
+      int gd_x1, gd_x2, gd_y1, gd_y2;
+      unsigned int event_mask;
       char infotext[max_infotext_len + 1];
 
       event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
 
       if (i == ED_COUNTER_ID_SELECT_LEVEL)
       {
-	int sid = (j == 0 ?
-		   ED_SCROLLBUTTON_ID_AREA_LEFT :
-		   ED_SCROLLBUTTON_ID_AREA_RIGHT);
+	graphic = (j == 0 ?
+		   IMG_GFX_EDITOR_BUTTON_PREV_LEVEL :
+		   IMG_GFX_EDITOR_BUTTON_NEXT_LEVEL);
 
 	event_mask |= GD_EVENT_RELEASED;
 
-	if (j == 1)
-	  x += 2 * ED_GADGET_DISTANCE;
-	y += ED_GADGET_DISTANCE;
-
-	gd_x1 = DOOR_GFX_PAGEX8 + scrollbutton_info[sid].gd_x;
-	gd_x2 = gd_x1 - ED_SCROLLBUTTON_XSIZE;
-	gd_y  = DOOR_GFX_PAGEY1 + scrollbutton_info[sid].gd_y;
-	x_size = ED_SCROLLBUTTON_XSIZE;
-	y_size = ED_SCROLLBUTTON_YSIZE;
+	if (j == 0)
+	{
+	  x = DX + editor.button.prev_level.x;
+	  y = DY + editor.button.prev_level.y;
+	}
+	else
+	{
+	  x = DX + editor.button.next_level.x;
+	  y = DY + editor.button.next_level.y;
+	}
       }
       else
       {
-	gd_xoffset = (j == 0 ? ED_BUTTON_MINUS_XPOS : ED_BUTTON_PLUS_XPOS);
-	gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
-	gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
-	gd_y  = DOOR_GFX_PAGEY1 + ED_BUTTON_COUNT_YPOS;
-	x_size = ED_BUTTON_COUNT_XSIZE;
-	y_size = ED_BUTTON_COUNT_YSIZE;
+	graphic = (j == 0 ?
+		   IMG_EDITOR_COUNTER_DOWN :
+		   IMG_EDITOR_COUNTER_UP);
       }
 
+      gd = &graphic_info[graphic];
+
+      gd_x1 = gd->src_x;
+      gd_y1 = gd->src_y;
+      gd_x2 = gd->src_x + gd->pressed_xoffset;
+      gd_y2 = gd->src_y + gd->pressed_yoffset;
+
       sprintf(infotext, "%s counter value by 1, 5 or 10",
 	      (j == 0 ? "decrease" : "increase"));
 
@@ -5555,12 +5767,12 @@ static void CreateCounterButtons()
 			GDI_INFO_TEXT, infotext,
 			GDI_X, x,
 			GDI_Y, y,
-			GDI_WIDTH, x_size,
-			GDI_HEIGHT, y_size,
+			GDI_WIDTH, gd->width,
+			GDI_HEIGHT, gd->height,
 			GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
 			GDI_STATE, GD_BUTTON_UNPRESSED,
-			GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
-			GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
+			GDI_DESIGN_UNPRESSED, gd->bitmap, gd_x1, gd_y1,
+			GDI_DESIGN_PRESSED, gd->bitmap, gd_x2, gd_y2,
 			GDI_EVENT_MASK, event_mask,
 			GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
 			GDI_CALLBACK_ACTION, HandleCounterButtons,
@@ -5573,38 +5785,39 @@ static void CreateCounterButtons()
       right_gadget_border[id] =
 	getRightGadgetBorder(gi, counterbutton_info[i].text_right);
 
-      x += gi->width + ED_GADGET_DISTANCE;	/* text count button */
+      x += gi->width + ED_GADGET_SMALL_DISTANCE;	/* text count button */
 
       if (j == 0)
       {
 	int font_type = FONT_INPUT_1;
 	int font_type_active = FONT_INPUT_1_ACTIVE;
-	int gd_width = ED_WIN_COUNT_XSIZE;
 
 	id = counterbutton_info[i].gadget_id_text;
+
 	event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
 
 	if (i == ED_COUNTER_ID_SELECT_LEVEL)
 	{
+	  graphic = IMG_GFX_EDITOR_INPUT_LEVEL_NUMBER;
+
 	  font_type = FONT_LEVEL_NUMBER;
-#if 1
 	  font_type_active = FONT_LEVEL_NUMBER_ACTIVE;
-#else
-	  font_type_active = FONT_LEVEL_NUMBER;
-#endif
-	  x += 2 * ED_GADGET_DISTANCE;
-	  y -= ED_GADGET_DISTANCE;
 
-	  gd_x = DOOR_GFX_PAGEX6 + ED_WIN_COUNT2_XPOS;
-	  gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT2_YPOS;
-	  gd_width = ED_WIN_COUNT2_XSIZE;
+	  x = DX + editor.input.level_number.x;
+	  y = DY + editor.input.level_number.y;
 	}
 	else
 	{
-	  gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS;
-	  gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS;
+	  graphic = IMG_EDITOR_COUNTER_INPUT;
 	}
 
+	gd = &graphic_info[graphic];
+
+	gd_x1 = gd->src_x;
+	gd_y1 = gd->src_y;
+	gd_x2 = gd->src_x + gd->active_xoffset;
+	gd_y2 = gd->src_y + gd->active_yoffset;
+
 	gi = CreateGadget(GDI_CUSTOM_ID, id,
 			  GDI_CUSTOM_TYPE_ID, i,
 			  GDI_INFO_TEXT, "enter counter value",
@@ -5617,10 +5830,10 @@ static void CreateCounterButtons()
 			  GDI_TEXT_SIZE, 3,	/* minimal counter text size */
 			  GDI_TEXT_FONT, font_type,
 			  GDI_TEXT_FONT_ACTIVE, font_type_active,
-			  GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x, gd_y,
-			  GDI_DESIGN_PRESSED, gd_bitmap, gd_x, gd_y,
-			  GDI_BORDER_SIZE, ED_BORDER_SIZE, ED_BORDER_SIZE,
-			  GDI_DESIGN_WIDTH, gd_width,
+			  GDI_DESIGN_UNPRESSED, gd->bitmap, gd_x1, gd_y1,
+			  GDI_DESIGN_PRESSED, gd->bitmap, gd_x2, gd_y2,
+			  GDI_BORDER_SIZE, gd->border_size, gd->border_size,
+			  GDI_DESIGN_WIDTH, gd->width,
 			  GDI_EVENT_MASK, event_mask,
 			  GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
 			  GDI_CALLBACK_ACTION, HandleCounterButtons,
@@ -5633,7 +5846,7 @@ static void CreateCounterButtons()
 	right_gadget_border[id] =
 	  getRightGadgetBorder(gi, counterbutton_info[i].text_right);
 
-	x += gi->width + ED_GADGET_DISTANCE;	/* up count button */
+	x += gi->width + ED_GADGET_SMALL_DISTANCE;	/* up count button */
       }
     }
   }
@@ -5650,12 +5863,14 @@ static void CreateDrawingAreas()
   for (i = 0; i < ED_NUM_DRAWING_AREAS; i++)
   {
     struct GadgetInfo *gi;
-    unsigned long event_mask;
+    unsigned int event_mask;
     int id = drawingarea_info[i].gadget_id;
-    int x = SX + drawingarea_info[i].x;
-    int y = SY + drawingarea_info[i].y;
+    int x = SX + ED_AREA_SETTINGS_X(drawingarea_info[i]);
+    int y = SY + ED_AREA_SETTINGS_Y(drawingarea_info[i]);
     int area_xsize = drawingarea_info[i].area_xsize;
     int area_ysize = drawingarea_info[i].area_ysize;
+    int item_size = (id == GADGET_ID_DRAWING_LEVEL ?
+		     ed_tilesize : ED_DRAWINGAREA_TILE_SIZE);
 
     event_mask =
       GD_EVENT_PRESSED | GD_EVENT_RELEASED | GD_EVENT_MOVING |
@@ -5676,7 +5891,7 @@ static void CreateDrawingAreas()
 		      GDI_Y, y,
 		      GDI_TYPE, GD_TYPE_DRAWING_AREA,
 		      GDI_AREA_SIZE, area_xsize, area_ysize,
-		      GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
+		      GDI_ITEM_SIZE, item_size, item_size,
 		      GDI_EVENT_MASK, event_mask,
 		      GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
 		      GDI_CALLBACK_ACTION, HandleDrawingAreas,
@@ -5693,22 +5908,45 @@ static void CreateDrawingAreas()
 
 static void CreateTextInputGadgets()
 {
+  struct GraphicInfo *gd = &graphic_info[IMG_EDITOR_INPUT_TEXT];
   int max_infotext_len = getMaxInfoTextLength();
   int i;
 
   for (i = 0; i < ED_NUM_TEXTINPUT; i++)
   {
-    Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
-    int gd_x, gd_y;
+    int gd_x1 = gd->src_x;
+    int gd_y1 = gd->src_y;
+    int gd_x2 = gd->src_x + gd->active_xoffset;
+    int gd_y2 = gd->src_y + gd->active_yoffset;
     struct GadgetInfo *gi;
-    unsigned long event_mask;
+    unsigned int event_mask;
     char infotext[MAX_OUTPUT_LINESIZE + 1];
     int id = textinput_info[i].gadget_id;
+    int x, y;
 
-    event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
+    if (i == ED_TEXTINPUT_ID_ELEMENT_NAME)
+    {
+      int element_border = graphic_info[IMG_EDITOR_ELEMENT_BORDER].border_size;
+      int border_size = gd->border_size;
+      int font_nr = FONT_INPUT_1;
+      int font_height = getFontHeight(font_nr);
+      int xoffset = element_border + TILEX + element_border + 3 * border_size;
+      int yoffset = element_border + (TILEY - font_height) / 2;
+
+      x = (editor.settings.element_name.x != -1 ?
+	   editor.settings.element_name.x :
+	   editor.settings.element_graphic.x + xoffset) - border_size;
+      y = (editor.settings.element_name.y != -1 ?
+	   editor.settings.element_name.y :
+	   editor.settings.element_graphic.y + yoffset) - border_size;
+    }
+    else
+    {
+      x = ED_SETTINGS_X(textinput_info[i].x);
+      y = ED_SETTINGS_Y(textinput_info[i].y);
+    }
 
-    gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS;
-    gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS;
+    event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
 
     sprintf(infotext, "Enter %s", textinput_info[i].infotext);
     infotext[max_infotext_len] = '\0';
@@ -5716,17 +5954,17 @@ static void CreateTextInputGadgets()
     gi = CreateGadget(GDI_CUSTOM_ID, id,
 		      GDI_CUSTOM_TYPE_ID, i,
 		      GDI_INFO_TEXT, infotext,
-		      GDI_X, SX + textinput_info[i].x,
-		      GDI_Y, SY + textinput_info[i].y,
+		      GDI_X, SX + x,
+		      GDI_Y, SY + y,
 		      GDI_TYPE, GD_TYPE_TEXT_INPUT_ALPHANUMERIC,
 		      GDI_TEXT_VALUE, textinput_info[i].value,
 		      GDI_TEXT_SIZE, textinput_info[i].size,
 		      GDI_TEXT_FONT, FONT_INPUT_1,
 		      GDI_TEXT_FONT_ACTIVE, FONT_INPUT_1_ACTIVE,
-		      GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x, gd_y,
-		      GDI_DESIGN_PRESSED, gd_bitmap, gd_x, gd_y,
-		      GDI_BORDER_SIZE, ED_BORDER_SIZE, ED_BORDER_SIZE,
-		      GDI_DESIGN_WIDTH, ED_WIN_COUNT_XSIZE,
+		      GDI_DESIGN_UNPRESSED, gd->bitmap, gd_x1, gd_y1,
+		      GDI_DESIGN_PRESSED, gd->bitmap, gd_x2, gd_y2,
+		      GDI_BORDER_SIZE, gd->border_size, gd->border_size,
+		      GDI_DESIGN_WIDTH, gd->width,
 		      GDI_EVENT_MASK, event_mask,
 		      GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
 		      GDI_CALLBACK_ACTION, HandleTextInputGadgets,
@@ -5746,10 +5984,13 @@ static void CreateTextAreaGadgets()
 
   for (i = 0; i < ED_NUM_TEXTAREAS; i++)
   {
-    Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
-    int gd_x, gd_y;
+    struct GraphicInfo *gd = &graphic_info[IMG_EDITOR_INPUT_TEXTAREA];
+    int gd_x1 = gd->src_x;
+    int gd_y1 = gd->src_y;
+    int gd_x2 = gd->src_x + gd->active_xoffset;
+    int gd_y2 = gd->src_y + gd->active_yoffset;
     struct GadgetInfo *gi;
-    unsigned long event_mask;
+    unsigned int event_mask;
     char infotext[MAX_OUTPUT_LINESIZE + 1];
     int id = textarea_info[i].gadget_id;
     int area_xsize = textarea_info[i].xsize;
@@ -5757,25 +5998,22 @@ static void CreateTextAreaGadgets()
 
     event_mask = GD_EVENT_TEXT_LEAVING;
 
-    gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS;
-    gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS;
-
     sprintf(infotext, "Enter %s", textarea_info[i].infotext);
     infotext[max_infotext_len] = '\0';
 
     gi = CreateGadget(GDI_CUSTOM_ID, id,
 		      GDI_CUSTOM_TYPE_ID, i,
 		      GDI_INFO_TEXT, infotext,
-		      GDI_X, SX + textarea_info[i].x,
-		      GDI_Y, SY + textarea_info[i].y,
+		      GDI_X, SX + ED_SETTINGS_X(textarea_info[i].x),
+		      GDI_Y, SY + ED_SETTINGS_Y(textarea_info[i].y),
 		      GDI_TYPE, GD_TYPE_TEXT_AREA,
 		      GDI_AREA_SIZE, area_xsize, area_ysize,
 		      GDI_TEXT_FONT, FONT_INPUT_1,
 		      GDI_TEXT_FONT_ACTIVE, FONT_INPUT_1_ACTIVE,
-		      GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x, gd_y,
-		      GDI_DESIGN_PRESSED, gd_bitmap, gd_x, gd_y,
-		      GDI_BORDER_SIZE, ED_BORDER_SIZE, ED_BORDER_SIZE,
-		      GDI_DESIGN_WIDTH, ED_WIN_COUNT_XSIZE,
+		      GDI_DESIGN_UNPRESSED, gd->bitmap, gd_x1, gd_y1,
+		      GDI_DESIGN_PRESSED, gd->bitmap, gd_x2, gd_y2,
+		      GDI_BORDER_SIZE, gd->border_size, gd->border_size,
+		      GDI_DESIGN_WIDTH, gd->width,
 		      GDI_EVENT_MASK, event_mask,
 		      GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
 		      GDI_CALLBACK_ACTION, HandleTextAreaGadgets,
@@ -5795,14 +6033,19 @@ static void CreateSelectboxGadgets()
 
   for (i = 0; i < ED_NUM_SELECTBOX; i++)
   {
-    Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
-    int gd_x, gd_y;
+    struct GraphicInfo *gd = &graphic_info[IMG_EDITOR_SELECTBOX_INPUT];
+    struct GraphicInfo *gd2 = &graphic_info[IMG_EDITOR_SELECTBOX_BUTTON];
+    int gd_x1 = gd->src_x;
+    int gd_y1 = gd->src_y;
+    int gd_x2 = gd->src_x + gd->active_xoffset;
+    int gd_y2 = gd->src_y + gd->active_yoffset;
+    int selectbox_button_xsize = gd2->width;
     struct GadgetInfo *gi;
-    unsigned long event_mask;
+    unsigned int event_mask;
     char infotext[MAX_OUTPUT_LINESIZE + 1];
     int id = selectbox_info[i].gadget_id;
-    int x = SX + selectbox_info[i].x;
-    int y = SY + selectbox_info[i].y;
+    int x = SX + ED_SETTINGS_X(selectbox_info[i].x);
+    int y = SY + ED_SETTINGS_Y(selectbox_info[i].y);
 
     if (selectbox_info[i].size == -1)	/* dynamically determine size */
     {
@@ -5821,9 +6064,6 @@ static void CreateSelectboxGadgets()
     event_mask = GD_EVENT_RELEASED |
       GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
 
-    gd_x = DOOR_GFX_PAGEX4 + ED_SELECTBOX_XPOS;
-    gd_y = DOOR_GFX_PAGEY1 + ED_SELECTBOX_YPOS;
-
     /* determine horizontal position to the right of specified gadget */
     if (selectbox_info[i].gadget_id_align != GADGET_ID_NONE)
       x = (right_gadget_border[selectbox_info[i].gadget_id_align] +
@@ -5843,14 +6083,16 @@ static void CreateSelectboxGadgets()
 		      GDI_Y, y,
 		      GDI_TYPE, GD_TYPE_SELECTBOX,
 		      GDI_SELECTBOX_OPTIONS, selectbox_info[i].options,
+		      GDI_SELECTBOX_CHAR_UNSELECTABLE, '[',
 		      GDI_TEXT_SIZE, selectbox_info[i].size,
 		      GDI_TEXT_FONT, FONT_INPUT_1,
 		      GDI_TEXT_FONT_ACTIVE, FONT_INPUT_1_ACTIVE,
-		      GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x, gd_y,
-		      GDI_DESIGN_PRESSED, gd_bitmap, gd_x, gd_y,
-		      GDI_BORDER_SIZE, ED_BORDER_SIZE, ED_BORDER_SIZE,
-		      GDI_BORDER_SIZE_SELECTBUTTON, ED_SELECTBOX_BUTTON_XSIZE,
-		      GDI_DESIGN_WIDTH, ED_WIN_COUNT_XSIZE,
+		      GDI_TEXT_FONT_UNSELECTABLE, FONT_TEXT_1,
+		      GDI_DESIGN_UNPRESSED, gd->bitmap, gd_x1, gd_y1,
+		      GDI_DESIGN_PRESSED, gd->bitmap, gd_x2, gd_y2,
+		      GDI_BORDER_SIZE, gd->border_size, gd->border_size,
+		      GDI_BORDER_SIZE_SELECTBUTTON, selectbox_button_xsize,
+		      GDI_DESIGN_WIDTH, gd->width,
 		      GDI_EVENT_MASK, event_mask,
 		      GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
 		      GDI_CALLBACK_ACTION, HandleSelectboxGadgets,
@@ -5872,43 +6114,47 @@ static void CreateTextbuttonGadgets()
 
   for (i = 0; i < ED_NUM_TEXTBUTTONS; i++)
   {
-    Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
-    int gd_x1, gd_x2, gd_y1, gd_y2;
+    int id = textbutton_info[i].gadget_id;
+    int is_tab_button =
+      ((id >= GADGET_ID_LEVELINFO_LEVEL && id <= GADGET_ID_LEVELINFO_EDITOR) ||
+       (id >= GADGET_ID_PROPERTIES_INFO && id <= GADGET_ID_PROPERTIES_CHANGE));
+    int graphic =
+      (is_tab_button ? IMG_EDITOR_TABBUTTON : IMG_EDITOR_TEXTBUTTON);
+    int gadget_distance =
+      (is_tab_button ? ED_GADGET_SMALL_DISTANCE : ED_GADGET_TEXT_DISTANCE);
+    struct GraphicInfo *gd = &graphic_info[graphic];
+    int gd_x1 = gd->src_x;
+    int gd_y1 = gd->src_y;
+    int gd_x2 = gd->src_x + gd->pressed_xoffset;
+    int gd_y2 = gd->src_y + gd->pressed_yoffset;
+    int gd_x1a = gd->src_x + gd->active_xoffset;
+    int gd_y1a = gd->src_y + gd->active_yoffset;
+    int border_xsize = gd->border_size + gd->draw_xoffset;
+    int border_ysize = gd->border_size;
     struct GadgetInfo *gi;
-    unsigned long event_mask;
+    unsigned int event_mask;
     char infotext[MAX_OUTPUT_LINESIZE + 1];
-    int id = textbutton_info[i].gadget_id;
-    int x = SX + textbutton_info[i].x;
-    int y = SY + textbutton_info[i].y;
+    int x = SX + ED_TAB_SETTINGS_X(textbutton_info[i].x);
+    int y = SY + ED_TAB_SETTINGS_Y(textbutton_info[i].y);
 
     if (textbutton_info[i].size == -1)	/* dynamically determine size */
       textbutton_info[i].size = strlen(textbutton_info[i].text);
 
     event_mask = GD_EVENT_RELEASED;
 
-    if ((id >= GADGET_ID_LEVELINFO_LEVEL && id <= GADGET_ID_LEVELINFO_EDITOR) ||
-	(id >= GADGET_ID_PROPERTIES_INFO && id <= GADGET_ID_PROPERTIES_CHANGE))
-    {
-      gd_x1 = DOOR_GFX_PAGEX4 + ED_TEXTBUTTON_TAB_XPOS;
-      gd_x2 = DOOR_GFX_PAGEX3 + ED_TEXTBUTTON_TAB_XPOS;
-      gd_y1 = DOOR_GFX_PAGEY1 + ED_TEXTBUTTON_TAB_YPOS;
-      gd_y2 = DOOR_GFX_PAGEY1 + ED_TEXTBUTTON_TAB_INACTIVE_YPOS;
-    }
-    else
-    {
-      gd_x1 = DOOR_GFX_PAGEX4 + ED_TEXTBUTTON_XPOS;
-      gd_x2 = DOOR_GFX_PAGEX3 + ED_TEXTBUTTON_XPOS;
-      gd_y1 = DOOR_GFX_PAGEY1 + ED_TEXTBUTTON_YPOS;
-      gd_y2 = DOOR_GFX_PAGEY1 + ED_TEXTBUTTON_INACTIVE_YPOS;
-    }
-
     sprintf(infotext, "%s", textbutton_info[i].infotext);
     infotext[max_infotext_len] = '\0';
 
     /* determine horizontal position to the right of specified gadget */
     if (textbutton_info[i].gadget_id_align != GADGET_ID_NONE)
-      x = (right_gadget_border[textbutton_info[i].gadget_id_align] +
-	   ED_GADGET_TEXT_DISTANCE);
+    {
+      int gadget_id_align = textbutton_info[i].gadget_id_align;
+
+      x = right_gadget_border[gadget_id_align] + gadget_distance;
+
+      if (textbutton_info[i].y == -1)
+	y = level_editor_gadget[gadget_id_align]->y;
+    }
 
     /* determine horizontal offset for leading text */
     if (textbutton_info[i].text_left != NULL)
@@ -5922,13 +6168,13 @@ static void CreateTextbuttonGadgets()
 		      GDI_TYPE, GD_TYPE_TEXT_BUTTON,
 		      GDI_TEXT_VALUE, textbutton_info[i].text,
 		      GDI_TEXT_SIZE, textbutton_info[i].size,
-		      GDI_TEXT_FONT, FONT_INPUT_2_ACTIVE,
-		      GDI_TEXT_FONT_ACTIVE, FONT_INPUT_2,
-		      GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y1,
-		      GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y1,
-		      GDI_ALT_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y2,
-		      GDI_BORDER_SIZE, ED_BORDER_TEXT_XSIZE, ED_BORDER_SIZE,
-		      GDI_DESIGN_WIDTH, ED_WIN_COUNT_XSIZE,
+		      GDI_TEXT_FONT, FONT_INPUT_2,
+		      GDI_TEXT_FONT_ACTIVE, FONT_INPUT_2_ACTIVE,
+		      GDI_DESIGN_UNPRESSED, gd->bitmap, gd_x1, gd_y1,
+		      GDI_DESIGN_PRESSED, gd->bitmap, gd_x2, gd_y2,
+		      GDI_ALT_DESIGN_UNPRESSED, gd->bitmap, gd_x1a, gd_y1a,
+		      GDI_BORDER_SIZE, border_xsize, border_ysize,
+		      GDI_DESIGN_WIDTH, gd->width,
 		      GDI_DECORATION_SHIFTING, 1, 1,
 		      GDI_EVENT_MASK, event_mask,
 		      GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
@@ -5946,36 +6192,24 @@ static void CreateTextbuttonGadgets()
 
 static void CreateGraphicbuttonGadgets()
 {
-  Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
   struct GadgetInfo *gi;
-  unsigned long event_mask;
+  unsigned int event_mask;
   int i;
 
   /* create buttons for scrolling of drawing area and element list */
   for (i = 0; i < ED_NUM_GRAPHICBUTTONS; i++)
   {
     int id = graphicbutton_info[i].gadget_id;
-    int gd_x1, gd_x2, gd_y1, gd_y2;
-    int x = SX + graphicbutton_info[i].x;
-    int y = SY + graphicbutton_info[i].y;
+    int x = SX + ED_SETTINGS_X(graphicbutton_info[i].x);
+    int y = SY + ED_SETTINGS_Y(graphicbutton_info[i].y);
+    struct GraphicInfo *gd = &graphic_info[graphicbutton_info[i].graphic];
+    int gd_x1 = gd->src_x;
+    int gd_y1 = gd->src_y;
+    int gd_x2 = gd->src_x + gd->pressed_xoffset;
+    int gd_y2 = gd->src_y + gd->pressed_yoffset;
 
     event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
 
-    if (i <= ED_GRAPHICBUTTON_ID_NEXT_CHANGE_PAGE)
-    {
-      gd_x1 = DOOR_GFX_PAGEX4 + graphicbutton_info[i].gd_x;
-      gd_y1 = DOOR_GFX_PAGEY1 + graphicbutton_info[i].gd_y;
-      gd_x2 = DOOR_GFX_PAGEX3 + graphicbutton_info[i].gd_x;
-      gd_y2 = gd_y1;
-    }
-    else	/* (i <= ED_GRAPHICBUTTON_ID_PASTE_CHANGE_PAGE) */
-    {
-      gd_x1 = DOOR_GFX_PAGEX6 + graphicbutton_info[i].gd_x;
-      gd_y1 = DOOR_GFX_PAGEY1 + graphicbutton_info[i].gd_y;
-      gd_x2 = gd_x1 - ED_BUTTON_COUNT_XSIZE;
-      gd_y2 = gd_y1;
-    }
-
     /* determine horizontal position to the right of specified gadget */
     if (graphicbutton_info[i].gadget_id_align != GADGET_ID_NONE)
       x = (right_gadget_border[graphicbutton_info[i].gadget_id_align] +
@@ -5990,12 +6224,12 @@ static void CreateGraphicbuttonGadgets()
 		      GDI_INFO_TEXT, graphicbutton_info[i].infotext,
 		      GDI_X, x,
 		      GDI_Y, y,
-		      GDI_WIDTH, graphicbutton_info[i].width,
-		      GDI_HEIGHT, graphicbutton_info[i].height,
+		      GDI_WIDTH, gd->width,
+		      GDI_HEIGHT, gd->height,
 		      GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
 		      GDI_STATE, GD_BUTTON_UNPRESSED,
-		      GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y1,
-		      GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y2,
+		      GDI_DESIGN_UNPRESSED, gd->bitmap, gd_x1, gd_y1,
+		      GDI_DESIGN_PRESSED, gd->bitmap, gd_x2, gd_y2,
 		      GDI_EVENT_MASK, event_mask,
 		      GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
 		      GDI_CALLBACK_ACTION, HandleGraphicbuttonGadgets,
@@ -6015,47 +6249,57 @@ static void CreateScrollbarGadgets()
   int i;
 
   /* these values are not constant, but can change at runtime */
-  scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].x =
+  scrollbar_pos[ED_SCROLLBAR_ID_AREA_HORIZONTAL].x =
     SX + ED_SCROLL_HORIZONTAL_XPOS;
-  scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].y =
+  scrollbar_pos[ED_SCROLLBAR_ID_AREA_HORIZONTAL].y =
     SY + ED_SCROLL_HORIZONTAL_YPOS;
-  scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].width =
+  scrollbar_pos[ED_SCROLLBAR_ID_AREA_HORIZONTAL].width =
     ED_SCROLL_HORIZONTAL_XSIZE;
-  scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].height =
+  scrollbar_pos[ED_SCROLLBAR_ID_AREA_HORIZONTAL].height =
     ED_SCROLL_HORIZONTAL_YSIZE;
-  scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].wheel_x      = SX;
-  scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].wheel_y      = SY;
-  scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].wheel_width  = SXSIZE;
-  scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].wheel_height = SYSIZE;
+  scrollbar_pos[ED_SCROLLBAR_ID_AREA_HORIZONTAL].wheel_x      = SX;
+  scrollbar_pos[ED_SCROLLBAR_ID_AREA_HORIZONTAL].wheel_y      = SY;
+  scrollbar_pos[ED_SCROLLBAR_ID_AREA_HORIZONTAL].wheel_width  = SXSIZE;
+  scrollbar_pos[ED_SCROLLBAR_ID_AREA_HORIZONTAL].wheel_height = SYSIZE;
 
-  scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].x =
+  scrollbar_pos[ED_SCROLLBAR_ID_AREA_VERTICAL].x =
     SX + ED_SCROLL_VERTICAL_XPOS;
-  scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].y =
+  scrollbar_pos[ED_SCROLLBAR_ID_AREA_VERTICAL].y =
     SY + ED_SCROLL_VERTICAL_YPOS;
-  scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].width =
+  scrollbar_pos[ED_SCROLLBAR_ID_AREA_VERTICAL].width =
     ED_SCROLL_VERTICAL_XSIZE;
-  scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].height =
+  scrollbar_pos[ED_SCROLLBAR_ID_AREA_VERTICAL].height =
     ED_SCROLL_VERTICAL_YSIZE;
-  scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].wheel_x      = SX;
-  scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].wheel_y      = SY;
-  scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].wheel_width  = SXSIZE;
-  scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].wheel_height = SYSIZE;
-
-  scrollbar_info[ED_SCROLLBAR_ID_LIST_VERTICAL].x =
-    DX + ED_SCROLL2_VERTICAL_XPOS;
-  scrollbar_info[ED_SCROLLBAR_ID_LIST_VERTICAL].y =
-    DY + ED_SCROLL2_VERTICAL_YPOS;
-  scrollbar_info[ED_SCROLLBAR_ID_LIST_VERTICAL].wheel_x = DX;
-  scrollbar_info[ED_SCROLLBAR_ID_LIST_VERTICAL].wheel_y = DY;
+  scrollbar_pos[ED_SCROLLBAR_ID_AREA_VERTICAL].wheel_x      = SX;
+  scrollbar_pos[ED_SCROLLBAR_ID_AREA_VERTICAL].wheel_y      = SY;
+  scrollbar_pos[ED_SCROLLBAR_ID_AREA_VERTICAL].wheel_width  = SXSIZE;
+  scrollbar_pos[ED_SCROLLBAR_ID_AREA_VERTICAL].wheel_height = SYSIZE;
+
+  scrollbar_pos[ED_SCROLLBAR_ID_LIST_VERTICAL].x =
+    PX + ED_SCROLL2_VERTICAL_XPOS;
+  scrollbar_pos[ED_SCROLLBAR_ID_LIST_VERTICAL].y =
+    PY + ED_SCROLL2_VERTICAL_YPOS;
+  scrollbar_pos[ED_SCROLLBAR_ID_LIST_VERTICAL].width =
+    ED_SCROLL2_VERTICAL_XSIZE;
+  scrollbar_pos[ED_SCROLLBAR_ID_LIST_VERTICAL].height =
+    ED_SCROLL2_VERTICAL_YSIZE;
+  scrollbar_pos[ED_SCROLLBAR_ID_LIST_VERTICAL].wheel_x = PX;
+  scrollbar_pos[ED_SCROLLBAR_ID_LIST_VERTICAL].wheel_y = PY;
+  scrollbar_pos[ED_SCROLLBAR_ID_LIST_VERTICAL].wheel_width  = PXSIZE;
+  scrollbar_pos[ED_SCROLLBAR_ID_LIST_VERTICAL].wheel_height = PYSIZE;
 
   for (i = 0; i < ED_NUM_SCROLLBARS; i++)
   {
     int id = scrollbar_info[i].gadget_id;
-    Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
-    int gd_x1, gd_x2, gd_y1, gd_y2;
+    int graphic = scrollbar_info[i].graphic;
+    struct GraphicInfo *gd = &graphic_info[graphic];
+    int gd_x1 = gd->src_x;
+    int gd_y1 = gd->src_y;
+    int gd_x2 = gd->src_x + gd->pressed_xoffset;
+    int gd_y2 = gd->src_y + gd->pressed_yoffset;
     struct GadgetInfo *gi;
     int items_max, items_visible, item_position;
-    unsigned long event_mask;
+    unsigned int event_mask;
 
     if (i == ED_SCROLLBAR_ID_LIST_VERTICAL)
     {
@@ -6081,31 +6325,25 @@ static void CreateScrollbarGadgets()
 
     event_mask = GD_EVENT_MOVING | GD_EVENT_OFF_BORDERS;
 
-    gd_x1 = DOOR_GFX_PAGEX8 + scrollbar_info[i].gd_x;
-    gd_x2 = (gd_x1 - (scrollbar_info[i].type == GD_TYPE_SCROLLBAR_HORIZONTAL ?
-		      scrollbar_info[i].height : scrollbar_info[i].width));
-    gd_y1 = DOOR_GFX_PAGEY1 + scrollbar_info[i].gd_y;
-    gd_y2 = DOOR_GFX_PAGEY1 + scrollbar_info[i].gd_y;
-
     gi = CreateGadget(GDI_CUSTOM_ID, id,
 		      GDI_CUSTOM_TYPE_ID, i,
 		      GDI_INFO_TEXT, scrollbar_info[i].infotext,
-		      GDI_X, scrollbar_info[i].x,
-		      GDI_Y, scrollbar_info[i].y,
-		      GDI_WIDTH, scrollbar_info[i].width,
-		      GDI_HEIGHT, scrollbar_info[i].height,
+		      GDI_X, scrollbar_pos[i].x,
+		      GDI_Y, scrollbar_pos[i].y,
+		      GDI_WIDTH, scrollbar_pos[i].width,
+		      GDI_HEIGHT, scrollbar_pos[i].height,
 		      GDI_TYPE, scrollbar_info[i].type,
 		      GDI_SCROLLBAR_ITEMS_MAX, items_max,
 		      GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible,
 		      GDI_SCROLLBAR_ITEM_POSITION, item_position,
-		      GDI_WHEEL_AREA_X, scrollbar_info[i].wheel_x,
-		      GDI_WHEEL_AREA_Y, scrollbar_info[i].wheel_y,
-		      GDI_WHEEL_AREA_WIDTH, scrollbar_info[i].wheel_width,
-		      GDI_WHEEL_AREA_HEIGHT, scrollbar_info[i].wheel_height,
+		      GDI_WHEEL_AREA_X, scrollbar_pos[i].wheel_x,
+		      GDI_WHEEL_AREA_Y, scrollbar_pos[i].wheel_y,
+		      GDI_WHEEL_AREA_WIDTH, scrollbar_pos[i].wheel_width,
+		      GDI_WHEEL_AREA_HEIGHT, scrollbar_pos[i].wheel_height,
 		      GDI_STATE, GD_BUTTON_UNPRESSED,
-		      GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y1,
-		      GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y2,
-		      GDI_BORDER_SIZE, ED_BORDER_SIZE, ED_BORDER_SIZE,
+		      GDI_DESIGN_UNPRESSED, gd->bitmap, gd_x1, gd_y1,
+		      GDI_DESIGN_PRESSED, gd->bitmap, gd_x2, gd_y2,
+		      GDI_BORDER_SIZE, gd->border_size, gd->border_size,
 		      GDI_EVENT_MASK, event_mask,
 		      GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
 		      GDI_CALLBACK_ACTION, HandleControlButtons,
@@ -6120,30 +6358,28 @@ static void CreateScrollbarGadgets()
 
 static void CreateCheckbuttonGadgets()
 {
-  Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
   struct GadgetInfo *gi;
-  unsigned long event_mask;
-  int gd_x1, gd_x2, gd_x3, gd_x4, gd_y;
+  unsigned int event_mask;
   int i;
 
   event_mask = GD_EVENT_PRESSED;
 
-  gd_x1 = DOOR_GFX_PAGEX4 + ED_CHECKBUTTON_UNCHECKED_XPOS;
-  gd_x2 = DOOR_GFX_PAGEX3 + ED_CHECKBUTTON_UNCHECKED_XPOS;
-  gd_x3 = DOOR_GFX_PAGEX4 + ED_CHECKBUTTON_CHECKED_XPOS;
-  gd_x4 = DOOR_GFX_PAGEX3 + ED_CHECKBUTTON_CHECKED_XPOS;
-  gd_y  = DOOR_GFX_PAGEY1 + ED_RADIOBUTTON_YPOS;
-
   for (i = 0; i < ED_NUM_CHECKBUTTONS; i++)
   {
     int id = checkbutton_info[i].gadget_id;
-    int x = SX + checkbutton_info[i].x;
-    int y = SY + checkbutton_info[i].y;
-
-    if (id == GADGET_ID_STICK_ELEMENT)
-      gd_y  = DOOR_GFX_PAGEY1 + ED_STICKYBUTTON_YPOS;
-    else
-      gd_y  = DOOR_GFX_PAGEY1 + ED_CHECKBUTTON_YPOS;
+    int graphic = (id == GADGET_ID_STICK_ELEMENT ? IMG_EDITOR_STICKYBUTTON :
+		   IMG_EDITOR_CHECKBOX);
+    struct GraphicInfo *gd = &graphic_info[graphic];
+    int gd_x1 = gd->src_x;
+    int gd_y1 = gd->src_y;
+    int gd_x2 = gd->src_x + gd->pressed_xoffset;
+    int gd_y2 = gd->src_y + gd->pressed_yoffset;
+    int gd_x1a = gd->src_x + gd->active_xoffset;
+    int gd_y1a = gd->src_y + gd->active_yoffset;
+    int gd_x2a = gd->src_x + gd->active_xoffset + gd->pressed_xoffset;
+    int gd_y2a = gd->src_y + gd->active_yoffset + gd->pressed_yoffset;
+    int x = SX + ED_SETTINGS_X(checkbutton_info[i].x);
+    int y = SY + ED_SETTINGS_Y(checkbutton_info[i].y);
 
     /* determine horizontal position to the right of specified gadget */
     if (checkbutton_info[i].gadget_id_align != GADGET_ID_NONE)
@@ -6159,14 +6395,14 @@ static void CreateCheckbuttonGadgets()
 		      GDI_INFO_TEXT, checkbutton_info[i].infotext,
 		      GDI_X, x,
 		      GDI_Y, y,
-		      GDI_WIDTH, ED_CHECKBUTTON_XSIZE,
-		      GDI_HEIGHT, ED_CHECKBUTTON_YSIZE,
+		      GDI_WIDTH, gd->width,
+		      GDI_HEIGHT, gd->height,
 		      GDI_TYPE, GD_TYPE_CHECK_BUTTON,
 		      GDI_CHECKED, *checkbutton_info[i].value,
-		      GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
-		      GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
-		      GDI_ALT_DESIGN_UNPRESSED, gd_bitmap, gd_x3, gd_y,
-		      GDI_ALT_DESIGN_PRESSED, gd_bitmap, gd_x4, gd_y,
+		      GDI_DESIGN_UNPRESSED, gd->bitmap, gd_x1, gd_y1,
+		      GDI_DESIGN_PRESSED, gd->bitmap, gd_x2, gd_y2,
+		      GDI_ALT_DESIGN_UNPRESSED, gd->bitmap, gd_x1a, gd_y1a,
+		      GDI_ALT_DESIGN_PRESSED, gd->bitmap, gd_x2a, gd_y2a,
 		      GDI_EVENT_MASK, event_mask,
 		      GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
 		      GDI_CALLBACK_ACTION, HandleCheckbuttons,
@@ -6183,25 +6419,26 @@ static void CreateCheckbuttonGadgets()
 
 static void CreateRadiobuttonGadgets()
 {
-  Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
+  struct GraphicInfo *gd = &graphic_info[IMG_EDITOR_RADIOBUTTON];
+  int gd_x1 = gd->src_x;
+  int gd_y1 = gd->src_y;
+  int gd_x2 = gd->src_x + gd->pressed_xoffset;
+  int gd_y2 = gd->src_y + gd->pressed_yoffset;
+  int gd_x1a = gd->src_x + gd->active_xoffset;
+  int gd_y1a = gd->src_y + gd->active_yoffset;
+  int gd_x2a = gd->src_x + gd->active_xoffset + gd->pressed_xoffset;
+  int gd_y2a = gd->src_y + gd->active_yoffset + gd->pressed_yoffset;
   struct GadgetInfo *gi;
-  unsigned long event_mask;
-  int gd_x1, gd_x2, gd_x3, gd_x4, gd_y;
+  unsigned int event_mask;
   int i;
 
   event_mask = GD_EVENT_PRESSED;
 
-  gd_x1 = DOOR_GFX_PAGEX4 + ED_CHECKBUTTON_UNCHECKED_XPOS;
-  gd_x2 = DOOR_GFX_PAGEX3 + ED_CHECKBUTTON_UNCHECKED_XPOS;
-  gd_x3 = DOOR_GFX_PAGEX4 + ED_CHECKBUTTON_CHECKED_XPOS;
-  gd_x4 = DOOR_GFX_PAGEX3 + ED_CHECKBUTTON_CHECKED_XPOS;
-  gd_y  = DOOR_GFX_PAGEY1 + ED_RADIOBUTTON_YPOS;
-
   for (i = 0; i < ED_NUM_RADIOBUTTONS; i++)
   {
     int id = radiobutton_info[i].gadget_id;
-    int x = SX + radiobutton_info[i].x;
-    int y = SY + radiobutton_info[i].y;
+    int x = SX + ED_SETTINGS_X(radiobutton_info[i].x);
+    int y = SY + ED_SETTINGS_Y(radiobutton_info[i].y);
 
     int checked =
       (*radiobutton_info[i].value == radiobutton_info[i].checked_value);
@@ -6220,15 +6457,15 @@ static void CreateRadiobuttonGadgets()
 		      GDI_INFO_TEXT, radiobutton_info[i].infotext,
 		      GDI_X, x,
 		      GDI_Y, y,
-		      GDI_WIDTH, ED_CHECKBUTTON_XSIZE,
-		      GDI_HEIGHT, ED_CHECKBUTTON_YSIZE,
+		      GDI_WIDTH, gd->width,
+		      GDI_HEIGHT, gd->height,
 		      GDI_TYPE, GD_TYPE_RADIO_BUTTON,
 		      GDI_RADIO_NR, radiobutton_info[i].radio_button_nr,
 		      GDI_CHECKED, checked,
-		      GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
-		      GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
-		      GDI_ALT_DESIGN_UNPRESSED, gd_bitmap, gd_x3, gd_y,
-		      GDI_ALT_DESIGN_PRESSED, gd_bitmap, gd_x4, gd_y,
+		      GDI_DESIGN_UNPRESSED, gd->bitmap, gd_x1, gd_y1,
+		      GDI_DESIGN_PRESSED, gd->bitmap, gd_x2, gd_y2,
+		      GDI_ALT_DESIGN_UNPRESSED, gd->bitmap, gd_x1a, gd_y1a,
+		      GDI_ALT_DESIGN_PRESSED, gd->bitmap, gd_x2a, gd_y2a,
 		      GDI_EVENT_MASK, event_mask,
 		      GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
 		      GDI_CALLBACK_ACTION, HandleRadiobuttons,
@@ -6245,15 +6482,27 @@ static void CreateRadiobuttonGadgets()
 
 void CreateLevelEditorGadgets()
 {
-  int old_game_status = game_status;
-
-  /* setting 'game_status' is needed to get the right fonts for the editor */
-  game_status = GAME_MODE_EDITOR;
+  /* force EDITOR font inside level editor */
+  SetFontStatus(GAME_MODE_EDITOR);
 
   /* these values are not constant, but can change at runtime */
   ed_fieldx = MAX_ED_FIELDX - 1;
   ed_fieldy = MAX_ED_FIELDY - 1;
 
+  num_editor_gadgets = NUM_EDITOR_GADGETS;
+
+  // printf("::: allocating %d gadgets ...\n", num_editor_gadgets);
+
+  level_editor_gadget =
+    checked_calloc(num_editor_gadgets * sizeof(struct GadgetInfo *));
+  right_gadget_border =
+    checked_calloc(num_editor_gadgets * sizeof(int));
+
+  editor_el_empty = checked_calloc(ED_NUM_ELEMENTLIST_BUTTONS * sizeof(int));
+  editor_el_empty_ptr = editor_el_empty;
+
+  use_permanent_palette = !editor.palette.show_as_separate_screen;
+
   ReinitializeElementList();
 
   CreateControlButtons();
@@ -6270,23 +6519,32 @@ void CreateLevelEditorGadgets()
   CreateTextbuttonGadgets();
   CreateDrawingAreas();
 
-  game_status = old_game_status;
+  ResetFontStatus();
 }
 
 void FreeLevelEditorGadgets()
 {
   int i;
 
-  for (i = 0; i < NUM_EDITOR_GADGETS; i++)
+  // printf("::: freeing %d gadgets ...\n", num_editor_gadgets);
+
+  for (i = 0; i < num_editor_gadgets; i++)
   {
     FreeGadget(level_editor_gadget[i]);
 
     level_editor_gadget[i] = NULL;
   }
+
+  checked_free(level_editor_gadget);
+  checked_free(right_gadget_border);
+
+  checked_free(editor_el_empty);
 }
 
 static void MapCounterButtons(int id)
 {
+  int font_nr = FONT_TEXT_1;
+  int font_height = getFontHeight(font_nr);
   int gadget_id_down = counterbutton_info[id].gadget_id_down;
   int gadget_id_text = counterbutton_info[id].gadget_id_text;
   int gadget_id_up   = counterbutton_info[id].gadget_id_up;
@@ -6295,8 +6553,8 @@ static void MapCounterButtons(int id)
   struct GadgetInfo *gi_up   = level_editor_gadget[gadget_id_up];
   int xoffset_left = getTextWidthForGadget(counterbutton_info[id].text_left);
   int xoffset_right = ED_GADGET_TEXT_DISTANCE;
-  int yoffset_above = MINI_TILEX + ED_GADGET_DISTANCE;
-  int yoffset = ED_BORDER_SIZE;
+  int yoffset_above = font_height + ED_GADGET_LINE_DISTANCE;
+  int yoffset = (gi_down->height - font_height) / 2;
   int x_left = gi_down->x - xoffset_left;
   int x_right;	/* set after gadget position was modified */
   int y_above = gi_down->y - yoffset_above;
@@ -6316,22 +6574,25 @@ static void MapCounterButtons(int id)
   if (id >= ED_COUNTER_ID_ELEMENT_VALUE1 &&
       id <= ED_COUNTER_ID_ELEMENT_VALUE4)
   {
-    ModifyGadget(gi_down, GDI_Y, SY + counterbutton_info[id].y, GDI_END);
-    ModifyGadget(gi_text, GDI_Y, SY + counterbutton_info[id].y, GDI_END);
-    ModifyGadget(gi_up,   GDI_Y, SY + counterbutton_info[id].y, GDI_END);
+    ModifyGadget(gi_down, GDI_Y,
+		 SY + ED_SETTINGS_Y(counterbutton_info[id].y), GDI_END);
+    ModifyGadget(gi_text, GDI_Y,
+		 SY + ED_SETTINGS_Y(counterbutton_info[id].y), GDI_END);
+    ModifyGadget(gi_up,   GDI_Y,
+		 SY + ED_SETTINGS_Y(counterbutton_info[id].y), GDI_END);
   }
 
   /* vertical position might have changed after setting position above */
   y = gi_up->y + yoffset;
 
   if (counterbutton_info[id].text_above)
-    DrawText(x, y_above, counterbutton_info[id].text_above, FONT_TEXT_1);
+    DrawText(x, y_above, counterbutton_info[id].text_above, font_nr);
 
   if (counterbutton_info[id].text_left)
-    DrawText(x_left, y, counterbutton_info[id].text_left, FONT_TEXT_1);
+    DrawText(x_left, y, counterbutton_info[id].text_left, font_nr);
 
   if (counterbutton_info[id].text_right)
-    DrawText(x_right, y, counterbutton_info[id].text_right, FONT_TEXT_1);
+    DrawText(x_right, y, counterbutton_info[id].text_right, font_nr);
 
   MapGadget(gi_down);
   MapGadget(gi_text);
@@ -6347,12 +6608,19 @@ static void MapControlButtons()
   for (i = 0; i < ED_NUM_CTRL1_2_BUTTONS; i++)
     MapGadget(level_editor_gadget[i]);
 
-  /* map buttons to select elements */
-  for (i = 0; i < ED_NUM_ELEMENTLIST_BUTTONS; i++)
-    MapGadget(level_editor_gadget[GADGET_ID_ELEMENTLIST_FIRST + i]);
-  MapGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_VERTICAL]);
-  MapGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_UP]);
-  MapGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_DOWN]);
+  /* map toolbox buttons (element properties buttons) */
+  for (i = ED_NUM_CTRL1_4_BUTTONS; i < ED_NUM_CTRL1_7_BUTTONS; i++)
+    MapGadget(level_editor_gadget[i]);
+
+  if (use_permanent_palette)
+  {
+    /* map buttons to select elements */
+    for (i = 0; i < ED_NUM_ELEMENTLIST_BUTTONS; i++)
+      MapGadget(level_editor_gadget[GADGET_ID_ELEMENTLIST_FIRST + i]);
+    MapGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_VERTICAL]);
+    MapGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_UP]);
+    MapGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_DOWN]);
+  }
 
   /* map buttons to select level */
   counter_id = ED_COUNTER_ID_SELECT_LEVEL;
@@ -6363,30 +6631,33 @@ static void MapControlButtons()
 
 static void MapDrawingArea(int id)
 {
+  int font_nr = FONT_TEXT_1;
+  int font_height = getFontHeight(font_nr);
   struct GadgetInfo *gi = level_editor_gadget[drawingarea_info[id].gadget_id];
   int area_xsize = gi->drawing.area_xsize;
   int area_ysize = gi->drawing.area_ysize;
-  int xoffset_left= getTextWidthForDrawingArea(drawingarea_info[id].text_left);
-  int xoffset_below= getTextWidth(drawingarea_info[id].text_below,FONT_TEXT_1);
+  int xoffset_left = getTextWidthForDrawingArea(drawingarea_info[id].text_left);
+  int xoffset_below = getTextWidth(drawingarea_info[id].text_below, font_nr);
   int x_left  = gi->x - xoffset_left;
   int x_right = gi->x + gi->width + ED_DRAWINGAREA_TEXT_DISTANCE;
   int x_below = gi->x + (gi->width - xoffset_below) / 2;
-  int y_side  = gi->y + (gi->height - getFontHeight(FONT_TEXT_1)) / 2;
+  int y_side  = gi->y + (gi->height - font_height) / 2;
   int y_below = gi->y + gi->height + ED_DRAWINGAREA_TEXT_DISTANCE;
 
   if (drawingarea_info[id].text_left)
-    DrawText(x_left, y_side, drawingarea_info[id].text_left, FONT_TEXT_1);
+    DrawText(x_left, y_side, drawingarea_info[id].text_left, font_nr);
 
   if (drawingarea_info[id].text_right)
-    DrawText(x_right, y_side, drawingarea_info[id].text_right, FONT_TEXT_1);
+    DrawText(x_right, y_side, drawingarea_info[id].text_right, font_nr);
 
   if (drawingarea_info[id].text_below)
-    DrawText(x_below, y_below, drawingarea_info[id].text_below, FONT_TEXT_1);
+    DrawText(x_below, y_below, drawingarea_info[id].text_below, font_nr);
 
   if (id != ED_DRAWING_ID_DRAWING_LEVEL)
   {
     DrawElementBorder(gi->x, gi->y,
-		      area_xsize * MINI_TILEX, area_ysize * MINI_TILEY, TRUE);
+		      area_xsize * ED_DRAWINGAREA_TILE_SIZE,
+		      area_ysize * ED_DRAWINGAREA_TILE_SIZE, TRUE);
 
     DrawDrawingArea(id);
   }
@@ -6396,14 +6667,15 @@ static void MapDrawingArea(int id)
 
 static void MapTextInputGadget(int id)
 {
+  int font_nr = FONT_TEXT_1;
+  int font_height = getFontHeight(font_nr);
   struct GadgetInfo *gi = level_editor_gadget[textinput_info[id].gadget_id];
-  int xoffset_above = 0;
-  int yoffset_above = -(MINI_TILEX + ED_GADGET_DISTANCE);
-  int x_above = textinput_info[id].x + xoffset_above;
-  int y_above = textinput_info[id].y + yoffset_above;
+  int yoffset_above = font_height + ED_GADGET_LINE_DISTANCE;
+  int x_above = ED_SETTINGS_X(textinput_info[id].x);
+  int y_above = ED_SETTINGS_Y(textinput_info[id].y) - yoffset_above;
 
   if (textinput_info[id].text_above)
-    DrawTextS(x_above, y_above, FONT_TEXT_1, textinput_info[id].text_above);
+    DrawTextS(x_above, y_above, font_nr, textinput_info[id].text_above);
 
   ModifyGadget(gi, GDI_TEXT_VALUE, textinput_info[id].value, GDI_END);
 
@@ -6412,14 +6684,15 @@ static void MapTextInputGadget(int id)
 
 static void MapTextAreaGadget(int id)
 {
+  int font_nr = FONT_TEXT_1;
+  int font_height = getFontHeight(font_nr);
   struct GadgetInfo *gi = level_editor_gadget[textarea_info[id].gadget_id];
-  int xoffset_above = 0;
-  int yoffset_above = -(MINI_TILEX + ED_GADGET_DISTANCE);
-  int x_above = textarea_info[id].x + xoffset_above;
-  int y_above = textarea_info[id].y + yoffset_above;
+  int yoffset_above = font_height + ED_GADGET_LINE_DISTANCE;
+  int x_above = ED_SETTINGS_X(textarea_info[id].x);
+  int y_above = ED_SETTINGS_Y(textarea_info[id].y) - yoffset_above;
 
   if (textarea_info[id].text_above)
-    DrawTextS(x_above, y_above, FONT_TEXT_1, textarea_info[id].text_above);
+    DrawTextS(x_above, y_above, font_nr, textarea_info[id].text_above);
 
   ModifyGadget(gi, GDI_TEXT_VALUE, textarea_info[id].value, GDI_END);
 
@@ -6428,19 +6701,21 @@ static void MapTextAreaGadget(int id)
 
 static void MapSelectboxGadget(int id)
 {
+  int font_nr = FONT_TEXT_1;
+  int font_height = getFontHeight(font_nr);
   struct GadgetInfo *gi = level_editor_gadget[selectbox_info[id].gadget_id];
   int xoffset_left = getTextWidthForGadget(selectbox_info[id].text_left);
   int xoffset_right = ED_GADGET_TEXT_DISTANCE;
-  int yoffset = ED_BORDER_SIZE;
+  int yoffset = (gi->height - font_height) / 2;
   int x_left = gi->x - xoffset_left;
   int x_right = gi->x + gi->width + xoffset_right;
   int y = gi->y + yoffset;
 
   if (selectbox_info[id].text_left)
-    DrawText(x_left, y, selectbox_info[id].text_left, FONT_TEXT_1);
+    DrawText(x_left, y, selectbox_info[id].text_left, font_nr);
 
   if (selectbox_info[id].text_right)
-    DrawText(x_right, y, selectbox_info[id].text_right, FONT_TEXT_1);
+    DrawText(x_right, y, selectbox_info[id].text_right, font_nr);
 
   ModifyEditorSelectboxValue(id, *selectbox_info[id].value);
 
@@ -6449,10 +6724,12 @@ static void MapSelectboxGadget(int id)
 
 static void MapTextbuttonGadget(int id)
 {
+  int font_nr = FONT_TEXT_1;
+  int font_height = getFontHeight(font_nr);
   struct GadgetInfo *gi = level_editor_gadget[textbutton_info[id].gadget_id];
   int xoffset_left = getTextWidthForGadget(textbutton_info[id].text_left);
   int xoffset_right = ED_GADGET_TEXT_DISTANCE;
-  int yoffset = ED_BORDER_SIZE;
+  int yoffset = (gi->height - font_height) / 2;
   int x_left = gi->x - xoffset_left;
   int x_right = gi->x + gi->width + xoffset_right;
   int y = gi->y + yoffset;
@@ -6463,39 +6740,43 @@ static void MapTextbuttonGadget(int id)
     return;
 
   if (textbutton_info[id].text_left)
-    DrawText(x_left, y, textbutton_info[id].text_left, FONT_TEXT_1);
+    DrawText(x_left, y, textbutton_info[id].text_left, font_nr);
 
   if (textbutton_info[id].text_right)
-    DrawText(x_right, y, textbutton_info[id].text_right, FONT_TEXT_1);
+    DrawText(x_right, y, textbutton_info[id].text_right, font_nr);
 
   MapGadget(gi);
 }
 
 static void MapGraphicbuttonGadget(int id)
 {
+  int font_nr = FONT_TEXT_1;
+  int font_height = getFontHeight(font_nr);
   struct GadgetInfo *gi= level_editor_gadget[graphicbutton_info[id].gadget_id];
   int xoffset_left = getTextWidthForGadget(graphicbutton_info[id].text_left);
   int xoffset_right = ED_GADGET_TEXT_DISTANCE;
-  int yoffset = ED_BORDER_SIZE;
+  int yoffset = (gi->height - font_height) / 2;
   int x_left = gi->x - xoffset_left;
   int x_right = gi->x + gi->width + xoffset_right;
   int y = gi->y + yoffset;
 
   if (graphicbutton_info[id].text_left)
-    DrawText(x_left, y, graphicbutton_info[id].text_left, FONT_TEXT_1);
+    DrawText(x_left, y, graphicbutton_info[id].text_left, font_nr);
 
   if (graphicbutton_info[id].text_right)
-    DrawText(x_right, y, graphicbutton_info[id].text_right, FONT_TEXT_1);
+    DrawText(x_right, y, graphicbutton_info[id].text_right, font_nr);
 
   MapGadget(gi);
 }
 
 static void MapRadiobuttonGadget(int id)
 {
+  int font_nr = FONT_TEXT_1;
+  int font_height = getFontHeight(font_nr);
   struct GadgetInfo *gi = level_editor_gadget[radiobutton_info[id].gadget_id];
   int xoffset_left = getTextWidthForGadget(checkbutton_info[id].text_left);
   int xoffset_right = ED_GADGET_TEXT_DISTANCE;
-  int yoffset = ED_BORDER_SIZE;
+  int yoffset = (gi->height - font_height) / 2;
   int x_left = gi->x - xoffset_left;
   int x_right = gi->x + gi->width + xoffset_right;
   int y = gi->y + yoffset;
@@ -6503,10 +6784,10 @@ static void MapRadiobuttonGadget(int id)
     (*radiobutton_info[id].value == radiobutton_info[id].checked_value);
 
   if (radiobutton_info[id].text_left)
-    DrawText(x_left, y, radiobutton_info[id].text_left, FONT_TEXT_1);
+    DrawText(x_left, y, radiobutton_info[id].text_left, font_nr);
 
   if (radiobutton_info[id].text_right)
-    DrawText(x_right, y, radiobutton_info[id].text_right, FONT_TEXT_1);
+    DrawText(x_right, y, radiobutton_info[id].text_right, font_nr);
 
   ModifyGadget(gi, GDI_CHECKED, checked, GDI_END);
 
@@ -6515,26 +6796,28 @@ static void MapRadiobuttonGadget(int id)
 
 static void MapCheckbuttonGadget(int id)
 {
+  int font_nr = FONT_TEXT_1;
+  int font_height = getFontHeight(font_nr);
   struct GadgetInfo *gi = level_editor_gadget[checkbutton_info[id].gadget_id];
   int xoffset_left = getTextWidthForGadget(checkbutton_info[id].text_left);
   int xoffset_right = ED_GADGET_TEXT_DISTANCE;
-  int yoffset = ED_BORDER_SIZE;
+  int yoffset = (gi->height - font_height) / 2;
   int x_left, x_right, y;	/* set after gadget position was modified */
 
   /* set position for gadgets with dynamically determined position */
   if (checkbutton_info[id].x != -1)	/* do not change dynamic positions */
-    ModifyGadget(gi, GDI_X, SX + checkbutton_info[id].x, GDI_END);
-  ModifyGadget(gi, GDI_Y, SY + checkbutton_info[id].y, GDI_END);
+    ModifyGadget(gi, GDI_X, SX + ED_SETTINGS_X(checkbutton_info[id].x),GDI_END);
+  ModifyGadget(gi, GDI_Y, SY + ED_SETTINGS_Y(checkbutton_info[id].y), GDI_END);
 
   x_left = gi->x - xoffset_left;
   x_right = gi->x + gi->width + xoffset_right;
   y = gi->y + yoffset;
 
   if (checkbutton_info[id].text_left)
-    DrawText(x_left, y, checkbutton_info[id].text_left, FONT_TEXT_1);
+    DrawText(x_left, y, checkbutton_info[id].text_left, font_nr);
 
   if (checkbutton_info[id].text_right)
-    DrawText(x_right, y, checkbutton_info[id].text_right, FONT_TEXT_1);
+    DrawText(x_right, y, checkbutton_info[id].text_right, font_nr);
 
   ModifyGadget(gi, GDI_CHECKED, *checkbutton_info[id].value, GDI_END);
 
@@ -6604,26 +6887,27 @@ static void UnmapLevelEditorToolboxCustomGadgets()
 
 static void MapOrUnmapLevelEditorToolboxDrawingGadgets(boolean map)
 {
-  Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
   int i;
 
   for (i = 0; i < ED_NUM_CTRL1_BUTTONS; i++)
   {
     if (i != GADGET_ID_SINGLE_ITEMS &&
-	i != GADGET_ID_PROPERTIES &&
 	i != GADGET_ID_PICK_ELEMENT)
     {
       struct GadgetInfo *gi = level_editor_gadget[i];
 
       if (map)
+      {
 	MapGadget(gi);
+      }
       else
       {
+	int graphic = IMG_EDITOR_NO_TOOLBOX_BUTTON;
+	struct GraphicInfo *gd = &graphic_info[graphic];
+
 	UnmapGadget(gi);
 
-	BlitBitmap(gd_bitmap, drawto,
-		   DOOR_GFX_PAGEX6 + ED_CTRL_NO_BUTTONS_GFX_XPOS,
-		   DOOR_GFX_PAGEY1 + ED_CTRL_NO_BUTTONS_GFX_YPOS,
+	BlitBitmap(gd->bitmap, drawto, gd->src_x, gd->src_y,
 		   gi->width, gi->height, gi->x, gi->y);
 
 	redraw_mask |= REDRAW_DOOR_3;
@@ -6647,12 +6931,13 @@ static void UnmapDrawingArea(int id)
   UnmapGadget(level_editor_gadget[drawingarea_info[id].gadget_id]);
 }
 
-static void UnmapLevelEditorWindowGadgets()
+static void UnmapLevelEditorFieldGadgets()
 {
   int i;
 
-  for (i = 0; i < NUM_EDITOR_GADGETS; i++)
-    if (level_editor_gadget[i]->x < SX + SXSIZE)
+  for (i = 0; i < num_editor_gadgets; i++)
+    if (IN_GFX_FIELD_FULL(level_editor_gadget[i]->x,
+			  level_editor_gadget[i]->y))
       UnmapGadget(level_editor_gadget[i]);
 }
 
@@ -6660,7 +6945,7 @@ void UnmapLevelEditorGadgets()
 {
   int i;
 
-  for (i = 0; i < NUM_EDITOR_GADGETS; i++)
+  for (i = 0; i < num_editor_gadgets; i++)
     UnmapGadget(level_editor_gadget[i]);
 }
 
@@ -6668,6 +6953,8 @@ static void ResetUndoBuffer()
 {
   undo_buffer_position = -1;
   undo_buffer_steps = -1;
+  redo_buffer_steps = 0;
+
   CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
 
   level.changed = FALSE;
@@ -6682,22 +6969,24 @@ static void DrawEditModeWindow()
     DrawLevelInfoWindow();
   else if (edit_mode == ED_MODE_PROPERTIES)
     DrawPropertiesWindow();
+  else if (edit_mode == ED_MODE_PALETTE)
+    DrawPaletteWindow();
   else	/* edit_mode == ED_MODE_DRAWING */
     DrawDrawingWindow();
 }
 
+static void ChangeEditModeWindow(int new_edit_mode)
+{
+  edit_mode = (new_edit_mode != edit_mode ? new_edit_mode : ED_MODE_DRAWING);
+
+  DrawEditModeWindow();
+}
+
 static boolean LevelChanged()
 {
   boolean field_changed = FALSE;
   int x, y;
 
-#if 1
-  /* changed read-only levels can now be saved in personal level set */
-#else
-  if (leveldir_current->readonly)
-    return FALSE;
-#endif
-
   for (y = 0; y < lev_fieldy; y++) 
     for (x = 0; x < lev_fieldx; x++)
       if (Feld[x][y] != level.field[x][y])
@@ -6728,8 +7017,8 @@ static boolean PrepareSavingIntoPersonalLevelSet()
     return TRUE;
   }
 
-  if (!Request("This level is read only ! "
-	       "Save into personal level set ?", REQ_ASK))
+  if (!Request("This level is read only! "
+	       "Save into personal level set?", REQ_ASK))
     return FALSE;
 
   // "cd" to personal level set dir (for writing copy the first time)
@@ -7007,13 +7296,13 @@ static boolean CopyCustomElement(int element_old, int element_new,
   }
   else if (IS_CUSTOM_ELEMENT(element_old) && !IS_CUSTOM_ELEMENT(element_new))
   {
-    Request("Please choose custom element !", REQ_CONFIRM);
+    Request("Please choose custom element!", REQ_CONFIRM);
 
     return FALSE;
   }
   else if (IS_GROUP_ELEMENT(element_old) && !IS_GROUP_ELEMENT(element_new))
   {
-    Request("Please choose group element !", REQ_CONFIRM);
+    Request("Please choose group element!", REQ_CONFIRM);
 
     return FALSE;
   }
@@ -7238,7 +7527,7 @@ static void CopyCustomElementPropertiesToGame(int element)
 
   if (level.use_custom_template)
   {
-    if (Request("Copy and modify level template ?", REQ_ASK))
+    if (Request("Copy and modify level template?", REQ_ASK))
     {
       level.use_custom_template = FALSE;
       ModifyGadget(level_editor_gadget[GADGET_ID_CUSTOM_USE_TEMPLATE],
@@ -7399,22 +7688,50 @@ void CheckElementDescriptions()
       Error(ERR_WARN, "no element description for element '%s'", EL_NAME(i));
 }
 
+static int getMaxEdFieldX(boolean has_scrollbar)
+{
+  int scrollbar_width = (has_scrollbar ? ED_SCROLLBUTTON_XSIZE : 0);
+  int sxsize = SXSIZE - scrollbar_width;
+  int max_ed_fieldx = sxsize / ed_tilesize;
+
+  return max_ed_fieldx;
+}
+
+static int getMaxEdFieldY(boolean has_scrollbar)
+{
+  int infotext_height = INFOTEXT_YSIZE_FULL;
+  int scrollbar_height = (has_scrollbar ? ED_SCROLLBUTTON_YSIZE : 0);
+  int sysize = SYSIZE - scrollbar_height - infotext_height;
+  int max_ed_fieldy = sysize / ed_tilesize;
+
+  return max_ed_fieldy;
+}
+
+void InitZoomLevelSettings()
+{
+  MAX_ED_FIELDX = getMaxEdFieldX(FALSE);
+  MAX_ED_FIELDY = getMaxEdFieldY(FALSE);
+}
+
 void DrawLevelEd()
 {
-  StopAnimation();
+  int fade_mask = REDRAW_FIELD;
 
-  CloseDoor(DOOR_CLOSE_ALL);
+  FadeSoundsAndMusic();
 
-#if 1
-  FadeOut(REDRAW_FIELD);
-#endif
+  if (CheckIfGlobalBorderHasChanged())
+    fade_mask = REDRAW_ALL;
+
+  FadeOut(fade_mask);
 
-#if 1
   /* needed if different viewport properties defined for editor */
   ChangeViewportPropertiesIfNeeded();
-#endif
 
-  OpenDoor(DOOR_OPEN_2 | DOOR_NO_DELAY);
+  ClearField();
+
+  InitZoomLevelSettings();
+
+  OpenDoor(DOOR_OPEN_1 | DOOR_OPEN_2 | DOOR_NO_DELAY);
 
 #if DEBUG
   CheckElementDescriptions();
@@ -7439,61 +7756,49 @@ void DrawLevelEd()
     level_ypos = -1;
   }
 
-  /* copy default editor door content to main double buffer */
-  BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
-	     DOOR_GFX_PAGEX6, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY);
+  /* needed for gadgets drawn on background (like palette scrollbar) */
+  SetDoorBackgroundImage(IMG_UNDEFINED);
 
-#if 0
-  printf("::: %d, %d  /  %d, %d\n", VX, VY, EX, EY);
-#endif
+  /* copy default editor door content to main double buffer */
+  BlitBitmap(graphic_info[IMG_BACKGROUND_PALETTE].bitmap, drawto,
+	     graphic_info[IMG_BACKGROUND_PALETTE].src_x,
+	     graphic_info[IMG_BACKGROUND_PALETTE].src_y,
+	     MIN(DXSIZE, graphic_info[IMG_BACKGROUND_PALETTE].width),
+	     MIN(DYSIZE, graphic_info[IMG_BACKGROUND_PALETTE].height),
+	     DX, DY);
 
   /* draw bigger door */
   DrawSpecialEditorDoor();
 
   /* draw new control window */
-  BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
-	     DOOR_GFX_PAGEX8, 236, EXSIZE, EYSIZE, EX, EY);
+  BlitBitmap(graphic_info[IMG_BACKGROUND_TOOLBOX].bitmap, drawto,
+	     graphic_info[IMG_BACKGROUND_TOOLBOX].src_x,
+	     graphic_info[IMG_BACKGROUND_TOOLBOX].src_y,
+	     MIN(EXSIZE, graphic_info[IMG_BACKGROUND_TOOLBOX].width),
+	     MIN(EYSIZE, graphic_info[IMG_BACKGROUND_TOOLBOX].height),
+	     EX, EY);
 
-  redraw_mask |= REDRAW_ALL;
+  // redraw_mask |= REDRAW_ALL;
 
-#if 1
   FreeLevelEditorGadgets();
   CreateLevelEditorGadgets();
-#endif
 
   ReinitializeElementList();		/* update dynamic level element list */
   ReinitializeElementListButtons();	/* custom element may look different */
 
   InitElementPropertiesGfxElement();
 
-#if 1
   UnmapAllGadgets();
-#else
-  UnmapTapeButtons();
-#endif
   MapControlButtons();
 
-#if 0
-  FadeOut(REDRAW_FIELD);
-#endif
-
   DrawEditModeWindow();
 
-#if 1
-  FadeIn(REDRAW_FIELD);
-#endif
-
-  /* copy actual editor door content to door double buffer for OpenDoor() */
-  BlitBitmap(drawto, bitmap_db_door,
-	     DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+  DrawMaskedBorder(fade_mask);
 
-#if 1
-  /* draw new control window (with border) to window */
-  redraw_mask |= REDRAW_ALL;
-  BackToFront();
-#endif
+  FadeIn(fade_mask);
 
-  OpenDoor(DOOR_OPEN_1);
+  /* copy actual editor door content to door double buffer for OpenDoor() */
+  BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0);
 }
 
 static void AdjustDrawingAreaGadgets()
@@ -7505,54 +7810,62 @@ static void AdjustDrawingAreaGadgets()
   boolean horizontal_scrollbar_needed;
   boolean vertical_scrollbar_needed;
   int x, y, width, height;
-  int xoffset, yoffset;
 
   /* check if we need any scrollbars */
   horizontal_scrollbar_needed = (ed_xsize > max_ed_fieldx);
-  vertical_scrollbar_needed = (ed_ysize > max_ed_fieldy);
+  vertical_scrollbar_needed   = (ed_ysize > max_ed_fieldy);
 
   /* check if we have a smaller editor field because of scrollbars */
-  if (horizontal_scrollbar_needed)
-    max_ed_fieldy = MAX_ED_FIELDY - 1;
-  if (vertical_scrollbar_needed)
-    max_ed_fieldx = MAX_ED_FIELDX - 1;
+  max_ed_fieldx = getMaxEdFieldX(vertical_scrollbar_needed);
+  max_ed_fieldy = getMaxEdFieldY(horizontal_scrollbar_needed);
 
   /* check again if we now need more scrollbars because of less space */
   horizontal_scrollbar_needed = (ed_xsize > max_ed_fieldx);
-  vertical_scrollbar_needed = (ed_ysize > max_ed_fieldy);
+  vertical_scrollbar_needed   = (ed_ysize > max_ed_fieldy);
 
   /* check if editor field gets even smaller after adding new scrollbars */
-  if (horizontal_scrollbar_needed)
-    max_ed_fieldy = MAX_ED_FIELDY - 1;
-  if (vertical_scrollbar_needed)
-    max_ed_fieldx = MAX_ED_FIELDX - 1;
+  max_ed_fieldx = getMaxEdFieldX(vertical_scrollbar_needed);
+  max_ed_fieldy = getMaxEdFieldY(horizontal_scrollbar_needed);
+
+  ed_fieldx = (ed_xsize > max_ed_fieldx ? max_ed_fieldx : ed_xsize);
+  ed_fieldy = (ed_ysize > max_ed_fieldy ? max_ed_fieldy : ed_ysize);
 
-  ed_fieldx = (ed_xsize < MAX_ED_FIELDX ? ed_xsize : max_ed_fieldx);
-  ed_fieldy = (ed_ysize < MAX_ED_FIELDY ? ed_ysize : max_ed_fieldy);
+  x = SX + ed_fieldx * ed_tilesize;
+  y = SY + ed_fieldy * ed_tilesize;
 
+  width  = ed_fieldx * ed_tilesize - 2 * ED_SCROLLBUTTON_XSIZE;
+  height = ed_fieldy * ed_tilesize - 2 * ED_SCROLLBUTTON_YSIZE;
+
+  /* adjust drawing area gadget */
   ModifyGadget(level_editor_gadget[GADGET_ID_DRAWING_LEVEL],
-	       GDI_WIDTH, ed_fieldx * MINI_TILEX,
-	       GDI_HEIGHT, ed_fieldy * MINI_TILEY,
 	       GDI_AREA_SIZE, ed_fieldx, ed_fieldy,
+	       GDI_ITEM_SIZE, ed_tilesize, ed_tilesize,
 	       GDI_END);
 
-  xoffset = (ed_fieldx == MAX_ED_FIELDX ? ED_SCROLLBUTTON_XSIZE : 0);
-  yoffset = (ed_fieldy == MAX_ED_FIELDY ? ED_SCROLLBUTTON_YSIZE : 0);
-
-  x = SX + scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_RIGHT].x + xoffset;
-  y = SX + scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_DOWN].y + yoffset;
-
-  ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_RIGHT], GDI_X, x, GDI_END);
-  ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_DOWN], GDI_Y, y, GDI_END);
-
-  width = scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].width + xoffset;
-  height = scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].height + yoffset;
-
+  /* adjust horizontal scrollbar gadgets */
+  ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_LEFT],
+	       GDI_Y, y,
+	       GDI_END);
+  ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_RIGHT],
+	       GDI_X, x - ED_SCROLLBUTTON_XSIZE,
+	       GDI_Y, y,
+	       GDI_END);
   ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_HORIZONTAL],
+	       GDI_Y, y,
 	       GDI_WIDTH, width,
 	       GDI_SCROLLBAR_ITEMS_VISIBLE, ed_fieldx,
 	       GDI_END);
+
+  /* adjust vertical scrollbar gadgets */
+  ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_UP],
+	       GDI_X, x,
+	       GDI_END);
+  ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_DOWN],
+	       GDI_X, x,
+	       GDI_Y, y - ED_SCROLLBUTTON_YSIZE,
+	       GDI_END);
   ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_VERTICAL],
+	       GDI_X, x,
 	       GDI_HEIGHT, height,
 	       GDI_SCROLLBAR_ITEMS_VISIBLE, ed_fieldy,
 	       GDI_END);
@@ -7646,7 +7959,8 @@ static void ModifyEditorCounterLimits(int counter_id, int min, int max)
     struct GadgetInfo *gi_up = level_editor_gadget[gadget_id_up];
 
     ModifyGadget(gi, GDI_TEXT_SIZE, (max < 10 ? 1 : 3), GDI_END);
-    ModifyGadget(gi_up, GDI_X, gi->x + gi->width + ED_GADGET_DISTANCE,GDI_END);
+    ModifyGadget(gi_up, GDI_X, gi->x + gi->width + ED_GADGET_SMALL_DISTANCE,
+		 GDI_END);
   }
 }
 
@@ -7687,48 +8001,74 @@ static void ModifyEditorElementList()
 {
   int i;
 
+  if (!use_permanent_palette && edit_mode != ED_MODE_PALETTE)
+    return;
+
   for (i = 0; i < ED_NUM_ELEMENTLIST_BUTTONS; i++)
   {
     int gadget_id = GADGET_ID_ELEMENTLIST_FIRST + i;
     struct GadgetInfo *gi = level_editor_gadget[gadget_id];
     struct GadgetDesign *gd = &gi->deco.design;
     int element = editor_elements[element_shift + i];
+    int tile_size = BUTTON_TILE_SIZE(editor.palette.tile_size);
 
     UnmapGadget(gi);
 
-    getMiniGraphicSource(el2edimg(element), &gd->bitmap, &gd->x, &gd->y);
+    getEditorGraphicSource(element, tile_size, &gd->bitmap, &gd->x, &gd->y);
+
     ModifyGadget(gi, GDI_INFO_TEXT, getElementInfoText(element), GDI_END);
 
     MapGadget(gi);
   }
 }
 
-static void PickDrawingElement(int button, int element)
+static void DrawDrawingElementGraphic(int element, struct XYTileSize *pos)
 {
-  if (button < 1 || button > 3)
+  int graphic = el2edimg(element);
+  int tile_size = BUTTON_TILE_SIZE(pos->tile_size);
+
+  if (pos->x == -1 &&
+      pos->y == -1)
     return;
 
-  if (button == 1)
-  {
-    new_element1 = element;
-    DrawMiniGraphicExt(drawto,
-		       DX + ED_WIN_MB_LEFT_XPOS, DY + ED_WIN_MB_LEFT_YPOS,
-		       el2edimg(new_element1));
-  }
-  else if (button == 2)
+  DrawSizedGraphicExt(drawto, DX + pos->x, DY + pos->y, graphic, 0, tile_size);
+}
+
+static void ModifyDrawingElementButton(int element, int id)
+{
+  struct GadgetInfo *gi = level_editor_gadget[id];
+  Bitmap *deco_bitmap;
+  int deco_x, deco_y;
+  int tile_size = gi->deco.width;
+
+  getEditorGraphicSource(element, tile_size, &deco_bitmap, &deco_x, &deco_y);
+
+  ModifyGadget(gi, GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y, GDI_END);
+}
+
+static void PickDrawingElement(int button, int element)
+{
+  struct
   {
-    new_element2 = element;
-    DrawMiniGraphicExt(drawto,
-		       DX + ED_WIN_MB_MIDDLE_XPOS, DY + ED_WIN_MB_MIDDLE_YPOS,
-		       el2edimg(new_element2));
-  }
-  else
+    int *new_element;
+    struct XYTileSize *pos;
+    int id;
+  } de, drawing_elements[] =
   {
-    new_element3 = element;
-    DrawMiniGraphicExt(drawto,
-		       DX + ED_WIN_MB_RIGHT_XPOS, DY + ED_WIN_MB_RIGHT_YPOS,
-		       el2edimg(new_element3));
-  }
+    { &new_element1, &editor.palette.element_left,   GADGET_ID_ELEMENT_LEFT   },
+    { &new_element2, &editor.palette.element_middle, GADGET_ID_ELEMENT_MIDDLE },
+    { &new_element3, &editor.palette.element_right,  GADGET_ID_ELEMENT_RIGHT  },
+  };
+
+  if (button < 1 || button > 3)
+    return;
+
+  de = drawing_elements[button - 1];
+
+  *de.new_element = element;	// update global drawing element variable
+
+  DrawDrawingElementGraphic(element, de.pos);
+  ModifyDrawingElementButton(element, de.id);
 
   redraw_mask |= REDRAW_DOOR_1;
 }
@@ -7747,7 +8087,7 @@ static void DrawDrawingWindow()
   SetMainBackgroundImage(IMG_UNDEFINED);
   ClearField();
 
-  UnmapLevelEditorWindowGadgets();
+  UnmapLevelEditorFieldGadgets();
   UnmapLevelEditorToolboxCustomGadgets();
 
   AdjustDrawingAreaGadgets();
@@ -7755,7 +8095,7 @@ static void DrawDrawingWindow()
   AdjustEditorScrollbar(GADGET_ID_SCROLL_HORIZONTAL);
   AdjustEditorScrollbar(GADGET_ID_SCROLL_VERTICAL);
 
-  DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
+  DrawEditorLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
 
   MapMainDrawingArea();
   MapLevelEditorToolboxDrawingGadgets();
@@ -7769,6 +8109,11 @@ static int getTabulatorBarWidth()
   return gd_gi4->x - gd_gi1->x + gd_gi4->width;
 }
 
+static int getTabulatorBarHeight()
+{
+  return ED_TAB_BAR_HEIGHT;
+}
+
 static void DrawLevelInfoTabulatorGadgets()
 {
   struct GadgetInfo *gd_gi1 = level_editor_gadget[GADGET_ID_LEVELINFO_LEVEL];
@@ -7778,10 +8123,6 @@ static void DrawLevelInfoTabulatorGadgets()
   Pixel tab_color = GetPixel(gd->bitmap, gd_x, gd_y);
   int id_first = ED_TEXTBUTTON_ID_LEVELINFO_LEVEL;
   int id_last  = ED_TEXTBUTTON_ID_LEVELINFO_EDITOR;
-#if 1
-#else
-  int max_tabs = 2;
-#endif
   int i;
 
   for (i = id_first; i <= id_last; i++)
@@ -7795,25 +8136,18 @@ static void DrawLevelInfoTabulatorGadgets()
 
     /* draw solid line below inactive tabulator buttons */
     if (!active && tab_color != BLACK_PIXEL)	/* black => transparent */
-      FillRectangle(drawto, gi->x, gi->y + gi->height, gi->width, 1, tab_color);
+      FillRectangle(drawto, gi->x, gi->y + gi->height, gi->width,
+		    ED_GADGET_TINY_DISTANCE, tab_color);
 
     ModifyGadget(gi, GDI_ACTIVE, active, GDI_END);
     MapTextbuttonGadget(i);
   }
 
-#if 1
   /* draw little border line below tabulator buttons */
   if (tab_color != BLACK_PIXEL)			/* black => transparent */
-    FillRectangle(drawto, gd_gi1->x, gd_gi1->y + gd_gi1->height + 1,
-		  getTabulatorBarWidth(), ED_GADGET_DISTANCE,
-		  tab_color);
-#else
-  /* draw little border line below tabulator buttons */
-  if (tab_color != BLACK_PIXEL)			/* black => transparent */
-    FillRectangle(drawto, gd_gi1->x, gd_gi1->y + gd_gi1->height + 1,
-		  max_tabs * gd_gi1->width + (max_tabs -1) * ED_GADGET_DISTANCE,
-		  ED_GADGET_DISTANCE, tab_color);
-#endif
+    FillRectangle(drawto, gd_gi1->x, gd_gi1->y + gd_gi1->height +
+		  ED_GADGET_TINY_DISTANCE,
+		  getTabulatorBarWidth(), getTabulatorBarHeight(), tab_color);
 }
 
 static void DrawPropertiesTabulatorGadgets()
@@ -7825,10 +8159,6 @@ static void DrawPropertiesTabulatorGadgets()
   Pixel tab_color = GetPixel(gd->bitmap, gd_x, gd_y);
   int id_first = ED_TEXTBUTTON_ID_PROPERTIES_INFO;
   int id_last  = ED_TEXTBUTTON_ID_PROPERTIES_CONFIG;
-#if 1
-#else
-  int max_tabs = 4;
-#endif
   int i;
 
   /* draw two config tabulators for player elements */
@@ -7856,25 +8186,18 @@ static void DrawPropertiesTabulatorGadgets()
 
     /* draw solid line below inactive tabulator buttons */
     if (!active && tab_color != BLACK_PIXEL)	/* black => transparent */
-      FillRectangle(drawto, gi->x, gi->y + gi->height, gi->width, 1, tab_color);
+      FillRectangle(drawto, gi->x, gi->y + gi->height, gi->width,
+		    ED_GADGET_TINY_DISTANCE, tab_color);
 
     ModifyGadget(gi, GDI_ACTIVE, active, GDI_END);
     MapTextbuttonGadget(i);
   }
 
-#if 1
   /* draw little border line below tabulator buttons */
   if (tab_color != BLACK_PIXEL)			/* black => transparent */
-    FillRectangle(drawto, gd_gi1->x, gd_gi1->y + gd_gi1->height + 1,
-		  getTabulatorBarWidth(), ED_GADGET_DISTANCE,
-		  tab_color);
-#else
-  /* draw little border line below tabulator buttons */
-  if (tab_color != BLACK_PIXEL)			/* black => transparent */
-    FillRectangle(drawto, gd_gi1->x, gd_gi1->y + gd_gi1->height + 1,
-		  max_tabs * gd_gi1->width + (max_tabs -1) * ED_GADGET_DISTANCE,
-		  ED_GADGET_DISTANCE, tab_color);
-#endif
+    FillRectangle(drawto, gd_gi1->x, gd_gi1->y + gd_gi1->height +
+		  ED_GADGET_TINY_DISTANCE,
+		  getTabulatorBarWidth(), getTabulatorBarHeight(), tab_color);
 }
 
 static void DrawLevelInfoLevel()
@@ -7916,26 +8239,20 @@ static void DrawLevelInfoEditor()
 
 static void DrawLevelInfoWindow()
 {
+  char *text = "Global Settings";
+  int font_nr = FONT_TITLE_1;
+  struct MenuPosInfo *pos = &editor.settings.headline;
+  int sx = SX + ALIGNED_XPOS(pos->x, getTextWidth(text, font_nr), pos->align);
+  int sy = SY + pos->y;
+
   stick_element_properties_window = FALSE;
 
-  UnmapLevelEditorWindowGadgets();
+  UnmapLevelEditorFieldGadgets();
 
   SetMainBackgroundImage(IMG_BACKGROUND_EDITOR);
   ClearField();
 
-#if 1
-#if 1
-  DrawTextSCentered(ED_SETTINGS1_YPOS, FONT_TITLE_1, "Global Settings");
-#else
-  DrawTextSCentered(ED_SETTINGS1_YPOS, FONT_TITLE_1, "Level Settings");
-  DrawTextSCentered(ED_SETTINGS2_YPOS, FONT_TITLE_1, "Editor Settings");
-#endif
-#else
-  DrawText(SX + ED_SETTINGS2_XPOS, SY + ED_SETTINGS1_YPOS,
-	   "Level Settings", FONT_TITLE_1);
-  DrawText(SX + ED_SETTINGS2_XPOS, SY + ED_SETTINGS2_YPOS,
-	   "Editor Settings", FONT_TITLE_1);
-#endif
+  DrawText(sx, sy, text, font_nr);
 
   DrawLevelInfoTabulatorGadgets();
 
@@ -7952,7 +8269,7 @@ static void DrawCustomContentArea()
   int x1 = right_gadget_border[GADGET_ID_CUSTOM_DEADLINESS];
   int x2 = right_gadget_border[GADGET_ID_CUSTOM_EXPLOSION_TYPE];
   int x3 = right_gadget_border[GADGET_ID_CUSTOM_EXPLODE_IMPACT];
-  int xoffset = ED_DRAWINGAREA_TEXT_DISTANCE;
+  int xoffset = ED_GADGET_SPACE_DISTANCE;
 
   /* add distance for potential left text (without drawing area border) */
   x2 += getTextWidthForGadget(drawingarea_info[id].text_left);
@@ -7969,17 +8286,32 @@ static void DrawCustomChangeContentArea()
   int x1 = right_gadget_border[GADGET_ID_CHANGE_USE_CONTENT];
   int x2 = right_gadget_border[GADGET_ID_CHANGE_REPLACE_WHEN];
   int x3 = right_gadget_border[GADGET_ID_CHANGE_ONLY_COMPLETE];
-  int xoffset = ED_DRAWINGAREA_TEXT_DISTANCE;
+  int xoffset = ED_GADGET_SPACE_DISTANCE;
 
   ModifyGadget(gi, GDI_X, MAX(x1, MAX(x2, x3)) + xoffset, GDI_END);
 
   MapDrawingArea(id);
 }
 
+static void RemoveElementContentArea(int id, int font_height)
+{
+  int border_size = ED_DRAWINGAREA_BORDER_SIZE;
+
+  DrawBackground(SX + ED_AREA_SETTINGS_X(drawingarea_info[id]) - border_size,
+		 SY + ED_AREA_SETTINGS_Y(drawingarea_info[id]) - border_size,
+		 3 * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size,
+		 3 * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size +
+		 ED_GADGET_TEXT_DISTANCE + font_height);
+}
+
 static void DrawYamYamContentAreas()
 {
-  int x = SX + ED_AREA_YAMYAM_CONTENT_XPOS(3) + 4 * MINI_TILEX;
-  int y = SY + ED_AREA_YAMYAM_CONTENT_YPOS(0) + ED_BORDER_AREA_YSIZE;
+  int font_nr = FONT_TEXT_1;
+  int font_height = getFontHeight(font_nr);
+  int tilesize = ED_DRAWINGAREA_TILE_SIZE;
+  int yoffset = (tilesize - font_height) / 2;
+  int x = SX + ED_AREA_YAMYAM_CONTENT_X(3) + 4 * tilesize;
+  int y = SY + ED_AREA_YAMYAM_CONTENT_Y(3) + yoffset;
   int i;
 
   /* display counter to choose number of element content areas */
@@ -7995,27 +8327,26 @@ static void DrawYamYamContentAreas()
     }
     else
     {
-      int font_height = getFontHeight(FONT_TEXT_1);
-
       UnmapDrawingArea(id);
 
       /* delete content areas in case of reducing number of them */
-      DrawBackground(SX + drawingarea_info[id].x - MINI_TILEX / 2,
-		     SY + drawingarea_info[id].y - MINI_TILEY / 2,
-		     4 * MINI_TILEX,
-		     4 * MINI_TILEY + ED_GADGET_TEXT_DISTANCE + font_height);
+      RemoveElementContentArea(id, font_height);
     }
   }
 
-  DrawText(x, y + 0 * MINI_TILEY, "content", FONT_TEXT_1);
-  DrawText(x, y + 1 * MINI_TILEY, "when",    FONT_TEXT_1);
-  DrawText(x, y + 2 * MINI_TILEY, "smashed", FONT_TEXT_1);
+  DrawText(x, y + 0 * tilesize, "content", font_nr);
+  DrawText(x, y + 1 * tilesize, "when",    font_nr);
+  DrawText(x, y + 2 * tilesize, "smashed", font_nr);
 }
 
 static void DrawMagicBallContentAreas()
 {
-  int x = SX + ED_AREA_MAGIC_BALL_CONTENT_XPOS(3) + 4 * MINI_TILEX;
-  int y = SY + ED_AREA_MAGIC_BALL_CONTENT_YPOS(0) + ED_BORDER_AREA_YSIZE;
+  int font_nr = FONT_TEXT_1;
+  int font_height = getFontHeight(font_nr);
+  int tilesize = ED_DRAWINGAREA_TILE_SIZE;
+  int yoffset = (tilesize - font_height) / 2;
+  int x = SX + ED_AREA_MAGIC_BALL_CONTENT_X(3) + 4 * tilesize;
+  int y = SY + ED_AREA_MAGIC_BALL_CONTENT_Y(3) + yoffset;
   int i;
 
   /* display counter to choose number of element content areas */
@@ -8031,29 +8362,25 @@ static void DrawMagicBallContentAreas()
     }
     else
     {
-      int font_height = getFontHeight(FONT_TEXT_1);
-
       UnmapDrawingArea(id);
 
       /* delete content areas in case of reducing number of them */
-      DrawBackground(SX + drawingarea_info[id].x - MINI_TILEX / 2,
-		     SY + drawingarea_info[id].y - MINI_TILEY / 2,
-		     4 * MINI_TILEX,
-		     4 * MINI_TILEY + ED_GADGET_TEXT_DISTANCE + font_height);
+      RemoveElementContentArea(id, font_height);
     }
   }
 
-  DrawText(x, y + 0 * MINI_TILEY, "generated", FONT_TEXT_1);
-  DrawText(x, y + 1 * MINI_TILEY, "when",      FONT_TEXT_1);
-  DrawText(x, y + 2 * MINI_TILEY, "active",    FONT_TEXT_1);
+  DrawText(x, y + 0 * tilesize, "generated", font_nr);
+  DrawText(x, y + 1 * tilesize, "when",      font_nr);
+  DrawText(x, y + 2 * tilesize, "active",    font_nr);
 }
 
 static void DrawAndroidElementArea(int element)
 {
-  int num_elements = level.num_android_clone_elements;
   int id = ED_DRAWING_ID_ANDROID_CONTENT;
-  int sx = SX + drawingarea_info[id].x - MINI_TILEX / 2;
-  int sy = SY + drawingarea_info[id].y - MINI_TILEY / 2;
+  int num_elements = level.num_android_clone_elements;
+  int border_size = ED_DRAWINGAREA_BORDER_SIZE;
+  int sx = SX + ED_AREA_SETTINGS_X(drawingarea_info[id]) - border_size;
+  int sy = SY + ED_AREA_SETTINGS_Y(drawingarea_info[id]) - border_size;
   int xsize = MAX_ANDROID_ELEMENTS;
   int ysize = 1;
 
@@ -8068,17 +8395,20 @@ static void DrawAndroidElementArea(int element)
   ModifyEditorDrawingArea(id, num_elements, 1);
 
   /* delete content areas in case of reducing number of them */
-  DrawBackground(sx, sy, (xsize + 1) * MINI_TILEX, (ysize + 1) * MINI_TILEY);
+  DrawBackground(sx, sy,
+		 xsize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size,
+		 ysize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size);
 
   MapDrawingArea(id);
 }
 
 static void DrawGroupElementArea(int element)
 {
-  int num_elements = group_element_info.num_elements;
   int id = ED_DRAWING_ID_GROUP_CONTENT;
-  int sx = SX + drawingarea_info[id].x - MINI_TILEX / 2;
-  int sy = SY + drawingarea_info[id].y - MINI_TILEY / 2;
+  int num_elements = group_element_info.num_elements;
+  int border_size = ED_DRAWINGAREA_BORDER_SIZE;
+  int sx = SX + ED_AREA_SETTINGS_X(drawingarea_info[id]) - border_size;
+  int sy = SY + ED_AREA_SETTINGS_Y(drawingarea_info[id]) - border_size;
   int xsize = MAX_ELEMENTS_IN_GROUP;
   int ysize = 1;
 
@@ -8090,25 +8420,28 @@ static void DrawGroupElementArea(int element)
   ModifyEditorDrawingArea(id, num_elements, 1);
 
   /* delete content areas in case of reducing number of them */
-  DrawBackground(sx, sy, (xsize + 1) * MINI_TILEX, (ysize + 1) * MINI_TILEY);
+  DrawBackground(sx, sy,
+		 xsize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size,
+		 ysize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size);
 
   MapDrawingArea(id);
 }
 
 static void DrawPlayerInitialInventoryArea(int element)
 {
+  int id = ED_DRAWING_ID_INVENTORY_CONTENT;
   int player_nr = GET_PLAYER_NR(element);
   int num_elements = level.initial_inventory_size[player_nr];
-  int id = ED_DRAWING_ID_INVENTORY_CONTENT;
-  int sx = SX + drawingarea_info[id].x - MINI_TILEX / 2;
-  int sy = SY + drawingarea_info[id].y - MINI_TILEY / 2;
+  int border_size = ED_DRAWINGAREA_BORDER_SIZE;
+  int sx = SX + ED_AREA_SETTINGS_X(drawingarea_info[id]) - border_size;
+  int sy = SY + ED_AREA_SETTINGS_Y(drawingarea_info[id]) - border_size;
   int xsize = MAX_INITIAL_INVENTORY_SIZE;
   int ysize = 1;
 
   /* determine horizontal position to the right of specified gadget */
   if (drawingarea_info[id].gadget_id_align != GADGET_ID_NONE)
-    sx += (right_gadget_border[drawingarea_info[id].gadget_id_align] +
-	   ED_DRAWINGAREA_TEXT_DISTANCE);
+    sx = (right_gadget_border[drawingarea_info[id].gadget_id_align] +
+	  ED_DRAWINGAREA_TEXT_DISTANCE);
 
   /* determine horizontal offset for leading text */
   if (drawingarea_info[id].text_left != NULL)
@@ -8119,7 +8452,9 @@ static void DrawPlayerInitialInventoryArea(int element)
   ModifyEditorDrawingArea(id, num_elements, 1);
 
   /* delete content areas in case of reducing number of them */
-  DrawBackground(sx, sy, (xsize + 1) * MINI_TILEX, (ysize + 1) * MINI_TILEY);
+  DrawBackground(sx, sy,
+		 xsize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size,
+		 ysize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size);
 
   MapDrawingArea(id);
 }
@@ -8146,8 +8481,8 @@ static void DrawEnvelopeTextArea(int envelope_nr)
 static boolean PrintInfoText(char *text, int font_nr, int start_line)
 {
   int font_height = getFontHeight(font_nr);
-  int pad_x = ED_ELEMENT_SETTINGS_XPOS(0);
-  int pad_y = ED_ELEMENT_SETTINGS_YPOS(0) + ED_BORDER_SIZE;
+  int pad_x = ED_ELEMENT_SETTINGS_X(0);
+  int pad_y = ED_ELEMENT_SETTINGS_Y(0) + ED_GADGET_SMALL_DISTANCE;
   int sx = SX + pad_x;
   int sy = SY + pad_y;
   int max_lines_per_screen = (SYSIZE - pad_y) / font_height - 1;
@@ -8165,15 +8500,19 @@ static int PrintElementDescriptionFromFile(char *filename, int start_line)
   int font_nr = FONT_TEXT_2;
   int font_width = getFontWidth(font_nr);
   int font_height = getFontHeight(font_nr);
-  int pad_x = ED_ELEMENT_SETTINGS_XPOS(0);
-  int pad_y = ED_ELEMENT_SETTINGS_YPOS(0) + ED_BORDER_SIZE;
+  int pad_x = ED_ELEMENT_SETTINGS_X(0);
+  int pad_y = ED_ELEMENT_SETTINGS_Y(0) + ED_GADGET_SMALL_DISTANCE;
   int sx = SX + pad_x;
   int sy = SY + pad_y + start_line * font_height;
   int max_chars_per_line = (SXSIZE - 2 * pad_x) / font_width;
   int max_lines_per_screen = (SYSIZE - pad_y) / font_height - 1;
+  int max_lines_drawable = max_lines_per_screen - start_line;
+
+  if (start_line >= max_lines_per_screen)
+    return FALSE;
 
   return DrawTextFile(sx, sy, filename, font_nr, max_chars_per_line, -1,
-		      max_lines_per_screen, 0, -1, TRUE, FALSE, FALSE);
+		      max_lines_drawable, 0, -1, TRUE, FALSE, FALSE);
 }
 
 static void DrawPropertiesInfo()
@@ -8237,8 +8576,8 @@ static void DrawPropertiesInfo()
     { -1,			NULL					}
   };
   char *filename = getElementDescriptionFilename(properties_element);
-  char *percentage_text = "In this level:";
-  char *properties_text = "Standard properties:";
+  char *percentage_text = "In this level: ";
+  char *properties_text = "Standard properties: ";
   float percentage;
   int num_elements_in_level;
   int num_standard_properties = 0;
@@ -8246,8 +8585,8 @@ static void DrawPropertiesInfo()
   int font2_nr = FONT_TEXT_2;
   int font1_width = getFontWidth(font1_nr);
   int font2_height = getFontHeight(font2_nr);
-  int pad_x = ED_ELEMENT_SETTINGS_XPOS(0);
-  int pad_y = ED_ELEMENT_SETTINGS_YPOS(0) + ED_BORDER_SIZE;
+  int pad_x = ED_ELEMENT_SETTINGS_X(0);
+  int pad_y = ED_ELEMENT_SETTINGS_Y(0) + ED_GADGET_SMALL_DISTANCE;
   int screen_line = 0;
   int i, x, y;
 
@@ -8456,6 +8795,7 @@ static boolean checkPropertiesConfig(int element)
 
 static void DrawPropertiesConfig()
 {
+  boolean draw_footer_line = FALSE;
   int max_num_element_counters = 4;
   int num_element_counters = 0;
   int i;
@@ -8566,6 +8906,7 @@ static void DrawPropertiesConfig()
       MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CONTINUOUS_SNAPPING);
       MapCheckbuttonGadget(ED_CHECKBUTTON_ID_INSTANT_RELOCATION);
       MapCheckbuttonGadget(ED_CHECKBUTTON_ID_SHIFTED_RELOCATION);
+      MapCheckbuttonGadget(ED_CHECKBUTTON_ID_LAZY_RELOCATION);
       MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_START_ELEMENT);
       MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_ARTWORK_ELEMENT);
       MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_EXPLOSION_ELEMENT);
@@ -8698,6 +9039,8 @@ static void DrawPropertiesConfig()
 
       /* draw drawing area gadgets */
       MapDrawingArea(ED_DRAWING_ID_CUSTOM_GRAPHIC);
+
+      draw_footer_line = TRUE;
     }
     else if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG_2)
     {
@@ -8748,6 +9091,25 @@ static void DrawPropertiesConfig()
 
     /* draw drawing area gadgets */
     MapDrawingArea(ED_DRAWING_ID_CUSTOM_GRAPHIC);
+
+    draw_footer_line = TRUE;
+  }
+
+  /* draw little footer border line above CE/GE use/save template gadgets */
+  if (draw_footer_line)
+  {
+    struct GadgetInfo *gd_gi1 = level_editor_gadget[GADGET_ID_PROPERTIES_INFO];
+    struct GadgetDesign *gd = &gd_gi1->alt_design[GD_BUTTON_UNPRESSED];
+    int gd_x = gd->x + gd_gi1->border.width / 2;
+    int gd_y = gd->y + gd_gi1->height - 1;
+    Pixel tab_color = GetPixel(gd->bitmap, gd_x, gd_y);
+
+    if (tab_color != BLACK_PIXEL)		/* black => transparent */
+      FillRectangle(drawto,
+		    SX + ED_ELEMENT_SETTINGS_X(0),
+		    SY + ED_ELEMENT_SETTINGS_Y(14) - ED_SETTINGS_TABS_YOFFSET -
+		    ED_TAB_BAR_HEIGHT,
+		    getTabulatorBarWidth(), getTabulatorBarHeight(), tab_color);
   }
 }
 
@@ -8812,16 +9174,15 @@ static void DrawEditorElementAnimation(int x, int y)
 	       ANIM_MODE(graphic) == ANIM_CE_SCORE ?
 	       custom_element.collect_score_initial : FrameCounter);
 
-  DrawGraphicAnimationExt(drawto, x, y, graphic, frame, NO_MASKING);
+  DrawFixedGraphicAnimationExt(drawto, x, y, graphic, frame, NO_MASKING);
 }
 
-static void DrawEditorElementName(int x, int y, int element)
+static void DrawEditorElementName(int x, int y, int font_nr)
 {
-  char *element_name = getElementInfoText(element);
-  int font_nr = FONT_TEXT_1;
+  char *element_name = getElementInfoText(properties_element);
   int font_width = getFontWidth(font_nr);
   int font_height = getFontHeight(font_nr);
-  int max_text_width = SXSIZE - x - ED_ELEMENT_SETTINGS_XPOS(0);
+  int max_text_width = SXSIZE - x - ED_ELEMENT_SETTINGS_X(0);
   int max_chars_per_line = max_text_width / font_width;
   char buffer[max_chars_per_line + 1];
 
@@ -8862,8 +9223,24 @@ static void DrawEditorElementName(int x, int y, int element)
 
 static void DrawPropertiesWindow()
 {
-  int xstart = 2;
-  int ystart = 4;
+  struct GraphicInfo *gd = &graphic_info[IMG_EDITOR_INPUT_TEXT];
+  int element_border = graphic_info[IMG_EDITOR_ELEMENT_BORDER].border_size;
+  int border_size = gd->border_size;
+  int font_nr = FONT_TEXT_1;
+  int font_height = getFontHeight(font_nr);
+  int xoffset = TILEX + element_border + 3 * border_size;
+  int yoffset = (TILEY - font_height) / 2;
+  int x1 = editor.settings.element_graphic.x + element_border;
+  int y1 = editor.settings.element_graphic.y + element_border;
+  int x2 = (editor.settings.element_name.x == -1 ? x1 + xoffset :
+	    editor.settings.element_name.x);
+  int y2 = (editor.settings.element_name.y == -1 ? y1 + yoffset :
+	    editor.settings.element_name.y);
+  char *text = "Element Settings";
+  int font2_nr = FONT_TITLE_1;
+  struct MenuPosInfo *pos = &editor.settings.headline;
+  int sx = SX + ALIGNED_XPOS(pos->x, getTextWidth(text, font2_nr), pos->align);
+  int sy = SY + pos->y;
 
   stick_element_properties_window = FALSE;
 
@@ -8884,7 +9261,7 @@ static void DrawPropertiesWindow()
 
   CopyElementPropertiesToEditor(properties_element);
 
-  UnmapLevelEditorWindowGadgets();
+  UnmapLevelEditorFieldGadgets();
   UnmapLevelEditorToolboxDrawingGadgets();
   UnmapLevelEditorToolboxCustomGadgets();
 
@@ -8895,25 +9272,13 @@ static void DrawPropertiesWindow()
   SetMainBackgroundImage(IMG_BACKGROUND_EDITOR);
   ClearField();
 
-#if 1
-  DrawTextSCentered(ED_SETTINGS1_YPOS, FONT_TITLE_1, "Element Settings");
-#else
-  DrawText(SX + ED_SETTINGS2_XPOS, SY + ED_SETTINGS1_YPOS,
-	   "Element Settings", FONT_TITLE_1);
-#endif
+  DrawText(sx, sy, text, font2_nr);
 
   FrameCounter = 0;	/* restart animation frame counter */
 
-  DrawElementBorder(SX + xstart * MINI_TILEX,
-		    SY + ystart * MINI_TILEY + MINI_TILEY / 2,
-		    TILEX, TILEY, FALSE);
-
-  DrawEditorElementAnimation(SX + xstart * MINI_TILEX,
-			     SY + ystart * MINI_TILEY + MINI_TILEY / 2);
-
-  DrawEditorElementName((xstart + 3) * MINI_TILEX + 1,
-			(ystart + 1) * MINI_TILEY + 1,
-			properties_element);
+  DrawElementBorder(SX + x1, SY + y1, TILEX, TILEY, FALSE);
+  DrawEditorElementAnimation(SX + x1, SY + y1);
+  DrawEditorElementName(x2, y2, font_nr);
 
   DrawPropertiesTabulatorGadgets();
 
@@ -8925,6 +9290,23 @@ static void DrawPropertiesWindow()
     DrawPropertiesConfig();
 }
 
+static void DrawPaletteWindow()
+{
+  int i;
+
+  UnmapLevelEditorFieldGadgets();
+
+  SetMainBackgroundImage(IMG_BACKGROUND_EDITOR);
+  ClearField();
+
+  /* map buttons to select elements */
+  for (i = 0; i < ED_NUM_ELEMENTLIST_BUTTONS; i++)
+    MapGadget(level_editor_gadget[GADGET_ID_ELEMENTLIST_FIRST + i]);
+  MapGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_VERTICAL]);
+  MapGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_UP]);
+  MapGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_DOWN]);
+}
+
 static void UpdateCustomElementGraphicGadgets()
 {
   struct ElementInfo *ei = &element_info[properties_element];
@@ -9387,7 +9769,7 @@ static void SetElementSimple(int x, int y, int element, boolean change_level)
     Feld[x][y] = element;
 
   if (IN_ED_FIELD(sx, sy))
-    DrawMiniElement(sx, sy, element);
+    DrawEditorElement(sx, sy, element);
 }
 
 static void MergeAndCloseNeighbourElements(int x1, int y1, int *element1,
@@ -10088,10 +10470,10 @@ static void DrawAreaBorder(int from_x, int from_y, int to_x, int to_y)
   if (from_y > to_y)
     swap_numbers(&from_y, &to_y);
 
-  from_sx = SX + from_x * MINI_TILEX;
-  from_sy = SY + from_y * MINI_TILEY;
-  to_sx = SX + to_x * MINI_TILEX + MINI_TILEX - 1;
-  to_sy = SY + to_y * MINI_TILEY + MINI_TILEY - 1;
+  from_sx = SX + from_x * ed_tilesize;
+  from_sy = SY + from_y * ed_tilesize;
+  to_sx = SX + (to_x + 1) * ed_tilesize - 1;
+  to_sy = SY + (to_y + 1) * ed_tilesize - 1;
 
   DrawSimpleWhiteLine(drawto, from_sx, from_sy, to_sx, from_sy);
   DrawSimpleWhiteLine(drawto, to_sx, from_sy, to_sx, to_sy);
@@ -10124,11 +10506,7 @@ static void SelectArea(int from_x, int from_y, int to_x, int to_y,
 static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y,
 			 int button, int mode)
 {
-#if 1
   static short brush_buffer[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
-#else
-  static short brush_buffer[MAX_ED_FIELDX][MAX_ED_FIELDY];
-#endif
   static int brush_width, brush_height;
   static int last_cursor_x = -1, last_cursor_y = -1;
   static boolean delete_old_brush;
@@ -10159,7 +10537,10 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y,
 	else if (element >= NUM_FILE_ELEMENTS)
 	  element_mapped = EL_UNKNOWN;
 
-	printf("%c%03d", (mode == CB_DUMP_BRUSH ? '`' : '�'), element_mapped);
+	// dump brush as level sketch text for the R'n'D forum:
+	// - large tiles: `xxx (0x60 ASCII)
+	// - small tiles: ¸xxx (0xb8 ISO-8859-1, 0xc2b8 UTF-8)
+	printf("%s%03d", (mode == CB_DUMP_BRUSH ? "`" : "¸"), element_mapped);
       }
 
       printf("\n");
@@ -10309,7 +10690,7 @@ static void FloodFill(int from_x, int from_y, int fill_element)
 static int DrawLevelText(int sx, int sy, char letter, int mode)
 {
   static short delete_buffer[MAX_LEV_FIELDX];
-  static int start_sx, start_sy;
+  static int start_sx;
   static int last_sx, last_sy;
   static boolean typing = FALSE;
   int letter_element = EL_CHAR_ASCII0 + letter;
@@ -10318,11 +10699,11 @@ static int DrawLevelText(int sx, int sy, char letter, int mode)
   /* map lower case letters to upper case and convert special characters */
   if (letter >= 'a' && letter <= 'z')
     letter_element = EL_CHAR_ASCII0 + letter + (int)('A' - 'a');
-  else if (letter == '�' || letter == '�')
+  else if (letter == CHAR_BYTE_UMLAUT_a || letter == CHAR_BYTE_UMLAUT_A)
     letter_element = EL_CHAR_AUMLAUT;
-  else if (letter == '�' || letter == '�')
+  else if (letter == CHAR_BYTE_UMLAUT_o || letter == CHAR_BYTE_UMLAUT_O)
     letter_element = EL_CHAR_OUMLAUT;
-  else if (letter == '�' || letter == '�')
+  else if (letter == CHAR_BYTE_UMLAUT_u || letter == CHAR_BYTE_UMLAUT_U)
     letter_element = EL_CHAR_UUMLAUT;
   else if (letter == '^')
     letter_element = EL_CHAR_COPYRIGHT;
@@ -10351,13 +10732,14 @@ static int DrawLevelText(int sx, int sy, char letter, int mode)
 	DrawLevelText(0, 0, 0, TEXT_END);
 
       typing = TRUE;
-      start_sx = last_sx = sx;
-      start_sy = last_sy = sy;
+      start_sx = sx;
+      last_sx = sx;
+      last_sy = sy;
       DrawLevelText(sx, sy, 0, TEXT_SETCURSOR);
       break;
 
     case TEXT_SETCURSOR:
-      DrawMiniElement(last_sx, last_sy, Feld[lx][ly]);
+      DrawEditorElement(last_sx, last_sy, Feld[lx][ly]);
       DrawAreaBorder(sx, sy, sx, sy);
       last_sx = sx;
       last_sy = sy;
@@ -10366,6 +10748,10 @@ static int DrawLevelText(int sx, int sy, char letter, int mode)
     case TEXT_WRITECHAR:
       if (letter_element >= EL_CHAR_START && letter_element <= EL_CHAR_END)
       {
+	if (new_element1 >= EL_STEEL_CHAR_START &&
+	    new_element1 <= EL_STEEL_CHAR_END)
+	  letter_element = letter_element - EL_CHAR_START + EL_STEEL_CHAR_START;
+
 	delete_buffer[sx - start_sx] = Feld[lx][ly];
 	Feld[lx][ly] = letter_element;
 
@@ -10384,7 +10770,7 @@ static int DrawLevelText(int sx, int sy, char letter, int mode)
       if (sx > start_sx)
       {
 	Feld[lx - 1][ly] = delete_buffer[sx - start_sx - 1];
-	DrawMiniElement(sx - 1, sy, Feld[lx - 1][ly]);
+	DrawEditorElement(sx - 1, sy, Feld[lx - 1][ly]);
 	DrawLevelText(sx - 1, sy, 0, TEXT_SETCURSOR);
       }
       break;
@@ -10398,7 +10784,7 @@ static int DrawLevelText(int sx, int sy, char letter, int mode)
 
     case TEXT_END:
       CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
-      DrawMiniElement(sx, sy, Feld[lx][ly]);
+      DrawEditorElement(sx, sy, Feld[lx][ly]);
       typing = FALSE;
       break;
 
@@ -10419,7 +10805,7 @@ static void SetTextCursor(int unused_sx, int unused_sy, int sx, int sy,
   int ly = sy + level_ypos;
 
   if (element == -1)
-    DrawMiniElement(sx, sy, Feld[lx][ly]);
+    DrawEditorElement(sx, sy, Feld[lx][ly]);
   else
     DrawAreaBorder(sx, sy, sx, sy);
 }
@@ -10431,7 +10817,7 @@ static void CheckLevelBorderElement(boolean redraw_playfield)
   SetBorderElement();
 
   if (redraw_playfield && BorderElement != last_border_element)
-    DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
+    DrawEditorLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
 }
 
 static void CopyLevelToUndoBuffer(int mode)
@@ -10440,6 +10826,9 @@ static void CopyLevelToUndoBuffer(int mode)
   boolean new_undo_buffer_position = TRUE;
   int x, y;
 
+  if (undo_buffer_steps == 0)
+    accumulated_undo = FALSE;
+
   switch (mode)
   {
     case UNDO_IMMEDIATE:
@@ -10458,13 +10847,16 @@ static void CopyLevelToUndoBuffer(int mode)
 
   if (new_undo_buffer_position)
   {
-    /* new position in undo buffer ring */
+    /* advance position in undo buffer ring */
     undo_buffer_position = (undo_buffer_position + 1) % NUM_UNDO_STEPS;
 
     if (undo_buffer_steps < NUM_UNDO_STEPS - 1)
       undo_buffer_steps++;
   }
 
+  /* always reset redo buffer when storing level change into undo buffer */
+  redo_buffer_steps = 0;
+
   for (x = 0; x < lev_fieldx; x++)
     for (y = 0; y < lev_fieldy; y++)
       UndoBuffer[undo_buffer_position][x][y] = Feld[x][y];
@@ -10482,9 +10874,7 @@ static void RandomPlacement(int new_element)
   int num_percentage, num_elements;
   int x, y;
 
-#if 1
   ResetIntelliDraw();
-#endif
 
   /* determine number of free positions for randomly placing the new element */
   for (x = 0; x < lev_fieldx; x++) for (y = 0; y < lev_fieldy; y++)
@@ -10509,11 +10899,7 @@ static void RandomPlacement(int new_element)
     for (x = 0; x < lev_fieldx; x++)
       for (y = 0; y < lev_fieldy; y++)
 	if (free_position[x][y])
-#if 1
 	  SetElement(x, y, new_element);
-#else
-	  Feld[x][y] = new_element;
-#endif
   }
   else
   {
@@ -10526,17 +10912,13 @@ static void RandomPlacement(int new_element)
       if (free_position[x][y])
       {
 	free_position[x][y] = FALSE;
-#if 1
 	SetElement(x, y, new_element);
-#else
-	Feld[x][y] = new_element;
-#endif
 	num_elements--;
       }
     }
   }
 
-  DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
+  DrawEditorLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
   CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
 }
 
@@ -10555,7 +10937,7 @@ void WrapLevel(int dx, int dy)
       Feld[x][y] =
 	FieldBackup[(x + wrap_dx) % lev_fieldx][(y + wrap_dy) % lev_fieldy];
 
-  DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
+  DrawEditorLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
   CopyLevelToUndoBuffer(UNDO_ACCUMULATE);
 }
 
@@ -10649,10 +11031,6 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
 	  if (edit_mode == ED_MODE_DRAWING && draw_with_brush &&
 	      !inside_drawing_area)
 	    DeleteBrushFromCursor();
-
-#if 0
-	  ResetIntelliDraw();
-#endif
 	}
 
 	if (!button || button_release_event)
@@ -10660,50 +11038,20 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
 
 	if (draw_with_brush)
 	{
-#if 0
-	  if (!button_release_event)
-#endif
-	    CopyBrushToLevel(sx, sy, button);
+	  CopyBrushToLevel(sx, sy, button);
 	}
-#if 1
 	else
-#else
-	else if (new_element != Feld[lx][ly])
-#endif
 	{
 	  if (new_element == EL_PLAYER_1)
 	  {
 	    /* remove player at old position */
 	    for (y = 0; y < lev_fieldy; y++)
-	    {
 	      for (x = 0; x < lev_fieldx; x++)
-	      {
 		if (Feld[x][y] == EL_PLAYER_1)
-		{
-#if 1
 		  SetElement(x, y, EL_EMPTY);
-#else
-		  Feld[x][y] = EL_EMPTY;
-#if 1
-		  if (IN_ED_FIELD(x - level_xpos, y - level_ypos))
-		    DrawMiniElement(x - level_xpos, y - level_ypos, EL_EMPTY);
-#else
-		  if (x - level_xpos >= 0 && x - level_xpos < ed_fieldx &&
-		      y - level_ypos >= 0 && y - level_ypos < ed_fieldy)
-		    DrawMiniElement(x - level_xpos, y - level_ypos, EL_EMPTY);
-#endif
-#endif
-		}
-	      }
-	    }
 	  }
 
-#if 1
 	  SetElementButton(lx, ly, new_element, button);
-#else
-	  Feld[lx][ly] = new_element;
-	  DrawMiniElement(sx, sy, new_element);
-#endif
 	}
       }
       else
@@ -10717,10 +11065,10 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
 			     gi->y + sy * MINI_TILEY,
 			     el2edimg(new_element));
 	else
-	  DrawGraphicExt(drawto,
-			 gi->x + sx * TILEX,
-			 gi->y + sy * TILEY,
-			 el2img(new_element), 0);
+	  DrawFixedGraphicExt(drawto,
+			      gi->x + sx * TILEX,
+			      gi->y + sy * TILEY,
+			      el2edimg(new_element), 0);
 
 	if (id == GADGET_ID_CUSTOM_GRAPHIC)
 	  new_element = GFX_ELEMENT(new_element);
@@ -10822,7 +11170,7 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
       if (button_press_event && Feld[lx][ly] != new_element)
       {
 	FloodFill(lx, ly, new_element);
-	DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
+	DrawEditorLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
 	CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
       }
       break;
@@ -10866,7 +11214,7 @@ static void HandleCounterButtons(struct GadgetInfo *gi)
     if ((level_changed && pressed) || (!level_changed && released))
       return;
 
-    if (level_changed && !Request("Level has changed ! Discard changes ?",
+    if (level_changed && !Request("Level has changed! Discard changes?",
 				  REQ_ASK))
     {
       if (gadget_id == counterbutton_info[counter_id].gadget_id_text)
@@ -10926,6 +11274,10 @@ static void HandleCounterButtons(struct GadgetInfo *gi)
     case ED_COUNTER_ID_LEVEL_YSIZE:
       lev_fieldx = level.fieldx;
       lev_fieldy = level.fieldy;
+
+      /* check if resizing of level results in change of border border */
+      SetBorderElement();
+
       break;
 
     default:
@@ -10961,14 +11313,9 @@ static void HandleTextAreaGadgets(struct GadgetInfo *gi)
 {
   int type_id = gi->custom_type_id;
 
-#if 1
   strncpy(textarea_info[type_id].value, gi->textarea.value,
 	  MAX_ENVELOPE_TEXT_LEN);
   textarea_info[type_id].value[MAX_ENVELOPE_TEXT_LEN] = '\0';
-#else
-  /* !!! BUGGY !!! MAX_ENVELOPE_TEXT_LEN != MAX_GADGET_TEXTSIZE !!! */
-  strcpy(textarea_info[type_id].value, gi->textarea.value);
-#endif
 
   level.changed = TRUE;
 }
@@ -11039,11 +11386,11 @@ static void HandleTextbuttonGadgets(struct GadgetInfo *gi)
     CopyPlayfield(Feld, level.field);
 
     if (new_template ||
-	Request("Save this template and kill the old ?", REQ_ASK))
+	Request("Save this template and kill the old?", REQ_ASK))
       SaveLevelTemplate();
 
     if (new_template)
-      Request("Template saved !", REQ_CONFIRM);
+      Request("Template saved!", REQ_CONFIRM);
 
     /* restore original "level.field" (needed to track playfield changes) */
     CopyPlayfield(FieldBackup, level.field);
@@ -11159,7 +11506,7 @@ static void HandleCheckbuttons(struct GadgetInfo *gi)
 
     if (level.use_custom_template && !fileExists(template_filename))
     {
-      Request("No level template found !", REQ_CONFIRM);
+      Request("No level template found!", REQ_CONFIRM);
 
       level.use_custom_template = FALSE;
       ModifyGadget(gi, GDI_CHECKED, FALSE, GDI_END);
@@ -11180,10 +11527,12 @@ static void HandleControlButtons(struct GadgetInfo *gi)
   static int last_level_drawing_function = GADGET_ID_SINGLE_ITEMS;
   static int last_edit_mode = ED_MODE_DRAWING;
   static int last_custom_copy_mode = -1;
+  static int last_button = 0;
   int id = gi->custom_id;
   int button = gi->event.button;
   int step = BUTTON_STEPSIZE(button);
   int new_element = BUTTON_ELEMENT(button);
+  int last_properties_element = properties_element;
   int x, y;
 
   if (edit_mode == ED_MODE_DRAWING && drawing_function == GADGET_ID_TEXT)
@@ -11191,20 +11540,25 @@ static void HandleControlButtons(struct GadgetInfo *gi)
 
   if (id < ED_NUM_CTRL1_BUTTONS &&
       id != GADGET_ID_SINGLE_ITEMS &&
-      id != GADGET_ID_PROPERTIES &&
       id != GADGET_ID_PICK_ELEMENT &&
       edit_mode != ED_MODE_DRAWING &&
       drawing_function != GADGET_ID_PICK_ELEMENT &&
       !(GetKeyModState() & KMOD_Control))
-  {
-    DrawDrawingWindow();
-    edit_mode = ED_MODE_DRAWING;
-  }
+    ChangeEditModeWindow(ED_MODE_DRAWING);
 
   /* element copy mode active, but no element button pressed => deactivate */
   if (last_custom_copy_mode != -1 && id < ED_NUM_CTRL_BUTTONS)
     last_custom_copy_mode = -1;
 
+  /* when showing palette on element buttons, change element of button used */
+  if (editor.palette.show_on_element_buttons &&
+      id >= GADGET_ID_ELEMENT_LEFT && id <= GADGET_ID_ELEMENT_RIGHT)
+  {
+    last_button = id - GADGET_ID_ELEMENT_LEFT + 1;
+
+    id = GADGET_ID_PALETTE;
+  }
+
   switch (id)
   {
     case GADGET_ID_SCROLL_LEFT:
@@ -11217,9 +11571,9 @@ static void HandleControlButtons(struct GadgetInfo *gi)
 	if (level_xpos < -1)
 	  level_xpos = -1;
 	if (button == 1)
-	  ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_RIGHT);
+	  ScrollEditorLevel(level_xpos, level_ypos, ED_SCROLL_RIGHT);
 	else
-	  DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
+	  DrawEditorLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
 
 	ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_HORIZONTAL],
 		     GDI_SCROLLBAR_ITEM_POSITION, level_xpos + 1, GDI_END);
@@ -11236,9 +11590,9 @@ static void HandleControlButtons(struct GadgetInfo *gi)
 	if (level_xpos > lev_fieldx - ed_fieldx + 1)
 	  level_xpos = lev_fieldx - ed_fieldx + 1;
 	if (button == 1)
-	  ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_LEFT);
+	  ScrollEditorLevel(level_xpos, level_ypos, ED_SCROLL_LEFT);
 	else
-	  DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
+	  DrawEditorLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
 
 	ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_HORIZONTAL],
 		     GDI_SCROLLBAR_ITEM_POSITION, level_xpos + 1, GDI_END);
@@ -11255,9 +11609,9 @@ static void HandleControlButtons(struct GadgetInfo *gi)
 	if (level_ypos < -1)
 	  level_ypos = -1;
 	if (button == 1)
-	  ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_DOWN);
+	  ScrollEditorLevel(level_xpos, level_ypos, ED_SCROLL_DOWN);
 	else
-	  DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
+	  DrawEditorLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
 
 	ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_VERTICAL],
 		     GDI_SCROLLBAR_ITEM_POSITION, level_ypos + 1, GDI_END);
@@ -11274,9 +11628,9 @@ static void HandleControlButtons(struct GadgetInfo *gi)
 	if (level_ypos > lev_fieldy - ed_fieldy + 1)
 	  level_ypos = lev_fieldy - ed_fieldy + 1;
 	if (button == 1)
-	  ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_UP);
+	  ScrollEditorLevel(level_xpos, level_ypos, ED_SCROLL_UP);
 	else
-	  DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
+	  DrawEditorLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
 
 	ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_VERTICAL],
 		     GDI_SCROLLBAR_ITEM_POSITION, level_ypos + 1, GDI_END);
@@ -11285,12 +11639,18 @@ static void HandleControlButtons(struct GadgetInfo *gi)
 
     case GADGET_ID_SCROLL_HORIZONTAL:
       level_xpos = gi->event.item_position - 1;
-      DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
+
+      DrawEditorLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
+      BackToFront();
+
       break;
 
     case GADGET_ID_SCROLL_VERTICAL:
       level_ypos = gi->event.item_position - 1;
-      DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
+
+      DrawEditorLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
+      BackToFront();
+
       break;
 
     case GADGET_ID_SCROLL_LIST_UP:
@@ -11317,6 +11677,53 @@ static void HandleControlButtons(struct GadgetInfo *gi)
 
       break;
 
+    case GADGET_ID_PROPERTIES:
+      // always switch off element properties when they are already displayed
+      last_properties_element = new_element;
+    case GADGET_ID_ELEMENT_LEFT:
+    case GADGET_ID_ELEMENT_MIDDLE:
+    case GADGET_ID_ELEMENT_RIGHT:
+      properties_element = (id == GADGET_ID_ELEMENT_LEFT   ? new_element1 :
+			    id == GADGET_ID_ELEMENT_MIDDLE ? new_element2 :
+			    id == GADGET_ID_ELEMENT_RIGHT  ? new_element3 :
+			    new_element);
+
+      if (edit_mode != ED_MODE_PROPERTIES)
+      {
+	last_edit_mode = edit_mode;
+
+	ChangeEditModeWindow(ED_MODE_PROPERTIES);
+
+	last_level_drawing_function = drawing_function;
+	ClickOnGadget(level_editor_gadget[GADGET_ID_SINGLE_ITEMS],
+		      MB_LEFTBUTTON);
+      }
+      else if (properties_element != last_properties_element)
+      {
+	DrawEditModeWindow();
+      }
+      else
+      {
+	ChangeEditModeWindow(last_edit_mode);
+
+	ClickOnGadget(level_editor_gadget[last_level_drawing_function],
+		      MB_LEFTBUTTON);
+      }
+      break;
+
+    case GADGET_ID_PALETTE:
+      if (edit_mode != ED_MODE_PALETTE)
+      {
+	last_edit_mode = edit_mode;
+
+	ChangeEditModeWindow(ED_MODE_PALETTE);
+      }
+      else
+      {
+	ChangeEditModeWindow(last_edit_mode);
+      }
+      break;
+
     case GADGET_ID_WRAP_LEFT:
       WrapLevel(-step, 0);
       break;
@@ -11353,25 +11760,20 @@ static void HandleControlButtons(struct GadgetInfo *gi)
       RandomPlacement(new_element);
       break;
 
-    case GADGET_ID_PROPERTIES:
-      if (edit_mode != ED_MODE_PROPERTIES)
-      {
-	properties_element = new_element;
-	DrawPropertiesWindow();
-	edit_mode = ED_MODE_PROPERTIES;
+    case GADGET_ID_ZOOM:
+      // zoom level editor tile size in or out (or reset to default size)
+      ed_tilesize = (button == 1 ? ed_tilesize * 2 :
+		     button == 2 ? DEFAULT_EDITOR_TILESIZE :
+		     button == 3 ? ed_tilesize / 2 : ed_tilesize);
 
-	last_level_drawing_function = drawing_function;
-	ClickOnGadget(level_editor_gadget[GADGET_ID_SINGLE_ITEMS],
-		      MB_LEFTBUTTON);
-      }
-      else
-      {
+      // limit zoom level by upper and lower bound
+      ed_tilesize = MIN(MAX(MICRO_TILESIZE, ed_tilesize), TILESIZE);
+
+      InitZoomLevelSettings();
+
+      if (edit_mode == ED_MODE_DRAWING)
 	DrawDrawingWindow();
-	edit_mode = ED_MODE_DRAWING;
 
-	ClickOnGadget(level_editor_gadget[last_level_drawing_function],
-		      MB_LEFTBUTTON);
-      }
       break;
 
     case GADGET_ID_CUSTOM_COPY_FROM:
@@ -11390,21 +11792,45 @@ static void HandleControlButtons(struct GadgetInfo *gi)
       break;
 
     case GADGET_ID_UNDO:
-      if (undo_buffer_steps == 0)
+      if (button == 1 && undo_buffer_steps == 0)
+      {
+	Request("Undo buffer empty!", REQ_CONFIRM);
+
+	break;
+      }
+      else if (button == 2)
+      {
+	break;
+      }
+      else if (button == 3 && redo_buffer_steps == 0)
       {
-	Request("Undo buffer empty !", REQ_CONFIRM);
+	Request("Redo buffer empty!", REQ_CONFIRM);
+
 	break;
       }
 
       if (edit_mode != ED_MODE_DRAWING)
+	ChangeEditModeWindow(ED_MODE_DRAWING);
+
+      if (button == 1)
       {
-	DrawDrawingWindow();
-	edit_mode = ED_MODE_DRAWING;
+	/* undo */
+
+	undo_buffer_position =
+	  (undo_buffer_position - 1 + NUM_UNDO_STEPS) % NUM_UNDO_STEPS;
+
+	undo_buffer_steps--;
+	redo_buffer_steps++;
       }
+      else
+      {
+	/* redo */
 
-      undo_buffer_position =
-	(undo_buffer_position - 1 + NUM_UNDO_STEPS) % NUM_UNDO_STEPS;
-      undo_buffer_steps--;
+	undo_buffer_position = (undo_buffer_position + 1) % NUM_UNDO_STEPS;
+
+	undo_buffer_steps++;
+	redo_buffer_steps--;
+      }
 
       for (x = 0; x < lev_fieldx; x++)
 	for (y = 0; y < lev_fieldy; y++)
@@ -11413,7 +11839,7 @@ static void HandleControlButtons(struct GadgetInfo *gi)
       /* check if undo operation forces change of border style */
       CheckLevelBorderElement(FALSE);
 
-      DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
+      DrawEditorLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
 
       break;
 
@@ -11421,24 +11847,18 @@ static void HandleControlButtons(struct GadgetInfo *gi)
       if (edit_mode != ED_MODE_INFO)
       {
 	last_edit_mode = edit_mode;
-	edit_mode = ED_MODE_INFO;
 
-	DrawLevelInfoWindow();
+	ChangeEditModeWindow(ED_MODE_INFO);
       }
       else
       {
-	edit_mode = last_edit_mode;
-
-	DrawEditModeWindow();
+	ChangeEditModeWindow(last_edit_mode);
       }
       break;
 
     case GADGET_ID_CLEAR:
       if (edit_mode != ED_MODE_DRAWING)
-      {
-	DrawDrawingWindow();
-	edit_mode = ED_MODE_DRAWING;
-      }
+	ChangeEditModeWindow(ED_MODE_DRAWING);
 
       for (x = 0; x < MAX_LEV_FIELDX; x++) 
 	for (y = 0; y < MAX_LEV_FIELDY; y++) 
@@ -11446,7 +11866,7 @@ static void HandleControlButtons(struct GadgetInfo *gi)
 
       CopyLevelToUndoBuffer(GADGET_ID_CLEAR);
 
-      DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
+      DrawEditorLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
       break;
 
     case GADGET_ID_SAVE:
@@ -11466,7 +11886,7 @@ static void HandleControlButtons(struct GadgetInfo *gi)
       new_level = !fileExists(level_filename);
 
       if (new_level ||
-	  Request("Save this level and kill the old ?", REQ_ASK))
+	  Request("Save this level and kill the old?", REQ_ASK))
       {
 	if (leveldir_former->readonly)
 	  ModifyLevelInfoForSavingIntoPersonalLevelSet(leveldir_former->name);
@@ -11482,10 +11902,10 @@ static void HandleControlButtons(struct GadgetInfo *gi)
 
 	  if (leveldir_former->readonly)
 	    sprintf(level_saved_msg,
-		    "Level saved as level %d into personal level set !",
+		    "Level saved as level %d into personal level set!",
 		    level_nr);
 	  else
-	    strcpy(level_saved_msg, "Level saved !");
+	    strcpy(level_saved_msg, "Level saved!");
 
 	  Request(level_saved_msg, REQ_CONFIRM);
 	}
@@ -11512,11 +11932,10 @@ static void HandleControlButtons(struct GadgetInfo *gi)
 
       CloseDoor(DOOR_CLOSE_ALL);
 
-      BackToFront();		/* force redraw of undrawn special door */
+      /* needed before playing if editor playfield area has different size */
+      ClearRectangle(drawto, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
 
-#if 0
-      DrawCompleteVideoDisplay();
-#endif
+      // redraw_mask = REDRAW_ALL;
 
       level_editor_test_game = TRUE;
 
@@ -11580,6 +11999,10 @@ static void HandleControlButtons(struct GadgetInfo *gi)
 	  break;
 	}
 
+	/* change element of button used to show palette */
+	if (editor.palette.show_on_element_buttons)
+	  button = last_button;
+
 	PickDrawingElement(button, new_element);
 
 	if (!stick_element_properties_window &&
@@ -11594,6 +12017,9 @@ static void HandleControlButtons(struct GadgetInfo *gi)
 	if (drawing_function == GADGET_ID_PICK_ELEMENT)
 	  ClickOnGadget(level_editor_gadget[last_drawing_function],
 			MB_LEFTBUTTON);
+
+	if (!use_permanent_palette)
+	  ChangeEditModeWindow(last_edit_mode);
       }
 #ifdef DEBUG
       else if (gi->event.type == GD_EVENT_PRESSED)
@@ -11630,6 +12056,7 @@ void HandleLevelEditorKeyInput(Key key)
   {
     int id = GADGET_ID_NONE;
     int new_element_shift = element_shift;
+    int step = ED_ELEMENTLIST_BUTTONS_VERT - 1;
     int i;
 
     switch (key)
@@ -11646,13 +12073,23 @@ void HandleLevelEditorKeyInput(Key key)
       case KSYM_Down:
 	id = GADGET_ID_SCROLL_DOWN;
 	break;
+
       case KSYM_Page_Up:
-	id = GADGET_ID_SCROLL_LIST_UP;
-	button = MB_RIGHTBUTTON;
-	break;
       case KSYM_Page_Down:
-	id = GADGET_ID_SCROLL_LIST_DOWN;
-	button = MB_RIGHTBUTTON;
+	step *= (key == KSYM_Page_Up ? -1 : +1);
+        element_shift += step * ED_ELEMENTLIST_BUTTONS_HORIZ;
+
+        if (element_shift < 0)
+          element_shift = 0;
+        if (element_shift > num_editor_elements - ED_NUM_ELEMENTLIST_BUTTONS)
+          element_shift = num_editor_elements - ED_NUM_ELEMENTLIST_BUTTONS;
+
+        ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_VERTICAL],
+                     GDI_SCROLLBAR_ITEM_POSITION,
+                     element_shift / ED_ELEMENTLIST_BUTTONS_HORIZ, GDI_END);
+
+	ModifyEditorElementList();
+
 	break;
 
       case KSYM_Home:
@@ -11714,10 +12151,13 @@ void HandleLevelEditorKeyInput(Key key)
 	{
 	  HandleControlButtons(level_editor_gadget[GADGET_ID_PROPERTIES]);
 	}
+        else if (edit_mode == ED_MODE_PALETTE)
+	{
+	  HandleControlButtons(level_editor_gadget[GADGET_ID_PALETTE]);
+	}
 	else		/* should never happen */
 	{
-	  DrawDrawingWindow();
-	  edit_mode = ED_MODE_DRAWING;
+	  ChangeEditModeWindow(ED_MODE_DRAWING);
 	}
 
         break;
@@ -11728,15 +12168,30 @@ void HandleLevelEditorKeyInput(Key key)
 
     if (id != GADGET_ID_NONE)
       ClickOnGadget(level_editor_gadget[id], button);
+    else if (letter == '1' || letter == '?')
+      ClickOnGadget(level_editor_gadget[GADGET_ID_ELEMENT_LEFT], button);
+    else if (letter == '2')
+      ClickOnGadget(level_editor_gadget[GADGET_ID_ELEMENT_MIDDLE], button);
+    else if (letter == '3')
+      ClickOnGadget(level_editor_gadget[GADGET_ID_ELEMENT_RIGHT], button);
     else if (letter == '.')
       ClickOnGadget(level_editor_gadget[GADGET_ID_SINGLE_ITEMS], button);
+    else if (letter == 'U')
+      ClickOnGadget(level_editor_gadget[GADGET_ID_UNDO], 3);
+    else if (letter == '-' || key == KSYM_KP_Subtract)
+      ClickOnGadget(level_editor_gadget[GADGET_ID_ZOOM], 3);
+    else if (letter == '0' || key == KSYM_KP_0)
+      ClickOnGadget(level_editor_gadget[GADGET_ID_ZOOM], 2);
+    else if (letter == '+' || key == KSYM_KP_Add ||
+	     letter == '=')	// ("Shift-=" is "+" on US keyboards)
+      ClickOnGadget(level_editor_gadget[GADGET_ID_ZOOM], 1);
     else if (key == KSYM_Return ||
 	     key == KSYM_space ||
 	     key == setup.shortcut.toggle_pause)
       ClickOnGadget(level_editor_gadget[GADGET_ID_TEST], button);
     else
       for (i = 0; i < ED_NUM_CTRL_BUTTONS; i++)
-	if (letter && letter == control_info[i].shortcut)
+	if (letter && letter == controlbutton_info[i].shortcut)
 	  if (!anyTextGadgetActive())
 	    ClickOnGadget(level_editor_gadget[i], button);
   }
@@ -11744,9 +12199,11 @@ void HandleLevelEditorKeyInput(Key key)
 
 void HandleLevelEditorIdle()
 {
-  static unsigned long action_delay = 0;
-  unsigned long action_delay_value = GameFrameDelay;
-  int xpos = 1, ypos = 2;
+  int element_border = graphic_info[IMG_EDITOR_ELEMENT_BORDER].border_size;
+  int x = editor.settings.element_graphic.x + element_border;
+  int y = editor.settings.element_graphic.y + element_border;
+  static unsigned int action_delay = 0;
+  unsigned int action_delay_value = GameFrameDelay;
   int i;
 
   if (edit_mode != ED_MODE_PROPERTIES)
@@ -11763,11 +12220,9 @@ void HandleLevelEditorIdle()
       return;
   }
 
-  DrawEditorElementAnimation(SX + xpos * TILEX,
-			     SY + ypos * TILEY + MINI_TILEY / 2);
+  DrawEditorElementAnimation(SX + x, SY + y);
 
-  MarkTileDirty(xpos, ypos);
-  MarkTileDirty(xpos, ypos + 1);
+  redraw_mask |= REDRAW_FIELD;
 
   FrameCounter++;	/* increase animation frame counter */
 }
@@ -11783,7 +12238,7 @@ void PrintEditorGadgetInfoText(struct GadgetInfo *gi)
   char shortcut[MAX_OUTPUT_LINESIZE + 1];
   int max_infotext_len = getMaxInfoTextLength();
 
-  if (gi == NULL || gi->info_text == NULL)
+  if (gi == NULL || strlen(gi->info_text) == 0)
     return;
 
   strncpy(infotext, gi->info_text, max_infotext_len);
@@ -11791,17 +12246,21 @@ void PrintEditorGadgetInfoText(struct GadgetInfo *gi)
 
   if (gi->custom_id < ED_NUM_CTRL_BUTTONS)
   {
-    int key = control_info[gi->custom_id].shortcut;
+    int key = controlbutton_info[gi->custom_id].shortcut;
 
     if (key)
     {
-      if (gi->custom_id == GADGET_ID_SINGLE_ITEMS)	/* special case 1 */
+      if (gi->custom_id == GADGET_ID_SINGLE_ITEMS)
 	sprintf(shortcut, " ('.' or '%c')", key);
-      else if (gi->custom_id == GADGET_ID_PICK_ELEMENT)	/* special case 2 */
+      else if (gi->custom_id == GADGET_ID_PICK_ELEMENT)
 	sprintf(shortcut, " ('%c' or 'Ctrl')", key);
-      else if (gi->custom_id == GADGET_ID_TEST)		/* special case 3 */
+      else if (gi->custom_id == GADGET_ID_TEST)
 	sprintf(shortcut, " ('Enter' or 'Shift-%c')", key);
-      else						/* normal case */
+      else if (gi->custom_id == GADGET_ID_UNDO)
+	sprintf(shortcut, " ('%c/Shift-U')", key);
+      else if (gi->custom_id == GADGET_ID_ZOOM)
+	sprintf(shortcut, " ('%c', '0', '+')", key);
+      else
 	sprintf(shortcut, " ('%s%c')",
 		(key >= 'A' && key <= 'Z' ? "Shift-" : ""), key);
 
@@ -11810,7 +12269,7 @@ void PrintEditorGadgetInfoText(struct GadgetInfo *gi)
     }
   }
 
-  DrawText(INFOTEXT_XPOS, INFOTEXT_YPOS, infotext, FONT_TEXT_2);
+  DrawText(INFOTEXT_XPOS, INFOTEXT_YPOS, infotext, INFOTEXT_FONT);
 }
 
 void HandleEditorGadgetInfoText(void *ptr)
@@ -11983,7 +12442,7 @@ static void HandleDrawingAreaInfo(struct GadgetInfo *gi)
   infotext[max_infotext_len] = '\0';
 
   if (strlen(infotext) > 0)
-    DrawTextS(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, infotext);
+    DrawTextS(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, INFOTEXT_FONT, infotext);
 }
 
 void RequestExitLevelEditor(boolean ask_if_level_has_changed,
@@ -11991,30 +12450,43 @@ void RequestExitLevelEditor(boolean ask_if_level_has_changed,
 {
   if (!ask_if_level_has_changed ||
       !LevelChanged() ||
-      Request("Level has changed ! Exit without saving ?",
+      Request("Level has changed! Exit without saving?",
 	      REQ_ASK | REQ_STAY_OPEN))
   {
-    CloseDoor(DOOR_CLOSE_1);
-    SetDoorState(DOOR_CLOSE_2);
+    struct RectWithBorder *vp_door_1 = &viewport.door_1[GAME_MODE_MAIN];
+    struct RectWithBorder *vp_door_2 = &viewport.door_2[GAME_MODE_MAIN];
+
+    /* draw normal door */
+    UndrawSpecialEditorDoor();
+
+    // close editor doors if viewport definition is the same as in main menu
+    if (vp_door_1->x      == DX     &&
+	vp_door_1->y      == DY     &&
+	vp_door_1->width  == DXSIZE &&
+	vp_door_1->height == DYSIZE &&
+	vp_door_2->x      == VX     &&
+	vp_door_2->y      == VY     &&
+	vp_door_2->width  == VXSIZE &&
+	vp_door_2->height == VYSIZE)
+      CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
+    else
+      SetDoorState(DOOR_CLOSE_2);
+
+    BackToFront();
 
-#if 1
     if (quick_quit)
       FadeSkipNextFadeIn();
-#else
-    if (quick_quit)
-      fading = fading_none;
-#endif
 
-    game_status = GAME_MODE_MAIN;
-#if 1
-    DrawAndFadeInMainMenu(REDRAW_FIELD);
-#else
+    SetGameStatus(GAME_MODE_MAIN);
+
     DrawMainMenu();
-#endif
   }
   else
   {
-    CloseDoor(DOOR_CLOSE_1);
-    OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
+    if (!global.use_envelope_request)
+    {
+      CloseDoor(DOOR_CLOSE_1);
+      OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
+    }
   }
 }
diff --git a/src/editor.h b/src/editor.h
index 717c07a..b39d676 100644
--- a/src/editor.h
+++ b/src/editor.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* editor.h                                                 *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// editor.h
+// ============================================================================
 
 #ifndef EDITOR_H
 #define EDITOR_H
diff --git a/src/engines.h b/src/engines.h
index 8bd49cb..ab6c38f 100644
--- a/src/engines.h
+++ b/src/engines.h
@@ -1,20 +1,19 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* engines.h                                                *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// engines.h
+// ============================================================================
 
 #ifndef ENGINES_H
 #define ENGINES_H
 
 #include "libgame/libgame.h"
+
 #include "game_em/export.h"
 #include "game_sp/export.h"
 
@@ -26,15 +25,15 @@
 /* ========================================================================= */
 
 extern void SetBitmaps_EM(Bitmap **);
-extern void UpdateEngineValues(int, int);
-extern void DrawAllGameValues(int, int, int, int, int);
+extern void UpdateEngineValues(int, int, int, int);
 
-extern int getNumActivePlayers_EM();
+extern boolean getTeamMode_EM();
 extern int getGameFrameDelay_EM(int);
 
 extern void PlayLevelSound_EM(int, int, int, int);
 extern void InitGraphicInfo_EM(void);
-extern void CheckSingleStepMode_EM(byte action[], int, boolean);
+extern void CheckSingleStepMode_EM(byte action[], int,
+				   boolean, boolean, boolean);
 
 void SetGfxAnimation_EM(struct GraphicInfo_EM *, int, int, int, int);
 void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *, int, int, int, int);
@@ -45,11 +44,7 @@ void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *, int, int, int);
 /* functions and definitions exported from main program to game_sp           */
 /* ========================================================================= */
 
-#if 0
-extern void SetBitmaps_SP(Bitmap **);
-#endif
-
-void CheckSingleStepMode_SP(boolean);
+void CheckSingleStepMode_SP(boolean, boolean);
 
 void getGraphicSource_SP(struct GraphicInfo_SP *, int, int, int, int);
 int getGraphicInfo_Delay(int);
diff --git a/src/events.c b/src/events.c
index 8c7aeca..e2d5ab9 100644
--- a/src/events.c
+++ b/src/events.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* events.c                                                 *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// events.c
+// ============================================================================
 
 #include "libgame/libgame.h"
 
@@ -21,25 +19,57 @@
 #include "editor.h"
 #include "files.h"
 #include "tape.h"
+#include "anim.h"
 #include "network.h"
 
 
 #define	DEBUG_EVENTS		0
 
+#define DEBUG_EVENTS_BUTTON	(DEBUG_EVENTS	* 0)
+#define DEBUG_EVENTS_MOTION	(DEBUG_EVENTS	* 0)
+#define DEBUG_EVENTS_WHEEL	(DEBUG_EVENTS	* 1)
+#define DEBUG_EVENTS_WINDOW	(DEBUG_EVENTS	* 0)
+#define DEBUG_EVENTS_FINGER	(DEBUG_EVENTS	* 0)
+#define DEBUG_EVENTS_TEXT	(DEBUG_EVENTS	* 1)
+#define DEBUG_EVENTS_KEY	(DEBUG_EVENTS	* 1)
 
-static boolean cursor_inside_playfield = FALSE;
-static boolean playfield_cursor_set = FALSE;
-static unsigned long playfield_cursor_delay = 0;
 
+static boolean cursor_inside_playfield = FALSE;
+static int cursor_mode_last = CURSOR_DEFAULT;
+static unsigned int special_cursor_delay = 0;
+static unsigned int special_cursor_delay_value = 1000;
 
 /* event filter especially needed for SDL event filtering due to
    delay problems with lots of mouse motion events when mouse button
    not pressed (X11 can handle this with 'PointerMotionHintMask') */
 
-int FilterMouseMotionEvents(const Event *event)
+/* event filter addition for SDL2: as SDL2 does not have a function to enable
+   or disable keyboard auto-repeat, filter repeated keyboard events instead */
+
+static int FilterEvents(const Event *event)
 {
   MotionEvent *motion;
 
+#if defined(TARGET_SDL2)
+  /* skip repeated key press events if keyboard auto-repeat is disabled */
+  if (event->type == EVENT_KEYPRESS &&
+      event->key.repeat &&
+      !keyrepeat_status)
+    return 0;
+#endif
+
+  if (event->type == EVENT_BUTTONPRESS ||
+      event->type == EVENT_BUTTONRELEASE)
+  {
+    ((ButtonEvent *)event)->x -= video.screen_xoffset;
+    ((ButtonEvent *)event)->y -= video.screen_yoffset;
+  }
+  else if (event->type == EVENT_MOTIONNOTIFY)
+  {
+    ((MotionEvent *)event)->x -= video.screen_xoffset;
+    ((MotionEvent *)event)->y -= video.screen_yoffset;
+  }
+
   /* non-motion events are directly passed to event handler functions */
   if (event->type != EVENT_MOTIONNOTIFY)
     return 1;
@@ -48,34 +78,40 @@ int FilterMouseMotionEvents(const Event *event)
   cursor_inside_playfield = (motion->x >= SX && motion->x < SX + SXSIZE &&
 			     motion->y >= SY && motion->y < SY + SYSIZE);
 
-  if (game_status == GAME_MODE_PLAYING && playfield_cursor_set)
+  /* do no reset mouse cursor before all pending events have been processed */
+  if (gfx.cursor_mode == cursor_mode_last &&
+      ((game_status == GAME_MODE_TITLE &&
+	gfx.cursor_mode == CURSOR_NONE) ||
+       (game_status == GAME_MODE_PLAYING &&
+	gfx.cursor_mode == CURSOR_PLAYFIELD)))
   {
     SetMouseCursor(CURSOR_DEFAULT);
-    playfield_cursor_set = FALSE;
-    DelayReached(&playfield_cursor_delay, 0);
+
+    DelayReached(&special_cursor_delay, 0);
+
+    cursor_mode_last = CURSOR_DEFAULT;
   }
 
   /* skip mouse motion events without pressed button outside level editor */
   if (button_status == MB_RELEASED &&
       game_status != GAME_MODE_EDITOR && game_status != GAME_MODE_PLAYING)
     return 0;
-  else
-    return 1;
+
+  return 1;
 }
 
 /* to prevent delay problems, skip mouse motion events if the very next
    event is also a mouse motion event (and therefore effectively only
    handling the last of a row of mouse motion events in the event queue) */
 
-boolean SkipPressedMouseMotionEvent(const Event *event)
+static boolean SkipPressedMouseMotionEvent(const Event *event)
 {
   /* nothing to do if the current event is not a mouse motion event */
   if (event->type != EVENT_MOTIONNOTIFY)
     return FALSE;
 
-  /* only skip motion events with pressed button outside level editor */
-  if (button_status == MB_RELEASED ||
-      game_status == GAME_MODE_EDITOR || game_status == GAME_MODE_PLAYING)
+  /* only skip motion events with pressed button outside the game */
+  if (button_status == MB_RELEASED || game_status == GAME_MODE_PLAYING)
     return FALSE;
 
   if (PendingEvent())
@@ -92,11 +128,15 @@ boolean SkipPressedMouseMotionEvent(const Event *event)
   return FALSE;
 }
 
-/* this is only really needed for non-SDL targets to filter unwanted events;
-   when using SDL with properly installed event filter, this function can be
-   replaced with a simple "NextEvent()" call, but it doesn't hurt either */
+/* this is especially needed for event modifications for the Android target:
+   if mouse coordinates should be modified in the event filter function,
+   using a properly installed SDL event filter does not work, because in
+   the event filter, mouse coordinates in the event structure are still
+   physical pixel positions, not logical (scaled) screen positions, so this
+   has to be handled at a later stage in the event processing functions
+   (when device pixel positions are already converted to screen positions) */
 
-static boolean NextValidEvent(Event *event)
+boolean NextValidEvent(Event *event)
 {
   while (PendingEvent())
   {
@@ -104,7 +144,7 @@ static boolean NextValidEvent(Event *event)
 
     NextEvent(event);
 
-    if (FilterMouseMotionEvents(event))
+    if (FilterEvents(event))
       handle_this_event = TRUE;
 
     if (SkipPressedMouseMotionEvent(event))
@@ -117,78 +157,67 @@ static boolean NextValidEvent(Event *event)
   return FALSE;
 }
 
-void EventLoop(void)
+void HandleEvents()
 {
-  while (1)
+  Event event;
+  unsigned int event_frame_delay = 0;
+  unsigned int event_frame_delay_value = GAME_FRAME_DELAY;
+
+  ResetDelayCounter(&event_frame_delay);
+
+  while (NextValidEvent(&event))
   {
-    if (PendingEvent())		/* got event */
+    switch (event.type)
     {
-      Event event;
+      case EVENT_BUTTONPRESS:
+      case EVENT_BUTTONRELEASE:
+	HandleButtonEvent((ButtonEvent *) &event);
+	break;
 
-      while (NextValidEvent(&event))
-      {
-  	switch (event.type)
-  	{
-  	  case EVENT_BUTTONPRESS:
-  	  case EVENT_BUTTONRELEASE:
-  	    HandleButtonEvent((ButtonEvent *) &event);
-  	    break;
-  
-  	  case EVENT_MOTIONNOTIFY:
-  	    HandleMotionEvent((MotionEvent *) &event);
-  	    break;
-  
-  	  case EVENT_KEYPRESS:
-  	  case EVENT_KEYRELEASE:
-  	    HandleKeyEvent((KeyEvent *) &event);
-  	    break;
-  
-  	  default:
-  	    HandleOtherEvents(&event);
-  	    break;
-  	}
-      }
-    }
-    else
-    {
-      /* when playing, display a special mouse pointer inside the playfield */
-      if (game_status == GAME_MODE_PLAYING && !tape.pausing)
-      {
-	if (!playfield_cursor_set && cursor_inside_playfield &&
-	    DelayReached(&playfield_cursor_delay, 1000))
-	{
-	  SetMouseCursor(CURSOR_PLAYFIELD);
-	  playfield_cursor_set = TRUE;
-	}
-      }
-      else if (playfield_cursor_set)
-      {
-	SetMouseCursor(CURSOR_DEFAULT);
-	playfield_cursor_set = FALSE;
-      }
+      case EVENT_MOTIONNOTIFY:
+	HandleMotionEvent((MotionEvent *) &event);
+	break;
 
-      HandleNoEvent();
-    }
+#if defined(TARGET_SDL2)
+      case EVENT_WHEELMOTION:
+	HandleWheelEvent((WheelEvent *) &event);
+	break;
 
-    /* don't use all CPU time when idle; the main loop while playing
-       has its own synchronization and is CPU friendly, too */
+      case SDL_WINDOWEVENT:
+	HandleWindowEvent((WindowEvent *) &event);
+	break;
 
-    if (game_status == GAME_MODE_PLAYING)
-    {
-      HandleGameActions();
-    }
-    else
-    {
-      SyncDisplay();
-      if (!PendingEvent())	/* delay only if no pending events */
-	Delay(10);
-    }
+      case EVENT_FINGERPRESS:
+      case EVENT_FINGERRELEASE:
+      case EVENT_FINGERMOTION:
+	HandleFingerEvent((FingerEvent *) &event);
+	break;
 
-    /* refresh window contents from drawing buffer, if needed */
-    BackToFront();
+      case EVENT_TEXTINPUT:
+	HandleTextEvent((TextEvent *) &event);
+	break;
 
-    if (game_status == GAME_MODE_QUIT)
-      return;
+      case SDL_APP_WILLENTERBACKGROUND:
+      case SDL_APP_DIDENTERBACKGROUND:
+      case SDL_APP_WILLENTERFOREGROUND:
+      case SDL_APP_DIDENTERFOREGROUND:
+	HandlePauseResumeEvent((PauseResumeEvent *) &event);
+	break;
+#endif
+
+      case EVENT_KEYPRESS:
+      case EVENT_KEYRELEASE:
+	HandleKeyEvent((KeyEvent *) &event);
+	break;
+
+      default:
+	HandleOtherEvents(&event);
+	break;
+    }
+
+    // do not handle events for longer than standard frame delay period
+    if (DelayReached(&event_frame_delay, event_frame_delay_value))
+      break;
   }
 }
 
@@ -234,6 +263,68 @@ void HandleOtherEvents(Event *event)
   }
 }
 
+void HandleMouseCursor()
+{
+  if (game_status == GAME_MODE_TITLE)
+  {
+    /* when showing title screens, hide mouse pointer (if not moved) */
+
+    if (gfx.cursor_mode != CURSOR_NONE &&
+	DelayReached(&special_cursor_delay, special_cursor_delay_value))
+    {
+      SetMouseCursor(CURSOR_NONE);
+    }
+  }
+  else if (game_status == GAME_MODE_PLAYING && (!tape.pausing ||
+						tape.single_step))
+  {
+    /* when playing, display a special mouse pointer inside the playfield */
+
+    if (gfx.cursor_mode != CURSOR_PLAYFIELD &&
+	cursor_inside_playfield &&
+	DelayReached(&special_cursor_delay, special_cursor_delay_value))
+    {
+      SetMouseCursor(CURSOR_PLAYFIELD);
+    }
+  }
+  else if (gfx.cursor_mode != CURSOR_DEFAULT)
+  {
+    SetMouseCursor(CURSOR_DEFAULT);
+  }
+
+  /* this is set after all pending events have been processed */
+  cursor_mode_last = gfx.cursor_mode;
+}
+
+void EventLoop(void)
+{
+  while (1)
+  {
+    if (PendingEvent())
+      HandleEvents();
+    else
+      HandleMouseCursor();
+
+    /* also execute after pending events have been processed before */
+    HandleNoEvent();
+
+    /* don't use all CPU time when idle; the main loop while playing
+       has its own synchronization and is CPU friendly, too */
+
+    if (game_status == GAME_MODE_PLAYING)
+      HandleGameActions();
+
+    /* always copy backbuffer to visible screen for every video frame */
+    BackToFront();
+
+    /* reset video frame delay to default (may change again while playing) */
+    SetVideoFrameDelay(MenuFrameDelay);
+
+    if (game_status == GAME_MODE_QUIT)
+      return;
+  }
+}
+
 void ClearEventQueue()
 {
   while (PendingEvent())
@@ -249,11 +340,57 @@ void ClearEventQueue()
 	break;
 
       case EVENT_KEYRELEASE:
-#if 1
 	ClearPlayerAction();
-#else
+	break;
+
+      default:
+	HandleOtherEvents(&event);
+	break;
+    }
+  }
+}
+
+void ClearPlayerAction()
+{
+  int i;
+
+  /* simulate key release events for still pressed keys */
+  key_joystick_mapping = 0;
+  for (i = 0; i < MAX_PLAYERS; i++)
+    stored_player[i].action = 0;
+}
+
+void SleepWhileUnmapped()
+{
+  boolean window_unmapped = TRUE;
+
+  KeyboardAutoRepeatOn();
+
+  while (window_unmapped)
+  {
+    Event event;
+
+    NextEvent(&event);
+
+    switch (event.type)
+    {
+      case EVENT_BUTTONRELEASE:
+	button_status = MB_RELEASED;
+	break;
+
+      case EVENT_KEYRELEASE:
 	key_joystick_mapping = 0;
-#endif
+	break;
+
+      case EVENT_MAPNOTIFY:
+	window_unmapped = FALSE;
+	break;
+
+      case EVENT_UNMAPNOTIFY:
+	/* this is only to surely prevent the 'should not happen' case
+	 * of recursively looping between 'SleepWhileUnmapped()' and
+	 * 'HandleOtherEvents()' which usually calls this funtion.
+	 */
 	break;
 
       default:
@@ -261,113 +398,747 @@ void ClearEventQueue()
 	break;
     }
   }
-}
 
-void ClearPlayerAction()
-{
-  int i;
+  if (game_status == GAME_MODE_PLAYING)
+    KeyboardAutoRepeatOffUnlessAutoplay();
+}
+
+void HandleExposeEvent(ExposeEvent *event)
+{
+}
+
+void HandleButtonEvent(ButtonEvent *event)
+{
+#if DEBUG_EVENTS_BUTTON
+  Error(ERR_DEBUG, "BUTTON EVENT: button %d %s, x/y %d/%d\n",
+	event->button,
+	event->type == EVENT_BUTTONPRESS ? "pressed" : "released",
+	event->x, event->y);
+#endif
+
+#if defined(HAS_SCREEN_KEYBOARD)
+  if (video.shifted_up)
+    event->y += video.shifted_up_pos;
+#endif
+
+  motion_status = FALSE;
+
+  if (event->type == EVENT_BUTTONPRESS)
+    button_status = event->button;
+  else
+    button_status = MB_RELEASED;
+
+  HandleButton(event->x, event->y, button_status, event->button);
+}
+
+void HandleMotionEvent(MotionEvent *event)
+{
+  if (button_status == MB_RELEASED && game_status != GAME_MODE_EDITOR)
+    return;
+
+  motion_status = TRUE;
+
+#if DEBUG_EVENTS_MOTION
+  Error(ERR_DEBUG, "MOTION EVENT: button %d moved, x/y %d/%d\n",
+	button_status, event->x, event->y);
+#endif
+
+  HandleButton(event->x, event->y, button_status, button_status);
+}
+
+#if defined(TARGET_SDL2)
+
+void HandleWheelEvent(WheelEvent *event)
+{
+  int button_nr;
+
+#if DEBUG_EVENTS_WHEEL
+#if 1
+  Error(ERR_DEBUG, "WHEEL EVENT: mouse == %d, x/y == %d/%d\n",
+	event->which, event->x, event->y);
+#else
+  // (SDL_MOUSEWHEEL_NORMAL/SDL_MOUSEWHEEL_FLIPPED needs SDL 2.0.4 or newer)
+  Error(ERR_DEBUG, "WHEEL EVENT: mouse == %d, x/y == %d/%d, direction == %s\n",
+	event->which, event->x, event->y,
+	(event->direction == SDL_MOUSEWHEEL_NORMAL ? "SDL_MOUSEWHEEL_NORMAL" :
+	 "SDL_MOUSEWHEEL_FLIPPED"));
+#endif
+#endif
+
+  button_nr = (event->x < 0 ? MB_WHEEL_LEFT :
+	       event->x > 0 ? MB_WHEEL_RIGHT :
+	       event->y < 0 ? MB_WHEEL_DOWN :
+	       event->y > 0 ? MB_WHEEL_UP : 0);
+
+#if defined(PLATFORM_WIN32) || defined(PLATFORM_MACOSX)
+  // accelerated mouse wheel available on Mac and Windows
+  wheel_steps = (event->x ? ABS(event->x) : ABS(event->y));
+#else
+  // no accelerated mouse wheel available on Unix/Linux
+  wheel_steps = DEFAULT_WHEEL_STEPS;
+#endif
+
+  motion_status = FALSE;
+
+  button_status = button_nr;
+  HandleButton(0, 0, button_status, -button_nr);
+
+  button_status = MB_RELEASED;
+  HandleButton(0, 0, button_status, -button_nr);
+}
+
+void HandleWindowEvent(WindowEvent *event)
+{
+#if DEBUG_EVENTS_WINDOW
+  int subtype = event->event;
+
+  char *event_name =
+    (subtype == SDL_WINDOWEVENT_SHOWN ? "SDL_WINDOWEVENT_SHOWN" :
+     subtype == SDL_WINDOWEVENT_HIDDEN ? "SDL_WINDOWEVENT_HIDDEN" :
+     subtype == SDL_WINDOWEVENT_EXPOSED ? "SDL_WINDOWEVENT_EXPOSED" :
+     subtype == SDL_WINDOWEVENT_MOVED ? "SDL_WINDOWEVENT_MOVED" :
+     subtype == SDL_WINDOWEVENT_SIZE_CHANGED ? "SDL_WINDOWEVENT_SIZE_CHANGED" :
+     subtype == SDL_WINDOWEVENT_RESIZED ? "SDL_WINDOWEVENT_RESIZED" :
+     subtype == SDL_WINDOWEVENT_MINIMIZED ? "SDL_WINDOWEVENT_MINIMIZED" :
+     subtype == SDL_WINDOWEVENT_MAXIMIZED ? "SDL_WINDOWEVENT_MAXIMIZED" :
+     subtype == SDL_WINDOWEVENT_RESTORED ? "SDL_WINDOWEVENT_RESTORED" :
+     subtype == SDL_WINDOWEVENT_ENTER ? "SDL_WINDOWEVENT_ENTER" :
+     subtype == SDL_WINDOWEVENT_LEAVE ? "SDL_WINDOWEVENT_LEAVE" :
+     subtype == SDL_WINDOWEVENT_FOCUS_GAINED ? "SDL_WINDOWEVENT_FOCUS_GAINED" :
+     subtype == SDL_WINDOWEVENT_FOCUS_LOST ? "SDL_WINDOWEVENT_FOCUS_LOST" :
+     subtype == SDL_WINDOWEVENT_CLOSE ? "SDL_WINDOWEVENT_CLOSE" :
+     "(UNKNOWN)");
+
+  Error(ERR_DEBUG, "WINDOW EVENT: '%s', %ld, %ld",
+	event_name, event->data1, event->data2);
+#endif
+
+#if 0
+  // (not needed, as the screen gets redrawn every 20 ms anyway)
+  if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED ||
+      event->event == SDL_WINDOWEVENT_RESIZED ||
+      event->event == SDL_WINDOWEVENT_EXPOSED)
+    SDLRedrawWindow();
+#endif
+
+  if (event->event == SDL_WINDOWEVENT_RESIZED)
+  {
+    if (!video.fullscreen_enabled)
+    {
+      int new_window_width  = event->data1;
+      int new_window_height = event->data2;
+
+      // if window size has changed after resizing, calculate new scaling factor
+      if (new_window_width  != video.window_width ||
+	  new_window_height != video.window_height)
+      {
+	int new_xpercent = (100 * new_window_width  / video.screen_width);
+	int new_ypercent = (100 * new_window_height / video.screen_height);
+
+	// (extreme window scaling allowed, but cannot be saved permanently)
+	video.window_scaling_percent = MIN(new_xpercent, new_ypercent);
+	setup.window_scaling_percent =
+	  MIN(MAX(MIN_WINDOW_SCALING_PERCENT, video.window_scaling_percent),
+	      MAX_WINDOW_SCALING_PERCENT);
+
+	video.window_width  = new_window_width;
+	video.window_height = new_window_height;
+
+	if (game_status == GAME_MODE_SETUP)
+	  RedrawSetupScreenAfterFullscreenToggle();
+
+	SetWindowTitle();
+      }
+    }
+#if defined(PLATFORM_ANDROID)
+    else
+    {
+      int new_display_width  = event->data1;
+      int new_display_height = event->data2;
+
+      // if fullscreen display size has changed, device has been rotated
+      if (new_display_width  != video.display_width ||
+	  new_display_height != video.display_height)
+      {
+	video.display_width  = new_display_width;
+	video.display_height = new_display_height;
+
+	SDLSetScreenProperties();
+      }
+    }
+#endif
+  }
+}
+
+#define NUM_TOUCH_FINGERS		3
+
+static struct
+{
+  boolean touched;
+  SDL_FingerID finger_id;
+  int counter;
+  Key key;
+} touch_info[NUM_TOUCH_FINGERS];
+
+void HandleFingerEvent(FingerEvent *event)
+{
+  static Key motion_key_x = KSYM_UNDEFINED;
+  static Key motion_key_y = KSYM_UNDEFINED;
+  static Key button_key = KSYM_UNDEFINED;
+  static float motion_x1, motion_y1;
+  static float button_x1, button_y1;
+  static SDL_FingerID motion_id = -1;
+  static SDL_FingerID button_id = -1;
+  int move_trigger_distance_percent = setup.touch.move_distance;
+  int drop_trigger_distance_percent = setup.touch.drop_distance;
+  float move_trigger_distance = (float)move_trigger_distance_percent / 100;
+  float drop_trigger_distance = (float)drop_trigger_distance_percent / 100;
+  float event_x = event->x;
+  float event_y = event->y;
+
+#if DEBUG_EVENTS_FINGER
+  Error(ERR_DEBUG, "FINGER EVENT: finger was %s, touch ID %lld, finger ID %lld, x/y %f/%f, dx/dy %f/%f, pressure %f",
+	event->type == EVENT_FINGERPRESS ? "pressed" :
+	event->type == EVENT_FINGERRELEASE ? "released" : "moved",
+	event->touchId,
+	event->fingerId,
+	event->x, event->y,
+	event->dx, event->dy,
+	event->pressure);
+#endif
+
+  if (game_status != GAME_MODE_PLAYING)
+    return;
+
+  if (strEqual(setup.touch.control_type, TOUCH_CONTROL_FOLLOW_FINGER))
+    return;
+
+  if (strEqual(setup.touch.control_type, TOUCH_CONTROL_VIRTUAL_BUTTONS))
+  {
+    int key_status = (event->type == EVENT_FINGERRELEASE ? KEY_RELEASED :
+		      KEY_PRESSED);
+    float ypos = 1.0 - 1.0 / 3.0 * video.display_width / video.display_height;
+
+    event_y = (event_y - ypos) / (1 - ypos);
+
+    Key key = (event_x > 0         && event_x < 1.0 / 6.0 &&
+	       event_y > 2.0 / 3.0 && event_y < 1 ?
+	       setup.input[0].key.snap :
+	       event_x > 1.0 / 6.0 && event_x < 1.0 / 3.0 &&
+	       event_y > 2.0 / 3.0 && event_y < 1 ?
+	       setup.input[0].key.drop :
+	       event_x > 7.0 / 9.0 && event_x < 8.0 / 9.0 &&
+	       event_y > 0         && event_y < 1.0 / 3.0 ?
+	       setup.input[0].key.up :
+	       event_x > 6.0 / 9.0 && event_x < 7.0 / 9.0 &&
+	       event_y > 1.0 / 3.0 && event_y < 2.0 / 3.0 ?
+	       setup.input[0].key.left :
+	       event_x > 8.0 / 9.0 && event_x < 1 &&
+	       event_y > 1.0 / 3.0 && event_y < 2.0 / 3.0 ?
+	       setup.input[0].key.right :
+	       event_x > 7.0 / 9.0 && event_x < 8.0 / 9.0 &&
+	       event_y > 2.0 / 3.0 && event_y < 1 ?
+	       setup.input[0].key.down :
+	       KSYM_UNDEFINED);
+
+    char *key_status_name = (key_status == KEY_RELEASED ? "KEY_RELEASED" :
+			     "KEY_PRESSED");
+    int i;
+
+    Error(ERR_DEBUG, "::: key '%s' was '%s' [fingerId: %lld]",
+	  getKeyNameFromKey(key), key_status_name, event->fingerId);
+
+    // check if we already know this touch event's finger id
+    for (i = 0; i < NUM_TOUCH_FINGERS; i++)
+    {
+      if (touch_info[i].touched &&
+	  touch_info[i].finger_id == event->fingerId)
+      {
+	// Error(ERR_DEBUG, "MARK 1: %d", i);
+
+	break;
+      }
+    }
+
+    if (i >= NUM_TOUCH_FINGERS)
+    {
+      if (key_status == KEY_PRESSED)
+      {
+	int oldest_pos = 0, oldest_counter = touch_info[0].counter;
+
+	// unknown finger id -- get new, empty slot, if available
+	for (i = 0; i < NUM_TOUCH_FINGERS; i++)
+	{
+	  if (touch_info[i].counter < oldest_counter)
+	  {
+	    oldest_pos = i;
+	    oldest_counter = touch_info[i].counter;
+
+	    // Error(ERR_DEBUG, "MARK 2: %d", i);
+	  }
+
+	  if (!touch_info[i].touched)
+	  {
+	    // Error(ERR_DEBUG, "MARK 3: %d", i);
+
+	    break;
+	  }
+	}
+
+	if (i >= NUM_TOUCH_FINGERS)
+	{
+	  // all slots allocated -- use oldest slot
+	  i = oldest_pos;
+
+	  // Error(ERR_DEBUG, "MARK 4: %d", i);
+	}
+      }
+      else
+      {
+	// release of previously unknown key (should not happen)
+
+	if (key != KSYM_UNDEFINED)
+	{
+	  HandleKey(key, KEY_RELEASED);
+
+	  Error(ERR_DEBUG, "=> key == '%s', key_status == '%s' [slot %d] [1]",
+		getKeyNameFromKey(key), "KEY_RELEASED", i);
+	}
+      }
+    }
+
+    if (i < NUM_TOUCH_FINGERS)
+    {
+      if (key_status == KEY_PRESSED)
+      {
+	if (touch_info[i].key != key)
+	{
+	  if (touch_info[i].key != KSYM_UNDEFINED)
+	  {
+	    HandleKey(touch_info[i].key, KEY_RELEASED);
+
+	    Error(ERR_DEBUG, "=> key == '%s', key_status == '%s' [slot %d] [2]",
+		  getKeyNameFromKey(touch_info[i].key), "KEY_RELEASED", i);
+	  }
+
+	  if (key != KSYM_UNDEFINED)
+	  {
+	    HandleKey(key, KEY_PRESSED);
+
+	    Error(ERR_DEBUG, "=> key == '%s', key_status == '%s' [slot %d] [3]",
+		  getKeyNameFromKey(key), "KEY_PRESSED", i);
+	  }
+	}
+
+	touch_info[i].touched = TRUE;
+	touch_info[i].finger_id = event->fingerId;
+	touch_info[i].counter = Counter();
+	touch_info[i].key = key;
+      }
+      else
+      {
+	if (touch_info[i].key != KSYM_UNDEFINED)
+	{
+	  HandleKey(touch_info[i].key, KEY_RELEASED);
+
+	  Error(ERR_DEBUG, "=> key == '%s', key_status == '%s' [slot %d] [4]",
+		getKeyNameFromKey(touch_info[i].key), "KEY_RELEASED", i);
+	}
+
+	touch_info[i].touched = FALSE;
+	touch_info[i].finger_id = 0;
+	touch_info[i].counter = 0;
+	touch_info[i].key = 0;
+      }
+    }
+
+    return;
+  }
+
+  // use touch direction control
+
+  if (event->type == EVENT_FINGERPRESS)
+  {
+    if (event_x > 1.0 / 3.0)
+    {
+      // motion area
+
+      motion_id = event->fingerId;
+
+      motion_x1 = event_x;
+      motion_y1 = event_y;
+
+      motion_key_x = KSYM_UNDEFINED;
+      motion_key_y = KSYM_UNDEFINED;
+
+      Error(ERR_DEBUG, "---------- MOVE STARTED (WAIT) ----------");
+    }
+    else
+    {
+      // button area
+
+      button_id = event->fingerId;
+
+      button_x1 = event_x;
+      button_y1 = event_y;
+
+      button_key = setup.input[0].key.snap;
+
+      HandleKey(button_key, KEY_PRESSED);
+
+      Error(ERR_DEBUG, "---------- SNAP STARTED ----------");
+    }
+  }
+  else if (event->type == EVENT_FINGERRELEASE)
+  {
+    if (event->fingerId == motion_id)
+    {
+      motion_id = -1;
+
+      if (motion_key_x != KSYM_UNDEFINED)
+	HandleKey(motion_key_x, KEY_RELEASED);
+      if (motion_key_y != KSYM_UNDEFINED)
+	HandleKey(motion_key_y, KEY_RELEASED);
+
+      motion_key_x = KSYM_UNDEFINED;
+      motion_key_y = KSYM_UNDEFINED;
+
+      Error(ERR_DEBUG, "---------- MOVE STOPPED ----------");
+    }
+    else if (event->fingerId == button_id)
+    {
+      button_id = -1;
+
+      if (button_key != KSYM_UNDEFINED)
+	HandleKey(button_key, KEY_RELEASED);
+
+      button_key = KSYM_UNDEFINED;
+
+      Error(ERR_DEBUG, "---------- SNAP STOPPED ----------");
+    }
+  }
+  else if (event->type == EVENT_FINGERMOTION)
+  {
+    if (event->fingerId == motion_id)
+    {
+      float distance_x = ABS(event_x - motion_x1);
+      float distance_y = ABS(event_y - motion_y1);
+      Key new_motion_key_x = (event_x < motion_x1 ? setup.input[0].key.left :
+			      event_x > motion_x1 ? setup.input[0].key.right :
+			      KSYM_UNDEFINED);
+      Key new_motion_key_y = (event_y < motion_y1 ? setup.input[0].key.up :
+			      event_y > motion_y1 ? setup.input[0].key.down :
+			      KSYM_UNDEFINED);
+
+      if (distance_x < move_trigger_distance / 2 ||
+	  distance_x < distance_y)
+	new_motion_key_x = KSYM_UNDEFINED;
+
+      if (distance_y < move_trigger_distance / 2 ||
+	  distance_y < distance_x)
+	new_motion_key_y = KSYM_UNDEFINED;
+
+      if (distance_x > move_trigger_distance ||
+	  distance_y > move_trigger_distance)
+      {
+	if (new_motion_key_x != motion_key_x)
+	{
+	  if (motion_key_x != KSYM_UNDEFINED)
+	    HandleKey(motion_key_x, KEY_RELEASED);
+	  if (new_motion_key_x != KSYM_UNDEFINED)
+	    HandleKey(new_motion_key_x, KEY_PRESSED);
+	}
+
+	if (new_motion_key_y != motion_key_y)
+	{
+	  if (motion_key_y != KSYM_UNDEFINED)
+	    HandleKey(motion_key_y, KEY_RELEASED);
+	  if (new_motion_key_y != KSYM_UNDEFINED)
+	    HandleKey(new_motion_key_y, KEY_PRESSED);
+	}
+
+	motion_x1 = event_x;
+	motion_y1 = event_y;
+
+	motion_key_x = new_motion_key_x;
+	motion_key_y = new_motion_key_y;
+
+	Error(ERR_DEBUG, "---------- MOVE STARTED (MOVE) ----------");
+      }
+    }
+    else if (event->fingerId == button_id)
+    {
+      float distance_x = ABS(event_x - button_x1);
+      float distance_y = ABS(event_y - button_y1);
+
+      if (distance_x < drop_trigger_distance / 2 &&
+	  distance_y > drop_trigger_distance)
+      {
+	if (button_key == setup.input[0].key.snap)
+	  HandleKey(button_key, KEY_RELEASED);
+
+	button_x1 = event_x;
+	button_y1 = event_y;
+
+	button_key = setup.input[0].key.drop;
+
+	HandleKey(button_key, KEY_PRESSED);
+
+	Error(ERR_DEBUG, "---------- DROP STARTED ----------");
+      }
+    }
+  }
+}
+
+static void HandleFollowFinger(int mx, int my, int button)
+{
+  static int old_mx = 0, old_my = 0;
+  static Key motion_key_x = KSYM_UNDEFINED;
+  static Key motion_key_y = KSYM_UNDEFINED;
+  static boolean started_on_player = FALSE;
+  static boolean player_is_dropping = FALSE;
+  static int player_drop_count = 0;
+  static int last_player_x = -1;
+  static int last_player_y = -1;
+
+  if (!strEqual(setup.touch.control_type, TOUCH_CONTROL_FOLLOW_FINGER))
+    return;
+
+  if (button == MB_PRESSED && IN_GFX_FIELD_PLAY(mx, my))
+  {
+    touch_info[0].touched = TRUE;
+    touch_info[0].key = 0;
+
+    old_mx = mx;
+    old_my = my;
+
+    if (!motion_status)
+    {
+      started_on_player = FALSE;
+      player_is_dropping = FALSE;
+      player_drop_count = 0;
+      last_player_x = -1;
+      last_player_y = -1;
+
+      motion_key_x = KSYM_UNDEFINED;
+      motion_key_y = KSYM_UNDEFINED;
+
+      Error(ERR_DEBUG, "---------- TOUCH ACTION STARTED ----------");
+    }
+  }
+  else if (button == MB_RELEASED && touch_info[0].touched)
+  {
+    touch_info[0].touched = FALSE;
+    touch_info[0].key = 0;
+
+    old_mx = 0;
+    old_my = 0;
+
+    if (motion_key_x != KSYM_UNDEFINED)
+      HandleKey(motion_key_x, KEY_RELEASED);
+    if (motion_key_y != KSYM_UNDEFINED)
+      HandleKey(motion_key_y, KEY_RELEASED);
+
+    if (started_on_player)
+    {
+      if (player_is_dropping)
+      {
+	Error(ERR_DEBUG, "---------- DROP STOPPED ----------");
+
+	HandleKey(setup.input[0].key.drop, KEY_RELEASED);
+      }
+      else
+      {
+	Error(ERR_DEBUG, "---------- SNAP STOPPED ----------");
+
+	HandleKey(setup.input[0].key.snap, KEY_RELEASED);
+      }
+    }
+
+    motion_key_x = KSYM_UNDEFINED;
+    motion_key_y = KSYM_UNDEFINED;
+
+    Error(ERR_DEBUG, "---------- TOUCH ACTION STOPPED ----------");
+  }
+
+  if (touch_info[0].touched)
+  {
+    int src_x = local_player->jx;
+    int src_y = local_player->jy;
+    int dst_x = getLevelFromScreenX(old_mx);
+    int dst_y = getLevelFromScreenY(old_my);
+    int dx = dst_x - src_x;
+    int dy = dst_y - src_y;
+    Key new_motion_key_x = (dx < 0 ? setup.input[0].key.left :
+			    dx > 0 ? setup.input[0].key.right :
+			    KSYM_UNDEFINED);
+    Key new_motion_key_y = (dy < 0 ? setup.input[0].key.up :
+			    dy > 0 ? setup.input[0].key.down :
+			    KSYM_UNDEFINED);
+
+    if (dx != 0 && dy != 0 && ABS(dx) != ABS(dy) &&
+	(last_player_x != local_player->jx ||
+	 last_player_y != local_player->jy))
+    {
+      // in case of asymmetric diagonal movement, use "preferred" direction
 
-  /* simulate key release events for still pressed keys */
-  key_joystick_mapping = 0;
-  for (i = 0; i < MAX_PLAYERS; i++)
-    stored_player[i].action = 0;
-}
+      int last_move_dir = (ABS(dx) > ABS(dy) ? MV_VERTICAL : MV_HORIZONTAL);
 
-void SleepWhileUnmapped()
-{
-  boolean window_unmapped = TRUE;
+      if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+	level.native_em_level->ply[0]->last_move_dir = last_move_dir;
+      else
+	local_player->last_move_dir = last_move_dir;
 
-  KeyboardAutoRepeatOn();
+      // (required to prevent accidentally forcing direction for next movement)
+      last_player_x = local_player->jx;
+      last_player_y = local_player->jy;
+    }
 
-  while (window_unmapped)
-  {
-    Event event;
+    if (button == MB_PRESSED && !motion_status && dx == 0 && dy == 0)
+    {
+      started_on_player = TRUE;
+      player_drop_count = getPlayerInventorySize(0);
+      player_is_dropping = (player_drop_count > 0);
 
-    NextEvent(&event);
+      if (player_is_dropping)
+      {
+	Error(ERR_DEBUG, "---------- DROP STARTED ----------");
 
-    switch (event.type)
+	HandleKey(setup.input[0].key.drop, KEY_PRESSED);
+      }
+      else
+      {
+	Error(ERR_DEBUG, "---------- SNAP STARTED ----------");
+
+	HandleKey(setup.input[0].key.snap, KEY_PRESSED);
+      }
+    }
+    else if (dx != 0 || dy != 0)
     {
-      case EVENT_BUTTONRELEASE:
-	button_status = MB_RELEASED;
-	break;
+      if (player_is_dropping &&
+	  player_drop_count == getPlayerInventorySize(0))
+      {
+	Error(ERR_DEBUG, "---------- DROP -> SNAP ----------");
 
-      case EVENT_KEYRELEASE:
-	key_joystick_mapping = 0;
-	break;
+	HandleKey(setup.input[0].key.drop, KEY_RELEASED);
+	HandleKey(setup.input[0].key.snap, KEY_PRESSED);
 
-      case EVENT_MAPNOTIFY:
-	window_unmapped = FALSE;
-	break;
+	player_is_dropping = FALSE;
+      }
+    }
 
-      case EVENT_UNMAPNOTIFY:
-	/* this is only to surely prevent the 'should not happen' case
-	 * of recursively looping between 'SleepWhileUnmapped()' and
-	 * 'HandleOtherEvents()' which usually calls this funtion.
-	 */
-	break;
+    if (new_motion_key_x != motion_key_x)
+    {
+      Error(ERR_DEBUG, "---------- %s %s ----------",
+	    started_on_player && !player_is_dropping ? "SNAPPING" : "MOVING",
+	    dx < 0 ? "LEFT" : dx > 0 ? "RIGHT" : "PAUSED");
+
+      if (motion_key_x != KSYM_UNDEFINED)
+	HandleKey(motion_key_x, KEY_RELEASED);
+      if (new_motion_key_x != KSYM_UNDEFINED)
+	HandleKey(new_motion_key_x, KEY_PRESSED);
+    }
 
-      default:
-	HandleOtherEvents(&event);
-	break;
+    if (new_motion_key_y != motion_key_y)
+    {
+      Error(ERR_DEBUG, "---------- %s %s ----------",
+	    started_on_player && !player_is_dropping ? "SNAPPING" : "MOVING",
+	    dy < 0 ? "UP" : dy > 0 ? "DOWN" : "PAUSED");
+
+      if (motion_key_y != KSYM_UNDEFINED)
+	HandleKey(motion_key_y, KEY_RELEASED);
+      if (new_motion_key_y != KSYM_UNDEFINED)
+	HandleKey(new_motion_key_y, KEY_PRESSED);
     }
-  }
 
-  if (game_status == GAME_MODE_PLAYING)
-    KeyboardAutoRepeatOffUnlessAutoplay();
+    motion_key_x = new_motion_key_x;
+    motion_key_y = new_motion_key_y;
+  }
 }
 
-void HandleExposeEvent(ExposeEvent *event)
+static boolean checkTextInputKeyModState()
 {
-#ifndef TARGET_SDL
-  RedrawPlayfield(FALSE, event->x, event->y, event->width, event->height);
-  FlushDisplay();
-#endif
+  // when playing, only handle raw key events and ignore text input
+  if (game_status == GAME_MODE_PLAYING)
+    return FALSE;
+
+  return ((GetKeyModState() & KMOD_TextInput) != KMOD_None);
 }
 
-void HandleButtonEvent(ButtonEvent *event)
+void HandleTextEvent(TextEvent *event)
 {
-#if DEBUG_EVENTS
-  printf("::: BUTTON EVENT: button %d %s\n", event->button,
-	 event->type == EVENT_BUTTONPRESS ? "pressed" : "released");
+  char *text = event->text;
+  Key key = getKeyFromKeyName(text);
+
+#if DEBUG_EVENTS_TEXT
+  Error(ERR_DEBUG, "TEXT EVENT: text == '%s' [%d byte(s), '%c'/%d], resulting key == %d (%s) [%04x]",
+	text,
+	strlen(text),
+	text[0], (int)(text[0]),
+	key,
+	getKeyNameFromKey(key),
+	GetKeyModState());
 #endif
 
-  motion_status = FALSE;
-
-  if (event->type == EVENT_BUTTONPRESS)
-    button_status = event->button;
-  else
-    button_status = MB_RELEASED;
+#if !defined(HAS_SCREEN_KEYBOARD)
+  // non-mobile devices: only handle key input with modifier keys pressed here
+  // (every other key input is handled directly as physical key input event)
+  if (!checkTextInputKeyModState())
+    return;
+#endif
 
-  HandleButton(event->x, event->y, button_status, event->button);
+  // process text input as "classic" (with uppercase etc.) key input event
+  HandleKey(key, KEY_PRESSED);
+  HandleKey(key, KEY_RELEASED);
 }
 
-void HandleMotionEvent(MotionEvent *event)
+void HandlePauseResumeEvent(PauseResumeEvent *event)
 {
-  if (!PointerInWindow(window))
-    return;	/* window and pointer are on different screens */
-
-  if (button_status == MB_RELEASED && game_status != GAME_MODE_EDITOR)
-    return;
-
-  motion_status = TRUE;
-
-  HandleButton(event->x, event->y, button_status, button_status);
+  if (event->type == SDL_APP_WILLENTERBACKGROUND)
+  {
+    Mix_PauseMusic();
+  }
+  else if (event->type == SDL_APP_DIDENTERFOREGROUND)
+  {
+    Mix_ResumeMusic();
+  }
 }
 
+#endif
+
 void HandleKeyEvent(KeyEvent *event)
 {
-  int key_status = (event->type==EVENT_KEYPRESS ? KEY_PRESSED : KEY_RELEASED);
+  int key_status = (event->type == EVENT_KEYPRESS ? KEY_PRESSED : KEY_RELEASED);
   boolean with_modifiers = (game_status == GAME_MODE_PLAYING ? FALSE : TRUE);
   Key key = GetEventKey(event, with_modifiers);
   Key keymod = (with_modifiers ? GetEventKey(event, FALSE) : key);
 
-#if DEBUG_EVENTS
-  printf("::: KEY EVENT: %d %s\n", GetEventKey(event, TRUE),
-	 event->type == EVENT_KEYPRESS ? "pressed" : "released");
+#if DEBUG_EVENTS_KEY
+  Error(ERR_DEBUG, "KEY EVENT: key was %s, keysym.scancode == %d, keysym.sym == %d, keymod = %d, GetKeyModState() = 0x%04x, resulting key == %d (%s)",
+	event->type == EVENT_KEYPRESS ? "pressed" : "released",
+	event->keysym.scancode,
+	event->keysym.sym,
+	keymod,
+	GetKeyModState(),
+	key,
+	getKeyNameFromKey(key));
+#endif
+
+#if defined(PLATFORM_ANDROID)
+  // always map the "back" button to the "escape" key on Android devices
+  if (key == KSYM_Back)
+    key = KSYM_Escape;
 #endif
 
   HandleKeyModState(keymod, key_status);
+
+#if defined(TARGET_SDL2)
+  // only handle raw key input without text modifier keys pressed
+  if (!checkTextInputKeyModState())
+    HandleKey(key, key_status);
+#else
   HandleKey(key, key_status);
+#endif
 }
 
 void HandleFocusEvent(FocusChangeEvent *event)
@@ -427,12 +1198,14 @@ void HandleWindowManagerEvent(Event *event)
 void HandleButton(int mx, int my, int button, int button_nr)
 {
   static int old_mx = 0, old_my = 0;
+  boolean button_hold = FALSE;
 
-  if (button < 0)
+  if (button_nr < 0)
   {
     mx = old_mx;
     my = old_my;
-    button = -button;
+    button_nr = -button_nr;
+    button_hold = TRUE;
   }
   else
   {
@@ -440,11 +1213,28 @@ void HandleButton(int mx, int my, int button, int button_nr)
     old_my = my;
   }
 
+#if defined(PLATFORM_ANDROID)
+  // when playing, only handle gadgets when using "follow finger" controls
+  boolean handle_gadgets =
+    (game_status != GAME_MODE_PLAYING ||
+     strEqual(setup.touch.control_type, TOUCH_CONTROL_FOLLOW_FINGER));
+
+  if (handle_gadgets &&
+      HandleGadgets(mx, my, button))
+  {
+    /* do not handle this button event anymore */
+    mx = my = -32;	/* force mouse event to be outside screen tiles */
+  }
+#else
   if (HandleGadgets(mx, my, button))
   {
     /* do not handle this button event anymore */
     mx = my = -32;	/* force mouse event to be outside screen tiles */
   }
+#endif
+
+  if (button_hold && game_status == GAME_MODE_PLAYING && tape.pausing)
+    return;
 
   /* do not use scroll wheel button events for anything other than gadgets */
   if (IS_WHEEL_BUTTON(button_nr))
@@ -465,7 +1255,11 @@ void HandleButton(int mx, int my, int button, int button_nr)
       break;
 
     case GAME_MODE_LEVELS:
-      HandleChooseLevel(mx, my, 0, 0, button);
+      HandleChooseLevelSet(mx, my, 0, 0, button);
+      break;
+
+    case GAME_MODE_LEVELNR:
+      HandleChooseLevelNr(mx, my, 0, 0, button);
       break;
 
     case GAME_MODE_SCORES:
@@ -484,11 +1278,17 @@ void HandleButton(int mx, int my, int button, int button_nr)
       HandleSetupScreen(mx, my, 0, 0, button);
       break;
 
+#if defined(TARGET_SDL2)
     case GAME_MODE_PLAYING:
+      HandleFollowFinger(mx, my, button);
+#endif
+
 #ifdef DEBUG
-      if (button == MB_PRESSED && !motion_status && IN_GFX_SCREEN(mx, my))
-	DumpTile(LEVELX((mx - SX) / TILEX), LEVELY((my - SY) / TILEY));
+      if (button == MB_PRESSED && !motion_status && IN_GFX_FIELD_PLAY(mx, my) &&
+	  GetKeyModState() & KMOD_Control)
+	DumpTileFromScreen(mx, my);
 #endif
+
       break;
 
     default:
@@ -530,8 +1330,8 @@ static void HandleKeysSpecial(Key key)
   cheat_input[cheat_input_len++] = letter;
   cheat_input[cheat_input_len] = '\0';
 
-#if DEBUG_EVENTS
-  printf("::: '%s' [%d]\n", cheat_input, cheat_input_len);
+#if DEBUG_EVENTS_KEY
+  Error(ERR_DEBUG, "SPECIAL KEY '%s' [%d]\n", cheat_input, cheat_input_len);
 #endif
 
   if (game_status == GAME_MODE_MAIN)
@@ -577,6 +1377,20 @@ static void HandleKeysSpecial(Key key)
     {
       DumpTape(&tape);
     }
+    else if (is_string_suffix(cheat_input, ":fix-tape") ||
+	     is_string_suffix(cheat_input, ":ft"))
+    {
+      /* fix single-player tapes that contain player input for more than one
+	 player (due to a bug in 3.3.1.2 and earlier versions), which results
+	 in playing levels with more than one player in multi-player mode,
+	 even though the tape was originally recorded in single-player mode */
+
+      /* remove player input actions for all players but the first one */
+      for (i = 1; i < MAX_PLAYERS; i++)
+	tape.player_participates[i] = FALSE;
+
+      tape.changed = TRUE;
+    }
     else if (is_string_suffix(cheat_input, ":save-native-level") ||
 	     is_string_suffix(cheat_input, ":snl"))
     {
@@ -604,9 +1418,64 @@ static void HandleKeysSpecial(Key key)
   }
 }
 
+void HandleKeysDebug(Key key)
+{
+#ifdef DEBUG
+  int i;
+
+  if (game_status == GAME_MODE_PLAYING || !setup.debug.frame_delay_game_only)
+  {
+    boolean mod_key_pressed = (GetKeyModState() != KMOD_None);
+
+    for (i = 0; i < NUM_DEBUG_FRAME_DELAY_KEYS; i++)
+    {
+      if (key == setup.debug.frame_delay_key[i] &&
+	  (mod_key_pressed == setup.debug.frame_delay_use_mod_key))
+      {
+	GameFrameDelay = (GameFrameDelay != setup.debug.frame_delay[i] ?
+			  setup.debug.frame_delay[i] : setup.game_frame_delay);
+
+	if (!setup.debug.frame_delay_game_only)
+	  MenuFrameDelay = GameFrameDelay;
+
+	SetVideoFrameDelay(GameFrameDelay);
+
+	if (GameFrameDelay > ONE_SECOND_DELAY)
+	  Error(ERR_DEBUG, "frame delay == %d ms", GameFrameDelay);
+	else if (GameFrameDelay != 0)
+	  Error(ERR_DEBUG, "frame delay == %d ms (max. %d fps / %d %%)",
+		GameFrameDelay, ONE_SECOND_DELAY / GameFrameDelay,
+		GAME_FRAME_DELAY * 100 / GameFrameDelay);
+	else
+	  Error(ERR_DEBUG, "frame delay == 0 ms (maximum speed)");
+
+	break;
+      }
+    }
+  }
+
+  if (game_status == GAME_MODE_PLAYING)
+  {
+    if (key == KSYM_d)
+    {
+      options.debug = !options.debug;
+
+      Error(ERR_DEBUG, "debug mode %s",
+	    (options.debug ? "enabled" : "disabled"));
+    }
+    else if (key == KSYM_v)
+    {
+      Error(ERR_DEBUG, "currently using game engine version %d",
+	    game.engine_version);
+    }
+  }
+#endif
+}
+
 void HandleKey(Key key, int key_status)
 {
   boolean anyTextGadgetActiveOrJustFinished = anyTextGadgetActive();
+  static boolean ignore_repeated_key = FALSE;
   static struct SetupKeyboardInfo ski;
   static struct SetupShortcutInfo ssi;
   static struct
@@ -630,12 +1499,12 @@ void HandleKey(Key key, int key_status)
   if (game_status == GAME_MODE_PLAYING)
   {
     /* only needed for single-step tape recording mode */
-    static boolean clear_button_2[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
+    static boolean clear_snap_button[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
+    static boolean clear_drop_button[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
+    static boolean element_snapped[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
     static boolean element_dropped[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
     int pnr;
 
-    ssi = setup.shortcut;
-
     for (pnr = 0; pnr < MAX_PLAYERS; pnr++)
     {
       byte key_action = 0;
@@ -649,14 +1518,30 @@ void HandleKey(Key key, int key_status)
 	if (key == *key_info[i].key_custom)
 	  key_action |= key_info[i].action;
 
-      for (i = 0; i < NUM_DIRECTIONS; i++)
-	if (key == *key_info[i].key_snap)
-	  key_action |= key_info[i].action | JOY_BUTTON_SNAP;
+      /* use combined snap+direction keys for the first player only */
+      if (pnr == 0)
+      {
+	ssi = setup.shortcut;
+
+	for (i = 0; i < NUM_DIRECTIONS; i++)
+	  if (key == *key_info[i].key_snap)
+	    key_action |= key_info[i].action | JOY_BUTTON_SNAP;
+      }
 
-      if (tape.single_step && clear_button_2[pnr])
+      /* clear delayed snap and drop actions in single step mode (see below) */
+      if (tape.single_step)
       {
-	stored_player[pnr].action &= ~KEY_BUTTON_2;
-	clear_button_2[pnr] = FALSE;
+	if (clear_snap_button[pnr])
+	{
+	  stored_player[pnr].action &= ~KEY_BUTTON_SNAP;
+	  clear_snap_button[pnr] = FALSE;
+	}
+
+	if (clear_drop_button[pnr])
+	{
+	  stored_player[pnr].action &= ~KEY_BUTTON_DROP;
+	  clear_drop_button[pnr] = FALSE;
+	}
       }
 
       if (key_status == KEY_PRESSED)
@@ -666,43 +1551,75 @@ void HandleKey(Key key, int key_status)
 
       if (tape.single_step && tape.recording && tape.pausing)
       {
-	if (key_status == KEY_PRESSED &&
-	    (key_action & (KEY_MOTION | KEY_BUTTON_1)))
+	if (key_status == KEY_PRESSED && key_action & KEY_MOTION)
 	{
 	  TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
 
-	  if (key_action & KEY_MOTION)
+	  /* if snap key already pressed, don't snap when releasing (below) */
+	  if (stored_player[pnr].action & KEY_BUTTON_SNAP)
+	    element_snapped[pnr] = TRUE;
+
+	  /* if drop key already pressed, don't drop when releasing (below) */
+	  if (stored_player[pnr].action & KEY_BUTTON_DROP)
+	    element_dropped[pnr] = TRUE;
+	}
+	else if (key_status == KEY_PRESSED && key_action & KEY_BUTTON_DROP)
+	{
+	  if (level.game_engine_type == GAME_ENGINE_TYPE_EM ||
+	      level.game_engine_type == GAME_ENGINE_TYPE_SP)
 	  {
-	    if (stored_player[pnr].action & KEY_BUTTON_2)
-	      element_dropped[pnr] = TRUE;
+
+	    if (level.game_engine_type == GAME_ENGINE_TYPE_SP &&
+		getRedDiskReleaseFlag_SP() == 0)
+	      stored_player[pnr].action &= ~KEY_BUTTON_DROP;
+
+	    TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
 	  }
 	}
-	else if (key_status == KEY_RELEASED &&
-		 (key_action & KEY_BUTTON_2))
+	else if (key_status == KEY_RELEASED && key_action & KEY_BUTTON)
 	{
-	  if (!element_dropped[pnr])
+	  if (key_action & KEY_BUTTON_SNAP)
 	  {
-	    TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
+	    /* if snap key was released without moving (see above), snap now */
+	    if (!element_snapped[pnr])
+	    {
+	      TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
+
+	      stored_player[pnr].action |= KEY_BUTTON_SNAP;
+
+	      /* clear delayed snap button on next event */
+	      clear_snap_button[pnr] = TRUE;
+	    }
 
-	    stored_player[pnr].action |= KEY_BUTTON_2;
-	    clear_button_2[pnr] = TRUE;
+	    element_snapped[pnr] = FALSE;
 	  }
 
-	  element_dropped[pnr] = FALSE;
+	  if (key_action & KEY_BUTTON_DROP &&
+	      level.game_engine_type == GAME_ENGINE_TYPE_RND)
+	  {
+	    /* if drop key was released without moving (see above), drop now */
+	    if (!element_dropped[pnr])
+	    {
+	      TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
+
+	      if (level.game_engine_type != GAME_ENGINE_TYPE_SP ||
+		  getRedDiskReleaseFlag_SP() != 0)
+		stored_player[pnr].action |= KEY_BUTTON_DROP;
+
+	      /* clear delayed drop button on next event */
+	      clear_drop_button[pnr] = TRUE;
+	    }
+
+	    element_dropped[pnr] = FALSE;
+	  }
 	}
       }
-#if 1
       else if (tape.recording && tape.pausing)
       {
 	/* prevent key release events from un-pausing a paused game */
-	if (key_status == KEY_PRESSED &&
-	    (key_action & KEY_ACTION))
+	if (key_status == KEY_PRESSED && key_action & KEY_ACTION)
 	  TapeTogglePause(TAPE_TOGGLE_MANUAL);
       }
-#else
-      else if (tape.recording && tape.pausing && (key_action & KEY_ACTION))
-	TapeTogglePause(TAPE_TOGGLE_MANUAL);
-#endif
     }
   }
   else
@@ -726,14 +1643,53 @@ void HandleKey(Key key, int key_status)
     key_joystick_mapping = 0;
 
   if (key_status == KEY_RELEASED)
+  {
+    // reset flag to ignore repeated "key pressed" events after key release
+    ignore_repeated_key = FALSE;
+
     return;
+  }
 
-  if ((key == KSYM_Return || key == KSYM_KP_Enter) &&
-      (GetKeyModState() & KMOD_Alt) && video.fullscreen_available)
+  if ((key == KSYM_F11 ||
+       ((key == KSYM_Return ||
+	 key == KSYM_KP_Enter) && (GetKeyModState() & KMOD_Alt))) &&
+      video.fullscreen_available &&
+      !ignore_repeated_key)
   {
     setup.fullscreen = !setup.fullscreen;
 
-    ToggleFullscreenIfNeeded();
+    ToggleFullscreenOrChangeWindowScalingIfNeeded();
+
+    if (game_status == GAME_MODE_SETUP)
+      RedrawSetupScreenAfterFullscreenToggle();
+
+    // set flag to ignore repeated "key pressed" events
+    ignore_repeated_key = TRUE;
+
+    return;
+  }
+
+  if ((key == KSYM_0     || key == KSYM_KP_0 ||
+       key == KSYM_minus || key == KSYM_KP_Subtract ||
+       key == KSYM_plus  || key == KSYM_KP_Add ||
+       key == KSYM_equal) &&	// ("Shift-=" is "+" on US keyboards)
+      (GetKeyModState() & (KMOD_Control | KMOD_Meta)) &&
+      video.window_scaling_available &&
+      !video.fullscreen_enabled)
+  {
+    if (key == KSYM_0 || key == KSYM_KP_0)
+      setup.window_scaling_percent = STD_WINDOW_SCALING_PERCENT;
+    else if (key == KSYM_minus || key == KSYM_KP_Subtract)
+      setup.window_scaling_percent -= STEP_WINDOW_SCALING_PERCENT;
+    else
+      setup.window_scaling_percent += STEP_WINDOW_SCALING_PERCENT;
+
+    if (setup.window_scaling_percent < MIN_WINDOW_SCALING_PERCENT)
+      setup.window_scaling_percent = MIN_WINDOW_SCALING_PERCENT;
+    else if (setup.window_scaling_percent > MAX_WINDOW_SCALING_PERCENT)
+      setup.window_scaling_percent = MAX_WINDOW_SCALING_PERCENT;
+
+    ToggleFullscreenOrChangeWindowScalingIfNeeded();
 
     if (game_status == GAME_MODE_SETUP)
       RedrawSetupScreenAfterFullscreenToggle();
@@ -741,13 +1697,8 @@ void HandleKey(Key key, int key_status)
     return;
   }
 
-#if 0
-  if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd &&
-      (key == KSYM_Return || key == setup.shortcut.toggle_pause))
-#else
   if (game_status == GAME_MODE_PLAYING && AllPlayersGone &&
       (key == KSYM_Return || key == setup.shortcut.toggle_pause))
-#endif
   {
     GameEnd();
 
@@ -769,7 +1720,7 @@ void HandleKey(Key key, int key_status)
     else if (key == setup.shortcut.load_game)
       TapeQuickLoad();
     else if (key == setup.shortcut.toggle_pause)
-      TapeTogglePause(TAPE_TOGGLE_MANUAL);
+      TapeTogglePause(TAPE_TOGGLE_MANUAL | TAPE_TOGGLE_PLAY_PAUSE);
 
     HandleTapeButtonKeys(key);
     HandleSoundButtonKeys(key);
@@ -816,6 +1767,7 @@ void HandleKey(Key key, int key_status)
     case GAME_MODE_TITLE:
     case GAME_MODE_MAIN:
     case GAME_MODE_LEVELS:
+    case GAME_MODE_LEVELNR:
     case GAME_MODE_SETUP:
     case GAME_MODE_INFO:
     case GAME_MODE_SCORES:
@@ -828,7 +1780,9 @@ void HandleKey(Key key, int key_status)
 	  else if (game_status == GAME_MODE_MAIN)
 	    HandleMainMenu(0, 0, 0, 0, MB_MENU_CHOICE);
           else if (game_status == GAME_MODE_LEVELS)
-            HandleChooseLevel(0, 0, 0, 0, MB_MENU_CHOICE);
+            HandleChooseLevelSet(0, 0, 0, 0, MB_MENU_CHOICE);
+          else if (game_status == GAME_MODE_LEVELNR)
+            HandleChooseLevelNr(0, 0, 0, 0, MB_MENU_CHOICE);
 	  else if (game_status == GAME_MODE_SETUP)
 	    HandleSetupScreen(0, 0, 0, 0, MB_MENU_CHOICE);
 	  else if (game_status == GAME_MODE_INFO)
@@ -844,7 +1798,9 @@ void HandleKey(Key key, int key_status)
 	  if (game_status == GAME_MODE_TITLE)
 	    HandleTitleScreen(0, 0, 0, 0, MB_MENU_LEAVE);
           else if (game_status == GAME_MODE_LEVELS)
-            HandleChooseLevel(0, 0, 0, 0, MB_MENU_LEAVE);
+            HandleChooseLevelSet(0, 0, 0, 0, MB_MENU_LEAVE);
+          else if (game_status == GAME_MODE_LEVELNR)
+            HandleChooseLevelNr(0, 0, 0, 0, MB_MENU_LEAVE);
 	  else if (game_status == GAME_MODE_SETUP)
 	    HandleSetupScreen(0, 0, 0, 0, MB_MENU_LEAVE);
 	  else if (game_status == GAME_MODE_INFO)
@@ -855,7 +1811,9 @@ void HandleKey(Key key, int key_status)
 
         case KSYM_Page_Up:
           if (game_status == GAME_MODE_LEVELS)
-            HandleChooseLevel(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
+            HandleChooseLevelSet(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
+          else if (game_status == GAME_MODE_LEVELNR)
+            HandleChooseLevelNr(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
 	  else if (game_status == GAME_MODE_SETUP)
 	    HandleSetupScreen(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
 	  else if (game_status == GAME_MODE_INFO)
@@ -866,7 +1824,9 @@ void HandleKey(Key key, int key_status)
 
         case KSYM_Page_Down:
           if (game_status == GAME_MODE_LEVELS)
-            HandleChooseLevel(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
+            HandleChooseLevelSet(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
+          else if (game_status == GAME_MODE_LEVELNR)
+            HandleChooseLevelNr(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
 	  else if (game_status == GAME_MODE_SETUP)
 	    HandleSetupScreen(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
 	  else if (game_status == GAME_MODE_INFO)
@@ -875,18 +1835,6 @@ void HandleKey(Key key, int key_status)
 	    HandleHallOfFame(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
 	  break;
 
-#ifdef DEBUG
-	case KSYM_0:
-	  GameFrameDelay = (GameFrameDelay == 500 ? GAME_FRAME_DELAY : 500);
-	  break;
-
-	case KSYM_b:
-	  setup.sp_show_border_elements = !setup.sp_show_border_elements;
-	  printf("Supaplex border elements %s\n",
-		 setup.sp_show_border_elements ? "enabled" : "disabled");
-	  break;
-#endif
-
 	default:
 	  break;
       }
@@ -905,91 +1853,6 @@ void HandleKey(Key key, int key_status)
 	  RequestQuitGame(setup.ask_on_escape);
 	  break;
 
-#ifdef DEBUG
-	case KSYM_0:
-#if 0
-	case KSYM_1:
-	case KSYM_2:
-	case KSYM_3:
-	case KSYM_4:
-	case KSYM_5:
-	case KSYM_6:
-	case KSYM_7:
-	case KSYM_8:
-	case KSYM_9:
-#endif
-	  if (key == KSYM_0)
-	  {
-	    if (GameFrameDelay == 500)
-	      GameFrameDelay = GAME_FRAME_DELAY;
-	    else
-	      GameFrameDelay = 500;
-	  }
-	  else
-	    GameFrameDelay = (key - KSYM_0) * 10;
-	  printf("Game speed == %d%% (%d ms delay between two frames)\n",
-		 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
-	  break;
-
-	case KSYM_d:
-	  if (options.debug)
-	  {
-	    options.debug = FALSE;
-	    printf("debug mode disabled\n");
-	  }
-	  else
-	  {
-	    options.debug = TRUE;
-	    printf("debug mode enabled\n");
-	  }
-	  break;
-
-	case KSYM_S:
-	  if (!global.fps_slowdown)
-	  {
-	    global.fps_slowdown = TRUE;
-	    global.fps_slowdown_factor = 2;
-	    printf("fps slowdown enabled -- display only every 2nd frame\n");
-	  }
-	  else if (global.fps_slowdown_factor == 2)
-	  {
-	    global.fps_slowdown_factor = 4;
-	    printf("fps slowdown enabled -- display only every 4th frame\n");
-	  }
-	  else
-	  {
-	    global.fps_slowdown = FALSE;
-	    global.fps_slowdown_factor = 1;
-	    printf("fps slowdown disabled\n");
-	  }
-	  break;
-
-	case KSYM_f:
-	  ScrollStepSize = TILEX/8;
-	  printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
-	  break;
-
-	case KSYM_g:
-	  ScrollStepSize = TILEX/4;
-	  printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
-	  break;
-
-	case KSYM_h:
-	  ScrollStepSize = TILEX/2;
-	  printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
-	  break;
-
-	case KSYM_l:
-	  ScrollStepSize = TILEX;
-	  printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
-	  break;
-
-	case KSYM_v:
-	  printf("::: currently using game engine version %d\n",
-		 game.engine_version);
-	  break;
-#endif
-
 	default:
 	  break;
       }
@@ -999,21 +1862,27 @@ void HandleKey(Key key, int key_status)
     default:
       if (key == KSYM_Escape)
       {
-	game_status = GAME_MODE_MAIN;
+	SetGameStatus(GAME_MODE_MAIN);
+
 	DrawMainMenu();
 
 	return;
       }
   }
+
+  HandleKeysDebug(key);
 }
 
 void HandleNoEvent()
 {
-  if (button_status && game_status != GAME_MODE_PLAYING)
+  // if (button_status && game_status != GAME_MODE_PLAYING)
+  if (button_status && (game_status != GAME_MODE_PLAYING || tape.pausing))
   {
-    HandleButton(0, 0, -button_status, button_status);
-
-    return;
+    HandleButton(0, 0, button_status, -button_status);
+  }
+  else
+  {
+    HandleJoystick();
   }
 
 #if defined(NETWORK_AVALIABLE)
@@ -1021,7 +1890,25 @@ void HandleNoEvent()
     HandleNetworking();
 #endif
 
-  HandleJoystick();
+  switch (game_status)
+  {
+    case GAME_MODE_MAIN:
+      DrawPreviewLevelAnimation();
+      break;
+
+    case GAME_MODE_EDITOR:
+      HandleLevelEditorIdle();
+      break;
+
+#if defined(TARGET_SDL2)
+    case GAME_MODE_PLAYING:
+      HandleFollowFinger(-1, -1, -1);
+      break;
+#endif
+
+    default:
+      break;
+  }
 }
 
 static int HandleJoystickForAllPlayers()
@@ -1069,10 +1956,11 @@ void HandleJoystick()
     case GAME_MODE_TITLE:
     case GAME_MODE_MAIN:
     case GAME_MODE_LEVELS:
+    case GAME_MODE_LEVELNR:
     case GAME_MODE_SETUP:
     case GAME_MODE_INFO:
     {
-      static unsigned long joystickmove_delay = 0;
+      static unsigned int joystickmove_delay = 0;
 
       if (joystick && !button &&
 	  !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
@@ -1083,7 +1971,9 @@ void HandleJoystick()
       else if (game_status == GAME_MODE_MAIN)
 	HandleMainMenu(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
       else if (game_status == GAME_MODE_LEVELS)
-        HandleChooseLevel(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
+        HandleChooseLevelSet(0,0,dx,dy,newbutton?MB_MENU_CHOICE : MB_MENU_MARK);
+      else if (game_status == GAME_MODE_LEVELNR)
+        HandleChooseLevelNr(0,0,dx,dy,newbutton? MB_MENU_CHOICE : MB_MENU_MARK);
       else if (game_status == GAME_MODE_SETUP)
 	HandleSetupScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
       else if (game_status == GAME_MODE_INFO)
@@ -1095,19 +1985,11 @@ void HandleJoystick()
       HandleHallOfFame(0, 0, dx, dy, !newbutton);
       break;
 
-    case GAME_MODE_EDITOR:
-      HandleLevelEditorIdle();
-      break;
-
     case GAME_MODE_PLAYING:
       if (tape.playing || keyboard)
 	newbutton = ((joy & JOY_BUTTON) != 0);
 
-#if 0
-      if (local_player->LevelSolved_GameEnd && newbutton)
-#else
-      if (AllPlayersGone && newbutton)
-#endif
+      if (newbutton && AllPlayersGone)
       {
 	GameEnd();
 
diff --git a/src/events.h b/src/events.h
index 7cde0e0..e5d2dcc 100644
--- a/src/events.h
+++ b/src/events.h
@@ -1,22 +1,21 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* events.h                                                 *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// events.h
+// ============================================================================
 
 #ifndef EVENTS_H
 #define EVENTS_H
 
 #include "main.h"
 
-int FilterMouseMotionEvents(const Event *);
+boolean NextValidEvent(Event *);
+
 void EventLoop(void);
 void HandleOtherEvents(Event *);
 void ClearEventQueue(void);
@@ -26,12 +25,21 @@ void SleepWhileUnmapped(void);
 void HandleExposeEvent(ExposeEvent *);
 void HandleButtonEvent(ButtonEvent *);
 void HandleMotionEvent(MotionEvent *);
+#if defined(TARGET_SDL2)
+void HandleWheelEvent(WheelEvent *);
+void HandleWindowEvent(WindowEvent *);
+void HandleFingerEvent(FingerEvent *);
+void HandleTextEvent(TextEvent *);
+void HandlePauseResumeEvent(PauseResumeEvent *);
+#endif
+void HandleKeysDebug(Key);
 void HandleKeyEvent(KeyEvent *);
 void HandleFocusEvent(FocusChangeEvent *);
 void HandleClientMessageEvent(ClientMessageEvent *);
 void HandleWindowManagerEvent(Event *);
 
 void HandleNoEvent(void);
+void HandleToonAnimations(void);
 
 void HandleButton(int, int, int, int);
 void HandleKey(Key, int);
diff --git a/src/files.c b/src/files.c
index 349d2d5..eb33f7d 100644
--- a/src/files.c
+++ b/src/files.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* files.c                                                  *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// files.c
+// ============================================================================
 
 #include <ctype.h>
 #include <sys/stat.h>
@@ -23,6 +21,9 @@
 #include "tools.h"
 #include "tape.h"
 
+#define ENABLE_UNUSED_CODE	0	/* currently unused functions */
+#define ENABLE_HISTORIC_CHUNKS	0	/* only for historic reference */
+#define ENABLE_RESERVED_CODE	0	/* reserved for later use */
 
 #define CHUNK_ID_LEN		4	/* IFF style chunk id length  */
 #define CHUNK_SIZE_UNDEFINED	0	/* undefined chunk size == 0  */
@@ -287,6 +288,11 @@ static struct LevelFileConfigInfo chunk_config_ELEM[] =
     TYPE_BOOLEAN,			CONF_VALUE_8_BIT(12),
     &li.shifted_relocation,		FALSE
   },
+  {
+    EL_PLAYER_1,			-1,
+    TYPE_BOOLEAN,			CONF_VALUE_8_BIT(15),
+    &li.lazy_relocation,		FALSE
+  },
 
   /* (these values are different for each player) */
   {
@@ -869,8 +875,8 @@ static struct LevelFileConfigInfo chunk_config_CUSX_base[] =
     &xx_ei.properties[EP_BITFIELD_BASE_NR], EP_BITMASK_BASE_DEFAULT,
     &yy_ei.properties[EP_BITFIELD_BASE_NR]
   },
-#if 0
-  /* (reserved) */
+#if ENABLE_RESERVED_CODE
+  /* (reserved for later use) */
   {
     -1,					-1,
     TYPE_BITFIELD,			CONF_VALUE_32_BIT(2),
@@ -1322,13 +1328,6 @@ filetype_id_list[] =
 
 static boolean check_special_flags(char *flag)
 {
-#if 0
-  printf("::: '%s', '%s', '%s'\n",
-	 flag,
-	 options.special_flags,
-	 leveldir_current->special_flags);
-#endif
-
   if (strEqual(options.special_flags, flag) ||
       strEqual(leveldir_current->special_flags, flag))
     return TRUE;
@@ -1577,11 +1576,6 @@ void setElementChangeInfoToDefaults(struct ElementChangeInfo *change)
 {
   xx_change = *change;		/* copy change data into temporary buffer */
 
-#if 0
-  /* (not needed; set by setConfigToDefaultsFromConfigList()) */
-  xx_num_contents = 1;
-#endif
-
   setConfigToDefaultsFromConfigList(chunk_config_CUSX_change);
 
   *change = xx_change;
@@ -1596,18 +1590,12 @@ void setElementChangeInfoToDefaults(struct ElementChangeInfo *change)
   change->post_change_function = NULL;
 }
 
-static void setLevelInfoToDefaults(struct LevelInfo *level)
+static void setLevelInfoToDefaults_Level(struct LevelInfo *level)
 {
-  static boolean clipboard_elements_initialized = FALSE;
   int i, x, y;
 
-  InitElementPropertiesStatic();
-
   li = *level;		/* copy level data into temporary buffer */
-
   setConfigToDefaultsFromConfigList(chunk_config_INFO);
-  setConfigToDefaultsFromConfigList(chunk_config_ELEM);
-
   *level = li;		/* copy temporary buffer back to level data */
 
   setLevelInfoToDefaults_EM();
@@ -1625,21 +1613,74 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
   level->encoding_16bit_yamyam = TRUE;
   level->encoding_16bit_amoeba = TRUE;
 
-  for (x = 0; x < MAX_LEV_FIELDX; x++)
-    for (y = 0; y < MAX_LEV_FIELDY; y++)
-      level->field[x][y] = EL_SAND;
-
+  /* clear level name and level author string buffers */
   for (i = 0; i < MAX_LEVEL_NAME_LEN; i++)
     level->name[i] = '\0';
   for (i = 0; i < MAX_LEVEL_AUTHOR_LEN; i++)
     level->author[i] = '\0';
 
+  /* set level name and level author to default values */
   strcpy(level->name, NAMELESS_LEVEL_NAME);
   strcpy(level->author, ANONYMOUS_NAME);
 
+  /* set level playfield to playable default level with player and exit */
+  for (x = 0; x < MAX_LEV_FIELDX; x++)
+    for (y = 0; y < MAX_LEV_FIELDY; y++)
+      level->field[x][y] = EL_SAND;
+
   level->field[0][0] = EL_PLAYER_1;
   level->field[STD_LEV_FIELDX - 1][STD_LEV_FIELDY - 1] = EL_EXIT_CLOSED;
 
+  BorderElement = EL_STEELWALL;
+
+  /* set all bug compatibility flags to "false" => do not emulate this bug */
+  level->use_action_after_change_bug = FALSE;
+
+  if (leveldir_current)
+  {
+    /* try to determine better author name than 'anonymous' */
+    if (!strEqual(leveldir_current->author, ANONYMOUS_NAME))
+    {
+      strncpy(level->author, leveldir_current->author, MAX_LEVEL_AUTHOR_LEN);
+      level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
+    }
+    else
+    {
+      switch (LEVELCLASS(leveldir_current))
+      {
+	case LEVELCLASS_TUTORIAL:
+	  strcpy(level->author, PROGRAM_AUTHOR_STRING);
+	  break;
+
+        case LEVELCLASS_CONTRIB:
+	  strncpy(level->author, leveldir_current->name, MAX_LEVEL_AUTHOR_LEN);
+	  level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
+	  break;
+
+        case LEVELCLASS_PRIVATE:
+	  strncpy(level->author, getRealName(), MAX_LEVEL_AUTHOR_LEN);
+	  level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
+	  break;
+
+        default:
+	  /* keep default value */
+	  break;
+      }
+    }
+  }
+}
+
+static void setLevelInfoToDefaults_Elements(struct LevelInfo *level)
+{
+  static boolean clipboard_elements_initialized = FALSE;
+  int i;
+
+  InitElementPropertiesStatic();
+
+  li = *level;		/* copy level data into temporary buffer */
+  setConfigToDefaultsFromConfigList(chunk_config_ELEM);
+  *level = li;		/* copy temporary buffer back to level data */
+
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
   {
     int element = i;
@@ -1721,48 +1762,19 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
   }
 
   clipboard_elements_initialized = TRUE;
+}
 
-  BorderElement = EL_STEELWALL;
+static void setLevelInfoToDefaults(struct LevelInfo *level,
+				   boolean level_info_only)
+{
+  setLevelInfoToDefaults_Level(level);
+
+  if (!level_info_only)
+    setLevelInfoToDefaults_Elements(level);
 
   level->no_valid_file = FALSE;
 
   level->changed = FALSE;
-
-  /* set all bug compatibility flags to "false" => do not emulate this bug */
-  level->use_action_after_change_bug = FALSE;
-
-  if (leveldir_current == NULL)		/* only when dumping level */
-    return;
-
-  /* try to determine better author name than 'anonymous' */
-  if (!strEqual(leveldir_current->author, ANONYMOUS_NAME))
-  {
-    strncpy(level->author, leveldir_current->author, MAX_LEVEL_AUTHOR_LEN);
-    level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
-  }
-  else
-  {
-    switch (LEVELCLASS(leveldir_current))
-    {
-      case LEVELCLASS_TUTORIAL:
-	strcpy(level->author, PROGRAM_AUTHOR_STRING);
-	break;
-
-      case LEVELCLASS_CONTRIB:
-	strncpy(level->author, leveldir_current->name, MAX_LEVEL_AUTHOR_LEN);
-	level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
-	break;
-
-      case LEVELCLASS_PRIVATE:
-	strncpy(level->author, getRealName(), MAX_LEVEL_AUTHOR_LEN);
-	level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
-	break;
-
-      default:
-	/* keep default value */
-	break;
-    }
-  }
 }
 
 static void setFileInfoToDefaults(struct LevelFileInfo *level_file_info)
@@ -1774,10 +1786,41 @@ static void setFileInfoToDefaults(struct LevelFileInfo *level_file_info)
   level_file_info->filename = NULL;
 }
 
+int getMappedElement_SB(int, boolean);
+
 static void ActivateLevelTemplate()
 {
   int x, y;
 
+  if (check_special_flags("load_xsb_to_ces"))
+  {
+    /* fill smaller playfields with padding "beyond border wall" elements */
+    if (level.fieldx < level_template.fieldx ||
+	level.fieldy < level_template.fieldy)
+    {
+      short field[level.fieldx][level.fieldy];
+      int new_fieldx = MAX(level.fieldx, level_template.fieldx);
+      int new_fieldy = MAX(level.fieldy, level_template.fieldy);
+      int pos_fieldx = (new_fieldx - level.fieldx) / 2;
+      int pos_fieldy = (new_fieldy - level.fieldy) / 2;
+
+      /* copy old playfield (which is smaller than the visible area) */
+      for (y = 0; y < level.fieldy; y++) for (x = 0; x < level.fieldx; x++)
+	field[x][y] = level.field[x][y];
+
+      /* fill new, larger playfield with "beyond border wall" elements */
+      for (y = 0; y < new_fieldy; y++) for (x = 0; x < new_fieldx; x++)
+	level.field[x][y] = getMappedElement_SB('_', TRUE);
+
+      /* copy the old playfield to the middle of the new playfield */
+      for (y = 0; y < level.fieldy; y++) for (x = 0; x < level.fieldx; x++)
+	level.field[pos_fieldx + x][pos_fieldy + y] = field[x][y];
+
+      level.fieldx = new_fieldx;
+      level.fieldy = new_fieldy;
+    }
+  }
+
   /* Currently there is no special action needed to activate the template
      data, because 'element_info' property settings overwrite the original
      level data, while all other variables do not change. */
@@ -1837,14 +1880,8 @@ static int getFileTypeFromBasename(char *basename)
   /* ---------- try to determine file type from filename ---------- */
 
   /* check for typical filename of a Supaplex level package file */
-#if 1
   if (strlen(basename) == 10 && strPrefixLower(basename, "levels.d"))
     return LEVEL_FILE_TYPE_SP;
-#else
-  if (strlen(basename) == 10 && (strncmp(basename, "levels.d", 8) == 0 ||
-				 strncmp(basename, "LEVELS.D", 8) == 0))
-    return LEVEL_FILE_TYPE_SP;
-#endif
 
   /* check for typical filename of a Diamond Caves II level package file */
   if (strSuffixLower(basename, ".dc") ||
@@ -1900,21 +1937,21 @@ static char *getPackedLevelBasename(int type)
 {
   static char basename[MAX_FILENAME_LEN];
   char *directory = getCurrentLevelDir();
-  DIR *dir;
-  struct dirent *dir_entry;
+  Directory *dir;
+  DirectoryEntry *dir_entry;
 
   strcpy(basename, UNDEFINED_FILENAME);		/* default: undefined file */
 
-  if ((dir = opendir(directory)) == NULL)
+  if ((dir = openDirectory(directory)) == NULL)
   {
     Error(ERR_WARN, "cannot read current level directory '%s'", directory);
 
     return basename;
   }
 
-  while ((dir_entry = readdir(dir)) != NULL)	/* loop until last dir entry */
+  while ((dir_entry = readDirectory(dir)) != NULL)	/* loop all entries */
   {
-    char *entry_basename = dir_entry->d_name;
+    char *entry_basename = dir_entry->basename;
     int entry_type = getFileTypeFromBasename(entry_basename);
 
     if (entry_type != LEVEL_FILE_TYPE_UNKNOWN)	/* found valid level package */
@@ -1929,7 +1966,7 @@ static char *getPackedLevelBasename(int type)
     }
   }
 
-  closedir(dir);
+  closeDirectory(dir);
 
   return basename;
 }
@@ -1939,7 +1976,7 @@ static char *getSingleLevelFilename(int nr)
   return getLevelFilenameFromBasename(getSingleLevelBasename(nr));
 }
 
-#if 0
+#if ENABLE_UNUSED_CODE
 static char *getPackedLevelFilename(int type)
 {
   return getLevelFilenameFromBasename(getPackedLevelBasename(type));
@@ -1951,7 +1988,7 @@ char *getDefaultLevelFilename(int nr)
   return getSingleLevelFilename(nr);
 }
 
-#if 0
+#if ENABLE_UNUSED_CODE
 static void setLevelFileInfo_SingleLevelFilename(struct LevelFileInfo *lfi,
 						 int type)
 {
@@ -2023,7 +2060,6 @@ static void determineLevelFileInfo_Filename(struct LevelFileInfo *lfi)
   /* special case: level number is negative => check for level template file */
   if (nr < 0)
   {
-#if 1
     /* global variable "leveldir_current" must be modified in the loop below */
     LevelDirTree *leveldir_current_last = leveldir_current;
 
@@ -2043,13 +2079,6 @@ static void determineLevelFileInfo_Filename(struct LevelFileInfo *lfi)
     /* restore global variable "leveldir_current" modified in above loop */
     leveldir_current = leveldir_current_last;
 
-#else
-
-    setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_RND,
-					 "template.%s", LEVELFILE_EXTENSION);
-
-#endif
-
     /* no fallback if template file not existing */
     return;
   }
@@ -2213,7 +2242,7 @@ int getMappedElementByVersion(int element, int game_version)
   return element;
 }
 
-static int LoadLevel_VERS(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_VERS(File *file, int chunk_size, struct LevelInfo *level)
 {
   level->file_version = getFileVersion(file);
   level->game_version = getFileVersion(file);
@@ -2221,7 +2250,7 @@ static int LoadLevel_VERS(FILE *file, int chunk_size, struct LevelInfo *level)
   return chunk_size;
 }
 
-static int LoadLevel_DATE(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_DATE(File *file, int chunk_size, struct LevelInfo *level)
 {
   level->creation_date.year  = getFile16BitBE(file);
   level->creation_date.month = getFile8Bit(file);
@@ -2232,7 +2261,7 @@ static int LoadLevel_DATE(FILE *file, int chunk_size, struct LevelInfo *level)
   return chunk_size;
 }
 
-static int LoadLevel_HEAD(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_HEAD(File *file, int chunk_size, struct LevelInfo *level)
 {
   int initial_player_stepsize;
   int initial_player_gravity;
@@ -2297,7 +2326,7 @@ static int LoadLevel_HEAD(FILE *file, int chunk_size, struct LevelInfo *level)
   return chunk_size;
 }
 
-static int LoadLevel_NAME(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_NAME(File *file, int chunk_size, struct LevelInfo *level)
 {
   int i;
 
@@ -2308,7 +2337,7 @@ static int LoadLevel_NAME(FILE *file, int chunk_size, struct LevelInfo *level)
   return chunk_size;
 }
 
-static int LoadLevel_AUTH(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_AUTH(File *file, int chunk_size, struct LevelInfo *level)
 {
   int i;
 
@@ -2319,7 +2348,7 @@ static int LoadLevel_AUTH(FILE *file, int chunk_size, struct LevelInfo *level)
   return chunk_size;
 }
 
-static int LoadLevel_BODY(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_BODY(File *file, int chunk_size, struct LevelInfo *level)
 {
   int x, y;
   int chunk_size_expected = level->fieldx * level->fieldy;
@@ -2346,7 +2375,7 @@ static int LoadLevel_BODY(FILE *file, int chunk_size, struct LevelInfo *level)
   return chunk_size;
 }
 
-static int LoadLevel_CONT(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_CONT(File *file, int chunk_size, struct LevelInfo *level)
 {
   int i, x, y;
   int header_size = 4;
@@ -2386,17 +2415,18 @@ static int LoadLevel_CONT(FILE *file, int chunk_size, struct LevelInfo *level)
   return chunk_size;
 }
 
-static int LoadLevel_CNT2(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_CNT2(File *file, int chunk_size, struct LevelInfo *level)
 {
   int i, x, y;
   int element;
-  int num_contents, content_xsize, content_ysize;
+  int num_contents;
   int content_array[MAX_ELEMENT_CONTENTS][3][3];
 
   element = getMappedElement(getFile16BitBE(file));
   num_contents = getFile8Bit(file);
-  content_xsize = getFile8Bit(file);
-  content_ysize = getFile8Bit(file);
+
+  getFile8Bit(file);	/* content x size (unused) */
+  getFile8Bit(file);	/* content y size (unused) */
 
   ReadUnusedBytesFromFile(file, LEVEL_CHUNK_CNT2_UNUSED);
 
@@ -2430,7 +2460,7 @@ static int LoadLevel_CNT2(FILE *file, int chunk_size, struct LevelInfo *level)
   return chunk_size;
 }
 
-static int LoadLevel_CNT3(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_CNT3(File *file, int chunk_size, struct LevelInfo *level)
 {
   int i;
   int element;
@@ -2464,7 +2494,7 @@ static int LoadLevel_CNT3(FILE *file, int chunk_size, struct LevelInfo *level)
   return chunk_size;
 }
 
-static int LoadLevel_CUS1(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_CUS1(File *file, int chunk_size, struct LevelInfo *level)
 {
   int num_changed_custom_elements = getFile16BitBE(file);
   int chunk_size_expected = 2 + num_changed_custom_elements * 6;
@@ -2495,7 +2525,7 @@ static int LoadLevel_CUS1(FILE *file, int chunk_size, struct LevelInfo *level)
   return chunk_size;
 }
 
-static int LoadLevel_CUS2(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_CUS2(File *file, int chunk_size, struct LevelInfo *level)
 {
   int num_changed_custom_elements = getFile16BitBE(file);
   int chunk_size_expected = 2 + num_changed_custom_elements * 4;
@@ -2521,7 +2551,7 @@ static int LoadLevel_CUS2(FILE *file, int chunk_size, struct LevelInfo *level)
   return chunk_size;
 }
 
-static int LoadLevel_CUS3(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_CUS3(File *file, int chunk_size, struct LevelInfo *level)
 {
   int num_changed_custom_elements = getFile16BitBE(file);
   int chunk_size_expected = LEVEL_CHUNK_CUS3_SIZE(num_changed_custom_elements);
@@ -2612,7 +2642,7 @@ static int LoadLevel_CUS3(FILE *file, int chunk_size, struct LevelInfo *level)
   return chunk_size;
 }
 
-static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_CUS4(File *file, int chunk_size, struct LevelInfo *level)
 {
   struct ElementInfo *ei;
   int chunk_size_expected;
@@ -2760,7 +2790,7 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level)
   return chunk_size;
 }
 
-static int LoadLevel_GRP1(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_GRP1(File *file, int chunk_size, struct LevelInfo *level)
 {
   struct ElementInfo *ei;
   struct ElementGroupInfo *group;
@@ -2804,7 +2834,7 @@ static int LoadLevel_GRP1(FILE *file, int chunk_size, struct LevelInfo *level)
   return chunk_size;
 }
 
-static int LoadLevel_MicroChunk(FILE *file, struct LevelFileConfigInfo *conf,
+static int LoadLevel_MicroChunk(File *file, struct LevelFileConfigInfo *conf,
 				int element, int real_element)
 {
   int micro_chunk_size = 0;
@@ -2944,13 +2974,13 @@ static int LoadLevel_MicroChunk(FILE *file, struct LevelFileConfigInfo *conf,
   return micro_chunk_size;
 }
 
-static int LoadLevel_INFO(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_INFO(File *file, int chunk_size, struct LevelInfo *level)
 {
   int real_chunk_size = 0;
 
   li = *level;		/* copy level data into temporary buffer */
 
-  while (!feof(file))
+  while (!checkEndOfFile(file))
   {
     real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_INFO, -1, -1);
 
@@ -2963,13 +2993,13 @@ static int LoadLevel_INFO(FILE *file, int chunk_size, struct LevelInfo *level)
   return real_chunk_size;
 }
 
-static int LoadLevel_CONF(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_CONF(File *file, int chunk_size, struct LevelInfo *level)
 {
   int real_chunk_size = 0;
 
   li = *level;		/* copy level data into temporary buffer */
 
-  while (!feof(file))
+  while (!checkEndOfFile(file))
   {
     int element = getMappedElement(getFile16BitBE(file));
 
@@ -2985,13 +3015,13 @@ static int LoadLevel_CONF(FILE *file, int chunk_size, struct LevelInfo *level)
   return real_chunk_size;
 }
 
-static int LoadLevel_ELEM(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_ELEM(File *file, int chunk_size, struct LevelInfo *level)
 {
   int real_chunk_size = 0;
 
   li = *level;		/* copy level data into temporary buffer */
 
-  while (!feof(file))
+  while (!checkEndOfFile(file))
   {
     int element = getMappedElement(getFile16BitBE(file));
 
@@ -3007,13 +3037,15 @@ static int LoadLevel_ELEM(FILE *file, int chunk_size, struct LevelInfo *level)
   return real_chunk_size;
 }
 
-static int LoadLevel_NOTE(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_NOTE(File *file, int chunk_size, struct LevelInfo *level)
 {
   int element = getMappedElement(getFile16BitBE(file));
   int envelope_nr = element - EL_ENVELOPE_1;
   int real_chunk_size = 2;
 
-  while (!feof(file))
+  xx_envelope = level->envelope[envelope_nr];	/* copy into temporary buffer */
+
+  while (!checkEndOfFile(file))
   {
     real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_NOTE,
 					    -1, element);
@@ -3022,12 +3054,12 @@ static int LoadLevel_NOTE(FILE *file, int chunk_size, struct LevelInfo *level)
       break;
   }
 
-  level->envelope[envelope_nr] = xx_envelope;
+  level->envelope[envelope_nr] = xx_envelope;	/* copy from temporary buffer */
 
   return real_chunk_size;
 }
 
-static int LoadLevel_CUSX(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_CUSX(File *file, int chunk_size, struct LevelInfo *level)
 {
   int element = getMappedElement(getFile16BitBE(file));
   int real_chunk_size = 2;
@@ -3038,7 +3070,7 @@ static int LoadLevel_CUSX(FILE *file, int chunk_size, struct LevelInfo *level)
 
   xx_ei.num_change_pages = -1;
 
-  while (!feof(file))
+  while (!checkEndOfFile(file))
   {
     real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_CUSX_base,
 					    -1, element);
@@ -3072,7 +3104,7 @@ static int LoadLevel_CUSX(FILE *file, int chunk_size, struct LevelInfo *level)
   /* start with reading properties for the first change page */
   xx_current_change_page = 0;
 
-  while (!feof(file))
+  while (!checkEndOfFile(file))
   {
     struct ElementChangeInfo *change = &ei->change_page[xx_current_change_page];
 
@@ -3094,7 +3126,7 @@ static int LoadLevel_CUSX(FILE *file, int chunk_size, struct LevelInfo *level)
   return real_chunk_size;
 }
 
-static int LoadLevel_GRPX(FILE *file, int chunk_size, struct LevelInfo *level)
+static int LoadLevel_GRPX(File *file, int chunk_size, struct LevelInfo *level)
 {
   int element = getMappedElement(getFile16BitBE(file));
   int real_chunk_size = 2;
@@ -3104,7 +3136,7 @@ static int LoadLevel_GRPX(FILE *file, int chunk_size, struct LevelInfo *level)
   xx_ei = *ei;		/* copy element data into temporary buffer */
   xx_group = *group;	/* copy group data into temporary buffer */
 
-  while (!feof(file))
+  while (!checkEndOfFile(file))
   {
     real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_GRPX,
 					    -1, element);
@@ -3120,24 +3152,21 @@ static int LoadLevel_GRPX(FILE *file, int chunk_size, struct LevelInfo *level)
 }
 
 static void LoadLevelFromFileInfo_RND(struct LevelInfo *level,
-				      struct LevelFileInfo *level_file_info)
+				      struct LevelFileInfo *level_file_info,
+				      boolean level_info_only)
 {
   char *filename = level_file_info->filename;
   char cookie[MAX_LINE_LEN];
   char chunk_name[CHUNK_ID_LEN + 1];
   int chunk_size;
-  FILE *file;
+  File *file;
 
-  if (!(file = fopen(filename, MODE_READ)))
+  if (!(file = openFile(filename, MODE_READ)))
   {
     level->no_valid_file = TRUE;
 
-#if 1
-    Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
-#else
-    if (level != &level_template)
+    if (!level_info_only)
       Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
-#endif
 
     return;
   }
@@ -3153,14 +3182,17 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level,
       level->no_valid_file = TRUE;
 
       Error(ERR_WARN, "unknown format of level file '%s'", filename);
-      fclose(file);
+
+      closeFile(file);
+
       return;
     }
   }
   else	/* check for pre-2.0 file format with cookie string */
   {
     strcpy(cookie, chunk_name);
-    fgets(&cookie[4], MAX_LINE_LEN - 4, file);
+    if (getStringFromFile(file, &cookie[4], MAX_LINE_LEN - 4) == NULL)
+      cookie[4] = '\0';
     if (strlen(cookie) > 0 && cookie[strlen(cookie) - 1] == '\n')
       cookie[strlen(cookie) - 1] = '\0';
 
@@ -3169,7 +3201,9 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level,
       level->no_valid_file = TRUE;
 
       Error(ERR_WARN, "unknown format of level file '%s'", filename);
-      fclose(file);
+
+      closeFile(file);
+
       return;
     }
 
@@ -3178,7 +3212,9 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level,
       level->no_valid_file = TRUE;
 
       Error(ERR_WARN, "unsupported version of level file '%s'", filename);
-      fclose(file);
+
+      closeFile(file);
+
       return;
     }
 
@@ -3198,7 +3234,7 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level,
     {
       char *name;
       int size;
-      int (*loader)(FILE *, int, struct LevelInfo *);
+      int (*loader)(File *, int, struct LevelInfo *);
     }
     chunk_info[] =
     {
@@ -3265,435 +3301,14 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level,
     }
   }
 
-  fclose(file);
+  closeFile(file);
 }
 
+
 /* ------------------------------------------------------------------------- */
 /* functions for loading EM level                                            */
 /* ------------------------------------------------------------------------- */
 
-#if 0
-
-static int map_em_element_yam(int element)
-{
-  switch (element)
-  {
-    case 0x00:	return EL_EMPTY;
-    case 0x01:	return EL_EMERALD;
-    case 0x02:	return EL_DIAMOND;
-    case 0x03:	return EL_ROCK;
-    case 0x04:	return EL_ROBOT;
-    case 0x05:	return EL_SPACESHIP_UP;
-    case 0x06:	return EL_BOMB;
-    case 0x07:	return EL_BUG_UP;
-    case 0x08:	return EL_AMOEBA_DROP;
-    case 0x09:	return EL_NUT;
-    case 0x0a:	return EL_YAMYAM;
-    case 0x0b:	return EL_QUICKSAND_FULL;
-    case 0x0c:	return EL_SAND;
-    case 0x0d:	return EL_WALL_SLIPPERY;
-    case 0x0e:	return EL_STEELWALL;
-    case 0x0f:	return EL_WALL;
-    case 0x10:	return EL_EM_KEY_1;
-    case 0x11:	return EL_EM_KEY_2;
-    case 0x12:	return EL_EM_KEY_4;
-    case 0x13:	return EL_EM_KEY_3;
-    case 0x14:	return EL_MAGIC_WALL;
-    case 0x15:	return EL_ROBOT_WHEEL;
-    case 0x16:	return EL_DYNAMITE;
-
-    case 0x17:	return EL_EM_KEY_1;			/* EMC */
-    case 0x18:	return EL_BUG_UP;			/* EMC */
-    case 0x1a:	return EL_DIAMOND;			/* EMC */
-    case 0x1b:	return EL_EMERALD;			/* EMC */
-    case 0x25:	return EL_NUT;				/* EMC */
-    case 0x80:	return EL_EMPTY;			/* EMC */
-    case 0x85:	return EL_EM_KEY_1;			/* EMC */
-    case 0x86:	return EL_EM_KEY_2;			/* EMC */
-    case 0x87:	return EL_EM_KEY_4;			/* EMC */
-    case 0x88:	return EL_EM_KEY_3;			/* EMC */
-    case 0x94:	return EL_QUICKSAND_EMPTY;		/* EMC */
-    case 0x9a:	return EL_AMOEBA_WET;			/* EMC */
-    case 0xaf:	return EL_DYNAMITE;			/* EMC */
-    case 0xbd:	return EL_SAND;				/* EMC */
-
-    default:
-      Error(ERR_WARN, "invalid level element %d", element);
-      return EL_UNKNOWN;
-  }
-}
-
-static int map_em_element_field(int element)
-{
-  if (element >= 0xc8 && element <= 0xe1)
-    return EL_CHAR_A + (element - 0xc8);
-  else if (element >= 0xe2 && element <= 0xeb)
-    return EL_CHAR_0 + (element - 0xe2);
-
-  switch (element)
-  {
-    case 0x00:	return EL_ROCK;
-    case 0x01:	return EL_ROCK;				/* EMC */
-    case 0x02:	return EL_DIAMOND;
-    case 0x03:	return EL_DIAMOND;
-    case 0x04:	return EL_ROBOT;
-    case 0x05:	return EL_ROBOT;			/* EMC */
-    case 0x06:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x07:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x08:	return EL_SPACESHIP_UP;
-    case 0x09:	return EL_SPACESHIP_RIGHT;
-    case 0x0a:	return EL_SPACESHIP_DOWN;
-    case 0x0b:	return EL_SPACESHIP_LEFT;
-    case 0x0c:	return EL_SPACESHIP_UP;
-    case 0x0d:	return EL_SPACESHIP_RIGHT;
-    case 0x0e:	return EL_SPACESHIP_DOWN;
-    case 0x0f:	return EL_SPACESHIP_LEFT;
-
-    case 0x10:	return EL_BOMB;
-    case 0x11:	return EL_BOMB;				/* EMC */
-    case 0x12:	return EL_EMERALD;
-    case 0x13:	return EL_EMERALD;
-    case 0x14:	return EL_BUG_UP;
-    case 0x15:	return EL_BUG_RIGHT;
-    case 0x16:	return EL_BUG_DOWN;
-    case 0x17:	return EL_BUG_LEFT;
-    case 0x18:	return EL_BUG_UP;
-    case 0x19:	return EL_BUG_RIGHT;
-    case 0x1a:	return EL_BUG_DOWN;
-    case 0x1b:	return EL_BUG_LEFT;
-    case 0x1c:	return EL_AMOEBA_DROP;
-    case 0x1d:	return EL_AMOEBA_DROP;			/* EMC */
-    case 0x1e:	return EL_AMOEBA_DROP;			/* EMC */
-    case 0x1f:	return EL_AMOEBA_DROP;			/* EMC */
-
-    case 0x20:	return EL_ROCK;
-    case 0x21:	return EL_BOMB;				/* EMC */
-    case 0x22:	return EL_DIAMOND;			/* EMC */
-    case 0x23:	return EL_EMERALD;			/* EMC */
-    case 0x24:	return EL_MAGIC_WALL;
-    case 0x25:	return EL_NUT;
-    case 0x26:	return EL_NUT;				/* EMC */
-    case 0x27:	return EL_NUT;				/* EMC */
-
-      /* looks like magic wheel, but is _always_ activated */
-    case 0x28:	return EL_ROBOT_WHEEL;			/* EMC */
-
-    case 0x29:	return EL_YAMYAM;	/* up */
-    case 0x2a:	return EL_YAMYAM;	/* down */
-    case 0x2b:	return EL_YAMYAM;	/* left */	/* EMC */
-    case 0x2c:	return EL_YAMYAM;	/* right */	/* EMC */
-    case 0x2d:	return EL_QUICKSAND_FULL;
-    case 0x2e:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x2f:	return EL_EMPTY_SPACE;			/* EMC */
-
-    case 0x30:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x31:	return EL_SAND;				/* EMC */
-    case 0x32:	return EL_SAND;				/* EMC */
-    case 0x33:	return EL_SAND;				/* EMC */
-    case 0x34:	return EL_QUICKSAND_FULL;		/* EMC */
-    case 0x35:	return EL_QUICKSAND_FULL;		/* EMC */
-    case 0x36:	return EL_QUICKSAND_FULL;		/* EMC */
-    case 0x37:	return EL_SAND;				/* EMC */
-    case 0x38:	return EL_ROCK;				/* EMC */
-    case 0x39:	return EL_EXPANDABLE_WALL_HORIZONTAL;	/* EMC */
-    case 0x3a:	return EL_EXPANDABLE_WALL_VERTICAL;	/* EMC */
-    case 0x3b:	return EL_DYNAMITE_ACTIVE;	/* 1 */
-    case 0x3c:	return EL_DYNAMITE_ACTIVE;	/* 2 */
-    case 0x3d:	return EL_DYNAMITE_ACTIVE;	/* 3 */
-    case 0x3e:	return EL_DYNAMITE_ACTIVE;	/* 4 */
-    case 0x3f:	return EL_ACID_POOL_BOTTOM;
-
-    case 0x40:	return EL_EXIT_OPEN;	/* 1 */
-    case 0x41:	return EL_EXIT_OPEN;	/* 2 */
-    case 0x42:	return EL_EXIT_OPEN;	/* 3 */
-    case 0x43:	return EL_BALLOON;			/* EMC */
-    case 0x44:	return EL_UNKNOWN;			/* EMC ("plant") */
-    case 0x45:	return EL_SPRING;			/* EMC */
-    case 0x46:	return EL_SPRING;	/* falling */	/* EMC */
-    case 0x47:	return EL_SPRING;	/* left */	/* EMC */
-    case 0x48:	return EL_SPRING;	/* right */	/* EMC */
-    case 0x49:	return EL_UNKNOWN;			/* EMC ("ball 1") */
-    case 0x4a:	return EL_UNKNOWN;			/* EMC ("ball 2") */
-    case 0x4b:	return EL_UNKNOWN;			/* EMC ("android") */
-    case 0x4c:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x4d:	return EL_UNKNOWN;			/* EMC ("android") */
-    case 0x4e:	return EL_INVISIBLE_WALL;		/* EMC (? "android") */
-    case 0x4f:	return EL_UNKNOWN;			/* EMC ("android") */
-
-    case 0x50:	return EL_UNKNOWN;			/* EMC ("android") */
-    case 0x51:	return EL_UNKNOWN;			/* EMC ("android") */
-    case 0x52:	return EL_UNKNOWN;			/* EMC ("android") */
-    case 0x53:	return EL_UNKNOWN;			/* EMC ("android") */
-    case 0x54:	return EL_UNKNOWN;			/* EMC ("android") */
-    case 0x55:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x56:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x57:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x58:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x59:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x5a:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x5b:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x5c:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x5d:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x5e:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x5f:	return EL_EMPTY_SPACE;			/* EMC */
-
-    case 0x60:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x61:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x62:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x63:	return EL_SPRING;	/* left */	/* EMC */
-    case 0x64:	return EL_SPRING;	/* right */	/* EMC */
-    case 0x65:	return EL_ACID;		/* 1 */		/* EMC */
-    case 0x66:	return EL_ACID;		/* 2 */		/* EMC */
-    case 0x67:	return EL_ACID;		/* 3 */		/* EMC */
-    case 0x68:	return EL_ACID;		/* 4 */		/* EMC */
-    case 0x69:	return EL_ACID;		/* 5 */		/* EMC */
-    case 0x6a:	return EL_ACID;		/* 6 */		/* EMC */
-    case 0x6b:	return EL_ACID;		/* 7 */		/* EMC */
-    case 0x6c:	return EL_ACID;		/* 8 */		/* EMC */
-    case 0x6d:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x6e:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x6f:	return EL_EMPTY_SPACE;			/* EMC */
-
-    case 0x70:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x71:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x72:	return EL_NUT;		/* left */	/* EMC */
-    case 0x73:	return EL_SAND;				/* EMC (? "nut") */
-    case 0x74:	return EL_STEELWALL;
-    case 0x75:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x76:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x77:	return EL_BOMB;		/* left */	/* EMC */
-    case 0x78:	return EL_BOMB;		/* right */	/* EMC */
-    case 0x79:	return EL_ROCK;		/* left */	/* EMC */
-    case 0x7a:	return EL_ROCK;		/* right */	/* EMC */
-    case 0x7b:	return EL_ACID;				/* (? EMC "blank") */
-    case 0x7c:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x7d:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x7e:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0x7f:	return EL_EMPTY_SPACE;			/* EMC */
-
-    case 0x80:	return EL_EMPTY;
-    case 0x81:	return EL_WALL_SLIPPERY;
-    case 0x82:	return EL_SAND;
-    case 0x83:	return EL_STEELWALL;
-    case 0x84:	return EL_WALL;
-    case 0x85:	return EL_EM_KEY_1;
-    case 0x86:	return EL_EM_KEY_2;
-    case 0x87:	return EL_EM_KEY_4;
-    case 0x88:	return EL_EM_KEY_3;
-    case 0x89:	return EL_EM_GATE_1;
-    case 0x8a:	return EL_EM_GATE_2;
-    case 0x8b:	return EL_EM_GATE_4;
-    case 0x8c:	return EL_EM_GATE_3;
-    case 0x8d:	return EL_INVISIBLE_WALL;		/* EMC (? "dripper") */
-    case 0x8e:	return EL_EM_GATE_1_GRAY;
-    case 0x8f:	return EL_EM_GATE_2_GRAY;
-
-    case 0x90:	return EL_EM_GATE_4_GRAY;
-    case 0x91:	return EL_EM_GATE_3_GRAY;
-    case 0x92:	return EL_MAGIC_WALL;
-    case 0x93:	return EL_ROBOT_WHEEL;
-    case 0x94:	return EL_QUICKSAND_EMPTY;		/* (? EMC "sand") */
-    case 0x95:	return EL_ACID_POOL_TOPLEFT;
-    case 0x96:	return EL_ACID_POOL_TOPRIGHT;
-    case 0x97:	return EL_ACID_POOL_BOTTOMLEFT;
-    case 0x98:	return EL_ACID_POOL_BOTTOMRIGHT;
-    case 0x99:	return EL_ACID;			/* (? EMC "fake blank") */
-    case 0x9a:	return EL_AMOEBA_DEAD;		/* 1 */
-    case 0x9b:	return EL_AMOEBA_DEAD;		/* 2 */
-    case 0x9c:	return EL_AMOEBA_DEAD;		/* 3 */
-    case 0x9d:	return EL_AMOEBA_DEAD;		/* 4 */
-    case 0x9e:	return EL_EXIT_CLOSED;
-    case 0x9f:	return EL_CHAR_LESS;		/* arrow left */
-
-      /* looks like normal sand, but behaves like wall */
-    case 0xa0:	return EL_UNKNOWN;		/* EMC ("fake grass") */
-    case 0xa1:	return EL_UNKNOWN;		/* EMC ("lenses") */
-    case 0xa2:	return EL_UNKNOWN;		/* EMC ("magnify") */
-    case 0xa3:	return EL_UNKNOWN;		/* EMC ("fake blank") */
-    case 0xa4:	return EL_UNKNOWN;		/* EMC ("fake grass") */
-    case 0xa5:	return EL_UNKNOWN;		/* EMC ("switch") */
-    case 0xa6:	return EL_UNKNOWN;		/* EMC ("switch") */
-    case 0xa7:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0xa8:	return EL_EMC_WALL_1;			/* EMC ("decor 8") */
-    case 0xa9:	return EL_EMC_WALL_2;			/* EMC ("decor 9") */
-    case 0xaa:	return EL_EMC_WALL_3;			/* EMC ("decor 10") */
-    case 0xab:	return EL_EMC_WALL_7;			/* EMC ("decor 5") */
-    case 0xac:	return EL_CHAR_COMMA;			/* EMC */
-    case 0xad:	return EL_CHAR_QUOTEDBL;		/* EMC */
-    case 0xae:	return EL_CHAR_MINUS;			/* EMC */
-    case 0xaf:	return EL_DYNAMITE;
-
-    case 0xb0:	return EL_EMC_STEELWALL_1;		/* EMC ("steel 3") */
-    case 0xb1:	return EL_EMC_WALL_8;			/* EMC ("decor 6") */
-    case 0xb2:	return EL_UNKNOWN;			/* EMC ("decor 7") */
-    case 0xb3:	return EL_STEELWALL;		/* 2 */	/* EMC */
-    case 0xb4:	return EL_WALL_SLIPPERY;	/* 2 */	/* EMC */
-    case 0xb5:	return EL_EMC_WALL_6;			/* EMC ("decor 2") */
-    case 0xb6:	return EL_EMC_WALL_5;			/* EMC ("decor 4") */
-    case 0xb7:	return EL_EMC_WALL_4;			/* EMC ("decor 3") */
-    case 0xb8:	return EL_BALLOON_SWITCH_ANY;		/* EMC */
-    case 0xb9:	return EL_BALLOON_SWITCH_RIGHT;		/* EMC */
-    case 0xba:	return EL_BALLOON_SWITCH_DOWN;		/* EMC */
-    case 0xbb:	return EL_BALLOON_SWITCH_LEFT;		/* EMC */
-    case 0xbc:	return EL_BALLOON_SWITCH_UP;		/* EMC */
-    case 0xbd:	return EL_SAND;				/* EMC ("dirt") */
-    case 0xbe:	return EL_UNKNOWN;			/* EMC ("plant") */
-    case 0xbf:	return EL_UNKNOWN;			/* EMC ("key 5") */
-
-    case 0xc0:	return EL_UNKNOWN;			/* EMC ("key 6") */
-    case 0xc1:	return EL_UNKNOWN;			/* EMC ("key 7") */
-    case 0xc2:	return EL_UNKNOWN;			/* EMC ("key 8") */
-    case 0xc3:	return EL_UNKNOWN;			/* EMC ("door 5") */
-    case 0xc4:	return EL_UNKNOWN;			/* EMC ("door 6") */
-    case 0xc5:	return EL_UNKNOWN;			/* EMC ("door 7") */
-    case 0xc6:	return EL_UNKNOWN;			/* EMC ("door 8") */
-    case 0xc7:	return EL_UNKNOWN;			/* EMC ("bumper") */
-
-      /* characters: see above */
-
-    case 0xec:	return EL_CHAR_PERIOD;
-    case 0xed:	return EL_CHAR_EXCLAM;
-    case 0xee:	return EL_CHAR_COLON;
-    case 0xef:	return EL_CHAR_QUESTION;
-
-    case 0xf0:	return EL_CHAR_GREATER;			/* arrow right */
-    case 0xf1:	return EL_CHAR_COPYRIGHT;		/* EMC: "decor 1" */
-    case 0xf2:	return EL_UNKNOWN;		/* EMC ("fake door 5") */
-    case 0xf3:	return EL_UNKNOWN;		/* EMC ("fake door 6") */
-    case 0xf4:	return EL_UNKNOWN;		/* EMC ("fake door 7") */
-    case 0xf5:	return EL_UNKNOWN;		/* EMC ("fake door 8") */
-    case 0xf6:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0xf7:	return EL_EMPTY_SPACE;			/* EMC */
-
-    case 0xf8:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0xf9:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0xfa:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0xfb:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0xfc:	return EL_EMPTY_SPACE;			/* EMC */
-    case 0xfd:	return EL_EMPTY_SPACE;			/* EMC */
-
-    case 0xfe:	return EL_PLAYER_1;			/* EMC: "blank" */
-    case 0xff:	return EL_PLAYER_2;			/* EMC: "blank" */
-
-    default:
-      /* should never happen (all 8-bit value cases should be handled) */
-      Error(ERR_WARN, "invalid level element %d", element);
-      return EL_UNKNOWN;
-  }
-}
-
-#define EM_LEVEL_SIZE			2106
-#define EM_LEVEL_XSIZE			64
-#define EM_LEVEL_YSIZE			32
-
-static void OLD_LoadLevelFromFileInfo_EM(struct LevelInfo *level,
-					 struct LevelFileInfo *level_file_info)
-{
-  char *filename = level_file_info->filename;
-  FILE *file;
-  unsigned char leveldata[EM_LEVEL_SIZE];
-  unsigned char *header = &leveldata[EM_LEVEL_XSIZE * EM_LEVEL_YSIZE];
-  int nr = level_file_info->nr;
-  int i, x, y;
-
-  if (!(file = fopen(filename, MODE_READ)))
-  {
-    level->no_valid_file = TRUE;
-
-    Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
-
-    return;
-  }
-
-  for (i = 0; i < EM_LEVEL_SIZE; i++)
-    leveldata[i] = fgetc(file);
-
-  fclose(file);
-
-  /* check if level data is crypted by testing against known starting bytes
-     of the few existing crypted level files (from Emerald Mine 1 + 2) */
-
-  if ((leveldata[0] == 0xf1 ||
-       leveldata[0] == 0xf5) && leveldata[2] == 0xe7 && leveldata[3] == 0xee)
-  {
-    unsigned char code0 = 0x65;
-    unsigned char code1 = 0x11;
-
-    if (leveldata[0] == 0xf5)	/* error in crypted Emerald Mine 2 levels */
-      leveldata[0] = 0xf1;
-
-    /* decode crypted level data */
-
-    for (i = 0; i < EM_LEVEL_SIZE; i++)
-    {
-      leveldata[i] ^= code0;
-      leveldata[i] -= code1;
-
-      code0 = (code0 + 7) & 0xff;
-    }
-  }
-
-  level->fieldx	= EM_LEVEL_XSIZE;
-  level->fieldy	= EM_LEVEL_YSIZE;
-
-  level->time		= header[46] * 10;
-  level->gems_needed	= header[47];
-
-  /* The original Emerald Mine levels have their level number stored
-     at the second byte of the level file...
-     Do not trust this information at other level files, e.g. EMC,
-     but correct it anyway (normally the first row is completely
-     steel wall, so the correction does not hurt anyway). */
-
-  if (leveldata[1] == nr)
-    leveldata[1] = leveldata[2];	/* correct level number field */
-
-  sprintf(level->name, "Level %d", nr);		/* set level name */
-
-  level->score[SC_EMERALD]	= header[36];
-  level->score[SC_DIAMOND]	= header[37];
-  level->score[SC_ROBOT]	= header[38];
-  level->score[SC_SPACESHIP]	= header[39];
-  level->score[SC_BUG]		= header[40];
-  level->score[SC_YAMYAM]	= header[41];
-  level->score[SC_NUT]		= header[42];
-  level->score[SC_DYNAMITE]	= header[43];
-  level->score[SC_TIME_BONUS]	= header[44];
-
-  level->num_yamyam_contents = 4;
-
-  for (i = 0; i < level->num_yamyam_contents; i++)
-    for (y = 0; y < 3; y++)
-      for (x = 0; x < 3; x++)
-	level->yamyam_content[i].e[x][y] =
-	  map_em_element_yam(header[i * 9 + y * 3 + x]);
-
-  level->amoeba_speed		= (header[52] * 256 + header[53]) % 256;
-  level->time_magic_wall	= (header[54] * 256 + header[55]) * 16 / 100;
-  level->time_wheel		= (header[56] * 256 + header[57]) * 16 / 100;
-  level->amoeba_content		= EL_DIAMOND;
-
-  for (y = 0; y < level->fieldy; y++) for (x = 0; x < level->fieldx; x++)
-  {
-    int new_element = map_em_element_field(leveldata[y * EM_LEVEL_XSIZE + x]);
-
-    if (new_element == EL_AMOEBA_DEAD && level->amoeba_speed)
-      new_element = EL_AMOEBA_WET;
-
-    level->field[x][y] = new_element;
-  }
-
-  x = (header[48] * 256 + header[49]) % EM_LEVEL_XSIZE;
-  y = (header[48] * 256 + header[49]) / EM_LEVEL_XSIZE;
-  level->field[x][y] = EL_PLAYER_1;
-
-  x = (header[50] * 256 + header[51]) % EM_LEVEL_XSIZE;
-  y = (header[50] * 256 + header[51]) / EM_LEVEL_XSIZE;
-  level->field[x][y] = EL_PLAYER_2;
-}
-
-#endif
-
 void CopyNativeLevel_RND_to_EM(struct LevelInfo *level)
 {
   static int ball_xy[8][2] =
@@ -3923,393 +3538,44 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level)
 /* functions for loading SP level                                            */
 /* ------------------------------------------------------------------------- */
 
-#if 0
-
-#define NUM_SUPAPLEX_LEVELS_PER_PACKAGE	111
-#define SP_LEVEL_SIZE			1536
-#define SP_LEVEL_XSIZE			60
-#define SP_LEVEL_YSIZE			24
-#define SP_LEVEL_NAME_LEN		23
-
-static void LoadLevelFromFileStream_SP(FILE *file, struct LevelInfo *level,
-				       int nr)
+void CopyNativeLevel_RND_to_SP(struct LevelInfo *level)
 {
-  int initial_player_gravity;
-  int num_special_ports;
+  struct LevelInfo_SP *level_sp = level->native_sp_level;
+  LevelInfoType *header = &level_sp->header;
   int i, x, y;
 
-  /* for details of the Supaplex level format, see Herman Perk's Supaplex
-     documentation file "SPFIX63.DOC" from his Supaplex "SpeedFix" package */
-
-  /* read level body (width * height == 60 * 24 tiles == 1440 bytes) */
-  for (y = 0; y < SP_LEVEL_YSIZE; y++)
-  {
-    for (x = 0; x < SP_LEVEL_XSIZE; x++)
-    {
-      int element_old = fgetc(file);
-      int element_new;
-
-      if (element_old <= 0x27)
-	element_new = getMappedElement(EL_SP_START + element_old);
-      else if (element_old == 0x28)
-	element_new = EL_INVISIBLE_WALL;
-      else
-      {
-	Error(ERR_WARN, "in level %d, at position %d, %d:", nr, x, y);
-	Error(ERR_WARN, "invalid level element %d", element_old);
-
-	element_new = EL_UNKNOWN;
-      }
-
-      level->field[x][y] = element_new;
-    }
-  }
-
-  ReadUnusedBytesFromFile(file, 4);	/* (not used by Supaplex engine) */
-
-  /* initial gravity: 1 == "on", anything else (0) == "off" */
-  initial_player_gravity = (fgetc(file) == 1 ? TRUE : FALSE);
+  level_sp->width  = level->fieldx;
+  level_sp->height = level->fieldy;
 
-  for (i = 0; i < MAX_PLAYERS; i++)
-    level->initial_player_gravity[i] = initial_player_gravity;
+  for (x = 0; x < level->fieldx; x++)
+    for (y = 0; y < level->fieldy; y++)
+      level_sp->playfield[x][y] = map_element_RND_to_SP(level->field[x][y]);
 
-  ReadUnusedBytesFromFile(file, 1);	/* (not used by Supaplex engine) */
+  header->InitialGravity = (level->initial_player_gravity[0] ? 1 : 0);
 
-  /* level title in uppercase letters, padded with dashes ("-") (23 bytes) */
   for (i = 0; i < SP_LEVEL_NAME_LEN; i++)
-    level->name[i] = fgetc(file);
-  level->name[SP_LEVEL_NAME_LEN] = '\0';
-
-  /* initial "freeze zonks": 2 == "on", anything else (0, 1) == "off" */
-  ReadUnusedBytesFromFile(file, 1);	/* (not used by R'n'D engine) */
+    header->LevelTitle[i] = level->name[i];
+  /* !!! NO STRING TERMINATION IN SUPAPLEX VB CODE YET -- FIX THIS !!! */
 
-  /* number of infotrons needed; 0 means that Supaplex will count the total
-     amount of infotrons in the level and use the low byte of that number
-     (a multiple of 256 infotrons will result in "0 infotrons needed"!) */
-  level->gems_needed = fgetc(file);
+  header->InfotronsNeeded = level->gems_needed;
 
-  /* number of special ("gravity") port entries below (maximum 10 allowed) */
-  num_special_ports = fgetc(file);
+  header->SpecialPortCount = 0;
 
-  /* database of properties of up to 10 special ports (6 bytes per port) */
-  for (i = 0; i < 10; i++)
+  for (x = 0; x < level->fieldx; x++) for (y = 0; y < level->fieldy; y++)
   {
-    int port_location, port_x, port_y, port_element;
-    int gravity;
-
-    /* high and low byte of the location of a special port; if (x, y) are the
-       coordinates of a port in the field and (0, 0) is the top-left corner,
-       the 16 bit value here calculates as 2 * (x + (y * 60)) (this is twice
-       of what may be expected: Supaplex works with a game field in memory
-       which is 2 bytes per tile) */
-    port_location = getFile16BitBE(file);
-
-    /* change gravity: 1 == "turn on", anything else (0) == "turn off" */
-    gravity = fgetc(file);
-
-    /* "freeze zonks": 2 == "turn on", anything else (0, 1) == "turn off" */
-    ReadUnusedBytesFromFile(file, 1);	/* (not used by R'n'D engine) */
-
-    /* "freeze enemies": 1 == "turn on", anything else (0) == "turn off" */
-    ReadUnusedBytesFromFile(file, 1);	/* (not used by R'n'D engine) */
-
-    ReadUnusedBytesFromFile(file, 1);	/* (not used by Supaplex engine) */
-
-    if (i >= num_special_ports)
-      continue;
-
-    port_x = (port_location / 2) % SP_LEVEL_XSIZE;
-    port_y = (port_location / 2) / SP_LEVEL_XSIZE;
+    boolean gravity_port_found = FALSE;
+    boolean gravity_port_valid = FALSE;
+    int gravity_port_flag;
+    int gravity_port_base_element;
+    int element = level->field[x][y];
 
-    if (port_x < 0 || port_x >= SP_LEVEL_XSIZE ||
-	port_y < 0 || port_y >= SP_LEVEL_YSIZE)
+    if (element >= EL_SP_GRAVITY_ON_PORT_RIGHT &&
+	element <= EL_SP_GRAVITY_ON_PORT_UP)
     {
-      Error(ERR_WARN, "special port position (%d, %d) out of bounds",
-	    port_x, port_y);
-
-      continue;
-    }
-
-    port_element = level->field[port_x][port_y];
-
-    if (port_element < EL_SP_GRAVITY_PORT_RIGHT ||
-	port_element > EL_SP_GRAVITY_PORT_UP)
-    {
-      Error(ERR_WARN, "no special port at position (%d, %d)", port_x, port_y);
-
-      continue;
-    }
-
-    /* change previous (wrong) gravity inverting special port to either
-       gravity enabling special port or gravity disabling special port */
-    level->field[port_x][port_y] +=
-      (gravity == 1 ? EL_SP_GRAVITY_ON_PORT_RIGHT :
-       EL_SP_GRAVITY_OFF_PORT_RIGHT) - EL_SP_GRAVITY_PORT_RIGHT;
-  }
-
-  ReadUnusedBytesFromFile(file, 4);	/* (not used by Supaplex engine) */
-
-  /* change special gravity ports without database entries to normal ports */
-  for (y = 0; y < SP_LEVEL_YSIZE; y++)
-    for (x = 0; x < SP_LEVEL_XSIZE; x++)
-      if (level->field[x][y] >= EL_SP_GRAVITY_PORT_RIGHT &&
-	  level->field[x][y] <= EL_SP_GRAVITY_PORT_UP)
-	level->field[x][y] += EL_SP_PORT_RIGHT - EL_SP_GRAVITY_PORT_RIGHT;
-
-  /* auto-determine number of infotrons if it was stored as "0" -- see above */
-  if (level->gems_needed == 0)
-  {
-    for (y = 0; y < SP_LEVEL_YSIZE; y++)
-      for (x = 0; x < SP_LEVEL_XSIZE; x++)
-	if (level->field[x][y] == EL_SP_INFOTRON)
-	  level->gems_needed++;
-
-    level->gems_needed &= 0xff;		/* only use low byte -- see above */
-  }
-
-  level->fieldx = SP_LEVEL_XSIZE;
-  level->fieldy = SP_LEVEL_YSIZE;
-
-  level->time = 0;			/* no time limit */
-  level->amoeba_speed = 0;
-  level->time_magic_wall = 0;
-  level->time_wheel = 0;
-  level->amoeba_content = EL_EMPTY;
-
-#if 1
-  /* original Supaplex does not use score values -- use default values */
-#else
-  for (i = 0; i < LEVEL_SCORE_ELEMENTS; i++)
-    level->score[i] = 0;
-#endif
-
-  /* there are no yamyams in supaplex levels */
-  for (i = 0; i < level->num_yamyam_contents; i++)
-    for (y = 0; y < 3; y++)
-      for (x = 0; x < 3; x++)
-	level->yamyam_content[i].e[x][y] = EL_EMPTY;
-}
-
-static void LoadLevelFromFileInfo_SP(struct LevelInfo *level,
-				     struct LevelFileInfo *level_file_info)
-{
-  char *filename = level_file_info->filename;
-  FILE *file;
-  int nr = level_file_info->nr - leveldir_current->first_level;
-  int i, l, x, y;
-  char name_first, name_last;
-  struct LevelInfo multipart_level;
-  int multipart_xpos, multipart_ypos;
-  boolean is_multipart_level;
-  boolean is_first_part;
-  boolean reading_multipart_level = FALSE;
-  boolean use_empty_level = FALSE;
-
-  if (!(file = fopen(filename, MODE_READ)))
-  {
-    level->no_valid_file = TRUE;
-
-    Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
-
-    return;
-  }
-
-  /* position file stream to the requested level inside the level package */
-  if (level_file_info->packed &&
-      fseek(file, nr * SP_LEVEL_SIZE, SEEK_SET) != 0)
-  {
-    level->no_valid_file = TRUE;
-
-    Error(ERR_WARN, "cannot fseek in file '%s' -- using empty level", filename);
-
-    return;
-  }
-
-  /* there exist Supaplex level package files with multi-part levels which
-     can be detected as follows: instead of leading and trailing dashes ('-')
-     to pad the level name, they have leading and trailing numbers which are
-     the x and y coordinations of the current part of the multi-part level;
-     if there are '?' characters instead of numbers on the left or right side
-     of the level name, the multi-part level consists of only horizontal or
-     vertical parts */
-
-  for (l = nr; l < NUM_SUPAPLEX_LEVELS_PER_PACKAGE; l++)
-  {
-    LoadLevelFromFileStream_SP(file, level, l);
-
-    /* check if this level is a part of a bigger multi-part level */
-
-    name_first = level->name[0];
-    name_last  = level->name[SP_LEVEL_NAME_LEN - 1];
-
-    is_multipart_level =
-      ((name_first == '?' || (name_first >= '0' && name_first <= '9')) &&
-       (name_last  == '?' || (name_last  >= '0' && name_last  <= '9')));
-
-    is_first_part =
-      ((name_first == '?' || name_first == '1') &&
-       (name_last  == '?' || name_last  == '1'));
-
-    /* correct leading multipart level meta information in level name */
-    for (i = 0; i < SP_LEVEL_NAME_LEN && level->name[i] == name_first; i++)
-      level->name[i] = '-';
-
-    /* correct trailing multipart level meta information in level name */
-    for (i = SP_LEVEL_NAME_LEN - 1; i >= 0 && level->name[i] == name_last; i--)
-      level->name[i] = '-';
-
-    /* ---------- check for normal single level ---------- */
-
-    if (!reading_multipart_level && !is_multipart_level)
-    {
-      /* the current level is simply a normal single-part level, and we are
-	 not reading a multi-part level yet, so return the level as it is */
-
-      break;
-    }
-
-    /* ---------- check for empty level (unused multi-part) ---------- */
-
-    if (!reading_multipart_level && is_multipart_level && !is_first_part)
-    {
-      /* this is a part of a multi-part level, but not the first part
-	 (and we are not already reading parts of a multi-part level);
-	 in this case, use an empty level instead of the single part */
-
-      use_empty_level = TRUE;
-
-      break;
-    }
-
-    /* ---------- check for finished multi-part level ---------- */
-
-    if (reading_multipart_level &&
-	(!is_multipart_level ||
-	 !strEqual(level->name, multipart_level.name)))
-    {
-      /* we are already reading parts of a multi-part level, but this level is
-	 either not a multi-part level, or a part of a different multi-part
-	 level; in both cases, the multi-part level seems to be complete */
-
-      break;
-    }
-
-    /* ---------- here we have one part of a multi-part level ---------- */
-
-    reading_multipart_level = TRUE;
-
-    if (is_first_part)	/* start with first part of new multi-part level */
-    {
-      /* copy level info structure from first part */
-      multipart_level = *level;
-
-      /* clear playfield of new multi-part level */
-      for (y = 0; y < MAX_LEV_FIELDY; y++)
-	for (x = 0; x < MAX_LEV_FIELDX; x++)
-	  multipart_level.field[x][y] = EL_EMPTY;
-    }
-
-    if (name_first == '?')
-      name_first = '1';
-    if (name_last == '?')
-      name_last = '1';
-
-    multipart_xpos = (int)(name_first - '0');
-    multipart_ypos = (int)(name_last  - '0');
-
-#if 0
-    printf("----------> part (%d/%d) of multi-part level '%s'\n",
-	   multipart_xpos, multipart_ypos, multipart_level.name);
-#endif
-
-    if (multipart_xpos * SP_LEVEL_XSIZE > MAX_LEV_FIELDX ||
-	multipart_ypos * SP_LEVEL_YSIZE > MAX_LEV_FIELDY)
-    {
-      Error(ERR_WARN, "multi-part level is too big -- ignoring part of it");
-
-      break;
-    }
-
-    multipart_level.fieldx = MAX(multipart_level.fieldx,
-				 multipart_xpos * SP_LEVEL_XSIZE);
-    multipart_level.fieldy = MAX(multipart_level.fieldy,
-				 multipart_ypos * SP_LEVEL_YSIZE);
-
-    /* copy level part at the right position of multi-part level */
-    for (y = 0; y < SP_LEVEL_YSIZE; y++)
-    {
-      for (x = 0; x < SP_LEVEL_XSIZE; x++)
-      {
-	int start_x = (multipart_xpos - 1) * SP_LEVEL_XSIZE;
-	int start_y = (multipart_ypos - 1) * SP_LEVEL_YSIZE;
-
-	multipart_level.field[start_x + x][start_y + y] = level->field[x][y];
-      }
-    }
-  }
-
-  fclose(file);
-
-  if (use_empty_level)
-  {
-    setLevelInfoToDefaults(level);
-
-    level->fieldx = SP_LEVEL_XSIZE;
-    level->fieldy = SP_LEVEL_YSIZE;
-
-    for (y = 0; y < SP_LEVEL_YSIZE; y++)
-      for (x = 0; x < SP_LEVEL_XSIZE; x++)
-	level->field[x][y] = EL_EMPTY;
-
-    strcpy(level->name, "-------- EMPTY --------");
-
-    Error(ERR_WARN, "single part of multi-part level -- using empty level");
-  }
-
-  if (reading_multipart_level)
-    *level = multipart_level;
-}
-
-#endif
-
-void CopyNativeLevel_RND_to_SP(struct LevelInfo *level)
-{
-  struct LevelInfo_SP *level_sp = level->native_sp_level;
-  LevelInfoType *header = &level_sp->header;
-  int i, x, y;
-
-  level_sp->width  = level->fieldx;
-  level_sp->height = level->fieldy;
-
-  for (x = 0; x < level->fieldx; x++)
-    for (y = 0; y < level->fieldy; y++)
-      level_sp->playfield[x][y] = map_element_RND_to_SP(level->field[x][y]);
-
-  header->InitialGravity = (level->initial_player_gravity[0] ? 1 : 0);
-
-  for (i = 0; i < SP_LEVEL_NAME_LEN; i++)
-    header->LevelTitle[i] = level->name[i];
-  /* !!! NO STRING TERMINATION IN SUPAPLEX VB CODE YET -- FIX THIS !!! */
-
-  header->InfotronsNeeded = level->gems_needed;
-
-  header->SpecialPortCount = 0;
-
-  for (x = 0; x < level->fieldx; x++) for (y = 0; y < level->fieldy; y++)
-  {
-    boolean gravity_port_found = FALSE;
-    boolean gravity_port_valid = FALSE;
-    int gravity_port_flag;
-    int gravity_port_base_element;
-    int element = level->field[x][y];
-
-    if (element >= EL_SP_GRAVITY_ON_PORT_RIGHT &&
-	element <= EL_SP_GRAVITY_ON_PORT_UP)
-    {
-      gravity_port_found = TRUE;
-      gravity_port_valid = TRUE;
-      gravity_port_flag = 1;
-      gravity_port_base_element = EL_SP_GRAVITY_ON_PORT_RIGHT;
+      gravity_port_found = TRUE;
+      gravity_port_valid = TRUE;
+      gravity_port_flag = 1;
+      gravity_port_base_element = EL_SP_GRAVITY_ON_PORT_RIGHT;
     }
     else if (element >= EL_SP_GRAVITY_OFF_PORT_RIGHT &&
 	     element <= EL_SP_GRAVITY_OFF_PORT_UP)
@@ -4518,7 +3784,8 @@ static void CopyNativeTape_SP_to_RND(struct LevelInfo *level)
     tape.pos[i].delay = demo_repeat + 1;
   }
 
-  tape.length_seconds = GetTapeLength();
+  tape.length_frames  = GetTapeLengthFrames();
+  tape.length_seconds = GetTapeLengthSeconds();
 }
 
 
@@ -5995,9 +5262,7 @@ int getMappedElement_DC(int element)
   return getMappedElement(element);
 }
 
-#if 1
-
-static void LoadLevelFromFileStream_DC(FILE *file, struct LevelInfo *level,
+static void LoadLevelFromFileStream_DC(File *file, struct LevelInfo *level,
 				       int nr)
 {
   byte header[DC_LEVEL_HEADER_SIZE];
@@ -6095,11 +5360,7 @@ static void LoadLevelFromFileStream_DC(FILE *file, struct LevelInfo *level,
     for (y = 0; y < 3; y++) for (x = 0; x < 3; x++)
     {
       unsigned short word = getDecodedWord_DC(getFile16BitBE(file), FALSE);
-#if 1
       int element_dc = ((word & 0xff) << 8) | ((word >> 8) & 0xff);
-#else
-      int element_dc = word;
-#endif
 
       if (i < MAX_ELEMENT_CONTENTS)
 	level->yamyam_content[i].e[x][y] = getMappedElement_DC(element_dc);
@@ -6114,11 +5375,7 @@ static void LoadLevelFromFileStream_DC(FILE *file, struct LevelInfo *level,
   for (y = 0; y < fieldy; y++) for (x = 0; x < fieldx; x++)
   {
     unsigned short word = getDecodedWord_DC(getFile16BitBE(file), FALSE);
-#if 1
     int element_dc = ((word & 0xff) << 8) | ((word >> 8) & 0xff);
-#else
-    int element_dc = word;
-#endif
 
     if (x < MAX_LEV_FIELDX && y < MAX_LEV_FIELDY)
       level->field[x][y] = getMappedElement_DC(element_dc);
@@ -6160,45 +5417,24 @@ static void LoadLevelFromFileStream_DC(FILE *file, struct LevelInfo *level,
   /* Diamond Caves has the same (strange) behaviour as Emerald Mine that gems
      can slip down from flat walls, like normal walls and steel walls */
   level->em_slippery_gems = TRUE;
-
-#if 0
-  /* Diamond Caves II levels are always surrounded by indestructible wall, but
-     not necessarily in a rectangular way -- fill with invisible steel wall */
-
-  /* !!! not always true !!! keep level and set BorderElement instead !!! */
-
-  for (y = 0; y < level->fieldy; y++) for (x = 0; x < level->fieldx; x++)
-  {
-#if 1
-    if ((x == 0 || x == level->fieldx - 1 ||
-	 y == 0 || y == level->fieldy - 1) &&
-	level->field[x][y] == EL_EMPTY)
-      level->field[x][y] = EL_INVISIBLE_STEELWALL;
-#else
-    if ((x == 0 || x == level->fieldx - 1 ||
-	 y == 0 || y == level->fieldy - 1) &&
-	level->field[x][y] == EL_EMPTY)
-      FloodFillLevel(x, y, EL_INVISIBLE_STEELWALL,
-		     level->field, level->fieldx, level->fieldy);
-#endif
-  }
-#endif
 }
 
 static void LoadLevelFromFileInfo_DC(struct LevelInfo *level,
-				     struct LevelFileInfo *level_file_info)
+				     struct LevelFileInfo *level_file_info,
+				     boolean level_info_only)
 {
   char *filename = level_file_info->filename;
-  FILE *file;
+  File *file;
   int num_magic_bytes = 8;
   char magic_bytes[num_magic_bytes + 1];
   int num_levels_to_skip = level_file_info->nr - leveldir_current->first_level;
 
-  if (!(file = fopen(filename, MODE_READ)))
+  if (!(file = openFile(filename, MODE_READ)))
   {
     level->no_valid_file = TRUE;
 
-    Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
+    if (!level_info_only)
+      Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
 
     return;
   }
@@ -6208,7 +5444,8 @@ static void LoadLevelFromFileInfo_DC(struct LevelInfo *level,
   if (level_file_info->packed)
   {
     /* read "magic bytes" from start of file */
-    fgets(magic_bytes, num_magic_bytes + 1, file);
+    if (getStringFromFile(file, magic_bytes, num_magic_bytes + 1) == NULL)
+      magic_bytes[0] = '\0';
 
     /* check "magic bytes" for correct file format */
     if (!strPrefix(magic_bytes, "DC2"))
@@ -6238,7 +5475,7 @@ static void LoadLevelFromFileInfo_DC(struct LevelInfo *level,
       while (num_levels_to_skip >= 0)
       {
 	/* advance file stream to next level inside the level package */
-	if (fseek(file, skip_bytes, SEEK_CUR) != 0)
+	if (seekFile(file, skip_bytes, SEEK_CUR) != 0)
 	{
 	  level->no_valid_file = TRUE;
 
@@ -6270,230 +5507,9 @@ static void LoadLevelFromFileInfo_DC(struct LevelInfo *level,
 
   LoadLevelFromFileStream_DC(file, level, level_file_info->nr);
 
-  fclose(file);
-}
-
-#else
-
-static void LoadLevelFromFileInfo_DC(struct LevelInfo *level,
-				     struct LevelFileInfo *level_file_info)
-{
-  char *filename = level_file_info->filename;
-  FILE *file;
-#if 0
-  int nr = level_file_info->nr - leveldir_current->first_level;
-#endif
-  byte header[DC_LEVEL_HEADER_SIZE];
-  int envelope_size;
-  int envelope_header_pos = 62;
-  int envelope_content_pos = 94;
-  int level_name_pos = 251;
-  int level_author_pos = 292;
-  int envelope_header_len;
-  int envelope_content_len;
-  int level_name_len;
-  int level_author_len;
-  int fieldx, fieldy;
-  int num_yamyam_contents;
-  int i, x, y;
-
-  if (!(file = fopen(filename, MODE_READ)))
-  {
-    level->no_valid_file = TRUE;
-
-    Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
-
-    return;
-  }
-
-#if 0
-  /* position file stream to the requested level inside the level package */
-  if (fseek(file, nr * SP_LEVEL_SIZE, SEEK_SET) != 0)
-  {
-    level->no_valid_file = TRUE;
-
-    Error(ERR_WARN, "cannot fseek in file '%s' -- using empty level", filename);
-
-    return;
-  }
-#endif
-
-  getDecodedWord_DC(0, TRUE);		/* initialize DC2 decoding engine */
-
-  for (i = 0; i < DC_LEVEL_HEADER_SIZE / 2; i++)
-  {
-    unsigned short header_word = getDecodedWord_DC(getFile16BitBE(file), FALSE);
-
-    header[i * 2 + 0] = header_word >> 8;
-    header[i * 2 + 1] = header_word & 0xff;
-  }
-
-  /* read some values from level header to check level decoding integrity */
-  fieldx = header[6] | (header[7] << 8);
-  fieldy = header[8] | (header[9] << 8);
-  num_yamyam_contents = header[60] | (header[61] << 8);
-
-  /* do some simple sanity checks to ensure that level was correctly decoded */
-  if (fieldx < 1 || fieldx > 256 ||
-      fieldy < 1 || fieldy > 256 ||
-      num_yamyam_contents < 1 || num_yamyam_contents > 8)
-  {
-    level->no_valid_file = TRUE;
-
-    Error(ERR_WARN, "cannot read level from file '%s' -- using empty level",
-	  filename);
-
-    return;
-  }
-
-  /* maximum envelope header size is 31 bytes */
-  envelope_header_len	= header[envelope_header_pos];
-  /* maximum envelope content size is 110 (156?) bytes */
-  envelope_content_len	= header[envelope_content_pos];
-
-  /* maximum level title size is 40 bytes */
-  level_name_len	= MIN(header[level_name_pos],   MAX_LEVEL_NAME_LEN);
-  /* maximum level author size is 30 (51?) bytes */
-  level_author_len	= MIN(header[level_author_pos], MAX_LEVEL_AUTHOR_LEN);
-
-  envelope_size = 0;
-
-  for (i = 0; i < envelope_header_len; i++)
-    if (envelope_size < MAX_ENVELOPE_TEXT_LEN)
-      level->envelope[0].text[envelope_size++] =
-	header[envelope_header_pos + 1 + i];
-
-  if (envelope_header_len > 0 && envelope_content_len > 0)
-  {
-    if (envelope_size < MAX_ENVELOPE_TEXT_LEN)
-      level->envelope[0].text[envelope_size++] = '\n';
-    if (envelope_size < MAX_ENVELOPE_TEXT_LEN)
-      level->envelope[0].text[envelope_size++] = '\n';
-  }
-
-  for (i = 0; i < envelope_content_len; i++)
-    if (envelope_size < MAX_ENVELOPE_TEXT_LEN)
-      level->envelope[0].text[envelope_size++] =
-	header[envelope_content_pos + 1 + i];
-
-  level->envelope[0].text[envelope_size] = '\0';
-
-  level->envelope[0].xsize = MAX_ENVELOPE_XSIZE;
-  level->envelope[0].ysize = 10;
-  level->envelope[0].autowrap = TRUE;
-  level->envelope[0].centered = TRUE;
-
-  for (i = 0; i < level_name_len; i++)
-    level->name[i] = header[level_name_pos + 1 + i];
-  level->name[level_name_len] = '\0';
-
-  for (i = 0; i < level_author_len; i++)
-    level->author[i] = header[level_author_pos + 1 + i];
-  level->author[level_author_len] = '\0';
-
-  num_yamyam_contents = header[60] | (header[61] << 8);
-  level->num_yamyam_contents =
-    MIN(MAX(MIN_ELEMENT_CONTENTS, num_yamyam_contents), MAX_ELEMENT_CONTENTS);
-
-  for (i = 0; i < num_yamyam_contents; i++)
-  {
-    for (y = 0; y < 3; y++) for (x = 0; x < 3; x++)
-    {
-      unsigned short word = getDecodedWord_DC(getFile16BitBE(file), FALSE);
-#if 1
-      int element_dc = ((word & 0xff) << 8) | ((word >> 8) & 0xff);
-#else
-      int element_dc = word;
-#endif
-
-      if (i < MAX_ELEMENT_CONTENTS)
-	level->yamyam_content[i].e[x][y] = getMappedElement_DC(element_dc);
-    }
-  }
-
-  fieldx = header[6] | (header[7] << 8);
-  fieldy = header[8] | (header[9] << 8);
-  level->fieldx = MIN(MAX(MIN_LEV_FIELDX, fieldx), MAX_LEV_FIELDX);
-  level->fieldy = MIN(MAX(MIN_LEV_FIELDY, fieldy), MAX_LEV_FIELDY);
-
-  for (y = 0; y < fieldy; y++) for (x = 0; x < fieldx; x++)
-  {
-    unsigned short word = getDecodedWord_DC(getFile16BitBE(file), FALSE);
-#if 1
-    int element_dc = ((word & 0xff) << 8) | ((word >> 8) & 0xff);
-#else
-    int element_dc = word;
-#endif
-
-    if (x < MAX_LEV_FIELDX && y < MAX_LEV_FIELDY)
-      level->field[x][y] = getMappedElement_DC(element_dc);
-  }
-
-  x = MIN(MAX(0, (header[10] | (header[11] << 8)) - 1), MAX_LEV_FIELDX - 1);
-  y = MIN(MAX(0, (header[12] | (header[13] << 8)) - 1), MAX_LEV_FIELDY - 1);
-  level->field[x][y] = EL_PLAYER_1;
-
-  x = MIN(MAX(0, (header[14] | (header[15] << 8)) - 1), MAX_LEV_FIELDX - 1);
-  y = MIN(MAX(0, (header[16] | (header[17] << 8)) - 1), MAX_LEV_FIELDY - 1);
-  level->field[x][y] = EL_PLAYER_2;
-
-  level->gems_needed		= header[18] | (header[19] << 8);
-
-  level->score[SC_EMERALD]	= header[20] | (header[21] << 8);
-  level->score[SC_DIAMOND]	= header[22] | (header[23] << 8);
-  level->score[SC_PEARL]	= header[24] | (header[25] << 8);
-  level->score[SC_CRYSTAL]	= header[26] | (header[27] << 8);
-  level->score[SC_NUT]		= header[28] | (header[29] << 8);
-  level->score[SC_ROBOT]	= header[30] | (header[31] << 8);
-  level->score[SC_SPACESHIP]	= header[32] | (header[33] << 8);
-  level->score[SC_BUG]		= header[34] | (header[35] << 8);
-  level->score[SC_YAMYAM]	= header[36] | (header[37] << 8);
-  level->score[SC_DYNAMITE]	= header[38] | (header[39] << 8);
-  level->score[SC_KEY]		= header[40] | (header[41] << 8);
-  level->score[SC_TIME_BONUS]	= header[42] | (header[43] << 8);
-
-  level->time			= header[44] | (header[45] << 8);
-
-  level->amoeba_speed		= header[46] | (header[47] << 8);
-  level->time_light		= header[48] | (header[49] << 8);
-  level->time_timegate		= header[50] | (header[51] << 8);
-  level->time_wheel		= header[52] | (header[53] << 8);
-  level->time_magic_wall	= header[54] | (header[55] << 8);
-  level->extra_time		= header[56] | (header[57] << 8);
-  level->shield_normal_time	= header[58] | (header[59] << 8);
-
-  fclose(file);
-
-  /* Diamond Caves has the same (strange) behaviour as Emerald Mine that gems
-     can slip down from flat walls, like normal walls and steel walls */
-  level->em_slippery_gems = TRUE;
-
-#if 0
-  /* Diamond Caves II levels are always surrounded by indestructible wall, but
-     not necessarily in a rectangular way -- fill with invisible steel wall */
-
-  /* !!! not always true !!! keep level and set BorderElement instead !!! */
-
-  for (y = 0; y < level->fieldy; y++) for (x = 0; x < level->fieldx; x++)
-  {
-#if 1
-    if ((x == 0 || x == level->fieldx - 1 ||
-	 y == 0 || y == level->fieldy - 1) &&
-	level->field[x][y] == EL_EMPTY)
-      level->field[x][y] = EL_INVISIBLE_STEELWALL;
-#else
-    if ((x == 0 || x == level->fieldx - 1 ||
-	 y == 0 || y == level->fieldy - 1) &&
-	level->field[x][y] == EL_EMPTY)
-      FloodFillLevel(x, y, EL_INVISIBLE_STEELWALL,
-		     level->field, level->fieldx, level->fieldy);
-#endif
-  }
-#endif
+  closeFile(file);
 }
 
-#endif
-
 
 /* ------------------------------------------------------------------------- */
 /* functions for loading SB level                                            */
@@ -6516,11 +5532,7 @@ int getMappedElement_SB(int element_ascii, boolean use_ces)
     { '.', EL_SOKOBAN_FIELD_EMPTY,  EL_CUSTOM_5 },  /* goal square */
     { '*', EL_SOKOBAN_FIELD_FULL,   EL_CUSTOM_6 },  /* box on goal square */
     { '+', EL_SOKOBAN_FIELD_PLAYER, EL_CUSTOM_7 },  /* player on goal square */
-#if 0
-    { '_', EL_INVISIBLE_STEELWALL,  EL_CUSTOM_8 },  /* floor beyond border */
-#else
     { '_', EL_INVISIBLE_STEELWALL,  EL_FROM_LEVEL_TEMPLATE },  /* floor beyond border */
-#endif
 
     { 0,   -1,                      -1          },
   };
@@ -6535,14 +5547,15 @@ int getMappedElement_SB(int element_ascii, boolean use_ces)
 }
 
 static void LoadLevelFromFileInfo_SB(struct LevelInfo *level,
-				     struct LevelFileInfo *level_file_info)
+				     struct LevelFileInfo *level_file_info,
+				     boolean level_info_only)
 {
   char *filename = level_file_info->filename;
   char line[MAX_LINE_LEN], line_raw[MAX_LINE_LEN], previous_line[MAX_LINE_LEN];
   char last_comment[MAX_LINE_LEN];
   char level_name[MAX_LINE_LEN];
   char *line_ptr;
-  FILE *file;
+  File *file;
   int num_levels_to_skip = level_file_info->nr - leveldir_current->first_level;
   boolean read_continued_line = FALSE;
   boolean reading_playfield = FALSE;
@@ -6553,32 +5566,24 @@ static void LoadLevelFromFileInfo_SB(struct LevelInfo *level,
   int line_nr = 0;
   int x = 0, y = 0;		/* initialized to make compilers happy */
 
-#if 0
-  printf("::: looking for level number %d [%d]\n",
-	 level_file_info->nr, num_levels_to_skip);
-#endif
-
   last_comment[0] = '\0';
   level_name[0] = '\0';
 
-  if (!(file = fopen(filename, MODE_READ)))
+  if (!(file = openFile(filename, MODE_READ)))
   {
     level->no_valid_file = TRUE;
 
-    Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
+    if (!level_info_only)
+      Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
 
     return;
   }
 
-  while (!feof(file))
+  while (!checkEndOfFile(file))
   {
     /* level successfully read, but next level may follow here */
     if (!got_valid_playfield_line && reading_playfield)
     {
-#if 0
-      printf("::: read complete playfield\n");
-#endif
-
       /* read playfield from single level file -- skip remaining file */
       if (!level_file_info->packed)
 	break;
@@ -6597,7 +5602,7 @@ static void LoadLevelFromFileInfo_SB(struct LevelInfo *level,
     got_valid_playfield_line = FALSE;
 
     /* read next line of input file */
-    if (!fgets(line, MAX_LINE_LEN, file))
+    if (!getStringFromFile(file, line, MAX_LINE_LEN))
       break;
 
     /* check if line was completely read and is terminated by line break */
@@ -6647,10 +5652,6 @@ static void LoadLevelFromFileInfo_SB(struct LevelInfo *level,
 
       strcpy(last_comment, line_ptr);
 
-#if 0
-      printf("::: found comment '%s' in line %d\n", last_comment, line_nr);
-#endif
-
       continue;
     }
 
@@ -6662,10 +5663,6 @@ static void LoadLevelFromFileInfo_SB(struct LevelInfo *level,
       if (strlen(level_name) > 0 && level_name[strlen(level_name) - 1] == '\'')
 	level_name[strlen(level_name) - 1] = '\0';
 
-#if 0
-      printf("::: found level name '%s' in line %d\n", level_name, line_nr);
-#endif
-
       continue;
     }
 
@@ -6678,10 +5675,6 @@ static void LoadLevelFromFileInfo_SB(struct LevelInfo *level,
 
     /* at this point, we have found a line containing part of a playfield */
 
-#if 0
-    printf("::: found playfield row in line %d\n", line_nr);
-#endif
-
     got_valid_playfield_line = TRUE;
 
     if (!reading_playfield)
@@ -6744,7 +5737,7 @@ static void LoadLevelFromFileInfo_SB(struct LevelInfo *level,
     y++;
   }
 
-  fclose(file);
+  closeFile(file);
 
   level->fieldy = y;
 
@@ -6764,19 +5757,11 @@ static void LoadLevelFromFileInfo_SB(struct LevelInfo *level,
   {
     strncpy(level->name, level_name, MAX_LEVEL_NAME_LEN);
     level->name[MAX_LEVEL_NAME_LEN] = '\0';
-
-#if 0
-    printf(":1: level name: '%s'\n", level->name);
-#endif
   }
   else if (*last_comment != '\0')
   {
     strncpy(level->name, last_comment, MAX_LEVEL_NAME_LEN);
     level->name[MAX_LEVEL_NAME_LEN] = '\0';
-
-#if 0
-    printf(":2: level name: '%s'\n", level->name);
-#endif
   }
   else
   {
@@ -6800,37 +5785,7 @@ static void LoadLevelFromFileInfo_SB(struct LevelInfo *level,
 
   if (load_xsb_to_ces)
   {
-#if 1
-    /* !!! special global settings can now be set in level template !!! */
-#else
-    level->initial_player_stepsize[0] = STEPSIZE_SLOW;
-#endif
-
-    /* fill smaller playfields with padding "beyond border wall" elements */
-    if (level->fieldx < SCR_FIELDX ||
-	level->fieldy < SCR_FIELDY)
-    {
-      short field[level->fieldx][level->fieldy];
-      int new_fieldx = MAX(level->fieldx, SCR_FIELDX);
-      int new_fieldy = MAX(level->fieldy, SCR_FIELDY);
-      int pos_fieldx = (new_fieldx - level->fieldx) / 2;
-      int pos_fieldy = (new_fieldy - level->fieldy) / 2;
-
-      /* copy old playfield (which is smaller than the visible area) */
-      for (y = 0; y < level->fieldy; y++) for (x = 0; x < level->fieldx; x++)
-	field[x][y] = level->field[x][y];
-
-      /* fill new, larger playfield with "beyond border wall" elements */
-      for (y = 0; y < new_fieldy; y++) for (x = 0; x < new_fieldx; x++)
-	level->field[x][y] = getMappedElement_SB('_', load_xsb_to_ces);
-
-      /* copy the old playfield to the middle of the new playfield */
-      for (y = 0; y < level->fieldy; y++) for (x = 0; x < level->fieldx; x++)
-	level->field[pos_fieldx + x][pos_fieldy + y] = field[x][y];
-
-      level->fieldx = new_fieldx;
-      level->fieldy = new_fieldy;
-    }
+    /* special global settings can now be set in level template */
 
     level->use_custom_template = TRUE;
   }
@@ -6842,14 +5797,16 @@ static void LoadLevelFromFileInfo_SB(struct LevelInfo *level,
 /* ------------------------------------------------------------------------- */
 
 static void LoadLevelFromFileInfo_EM(struct LevelInfo *level,
-				     struct LevelFileInfo *level_file_info)
+				     struct LevelFileInfo *level_file_info,
+				     boolean level_info_only)
 {
-  if (!LoadNativeLevel_EM(level_file_info->filename))
+  if (!LoadNativeLevel_EM(level_file_info->filename, level_info_only))
     level->no_valid_file = TRUE;
 }
 
 static void LoadLevelFromFileInfo_SP(struct LevelInfo *level,
-				     struct LevelFileInfo *level_file_info)
+				     struct LevelFileInfo *level_file_info,
+				     boolean level_info_only)
 {
   int pos = 0;
 
@@ -6857,7 +5814,7 @@ static void LoadLevelFromFileInfo_SP(struct LevelInfo *level,
   if (level_file_info->packed)
     pos = level_file_info->nr - leveldir_current->first_level;
 
-  if (!LoadNativeLevel_SP(level_file_info->filename, pos))
+  if (!LoadNativeLevel_SP(level_file_info->filename, pos, level_info_only))
     level->no_valid_file = TRUE;
 }
 
@@ -6896,44 +5853,49 @@ void SaveNativeLevel(struct LevelInfo *level)
 /* functions for loading generic level                                       */
 /* ------------------------------------------------------------------------- */
 
-void LoadLevelFromFileInfo(struct LevelInfo *level,
-			   struct LevelFileInfo *level_file_info)
+static void LoadLevelFromFileInfo(struct LevelInfo *level,
+				  struct LevelFileInfo *level_file_info,
+				  boolean level_info_only)
 {
   /* always start with reliable default values */
-  setLevelInfoToDefaults(level);
+  setLevelInfoToDefaults(level, level_info_only);
 
   switch (level_file_info->type)
   {
     case LEVEL_FILE_TYPE_RND:
-      LoadLevelFromFileInfo_RND(level, level_file_info);
+      LoadLevelFromFileInfo_RND(level, level_file_info, level_info_only);
       break;
 
     case LEVEL_FILE_TYPE_EM:
-      LoadLevelFromFileInfo_EM(level, level_file_info);
+      LoadLevelFromFileInfo_EM(level, level_file_info, level_info_only);
       level->game_engine_type = GAME_ENGINE_TYPE_EM;
       break;
 
     case LEVEL_FILE_TYPE_SP:
-      LoadLevelFromFileInfo_SP(level, level_file_info);
+      LoadLevelFromFileInfo_SP(level, level_file_info, level_info_only);
       level->game_engine_type = GAME_ENGINE_TYPE_SP;
       break;
 
     case LEVEL_FILE_TYPE_DC:
-      LoadLevelFromFileInfo_DC(level, level_file_info);
+      LoadLevelFromFileInfo_DC(level, level_file_info, level_info_only);
       break;
 
     case LEVEL_FILE_TYPE_SB:
-      LoadLevelFromFileInfo_SB(level, level_file_info);
+      LoadLevelFromFileInfo_SB(level, level_file_info, level_info_only);
       break;
 
     default:
-      LoadLevelFromFileInfo_RND(level, level_file_info);
+      LoadLevelFromFileInfo_RND(level, level_file_info, level_info_only);
       break;
   }
 
   /* if level file is invalid, restore level structure to default values */
   if (level->no_valid_file)
-    setLevelInfoToDefaults(level);
+  {
+    setLevelInfoToDefaults(level, level_info_only);
+
+    level->no_valid_file = TRUE;	/* but keep "no valid file" flag */
+  }
 
   if (level->game_engine_type == GAME_ENGINE_TYPE_UNKNOWN)
     level->game_engine_type = GAME_ENGINE_TYPE_RND;
@@ -6953,7 +5915,7 @@ void LoadLevelFromFilename(struct LevelInfo *level, char *filename)
   level_file_info.type = LEVEL_FILE_TYPE_RND;	/* no others supported yet */
   level_file_info.filename = filename;
 
-  LoadLevelFromFileInfo(level, &level_file_info);
+  LoadLevelFromFileInfo(level, &level_file_info, FALSE);
 }
 
 static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
@@ -6970,10 +5932,6 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
     level->score[SC_TIME_BONUS] /= 10;
   }
 
-#if 0
-  leveldir_current->latest_engine = TRUE;	/* !!! TEST ONLY !!! */
-#endif
-
   if (leveldir_current->latest_engine)
   {
     /* ---------- use latest game engine ----------------------------------- */
@@ -7036,11 +5994,6 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
 
     /* extra time score was same value as time left score before 3.2.0-5 */
     level->extra_time_score = level->score[SC_TIME_BONUS];
-
-#if 0
-    /* time bonus score was given for 10 s instead of 1 s before 3.2.0-5 */
-    level->score[SC_TIME_BONUS] /= 10;
-#endif
   }
 
   if (level->game_version < VERSION_IDENT(3,2,0,7))
@@ -7105,7 +6058,6 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
       change->target_element = EL_PLAYER_1;
   }
 
-#if 1
   /* try to detect and fix "Zelda" style levels, which are broken with 3.2.5 */
   if (level->game_version < VERSION_IDENT(3,2,5,0))
   {
@@ -7129,35 +6081,6 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
 
     level->use_action_after_change_bug = TRUE;
   }
-#else
-  /* !!! THIS DOES NOT FIX "Zelda I" (GRAPHICALLY) AND "Alan's FMV" LEVELS */
-  /* try to detect and fix "Zelda II" levels, which are broken with 3.2.5 */
-  {
-    int element = EL_CUSTOM_16;
-    struct ElementInfo *ei = &element_info[element];
-
-    /* This is needed to fix a problem that was caused by a bugfix in function
-       game.c/CheckTriggeredElementChangeExt() introduced with 3.2.5 that
-       corrects the behaviour when a custom element changes to another custom
-       element with a higher element number that has change actions defined.
-       Normally, only one change per frame is allowed for custom elements.
-       Therefore, it is checked if a custom element already changed in the
-       current frame; if it did, subsequent changes are suppressed.
-       Unfortunately, this is only checked for element changes, but not for
-       change actions, which are still executed. As the function above loops
-       through all custom elements from lower to higher, an element change
-       resulting in a lower CE number won't be checked again, while a target
-       element with a higher number will also be checked, and potential change
-       actions will get executed for this CE, too (which is wrong), while
-       further changes are ignored (which is correct). As this bugfix breaks
-       Zelda II (but no other levels), allow the previous, incorrect behaviour
-       for this outstanding level set to not break the game or existing tapes */
-
-    if (strncmp(leveldir_current->identifier, "zelda2", 6) == 0 ||
-	strncmp(ei->description, "scanline - row 1", 16) == 0)
-      level->use_action_after_change_bug = TRUE;
-  }
-#endif
 
   /* not centering level after relocating player was default only in 3.2.3 */
   if (level->game_version == VERSION_IDENT(3,2,3,0))	/* (no pre-releases) */
@@ -7310,6 +6233,12 @@ static void LoadLevel_InitPlayfield(struct LevelInfo *level, char *filename)
       level->field[x][y] = getMappedElementByVersion(level->field[x][y],
 						     level->game_version);
 
+  /* clear unused playfield data (nicer if level gets resized in editor) */
+  for (x = 0; x < MAX_LEV_FIELDX; x++)
+    for (y = 0; y < MAX_LEV_FIELDY; y++)
+      if (x >= level->fieldx || y >= level->fieldy)
+	level->field[x][y] = EL_EMPTY;
+
   /* copy elements to runtime playfield array */
   for (x = 0; x < MAX_LEV_FIELDX; x++)
     for (y = 0; y < MAX_LEV_FIELDY; y++)
@@ -7341,7 +6270,7 @@ void LoadLevelTemplate(int nr)
   setLevelFileInfo(&level_template.file_info, nr);
   filename = level_template.file_info.filename;
 
-  LoadLevelFromFileInfo(&level_template, &level_template.file_info);
+  LoadLevelFromFileInfo(&level_template, &level_template.file_info, FALSE);
 
   LoadLevel_InitVersion(&level_template, filename);
   LoadLevel_InitElements(&level_template, filename);
@@ -7356,7 +6285,7 @@ void LoadLevel(int nr)
   setLevelFileInfo(&level.file_info, nr);
   filename = level.file_info.filename;
 
-  LoadLevelFromFileInfo(&level, &level.file_info);
+  LoadLevelFromFileInfo(&level, &level.file_info, FALSE);
 
   if (level.use_custom_template)
     LoadLevelTemplate(-1);
@@ -7368,6 +6297,13 @@ void LoadLevel(int nr)
   LoadLevel_InitNativeEngines(&level, filename);
 }
 
+void LoadLevelInfoOnly(int nr)
+{
+  setLevelFileInfo(&level.file_info, nr);
+
+  LoadLevelFromFileInfo(&level, &level.file_info, TRUE);
+}
+
 static int SaveLevel_VERS(FILE *file, struct LevelInfo *level)
 {
   int chunk_size = 0;
@@ -7389,7 +6325,7 @@ static int SaveLevel_DATE(FILE *file, struct LevelInfo *level)
   return chunk_size;
 }
 
-#if 0
+#if ENABLE_HISTORIC_CHUNKS
 static void SaveLevel_HEAD(FILE *file, struct LevelInfo *level)
 {
   int i, x, y;
@@ -7463,7 +6399,7 @@ static int SaveLevel_AUTH(FILE *file, struct LevelInfo *level)
   return chunk_size;
 }
 
-#if 0
+#if ENABLE_HISTORIC_CHUNKS
 static int SaveLevel_BODY(FILE *file, struct LevelInfo *level)
 {
   int chunk_size = 0;
@@ -7492,7 +6428,7 @@ static int SaveLevel_BODY(FILE *file, struct LevelInfo *level)
   return chunk_size;
 }
 
-#if 0
+#if ENABLE_HISTORIC_CHUNKS
 static void SaveLevel_CONT(FILE *file, struct LevelInfo *level)
 {
   int i, x, y;
@@ -7512,7 +6448,7 @@ static void SaveLevel_CONT(FILE *file, struct LevelInfo *level)
 }
 #endif
 
-#if 0
+#if ENABLE_HISTORIC_CHUNKS
 static void SaveLevel_CNT2(FILE *file, struct LevelInfo *level, int element)
 {
   int i, x, y;
@@ -7565,7 +6501,7 @@ static void SaveLevel_CNT2(FILE *file, struct LevelInfo *level, int element)
 }
 #endif
 
-#if 0
+#if ENABLE_HISTORIC_CHUNKS
 static int SaveLevel_CNT3(FILE *file, struct LevelInfo *level, int element)
 {
   int envelope_nr = element - EL_ENVELOPE_1;
@@ -7588,7 +6524,7 @@ static int SaveLevel_CNT3(FILE *file, struct LevelInfo *level, int element)
 }
 #endif
 
-#if 0
+#if ENABLE_HISTORIC_CHUNKS
 static void SaveLevel_CUS1(FILE *file, struct LevelInfo *level,
 			   int num_changed_custom_elements)
 {
@@ -7619,7 +6555,7 @@ static void SaveLevel_CUS1(FILE *file, struct LevelInfo *level,
 }
 #endif
 
-#if 0
+#if ENABLE_HISTORIC_CHUNKS
 static void SaveLevel_CUS2(FILE *file, struct LevelInfo *level,
 			   int num_changed_custom_elements)
 {
@@ -7648,7 +6584,7 @@ static void SaveLevel_CUS2(FILE *file, struct LevelInfo *level,
 }
 #endif
 
-#if 0
+#if ENABLE_HISTORIC_CHUNKS
 static void SaveLevel_CUS3(FILE *file, struct LevelInfo *level,
 			   int num_changed_custom_elements)
 {
@@ -7731,7 +6667,7 @@ static void SaveLevel_CUS3(FILE *file, struct LevelInfo *level,
 }
 #endif
 
-#if 0
+#if ENABLE_HISTORIC_CHUNKS
 static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element)
 {
   struct ElementInfo *ei = &element_info[element];
@@ -7851,7 +6787,7 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element)
 }
 #endif
 
-#if 0
+#if ENABLE_HISTORIC_CHUNKS
 static void SaveLevel_GRP1(FILE *file, struct LevelInfo *level, int element)
 {
   struct ElementInfo *ei = &element_info[element];
@@ -8053,12 +6989,6 @@ static int SaveLevel_CUSX(FILE *file, struct LevelInfo *level, int element)
   /* set default description string for this specific element */
   strcpy(xx_default_description, getDefaultElementDescription(ei));
 
-#if 0
-  /* set (fixed) number of content areas (may be wrong by broken level file) */
-  /* (this is now directly corrected for broken level files after loading) */
-  xx_num_contents = 1;
-#endif
-
   for (i = 0; chunk_config_CUSX_base[i].data_type != -1; i++)
     chunk_size += SaveLevel_MicroChunk(file, &chunk_config_CUSX_base[i], FALSE);
 
@@ -8218,12 +7148,12 @@ boolean SaveLevelChecked(int nr)
   boolean new_level = !fileExists(filename);
   boolean level_saved = FALSE;
 
-  if (new_level || Request("Save this level and kill the old ?", REQ_ASK))
+  if (new_level || Request("Save this level and kill the old?", REQ_ASK))
   {
     SaveLevel(nr);
 
     if (new_level)
-      Request("Level saved !", REQ_CONFIRM);
+      Request("Level saved!", REQ_CONFIRM);
 
     level_saved = TRUE;
   }
@@ -8240,34 +7170,34 @@ void DumpLevel(struct LevelInfo *level)
     return;
   }
 
-  printf_line("-", 79);
-  printf("Level xxx (file version %08d, game version %08d)\n",
-	 level->file_version, level->game_version);
-  printf_line("-", 79);
+  PrintLine("-", 79);
+  Print("Level xxx (file version %08d, game version %08d)\n",
+	level->file_version, level->game_version);
+  PrintLine("-", 79);
 
-  printf("Level author: '%s'\n", level->author);
-  printf("Level title:  '%s'\n", level->name);
-  printf("\n");
-  printf("Playfield size: %d x %d\n", level->fieldx, level->fieldy);
-  printf("\n");
-  printf("Level time:  %d seconds\n", level->time);
-  printf("Gems needed: %d\n", level->gems_needed);
-  printf("\n");
-  printf("Time for magic wall: %d seconds\n", level->time_magic_wall);
-  printf("Time for wheel:      %d seconds\n", level->time_wheel);
-  printf("Time for light:      %d seconds\n", level->time_light);
-  printf("Time for timegate:   %d seconds\n", level->time_timegate);
-  printf("\n");
-  printf("Amoeba speed: %d\n", level->amoeba_speed);
-  printf("\n");
+  Print("Level author: '%s'\n", level->author);
+  Print("Level title:  '%s'\n", level->name);
+  Print("\n");
+  Print("Playfield size: %d x %d\n", level->fieldx, level->fieldy);
+  Print("\n");
+  Print("Level time:  %d seconds\n", level->time);
+  Print("Gems needed: %d\n", level->gems_needed);
+  Print("\n");
+  Print("Time for magic wall: %d seconds\n", level->time_magic_wall);
+  Print("Time for wheel:      %d seconds\n", level->time_wheel);
+  Print("Time for light:      %d seconds\n", level->time_light);
+  Print("Time for timegate:   %d seconds\n", level->time_timegate);
+  Print("\n");
+  Print("Amoeba speed: %d\n", level->amoeba_speed);
+  Print("\n");
 
-  printf("EM style slippery gems:      %s\n", (level->em_slippery_gems ? "yes" : "no"));
-  printf("Player blocks last field:    %s\n", (level->block_last_field ? "yes" : "no"));
-  printf("SP player blocks last field: %s\n", (level->sp_block_last_field ? "yes" : "no"));
-  printf("use spring bug: %s\n", (level->use_spring_bug ? "yes" : "no"));
-  printf("use step counter: %s\n", (level->use_step_counter ? "yes" : "no"));
+  Print("EM style slippery gems:      %s\n", (level->em_slippery_gems ? "yes" : "no"));
+  Print("Player blocks last field:    %s\n", (level->block_last_field ? "yes" : "no"));
+  Print("SP player blocks last field: %s\n", (level->sp_block_last_field ? "yes" : "no"));
+  Print("use spring bug: %s\n", (level->use_spring_bug ? "yes" : "no"));
+  Print("use step counter: %s\n", (level->use_step_counter ? "yes" : "no"));
 
-  printf_line("-", 79);
+  PrintLine("-", 79);
 }
 
 
@@ -8301,7 +7231,7 @@ static void setTapeInfoToDefaults()
   tape.no_valid_file = FALSE;
 }
 
-static int LoadTape_VERS(FILE *file, int chunk_size, struct TapeInfo *tape)
+static int LoadTape_VERS(File *file, int chunk_size, struct TapeInfo *tape)
 {
   tape->file_version = getFileVersion(file);
   tape->game_version = getFileVersion(file);
@@ -8309,7 +7239,7 @@ static int LoadTape_VERS(FILE *file, int chunk_size, struct TapeInfo *tape)
   return chunk_size;
 }
 
-static int LoadTape_HEAD(FILE *file, int chunk_size, struct TapeInfo *tape)
+static int LoadTape_HEAD(File *file, int chunk_size, struct TapeInfo *tape)
 {
   int i;
 
@@ -8348,7 +7278,7 @@ static int LoadTape_HEAD(FILE *file, int chunk_size, struct TapeInfo *tape)
   return chunk_size;
 }
 
-static int LoadTape_INFO(FILE *file, int chunk_size, struct TapeInfo *tape)
+static int LoadTape_INFO(File *file, int chunk_size, struct TapeInfo *tape)
 {
   int level_identifier_size;
   int i;
@@ -8368,7 +7298,7 @@ static int LoadTape_INFO(FILE *file, int chunk_size, struct TapeInfo *tape)
   return chunk_size;
 }
 
-static int LoadTape_BODY(FILE *file, int chunk_size, struct TapeInfo *tape)
+static int LoadTape_BODY(File *file, int chunk_size, struct TapeInfo *tape)
 {
   int i, j;
   int chunk_size_expected =
@@ -8442,7 +7372,7 @@ static int LoadTape_BODY(FILE *file, int chunk_size, struct TapeInfo *tape)
       }
     }
 
-    if (feof(file))
+    if (checkEndOfFile(file))
       break;
   }
 
@@ -8454,21 +7384,21 @@ static int LoadTape_BODY(FILE *file, int chunk_size, struct TapeInfo *tape)
 
 void LoadTape_SokobanSolution(char *filename)
 {
-  FILE *file;
+  File *file;
   int move_delay = TILESIZE / level.initial_player_stepsize[0];
 
-  if (!(file = fopen(filename, MODE_READ)))
+  if (!(file = openFile(filename, MODE_READ)))
   {
     tape.no_valid_file = TRUE;
 
     return;
   }
 
-  while (!feof(file))
+  while (!checkEndOfFile(file))
   {
-    unsigned char c = fgetc(file);
+    unsigned char c = getByteFromFile(file);
 
-    if (feof(file))
+    if (checkEndOfFile(file))
       break;
 
     switch (c)
@@ -8517,19 +7447,20 @@ void LoadTape_SokobanSolution(char *filename)
     }
   }
 
-  fclose(file);
+  closeFile(file);
 
   if (tape.no_valid_file)
     return;
 
-  tape.length_seconds = GetTapeLength();
+  tape.length_frames  = GetTapeLengthFrames();
+  tape.length_seconds = GetTapeLengthSeconds();
 }
 
 void LoadTapeFromFilename(char *filename)
 {
   char cookie[MAX_LINE_LEN];
   char chunk_name[CHUNK_ID_LEN + 1];
-  FILE *file;
+  File *file;
   int chunk_size;
 
   /* always start with reliable default values */
@@ -8542,7 +7473,7 @@ void LoadTapeFromFilename(char *filename)
     return;
   }
 
-  if (!(file = fopen(filename, MODE_READ)))
+  if (!(file = openFile(filename, MODE_READ)))
   {
     tape.no_valid_file = TRUE;
 
@@ -8560,14 +7491,17 @@ void LoadTapeFromFilename(char *filename)
       tape.no_valid_file = TRUE;
 
       Error(ERR_WARN, "unknown format of tape file '%s'", filename);
-      fclose(file);
+
+      closeFile(file);
+
       return;
     }
   }
   else	/* check for pre-2.0 file format with cookie string */
   {
     strcpy(cookie, chunk_name);
-    fgets(&cookie[4], MAX_LINE_LEN - 4, file);
+    if (getStringFromFile(file, &cookie[4], MAX_LINE_LEN - 4) == NULL)
+      cookie[4] = '\0';
     if (strlen(cookie) > 0 && cookie[strlen(cookie) - 1] == '\n')
       cookie[strlen(cookie) - 1] = '\0';
 
@@ -8576,7 +7510,9 @@ void LoadTapeFromFilename(char *filename)
       tape.no_valid_file = TRUE;
 
       Error(ERR_WARN, "unknown format of tape file '%s'", filename);
-      fclose(file);
+
+      closeFile(file);
+
       return;
     }
 
@@ -8585,7 +7521,8 @@ void LoadTapeFromFilename(char *filename)
       tape.no_valid_file = TRUE;
 
       Error(ERR_WARN, "unsupported version of tape file '%s'", filename);
-      fclose(file);
+
+      closeFile(file);
 
       return;
     }
@@ -8606,7 +7543,7 @@ void LoadTapeFromFilename(char *filename)
     {
       char *name;
       int size;
-      int (*loader)(FILE *, int, struct TapeInfo *);
+      int (*loader)(File *, int, struct TapeInfo *);
     }
     chunk_info[] =
     {
@@ -8656,13 +7593,14 @@ void LoadTapeFromFilename(char *filename)
     }
   }
 
-  fclose(file);
+  closeFile(file);
 
-  tape.length_seconds = GetTapeLength();
+  tape.length_frames  = GetTapeLengthFrames();
+  tape.length_seconds = GetTapeLengthSeconds();
 
 #if 0
-  printf("::: tape file version: %d\n", tape.file_version);
-  printf("::: tape game version: %d\n", tape.game_version);
+  printf("::: tape file version: %d\n",   tape.file_version);
+  printf("::: tape game version: %d\n",   tape.game_version);
   printf("::: tape engine version: %d\n", tape.engine_version);
 #endif
 }
@@ -8680,12 +7618,10 @@ void LoadSolutionTape(int nr)
 
   LoadTapeFromFilename(filename);
 
-#if 1
   if (TAPE_IS_EMPTY(tape) &&
       level.game_engine_type == GAME_ENGINE_TYPE_SP &&
       level.native_sp_level->demo.is_available)
     CopyNativeTape_SP_to_RND(&level);
-#endif
 }
 
 static void SaveTape_VERS(FILE *file, struct TapeInfo *tape)
@@ -8747,9 +7683,6 @@ void SaveTape(int nr)
 {
   char *filename = getTapeFilename(nr);
   FILE *file;
-#if 0
-  boolean new_tape = TRUE;
-#endif
   int num_participating_players = 0;
   int info_chunk_size;
   int body_chunk_size;
@@ -8757,16 +7690,6 @@ void SaveTape(int nr)
 
   InitTapeDirectory(leveldir_current->subdir);
 
-#if 0
-  /* if a tape still exists, ask to overwrite it */
-  if (fileExists(filename))
-  {
-    new_tape = FALSE;
-    if (!Request("Replace old tape ?", REQ_ASK))
-      return;
-  }
-#endif
-
   if (!(file = fopen(filename, MODE_WRITE)))
   {
     Error(ERR_WARN, "cannot save level recording file '%s'", filename);
@@ -8804,11 +7727,6 @@ void SaveTape(int nr)
   SetFilePermissions(filename, PERMS_PRIVATE);
 
   tape.changed = FALSE;
-
-#if 0
-  if (new_tape)
-    Request("Tape saved !", REQ_CONFIRM);
-#endif
 }
 
 boolean SaveTapeChecked(int nr)
@@ -8817,12 +7735,12 @@ boolean SaveTapeChecked(int nr)
   boolean new_tape = !fileExists(filename);
   boolean tape_saved = FALSE;
 
-  if (new_tape || Request("Replace old tape ?", REQ_ASK))
+  if (new_tape || Request("Replace old tape?", REQ_ASK))
   {
     SaveTape(nr);
 
     if (new_tape)
-      Request("Tape saved !", REQ_CONFIRM);
+      Request("Tape saved!", REQ_CONFIRM);
 
     tape_saved = TRUE;
   }
@@ -8842,13 +7760,13 @@ void DumpTape(struct TapeInfo *tape)
     return;
   }
 
-  printf_line("-", 79);
-  printf("Tape of Level %03d (file version %08d, game version %08d)\n",
-	 tape->level_nr, tape->file_version, tape->game_version);
-  printf("                  (effective engine version %08d)\n",
-	 tape->engine_version);
-  printf("Level series identifier: '%s'\n", tape->level_identifier);
-  printf_line("-", 79);
+  PrintLine("-", 79);
+  Print("Tape of Level %03d (file version %08d, game version %08d)\n",
+	tape->level_nr, tape->file_version, tape->game_version);
+  Print("                  (effective engine version %08d)\n",
+	tape->engine_version);
+  Print("Level series identifier: '%s'\n", tape->level_identifier);
+  PrintLine("-", 79);
 
   tape_frame_counter = 0;
 
@@ -8857,7 +7775,7 @@ void DumpTape(struct TapeInfo *tape)
     if (i >= MAX_TAPE_LEN)
       break;
 
-    printf("%04d: ", i);
+    Print("%04d: ", i);
 
     for (j = 0; j < MAX_PLAYERS; j++)
     {
@@ -8865,24 +7783,24 @@ void DumpTape(struct TapeInfo *tape)
       {
 	int action = tape->pos[i].action[j];
 
-	printf("%d:%02x ", j, action);
-	printf("[%c%c%c%c|%c%c] - ",
-	       (action & JOY_LEFT ? '<' : ' '),
-	       (action & JOY_RIGHT ? '>' : ' '),
-	       (action & JOY_UP ? '^' : ' '),
-	       (action & JOY_DOWN ? 'v' : ' '),
-	       (action & JOY_BUTTON_1 ? '1' : ' '),
-	       (action & JOY_BUTTON_2 ? '2' : ' '));
+	Print("%d:%02x ", j, action);
+	Print("[%c%c%c%c|%c%c] - ",
+	      (action & JOY_LEFT ? '<' : ' '),
+	      (action & JOY_RIGHT ? '>' : ' '),
+	      (action & JOY_UP ? '^' : ' '),
+	      (action & JOY_DOWN ? 'v' : ' '),
+	      (action & JOY_BUTTON_1 ? '1' : ' '),
+	      (action & JOY_BUTTON_2 ? '2' : ' '));
       }
     }
 
-    printf("(%03d) ", tape->pos[i].delay);
-    printf("[%05d]\n", tape_frame_counter);
+    Print("(%03d) ", tape->pos[i].delay);
+    Print("[%05d]\n", tape_frame_counter);
 
     tape_frame_counter += tape->pos[i].delay;
   }
 
-  printf_line("-", 79);
+  PrintLine("-", 79);
 }
 
 
@@ -8910,7 +7828,8 @@ void LoadScore(int nr)
     return;
 
   /* check file identifier */
-  fgets(cookie, MAX_LINE_LEN, file);
+  if (fgets(cookie, MAX_LINE_LEN, file) == NULL)
+    cookie[0] = '\0';
   if (strlen(cookie) > 0 && cookie[strlen(cookie) - 1] == '\n')
     cookie[strlen(cookie) - 1] = '\0';
 
@@ -8923,10 +7842,12 @@ void LoadScore(int nr)
 
   for (i = 0; i < MAX_SCORE_ENTRIES; i++)
   {
-    fscanf(file, "%d", &highscore[i].Score);
-    fgets(line, MAX_LINE_LEN, file);
+    if (fscanf(file, "%d", &highscore[i].Score) == EOF)
+      Error(ERR_WARN, "fscanf() failed; %s", strerror(errno));
+    if (fgets(line, MAX_LINE_LEN, file) == NULL)
+      line[0] = '\0';
 
-    if (line[strlen(line) - 1] == '\n')
+    if (strlen(line) > 0 && line[strlen(line) - 1] == '\n')
       line[strlen(line) - 1] = '\0';
 
     for (line_ptr = line; *line_ptr; line_ptr++)
@@ -8946,6 +7867,7 @@ void LoadScore(int nr)
 void SaveScore(int nr)
 {
   int i;
+  int permissions = (program.global_scores ? PERMS_PUBLIC : PERMS_PRIVATE);
   char *filename = getScoreFilename(nr);
   FILE *file;
 
@@ -8964,7 +7886,7 @@ void SaveScore(int nr)
 
   fclose(file);
 
-  SetFilePermissions(filename, PERMS_PUBLIC);
+  SetFilePermissions(filename, permissions);
 }
 
 
@@ -8983,53 +7905,53 @@ void SaveScore(int nr)
 #define SETUP_TOKEN_TOONS			5
 #define SETUP_TOKEN_SCROLL_DELAY		6
 #define SETUP_TOKEN_SCROLL_DELAY_VALUE		7
-#define SETUP_TOKEN_SOFT_SCROLLING		8
-#define SETUP_TOKEN_FADE_SCREENS		9
-#define SETUP_TOKEN_AUTORECORD			10
-#define SETUP_TOKEN_SHOW_TITLESCREEN		11
-#define SETUP_TOKEN_QUICK_DOORS			12
-#define SETUP_TOKEN_TEAM_MODE			13
-#define SETUP_TOKEN_HANDICAP			14
-#define SETUP_TOKEN_SKIP_LEVELS			15
-#define SETUP_TOKEN_TIME_LIMIT			16
-#define SETUP_TOKEN_FULLSCREEN			17
-#define SETUP_TOKEN_FULLSCREEN_MODE		18
-#define SETUP_TOKEN_ASK_ON_ESCAPE		19
-#define SETUP_TOKEN_ASK_ON_ESCAPE_EDITOR	20
-#define SETUP_TOKEN_QUICK_SWITCH		21
-#define SETUP_TOKEN_INPUT_ON_FOCUS		22
-#define SETUP_TOKEN_PREFER_AGA_GRAPHICS		23
-#define SETUP_TOKEN_GAME_FRAME_DELAY		24
-#define SETUP_TOKEN_SP_SHOW_BORDER_ELEMENTS	25
-#define SETUP_TOKEN_GRAPHICS_SET		26
-#define SETUP_TOKEN_SOUNDS_SET			27
-#define SETUP_TOKEN_MUSIC_SET			28
-#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS	29
-#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS	30
-#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC	31
-
-#define NUM_GLOBAL_SETUP_TOKENS			32
+#define SETUP_TOKEN_ENGINE_SNAPSHOT_MODE	8
+#define SETUP_TOKEN_ENGINE_SNAPSHOT_MEMORY	9
+#define SETUP_TOKEN_FADE_SCREENS		10
+#define SETUP_TOKEN_AUTORECORD			11
+#define SETUP_TOKEN_SHOW_TITLESCREEN		12
+#define SETUP_TOKEN_QUICK_DOORS			13
+#define SETUP_TOKEN_TEAM_MODE			14
+#define SETUP_TOKEN_HANDICAP			15
+#define SETUP_TOKEN_SKIP_LEVELS			16
+#define SETUP_TOKEN_TIME_LIMIT			17
+#define SETUP_TOKEN_FULLSCREEN			18
+#define SETUP_TOKEN_WINDOW_SCALING_PERCENT	19
+#define SETUP_TOKEN_WINDOW_SCALING_QUALITY	20
+#define SETUP_TOKEN_SCREEN_RENDERING_MODE	21
+#define SETUP_TOKEN_ASK_ON_ESCAPE		22
+#define SETUP_TOKEN_ASK_ON_ESCAPE_EDITOR	23
+#define SETUP_TOKEN_QUICK_SWITCH		24
+#define SETUP_TOKEN_INPUT_ON_FOCUS		25
+#define SETUP_TOKEN_PREFER_AGA_GRAPHICS		26
+#define SETUP_TOKEN_GAME_FRAME_DELAY		27
+#define SETUP_TOKEN_SP_SHOW_BORDER_ELEMENTS	28
+#define SETUP_TOKEN_SMALL_GAME_GRAPHICS		29
+#define SETUP_TOKEN_SHOW_SNAPSHOT_BUTTONS	30
+#define SETUP_TOKEN_GRAPHICS_SET		31
+#define SETUP_TOKEN_SOUNDS_SET			32
+#define SETUP_TOKEN_MUSIC_SET			33
+#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS	34
+#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS	35
+#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC	36
+#define SETUP_TOKEN_VOLUME_SIMPLE		37
+#define SETUP_TOKEN_VOLUME_LOOPS		38
+#define SETUP_TOKEN_VOLUME_MUSIC		39
+#define SETUP_TOKEN_TOUCH_CONTROL_TYPE		40
+#define SETUP_TOKEN_TOUCH_MOVE_DISTANCE		41
+#define SETUP_TOKEN_TOUCH_DROP_DISTANCE		42
+
+#define NUM_GLOBAL_SETUP_TOKENS			43
 
 /* editor setup */
-#define SETUP_TOKEN_EDITOR_EL_BOULDERDASH	0
-#define SETUP_TOKEN_EDITOR_EL_EMERALD_MINE	1
-#define SETUP_TOKEN_EDITOR_EL_EMERALD_MINE_CLUB	2
-#define SETUP_TOKEN_EDITOR_EL_MORE		3
-#define SETUP_TOKEN_EDITOR_EL_SOKOBAN		4
-#define SETUP_TOKEN_EDITOR_EL_SUPAPLEX		5
-#define SETUP_TOKEN_EDITOR_EL_DIAMOND_CAVES	6
-#define SETUP_TOKEN_EDITOR_EL_DX_BOULDERDASH	7
-#define SETUP_TOKEN_EDITOR_EL_CHARS		8
-#define SETUP_TOKEN_EDITOR_EL_STEEL_CHARS	9
-#define SETUP_TOKEN_EDITOR_EL_CUSTOM		10
-#define SETUP_TOKEN_EDITOR_EL_HEADLINES		11
-#define SETUP_TOKEN_EDITOR_EL_USER_DEFINED	12
-#define SETUP_TOKEN_EDITOR_EL_DYNAMIC		13
-#define SETUP_TOKEN_EDITOR_EL_BY_GAME		14
-#define SETUP_TOKEN_EDITOR_EL_BY_TYPE		15
-#define SETUP_TOKEN_EDITOR_SHOW_ELEMENT_TOKEN	16
-
-#define NUM_EDITOR_SETUP_TOKENS			17
+#define SETUP_TOKEN_EDITOR_EL_CHARS		0
+#define SETUP_TOKEN_EDITOR_EL_STEEL_CHARS	1
+#define SETUP_TOKEN_EDITOR_EL_CUSTOM		2
+#define SETUP_TOKEN_EDITOR_EL_USER_DEFINED	3
+#define SETUP_TOKEN_EDITOR_EL_DYNAMIC		4
+#define SETUP_TOKEN_EDITOR_SHOW_ELEMENT_TOKEN	5
+
+#define NUM_EDITOR_SETUP_TOKENS			6
 
 /* editor cascade setup */
 #define SETUP_TOKEN_EDITOR_CASCADE_BD		0
@@ -9060,19 +7982,20 @@ void SaveScore(int nr)
 #define SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_4	6
 #define SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_ALL	7
 #define SETUP_TOKEN_SHORTCUT_TAPE_EJECT		8
-#define SETUP_TOKEN_SHORTCUT_TAPE_STOP		9
-#define SETUP_TOKEN_SHORTCUT_TAPE_PAUSE		10
-#define SETUP_TOKEN_SHORTCUT_TAPE_RECORD	11
-#define SETUP_TOKEN_SHORTCUT_TAPE_PLAY		12
-#define SETUP_TOKEN_SHORTCUT_SOUND_SIMPLE	13
-#define SETUP_TOKEN_SHORTCUT_SOUND_LOOPS	14
-#define SETUP_TOKEN_SHORTCUT_SOUND_MUSIC	15
-#define SETUP_TOKEN_SHORTCUT_SNAP_LEFT		16
-#define SETUP_TOKEN_SHORTCUT_SNAP_RIGHT		17
-#define SETUP_TOKEN_SHORTCUT_SNAP_UP		18
-#define SETUP_TOKEN_SHORTCUT_SNAP_DOWN		19
-
-#define NUM_SHORTCUT_SETUP_TOKENS		20
+#define SETUP_TOKEN_SHORTCUT_TAPE_EXTRA		9
+#define SETUP_TOKEN_SHORTCUT_TAPE_STOP		10
+#define SETUP_TOKEN_SHORTCUT_TAPE_PAUSE		11
+#define SETUP_TOKEN_SHORTCUT_TAPE_RECORD	12
+#define SETUP_TOKEN_SHORTCUT_TAPE_PLAY		13
+#define SETUP_TOKEN_SHORTCUT_SOUND_SIMPLE	14
+#define SETUP_TOKEN_SHORTCUT_SOUND_LOOPS	15
+#define SETUP_TOKEN_SHORTCUT_SOUND_MUSIC	16
+#define SETUP_TOKEN_SHORTCUT_SNAP_LEFT		17
+#define SETUP_TOKEN_SHORTCUT_SNAP_RIGHT		18
+#define SETUP_TOKEN_SHORTCUT_SNAP_UP		19
+#define SETUP_TOKEN_SHORTCUT_SNAP_DOWN		20
+
+#define NUM_SHORTCUT_SETUP_TOKENS		21
 
 /* player setup */
 #define SETUP_TOKEN_PLAYER_USE_JOYSTICK		0
@@ -9101,6 +8024,53 @@ void SaveScore(int nr)
 
 #define NUM_SYSTEM_SETUP_TOKENS			3
 
+/* internal setup */
+#define SETUP_TOKEN_INT_PROGRAM_TITLE		0
+#define SETUP_TOKEN_INT_PROGRAM_AUTHOR		1
+#define SETUP_TOKEN_INT_PROGRAM_EMAIL		2
+#define SETUP_TOKEN_INT_PROGRAM_WEBSITE		3
+#define SETUP_TOKEN_INT_PROGRAM_COPYRIGHT	4
+#define SETUP_TOKEN_INT_PROGRAM_COMPANY		5
+#define SETUP_TOKEN_INT_PROGRAM_ICON_FILE	6
+#define SETUP_TOKEN_INT_DEFAULT_GRAPHICS_SET	7
+#define SETUP_TOKEN_INT_DEFAULT_SOUNDS_SET	8
+#define SETUP_TOKEN_INT_DEFAULT_MUSIC_SET	9
+#define SETUP_TOKEN_INT_FALLBACK_GRAPHICS_FILE	10
+#define SETUP_TOKEN_INT_FALLBACK_SOUNDS_FILE	11
+#define SETUP_TOKEN_INT_FALLBACK_MUSIC_FILE	12
+#define SETUP_TOKEN_INT_DEFAULT_LEVEL_SERIES	13
+#define SETUP_TOKEN_INT_CHOOSE_FROM_TOP_LEVELDIR 14
+#define SETUP_TOKEN_INT_DEFAULT_WINDOW_WIDTH	15
+#define SETUP_TOKEN_INT_DEFAULT_WINDOW_HEIGHT	16
+
+#define NUM_INTERNAL_SETUP_TOKENS		17
+
+/* debug setup */
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_0		0
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_1		1
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_2		2
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_3		3
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_4		4
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_5		5
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_6		6
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_7		7
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_8		8
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_9		9
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_0	10
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_1	11
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_2	12
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_3	13
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_4	14
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_5	15
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_6	16
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_7	17
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_8	18
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_9	19
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_USE_MOD_KEY 20
+#define SETUP_TOKEN_DEBUG_FRAME_DELAY_GAME_ONLY	21
+
+#define NUM_DEBUG_SETUP_TOKENS			22
+
 /* options setup */
 #define SETUP_TOKEN_OPTIONS_VERBOSE		0
 
@@ -9113,6 +8083,8 @@ static struct SetupEditorCascadeInfo seci;
 static struct SetupShortcutInfo ssi;
 static struct SetupInputInfo sii;
 static struct SetupSystemInfo syi;
+static struct SetupInternalInfo sxi;
+static struct SetupDebugInfo sdi;
 static struct OptionInfo soi;
 
 static struct TokenInfo global_setup_tokens[] =
@@ -9125,7 +8097,8 @@ static struct TokenInfo global_setup_tokens[] =
   { TYPE_SWITCH, &si.toons,                   "toons"			},
   { TYPE_SWITCH, &si.scroll_delay,            "scroll_delay"		},
   { TYPE_INTEGER,&si.scroll_delay_value,      "scroll_delay_value"	},
-  { TYPE_SWITCH, &si.soft_scrolling,          "soft_scrolling"		},
+  { TYPE_STRING, &si.engine_snapshot_mode,    "engine_snapshot_mode"	},
+  { TYPE_INTEGER,&si.engine_snapshot_memory,  "engine_snapshot_memory"	},
   { TYPE_SWITCH, &si.fade_screens,            "fade_screens"		},
   { TYPE_SWITCH, &si.autorecord,              "automatic_tape_recording"},
   { TYPE_SWITCH, &si.show_titlescreen,        "show_titlescreen"	},
@@ -9135,7 +8108,9 @@ static struct TokenInfo global_setup_tokens[] =
   { TYPE_SWITCH, &si.skip_levels,             "skip_levels"		},
   { TYPE_SWITCH, &si.time_limit,              "time_limit"		},
   { TYPE_SWITCH, &si.fullscreen,              "fullscreen"		},
-  { TYPE_STRING, &si.fullscreen_mode,         "fullscreen_mode"		},
+  { TYPE_INTEGER,&si.window_scaling_percent,  "window_scaling_percent"	},
+  { TYPE_STRING, &si.window_scaling_quality,  "window_scaling_quality"	},
+  { TYPE_STRING, &si.screen_rendering_mode,   "screen_rendering_mode"	},
   { TYPE_SWITCH, &si.ask_on_escape,           "ask_on_escape"		},
   { TYPE_SWITCH, &si.ask_on_escape_editor,    "ask_on_escape_editor"	},
   { TYPE_SWITCH, &si.quick_switch,            "quick_player_switch"	},
@@ -9143,48 +8118,29 @@ static struct TokenInfo global_setup_tokens[] =
   { TYPE_SWITCH, &si.prefer_aga_graphics,     "prefer_aga_graphics"	},
   { TYPE_INTEGER,&si.game_frame_delay,        "game_frame_delay"	},
   { TYPE_SWITCH, &si.sp_show_border_elements, "sp_show_border_elements"	},
+  { TYPE_SWITCH, &si.small_game_graphics,     "small_game_graphics"	},
+  { TYPE_SWITCH, &si.show_snapshot_buttons,   "show_snapshot_buttons"	},
   { TYPE_STRING, &si.graphics_set,            "graphics_set"		},
   { TYPE_STRING, &si.sounds_set,              "sounds_set"		},
   { TYPE_STRING, &si.music_set,               "music_set"		},
   { TYPE_SWITCH3,&si.override_level_graphics, "override_level_graphics"	},
   { TYPE_SWITCH3,&si.override_level_sounds,   "override_level_sounds"	},
   { TYPE_SWITCH3,&si.override_level_music,    "override_level_music"	},
+  { TYPE_INTEGER,&si.volume_simple,           "volume_simple"		},
+  { TYPE_INTEGER,&si.volume_loops,            "volume_loops"		},
+  { TYPE_INTEGER,&si.volume_music,            "volume_music"		},
+  { TYPE_STRING, &si.touch.control_type,      "touch.control_type"	},
+  { TYPE_INTEGER,&si.touch.move_distance,     "touch.move_distance"	},
+  { TYPE_INTEGER,&si.touch.drop_distance,     "touch.drop_distance"	},
 };
 
-static boolean not_used = FALSE;
 static struct TokenInfo editor_setup_tokens[] =
 {
-#if 1
-  { TYPE_SWITCH, &not_used,		"editor.el_boulderdash"		},
-  { TYPE_SWITCH, &not_used,		"editor.el_emerald_mine"	},
-  { TYPE_SWITCH, &not_used,		"editor.el_emerald_mine_club"	},
-  { TYPE_SWITCH, &not_used,		"editor.el_more"		},
-  { TYPE_SWITCH, &not_used,		"editor.el_sokoban"		},
-  { TYPE_SWITCH, &not_used,		"editor.el_supaplex"		},
-  { TYPE_SWITCH, &not_used,		"editor.el_diamond_caves"	},
-  { TYPE_SWITCH, &not_used,		"editor.el_dx_boulderdash"	},
-#else
-  { TYPE_SWITCH, &sei.el_boulderdash,	"editor.el_boulderdash"		},
-  { TYPE_SWITCH, &sei.el_emerald_mine,	"editor.el_emerald_mine"	},
-  { TYPE_SWITCH, &sei.el_emerald_mine_club,"editor.el_emerald_mine_club"},
-  { TYPE_SWITCH, &sei.el_more,		"editor.el_more"		},
-  { TYPE_SWITCH, &sei.el_sokoban,	"editor.el_sokoban"		},
-  { TYPE_SWITCH, &sei.el_supaplex,	"editor.el_supaplex"		},
-  { TYPE_SWITCH, &sei.el_diamond_caves,	"editor.el_diamond_caves"	},
-  { TYPE_SWITCH, &sei.el_dx_boulderdash,"editor.el_dx_boulderdash"	},
-#endif
   { TYPE_SWITCH, &sei.el_chars,		"editor.el_chars"		},
   { TYPE_SWITCH, &sei.el_steel_chars,	"editor.el_steel_chars"		},
   { TYPE_SWITCH, &sei.el_custom,	"editor.el_custom"		},
-#if 1
-  { TYPE_SWITCH, &not_used,		"editor.el_headlines"		},
-#else
-  { TYPE_SWITCH, &sei.el_headlines,	"editor.el_headlines"		},
-#endif
   { TYPE_SWITCH, &sei.el_user_defined,	"editor.el_user_defined"	},
   { TYPE_SWITCH, &sei.el_dynamic,	"editor.el_dynamic"		},
-  { TYPE_SWITCH, &sei.el_by_game,	"editor.el_by_game"		},
-  { TYPE_SWITCH, &sei.el_by_type,	"editor.el_by_type"		},
   { TYPE_SWITCH, &sei.show_element_token,"editor.show_element_token"	},
 };
 
@@ -9218,6 +8174,7 @@ static struct TokenInfo shortcut_setup_tokens[] =
   { TYPE_KEY_X11, &ssi.focus_player[3],	"shortcut.focus_player_4"	},
   { TYPE_KEY_X11, &ssi.focus_player_all,"shortcut.focus_player_all"	},
   { TYPE_KEY_X11, &ssi.tape_eject,	"shortcut.tape_eject"		},
+  { TYPE_KEY_X11, &ssi.tape_extra,	"shortcut.tape_extra"		},
   { TYPE_KEY_X11, &ssi.tape_stop,	"shortcut.tape_stop"		},
   { TYPE_KEY_X11, &ssi.tape_pause,	"shortcut.tape_pause"		},
   { TYPE_KEY_X11, &ssi.tape_record,	"shortcut.tape_record"		},
@@ -9253,11 +8210,58 @@ static struct TokenInfo player_setup_tokens[] =
 
 static struct TokenInfo system_setup_tokens[] =
 {
-  { TYPE_STRING,  &syi.sdl_videodriver,	"system.sdl_videodriver"	},
-  { TYPE_STRING,  &syi.sdl_audiodriver,	"system.sdl_audiodriver"	},
+  { TYPE_STRING,  &syi.sdl_videodriver,    "system.sdl_videodriver"	},
+  { TYPE_STRING,  &syi.sdl_audiodriver,	   "system.sdl_audiodriver"	},
   { TYPE_INTEGER, &syi.audio_fragment_size,"system.audio_fragment_size"	},
 };
 
+static struct TokenInfo internal_setup_tokens[] =
+{
+  { TYPE_STRING, &sxi.program_title,		"program_title"		},
+  { TYPE_STRING, &sxi.program_author,		"program_author"	},
+  { TYPE_STRING, &sxi.program_email,		"program_email"		},
+  { TYPE_STRING, &sxi.program_website,		"program_website"	},
+  { TYPE_STRING, &sxi.program_copyright,	"program_copyright"	},
+  { TYPE_STRING, &sxi.program_company,		"program_company"	},
+  { TYPE_STRING, &sxi.program_icon_file,	"program_icon_file"	},
+  { TYPE_STRING, &sxi.default_graphics_set,	"default_graphics_set"	},
+  { TYPE_STRING, &sxi.default_sounds_set,	"default_sounds_set"	},
+  { TYPE_STRING, &sxi.default_music_set,	"default_music_set"	},
+  { TYPE_STRING, &sxi.fallback_graphics_file,	"fallback_graphics_file"},
+  { TYPE_STRING, &sxi.fallback_sounds_file,	"fallback_sounds_file"	},
+  { TYPE_STRING, &sxi.fallback_music_file,	"fallback_music_file"	},
+  { TYPE_STRING, &sxi.default_level_series,	"default_level_series"	},
+  { TYPE_BOOLEAN,&sxi.choose_from_top_leveldir,	"choose_from_top_leveldir" },
+  { TYPE_INTEGER,&sxi.default_window_width,	"default_window_width"	},
+  { TYPE_INTEGER,&sxi.default_window_height,	"default_window_height"	},
+};
+
+static struct TokenInfo debug_setup_tokens[] =
+{
+  { TYPE_INTEGER, &sdi.frame_delay[0],		"debug.frame_delay_0"	},
+  { TYPE_INTEGER, &sdi.frame_delay[1],		"debug.frame_delay_1"	},
+  { TYPE_INTEGER, &sdi.frame_delay[2],		"debug.frame_delay_2"	},
+  { TYPE_INTEGER, &sdi.frame_delay[3],		"debug.frame_delay_3"	},
+  { TYPE_INTEGER, &sdi.frame_delay[4],		"debug.frame_delay_4"	},
+  { TYPE_INTEGER, &sdi.frame_delay[5],		"debug.frame_delay_5"	},
+  { TYPE_INTEGER, &sdi.frame_delay[6],		"debug.frame_delay_6"	},
+  { TYPE_INTEGER, &sdi.frame_delay[7],		"debug.frame_delay_7"	},
+  { TYPE_INTEGER, &sdi.frame_delay[8],		"debug.frame_delay_8"	},
+  { TYPE_INTEGER, &sdi.frame_delay[9],		"debug.frame_delay_9"	},
+  { TYPE_KEY_X11, &sdi.frame_delay_key[0],	"debug.key.frame_delay_0" },
+  { TYPE_KEY_X11, &sdi.frame_delay_key[1],	"debug.key.frame_delay_1" },
+  { TYPE_KEY_X11, &sdi.frame_delay_key[2],	"debug.key.frame_delay_2" },
+  { TYPE_KEY_X11, &sdi.frame_delay_key[3],	"debug.key.frame_delay_3" },
+  { TYPE_KEY_X11, &sdi.frame_delay_key[4],	"debug.key.frame_delay_4" },
+  { TYPE_KEY_X11, &sdi.frame_delay_key[5],	"debug.key.frame_delay_5" },
+  { TYPE_KEY_X11, &sdi.frame_delay_key[6],	"debug.key.frame_delay_6" },
+  { TYPE_KEY_X11, &sdi.frame_delay_key[7],	"debug.key.frame_delay_7" },
+  { TYPE_KEY_X11, &sdi.frame_delay_key[8],	"debug.key.frame_delay_8" },
+  { TYPE_KEY_X11, &sdi.frame_delay_key[9],	"debug.key.frame_delay_9" },
+  { TYPE_BOOLEAN, &sdi.frame_delay_use_mod_key,"debug.frame_delay.use_mod_key"},
+  { TYPE_BOOLEAN, &sdi.frame_delay_game_only,  "debug.frame_delay.game_only" },
+};
+
 static struct TokenInfo options_setup_tokens[] =
 {
   { TYPE_BOOLEAN, &soi.verbose,		"options.verbose"		},
@@ -9291,7 +8295,8 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->toons = TRUE;
   si->scroll_delay = TRUE;
   si->scroll_delay_value = STD_SCROLL_DELAY;
-  si->soft_scrolling = TRUE;
+  si->engine_snapshot_mode = getStringCopy(STR_SNAPSHOT_MODE_DEFAULT);
+  si->engine_snapshot_memory = SNAPSHOT_MEMORY_DEFAULT;
   si->fade_screens = TRUE;
   si->autorecord = TRUE;
   si->show_titlescreen = TRUE;
@@ -9301,7 +8306,9 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->skip_levels = TRUE;
   si->time_limit = TRUE;
   si->fullscreen = FALSE;
-  si->fullscreen_mode = getStringCopy(DEFAULT_FULLSCREEN_MODE);
+  si->window_scaling_percent = STD_WINDOW_SCALING_PERCENT;
+  si->window_scaling_quality = getStringCopy(SCALING_QUALITY_DEFAULT);
+  si->screen_rendering_mode = getStringCopy(STR_SPECIAL_RENDERING_DEFAULT);
   si->ask_on_escape = TRUE;
   si->ask_on_escape_editor = TRUE;
   si->quick_switch = FALSE;
@@ -9309,14 +8316,25 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->prefer_aga_graphics = TRUE;
   si->game_frame_delay = GAME_FRAME_DELAY;
   si->sp_show_border_elements = FALSE;
+  si->small_game_graphics = FALSE;
+  si->show_snapshot_buttons = FALSE;
+
+  si->graphics_set = getStringCopy(GFX_CLASSIC_SUBDIR);
+  si->sounds_set   = getStringCopy(SND_CLASSIC_SUBDIR);
+  si->music_set    = getStringCopy(MUS_CLASSIC_SUBDIR);
 
-  si->graphics_set = getStringCopy(GFX_DEFAULT_SUBDIR);
-  si->sounds_set = getStringCopy(SND_DEFAULT_SUBDIR);
-  si->music_set = getStringCopy(MUS_DEFAULT_SUBDIR);
   si->override_level_graphics = FALSE;
   si->override_level_sounds = FALSE;
   si->override_level_music = FALSE;
 
+  si->volume_simple = 100;		/* percent */
+  si->volume_loops = 100;		/* percent */
+  si->volume_music = 100;		/* percent */
+
+  si->touch.control_type = getStringCopy(TOUCH_CONTROL_DEFAULT);
+  si->touch.move_distance = TOUCH_MOVE_DISTANCE_DEFAULT;	/* percent */
+  si->touch.drop_distance = TOUCH_DROP_DISTANCE_DEFAULT;	/* percent */
+
   si->editor.el_boulderdash		= TRUE;
   si->editor.el_emerald_mine		= TRUE;
   si->editor.el_emerald_mine_club	= TRUE;
@@ -9346,6 +8364,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->shortcut.focus_player_all	= DEFAULT_KEY_FOCUS_PLAYER_ALL;
 
   si->shortcut.tape_eject	= DEFAULT_KEY_TAPE_EJECT;
+  si->shortcut.tape_extra	= DEFAULT_KEY_TAPE_EXTRA;
   si->shortcut.tape_stop	= DEFAULT_KEY_TAPE_STOP;
   si->shortcut.tape_pause	= DEFAULT_KEY_TAPE_PAUSE;
   si->shortcut.tape_record	= DEFAULT_KEY_TAPE_RECORD;
@@ -9384,15 +8403,58 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->system.sdl_audiodriver = getStringCopy(ARG_DEFAULT);
   si->system.audio_fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
 
+  si->internal.program_title     = getStringCopy(PROGRAM_TITLE_STRING);
+  si->internal.program_author    = getStringCopy(PROGRAM_AUTHOR_STRING);
+  si->internal.program_email     = getStringCopy(PROGRAM_EMAIL_STRING);
+  si->internal.program_website   = getStringCopy(PROGRAM_WEBSITE_STRING);
+  si->internal.program_copyright = getStringCopy(PROGRAM_COPYRIGHT_STRING);
+  si->internal.program_company   = getStringCopy(PROGRAM_COMPANY_STRING);
+
+  si->internal.program_icon_file = getStringCopy(PROGRAM_ICON_FILENAME);
+
+  si->internal.default_graphics_set = getStringCopy(GFX_CLASSIC_SUBDIR);
+  si->internal.default_sounds_set   = getStringCopy(SND_CLASSIC_SUBDIR);
+  si->internal.default_music_set    = getStringCopy(MUS_CLASSIC_SUBDIR);
+
+  si->internal.fallback_graphics_file = getStringCopy(UNDEFINED_FILENAME);
+  si->internal.fallback_sounds_file   = getStringCopy(UNDEFINED_FILENAME);
+  si->internal.fallback_music_file    = getStringCopy(UNDEFINED_FILENAME);
+
+  si->internal.default_level_series = getStringCopy(UNDEFINED_LEVELSET);
+  si->internal.choose_from_top_leveldir = FALSE;
+
+  si->internal.default_window_width  = WIN_XSIZE_DEFAULT;
+  si->internal.default_window_height = WIN_YSIZE_DEFAULT;
+
+  si->debug.frame_delay[0] = DEFAULT_FRAME_DELAY_0;
+  si->debug.frame_delay[1] = DEFAULT_FRAME_DELAY_1;
+  si->debug.frame_delay[2] = DEFAULT_FRAME_DELAY_2;
+  si->debug.frame_delay[3] = DEFAULT_FRAME_DELAY_3;
+  si->debug.frame_delay[4] = DEFAULT_FRAME_DELAY_4;
+  si->debug.frame_delay[5] = DEFAULT_FRAME_DELAY_5;
+  si->debug.frame_delay[6] = DEFAULT_FRAME_DELAY_6;
+  si->debug.frame_delay[7] = DEFAULT_FRAME_DELAY_7;
+  si->debug.frame_delay[8] = DEFAULT_FRAME_DELAY_8;
+  si->debug.frame_delay[9] = DEFAULT_FRAME_DELAY_9;
+
+  si->debug.frame_delay_key[0] = DEFAULT_KEY_FRAME_DELAY_0;
+  si->debug.frame_delay_key[1] = DEFAULT_KEY_FRAME_DELAY_1;
+  si->debug.frame_delay_key[2] = DEFAULT_KEY_FRAME_DELAY_2;
+  si->debug.frame_delay_key[3] = DEFAULT_KEY_FRAME_DELAY_3;
+  si->debug.frame_delay_key[4] = DEFAULT_KEY_FRAME_DELAY_4;
+  si->debug.frame_delay_key[5] = DEFAULT_KEY_FRAME_DELAY_5;
+  si->debug.frame_delay_key[6] = DEFAULT_KEY_FRAME_DELAY_6;
+  si->debug.frame_delay_key[7] = DEFAULT_KEY_FRAME_DELAY_7;
+  si->debug.frame_delay_key[8] = DEFAULT_KEY_FRAME_DELAY_8;
+  si->debug.frame_delay_key[9] = DEFAULT_KEY_FRAME_DELAY_9;
+
+  si->debug.frame_delay_use_mod_key = DEFAULT_FRAME_DELAY_USE_MOD_KEY;
+  si->debug.frame_delay_game_only   = DEFAULT_FRAME_DELAY_GAME_ONLY;
+
   si->options.verbose = FALSE;
 
-#if defined(CREATE_SPECIAL_EDITION_RND_JUE)
-  si->toons = FALSE;
-  si->handicap = FALSE;
+#if defined(PLATFORM_ANDROID)
   si->fullscreen = TRUE;
-  si->override_level_graphics = AUTO;
-  si->override_level_sounds = AUTO;
-  si->override_level_music = AUTO;
 #endif
 }
 
@@ -9470,6 +8532,20 @@ static void decodeSetupFileHash(SetupFileHash *setup_file_hash)
 		 getHashEntry(setup_file_hash, system_setup_tokens[i].text));
   setup.system = syi;
 
+  /* internal setup */
+  sxi = setup.internal;
+  for (i = 0; i < NUM_INTERNAL_SETUP_TOKENS; i++)
+    setSetupInfo(internal_setup_tokens, i,
+		 getHashEntry(setup_file_hash, internal_setup_tokens[i].text));
+  setup.internal = sxi;
+
+  /* debug setup */
+  sdi = setup.debug;
+  for (i = 0; i < NUM_DEBUG_SETUP_TOKENS; i++)
+    setSetupInfo(debug_setup_tokens, i,
+		 getHashEntry(setup_file_hash, debug_setup_tokens[i].text));
+  setup.debug = sdi;
+
   /* options setup */
   soi = setup.options;
   for (i = 0; i < NUM_OPTIONS_SETUP_TOKENS; i++)
@@ -9494,43 +8570,62 @@ static void decodeSetupFileHash_EditorCascade(SetupFileHash *setup_file_hash)
   setup.editor_cascade = seci;
 }
 
-void LoadSetup()
+void LoadSetupFromFilename(char *filename)
 {
-  char *filename = getSetupFilename();
-  SetupFileHash *setup_file_hash = NULL;
-
-  /* always start with reliable default values */
-  setSetupInfoToDefaults(&setup);
-
-  setup_file_hash = loadSetupFileHash(filename);
+  SetupFileHash *setup_file_hash = loadSetupFileHash(filename);
 
   if (setup_file_hash)
   {
-    char *player_name_new;
-
-    checkSetupFileHashIdentifier(setup_file_hash, filename,getCookie("SETUP"));
     decodeSetupFileHash(setup_file_hash);
 
     freeSetupFileHash(setup_file_hash);
+  }
+  else
+  {
+    Error(ERR_WARN, "using default setup values");
+  }
+}
 
-    /* needed to work around problems with fixed length strings */
-    player_name_new = get_corrected_login_name(setup.player_name);
-    free(setup.player_name);
-    setup.player_name = player_name_new;
+static void LoadSetup_SpecialPostProcessing()
+{
+  char *player_name_new;
 
-    /* "scroll_delay: on(3) / off(0)" was replaced by scroll delay value */
-    if (setup.scroll_delay == FALSE)
-    {
-      setup.scroll_delay_value = MIN_SCROLL_DELAY;
-      setup.scroll_delay = TRUE;			/* now always "on" */
-    }
+  /* needed to work around problems with fixed length strings */
+  player_name_new = get_corrected_login_name(setup.player_name);
+  free(setup.player_name);
+  setup.player_name = player_name_new;
 
-    /* make sure that scroll delay value stays inside valid range */
-    setup.scroll_delay_value =
-      MIN(MAX(MIN_SCROLL_DELAY, setup.scroll_delay_value), MAX_SCROLL_DELAY);
+  /* "scroll_delay: on(3) / off(0)" was replaced by scroll delay value */
+  if (setup.scroll_delay == FALSE)
+  {
+    setup.scroll_delay_value = MIN_SCROLL_DELAY;
+    setup.scroll_delay = TRUE;			/* now always "on" */
   }
-  else
-    Error(ERR_WARN, "using default setup values");
+
+  /* make sure that scroll delay value stays inside valid range */
+  setup.scroll_delay_value =
+    MIN(MAX(MIN_SCROLL_DELAY, setup.scroll_delay_value), MAX_SCROLL_DELAY);
+}
+
+void LoadSetup()
+{
+  char *filename;
+
+  /* always start with reliable default values */
+  setSetupInfoToDefaults(&setup);
+
+  /* try to load setup values from default setup file */
+  filename = getDefaultSetupFilename();
+
+  if (fileExists(filename))
+    LoadSetupFromFilename(filename);
+
+  /* try to load setup values from user setup file */
+  filename = getSetupFilename();
+
+  LoadSetupFromFilename(filename);
+
+  LoadSetup_SpecialPostProcessing();
 }
 
 void LoadSetup_EditorCascade()
@@ -9545,7 +8640,6 @@ void LoadSetup_EditorCascade()
 
   if (setup_file_hash)
   {
-    checkSetupFileHashIdentifier(setup_file_hash, filename,getCookie("SETUP"));
     decodeSetupFileHash_EditorCascade(setup_file_hash);
 
     freeSetupFileHash(setup_file_hash);
@@ -9568,9 +8662,7 @@ void SaveSetup()
     return;
   }
 
-  fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER,
-					       getCookie("SETUP")));
-  fprintf(file, "\n");
+  fprintFileHeader(file, SETUP_FILENAME);
 
   /* global setup */
   si = setup;
@@ -9578,7 +8670,9 @@ void SaveSetup()
   {
     /* just to make things nicer :) */
     if (i == SETUP_TOKEN_PLAYER_NAME + 1 ||
-	i == SETUP_TOKEN_GRAPHICS_SET)
+	i == SETUP_TOKEN_GRAPHICS_SET ||
+	i == SETUP_TOKEN_VOLUME_SIMPLE ||
+	i == SETUP_TOKEN_TOUCH_CONTROL_TYPE)
       fprintf(file, "\n");
 
     fprintf(file, "%s\n", getSetupLine(global_setup_tokens, "", i));
@@ -9615,6 +8709,15 @@ void SaveSetup()
   for (i = 0; i < NUM_SYSTEM_SETUP_TOKENS; i++)
     fprintf(file, "%s\n", getSetupLine(system_setup_tokens, "", i));
 
+  /* internal setup */
+  /* (internal setup values not saved to user setup file) */
+
+  /* debug setup */
+  sdi = setup.debug;
+  fprintf(file, "\n");
+  for (i = 0; i < NUM_DEBUG_SETUP_TOKENS; i++)
+    fprintf(file, "%s\n", getSetupLine(debug_setup_tokens, "", i));
+
   /* options setup */
   soi = setup.options;
   fprintf(file, "\n");
@@ -9641,12 +8744,9 @@ void SaveSetup_EditorCascade()
     return;
   }
 
-  fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER,
-					       getCookie("SETUP")));
-  fprintf(file, "\n");
+  fprintFileHeader(file, EDITORCASCADE_FILENAME);
 
   seci = setup.editor_cascade;
-  fprintf(file, "\n");
   for (i = 0; i < NUM_EDITOR_CASCADE_SETUP_TOKENS; i++)
     fprintf(file, "%s\n", getSetupLine(editor_cascade_setup_tokens, "", i));
 
@@ -9691,19 +8791,10 @@ void LoadCustomElementDescriptions()
 
 static int getElementFromToken(char *token)
 {
-#if 1
   char *value = getHashEntry(element_token_hash, token);
 
   if (value != NULL)
     return atoi(value);
-#else
-  int i;
-
-  /* !!! OPTIMIZE THIS BY USING HASH !!! */
-  for (i = 0; i < MAX_NUM_ELEMENTS; i++)
-    if (strEqual(token, element_info[i].token_name))
-      return i;
-#endif
 
   Error(ERR_WARN, "unknown element token '%s'", token);
 
@@ -9721,25 +8812,8 @@ static int get_token_parameter_value(char *token, char *value_raw)
   if (suffix == NULL)
     suffix = token;
 
-#if 1
   if (strEqual(suffix, ".element"))
     return getElementFromToken(value_raw);
-#endif
-
-#if 0
-  if (strncmp(suffix, ".font", 5) == 0)
-  {
-    int i;
-
-    /* !!! OPTIMIZE THIS BY USING HASH !!! */
-    for (i = 0; i < NUM_FONTS; i++)
-      if (strEqual(value_raw, font_info[i].token_name))
-	return i;
-
-    /* if font not found, use reliable default value */
-    return FONT_INITIAL_1;
-  }
-#endif
 
   /* !!! USE CORRECT VALUE TYPE (currently works also for TYPE_BOOLEAN) !!! */
   return get_parameter_value(value_raw, suffix, TYPE_INTEGER);
@@ -9747,24 +8821,8 @@ static int get_token_parameter_value(char *token, char *value_raw)
 
 void InitMenuDesignSettings_Static()
 {
-#if 0
-  static SetupFileHash *image_config_hash = NULL;
-#endif
   int i;
 
-#if 0
-  if (image_config_hash == NULL)
-  {
-    image_config_hash = newSetupFileHash();
-
-    for (i = 0; image_config[i].token != NULL; i++)
-      setHashEntry(image_config_hash,
-		   image_config[i].token,
-		   image_config[i].value);
-  }
-#endif
-
-#if 1
   /* always start with reliable default values from static default config */
   for (i = 0; image_config_vars[i].token != NULL; i++)
   {
@@ -9774,19 +8832,6 @@ void InitMenuDesignSettings_Static()
       *image_config_vars[i].value =
 	get_token_parameter_value(image_config_vars[i].token, value);
   }
-
-#else
-
-  int j;
-
-  /* always start with reliable default values from static default config */
-  for (i = 0; image_config_vars[i].token != NULL; i++)
-    for (j = 0; image_config[j].token != NULL; j++)
-      if (strEqual(image_config_vars[i].token, image_config[j].token))
-	*image_config_vars[i].value =
-	  get_token_parameter_value(image_config_vars[i].token,
-				    image_config[j].value);
-#endif
 }
 
 static void InitMenuDesignSettings_SpecialPreProcessing()
@@ -9797,6 +8842,39 @@ static void InitMenuDesignSettings_SpecialPreProcessing()
 
   /* special case: initialize "ARG_DEFAULT" values in static default config */
   /* (e.g., initialize "[titlemessage].fade_mode" from "[title].fade_mode") */
+  titlescreen_initial_first_default.fade_mode  =
+    title_initial_first_default.fade_mode;
+  titlescreen_initial_first_default.fade_delay =
+    title_initial_first_default.fade_delay;
+  titlescreen_initial_first_default.post_delay =
+    title_initial_first_default.post_delay;
+  titlescreen_initial_first_default.auto_delay =
+    title_initial_first_default.auto_delay;
+  titlescreen_first_default.fade_mode  = title_first_default.fade_mode;
+  titlescreen_first_default.fade_delay = title_first_default.fade_delay;
+  titlescreen_first_default.post_delay = title_first_default.post_delay;
+  titlescreen_first_default.auto_delay = title_first_default.auto_delay;
+  titlemessage_initial_first_default.fade_mode  =
+    title_initial_first_default.fade_mode;
+  titlemessage_initial_first_default.fade_delay =
+    title_initial_first_default.fade_delay;
+  titlemessage_initial_first_default.post_delay =
+    title_initial_first_default.post_delay;
+  titlemessage_initial_first_default.auto_delay =
+    title_initial_first_default.auto_delay;
+  titlemessage_first_default.fade_mode  = title_first_default.fade_mode;
+  titlemessage_first_default.fade_delay = title_first_default.fade_delay;
+  titlemessage_first_default.post_delay = title_first_default.post_delay;
+  titlemessage_first_default.auto_delay = title_first_default.auto_delay;
+
+  titlescreen_initial_default.fade_mode  = title_initial_default.fade_mode;
+  titlescreen_initial_default.fade_delay = title_initial_default.fade_delay;
+  titlescreen_initial_default.post_delay = title_initial_default.post_delay;
+  titlescreen_initial_default.auto_delay = title_initial_default.auto_delay;
+  titlescreen_default.fade_mode  = title_default.fade_mode;
+  titlescreen_default.fade_delay = title_default.fade_delay;
+  titlescreen_default.post_delay = title_default.post_delay;
+  titlescreen_default.auto_delay = title_default.auto_delay;
   titlemessage_initial_default.fade_mode  = title_initial_default.fade_mode;
   titlemessage_initial_default.fade_delay = title_initial_default.fade_delay;
   titlemessage_initial_default.post_delay = title_initial_default.post_delay;
@@ -9810,6 +8888,13 @@ static void InitMenuDesignSettings_SpecialPreProcessing()
   /* (e.g., init "titlemessage_1.fade_mode" from "[titlemessage].fade_mode") */
   for (i = 0; i < MAX_NUM_TITLE_MESSAGES; i++)
   {
+    titlescreen_initial_first[i] = titlescreen_initial_first_default;
+    titlescreen_first[i] = titlescreen_first_default;
+    titlemessage_initial_first[i] = titlemessage_initial_first_default;
+    titlemessage_first[i] = titlemessage_first_default;
+
+    titlescreen_initial[i] = titlescreen_initial_default;
+    titlescreen[i] = titlescreen_default;
     titlemessage_initial[i] = titlemessage_initial_default;
     titlemessage[i] = titlemessage_default;
   }
@@ -9818,31 +8903,112 @@ static void InitMenuDesignSettings_SpecialPreProcessing()
   /* (eg, init "menu.enter_screen.SCORES.xyz" from "menu.enter_screen.xyz") */
   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
   {
+    if (i == GFX_SPECIAL_ARG_TITLE)	/* title values already initialized */
+      continue;
+
     menu.enter_screen[i] = menu.enter_screen[GFX_SPECIAL_ARG_DEFAULT];
     menu.leave_screen[i] = menu.leave_screen[GFX_SPECIAL_ARG_DEFAULT];
+    menu.next_screen[i]  = menu.next_screen[GFX_SPECIAL_ARG_DEFAULT];
   }
 
   /* special case: initialize "ARG_DEFAULT" values in static default config */
   /* (eg, init "viewport.door_1.MAIN.xyz" from "viewport.door_1.xyz") */
   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
   {
+    viewport.window[i]    = viewport.window[GFX_SPECIAL_ARG_DEFAULT];
     viewport.playfield[i] = viewport.playfield[GFX_SPECIAL_ARG_DEFAULT];
-    viewport.door_1[i] = viewport.door_1[GFX_SPECIAL_ARG_DEFAULT];
-    if (i != GFX_SPECIAL_ARG_EDITOR)	/* editor value already initialized */
-      viewport.door_2[i] = viewport.door_2[GFX_SPECIAL_ARG_DEFAULT];
+    viewport.door_1[i]    = viewport.door_1[GFX_SPECIAL_ARG_DEFAULT];
+
+    if (i == GFX_SPECIAL_ARG_EDITOR)	/* editor values already initialized */
+      continue;
+
+    viewport.door_2[i] = viewport.door_2[GFX_SPECIAL_ARG_DEFAULT];
   }
 }
 
 static void InitMenuDesignSettings_SpecialPostProcessing()
 {
+  static struct
+  {
+    struct XY *dst, *src;
+  }
+  game_buttons_xy[] =
+  {
+    { &game.button.save,	&game.button.stop	},
+    { &game.button.pause2,	&game.button.pause	},
+    { &game.button.load,	&game.button.play	},
+    { &game.button.undo,	&game.button.stop	},
+    { &game.button.redo,	&game.button.play	},
+
+    { NULL,			NULL			}
+  };
+  int i;
+
   /* special case: initialize later added SETUP list size from LEVELS value */
   if (menu.list_size[GAME_MODE_SETUP] == -1)
     menu.list_size[GAME_MODE_SETUP] = menu.list_size[GAME_MODE_LEVELS];
+
+  /* set default position for snapshot buttons to stop/pause/play buttons */
+  for (i = 0; game_buttons_xy[i].dst != NULL; i++)
+    if ((*game_buttons_xy[i].dst).x == -1 &&
+	(*game_buttons_xy[i].dst).y == -1)
+      *game_buttons_xy[i].dst = *game_buttons_xy[i].src;
+}
+
+static void InitMenuDesignSettings_SpecialPostProcessing_AfterGraphics()
+{
+  static struct
+  {
+    struct XYTileSize *dst, *src;
+    int graphic;
+  }
+  editor_buttons_xy[] =
+  {
+    {
+      &editor.button.element_left,	&editor.palette.element_left,
+      IMG_GFX_EDITOR_BUTTON_ELEMENT_LEFT
+    },
+    {
+      &editor.button.element_middle,	&editor.palette.element_middle,
+      IMG_GFX_EDITOR_BUTTON_ELEMENT_MIDDLE
+    },
+    {
+      &editor.button.element_right,	&editor.palette.element_right,
+      IMG_GFX_EDITOR_BUTTON_ELEMENT_RIGHT
+    },
+
+    { NULL,			NULL			}
+  };
+  int i;
+
+  /* set default position for element buttons to element graphics */
+  for (i = 0; editor_buttons_xy[i].dst != NULL; i++)
+  {
+    if ((*editor_buttons_xy[i].dst).x == -1 &&
+	(*editor_buttons_xy[i].dst).y == -1)
+    {
+      struct GraphicInfo *gd = &graphic_info[editor_buttons_xy[i].graphic];
+
+      gd->width = gd->height = editor_buttons_xy[i].src->tile_size;
+
+      *editor_buttons_xy[i].dst = *editor_buttons_xy[i].src;
+    }
+  }
 }
 
 static void LoadMenuDesignSettingsFromFilename(char *filename)
 {
+  static struct TitleFadingInfo tfi;
   static struct TitleMessageInfo tmi;
+  static struct TokenInfo title_tokens[] =
+  {
+    { TYPE_INTEGER,	&tfi.fade_mode,		".fade_mode"		},
+    { TYPE_INTEGER,	&tfi.fade_delay,	".fade_delay"		},
+    { TYPE_INTEGER,	&tfi.post_delay,	".post_delay"		},
+    { TYPE_INTEGER,	&tfi.auto_delay,	".auto_delay"		},
+
+    { -1,		NULL,			NULL			}
+  };
   static struct TokenInfo titlemessage_tokens[] =
   {
     { TYPE_INTEGER,	&tmi.x,			".x"			},
@@ -9867,11 +9033,59 @@ static void LoadMenuDesignSettingsFromFilename(char *filename)
   };
   static struct
   {
+    struct TitleFadingInfo *info;
+    char *text;
+  }
+  title_info[] =
+  {
+    /* initialize first titles from "enter screen" definitions, if defined */
+    { &title_initial_first_default,	"menu.enter_screen.TITLE"	},
+    { &title_first_default,		"menu.enter_screen.TITLE"	},
+
+    /* initialize title screens from "next screen" definitions, if defined */
+    { &title_initial_default,		"menu.next_screen.TITLE"	},
+    { &title_default,			"menu.next_screen.TITLE"	},
+
+    { NULL,				NULL				}
+  };
+  static struct
+  {
     struct TitleMessageInfo *array;
     char *text;
   }
   titlemessage_arrays[] =
   {
+    /* initialize first titles from "enter screen" definitions, if defined */
+    { titlescreen_initial_first,	"menu.enter_screen.TITLE"	},
+    { titlescreen_first,		"menu.enter_screen.TITLE"	},
+    { titlemessage_initial_first,	"menu.enter_screen.TITLE"	},
+    { titlemessage_first,		"menu.enter_screen.TITLE"	},
+
+    /* initialize titles from "next screen" definitions, if defined */
+    { titlescreen_initial,		"menu.next_screen.TITLE"	},
+    { titlescreen,			"menu.next_screen.TITLE"	},
+    { titlemessage_initial,		"menu.next_screen.TITLE"	},
+    { titlemessage,			"menu.next_screen.TITLE"	},
+
+    /* overwrite titles with title definitions, if defined */
+    { titlescreen_initial_first,	"[title_initial]"		},
+    { titlescreen_first,		"[title]"			},
+    { titlemessage_initial_first,	"[title_initial]"		},
+    { titlemessage_first,		"[title]"			},
+
+    { titlescreen_initial,		"[title_initial]"		},
+    { titlescreen,			"[title]"			},
+    { titlemessage_initial,		"[title_initial]"		},
+    { titlemessage,			"[title]"			},
+
+    /* overwrite titles with title screen/message definitions, if defined */
+    { titlescreen_initial_first,	"[titlescreen_initial]"		},
+    { titlescreen_first,		"[titlescreen]"			},
+    { titlemessage_initial_first,	"[titlemessage_initial]"	},
+    { titlemessage_first,		"[titlemessage]"		},
+
+    { titlescreen_initial,		"[titlescreen_initial]"		},
+    { titlescreen,			"[titlescreen]"			},
     { titlemessage_initial,		"[titlemessage_initial]"	},
     { titlemessage,			"[titlemessage]"		},
 
@@ -9880,10 +9094,6 @@ static void LoadMenuDesignSettingsFromFilename(char *filename)
   SetupFileHash *setup_file_hash;
   int i, j, k;
 
-#if 0
-  printf("LoadMenuDesignSettings from file '%s' ...\n", filename);
-#endif
-
   if ((setup_file_hash = loadSetupFileHash(filename)) == NULL)
     return;
 
@@ -9916,6 +9126,14 @@ static void LoadMenuDesignSettingsFromFilename(char *filename)
       menu.draw_xoffset_info[i] = get_integer_from_string(value_1);
     if (value_2 != NULL)
       menu.draw_yoffset_info[i] = get_integer_from_string(value_2);
+
+    if (i == GFX_SPECIAL_ARG_INFO_ELEMENTS)
+    {
+      char *value_1 = getHashEntry(setup_file_hash, "menu.list_size.INFO");
+
+      if (value_1 != NULL)
+	menu.list_size_info[i] = get_integer_from_string(value_1);
+    }
   }
 
   /* special case: initialize with default values that may be overwritten */
@@ -9941,12 +9159,18 @@ static void LoadMenuDesignSettingsFromFilename(char *filename)
     char *token_4 = "menu.leave_screen.fade_mode";
     char *token_5 = "menu.leave_screen.fade_delay";
     char *token_6 = "menu.leave_screen.post_delay";
+    char *token_7 = "menu.next_screen.fade_mode";
+    char *token_8 = "menu.next_screen.fade_delay";
+    char *token_9 = "menu.next_screen.post_delay";
     char *value_1 = getHashEntry(setup_file_hash, token_1);
     char *value_2 = getHashEntry(setup_file_hash, token_2);
     char *value_3 = getHashEntry(setup_file_hash, token_3);
     char *value_4 = getHashEntry(setup_file_hash, token_4);
     char *value_5 = getHashEntry(setup_file_hash, token_5);
     char *value_6 = getHashEntry(setup_file_hash, token_6);
+    char *value_7 = getHashEntry(setup_file_hash, token_7);
+    char *value_8 = getHashEntry(setup_file_hash, token_8);
+    char *value_9 = getHashEntry(setup_file_hash, token_9);
 
     if (value_1 != NULL)
       menu.enter_screen[i].fade_mode = get_token_parameter_value(token_1,
@@ -9966,50 +9190,122 @@ static void LoadMenuDesignSettingsFromFilename(char *filename)
     if (value_6 != NULL)
       menu.leave_screen[i].post_delay = get_token_parameter_value(token_6,
 								  value_6);
+    if (value_7 != NULL)
+      menu.next_screen[i].fade_mode = get_token_parameter_value(token_7,
+								value_7);
+    if (value_8 != NULL)
+      menu.next_screen[i].fade_delay = get_token_parameter_value(token_8,
+								 value_8);
+    if (value_9 != NULL)
+      menu.next_screen[i].post_delay = get_token_parameter_value(token_9,
+								 value_9);
   }
 
   /* special case: initialize with default values that may be overwritten */
   /* (eg, init "viewport.door_1.MAIN.xyz" from "viewport.door_1.xyz") */
   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
   {
-    char *token_1 = "viewport.playfield.x";
-    char *token_2 = "viewport.playfield.y";
-    char *token_3 = "viewport.playfield.width";
-    char *token_4 = "viewport.playfield.height";
-    char *token_5 = "viewport.playfield.border_size";
-    char *token_6 = "viewport.door_1.x";
-    char *token_7 = "viewport.door_1.y";
-    char *token_8 = "viewport.door_2.x";
-    char *token_9 = "viewport.door_2.y";
-    char *value_1 = getHashEntry(setup_file_hash, token_1);
-    char *value_2 = getHashEntry(setup_file_hash, token_2);
-    char *value_3 = getHashEntry(setup_file_hash, token_3);
-    char *value_4 = getHashEntry(setup_file_hash, token_4);
-    char *value_5 = getHashEntry(setup_file_hash, token_5);
-    char *value_6 = getHashEntry(setup_file_hash, token_6);
-    char *value_7 = getHashEntry(setup_file_hash, token_7);
-    char *value_8 = getHashEntry(setup_file_hash, token_8);
-    char *value_9 = getHashEntry(setup_file_hash, token_9);
+    char *token_w1 = "viewport.window.width";
+    char *token_w2 = "viewport.window.height";
+    char *token_01 = "viewport.playfield.x";
+    char *token_02 = "viewport.playfield.y";
+    char *token_03 = "viewport.playfield.width";
+    char *token_04 = "viewport.playfield.height";
+    char *token_05 = "viewport.playfield.border_size";
+    char *token_06 = "viewport.door_1.x";
+    char *token_07 = "viewport.door_1.y";
+    char *token_08 = "viewport.door_1.width";
+    char *token_09 = "viewport.door_1.height";
+    char *token_10 = "viewport.door_1.border_size";
+    char *token_11 = "viewport.door_2.x";
+    char *token_12 = "viewport.door_2.y";
+    char *token_13 = "viewport.door_2.width";
+    char *token_14 = "viewport.door_2.height";
+    char *token_15 = "viewport.door_2.border_size";
+    char *value_w1 = getHashEntry(setup_file_hash, token_w1);
+    char *value_w2 = getHashEntry(setup_file_hash, token_w2);
+    char *value_01 = getHashEntry(setup_file_hash, token_01);
+    char *value_02 = getHashEntry(setup_file_hash, token_02);
+    char *value_03 = getHashEntry(setup_file_hash, token_03);
+    char *value_04 = getHashEntry(setup_file_hash, token_04);
+    char *value_05 = getHashEntry(setup_file_hash, token_05);
+    char *value_06 = getHashEntry(setup_file_hash, token_06);
+    char *value_07 = getHashEntry(setup_file_hash, token_07);
+    char *value_08 = getHashEntry(setup_file_hash, token_08);
+    char *value_09 = getHashEntry(setup_file_hash, token_09);
+    char *value_10 = getHashEntry(setup_file_hash, token_10);
+    char *value_11 = getHashEntry(setup_file_hash, token_11);
+    char *value_12 = getHashEntry(setup_file_hash, token_12);
+    char *value_13 = getHashEntry(setup_file_hash, token_13);
+    char *value_14 = getHashEntry(setup_file_hash, token_14);
+    char *value_15 = getHashEntry(setup_file_hash, token_15);
+
+    if (value_w1 != NULL)
+      viewport.window[i].width = get_token_parameter_value(token_w1, value_w1);
+    if (value_w2 != NULL)
+      viewport.window[i].height = get_token_parameter_value(token_w2, value_w2);
+    if (value_01 != NULL)
+      viewport.playfield[i].x = get_token_parameter_value(token_01, value_01);
+    if (value_02 != NULL)
+      viewport.playfield[i].y = get_token_parameter_value(token_02, value_02);
+    if (value_03 != NULL)
+      viewport.playfield[i].width = get_token_parameter_value(token_03,
+							      value_03);
+    if (value_04 != NULL)
+      viewport.playfield[i].height = get_token_parameter_value(token_04,
+							       value_04);
+    if (value_05 != NULL)
+      viewport.playfield[i].border_size = get_token_parameter_value(token_05,
+								    value_05);
+    if (value_06 != NULL)
+      viewport.door_1[i].x = get_token_parameter_value(token_06, value_06);
+    if (value_07 != NULL)
+      viewport.door_1[i].y = get_token_parameter_value(token_07, value_07);
+    if (value_08 != NULL)
+      viewport.door_1[i].width = get_token_parameter_value(token_08, value_08);
+    if (value_09 != NULL)
+      viewport.door_1[i].height = get_token_parameter_value(token_09, value_09);
+    if (value_10 != NULL)
+      viewport.door_1[i].border_size = get_token_parameter_value(token_10,
+								 value_10);
+    if (value_11 != NULL)
+      viewport.door_2[i].x = get_token_parameter_value(token_11, value_11);
+    if (value_12 != NULL)
+      viewport.door_2[i].y = get_token_parameter_value(token_12, value_12);
+    if (value_13 != NULL)
+      viewport.door_2[i].width = get_token_parameter_value(token_13, value_13);
+    if (value_14 != NULL)
+      viewport.door_2[i].height = get_token_parameter_value(token_14, value_14);
+    if (value_15 != NULL)
+      viewport.door_1[i].border_size = get_token_parameter_value(token_15,
+								 value_15);
+  }
 
-    if (value_1 != NULL)
-      viewport.playfield[i].x = get_token_parameter_value(token_1, value_1);
-    if (value_2 != NULL)
-      viewport.playfield[i].y = get_token_parameter_value(token_2, value_2);
-    if (value_3 != NULL)
-      viewport.playfield[i].width = get_token_parameter_value(token_3, value_3);
-    if (value_4 != NULL)
-      viewport.playfield[i].height = get_token_parameter_value(token_4,value_4);
-    if (value_5 != NULL)
-      viewport.playfield[i].border_size = get_token_parameter_value(token_5,
-								    value_5);
-    if (value_6 != NULL)
-      viewport.door_1[i].x = get_token_parameter_value(token_6, value_6);
-    if (value_7 != NULL)
-      viewport.door_1[i].y = get_token_parameter_value(token_7, value_7);
-    if (value_8 != NULL)
-      viewport.door_2[i].x = get_token_parameter_value(token_8, value_8);
-    if (value_9 != NULL)
-      viewport.door_2[i].y = get_token_parameter_value(token_9, value_9);
+  /* special case: initialize with default values that may be overwritten */
+  /* (e.g., init "[title].fade_mode" from "menu.next_screen.TITLE.fade_mode") */
+  for (i = 0; title_info[i].info != NULL; i++)
+  {
+    struct TitleFadingInfo *info = title_info[i].info;
+    char *base_token = title_info[i].text;
+
+    for (j = 0; title_tokens[j].type != -1; j++)
+    {
+      char *token = getStringCat2(base_token, title_tokens[j].text);
+      char *value = getHashEntry(setup_file_hash, token);
+
+      if (value != NULL)
+      {
+	int parameter_value = get_token_parameter_value(token, value);
+
+	tfi = *info;
+
+	*(int *)title_tokens[j].value = (int)parameter_value;
+
+	*info = tfi;
+      }
+
+      free(token);
+    }
   }
 
   /* special case: initialize with default values that may be overwritten */
@@ -10033,9 +9329,9 @@ static void LoadMenuDesignSettingsFromFilename(char *filename)
 	  tmi = array[k];
 
 	  if (titlemessage_tokens[j].type == TYPE_INTEGER)
-	    *(boolean *)titlemessage_tokens[j].value = (boolean)parameter_value;
-	  else
 	    *(int     *)titlemessage_tokens[j].value = (int)parameter_value;
+	  else
+	    *(boolean *)titlemessage_tokens[j].value = (boolean)parameter_value;
 
 	  array[k] = tmi;
 	}
@@ -10066,11 +9362,7 @@ void LoadMenuDesignSettings()
   InitMenuDesignSettings_Static();
   InitMenuDesignSettings_SpecialPreProcessing();
 
-#if 1
   if (!GFX_OVERRIDE_ARTWORK(ARTWORK_TYPE_GRAPHICS))
-#else
-  if (!SETUP_OVERRIDE_ARTWORK(setup, ARTWORK_TYPE_GRAPHICS))
-#endif
   {
     /* first look for special settings configured in level series config */
     filename_base = getCustomArtworkLevelConfigFilename(ARTWORK_TYPE_GRAPHICS);
@@ -10087,6 +9379,11 @@ void LoadMenuDesignSettings()
   InitMenuDesignSettings_SpecialPostProcessing();
 }
 
+void LoadMenuDesignSettings_AfterGraphics()
+{
+  InitMenuDesignSettings_SpecialPostProcessing_AfterGraphics();
+}
+
 void LoadUserDefinedEditorElementList(int **elements, int *num_elements)
 {
   char *filename = getEditorSetupFilename();
@@ -10209,10 +9506,6 @@ static struct MusicFileInfo *get_music_file_info_ext(char *basename, int music,
     *strrchr(filename_prefix, '.') = '\0';
   filename_info = getStringCat2(filename_prefix, ".txt");
 
-#if 0
-  printf("trying to load file '%s'...\n", filename_info);
-#endif
-
   if (fileExists(filename_info))
     setup_file_hash = loadSetupFileHash(filename_info);
 
@@ -10226,10 +9519,6 @@ static struct MusicFileInfo *get_music_file_info_ext(char *basename, int music,
     filename_prefix = getStringCopy(filename_music);
     filename_info = getStringCat2(filename_prefix, ".txt");
 
-#if 0
-    printf("trying to load file '%s'...\n", filename_info);
-#endif
-
     if (fileExists(filename_info))
       setup_file_hash = loadSetupFileHash(filename_info);
 
@@ -10298,8 +9587,8 @@ void LoadMusicInfo()
   int num_music = getMusicListSize();
   int num_music_noconf = 0;
   int num_sounds = getSoundListSize();
-  DIR *dir;
-  struct dirent *dir_entry;
+  Directory *dir;
+  DirectoryEntry *dir_entry;
   struct FileInfo *music, *sound;
   struct MusicFileInfo *next, **new;
   int i;
@@ -10341,31 +9630,24 @@ void LoadMusicInfo()
     if (!FileIsMusic(music->filename))
       continue;
 
-#if 0
-    printf("::: -> '%s' (configured)\n", music->filename);
-#endif
-
     if (!music_info_listed(music_file_info, music->filename))
     {
       *new = get_music_file_info(music->filename, i);
-#if 0
-      if (*new != NULL)
-	printf(":1: adding '%s' ['%s'] ...\n", (*new)->title, music->filename);
-#endif
+
       if (*new != NULL)
 	new = &(*new)->next;
     }
   }
 
-  if ((dir = opendir(music_directory)) == NULL)
+  if ((dir = openDirectory(music_directory)) == NULL)
   {
     Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
     return;
   }
 
-  while ((dir_entry = readdir(dir)) != NULL)	/* loop until last dir entry */
+  while ((dir_entry = readDirectory(dir)) != NULL)	/* loop all entries */
   {
-    char *basename = dir_entry->d_name;
+    char *basename = dir_entry->basename;
     boolean music_already_used = FALSE;
     int i;
 
@@ -10387,20 +9669,13 @@ void LoadMusicInfo()
     if (music_already_used)
       continue;
 
-    if (!FileIsMusic(basename))
+    if (!FileIsMusic(dir_entry->filename))
       continue;
 
-#if 0
-    printf("::: -> '%s' (found in directory)\n", basename);
-#endif
-
     if (!music_info_listed(music_file_info, basename))
     {
       *new = get_music_file_info(basename, MAP_NOCONF_MUSIC(num_music_noconf));
-#if 0
-      if (*new != NULL)
-	printf(":2: adding '%s' ['%s'] ...\n", (*new)->title, basename);
-#endif
+
       if (*new != NULL)
 	new = &(*new)->next;
     }
@@ -10408,7 +9683,7 @@ void LoadMusicInfo()
     num_music_noconf++;
   }
 
-  closedir(dir);
+  closeDirectory(dir);
 
   for (i = 0; i < num_sounds; i++)
   {
@@ -10424,10 +9699,6 @@ void LoadMusicInfo()
     if (!FileIsSound(sound->filename))
       continue;
 
-#if 0
-    printf("::: -> '%s' (configured)\n", sound->filename);
-#endif
-
     if (!sound_info_listed(music_file_info, sound->filename))
     {
       *new = get_sound_file_info(sound->filename, i);
@@ -10435,11 +9706,6 @@ void LoadMusicInfo()
 	new = &(*new)->next;
     }
   }
-
-#if 0
-  for (next = music_file_info; next != NULL; next = next->next)
-    printf("::: title == '%s'\n", next->title);
-#endif
 }
 
 void add_helpanim_entry(int element, int action, int direction, int delay,
@@ -10755,15 +10021,15 @@ void ConvertLevels()
 
   convert_level_nr = convert_leveldir->first_level;
 
-  printf_line("=", 79);
-  printf("Converting levels\n");
-  printf_line("-", 79);
-  printf("Level series identifier: '%s'\n", convert_leveldir->identifier);
-  printf("Level series name:       '%s'\n", convert_leveldir->name);
-  printf("Level series author:     '%s'\n", convert_leveldir->author);
-  printf("Number of levels:        %d\n",   convert_leveldir->levels);
-  printf_line("=", 79);
-  printf("\n");
+  PrintLine("=", 79);
+  Print("Converting levels\n");
+  PrintLine("-", 79);
+  Print("Level series identifier: '%s'\n", convert_leveldir->identifier);
+  Print("Level series name:       '%s'\n", convert_leveldir->name);
+  Print("Level series author:     '%s'\n", convert_leveldir->author);
+  Print("Number of levels:        %d\n",   convert_leveldir->levels);
+  PrintLine("=", 79);
+  Print("\n");
 
   for (i = 0; i < MAX_NUM_CONVERT_LEVELS; i++)
     levels_failed[i] = FALSE;
@@ -10775,16 +10041,16 @@ void ConvertLevels()
 
     level_nr = convert_level_nr++;
 
-    printf("Level %03d: ", level_nr);
+    Print("Level %03d: ", level_nr);
 
     LoadLevel(level_nr);
     if (level.no_valid_file)
     {
-      printf("(no level)\n");
+      Print("(no level)\n");
       continue;
     }
 
-    printf("converting level ... ");
+    Print("converting level ... ");
 
     level_filename = getDefaultLevelFilename(level_nr);
     new_level = !fileExists(level_filename);
@@ -10795,28 +10061,28 @@ void ConvertLevels()
 
       num_levels_converted++;
 
-      printf("converted.\n");
+      Print("converted.\n");
     }
     else
     {
       if (level_nr >= 0 && level_nr < MAX_NUM_CONVERT_LEVELS)
 	levels_failed[level_nr] = TRUE;
 
-      printf("NOT CONVERTED -- LEVEL ALREADY EXISTS.\n");
+      Print("NOT CONVERTED -- LEVEL ALREADY EXISTS.\n");
     }
 
     num_levels_handled++;
   }
 
-  printf("\n");
-  printf_line("=", 79);
-  printf("Number of levels handled: %d\n", num_levels_handled);
-  printf("Number of levels converted: %d (%d%%)\n", num_levels_converted,
+  Print("\n");
+  PrintLine("=", 79);
+  Print("Number of levels handled: %d\n", num_levels_handled);
+  Print("Number of levels converted: %d (%d%%)\n", num_levels_converted,
 	 (num_levels_handled ?
 	  num_levels_converted * 100 / num_levels_handled : 0));
-  printf_line("-", 79);
-  printf("Summary (for automatic parsing by scripts):\n");
-  printf("LEVELDIR '%s', CONVERTED %d/%d (%d%%)",
+  PrintLine("-", 79);
+  Print("Summary (for automatic parsing by scripts):\n");
+  Print("LEVELDIR '%s', CONVERTED %d/%d (%d%%)",
 	 convert_leveldir->identifier, num_levels_converted,
 	 num_levels_handled,
 	 (num_levels_handled ?
@@ -10824,14 +10090,14 @@ void ConvertLevels()
 
   if (num_levels_handled != num_levels_converted)
   {
-    printf(", FAILED:");
+    Print(", FAILED:");
     for (i = 0; i < MAX_NUM_CONVERT_LEVELS; i++)
       if (levels_failed[i])
-	printf(" %03d", i);
+	Print(" %03d", i);
   }
 
-  printf("\n");
-  printf_line("=", 79);
+  Print("\n");
+  PrintLine("=", 79);
 
   CloseAllAndExit(0);
 }
@@ -10870,8 +10136,9 @@ void CreateLevelSketchImages()
     filename1 = getPath2(global.create_images_dir, basename1);
     filename2 = getPath2(global.create_images_dir, basename2);
 
-    getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
-    BlitBitmap(src_bitmap, bitmap1, src_x, src_y, TILEX, TILEY, 0, 0);
+    getFixedGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
+    BlitBitmap(src_bitmap, bitmap1, src_x, src_y, TILEX, TILEY,
+	       0, 0);
 
     if (SDL_SaveBMP(bitmap1->surface, filename1) != 0)
       Error(ERR_EXIT, "cannot save level sketch image file '%s'", filename1);
@@ -10906,24 +10173,29 @@ void CreateLevelSketchImages()
 /* create and save images for custom and group elements (raw BMP format)     */
 /* ------------------------------------------------------------------------- */
 
-void CreateCustomElementImages()
+void CreateCustomElementImages(char *directory)
 {
 #if defined(TARGET_SDL)
-  char *filename = "graphics.classic/RocksCE.bmp";
-  Bitmap *bitmap;
+  char *src_basename = "RocksCE-template.ilbm";
+  char *dst_basename = "RocksCE.bmp";
+  char *src_filename = getPath2(directory, src_basename);
+  char *dst_filename = getPath2(directory, dst_basename);
   Bitmap *src_bitmap;
-  int dummy_graphic = IMG_CUSTOM_99;
+  Bitmap *bitmap;
   int yoffset_ce = 0;
   int yoffset_ge = (TILEY * NUM_CUSTOM_ELEMENTS / 16);
-  int src_x, src_y;
   int i;
 
+  SDLInitVideoDisplay();
+
+  ReCreateBitmap(&backbuffer, video.width, video.height);
+
+  src_bitmap = LoadImage(src_filename);
+
   bitmap = CreateBitmap(TILEX * 16 * 2,
 			TILEY * (NUM_CUSTOM_ELEMENTS + NUM_GROUP_ELEMENTS) / 16,
 			DEFAULT_DEPTH);
 
-  getGraphicSource(dummy_graphic, 0, &src_bitmap, &src_x, &src_y);
-
   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
   {
     int x = i % 16;
@@ -10934,18 +10206,22 @@ void CreateCustomElementImages()
     BlitBitmap(src_bitmap, bitmap, 0, 0, TILEX, TILEY,
 	       TILEX * x, TILEY * y + yoffset_ce);
 
-    BlitBitmap(src_bitmap, bitmap, 0, TILEY, TILEX, TILEY,
-	       TILEX * x + TILEX * 16, TILEY * y + yoffset_ce);
+    BlitBitmap(src_bitmap, bitmap, 0, TILEY,
+	       TILEX, TILEY,
+	       TILEX * x + TILEX * 16,
+	       TILEY * y + yoffset_ce);
 
     for (j = 2; j >= 0; j--)
     {
       int c = ii % 10;
 
-      BlitBitmap(src_bitmap, bitmap, TILEX + c * 7, 0, 6, 10,
+      BlitBitmap(src_bitmap, bitmap,
+		 TILEX + c * 7, 0, 6, 10,
 		 TILEX * x + 6 + j * 7,
 		 TILEY * y + 11 + yoffset_ce);
 
-      BlitBitmap(src_bitmap, bitmap, TILEX + c * 8, TILEY, 6, 10,
+      BlitBitmap(src_bitmap, bitmap,
+		 TILEX + c * 8, TILEY, 6, 10,
 		 TILEX * 16 + TILEX * x + 6 + j * 8,
 		 TILEY * y + 10 + yoffset_ce);
 
@@ -10963,8 +10239,10 @@ void CreateCustomElementImages()
     BlitBitmap(src_bitmap, bitmap, 0, 0, TILEX, TILEY,
 	       TILEX * x, TILEY * y + yoffset_ge);
 
-    BlitBitmap(src_bitmap, bitmap, 0, TILEY, TILEX, TILEY,
-	       TILEX * x + TILEX * 16, TILEY * y + yoffset_ge);
+    BlitBitmap(src_bitmap, bitmap, 0, TILEY,
+	       TILEX, TILEY,
+	       TILEX * x + TILEX * 16,
+	       TILEY * y + yoffset_ge);
 
     for (j = 1; j >= 0; j--)
     {
@@ -10974,7 +10252,8 @@ void CreateCustomElementImages()
 		 TILEX * x + 6 + j * 10,
 		 TILEY * y + 11 + yoffset_ge);
 
-      BlitBitmap(src_bitmap, bitmap, TILEX + c * 8, TILEY + 12, 6, 10,
+      BlitBitmap(src_bitmap, bitmap,
+		 TILEX + c * 8, TILEY + 12, 6, 10,
 		 TILEX * 16 + TILEX * x + 10 + j * 8,
 		 TILEY * y + 10 + yoffset_ge);
 
@@ -10982,18 +10261,11 @@ void CreateCustomElementImages()
     }
   }
 
-  if (SDL_SaveBMP(bitmap->surface, filename) != 0)
-    Error(ERR_EXIT, "cannot save CE graphics file '%s'", filename);
+  if (SDL_SaveBMP(bitmap->surface, dst_filename) != 0)
+    Error(ERR_EXIT, "cannot save CE graphics file '%s'", dst_filename);
 
   FreeBitmap(bitmap);
 
   CloseAllAndExit(0);
 #endif
 }
-
-#if 0
-void CreateLevelSketchImages_TEST()
-{
-  void CreateCustomElementImages()
-}
-#endif
diff --git a/src/files.h b/src/files.h
index 9edda32..1bb5380 100644
--- a/src/files.h
+++ b/src/files.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* files.h                                                  *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// files.h
+// ============================================================================
 
 #ifndef FILES_H
 #define FILES_H
@@ -36,6 +34,7 @@ char *getDefaultLevelFilename(int);
 void LoadLevelFromFilename(struct LevelInfo *, char *);
 void LoadLevel(int);
 void LoadLevelTemplate(int);
+void LoadLevelInfoOnly(int);
 void SaveLevel(int);
 void SaveLevelTemplate();
 void SaveNativeLevel(struct LevelInfo *);
@@ -55,6 +54,7 @@ boolean SaveTapeChecked(int);
 void LoadScore(int);
 void SaveScore(int);
 
+void LoadSetupFromFilename(char *);
 void LoadSetup();
 void SaveSetup();
 
@@ -64,6 +64,7 @@ void SaveSetup_EditorCascade();
 void LoadCustomElementDescriptions();
 void InitMenuDesignSettings_Static();
 void LoadMenuDesignSettings();
+void LoadMenuDesignSettings_AfterGraphics();
 void LoadUserDefinedEditorElementList(int **, int *);
 void LoadMusicInfo();
 void LoadHelpAnimInfo();
@@ -71,5 +72,6 @@ void LoadHelpTextInfo();
 
 void ConvertLevels();
 void CreateLevelSketchImages();
+void CreateCustomElementImages(char *);
 
 #endif	/* FILES_H */
diff --git a/src/game.c b/src/game.c
index aeb40a5..de245df 100644
--- a/src/game.c
+++ b/src/game.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* game.c                                                   *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// game.c
+// ============================================================================
 
 #include "libgame/libgame.h"
 
@@ -17,57 +15,25 @@
 #include "init.h"
 #include "tools.h"
 #include "screens.h"
+#include "events.h"
 #include "files.h"
 #include "tape.h"
 #include "network.h"
+#include "anim.h"
+
+
+/* DEBUG SETTINGS */
+#define DEBUG_INIT_PLAYER	1
+#define DEBUG_PLAYER_ACTIONS	0
 
 /* EXPERIMENTAL STUFF */
 #define USE_NEW_AMOEBA_CODE	FALSE
 
 /* EXPERIMENTAL STUFF */
-#define USE_NEW_STUFF			(			  1)
-
-#define USE_NEW_SP_SLIPPERY		(USE_NEW_STUFF		* 1)
-#define USE_NEW_CUSTOM_VALUE		(USE_NEW_STUFF		* 1)
-#define USE_NEW_PLAYER_ANIM		(USE_NEW_STUFF		* 1)
-#define USE_NEW_ALL_SLIPPERY		(USE_NEW_STUFF		* 1)
-#define USE_NEW_PLAYER_SPEED		(USE_NEW_STUFF		* 1)
-#define USE_NEW_DELAYED_ACTION		(USE_NEW_STUFF		* 1)
-#define USE_NEW_SNAP_DELAY		(USE_NEW_STUFF		* 1)
-#define USE_ONLY_ONE_CHANGE_PER_FRAME	(USE_NEW_STUFF		* 1)
-#define USE_ONE_MORE_CHANGE_PER_FRAME	(USE_NEW_STUFF		* 1)
-#define USE_FIXED_DONT_RUN_INTO		(USE_NEW_STUFF		* 1)
-#define USE_NEW_SPRING_BUMPER		(USE_NEW_STUFF		* 1)
-#define USE_STOP_CHANGED_ELEMENTS	(USE_NEW_STUFF		* 1)
-#define USE_ELEMENT_TOUCHING_BUGFIX	(USE_NEW_STUFF		* 1)
-#define USE_NEW_CONTINUOUS_SNAPPING	(USE_NEW_STUFF		* 1)
-#define USE_GFX_RESET_GFX_ANIMATION	(USE_NEW_STUFF		* 1)
-#define USE_BOTH_SWITCHGATE_SWITCHES	(USE_NEW_STUFF		* 1)
-#define USE_PLAYER_GRAVITY		(USE_NEW_STUFF		* 1)
-#define USE_FIXED_BORDER_RUNNING_GFX	(USE_NEW_STUFF		* 1)
-#define USE_QUICKSAND_BD_ROCK_BUGFIX	(USE_NEW_STUFF		* 0)
-
-#define USE_QUICKSAND_IMPACT_BUGFIX	(USE_NEW_STUFF		* 0)
-
-#define USE_CODE_THAT_BREAKS_SNAKE_BITE	(USE_NEW_STUFF		* 1)
-
-#define USE_UFAST_PLAYER_EXIT_BUGFIX	(USE_NEW_STUFF		* 1)
-
-#define USE_GFX_RESET_ONLY_WHEN_MOVING	(USE_NEW_STUFF		* 1)
-#define USE_GFX_RESET_PLAYER_ARTWORK	(USE_NEW_STUFF		* 1)
-
-#define USE_FIX_KILLED_BY_NON_WALKABLE	(USE_NEW_STUFF		* 1)
-#define USE_FIX_IMPACT_COLLISION	(USE_NEW_STUFF		* 1)
-#define USE_FIX_CE_ACTION_WITH_PLAYER	(USE_NEW_STUFF		* 1)
-#define USE_FIX_NO_ACTION_AFTER_CHANGE	(USE_NEW_STUFF		* 1)
-
-#define USE_PLAYER_REANIMATION		(USE_NEW_STUFF		* 1)
-
-#define USE_GFX_RESET_WHEN_NOT_MOVING	(USE_NEW_STUFF		* 1)
-
-#define USE_NEW_PLAYER_ASSIGNMENTS	(USE_NEW_STUFF		* 1)
-
-#define USE_DELAYED_GFX_REDRAW		(USE_NEW_STUFF		* 0)
+#define USE_QUICKSAND_BD_ROCK_BUGFIX	0
+#define USE_QUICKSAND_IMPACT_BUGFIX	0
+#define USE_DELAYED_GFX_REDRAW		0
+#define USE_NEW_PLAYER_ASSIGNMENTS	1
 
 #if USE_DELAYED_GFX_REDRAW
 #define TEST_DrawLevelField(x, y)				\
@@ -120,45 +86,7 @@
 #define PANEL_XPOS(p)		(DX + ALIGNED_TEXT_XPOS(p))
 #define PANEL_YPOS(p)		(DY + ALIGNED_TEXT_YPOS(p))
 
-/* special positions in the game control window (relative to control window) */
-#define XX_LEVEL1		(PANEL_XPOS(game.panel.level))
-#define XX_LEVEL2		(PANEL_XPOS(game.panel.level) - 1)
-#define XX_LEVEL		(PANEL_XPOS(game.panel.level))
-#define YY_LEVEL		(PANEL_YPOS(game.panel.level))
-#define XX_EMERALDS		(PANEL_XPOS(game.panel.gems))
-#define YY_EMERALDS		(PANEL_YPOS(game.panel.gems))
-#define XX_DYNAMITE		(PANEL_XPOS(game.panel.inventory))
-#define YY_DYNAMITE		(PANEL_YPOS(game.panel.inventory))
-#define XX_KEYS			(PANEL_XPOS(game.panel.keys))
-#define YY_KEYS			(PANEL_YPOS(game.panel.keys))
-#define XX_SCORE		(PANEL_XPOS(game.panel.score))
-#define YY_SCORE		(PANEL_YPOS(game.panel.score))
-#define XX_TIME1		(PANEL_XPOS(game.panel.time))
-#define XX_TIME2		(PANEL_XPOS(game.panel.time) + 1)
-#define XX_TIME			(PANEL_XPOS(game.panel.time))
-#define YY_TIME			(PANEL_YPOS(game.panel.time))
-
-/* special positions in the game control window (relative to main window) */
-#define DX_LEVEL1		(DX + XX_LEVEL1)
-#define DX_LEVEL2		(DX + XX_LEVEL2)
-#define DX_LEVEL		(DX + XX_LEVEL)
-#define DY_LEVEL		(DY + YY_LEVEL)
-#define DX_EMERALDS		(DX + XX_EMERALDS)
-#define DY_EMERALDS		(DY + YY_EMERALDS)
-#define DX_DYNAMITE		(DX + XX_DYNAMITE)
-#define DY_DYNAMITE		(DY + YY_DYNAMITE)
-#define DX_KEYS			(DX + XX_KEYS)
-#define DY_KEYS			(DY + YY_KEYS)
-#define DX_SCORE		(DX + XX_SCORE)
-#define DY_SCORE		(DY + YY_SCORE)
-#define DX_TIME1		(DX + XX_TIME1)
-#define DX_TIME2		(DX + XX_TIME2)
-#define DX_TIME			(DX + XX_TIME)
-#define DY_TIME			(DY + YY_TIME)
-
-#if 1
 /* game panel display and control definitions */
-
 #define GAME_PANEL_LEVEL_NUMBER			0
 #define GAME_PANEL_GEMS				1
 #define GAME_PANEL_INVENTORY_COUNT		2
@@ -876,8 +804,6 @@ static struct GamePanelControlInfo game_panel_controls[] =
     -1,
   }
 };
-#endif
-
 
 /* values for delayed check of falling and moving elements and for collision */
 #define CHECK_DELAY_MOVING	3
@@ -1046,11 +972,16 @@ static struct GamePanelControlInfo game_panel_controls[] =
 #define GAME_CTRL_ID_STOP		0
 #define GAME_CTRL_ID_PAUSE		1
 #define GAME_CTRL_ID_PLAY		2
-#define SOUND_CTRL_ID_MUSIC		3
-#define SOUND_CTRL_ID_LOOPS		4
-#define SOUND_CTRL_ID_SIMPLE		5
+#define GAME_CTRL_ID_UNDO		3
+#define GAME_CTRL_ID_REDO		4
+#define GAME_CTRL_ID_SAVE		5
+#define GAME_CTRL_ID_PAUSE2		6
+#define GAME_CTRL_ID_LOAD		7
+#define SOUND_CTRL_ID_MUSIC		8
+#define SOUND_CTRL_ID_LOOPS		9
+#define SOUND_CTRL_ID_SIMPLE		10
 
-#define NUM_GAME_BUTTONS		6
+#define NUM_GAME_BUTTONS		11
 
 
 /* forward declaration for internal use */
@@ -1082,9 +1013,6 @@ static void KillPlayerUnlessExplosionProtected(int, int);
 static void TestIfPlayerTouchesCustomElement(int, int);
 static void TestIfElementTouchesCustomElement(int, int);
 static void TestIfElementHitsCustomElement(int, int, int);
-#if 0
-static void TestIfElementSmashesCustomElement(int, int, int);
-#endif
 
 static void HandleElementChange(int, int, int);
 static void ExecuteCustomElementAction(int, int, int, int);
@@ -1117,7 +1045,6 @@ static void PlayLevelSoundActionIfLoop(int, int, int);
 static void StopLevelSoundActionIfLoop(int, int, int);
 static void PlayLevelMusic();
 
-static void MapGameButtons();
 static void HandleGameButtons(struct GadgetInfo *);
 
 int AmoebeNachbarNr(int, int);
@@ -1271,11 +1198,7 @@ static struct ChangingElementInfo change_delay_list[] =
   },
   {
     EL_EM_EXIT_CLOSING,
-#if 1
     EL_EMPTY,
-#else
-    EL_EM_EXIT_CLOSED,
-#endif
     29,
     NULL,
     NULL,
@@ -1291,11 +1214,7 @@ static struct ChangingElementInfo change_delay_list[] =
   },
   {
     EL_EM_STEEL_EXIT_CLOSING,
-#if 1
     EL_STEELWALL,
-#else
-    EL_EM_STEEL_EXIT_CLOSED,
-#endif
     29,
     NULL,
     NULL,
@@ -1780,14 +1699,16 @@ static void InitPlayerField(int x, int y, int element, boolean init_game)
 
       StorePlayer[x][y] = Feld[x][y];
 
+#if DEBUG_INIT_PLAYER
       if (options.debug)
       {
-	printf("Player %d activated.\n", player->element_nr);
-	printf("[Local player is %d and currently %s.]\n",
+	printf("- player element %d activated", player->element_nr);
+	printf(" (local player is %d and currently %s)\n",
 	       local_player->element_nr,
 	       local_player->active ? "active" : "not active");
       }
     }
+#endif
 
     Feld[x][y] = EL_EMPTY;
 
@@ -1795,7 +1716,6 @@ static void InitPlayerField(int x, int y, int element, boolean init_game)
     player->jy = player->last_jy = y;
   }
 
-#if USE_PLAYER_REANIMATION
   if (!init_game)
   {
     int player_nr = GET_PLAYER_NR(element);
@@ -1804,7 +1724,6 @@ static void InitPlayerField(int x, int y, int element, boolean init_game)
     if (player->active && player->killed)
       player->reanimated = TRUE; /* if player was just killed, reanimate him */
   }
-#endif
 }
 
 static void InitField(int x, int y, boolean init_game)
@@ -1957,18 +1876,6 @@ static void InitField(int x, int y, boolean init_game)
       }
       break;
 
-#if !USE_BOTH_SWITCHGATE_SWITCHES
-    case EL_SWITCHGATE_SWITCH_DOWN:	/* always start with same switch pos */
-      if (init_game)
-	Feld[x][y] = EL_SWITCHGATE_SWITCH_UP;
-      break;
-
-    case EL_DC_SWITCHGATE_SWITCH_DOWN:	/* always start with same switch pos */
-      if (init_game)
-	Feld[x][y] = EL_DC_SWITCHGATE_SWITCH_UP;
-      break;
-#endif
-
     case EL_LIGHT_SWITCH_ACTIVE:
       if (init_game)
 	game.light_time_left = level.time_light * FRAMES_PER_SECOND;
@@ -2026,10 +1933,8 @@ static void InitField(int x, int y, boolean init_game)
 	if (CAN_MOVE(element))
 	  InitMovDir(x, y);
 
-#if USE_NEW_CUSTOM_VALUE
 	if (!element_info[element].use_last_ce_value || init_game)
 	  CustomValue[x][y] = GET_NEW_CE_VALUE(Feld[x][y]);
-#endif
       }
       else if (IS_GROUP_ELEMENT(element))
       {
@@ -2045,7 +1950,7 @@ static void InitField(int x, int y, boolean init_game)
     CheckTriggeredElementChange(x, y, element, CE_CREATION_OF_X);
 }
 
-static inline void InitField_WithBug1(int x, int y, boolean init_game)
+inline static void InitField_WithBug1(int x, int y, boolean init_game)
 {
   InitField(x, y, init_game);
 
@@ -2055,7 +1960,7 @@ static inline void InitField_WithBug1(int x, int y, boolean init_game)
     InitMovDir(x, y);
 }
 
-static inline void InitField_WithBug2(int x, int y, boolean init_game)
+inline static void InitField_WithBug2(int x, int y, boolean init_game)
 {
   int old_element = Feld[x][y];
 
@@ -2076,8 +1981,6 @@ static inline void InitField_WithBug2(int x, int y, boolean init_game)
   */
 }
 
-#if 1
-
 static int get_key_element_from_nr(int key_nr)
 {
   int key_base_element = (key_nr >= STD_NUM_KEYS ? EL_EMC_KEY_5 - STD_NUM_KEYS :
@@ -2147,6 +2050,16 @@ static int compareGamePanelOrderInfo(const void *object1, const void *object2)
   return compare_result;
 }
 
+int getPlayerInventorySize(int player_nr)
+{
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+    return level.native_em_level->ply[player_nr]->dynamite;
+  else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+    return level.native_sp_level->game_sp->red_disk_count;
+  else
+    return stored_player[player_nr].inventory_size;
+}
+
 void InitGameControlValues()
 {
   int i;
@@ -2229,7 +2142,7 @@ void UpdateGameControlValues()
 	      level.native_em_level->lev->time :
 	      level.game_engine_type == GAME_ENGINE_TYPE_SP ?
 	      level.native_sp_level->game_sp->time_played :
-	      level.time == 0 ? TimePlayed : TimeLeft);
+	      game.no_time_limit ? TimePlayed : TimeLeft);
   int score = (local_player->LevelSolved ?
 	       local_player->LevelSolved_CountingScore :
 	       level.game_engine_type == GAME_ENGINE_TYPE_EM ?
@@ -2284,15 +2197,8 @@ void UpdateGameControlValues()
 	    get_key_element_from_nr(k);
       }
 
-      if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
-	game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
-	  level.native_em_level->ply[i]->dynamite;
-      else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
-	game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
-	  level.native_sp_level->game_sp->red_disk_count;
-      else
-	game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
-	  stored_player[i].inventory_size;
+      game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
+	getPlayerInventorySize(i);
 
       if (stored_player[i].num_white_keys > 0)
 	game_panel_controls[GAME_PANEL_KEY_WHITE].value =
@@ -2319,15 +2225,8 @@ void UpdateGameControlValues()
 	  get_key_element_from_nr(k);
     }
 
-    if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
-      game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
-	level.native_em_level->ply[player_nr]->dynamite;
-    else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
-      game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
-	level.native_sp_level->game_sp->red_disk_count;
-    else
-      game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
-	stored_player[player_nr].inventory_size;
+    game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
+      getPlayerInventorySize(player_nr);
 
     if (stored_player[player_nr].num_white_keys > 0)
       game_panel_controls[GAME_PANEL_KEY_WHITE].value = EL_DC_KEY_WHITE;
@@ -2437,12 +2336,8 @@ void UpdateGameControlValues()
   game_panel_controls[GAME_PANEL_MAGIC_WALL_TIME].value =
     game.magic_wall_time_left;
 
-#if USE_PLAYER_GRAVITY
   game_panel_controls[GAME_PANEL_GRAVITY_STATE].value =
     local_player->gravity;
-#else
-  game_panel_controls[GAME_PANEL_GRAVITY_STATE].value = game.gravity;
-#endif
 
   for (i = 0; i < NUM_PANEL_GRAPHICS; i++)
     game_panel_controls[GAME_PANEL_GRAPHIC_1 + i].value = EL_GRAPHIC_1 + i;
@@ -2539,40 +2434,25 @@ void DisplayGameControlValues()
     return;
 
   /* copy default game door content to main double buffer */
-  BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
-	     DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY);
+
+  /* !!! CHECK AGAIN !!! */
+  SetPanelBackground();
+  // SetDoorBackgroundImage(IMG_BACKGROUND_PANEL);
+  DrawBackground(DX, DY, DXSIZE, DYSIZE);
 
   /* redraw game control buttons */
-#if 1
   RedrawGameButtons();
-#else
-  UnmapGameButtons();
-  MapGameButtons();
-#endif
 
-  game_status = GAME_MODE_PSEUDO_PANEL;
+  SetGameStatus(GAME_MODE_PSEUDO_PANEL);
 
-#if 1
   for (i = 0; i < NUM_GAME_PANEL_CONTROLS; i++)
-#else
-  for (i = 0; game_panel_controls[i].nr != -1; i++)
-#endif
   {
-#if 1
     int nr = game_panel_order[i].nr;
     struct GamePanelControlInfo *gpc = &game_panel_controls[nr];
-#else
-    struct GamePanelControlInfo *gpc = &game_panel_controls[i];
-    int nr = gpc->nr;
-#endif
     struct TextPosInfo *pos = gpc->pos;
     int type = gpc->type;
     int value = gpc->value;
     int frame = gpc->frame;
-#if 0
-    int last_value = gpc->last_value;
-    int last_frame = gpc->last_frame;
-#endif
     int size = pos->size;
     int font = pos->font;
     boolean draw_masked = pos->draw_masked;
@@ -2581,18 +2461,9 @@ void DisplayGameControlValues()
     if (PANEL_DEACTIVATED(pos))
       continue;
 
-#if 0
-    if (value == last_value && frame == last_frame)
-      continue;
-#endif
-
     gpc->last_value = value;
     gpc->last_frame = frame;
 
-#if 0
-    printf("::: value %d changed from %d to %d\n", nr, last_value, value);
-#endif
-
     if (type == TYPE_INTEGER)
     {
       if (nr == GAME_PANEL_LEVEL_NUMBER ||
@@ -2610,33 +2481,15 @@ void DisplayGameControlValues()
 
 	  size = (value < value_change ? size1 : size2);
 	  font = (value < value_change ? font1 : font2);
-
-#if 0
-	  /* clear background if value just changed its size (dynamic digits) */
-	  if ((last_value < value_change) != (value < value_change))
-	  {
-	    int width1 = size1 * getFontWidth(font1);
-	    int width2 = size2 * getFontWidth(font2);
-	    int max_width = MAX(width1, width2);
-	    int max_height = MAX(getFontHeight(font1), getFontHeight(font2));
-
-	    pos->width = max_width;
-
-	    ClearRectangleOnBackground(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
-				       max_width, max_height);
-	  }
-#endif
 	}
       }
 
-#if 1
       /* correct text size if "digits" is zero or less */
       if (size <= 0)
 	size = strlen(int2str(value, size));
 
       /* dynamically correct text alignment */
       pos->width = size * getFontWidth(font);
-#endif
 
       DrawTextExt(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
 		  int2str(value, size), font, mask_mode);
@@ -2650,7 +2503,6 @@ void DisplayGameControlValues()
       int dst_x = PANEL_XPOS(pos);
       int dst_y = PANEL_YPOS(pos);
 
-#if 1
       if (value != EL_UNDEFINED && value != EL_EMPTY)
       {
 	element = value;
@@ -2658,10 +2510,8 @@ void DisplayGameControlValues()
 
 	// printf("::: %d, '%s' [%d]\n", element, EL_NAME(element), size);
 
-#if 1
 	if (element >= EL_GRAPHIC_1 && element <= EL_GRAPHIC_8 && size == 0)
 	  size = TILESIZE;
-#endif
 
 	getSizedGraphicSource(graphic, frame, size, &src_bitmap,
 			      &src_x, &src_y);
@@ -2670,41 +2520,12 @@ void DisplayGameControlValues()
 	height = graphic_info[graphic].height * size / TILESIZE;
 
 	if (draw_masked)
-	{
-	  SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
-			dst_x - src_x, dst_y - src_y);
 	  BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, width, height,
 			   dst_x, dst_y);
-	}
 	else
-	{
 	  BlitBitmap(src_bitmap, drawto, src_x, src_y, width, height,
 		     dst_x, dst_y);
-	}
-      }
-#else
-      if (value == EL_UNDEFINED || value == EL_EMPTY)
-      {
-	element = (last_value == EL_UNDEFINED ? EL_EMPTY : last_value);
-	graphic = el2panelimg(element);
-
-	src_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
-	src_x = DOOR_GFX_PAGEX5 + ALIGNED_TEXT_XPOS(pos);
-	src_y = DOOR_GFX_PAGEY1 + ALIGNED_TEXT_YPOS(pos);
       }
-      else
-      {
-	element = value;
-	graphic = el2panelimg(value);
-
-	getSizedGraphicSource(graphic, frame, size, &src_bitmap, &src_x,&src_y);
-      }
-
-      width  = graphic_info[graphic].width  * size / TILESIZE;
-      height = graphic_info[graphic].height * size / TILESIZE;
-
-      BlitBitmap(src_bitmap, drawto, src_x, src_y, width, height, dst_x, dst_y);
-#endif
     }
     else if (type == TYPE_STRING)
     {
@@ -2721,20 +2542,6 @@ void DisplayGameControlValues()
       {
 	int font1 = pos->font;		/* (used for normal state) */
 	int font2 = pos->font_alt;	/* (used for active state) */
-#if 0
-	int size1 = strlen(state_normal);
-	int size2 = strlen(state_active);
-	int width1 = size1 * getFontWidth(font1);
-	int width2 = size2 * getFontWidth(font2);
-	int max_width = MAX(width1, width2);
-	int max_height = MAX(getFontHeight(font1), getFontHeight(font2));
-
-	pos->width = max_width;
-
-	/* clear background for values that may have changed its size */
-	ClearRectangleOnBackground(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
-				   max_width, max_height);
-#endif
 
 	font = (active ? font2 : font1);
       }
@@ -2743,7 +2550,6 @@ void DisplayGameControlValues()
       {
 	char *s_cut;
 
-#if 1
 	if (size <= 0)
 	{
 	  /* don't truncate output if "chars" is zero or less */
@@ -2752,7 +2558,6 @@ void DisplayGameControlValues()
 	  /* dynamically correct text alignment */
 	  pos->width = size * getFontWidth(font);
 	}
-#endif
 
 	s_cut = getStringCopyN(s, size);
 
@@ -2766,586 +2571,146 @@ void DisplayGameControlValues()
     redraw_mask |= REDRAW_DOOR_1;
   }
 
-  game_status = GAME_MODE_PLAYING;
+  SetGameStatus(GAME_MODE_PLAYING);
 }
 
 void UpdateAndDisplayGameControlValues()
 {
-  if (tape.warp_forward)
+  if (tape.deactivate_display)
     return;
 
   UpdateGameControlValues();
   DisplayGameControlValues();
 }
 
-void DrawGameValue_Emeralds(int value)
+void UpdateGameDoorValues()
 {
-  struct TextPosInfo *pos = &game.panel.gems;
-#if 1
-  int font_nr = pos->font;
-#else
-  int font_nr = FONT_TEXT_2;
-#endif
-  int font_width = getFontWidth(font_nr);
-  int chars = pos->size;
-
-#if 1
-  return;	/* !!! USE NEW STUFF !!! */
-#endif
-
-  if (PANEL_DEACTIVATED(pos))
-    return;
-
-  pos->width = chars * font_width;
-
-  DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, chars), font_nr);
+  UpdateGameControlValues();
 }
 
-void DrawGameValue_Dynamite(int value)
+void DrawGameDoorValues()
 {
-  struct TextPosInfo *pos = &game.panel.inventory_count;
-#if 1
-  int font_nr = pos->font;
-#else
-  int font_nr = FONT_TEXT_2;
-#endif
-  int font_width = getFontWidth(font_nr);
-  int chars = pos->size;
-
-#if 1
-  return;	/* !!! USE NEW STUFF !!! */
-#endif
-
-  if (PANEL_DEACTIVATED(pos))
-    return;
+  DisplayGameControlValues();
+}
 
-  pos->width = chars * font_width;
 
-  DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, chars), font_nr);
-}
+/*
+  =============================================================================
+  InitGameEngine()
+  -----------------------------------------------------------------------------
+  initialize game engine due to level / tape version number
+  =============================================================================
+*/
 
-void DrawGameValue_Score(int value)
+static void InitGameEngine()
 {
-  struct TextPosInfo *pos = &game.panel.score;
-#if 1
-  int font_nr = pos->font;
-#else
-  int font_nr = FONT_TEXT_2;
-#endif
-  int font_width = getFontWidth(font_nr);
-  int chars = pos->size;
+  int i, j, k, l, x, y;
 
-#if 1
-  return;	/* !!! USE NEW STUFF !!! */
-#endif
+  /* set game engine from tape file when re-playing, else from level file */
+  game.engine_version = (tape.playing ? tape.engine_version :
+			 level.game_version);
 
-  if (PANEL_DEACTIVATED(pos))
-    return;
+  /* set single or multi-player game mode (needed for re-playing tapes) */
+  game.team_mode = setup.team_mode;
 
-  pos->width = chars * font_width;
+  if (tape.playing)
+  {
+    int num_players = 0;
 
-  DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, chars), font_nr);
-}
+    for (i = 0; i < MAX_PLAYERS; i++)
+      if (tape.player_participates[i])
+	num_players++;
 
-void DrawGameValue_Time(int value)
-{
-  struct TextPosInfo *pos = &game.panel.time;
-  static int last_value = -1;
-  int chars1 = 3;
-  int chars2 = 4;
-  int chars = pos->size;
-#if 1
-  int font1_nr = pos->font;
-  int font2_nr = pos->font_alt;
-#else
-  int font1_nr = FONT_TEXT_2;
-  int font2_nr = FONT_TEXT_1;
-#endif
-  int font_nr = font1_nr;
-  boolean use_dynamic_chars = (chars == -1 ? TRUE : FALSE);
+    /* multi-player tapes contain input data for more than one player */
+    game.team_mode = (num_players > 1);
+  }
 
-#if 1
-  return;	/* !!! USE NEW STUFF !!! */
-#endif
+  /* ---------------------------------------------------------------------- */
+  /* set flags for bugs and changes according to active game engine version */
+  /* ---------------------------------------------------------------------- */
 
-  if (PANEL_DEACTIVATED(pos))
-    return;
+  /*
+    Summary of bugfix/change:
+    Fixed handling for custom elements that change when pushed by the player.
 
-  if (use_dynamic_chars)		/* use dynamic number of chars */
-  {
-    chars   = (value < 1000 ? chars1   : chars2);
-    font_nr = (value < 1000 ? font1_nr : font2_nr);
-  }
+    Fixed/changed in version:
+    3.1.0
 
-  /* clear background if value just changed its size (dynamic chars only) */
-  if (use_dynamic_chars && (last_value < 1000) != (value < 1000))
-  {
-    int width1 = chars1 * getFontWidth(font1_nr);
-    int width2 = chars2 * getFontWidth(font2_nr);
-    int max_width = MAX(width1, width2);
-    int max_height = MAX(getFontHeight(font1_nr), getFontHeight(font2_nr));
+    Description:
+    Before 3.1.0, custom elements that "change when pushing" changed directly
+    after the player started pushing them (until then handled in "DigField()").
+    Since 3.1.0, these custom elements are not changed until the "pushing"
+    move of the element is finished (now handled in "ContinueMoving()").
 
-    pos->width = max_width;
+    Affected levels/tapes:
+    The first condition is generally needed for all levels/tapes before version
+    3.1.0, which might use the old behaviour before it was changed; known tapes
+    that are affected are some tapes from the level set "Walpurgis Gardens" by
+    Jamie Cullen.
+    The second condition is an exception from the above case and is needed for
+    the special case of tapes recorded with game (not engine!) version 3.1.0 or
+    above (including some development versions of 3.1.0), but before it was
+    known that this change would break tapes like the above and was fixed in
+    3.1.1, so that the changed behaviour was active although the engine version
+    while recording maybe was before 3.1.0. There is at least one tape that is
+    affected by this exception, which is the tape for the one-level set "Bug
+    Machine" by Juergen Bonhagen.
+  */
 
-    ClearRectangleOnBackground(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
-			       max_width, max_height);
-  }
+  game.use_change_when_pushing_bug =
+    (game.engine_version < VERSION_IDENT(3,1,0,0) &&
+     !(tape.playing &&
+       tape.game_version >= VERSION_IDENT(3,1,0,0) &&
+       tape.game_version <  VERSION_IDENT(3,1,1,0)));
 
-  pos->width = chars * getFontWidth(font_nr);
+  /*
+    Summary of bugfix/change:
+    Fixed handling for blocking the field the player leaves when moving.
 
-  DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, chars), font_nr);
+    Fixed/changed in version:
+    3.1.1
 
-  last_value = value;
-}
+    Description:
+    Before 3.1.1, when "block last field when moving" was enabled, the field
+    the player is leaving when moving was blocked for the time of the move,
+    and was directly unblocked afterwards. This resulted in the last field
+    being blocked for exactly one less than the number of frames of one player
+    move. Additionally, even when blocking was disabled, the last field was
+    blocked for exactly one frame.
+    Since 3.1.1, due to changes in player movement handling, the last field
+    is not blocked at all when blocking is disabled. When blocking is enabled,
+    the last field is blocked for exactly the number of frames of one player
+    move. Additionally, if the player is Murphy, the hero of Supaplex, the
+    last field is blocked for exactly one more than the number of frames of
+    one player move.
 
-void DrawGameValue_Level(int value)
-{
-  struct TextPosInfo *pos = &game.panel.level_number;
-  int chars1 = 2;
-  int chars2 = 3;
-  int chars = pos->size;
-#if 1
-  int font1_nr = pos->font;
-  int font2_nr = pos->font_alt;
-#else
-  int font1_nr = FONT_TEXT_2;
-  int font2_nr = FONT_TEXT_1;
-#endif
-  int font_nr = font1_nr;
-  boolean use_dynamic_chars = (chars == -1 ? TRUE : FALSE);
+    Affected levels/tapes:
+    (!!! yet to be determined -- probably many !!!)
+  */
 
-#if 1
-  return;	/* !!! USE NEW STUFF !!! */
-#endif
+  game.use_block_last_field_bug =
+    (game.engine_version < VERSION_IDENT(3,1,1,0));
 
-  if (PANEL_DEACTIVATED(pos))
-    return;
+  /* ---------------------------------------------------------------------- */
 
-  if (use_dynamic_chars)		/* use dynamic number of chars */
-  {
-    chars   = (level_nr < 100 ? chars1   : chars2);
-    font_nr = (level_nr < 100 ? font1_nr : font2_nr);
-  }
+  /* set maximal allowed number of custom element changes per game frame */
+  game.max_num_changes_per_frame = 1;
 
-  pos->width = chars * getFontWidth(font_nr);
+  /* default scan direction: scan playfield from top/left to bottom/right */
+  InitPlayfieldScanMode(CA_ARG_SCAN_MODE_NORMAL);
 
-  DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, chars), font_nr);
-}
+  /* dynamically adjust element properties according to game engine version */
+  InitElementPropertiesEngine(game.engine_version);
 
-void DrawGameValue_Keys(int key[MAX_NUM_KEYS])
-{
-#if 0
-  struct TextPosInfo *pos = &game.panel.keys;
-#endif
 #if 0
-  int base_key_graphic = EL_KEY_1;
-#endif
-  int i;
-
-#if 1
-  return;	/* !!! USE NEW STUFF !!! */
+  printf("level %d: level version == %06d\n", level_nr, level.game_version);
+  printf("          tape version == %06d [%s] [file: %06d]\n",
+	 tape.engine_version, (tape.playing ? "PLAYING" : "RECORDING"),
+	 tape.file_version);
+  printf("       => game.engine_version == %06d\n", game.engine_version);
 #endif
 
-#if 0
-  if (PANEL_DEACTIVATED(pos))
-    return;
-#endif
-
-#if 0
-  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
-    base_key_graphic = EL_EM_KEY_1;
-#endif
-
-#if 0
-  pos->width = 4 * MINI_TILEX;
-#endif
-
-#if 1
-  for (i = 0; i < MAX_NUM_KEYS; i++)
-#else
-  /* currently only 4 of 8 possible keys are displayed */
-  for (i = 0; i < STD_NUM_KEYS; i++)
-#endif
-  {
-#if 1
-    struct TextPosInfo *pos = &game.panel.key[i];
-#endif
-    int src_x = DOOR_GFX_PAGEX5 + 18 + (i % 4) * MINI_TILEX;
-    int src_y = DOOR_GFX_PAGEY1 + 123;
-#if 1
-    int dst_x = PANEL_XPOS(pos);
-    int dst_y = PANEL_YPOS(pos);
-#else
-    int dst_x = PANEL_XPOS(pos) + i * MINI_TILEX;
-    int dst_y = PANEL_YPOS(pos);
-#endif
-
-#if 1
-    int element = (i >= STD_NUM_KEYS ? EL_EMC_KEY_5 - 4 :
-		   level.game_engine_type == GAME_ENGINE_TYPE_EM ? EL_EM_KEY_1 :
-		   EL_KEY_1) + i;
-    int graphic = el2edimg(element);
-#endif
-
-#if 1
-    if (PANEL_DEACTIVATED(pos))
-      continue;
-#endif
-
-#if 0
-    /* masked blit with tiles from half-size scaled bitmap does not work yet
-       (no mask bitmap created for these sizes after loading and scaling) --
-       solution: load without creating mask, scale, then create final mask */
-
-    BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, src_x, src_y,
-	       MINI_TILEX, MINI_TILEY, dst_x, dst_y);
-
-    if (key[i])
-    {
-#if 0
-      int graphic = el2edimg(base_key_graphic + i);
-#endif
-      Bitmap *src_bitmap;
-      int src_x, src_y;
-
-      getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
-
-      SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
-		    dst_x - src_x, dst_y - src_y);
-      BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, MINI_TILEX, MINI_TILEY,
-		       dst_x, dst_y);
-    }
-#else
-#if 1
-    if (key[i])
-      DrawMiniGraphicExt(drawto, dst_x, dst_y, graphic);
-    else
-      BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, src_x, src_y,
-		 MINI_TILEX, MINI_TILEY, dst_x, dst_y);
-#else
-    if (key[i])
-      DrawMiniGraphicExt(drawto, dst_x, dst_y, el2edimg(base_key_graphic + i));
-    else
-      BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, src_x, src_y,
-		 MINI_TILEX, MINI_TILEY, dst_x, dst_y);
-#endif
-#endif
-  }
-}
-
-#else
-
-void DrawGameValue_Emeralds(int value)
-{
-  int font_nr = FONT_TEXT_2;
-  int xpos = (3 * 14 - 3 * getFontWidth(font_nr)) / 2;
-
-  if (PANEL_DEACTIVATED(game.panel.gems))
-    return;
-
-  DrawText(DX_EMERALDS + xpos, DY_EMERALDS, int2str(value, 3), font_nr);
-}
-
-void DrawGameValue_Dynamite(int value)
-{
-  int font_nr = FONT_TEXT_2;
-  int xpos = (3 * 14 - 3 * getFontWidth(font_nr)) / 2;
-
-  if (PANEL_DEACTIVATED(game.panel.inventory_count))
-    return;
-
-  DrawText(DX_DYNAMITE + xpos, DY_DYNAMITE, int2str(value, 3), font_nr);
-}
-
-void DrawGameValue_Score(int value)
-{
-  int font_nr = FONT_TEXT_2;
-  int xpos = (5 * 14 - 5 * getFontWidth(font_nr)) / 2;
-
-  if (PANEL_DEACTIVATED(game.panel.score))
-    return;
-
-  DrawText(DX_SCORE + xpos, DY_SCORE, int2str(value, 5), font_nr);
-}
-
-void DrawGameValue_Time(int value)
-{
-  int font1_nr = FONT_TEXT_2;
-#if 1
-  int font2_nr = FONT_TEXT_1;
-#else
-  int font2_nr = FONT_LEVEL_NUMBER;
-#endif
-  int xpos3 = (3 * 14 - 3 * getFontWidth(font1_nr)) / 2;
-  int xpos4 = (4 * 10 - 4 * getFontWidth(font2_nr)) / 2;
-
-  if (PANEL_DEACTIVATED(game.panel.time))
-    return;
-
-  /* clear background if value just changed its size */
-  if (value == 999 || value == 1000)
-    ClearRectangleOnBackground(drawto, DX_TIME1, DY_TIME, 14 * 3, 14);
-
-  if (value < 1000)
-    DrawText(DX_TIME1 + xpos3, DY_TIME, int2str(value, 3), font1_nr);
-  else
-    DrawText(DX_TIME2 + xpos4, DY_TIME, int2str(value, 4), font2_nr);
-}
-
-void DrawGameValue_Level(int value)
-{
-  int font1_nr = FONT_TEXT_2;
-#if 1
-  int font2_nr = FONT_TEXT_1;
-#else
-  int font2_nr = FONT_LEVEL_NUMBER;
-#endif
-
-  if (PANEL_DEACTIVATED(game.panel.level))
-    return;
-
-  if (level_nr < 100)
-    DrawText(DX_LEVEL1, DY_LEVEL, int2str(value, 2), font1_nr);
-  else
-    DrawText(DX_LEVEL2, DY_LEVEL, int2str(value, 3), font2_nr);
-}
-
-void DrawGameValue_Keys(int key[MAX_NUM_KEYS])
-{
-  int base_key_graphic = EL_KEY_1;
-  int i;
-
-  if (PANEL_DEACTIVATED(game.panel.keys))
-    return;
-
-  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
-    base_key_graphic = EL_EM_KEY_1;
-
-  /* currently only 4 of 8 possible keys are displayed */
-  for (i = 0; i < STD_NUM_KEYS; i++)
-  {
-    int x = XX_KEYS + i * MINI_TILEX;
-    int y = YY_KEYS;
-
-    if (key[i])
-      DrawMiniGraphicExt(drawto, DX + x,DY + y, el2edimg(base_key_graphic + i));
-    else
-      BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
-		 DOOR_GFX_PAGEX5 + x, y, MINI_TILEX, MINI_TILEY, DX + x,DY + y);
-  }
-}
-
-#endif
-
-void DrawAllGameValues(int emeralds, int dynamite, int score, int time,
-		       int key_bits)
-{
-  int key[MAX_NUM_KEYS];
-  int i;
-
-  /* prevent EM engine from updating time/score values parallel to GameWon() */
-  if (level.game_engine_type == GAME_ENGINE_TYPE_EM &&
-      local_player->LevelSolved)
-    return;
-
-  for (i = 0; i < MAX_NUM_KEYS; i++)
-    key[i] = key_bits & (1 << i);
-
-  DrawGameValue_Level(level_nr);
-
-  DrawGameValue_Emeralds(emeralds);
-  DrawGameValue_Dynamite(dynamite);
-  DrawGameValue_Score(score);
-  DrawGameValue_Time(time);
-
-  DrawGameValue_Keys(key);
-}
-
-void UpdateGameDoorValues()
-{
-  UpdateGameControlValues();
-}
-
-void DrawGameDoorValues()
-{
-  DisplayGameControlValues();
-}
-
-void DrawGameDoorValues_OLD()
-{
-  int time_value = (level.time == 0 ? TimePlayed : TimeLeft);
-  int dynamite_value = 0;
-  int score_value = (local_player->LevelSolved ? local_player->score_final :
-		     local_player->score);
-  int gems_value = local_player->gems_still_needed;
-  int key_bits = 0;
-  int i, j;
-
-  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
-  {
-    DrawGameDoorValues_EM();
-
-    return;
-  }
-
-  if (game.centered_player_nr == -1)
-  {
-    for (i = 0; i < MAX_PLAYERS; i++)
-    {
-      for (j = 0; j < MAX_NUM_KEYS; j++)
-	if (stored_player[i].key[j])
-	  key_bits |= (1 << j);
-
-      dynamite_value += stored_player[i].inventory_size;
-    }
-  }
-  else
-  {
-    int player_nr = game.centered_player_nr;
-
-    for (i = 0; i < MAX_NUM_KEYS; i++)
-      if (stored_player[player_nr].key[i])
-	key_bits |= (1 << i);
-
-    dynamite_value = stored_player[player_nr].inventory_size;
-  }
-
-  DrawAllGameValues(gems_value, dynamite_value, score_value, time_value,
-		    key_bits);
-}
-
-
-/*
-  =============================================================================
-  InitGameEngine()
-  -----------------------------------------------------------------------------
-  initialize game engine due to level / tape version number
-  =============================================================================
-*/
-
-static void InitGameEngine()
-{
-  int i, j, k, l, x, y;
-
-  /* set game engine from tape file when re-playing, else from level file */
-  game.engine_version = (tape.playing ? tape.engine_version :
-			 level.game_version);
-
-  /* ---------------------------------------------------------------------- */
-  /* set flags for bugs and changes according to active game engine version */
-  /* ---------------------------------------------------------------------- */
-
-  /*
-    Summary of bugfix/change:
-    Fixed handling for custom elements that change when pushed by the player.
-
-    Fixed/changed in version:
-    3.1.0
-
-    Description:
-    Before 3.1.0, custom elements that "change when pushing" changed directly
-    after the player started pushing them (until then handled in "DigField()").
-    Since 3.1.0, these custom elements are not changed until the "pushing"
-    move of the element is finished (now handled in "ContinueMoving()").
-
-    Affected levels/tapes:
-    The first condition is generally needed for all levels/tapes before version
-    3.1.0, which might use the old behaviour before it was changed; known tapes
-    that are affected are some tapes from the level set "Walpurgis Gardens" by
-    Jamie Cullen.
-    The second condition is an exception from the above case and is needed for
-    the special case of tapes recorded with game (not engine!) version 3.1.0 or
-    above (including some development versions of 3.1.0), but before it was
-    known that this change would break tapes like the above and was fixed in
-    3.1.1, so that the changed behaviour was active although the engine version
-    while recording maybe was before 3.1.0. There is at least one tape that is
-    affected by this exception, which is the tape for the one-level set "Bug
-    Machine" by Juergen Bonhagen.
-  */
-
-  game.use_change_when_pushing_bug =
-    (game.engine_version < VERSION_IDENT(3,1,0,0) &&
-     !(tape.playing &&
-       tape.game_version >= VERSION_IDENT(3,1,0,0) &&
-       tape.game_version <  VERSION_IDENT(3,1,1,0)));
-
-  /*
-    Summary of bugfix/change:
-    Fixed handling for blocking the field the player leaves when moving.
-
-    Fixed/changed in version:
-    3.1.1
-
-    Description:
-    Before 3.1.1, when "block last field when moving" was enabled, the field
-    the player is leaving when moving was blocked for the time of the move,
-    and was directly unblocked afterwards. This resulted in the last field
-    being blocked for exactly one less than the number of frames of one player
-    move. Additionally, even when blocking was disabled, the last field was
-    blocked for exactly one frame.
-    Since 3.1.1, due to changes in player movement handling, the last field
-    is not blocked at all when blocking is disabled. When blocking is enabled,
-    the last field is blocked for exactly the number of frames of one player
-    move. Additionally, if the player is Murphy, the hero of Supaplex, the
-    last field is blocked for exactly one more than the number of frames of
-    one player move.
-
-    Affected levels/tapes:
-    (!!! yet to be determined -- probably many !!!)
-  */
-
-  game.use_block_last_field_bug =
-    (game.engine_version < VERSION_IDENT(3,1,1,0));
-
-  /*
-    Summary of bugfix/change:
-    Changed behaviour of CE changes with multiple changes per single frame.
-
-    Fixed/changed in version:
-    3.2.0-6
-
-    Description:
-    Before 3.2.0-6, only one single CE change was allowed in each engine frame.
-    This resulted in race conditions where CEs seem to behave strange in some
-    situations (where triggered CE changes were just skipped because there was
-    already a CE change on that tile in the playfield in that engine frame).
-    Since 3.2.0-6, this was changed to allow up to MAX_NUM_CHANGES_PER_FRAME.
-    (The number of changes per frame must be limited in any case, because else
-    it is easily possible to define CE changes that would result in an infinite
-    loop, causing the whole game to freeze. The MAX_NUM_CHANGES_PER_FRAME value
-    should be set large enough so that it would only be reached in cases where
-    the corresponding CE change conditions run into a loop. Therefore, it seems
-    to be reasonable to set MAX_NUM_CHANGES_PER_FRAME to the same value as the
-    maximal number of change pages for custom elements.)
-
-    Affected levels/tapes:
-    Probably many.
-  */
-
-#if USE_ONLY_ONE_CHANGE_PER_FRAME
-  game.max_num_changes_per_frame = 1;
-#else
-  game.max_num_changes_per_frame =
-    (game.engine_version < VERSION_IDENT(3,2,0,6) ? 1 : 32);
-#endif
-
-  /* ---------------------------------------------------------------------- */
-
-  /* default scan direction: scan playfield from top/left to bottom/right */
-  InitPlayfieldScanMode(CA_ARG_SCAN_MODE_NORMAL);
-
-  /* dynamically adjust element properties according to game engine version */
-  InitElementPropertiesEngine(game.engine_version);
-
-#if 0
-  printf("level %d: level version == %06d\n", level_nr, level.game_version);
-  printf("          tape version == %06d [%s] [file: %06d]\n",
-	 tape.engine_version, (tape.playing ? "PLAYING" : "RECORDING"),
-	 tape.file_version);
-  printf("       => game.engine_version == %06d\n", game.engine_version);
-#endif
-
-  /* ---------- initialize player's initial move delay --------------------- */
+  /* ---------- initialize player's initial move delay --------------------- */
 
   /* dynamically adjust player properties according to level information */
   for (i = 0; i < MAX_PLAYERS; i++)
@@ -3451,7 +2816,6 @@ static void InitGameEngine()
     }
   }
 
-#if 1
   /* ---------- initialize reference elements in change conditions --------- */
 
   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
@@ -3470,7 +2834,6 @@ static void InitGameEngine()
       ei->change_page[j].trigger_element = trigger_element;
     }
   }
-#endif
 
   /* ---------- initialize run-time trigger player and element ------------- */
 
@@ -3669,6 +3032,20 @@ static void InitGameEngine()
      setup.scroll_delay                   ? setup.scroll_delay_value       : 0);
   game.scroll_delay_value =
     MIN(MAX(MIN_SCROLL_DELAY, game.scroll_delay_value), MAX_SCROLL_DELAY);
+
+  /* ---------- initialize game engine snapshots ---------------------------- */
+  for (i = 0; i < MAX_PLAYERS; i++)
+    game.snapshot.last_action[i] = 0;
+  game.snapshot.changed_action = FALSE;
+  game.snapshot.collected_item = FALSE;
+  game.snapshot.mode =
+    (strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_STEP) ?
+     SNAPSHOT_MODE_EVERY_STEP :
+     strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_MOVE) ?
+     SNAPSHOT_MODE_EVERY_MOVE :
+     strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_COLLECT) ?
+     SNAPSHOT_MODE_EVERY_COLLECT : SNAPSHOT_MODE_OFF);
+  game.snapshot.save_snapshot = FALSE;
 }
 
 int get_num_special_action(int element, int action_first, int action_last)
@@ -3705,29 +3082,46 @@ int get_num_special_action(int element, int action_first, int action_last)
 
 void InitGame()
 {
+  int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0);
+  int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0);
+  int fade_mask = REDRAW_FIELD;
+
   boolean emulate_bd = TRUE;	/* unless non-BOULDERDASH elements found */
   boolean emulate_sb = TRUE;	/* unless non-SOKOBAN     elements found */
   boolean emulate_sp = TRUE;	/* unless non-SUPAPLEX    elements found */
-#if 0
-  boolean do_fading = (game_status == GAME_MODE_MAIN);
-#endif
-#if 1
   int initial_move_dir = MV_DOWN;
-#else
-  int initial_move_dir = MV_NONE;
-#endif
   int i, j, x, y;
 
-  game_status = GAME_MODE_PLAYING;
+  // required here to update video display before fading (FIX THIS)
+  DrawMaskedBorder(REDRAW_DOOR_2);
+
+  if (!game.restart_level)
+    CloseDoor(DOOR_CLOSE_1);
+
+  SetGameStatus(GAME_MODE_PLAYING);
+
+  if (level_editor_test_game)
+    FadeSkipNextFadeIn();
+  else
+    FadeSetEnterScreen();
+
+  if (CheckIfGlobalBorderHasChanged())
+    fade_mask = REDRAW_ALL;
+
+  FadeSoundsAndMusic();
+
+  ExpireSoundLoops(TRUE);
+
+  FadeOut(fade_mask);
 
-#if 1
   /* needed if different viewport properties defined for playing */
   ChangeViewportPropertiesIfNeeded();
-#endif
 
-#if 1
+  ClearField();
+
+  OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
+
   DrawCompleteVideoDisplay();
-#endif
 
   InitGameEngine();
   InitGameControlValues();
@@ -3815,6 +3209,11 @@ void InitGame()
     player->is_bored = FALSE;
     player->is_sleeping = FALSE;
 
+    player->was_waiting = TRUE;
+    player->was_moving = FALSE;
+    player->was_snapping = FALSE;
+    player->was_dropping = FALSE;
+
     player->frame_counter_bored = -1;
     player->frame_counter_sleeping = -1;
 
@@ -3916,6 +3315,8 @@ void InitGame()
 
   AllPlayersGone = FALSE;
 
+  game.no_time_limit = (level.time == 0);
+
   game.yamyam_content_nr = 0;
   game.robot_wheel_active = FALSE;
   game.magic_wall_active = FALSE;
@@ -3925,11 +3326,6 @@ void InitGame()
   game.switchgate_pos = 0;
   game.wind_direction = level.wind_direction_initial;
 
-#if !USE_PLAYER_GRAVITY
-  game.gravity = FALSE;
-  game.explosions_delayed = TRUE;
-#endif
-
   game.lenses_time_left = 0;
   game.magnify_time_left = 0;
 
@@ -3959,15 +3355,20 @@ void InitGame()
   for (i = 0; i < MAX_NUM_AMOEBA; i++)
     AmoebaCnt[i] = AmoebaCnt2[i] = 0;
 
+#if DEBUG_INIT_PLAYER
+  if (options.debug)
+  {
+    printf("Player status at level initialization:\n");
+  }
+#endif
+
   SCAN_PLAYFIELD(x, y)
   {
     Feld[x][y] = level.field[x][y];
     MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
     ChangeDelay[x][y] = 0;
     ChangePage[x][y] = -1;
-#if USE_NEW_CUSTOM_VALUE
     CustomValue[x][y] = 0;		/* initialized in InitField() */
-#endif
     Store[x][y] = Store2[x][y] = StorePlayer[x][y] = Back[x][y] = 0;
     AmoebaNr[x][y] = 0;
     WasJustMoving[x][y] = 0;
@@ -4028,7 +3429,6 @@ void InitGame()
 		    emulate_sb ? EMU_SOKOBAN :
 		    emulate_sp ? EMU_SUPAPLEX : EMU_NONE);
 
-#if USE_NEW_ALL_SLIPPERY
   /* initialize type of slippery elements */
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
   {
@@ -4046,7 +3446,6 @@ void InitGame()
 	element_info[i].slippery_type = SLIPPERY_ANY_LEFT_RIGHT;
     }
   }
-#endif
 
   /* initialize explosion and ignition delay */
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
@@ -4066,14 +3465,6 @@ void InitGame()
       if (i == EL_BLACK_ORB)
 	element_info[i].ignition_delay = 1;
     }
-
-#if 0
-    if (element_info[i].explosion_delay < 1)	/* !!! check again !!! */
-      element_info[i].explosion_delay = 1;
-
-    if (element_info[i].ignition_delay < 1)	/* !!! check again !!! */
-      element_info[i].ignition_delay = 1;
-#endif
   }
 
   /* correct non-moving belts to start moving left */
@@ -4094,14 +3485,10 @@ void InitGame()
 
   if (tape.playing)
   {
-    /* try to guess locally connected team mode players (needed for correct
-       assignment of player figures from level to locally playing players) */
-
     for (i = 0; i < MAX_PLAYERS; i++)
-      if (tape.player_participates[i])
-	stored_player[i].connected = TRUE;
+      stored_player[i].connected = tape.player_participates[i];
   }
-  else if (setup.team_mode && !options.network)
+  else if (game.team_mode && !options.network)
   {
     /* try to guess locally connected team mode players (needed for correct
        assignment of player figures from level to locally playing players) */
@@ -4112,14 +3499,32 @@ void InitGame()
 	stored_player[i].connected = TRUE;
   }
 
-#if 0
-  for (i = 0; i < MAX_PLAYERS; i++)
-    printf("::: player %d: %s\n", i,
-	   (stored_player[i].connected ? "connected" : "not connected"));
+#if DEBUG_INIT_PLAYER
+  if (options.debug)
+  {
+    printf("Player status after level initialization:\n");
 
-  for (i = 0; i < MAX_PLAYERS; i++)
-    printf("::: player %d: %s\n", i,
-	   (stored_player[i].present ? "present" : "not present"));
+    for (i = 0; i < MAX_PLAYERS; i++)
+    {
+      struct PlayerInfo *player = &stored_player[i];
+
+      printf("- player %d: present == %d, connected == %d, active == %d",
+	     i + 1,
+	     player->present,
+	     player->connected,
+	     player->active);
+
+      if (local_player == player)
+	printf(" (local player)");
+
+      printf("\n");
+    }
+  }
+#endif
+
+#if DEBUG_INIT_PLAYER
+  if (options.debug)
+    printf("Reassigning players ...\n");
 #endif
 
   /* check if any connected player was not found in playfield */
@@ -4131,33 +3536,35 @@ void InitGame()
     {
       struct PlayerInfo *field_player = NULL;
 
-#if 0
-      printf("::: looking for field player for player %d ...\n", i);
+#if DEBUG_INIT_PLAYER
+      if (options.debug)
+	printf("- looking for field player for player %d ...\n", i + 1);
 #endif
 
       /* assign first free player found that is present in the playfield */
 
       /* first try: look for unmapped playfield player that is not connected */
-      if (field_player == NULL)
-	for (j = 0; j < MAX_PLAYERS; j++)
-	  if (stored_player[j].present &&
-	      !stored_player[j].mapped &&
-	      !stored_player[j].connected)
-	    field_player = &stored_player[j];
+      for (j = 0; j < MAX_PLAYERS; j++)
+	if (field_player == NULL &&
+	    stored_player[j].present &&
+	    !stored_player[j].mapped &&
+	    !stored_player[j].connected)
+	  field_player = &stored_player[j];
 
       /* second try: look for *any* unmapped playfield player */
-      if (field_player == NULL)
-	for (j = 0; j < MAX_PLAYERS; j++)
-	  if (stored_player[j].present &&
-	      !stored_player[j].mapped)
-	    field_player = &stored_player[j];
+      for (j = 0; j < MAX_PLAYERS; j++)
+	if (field_player == NULL &&
+	    stored_player[j].present &&
+	    !stored_player[j].mapped)
+	  field_player = &stored_player[j];
 
       if (field_player != NULL)
       {
 	int jx = field_player->jx, jy = field_player->jy;
 
-#if 0
-	printf("::: found player figure %d\n", field_player->index_nr);
+#if DEBUG_INIT_PLAYER
+	if (options.debug)
+	  printf("- found player %d\n", field_player->index_nr + 1);
 #endif
 
 	player->present = FALSE;
@@ -4186,9 +3593,10 @@ void InitGame()
 
 	field_player->mapped = TRUE;
 
-#if 0
-	printf("::: map_player_action[%d] == %d\n",
-	       field_player->index_nr, i);
+#if DEBUG_INIT_PLAYER
+	if (options.debug)
+	  printf("- map_player_action[%d] == %d\n",
+		 field_player->index_nr + 1, i + 1);
 #endif
       }
     }
@@ -4197,6 +3605,29 @@ void InitGame()
       player->mapped = TRUE;
   }
 
+#if DEBUG_INIT_PLAYER
+  if (options.debug)
+  {
+    printf("Player status after player assignment (first stage):\n");
+
+    for (i = 0; i < MAX_PLAYERS; i++)
+    {
+      struct PlayerInfo *player = &stored_player[i];
+
+      printf("- player %d: present == %d, connected == %d, active == %d",
+	     i + 1,
+	     player->present,
+	     player->connected,
+	     player->active);
+
+      if (local_player == player)
+	printf(" (local player)");
+
+      printf("\n");
+    }
+  }
+#endif
+
 #else
 
   /* check if any connected player was not found in playfield */
@@ -4247,20 +3678,31 @@ void InitGame()
     /* when playing a tape, eliminate all players who do not participate */
 
 #if USE_NEW_PLAYER_ASSIGNMENTS
-    for (i = 0; i < MAX_PLAYERS; i++)
+
+    if (!game.team_mode)
     {
-      if (stored_player[i].active &&
-	  !tape.player_participates[map_player_action[i]])
+      for (i = 0; i < MAX_PLAYERS; i++)
       {
-	struct PlayerInfo *player = &stored_player[i];
-	int jx = player->jx, jy = player->jy;
+	if (stored_player[i].active &&
+	    !tape.player_participates[map_player_action[i]])
+	{
+	  struct PlayerInfo *player = &stored_player[i];
+	  int jx = player->jx, jy = player->jy;
 
-	player->active = FALSE;
-	StorePlayer[jx][jy] = 0;
-	Feld[jx][jy] = EL_EMPTY;
+#if DEBUG_INIT_PLAYER
+	  if (options.debug)
+	    printf("Removing player %d at (%d, %d)\n", i + 1, jx, jy);
+#endif
+
+	  player->active = FALSE;
+	  StorePlayer[jx][jy] = 0;
+	  Feld[jx][jy] = EL_EMPTY;
+	}
       }
     }
+
 #else
+
     for (i = 0; i < MAX_PLAYERS; i++)
     {
       if (stored_player[i].active &&
@@ -4276,7 +3718,7 @@ void InitGame()
     }
 #endif
   }
-  else if (!options.network && !setup.team_mode)	/* && !tape.playing */
+  else if (!options.network && !game.team_mode)		/* && !tape.playing */
   {
     /* when in single player mode, eliminate all but the first active player */
 
@@ -4316,21 +3758,28 @@ void InitGame()
 #endif
   }
 
+#if DEBUG_INIT_PLAYER
   if (options.debug)
   {
+    printf("Player status after player assignment (final stage):\n");
+
     for (i = 0; i < MAX_PLAYERS; i++)
     {
       struct PlayerInfo *player = &stored_player[i];
 
-      printf("Player %d: present == %d, connected == %d, active == %d.\n",
-	     i+1,
+      printf("- player %d: present == %d, connected == %d, active == %d",
+	     i + 1,
 	     player->present,
 	     player->connected,
 	     player->active);
+
       if (local_player == player)
-	printf("Player 	%d is local player.\n", i+1);
+	printf(" (local player)");
+
+      printf("\n");
     }
   }
+#endif
 
   if (BorderElement == EL_EMPTY)
   {
@@ -4347,12 +3796,16 @@ void InitGame()
     SBY_Lower = lev_fieldy - SCR_FIELDY + 1;
   }
 
-  if (lev_fieldx + (SBX_Left == -1 ? 2 : 0) <= SCR_FIELDX)
+  if (full_lev_fieldx <= SCR_FIELDX)
     SBX_Left = SBX_Right = -1 * (SCR_FIELDX - lev_fieldx) / 2;
-
-  if (lev_fieldy + (SBY_Upper == -1 ? 2 : 0) <= SCR_FIELDY)
+  if (full_lev_fieldy <= SCR_FIELDY)
     SBY_Upper = SBY_Lower = -1 * (SCR_FIELDY - lev_fieldy) / 2;
 
+  if (EVEN(SCR_FIELDX) && full_lev_fieldx > SCR_FIELDX)
+    SBX_Left--;
+  if (EVEN(SCR_FIELDY) && full_lev_fieldy > SCR_FIELDY)
+    SBY_Upper--;
+
   /* if local player not found, look for custom element that might create
      the player (make some assumptions about the right custom element) */
   if (!local_player->present)
@@ -4462,110 +3915,73 @@ void InitGame()
 		local_player->jy - MIDPOSY);
   }
 
-#if 0
-  /* do not use PLAYING mask for fading out from main screen */
-  game_status = GAME_MODE_MAIN;
-#endif
-
-  StopAnimation();
-
-  if (!game.restart_level)
-    CloseDoor(DOOR_CLOSE_1);
-
-#if 1
-  if (level_editor_test_game)
-    FadeSkipNextFadeIn();
-  else
-    FadeSetEnterScreen();
-#else
-  if (level_editor_test_game)
-    fading = fading_none;
-  else
-    fading = menu.destination;
-#endif
-
-#if 1
-  FadeOut(REDRAW_FIELD);
-#else
-  if (do_fading)
-    FadeOut(REDRAW_FIELD);
-#endif
-
-#if 0
-  game_status = GAME_MODE_PLAYING;
-#endif
-
   /* !!! FIX THIS (START) !!! */
   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
   {
     InitGameEngine_EM();
-
-    /* blit playfield from scroll buffer to normal back buffer for fading in */
-    BlitScreenToBitmap_EM(backbuffer);
   }
   else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
   {
     InitGameEngine_SP();
-
-    /* blit playfield from scroll buffer to normal back buffer for fading in */
-    BlitScreenToBitmap_SP(backbuffer);
   }
   else
   {
-    DrawLevel();
+    DrawLevel(REDRAW_FIELD);
     DrawAllPlayers();
 
     /* after drawing the level, correct some elements */
     if (game.timegate_time_left == 0)
       CloseAllOpenTimegates();
-
-    /* blit playfield from scroll buffer to normal back buffer for fading in */
-    if (setup.soft_scrolling)
-      BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
-
-    redraw_mask |= REDRAW_FROM_BACKBUFFER;
   }
+
+  /* blit playfield from scroll buffer to normal back buffer for fading in */
+  BlitScreenToBitmap(backbuffer);
   /* !!! FIX THIS (END) !!! */
 
-#if 1
-  FadeIn(REDRAW_FIELD);
-#else
-  if (do_fading)
-    FadeIn(REDRAW_FIELD);
+  DrawMaskedBorder(fade_mask);
+
+  FadeIn(fade_mask);
 
+#if 1
+  // full screen redraw is required at this point in the following cases:
+  // - special editor door undrawn when game was started from level editor
+  // - drawing area (playfield) was changed and has to be removed completely
+  redraw_mask = REDRAW_ALL;
   BackToFront();
 #endif
 
   if (!game.restart_level)
   {
     /* copy default game door content to main double buffer */
-    BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
-	       DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY);
+
+    /* !!! CHECK AGAIN !!! */
+    SetPanelBackground();
+    // SetDoorBackgroundImage(IMG_BACKGROUND_PANEL);
+    DrawBackground(DX, DY, DXSIZE, DYSIZE);
   }
 
   SetPanelBackground();
   SetDrawBackgroundMask(REDRAW_DOOR_1);
 
-#if 1
   UpdateAndDisplayGameControlValues();
-#else
-  UpdateGameDoorValues();
-  DrawGameDoorValues();
-#endif
 
   if (!game.restart_level)
   {
     UnmapGameButtons();
     UnmapTapeButtons();
+
+    FreeGameButtons();
+    CreateGameButtons();
+
     game_gadget[SOUND_CTRL_ID_MUSIC]->checked = setup.sound_music;
     game_gadget[SOUND_CTRL_ID_LOOPS]->checked = setup.sound_loops;
     game_gadget[SOUND_CTRL_ID_SIMPLE]->checked = setup.sound_simple;
+
     MapGameButtons();
     MapTapeButtons();
 
     /* copy actual game door content to door double buffer for OpenDoor() */
-    BlitBitmap(drawto, bitmap_db_door,
-	       DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+    BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0);
 
     OpenDoor(DOOR_OPEN_ALL);
 
@@ -4576,31 +3992,65 @@ void InitGame()
 
     KeyboardAutoRepeatOffUnlessAutoplay();
 
+#if DEBUG_INIT_PLAYER
     if (options.debug)
     {
+      printf("Player status (final):\n");
+
       for (i = 0; i < MAX_PLAYERS; i++)
-	printf("Player %d %sactive.\n",
-	       i + 1, (stored_player[i].active ? "" : "not "));
+      {
+	struct PlayerInfo *player = &stored_player[i];
+
+	printf("- player %d: present == %d, connected == %d, active == %d",
+	       i + 1,
+	       player->present,
+	       player->connected,
+	       player->active);
+
+	if (local_player == player)
+	  printf(" (local player)");
+
+	printf("\n");
+      }
     }
+#endif
   }
 
-#if 1
   UnmapAllGadgets();
 
   MapGameButtons();
   MapTapeButtons();
-#endif
+
+  if (!game.restart_level && !tape.playing)
+  {
+    LevelStats_incPlayed(level_nr);
+
+    SaveLevelSetup_SeriesInfo();
+  }
 
   game.restart_level = FALSE;
+
+  SaveEngineSnapshotToListInitial();
 }
 
-void UpdateEngineValues(int actual_scroll_x, int actual_scroll_y)
+void UpdateEngineValues(int actual_scroll_x, int actual_scroll_y,
+			int actual_player_x, int actual_player_y)
 {
   /* this is used for non-R'n'D game engines to update certain engine values */
 
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+  {
+    actual_player_x = correctLevelPosX_EM(actual_player_x);
+    actual_player_y = correctLevelPosY_EM(actual_player_y);
+  }
+
   /* needed to determine if sounds are played within the visible screen area */
   scroll_x = actual_scroll_x;
   scroll_y = actual_scroll_y;
+
+  /* needed to get player position for "follow finger" playing input method */
+  local_player->jx = actual_player_x;
+  local_player->jy = actual_player_y;
 }
 
 void InitMovDir(int x, int y)
@@ -4809,7 +4259,8 @@ static void PlayerWins(struct PlayerInfo *player)
   player->score_final = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
 			 level.native_em_level->lev->score : player->score);
 
-  player->LevelSolved_CountingTime = (level.time == 0 ? TimePlayed : TimeLeft);
+  player->LevelSolved_CountingTime = (game.no_time_limit ? TimePlayed :
+				      TimeLeft);
   player->LevelSolved_CountingScore = player->score_final;
 }
 
@@ -4834,17 +4285,22 @@ void GameWon()
     local_player->LevelSolved_SaveTape = tape.recording;
     local_player->LevelSolved_SaveScore = !tape.playing;
 
+    if (!tape.playing)
+    {
+      LevelStats_incSolved(level_nr);
+
+      SaveLevelSetup_SeriesInfo();
+    }
+
     if (tape.auto_play)		/* tape might already be stopped here */
       tape.auto_play_level_solved = TRUE;
 
-#if 1
     TapeStop();
-#endif
 
     game_over_delay_1 = game_over_delay_value_1;
     game_over_delay_2 = game_over_delay_value_2;
 
-    time = time_final = (level.time == 0 ? TimePlayed : TimeLeft);
+    time = time_final = (game.no_time_limit ? TimePlayed : TimeLeft);
     score = score_final = local_player->score_final;
 
     if (TimeLeft > 0)
@@ -4852,7 +4308,7 @@ void GameWon()
       time_final = 0;
       score_final += TimeLeft * level.score[SC_TIME_BONUS];
     }
-    else if (level.time == 0 && TimePlayed < 999)
+    else if (game.no_time_limit && TimePlayed < 999)
     {
       time_final = 999;
       score_final += (999 - TimePlayed) * level.score[SC_TIME_BONUS];
@@ -4865,7 +4321,6 @@ void GameWon()
       time = time_final;
       score = score_final;
 
-#if 1
       local_player->LevelSolved_CountingTime = time;
       local_player->LevelSolved_CountingScore = score;
 
@@ -4873,10 +4328,6 @@ void GameWon()
       game_panel_controls[GAME_PANEL_SCORE].value = score;
 
       DisplayGameControlValues();
-#else
-      DrawGameValue_Time(time);
-      DrawGameValue_Score(score);
-#endif
     }
 
     if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
@@ -4893,24 +4344,14 @@ void GameWon()
 	{
 	  int element = Feld[ExitX][ExitY];
 
-#if 0
-	  if (element == EL_EM_EXIT_OPEN ||
-	      element == EL_EM_STEEL_EXIT_OPEN)
-	  {
-	    Bang(ExitX, ExitY);
-	  }
-	  else
-#endif
-	  {
-	    Feld[ExitX][ExitY] =
-	      (element == EL_EXIT_OPEN		? EL_EXIT_CLOSING :
-	       element == EL_EM_EXIT_OPEN	? EL_EM_EXIT_CLOSING :
-	       element == EL_SP_EXIT_OPEN	? EL_SP_EXIT_CLOSING:
-	       element == EL_STEEL_EXIT_OPEN	? EL_STEEL_EXIT_CLOSING:
-	       EL_EM_STEEL_EXIT_CLOSING);
-
-	    PlayLevelSoundElementAction(ExitX, ExitY, element, ACTION_CLOSING);
-	  }
+	  Feld[ExitX][ExitY] =
+	    (element == EL_EXIT_OPEN		? EL_EXIT_CLOSING :
+	     element == EL_EM_EXIT_OPEN	? EL_EM_EXIT_CLOSING :
+	     element == EL_SP_EXIT_OPEN	? EL_SP_EXIT_CLOSING:
+	     element == EL_STEEL_EXIT_OPEN	? EL_STEEL_EXIT_CLOSING:
+	     EL_EM_STEEL_EXIT_CLOSING);
+
+	  PlayLevelSoundElementAction(ExitX, ExitY, element, ACTION_CLOSING);
 	}
 
 	/* player disappears */
@@ -4950,7 +4391,6 @@ void GameWon()
     time  += time_count_steps * time_count_dir;
     score += time_count_steps * level.score[SC_TIME_BONUS];
 
-#if 1
     local_player->LevelSolved_CountingTime = time;
     local_player->LevelSolved_CountingScore = score;
 
@@ -4958,10 +4398,6 @@ void GameWon()
     game_panel_controls[GAME_PANEL_SCORE].value = score;
 
     DisplayGameControlValues();
-#else
-    DrawGameValue_Time(time);
-    DrawGameValue_Score(score);
-#endif
 
     if (time == time_final)
       StopSound(SND_GAME_LEVELTIME_BONUS);
@@ -4982,9 +4418,7 @@ void GameWon()
     return;
   }
 
-#if 1
   GameEnd();
-#endif
 }
 
 void GameEnd()
@@ -4994,43 +4428,30 @@ void GameEnd()
 
   local_player->LevelSolved_GameEnd = TRUE;
 
-  CloseDoor(DOOR_CLOSE_1);
+  if (!global.use_envelope_request)
+    CloseDoor(DOOR_CLOSE_1);
 
   if (local_player->LevelSolved_SaveTape)
   {
-#if 0
-    TapeStop();
-#endif
-
-#if 1
     SaveTapeChecked(tape.level_nr);	/* ask to save tape */
-#else
-    SaveTape(tape.level_nr);		/* ask to save tape */
-#endif
   }
 
+  CloseDoor(DOOR_CLOSE_ALL);
+
   if (level_editor_test_game)
   {
-    game_status = GAME_MODE_MAIN;
+    SetGameStatus(GAME_MODE_MAIN);
 
-#if 1
-    DrawAndFadeInMainMenu(REDRAW_FIELD);
-#else
     DrawMainMenu();
-#endif
 
     return;
   }
 
   if (!local_player->LevelSolved_SaveScore)
   {
-#if 1
-    FadeOut(REDRAW_FIELD);
-#endif
-
-    game_status = GAME_MODE_MAIN;
+    SetGameStatus(GAME_MODE_MAIN);
 
-    DrawAndFadeInMainMenu(REDRAW_FIELD);
+    DrawMainMenu();
 
     return;
   }
@@ -5038,6 +4459,7 @@ void GameEnd()
   if (level_nr == leveldir_current->handicap_level)
   {
     leveldir_current->handicap_level++;
+
     SaveLevelSetup_SeriesInfo();
   }
 
@@ -5046,7 +4468,7 @@ void GameEnd()
 
   if ((hi_pos = NewHiScore()) >= 0) 
   {
-    game_status = GAME_MODE_SCORES;
+    SetGameStatus(GAME_MODE_SCORES);
 
     DrawHallOfFame(hi_pos);
 
@@ -5058,11 +4480,7 @@ void GameEnd()
   }
   else
   {
-#if 1
-    FadeOut(REDRAW_FIELD);
-#endif
-
-    game_status = GAME_MODE_MAIN;
+    SetGameStatus(GAME_MODE_MAIN);
 
     if (raise_level)
     {
@@ -5070,7 +4488,7 @@ void GameEnd()
       TapeErase();
     }
 
-    DrawAndFadeInMainMenu(REDRAW_FIELD);
+    DrawMainMenu();
   }
 }
 
@@ -5165,11 +4583,6 @@ void InitPlayerGfxAnimation(struct PlayerInfo *player, int action, int dir)
 {
   if (player->GfxAction != action || player->GfxDir != dir)
   {
-#if 0
-    printf("Player frame reset! (%d => %d, %d => %d)\n",
-	   player->GfxAction, action, player->GfxDir, dir);
-#endif
-
     player->GfxAction = action;
     player->GfxDir = dir;
     player->Frame = 0;
@@ -5177,12 +4590,10 @@ void InitPlayerGfxAnimation(struct PlayerInfo *player, int action, int dir)
   }
 }
 
-#if USE_GFX_RESET_GFX_ANIMATION
-static void ResetGfxFrame(int x, int y, boolean redraw)
+static void ResetGfxFrame(int x, int y)
 {
   int element = Feld[x][y];
   int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
-  int last_gfx_frame = GfxFrame[x][y];
 
   if (graphic_info[graphic].anim_global_sync)
     GfxFrame[x][y] = FrameCounter;
@@ -5192,11 +4603,7 @@ static void ResetGfxFrame(int x, int y, boolean redraw)
     GfxFrame[x][y] = element_info[element].collect_score;
   else if (ANIM_MODE(graphic) == ANIM_CE_DELAY)
     GfxFrame[x][y] = ChangeDelay[x][y];
-
-  if (redraw && GfxFrame[x][y] != last_gfx_frame)
-    DrawLevelGraphicAnimation(x, y, graphic);
 }
-#endif
 
 static void ResetGfxAnimation(int x, int y)
 {
@@ -5204,9 +4611,7 @@ static void ResetGfxAnimation(int x, int y)
   GfxDir[x][y] = MovDir[x][y];
   GfxFrame[x][y] = 0;
 
-#if USE_GFX_RESET_GFX_ANIMATION
-  ResetGfxFrame(x, y, FALSE);
-#endif
+  ResetGfxFrame(x, y);
 }
 
 static void ResetRandomAnimationValue(int x, int y)
@@ -5222,51 +4627,24 @@ void InitMovingField(int x, int y, int direction)
   int newx = x + dx;
   int newy = y + dy;
   boolean is_moving_before, is_moving_after;
-#if 0
-  boolean continues_moving = (WasJustMoving[x][y] && direction == MovDir[x][y]);
-#endif
 
   /* check if element was/is moving or being moved before/after mode change */
-#if 1
-#if 1
   is_moving_before = (WasJustMoving[x][y] != 0);
-#else
-  /* (!!! this does not work -- WasJustMoving is NOT a boolean value !!!) */
-  is_moving_before = WasJustMoving[x][y];
-#endif
-#else
-  is_moving_before = (getElementMoveStepsizeExt(x, y, MovDir[x][y]) != 0);
-#endif
   is_moving_after  = (getElementMoveStepsizeExt(x, y, direction)    != 0);
 
   /* reset animation only for moving elements which change direction of moving
      or which just started or stopped moving
      (else CEs with property "can move" / "not moving" are reset each frame) */
-#if USE_GFX_RESET_ONLY_WHEN_MOVING
-#if 1
   if (is_moving_before != is_moving_after ||
       direction != MovDir[x][y])
     ResetGfxAnimation(x, y);
-#else
-  if ((is_moving_before || is_moving_after) && !continues_moving)
-    ResetGfxAnimation(x, y);
-#endif
-#else
-  if (!continues_moving)
-    ResetGfxAnimation(x, y);
-#endif
 
   MovDir[x][y] = direction;
   GfxDir[x][y] = direction;
 
-#if USE_GFX_RESET_ONLY_WHEN_MOVING
   GfxAction[x][y] = (!is_moving_after ? ACTION_WAITING :
 		     direction == MV_DOWN && CAN_FALL(element) ?
 		     ACTION_FALLING : ACTION_MOVING);
-#else
-  GfxAction[x][y] = (direction == MV_DOWN && CAN_FALL(element) ?
-		     ACTION_FALLING : ACTION_MOVING);
-#endif
 
   /* this is needed for CEs with property "can move" / "not moving" */
 
@@ -5277,9 +4655,7 @@ void InitMovingField(int x, int y, int direction)
 
     MovDir[newx][newy] = MovDir[x][y];
 
-#if USE_NEW_CUSTOM_VALUE
     CustomValue[newx][newy] = CustomValue[x][y];
-#endif
 
     GfxFrame[newx][newy] = GfxFrame[x][y];
     GfxRandom[newx][newy] = GfxRandom[x][y];
@@ -5362,26 +4738,16 @@ static void RemoveField(int x, int y)
   MovDir[x][y] = 0;
   MovDelay[x][y] = 0;
 
-#if USE_NEW_CUSTOM_VALUE
   CustomValue[x][y] = 0;
-#endif
 
   AmoebaNr[x][y] = 0;
   ChangeDelay[x][y] = 0;
   ChangePage[x][y] = -1;
   Pushed[x][y] = FALSE;
 
-#if 0
-  ExplodeField[x][y] = EX_TYPE_NONE;
-#endif
-
   GfxElement[x][y] = EL_UNDEFINED;
   GfxAction[x][y] = ACTION_DEFAULT;
   GfxDir[x][y] = MV_NONE;
-#if 0
-  /* !!! this would prevent the removed tile from being redrawn !!! */
-  GfxRedraw[x][y] = GFX_REDRAW_NONE;
-#endif
 }
 
 void RemoveMovingField(int x, int y)
@@ -5538,204 +4904,107 @@ static void setScreenCenteredToAllPlayers(int *sx, int *sy)
 void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir,
 			boolean center_screen, boolean quick_relocation)
 {
+  unsigned int frame_delay_value_old = GetVideoFrameDelay();
   boolean ffwd_delay = (tape.playing && tape.fast_forward);
   boolean no_delay = (tape.warp_forward);
   int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
   int wait_delay_value = (no_delay ? 0 : frame_delay_value);
+  int new_scroll_x, new_scroll_y;
 
-  if (quick_relocation)
+  if (level.lazy_relocation && IN_VIS_FIELD(SCREENX(x), SCREENY(y)))
   {
-    if (!IN_VIS_FIELD(SCREENX(x), SCREENY(y)) || center_screen)
-    {
-      if (!level.shifted_relocation || center_screen)
-      {
-	/* quick relocation (without scrolling), with centering of screen */
-
-	scroll_x = (x < SBX_Left  + MIDPOSX ? SBX_Left :
-		    x > SBX_Right + MIDPOSX ? SBX_Right :
-		    x - MIDPOSX);
-
-	scroll_y = (y < SBY_Upper + MIDPOSY ? SBY_Upper :
-		    y > SBY_Lower + MIDPOSY ? SBY_Lower :
-		    y - MIDPOSY);
-      }
-      else
-      {
-	/* quick relocation (without scrolling), but do not center screen */
+    /* case 1: quick relocation inside visible screen (without scrolling) */
 
-	int center_scroll_x = (old_x < SBX_Left  + MIDPOSX ? SBX_Left :
-			       old_x > SBX_Right + MIDPOSX ? SBX_Right :
-			       old_x - MIDPOSX);
+    RedrawPlayfield();
 
-	int center_scroll_y = (old_y < SBY_Upper + MIDPOSY ? SBY_Upper :
-			       old_y > SBY_Lower + MIDPOSY ? SBY_Lower :
-			       old_y - MIDPOSY);
-
-	int offset_x = x + (scroll_x - center_scroll_x);
-	int offset_y = y + (scroll_y - center_scroll_y);
-
-	scroll_x = (offset_x < SBX_Left  + MIDPOSX ? SBX_Left :
-		    offset_x > SBX_Right + MIDPOSX ? SBX_Right :
-		    offset_x - MIDPOSX);
+    return;
+  }
 
-	scroll_y = (offset_y < SBY_Upper + MIDPOSY ? SBY_Upper :
-		    offset_y > SBY_Lower + MIDPOSY ? SBY_Lower :
-		    offset_y - MIDPOSY);
-      }
-    }
-    else
-    {
-#if 1
-      if (!level.shifted_relocation || center_screen)
-      {
-	/* quick relocation (without scrolling), with centering of screen */
+  if (!level.shifted_relocation || center_screen)
+  {
+    /* relocation _with_ centering of screen */
 
-	scroll_x = (x < SBX_Left  + MIDPOSX ? SBX_Left :
+    new_scroll_x = (x < SBX_Left  + MIDPOSX ? SBX_Left :
 		    x > SBX_Right + MIDPOSX ? SBX_Right :
 		    x - MIDPOSX);
 
-	scroll_y = (y < SBY_Upper + MIDPOSY ? SBY_Upper :
+    new_scroll_y = (y < SBY_Upper + MIDPOSY ? SBY_Upper :
 		    y > SBY_Lower + MIDPOSY ? SBY_Lower :
 		    y - MIDPOSY);
-      }
-      else
-      {
-	/* quick relocation (without scrolling), but do not center screen */
+  }
+  else
+  {
+    /* relocation _without_ centering of screen */
 
-	int center_scroll_x = (old_x < SBX_Left  + MIDPOSX ? SBX_Left :
-			       old_x > SBX_Right + MIDPOSX ? SBX_Right :
-			       old_x - MIDPOSX);
+    int center_scroll_x = (old_x < SBX_Left  + MIDPOSX ? SBX_Left :
+			   old_x > SBX_Right + MIDPOSX ? SBX_Right :
+			   old_x - MIDPOSX);
 
-	int center_scroll_y = (old_y < SBY_Upper + MIDPOSY ? SBY_Upper :
-			       old_y > SBY_Lower + MIDPOSY ? SBY_Lower :
-			       old_y - MIDPOSY);
+    int center_scroll_y = (old_y < SBY_Upper + MIDPOSY ? SBY_Upper :
+			   old_y > SBY_Lower + MIDPOSY ? SBY_Lower :
+			   old_y - MIDPOSY);
 
-	int offset_x = x + (scroll_x - center_scroll_x);
-	int offset_y = y + (scroll_y - center_scroll_y);
+    int offset_x = x + (scroll_x - center_scroll_x);
+    int offset_y = y + (scroll_y - center_scroll_y);
 
-	scroll_x = (offset_x < SBX_Left  + MIDPOSX ? SBX_Left :
+    new_scroll_x = (offset_x < SBX_Left  + MIDPOSX ? SBX_Left :
 		    offset_x > SBX_Right + MIDPOSX ? SBX_Right :
 		    offset_x - MIDPOSX);
 
-	scroll_y = (offset_y < SBY_Upper + MIDPOSY ? SBY_Upper :
+    new_scroll_y = (offset_y < SBY_Upper + MIDPOSY ? SBY_Upper :
 		    offset_y > SBY_Lower + MIDPOSY ? SBY_Lower :
 		    offset_y - MIDPOSY);
-      }
-#else
-      /* quick relocation (without scrolling), inside visible screen area */
-
-      int offset = game.scroll_delay_value;
-
-      if ((move_dir == MV_LEFT  && scroll_x > x - MIDPOSX + offset) ||
-	  (move_dir == MV_RIGHT && scroll_x < x - MIDPOSX - offset))
-	scroll_x = x - MIDPOSX + (scroll_x < x - MIDPOSX ? -offset : +offset);
-
-      if ((move_dir == MV_UP   && scroll_y > y - MIDPOSY + offset) ||
-	  (move_dir == MV_DOWN && scroll_y < y - MIDPOSY - offset))
-	scroll_y = y - MIDPOSY + (scroll_y < y - MIDPOSY ? -offset : +offset);
-
-      /* don't scroll over playfield boundaries */
-      if (scroll_x < SBX_Left || scroll_x > SBX_Right)
-	scroll_x = (scroll_x < SBX_Left ? SBX_Left : SBX_Right);
-
-      /* don't scroll over playfield boundaries */
-      if (scroll_y < SBY_Upper || scroll_y > SBY_Lower)
-	scroll_y = (scroll_y < SBY_Upper ? SBY_Upper : SBY_Lower);
-#endif
-    }
-
-    RedrawPlayfield(TRUE, 0,0,0,0);
   }
-  else
-  {
-#if 1
-    int scroll_xx, scroll_yy;
-
-    if (!level.shifted_relocation || center_screen)
-    {
-      /* visible relocation (with scrolling), with centering of screen */
 
-      scroll_xx = (x < SBX_Left  + MIDPOSX ? SBX_Left :
-		   x > SBX_Right + MIDPOSX ? SBX_Right :
-		   x - MIDPOSX);
-
-      scroll_yy = (y < SBY_Upper + MIDPOSY ? SBY_Upper :
-		   y > SBY_Lower + MIDPOSY ? SBY_Lower :
-		   y - MIDPOSY);
-    }
-    else
-    {
-      /* visible relocation (with scrolling), but do not center screen */
-
-      int center_scroll_x = (old_x < SBX_Left  + MIDPOSX ? SBX_Left :
-			     old_x > SBX_Right + MIDPOSX ? SBX_Right :
-			     old_x - MIDPOSX);
-
-      int center_scroll_y = (old_y < SBY_Upper + MIDPOSY ? SBY_Upper :
-			     old_y > SBY_Lower + MIDPOSY ? SBY_Lower :
-			     old_y - MIDPOSY);
-
-      int offset_x = x + (scroll_x - center_scroll_x);
-      int offset_y = y + (scroll_y - center_scroll_y);
+  if (quick_relocation)
+  {
+    /* case 2: quick relocation (redraw without visible scrolling) */
 
-      scroll_xx = (offset_x < SBX_Left  + MIDPOSX ? SBX_Left :
-		   offset_x > SBX_Right + MIDPOSX ? SBX_Right :
-		   offset_x - MIDPOSX);
+    scroll_x = new_scroll_x;
+    scroll_y = new_scroll_y;
 
-      scroll_yy = (offset_y < SBY_Upper + MIDPOSY ? SBY_Upper :
-		   offset_y > SBY_Lower + MIDPOSY ? SBY_Lower :
-		   offset_y - MIDPOSY);
-    }
+    RedrawPlayfield();
 
-#else
+    return;
+  }
 
-    /* visible relocation (with scrolling), with centering of screen */
+  /* case 3: visible relocation (with scrolling to new position) */
 
-    int scroll_xx = (x < SBX_Left  + MIDPOSX ? SBX_Left :
-		     x > SBX_Right + MIDPOSX ? SBX_Right :
-		     x - MIDPOSX);
+  ScrollScreen(NULL, SCROLL_GO_ON);	/* scroll last frame to full tile */
 
-    int scroll_yy = (y < SBY_Upper + MIDPOSY ? SBY_Upper :
-		     y > SBY_Lower + MIDPOSY ? SBY_Lower :
-		     y - MIDPOSY);
-#endif
+  SetVideoFrameDelay(wait_delay_value);
 
-    ScrollScreen(NULL, SCROLL_GO_ON);	/* scroll last frame to full tile */
+  while (scroll_x != new_scroll_x || scroll_y != new_scroll_y)
+  {
+    int dx = 0, dy = 0;
+    int fx = FX, fy = FY;
 
-    while (scroll_x != scroll_xx || scroll_y != scroll_yy)
-    {
-      int dx = 0, dy = 0;
-      int fx = FX, fy = FY;
+    dx = (new_scroll_x < scroll_x ? +1 : new_scroll_x > scroll_x ? -1 : 0);
+    dy = (new_scroll_y < scroll_y ? +1 : new_scroll_y > scroll_y ? -1 : 0);
 
-      dx = (scroll_xx < scroll_x ? +1 : scroll_xx > scroll_x ? -1 : 0);
-      dy = (scroll_yy < scroll_y ? +1 : scroll_yy > scroll_y ? -1 : 0);
+    if (dx == 0 && dy == 0)		/* no scrolling needed at all */
+      break;
 
-      if (dx == 0 && dy == 0)		/* no scrolling needed at all */
-	break;
+    scroll_x -= dx;
+    scroll_y -= dy;
 
-      scroll_x -= dx;
-      scroll_y -= dy;
+    fx += dx * TILEX / 2;
+    fy += dy * TILEY / 2;
 
-      fx += dx * TILEX / 2;
-      fy += dy * TILEY / 2;
+    ScrollLevel(dx, dy);
+    DrawAllPlayers();
 
-      ScrollLevel(dx, dy);
-      DrawAllPlayers();
+    /* scroll in two steps of half tile size to make things smoother */
+    BlitBitmap(drawto_field, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
 
-      /* scroll in two steps of half tile size to make things smoother */
-      BlitBitmap(drawto_field, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
-      FlushDisplay();
-      Delay(wait_delay_value);
+    /* scroll second step to align at full tile size */
+    BlitScreenToBitmap(window);
+  }
 
-      /* scroll second step to align at full tile size */
-      BackToFront();
-      Delay(wait_delay_value);
-    }
+  DrawAllPlayers();
+  BackToFront();
 
-    DrawAllPlayers();
-    BackToFront();
-    Delay(wait_delay_value);
-  }
+  SetVideoFrameDelay(frame_delay_value_old);
 }
 
 void RelocatePlayer(int jx, int jy, int el_player_raw)
@@ -5785,8 +5054,7 @@ void RelocatePlayer(int jx, int jy, int el_player_raw)
 
       DrawPlayer(player);
 
-      BackToFront();
-      Delay(wait_delay_value);
+      BackToFront_WithFrameDelay(wait_delay_value);
     }
 
     DrawPlayer(player);		/* needed here only to cleanup last field */
@@ -5814,12 +5082,6 @@ void RelocatePlayer(int jx, int jy, int el_player_raw)
   if (!ELEM_IS_PLAYER(element))	/* player may be set on walkable element */
   {
     Feld[jx][jy] = element;	/* restore previously existing element */
-#if 0
-    /* !!! do not initialize already initialized element a second time !!! */
-    /* (this causes at least problems with "element creation" CE trigger for
-       already existing elements, and existing Sokoban fields counted twice) */
-    InitField(jx, jy, FALSE);
-#endif
   }
 
   /* only visually relocate centered player */
@@ -5836,7 +5098,6 @@ void RelocatePlayer(int jx, int jy, int el_player_raw)
   CheckTriggeredElementChangeByPlayer(jx, jy, element, CE_PLAYER_ENTERS_X,
 				      player->index_bit, enter_side);
 
-#if 1
   if (player->is_switching)
   {
     /* ensure that relocation while still switching an element does not cause
@@ -5849,7 +5110,6 @@ void RelocatePlayer(int jx, int jy, int el_player_raw)
     player->switch_x += jx - old_jx;
     player->switch_y += jy - old_jy;
   }
-#endif
 }
 
 void Explode(int ex, int ey, int phase, int mode)
@@ -5872,23 +5132,6 @@ void Explode(int ex, int ey, int phase, int mode)
     int center_element = Feld[ex][ey];
     int artwork_element, explosion_element;	/* set these values later */
 
-#if 0
-    /* --- This is only really needed (and now handled) in "Impact()". --- */
-    /* do not explode moving elements that left the explode field in time */
-    if (game.engine_version >= VERSION_IDENT(2,2,0,7) &&
-	center_element == EL_EMPTY &&
-	(mode == EX_TYPE_NORMAL || mode == EX_TYPE_CENTER))
-      return;
-#endif
-
-#if 0
-    /* !!! at this place, the center element may be EL_BLOCKED !!! */
-    if (mode == EX_TYPE_NORMAL ||
-	mode == EX_TYPE_CENTER ||
-	mode == EX_TYPE_CROSS)
-      PlayLevelSoundElementAction(ex, ey, artwork_element, ACTION_EXPLODING);
-#endif
-
     /* remove things displayed in background while burning dynamite */
     if (Back[ex][ey] != EL_EMPTY && !IS_INDESTRUCTIBLE(Back[ex][ey]))
       Back[ex][ey] = 0;
@@ -5918,12 +5161,10 @@ void Explode(int ex, int ey, int phase, int mode)
       }
     }
 
-#if 1
     if (mode == EX_TYPE_NORMAL ||
 	mode == EX_TYPE_CENTER ||
 	mode == EX_TYPE_CROSS)
       PlayLevelSoundElementAction(ex, ey, artwork_element, ACTION_EXPLODING);
-#endif
 
     last_phase = element_info[explosion_element].explosion_delay + 1;
 
@@ -6060,31 +5301,9 @@ void Explode(int ex, int ey, int phase, int mode)
 
   ExplodePhase[x][y] = (phase < last_phase ? phase + 1 : 0);
 
-#ifdef DEBUG
-
-  /* activate this even in non-DEBUG version until cause for crash in
-     getGraphicAnimationFrame() (see below) is found and eliminated */
-
-#endif
-#if 1
-
-#if 1
   /* this can happen if the player leaves an explosion just in time */
   if (GfxElement[x][y] == EL_UNDEFINED)
     GfxElement[x][y] = EL_EMPTY;
-#else
-  if (GfxElement[x][y] == EL_UNDEFINED)
-  {
-    printf("\n\n");
-    printf("Explode(): x = %d, y = %d: GfxElement == EL_UNDEFINED\n", x, y);
-    printf("Explode(): This should never happen!\n");
-    printf("\n\n");
-
-    GfxElement[x][y] = EL_EMPTY;
-  }
-#endif
-
-#endif
 
   border_element = Store2[x][y];
   if (IS_PLAYER(x, y) && !PLAYER_EXPLOSION_PROTECTED(x, y))
@@ -6156,9 +5375,7 @@ void Explode(int ex, int ey, int phase, int mode)
     ChangeDelay[x][y] = 0;
     ChangePage[x][y] = -1;
 
-#if USE_NEW_CUSTOM_VALUE
     CustomValue[x][y] = 0;
-#endif
 
     InitField_WithBug2(x, y, FALSE);
 
@@ -6258,12 +5475,7 @@ void Bang(int x, int y)
   {
     struct PlayerInfo *player = PLAYERINFO(x, y);
 
-#if USE_FIX_CE_ACTION_WITH_PLAYER
     element = Feld[x][y] = player->initial_element;
-#else
-    element = Feld[x][y] = (player->use_murphy ? EL_SP_MURPHY :
-			    player->element_nr);
-#endif
 
     if (level.use_explosion_element[player->index_nr])
     {
@@ -6301,10 +5513,6 @@ void Bang(int x, int y)
       break;
 
     case EL_DC_LANDMINE:
-#if 0
-    case EL_EM_EXIT_OPEN:
-    case EL_EM_STEEL_EXIT_OPEN:
-#endif
       explosion_type = EX_TYPE_CENTER;
       break;
 
@@ -6528,20 +5736,6 @@ static void ToggleSwitchgateSwitch(int x, int y)
   {
     int element = Feld[xx][yy];
 
-#if !USE_BOTH_SWITCHGATE_SWITCHES
-    if (element == EL_SWITCHGATE_SWITCH_UP ||
-	element == EL_SWITCHGATE_SWITCH_DOWN)
-    {
-      Feld[xx][yy] = EL_SWITCHGATE_SWITCH_UP + game.switchgate_pos;
-      TEST_DrawLevelField(xx, yy);
-    }
-    else if (element == EL_DC_SWITCHGATE_SWITCH_UP ||
-	     element == EL_DC_SWITCHGATE_SWITCH_DOWN)
-    {
-      Feld[xx][yy] = EL_DC_SWITCHGATE_SWITCH_UP + game.switchgate_pos;
-      TEST_DrawLevelField(xx, yy);
-    }
-#else
     if (element == EL_SWITCHGATE_SWITCH_UP)
     {
       Feld[xx][yy] = EL_SWITCHGATE_SWITCH_DOWN;
@@ -6562,7 +5756,6 @@ static void ToggleSwitchgateSwitch(int x, int y)
       Feld[xx][yy] = EL_DC_SWITCHGATE_SWITCH_UP;
       TEST_DrawLevelField(xx, yy);
     }
-#endif
     else if (element == EL_SWITCHGATE_OPEN ||
 	     element == EL_SWITCHGATE_OPENING)
     {
@@ -6795,12 +5988,8 @@ static void ActivateTimegateSwitch(int x, int y)
 
   }
 
-#if 1
   Feld[x][y] = (Feld[x][y] == EL_TIMEGATE_SWITCH ? EL_TIMEGATE_SWITCH_ACTIVE :
 		EL_DC_TIMEGATE_SWITCH_ACTIVE);
-#else
-  Feld[x][y] = EL_TIMEGATE_SWITCH_ACTIVE;
-#endif
 }
 
 void Impact(int x, int y)
@@ -7026,10 +6215,6 @@ void Impact(int x, int y)
 	}
 	else
 	{
-#if 0
-	  TestIfElementSmashesCustomElement(x, y, MV_DOWN);
-#endif
-
 	  CheckElementChange(x, y + 1, smashed, element, CE_SMASHED);
 
 	  CheckElementChangeBySide(x, y + 1, smashed, element,
@@ -7331,7 +6516,6 @@ inline static void TurnRoundExt(int x, int y)
   }
   else if (element == EL_SPRING)
   {
-#if USE_NEW_SPRING_BUMPER
     if (MovDir[x][y] & MV_HORIZONTAL)
     {
       if (SPRING_CAN_BUMP_FROM_FIELD(move_x, move_y) &&
@@ -7347,12 +6531,6 @@ inline static void TurnRoundExt(int x, int y)
 	       SPRING_CAN_ENTER_FIELD(element, x, y + 1))
 	MovDir[x][y] = MV_NONE;
     }
-#else
-    if (MovDir[x][y] & MV_HORIZONTAL &&
-	(!SPRING_CAN_ENTER_FIELD(element, move_x, move_y) ||
-	 SPRING_CAN_ENTER_FIELD(element, x, y + 1)))
-      MovDir[x][y] = MV_NONE;
-#endif
 
     MovDelay[x][y] = 0;
   }
@@ -7894,7 +7072,7 @@ static void TurnRound(int x, int y)
   if (MovDelay[x][y])
     GfxAction[x][y] = ACTION_TURNING_FROM_LEFT + MV_DIR_TO_BIT(direction);
 
-  ResetGfxFrame(x, y, FALSE);
+  ResetGfxFrame(x, y);
 }
 
 static boolean JustBeingPushed(int x, int y)
@@ -8115,7 +7293,7 @@ void StartMoving(int x, int y)
       else if (Feld[x][y + 1] == EL_MAGIC_WALL_ACTIVE)
       {
 	if (!MovDelay[x][y])
-	  MovDelay[x][y] = TILEY/4 + 1;
+	  MovDelay[x][y] = TILEY / 4 + 1;
 
 	if (MovDelay[x][y])
 	{
@@ -8143,7 +7321,7 @@ void StartMoving(int x, int y)
       else if (Feld[x][y + 1] == EL_BD_MAGIC_WALL_ACTIVE)
       {
 	if (!MovDelay[x][y])
-	  MovDelay[x][y] = TILEY/4 + 1;
+	  MovDelay[x][y] = TILEY / 4 + 1;
 
 	if (MovDelay[x][y])
 	{
@@ -8171,7 +7349,7 @@ void StartMoving(int x, int y)
       else if (Feld[x][y + 1] == EL_DC_MAGIC_WALL_ACTIVE)
       {
 	if (!MovDelay[x][y])
-	  MovDelay[x][y] = TILEY/4 + 1;
+	  MovDelay[x][y] = TILEY / 4 + 1;
 
 	if (MovDelay[x][y])
 	{
@@ -8212,13 +7390,8 @@ void StartMoving(int x, int y)
       Store[x][y] = EL_ACID;
     }
     else if (
-#if USE_FIX_IMPACT_COLLISION
 	     (game.engine_version >= VERSION_IDENT(3,1,0,0) &&
 	      CheckImpact[x][y] && !IS_FREE(x, y + 1)) ||
-#else
-	     (game.engine_version >= VERSION_IDENT(3,1,0,0) &&
-	      CheckCollision[x][y] && !IS_FREE(x, y + 1)) ||
-#endif
 	     (game.engine_version >= VERSION_IDENT(3,0,7,0) &&
 	      CAN_FALL(element) && WasJustFalling[x][y] &&
 	      (Feld[x][y + 1] == EL_BLOCKED || IS_PLAYER(x, y + 1))) ||
@@ -8278,7 +7451,6 @@ void StartMoving(int x, int y)
       boolean can_fall_both = (can_fall_left && can_fall_right);
       int slippery_type = element_info[Feld[x][y + 1]].slippery_type;
 
-#if USE_NEW_ALL_SLIPPERY
       if (can_fall_any && slippery_type != SLIPPERY_ANY_RANDOM)
       {
 	if (slippery_type == SLIPPERY_ANY_LEFT_RIGHT && can_fall_both)
@@ -8293,37 +7465,7 @@ void StartMoving(int x, int y)
 	can_fall_any  = (can_fall_left || can_fall_right);
 	can_fall_both = FALSE;
       }
-#else
-      if (can_fall_any && IS_CUSTOM_ELEMENT(Feld[x][y + 1]))
-      {
-	if (slippery_type == SLIPPERY_ONLY_LEFT)
-	  can_fall_right = FALSE;
-	else if (slippery_type == SLIPPERY_ONLY_RIGHT)
-	  can_fall_left = FALSE;
-	else if (slippery_type == SLIPPERY_ANY_LEFT_RIGHT && can_fall_both)
-	  can_fall_right = FALSE;
-	else if (slippery_type == SLIPPERY_ANY_RIGHT_LEFT && can_fall_both)
-	  can_fall_left = FALSE;
-
-	can_fall_any  = (can_fall_left || can_fall_right);
-	can_fall_both = (can_fall_left && can_fall_right);
-      }
-#endif
-
-#if USE_NEW_ALL_SLIPPERY
-#else
-#if USE_NEW_SP_SLIPPERY
-      /* !!! better use the same properties as for custom elements here !!! */
-      else if (game.engine_version >= VERSION_IDENT(3,1,1,0) &&
-	       can_fall_both && IS_SP_ELEMENT(Feld[x][y + 1]))
-      {
-	can_fall_right = FALSE;		/* slip down on left side */
-	can_fall_both = FALSE;
-      }
-#endif
-#endif
 
-#if USE_NEW_ALL_SLIPPERY
       if (can_fall_both)
       {
 	if (element == EL_BD_ROCK || element == EL_BD_DIAMOND)
@@ -8333,18 +7475,6 @@ void StartMoving(int x, int y)
 
 	can_fall_both = FALSE;
       }
-#else
-      if (can_fall_both)
-      {
-	if (game.emulation == EMU_BOULDERDASH ||
-	    element == EL_BD_ROCK || element == EL_BD_DIAMOND)
-	  can_fall_right = FALSE;	/* slip down on left side */
-	else
-	  can_fall_left = !(can_fall_right = RND(2));
-
-	can_fall_both = FALSE;
-      }
-#endif
 
       if (can_fall_any)
       {
@@ -8353,11 +7483,7 @@ void StartMoving(int x, int y)
 	started_moving = TRUE;
       }
     }
-#if 0
-    else if (IS_BELT_ACTIVE(Feld[x][y + 1]) && !CAN_MOVE(element))
-#else
     else if (IS_BELT_ACTIVE(Feld[x][y + 1]))
-#endif
     {
       boolean left_is_free  = (x > 0 && IS_FREE(x - 1, y));
       boolean right_is_free = (x < lev_fieldx - 1 && IS_FREE(x + 1, y));
@@ -8385,26 +7511,11 @@ void StartMoving(int x, int y)
   }
 
   /* not "else if" because of elements that can fall and move (EL_SPRING) */
-#if 0
-  if (CAN_MOVE(element) && !started_moving && MovDir[x][y] != MV_NONE)
-#else
   if (CAN_MOVE(element) && !started_moving)
-#endif
   {
     int move_pattern = element_info[element].move_pattern;
     int newx, newy;
 
-#if 0
-#if DEBUG
-    if (MovDir[x][y] == MV_NONE)
-    {
-      printf("StartMoving(): %d,%d: element %d ['%s'] not moving\n",
-	     x, y, element, element_info[element].token_name);
-      printf("StartMoving(): This should never happen!\n");
-    }
-#endif
-#endif
-
     Moving2Blocked(x, y, &newx, &newy);
 
     if (IS_PUSHABLE(element) && JustBeingPushed(x, y))
@@ -8497,20 +7608,10 @@ void StartMoving(int x, int y)
 	  {
 	    int flamed = MovingOrBlocked2Element(xx, yy);
 
-	    /* !!! */
-#if 0
-	    if (IS_CLASSIC_ENEMY(flamed) || CAN_EXPLODE_BY_DRAGONFIRE(flamed))
-	      Bang(xx, yy);
-	    else if (IS_MOVING(xx, yy) || IS_BLOCKED(xx, yy))
-	      RemoveMovingField(xx, yy);
-	    else
-	      RemoveField(xx, yy);
-#else
 	    if (IS_CLASSIC_ENEMY(flamed) || CAN_EXPLODE_BY_DRAGONFIRE(flamed))
 	      Bang(xx, yy);
 	    else
 	      RemoveMovingField(xx, yy);
-#endif
 
 	    ChangeDelay[xx][yy] = 0;
 
@@ -8706,78 +7807,14 @@ void StartMoving(int x, int y)
       }
       else if (!IS_FREE(newx, newy))
       {
-#if 0
-	if (IS_PLAYER(x, y))
-	  DrawPlayerField(x, y);
-	else
-	  TEST_DrawLevelField(x, y);
-#endif
-
 	return;
       }
     }
     else if (IS_CUSTOM_ELEMENT(element) &&
 	     CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, newx, newy))
     {
-#if 1
       if (!DigFieldByCE(newx, newy, element))
 	return;
-#else
-      int new_element = Feld[newx][newy];
-
-      if (!IS_FREE(newx, newy))
-      {
-	int action = (IS_DIGGABLE(new_element) ? ACTION_DIGGING :
-		      IS_COLLECTIBLE(new_element) ? ACTION_COLLECTING :
-		      ACTION_BREAKING);
-
-	/* no element can dig solid indestructible elements */
-	if (IS_INDESTRUCTIBLE(new_element) &&
-	    !IS_DIGGABLE(new_element) &&
-	    !IS_COLLECTIBLE(new_element))
-	  return;
-
-	if (AmoebaNr[newx][newy] &&
-	    (new_element == EL_AMOEBA_FULL ||
-	     new_element == EL_BD_AMOEBA ||
-	     new_element == EL_AMOEBA_GROWING))
-	{
-	  AmoebaCnt[AmoebaNr[newx][newy]]--;
-	  AmoebaCnt2[AmoebaNr[newx][newy]]--;
-	}
-
-	if (IS_MOVING(newx, newy))
-	  RemoveMovingField(newx, newy);
-	else
-	{
-	  RemoveField(newx, newy);
-	  TEST_DrawLevelField(newx, newy);
-	}
-
-	/* if digged element was about to explode, prevent the explosion */
-	ExplodeField[newx][newy] = EX_TYPE_NONE;
-
-	PlayLevelSoundAction(x, y, action);
-      }
-
-      Store[newx][newy] = EL_EMPTY;
-
-#if 1
-      /* this makes it possible to leave the removed element again */
-      if (IS_EQUAL_OR_IN_GROUP(new_element, MOVE_ENTER_EL(element)))
-	Store[newx][newy] = new_element;
-#else
-      if (IS_EQUAL_OR_IN_GROUP(new_element, MOVE_ENTER_EL(element)))
-      {
-	int move_leave_element = element_info[element].move_leave_element;
-
-	/* this makes it possible to leave the removed element again */
-	Store[newx][newy] = (move_leave_element == EL_TRIGGER_ELEMENT ?
-			     new_element : move_leave_element);
-      }
-#endif
-
-#endif
 
       if (move_pattern & MV_MAZE_RUNNER_STYLE)
       {
@@ -8824,26 +7861,12 @@ void StartMoving(int x, int y)
 	  PlayLevelSound(x, y, SND_DRAGON_ATTACKING);
 
 	  MovDelay[x][y] = 50;
-
-	  /* !!! */
-#if 0
-	  RemoveField(newx, newy);
-#endif
+
 	  Feld[newx][newy] = EL_FLAMES;
 	  if (IN_LEV_FIELD(newx1, newy1) && Feld[newx1][newy1] == EL_EMPTY)
-	  {
-#if 0
-	    RemoveField(newx1, newy1);
-#endif
 	    Feld[newx1][newy1] = EL_FLAMES;
-	  }
 	  if (IN_LEV_FIELD(newx2, newy2) && Feld[newx2][newy2] == EL_EMPTY)
-	  {
-#if 0
-	    RemoveField(newx2, newy2);
-#endif
 	    Feld[newx2][newy2] = EL_FLAMES;
-	  }
 
 	  return;
 	}
@@ -8873,18 +7896,10 @@ void StartMoving(int x, int y)
 	  AmoebaCnt[AmoebaNr[newx][newy]]--;
       }
 
-#if 0
-      /* !!! test !!! */
-      if (IS_MOVING(newx, newy) || IS_BLOCKED(newx, newy))
-      {
-	RemoveMovingField(newx, newy);
-      }
-#else
       if (IS_MOVING(newx, newy))
       {
 	RemoveMovingField(newx, newy);
       }
-#endif
       else
       {
 	Feld[newx][newy] = EL_EMPTY;
@@ -8937,21 +7952,6 @@ void StartMoving(int x, int y)
 
       TurnRound(x, y);
 
-#if 0
-      /* !!! NEW "CE_BLOCKED" STUFF !!! -- DOES NOT WORK YET... !!! */
-      if (move_pattern & MV_ANY_DIRECTION &&
-	  move_pattern == MovDir[x][y])
-      {
-	int blocking_element =
-	  (IN_LEV_FIELD(newx, newy) ? Feld[newx][newy] : BorderElement);
-
-	CheckElementChangeBySide(x, y, element, blocking_element, CE_BLOCKED,
-				 MovDir[x][y]);
-
-	element = Feld[x][y];	/* element might have changed */
-      }
-#endif
-
       if (GFX_ELEMENT(element) != EL_SAND)     /* !!! FIX THIS (crumble) !!! */
 	DrawLevelElementAnimation(x, y, element);
 
@@ -8991,17 +7991,6 @@ void ContinueMoving(int x, int y)
 
   if (ABS(MovPos[x][y]) < TILEX)
   {
-#if 0
-    int ee = Feld[x][y];
-    int gg = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
-    int ff = getGraphicAnimationFrame(gg, GfxFrame[x][y]);
-
-    printf("::: %d.%d: moving %d ... [%d, %d, %d] [%d, %d, %d]\n",
-	   x, y, ABS(MovPos[x][y]),
-	   ee, gg, ff,
-	   GfxAction[x][y], GfxDir[x][y], GfxFrame[x][y]);
-#endif
-
     TEST_DrawLevelField(x, y);
 
     return;	/* element is still moving */
@@ -9057,9 +8046,7 @@ void ContinueMoving(int x, int y)
       Feld[x][y] = EL_MAGIC_WALL_DEAD;
     element = Feld[newx][newy] = Store[x][y];
 
-#if USE_NEW_CUSTOM_VALUE
     InitField(newx, newy, FALSE);
-#endif
   }
   else if (element == EL_BD_MAGIC_WALL_FILLING)
   {
@@ -9075,9 +8062,7 @@ void ContinueMoving(int x, int y)
       Feld[x][y] = EL_BD_MAGIC_WALL_DEAD;
     element = Feld[newx][newy] = Store[x][y];
 
-#if USE_NEW_CUSTOM_VALUE
     InitField(newx, newy, FALSE);
-#endif
   }
   else if (element == EL_DC_MAGIC_WALL_FILLING)
   {
@@ -9093,9 +8078,7 @@ void ContinueMoving(int x, int y)
       Feld[x][y] = EL_DC_MAGIC_WALL_DEAD;
     element = Feld[newx][newy] = Store[x][y];
 
-#if USE_NEW_CUSTOM_VALUE
     InitField(newx, newy, FALSE);
-#endif
   }
   else if (element == EL_AMOEBA_DROPPING)
   {
@@ -9129,18 +8112,14 @@ void ContinueMoving(int x, int y)
     ChangeEvent[newx][newy] = ChangeEvent[x][y];
   }
 
-#if USE_NEW_CUSTOM_VALUE
   CustomValue[newx][newy] = CustomValue[x][y];
-#endif
 
   ChangeDelay[x][y] = 0;
   ChangePage[x][y] = -1;
   ChangeCount[x][y] = 0;
   ChangeEvent[x][y] = -1;
 
-#if USE_NEW_CUSTOM_VALUE
   CustomValue[x][y] = 0;
-#endif
 
   /* copy animation control values to new field */
   GfxFrame[newx][newy]  = GfxFrame[x][y];
@@ -9151,34 +8130,15 @@ void ContinueMoving(int x, int y)
   Pushed[x][y] = Pushed[newx][newy] = FALSE;
 
   /* some elements can leave other elements behind after moving */
-#if 1
   if (ei->move_leave_element != EL_EMPTY &&
       (ei->move_leave_type == LEAVE_TYPE_UNLIMITED || stored != EL_EMPTY) &&
       (!IS_PLAYER(x, y) || IS_WALKABLE(ei->move_leave_element)))
-#else
-  if (IS_CUSTOM_ELEMENT(element) && ei->move_leave_element != EL_EMPTY &&
-      (ei->move_leave_type == LEAVE_TYPE_UNLIMITED || stored != EL_EMPTY) &&
-      (!IS_PLAYER(x, y) || IS_WALKABLE(ei->move_leave_element)))
-#endif
   {
     int move_leave_element = ei->move_leave_element;
 
-#if 1
-#if 1
     /* this makes it possible to leave the removed element again */
     if (ei->move_leave_element == EL_TRIGGER_ELEMENT)
       move_leave_element = (stored == EL_ACID ? EL_EMPTY : stored);
-#else
-    /* this makes it possible to leave the removed element again */
-    if (ei->move_leave_element == EL_TRIGGER_ELEMENT)
-      move_leave_element = stored;
-#endif
-#else
-    /* this makes it possible to leave the removed element again */
-    if (ei->move_leave_type == LEAVE_TYPE_LIMITED &&
-        ei->move_leave_element == EL_TRIGGER_ELEMENT)
-      move_leave_element = stored;
-#endif
 
     Feld[x][y] = move_leave_element;
 
@@ -9233,10 +8193,8 @@ void ContinueMoving(int x, int y)
     if ((!CAN_FALL(element) || direction == MV_DOWN) && check_collision_again)
       CheckCollision[newx][newy] = CHECK_DELAY_COLLISION;
 
-#if USE_FIX_IMPACT_COLLISION
     if (CAN_FALL(element) && direction == MV_DOWN && check_collision_again)
       CheckImpact[newx][newy] = CHECK_DELAY_IMPACT;
-#endif
   }
 
   if (DONT_TOUCH(element))	/* object may be nasty to player or others */
@@ -9279,29 +8237,6 @@ void ContinueMoving(int x, int y)
   CheckTriggeredElementChangeBySide(x, y, element, CE_MOVE_OF_X, direction);
 
   TestIfElementTouchesCustomElement(x, y);	/* empty or new element */
-
-#if 0
-  if (ChangePage[newx][newy] != -1)		/* delayed change */
-  {
-    int page = ChangePage[newx][newy];
-    struct ElementChangeInfo *change = &ei->change_page[page];
-
-    ChangePage[newx][newy] = -1;
-
-    if (change->can_change)
-    {
-      if (ChangeElement(newx, newy, element, page))
-      {
-        if (change->post_change_function)
-          change->post_change_function(newx, newy);
-      }
-    }
-
-    if (change->has_action)
-      ExecuteCustomElementAction(newx, newy, element, page);
-  }
-#endif
-
   TestIfElementHitsCustomElement(newx, newy, direction);
   TestIfPlayerTouchesCustomElement(newx, newy);
   TestIfElementTouchesCustomElement(newx, newy);
@@ -9485,8 +8420,8 @@ void AmoebeUmwandelnBD(int ax, int ay, int new_element)
 
 void AmoebeWaechst(int x, int y)
 {
-  static unsigned long sound_delay = 0;
-  static unsigned long sound_delay_value = 0;
+  static unsigned int sound_delay = 0;
+  static unsigned int sound_delay_value = 0;
 
   if (!MovDelay[x][y])		/* start new growing cycle */
   {
@@ -9521,8 +8456,8 @@ void AmoebeWaechst(int x, int y)
 
 void AmoebaDisappearing(int x, int y)
 {
-  static unsigned long sound_delay = 0;
-  static unsigned long sound_delay_value = 0;
+  static unsigned int sound_delay = 0;
+  static unsigned int sound_delay_value = 0;
 
   if (!MovDelay[x][y])		/* start new shrinking cycle */
   {
@@ -9822,11 +8757,7 @@ static void RunTimegateWheel(int x, int y)
 
 static void InitMagicBallDelay(int x, int y)
 {
-#if 1
   ChangeDelay[x][y] = (level.ball_time + 1) * 8 + 1;
-#else
-  ChangeDelay[x][y] = level.ball_time * FRAMES_PER_SECOND + 1;
-#endif
 }
 
 static void ActivateMagicBall(int bx, int by)
@@ -10439,11 +9370,6 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
      EL_EMPTY);
   int action_arg_element = GetElementFromGroupElement(action_arg_element_raw);
 
-#if 0
-  if (action_arg_element_raw == EL_GROUP_START)
-    printf("::: %d,%d: %d ('%s')\n", x, y, element, EL_NAME(element));
-#endif
-
   int action_arg_direction =
     (action_arg >= CA_ARG_DIRECTION_LEFT &&
      action_arg <= CA_ARG_DIRECTION_DOWN ? action_arg - CA_ARG_DIRECTION :
@@ -10471,11 +9397,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
      action_type == CA_SET_LEVEL_GEMS ? level.gems_needed :
      action_type == CA_SET_LEVEL_TIME ? level.time :
      action_type == CA_SET_LEVEL_SCORE ? 0 :
-#if USE_NEW_CUSTOM_VALUE
      action_type == CA_SET_CE_VALUE ? GET_NEW_CE_VALUE(element) :
-#else
-     action_type == CA_SET_CE_VALUE ? ei->custom_value_initial :
-#endif
      action_type == CA_SET_CE_SCORE ? 0 :
      0);
 
@@ -10487,11 +9409,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
      action_arg == CA_ARG_NUMBER_MIN ? action_arg_number_min :
      action_arg == CA_ARG_NUMBER_MAX ? action_arg_number_max :
      action_arg == CA_ARG_NUMBER_RESET ? action_arg_number_reset :
-#if USE_NEW_CUSTOM_VALUE
      action_arg == CA_ARG_NUMBER_CE_VALUE ? CustomValue[x][y] :
-#else
-     action_arg == CA_ARG_NUMBER_CE_VALUE ? ei->custom_value_initial :
-#endif
      action_arg == CA_ARG_NUMBER_CE_SCORE ? ei->collect_score :
      action_arg == CA_ARG_NUMBER_CE_DELAY ? GET_CE_DELAY_VALUE(change) :
      action_arg == CA_ARG_NUMBER_LEVEL_TIME ? level_time_value :
@@ -10521,17 +9439,9 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
 			    action_mode, action_arg_number,
 			    action_arg_number_min, action_arg_number_max);
 
-#if 1
   int trigger_player_bits =
     (change->actual_trigger_player_bits != CH_PLAYER_NONE ?
      change->actual_trigger_player_bits : change->trigger_player);
-#else
-  int trigger_player_bits =
-    (change->actual_trigger_player >= EL_PLAYER_1 &&
-     change->actual_trigger_player <= EL_PLAYER_4 ?
-     (1 << (change->actual_trigger_player - EL_PLAYER_1)) :
-     PLAYER_BITS_ANY);
-#endif
 
   int action_arg_player_bits =
     (action_arg >= CA_ARG_PLAYER_1 &&
@@ -10575,13 +9485,9 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
       {
 	TimeLeft = action_arg_number_new;
 
-#if 1
 	game_panel_controls[GAME_PANEL_TIME].value = TimeLeft;
 
 	DisplayGameControlValues();
-#else
-	DrawGameValue_Time(TimeLeft);
-#endif
 
 	if (!TimeLeft && setup.time_limit)
 	  for (i = 0; i < MAX_PLAYERS; i++)
@@ -10595,13 +9501,9 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
     {
       local_player->score = action_arg_number_new;
 
-#if 1
       game_panel_controls[GAME_PANEL_SCORE].value = local_player->score;
 
       DisplayGameControlValues();
-#else
-      DrawGameValue_Score(local_player->score);
-#endif
 
       break;
     }
@@ -10610,27 +9512,15 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
     {
       local_player->gems_still_needed = action_arg_number_new;
 
-#if 1
-      game_panel_controls[GAME_PANEL_GEMS].value = local_player->gems_still_needed;
+      game.snapshot.collected_item = TRUE;
 
-      DisplayGameControlValues();
-#else
-      DrawGameValue_Emeralds(local_player->gems_still_needed);
-#endif
+      game_panel_controls[GAME_PANEL_GEMS].value =
+	local_player->gems_still_needed;
 
-      break;
-    }
+      DisplayGameControlValues();
 
-#if !USE_PLAYER_GRAVITY
-    case CA_SET_LEVEL_GRAVITY:
-    {
-      game.gravity = (action_arg == CA_ARG_GRAVITY_OFF    ? FALSE         :
-		      action_arg == CA_ARG_GRAVITY_ON     ? TRUE          :
-		      action_arg == CA_ARG_GRAVITY_TOGGLE ? !game.gravity :
-		      game.gravity);
       break;
     }
-#endif
 
     case CA_SET_LEVEL_WIND:
     {
@@ -10641,27 +9531,8 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
 
     case CA_SET_LEVEL_RANDOM_SEED:
     {
-#if 1
       /* ensure that setting a new random seed while playing is predictable */
       InitRND(action_arg_number_new ? action_arg_number_new : RND(1000000) + 1);
-#else
-      InitRND(action_arg_number_new);
-#endif
-
-#if 0
-      printf("::: %d -> %d\n", action_arg_number_new, RND(10));
-#endif
-
-#if 0
-      {
-	int i;
-
-	printf("::: ");
-	for (i = 0; i < 9; i++)
-	  printf("%d, ", RND(2));
-	printf("\n");
-      }
-#endif
 
       break;
     }
@@ -10720,10 +9591,6 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
 
     case CA_SET_PLAYER_SPEED:
     {
-#if 0
-      printf("::: trigger_player_bits == %d\n", trigger_player_bits);
-#endif
-
       for (i = 0; i < MAX_PLAYERS; i++)
       {
 	if (trigger_player_bits & (1 << i))
@@ -10787,7 +9654,6 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
       break;
     }
 
-#if USE_PLAYER_GRAVITY
     case CA_SET_PLAYER_GRAVITY:
     {
       for (i = 0; i < MAX_PLAYERS; i++)
@@ -10804,7 +9670,6 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
 
       break;
     }
-#endif
 
     case CA_SET_PLAYER_ARTWORK:
     {
@@ -10819,10 +9684,8 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
 	      (level.use_artwork_element[i] ? level.artwork_element[i] :
 	       stored_player[i].element_nr);
 
-#if USE_GFX_RESET_PLAYER_ARTWORK
 	  if (stored_player[i].artwork_element != artwork_element)
 	    stored_player[i].Frame = 0;
-#endif
 
 	  stored_player[i].artwork_element = artwork_element;
 
@@ -10943,7 +9806,6 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
 
     case CA_SET_CE_VALUE:
     {
-#if USE_NEW_CUSTOM_VALUE
       int last_ce_value = CustomValue[x][y];
 
       CustomValue[x][y] = action_arg_number_new;
@@ -10959,14 +9821,12 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
 	  CheckTriggeredElementChange(x, y, element, CE_VALUE_GETS_ZERO_OF_X);
 	}
       }
-#endif
 
       break;
     }
 
     case CA_SET_CE_SCORE:
     {
-#if USE_NEW_CUSTOM_VALUE
       int last_ce_score = ei->collect_score;
 
       ei->collect_score = action_arg_number_new;
@@ -11002,7 +9862,6 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
 	  }
 	}
       }
-#endif
 
       break;
     }
@@ -11058,32 +9917,13 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change)
   int old_element = Feld[x][y];
   int new_element = GetElementFromGroupElement(element);
   int previous_move_direction = MovDir[x][y];
-#if USE_NEW_CUSTOM_VALUE
   int last_ce_value = CustomValue[x][y];
-#endif
   boolean player_explosion_protected = PLAYER_EXPLOSION_PROTECTED(x, y);
   boolean new_element_is_player = ELEM_IS_PLAYER(new_element);
   boolean add_player_onto_element = (new_element_is_player &&
-#if USE_CODE_THAT_BREAKS_SNAKE_BITE
-				     /* this breaks SnakeBite when a snake is
-					halfway through a door that closes */
-				     /* NOW FIXED AT LEVEL INIT IN files.c */
 				     new_element != EL_SOKOBAN_FIELD_PLAYER &&
-#endif
 				     IS_WALKABLE(old_element));
 
-#if 0
-  /* check if element under the player changes from accessible to unaccessible
-     (needed for special case of dropping element which then changes) */
-  if (IS_PLAYER(x, y) && !PLAYER_EXPLOSION_PROTECTED(x, y) &&
-      IS_ACCESSIBLE(old_element) && !IS_ACCESSIBLE(new_element))
-  {
-    Bang(x, y);
-
-    return;
-  }
-#endif
-
   if (!add_player_onto_element)
   {
     if (IS_MOVING(x, y) || IS_BLOCKED(x, y))
@@ -11093,27 +9933,18 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change)
 
     Feld[x][y] = new_element;
 
-#if !USE_GFX_RESET_GFX_ANIMATION
-    ResetGfxAnimation(x, y);
-    ResetRandomAnimationValue(x, y);
-#endif
-
     if (element_info[new_element].move_direction_initial == MV_START_PREVIOUS)
       MovDir[x][y] = previous_move_direction;
 
-#if USE_NEW_CUSTOM_VALUE
     if (element_info[new_element].use_last_ce_value)
       CustomValue[x][y] = last_ce_value;
-#endif
 
     InitField_WithBug1(x, y, FALSE);
 
     new_element = Feld[x][y];	/* element may have changed */
 
-#if USE_GFX_RESET_GFX_ANIMATION
     ResetGfxAnimation(x, y);
     ResetRandomAnimationValue(x, y);
-#endif
 
     TEST_DrawLevelField(x, y);
 
@@ -11121,11 +9952,9 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change)
       TEST_DrawLevelFieldCrumbledNeighbours(x, y);
   }
 
-#if 1
   /* check if element under the player changes from accessible to unaccessible
      (needed for special case of dropping element which then changes) */
   /* (must be checked after creating new element for walkable group elements) */
-#if USE_FIX_KILLED_BY_NON_WALKABLE
   if (IS_PLAYER(x, y) && !player_explosion_protected &&
       IS_ACCESSIBLE(old_element) && !IS_ACCESSIBLE(new_element))
   {
@@ -11133,16 +9962,6 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change)
 
     return;
   }
-#else
-  if (IS_PLAYER(x, y) && !PLAYER_EXPLOSION_PROTECTED(x, y) &&
-      IS_ACCESSIBLE(old_element) && !IS_ACCESSIBLE(new_element))
-  {
-    Bang(x, y);
-
-    return;
-  }
-#endif
-#endif
 
   /* "ChangeCount" not set yet to allow "entered by player" change one time */
   if (new_element_is_player)
@@ -11165,7 +9984,6 @@ static void CreateElementFromChange(int x, int y, int element)
 {
   element = GET_VALID_RUNTIME_ELEMENT(element);
 
-#if USE_STOP_CHANGED_ELEMENTS
   if (game.engine_version >= VERSION_IDENT(3,2,0,7))
   {
     int old_element = Feld[x][y];
@@ -11176,7 +9994,6 @@ static void CreateElementFromChange(int x, int y, int element)
 	(!CAN_MOVE(old_element) || !CAN_MOVE(element)))
       Stop[x][y] = TRUE;
   }
-#endif
 
   CreateFieldExt(x, y, element, TRUE);
 }
@@ -11352,8 +10169,6 @@ static boolean ChangeElement(int x, int y, int element, int page)
   return TRUE;
 }
 
-#if USE_NEW_DELAYED_ACTION
-
 static void HandleElementChange(int x, int y, int page)
 {
   int element = MovingOrBlocked2Element(x, y);
@@ -11376,11 +10191,6 @@ static void HandleElementChange(int x, int y, int page)
   /* this can happen with classic bombs on walkable, changing elements */
   if (!CAN_CHANGE_OR_HAS_ACTION(element))
   {
-#if 0
-    if (!CAN_CHANGE(Back[x][y]))	/* prevent permanent repetition */
-      ChangeDelay[x][y] = 0;
-#endif
-
     return;
   }
 
@@ -11390,19 +10200,56 @@ static void HandleElementChange(int x, int y, int page)
 
     if (change->can_change)
     {
-#if 1
       /* !!! not clear why graphic animation should be reset at all here !!! */
       /* !!! UPDATE: but is needed for correct Snake Bite tail animation !!! */
-#if USE_GFX_RESET_WHEN_NOT_MOVING
+      /* !!! SOLUTION: do not reset if graphics engine set to 4 or above !!! */
+
+      /*
+	GRAPHICAL BUG ADDRESSED BY CHECKING GRAPHICS ENGINE VERSION:
+
+	When using an animation frame delay of 1 (this only happens with
+	"sp_zonk.moving.left/right" in the classic graphics), the default
+	(non-moving) animation shows wrong animation frames (while the
+	moving animation, like "sp_zonk.moving.left/right", is correct,
+	so this graphical bug never shows up with the classic graphics).
+	For an animation with 4 frames, this causes wrong frames 0,0,1,2
+	be drawn instead of the correct frames 0,1,2,3. This is caused by
+	"GfxFrame[][]" being reset *twice* (in two successive frames) after
+	an element change: First when the change delay ("ChangeDelay[][]")
+	counter has reached zero after decrementing, then a second time in
+	the next frame (after "GfxFrame[][]" was already incremented) when
+	"ChangeDelay[][]" is reset to the initial delay value again.
+
+	This causes frame 0 to be drawn twice, while the last frame won't
+	be drawn anymore, resulting in the wrong frame sequence 0,0,1,2.
+
+	As some animations may already be cleverly designed around this bug
+	(at least the "Snake Bite" snake tail animation does this), it cannot
+	simply be fixed here without breaking such existing animations.
+	Unfortunately, it cannot easily be detected if a graphics set was
+	designed "before" or "after" the bug was fixed. As a workaround,
+	a new graphics set option "game.graphics_engine_version" was added
+	to be able to specify the game's major release version for which the
+	graphics set was designed, which can then be used to decide if the
+	bugfix should be used (version 4 and above) or not (version 3 or
+	below, or if no version was specified at all, as with old sets).
+
+	(The wrong/fixed animation frames can be tested with the test level set
+	"test_gfxframe" and level "000", which contains a specially prepared
+	custom element at level position (x/y) == (11/9) which uses the zonk
+	animation mentioned above. Using "game.graphics_engine_version: 4"
+	fixes the wrong animation frames, showing the correct frames 0,1,2,3.
+	This can also be seen from the debug output for this test element.)
+      */
+
       /* when a custom element is about to change (for example by change delay),
 	 do not reset graphic animation when the custom element is moving */
-      if (!IS_MOVING(x, y))
-#endif
+      if (game.graphics_engine_version < 4 &&
+	  !IS_MOVING(x, y))
       {
 	ResetGfxAnimation(x, y);
 	ResetRandomAnimationValue(x, y);
       }
-#endif
 
       if (change->pre_change_function)
 	change->pre_change_function(x, y);
@@ -11442,14 +10289,12 @@ static void HandleElementChange(int x, int y, int page)
       return;
     }
 
-#if 1
     /* special case: set new level random seed before changing element */
     if (change->has_action && change->action_type == CA_SET_LEVEL_RANDOM_SEED)
       handle_action_before_change = TRUE;
 
     if (change->has_action && handle_action_before_change)
       ExecuteCustomElementAction(x, y, element, page);
-#endif
 
     if (change->can_change)
     {
@@ -11465,87 +10310,6 @@ static void HandleElementChange(int x, int y, int page)
   }
 }
 
-#else
-
-static void HandleElementChange(int x, int y, int page)
-{
-  int element = MovingOrBlocked2Element(x, y);
-  struct ElementInfo *ei = &element_info[element];
-  struct ElementChangeInfo *change = &ei->change_page[page];
-
-#ifdef DEBUG
-  if (!CAN_CHANGE(element) && !CAN_CHANGE(Back[x][y]))
-  {
-    printf("\n\n");
-    printf("HandleElementChange(): %d,%d: element = %d ('%s')\n",
-	   x, y, element, element_info[element].token_name);
-    printf("HandleElementChange(): This should never happen!\n");
-    printf("\n\n");
-  }
-#endif
-
-  /* this can happen with classic bombs on walkable, changing elements */
-  if (!CAN_CHANGE(element))
-  {
-#if 0
-    if (!CAN_CHANGE(Back[x][y]))	/* prevent permanent repetition */
-      ChangeDelay[x][y] = 0;
-#endif
-
-    return;
-  }
-
-  if (ChangeDelay[x][y] == 0)		/* initialize element change */
-  {
-    ChangeDelay[x][y] = GET_CHANGE_DELAY(change) + 1;
-
-    ResetGfxAnimation(x, y);
-    ResetRandomAnimationValue(x, y);
-
-    if (change->pre_change_function)
-      change->pre_change_function(x, y);
-  }
-
-  ChangeDelay[x][y]--;
-
-  if (ChangeDelay[x][y] != 0)		/* continue element change */
-  {
-    int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
-
-    if (IS_ANIMATED(graphic))
-      DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
-
-    if (change->change_function)
-      change->change_function(x, y);
-  }
-  else					/* finish element change */
-  {
-    if (ChangePage[x][y] != -1)		/* remember page from delayed change */
-    {
-      page = ChangePage[x][y];
-      ChangePage[x][y] = -1;
-
-      change = &ei->change_page[page];
-    }
-
-    if (IS_MOVING(x, y))		/* never change a running system ;-) */
-    {
-      ChangeDelay[x][y] = 1;		/* try change after next move step */
-      ChangePage[x][y] = page;		/* remember page to use for change */
-
-      return;
-    }
-
-    if (ChangeElement(x, y, element, page))
-    {
-      if (change->post_change_function)
-	change->post_change_function(x, y);
-    }
-  }
-}
-
-#endif
-
 static boolean CheckTriggeredElementChangeExt(int trigger_x, int trigger_y,
 					      int trigger_element,
 					      int trigger_event,
@@ -11560,12 +10324,6 @@ static boolean CheckTriggeredElementChangeExt(int trigger_x, int trigger_y,
   if (!(trigger_events[trigger_element][trigger_event]))
     return FALSE;
 
-#if 0
-  printf("::: CheckTriggeredElementChangeExt %d ... [%d, %d, %d, '%s']\n",
-	 trigger_event, recursion_loop_depth, recursion_loop_detected,
-	 recursion_loop_element, EL_NAME(recursion_loop_element));
-#endif
-
   RECURSION_LOOP_DETECTION_START(trigger_element, FALSE);
 
   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
@@ -11596,11 +10354,6 @@ static boolean CheckTriggeredElementChangeExt(int trigger_x, int trigger_y,
 	change->actual_trigger_ce_value = CustomValue[trigger_x][trigger_y];
 	change->actual_trigger_ce_score = GET_CE_SCORE(trigger_element);
 
-#if 0
-	printf("::: TRIGGERED CHANGE FOUND: %d ['%s'], %d\n",
-	       element, EL_NAME(element), p);
-#endif
-
 	if ((change->can_change && !change_done) || change->has_action)
 	{
 	  int x, y;
@@ -11611,7 +10364,6 @@ static boolean CheckTriggeredElementChangeExt(int trigger_x, int trigger_y,
 	    {
 	      if (change->can_change && !change_done)
 	      {
-#if USE_FIX_NO_ACTION_AFTER_CHANGE
 		/* if element already changed in this frame, not only prevent
 		   another element change (checked in ChangeElement()), but
 		   also prevent additional element actions for this element */
@@ -11619,22 +10371,14 @@ static boolean CheckTriggeredElementChangeExt(int trigger_x, int trigger_y,
 		if (ChangeCount[x][y] >= game.max_num_changes_per_frame &&
 		    !level.use_action_after_change_bug)
 		  continue;
-#endif
-
-#if 0
-		printf("::: TRIGGERED CHANGE FOUND: %d ['%s'], %d -- CHANGE\n",
-		       element, EL_NAME(element), p);
-#endif
 
 		ChangeDelay[x][y] = 1;
 		ChangeEvent[x][y] = trigger_event;
 
 		HandleElementChange(x, y, p);
 	      }
-#if USE_NEW_DELAYED_ACTION
 	      else if (change->has_action)
 	      {
-#if USE_FIX_NO_ACTION_AFTER_CHANGE
 		/* if element already changed in this frame, not only prevent
 		   another element change (checked in ChangeElement()), but
 		   also prevent additional element actions for this element */
@@ -11642,24 +10386,10 @@ static boolean CheckTriggeredElementChangeExt(int trigger_x, int trigger_y,
 		if (ChangeCount[x][y] >= game.max_num_changes_per_frame &&
 		    !level.use_action_after_change_bug)
 		  continue;
-#endif
-
 
-#if 0
-		printf("::: TRIGGERED CHANGE FOUND: %d ['%s'], %d -- ACTION\n",
-		       element, EL_NAME(element), p);
-#endif
-
-		ExecuteCustomElementAction(x, y, element, p);
-		PlayLevelSoundElementAction(x, y, element, ACTION_PAGE_1 + p);
-	      }
-#else
-	      if (change->has_action)
-	      {
 		ExecuteCustomElementAction(x, y, element, p);
 		PlayLevelSoundElementAction(x, y, element, ACTION_PAGE_1 + p);
 	      }
-#endif
 	    }
 	  }
 
@@ -11667,12 +10397,6 @@ static boolean CheckTriggeredElementChangeExt(int trigger_x, int trigger_y,
 	  {
 	    change_done = TRUE;
 	    change_done_any = TRUE;
-
-#if 0
-	    printf("::: TRIGGERED CHANGE FOUND: %d ['%s'], %d -- DONE\n",
-		   element, EL_NAME(element), p);
-#endif
-
 	  }
 	}
       }
@@ -11704,11 +10428,6 @@ static boolean CheckElementChangeExt(int x, int y,
     element = Feld[x][y];
   }
 
-#if 0
-  /* check if element has already changed */
-  if (Feld[x][y] != element)
-    return FALSE;
-#else
   /* check if element has already changed or is about to change after moving */
   if ((game.engine_version < VERSION_IDENT(3,2,0,7) &&
        Feld[x][y] != element) ||
@@ -11717,19 +10436,8 @@ static boolean CheckElementChangeExt(int x, int y,
        (ChangeCount[x][y] >= game.max_num_changes_per_frame ||
 	ChangePage[x][y] != -1)))
     return FALSE;
-#endif
-
-#if 0
-  printf("::: CheckElementChangeExt %d ... [%d, %d, %d, '%s']\n",
-	 trigger_event, recursion_loop_depth, recursion_loop_detected,
-	 recursion_loop_element, EL_NAME(recursion_loop_element));
-#endif
 
-  RECURSION_LOOP_DETECTION_START(trigger_element, FALSE);
-
-#if 0
-  printf("::: X: trigger_player_bits == %d\n", trigger_player);
-#endif
+  RECURSION_LOOP_DETECTION_START(trigger_element, FALSE);
 
   for (p = 0; p < element_info[element].num_change_pages; p++)
   {
@@ -11743,10 +10451,7 @@ static boolean CheckElementChangeExt(int x, int y,
       (trigger_event == CE_TOUCHING_X ||
        trigger_event == CE_HITTING_X ||
        trigger_event == CE_HIT_BY_X ||
-#if 1
-       /* this one was forgotten until 3.2.3 */
-       trigger_event == CE_DIGGING_X);
-#endif
+       trigger_event == CE_DIGGING_X); /* this one was forgotten until 3.2.3 */
 
     if (change->can_change_or_has_action &&
 	change->has_event[trigger_event] &&
@@ -11795,19 +10500,11 @@ static boolean CheckElementChangeExt(int x, int y,
 
 	change_done = TRUE;
       }
-#if USE_NEW_DELAYED_ACTION
       else if (change->has_action)
       {
 	ExecuteCustomElementAction(x, y, element, p);
 	PlayLevelSoundElementAction(x, y, element, ACTION_PAGE_1 + p);
       }
-#else
-      if (change->has_action)
-      {
-	ExecuteCustomElementAction(x, y, element, p);
-	PlayLevelSoundElementAction(x, y, element, ACTION_PAGE_1 + p);
-      }
-#endif
     }
   }
 
@@ -11998,9 +10695,51 @@ static void SetPlayerWaiting(struct PlayerInfo *player, boolean is_waiting)
   }
 }
 
+static void CheckSaveEngineSnapshot(struct PlayerInfo *player)
+{
+  if ((!player->is_moving  && player->was_moving) ||
+      (player->MovPos == 0 && player->was_moving) ||
+      (player->is_snapping && !player->was_snapping) ||
+      (player->is_dropping && !player->was_dropping))
+  {
+    if (!CheckSaveEngineSnapshotToList())
+      return;
+
+    player->was_moving = FALSE;
+    player->was_snapping = TRUE;
+    player->was_dropping = TRUE;
+  }
+  else
+  {
+    if (player->is_moving)
+      player->was_moving = TRUE;
+
+    if (!player->is_snapping)
+      player->was_snapping = FALSE;
+
+    if (!player->is_dropping)
+      player->was_dropping = FALSE;
+  }
+}
+
+static void CheckSingleStepMode(struct PlayerInfo *player)
+{
+  if (tape.single_step && tape.recording && !tape.pausing)
+  {
+    /* as it is called "single step mode", just return to pause mode when the
+       player stopped moving after one tile (or never starts moving at all) */
+    if (!player->is_moving && !player->is_pushing)
+    {
+      TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
+      SnapField(player, 0, 0);			/* stop snapping */
+    }
+  }
+
+  CheckSaveEngineSnapshot(player);
+}
+
 static byte PlayerActions(struct PlayerInfo *player, byte player_action)
 {
-  boolean moved = FALSE, snapped = FALSE, dropped = FALSE;
   int left	= player_action & JOY_LEFT;
   int right	= player_action & JOY_RIGHT;
   int up	= player_action & JOY_UP;
@@ -12016,32 +10755,16 @@ static byte PlayerActions(struct PlayerInfo *player, byte player_action)
   if (player_action)
   {
     if (button1)
-      snapped = SnapField(player, dx, dy);
+      SnapField(player, dx, dy);
     else
     {
       if (button2)
-	dropped = DropElement(player);
+	DropElement(player);
 
-      moved = MovePlayer(player, dx, dy);
+      MovePlayer(player, dx, dy);
     }
 
-    if (tape.single_step && tape.recording && !tape.pausing)
-    {
-#if 1
-      /* as it is called "single step mode", just return to pause mode when the
-	 player stopped moving after one tile (or never starts moving at all) */
-      if (!player->is_moving)
-#else
-      /* this is buggy: there are quite some cases where the single step mode
-	 does not return to pause mode (like pushing things that don't move
-	 or simply by trying to run against a wall) */
-      if (button1 || (dropped && !moved))
-#endif
-      {
-	TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
-	SnapField(player, 0, 0);		/* stop snapping */
-      }
-    }
+    CheckSingleStepMode(player);
 
     SetPlayerWaiting(player, FALSE);
 
@@ -12065,6 +10788,8 @@ static byte PlayerActions(struct PlayerInfo *player, byte player_action)
     player->is_dropping_pressed = FALSE;
     player->drop_pressed_delay = 0;
 
+    CheckSingleStepMode(player);
+
     return 0;
   }
 }
@@ -12136,13 +10861,10 @@ static void CheckLevelTime()
 	if (TimeLeft <= 10 && setup.time_limit)
 	  PlaySound(SND_GAME_RUNNING_OUT_OF_TIME);
 
-#if 1
-	game_panel_controls[GAME_PANEL_TIME].value = TimeLeft;
+	/* this does not make sense: game_panel_controls[GAME_PANEL_TIME].value
+	   is reset from other values in UpdateGameDoorValues() -- FIX THIS */
 
-	DisplayGameControlValues();
-#else
-	DrawGameValue_Time(TimeLeft);
-#endif
+	game_panel_controls[GAME_PANEL_TIME].value = TimeLeft;
 
 	if (!TimeLeft && setup.time_limit)
 	{
@@ -12153,32 +10875,23 @@ static void CheckLevelTime()
 	      KillPlayer(&stored_player[i]);
 	}
       }
-#if 1
-      else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */
+      else if (game.no_time_limit && !AllPlayersGone) /* level w/o time limit */
       {
 	game_panel_controls[GAME_PANEL_TIME].value = TimePlayed;
-
-	DisplayGameControlValues();
       }
-#else
-      else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */
-	DrawGameValue_Time(TimePlayed);
-#endif
 
       level.native_em_level->lev->time =
-	(level.time == 0 ? TimePlayed : TimeLeft);
+	(game.no_time_limit ? TimePlayed : TimeLeft);
     }
 
     if (tape.recording || tape.playing)
       DrawVideoDisplay(VIDEO_STATE_TIME_ON, TapeTime);
   }
 
-#if 1
+  if (tape.recording || tape.playing)
+    DrawVideoDisplay(VIDEO_STATE_FRAME_ON, FrameCounter);
+
   UpdateAndDisplayGameControlValues();
-#else
-  UpdateGameDoorValues();
-  DrawGameDoorValues();
-#endif
 }
 
 void AdvanceFrameAndPlayerCounters(int player_nr)
@@ -12199,7 +10912,6 @@ void AdvanceFrameAndPlayerCounters(int player_nr)
     if (!advance_player_counters)	/* not all players may be affected */
       continue;
 
-#if USE_NEW_PLAYER_ANIM
     if (move_frames == 0)	/* less than one move per game frame */
     {
       int stepsize = TILEX / move_delay_value;
@@ -12210,7 +10922,6 @@ void AdvanceFrameAndPlayerCounters(int player_nr)
       if (count % delay == 0)
 	move_frames = 1;
     }
-#endif
 
     stored_player[i].Frame += move_frames;
 
@@ -12233,9 +10944,9 @@ void AdvanceFrameAndPlayerCounters(int player_nr)
 }
 
 void StartGameActions(boolean init_network_game, boolean record_tape,
-		      long random_seed)
+		      int random_seed)
 {
-  unsigned long new_random_seed = InitRND(random_seed);
+  unsigned int new_random_seed = InitRND(random_seed);
 
   if (record_tape)
     TapeStartRecording(new_random_seed);
@@ -12252,10 +10963,12 @@ void StartGameActions(boolean init_network_game, boolean record_tape,
   InitGame();
 }
 
-void GameActions()
+void GameActionsExt()
 {
-  static unsigned long game_frame_delay = 0;
-  unsigned long game_frame_delay_value;
+#if 0
+  static unsigned int game_frame_delay = 0;
+#endif
+  unsigned int game_frame_delay_value;
   byte *recorded_player_action;
   byte summarized_player_action = 0;
   byte tape_action[MAX_PLAYERS];
@@ -12264,9 +10977,9 @@ void GameActions()
   /* detect endless loops, caused by custom element programming */
   if (recursion_loop_detected && recursion_loop_depth == 0)
   {
-    char *message = getStringCat3("Internal Error ! Element ",
+    char *message = getStringCat3("Internal Error! Element ",
 				  EL_NAME(recursion_loop_element),
-				  " caused endless loop ! Quit the game ?");
+				  " caused endless loop! Quit the game?");
 
     Error(ERR_WARN, "element '%s' caused endless loop in game engine",
 	  EL_NAME(recursion_loop_element));
@@ -12332,9 +11045,22 @@ void GameActions()
   if (tape.playing && tape.warp_forward && !tape.pausing)
     game_frame_delay_value = 0;
 
+  SetVideoFrameDelay(game_frame_delay_value);
+
+#if 0
+#if 0
+  /* ---------- main game synchronization point ---------- */
+
+  int skip = WaitUntilDelayReached(&game_frame_delay, game_frame_delay_value);
+
+  printf("::: skip == %d\n", skip);
+
+#else
   /* ---------- main game synchronization point ---------- */
 
   WaitUntilDelayReached(&game_frame_delay, game_frame_delay_value);
+#endif
+#endif
 
   if (network_playing && !network_player_action_received)
   {
@@ -12365,11 +11091,9 @@ void GameActions()
   /* when playing tape, read previously recorded player input from tape data */
   recorded_player_action = (tape.playing ? TapePlayAction() : NULL);
 
-#if 1
   /* TapePlayAction() may return NULL when toggling to "pause before death" */
   if (tape.pausing)
     return;
-#endif
 
   if (tape.set_centered_player)
   {
@@ -12381,7 +11105,7 @@ void GameActions()
   {
     summarized_player_action |= stored_player[i].action;
 
-    if (!network_playing)
+    if (!network_playing && (game.team_mode || tape.playing))
       stored_player[i].effective_action = stored_player[i].action;
   }
 
@@ -12390,10 +11114,16 @@ void GameActions()
     SendToServer_MovePlayer(summarized_player_action);
 #endif
 
-  if (!options.network && !setup.team_mode)
-    local_player->effective_action = summarized_player_action;
+  // summarize all actions at local players mapped input device position
+  // (this allows using different input devices in single player mode)
+  if (!options.network && !game.team_mode)
+    stored_player[map_player_action[local_player->index_nr]].effective_action =
+      summarized_player_action;
 
-  if (setup.team_mode && setup.input_on_focus && game.centered_player_nr != -1)
+  if (tape.recording &&
+      setup.team_mode &&
+      setup.input_on_focus &&
+      game.centered_player_nr != -1)
   {
     for (i = 0; i < MAX_PLAYERS; i++)
       stored_player[i].effective_action =
@@ -12408,9 +11138,13 @@ void GameActions()
   {
     tape_action[i] = stored_player[i].effective_action;
 
-    /* (this can only happen in the R'n'D game engine) */
-    if (tape.recording && tape_action[i] && !tape.player_participates[i])
-      tape.player_participates[i] = TRUE;    /* player just appeared from CE */
+    /* (this may happen in the RND game engine if a player was not present on
+       the playfield on level start, but appeared later from a custom element */
+    if (setup.team_mode &&
+	tape.recording &&
+	tape_action[i] &&
+	!tape.player_participates[i])
+      tape.player_participates[i] = TRUE;
   }
 
   /* only record actions from input devices, but not programmed actions */
@@ -12418,16 +11152,56 @@ void GameActions()
     TapeRecordAction(tape_action);
 
 #if USE_NEW_PLAYER_ASSIGNMENTS
+  // !!! also map player actions in single player mode !!!
+  // if (game.team_mode)
+  if (1)
   {
     byte mapped_action[MAX_PLAYERS];
 
+#if DEBUG_PLAYER_ACTIONS
+    printf(":::");
+    for (i = 0; i < MAX_PLAYERS; i++)
+      printf(" %d, ", stored_player[i].effective_action);
+#endif
+
     for (i = 0; i < MAX_PLAYERS; i++)
       mapped_action[i] = stored_player[map_player_action[i]].effective_action;
 
     for (i = 0; i < MAX_PLAYERS; i++)
       stored_player[i].effective_action = mapped_action[i];
+
+#if DEBUG_PLAYER_ACTIONS
+    printf(" =>");
+    for (i = 0; i < MAX_PLAYERS; i++)
+      printf(" %d, ", stored_player[i].effective_action);
+    printf("\n");
+#endif
+  }
+#if DEBUG_PLAYER_ACTIONS
+  else
+  {
+    printf(":::");
+    for (i = 0; i < MAX_PLAYERS; i++)
+      printf(" %d, ", stored_player[i].effective_action);
+    printf("\n");
   }
 #endif
+#endif
+
+  for (i = 0; i < MAX_PLAYERS; i++)
+  {
+    // allow engine snapshot in case of changed movement attempt
+    if ((game.snapshot.last_action[i] & KEY_MOTION) !=
+	(stored_player[i].effective_action & KEY_MOTION))
+      game.snapshot.changed_action = TRUE;
+
+    // allow engine snapshot in case of snapping/dropping attempt
+    if ((game.snapshot.last_action[i] & KEY_BUTTON) == 0 &&
+	(stored_player[i].effective_action & KEY_BUTTON) != 0)
+      game.snapshot.changed_action = TRUE;
+
+    game.snapshot.last_action[i] = stored_player[i].effective_action;
+  }
 
   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
   {
@@ -12439,10 +11213,53 @@ void GameActions()
   }
   else
   {
-    GameActions_RND();
+    GameActions_RND_Main();
+  }
+
+  BlitScreenToBitmap(backbuffer);
+
+  CheckLevelTime();
+
+  AdvanceFrameAndPlayerCounters(-1);	/* advance counters for all players */
+
+  if (options.debug)			/* calculate frames per second */
+  {
+    static unsigned int fps_counter = 0;
+    static int fps_frames = 0;
+    unsigned int fps_delay_ms = Counter() - fps_counter;
+
+    fps_frames++;
+
+    if (fps_delay_ms >= 500)	/* calculate fps every 0.5 seconds */
+    {
+      global.frames_per_second = 1000 * (float)fps_frames / fps_delay_ms;
+
+      fps_frames = 0;
+      fps_counter = Counter();
+    }
+
+    redraw_mask |= REDRAW_FPS;
   }
 }
 
+static void GameActions_CheckSaveEngineSnapshot()
+{
+  if (!game.snapshot.save_snapshot)
+    return;
+
+  // clear flag for saving snapshot _before_ saving snapshot
+  game.snapshot.save_snapshot = FALSE;
+
+  SaveEngineSnapshotToList();
+}
+
+void GameActions()
+{
+  GameActionsExt();
+
+  GameActions_CheckSaveEngineSnapshot();
+}
+
 void GameActions_EM_Main()
 {
   byte effective_action[MAX_PLAYERS];
@@ -12453,10 +11270,6 @@ void GameActions_EM_Main()
     effective_action[i] = stored_player[i].effective_action;
 
   GameActions_EM(effective_action, warp_mode);
-
-  CheckLevelTime();
-
-  AdvanceFrameAndPlayerCounters(-1);	/* advance counters for all players */
 }
 
 void GameActions_SP_Main()
@@ -12469,20 +11282,20 @@ void GameActions_SP_Main()
     effective_action[i] = stored_player[i].effective_action;
 
   GameActions_SP(effective_action, warp_mode);
+}
 
-  CheckLevelTime();
-
-  AdvanceFrameAndPlayerCounters(-1);	/* advance counters for all players */
+void GameActions_RND_Main()
+{
+  GameActions_RND();
 }
 
 void GameActions_RND()
 {
   int magic_wall_x = 0, magic_wall_y = 0;
-  int i, x, y, element, graphic;
+  int i, x, y, element, graphic, last_gfx_frame;
 
   InitPlayfieldScanModeVars();
 
-#if USE_ONE_MORE_CHANGE_PER_FRAME
   if (game.engine_version >= VERSION_IDENT(3,2,0,7))
   {
     SCAN_PLAYFIELD(x, y)
@@ -12491,7 +11304,6 @@ void GameActions_RND()
       ChangeEvent[x][y] = -1;
     }
   }
-#endif
 
   if (game.set_centered_player)
   {
@@ -12591,10 +11403,6 @@ void GameActions_RND()
     }
   }
 
-#if 0
-  debug_print_timestamp(0, "start main loop profiling");
-#endif
-
   SCAN_PLAYFIELD(x, y)
   {
     ChangeCount[x][y] = 0;
@@ -12608,7 +11416,6 @@ void GameActions_RND()
 	RemoveField(x, y);
     }
 
-#if USE_NEW_SNAP_DELAY
     if (Feld[x][y] == EL_ELEMENT_SNAPPING)
     {
       MovDelay[x][y]--;
@@ -12620,7 +11427,6 @@ void GameActions_RND()
 	TestIfElementTouchesCustomElement(x, y);	/* for empty space */
       }
     }
-#endif
 
 #if DEBUG
     if (ChangePage[x][y] != -1 && ChangeDelay[x][y] != 1)
@@ -12669,69 +11475,16 @@ void GameActions_RND()
 #endif
   }
 
-#if 0
-  debug_print_timestamp(0, "- time for pre-main loop:");
-#endif
-
-#if 0	// -------------------- !!! TEST ONLY !!! --------------------
   SCAN_PLAYFIELD(x, y)
   {
     element = Feld[x][y];
     graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
+    last_gfx_frame = GfxFrame[x][y];
 
-#if 1
-    {
-#if 1
-      int element2 = element;
-      int graphic2 = graphic;
-#else
-      int element2 = Feld[x][y];
-      int graphic2 = el_act_dir2img(element2, GfxAction[x][y], GfxDir[x][y]);
-#endif
-      int last_gfx_frame = GfxFrame[x][y];
-
-      if (graphic_info[graphic2].anim_global_sync)
-	GfxFrame[x][y] = FrameCounter;
-      else if (ANIM_MODE(graphic2) == ANIM_CE_VALUE)
-	GfxFrame[x][y] = CustomValue[x][y];
-      else if (ANIM_MODE(graphic2) == ANIM_CE_SCORE)
-	GfxFrame[x][y] = element_info[element2].collect_score;
-      else if (ANIM_MODE(graphic2) == ANIM_CE_DELAY)
-	GfxFrame[x][y] = ChangeDelay[x][y];
-
-      if (redraw && GfxFrame[x][y] != last_gfx_frame)
-	DrawLevelGraphicAnimation(x, y, graphic2);
-    }
-#else
-    ResetGfxFrame(x, y, TRUE);
-#endif
-
-#if 1
-    if (ANIM_MODE(graphic) == ANIM_RANDOM &&
-	IS_NEXT_FRAME(GfxFrame[x][y], graphic))
-      ResetRandomAnimationValue(x, y);
-#endif
-
-#if 1
-    SetRandomAnimationValue(x, y);
-#endif
-
-#if 1
-    PlayLevelSoundActionIfLoop(x, y, GfxAction[x][y]);
-#endif
-  }
-#endif	// -------------------- !!! TEST ONLY !!! --------------------
-
-#if 0
-  debug_print_timestamp(0, "- time for TEST loop:     -->");
-#endif
-
-  SCAN_PLAYFIELD(x, y)
-  {
-    element = Feld[x][y];
-    graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
+    ResetGfxFrame(x, y);
 
-    ResetGfxFrame(x, y, TRUE);
+    if (GfxFrame[x][y] != last_gfx_frame && !Stop[x][y])
+      DrawLevelGraphicAnimation(x, y, graphic);
 
     if (ANIM_MODE(graphic) == ANIM_RANDOM &&
 	IS_NEXT_FRAME(GfxFrame[x][y], graphic))
@@ -12755,22 +11508,12 @@ void GameActions_RND()
     {
       int page = element_info[element].event_page_nr[CE_DELAY];
 
-#if 1
       HandleElementChange(x, y, page);
-#else
-      if (CAN_CHANGE(element))
-	HandleElementChange(x, y, page);
-
-      if (HAS_ACTION(element))
-	ExecuteCustomElementAction(x, y, element, page);
-#endif
 
       element = Feld[x][y];
       graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
     }
 
-#if 0	// ---------------------------------------------------------------------
-
     if (!IS_MOVING(x, y) && (CAN_FALL(element) || CAN_MOVE(element)))
     {
       StartMoving(x, y);
@@ -12786,143 +11529,12 @@ void GameActions_RND()
       if (IS_GEM(element) || element == EL_SP_INFOTRON)
 	TEST_DrawTwinkleOnField(x, y);
     }
-    else if (IS_MOVING(x, y))
-      ContinueMoving(x, y);
-    else
-    {
-      switch (element)
-      {
-        case EL_ACID:
-        case EL_EXIT_OPEN:
-        case EL_EM_EXIT_OPEN:
-        case EL_SP_EXIT_OPEN:
-        case EL_STEEL_EXIT_OPEN:
-        case EL_EM_STEEL_EXIT_OPEN:
-        case EL_SP_TERMINAL:
-        case EL_SP_TERMINAL_ACTIVE:
-        case EL_EXTRA_TIME:
-        case EL_SHIELD_NORMAL:
-        case EL_SHIELD_DEADLY:
-	  if (IS_ANIMATED(graphic))
-	    DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
-	  break;
-
-        case EL_DYNAMITE_ACTIVE:
-        case EL_EM_DYNAMITE_ACTIVE:
-        case EL_DYNABOMB_PLAYER_1_ACTIVE:
-        case EL_DYNABOMB_PLAYER_2_ACTIVE:
-        case EL_DYNABOMB_PLAYER_3_ACTIVE:
-        case EL_DYNABOMB_PLAYER_4_ACTIVE:
-        case EL_SP_DISK_RED_ACTIVE:
-	  CheckDynamite(x, y);
-	  break;
-
-        case EL_AMOEBA_GROWING:
-	  AmoebeWaechst(x, y);
-	  break;
-
-        case EL_AMOEBA_SHRINKING:
-	  AmoebaDisappearing(x, y);
-	  break;
-
-#if !USE_NEW_AMOEBA_CODE
-        case EL_AMOEBA_WET:
-        case EL_AMOEBA_DRY:
-        case EL_AMOEBA_FULL:
-        case EL_BD_AMOEBA:
-        case EL_EMC_DRIPPER:
-	  AmoebeAbleger(x, y);
-	  break;
-#endif
-
-        case EL_GAME_OF_LIFE:
-        case EL_BIOMAZE:
-	  Life(x, y);
-	  break;
-
-        case EL_EXIT_CLOSED:
-	  CheckExit(x, y);
-	  break;
-
-        case EL_EM_EXIT_CLOSED:
-	  CheckExitEM(x, y);
-	  break;
-
-        case EL_STEEL_EXIT_CLOSED:
-	  CheckExitSteel(x, y);
-	  break;
-
-        case EL_EM_STEEL_EXIT_CLOSED:
-	  CheckExitSteelEM(x, y);
-	  break;
-
-        case EL_SP_EXIT_CLOSED:
-	  CheckExitSP(x, y);
-	  break;
-
-        case EL_EXPANDABLE_WALL_GROWING:
-        case EL_EXPANDABLE_STEELWALL_GROWING:
-	  MauerWaechst(x, y);
-	  break;
-
-        case EL_EXPANDABLE_WALL:
-        case EL_EXPANDABLE_WALL_HORIZONTAL:
-        case EL_EXPANDABLE_WALL_VERTICAL:
-        case EL_EXPANDABLE_WALL_ANY:
-        case EL_BD_EXPANDABLE_WALL:
-	  MauerAbleger(x, y);
-	  break;
-
-        case EL_EXPANDABLE_STEELWALL_HORIZONTAL:
-        case EL_EXPANDABLE_STEELWALL_VERTICAL:
-        case EL_EXPANDABLE_STEELWALL_ANY:
-	  MauerAblegerStahl(x, y);
-	  break;
-
-        case EL_FLAMES:
-	  CheckForDragon(x, y);
-	  break;
-
-        case EL_EXPLOSION:
-	  break;
-
-        case EL_ELEMENT_SNAPPING:
-        case EL_DIAGONAL_SHRINKING:
-        case EL_DIAGONAL_GROWING:
-	{
-	  graphic =
-	    el_act_dir2img(GfxElement[x][y], GfxAction[x][y],GfxDir[x][y]);
-
-	  DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
-	  break;
-	}
-
-        default:
-	  if (IS_ANIMATED(graphic) && !IS_CHANGING(x, y))
-	    DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
-	  break;
-      }
-    }
-
-#else	// ---------------------------------------------------------------------
-
-    if (!IS_MOVING(x, y) && (CAN_FALL(element) || CAN_MOVE(element)))
+    else if (element == EL_ACID)
     {
-      StartMoving(x, y);
-
-      element = Feld[x][y];
-      graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
-
-      if (IS_ANIMATED(graphic) &&
-	  !IS_MOVING(x, y) &&
-	  !Stop[x][y])
+      if (!Stop[x][y])
 	DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
-
-      if (IS_GEM(element) || element == EL_SP_INFOTRON)
-	TEST_DrawTwinkleOnField(x, y);
     }
-    else if ((element == EL_ACID ||
-	      element == EL_EXIT_OPEN ||
+    else if ((element == EL_EXIT_OPEN ||
 	      element == EL_EM_EXIT_OPEN ||
 	      element == EL_SP_EXIT_OPEN ||
 	      element == EL_STEEL_EXIT_OPEN ||
@@ -12988,8 +11600,6 @@ void GameActions_RND()
     else if (IS_ANIMATED(graphic) && !IS_CHANGING(x, y))
       DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
 
-#endif	// ---------------------------------------------------------------------
-
     if (IS_BELT_ACTIVE(element))
       PlayLevelSoundAction(x, y, ACTION_ACTIVE);
 
@@ -13015,15 +11625,11 @@ void GameActions_RND()
     }
   }
 
-#if 0
-  debug_print_timestamp(0, "- time for MAIN loop:     -->");
-#endif
-
 #if USE_NEW_AMOEBA_CODE
   /* new experimental amoeba growth stuff */
   if (!(FrameCounter % 8))
   {
-    static unsigned long random = 1684108901;
+    static unsigned int random = 1684108901;
 
     for (i = 0; i < level.amoeba_speed * 28 / 8; i++)
     {
@@ -13051,27 +11657,22 @@ void GameActions_RND()
   }
 #endif
 
-#if 0
-  if (game.explosions_delayed)
-#endif
-  {
-    game.explosions_delayed = FALSE;
-
-    SCAN_PLAYFIELD(x, y)
-    {
-      element = Feld[x][y];
+  game.explosions_delayed = FALSE;
 
-      if (ExplodeField[x][y])
-	Explode(x, y, EX_PHASE_START, ExplodeField[x][y]);
-      else if (element == EL_EXPLOSION)
-	Explode(x, y, ExplodePhase[x][y], EX_TYPE_NORMAL);
+  SCAN_PLAYFIELD(x, y)
+  {
+    element = Feld[x][y];
 
-      ExplodeField[x][y] = EX_TYPE_NONE;
-    }
+    if (ExplodeField[x][y])
+      Explode(x, y, EX_PHASE_START, ExplodeField[x][y]);
+    else if (element == EL_EXPLOSION)
+      Explode(x, y, ExplodePhase[x][y], EX_TYPE_NORMAL);
 
-    game.explosions_delayed = TRUE;
+    ExplodeField[x][y] = EX_TYPE_NONE;
   }
 
+  game.explosions_delayed = TRUE;
+
   if (game.magic_wall_active)
   {
     if (!(game.magic_wall_time_left % 4))
@@ -13173,12 +11774,7 @@ void GameActions_RND()
 #if USE_DELAYED_GFX_REDRAW
   SCAN_PLAYFIELD(x, y)
   {
-#if 1
     if (GfxRedraw[x][y] != GFX_REDRAW_NONE)
-#else
-    if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)) &&
-	GfxRedraw[x][y] != GFX_REDRAW_NONE)
-#endif
     {
       /* !!! PROBLEM: THIS REDRAWS THE PLAYFIELD _AFTER_ THE SCAN, BUT TILES
 	 !!! MAY HAVE CHANGED AFTER BEING DRAWN DURING PLAYFIELD SCAN !!! */
@@ -13200,32 +11796,9 @@ void GameActions_RND()
   }
 #endif
 
-  CheckLevelTime();
-
   DrawAllPlayers();
   PlayAllPlayersSound();
 
-  if (options.debug)			/* calculate frames per second */
-  {
-    static unsigned long fps_counter = 0;
-    static int fps_frames = 0;
-    unsigned long fps_delay_ms = Counter() - fps_counter;
-
-    fps_frames++;
-
-    if (fps_delay_ms >= 500)	/* calculate fps every 0.5 seconds */
-    {
-      global.frames_per_second = 1000 * (float)fps_frames / fps_delay_ms;
-
-      fps_frames = 0;
-      fps_counter = Counter();
-    }
-
-    redraw_mask |= REDRAW_FPS;
-  }
-
-  AdvanceFrameAndPlayerCounters(-1);	/* advance counters for all players */
-
   if (local_player->show_envelope != 0 && local_player->MovPos == 0)
   {
     ShowEnvelope(local_player->show_envelope - EL_ENVELOPE_1);
@@ -13233,11 +11806,6 @@ void GameActions_RND()
     local_player->show_envelope = 0;
   }
 
-#if 0
-  debug_print_timestamp(0, "stop main loop profiling ");
-  printf("----------------------------------------------------------\n");
-#endif
-
   /* use random number generator in every frame to make it less predictable */
   if (game.engine_version >= VERSION_IDENT(3,1,1,0))
     RND(1);
@@ -13284,78 +11852,16 @@ static boolean AllPlayersInVisibleScreen()
 
 void ScrollLevel(int dx, int dy)
 {
-#if 0
-  /* (directly solved in BlitBitmap() now) */
-  static Bitmap *bitmap_db_field2 = NULL;
-  int softscroll_offset = (setup.soft_scrolling ? TILEX : 0);
+  int scroll_offset = 2 * TILEX_VAR;
   int x, y;
-#else
-  int x, y;
-#endif
-
-#if 0
-  /* !!! THIS IS APPARENTLY WRONG FOR PLAYER RELOCATION !!! */
-  /* only horizontal XOR vertical scroll direction allowed */
-  if ((dx == 0 && dy == 0) || (dx != 0 && dy != 0))
-    return;
-#endif
-
-#if 0
-  /* (directly solved in BlitBitmap() now) */
-  if (bitmap_db_field2 == NULL)
-    bitmap_db_field2 = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
-
-  /* needed when blitting directly to same bitmap -- should not be needed with
-     recent SDL libraries, but apparently does not work in 1.2.11 directly */
-  BlitBitmap(drawto_field, bitmap_db_field2,
-	     FX + TILEX * (dx == -1) - softscroll_offset,
-	     FY + TILEY * (dy == -1) - softscroll_offset,
-	     SXSIZE - TILEX * (dx != 0) + 2 * softscroll_offset,
-	     SYSIZE - TILEY * (dy != 0) + 2 * softscroll_offset,
-	     FX + TILEX * (dx == 1) - softscroll_offset,
-	     FY + TILEY * (dy == 1) - softscroll_offset);
-  BlitBitmap(bitmap_db_field2, drawto_field,
-	     FX + TILEX * (dx == 1) - softscroll_offset,
-	     FY + TILEY * (dy == 1) - softscroll_offset,
-	     SXSIZE - TILEX * (dx != 0) + 2 * softscroll_offset,
-	     SYSIZE - TILEY * (dy != 0) + 2 * softscroll_offset,
-	     FX + TILEX * (dx == 1) - softscroll_offset,
-	     FY + TILEY * (dy == 1) - softscroll_offset);
-
-#else
-
-#if 0
-  /* !!! DOES NOT WORK FOR DIAGONAL PLAYER RELOCATION !!! */
-  int xsize = (BX2 - BX1 + 1);
-  int ysize = (BY2 - BY1 + 1);
-  int start = (dx != 0 ? (dx == -1 ? BX1 : BX2) : (dy == -1 ? BY1 : BY2));
-  int end   = (dx != 0 ? (dx == -1 ? BX2 : BX1) : (dy == -1 ? BY2 : BY1));
-  int step  = (start < end ? +1 : -1);
-
-  for (i = start; i != end; i += step)
-  {
-    BlitBitmap(drawto_field, drawto_field,
-	       FX + TILEX * (dx != 0 ? i + step : 0),
-	       FY + TILEY * (dy != 0 ? i + step : 0),
-	       TILEX * (dx != 0 ? 1 : xsize),
-	       TILEY * (dy != 0 ? 1 : ysize),
-	       FX + TILEX * (dx != 0 ? i : 0),
-	       FY + TILEY * (dy != 0 ? i : 0));
-  }
-
-#else
-
-  int softscroll_offset = (setup.soft_scrolling ? TILEX : 0);
 
   BlitBitmap(drawto_field, drawto_field,
-	     FX + TILEX * (dx == -1) - softscroll_offset,
-	     FY + TILEY * (dy == -1) - softscroll_offset,
-	     SXSIZE - TILEX * (dx != 0) + 2 * softscroll_offset,
-	     SYSIZE - TILEY * (dy != 0) + 2 * softscroll_offset,
-	     FX + TILEX * (dx == 1) - softscroll_offset,
-	     FY + TILEY * (dy == 1) - softscroll_offset);
-#endif
-#endif
+	     FX + TILEX_VAR * (dx == -1) - scroll_offset,
+	     FY + TILEY_VAR * (dy == -1) - scroll_offset,
+	     SXSIZE - TILEX_VAR * (dx != 0) + 2 * scroll_offset,
+	     SYSIZE - TILEY_VAR * (dy != 0) + 2 * scroll_offset,
+	     FX + TILEX_VAR * (dx == 1) - scroll_offset,
+	     FY + TILEY_VAR * (dy == 1) - scroll_offset);
 
   if (dx != 0)
   {
@@ -13418,11 +11924,7 @@ static boolean canMoveToValidFieldWithGravity(int x, int y, int move_dir)
 
 static void CheckGravityMovement(struct PlayerInfo *player)
 {
-#if USE_PLAYER_GRAVITY
   if (player->gravity && !player->programmed_action)
-#else
-  if (game.gravity && !player->programmed_action)
-#endif
   {
     int move_dir_horizontal = player->effective_action & MV_HORIZONTAL;
     int move_dir_vertical   = player->effective_action & MV_VERTICAL;
@@ -13444,11 +11946,7 @@ static void CheckGravityMovementWhenNotMoving(struct PlayerInfo *player)
 {
   return CheckGravityMovement(player);
 
-#if USE_PLAYER_GRAVITY
   if (player->gravity && !player->programmed_action)
-#else
-  if (game.gravity && !player->programmed_action)
-#endif
   {
     int jx = player->jx, jy = player->jy;
     boolean field_under_player_is_free =
@@ -13475,9 +11973,6 @@ boolean MovePlayerOneStep(struct PlayerInfo *player,
 {
   int jx = player->jx, jy = player->jy;
   int new_jx = jx + dx, new_jy = jy + dy;
-#if !USE_FIXED_DONT_RUN_INTO
-  int element;
-#endif
   int can_move;
   boolean player_can_move = !player->cannot_move;
 
@@ -13504,36 +11999,9 @@ boolean MovePlayerOneStep(struct PlayerInfo *player,
     }
   }
 
-#if 1
   if (!options.network && game.centered_player_nr == -1 &&
       !AllPlayersInSight(player, new_jx, new_jy))
     return MP_NO_ACTION;
-#else
-  if (!options.network && !AllPlayersInSight(player, new_jx, new_jy))
-    return MP_NO_ACTION;
-#endif
-
-#if !USE_FIXED_DONT_RUN_INTO
-  element = MovingOrBlocked2ElementIfNotLeaving(new_jx, new_jy);
-
-  /* (moved to DigField()) */
-  if (player_can_move && DONT_RUN_INTO(element))
-  {
-    if (element == EL_ACID && dx == 0 && dy == 1)
-    {
-      SplashAcid(new_jx, new_jy);
-      Feld[jx][jy] = EL_PLAYER_1;
-      InitMovingField(jx, jy, MV_DOWN);
-      Store[jx][jy] = EL_ACID;
-      ContinueMoving(jx, jy);
-      BuryPlayer(player);
-    }
-    else
-      TestIfPlayerRunsIntoBadThing(jx, jy, player->MovDir);
-
-    return MP_MOVING;
-  }
-#endif
 
   can_move = DigField(player, jx, jy, new_jx, new_jy, real_dx,real_dy, DF_DIG);
   if (can_move != MP_MOVING)
@@ -13563,9 +12031,7 @@ boolean MovePlayerOneStep(struct PlayerInfo *player,
 
   PlayerVisit[jx][jy] = FrameCounter;
 
-#if USE_UFAST_PLAYER_EXIT_BUGFIX
   player->is_moving = TRUE;
-#endif
 
 #if 1
   /* should better be called in MovePlayer(), but this breaks some tapes */
@@ -13617,7 +12083,7 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
     int original_move_delay_value = player->move_delay_value;
 
 #if DEBUG
-    printf("THIS SHOULD ONLY HAPPEN WITH PRE-1.2 LEVEL TAPES. [%ld]\n",
+    printf("THIS SHOULD ONLY HAPPEN WITH PRE-1.2 LEVEL TAPES. [%d]\n",
 	   tape.counter);
 #endif
 
@@ -13632,7 +12098,7 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
       AdvanceFrameAndPlayerCounters(player->index_nr);
 
       DrawAllPlayers();
-      BackToFront();
+      BackToFront_WithFrameDelay(0);
     }
 
     player->move_delay_value = original_move_delay_value;
@@ -13651,7 +12117,6 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
       moved |= MovePlayerOneStep(player, 0, dy, dx, dy);
   }
 
-#if USE_FIXED_BORDER_RUNNING_GFX
   if (!moved && !player->is_active)
   {
     player->is_moving = FALSE;
@@ -13660,19 +12125,13 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
     player->is_snapping = FALSE;
     player->is_pushing = FALSE;
   }
-#endif
 
   jx = player->jx;
   jy = player->jy;
 
-#if 1
   if (moved & MP_MOVING && !ScreenMovPos &&
       (player->index_nr == game.centered_player_nr ||
        game.centered_player_nr == -1))
-#else
-  if (moved & MP_MOVING && !ScreenMovPos &&
-      (player == local_player || !options.network))
-#endif
   {
     int old_scroll_x = scroll_x, old_scroll_y = scroll_y;
     int offset = game.scroll_delay_value;
@@ -13727,7 +12186,6 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
 
     if (scroll_x != old_scroll_x || scroll_y != old_scroll_y)
     {
-#if 1
       if (!options.network && game.centered_player_nr == -1 &&
 	  !AllPlayersInVisibleScreen())
       {
@@ -13735,14 +12193,6 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
 	scroll_y = old_scroll_y;
       }
       else
-#else
-      if (!options.network && !AllPlayersInVisibleScreen())
-      {
-	scroll_x = old_scroll_x;
-	scroll_y = old_scroll_y;
-      }
-      else
-#endif
       {
 	ScrollScreen(player, SCROLL_INIT);
 	ScrollLevel(old_scroll_x - scroll_x, old_scroll_y - scroll_y);
@@ -13810,16 +12260,11 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
   int last_jx = player->last_jx, last_jy = player->last_jy;
   int move_stepsize = TILEX / player->move_delay_value;
 
-#if USE_NEW_PLAYER_SPEED
   if (!player->active)
     return;
 
   if (player->MovPos == 0 && mode == SCROLL_GO_ON)	/* player not moving */
     return;
-#else
-  if (!player->active || player->MovPos == 0)
-    return;
-#endif
 
   if (mode == SCROLL_INIT)
   {
@@ -13838,13 +12283,8 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
 	last_field_block_delay += player->move_delay_value;
 
 	/* when blocking enabled, prevent moving up despite gravity */
-#if USE_PLAYER_GRAVITY
 	if (player->gravity && player->MovDir == MV_UP)
 	  block_delay_adjustment = -1;
-#else
-	if (game.gravity && player->MovDir == MV_UP)
-	  block_delay_adjustment = -1;
-#endif
       }
 
       /* add block delay adjustment (also possible when not blocking) */
@@ -13854,17 +12294,12 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
       MovDelay[last_jx][last_jy] = last_field_block_delay + 1;
     }
 
-#if USE_NEW_PLAYER_SPEED
     if (player->MovPos != 0)	/* player has not yet reached destination */
       return;
-#else
-    return;
-#endif
   }
   else if (!FrameReached(&player->actual_frame_counter, 1))
     return;
 
-#if USE_NEW_PLAYER_SPEED
   if (player->MovPos != 0)
   {
     player->MovPos += (player->MovPos > 0 ? -1 : 1) * move_stepsize;
@@ -13874,14 +12309,6 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
     if (player->MovPos == 0)
       CheckGravityMovement(player);
   }
-#else
-  player->MovPos += (player->MovPos > 0 ? -1 : 1) * move_stepsize;
-  player->GfxPos = move_stepsize * (player->MovPos / move_stepsize);
-
-  /* before DrawPlayer() to draw correct player graphic for this case */
-  if (player->MovPos == 0)
-    CheckGravityMovement(player);
-#endif
 
   if (player->MovPos == 0)	/* player reached destination field */
   {
@@ -13904,14 +12331,10 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
 
     if (Feld[jx][jy] == EL_EXIT_OPEN ||
 	Feld[jx][jy] == EL_EM_EXIT_OPEN ||
-#if 1
 	Feld[jx][jy] == EL_EM_EXIT_OPENING ||
-#endif
 	Feld[jx][jy] == EL_STEEL_EXIT_OPEN ||
 	Feld[jx][jy] == EL_EM_STEEL_EXIT_OPEN ||
-#if 1
 	Feld[jx][jy] == EL_EM_STEEL_EXIT_OPENING ||
-#endif
 	Feld[jx][jy] == EL_SP_EXIT_OPEN ||
 	Feld[jx][jy] == EL_SP_EXIT_OPENING)	/* <-- special case */
     {
@@ -13950,13 +12373,8 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
 					  CE_PLAYER_ENTERS_X,
 					  player->index_bit, enter_side);
 
-#if USE_FIX_CE_ACTION_WITH_PLAYER
       CheckTriggeredElementChangeBySide(jx, jy, player->initial_element,
 					CE_MOVE_OF_X, move_direction);
-#else
-      CheckTriggeredElementChangeBySide(jx, jy, player->element_nr,
-					CE_MOVE_OF_X, move_direction);
-#endif
     }
 
     if (game.engine_version >= VERSION_IDENT(3,0,7,0))
@@ -13986,40 +12404,34 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
 	if (TimeLeft <= 10 && setup.time_limit)
 	  PlaySound(SND_GAME_RUNNING_OUT_OF_TIME);
 
-#if 1
 	game_panel_controls[GAME_PANEL_TIME].value = TimeLeft;
 
 	DisplayGameControlValues();
-#else
-	DrawGameValue_Time(TimeLeft);
-#endif
 
 	if (!TimeLeft && setup.time_limit)
 	  for (i = 0; i < MAX_PLAYERS; i++)
 	    KillPlayer(&stored_player[i]);
       }
-#if 1
-      else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */
+      else if (game.no_time_limit && !AllPlayersGone) /* level w/o time limit */
       {
 	game_panel_controls[GAME_PANEL_TIME].value = TimePlayed;
 
 	DisplayGameControlValues();
       }
-#else
-      else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */
-	DrawGameValue_Time(TimePlayed);
-#endif
     }
 
     if (tape.single_step && tape.recording && !tape.pausing &&
 	!player->programmed_action)
       TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
+
+    if (!player->programmed_action)
+      CheckSaveEngineSnapshot(player);
   }
 }
 
 void ScrollScreen(struct PlayerInfo *player, int mode)
 {
-  static unsigned long screen_frame_counter = 0;
+  static unsigned int screen_frame_counter = 0;
 
   if (mode == SCROLL_INIT)
   {
@@ -14102,7 +12514,6 @@ void TestIfPlayerTouchesCustomElement(int x, int y)
 					  CE_PLAYER_TOUCHES_X,
 					  player->index_bit, border_side);
 
-#if USE_FIX_CE_ACTION_WITH_PLAYER
       {
 	/* use player element that is initially defined in the level playfield,
 	   not the player element that corresponds to the runtime player number
@@ -14113,7 +12524,6 @@ void TestIfPlayerTouchesCustomElement(int x, int y)
 	CheckElementChangeBySide(xx, yy, border_element, player_element,
 				 CE_TOUCHING_X, border_side);
       }
-#endif
     }
     else if (IS_PLAYER(xx, yy))		/* player found at border element */
     {
@@ -14131,7 +12541,6 @@ void TestIfPlayerTouchesCustomElement(int x, int y)
 					  CE_PLAYER_TOUCHES_X,
 					  player->index_bit, center_side);
 
-#if USE_FIX_CE_ACTION_WITH_PLAYER
       {
 	/* use player element that is initially defined in the level playfield,
 	   not the player element that corresponds to the runtime player number
@@ -14142,15 +12551,12 @@ void TestIfPlayerTouchesCustomElement(int x, int y)
 	CheckElementChangeBySide(x, y, center_element, player_element,
 				 CE_TOUCHING_X, center_side);
       }
-#endif
 
       break;
     }
   }
 }
 
-#if USE_ELEMENT_TOUCHING_BUGFIX
-
 void TestIfElementTouchesCustomElement(int x, int y)
 {
   static int xy[4][2] =
@@ -14236,7 +12642,6 @@ void TestIfElementTouchesCustomElement(int x, int y)
 	CheckElementChangeBySide(x, y, center_element, border_element,
 				 CE_TOUCHING_X, border_side);
 
-#if USE_FIX_CE_ACTION_WITH_PLAYER
     if (IS_PLAYER(xx, yy))
     {
       /* use player element that is initially defined in the level playfield,
@@ -14248,74 +12653,9 @@ void TestIfElementTouchesCustomElement(int x, int y)
       CheckElementChangeBySide(x, y, center_element, player_element,
 			       CE_TOUCHING_X, border_side);
     }
-#endif
-  }
-}
-
-#else
-
-void TestIfElementTouchesCustomElement_OLD(int x, int y)
-{
-  static int xy[4][2] =
-  {
-    { 0, -1 },
-    { -1, 0 },
-    { +1, 0 },
-    { 0, +1 }
-  };
-  static int trigger_sides[4][2] =
-  {
-    /* center side	border side */
-    { CH_SIDE_TOP,	CH_SIDE_BOTTOM	},	/* check top    */
-    { CH_SIDE_LEFT,	CH_SIDE_RIGHT	},	/* check left   */
-    { CH_SIDE_RIGHT,	CH_SIDE_LEFT	},	/* check right  */
-    { CH_SIDE_BOTTOM,	CH_SIDE_TOP	}	/* check bottom */
-  };
-  static int touch_dir[4] =
-  {
-    MV_LEFT | MV_RIGHT,
-    MV_UP   | MV_DOWN,
-    MV_UP   | MV_DOWN,
-    MV_LEFT | MV_RIGHT
-  };
-  boolean change_center_element = FALSE;
-  int center_element = Feld[x][y];	/* should always be non-moving! */
-  int i;
-
-  for (i = 0; i < NUM_DIRECTIONS; i++)
-  {
-    int xx = x + xy[i][0];
-    int yy = y + xy[i][1];
-    int center_side = trigger_sides[i][0];
-    int border_side = trigger_sides[i][1];
-    int border_element;
-
-    if (!IN_LEV_FIELD(xx, yy))
-      continue;
-
-    if (game.engine_version < VERSION_IDENT(3,0,7,0))
-      border_element = Feld[xx][yy];	/* may be moving! */
-    else if (!IS_MOVING(xx, yy) && !IS_BLOCKED(xx, yy))
-      border_element = Feld[xx][yy];
-    else if (MovDir[xx][yy] & touch_dir[i])	/* elements are touching */
-      border_element = MovingOrBlocked2Element(xx, yy);
-    else
-      continue;			/* center and border element do not touch */
-
-    /* check for change of center element (but change it only once) */
-    if (!change_center_element)
-      change_center_element =
-	CheckElementChangeBySide(x, y, center_element, border_element,
-				 CE_TOUCHING_X, border_side);
-
-    /* check for change of border element */
-    CheckElementChangeBySide(xx, yy, border_element, center_element,
-			     CE_TOUCHING_X, center_side);
   }
 }
 
-#endif
-
 void TestIfElementHitsCustomElement(int x, int y, int direction)
 {
   int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
@@ -14352,7 +12692,6 @@ void TestIfElementHitsCustomElement(int x, int y, int direction)
       CheckElementChangeBySide(hitx, hity, touched_element, hitting_element,
 			       CE_HIT_BY_SOMETHING, opposite_direction);
 
-#if USE_FIX_CE_ACTION_WITH_PLAYER
       if (IS_PLAYER(hitx, hity))
       {
 	/* use player element that is initially defined in the level playfield,
@@ -14364,7 +12703,6 @@ void TestIfElementHitsCustomElement(int x, int y, int direction)
 	CheckElementChangeBySide(x, y, hitting_element, player_element,
 				 CE_HITTING_X, touched_side);
       }
-#endif
     }
   }
 
@@ -14373,69 +12711,6 @@ void TestIfElementHitsCustomElement(int x, int y, int direction)
 			   CE_HITTING_SOMETHING, direction);
 }
 
-#if 0
-void TestIfElementSmashesCustomElement(int x, int y, int direction)
-{
-  int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
-  int dy = (direction == MV_UP   ? -1 : direction == MV_DOWN  ? +1 : 0);
-  int hitx = x + dx, hity = y + dy;
-  int hitting_element = Feld[x][y];
-  int touched_element;
-#if 0
-  boolean object_hit = (IN_LEV_FIELD(hitx, hity) &&
-			!IS_FREE(hitx, hity) &&
-			(!IS_MOVING(hitx, hity) ||
-			 MovDir[hitx][hity] != direction ||
-			 ABS(MovPos[hitx][hity]) <= TILEY / 2));
-#endif
-
-  if (IN_LEV_FIELD(hitx, hity) && IS_FREE(hitx, hity))
-    return;
-
-#if 0
-  if (IN_LEV_FIELD(hitx, hity) && !object_hit)
-    return;
-#endif
-
-  touched_element = (IN_LEV_FIELD(hitx, hity) ?
-		     MovingOrBlocked2Element(hitx, hity) : EL_STEELWALL);
-
-  CheckElementChangeBySide(x, y, hitting_element, touched_element,
-			   EP_CAN_SMASH_EVERYTHING, direction);
-
-  if (IN_LEV_FIELD(hitx, hity))
-  {
-    int opposite_direction = MV_DIR_OPPOSITE(direction);
-    int hitting_side = direction;
-    int touched_side = opposite_direction;
-#if 0
-    int touched_element = MovingOrBlocked2Element(hitx, hity);
-#endif
-#if 1
-    boolean object_hit = (!IS_MOVING(hitx, hity) ||
-			  MovDir[hitx][hity] != direction ||
-			  ABS(MovPos[hitx][hity]) <= TILEY / 2);
-
-    object_hit = TRUE;
-#endif
-
-    if (object_hit)
-    {
-      int i;
-
-      CheckElementChangeBySide(hitx, hity, touched_element, hitting_element,
-			       CE_SMASHED_BY_SOMETHING, opposite_direction);
-
-      CheckElementChangeBySide(x, y, hitting_element, touched_element,
-			       CE_OTHER_IS_SMASHING, touched_side);
-
-      CheckElementChangeBySide(hitx, hity, touched_element, hitting_element,
-			       CE_OTHER_GETS_SMASHED, hitting_side);
-    }
-  }
-}
-#endif
-
 void TestIfGoodThingHitsBadThing(int good_x, int good_y, int good_move_dir)
 {
   int i, kill_x = -1, kill_y = -1;
@@ -14767,19 +13042,10 @@ void KillPlayer(struct PlayerInfo *player)
 	 player->killed, player->active, player->reanimated);
 #endif
 
-#if USE_PLAYER_REANIMATION
-#if 1
   if (player->reanimated)	/* killed player may have been reanimated */
     player->killed = player->reanimated = FALSE;
   else
     BuryPlayer(player);
-#else
-  if (player->killed)		/* player may have been reanimated */
-    BuryPlayer(player);
-#endif
-#else
-  BuryPlayer(player);
-#endif
 }
 
 static void KillPlayerUnlessEnemyProtected(int x, int y)
@@ -14833,7 +13099,6 @@ void RemovePlayer(struct PlayerInfo *player)
   ExitY = ZY = jy;
 }
 
-#if USE_NEW_SNAP_DELAY
 static void setFieldForSnapping(int x, int y, int element, int direction)
 {
   struct ElementInfo *ei = &element_info[element];
@@ -14852,7 +13117,6 @@ static void setFieldForSnapping(int x, int y, int element, int direction)
   GfxDir[x][y] = direction;
   GfxFrame[x][y] = -1;
 }
-#endif
 
 /*
   =============================================================================
@@ -14909,11 +13173,7 @@ static int DigField(struct PlayerInfo *player,
   int opposite_direction = MV_DIR_OPPOSITE(move_direction);
   int dig_side = MV_DIR_OPPOSITE(move_direction);
   int old_element = Feld[jx][jy];
-#if USE_FIXED_DONT_RUN_INTO
   int element = MovingOrBlocked2ElementIfNotLeaving(x, y);
-#else
-  int element;
-#endif
   int collect_count;
 
   if (is_player)		/* function can also be called by EL_PENGUIN */
@@ -14936,11 +13196,6 @@ static int DigField(struct PlayerInfo *player,
     }
   }
 
-#if !USE_FIXED_DONT_RUN_INTO
-  if (IS_MOVING(x, y) || IS_PLAYER(x, y))
-    return MP_NO_ACTION;
-#endif
-
   if (IS_TUBE(Back[jx][jy]) && game.engine_version >= VERSION_IDENT(2,2,0,0))
     old_element = Back[jx][jy];
 
@@ -14955,7 +13210,6 @@ static int DigField(struct PlayerInfo *player,
   if (IS_PASSABLE(old_element) && !ACCESS_FROM(old_element,opposite_direction))
     return MP_NO_ACTION;	/* field has no opening in this direction */
 
-#if USE_FIXED_DONT_RUN_INTO
   if (player_can_move && element == EL_ACID && move_direction == MV_DOWN)
   {
     SplashAcid(x, y);
@@ -14968,25 +13222,16 @@ static int DigField(struct PlayerInfo *player,
 
     return MP_DONT_RUN_INTO;
   }
-#endif
 
-#if USE_FIXED_DONT_RUN_INTO
   if (player_can_move && DONT_RUN_INTO(element))
   {
     TestIfPlayerRunsIntoBadThing(jx, jy, player->MovDir);
 
     return MP_DONT_RUN_INTO;
   }
-#endif
 
-#if USE_FIXED_DONT_RUN_INTO
   if (IS_MOVING(x, y) || IS_PLAYER(x, y))
     return MP_NO_ACTION;
-#endif
-
-#if !USE_FIXED_DONT_RUN_INTO
-  element = Feld[x][y];
-#endif
 
   collect_count = element_info[element].collect_count_initial;
 
@@ -15013,17 +13258,10 @@ static int DigField(struct PlayerInfo *player,
     return MP_NO_ACTION;
   }
 
-#if USE_PLAYER_GRAVITY
   if (player->gravity && is_player && !player->is_auto_moving &&
       canFallDown(player) && move_direction != MV_DOWN &&
       !canMoveToValidFieldWithGravity(jx, jy, move_direction))
     return MP_NO_ACTION;	/* player cannot walk here due to gravity */
-#else
-  if (game.gravity && is_player && !player->is_auto_moving &&
-      canFallDown(player) && move_direction != MV_DOWN &&
-      !canMoveToValidFieldWithGravity(jx, jy, move_direction))
-    return MP_NO_ACTION;	/* player cannot walk here due to gravity */
-#endif
 
   if (player_can_move &&
       IS_WALKABLE(element) && ACCESS_FROM(element, opposite_direction))
@@ -15048,14 +13286,10 @@ static int DigField(struct PlayerInfo *player,
     }
     else if (element == EL_EXIT_OPEN ||
 	     element == EL_EM_EXIT_OPEN ||
-#if 1
 	     element == EL_EM_EXIT_OPENING ||
-#endif
 	     element == EL_STEEL_EXIT_OPEN ||
 	     element == EL_EM_STEEL_EXIT_OPEN ||
-#if 1
 	     element == EL_EM_STEEL_EXIT_OPENING ||
-#endif
 	     element == EL_SP_EXIT_OPEN ||
 	     element == EL_SP_EXIT_OPENING)
     {
@@ -15126,29 +13360,17 @@ static int DigField(struct PlayerInfo *player,
 	  element == EL_SP_GRAVITY_PORT_RIGHT ||
 	  element == EL_SP_GRAVITY_PORT_UP ||
 	  element == EL_SP_GRAVITY_PORT_DOWN)
-#if USE_PLAYER_GRAVITY
 	player->gravity = !player->gravity;
-#else
-	game.gravity = !game.gravity;
-#endif
       else if (element == EL_SP_GRAVITY_ON_PORT_LEFT ||
 	       element == EL_SP_GRAVITY_ON_PORT_RIGHT ||
 	       element == EL_SP_GRAVITY_ON_PORT_UP ||
 	       element == EL_SP_GRAVITY_ON_PORT_DOWN)
-#if USE_PLAYER_GRAVITY
 	player->gravity = TRUE;
-#else
-	game.gravity = TRUE;
-#endif
       else if (element == EL_SP_GRAVITY_OFF_PORT_LEFT ||
 	       element == EL_SP_GRAVITY_OFF_PORT_RIGHT ||
 	       element == EL_SP_GRAVITY_OFF_PORT_UP ||
 	       element == EL_SP_GRAVITY_OFF_PORT_DOWN)
-#if USE_PLAYER_GRAVITY
 	player->gravity = FALSE;
-#else
-	game.gravity = FALSE;
-#endif
     }
 
     /* automatically move to the next field with double speed */
@@ -15180,14 +13402,10 @@ static int DigField(struct PlayerInfo *player,
 
     if (mode == DF_SNAP)
     {
-#if USE_NEW_SNAP_DELAY
       if (level.block_snap_field)
 	setFieldForSnapping(x, y, element, move_direction);
       else
 	TestIfElementTouchesCustomElement(x, y);	/* for empty space */
-#else
-      TestIfElementTouchesCustomElement(x, y);		/* for empty space */
-#endif
 
       CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SNAPS_X,
 					  player->index_bit, dig_side);
@@ -15211,13 +13429,9 @@ static int DigField(struct PlayerInfo *player,
     {
       TimeLeft += level.extra_time;
 
-#if 1
       game_panel_controls[GAME_PANEL_TIME].value = TimeLeft;
 
       DisplayGameControlValues();
-#else
-      DrawGameValue_Time(TimeLeft);
-#endif
     }
     else if (element == EL_SHIELD_NORMAL || element == EL_SHIELD_DEADLY)
     {
@@ -15296,13 +13510,11 @@ static int DigField(struct PlayerInfo *player,
       if (local_player->gems_still_needed < 0)
 	local_player->gems_still_needed = 0;
 
-#if 1
+      game.snapshot.collected_item = TRUE;
+
       game_panel_controls[GAME_PANEL_GEMS].value = local_player->gems_still_needed;
 
       DisplayGameControlValues();
-#else
-      DrawGameValue_Emeralds(local_player->gems_still_needed);
-#endif
     }
 
     RaiseScoreElement(element);
@@ -15314,14 +13526,10 @@ static int DigField(struct PlayerInfo *player,
 
     if (mode == DF_SNAP)
     {
-#if USE_NEW_SNAP_DELAY
       if (level.block_snap_field)
 	setFieldForSnapping(x, y, element, move_direction);
       else
 	TestIfElementTouchesCustomElement(x, y);	/* for empty space */
-#else
-      TestIfElementTouchesCustomElement(x, y);		/* for empty space */
-#endif
 
       CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SNAPS_X,
 					  player->index_bit, dig_side);
@@ -15433,13 +13641,8 @@ static int DigField(struct PlayerInfo *player,
 	PlayLevelSoundElementAction(nextx, nexty, EL_SOKOBAN_FIELD_EMPTY,
 				    ACTION_FILLING);
 
-#if 1
       if (local_player->sokobanfields_still_needed == 0 &&
 	  (game.emulation == EMU_SOKOBAN || level.auto_exit_sokoban))
-#else
-      if (local_player->sokobanfields_still_needed == 0 &&
-	  game.emulation == EMU_SOKOBAN)
-#endif
       {
 	PlayerWins(player);
 
@@ -15507,9 +13710,16 @@ static int DigField(struct PlayerInfo *player,
       SCAN_PLAYFIELD(xx, yy)
       {
 	if (Feld[xx][yy] == EL_SP_DISK_YELLOW)
+	{
 	  Bang(xx, yy);
+	}
 	else if (Feld[xx][yy] == EL_SP_TERMINAL)
+	{
 	  Feld[xx][yy] = EL_SP_TERMINAL_ACTIVE;
+
+	  ResetGfxAnimation(xx, yy);
+	  TEST_DrawLevelField(xx, yy);
+	}
       }
     }
     else if (IS_BELT_SWITCH(element))
@@ -15562,14 +13772,11 @@ static int DigField(struct PlayerInfo *player,
       if (level.time > 0 || level.use_time_orb_bug)
       {
 	TimeLeft += level.time_orb_time;
+	game.no_time_limit = FALSE;
 
-#if 1
 	game_panel_controls[GAME_PANEL_TIME].value = TimeLeft;
 
 	DisplayGameControlValues();
-#else
-	DrawGameValue_Time(TimeLeft);
-#endif
       }
 
       ResetGfxAnimation(x, y);
@@ -15696,20 +13903,9 @@ static boolean DigFieldByCE(int x, int y, int digging_element)
 
   Store[x][y] = EL_EMPTY;
 
-#if 1
   /* this makes it possible to leave the removed element again */
   if (IS_EQUAL_OR_IN_GROUP(element, MOVE_ENTER_EL(digging_element)))
     Store[x][y] = element;
-#else
-  if (IS_EQUAL_OR_IN_GROUP(element, MOVE_ENTER_EL(digging_element)))
-  {
-    int move_leave_element = element_info[digging_element].move_leave_element;
-
-    /* this makes it possible to leave the removed element again */
-    Store[x][y] = (move_leave_element == EL_TRIGGER_ELEMENT ?
-		   element : move_leave_element);
-  }
-#endif
 
   return TRUE;
 }
@@ -15751,14 +13947,9 @@ static boolean SnapField(struct PlayerInfo *player, int dx, int dy)
     return FALSE;
   }
 
-#if USE_NEW_CONTINUOUS_SNAPPING
   /* prevent snapping with already pressed snap key when not allowed */
   if (player->is_snapping && !can_continue_snapping)
     return FALSE;
-#else
-  if (player->is_snapping)
-    return FALSE;
-#endif
 
   player->MovDir = snap_direction;
 
@@ -15800,17 +13991,7 @@ static boolean DropElement(struct PlayerInfo *player)
   int dropx = player->jx, dropy = player->jy;
   int drop_direction = player->MovDir;
   int drop_side = drop_direction;
-#if 1
   int drop_element = get_next_dropped_element(player);
-#else
-  int drop_element = (player->inventory_size > 0 ?
-		      player->inventory_element[player->inventory_size - 1] :
-		      player->inventory_infinite_element != EL_UNDEFINED ?
-		      player->inventory_infinite_element :
-		      player->dynabombs_left > 0 ?
-		      EL_DYNABOMB_PLAYER_1_ACTIVE + player->index_nr :
-		      EL_UNDEFINED);
-#endif
 
   player->is_dropping_pressed = TRUE;
 
@@ -15916,23 +14097,13 @@ static boolean DropElement(struct PlayerInfo *player)
   if (IS_CUSTOM_ELEMENT(new_element) && CAN_MOVE(new_element) &&
       element_info[new_element].move_pattern == MV_WHEN_DROPPED)
   {
-    int move_direction, nextx, nexty;
-
     if (element_info[new_element].move_direction_initial == MV_START_AUTOMATIC)
       MovDir[dropx][dropy] = drop_direction;
 
-    move_direction = MovDir[dropx][dropy];
-    nextx = dropx + GET_DX_FROM_DIR(move_direction);
-    nexty = dropy + GET_DY_FROM_DIR(move_direction);
-
     ChangeCount[dropx][dropy] = 0;	/* allow at least one more change */
 
-#if USE_FIX_IMPACT_COLLISION
     /* do not cause impact style collision by dropping elements that can fall */
     CheckCollision[dropx][dropy] = CHECK_DELAY_COLLISION;
-#else
-    CheckCollision[dropx][dropy] = CHECK_DELAY_COLLISION;
-#endif
   }
 
   player->drop_delay = GET_NEW_DROP_DELAY(drop_element);
@@ -16233,49 +14404,16 @@ void PlayLevelSound_SP(int xx, int yy, int element_sp, int action_sp)
   int x = xx - offset;
   int y = yy - offset;
 
-#if 0
-  printf("::: %d -> %d\n", element_sp, action_sp);
-#endif
-
   PlayLevelSoundElementAction(x, y, element, action);
 }
 
-#if 0
-void ChangeTime(int value)
-{
-  int *time = (level.time == 0 ? &TimePlayed : &TimeLeft);
-
-  *time += value;
-
-  /* EMC game engine uses value from time counter of RND game engine */
-  level.native_em_level->lev->time = *time;
-
-  DrawGameValue_Time(*time);
-}
-
-void RaiseScore(int value)
-{
-  /* EMC game engine and RND game engine have separate score counters */
-  int *score = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
-		&level.native_em_level->lev->score : &local_player->score);
-
-  *score += value;
-
-  DrawGameValue_Score(*score);
-}
-#endif
-
 void RaiseScore(int value)
 {
   local_player->score += value;
 
-#if 1
   game_panel_controls[GAME_PANEL_SCORE].value = local_player->score;
 
   DisplayGameControlValues();
-#else
-  DrawGameValue_Score(local_player->score);
-#endif
 }
 
 void RaiseScoreElement(int element)
@@ -16362,6 +14500,10 @@ void RequestQuitGameExt(boolean skip_request, boolean quick_quit, char *message)
 {
   if (skip_request || Request(message, REQ_ASK | REQ_STAY_CLOSED))
   {
+    /* closing door required in case of envelope style request dialogs */
+    if (!skip_request)
+      CloseDoor(DOOR_CLOSE_1);
+
 #if defined(NETWORK_AVALIABLE)
     if (options.network)
       SendToServer_StopPlaying(NETWORK_STOP_BY_PLAYER);
@@ -16369,37 +14511,11 @@ void RequestQuitGameExt(boolean skip_request, boolean quick_quit, char *message)
 #endif
     {
       if (quick_quit)
-      {
-#if 1
-
-#if 1
 	FadeSkipNextFadeIn();
-#else
-	fading = fading_none;
-#endif
-
-#else
-	OpenDoor(DOOR_CLOSE_1);
-#endif
 
-	game_status = GAME_MODE_MAIN;
+      SetGameStatus(GAME_MODE_MAIN);
 
-#if 1
-	DrawAndFadeInMainMenu(REDRAW_FIELD);
-#else
-	DrawMainMenu();
-#endif
-      }
-      else
-      {
-#if 0
-	FadeOut(REDRAW_FIELD);
-#endif
-
-	game_status = GAME_MODE_MAIN;
-
-	DrawAndFadeInMainMenu(REDRAW_FIELD);
-      }
+      DrawMainMenu();
     }
   }
   else		/* continue playing the game */
@@ -16420,7 +14536,7 @@ void RequestQuitGame(boolean ask_if_really_quit)
   boolean skip_request = AllPlayersGone || quick_quit;
 
   RequestQuitGameExt(skip_request, quick_quit,
-		     "Do you really want to quit the game ?");
+		     "Do you really want to quit the game?");
 }
 
 
@@ -16428,22 +14544,11 @@ void RequestQuitGame(boolean ask_if_really_quit)
 /* random generator functions                                                */
 /* ------------------------------------------------------------------------- */
 
-unsigned int InitEngineRandom_RND(long seed)
+unsigned int InitEngineRandom_RND(int seed)
 {
   game.num_random_calls = 0;
 
-#if 0
-  unsigned int rnd_seed = InitEngineRandom(seed);
-
-  printf("::: START RND: %d\n", rnd_seed);
-
-  return rnd_seed;
-#else
-
   return InitEngineRandom(seed);
-
-#endif
-
 }
 
 unsigned int RND(int max)
@@ -16521,7 +14626,7 @@ static void SaveEngineSnapshotValues_RND()
 
 static void LoadEngineSnapshotValues_RND()
 {
-  unsigned long num_random_calls = game.num_random_calls;
+  unsigned int num_random_calls = game.num_random_calls;
   int i, j;
 
   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
@@ -16565,97 +14670,106 @@ static void LoadEngineSnapshotValues_RND()
   }
 }
 
-void SaveEngineSnapshot()
+void FreeEngineSnapshotSingle()
 {
-  /* do not save snapshots from editor */
-  if (level_editor_test_game)
-    return;
+  FreeSnapshotSingle();
+
+  setString(&snapshot_level_identifier, NULL);
+  snapshot_level_nr = -1;
+}
+
+void FreeEngineSnapshotList()
+{
+  FreeSnapshotList();
+}
 
-  /* free previous snapshot buffers, if needed */
-  FreeEngineSnapshotBuffers();
+ListNode *SaveEngineSnapshotBuffers()
+{
+  ListNode *buffers = NULL;
 
   /* copy some special values to a structure better suited for the snapshot */
 
-  SaveEngineSnapshotValues_RND();
-  SaveEngineSnapshotValues_EM();
-  SaveEngineSnapshotValues_SP();
+  if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
+    SaveEngineSnapshotValues_RND();
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+    SaveEngineSnapshotValues_EM();
+  if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+    SaveEngineSnapshotValues_SP(&buffers);
 
   /* save values stored in special snapshot structure */
 
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_rnd));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_em));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_sp));
+  if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
+    SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_rnd));
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+    SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_em));
+  if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+    SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_sp));
 
   /* save further RND engine values */
 
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(stored_player));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(game));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(tape));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ZX));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ZY));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExitX));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExitY));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(FrameCounter));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TimeFrames));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TimePlayed));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TimeLeft));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TapeTime));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScreenMovDir));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScreenMovPos));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScreenGfxPos));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollStepSize));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(AllPlayersGone));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(AmoebaCnt));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(AmoebaCnt2));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Feld));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MovPos));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MovDir));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MovDelay));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ChangeDelay));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ChangePage));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(CustomValue));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Store));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Store2));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(StorePlayer));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Back));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(AmoebaNr));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(WasJustMoving));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(WasJustFalling));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(CheckCollision));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(CheckImpact));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Stop));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Pushed));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ChangeCount));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ChangeEvent));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExplodePhase));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExplodeDelay));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExplodeField));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RunnerVisit));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(PlayerVisit));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxFrame));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxRandom));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxElement));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxAction));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxDir));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(scroll_x));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(scroll_y));
-
-  /* save level identification information */
-
-  setString(&snapshot_level_identifier, leveldir_current->identifier);
-  snapshot_level_nr = level_nr;
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(stored_player));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(game));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(tape));
+
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ZX));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ZY));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ExitX));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ExitY));
+
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(FrameCounter));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(TimeFrames));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(TimePlayed));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(TimeLeft));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(TapeTime));
+
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ScreenMovDir));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ScreenMovPos));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ScreenGfxPos));
+
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ScrollStepSize));
+
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(AllPlayersGone));
+
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(AmoebaCnt));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(AmoebaCnt2));
+
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(Feld));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(MovPos));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(MovDir));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(MovDelay));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ChangeDelay));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ChangePage));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(CustomValue));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(Store));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(Store2));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(StorePlayer));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(Back));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(AmoebaNr));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(WasJustMoving));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(WasJustFalling));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(CheckCollision));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(CheckImpact));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(Stop));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(Pushed));
+
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ChangeCount));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ChangeEvent));
+
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ExplodePhase));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ExplodeDelay));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ExplodeField));
+
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(RunnerVisit));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(PlayerVisit));
+
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(GfxFrame));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(GfxRandom));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(GfxElement));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(GfxAction));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(GfxDir));
+
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(scroll_x));
+  SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(scroll_y));
 
 #if 0
   ListNode *node = engine_snapshot_list_rnd;
@@ -16670,122 +14784,156 @@ void SaveEngineSnapshot()
 
   printf("::: size of engine snapshot: %d bytes\n", num_bytes);
 #endif
+
+  return buffers;
+}
+
+void SaveEngineSnapshotSingle()
+{
+  ListNode *buffers = SaveEngineSnapshotBuffers();
+
+  /* finally save all snapshot buffers to single snapshot */
+  SaveSnapshotSingle(buffers);
+
+  /* save level identification information */
+  setString(&snapshot_level_identifier, leveldir_current->identifier);
+  snapshot_level_nr = level_nr;
+}
+
+boolean CheckSaveEngineSnapshotToList()
+{
+  boolean save_snapshot =
+    ((game.snapshot.mode == SNAPSHOT_MODE_EVERY_STEP) ||
+     (game.snapshot.mode == SNAPSHOT_MODE_EVERY_MOVE &&
+      game.snapshot.changed_action) ||
+     (game.snapshot.mode == SNAPSHOT_MODE_EVERY_COLLECT &&
+      game.snapshot.collected_item));
+
+  game.snapshot.changed_action = FALSE;
+  game.snapshot.collected_item = FALSE;
+  game.snapshot.save_snapshot = save_snapshot;
+
+  return save_snapshot;
+}
+
+void SaveEngineSnapshotToList()
+{
+  if (game.snapshot.mode == SNAPSHOT_MODE_OFF ||
+      tape.quick_resume)
+    return;
+
+  ListNode *buffers = SaveEngineSnapshotBuffers();
+
+  /* finally save all snapshot buffers to snapshot list */
+  SaveSnapshotToList(buffers);
 }
 
-void LoadEngineSnapshot()
+void SaveEngineSnapshotToListInitial()
 {
-  /* restore generically stored snapshot buffers */
+  FreeEngineSnapshotList();
 
-  LoadEngineSnapshotBuffers();
+  SaveEngineSnapshotToList();
+}
 
+void LoadEngineSnapshotValues()
+{
   /* restore special values from snapshot structure */
 
-  LoadEngineSnapshotValues_RND();
-  LoadEngineSnapshotValues_EM();
-  LoadEngineSnapshotValues_SP();
+  if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
+    LoadEngineSnapshotValues_RND();
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+    LoadEngineSnapshotValues_EM();
+  if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+    LoadEngineSnapshotValues_SP();
+}
+
+void LoadEngineSnapshotSingle()
+{
+  LoadSnapshotSingle();
+
+  LoadEngineSnapshotValues();
 }
 
-boolean CheckEngineSnapshot()
+void LoadEngineSnapshot_Undo(int steps)
+{
+  LoadSnapshotFromList_Older(steps);
+
+  LoadEngineSnapshotValues();
+}
+
+void LoadEngineSnapshot_Redo(int steps)
+{
+  LoadSnapshotFromList_Newer(steps);
+
+  LoadEngineSnapshotValues();
+}
+
+boolean CheckEngineSnapshotSingle()
 {
   return (strEqual(snapshot_level_identifier, leveldir_current->identifier) &&
 	  snapshot_level_nr == level_nr);
 }
 
+boolean CheckEngineSnapshotList()
+{
+  return CheckSnapshotList();
+}
 
-/* ---------- new game button stuff ---------------------------------------- */
 
-/* graphic position values for game buttons */
-#define GAME_BUTTON_XSIZE	30
-#define GAME_BUTTON_YSIZE	30
-#define GAME_BUTTON_XPOS	5
-#define GAME_BUTTON_YPOS	215
-#define SOUND_BUTTON_XPOS	5
-#define SOUND_BUTTON_YPOS	(GAME_BUTTON_YPOS + GAME_BUTTON_YSIZE)
-
-#define GAME_BUTTON_STOP_XPOS	(GAME_BUTTON_XPOS + 0 * GAME_BUTTON_XSIZE)
-#define GAME_BUTTON_PAUSE_XPOS	(GAME_BUTTON_XPOS + 1 * GAME_BUTTON_XSIZE)
-#define GAME_BUTTON_PLAY_XPOS	(GAME_BUTTON_XPOS + 2 * GAME_BUTTON_XSIZE)
-#define SOUND_BUTTON_MUSIC_XPOS	(SOUND_BUTTON_XPOS + 0 * GAME_BUTTON_XSIZE)
-#define SOUND_BUTTON_LOOPS_XPOS	(SOUND_BUTTON_XPOS + 1 * GAME_BUTTON_XSIZE)
-#define SOUND_BUTTON_SIMPLE_XPOS (SOUND_BUTTON_XPOS + 2 * GAME_BUTTON_XSIZE)
+/* ---------- new game button stuff ---------------------------------------- */
 
 static struct
 {
-  int *x, *y;
-  int gd_x, gd_y;
+  int graphic;
+  struct XY *pos;
   int gadget_id;
   char *infotext;
 } gamebutton_info[NUM_GAME_BUTTONS] =
 {
-#if 1
   {
-    &game.button.stop.x,	&game.button.stop.y,
-    GAME_BUTTON_STOP_XPOS,	GAME_BUTTON_YPOS,
-    GAME_CTRL_ID_STOP,
-    "stop game"
+    IMG_GFX_GAME_BUTTON_STOP,		&game.button.stop,
+    GAME_CTRL_ID_STOP,			"stop game"
   },
   {
-    &game.button.pause.x,	&game.button.pause.y,
-    GAME_BUTTON_PAUSE_XPOS,	GAME_BUTTON_YPOS,
-    GAME_CTRL_ID_PAUSE,
-    "pause game"
+    IMG_GFX_GAME_BUTTON_PAUSE,		&game.button.pause,
+    GAME_CTRL_ID_PAUSE,			"pause game"
   },
   {
-    &game.button.play.x,	&game.button.play.y,
-    GAME_BUTTON_PLAY_XPOS,	GAME_BUTTON_YPOS,
-    GAME_CTRL_ID_PLAY,
-    "play game"
+    IMG_GFX_GAME_BUTTON_PLAY,		&game.button.play,
+    GAME_CTRL_ID_PLAY,			"play game"
   },
   {
-    &game.button.sound_music.x,	&game.button.sound_music.y,
-    SOUND_BUTTON_MUSIC_XPOS,	SOUND_BUTTON_YPOS,
-    SOUND_CTRL_ID_MUSIC,
-    "background music on/off"
+    IMG_GFX_GAME_BUTTON_UNDO,		&game.button.undo,
+    GAME_CTRL_ID_UNDO,			"undo step"
   },
   {
-    &game.button.sound_loops.x,	&game.button.sound_loops.y,
-    SOUND_BUTTON_LOOPS_XPOS,	SOUND_BUTTON_YPOS,
-    SOUND_CTRL_ID_LOOPS,
-    "sound loops on/off"
+    IMG_GFX_GAME_BUTTON_REDO,		&game.button.redo,
+    GAME_CTRL_ID_REDO,			"redo step"
   },
   {
-    &game.button.sound_simple.x,&game.button.sound_simple.y,
-    SOUND_BUTTON_SIMPLE_XPOS,	SOUND_BUTTON_YPOS,
-    SOUND_CTRL_ID_SIMPLE,
-    "normal sounds on/off"
-  }
-#else
-  {
-    GAME_BUTTON_STOP_XPOS,	GAME_BUTTON_YPOS,
-    GAME_CTRL_ID_STOP,
-    "stop game"
+    IMG_GFX_GAME_BUTTON_SAVE,		&game.button.save,
+    GAME_CTRL_ID_SAVE,			"save game"
   },
   {
-    GAME_BUTTON_PAUSE_XPOS,	GAME_BUTTON_YPOS,
-    GAME_CTRL_ID_PAUSE,
-    "pause game"
+    IMG_GFX_GAME_BUTTON_PAUSE2,		&game.button.pause2,
+    GAME_CTRL_ID_PAUSE2,		"pause game"
   },
   {
-    GAME_BUTTON_PLAY_XPOS,	GAME_BUTTON_YPOS,
-    GAME_CTRL_ID_PLAY,
-    "play game"
+    IMG_GFX_GAME_BUTTON_LOAD,		&game.button.load,
+    GAME_CTRL_ID_LOAD,			"load game"
   },
   {
-    SOUND_BUTTON_MUSIC_XPOS,	SOUND_BUTTON_YPOS,
-    SOUND_CTRL_ID_MUSIC,
-    "background music on/off"
+    IMG_GFX_GAME_BUTTON_SOUND_MUSIC,	&game.button.sound_music,
+    SOUND_CTRL_ID_MUSIC,		"background music on/off"
   },
   {
-    SOUND_BUTTON_LOOPS_XPOS,	SOUND_BUTTON_YPOS,
-    SOUND_CTRL_ID_LOOPS,
-    "sound loops on/off"
+    IMG_GFX_GAME_BUTTON_SOUND_LOOPS,	&game.button.sound_loops,
+    SOUND_CTRL_ID_LOOPS,		"sound loops on/off"
   },
   {
-    SOUND_BUTTON_SIMPLE_XPOS,	SOUND_BUTTON_YPOS,
-    SOUND_CTRL_ID_SIMPLE,
-    "normal sounds on/off"
+    IMG_GFX_GAME_BUTTON_SOUND_SIMPLE,	&game.button.sound_simple,
+    SOUND_CTRL_ID_SIMPLE,		"normal sounds on/off"
   }
-#endif
 };
 
 void CreateGameButtons()
@@ -16794,32 +14942,46 @@ void CreateGameButtons()
 
   for (i = 0; i < NUM_GAME_BUTTONS; i++)
   {
-    Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
+    struct GraphicInfo *gfx = &graphic_info[gamebutton_info[i].graphic];
+    struct XY *pos = gamebutton_info[i].pos;
     struct GadgetInfo *gi;
     int button_type;
     boolean checked;
-    unsigned long event_mask;
-    int x, y;
-    int gd_xoffset, gd_yoffset;
-    int gd_x1, gd_x2, gd_y1, gd_y2;
+    unsigned int event_mask;
+    int base_x = (tape.show_game_buttons ? VX : DX);
+    int base_y = (tape.show_game_buttons ? VY : DY);
+    int gd_x   = gfx->src_x;
+    int gd_y   = gfx->src_y;
+    int gd_xp  = gfx->src_x + gfx->pressed_xoffset;
+    int gd_yp  = gfx->src_y + gfx->pressed_yoffset;
+    int gd_xa  = gfx->src_x + gfx->active_xoffset;
+    int gd_ya  = gfx->src_y + gfx->active_yoffset;
+    int gd_xap = gfx->src_x + gfx->active_xoffset + gfx->pressed_xoffset;
+    int gd_yap = gfx->src_y + gfx->active_yoffset + gfx->pressed_yoffset;
     int id = i;
 
-    x = DX + *gamebutton_info[i].x;
-    y = DY + *gamebutton_info[i].y;
-    gd_xoffset = gamebutton_info[i].gd_x;
-    gd_yoffset = gamebutton_info[i].gd_y;
-    gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
-    gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
+    if (gfx->bitmap == NULL)
+    {
+      game_gadget[id] = NULL;
+
+      continue;
+    }
 
     if (id == GAME_CTRL_ID_STOP ||
-	id == GAME_CTRL_ID_PAUSE ||
-	id == GAME_CTRL_ID_PLAY)
+	id == GAME_CTRL_ID_PLAY ||
+	id == GAME_CTRL_ID_SAVE ||
+	id == GAME_CTRL_ID_LOAD)
     {
       button_type = GD_TYPE_NORMAL_BUTTON;
       checked = FALSE;
       event_mask = GD_EVENT_RELEASED;
-      gd_y1  = DOOR_GFX_PAGEY1 + gd_yoffset - GAME_BUTTON_YSIZE;
-      gd_y2  = DOOR_GFX_PAGEY1 + gd_yoffset - GAME_BUTTON_YSIZE;
+    }
+    else if (id == GAME_CTRL_ID_UNDO ||
+	     id == GAME_CTRL_ID_REDO)
+    {
+      button_type = GD_TYPE_NORMAL_BUTTON;
+      checked = FALSE;
+      event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
     }
     else
     {
@@ -16829,28 +14991,21 @@ void CreateGameButtons()
 	 (id == SOUND_CTRL_ID_LOOPS && setup.sound_loops) ||
 	 (id == SOUND_CTRL_ID_SIMPLE && setup.sound_simple) ? TRUE : FALSE);
       event_mask = GD_EVENT_PRESSED;
-      gd_y1  = DOOR_GFX_PAGEY1 + gd_yoffset;
-      gd_y2  = DOOR_GFX_PAGEY1 + gd_yoffset - GAME_BUTTON_YSIZE;
     }
 
     gi = CreateGadget(GDI_CUSTOM_ID, id,
 		      GDI_INFO_TEXT, gamebutton_info[i].infotext,
-#if 1
-		      GDI_X, x,
-		      GDI_Y, y,
-#else
-		      GDI_X, DX + gd_xoffset,
-		      GDI_Y, DY + gd_yoffset,
-#endif
-		      GDI_WIDTH, GAME_BUTTON_XSIZE,
-		      GDI_HEIGHT, GAME_BUTTON_YSIZE,
+		      GDI_X, base_x + GDI_ACTIVE_POS(pos->x),
+		      GDI_Y, base_y + GDI_ACTIVE_POS(pos->y),
+		      GDI_WIDTH, gfx->width,
+		      GDI_HEIGHT, gfx->height,
 		      GDI_TYPE, button_type,
 		      GDI_STATE, GD_BUTTON_UNPRESSED,
 		      GDI_CHECKED, checked,
-		      GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y1,
-		      GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y1,
-		      GDI_ALT_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y2,
-		      GDI_ALT_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y2,
+		      GDI_DESIGN_UNPRESSED, gfx->bitmap, gd_x, gd_y,
+		      GDI_DESIGN_PRESSED, gfx->bitmap, gd_xp, gd_yp,
+		      GDI_ALT_DESIGN_UNPRESSED, gfx->bitmap, gd_xa, gd_ya,
+		      GDI_ALT_DESIGN_PRESSED, gfx->bitmap, gd_xap, gd_yap,
 		      GDI_DIRECT_DRAW, FALSE,
 		      GDI_EVENT_MASK, event_mask,
 		      GDI_CALLBACK_ACTION, HandleGameButtons,
@@ -16871,12 +15026,80 @@ void FreeGameButtons()
     FreeGadget(game_gadget[i]);
 }
 
-static void MapGameButtons()
+static void UnmapGameButtonsAtSamePosition(int id)
+{
+  int i;
+
+  for (i = 0; i < NUM_GAME_BUTTONS; i++)
+    if (i != id &&
+	gamebutton_info[i].pos->x == gamebutton_info[id].pos->x &&
+	gamebutton_info[i].pos->y == gamebutton_info[id].pos->y)
+      UnmapGadget(game_gadget[i]);
+}
+
+static void UnmapGameButtonsAtSamePosition_All()
+{
+  if (setup.show_snapshot_buttons)
+  {
+    UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_SAVE);
+    UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_PAUSE2);
+    UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_LOAD);
+  }
+  else
+  {
+    UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_STOP);
+    UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_PAUSE);
+    UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_PLAY);
+  }
+}
+
+static void MapGameButtonsAtSamePosition(int id)
+{
+  int i;
+
+  for (i = 0; i < NUM_GAME_BUTTONS; i++)
+    if (i != id &&
+	gamebutton_info[i].pos->x == gamebutton_info[id].pos->x &&
+	gamebutton_info[i].pos->y == gamebutton_info[id].pos->y)
+      MapGadget(game_gadget[i]);
+
+  UnmapGameButtonsAtSamePosition_All();
+}
+
+void MapUndoRedoButtons()
+{
+  UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_UNDO);
+  UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_REDO);
+
+  MapGadget(game_gadget[GAME_CTRL_ID_UNDO]);
+  MapGadget(game_gadget[GAME_CTRL_ID_REDO]);
+
+  ModifyGadget(game_gadget[GAME_CTRL_ID_PAUSE2], GDI_CHECKED, TRUE, GDI_END);
+}
+
+void UnmapUndoRedoButtons()
+{
+  UnmapGadget(game_gadget[GAME_CTRL_ID_UNDO]);
+  UnmapGadget(game_gadget[GAME_CTRL_ID_REDO]);
+
+  MapGameButtonsAtSamePosition(GAME_CTRL_ID_UNDO);
+  MapGameButtonsAtSamePosition(GAME_CTRL_ID_REDO);
+
+  ModifyGadget(game_gadget[GAME_CTRL_ID_PAUSE2], GDI_CHECKED, FALSE, GDI_END);
+}
+
+void MapGameButtons()
 {
   int i;
 
   for (i = 0; i < NUM_GAME_BUTTONS; i++)
-    MapGadget(game_gadget[i]);
+    if (i != GAME_CTRL_ID_UNDO &&
+	i != GAME_CTRL_ID_REDO)
+      MapGadget(game_gadget[i]);
+
+  UnmapGameButtonsAtSamePosition_All();
+
+  RedrawGameButtons();
 }
 
 void UnmapGameButtons()
@@ -16893,24 +15116,75 @@ void RedrawGameButtons()
 
   for (i = 0; i < NUM_GAME_BUTTONS; i++)
     RedrawGadget(game_gadget[i]);
+
+  // RedrawGadget() may have set REDRAW_ALL if buttons are defined off-area
+  redraw_mask &= ~REDRAW_ALL;
+}
+
+void GameUndoRedoExt()
+{
+  ClearPlayerAction();
+
+  tape.pausing = TRUE;
+
+  RedrawPlayfield();
+  UpdateAndDisplayGameControlValues();
+
+  DrawCompleteVideoDisplay();
+  DrawVideoDisplay(VIDEO_STATE_TIME_ON, TapeTime);
+  DrawVideoDisplay(VIDEO_STATE_FRAME_ON, FrameCounter);
+  DrawVideoDisplay(VIDEO_STATE_1STEP(tape.single_step), 0);
+
+  BackToFront();
+}
+
+void GameUndo(int steps)
+{
+  if (!CheckEngineSnapshotList())
+    return;
+
+  LoadEngineSnapshot_Undo(steps);
+
+  GameUndoRedoExt();
+}
+
+void GameRedo(int steps)
+{
+  if (!CheckEngineSnapshotList())
+    return;
+
+  LoadEngineSnapshot_Redo(steps);
+
+  GameUndoRedoExt();
 }
 
-static void HandleGameButtonsExt(int id)
+static void HandleGameButtonsExt(int id, int button)
 {
-  if (game_status != GAME_MODE_PLAYING)
+  static boolean game_undo_executed = FALSE;
+  int steps = BUTTON_STEPSIZE(button);
+  boolean handle_game_buttons =
+    (game_status == GAME_MODE_PLAYING ||
+     (game_status == GAME_MODE_MAIN && tape.show_game_buttons));
+
+  if (!handle_game_buttons)
     return;
 
   switch (id)
   {
     case GAME_CTRL_ID_STOP:
+      if (game_status == GAME_MODE_MAIN)
+	break;
+
       if (tape.playing)
 	TapeStop();
       else
 	RequestQuitGame(TRUE);
+
       break;
 
     case GAME_CTRL_ID_PAUSE:
-      if (options.network)
+    case GAME_CTRL_ID_PAUSE2:
+      if (options.network && game_status == GAME_MODE_PLAYING)
       {
 #if defined(NETWORK_AVALIABLE)
 	if (tape.pausing)
@@ -16921,23 +15195,54 @@ static void HandleGameButtonsExt(int id)
       }
       else
 	TapeTogglePause(TAPE_TOGGLE_MANUAL);
+
+      game_undo_executed = FALSE;
+
       break;
 
     case GAME_CTRL_ID_PLAY:
-      if (tape.pausing)
+      if (game_status == GAME_MODE_MAIN)
+      {
+        StartGameActions(options.network, setup.autorecord, level.random_seed);
+      }
+      else if (tape.pausing)
       {
 #if defined(NETWORK_AVALIABLE)
 	if (options.network)
 	  SendToServer_ContinuePlaying();
 	else
 #endif
-	{
-	  tape.pausing = FALSE;
-	  DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF, 0);
-	}
+	  TapeTogglePause(TAPE_TOGGLE_MANUAL | TAPE_TOGGLE_PLAY_PAUSE);
       }
       break;
 
+    case GAME_CTRL_ID_UNDO:
+      // Important: When using "save snapshot when collecting an item" mode,
+      // load last (current) snapshot for first "undo" after pressing "pause"
+      // (else the last-but-one snapshot would be loaded, because the snapshot
+      // pointer already points to the last snapshot when pressing "pause",
+      // which is fine for "every step/move" mode, but not for "every collect")
+      if (game.snapshot.mode == SNAPSHOT_MODE_EVERY_COLLECT &&
+	  !game_undo_executed)
+	steps--;
+
+      game_undo_executed = TRUE;
+
+      GameUndo(steps);
+      break;
+
+    case GAME_CTRL_ID_REDO:
+      GameRedo(steps);
+      break;
+
+    case GAME_CTRL_ID_SAVE:
+      TapeQuickSave();
+      break;
+
+    case GAME_CTRL_ID_LOAD:
+      TapeQuickLoad();
+      break;
+
     case SOUND_CTRL_ID_MUSIC:
       if (setup.sound_music)
       { 
@@ -16984,24 +15289,16 @@ static void HandleGameButtonsExt(int id)
 
 static void HandleGameButtons(struct GadgetInfo *gi)
 {
-  HandleGameButtonsExt(gi->custom_id);
+  HandleGameButtonsExt(gi->custom_id, gi->event.button);
 }
 
 void HandleSoundButtonKeys(Key key)
 {
-#if 1
+
   if (key == setup.shortcut.sound_simple)
     ClickOnGadget(game_gadget[SOUND_CTRL_ID_SIMPLE], MB_LEFTBUTTON);
   else if (key == setup.shortcut.sound_loops)
     ClickOnGadget(game_gadget[SOUND_CTRL_ID_LOOPS], MB_LEFTBUTTON);
   else if (key == setup.shortcut.sound_music)
     ClickOnGadget(game_gadget[SOUND_CTRL_ID_MUSIC], MB_LEFTBUTTON);
-#else
-  if (key == setup.shortcut.sound_simple)
-    HandleGameButtonsExt(SOUND_CTRL_ID_SIMPLE);
-  else if (key == setup.shortcut.sound_loops)
-    HandleGameButtonsExt(SOUND_CTRL_ID_LOOPS);
-  else if (key == setup.shortcut.sound_music)
-    HandleGameButtonsExt(SOUND_CTRL_ID_MUSIC);
-#endif
 }
diff --git a/src/game.h b/src/game.h
index c764e1d..7bf665e 100644
--- a/src/game.h
+++ b/src/game.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* game.h                                                   *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// game.h
+// ============================================================================
 
 #ifndef GAME_H
 #define GAME_H
@@ -17,20 +15,32 @@
 /* (not included here due to collisions with Emerald Mine engine definitions) */
 /* #include "main.h" */
 
-#define MAX_INVENTORY_SIZE	1000
+#define MAX_INVENTORY_SIZE		1000
 
-#define STD_NUM_KEYS		4
-#define MAX_NUM_KEYS		8
+#define STD_NUM_KEYS			4
+#define MAX_NUM_KEYS			8
 
-#define NUM_BELTS		4
-#define NUM_BELT_PARTS		3
+#define NUM_BELTS			4
+#define NUM_BELT_PARTS			3
+
+#define NUM_PANEL_INVENTORY		8
+#define NUM_PANEL_GRAPHICS		8
+#define NUM_PANEL_ELEMENTS		8
+#define NUM_PANEL_CE_SCORE		8
+
+#define STR_SNAPSHOT_MODE_OFF		"off"
+#define STR_SNAPSHOT_MODE_EVERY_STEP	"every_step"
+#define STR_SNAPSHOT_MODE_EVERY_MOVE	"every_move"
+#define STR_SNAPSHOT_MODE_EVERY_COLLECT	"every_collect"
+#define STR_SNAPSHOT_MODE_DEFAULT	STR_SNAPSHOT_MODE_OFF
+
+#define SNAPSHOT_MODE_OFF		0
+#define SNAPSHOT_MODE_EVERY_STEP	1
+#define SNAPSHOT_MODE_EVERY_MOVE	2
+#define SNAPSHOT_MODE_EVERY_COLLECT	3
+#define SNAPSHOT_MODE_DEFAULT		SNAPSHOT_MODE_OFF
 
-#define NUM_PANEL_INVENTORY	8
-#define NUM_PANEL_GRAPHICS	8
-#define NUM_PANEL_ELEMENTS	8
-#define NUM_PANEL_CE_SCORE	8
 
-#if 1
 struct GamePanelInfo
 {
   struct TextPosInfo level_number;
@@ -89,26 +99,32 @@ struct GamePanelInfo
 
 struct GameButtonInfo
 {
-  struct MenuPosInfo stop;
-  struct MenuPosInfo pause;
-  struct MenuPosInfo play;
-  struct MenuPosInfo sound_music;
-  struct MenuPosInfo sound_loops;
-  struct MenuPosInfo sound_simple;
-};
+  struct XY stop;
+  struct XY pause;
+  struct XY play;
 
-#else
+  struct XY undo;
+  struct XY redo;
 
-struct GamePanelInfo
+  struct XY save;
+  struct XY pause2;
+  struct XY load;
+
+  struct XY sound_music;
+  struct XY sound_loops;
+  struct XY sound_simple;
+};
+
+struct GameSnapshotInfo
 {
-  struct XY level;
-  struct XY gems;
-  struct XY inventory;
-  struct XY keys;
-  struct XY score;
-  struct XY time;
+  int mode;
+
+  byte last_action[MAX_PLAYERS];
+  boolean changed_action;
+  boolean collected_item;
+
+  boolean save_snapshot;
 };
-#endif
 
 struct GameInfo
 {
@@ -117,11 +133,13 @@ struct GameInfo
   struct GameButtonInfo button;
 
   /* values for graphics engine customization */
+  int graphics_engine_version;
   boolean use_native_emc_graphics_engine;
   boolean use_native_sp_graphics_engine;
   boolean use_masked_pushing;
   int forced_scroll_delay_value;
   int scroll_delay_value;
+  int tile_size;
 
   /* values for engine initialization */
   int default_push_delay_fixed;
@@ -134,6 +152,10 @@ struct GameInfo
   int initial_move_delay_value[MAX_PLAYERS];
   int initial_push_delay_value;
 
+  /* flag for single or multi-player mode (needed for playing tapes) */
+  /* (when playing/recording games, this is identical to "setup.team_mode" */
+  boolean team_mode;
+
   /* flags to handle bugs in and changes between different engine versions */
   /* (for the latest engine version, these flags should always be "FALSE") */
   boolean use_change_when_pushing_bug;
@@ -155,6 +177,7 @@ struct GameInfo
   boolean gravity;
   boolean explosions_delayed;
   boolean envelope_active;
+  boolean no_time_limit;	/* (variable only in very special case) */
 
   /* values for the new EMC elements */
   int lenses_time_left;
@@ -177,7 +200,10 @@ struct GameInfo
   boolean set_centered_player;
 
   /* values for random number generator initialization after snapshot */
-  unsigned long num_random_calls;
+  unsigned int num_random_calls;
+
+  /* values for game engine snapshot control */
+  struct GameSnapshotInfo snapshot;
 };
 
 struct PlayerInfo
@@ -248,6 +274,11 @@ struct PlayerInfo
   boolean is_bored;
   boolean is_sleeping;
 
+  boolean was_waiting;
+  boolean was_moving;
+  boolean was_snapping;
+  boolean was_dropping;
+
   boolean cannot_move;
 
   int frame_counter_bored;
@@ -277,7 +308,7 @@ struct PlayerInfo
   int push_delay;
   int push_delay_value;
 
-  unsigned long actual_frame_counter;
+  unsigned int actual_frame_counter;
 
   int drop_delay;
   int drop_pressed_delay;
@@ -313,6 +344,8 @@ void DEBUG_SetMaximumDynamite();
 void GetPlayerConfig(void);
 int GetElementFromGroupElement(int);
 
+int getPlayerInventorySize(int);
+
 void DrawGameValue_Time(int);
 void DrawGameDoorValues(void);
 
@@ -321,7 +354,7 @@ void UpdateAndDisplayGameControlValues();
 void InitGameSound();
 void InitGame();
 
-void UpdateEngineValues(int, int);
+void UpdateEngineValues(int, int, int, int);
 void GameWon(void);
 void GameEnd(void);
 
@@ -330,11 +363,12 @@ void Moving2Blocked(int, int, int *, int *);
 void Blocked2Moving(int, int, int *, int *);
 void DrawDynamite(int, int);
 
-void StartGameActions(boolean, boolean, long);
+void StartGameActions(boolean, boolean, int);
 
 void GameActions(void);
 void GameActions_EM_Main();
 void GameActions_SP_Main();
+void GameActions_RND_Main();
 void GameActions_RND();
 
 void ScrollLevel(int, int);
@@ -349,16 +383,24 @@ void RaiseScoreElement(int);
 void RequestQuitGameExt(boolean, boolean, char *);
 void RequestQuitGame(boolean);
 
-unsigned int InitEngineRandom_RND(long);
+unsigned int InitEngineRandom_RND(int);
 unsigned int RND(int);
 
-void FreeEngineSnapshot();
-void LoadEngineSnapshot();
-void SaveEngineSnapshot();
-boolean CheckEngineSnapshot();
+void FreeEngineSnapshotSingle();
+void FreeEngineSnapshotList();
+void LoadEngineSnapshotSingle();
+void SaveEngineSnapshotSingle();
+boolean CheckSaveEngineSnapshotToList();
+void SaveEngineSnapshotToList();
+void SaveEngineSnapshotToListInitial();
+boolean CheckEngineSnapshotSingle();
+boolean CheckEngineSnapshotList();
 
 void CreateGameButtons();
 void FreeGameButtons();
+void MapUndoRedoButtons();
+void UnmapUndoRedoButtons();
+void MapGameButtons();
 void UnmapGameButtons();
 void RedrawGameButtons();
 
diff --git a/src/game_em/Makefile b/src/game_em/Makefile
index 4fc21cd..c5c0fc3 100644
--- a/src/game_em/Makefile
+++ b/src/game_em/Makefile
@@ -1,9 +1,15 @@
 # =============================================================================
-# Rocks'n'Diamonds Makefile (game_em)
+# Rocks'n'Diamonds - McDuffin Strikes Back!
 # -----------------------------------------------------------------------------
-# (c) 1995-2006 Holger Schemel <info at artsoft.org>
+# (c) 1995-2014 by Artsoft Entertainment
+#                  Holger Schemel
+#                  info at artsoft.org
+#                  http://www.artsoft.org/
 # -----------------------------------------------------------------------------
-# Emerald Mine for X11 � 2000,2001 David Tritscher
+# The native Emerald Mine game engine is based on:
+# Emerald Mine for X11 (c) 2000,2001 David Tritscher
+# -----------------------------------------------------------------------------
+# src/game_em/Makefile
 # =============================================================================
 
 # -----------------------------------------------------------------------------
diff --git a/src/game_em/cave.c b/src/game_em/cave.c
index 5fb55dc..b89c42f 100644
--- a/src/game_em/cave.c
+++ b/src/game_em/cave.c
@@ -45,7 +45,6 @@ void setLevelInfoToDefaults_EM(void)
   for (i = 0; i < TILE_MAX; i++)
     lev.android_array[i] = Xblank;
 
-#if 1
   /* initial number of players in this level */
   lev.home_initial = 0;
 
@@ -54,16 +53,6 @@ void setLevelInfoToDefaults_EM(void)
     ply[i].exists = 0;
     ply[i].alive_initial = FALSE;
   }
-#else
-  /* initial number of players in this level */
-  lev.home_initial = (setup.team_mode ? 2 : 1);
-
-  for (i = 0; i < MAX_PLAYERS; i++)
-  {
-    ply[i].exists = 0;
-    ply[i].alive_initial = (lev.home_initial > i ? TRUE : FALSE);
-  }
-#endif
 }
 
 
@@ -74,26 +63,27 @@ void setLevelInfoToDefaults_EM(void)
 
 #define MAX_EM_LEVEL_SIZE		16384
 
-boolean LoadNativeLevel_EM(char *filename)
+boolean LoadNativeLevel_EM(char *filename, boolean level_info_only)
 {
   unsigned char raw_leveldata[MAX_EM_LEVEL_SIZE];
   int raw_leveldata_length;
   int file_version;
-  FILE *file;
+  File *file;
 
   /* always start with reliable default values */
   setLevelInfoToDefaults_EM();
 
-  if (!(file = fopen(filename, MODE_READ)))
+  if (!(file = openFile(filename, MODE_READ)))
   {
-    Error(ERR_WARN, "cannot open level '%s' -- using empty level", filename);
+    if (!level_info_only)
+      Error(ERR_WARN, "cannot open level '%s' -- using empty level", filename);
 
     return FALSE;
   }
 
-  raw_leveldata_length = fread(raw_leveldata, 1, MAX_EM_LEVEL_SIZE, file);
+  raw_leveldata_length = readFile(file, raw_leveldata, 1, MAX_EM_LEVEL_SIZE);
 
-  fclose(file);
+  closeFile(file);
 
   if (raw_leveldata_length <= 0)
   {
diff --git a/src/game_em/convert.c b/src/game_em/convert.c
index a3553a7..d240739 100644
--- a/src/game_em/convert.c
+++ b/src/game_em/convert.c
@@ -150,9 +150,6 @@ int cleanup_em_level(unsigned char *src, int length, char *filename)
     for (i = 2112; i < 2148; i++)
       src[i] = src[i - 64];
   }
-
-#if 1	/* ================================================================== */
-
   else if (length >= 2106 &&
 	   (src[1983] == 27 ||		/* encrypted (only EM I/II/III) */
 	    src[1983] == 116 ||		/* unencrypted (usual case) */
@@ -237,93 +234,6 @@ int cleanup_em_level(unsigned char *src, int length, char *filename)
     return FILE_VERSION_EM_UNKNOWN;
   }
 
-#else	/* ================================================================== */
-
-#if 0
-  else if (length >= 2106)	/* !!! TEST ONLY: SHOW BROKEN LEVELS !!! */
-#else
-  else if (length >= 2106 &&
-	   src[1983] == 116)
-#endif
-  {
-    /* ---------- this cave has V4 file format ---------- */
-    file_version = FILE_VERSION_EM_V4;
-
-    /* remap elements to internal EMC level format */
-    for (i = 0; i < 2048; i++)
-      src[i] = remap_v4[src[i]];
-    for (i = 2048; i < 2084; i++)
-      src[i] = remap_v4eater[src[i] >= 28 ? 0 : src[i]];
-    for (i = 2112; i < 2148; i++)
-      src[i] = src[i - 64];
-  }
-  else if (length >= 2106 &&
-	   src[0] == 241 &&	/* <-- Emerald Mine I and III levels */
-	   src[1983] == 27)
-  {
-    unsigned char j = 94;
-
-    /* ---------- this cave has V3 file format ---------- */
-    file_version = FILE_VERSION_EM_V3;
-
-    /* decrypt encrypted level file */
-    for (i = 0; i < 2106; i++)
-      src[i] = (src[i] ^ (j += 7)) - 0x11;
-
-    src[1] = 131;
-
-    /* remap elements to internal EMC level format */
-    for (i = 0; i < 2048; i++)
-      src[i] = remap_v4[src[i]];
-    for (i = 2048; i < 2084; i++)
-      src[i] = remap_v4eater[src[i] >= 28 ? 0 : src[i]];
-    for (i = 2112; i < 2148; i++)
-      src[i] = src[i - 64];
-  }
-#if 1
-  else if (length >= 2106 &&
-	   src[0] == 245 &&	/* <-- Emerald Mine II levels */
-	   src[1983] == 27)
-  {
-    unsigned char j = 94;
-
-    /* ---------- this cave has V3 file format ---------- */
-    file_version = FILE_VERSION_EM_V3;
-
-    /* decrypt encrypted level file */
-    for (i = 0; i < 2106; i++)
-      src[i] = (src[i] ^ (j += 7)) - 0x11;
-
-    src[0] = 131;		/* needed for Emerald Mine II levels */
-    src[1] = 131;
-
-    /* remap elements to internal EMC level format */
-    for (i = 0; i < 2048; i++)
-      src[i] = remap_v4[src[i]];
-    for (i = 2048; i < 2084; i++)
-      src[i] = remap_v4eater[src[i] >= 28 ? 0 : src[i]];
-    for (i = 2112; i < 2148; i++)
-      src[i] = src[i - 64];
-
-    /* fix copyright sign in Emerald Mine II levels */
-    for (i = 0; i < 2048; i++)
-      if (src[i] == 241)
-	src[i] = 254;		/* replace 'Xdecor_1' with 'Xalpha_copyr' */
-  }
-#endif
-  else
-  {
-    /* ---------- this cave has unknown file format ---------- */
-
-#if 0
-    printf("::: %d, %d\n", src[0], src[1983]);
-#endif
-
-    return 0;
-  }
-
-#endif	/* ================================================================== */
-
   if (file_version < FILE_VERSION_EM_V6)
   {
     /* id */
@@ -347,17 +257,7 @@ int cleanup_em_level(unsigned char *src, int length, char *filename)
 
     /* ball data */
     src[2159] = 128;
-
-#if 0
-    printf("::: STORED TIME (< V6): %d s\n", src[2094] * 10);
-#endif
-  }
-#if 0
-  else
-  {
-    printf("::: STORED TIME (>= V6): %d s\n", src[2110] * 256 + src[2111]);
   }
-#endif
 
   /* ---------- at this stage, the cave data always has V6 format ---------- */
 
@@ -554,12 +454,8 @@ int cleanup_em_level(unsigned char *src, int length, char *filename)
   /* size of v6 cave */
   length = 2172;
 
-#if 1
-#if 1
   if (options.debug)
-#endif
     printf("::: EM level file version: %d\n", file_version);
-#endif
 
   return file_version;
 }
@@ -1093,14 +989,8 @@ void convert_em_level(unsigned char *src, int file_version)
 
   /* at last, set the two players at their positions in the playfield */
   /* (native EM[C] levels always have exactly two players in a level) */
-#if 1
   for (i = 0; i < 2; i++)
     native_em_level.cave[ply[i].x_initial][ply[i].y_initial] = Zplayer;
-#else
-  for (i = 0; i < 2; i++)
-    if (ply[i].alive_initial)
-      native_em_level.cave[ply[i].x_initial][ply[i].y_initial] = Zplayer;
-#endif
 
   native_em_level.file_version = file_version;
 }
@@ -1109,7 +999,7 @@ void prepare_em_level(void)
 {
   int i, x, y;
   int players_left;
-  int num_tape_players;
+  boolean team_mode;
 
   /* reset all runtime variables to their initial values */
 
@@ -1125,11 +1015,7 @@ void prepare_em_level(void)
     for (x = 0; x < WIDTH; x++)
       Draw[y][x] = Cave[y][x];
 
-#if 1
   lev.time_initial = lev.time_seconds;
-#else
-  lev.time_initial = (lev.time_seconds * 50 + 7) / 8;
-#endif
   lev.time = lev.time_initial;
 
   lev.required = lev.required_initial;
@@ -1176,12 +1062,10 @@ void prepare_em_level(void)
     }
   }
 
-  num_tape_players = getNumActivePlayers_EM();
+  team_mode = getTeamMode_EM();
 
-  if (num_tape_players != -1)
-    lev.home_initial = MIN(lev.home_initial, num_tape_players);
-  else if (!setup.team_mode)
-    lev.home_initial = MIN(lev.home_initial, 1);
+  if (!team_mode)
+    lev.home_initial = 1;
 
   lev.home = lev.home_initial;
   players_left = lev.home_initial;
@@ -1221,14 +1105,10 @@ void prepare_em_level(void)
     ply[i].joy_n = ply[i].joy_e = ply[i].joy_s = ply[i].joy_w = 0;
     ply[i].joy_snap  = ply[i].joy_drop = 0;
     ply[i].joy_stick = ply[i].joy_spin = 0;
-
-#if 0
-    printf("player %d: x/y == %d/%d, alive == %d\n",
-	   i, ply[i].x_initial, ply[i].y_initial, ply[i].alive);
-#endif
   }
 
   game_em.any_player_moving = FALSE;
+  game_em.any_player_snapping = FALSE;
   game_em.last_moving_player = 0;	/* default: first player */
 
   for (i = 0; i < MAX_PLAYERS; i++)
diff --git a/src/game_em/export.h b/src/game_em/export.h
index 05e7ae6..0968f1d 100644
--- a/src/game_em/export.h
+++ b/src/game_em/export.h
@@ -665,6 +665,7 @@ struct GlobalInfo_EM
 struct GameInfo_EM
 {
   boolean any_player_moving;
+  boolean any_player_snapping;
   int last_moving_player;
   int last_player_direction[MAX_PLAYERS];
 };
@@ -690,6 +691,7 @@ struct GraphicInfo_EM
   Bitmap *crumbled_bitmap;
   int crumbled_src_x, crumbled_src_y;
   int crumbled_border_size;
+  int crumbled_tile_size;
 
   boolean has_crumbled_graphics;
   boolean preserve_background;
@@ -700,7 +702,7 @@ struct GraphicInfo_EM
 struct EngineSnapshotInfo_EM
 {
   struct GameInfo_EM game_em;
-  unsigned long RandomEM;
+  unsigned int RandomEM;
   struct LEVEL lev;
   struct PLAYER ply[MAX_PLAYERS];
   short Array[4][EM_MAX_CAVE_HEIGHT][EM_MAX_CAVE_WIDTH];
@@ -727,18 +729,22 @@ extern struct EngineSnapshotInfo_EM engine_snapshot_em;
 extern void em_open_all();
 extern void em_close_all();
 
+extern void InitGfxBuffers_EM();
+
 extern void InitGameEngine_EM();
 extern void GameActions_EM(byte *, boolean);
 
-extern unsigned int InitEngineRandom_EM(long);
+extern unsigned int InitEngineRandom_EM(int);
 
 extern void setLevelInfoToDefaults_EM();
-extern boolean LoadNativeLevel_EM(char *);
+extern boolean LoadNativeLevel_EM(char *, boolean);
+
+extern int getFieldbufferOffsetX_EM();
+extern int getFieldbufferOffsetY_EM();
 
 extern void BackToFront_EM(void);
 extern void BlitScreenToBitmap_EM(Bitmap *);
 extern void RedrawPlayfield_EM(boolean);
-extern void DrawGameDoorValues_EM();
 
 extern void LoadEngineSnapshotValues_EM();
 extern void SaveEngineSnapshotValues_EM();
diff --git a/src/game_em/game_em.h b/src/game_em/game_em.h
index 4174781..5f99411 100644
--- a/src/game_em/game_em.h
+++ b/src/game_em/game_em.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* game_em.h                                                *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// game_em.h
+// ============================================================================
 
 #ifndef GAME_EM_H
 #define GAME_EM_H
diff --git a/src/game_em/global.h b/src/game_em/global.h
index 8cd8624..89c6804 100644
--- a/src/game_em/global.h
+++ b/src/game_em/global.h
@@ -24,24 +24,15 @@ extern unsigned char linear_to_ulaw[65536];
 int open_all(void);
 void close_all(void);
 
-#if 1
 void readjoy(byte, struct PLAYER *);
-#else
-void readjoy(byte);
-#endif
 void input_eventloop(void);
 
-void blitscreen(void);
 void game_initscreen(void);
-void game_animscreen(void);
-
-void DrawGameDoorValues_EM();
 
 void play_sound(int, int, int);
 void sound_play(void);
 
 int cave_convert(char *);
-boolean LoadNativeLevel_EM(char *);
 
 void game_init_vars(void);
 void game_play_init(int, char *);
@@ -56,7 +47,7 @@ void convert_em_level(unsigned char *, int);
 void prepare_em_level(void);
 
 int sound_thread(void);
-int read_sample(char *, short **, long *);
+int read_sample(char *, short **, int *);
 
 void read_cave_list(void);
 void free_cave_list(void);
diff --git a/src/game_em/graphics.c b/src/game_em/graphics.c
index 5764e9e..727b2b8 100644
--- a/src/game_em/graphics.c
+++ b/src/game_em/graphics.c
@@ -29,181 +29,82 @@
 
 #define USE_EXTENDED_GRAPHICS_ENGINE		1
 
+
 int frame;				/* current screen frame */
 int screen_x, screen_y;			/* current scroll position */
 
 /* tiles currently on screen */
-#if 1
 static int screentiles[MAX_PLAYFIELD_HEIGHT + 2][MAX_PLAYFIELD_WIDTH + 2];
 static int crumbled_state[MAX_PLAYFIELD_HEIGHT + 2][MAX_PLAYFIELD_WIDTH + 2];
 
-static boolean redraw[MAX_PLAYFIELD_WIDTH + 2][MAX_PLAYFIELD_HEIGHT + 2];
-#else
-static int screentiles[MAX_BUF_YSIZE][MAX_BUF_XSIZE];
-static int crumbled_state[MAX_BUF_YSIZE][MAX_BUF_XSIZE];
-
-static boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
-#endif
-
-#if 0
-#if 1
-int centered_player_nr;
-#else
-static int centered_player_nr;
-#endif
-#endif
+int getFieldbufferOffsetX_EM()
+{
+  return screen_x % TILEX;
+}
 
-/* copy the entire screen to the window at the scroll position */
+int getFieldbufferOffsetY_EM()
+{
+  return screen_y % TILEY;
+}
 
 void BlitScreenToBitmap_EM(Bitmap *target_bitmap)
 {
+  /* blit all (up to four) parts of the scroll buffer to the target bitmap */
+
   int x = screen_x % (MAX_BUF_XSIZE * TILEX);
   int y = screen_y % (MAX_BUF_YSIZE * TILEY);
+  int xsize = SXSIZE;
+  int ysize = SYSIZE;
+  int full_xsize = lev.width  * TILEX;
+  int full_ysize = lev.height * TILEY;
+  int sx = SX + (full_xsize < xsize ? (xsize - full_xsize) / 2 : 0);
+  int sy = SY + (full_ysize < ysize ? (ysize - full_ysize) / 2 : 0);
+  int sxsize = (full_xsize < xsize ? full_xsize : xsize);
+  int sysize = (full_ysize < ysize ? full_ysize : ysize);
 
   if (x < 2 * TILEX && y < 2 * TILEY)
   {
     BlitBitmap(screenBitmap, target_bitmap, x, y,
-	       SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
+	       sxsize, sysize, sx, sy);
   }
   else if (x < 2 * TILEX && y >= 2 * TILEY)
   {
     BlitBitmap(screenBitmap, target_bitmap, x, y,
-	       SCR_FIELDX * TILEX, MAX_BUF_YSIZE * TILEY - y,
-	       SX, SY);
+	       sxsize, MAX_BUF_YSIZE * TILEY - y,
+	       sx, sy);
     BlitBitmap(screenBitmap, target_bitmap, x, 0,
-	       SCR_FIELDX * TILEX, y - 2 * TILEY,
-	       SX, SY + MAX_BUF_YSIZE * TILEY - y);
+	       sxsize, y - 2 * TILEY,
+	       sx, sy + MAX_BUF_YSIZE * TILEY - y);
   }
   else if (x >= 2 * TILEX && y < 2 * TILEY)
   {
     BlitBitmap(screenBitmap, target_bitmap, x, y,
-	       MAX_BUF_XSIZE * TILEX - x, SCR_FIELDY * TILEY,
-	       SX, SY);
+	       MAX_BUF_XSIZE * TILEX - x, sysize,
+	       sx, sy);
     BlitBitmap(screenBitmap, target_bitmap, 0, y,
-	       x - 2 * TILEX, SCR_FIELDY * TILEY,
-	       SX + MAX_BUF_XSIZE * TILEX - x, SY);
+	       x - 2 * TILEX, sysize,
+	       sx + MAX_BUF_XSIZE * TILEX - x, sy);
   }
   else
   {
     BlitBitmap(screenBitmap, target_bitmap, x, y,
 	       MAX_BUF_XSIZE * TILEX - x, MAX_BUF_YSIZE * TILEY - y,
-	       SX, SY);
+	       sx, sy);
     BlitBitmap(screenBitmap, target_bitmap, 0, y,
 	       x - 2 * TILEX, MAX_BUF_YSIZE * TILEY - y,
-	       SX + MAX_BUF_XSIZE * TILEX - x, SY);
+	       sx + MAX_BUF_XSIZE * TILEX - x, sy);
     BlitBitmap(screenBitmap, target_bitmap, x, 0,
 	       MAX_BUF_XSIZE * TILEX - x, y - 2 * TILEY,
-	       SX, SY + MAX_BUF_YSIZE * TILEY - y);
+	       sx, sy + MAX_BUF_YSIZE * TILEY - y);
     BlitBitmap(screenBitmap, target_bitmap, 0, 0,
 	       x - 2 * TILEX, y - 2 * TILEY,
-	       SX + MAX_BUF_XSIZE * TILEX - x, SY + MAX_BUF_YSIZE * TILEY - y);
+	       sx + MAX_BUF_XSIZE * TILEX - x, sy + MAX_BUF_YSIZE * TILEY - y);
   }
 }
 
 void BackToFront_EM(void)
 {
-  static int screen_x_last = -1, screen_y_last = -1;
-  static boolean scrolling_last = FALSE;
-  int left = screen_x / TILEX;
-  int top  = screen_y / TILEY;
-#if 1
-  boolean scrolling = (screen_x != screen_x_last || screen_y != screen_y_last);
-#else
-  boolean scrolling = (screen_x % TILEX != 0 || screen_y % TILEY != 0);
-#endif
-  int x, y;
-
-#if 0
-  printf("::: %d, %d\n", screen_x, screen_y);
-#endif
-
-  SyncDisplay();
-
-  if (redraw_tiles > REDRAWTILES_THRESHOLD || scrolling || scrolling_last)
-  {
-    /* blit all (up to four) parts of the scroll buffer to the backbuffer */
-    BlitScreenToBitmap_EM(backbuffer);
-
-    /* blit the completely updated backbuffer to the window (in one blit) */
-    BlitBitmap(backbuffer, window, SX, SY, SXSIZE, SYSIZE, SX, SY);
-  }
-  else
-  {
-#if 1
-#if 1
-    boolean half_shifted_x = (screen_x % TILEX != 0);
-    boolean half_shifted_y = (screen_y % TILEY != 0);
-#else
-    boolean half_shifted_x = (EVEN(SCR_FIELDX) && screen_x % TILEX != 0);
-    boolean half_shifted_y = (EVEN(SCR_FIELDY) && screen_y % TILEY != 0);
-#endif
-
-#if 0
-#if 1
-    printf("::: %d, %d\n", EVEN(SCR_FIELDX), screen_x);
-#else
-    half_shifted_x = TRUE;
-    half_shifted_y = FALSE;
-#endif
-#endif
-
-    int x1 = 0, x2 = SCR_FIELDX - (half_shifted_x ? 0 : 1);
-    int y1 = 0, y2 = SCR_FIELDY - (half_shifted_y ? 0 : 1);
-    int scroll_xoffset = (half_shifted_x ? TILEX / 2 : 0);
-    int scroll_yoffset = (half_shifted_y ? TILEY / 2 : 0);
-
-    InitGfxClipRegion(TRUE, SX, SY, SXSIZE, SYSIZE);
-
-    for (x = x1; x <= x2; x++)
-    {
-      for (y = y1; y <= y2; y++)
-      {
-	int xx = (left + x) % MAX_BUF_XSIZE;
-	int yy = (top  + y) % MAX_BUF_YSIZE;
-
-	if (redraw[xx][yy])
-	  BlitBitmap(screenBitmap, window,
-		     xx * TILEX, yy * TILEY, TILEX, TILEY,
-		     SX + x * TILEX - scroll_xoffset,
-		     SY + y * TILEY - scroll_yoffset);
-      }
-    }
-
-    InitGfxClipRegion(FALSE, -1, -1, -1, -1);
-
-#else
-
-    for (x = 0; x < SCR_FIELDX; x++)
-    {
-      for (y = 0; y < SCR_FIELDY; y++)
-      {
-	int xx = (left + x) % MAX_BUF_XSIZE;
-	int yy = (top  + y) % MAX_BUF_YSIZE;
-
-	if (redraw[xx][yy])
-	  BlitBitmap(screenBitmap, window,
-		     xx * TILEX, yy * TILEY, TILEX, TILEY,
-		     SX + x * TILEX, SY + y * TILEY);
-      }
-    }
-#endif
-  }
-
-  FlushDisplay();
-
-  for (x = 0; x < MAX_BUF_XSIZE; x++)
-    for (y = 0; y < MAX_BUF_YSIZE; y++)
-      redraw[x][y] = FALSE;
-  redraw_tiles = 0;
-
-  screen_x_last = screen_x;
-  screen_y_last = screen_y;
-  scrolling_last = scrolling;
-}
-
-void blitscreen(void)
-{
-  BackToFront_EM();
+  BlitBitmap(backbuffer, window, SX, SY, SXSIZE, SYSIZE, SX, SY);
 }
 
 static struct GraphicInfo_EM *getObjectGraphic(int x, int y)
@@ -231,12 +132,12 @@ static void DrawLevelField_EM(int x, int y, int sx, int sy,
 			      boolean draw_masked)
 {
   struct GraphicInfo_EM *g = getObjectGraphic(x, y);
-  int src_x = g->src_x + g->src_offset_x;
-  int src_y = g->src_y + g->src_offset_y;
-  int dst_x = sx * TILEX + g->dst_offset_x;
-  int dst_y = sy * TILEY + g->dst_offset_y;
-  int width = g->width;
-  int height = g->height;
+  int src_x = g->src_x + g->src_offset_x * TILESIZE_VAR / TILESIZE;
+  int src_y = g->src_y + g->src_offset_y * TILESIZE_VAR / TILESIZE;
+  int dst_x = sx * TILEX + g->dst_offset_x * TILESIZE_VAR / TILESIZE;
+  int dst_y = sy * TILEY + g->dst_offset_y * TILESIZE_VAR / TILESIZE;
+  int width = g->width * TILESIZE_VAR / TILESIZE;
+  int height = g->height * TILESIZE_VAR / TILESIZE;
   int left = screen_x / TILEX;
   int top  = screen_y / TILEY;
 
@@ -248,12 +149,8 @@ static void DrawLevelField_EM(int x, int y, int sx, int sy,
   if (draw_masked)
   {
     if (width > 0 && height > 0)
-    {
-      SetClipOrigin(g->bitmap, g->bitmap->stored_clip_gc,
-		    dst_x - src_x, dst_y - src_y);
       BlitBitmapMasked(g->bitmap, screenBitmap,
 		       src_x, src_y, width, height, dst_x, dst_y);
-    }
   }
   else
   {
@@ -269,11 +166,8 @@ static void DrawLevelField_EM(int x, int y, int sx, int sy,
 static void DrawLevelFieldCrumbled_EM(int x, int y, int sx, int sy,
 				      int crm, boolean draw_masked)
 {
-#if 1
   struct GraphicInfo_EM *g;
-#else
-  struct GraphicInfo_EM *g = getObjectGraphic(x, y);
-#endif
+  int crumbled_border_size;
   int left = screen_x / TILEX;
   int top  = screen_y / TILEY;
   int i;
@@ -286,16 +180,10 @@ static void DrawLevelFieldCrumbled_EM(int x, int y, int sx, int sy,
   if (crm == 0)		/* no crumbled edges for this tile */
     return;
 
-#if 1
   g = getObjectGraphic(x, y);
-#endif
 
-#if 0
-  if (x == 3 && y == 3 && frame == 0)
-    printf("::: %d, %d\n",
-	   graphic_info_em_object[207][0].crumbled_src_x,
-	   graphic_info_em_object[207][0].crumbled_src_y);
-#endif
+  crumbled_border_size =
+    g->crumbled_border_size * TILESIZE_VAR / g->crumbled_tile_size;
 
   for (i = 0; i < 4; i++)
   {
@@ -305,17 +193,17 @@ static void DrawLevelFieldCrumbled_EM(int x, int y, int sx, int sy,
 
       if (i == 1 || i == 2)
       {
-	width = g->crumbled_border_size;
+	width = crumbled_border_size;
 	height = TILEY;
-	cx = (i == 2 ? TILEX - g->crumbled_border_size : 0);
+	cx = (i == 2 ? TILEX - crumbled_border_size : 0);
 	cy = 0;
       }
       else
       {
 	width = TILEX;
-	height = g->crumbled_border_size;
+	height = crumbled_border_size;
 	cx = 0;
-	cy = (i == 3 ? TILEY - g->crumbled_border_size : 0);
+	cy = (i == 3 ? TILEY - crumbled_border_size : 0);
       }
 
       if (width > 0 && height > 0)
@@ -326,12 +214,8 @@ static void DrawLevelFieldCrumbled_EM(int x, int y, int sx, int sy,
 	int dst_y = sy * TILEY + cy;
 
 	if (draw_masked)
-	{
-	  SetClipOrigin(g->crumbled_bitmap, g->crumbled_bitmap->stored_clip_gc,
-			dst_x - src_x, dst_y - src_y);
 	  BlitBitmapMasked(g->crumbled_bitmap, screenBitmap,
 			   src_x, src_y, width, height, dst_x, dst_y);
-	}
 	else
 	  BlitBitmap(g->crumbled_bitmap, screenBitmap,
 		     src_x, src_y, width, height, dst_x, dst_y);
@@ -360,24 +244,18 @@ static void DrawLevelPlayer_EM(int x1, int y1, int player_nr, int anim,
     /* draw the player to current location */
     dst_x = x1;
     dst_y = y1;
-    SetClipOrigin(g->bitmap, g->bitmap->stored_clip_gc,
-		  dst_x - src_x, dst_y - src_y);
     BlitBitmapMasked(g->bitmap, screenBitmap,
 		     src_x, src_y, TILEX, TILEY, dst_x, dst_y);
 
     /* draw the player to opposite wrap-around column */
     dst_x = x1 - MAX_BUF_XSIZE * TILEX;
     dst_y = y1;
-    SetClipOrigin(g->bitmap, g->bitmap->stored_clip_gc,
-		  dst_x - src_x, dst_y - src_y);
     BlitBitmapMasked(g->bitmap, screenBitmap,
 		     g->src_x, g->src_y, TILEX, TILEY, dst_x, dst_y);
 
     /* draw the player to opposite wrap-around row */
     dst_x = x1;
     dst_y = y1 - MAX_BUF_YSIZE * TILEY;
-    SetClipOrigin(g->bitmap, g->bitmap->stored_clip_gc,
-		  dst_x - src_x, dst_y - src_y);
     BlitBitmapMasked(g->bitmap, screenBitmap,
 		     g->src_x, g->src_y, TILEX, TILEY, dst_x, dst_y);
   }
@@ -462,12 +340,6 @@ static void animscreen(void)
       redraw_screen_tile = (screentiles[sy][sx]    != obj ||
 			    crumbled_state[sy][sx] != crm);
 
-#if 0
-      /* !!! TEST ONLY -- CHANGE THIS !!! */
-      if (!game.use_native_emc_graphics_engine)
-	redraw_screen_tile = TRUE;
-#endif
-
       /* only redraw screen tiles if they (or their crumbled state) changed */
       if (redraw_screen_tile)
       {
@@ -476,9 +348,6 @@ static void animscreen(void)
 
 	screentiles[sy][sx] = obj;
 	crumbled_state[sy][sx] = crm;
-
-	redraw[sx][sy] = TRUE;
-	redraw_tiles++;
       }
     }
   }
@@ -503,10 +372,6 @@ static void blitplayer(struct PLAYER *ply)
   x2 = x1 + TILEX - 1;
   y2 = y1 + TILEY - 1;
 
-#if 0
-  printf("::: %d, %d\n", x1, y1);
-#endif
-
   if ((int)(x2 - screen_x) < ((MAX_BUF_XSIZE - 1) * TILEX - 1) &&
       (int)(y2 - screen_y) < ((MAX_BUF_YSIZE - 1) * TILEY - 1))
   {
@@ -518,32 +383,16 @@ static void blitplayer(struct PLAYER *ply)
     int new_x = old_x + SIGN(dx);
     int new_y = old_y + SIGN(dy);
     int old_sx = old_x % MAX_BUF_XSIZE;
-    int old_sy = old_y % MAX_BUF_XSIZE;
+    int old_sy = old_y % MAX_BUF_YSIZE;
     int new_sx = new_x % MAX_BUF_XSIZE;
-    int new_sy = new_y % MAX_BUF_XSIZE;
-#if 0
-    int old_crm = crumbled_state[old_sy][old_sx];
-#endif
+    int new_sy = new_y % MAX_BUF_YSIZE;
     int new_crm = crumbled_state[new_sy][new_sx];
 
     /* only diggable elements can be crumbled in the classic EM engine */
     boolean player_is_digging = (new_crm != 0);
 
-#if 0
-    x1 %= MAX_BUF_XSIZE * TILEX;
-    y1 %= MAX_BUF_YSIZE * TILEY;
-    x2 %= MAX_BUF_XSIZE * TILEX;
-    y2 %= MAX_BUF_YSIZE * TILEY;
-#endif
-
     if (player_is_digging)
     {
-#if 0
-      /* draw the field the player is moving from (under the player) */
-      DrawLevelField_EM(old_x, old_y, old_sx, old_sy, FALSE);
-      DrawLevelFieldCrumbled_EM(old_x, old_y, old_sx, old_sy, old_crm, FALSE);
-#endif
-
       /* draw the field the player is moving to (under the player) */
       DrawLevelField_EM(new_x, new_y, new_sx, new_sy, FALSE);
       DrawLevelFieldCrumbled_EM(new_x, new_y, new_sx, new_sy, new_crm, FALSE);
@@ -551,10 +400,8 @@ static void blitplayer(struct PLAYER *ply)
       /* draw the player (masked) over the element he is just digging away */
       DrawLevelPlayer_EM(x1, y1, ply->num, ply->anim, TRUE);
 
-#if 1
       /* draw the field the player is moving from (masked over the player) */
       DrawLevelField_EM(old_x, old_y, old_sx, old_sy, TRUE);
-#endif
     }
     else
     {
@@ -571,27 +418,16 @@ static void blitplayer(struct PLAYER *ply)
     /* redraw screen tiles in the next frame (player may have left the tiles) */
     screentiles[old_sy][old_sx] = -1;
     screentiles[new_sy][new_sx] = -1;
-
-    /* mark screen tiles as dirty (force screen refresh with changed content) */
-    redraw[old_sx][old_sy] = TRUE;
-    redraw[new_sx][new_sy] = TRUE;
-    redraw_tiles += 2;
   }
 }
 
 void game_initscreen(void)
 {
-  int x,y;
-  int dynamite_state = ply[0].dynamite;		/* !!! ONLY PLAYER 1 !!! */
-  int all_keys_state = ply[0].keys | ply[1].keys | ply[2].keys | ply[3].keys;
   int player_nr;
+  int x,y;
 
   frame = 6;
 
-#if 0
-  game.centered_player_nr = getCenteredPlayerNr_EM();
-#endif
-
   player_nr = (game.centered_player_nr != -1 ? game.centered_player_nr : 0);
 
   screen_x = VALID_SCREEN_X(PLAYER_SCREEN_X(player_nr));
@@ -605,106 +441,7 @@ void game_initscreen(void)
       crumbled_state[y][x] = 0;
     }
   }
-
-  DrawAllGameValues(lev.required, dynamite_state, lev.score,
-		    lev.time, all_keys_state);
-}
-
-#if 0
-void DrawRelocatePlayer(struct PlayerInfo *player, boolean quick_relocation)
-{
-  boolean ffwd_delay = (tape.playing && tape.fast_forward);
-  boolean no_delay = (tape.warp_forward);
-  int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
-  int wait_delay_value = (no_delay ? 0 : frame_delay_value);
-  int jx = player->jx;
-  int jy = player->jy;
-
-  if (quick_relocation)
-  {
-    int offset = game.scroll_delay_value;
-
-    if (!IN_VIS_FIELD(SCREENX(jx), SCREENY(jy)))
-    {
-      scroll_x = (player->jx < SBX_Left  + MIDPOSX ? SBX_Left :
-		  player->jx > SBX_Right + MIDPOSX ? SBX_Right :
-		  player->jx - MIDPOSX);
-
-      scroll_y = (player->jy < SBY_Upper + MIDPOSY ? SBY_Upper :
-		  player->jy > SBY_Lower + MIDPOSY ? SBY_Lower :
-		  player->jy - MIDPOSY);
-    }
-    else
-    {
-      if ((player->MovDir == MV_LEFT  && scroll_x > jx - MIDPOSX + offset) ||
-	  (player->MovDir == MV_RIGHT && scroll_x < jx - MIDPOSX - offset))
-	scroll_x = jx - MIDPOSX + (scroll_x < jx-MIDPOSX ? -offset : +offset);
-
-      if ((player->MovDir == MV_UP  && scroll_y > jy - MIDPOSY + offset) ||
-	  (player->MovDir == MV_DOWN && scroll_y < jy - MIDPOSY - offset))
-	scroll_y = jy - MIDPOSY + (scroll_y < jy-MIDPOSY ? -offset : +offset);
-
-      /* don't scroll over playfield boundaries */
-      if (scroll_x < SBX_Left || scroll_x > SBX_Right)
-	scroll_x = (scroll_x < SBX_Left ? SBX_Left : SBX_Right);
-
-      /* don't scroll over playfield boundaries */
-      if (scroll_y < SBY_Upper || scroll_y > SBY_Lower)
-	scroll_y = (scroll_y < SBY_Upper ? SBY_Upper : SBY_Lower);
-    }
-
-    RedrawPlayfield(TRUE, 0,0,0,0);
-  }
-  else
-  {
-    int scroll_xx = -999, scroll_yy = -999;
-
-    ScrollScreen(NULL, SCROLL_GO_ON);	/* scroll last frame to full tile */
-
-    while (scroll_xx != scroll_x || scroll_yy != scroll_y)
-    {
-      int dx = 0, dy = 0;
-      int fx = FX, fy = FY;
-
-      scroll_xx = (player->jx < SBX_Left  + MIDPOSX ? SBX_Left :
-		   player->jx > SBX_Right + MIDPOSX ? SBX_Right :
-		   player->jx - MIDPOSX);
-
-      scroll_yy = (player->jy < SBY_Upper + MIDPOSY ? SBY_Upper :
-		   player->jy > SBY_Lower + MIDPOSY ? SBY_Lower :
-		   player->jy - MIDPOSY);
-
-      dx = (scroll_xx < scroll_x ? +1 : scroll_xx > scroll_x ? -1 : 0);
-      dy = (scroll_yy < scroll_y ? +1 : scroll_yy > scroll_y ? -1 : 0);
-
-      if (dx == 0 && dy == 0)		/* no scrolling needed at all */
-	break;
-
-      scroll_x -= dx;
-      scroll_y -= dy;
-
-      fx += dx * TILEX / 2;
-      fy += dy * TILEY / 2;
-
-      ScrollLevel(dx, dy);
-      DrawAllPlayers();
-
-      /* scroll in two steps of half tile size to make things smoother */
-      BlitBitmap(drawto_field, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
-      FlushDisplay();
-      Delay(wait_delay_value);
-
-      /* scroll second step to align at full tile size */
-      BackToFront();
-      Delay(wait_delay_value);
-    }
-
-    DrawPlayer(player);
-    BackToFront();
-    Delay(wait_delay_value);
-  }
 }
-#endif
 
 static int getMaxCenterDistancePlayerNr(int center_x, int center_y)
 {
@@ -807,24 +544,10 @@ static boolean checkIfAllPlayersAreVisible(int center_x, int center_y)
 
 void RedrawPlayfield_EM(boolean force_redraw)
 {
-#if 0
-  boolean all_players_visible = checkIfAllPlayersAreVisible();
-#endif
   boolean draw_new_player_location = FALSE;
   boolean quick_relocation = setup.quick_switch;
-#if 0
-  boolean scrolling = (screen_x % TILEX != 0 || screen_y % TILEY != 0);
-#endif
-#if 0
-  boolean game.set_centered_player = getSetCenteredPlayer_EM();
-  int game.centered_player_nr_next = getCenteredPlayerNr_EM();
-#endif
-#if 1
   int max_center_distance_player_nr =
     getMaxCenterDistancePlayerNr(screen_x, screen_y);
-#else
-  int player_nr = game_em.last_moving_player;
-#endif
   int stepsize = TILEX / 8;
   int offset = game.scroll_delay_value * TILEX;
   int offset_x = offset;
@@ -854,46 +577,27 @@ void RedrawPlayfield_EM(boolean force_redraw)
     }
   }
 
-#if 1
   /* also allow focus switching when screen is scrolled to half tile */
-#else
-  if (!scrolling)	/* screen currently aligned at tile position */
-#endif
+  if (game.set_centered_player)
   {
-#if 1
-    if (game.set_centered_player)
-#else
-    if (game.centered_player_nr != game.centered_player_nr_next)
-#endif
-    {
-      game.centered_player_nr = game.centered_player_nr_next;
+    game.centered_player_nr = game.centered_player_nr_next;
 
-      draw_new_player_location = TRUE;
-      force_redraw = TRUE;
+    draw_new_player_location = TRUE;
+    force_redraw = TRUE;
 
-      game.set_centered_player = FALSE;
-    }
+    game.set_centered_player = FALSE;
   }
 
   if (game.centered_player_nr == -1)
   {
-#if 1
     if (draw_new_player_location || offset == 0)
-#else
-    if (draw_new_player_location)
-#endif
     {
       setScreenCenteredToAllPlayers(&sx, &sy);
     }
     else
     {
-#if 1
       sx = PLAYER_SCREEN_X(max_center_distance_player_nr);
       sy = PLAYER_SCREEN_Y(max_center_distance_player_nr);
-#else
-      sx = PLAYER_SCREEN_X(game_em.last_moving_player);
-      sy = PLAYER_SCREEN_Y(game_em.last_moving_player);
-#endif
     }
   }
   else
@@ -908,20 +612,11 @@ void RedrawPlayfield_EM(boolean force_redraw)
     screen_y = VALID_SCREEN_Y(sy);
     screen_x_old = screen_x;
     screen_y_old = screen_y;
-
-#if 0
-    offset_x = 0;
-    offset_y = 0;
-#endif
   }
 
   if (draw_new_player_location && !quick_relocation)
   {
-#if 1
-    unsigned long game_frame_delay_value = getGameFrameDelay_EM(20);
-#else
-    unsigned long game_frame_delay_value = getGameFrameDelay_EM(25);
-#endif
+    unsigned int game_frame_delay_value = getGameFrameDelay_EM(20);
     int wait_delay_value = game_frame_delay_value;
     int screen_xx = VALID_SCREEN_X(sx);
     int screen_yy = VALID_SCREEN_Y(sy);
@@ -935,8 +630,6 @@ void RedrawPlayfield_EM(boolean force_redraw)
       if (dx == 0 && dy == 0)		/* no scrolling needed at all */
 	break;
 
-#if 1
-
       if (ABS(screen_xx - screen_x) >= TILEX)
       {
 	screen_x -= dx * TILEX;
@@ -959,36 +652,6 @@ void RedrawPlayfield_EM(boolean force_redraw)
 	dyy = 0;
       }
 
-#else
-
-#if 1
-      if (ABS(screen_xx - screen_x) >= TILEX ||
-	  ABS(screen_yy - screen_y) >= TILEY)
-      {
-	screen_x -= dx * TILEX;
-	screen_y -= dy * TILEY;
-
-	dxx = dx * TILEX / 2;
-	dyy = dy * TILEY / 2;
-      }
-      else
-      {
-	screen_x = screen_xx;
-	screen_y = screen_yy;
-
-	dxx = 0;
-	dyy = 0;
-      }
-#else
-      screen_x -= dx * TILEX;
-      screen_y -= dy * TILEY;
-
-      dxx += dx * TILEX / 2;
-      dyy += dy * TILEY / 2;
-#endif
-
-#endif
-
       /* scroll in two steps of half tile size to make things smoother */
       screen_x += dxx;
       screen_y += dyy;
@@ -998,7 +661,8 @@ void RedrawPlayfield_EM(boolean force_redraw)
       for (i = 0; i < MAX_PLAYERS; i++)
 	blitplayer(&ply[i]);
 
-      blitscreen();
+      BlitScreenToBitmap_EM(backbuffer);
+      BackToFront_EM();
 
       Delay(wait_delay_value);
 
@@ -1006,16 +670,13 @@ void RedrawPlayfield_EM(boolean force_redraw)
       screen_x -= dxx;
       screen_y -= dyy;
 
-#if 0
-      SyncDisplay();
-#endif
-
       animscreen();
 
       for (i = 0; i < MAX_PLAYERS; i++)
 	blitplayer(&ply[i]);
 
-      blitscreen();
+      BlitScreenToBitmap_EM(backbuffer);
+      BackToFront_EM();
 
       Delay(wait_delay_value);
     }
@@ -1044,22 +705,6 @@ void RedrawPlayfield_EM(boolean force_redraw)
 			    sy - offset_y > screen_y ? sy - offset_y :
 			    screen_y);
 
-#if 0
-  printf("::: (%d, %d) => (%d, %d) [(%d, %d), (%d, %d)] [%d, %d] [%d / %d]\n",
-	 screen_x_old, screen_y_old,
-	 screen_x, screen_y,
-	 ply[max_center_distance_player_nr].oldx,
-	 ply[max_center_distance_player_nr].x,
-	 ply[max_center_distance_player_nr].oldy,
-	 ply[max_center_distance_player_nr].y,
-	 sx, sy,
-	 ABS(screen_x - screen_x_old),
-	 ABS(screen_y - screen_y_old));
-#endif
-
-#if 1
-
-#if 1
   /* prevent scrolling further than double player step size when scrolling */
   if (ABS(screen_x - screen_x_old) > 2 * stepsize)
   {
@@ -1073,36 +718,10 @@ void RedrawPlayfield_EM(boolean force_redraw)
 
     screen_y = screen_y_old + dy * 2 * stepsize;
   }
-#else
-  /* prevent scrolling further than double player step size when scrolling */
-  if (ABS(screen_x - screen_x_old) > 2 * stepsize ||
-      ABS(screen_y - screen_y_old) > 2 * stepsize)
-  {
-    int dx = SIGN(screen_x - screen_x_old);
-    int dy = SIGN(screen_y - screen_y_old);
-
-    screen_x = screen_x_old + dx * 2 * stepsize;
-    screen_y = screen_y_old + dy * 2 * stepsize;
-  }
-#endif
-
-#else
-  /* prevent scrolling further than player step size when scrolling */
-  if (ABS(screen_x - screen_x_old) > stepsize ||
-      ABS(screen_y - screen_y_old) > stepsize)
-  {
-    int dx = SIGN(screen_x - screen_x_old);
-    int dy = SIGN(screen_y - screen_y_old);
-
-    screen_x = screen_x_old + dx * stepsize;
-    screen_y = screen_y_old + dy * stepsize;
-  }
-#endif
 
   /* prevent scrolling away from the other players when focus on all players */
   if (game.centered_player_nr == -1)
   {
-#if 1
     /* check if all players are still visible with new scrolling position */
     if (checkIfAllPlayersAreVisible(screen_x_old, screen_y_old) &&
 	!checkIfAllPlayersAreVisible(screen_x, screen_y))
@@ -1115,17 +734,6 @@ void RedrawPlayfield_EM(boolean force_redraw)
       if (!checkIfAllPlayersAreVisible(screen_x_old, screen_y))
 	screen_y = screen_y_old;
     }
-#else
-    boolean all_players_visible = checkIfAllPlayersAreVisible();
-
-    if (!all_players_visible)
-    {
-      printf("::: not all players visible\n");
-
-      screen_x = screen_x_old;
-      screen_y = screen_y_old;
-    }
-#endif
   }
 
   /* prevent scrolling (for screen correcting) if no player is moving */
@@ -1137,9 +745,6 @@ void RedrawPlayfield_EM(boolean force_redraw)
   else
   {
     /* prevent scrolling against the players move direction */
-#if 0
-    int player_nr = game_em.last_moving_player;
-#endif
     int player_nr = (game.centered_player_nr == -1 ?
 		     max_center_distance_player_nr : game.centered_player_nr);
     int player_move_dir = game_em.last_player_direction[player_nr];
@@ -1159,66 +764,4 @@ void RedrawPlayfield_EM(boolean force_redraw)
 
   for (i = 0; i < MAX_PLAYERS; i++)
     blitplayer(&ply[i]);
-
-#if 0
-#if 0
-  SyncDisplay();
-#endif
-
-  blitscreen();
-#endif
-}
-
-void game_animscreen(void)
-{
-  RedrawPlayfield_EM(FALSE);
-}
-
-void DrawGameDoorValues_EM()
-{
-#if 1
-  int dynamite_state;
-  int key_state;
-#else
-  int dynamite_state = ply[0].dynamite;		/* !!! ONLY PLAYER 1 !!! */
-  int key_state = ply[0].keys | ply[1].keys | ply[2].keys | ply[3].keys;
-#endif
-
-#if 1
-  if (game.centered_player_nr == -1)
-  {
-#if 1
-    int i;
-
-    dynamite_state = 0;
-    key_state = 0;
-
-    for (i = 0; i < MAX_PLAYERS; i++)
-    {
-      dynamite_state += ply[i].dynamite;
-      key_state |= ply[i].keys;
-    }
-
-#else
-
-    dynamite_state = ply[0].dynamite;		/* !!! ONLY PLAYER 1 !!! */
-    key_state = ply[0].keys | ply[1].keys | ply[2].keys | ply[3].keys;
-#endif
-  }
-  else
-  {
-    int player_nr = game.centered_player_nr;
-
-    dynamite_state = ply[player_nr].dynamite;
-    key_state = ply[player_nr].keys;
-  }
-#endif
-
-#if 1
-  DrawAllGameValues(lev.required, dynamite_state, lev.score,
-		    lev.time, key_state);
-#else
-  DrawAllGameValues(lev.required, ply1.dynamite, lev.score,
-		    DISPLAY_TIME(lev.time), ply1.keys | ply2.keys);
-#endif
 }
diff --git a/src/game_em/init.c b/src/game_em/init.c
index 6e7fe94..0d4c313 100644
--- a/src/game_em/init.c
+++ b/src/game_em/init.c
@@ -5,253 +5,51 @@
 
 #include "main_em.h"
 
-
 #include <signal.h>
 
-#if !defined(TARGET_SDL)
-#include <sys/wait.h>
-#endif
-
 
 Bitmap *objBitmap;
 Bitmap *sprBitmap;
 
 Bitmap *screenBitmap;
 
-#if 0
-Pixmap spriteBitmap;
-#endif
-
-Pixmap objPixmap;
-Pixmap sprPixmap;
-
-#if 0
-Pixmap objmaskBitmap;
-Pixmap sprmaskBitmap;
-
-GC spriteGC;
-#endif
-
 char play[SAMPLE_MAX];
 int play_x[SAMPLE_MAX];
 int play_y[SAMPLE_MAX];
 int play_element[SAMPLE_MAX];
 
-static boolean use_native_em_sound = 0;
-
 struct GlobalInfo_EM global_em_info;
 struct GameInfo_EM game_em;
 
-#if defined(AUDIO_UNIX_NATIVE)
-static int sound_pid = -1;
-int sound_pipe[2] = { -1, -1 };		/* for communication */
-short *sound_data[SAMPLE_MAX];		/* pointer to sound data */
-long sound_length[SAMPLE_MAX];		/* length of sound data */
-
-static const char *sound_names[SAMPLE_MAX] =
-{
-  "00.blank.au",
-  "01.roll.au",
-  "02.stone.au",
-  "03.nut.au",
-  "04.crack.au",
-  "05.bug.au",
-  "06.tank.au",
-  "07.android.au",
-  "06.tank.au",		/* android moving */
-  "08.spring.au",
-  "09.slurp.au",
-  "10.eater.au",
-  "10.eater.au",	/* eater eating */
-  "11.alien.au",
-  "12.collect.au",
-  "13.diamond.au",
-  "14.squash.au",
-  "14.squash.au",
-  "15.drip.au",
-  "16.push.au",
-  "17.dirt.au",
-  "18.acid.au",
-  "19.ball.au",
-  "20.grow.au",
-  "21.wonder.au",
-  "22.door.au",
-  "23.exit.au",
-  "23.exit.au",
-  "24.dynamite.au",
-  "25.tick.au",
-  "26.press.au",
-  "27.wheel.au",
-  "28.boom.au",
-  "29.time.au",
-  "30.die.au"
-};
-static const int sound_volume[SAMPLE_MAX] =
-{
-  20,
-  100,
-  100,
-  100,
-  100,
-  20,
-  20,
-  100,
-  20,
-  100,
-  100,
-  50,
-  50,
-  100,
-  100,
-  100,
-  100,
-  100,
-  100,
-  100,
-  100,
-  100,
-  100,
-  100,
-  20,
-  100,
-  100,
-  100,
-  100,
-  100,
-  100,
-  20,
-  100,
-  100,
-  100
-};
-#endif
-
 char *progname;
 char *arg_basedir;
 
 extern void tab_generate();
 extern void tab_generate_graphics_info_em();
-extern void ulaw_generate();
 
 int open_all(void)
 {
   Bitmap *emc_bitmaps[2];
-#if 0
-  XGCValues gcValues;
-#endif
 
-#if 1
   SetBitmaps_EM(emc_bitmaps);
 
   objBitmap = emc_bitmaps[0];
   sprBitmap = emc_bitmaps[1];
 
-#if 0
-  objPixmap = emc_bitmaps[0]->drawable;
-  sprPixmap = emc_bitmaps[1]->drawable;
-
-  objmaskBitmap = emc_bitmaps[0]->clip_mask;
-  sprmaskBitmap = emc_bitmaps[1]->clip_mask;
-#endif
+  return 0;
+}
 
-  screenBitmap = CreateBitmap(MAX_BUF_XSIZE * TILEX, MAX_BUF_YSIZE * TILEY,
-			      DEFAULT_DEPTH);
+void InitGfxBuffers_EM()
+{
+  ReCreateBitmap(&screenBitmap, MAX_BUF_XSIZE * TILEX, MAX_BUF_YSIZE * TILEY);
 
   global_em_info.screenbuffer = screenBitmap;
-
-#endif
-
-#if 0
-  spriteBitmap = XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
-  if (spriteBitmap == 0)
-    Error(ERR_EXIT, "failed to create sprite pixmap for EM engine");
-
-  gcValues.function =
-    objmaskBitmap ? GXcopyInverted : sprmaskBitmap ? GXcopy : GXset;
-  gcValues.graphics_exposures = False;
-  spriteGC = XCreateGC(display, spriteBitmap, GCFunction | GCGraphicsExposures,
-		       &gcValues);
-  if (spriteGC == 0)
-    Error(ERR_EXIT, "failed to create sprite GC for EM engine");
-#endif
-
-  /* ----------------------------------------------------------------- */
-
-#if defined(AUDIO_UNIX_NATIVE)
-
-#if defined(PLATFORM_LINUX) || defined(PLATFORM_BSD)
-
-  if (use_native_em_sound)
-  {
-    char name[MAXNAME+2];
-    int i;
-
-    for (i = 0; i < SAMPLE_MAX; i++)
-    {
-      name[MAXNAME] = 0;
-
-      if (arg_basedir)
-      {
-	snprintf(name, MAXNAME+2, "%s/%s/%s", arg_basedir, EM_SND_DIR,
-		 sound_names[i]);
-      }
-      else
-      {
-	snprintf(name, MAXNAME+2, "%s/%s", EM_SND_DIR, sound_names[i]);
-      }
-
-      if (name[MAXNAME])
-	Error(ERR_EXIT, "buffer overflow when reading sounds directory");
-
-      if (read_sample(name, &sound_data[i], &sound_length[i]))
-	return(1);
-
-      {
-	short *ptr, *stop;
-	int mult = sound_volume[i] * 65536 / (100 * MIXER_MAX);
-	stop = sound_data[i] + sound_length[i];
-	for (ptr = sound_data[i]; ptr < stop; ptr++)
-	  *ptr = (*ptr * mult) / 65536;
-      }
-    }
-
-    if (pipe(sound_pipe) == -1)
-    {
-      Error(ERR_WARN, "unable to create sound pipe for EM engine -- no sound");
-
-      return(1);
-    }
-
-    sound_pid = fork();
-    if (sound_pid == -1)
-    {
-      Error(ERR_WARN, "unable to fork sound thread for EM engine -- no sound");
-
-      return(1);
-    }
-
-    close(sound_pipe[sound_pid == 0]);
-    sound_pipe[sound_pid == 0] = -1;
-    if (sound_pid == 0)
-      _exit(sound_thread());
-
-    signal(SIGPIPE, SIG_IGN); /* dont crash if sound process dies */
-  }
-
-#endif	/* defined(PLATFORM_LINUX) || defined(PLATFORM_BSD) */
-
-#endif	/* AUDIO_UNIX_NATIVE */
-
-  return(0);
 }
 
 void em_open_all()
 {
   /* pre-calculate some data */
   tab_generate();
-#if defined(PLATFORM_LINUX) || defined(PLATFORM_BSD)
-  ulaw_generate();
-#endif
 
   progname = "emerald mine";
 
@@ -266,32 +64,6 @@ void em_open_all()
 
 void em_close_all(void)
 {
-#if defined(AUDIO_UNIX_NATIVE)
-  int i;
-
-  if (sound_pid != -1)
-  {
-    kill(sound_pid, SIGTERM);
-    waitpid(sound_pid, 0, 0);
-  }
-
-  if (sound_pipe[0] != -1)
-    close(sound_pipe[0]);
-  if (sound_pipe[1] != -1)
-    close(sound_pipe[1]);
-
-  for (i = 0; i < SAMPLE_MAX; i++)
-    if (sound_data[i])
-      free(sound_data[i]);
-#endif
-
-#if 0
-  if (spriteGC)
-    XFreeGC(display, spriteGC);
-
-  if (spriteBitmap)
-    XFreePixmap(display, spriteBitmap);
-#endif
 }
 
 /* ---------------------------------------------------------------------- */
@@ -301,24 +73,7 @@ extern int screen_y;
 
 void play_element_sound(int x, int y, int sample, int element)
 {
-#if 0
-  int left = screen_x / TILEX;
-  int top  = screen_y / TILEY;
-
-  if ((x == -1 && y == -1) ||	/* play sound in the middle of the screen */
-      ((int)(y - top)  <= SCR_FIELDY &&
-       (int)(x - left) <= SCR_FIELDX))
-#endif
-  {
-#if 1
-    PlayLevelSound_EM(x, y, element, sample);
-#else
-    play[sample] = 1;
-    play_x[sample] = x;
-    play_y[sample] = y;
-    play_element[sample] = element;
-#endif
-  }
+  PlayLevelSound_EM(x, y, element, sample);
 }
 
 void play_sound(int x, int y, int sample)
@@ -328,48 +83,9 @@ void play_sound(int x, int y, int sample)
 
 void sound_play(void)
 {
-  if (!use_native_em_sound)
-  {
-    int i;
-
-#if 0
-    UpdateEngineValues(screen_x / TILEX, screen_y / TILEY);
-#endif
-
-    return;
-
-    for (i = 0; i < SAMPLE_MAX; i++)
-      if (play[i])
-	PlayLevelSound_EM(play_x[i], play_y[i], play_element[i], i);
-  }
-
-#if defined(AUDIO_UNIX_NATIVE)
-  if (use_native_em_sound && sound_pipe[1] != -1)
-  {
-    if (write(sound_pipe[1], &play, sizeof(play)) == -1)
-    {
-      Error(ERR_WARN, "cannot write into pipe to child process -- no sounds");
-
-      if (sound_pipe[0] != -1)
-      {
-	close(sound_pipe[0]);
-	sound_pipe[0] = -1;
-      }
-
-      if (sound_pipe[1] != -1)
-      {
-	close(sound_pipe[1]);
-	sound_pipe[1] = -1;
-      }
-    }
-  }
-
-#endif
-
-  clear_mem(play, sizeof(play));
 }
 
-unsigned int InitEngineRandom_EM(long seed)
+unsigned int InitEngineRandom_EM(int seed)
 {
   if (seed == NEW_RANDOMIZE)
   {
diff --git a/src/game_em/input.c b/src/game_em/input.c
index 7447f4b..4028f19 100644
--- a/src/game_em/input.c
+++ b/src/game_em/input.c
@@ -6,7 +6,7 @@
 #include "main_em.h"
 
 
-unsigned long RandomEM;
+unsigned int RandomEM;
 
 struct LEVEL lev;
 struct PLAYER ply[MAX_PLAYERS];
@@ -63,45 +63,18 @@ void InitGameEngine_EM()
   prepare_em_level();
 
   game_initscreen();
-  game_animscreen();
 
-#if 0
-  /* blit playfield from scroll buffer to normal back buffer for fading in */
-  BlitScreenToBitmap_EM(backbuffer);
-#endif
+  RedrawPlayfield_EM(FALSE);
+}
+
+void UpdateGameDoorValues_EM()
+{
 }
 
 void GameActions_EM(byte action[MAX_PLAYERS], boolean warp_mode)
 {
   int i;
-
-#if 0
-  static int foo = -1;
-
-  if (action[0] == 0 && foo != 0)
-    printf("KEY RELEASED @ %05d\n", FrameCounter);
-
-  foo = action[0];
-#endif
-
-#if 0
-#if 1
-  if (FrameCounter % 10 == 0)
-#endif
-    printf("::: %05d: %lu, %d\n", FrameCounter, RandomEM, frame);
-#endif
-
-#if 0
-  game_animscreen();
-
-#if 1
-#if 0
-  SyncDisplay();
-#endif
-
-  blitscreen();
-#endif
-#endif
+  boolean any_player_dropping = FALSE;
 
   RandomEM = RandomEM * 129 + 1;
 
@@ -110,7 +83,7 @@ void GameActions_EM(byte action[MAX_PLAYERS], boolean warp_mode)
   for (i = 0; i < MAX_PLAYERS; i++)
     readjoy(action[i], &ply[i]);
 
-  UpdateEngineValues(screen_x / TILEX, screen_y / TILEY);
+  UpdateEngineValues(screen_x / TILEX, screen_y / TILEY, ply[0].x, ply[0].y);
 
   if (frame == 7)
   {
@@ -123,23 +96,20 @@ void GameActions_EM(byte action[MAX_PLAYERS], boolean warp_mode)
     synchro_3();
     sound_play();
 
-    if (!warp_mode)		/* do not redraw values in warp mode */
-      DrawGameDoorValues_EM();
+    UpdateGameDoorValues_EM();
   }
 
-  CheckSingleStepMode_EM(action, frame, game_em.any_player_moving);
-
-#if 1
-  game_animscreen();
+  for (i = 0; i < MAX_PLAYERS; i++)
+    if (ply[i].joy_drop &&
+	ply[i].dynamite &&
+	ply[i].dynamite_cnt > 0 &&
+	ply[i].dynamite_cnt < 5)
+      any_player_dropping = TRUE;
 
-#if 1
-#if 0
-  SyncDisplay();
-#endif
+  CheckSingleStepMode_EM(action, frame, game_em.any_player_moving,
+			 game_em.any_player_snapping, any_player_dropping);
 
-  blitscreen();
-#endif
-#endif
+  RedrawPlayfield_EM(FALSE);
 }
 
 /* read input device for players */
diff --git a/src/game_em/level.h b/src/game_em/level.h
deleted file mode 100644
index 5fee5e5..0000000
--- a/src/game_em/level.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef LEVEL_H
-#define LEVEL_H
-
-#include "main_em.h"
-
-#endif
diff --git a/src/game_em/main_em.h b/src/game_em/main_em.h
index c5efc41..6c96531 100644
--- a/src/game_em/main_em.h
+++ b/src/game_em/main_em.h
@@ -45,48 +45,22 @@
 
 /* screen sizes and positions for EM engine */
 
-#define ORIG_TILEX		16
-#define ORIG_TILEY		16
-#define ORIG_SCOREX		8
-#define ORIG_SCOREY		9
-#define ORIG_GFXMENUFONTX	14
-#define ORIG_GFXMENUFONTY	16
-#define ORIG_MENUFONTX		12
-#define ORIG_MENUFONTY		16
-
-#define ZOOM_FACTOR		2
-
-#define TILEX			(ORIG_TILEX		* ZOOM_FACTOR)
-#define TILEY			(ORIG_TILEY		* ZOOM_FACTOR)
-#define SCOREX			(ORIG_SCOREX		* ZOOM_FACTOR)
-#define SCOREY			(ORIG_SCOREY		* ZOOM_FACTOR)
-#define GFXMENUFONTX		(ORIG_GFXMENUFONTX	* ZOOM_FACTOR)
-#define GFXMENUFONTY		(ORIG_GFXMENUFONTY	* ZOOM_FACTOR)
-#define MENUFONTX		(ORIG_MENUFONTX		* ZOOM_FACTOR)
-#define MENUFONTY		(ORIG_MENUFONTY		* ZOOM_FACTOR)
-
-#define ORIG_SCR_MENUX		20
-#define ORIG_SCR_MENUY		12
-#define SCR_MENUX		17
-#define SCR_MENUY		12
-#if 1
+#define TILESIZE		32
+
+extern int			TILESIZE_VAR;
+
+#define TILEX			TILESIZE_VAR
+#define TILEY			TILESIZE_VAR
+
 extern int			SCR_FIELDX, SCR_FIELDY;
-#else
-#define SCR_FIELDX		17
-#define SCR_FIELDY		17
-#endif
+
 #define MAX_BUF_XSIZE		(SCR_FIELDX + 2)
 #define MAX_BUF_YSIZE		(SCR_FIELDY + 2)
 
 /* often used screen positions */
-#define ORIG_MENU_SX		((ORIG_SCR_MENUX - SCR_MENUX) * TILEX / 2)
-#define ORIG_MENU_SY		0
-#if 1
+
 extern int			SX, SY;
-#else
-#define SX			8
-#define SY			8
-#endif
+
 #define SXSIZE			(SCR_FIELDX * TILEX)
 #define SYSIZE			(SCR_FIELDY * TILEY)
 
@@ -117,7 +91,7 @@ extern int			SX, SY;
 /* exported variables                                                        */
 /* ------------------------------------------------------------------------- */
 
-extern unsigned long RandomEM;
+extern unsigned int RandomEM;
 
 extern struct LEVEL lev;
 extern struct PLAYER ply[MAX_PLAYERS];
@@ -152,15 +126,6 @@ extern Bitmap *sprBitmap;
 extern Bitmap *ttlBitmap;
 extern Bitmap *botBitmap;
 
-extern Pixmap screenPixmap;
-extern Pixmap scorePixmap;
-extern Pixmap spriteBitmap;
-
-extern Pixmap objmaskBitmap;
-extern Pixmap sprmaskBitmap;
-
-extern GC spriteGC;
-
 
 /* ------------------------------------------------------------------------- */
 /* exported functions                                                        */
diff --git a/src/game_em/sample.h b/src/game_em/sample.h
index 853b27d..41bc872 100644
--- a/src/game_em/sample.h
+++ b/src/game_em/sample.h
@@ -10,18 +10,8 @@ extern void play_element_sound(int, int, int, int);
 extern char play[SAMPLE_MAX];
 extern int sound_pipe[2];
 extern short *sound_data[SAMPLE_MAX];
-extern long sound_length[SAMPLE_MAX];
+extern int sound_length[SAMPLE_MAX];
 
 #define MIXER_MAX 4	/* maximum number of samples we can play at once */
 
-#if defined(AUDIO_UNIX_NATIVE)
-
-enum
-{
-  AUDIO_ULAW = 0,
-  AUDIO_U8
-};
-
-#endif	/* AUDIO_UNIX_NATIVE */
-
 #endif	/* SAMPLE_H */
diff --git a/src/game_em/sound.c b/src/game_em/sound.c
index c1334cc..174d623 100644
--- a/src/game_em/sound.c
+++ b/src/game_em/sound.c
@@ -4,514 +4,3 @@
  */
 
 #include "main_em.h"
-
-
-#if defined(AUDIO_UNIX_NATIVE)
-
-#if defined(PLATFORM_LINUX) || defined(PLATFORM_BSD)
-
-#ifdef PLATFORM_LINUX
-#include <sys/ioctl.h>
-#include <sys/soundcard.h>
-#endif
-
-#ifdef PLATFORM_BSD
-#include <ioctl.h>
-#include <soundcard.h>
-#endif
-
-static char audioname[] = "/dev/audio";
-
-static const int sound_priority[SAMPLE_MAX] =
-{
-  SAMPLE_exit_open,
-  SAMPLE_exit_leave,
-  SAMPLE_die,
-  SAMPLE_time,
-  SAMPLE_boom,
-  SAMPLE_tick,
-  SAMPLE_collect,
-  SAMPLE_roll,
-  SAMPLE_push,
-  SAMPLE_dynamite,
-  SAMPLE_press,
-  SAMPLE_door,
-  SAMPLE_dirt,
-  SAMPLE_blank,
-  SAMPLE_android_clone,
-  SAMPLE_android_move,
-  SAMPLE_ball,
-  SAMPLE_grow,
-  SAMPLE_squash,
-  SAMPLE_wonderfall,
-  SAMPLE_crack,
-  SAMPLE_slurp,
-  SAMPLE_drip,
-  SAMPLE_wonder,
-  SAMPLE_wheel,
-  SAMPLE_stone,
-  SAMPLE_spring,
-  SAMPLE_diamond,
-  SAMPLE_nut,
-  SAMPLE_bug,
-  SAMPLE_tank,
-  SAMPLE_eater,
-  SAMPLE_eater_eat,
-  SAMPLE_alien,
-  SAMPLE_acid
-};
-
-int sound_thread(void)
-{
-  int audio_fd; /* file descriptor of /dev/audio or -1 if not open */
-  int audio_format;
-  int sample_rate;
-  int fragment_size;
-  unsigned char *audio_buffer; /* actual buffer pumped to /dev/audio */
-  short *mix_buffer;
-
-  char sound_play[SAMPLE_MAX]; /* if set, we should be playing these sounds */
-  long sound_pos[SAMPLE_MAX]; /* position in the sound */
-  int mix_play[MIXER_MAX]; /* which sounds we have chosen to mix (calculated each time) */
-  int mix_count;
-  int i;
-
- loop:
-
-  audio_fd = -1;
-  audio_format = AUDIO_ULAW; /* defaults for non-OSS /dev/audio */
-  sample_rate = 8000;
-  fragment_size = 256;
-  audio_buffer = 0;
-  mix_buffer = 0;
-  mix_count = 0;
-
-  clear_mem(sound_play, sizeof(sound_play)); /* not playing any sounds */
-
-  for (;;)
-  {
-    for (;;)
-    {
-
-      /* pick sounds to play, if any */
-      if (sound_play[SAMPLE_exit_open] ||
-	  sound_play[SAMPLE_exit_leave] ||
-	  sound_play[SAMPLE_die])
-	sound_play[SAMPLE_boom] = 0; /* no explosions if player goes home */
-
-      mix_count = 0;
-      for (i = 0; i < SAMPLE_MAX; i++)
-      {
-	if (sound_play[sound_priority[i]])
-	{
-	  mix_play[mix_count++] = sound_priority[i];
-
-	  if (mix_count == MIXER_MAX)
-	    break; /* cant mix too many sounds at once */
-	}
-      }
-
-      /* check for incoming messages */
-      if (mix_count || audio_fd != -1)
-      {
-	/* dont block if we are playing sounds */
-	fd_set rfds;
-	struct timeval tv;
-	FD_ZERO(&rfds);
-	FD_SET(sound_pipe[0], &rfds);
-	tv.tv_sec = 0;
-	tv.tv_usec = 0; /* (900000 * fragment_size / sample_rate) */
-	i = select(sound_pipe[0] + 1, &rfds, 0, 0, &tv); /* dont block */
-
-	if (i == -1)
-	{
-	  Error(ERR_WARN, "select() failed in sound thread");
-
-	  goto fail;
-	}
-
-	if (i == 0)
-	  break; /* no messages */
-      }
-
-      /* get a message and start a sound */
-      i = read(sound_pipe[0], &play, sizeof(play));
-
-      if (i == -1)
-      {
-	Error(ERR_WARN, "read() failed in sound thread");
-
-	goto fail;
-      }
-
-      if (i == 0)
-      {
-	Error(ERR_WARN, "reading sound failed in sound thread");
-
-	goto fail;
-      }
-
-      if (i != sizeof(play))
-      {
-	Error(ERR_WARN, "bad message length in sound thread");
-
-	goto fail;
-      }
-
-      for (i = 0; i < SAMPLE_MAX; i++)
-      {
-	if (play[i])
-	{
-	  sound_play[i] = 1; /* play this sound */
-	  sound_pos[i] = 0; /* start it from the start */
-	}
-      }
-    }
-
-    /* open the audio device if there are sounds to play */
-    if (mix_count && audio_fd == -1)
-    {
-      audio_fd = open(audioname, O_WRONLY);
-
-      if (audio_fd == -1)
-	goto reset;
-
-#ifdef OPEN_SOUND_SYSTEM
-      i = 0x00020008;
-
-      if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &i) == -1)
-      {
-	Error(ERR_WARN, "unable to set fragment size in sound thread");
-
-	goto reset;
-      }
-
-      if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &i) == -1)
-      {
-	Error(ERR_WARN, "unable to query audio format in sound thread");
-
-	goto reset;
-      }
-
-      /* prefer 8 bit unsigned and fall back on mu-law */
-      audio_format = (i & AFMT_U8) ? AFMT_U8 : AFMT_MU_LAW;
-
-      i = audio_format;
-      if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &i) == -1)
-      {
-	Error(ERR_WARN, "unable to set audio format in sound thread");
-
-	goto reset;
-      }
-
-      if (i == AFMT_MU_LAW)
-      {
-	audio_format = AUDIO_ULAW;
-      }
-      else if (i == AFMT_U8)
-      {
-	audio_format = AUDIO_U8;
-      }
-      else
-      {
-	Error(ERR_WARN, "audio format required by device not supported");
-
-	goto reset;
-      }
-
-      i = 1;
-      if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &i) == -1)
-      {
-	Error(ERR_WARN, "unable to set channels to mono in sound thread");
-
-	goto reset;
-      }
-
-      if (i != 1)
-      {
-	Error(ERR_WARN, "channels required by device not supported");
-
-	goto reset;
-      }
-
-      i = 8000;
-      if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &i) == -1)
-      {
-	Error(ERR_WARN, "unable to set sampling rate in sound thread");
-
-	goto reset;
-      }
-
-      sample_rate = i;
-      if (ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &i) == -1)
-      {
-	Error(ERR_WARN, "unable to get block size in sound thread");
-
-	goto reset;
-      }
-
-      fragment_size = i;
-
-#else
-      if (fcntl(audio_fd, F_SETFL, O_NONBLOCK) == -1)
-      {
-	Error(ERR_WARN, "unable to make audio non blocking in sound thread");
-
-	goto reset;
-      }
-
-#endif /* OPEN_SOUND_SYSTEM */
-
-      audio_buffer = malloc(fragment_size * sizeof(*audio_buffer));
-      if (audio_buffer == 0)
-      {
-	Error(ERR_WARN, "unable to malloc audio buffer in sound thread");
-
-	goto fail;
-      }
-
-      mix_buffer = malloc(fragment_size * sizeof(*mix_buffer));
-      if (mix_buffer == 0)
-      {
-	Error(ERR_WARN, "unable to malloc mixing buffer in sound thread");
-
-	goto fail;
-      }
-    }
-
-    /* close the audio device if no sounds are playing */
-    if (mix_count == 0 && audio_fd != -1)
-    {
-      close(audio_fd);
-      free(audio_buffer);
-      free(mix_buffer);
-      audio_fd = -1;
-      audio_buffer = 0;
-      mix_buffer = 0;
-    }
-
-    /* if we are playing sounds and the audio device is open, mix them */
-    if (mix_count && audio_fd != -1)
-    {
-      /* prepare mix buffer */
-      clear_mem(mix_buffer, fragment_size * sizeof(*mix_buffer));
-
-      for (i = 0; i < mix_count; i++)
-      {
-	register short *mix_ptr = mix_buffer;
-	register short *sound_ptr =
-	  sound_data[mix_play[i]] + sound_pos[mix_play[i]];
-	register long count =
-	  sound_length[mix_play[i]] - sound_pos[mix_play[i]];
-
-	if (count > fragment_size)
-	  count = fragment_size;
-
-	while (count--)
-	  *mix_ptr++ += *sound_ptr++; /* mix the sounds in */
-      }
-
-      switch(audio_format)
-      {
-        case AUDIO_ULAW:
-	  for (i = 0; i < fragment_size; i++)
-	    audio_buffer[i] = linear_to_ulaw[mix_buffer[i] + 32768];
-	  break;
-
-        case AUDIO_U8:
-	  for (i = 0; i < fragment_size; i++)
-	    audio_buffer[i] = (mix_buffer[i] + 32768) >> 8;
-	  break;
-      }
-
-      /* advance sound pointers */
-      for (i = 0; i < SAMPLE_MAX; i++)
-      {
-	if (sound_play[i])
-	{
-	  if (sound_pos[i] + fragment_size < sound_length[i])
-	  {
-	    sound_pos[i] += fragment_size;
-	  }
-	  else
-	  {
-	    sound_play[i] = 0;
-	  }
-	}
-      }
-
-      /* send the data to the audio device */
-      i = write(audio_fd, audio_buffer, fragment_size);
-      if (i == -1)
-      {
-	Error(ERR_WARN, "cannot write to audio device in sound thread");
-
-	goto reset;
-      }
-
-      if (i != fragment_size)
-      {
-	Error(ERR_WARN, "bad write length to audio device in sound thread");
-
-	goto reset;
-      }
-    }
-  } /* for */
-
- reset:
-
-  if (audio_fd != -1)
-    close(audio_fd);
-  if (audio_buffer)
-    free(audio_buffer);
-  if (mix_buffer)
-    free(mix_buffer);
-
-  goto loop; /* back to top */
-
- fail:
-  if (audio_fd != -1)
-    close(audio_fd);
-  if (audio_buffer)
-    free(audio_buffer);
-  if (mix_buffer)
-    free(mix_buffer);
-
-  return(0);
-}
-
-int read_sample(char *name, short **data, long *length)
-{
-  int result;
-  FILE *file = 0;
-  short *dataptr = 0;
-  long datalength;
-
-  int i, actual, ch;
-  unsigned char buffer[24];
-  unsigned long temp;
-
-  file = fopen(name, "rb");
-  if (file == 0)
-  {
-    Error(ERR_WARN, "cannot open file '%s' in sound thread", name);
-
-    result = 1;
-    goto fail;
-  }
-
-  actual = fread(buffer, 1, 24, file);
-  if (actual == -1)
-  {
-    Error(ERR_WARN, "cannot read file '%s' in sound thread", name);
-
-    result = 1;
-    goto fail;
-  }
-
-  if (actual < 24)
-  {
-    Error(ERR_WARN, "premature eof of file '%s' in sound thread", name);
-
-    result = 1;
-    goto fail;
-  }
-
-  /* magic */
-  temp = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
-  if (temp != 0x2e736e64)
-  {
-    Error(ERR_WARN, "unrecognized format of file '%s' in sound thread", name);
-
-    result = 1;
-    goto fail;
-  }
-
-  /* header length */
-  temp = buffer[4] << 24 | buffer[5] << 16 | buffer[6] << 8 | buffer[7];
-  if (temp < 24)
-  {
-    Error(ERR_WARN, "bad header length of file '%s' in sound thread", name);
-
-    result = 1;
-    goto fail;
-  }
-
-  actual = temp;
-  for (i = 24; i < actual; i++)
-  {
-    /* skip the rest of the header */
-    ch = fgetc(file);
-    if (ch == EOF)
-      break;
-  }
-
- /* data length */
-  temp = buffer[8] << 24 | buffer[9] << 16 | buffer[10] << 8 | buffer[11];
-  datalength = temp;
-
-  /* encoding */
-  temp = buffer[12] << 24 | buffer[13] << 16 | buffer[14] << 8 | buffer[15];
-  if (temp != 1)
-  {
-    fprintf(stderr, "%s: \"%s\": %s (%ld != 1)\n", progname, name,
-	    "bad encoding type", temp);
-    result = 1;
-    goto fail;
-  }
-
-  /* sample rate */
-  temp = buffer[16] << 24 | buffer[17] << 16 | buffer[18] << 8 | buffer[19];
-  if (temp != 8000)
-  {
-    fprintf(stderr, "%s: \"%s\": %s (%ld != 8000)\n", progname, name,
-	    "bad sample rate", temp);
-    result = 1;
-    goto fail;
-  }
-
-  /* channels */
-  temp = buffer[20] << 24 | buffer[21] << 16 | buffer[22] << 8 | buffer[23];
-  if (temp != 1)
-  {
-    fprintf(stderr, "%s: \"%s\": %s (%ld != 1)\n", progname, name,
-	    "unsupported channels", temp);
-    result = 1;
-    goto fail;
-  }
-
-  dataptr = malloc(datalength * sizeof(*dataptr));
-  if (dataptr == 0)
-  {
-    Error(ERR_WARN, "unable to malloc buffer for file '%s' in sound thread",
-	  name);
-
-    result = 1;
-    goto fail;
-  }
-
-  for (i = 0; i < datalength; i++)
-  {
-    ch = fgetc(file);
-    if (ch == EOF) break;
-    dataptr[i] = ulaw_to_linear[ch];
-  }
-
-  fclose(file);
-  file = 0;
-
-  *data = dataptr;
-  *length = datalength;
-  result = 0;
-
- fail:
-
-  if (file)
-    fclose(file);
-
-  return(result);
-}
-
-#endif /* defined(PLATFORM_LINUX) || defined(PLATFORM_BSD) */
-
-#endif /* AUDIO_UNIX_NATIVE */
diff --git a/src/game_em/synchro_1.c b/src/game_em/synchro_1.c
index 3a469fd..7852eb7 100644
--- a/src/game_em/synchro_1.c
+++ b/src/game_em/synchro_1.c
@@ -8,10 +8,6 @@
 #include "main_em.h"
 
 
-#if 0
-extern int centered_player_nr;
-#endif
-
 #define USE_CHANGED_ACID_STUFF		1
 
 extern boolean checkIfAllPlayersFitToScreen();
@@ -23,15 +19,13 @@ static boolean player_killed(struct PLAYER *);
 
 void synchro_1(void)
 {
-#if 1
-
   int start_check_nr;
   int i;
 
   game_em.any_player_moving = FALSE;
+  game_em.any_player_snapping = FALSE;
 
   /* must test for death and actually kill separately */
-
   for (i = 0; i < MAX_PLAYERS; i++)
   {
     boolean ply_kill = player_killed(&ply[i]);
@@ -40,25 +34,6 @@ void synchro_1(void)
       kill_player(&ply[i]);
   }
 
-#else
-
-  /* must test for death and actually kill separately */
-  boolean ply1_kill = player_killed(&ply1);
-  boolean ply2_kill = player_killed(&ply2);
-
-  if (ply1.alive && ply1_kill)
-    kill_player(&ply1);
-  if (ply2.alive && ply2_kill)
-    kill_player(&ply2);
-
-#endif
-
-#if 0
-  ply1.alive = 1; /* debugging */
-#endif
-
-#if 1
-
   for (i = 0; i < MAX_PLAYERS; i++)
   {
     ply[i].oldx = ply[i].x;
@@ -93,58 +68,6 @@ void synchro_1(void)
       Next[ply[i].y][ply[i].x] = Zplayer;
     }
   }
-
-#else
-
-  ply1.oldx = ply1.x;
-  ply1.oldy = ply1.y;
-  ply1.anim = SPR_still;
-  ply2.oldx = ply2.x;
-  ply2.oldy = ply2.y;
-  ply2.anim = SPR_still;
-
-  if (RandomEM & 256)
-  {
-    if (ply1.alive) check_player(&ply1);
-    if (ply2.alive) check_player(&ply2);
-  }
-  else
-  {
-    if (ply2.alive) check_player(&ply2);
-    if (ply1.alive) check_player(&ply1);
-  }
-
-  if (ply1.alive)
-  {
-    if (Cave[ply1.oldy][ply1.oldx] == Zplayer)
-    {
-      Cave[ply1.oldy][ply1.oldx] = Xblank;
-      Next[ply1.oldy][ply1.oldx] = Xblank;
-    }
-
-    if (Cave[ply1.y][ply1.x] == Xblank)
-    {
-      Cave[ply1.y][ply1.x] = Zplayer;
-      Next[ply1.y][ply1.x] = Zplayer;
-    }
-  }
-
-  if (ply2.alive)
-  {
-    if (Cave[ply2.oldy][ply2.oldx] == Zplayer)
-    {
-      Cave[ply2.oldy][ply2.oldx] = Xblank;
-      Next[ply2.oldy][ply2.oldx] = Xblank;
-    }
-
-    if (Cave[ply2.y][ply2.x] == Xblank)
-    {
-      Cave[ply2.y][ply2.x] = Zplayer;
-      Next[ply2.y][ply2.x] = Zplayer;
-    }
-  }
-
-#endif
 }
 
 static boolean player_killed(struct PLAYER *ply)
@@ -152,20 +75,11 @@ static boolean player_killed(struct PLAYER *ply)
   int x = ply->x;
   int y = ply->y;
 
-#if 0
-  printf("::: %d: %d, %d\n", ply->num, x, y);
-#endif
-
   if (!ply->alive)
     return FALSE;
 
-#if 1
   if (lev.killed_out_of_time && setup.time_limit)
     return TRUE;
-#else
-  if (lev.time_initial > 0 && lev.time == 0 && setup.time_limit)
-    return TRUE;
-#endif
 
   switch(Cave[y-1][x])
   {
@@ -295,11 +209,6 @@ static void kill_player(struct PLAYER *ply)
     case Xbug_gos:
     case Xbug_gow:
       Cave[y-1][x] = Xboom_bug;
-#if 0
-#if PLAY_ELEMENT_SOUND
-      play_element_sound(x, y, SAMPLE_boom, Zplayer);
-#endif
-#endif
       break;
 
     case Xtank_n:
@@ -311,11 +220,6 @@ static void kill_player(struct PLAYER *ply)
     case Xtank_gos:
     case Xtank_gow:
       Cave[y-1][x] = Xboom_bomb;
-#if 0
-#if PLAY_ELEMENT_SOUND
-      play_element_sound(x, y, SAMPLE_boom, Zplayer);
-#endif
-#endif
       break;
   }
 
@@ -330,11 +234,6 @@ static void kill_player(struct PLAYER *ply)
     case Xbug_gos:
     case Xbug_gow:
       Cave[y][x+1] = Xboom_bug;
-#if 0
-#if PLAY_ELEMENT_SOUND
-      play_element_sound(x, y, SAMPLE_boom, Zplayer);
-#endif
-#endif
       break;
 
     case Xtank_n:
@@ -346,11 +245,6 @@ static void kill_player(struct PLAYER *ply)
     case Xtank_gos:
     case Xtank_gow:
       Cave[y][x+1] = Xboom_bomb;
-#if 0
-#if PLAY_ELEMENT_SOUND
-      play_element_sound(x, y, SAMPLE_boom, Zplayer);
-#endif
-#endif
       break;
   }
 
@@ -365,11 +259,6 @@ static void kill_player(struct PLAYER *ply)
     case Xbug_gos:
     case Xbug_gow:
       Cave[y+1][x] = Xboom_bug;
-#if 0
-#if PLAY_ELEMENT_SOUND
-      play_element_sound(x, y, SAMPLE_boom, Zplayer);
-#endif
-#endif
       break;
 
     case Xtank_n:
@@ -381,11 +270,6 @@ static void kill_player(struct PLAYER *ply)
     case Xtank_gos:
     case Xtank_gow:
       Cave[y+1][x] = Xboom_bomb;
-#if 0
-#if PLAY_ELEMENT_SOUND
-      play_element_sound(x, y, SAMPLE_boom, Zplayer);
-#endif
-#endif
       break;
   }
 
@@ -400,11 +284,6 @@ static void kill_player(struct PLAYER *ply)
     case Xbug_gos:
     case Xbug_gow:
       Cave[y][x-1] = Xboom_bug;
-#if 0
-#if PLAY_ELEMENT_SOUND
-      play_element_sound(x, y, SAMPLE_boom, Zplayer);
-#endif
-#endif
       break;
 
     case Xtank_n:
@@ -416,11 +295,6 @@ static void kill_player(struct PLAYER *ply)
     case Xtank_gos:
     case Xtank_gow:
       Cave[y][x-1] = Xboom_bomb;
-#if 0
-#if PLAY_ELEMENT_SOUND
-      play_element_sound(x, y, SAMPLE_boom, Zplayer);
-#endif
-#endif
       break;
   }
 
@@ -435,9 +309,6 @@ static void kill_player(struct PLAYER *ply)
       break;
 
     default:
-#if PLAY_ELEMENT_SOUND
-      play_element_sound(x, y, SAMPLE_boom, Zplayer);
-#endif
       play_element_sound(x, y, SAMPLE_die, Zplayer);
       break;
   }
@@ -469,101 +340,31 @@ static void check_player(struct PLAYER *ply)
   int oldy = ply->y;
   int x = oldx;
   int y = oldy;
-  int anim = 0;
   int dx = 0, dy = 0;
 
   game_em.last_player_direction[ply->num] = MV_NONE;
 
-#if 0
-  printf("::: up == %d, down == %d, left == %d, right == %d, fire == %d [spin == %d, stick == %d]\n",
-	 ply->joy_n, ply->joy_s, ply->joy_w, ply->joy_e, ply->joy_fire,
-	 ply->joy_spin, ply->joy_stick);
-#endif
-
-#if 1
   if (ply->joy_w)		/* west */
   {
     x--;
     dx = -1;
-    anim = 3;
   }
   else if (ply->joy_e)		/* east */
   {
     x++;
     dx = 1;
-    anim = 1;
   }
 
   if (ply->joy_n)		/* north */
   {
     y--;
     dy = -1;
-    anim = 0;
   }
   else if (ply->joy_s)		/* south */
   {
     y++;
     dy = 1;
-    anim = 2;
-  }
-
-#else
-
-  if ((ply->joy_spin = !ply->joy_spin))
-  {
-    if (ply->joy_n)		/* north */
-    {
-      y--;
-      dy = -1;
-      anim = 0;
-    }
-    else if (ply->joy_e)	/* east */
-    {
-      x++;
-      dx = 1;
-      anim = 1;
-    }
-    else if (ply->joy_s)	/* south */
-    {
-      y++;
-      dy = 1;
-      anim = 2;
-    }
-    else if (ply->joy_w)	/* west */
-    {
-      x--;
-      dx = -1;
-      anim = 3;
-    }
   }
-  else
-  {
-    if (ply->joy_w)		/* west */
-    {
-      x--;
-      dx = -1;
-      anim = 3;
-    }
-    else if (ply->joy_s)	/* south */
-    {
-      y++;
-      dy = 1;
-      anim = 2;
-    }
-    else if (ply->joy_e)	/* east */
-    {
-      x++;
-      dx = 1;
-      anim = 1;
-    }
-    else if (ply->joy_n)	/* north */
-    {
-      y--;
-      dy = -1;
-      anim = 0;
-    }
-  }
-#endif
 
   if (dx || dy)
   {
@@ -660,7 +461,7 @@ static void check_player(struct PLAYER *ply)
   }
   else					/* player wants to snap */
   {
-    player_digfield(ply, dx, dy);
+    game_em.any_player_snapping = player_digfield(ply, dx, dy);
   }
 }
 
@@ -784,6 +585,7 @@ static boolean player_digfield(struct PLAYER *ply, int dx, int dy)
 	play_element_sound(x, y, SAMPLE_collect, element);
 	lev.score += lev.diamond_score;
 	lev.required = lev.required < 3 ? 0 : lev.required - 3;
+	game.snapshot.collected_item = TRUE;
 	ply->anim = SPR_walk + anim;
 	ply->x = x;
 	ply->y = y;
@@ -796,6 +598,7 @@ static boolean player_digfield(struct PLAYER *ply, int dx, int dy)
 	play_element_sound(x, y, SAMPLE_collect, element);
 	lev.score += lev.emerald_score;
 	lev.required = lev.required < 1 ? 0 : lev.required - 1;
+	game.snapshot.collected_item = TRUE;
 	ply->anim = SPR_walk + anim;
 	ply->x = x;
 	ply->y = y;
@@ -1266,19 +1069,8 @@ static boolean player_digfield(struct PLAYER *ply, int dx, int dy)
       case Xexit_1:
       case Xexit_2:
       case Xexit_3:
-#if 0
-	/* !!! already played in kill_player !!! */
-	play_element_sound(x, y, SAMPLE_exit_leave, Xexit_1);
-#endif
-
 	lev.home--;
 
-#if 0
-	/* !!! CHECK SCORE CALCULATION !!! */
-	if (lev.home == 0 && lev.time_initial > 0)	/* game won */
-	  lev.score += lev.time * lev.exit_score / 100;
-#endif
-
 	ply->anim = SPR_walk + anim;
 	ply->x = x;
 	ply->y = y;
@@ -1318,6 +1110,7 @@ static boolean player_digfield(struct PLAYER *ply, int dx, int dy)
 	play_element_sound(x, y, SAMPLE_collect, element);
 	lev.score += lev.diamond_score;
 	lev.required = lev.required < 3 ? 0 : lev.required - 3;
+	game.snapshot.collected_item = TRUE;
 	ply->anim = SPR_walk + anim;
 	break;
 
@@ -1328,6 +1121,7 @@ static boolean player_digfield(struct PLAYER *ply, int dx, int dy)
 	play_element_sound(x, y, SAMPLE_collect, element);
 	lev.score += lev.emerald_score;
 	lev.required = lev.required < 1 ? 0 : lev.required - 1;
+	game.snapshot.collected_item = TRUE;
 	ply->anim = SPR_walk + anim;
 	break;
 
diff --git a/src/game_em/synchro_2.c b/src/game_em/synchro_2.c
index 82ca79b..8fc7ada 100644
--- a/src/game_em/synchro_2.c
+++ b/src/game_em/synchro_2.c
@@ -43,7 +43,7 @@ void synchro_2(void)
 {
   int x = 0;
   int y = 1;
-  unsigned long random = RandomEM;
+  unsigned int random = RandomEM;
   short *cave_cache = Cave[y];	/* might be a win */
   int score = 0;
 
@@ -1902,46 +1902,8 @@ void synchro_2(void)
 	    Cave[y+1][x+1] == Zplayer)
 	  goto android_still;
 
-#if 1
-
 	set_nearest_player_xy(x, y, &dx, &dy);
 
-#else
-
-  	if (ply1.alive && ply2.alive)
-	{
-  	  if ((ply1.x > x ? ply1.x - x : x - ply1.x) +
-	      (ply1.y > y ? ply1.y - y : y - ply1.y) <
-	      (ply2.x > x ? ply2.x - x : x - ply2.x) +
-	      (ply2.y > y ? ply2.y - y : y - ply2.y))
-	  {
-  	    dx = ply1.x;
-  	    dy = ply1.y;
-  	  }
-	  else
-	  {
-  	    dx = ply2.x;
-  	    dy = ply2.y;
-  	  }
-  	}
-	else if (ply1.alive)
-	{
-  	  dx = ply1.x;
-  	  dy = ply1.y;
-  	}
-	else if (ply2.alive)
-	{
-  	  dx = ply2.x;
-  	  dy = ply2.y;
-  	}
-	else
-	{
-  	  dx = 0;
-  	  dy = 0;
-  	}
-
-#endif
-
   	Next[y][x] = Xblank;	/* assume we will move */
   	temp = ((x < dx) + 1 - (x > dx)) + ((y < dy) + 1 - (y > dy)) * 3;
 
@@ -3237,8 +3199,6 @@ void synchro_2(void)
 
     case Xalien:
 
-#if 1
-
       if (lev.wheel_cnt)
       {
 	dx = lev.wheel_x;
@@ -3249,47 +3209,6 @@ void synchro_2(void)
 	set_nearest_player_xy(x, y, &dx, &dy);
       }
 
-#else
-
-      if (lev.wheel_cnt)
-      {
-	dx = lev.wheel_x;
-	dy = lev.wheel_y;
-      }
-      else if (ply1.alive && ply2.alive)
-      {
-	if ((ply1.x > x ? ply1.x - x : x - ply1.x) +
-	    (ply1.y > y ? ply1.y - y : y - ply1.y) <
-	    (ply2.x > x ? ply2.x - x : x - ply2.x) +
-	    (ply2.y > y ? ply2.y - y : y - ply2.y))
-	{
-	  dx = ply1.x;
-	  dy = ply1.y;
-	}
-	else
-	{
-	  dx = ply2.x;
-	  dy = ply2.y;
-	}
-      }
-      else if (ply1.alive)
-      {
-	dx = ply1.x;
-	dy = ply1.y;
-      }
-      else if (ply2.alive)
-      {
-	dx = ply2.x;
-	dy = ply2.y;
-      }
-      else
-      {
-	dx = 0;
-	dy = 0;
-      }
-
-#endif
-
       if (RANDOM & 1)
       {
 	if (y > dy)
@@ -4565,11 +4484,8 @@ void synchro_2(void)
 	}
       }
 
-#if 1
       lev.ball_pos = (lev.ball_pos + 1) % lev.num_ball_arrays;
-#else
-      lev.ball_pos = (lev.ball_pos + 1) & 7;
-#endif
+
       goto loop;
 
     /* --------------------------------------------------------------------- */
@@ -4716,7 +4632,6 @@ void synchro_2(void)
   	case Xacid_6:
   	case Xacid_7:
   	case Xacid_8:
-#if 1
   	  Cave[y][x] = Xsand_stonesand_quickout_1;
   	  if (Cave[y][x+1] == Xblank)
 	    Cave[y][x+1] = Yacid_splash_eB;
@@ -4725,33 +4640,15 @@ void synchro_2(void)
   	  Next[y][x] = Xsand_stonesand_quickout_2;
   	  play_element_sound(x, y, SAMPLE_acid, Xacid_1);
   	  goto loop;
-#else
-  	  Cave[y][x] = Xsand_stonesand_3;
-  	  if (Cave[y][x+1] == Xblank)
-	    Cave[y][x+1] = Yacid_splash_eB;
-  	  if (Cave[y][x-1] == Xblank)
-	    Cave[y][x-1] = Yacid_splash_wB;
-  	  Next[y][x] = Xsand_stonesand_4;
-  	  play_element_sound(x, y, SAMPLE_acid, Xacid_1);
-  	  goto loop;
-#endif
 
   	case Xblank:
   	case Yacid_splash_eB:
   	case Yacid_splash_wB:
-#if 1
   	  Cave[y][x] = Xsand_stonesand_quickout_1;
   	  Cave[y+1][x] = Xsand_stoneout_1;
   	  Next[y][x] = Xsand_stonesand_quickout_2;
   	  Next[y+1][x] = Xsand_stoneout_2;
   	  goto loop;
-#else
-  	  Cave[y][x] = Xsand_stonesand_3;
-  	  Cave[y+1][x] = Xsand_stoneout_1;
-  	  Next[y][x] = Xsand_stonesand_4;
-  	  Next[y+1][x] = Xsand_stoneout_2;
-  	  goto loop;
-#endif
 
   	case Xsand:
   	  Cave[y][x] = Xsand_stonesand_1;
diff --git a/src/game_em/synchro_3.c b/src/game_em/synchro_3.c
index bafc581..307d285 100644
--- a/src/game_em/synchro_3.c
+++ b/src/game_em/synchro_3.c
@@ -20,18 +20,6 @@ void synchro_3(void)
   if (lev.score > 9999)
     lev.score = 9999;
 
-#if 0
-#if 1
-  if (lev.time_initial == 0)
-    lev.time++;
-  else if (lev.time > 0)
-    lev.time--;
-#else
-  if (lev.time)
-    lev.time--;
-#endif
-#endif
-
   if (lev.android_move_cnt-- == 0)
     lev.android_move_cnt = lev.android_move_time;
   if (lev.android_clone_cnt-- == 0)
@@ -50,12 +38,6 @@ void synchro_3(void)
   if (lev.wonderwall_time && lev.wonderwall_state)
     lev.wonderwall_time--;
 
-#if 0
-  if (lev.time_initial > 0 &&
-      lev.time > 0 && lev.time <= 50 && lev.time % 5 == 0 && setup.time_limit)
-    play_sound(-1, -1, SAMPLE_time);
-#endif
-
   if (lev.wheel_cnt)
     play_element_sound(lev.wheel_x, lev.wheel_y, SAMPLE_wheel, Xwheel);
 
diff --git a/src/game_em/tab_generate.c b/src/game_em/tab_generate.c
index 8a3f731..9578451 100644
--- a/src/game_em/tab_generate.c
+++ b/src/game_em/tab_generate.c
@@ -4482,79 +4482,6 @@ void create_obj()
   int *map = obj_map;
   int buffer[8][TILE_MAX];
 
-#if 0
-
-  int debug = 0;
-
-  for (i = 0; i < 8; i++)
-    for (j = 0; j < TILE_MAX; j++)
-      buffer[i][j] = 0;
-
-  for (i = 0; i < 64; i++)
-  {
-    for (;*map != -1; map += 2)
-    {
-      if (map[0] < 0 || map[0] >= TILE_MAX || map[1] < 0 || map[1] >= 8)
-      {
-	fprintf(stderr, "obj_map: bad tile (%d, %d) @ %d+%d\n",
-		map[0], map[1], i / 16, i % 16);
-	debug = 1;
-	continue;
-      }
-      buffer[map[1]][map[0]]++;
-    }
-    map++;
-  }
-
-  for (i = 0; i < 896; i++)
-  {
-    for (;*map != -1; map += 2)
-    {
-      if (map[0] < 0 || map[0] >= TILE_MAX || map[1] < 0 || map[1] >= 8)
-      {
-	fprintf(stderr, "obj_map: bad tile (%d, %d) @ %d\n", map[0], map[1], i);
-	debug = 1;
-	continue;
-      }
-      buffer[map[1]][map[0]]++;
-    }
-    map++;
-  }
-
-  for (i = 0; i < TILE_MAX; i++)
-  {
-    for (j = 0; j < 8; j++)
-    {
-      switch(buffer[j][i])
-      {
-        case 0:
-	  fprintf(stderr, "obj_map: uninitialized (%d, %d)\n", i, j);
-	  debug = 1;
-	  break;
-        case 1:
-	  break; /* good */
-        default:
-	  fprintf(stderr, "obj_map: duplicate (%d, %d)\n", i, j);
-	  debug = 1;
-	  break;
-      }
-    }
-  }
-
-  if (sizeof(obj_map) / sizeof(*obj_map) != map - obj_map)
-  {
-    fprintf(stderr, "obj_map: bad end (%d != %d)\n",
-	    sizeof(obj_map) / sizeof(*obj_map), map - obj_map);
-    debug = 1;
-  }
-
-  if (debug == 0)
-    fprintf(stderr, "obj_map: looks good, now disable debug code\n");
-
-  abort();
-
-#else
-
   for (i = 0; i < 8; i++)
     for (j = 0; j < TILE_MAX; j++)
       buffer[i][j] = Xblank;
@@ -4578,8 +4505,6 @@ void create_obj()
   for (i = 0; i < 8; i++)
     for (j = 0; j < TILE_MAX; j++)
       map_obj[i][j] = buffer[7 - i][j];
-
-#endif
 }
 
 void create_obj_graphics_info_em()
@@ -4607,6 +4532,7 @@ void create_obj_graphics_info_em()
       g->crumbled_src_x = 0;
       g->crumbled_src_y = 0;
       g->crumbled_border_size = 0;
+      g->crumbled_tile_size = 0;
 
       g->has_crumbled_graphics = FALSE;
       g->preserve_background = FALSE;
diff --git a/src/game_em/ulaw_generate.c b/src/game_em/ulaw_generate.c
index 7c06c30..64488f6 100644
--- a/src/game_em/ulaw_generate.c
+++ b/src/game_em/ulaw_generate.c
@@ -5,132 +5,3 @@
  */
 
 #include "main_em.h"
-
-
-#if defined(PLATFORM_LINUX) || defined(PLATFORM_BSD)
-
-int calc_ulaw_to_linear(unsigned char);
-unsigned char calc_linear_to_ulaw(int);
-
-int buffer[65536];
-
-/* convert from 8 bit ulaw to signed 16 bit linear */
-short ulaw_to_linear[256];
-
-/* convert from signed 16 bit linear to 8 bit ulaw */
-unsigned char linear_to_ulaw[65536];
-
-void ulaw_generate()
-{
-  int i;
-
-  for(i = 0; i < 256; i++)
-    ulaw_to_linear[i] = calc_ulaw_to_linear(i);
-
-  for(i = -32768; i < 32768; i++)
-    linear_to_ulaw[i + 32768] = calc_linear_to_ulaw(i);
-}
-
-/*
-** This routine converts from ulaw to 16 bit linear.
-**
-** Craig Reese: IDA/Supercomputing Research Center
-** 29 September 1989
-**
-** References:
-** 1) CCITT Recommendation G.711  (very difficult to follow)
-** 2) MIL-STD-188-113,"Interoperability and Performance Standards
-**     for Analog-to_Digital Conversion Techniques,"
-**     17 February 1987
-**
-** Input: 8 bit ulaw sample
-** Output: signed 16 bit linear sample
-*/
-
-int calc_ulaw_to_linear(unsigned char ulawbyte)
-{
-  static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
-  int sign, exponent, mantissa, sample;
-
-  ulawbyte = ~ ulawbyte;
-  sign = ( ulawbyte & 0x80 );
-  exponent = ( ulawbyte >> 4 ) & 0x07;
-  mantissa = ulawbyte & 0x0F;
-  sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
-  if (sign != 0)
-    sample = -sample;
-
-  return(sample);
-}
-
-/*
-** This routine converts from linear to ulaw.
-**
-** Craig Reese: IDA/Supercomputing Research Center
-** Joe Campbell: Department of Defense
-** 29 September 1989
-**
-** References:
-** 1) CCITT Recommendation G.711  (very difficult to follow)
-** 2) "A New Digital Technique for Implementation of Any
-**     Continuous PCM Companding Law," Villeret, Michel,
-**     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
-**     1973, pg. 11.12-11.17
-** 3) MIL-STD-188-113,"Interoperability and Performance Standards
-**     for Analog-to_Digital Conversion Techniques,"
-**     17 February 1987
-**
-** Input: Signed 16 bit linear sample
-** Output: 8 bit ulaw sample
-*/
-
-#define ZEROTRAP    /* turn on the trap as per the MIL-STD */
-#define BIAS 0x84   /* define the add-in bias for 16 bit samples */
-#define CLIP 32635
-
-unsigned char calc_linear_to_ulaw(int sample)
-{
-  static int exp_lut[256] =
-  {
-    0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
-    4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
-    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
-  };
-
-  int sign, exponent, mantissa;
-  unsigned char ulawbyte;
-
-/* Get the sample into sign-magnitude. */
-  sign = (sample >> 8) & 0x80; /* set aside the sign */
-  if (sign != 0)
-    sample = -sample; /* get magnitude */
-  if (sample > CLIP)
-    sample = CLIP; /* clip the magnitude */
-
-/* Convert from 16 bit linear to ulaw. */
-  sample = sample + BIAS;
-  exponent = exp_lut[( sample >> 7 ) & 0xFF];
-  mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
-  ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
-#ifdef ZEROTRAP
-  if (ulawbyte == 0)
-    ulawbyte = 0x02; /* optional CCITT trap */
-#endif
-
-  return(ulawbyte);
-}
-
-#endif /* defined(PLATFORM_LINUX) || defined(PLATFORM_BSD) */
diff --git a/src/game_sp/BugsTerminals.c b/src/game_sp/BugsTerminals.c
index 9485027..afa7345 100644
--- a/src/game_sp/BugsTerminals.c
+++ b/src/game_sp/BugsTerminals.c
@@ -5,11 +5,7 @@
 #include "BugsTerminals.h"
 
 
-#if 1
 byte TerminalState[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE];
-#else
-byte *TerminalState;
-#endif
 
 int TerminalMaxCycles;
 
@@ -127,7 +123,7 @@ void subAnimateTerminals(int si)
 
 void subRandomize()
 {
-  long Tick = MyGetTickCount();
+  int Tick = MyGetTickCount();
 
   RandomSeed = (Tick ^ (Tick >> 16)) & 0xFFFF;
 }
diff --git a/src/game_sp/BugsTerminals.h b/src/game_sp/BugsTerminals.h
index 6145852..572395c 100644
--- a/src/game_sp/BugsTerminals.h
+++ b/src/game_sp/BugsTerminals.h
@@ -7,11 +7,7 @@
 
 #include "global.h"
 
-#if 1
 extern byte TerminalState[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE];
-#else
-extern byte *TerminalState;
-#endif
 
 extern int TerminalMaxCycles;
 
diff --git a/src/game_sp/DDScrollBuffer.c b/src/game_sp/DDScrollBuffer.c
index e8bd2fb..0992e0b 100644
--- a/src/game_sp/DDScrollBuffer.c
+++ b/src/game_sp/DDScrollBuffer.c
@@ -7,17 +7,41 @@
 #include <math.h>
 
 
-long mScrollX, mScrollY;
-long mScrollX_last, mScrollY_last;
-
-#if 1
-long ScreenBuffer[2 + MAX_PLAYFIELD_WIDTH + 2][2 + MAX_PLAYFIELD_HEIGHT + 2];
-boolean redraw[2 + MAX_PLAYFIELD_WIDTH + 2][2 + MAX_PLAYFIELD_HEIGHT + 2];
-#else
-long ScreenBuffer[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
-boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
-#endif
+int mScrollX, mScrollY;
+int mScrollX_last, mScrollY_last;
+
+int ScreenBuffer[2 + MAX_PLAYFIELD_WIDTH + 2][2 + MAX_PLAYFIELD_HEIGHT + 2];
+
+
+int getFieldbufferOffsetX_SP()
+{
+  int px = 2 * TILEX + (mScrollX - mScrollX_last) % TILEX;
+
+  /* scroll correction for even number of visible tiles (half tile shifted) */
+  px += game_sp.scroll_xoffset;
+
+  if (ExplosionShakeMurphy != 0)
+    px += TILEX / 2 - GetSimpleRandom(TILEX + 1);
+
+  px = px * TILESIZE_VAR / TILESIZE;
+
+  return px;
+}
+
+int getFieldbufferOffsetY_SP()
+{
+  int py = 2 * TILEY + (mScrollY - mScrollY_last) % TILEY;
 
+  /* scroll correction for even number of visible tiles (half tile shifted) */
+  py += game_sp.scroll_yoffset;
+
+  if (ExplosionShakeMurphy != 0)
+    py += TILEY / 2 - GetSimpleRandom(TILEX + 1);
+
+  py = py * TILESIZE_VAR / TILESIZE;
+
+  return py;
+}
 
 void RestorePlayfield()
 {
@@ -51,18 +75,12 @@ static void ScrollPlayfield(int dx, int dy)
   int x, y;
 
   BlitBitmap(bitmap_db_field_sp, bitmap_db_field_sp,
-             TILEX * (dx == -1),
-             TILEY * (dy == -1),
-             (MAX_BUF_XSIZE * TILEX) - TILEX * (dx != 0),
-             (MAX_BUF_YSIZE * TILEY) - TILEY * (dy != 0),
-             TILEX * (dx == 1),
-             TILEY * (dy == 1));
-
-  /* when scrolling the whole playfield, do not redraw single tiles */
-  for (x = 0; x < MAX_BUF_XSIZE; x++)
-    for (y = 0; y < MAX_BUF_YSIZE; y++)
-      redraw[x][y] = FALSE;
-  redraw_tiles = 0;
+             TILEX_VAR * (dx == -1),
+             TILEY_VAR * (dy == -1),
+             (MAX_BUF_XSIZE * TILEX_VAR) - TILEX_VAR * (dx != 0),
+             (MAX_BUF_YSIZE * TILEY_VAR) - TILEY_VAR * (dy != 0),
+             TILEX_VAR * (dx == 1),
+             TILEY_VAR * (dy == 1));
 
   DrawFrameIfNeeded();
 
@@ -75,9 +93,9 @@ static void ScrollPlayfield(int dx, int dy)
 	int sx = x - x1;
 	int sy = y - y1;
 	int tsi = GetSI(x, y);
-	long id = ((PlayField16[tsi]) |
-		   (PlayField8[tsi] << 16) |
-		   (DisPlayField[tsi] << 24));
+	int id = ((PlayField16[tsi]) |
+		  (PlayField8[tsi] << 16) |
+		  (DisPlayField[tsi] << 24));
 
 	if ((dx == -1 && x == x2) ||
 	    (dx == +1 && x == x1) ||
@@ -106,13 +124,8 @@ static void ScrollPlayfieldIfNeededExt(boolean reset)
 
   if (mScrollX_last == -1 || mScrollY_last == -1)
   {
-#if 1
     mScrollX_last = (mScrollX / TILESIZE) * TILESIZE;
     mScrollY_last = (mScrollY / TILESIZE) * TILESIZE;
-#else
-    mScrollX_last = mScrollX;
-    mScrollY_last = mScrollY;
-#endif
 
     return;
   }
@@ -145,10 +158,13 @@ void InitScrollPlayfield()
   ScrollPlayfieldIfNeededExt(TRUE);
 }
 
+#define DEBUG_REDRAW	0
+
 void UpdatePlayfield(boolean force_redraw)
 {
   int x, y;
-#if 1
+
+#if DEBUG_REDRAW
   int num_redrawn = 0;
 #endif
 
@@ -161,10 +177,6 @@ void UpdatePlayfield(boolean force_redraw)
       int sync_frame = GfxFrame[x][y];
       boolean redraw = force_redraw;
 
-#if 0
-      redraw = TRUE;	// !!! TEST ONLY -- ALWAYS REDRAW !!!
-#endif
-
       if (graphic < 0)
       {
 	GfxGraphicLast[x][y] = GfxGraphic[x][y];
@@ -201,108 +213,38 @@ void UpdatePlayfield(boolean force_redraw)
 	int sx = x * StretchWidth;
 	int sy = y * StretchWidth;
 
-#if 0
-	printf("::: REDRAW (%d, %d): %d, %d\n", x, y, graphic, sync_frame);
-#endif
-
 	DDSpriteBuffer_BltImg(sx, sy, graphic, sync_frame);
 
-#if 1
+#if DEBUG_REDRAW
 	num_redrawn++;
 #endif
       }
     }
   }
 
-#if 0
+#if DEBUG_REDRAW
   printf("::: FRAME %d: %d redrawn\n", FrameCounter, num_redrawn);
 #endif
 }
 
-/* copy the entire screen to the window at the scroll position */
-
 void BlitScreenToBitmap_SP(Bitmap *target_bitmap)
 {
-  int px = 2 * TILEX + (mScrollX - mScrollX_last) % TILEX;
-  int py = 2 * TILEY + (mScrollY - mScrollY_last) % TILEY;
-  int sx, sy, sxsize, sysize;
-
-#if 0
-  printf("::: %d, %d / %d, %d / %ld, %ld (%ld, %ld) / %d, %d\n",
-	 MurphyScreenXPos, MurphyScreenYPos,
-	 ScreenScrollXPos, ScreenScrollYPos,
-	 mScrollX, mScrollY,
-	 mScrollX_last, mScrollY_last,
-	 px, py);
-#endif
+  /* copy playfield buffer to target bitmap at scroll position */
 
+  int px = getFieldbufferOffsetX_SP();
+  int py = getFieldbufferOffsetY_SP();
   int xsize = SXSIZE;
   int ysize = SYSIZE;
-  int full_xsize = (FieldWidth  - (menBorder ? 0 : 1)) * TILEX;
-  int full_ysize = (FieldHeight - (menBorder ? 0 : 1)) * TILEY;
-
-  sxsize = (full_xsize < xsize ? full_xsize : xsize);
-  sysize = (full_ysize < ysize ? full_ysize : ysize);
-  sx = SX + (full_xsize < xsize ? (xsize - full_xsize) / 2 : 0);
-  sy = SY + (full_ysize < ysize ? (ysize - full_ysize) / 2 : 0);
-
-  /* scroll correction for even number of visible tiles (half tile shifted) */
-  px += game_sp.scroll_xoffset;
-  py += game_sp.scroll_yoffset;
-
-#if 1
-  if (ExplosionShakeMurphy != 0)
-  {
-    px += TILEX / 2 - GetSimpleRandom(TILEX + 1);
-    py += TILEY / 2 - GetSimpleRandom(TILEX + 1);
-  }
-#endif
+  int full_xsize = (FieldWidth  - (menBorder ? 0 : 1)) * TILEX_VAR;
+  int full_ysize = (FieldHeight - (menBorder ? 0 : 1)) * TILEY_VAR;
+  int sx = SX + (full_xsize < xsize ? (xsize - full_xsize) / 2 : 0);
+  int sy = SY + (full_ysize < ysize ? (ysize - full_ysize) / 2 : 0);
+  int sxsize = (full_xsize < xsize ? full_xsize : xsize);
+  int sysize = (full_ysize < ysize ? full_ysize : ysize);
 
   BlitBitmap(bitmap_db_field_sp, target_bitmap, px, py, sxsize, sysize, sx, sy);
 }
 
-void BackToFront_SP(void)
-{
-  static boolean scrolling_last = FALSE;
-  int left = mScrollX / TILEX;
-  int top  = mScrollY / TILEY;
-  boolean scrolling = (mScrollX % TILEX != 0 || mScrollY % TILEY != 0);
-  int x, y;
-
-  SyncDisplay();
-
-  if (1 ||
-      redraw_tiles > REDRAWTILES_THRESHOLD || scrolling || scrolling_last)
-  {
-    BlitScreenToBitmap_SP(window);
-  }
-  else
-  {
-    for (x = 0; x < SCR_FIELDX; x++)
-    {
-      for (y = 0; y < SCR_FIELDY; y++)
-      {
-	int xx = (left + x) % MAX_BUF_XSIZE;
-	int yy = (top  + y) % MAX_BUF_YSIZE;
-
-	if (redraw[xx][yy])
-	  BlitBitmap(bitmap_db_field_sp, window,
-		     xx * TILEX, yy * TILEY, TILEX, TILEY,
-		     SX + x * TILEX, SY + y * TILEY);
-      }
-    }
-  }
-
-  FlushDisplay();
-
-  for (x = 0; x < MAX_BUF_XSIZE; x++)
-    for (y = 0; y < MAX_BUF_YSIZE; y++)
-      redraw[x][y] = FALSE;
-  redraw_tiles = 0;
-
-  scrolling_last = scrolling;
-}
-
 void DDScrollBuffer_ScrollTo(int X, int Y)
 {
   if (NoDisplayFlag)
@@ -339,12 +281,12 @@ void DDScrollBuffer_ScrollTowards(int X, int Y, double Step)
   ScrollPlayfieldIfNeeded();
 }
 
-void DDScrollBuffer_SoftScrollTo(int X, int Y, long TimeMS, int FPS)
+void DDScrollBuffer_SoftScrollTo(int X, int Y, int TimeMS, int FPS)
 {
   double dx, dY;
-  long dT, StepCount;
+  int StepCount;
   double T, tStep;
-  long oldX, oldY, maxD;
+  int oldX, oldY, maxD;
   static boolean AlreadyRunning = False;
 
   if (NoDisplayFlag)
@@ -366,7 +308,6 @@ void DDScrollBuffer_SoftScrollTo(int X, int Y, long TimeMS, int FPS)
   if (StepCount == 0)
     StepCount = 1;
 
-  dT = 1000 / FPS;
   tStep = (double)1 / StepCount;
   oldX = mScrollX;
   oldY = mScrollY;
diff --git a/src/game_sp/DDScrollBuffer.h b/src/game_sp/DDScrollBuffer.h
index e34ef21..20346b3 100644
--- a/src/game_sp/DDScrollBuffer.h
+++ b/src/game_sp/DDScrollBuffer.h
@@ -8,24 +8,16 @@
 #include "global.h"
 
 
-extern long mScrollX, mScrollY;
-extern long mScrollX_last, mScrollY_last;
-
-#if 1
-extern boolean redraw[2 + MAX_PLAYFIELD_WIDTH + 2][2 + MAX_PLAYFIELD_HEIGHT + 2];
-#else
-extern boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
-#endif
-
-extern int TEST_flag;
+extern int mScrollX, mScrollY;
+extern int mScrollX_last, mScrollY_last;
 
 
 extern void InitScrollPlayfield();
-extern void UpdatePlayfield();
+extern void UpdatePlayfield(boolean);
 extern void RestorePlayfield();
 
 extern void DDScrollBuffer_ScrollTo(int X, int Y);
 extern void DDScrollBuffer_ScrollTowards(int X, int Y, double Step);
-extern void DDScrollBuffer_SoftScrollTo(int X, int Y, long TimeMS, int FPS);
+extern void DDScrollBuffer_SoftScrollTo(int X, int Y, int TimeMS, int FPS);
 
 #endif /* DDSCROLLBUFFER_H */
diff --git a/src/game_sp/DDSpriteBuffer.c b/src/game_sp/DDSpriteBuffer.c
index 4683d31..261459a 100644
--- a/src/game_sp/DDSpriteBuffer.c
+++ b/src/game_sp/DDSpriteBuffer.c
@@ -11,9 +11,8 @@ static void Blt(int pX, int pY, Bitmap *bitmap, int SpriteX, int SpriteY)
   int scy = (mScrollY_last < 0 ? 0 : mScrollY_last);
   int sx1 = scx - 2 * TILEX;
   int sy1 = scy - 2 * TILEY;
-  int sx2 = scx + SXSIZE + 1 * TILEX;
-  int sy2 = scy + SYSIZE + 1 * TILEY;
-
+  int sx2 = scx + (SCR_FIELDX + 1) * TILEX;
+  int sy2 = scy + (SCR_FIELDY + 1) * TILEY;
   int sx = pX - sx1;
   int sy = pY - sy1;
 
@@ -24,8 +23,11 @@ static void Blt(int pX, int pY, Bitmap *bitmap, int SpriteX, int SpriteY)
   if (pX < sx1 || pX > sx2 || pY < sy1 || pY > sy2)
     return;
 
+  sx = sx * TILESIZE_VAR / TILESIZE;
+  sy = sy * TILESIZE_VAR / TILESIZE;
+
   BlitBitmap(bitmap, bitmap_db_field_sp, SpriteX, SpriteY,
-	     TILEX, TILEY, sx, sy);
+	     TILEX_VAR, TILEY_VAR, sx, sy);
 }
 
 void DDSpriteBuffer_BltImg(int pX, int pY, int graphic, int sync_frame)
diff --git a/src/game_sp/Display.c b/src/game_sp/Display.c
index d3bf853..ae9d26e 100644
--- a/src/game_sp/Display.c
+++ b/src/game_sp/Display.c
@@ -10,8 +10,8 @@ int ScreenScrollXPos, ScreenScrollYPos;
 int ExplosionShake, ExplosionShakeMurphy;
 boolean NoDisplayFlag;
 
-long DisplayMinX, DisplayMaxX;
-long DisplayMinY, DisplayMaxY;
+int DisplayMinX, DisplayMaxX;
+int DisplayMinY, DisplayMaxY;
 
 
 void subDisplayLevel()
@@ -52,7 +52,7 @@ void ScrollTowards(int X, int Y)
   DDScrollBuffer_ScrollTowards(X, Y, 2 * ZoomFactor);
 }
 
-void SoftScrollTo(int X, int Y, long TimeMS, int FPS)
+void SoftScrollTo(int X, int Y, int TimeMS, int FPS)
 {
   if (NoDisplayFlag)
     return;
diff --git a/src/game_sp/Display.h b/src/game_sp/Display.h
index bc0934f..dee7b16 100644
--- a/src/game_sp/Display.h
+++ b/src/game_sp/Display.h
@@ -13,12 +13,12 @@ extern int ScreenScrollXPos, ScreenScrollYPos;
 extern int ExplosionShake, ExplosionShakeMurphy;
 extern boolean NoDisplayFlag;
 
-extern long DisplayMinX, DisplayMaxX;
-extern long DisplayMinY, DisplayMaxY;
+extern int DisplayMinX, DisplayMaxX;
+extern int DisplayMinY, DisplayMaxY;
 
 extern void subDisplayLevel();
 extern void ScrollTo(int, int);
 extern void ScrollTowards(int, int);
-extern void SoftScrollTo(int, int, long, int);
+extern void SoftScrollTo(int, int, int, int);
 
 #endif /* DISPLAY_H */
diff --git a/src/game_sp/DoGameStuff.c b/src/game_sp/DoGameStuff.c
index 5575d11..7a7c1ac 100644
--- a/src/game_sp/DoGameStuff.c
+++ b/src/game_sp/DoGameStuff.c
@@ -8,13 +8,8 @@
 static void CallAnimation(int si, byte bl);
 static boolean IsToBeAnimated(int bl);
 
-#if 1
 int AnimationPosTable[SP_MAX_PLAYFIELD_SIZE];
 byte AnimationSubTable[SP_MAX_PLAYFIELD_SIZE];
-#else
-int *AnimationPosTable;
-byte *AnimationSubTable;
-#endif
 
 
 // ==========================================================================
@@ -25,9 +20,13 @@ byte *AnimationSubTable;
 void subDoGameStuff()
 {
   int si, cx, dx, bl;
+  int InfotronsNeeded_last = InfotronsNeeded;
 
   subAnimateMurphy(&MurphyPosIndex);       // move Murphy in any direction
 
+  if (InfotronsNeeded != InfotronsNeeded_last)
+    game.snapshot.collected_item = TRUE;
+
   // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   // Build a database of locations and subs-to-call of animatable fields only:
   // Make a snapshot from the field before the animation cycle starts.
@@ -75,19 +74,10 @@ void subDoGameStuff()
 	!game_sp.LevelSolved &&
 	!game_sp.GameOver)
     {
-#if 0
-      printf("::: DoGameStuff.c: killing murphy [%d] ...\n", KillMurphyFlag);
-#endif
-
       KillMurphyFlag = 0;			// no more "kill Murphy"
       ExplodeFieldSP(MurphyExplodePos);		// Explode
       LeadOutCounter = 0x40;			// quit: start lead-out
 
-#if 0
-      printf("::: DoGameStuff.c: !!!!!!!!!! GAME OVER !!!!!!!!!!\n");
-      printf("::: [KillMurphyFlag == %d]\n", KillMurphyFlag);
-#endif
-
       /* give Murphy some more time (LeadOutCounter) to reach the exit */
     }
   } //  loc_g_22FB:
diff --git a/src/game_sp/DoGameStuff.h b/src/game_sp/DoGameStuff.h
index 4cf9818..4fff48c 100644
--- a/src/game_sp/DoGameStuff.h
+++ b/src/game_sp/DoGameStuff.h
@@ -7,13 +7,8 @@
 
 #include "global.h"
 
-#if 1
 extern int AnimationPosTable[SP_MAX_PLAYFIELD_SIZE];
 extern byte AnimationSubTable[SP_MAX_PLAYFIELD_SIZE];
-#else
-extern byte *AnimationSubTable;
-extern int *AnimationPosTable;
-#endif
 
 extern void subDoGameStuff();
 
diff --git a/src/game_sp/Explosions.c b/src/game_sp/Explosions.c
index 4eded7b..7729d84 100644
--- a/src/game_sp/Explosions.c
+++ b/src/game_sp/Explosions.c
@@ -17,7 +17,7 @@ static void subExplodeZonk(int tsi, int cx);
 
 void subAnimateExplosion(int si)
 {
-  int ax, bl, X, Y;
+  int ax, bl;
 
   if (LowByte(PlayField16[si]) != fiExplosion)
     return;
@@ -35,8 +35,6 @@ void subAnimateExplosion(int si)
   MovHighByte(&PlayField16[si], bl);
 
   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-  X = GetStretchX(si);
-  Y = GetStretchY(si);
   GfxGraphic[GetX(si)][GetY(si)] = aniDefaultExplosion;
   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
@@ -71,8 +69,6 @@ loc_g_28D0: // explosion produces infotron
   MovHighByte(&PlayField16[si], bl);
 
   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-  X = GetStretchX(si);
-  Y = GetStretchY(si);
   GfxGraphic[GetX(si)][GetY(si)] = aniElectronExplosion;
   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 }
@@ -94,15 +90,9 @@ void ExplodeFieldSP(int si)
 
   if (ax == fiMurphy)
   {
-#if 0
-    printf("::: Explosions.c: ExplodeFieldSP(): killing murphy\n");
-#endif
-
     KillMurphyFlag = 1;
 
-#if 1
     ExplosionShakeMurphy = 30;	// Murphy explodes
-#endif
   }
 
   if (ax == fiElectron)
@@ -136,7 +126,7 @@ static void LetExplodeFieldSP(int tsi, int cx, int dh)
 {
   int al;
 
-  if (tsi < (-FieldWidth))
+  if (tsi < -FieldWidth)
     return;
 
   al = LowByte(PlayField16[tsi]);
@@ -168,11 +158,6 @@ static void LetExplodeFieldSP(int tsi, int cx, int dh)
       break;
 
     case fiMurphy:
-#if 0
-      printf("::: Explosions.c: LetExplodeFieldSP(): killing murphy [%d]\n",
-	     tsi);
-#endif
-
       KillMurphyFlag = 1;
       PlayField8[tsi] = dh;
       PlayField16[tsi] = cx;
@@ -276,15 +261,11 @@ static void subExplodeInfotron(int tsi, int cx)
 
 void subClearFieldDueToExplosion(int si)
 {
-  int X, Y;
-
   if (LowByte(PlayField16[si]) == fiExplosion)
     return;
 
   PlayField16[si] = 0;
   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-  X = GetStretchX(si);
-  Y = GetStretchY(si);
   GfxGraphic[GetX(si)][GetY(si)] = aniSpace;
   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 }
@@ -304,12 +285,7 @@ void subRedDiskReleaseExplosion()
   // +++++++++++++++++++++++++++++++++++++++++
   X = GetStretchX(si);
   Y = GetStretchY(si);
-#if 0
-  // !!! causes flicker -- fix in Murphy.c !!!
-  GfxGraphic[GetX(si)][GetY(si)] = aniRedDisk;
-#else
   DDSpriteBuffer_BltImg(X, Y, aniRedDisk, 0);
-#endif
   // +++++++++++++++++++++++++++++++++++++++++
 
   RedDiskReleasePhase = RedDiskReleasePhase + 1;
diff --git a/src/game_sp/Globals.c b/src/game_sp/Globals.c
index e34d196..44affc0 100644
--- a/src/game_sp/Globals.c
+++ b/src/game_sp/Globals.c
@@ -14,24 +14,13 @@ int FieldWidth;		// standard size = 60
 int FieldHeight;	// standard size = 24
 int HeaderSize;		// standard size = 96
 int FieldMax, LevelMax;
-long FileMax;
 
-#if 1
-int PlayField16[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE];
-byte PlayField8[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE];
-byte DisPlayField[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE];
-#else
 int *PlayField16;
 byte *PlayField8;
-byte *DisPlayField;
-#endif
+byte DisPlayField[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE];
 
 int TimerVar;
-#if 1
 short RandomSeed;
-#else
-int RandomSeed;
-#endif
 
 int FreezeZonks;
 
@@ -44,7 +33,7 @@ int MurphyPosIndex, MurphyXPos, MurphyYPos;
 int MurphyScreenXPos, MurphyScreenYPos;
 int MurphyExplodePos, SplitMoveFlag, RedDiskReleaseMurphyPos;
 int KillMurphyFlag, MurphyMoveCounter;
-long YawnSleepCounter;
+int YawnSleepCounter;
 int MurphyVarFaceLeft;
 int ScratchGravity, GravityFlag;
 int RedDiskReleaseFlag, MovingPictureSequencePhase;
@@ -164,6 +153,8 @@ boolean isSnappingSequence(int sequence)
 
 void InitGlobals()
 {
+  InitPrecedingPlayfieldMemory();
+
   AutoScrollFlag = True;
   FreezeZonks = 0;
   LevelLoaded = False;
@@ -175,16 +166,17 @@ void InitGlobals()
   bPlaying = False;
   menBorder = False;
 
-#if 0
-  /* these defaults will be changed after reading a Supaplex level file */
-  PlayField8 = REDIM_1D(sizeof(byte), 0, FieldMax);
-  DisPlayField = REDIM_1D(sizeof(byte), 0, FieldMax);
-  PlayField16 = REDIM_1D(sizeof(int), 0, FieldMax);
-
-  AnimationPosTable = REDIM_1D(sizeof(int), 0, LevelMax);
-  AnimationSubTable = REDIM_1D(sizeof(byte), 0, LevelMax);
-  TerminalState = REDIM_1D(sizeof(byte), 0, FieldMax);
-#endif
+  /* add preceding playfield buffer (as large as preceding memory area) */
+  PlayField16 = checked_calloc((game_sp.preceding_buffer_size +
+				SP_MAX_PLAYFIELD_SIZE +
+				SP_HEADER_SIZE) * sizeof(int));
+  PlayField16 = &PlayField16[game_sp.preceding_buffer_size];
+
+  /* add preceding playfield buffer (as large as one playfield row) */
+  PlayField8 = checked_calloc((SP_MAX_PLAYFIELD_WIDTH +
+			       SP_MAX_PLAYFIELD_SIZE +
+			       SP_HEADER_SIZE) * sizeof(byte));
+  PlayField8 = &PlayField8[SP_MAX_PLAYFIELD_WIDTH];
 }
 
 int GetSI(int X, int Y)
@@ -216,26 +208,12 @@ void PrepareLevel()
 {
   copyInternalEngineVars_SP();
 
-#if 1
   SetDisplayRegion();
   SetScrollEdges();
-#endif
 
   LevelLoaded = True;
 }
 
-#if 0
-void Trace(char *Source, char *Message)
-{
-  printf("::: Trace: Source == '%s', Message == '%s'\n", Source, Message);
-}
-
-void ReportError(char *Source, char *Message)
-{
-  printf("::: ReportError: Source == '%s', Message == '%s'\n", Source, Message);
-}
-#endif
-
 int Min(int A, int B)
 {
   return (A < B ? A : B);
diff --git a/src/game_sp/Globals.h b/src/game_sp/Globals.h
index 05d4cd7..5923bad 100644
--- a/src/game_sp/Globals.h
+++ b/src/game_sp/Globals.h
@@ -13,7 +13,7 @@
 #define True				(!False)
 #endif
 
-#define ScrollDelta			((long)1)
+#define ScrollDelta			((int)1)
 
 #define ZoomFactor			(2)
 
@@ -224,8 +224,8 @@ typedef struct
 {
   int Width;
   int Height;
-  long OffSet;
-  long Size;
+  int OffSet;
+  int Size;
 } LevelDescriptor;
 #define HAS_LevelDescriptor
 #endif
@@ -277,11 +277,6 @@ extern void PrepareLevel();
 extern int getSequenceLength(int sequence);
 extern boolean isSnappingSequence(int sequence);
 
-#if 0
-extern void Trace(char *Source, char *Message);
-extern void ReportError(char *Source, char *Message);
-#endif
-
 extern int Min(int A, int B);
 extern int Max(int A, int B);
 
@@ -294,15 +289,9 @@ extern boolean LevelLoaded;
 extern boolean DemoAvailable;
 extern boolean menBorder;
 
-#if 1
-extern int PlayField16[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE];
-extern byte PlayField8[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE];
-extern byte DisPlayField[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE];
-#else
 extern int *PlayField16;
 extern byte *PlayField8;
-extern byte *DisPlayField;
-#endif
+extern byte DisPlayField[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE];
 
 extern int FieldHeight;
 extern int FieldMax, LevelMax;
@@ -312,8 +301,6 @@ extern int HeaderSize;
 extern int TimerVar;
 extern short RandomSeed;
 
-extern long FileMax;
-
 extern LevelInfoType LInfo;
 extern int ScrollMinX, ScrollMaxX, ScrollMinY, ScrollMaxY;
 extern int ScrollX, ScrollY;
@@ -334,6 +321,6 @@ extern int RedDiskReleasePhase;
 extern int ScratchGravity, GravityFlag;
 extern int SnikSnaksElectronsFrozen;
 extern int YellowDisksExploded;
-extern long YawnSleepCounter;
+extern int YawnSleepCounter;
 
 #endif /* GLOBALS_H */
diff --git a/src/game_sp/Infotrons.c b/src/game_sp/Infotrons.c
index c671c60..ecf29af 100644
--- a/src/game_sp/Infotrons.c
+++ b/src/game_sp/Infotrons.c
@@ -164,19 +164,8 @@ loc_g_1242: // infotron comes falling from above
   if (ax == fiOrangeDisk) // orange disk hit
     goto loc_g_1386;
 
-#if 1
-
-#if 1
   // play the infotron sound, 'cause infotron hits something "hard"
   subSoundFX(si, fiInfotron, actImpact);
-#else
- // play the zonk sound, 'cause zonk hits something "hard"
-  subSoundFX(si, fiZonk, actImpact);
-#endif
-
-#else
-  subSoundFXZonk(); // play the zonk sound,'cause zonk hits something "hard"
-#endif
 
   if (! (ax == fiZonk || ax == fiInfotron || ax == fiRAM))
     return;
diff --git a/src/game_sp/MainForm.c b/src/game_sp/MainForm.c
index c54bf63..b6d7952 100644
--- a/src/game_sp/MainForm.c
+++ b/src/game_sp/MainForm.c
@@ -17,10 +17,8 @@ void DrawFrameIfNeeded()
   DrawFrame(0);
 
   /* !!! CHECK THIS !!! */
-#if 1
   if (! menBorder)
     DrawFrame(1);
-#endif
 }
 
 void DisplayLevel()
@@ -31,16 +29,9 @@ void DisplayLevel()
     return;
 
   ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
-#if 1
   ClearRectangle(bitmap_db_field_sp, 0, 0, FXSIZE, FYSIZE);
-#else
-  ClearRectangle(bitmap_db_field_sp, 0, 0,
-		 MAX_BUF_XSIZE * TILEX, MAX_BUF_YSIZE * TILEY);
-#endif
 
-#if 1
   SetDisplayRegion();
-#endif
 
   DrawFrameIfNeeded();
 
@@ -157,14 +148,6 @@ void menPlay_Click()
   ReStretch();
 
   subMainGameLoop_Init();
-
-#if 1
-  return;
-#endif
-
-  bPlaying = False;
-
-  subFetchAndInitLevel();
 }
 
 static void ReStretch()
@@ -193,8 +176,8 @@ void SetScrollEdges()
   /* scroll correction for border frame (1 tile) or border element (2 tiles) */
   ScrollMinX = 0;
   ScrollMinY = 0;
-  ScrollMaxX = (DisplayMaxX + border1_offset) * TILEX - SXSIZE;
-  ScrollMaxY = (DisplayMaxY + border1_offset) * TILEY - SYSIZE;
+  ScrollMaxX = (DisplayMaxX + border1_offset - SCR_FIELDX) * TILEX;
+  ScrollMaxY = (DisplayMaxY + border1_offset - SCR_FIELDY) * TILEY;
 
   /* scroll correction for border element (half tile on left and right side) */
   ScrollMinX += border2_offset;
@@ -207,12 +190,6 @@ void SetScrollEdges()
   ScrollMaxX -= game_sp.scroll_xoffset;
   ScrollMinY -= game_sp.scroll_yoffset;
   ScrollMaxY -= game_sp.scroll_yoffset;
-
-#if 0
-  printf("::: (%ld, %ld), (%ld, %ld) -> (%d, %d), (%d, %d)\n",
-	 DisplayMinX, DisplayMinY, DisplayMaxX, DisplayMaxY,
-	 ScrollMinX, ScrollMinY, ScrollMaxX, ScrollMaxY);
-#endif
 }
 
 void DrawField(int X, int Y)
@@ -273,25 +250,7 @@ void DrawFieldNoAnimated(int X, int Y)
       break;
 
     default:
-#if 1
       DrawField(X, Y);
-#else
-      if (Tmp < fiFirst || Tmp > fiLast)
-	Tmp = fiSpace;
-
-      if (Tmp == fiRAM ||
-	  Tmp == fiHardWare ||
-	  Tmp == fiBug ||
-	  Tmp == fiWallSpace)
-	Tmp = DisPlayField[tsi];
-
-      subCopyImageToScreen(tsi, fiGraphic[Tmp]);
-
-      if (Tmp != fiSpace &&
-	  Tmp != fiSnikSnak &&
-	  Tmp != fiElectron)
-	GfxGraphic[X][Y] = fiGraphic[Tmp];
-#endif
       break;
   }
 }
diff --git a/src/game_sp/MainGameLoop.c b/src/game_sp/MainGameLoop.c
index 48a1ac4..61d5ed1 100644
--- a/src/game_sp/MainGameLoop.c
+++ b/src/game_sp/MainGameLoop.c
@@ -51,24 +51,13 @@ void subMainGameLoop_Main(byte action, boolean warp_mode)
 
   TimerVar = TimerVar + 1;
 
-#if 1
   if (ExplosionShakeMurphy > 0)
     ExplosionShakeMurphy--;
-#endif
 
-#if 1
   if (ExitToMenuFlag == 1)
   {
     // happens when demo ends or when Murphy enters exit (to be checked)
-
-#if 0
-    goto locExitMainGameLoop;
-#endif
   }
-#else
-  if (ExitToMenuFlag == 1)
-    goto locExitMainGameLoop;
-#endif
 
   if (LeadOutCounter == 0) // no lead-out: game busy
     return;
@@ -85,25 +74,13 @@ void subMainGameLoop_Main(byte action, boolean warp_mode)
   // lead-out done: exit now
   // ---------------------- END OF GAME-BUSY LOOP (including lead-out) ---------
 
-#if 0
-locExitMainGameLoop:
-#endif
-
-#if 0
-  printf("::: locExitMainGameLoop reached [%d]\n", LeadOutCounter);
-  printf("::: [KillMurphyFlag == %d]\n", KillMurphyFlag);
-#endif
-
-#if 1
   /* if the game is not won when reaching this point, then it is lost */
   if (!game_sp.LevelSolved)
     game_sp.GameOver = TRUE;
-#endif
 }
 
 void subCalculateScreenScrollPos()
 {
-#if 1
   int jump_pos = TILEX / 2;
 
   /* handle wrap-around */
@@ -117,7 +94,6 @@ void subCalculateScreenScrollPos()
     MurphyScreenXPos = MurphyScreenXPos - FieldWidth * TILEX;
     MurphyScreenYPos += TILEY;
   }
-#endif
 
   if (ExplosionShake != 0)
   {
diff --git a/src/game_sp/Makefile b/src/game_sp/Makefile
index d1d9ffc..ae7c37f 100644
--- a/src/game_sp/Makefile
+++ b/src/game_sp/Makefile
@@ -1,11 +1,17 @@
 # =============================================================================
-# Makefile for native Supaplex engine for Rocks'n'Diamonds (game_sp)
+# Rocks'n'Diamonds - McDuffin Strikes Back!
 # -----------------------------------------------------------------------------
-# (c) 1995-2009 Holger Schemel <info at artsoft.org>
+# (c) 1995-2014 by Artsoft Entertainment
+#                  Holger Schemel
+#                  info at artsoft.org
+#                  http://www.artsoft.org/
 # -----------------------------------------------------------------------------
-# based on MegaPlex version 0.5 beta release xmas 2001 by Frank Schindler,
-# based on the Speed Fix 6.3+ by Herman Perk,
-# based on original Supaplex by Michael Stopp & Philip Jespersen
+# The native Supaplex game engine is based on:
+# - MegaPlex version 0.5 beta release xmas 2001 by Frank Schindler
+# - Speed Fix 6.3+ by Herman Perk
+# - Supaplex by Michael Stopp & Philip Jespersen
+# -----------------------------------------------------------------------------
+# src/game_sp/Makefile
 # =============================================================================
 
 # -----------------------------------------------------------------------------
diff --git a/src/game_sp/Murphy.c b/src/game_sp/Murphy.c
index 06cd9f7..bf590db 100644
--- a/src/game_sp/Murphy.c
+++ b/src/game_sp/Murphy.c
@@ -8,18 +8,9 @@
 static void subEatRedDisk(int si);
 static boolean subMoveKillsMurphy(int si, int ax, int bl);
 
-#if 1
-
 #define LocalStretch 			(2)
 #define MurphyZoomFactor		(ZoomFactor)
 
-#else
-
-#define LocalStretch 			(1)
-#define MurphyZoomFactor		(1)
-
-#endif
-
 // ==========================================================================
 //                              SUBROUTINE
 // Move Murphy in any direction
@@ -92,14 +83,6 @@ void subAnimateMurphy(int *si)
     goto loc_g_6364;
   }
 
-#if 1
-
-#if 0
-  ax = (TimerVar & 3);
-  if (ax != 0)
-    return;
-#endif
-
   // ------------------------------------------------------------------
   // Murphy's YAWN & SLEEP sequence, counted down by YawnSleepCounter:
 
@@ -180,79 +163,6 @@ void subAnimateMurphy(int *si)
 
   // end of YAWN-SLEEP-Sequence
 
-#else
-
-  ax = (TimerVar & 3);
-  if (ax != 0)
-    return;
-
-  // ------------------------------------------------------------------
-  // Murphy's YAWN & SLEEP sequence, counted down by YawnSleepCounter:
-  YawnSleepCounter = YawnSleepCounter + 1;
-  if (YawnSleepCounter == 4)
-  {
-    subCopyFieldToScreen(*si, fiMurphy); // normal grin
-    return;
-  } // loc_g_5ECE:
-
-  if (YawnSleepCounter <= 500) // loc_g_5ED7:
-    return;
-
-  if (YawnSleepCounter <= 522)
-  {
-    bx = (YawnSleepCounter - 500) / 2;
-    subCopyFieldToScreen(*si, aniMurphyYawn + bx); // yawn! and look depressed afterwards...
-    return;
-  } // loc_g_5F00:
-
-  if (YawnSleepCounter <= 1000)
-    return;
-
-  if (YawnSleepCounter <= 1022)
-  {
-    bx = (YawnSleepCounter - 1000) / 2;
-    subCopyFieldToScreen(*si, aniMurphyYawn + bx); // yawn again!
-    return;
-  } // loc_g_5F32:
-
-  if (YawnSleepCounter <= 1600) // loc_g_5F3B:
-    return;
-
-  if (YawnSleepCounter <= 1622)
-  {
-    bx = (YawnSleepCounter - 1600) / 2;
-    subCopyFieldToScreen(*si, aniMurphyYawn + bx); // yawn again! - third time
-    return;
-  } // loc_g_5F64:
-
-  if (YawnSleepCounter > 1654)
-    return;
-
-  if (PlayField16[*si - 1] == 0)
-  {
-    if (PlayField16[*si + 1] == 0)
-    {
-      YawnSleepCounter = 36;
-      return;
-
-    }
-    else
-    {
-      bx = (YawnSleepCounter - 1622) / 16;
-      subCopyFieldToScreen(*si, aniMurphySleepRight + bx); // go to sleep
-      return;
-    }
-  } // loc_g_5F81:
-
-  bx = (YawnSleepCounter - 1622) / 16;
-  subCopyFieldToScreen(*si, aniMurphySleepLeft + bx); // go to sleep
-
-  return;
-
-  // end of YAWN-SLEEP-Sequence
-
-#endif
-
   // ------------------------------------------------------------------
   // ==========================================================================
   //                       (Direct Jump) a key was pressed
@@ -940,11 +850,6 @@ loc_g_65FE:
   subSoundFX(*si, fiInfotron, actCollecting);
 
   dx1 = aniEatInfotronLeft;
-#if 0
-  dx2 = fiInfotron;
-  dx2Step = -1;
-  ClearPos = -1;
-#endif
   PlayField16[*si - 1] = 0xA03;
   PlayField16[*si] = 0x300;
   *si = *si - 1;
@@ -971,11 +876,6 @@ loc_g_6662:
   subSoundFX(*si, fiInfotron, actCollecting);
 
   dx1 = aniEatInfotronRight;
-#if 0
-  dx2 = fiInfotron;
-  dx2Step = 1;
-  ClearPos = -1;
-#endif
   PlayField16[*si + 1] = 0xC03;
   PlayField16[*si] = 0x300;
   *si = *si + 1;
@@ -1046,14 +946,7 @@ loc_g_6756:
   if (LowByte(InfotronsNeeded) != 0)
     return;
 
-#if 0
-  if (!game_sp.LevelSolved)
-    printf("::: Murphy.c: !!!!!!!!!! LEVEL %d SOLVED !!!!!!!!!!\n", level_nr);
-#endif
-
-#if 1
   game_sp.LevelSolved = TRUE;
-#endif
 
   subSoundFX(*si, fiExit, actPassing);
 
@@ -1115,16 +1008,8 @@ loc_g_6817:
     return;
   } // loc_g_6838:
 
-#if 1
   // draw new terminal type
-#if 1
   GfxGraphic[GetX(*si - FieldWidth)][GetY(*si - FieldWidth)] = aniTerminalActive;
-#else
-  subCopyImageToScreen(*si - FieldWidth, aniTerminalActive);
-#endif
-#else
-  subCopyFieldToScreen(*si - FieldWidth, 0x88); // draw new terminal type
-#endif
   TerminalState[*si - FieldWidth] = 8;
   goto loc_g_68F0;
 
@@ -1141,16 +1026,8 @@ loc_g_684E:
     return;
   } // loc_g_6838:
 
-#if 1
   // draw new terminal type
-#if 1
   GfxGraphic[GetX(*si - 1)][GetY(*si - 1)] = aniTerminalActive;
-#else
-  subCopyImageToScreen(*si - 1, aniTerminalActive);
-#endif
-#else
-  subCopyFieldToScreen(*si - 1, 0x88); // draw new terminal type
-#endif
   TerminalState[*si - 1] = 8;
   goto loc_g_68F0;
 
@@ -1167,16 +1044,8 @@ loc_g_6884:
     return;
   } // loc_g_6838:
 
-#if 1
   // draw new terminal type
-#if 1
   GfxGraphic[GetX(*si + FieldWidth)][GetY(*si + FieldWidth)] = aniTerminalActive;
-#else
-  subCopyImageToScreen(*si + FieldWidth, aniTerminalActive);
-#endif
-#else
-  subCopyFieldToScreen(*si + FieldWidth, 0x88); // draw new terminal type
-#endif
   TerminalState[*si + FieldWidth] = 8;
   goto loc_g_68F0;
 
@@ -1193,16 +1062,8 @@ loc_g_68BA:
     return;
   } // loc_g_6838:
 
-#if 1
   // draw new terminal type
-#if 1
   GfxGraphic[GetX(*si + 1)][GetY(*si + 1)] = aniTerminalActive;
-#else
-  subCopyImageToScreen(*si + 1, aniTerminalActive);
-#endif
-#else
-  subCopyFieldToScreen(*si + 1, 0x88); // draw new terminal type
-#endif
   TerminalState[*si + 1] = 8;
   // ==========================================================================
   // common TERMINAL stuff moving/touching from all directions
@@ -1575,10 +1436,8 @@ locProceedMovingMurphy: // proceed moving murphy
 
 loc_g_6C8F:
 
-#if 1
   if (SeqPos <= 0)
     dx1SequenceLength = getSequenceLength(dx1);
-#endif
 
   if (SplitMoveFlag == 0)
   {
@@ -1590,55 +1449,28 @@ loc_g_6C8F:
     if (!(ClearPos < 0)) // clear field that murphy is leaving
       subCopyImageToScreen(ClearPos, aniSpace);
 
-#if 0
-    // !!! special two-tile animation currently not used !!!
-    if (dx2 == fiInfotron) // special case of infotron moving left or right
-    {
-      tDeltaX = 0;
-      tDeltaY = 0;
-    }
-    else
-#endif
-    {
-      tDeltaX = MurphyDX * LocalStretch * (SeqPos + 1);
-      tDeltaY = MurphyDY * LocalStretch * (SeqPos + 1);
-    }
+    tDeltaX = MurphyDX * LocalStretch * (SeqPos + 1);
+    tDeltaY = MurphyDY * LocalStretch * (SeqPos + 1);
 
     X = GetStretchX(dxPos) + tDeltaX;
     Y = GetStretchY(dxPos) + tDeltaY;
     Tmp = (SeqPos < 0 ? 0 : SeqPos); // 9StepBugFix!(red disk move right)
 
-#if 1
     if (isSnappingSequence(dx1) && SeqPos == dx1SequenceLength - 1)
       dx1 = aniSpace;
-#endif
 
-#if 1
     DDSpriteBuffer_BltImg(X, Y, dx1, Tmp);
     GfxGraphic[GetX(*si)][GetY(*si)] = -1;	// (Murphy's position)
     GfxGraphic[GetX(dxPos)][GetY(dxPos)] = -1;	// (snapping position)
-    // printf("::: Tmp: %d\n", Tmp);
-#else
-    StretchedSprites.BltEx(X, Y, dx[Tmp]);
-#endif
 
     if (!(dx2 < 0))
     {
       tPos = dxPos + dx2Step;
       X = GetStretchX(tPos);
       Y = GetStretchY(tPos);
-#if 0
-    // !!! special two-tile animation currently not used !!!
-      if (dx2 == fiInfotron) // special case of infotron moving left or right
-      {
-        StretchedSprites.BltEx(X, Y, dx[SeqPos] + dx2Step);
-      }
-      else // pushing something
-#endif
-      {
-	// (SeqPos iterates from 0 to 7 while pushing)
-        DDSpriteBuffer_BltImg(X + tDeltaX, Y + tDeltaY, dx2, SeqPos);
-      }
+
+      // (SeqPos iterates from 0 to 7 while pushing)
+      DDSpriteBuffer_BltImg(X + tDeltaX, Y + tDeltaY, dx2, SeqPos);
     }
 
     // End of normal movement
@@ -1667,13 +1499,8 @@ loc_g_6C8F:
   } // loc_g_6D1E:'loc_g_6D28:
 
   SeqPos = SeqPos + 1;
-#if 1
   if (SeqPos < dx1SequenceLength)
     return;
-#else
-  if (dx[SeqPos] > -1)
-    return;
-#endif
 
   // Follow-up after movement completed     'loc_g_6D35:
   MurphyXPos = MurphyXPos + MurphyDX;
@@ -1962,9 +1789,7 @@ loc_g_6F3B:
 loc_g_6F77:
   ExitToMenuFlag = 1;
 
-#if 1
   PlayField16[*si] = fiSpace;	// remove Murphy from playfield after exiting
-#endif
 
   return;
 
diff --git a/src/game_sp/SnikSnaks.c b/src/game_sp/SnikSnaks.c
index e23dc90..a03e332 100644
--- a/src/game_sp/SnikSnaks.c
+++ b/src/game_sp/SnikSnaks.c
@@ -33,11 +33,9 @@ void subAnimateSnikSnaks(int si)
   if (SnikSnaksElectronsFrozen == 1)
     return;
 
-#if 1
   /* (not sure why this was removed -- this broke several level solutions) */
   if (LowByte(PlayField16[si]) != fiSnikSnak)
     return;
-#endif
 
   // If LowByte(PlayField16(si)) <> fiSnikSnak Then Exit Function
   // Debug.Assert (LowByte(PlayField16[si]) == fiSnikSnak);
diff --git a/src/game_sp/Zonk.c b/src/game_sp/Zonk.c
index d828534..785b9c4 100644
--- a/src/game_sp/Zonk.c
+++ b/src/game_sp/Zonk.c
@@ -181,12 +181,8 @@ loc_g_0DE8: // zonk comes falling from above
   if (ax == fiOrangeDisk) // OrangeDisk explodes 'loc_g_0E95:
     goto loc_g_0F75;
 
-#if 1
   // play the zonk sound, 'cause zonk hits something "hard"
   subSoundFX(si, fiZonk, actImpact);
-#else
-  subSoundFXZonk(); // play the zonk sound,'cause zonk hits something "hard"
-#endif
 
   if (! (ax == fiZonk || ax == fiInfotron || ax == fiRAM))
     return;
diff --git a/src/game_sp/export.h b/src/game_sp/export.h
index fe5995f..4edac47 100644
--- a/src/game_sp/export.h
+++ b/src/game_sp/export.h
@@ -26,11 +26,6 @@
 					 SP_MAX_PLAYFIELD_HEIGHT)
 #define SP_STD_LEVEL_SIZE		(SP_HEADER_SIZE + SP_STD_PLAYFIELD_SIZE)
 
-#if 0
-#define SP_SCREEN_BUFFER_XSIZE		(SCR_FIELDX + 2)
-#define SP_SCREEN_BUFFER_YSIZE		(SCR_FIELDY + 2)
-#endif
-
 #define SP_FRAMES_PER_SECOND		35
 #define SP_MAX_TAPE_LEN			64010	/* (see "spfix63.doc") */
 
@@ -55,11 +50,7 @@
 #ifndef HAS_SpecialPortType
 typedef struct
 {
-#if 1
   short PortLocation; // = 2*(x+(y*60))		/* big endian format */
-#else
-  int PortLocation; // = 2*(x+(y*60))
-#endif
   byte Gravity; // 1 = turn on, anything else (0) = turn off
   byte FreezeZonks; // 2 = turn on, anything else (0) = turn off  (1=off!)
   byte FreezeEnemies; // 1 = turn on, anything else (0) = turn off
@@ -85,11 +76,7 @@ typedef struct
   SpecialPortType SpecialPort[10];
   byte SpeedByte; // = Speed XOR Highbyte(RandomSeed)
   byte CheckSumByte; // = CheckSum XOR SpeedByte
-#if 1
   short DemoRandomSeed;				/* little endian format */
-#else
-  int DemoRandomSeed;
-#endif
 } LevelInfoType;
 #define HAS_LevelInfoType
 #endif
@@ -110,6 +97,7 @@ struct GameInfo_SP
   int score;
 
   /* needed for engine snapshots */
+  char **preceding_buffer;
   int preceding_buffer_size;
 
   int scroll_xoffset, scroll_yoffset;
@@ -186,27 +174,31 @@ extern struct EngineSnapshotInfo_SP engine_snapshot_sp;
 extern void sp_open_all();
 extern void sp_close_all();
 
+extern void InitPrecedingPlayfieldMemory();
 extern void InitGfxBuffers_SP();
 
 extern void InitGameEngine_SP();
 extern void GameActions_SP(byte *, boolean);
 
-extern unsigned int InitEngineRandom_SP(long);
+extern unsigned int InitEngineRandom_SP(int);
 
 extern void setLevelInfoToDefaults_SP();
 extern void copyInternalEngineVars_SP();
-extern boolean LoadNativeLevel_SP(char *, int);
+extern boolean LoadNativeLevel_SP(char *, int, boolean);
 extern void SaveNativeLevel_SP(char *);
 
-extern void BackToFront_SP(void);
+extern int getFieldbufferOffsetX_SP();
+extern int getFieldbufferOffsetY_SP();
+
 extern void BlitScreenToBitmap_SP(Bitmap *);
 extern void RedrawPlayfield_SP(boolean);
-extern void DrawGameDoorValues_SP();
 
 extern void LoadEngineSnapshotValues_SP();
-extern void SaveEngineSnapshotValues_SP();
+extern void SaveEngineSnapshotValues_SP(ListNode **);
 
 extern int map_key_RND_to_SP(int);
 extern int map_key_SP_to_RND(int);
 
+extern int getRedDiskReleaseFlag_SP();
+
 #endif	/* GAME_SP_EXPORT_H */
diff --git a/src/game_sp/file.c b/src/game_sp/file.c
index f841cf2..a38c806 100644
--- a/src/game_sp/file.c
+++ b/src/game_sp/file.c
@@ -60,64 +60,9 @@ void setLevelInfoToDefaults_SP()
 
 void copyInternalEngineVars_SP()
 {
-  char *preceding_playfield_memory[] =
-  {
-    "95 89 95 89 95 89 3b 8a  3b 8a 3b 8a 3b 8a 3b 8a",	// |......;.;.;.;.;.|
-    "3b 8a 3b 8a 3b 8a e8 8a  e8 8a e8 8a e8 8a e8 8a",	// |;.;.;.�.�.�.�.�.|
-    "e8 8a e8 8a e8 8a b1 8b  b1 8b b1 8b b1 8b b1 8b",	// |�.�.�.�.�.�.�.�.|
-    "b1 8b b1 8b b1 8b 85 8c  85 8c 85 8c 85 8c 85 8c",	// |�.�.�...........|
-    "85 8c 85 8c 85 8c 5b 8d  5b 8d 5b 8d 5b 8d 5b 8d",	// |......[.[.[.[.[.|
-    "5b 8d 5b 8d 5b 8d 06 8e  06 8e 06 8e 06 8e 06 8e",	// |[.[.[...........|
-    "06 8e 06 8e 06 8e ac 8e  ac 8e ac 8e ac 8e ac 8e",	// |......�.�.�.�.�.|
-    "ac 8e ac 8e ac 8e 59 8f  59 8f 59 8f 59 8f 59 8f",	// |�.�.�.Y.Y.Y.Y.Y.|
-    "59 8f 59 8f 59 8f 00 00  70 13 00 00 00 00 e8 17",	// |Y.Y.Y...p.....�.|
-    "00 00 00 00 00 00 69 38  00 00 00 00 00 00 00 00",	// |......i8........|
-    "00 00 00 00 00 00 00 00  d0 86 00 00 b2 34 00 00",	// |........�...�4..|
-    "00 00 00 00 00 00 8f 8b  1d 34 00 00 00 00 00 00",	// |.........4......|
-    "00 00 00 00 23 39 09 09  00 0c 00 08 00 58 00 00",	// |....#9.......X..|
-    "00 00 00 25 77 06 7f 00  00 00 01 00 00 00 00 00",	// |...%w...........|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 ec 06 26 05 00 00 00",	// |.........�.&....|
-    "00 00 00 01 00 00 00 00  31 32 33 34 35 36 37 38",	// |........12345678|
-    "39 30 2d 00 08 00 51 57  45 52 54 59 55 49 4f 50",	// |90-...QWERTYUIOP|
-    "00 00 0a 00 41 53 44 46  47 48 4a 4b 4c 00 00 00",	// |....ASDFGHJKL...|
-    "00 00 5a 58 43 56 42 4e  4d 00 00 00 00 00 00 20",	// |..ZXCVBNM...... |
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 2e 00  1e 00 31 00 14 00 39 00",	// |..........1...9.|
-    "1f 00 14 00 18 00 ff ff  01 00 01 4c 45 56 45 4c",	// |......��...LEVEL|
-    "53 2e 44 41 54 00 00 00  00 00 00 00 00 00 00 00",	// |S.DAT...........|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
-
-    NULL
-  };
-  int preceding_buffer_size = 0;
   int count;
   int i, x, y;
 
-  for (i = 0; preceding_playfield_memory[i] != NULL; i++)
-    preceding_buffer_size += 8;		/* eight 16-bit integer values */
-
-  /* needed for engine snapshots */
-  game_sp.preceding_buffer_size = preceding_buffer_size;
-
   LInfo = native_sp_level.header;
 
   FieldWidth  = native_sp_level.width;
@@ -127,19 +72,18 @@ void copyInternalEngineVars_SP()
   FieldMax = (FieldWidth * FieldHeight) + HeaderSize - 1;
   LevelMax = (FieldWidth * FieldHeight) - 1;
 
-  /* (add one byte for the level number stored as first byte of demo data) */
-  FileMax = FieldMax + native_sp_level.demo.length + 1;
+  /* initialize preceding playfield buffer */
+  for (i = -game_sp.preceding_buffer_size; i < 0; i++)
+    PlayField16[i] = 0;
 
-#if 0
-  PlayField8 = REDIM_1D(sizeof(byte), 0, FileMax);
-  DisPlayField = REDIM_1D(sizeof(byte), 0, FieldMax);
-  PlayField16 = REDIM_1D(sizeof(int), -preceding_buffer_size, FieldMax);
-#endif
+  /* initialize preceding playfield buffer */
+  for (i = -SP_MAX_PLAYFIELD_WIDTH; i < 0; i++)
+    PlayField8[i] = 0;
 
   count = 0;
-  for (i = 0; preceding_playfield_memory[i] != NULL; i++)
+  for (i = 0; game_sp.preceding_buffer[i] != NULL; i++)
   {
-    char *s = preceding_playfield_memory[i];
+    char *s = game_sp.preceding_buffer[i];
     boolean hi_byte = FALSE;	/* little endian data => start with low byte */
 
     while (s[0] != '\0' && s[1] != '\0')
@@ -151,7 +95,7 @@ void copyInternalEngineVars_SP()
       if (hi_byte)
 	byte <<= 8;
 
-      PlayField16[-preceding_buffer_size + count] |= byte;
+      PlayField16[-game_sp.preceding_buffer_size + count] |= byte;
 
       if (hi_byte)
 	count++;
@@ -182,38 +126,17 @@ void copyInternalEngineVars_SP()
   }
 
   if (native_sp_level.demo.is_available)
-  {
     DemoAvailable = True;
 
-#if 0
-    /* !!! NEVER USED !!! */
-    PlayField8[FieldMax + 1] = native_sp_level.demo.level_nr;
-
-    /* !!! NEVER USED !!! */
-    for (i = 0; i < native_sp_level.demo.length; i++)
-      PlayField8[FieldMax + 2 + i] = native_sp_level.demo.data[i];
-#endif
-  }
-
-#if 0
-  AnimationPosTable = REDIM_1D(sizeof(int), 0, LevelMax - 2 * FieldWidth);
-  AnimationSubTable = REDIM_1D(sizeof(byte), 0, LevelMax - 2 * FieldWidth);
-  TerminalState = REDIM_1D(sizeof(byte), 0, FieldMax);
-#endif
-
   GravityFlag = LInfo.InitialGravity;
   FreezeZonks = LInfo.InitialFreezeZonks;
 
-#if 1
-  /* this is set by main game tape code to native random generator directly */
-#else
-  RandomSeed = LInfo.DemoRandomSeed;
-#endif
-
   LevelLoaded = True;
+
+  /* random seed set by main game tape code to native random generator seed */
 }
 
-static void LoadNativeLevelFromFileStream_SP(FILE *file, int width, int height,
+static void LoadNativeLevelFromFileStream_SP(File *file, int width, int height,
 					     boolean demo_available)
 {
   LevelInfoType *header = &native_sp_level.header;
@@ -310,9 +233,9 @@ static void LoadNativeLevelFromFileStream_SP(FILE *file, int width, int height,
 
   /* read raw level header bytes (96 bytes) */
 
-  fseek(file, -(SP_HEADER_SIZE), SEEK_CUR);	/* rewind file */
+  seekFile(file, -(SP_HEADER_SIZE), SEEK_CUR);	/* rewind file */
   for (i = 0; i < SP_HEADER_SIZE; i++)
-    native_sp_level.header_raw_bytes[i] = fgetc(file);
+    native_sp_level.header_raw_bytes[i] = getByteFromFile(file);
 
   /* also load demo tape, if available (only in single level files) */
 
@@ -326,7 +249,7 @@ static void LoadNativeLevelFromFileStream_SP(FILE *file, int width, int height,
 
     native_sp_level.demo.level_nr = level_nr;
 
-    for (i = 0; i < SP_MAX_TAPE_LEN && !feof(file); i++)
+    for (i = 0; i < SP_MAX_TAPE_LEN && !checkEndOfFile(file); i++)
     {
       native_sp_level.demo.data[i] = getFile8Bit(file);
 
@@ -343,9 +266,10 @@ static void LoadNativeLevelFromFileStream_SP(FILE *file, int width, int height,
   }
 }
 
-boolean LoadNativeLevel_SP(char *filename, int level_pos)
+boolean LoadNativeLevel_SP(char *filename, int level_pos,
+			   boolean level_info_only)
 {
-  FILE *file;
+  File *file;
   int i, l, x, y;
   char name_first, name_last;
   struct LevelInfo_SP multipart_level;
@@ -367,9 +291,10 @@ boolean LoadNativeLevel_SP(char *filename, int level_pos)
   setLevelInfoToDefaults_SP();
   copyInternalEngineVars_SP();
 
-  if (!(file = fopen(filename, MODE_READ)))
+  if (!(file = openFile(filename, MODE_READ)))
   {
-    Error(ERR_WARN, "cannot open file '%s' -- using empty level", filename);
+    if (!level_info_only)
+      Error(ERR_WARN, "cannot open file '%s' -- using empty level", filename);
 
     return FALSE;
   }
@@ -438,7 +363,7 @@ boolean LoadNativeLevel_SP(char *filename, int level_pos)
   }
 
   /* position file stream to the requested level (in case of level package) */
-  if (fseek(file, file_seek_pos, SEEK_SET) != 0)
+  if (seekFile(file, file_seek_pos, SEEK_SET) != 0)
   {
     Error(ERR_WARN, "cannot fseek in file '%s' -- using empty level", filename);
 
@@ -549,11 +474,6 @@ boolean LoadNativeLevel_SP(char *filename, int level_pos)
     multipart_xpos = (int)(name_first - '0');
     multipart_ypos = (int)(name_last  - '0');
 
-#if 0
-    printf("----------> part (%d/%d) of multi-part level '%s'\n",
-	   multipart_xpos, multipart_ypos, multipart_level.header.LevelTitle);
-#endif
-
     if (multipart_xpos * SP_STD_PLAYFIELD_WIDTH  > SP_MAX_PLAYFIELD_WIDTH ||
 	multipart_ypos * SP_STD_PLAYFIELD_HEIGHT > SP_MAX_PLAYFIELD_HEIGHT)
     {
@@ -581,7 +501,7 @@ boolean LoadNativeLevel_SP(char *filename, int level_pos)
     }
   }
 
-  fclose(file);
+  closeFile(file);
 
   if (use_empty_level)
   {
diff --git a/src/game_sp/game_sp.h b/src/game_sp/game_sp.h
index 9551e84..9747733 100644
--- a/src/game_sp/game_sp.h
+++ b/src/game_sp/game_sp.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* game_sp.h                                                *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// game_sp.h
+// ============================================================================
 
 #ifndef GAME_SP_H
 #define GAME_SP_H
diff --git a/src/game_sp/init.c b/src/game_sp/init.c
index d8e4597..e86e318 100644
--- a/src/game_sp/init.c
+++ b/src/game_sp/init.c
@@ -3,6 +3,56 @@
 #include "global.h"
 
 
+char *preceding_playfield_memory[] =
+{
+  "95 89 95 89 95 89 3b 8a  3b 8a 3b 8a 3b 8a 3b 8a",	// |......;.;.;.;.;.|
+  "3b 8a 3b 8a 3b 8a e8 8a  e8 8a e8 8a e8 8a e8 8a",	// |;.;.;...........|
+  "e8 8a e8 8a e8 8a b1 8b  b1 8b b1 8b b1 8b b1 8b",	// |................|
+  "b1 8b b1 8b b1 8b 85 8c  85 8c 85 8c 85 8c 85 8c",	// |................|
+  "85 8c 85 8c 85 8c 5b 8d  5b 8d 5b 8d 5b 8d 5b 8d",	// |......[.[.[.[.[.|
+  "5b 8d 5b 8d 5b 8d 06 8e  06 8e 06 8e 06 8e 06 8e",	// |[.[.[...........|
+  "06 8e 06 8e 06 8e ac 8e  ac 8e ac 8e ac 8e ac 8e",	// |................|
+  "ac 8e ac 8e ac 8e 59 8f  59 8f 59 8f 59 8f 59 8f",	// |......Y.Y.Y.Y.Y.|
+  "59 8f 59 8f 59 8f 00 00  70 13 00 00 00 00 e8 17",	// |Y.Y.Y...p.......|
+  "00 00 00 00 00 00 69 38  00 00 00 00 00 00 00 00",	// |......i8........|
+  "00 00 00 00 00 00 00 00  d0 86 00 00 b2 34 00 00",	// |.............4..|
+  "00 00 00 00 00 00 8f 8b  1d 34 00 00 00 00 00 00",	// |.........4......|
+  "00 00 00 00 23 39 09 09  00 0c 00 08 00 58 00 00",	// |....#9.......X..|
+  "00 00 00 25 77 06 7f 00  00 00 01 00 00 00 00 00",	// |...%w...........|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 ec 06 26 05 00 00 00",	// |...........&....|
+  "00 00 00 01 00 00 00 00  31 32 33 34 35 36 37 38",	// |........12345678|
+  "39 30 2d 00 08 00 51 57  45 52 54 59 55 49 4f 50",	// |90-...QWERTYUIOP|
+  "00 00 0a 00 41 53 44 46  47 48 4a 4b 4c 00 00 00",	// |....ASDFGHJKL...|
+  "00 00 5a 58 43 56 42 4e  4d 00 00 00 00 00 00 20",	// |..ZXCVBNM...... |
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 2e 00  1e 00 31 00 14 00 39 00",	// |..........1...9.|
+  "1f 00 14 00 18 00 ff ff  01 00 01 4c 45 56 45 4c",	// |...........LEVEL|
+  "53 2e 44 41 54 00 00 00  00 00 00 00 00 00 00 00",	// |S.DAT...........|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+  "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",	// |................|
+
+  NULL
+};
+
+
 Bitmap *bitmap_db_field_sp;
 
 struct EngineSnapshotInfo_SP engine_snapshot_sp;
@@ -16,18 +66,30 @@ void sp_close_all()
 {
 }
 
+void InitPrecedingPlayfieldMemory()
+{
+  int preceding_buffer_size = 0;
+  int i;
+
+  for (i = 0; preceding_playfield_memory[i] != NULL; i++)
+    preceding_buffer_size += 8;		/* eight 16-bit integer values */
+
+  game_sp.preceding_buffer = preceding_playfield_memory;
+  game_sp.preceding_buffer_size = preceding_buffer_size;
+}
+
 void InitGfxBuffers_SP()
 {
-  ReCreateBitmap(&bitmap_db_field_sp, FXSIZE, FYSIZE, DEFAULT_DEPTH);
+  ReCreateBitmap(&bitmap_db_field_sp, FXSIZE, FYSIZE);
 }
 
-unsigned int InitEngineRandom_SP(long seed)
+unsigned int InitEngineRandom_SP(int seed)
 {
   if (seed == NEW_RANDOMIZE)
   {
     subRandomize();
 
-    seed = (long)RandomSeed;
+    seed = (int)RandomSeed;
   }
 
   RandomSeed = (short)seed;
@@ -40,7 +102,7 @@ unsigned int InitEngineRandom_SP(long seed)
 /* Supaplex game engine snapshot handling functions                          */
 /* ------------------------------------------------------------------------- */
 
-void SaveEngineSnapshotValues_SP()
+void SaveEngineSnapshotValues_SP(ListNode **buffers)
 {
   int i;
 
@@ -64,67 +126,68 @@ void SaveEngineSnapshotValues_SP()
 
   /* store special data into engine snapshot buffers */
 
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(FieldWidth));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(FieldHeight));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(FieldMax));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(LevelMax));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(FileMax));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TimerVar));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RandomSeed));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TerminalMaxCycles));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(mScrollX));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(mScrollY));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(mScrollX_last));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(mScrollY_last));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScreenScrollXPos));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScreenScrollYPos));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(DisplayMinX));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(DisplayMinY));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(DisplayMaxX));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(DisplayMaxY));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(InfotronsNeeded));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(KillMurphyFlag));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyMoveCounter));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyExplodePos));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(SplitMoveFlag));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RedDiskReleaseMurphyPos));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyPosIndex));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyXPos));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyYPos));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyScreenXPos));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyScreenYPos));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyVarFaceLeft));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RedDiskCount));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RedDiskReleaseFlag));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MovingPictureSequencePhase));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RedDiskReleasePhase));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScratchGravity));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GravityFlag));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(SnikSnaksElectronsFrozen));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(YellowDisksExploded));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(YawnSleepCounter));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(LeadOutCounter));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxElementLast));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxGraphicLast));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxGraphic));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxFrame));
-
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollMinX));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollMinY));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollMaxX));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollMaxY));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollX));
-  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollY));
-
-  SaveEngineSnapshotBuffer(&PlayField16[-game_sp.preceding_buffer_size],
-			   game_sp.preceding_buffer_size * sizeof(int));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(FieldWidth));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(FieldHeight));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(FieldMax));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(LevelMax));
+
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(TimerVar));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(RandomSeed));
+
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(FreezeZonks));
+
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(TerminalMaxCycles));
+
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(mScrollX));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(mScrollY));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(mScrollX_last));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(mScrollY_last));
+
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(ScreenScrollXPos));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(ScreenScrollYPos));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(DisplayMinX));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(DisplayMinY));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(DisplayMaxX));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(DisplayMaxY));
+
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(InfotronsNeeded));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(KillMurphyFlag));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(MurphyMoveCounter));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(MurphyExplodePos));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(SplitMoveFlag));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(RedDiskReleaseMurphyPos));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(MurphyPosIndex));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(MurphyXPos));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(MurphyYPos));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(MurphyScreenXPos));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(MurphyScreenYPos));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(MurphyVarFaceLeft));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(RedDiskCount));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(RedDiskReleaseFlag));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(MovingPictureSequencePhase));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(RedDiskReleasePhase));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(ScratchGravity));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(GravityFlag));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(SnikSnaksElectronsFrozen));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(YellowDisksExploded));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(YawnSleepCounter));
+
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(LeadOutCounter));
+
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(GfxElementLast));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(GfxGraphicLast));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(GfxGraphic));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(GfxFrame));
+
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(ScrollMinX));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(ScrollMinY));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(ScrollMaxX));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(ScrollMaxY));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(ScrollX));
+  SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(ScrollY));
+
+  SaveSnapshotBuffer(buffers, &PlayField16[-game_sp.preceding_buffer_size],
+		     game_sp.preceding_buffer_size * sizeof(int));
 }
 
 void LoadEngineSnapshotValues_SP()
diff --git a/src/game_sp/main.c b/src/game_sp/main.c
index 1308353..92fc912 100644
--- a/src/game_sp/main.c
+++ b/src/game_sp/main.c
@@ -31,12 +31,10 @@ void InitGameEngine_SP()
   game_sp.scroll_xoffset = (EVEN(SCR_FIELDX) ? TILEX / 2 : 0);
   game_sp.scroll_yoffset = (EVEN(SCR_FIELDY) ? TILEY / 2 : 0);
 
-#if 1
   if (native_sp_level.width <= SCR_FIELDX)
     game_sp.scroll_xoffset = TILEX / 2;
   if (native_sp_level.height <= SCR_FIELDY)
     game_sp.scroll_yoffset = TILEY / 2;
-#endif
 
   for (x = 0; x < SP_MAX_PLAYFIELD_WIDTH; x++)
   {
@@ -60,13 +58,11 @@ void RedrawPlayfield_SP(boolean force_redraw)
     RestorePlayfield();
 
   UpdatePlayfield(force_redraw);
-
-  BackToFront_SP();
 }
 
-void DrawGameDoorValues_SP()
+void UpdateGameDoorValues_SP()
 {
-  game_sp.time_played = TimerVar / setup.game_frame_delay;
+  game_sp.time_played = TimerVar / FRAMES_PER_SECOND;
   game_sp.infotrons_still_needed = InfotronsNeeded;
   game_sp.red_disk_count = RedDiskCount;
   game_sp.score = 0;		// (currently no score in Supaplex engine)
@@ -77,18 +73,24 @@ void GameActions_SP(byte action[MAX_PLAYERS], boolean warp_mode)
   byte single_player_action = action[0];
   int x, y;
 
-  UpdateEngineValues(mScrollX / TILEX, mScrollY / TILEY);
+  UpdateEngineValues(mScrollX / TILEX, mScrollY / TILEY,
+		     MurphyScreenXPos / TILEX, MurphyScreenYPos / TILEY);
 
   subMainGameLoop_Main(single_player_action, warp_mode);
 
   RedrawPlayfield_SP(FALSE);
 
-  if (!warp_mode)		/* do not redraw values in warp mode */
-    DrawGameDoorValues_SP();
+  UpdateGameDoorValues_SP();
 
-  CheckSingleStepMode_SP(PlayField16[MurphyPosIndex] != fiMurphy);
+  CheckSingleStepMode_SP(PlayField16[MurphyPosIndex] == fiMurphy,
+			 HighByte(PlayField16[MurphyPosIndex]) == 0x2A);
 
   for (x = DisplayMinX; x <= DisplayMaxX; x++)
     for (y = DisplayMinY; y <= DisplayMaxY; y++)
       GfxFrame[x][y]++;
 }
+
+int getRedDiskReleaseFlag_SP()
+{
+  return RedDiskReleaseFlag;
+}
diff --git a/src/game_sp/main_sp.h b/src/game_sp/main_sp.h
index 6e61508..f34baa6 100644
--- a/src/game_sp/main_sp.h
+++ b/src/game_sp/main_sp.h
@@ -27,45 +27,30 @@
 
 /* screen sizes and positions for SP engine */
 
-#define ORIG_TILESIZE		16
+extern int			TILESIZE_VAR;
 
-#define ZOOM_FACTOR		2
-
-#define TILESIZE		(ORIG_TILESIZE * ZOOM_FACTOR)
+#define TILESIZE		32
 #define TILEX			TILESIZE
 #define TILEY			TILESIZE
+#define TILEX_VAR		TILESIZE_VAR
+#define TILEY_VAR		TILESIZE_VAR
 
-#define ORIG_SCR_MENUX		20
-#define ORIG_SCR_MENUY		12
-#define SCR_MENUX		17
-#define SCR_MENUY		12
-#if 1
 extern int			SCR_FIELDX, SCR_FIELDY;
-#else
-#define SCR_FIELDX		17
-#define SCR_FIELDY		17
-#endif
+
 #define MAX_BUF_XSIZE		(2 + SCR_FIELDX + 2)
 #define MAX_BUF_YSIZE		(2 + SCR_FIELDY + 2)
 
 /* often used screen positions */
-#if 1
+
 extern int			SX, SY;
-#else
-#define SX			8
-#define SY			8
-#endif
-#define SXSIZE			(SCR_FIELDX * TILEX)
-#define SYSIZE			(SCR_FIELDY * TILEY)
-#define FXSIZE			(MAX_BUF_XSIZE * TILEX)
-#define FYSIZE			(MAX_BUF_YSIZE * TILEY)
-
-#if 1
+
+#define SXSIZE			(SCR_FIELDX * TILEX_VAR)
+#define SYSIZE			(SCR_FIELDY * TILEY_VAR)
+#define FXSIZE			(MAX_BUF_XSIZE * TILEX_VAR)
+#define FYSIZE			(MAX_BUF_YSIZE * TILEY_VAR)
+
 extern int			REAL_SX, REAL_SY;
-#else
-#define REAL_SX			(SX - 2)
-#define REAL_SY			(SY - 2)
-#endif
+
 #define FULL_SXSIZE		(2 + SXSIZE + 2)
 #define FULL_SYSIZE		(2 + SYSIZE + 2)
 
diff --git a/src/game_sp/vb_lib.c b/src/game_sp/vb_lib.c
index f71693c..f7b402a 100644
--- a/src/game_sp/vb_lib.c
+++ b/src/game_sp/vb_lib.c
@@ -9,21 +9,7 @@
 
 /* helper functions for constructs not supported by C */
 
-#if 0
-void *REDIM_1D(int data_size, int first_data_pos, int last_data_pos)
-{
-  /* for a buffer of n elements, first_data_pos is 0 and last_data_pos is n-1 */
-  /* a negative value for "first_data_pos" indicates a preceding buffer zone */
-
-  int data_count = last_data_pos - first_data_pos + 1;
-  int buffer_size = data_size * data_count;
-  int buffer_start = data_size * first_data_pos;
-
-  return (checked_calloc(buffer_size) - buffer_start);
-}
-#endif
-
-long MyGetTickCount()
+int MyGetTickCount()
 {
   return random_linux_libc(RANDOM_SIMPLE);
 }
diff --git a/src/game_sp/vb_lib.h b/src/game_sp/vb_lib.h
index cf8e346..5c4852c 100644
--- a/src/game_sp/vb_lib.h
+++ b/src/game_sp/vb_lib.h
@@ -11,10 +11,6 @@
 
 /* helper functions for constructs not supported by C */
 
-#if 0
-extern void *REDIM_1D(int, int, int);
-#endif
-
-extern long MyGetTickCount();
+extern int MyGetTickCount();
 
 #endif /* VB_LIB_H */
diff --git a/src/init.c b/src/init.c
index 5e5301c..29f4fd4 100644
--- a/src/init.c
+++ b/src/init.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* init.c                                                   *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// init.c
+// ============================================================================
 
 #include "libgame/libgame.h"
 
@@ -23,7 +21,7 @@
 #include "files.h"
 #include "network.h"
 #include "netserv.h"
-#include "cartoons.h"
+#include "anim.h"
 #include "config.h"
 
 #include "conf_e2g.c"	/* include auto-generated data structure definitions */
@@ -38,9 +36,6 @@
 #define CONFIG_TOKEN_FONT_INITIAL		"font.initial"
 #define CONFIG_TOKEN_GLOBAL_BUSY		"global.busy"
 
-#define DEBUG_PRINT_INIT_TIMESTAMPS		TRUE
-#define DEBUG_PRINT_INIT_TIMESTAMPS_DEPTH	1
-
 
 static struct FontBitmapInfo font_initial[NUM_INITIAL_FONTS];
 static struct GraphicInfo    anim_initial;
@@ -89,78 +84,12 @@ static int copy_properties[][5] =
 };
 
 
-static void print_timestamp_ext(char *message, char *mode)
-{
-#if DEBUG
-#if DEBUG_PRINT_INIT_TIMESTAMPS
-  static char *debug_message = NULL;
-  static char *last_message = NULL;
-  static int counter_nr = 0;
-  int max_depth = DEBUG_PRINT_INIT_TIMESTAMPS_DEPTH;
-
-  checked_free(debug_message);
-  debug_message = getStringCat3(mode, " ", message);
-
-  if (strEqual(mode, "INIT"))
-  {
-    debug_print_timestamp(counter_nr, NULL);
-
-    if (counter_nr + 1 < max_depth)
-      debug_print_timestamp(counter_nr, debug_message);
-
-    counter_nr++;
-
-    debug_print_timestamp(counter_nr, NULL);
-  }
-  else if (strEqual(mode, "DONE"))
-  {
-    counter_nr--;
-
-    if (counter_nr + 1 < max_depth ||
-	(counter_nr == 0 && max_depth == 1))
-    {
-      last_message = message;
-
-      if (counter_nr == 0 && max_depth == 1)
-      {
-	checked_free(debug_message);
-	debug_message = getStringCat3("TIME", " ", message);
-      }
-
-      debug_print_timestamp(counter_nr, debug_message);
-    }
-  }
-  else if (!strEqual(mode, "TIME") ||
-	   !strEqual(message, last_message))
-  {
-    if (counter_nr < max_depth)
-      debug_print_timestamp(counter_nr, debug_message);
-  }
-#endif
-#endif
-}
-
-static void print_timestamp_init(char *message)
-{
-  print_timestamp_ext(message, "INIT");
-}
-
-static void print_timestamp_time(char *message)
-{
-  print_timestamp_ext(message, "TIME");
-}
-
-static void print_timestamp_done(char *message)
-{
-  print_timestamp_ext(message, "DONE");
-}
-
 void DrawInitAnim()
 {
   struct GraphicInfo *graphic_info_last = graphic_info;
   int graphic = 0;
-  static unsigned long action_delay = 0;
-  unsigned long action_delay_value = GameFrameDelay;
+  static unsigned int action_delay = 0;
+  unsigned int action_delay_value = GameFrameDelay;
   int sync_frame = FrameCounter;
   int x, y;
 
@@ -173,56 +102,26 @@ void DrawInitAnim()
   if (!DelayReached(&action_delay, action_delay_value))
     return;
 
-#if 0
-  {
-    static unsigned long last_counter = -1;
-    unsigned long current_counter = Counter();
-    unsigned long delay = current_counter - last_counter;
-
-    if (last_counter != -1 && delay > action_delay_value + 5)
-      printf("::: DrawInitAnim: DELAY TOO LONG: %ld\n", delay);
-
-    last_counter = current_counter;
-  }
-#endif
+  if (init_last.busy.x == -1)
+    init_last.busy.x = WIN_XSIZE / 2;
+  if (init_last.busy.y == -1)
+    init_last.busy.y = WIN_YSIZE / 2;
 
   x = ALIGNED_TEXT_XPOS(&init_last.busy);
   y = ALIGNED_TEXT_YPOS(&init_last.busy);
 
   graphic_info = &anim_initial;		/* graphic == 0 => anim_initial */
 
-#if 0
-  {
-    static boolean done = FALSE;
-
-    // if (!done)
-      printf("::: %d, %d, %d, %d => %d, %d [%d, %d] [%d, %d]\n",
-	     init.busy.x, init.busy.y,
-	     init.busy.align, init.busy.valign,
-	     x, y,
-	     graphic_info[graphic].width,
-	     graphic_info[graphic].height,
-	     sync_frame, anim_initial.anim_delay);
-
-    done = TRUE;
-  }
-#endif
-
   if (sync_frame % anim_initial.anim_delay == 0)
   {
-#if 1
     Bitmap *src_bitmap;
     int src_x, src_y;
     int width = graphic_info[graphic].width;
     int height = graphic_info[graphic].height;
     int frame = getGraphicAnimationFrame(graphic, sync_frame);
 
-    getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
+    getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
     BlitBitmap(src_bitmap, window, src_x, src_y, width, height, x, y);
-#else
-    /* !!! this can only draw TILEX/TILEY size animations !!! */
-    DrawGraphicAnimationExt(window, x, y, graphic, sync_frame, NO_MASKING);
-#endif
   }
 
   graphic_info = graphic_info_last;
@@ -257,21 +156,32 @@ void InitGadgets()
   gadgets_initialized = TRUE;
 }
 
-inline void InitElementSmallImagesScaledUp(int graphic)
+inline static void InitElementSmallImagesScaledUp(int graphic)
 {
-#if 0
-  struct FileInfo *fi = getImageListEntryFromImageID(graphic);
-
-  printf("::: '%s' -> '%s'\n", fi->token, fi->filename);
-#endif
+  struct GraphicInfo *g = &graphic_info[graphic];
 
-  CreateImageWithSmallImages(graphic, graphic_info[graphic].scale_up_factor);
+  // create small and game tile sized bitmaps (and scale up, if needed)
+  CreateImageWithSmallImages(graphic, g->scale_up_factor, g->tile_size);
 }
 
 void InitElementSmallImages()
 {
+  print_timestamp_init("InitElementSmallImages");
+
   static int special_graphics[] =
   {
+    IMG_FLAMES_1_LEFT,
+    IMG_FLAMES_2_LEFT,
+    IMG_FLAMES_3_LEFT,
+    IMG_FLAMES_1_RIGHT,
+    IMG_FLAMES_2_RIGHT,
+    IMG_FLAMES_3_RIGHT,
+    IMG_FLAMES_1_UP,
+    IMG_FLAMES_2_UP,
+    IMG_FLAMES_3_UP,
+    IMG_FLAMES_1_DOWN,
+    IMG_FLAMES_2_DOWN,
+    IMG_FLAMES_3_DOWN,
     IMG_EDITOR_ELEMENT_BORDER,
     IMG_EDITOR_ELEMENT_BORDER_INPUT,
     IMG_EDITOR_CASCADE_LIST,
@@ -282,21 +192,31 @@ void InitElementSmallImages()
   int num_property_mappings = getImageListPropertyMappingSize();
   int i;
 
-  /* initialize normal images from static configuration */
+  print_timestamp_time("getImageListPropertyMapping/Size");
+
+  print_timestamp_init("InitElementSmallImagesScaledUp (1)");
+  /* initialize normal element images from static configuration */
   for (i = 0; element_to_graphic[i].element > -1; i++)
     InitElementSmallImagesScaledUp(element_to_graphic[i].graphic);
+  print_timestamp_done("InitElementSmallImagesScaledUp (1)");
 
-  /* initialize special images from static configuration */
+  /* initialize special element images from static configuration */
   for (i = 0; element_to_special_graphic[i].element > -1; i++)
     InitElementSmallImagesScaledUp(element_to_special_graphic[i].graphic);
+  print_timestamp_time("InitElementSmallImagesScaledUp (2)");
 
-  /* initialize images from dynamic configuration (may be elements or other) */
+  /* initialize element images from dynamic configuration */
   for (i = 0; i < num_property_mappings; i++)
-    InitElementSmallImagesScaledUp(property_mapping[i].artwork_index);
+    if (property_mapping[i].base_index < MAX_NUM_ELEMENTS)
+      InitElementSmallImagesScaledUp(property_mapping[i].artwork_index);
+  print_timestamp_time("InitElementSmallImagesScaledUp (3)");
 
-  /* initialize special images from above list (non-element images) */
+  /* initialize special non-element images from above list */
   for (i = 0; special_graphics[i] > -1; i++)
     InitElementSmallImagesScaledUp(special_graphics[i]);
+  print_timestamp_time("InitElementSmallImagesScaledUp (4)");
+
+  print_timestamp_done("InitElementSmallImages");
 }
 
 void InitScaledImages()
@@ -308,6 +228,46 @@ void InitScaledImages()
     ScaleImage(i, graphic_info[i].scale_up_factor);
 }
 
+void InitBitmapPointers()
+{
+  int num_images = getImageListSize();
+  int i;
+
+  // standard size bitmap may have changed -- update default bitmap pointer
+  for (i = 0; i < num_images; i++)
+    if (graphic_info[i].bitmaps)
+      graphic_info[i].bitmap = graphic_info[i].bitmaps[IMG_BITMAP_STANDARD];
+}
+
+void InitImageTextures()
+{
+  int i, j, k;
+
+  FreeAllImageTextures();
+
+  for (i = IMG_GLOBAL_BORDER_FIRST; i <= IMG_GLOBAL_BORDER_LAST; i++)
+    CreateImageTextures(i);
+
+  for (i = 0; i < MAX_NUM_TOONS; i++)
+    CreateImageTextures(IMG_TOON_1 + i);
+
+  for (i = 0; i < NUM_GLOBAL_ANIMS; i++)
+  {
+    for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
+    {
+      for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
+      {
+	int graphic = global_anim_info[i].graphic[j][k];
+
+	if (graphic == IMG_UNDEFINED)
+	  continue;
+
+	CreateImageTextures(graphic);
+      }
+    }
+  }
+}
+
 #if 1
 /* !!! FIX THIS (CHANGE TO USING NORMAL ELEMENT GRAPHIC DEFINITIONS) !!! */
 void SetBitmaps_EM(Bitmap **em_bitmap)
@@ -335,19 +295,6 @@ static int getFontBitmapID(int font_nr)
     special = game_status;
   else if (game_status == GAME_MODE_PSEUDO_TYPENAME)
     special = GFX_SPECIAL_ARG_MAIN;
-#if 0
-  else if (game_status == GAME_MODE_PLAYING)
-    special = GFX_SPECIAL_ARG_DOOR;
-#endif
-
-#if 0
-  if (special != -1)
-  {
-    printf("%s%s\n",
-	   font_info[font_nr].token_name,
-	   special_suffix_info[special].suffix);
-  }
-#endif
 
   if (special != -1)
     return font_info[font_nr].special_bitmap_id[special];
@@ -357,19 +304,10 @@ static int getFontBitmapID(int font_nr)
 
 static int getFontFromToken(char *token)
 {
-#if 1
   char *value = getHashEntry(font_token_hash, token);
 
   if (value != NULL)
     return atoi(value);
-#else
-  int i;
-
-  /* !!! OPTIMIZE THIS BY USING HASH !!! */
-  for (i = 0; i < NUM_FONTS; i++)
-    if (strEqual(token, font_info[i].token_name))
-      return i;
-#endif
 
   /* if font not found, use reliable default value */
   return FONT_INITIAL_1;
@@ -609,6 +547,163 @@ void InitFontGraphicInfo()
 	       getFontBitmapID, getFontFromToken);
 }
 
+void InitGlobalAnimGraphicInfo()
+{
+  struct PropertyMapping *property_mapping = getImageListPropertyMapping();
+  int num_property_mappings = getImageListPropertyMappingSize();
+  int i, j, k;
+
+  if (graphic_info == NULL)		/* still at startup phase */
+    return;
+
+  /* always start with reliable default values (no global animations) */
+  for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
+    for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
+      for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
+	global_anim_info[i].graphic[j][k] = IMG_UNDEFINED;
+
+  /* initialize global animation definitions from static configuration */
+  for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
+  {
+    int j = GLOBAL_ANIM_ID_PART_BASE;
+    int k = GFX_SPECIAL_ARG_DEFAULT;
+
+    global_anim_info[i].graphic[j][k] = IMG_GFX_GLOBAL_ANIM_1 + i;
+  }
+
+  /* initialize global animation definitions from dynamic configuration */
+  for (i = 0; i < num_property_mappings; i++)
+  {
+    int anim_nr = property_mapping[i].base_index - MAX_NUM_ELEMENTS - NUM_FONTS;
+    int part_nr = property_mapping[i].ext1_index - ACTION_PART_1;
+    int special = property_mapping[i].ext3_index;
+    int graphic = property_mapping[i].artwork_index;
+
+    if (anim_nr < 0 || anim_nr >= NUM_GLOBAL_ANIM_TOKENS)
+      continue;
+
+    /* set animation part to base part, if not specified */
+    if (!IS_GLOBAL_ANIM_PART(part_nr))
+      part_nr = GLOBAL_ANIM_ID_PART_BASE;
+
+    /* set animation screen to default, if not specified */
+    if (!IS_SPECIAL_GFX_ARG(special))
+      special = GFX_SPECIAL_ARG_DEFAULT;
+
+    global_anim_info[anim_nr].graphic[part_nr][special] = graphic;
+  }
+
+#if 0
+  printf("::: InitGlobalAnimGraphicInfo\n");
+
+  for (i = 0; i < NUM_GLOBAL_ANIMS; i++)
+    for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
+      for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
+	if (global_anim_info[i].graphic[j][k] != IMG_UNDEFINED &&
+	    graphic_info[global_anim_info[i].graphic[j][k]].bitmap != NULL)
+	  printf("::: - anim %d, part %d, mode %d => %d\n",
+		 i, j, k, global_anim_info[i].graphic[j][k]);
+#endif
+}
+
+void InitGlobalAnimSoundInfo()
+{
+  struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
+  int num_property_mappings = getSoundListPropertyMappingSize();
+  int i, j, k;
+
+  /* always start with reliable default values (no global animation sounds) */
+  for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
+    for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
+      for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
+	global_anim_info[i].sound[j][k] = SND_UNDEFINED;
+
+  /* initialize global animation sound definitions from dynamic configuration */
+  for (i = 0; i < num_property_mappings; i++)
+  {
+    int anim_nr = property_mapping[i].base_index - 2 * MAX_NUM_ELEMENTS;
+    int part_nr = property_mapping[i].ext1_index - ACTION_PART_1;
+    int special = property_mapping[i].ext3_index;
+    int sound   = property_mapping[i].artwork_index;
+
+    // sound uses control definition; map it to position of graphic (artwork)
+    anim_nr -= GLOBAL_ANIM_ID_CONTROL_FIRST;
+
+    if (anim_nr < 0 || anim_nr >= NUM_GLOBAL_ANIM_TOKENS)
+      continue;
+
+    /* set animation part to base part, if not specified */
+    if (!IS_GLOBAL_ANIM_PART(part_nr))
+      part_nr = GLOBAL_ANIM_ID_PART_BASE;
+
+    /* set animation screen to default, if not specified */
+    if (!IS_SPECIAL_GFX_ARG(special))
+      special = GFX_SPECIAL_ARG_DEFAULT;
+
+    global_anim_info[anim_nr].sound[part_nr][special] = sound;
+  }
+
+#if 0
+  printf("::: InitGlobalAnimSoundInfo\n");
+
+  for (i = 0; i < NUM_GLOBAL_ANIMS; i++)
+    for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
+      for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
+	if (global_anim_info[i].sound[j][k] != SND_UNDEFINED)
+	  printf("::: - anim %d, part %d, mode %d => %d\n",
+		 i, j, k, global_anim_info[i].sound[j][k]);
+#endif
+}
+
+void InitGlobalAnimMusicInfo()
+{
+  struct PropertyMapping *property_mapping = getMusicListPropertyMapping();
+  int num_property_mappings = getMusicListPropertyMappingSize();
+  int i, j, k;
+
+  /* always start with reliable default values (no global animation music) */
+  for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
+    for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
+      for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
+	global_anim_info[i].music[j][k] = MUS_UNDEFINED;
+
+  /* initialize global animation music definitions from dynamic configuration */
+  for (i = 0; i < num_property_mappings; i++)
+  {
+    int anim_nr = property_mapping[i].base_index - NUM_MUSIC_PREFIXES;
+    int part_nr = property_mapping[i].ext1_index - ACTION_PART_1;
+    int special = property_mapping[i].ext2_index;
+    int music   = property_mapping[i].artwork_index;
+
+    // music uses control definition; map it to position of graphic (artwork)
+    anim_nr -= GLOBAL_ANIM_ID_CONTROL_FIRST;
+
+    if (anim_nr < 0 || anim_nr >= NUM_GLOBAL_ANIM_TOKENS)
+      continue;
+
+    /* set animation part to base part, if not specified */
+    if (!IS_GLOBAL_ANIM_PART(part_nr))
+      part_nr = GLOBAL_ANIM_ID_PART_BASE;
+
+    /* set animation screen to default, if not specified */
+    if (!IS_SPECIAL_GFX_ARG(special))
+      special = GFX_SPECIAL_ARG_DEFAULT;
+
+    global_anim_info[anim_nr].music[part_nr][special] = music;
+  }
+
+#if 0
+  printf("::: InitGlobalAnimMusicInfo\n");
+
+  for (i = 0; i < NUM_GLOBAL_ANIMS; i++)
+    for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
+      for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
+	if (global_anim_info[i].music[j][k] != MUS_UNDEFINED)
+	  printf("::: - anim %d, part %d, mode %d => %d\n",
+		 i, j, k, global_anim_info[i].music[j][k]);
+#endif
+}
+
 void InitElementGraphicInfo()
 {
   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
@@ -694,16 +789,6 @@ void InitElementGraphicInfo()
     int graphic   = property_mapping[i].artwork_index;
     boolean crumbled = FALSE;
 
-#if 0
-    if ((element == EL_EM_DYNAMITE ||
-	 element == EL_EM_DYNAMITE_ACTIVE) &&
-	action == ACTION_ACTIVE &&
-	(special == GFX_SPECIAL_ARG_EDITOR ||
-	 special == GFX_SPECIAL_ARG_PANEL))
-      printf("::: DYNAMIC: %d, %d, %d -> %d\n",
-	     element, action, special, graphic);
-#endif
-
     if (special == GFX_SPECIAL_ARG_CRUMBLED)
     {
       special = -1;
@@ -776,12 +861,9 @@ void InitElementGraphicInfo()
     }
   }
 
-#if 1
   /* set hardcoded definitions for some runtime elements without graphic */
   element_info[EL_AMOEBA_TO_DIAMOND].graphic[ACTION_DEFAULT] = IMG_AMOEBA_DEAD;
-#endif
 
-#if 1
   /* set hardcoded definitions for some internal elements without graphic */
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
   {
@@ -790,7 +872,6 @@ void InitElementGraphicInfo()
     else if (IS_EDITOR_CASCADE_ACTIVE(i))
       element_info[i].graphic[ACTION_DEFAULT] = IMG_EDITOR_CASCADE_LIST_ACTIVE;
   }
-#endif
 
   /* now set all undefined/invalid graphics to -1 to set to default after it */
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
@@ -856,14 +937,12 @@ void InitElementGraphicInfo()
 	      (move_dir == MV_BIT_UP    && !front_is_left_or_upper) ||
 	      (move_dir == MV_BIT_RIGHT &&  front_is_left_or_upper) ||
 	      (move_dir == MV_BIT_DOWN  &&  front_is_left_or_upper)));
-	  Bitmap *dummy;
 
 	  /* swap frontside and backside graphic tile coordinates, if needed */
 	  if (swap_movement_tiles_always || swap_movement_tiles_autodetected)
 	  {
 	    /* get current (wrong) backside tile coordinates */
-	    getGraphicSourceExt(graphic, 0, &dummy, &src_x_back, &src_y_back,
-				TRUE);
+	    getGraphicSourceXY(graphic, 0, &src_x_back, &src_y_back, TRUE);
 
 	    /* set frontside tile coordinates to backside tile coordinates */
 	    g->src_x = src_x_back;
@@ -893,14 +972,9 @@ void InitElementGraphicInfo()
 
     if (default_graphic == -1)
       default_graphic = IMG_UNKNOWN;
-#if 1
+
     if (default_crumbled == -1)
       default_crumbled = default_graphic;
-#else
-    /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
-    if (default_crumbled == -1)
-      default_crumbled = IMG_EMPTY;
-#endif
 
     for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
     {
@@ -911,14 +985,9 @@ void InitElementGraphicInfo()
 
       if (default_direction_graphic[dir] == -1)
 	default_direction_graphic[dir] = default_graphic;
-#if 1
+
       if (default_direction_crumbled[dir] == -1)
 	default_direction_crumbled[dir] = default_direction_graphic[dir];
-#else
-      /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
-      if (default_direction_crumbled[dir] == -1)
-	default_direction_crumbled[dir] = default_crumbled;
-#endif
     }
 
     for (act = 0; act < NUM_ACTIONS; act++)
@@ -954,7 +1023,6 @@ void InitElementGraphicInfo()
       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].crumbled[act] != -1)
 	default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act];
 
-#if 1
       /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
       /* !!! make this better !!! */
       if (i == EL_EMPTY_SPACE)
@@ -962,18 +1030,12 @@ void InitElementGraphicInfo()
 	default_action_graphic = element_info[EL_DEFAULT].graphic[act];
 	default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
       }
-#endif
 
       if (default_action_graphic == -1)
 	default_action_graphic = default_graphic;
-#if 1
+
       if (default_action_crumbled == -1)
 	default_action_crumbled = default_action_graphic;
-#else
-      /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
-      if (default_action_crumbled == -1)
-	default_action_crumbled = default_crumbled;
-#endif
 
       for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
       {
@@ -995,20 +1057,9 @@ void InitElementGraphicInfo()
 	  element_info[i].direction_graphic[act][dir] =
 	    default_action_direction_graphic;
 
-#if 1
 	if (default_action_direction_crumbled == -1)
 	  default_action_direction_crumbled =
 	    element_info[i].direction_graphic[act][dir];
-#else
-	if (default_action_direction_crumbled == -1)
-	  default_action_direction_crumbled =
-	    (act_remove ? default_remove_graphic :
-	     act_turning ?
-	     element_info[i].direction_crumbled[ACTION_TURNING][dir] :
-	     default_action_crumbled != default_crumbled ?
-	     default_action_crumbled :
-	     default_direction_crumbled[dir]);
-#endif
 
 	if (element_info[i].direction_crumbled[act][dir] == -1)
 	  element_info[i].direction_crumbled[act][dir] =
@@ -1021,62 +1072,13 @@ void InitElementGraphicInfo()
 	  (act_remove ? default_remove_graphic :
 	   act_turning ? element_info[i].graphic[ACTION_TURNING] :
 	   default_action_graphic);
-#if 1
+
       if (element_info[i].crumbled[act] == -1)
 	element_info[i].crumbled[act] = element_info[i].graphic[act];
-#else
-      if (element_info[i].crumbled[act] == -1)
-	element_info[i].crumbled[act] =
-	  (act_remove ? default_remove_graphic :
-	   act_turning ? element_info[i].crumbled[ACTION_TURNING] :
-	   default_action_crumbled);
-#endif
     }
   }
 
   UPDATE_BUSY_STATE();
-
-#if 0
-  /* !!! THIS ALSO CLEARS SPECIAL FLAGS (AND IS NOT NEEDED ANYWAY) !!! */
-  /* set animation mode to "none" for each graphic with only 1 frame */
-  for (i = 0; i < MAX_NUM_ELEMENTS; i++)
-  {
-    for (act = 0; act < NUM_ACTIONS; act++)
-    {
-      int graphic = element_info[i].graphic[act];
-      int crumbled = element_info[i].crumbled[act];
-
-      if (graphic_info[graphic].anim_frames == 1)
-	graphic_info[graphic].anim_mode = ANIM_NONE;
-      if (graphic_info[crumbled].anim_frames == 1)
-	graphic_info[crumbled].anim_mode = ANIM_NONE;
-
-      for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
-      {
-	graphic = element_info[i].direction_graphic[act][dir];
-	crumbled = element_info[i].direction_crumbled[act][dir];
-
-	if (graphic_info[graphic].anim_frames == 1)
-	  graphic_info[graphic].anim_mode = ANIM_NONE;
-	if (graphic_info[crumbled].anim_frames == 1)
-	  graphic_info[crumbled].anim_mode = ANIM_NONE;
-      }
-    }
-  }
-#endif
-
-#if 0
-#if DEBUG
-  if (options.verbose)
-  {
-    for (i = 0; i < MAX_NUM_ELEMENTS; i++)
-      if (element_info[i].graphic[ACTION_DEFAULT] == IMG_UNKNOWN &&
-	  i != EL_UNKNOWN)
-	Error(ERR_INFO, "warning: no graphic for element '%s' (%d)",
-	      element_info[i].token_name, i);
-  }
-#endif
-#endif
 }
 
 void InitElementSpecialGraphicInfo()
@@ -1103,15 +1105,6 @@ void InitElementSpecialGraphicInfo()
     boolean special_redefined =
       getImageListEntryFromImageID(graphic)->redefined;
 
-#if 0
-    if ((element == EL_EM_DYNAMITE ||
-	 element == EL_EM_DYNAMITE_ACTIVE) &&
-	(special == GFX_SPECIAL_ARG_EDITOR ||
-	 special == GFX_SPECIAL_ARG_PANEL))
-      printf("::: SPECIAL STATIC: %d, %d -> %d\n",
-	     element, special, graphic);
-#endif
-
     /* if the base graphic ("emerald", for example) has been redefined,
        but not the special graphic ("emerald.EDITOR", for example), do not
        use an existing (in this case considered obsolete) special graphic
@@ -1131,43 +1124,12 @@ void InitElementSpecialGraphicInfo()
     int special   = property_mapping[i].ext3_index;
     int graphic   = property_mapping[i].artwork_index;
 
-#if 0
-    if ((element == EL_EM_DYNAMITE ||
-	 element == EL_EM_DYNAMITE_ACTIVE ||
-	 element == EL_CONVEYOR_BELT_1_MIDDLE ||
-	 element == EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE) &&
-	(special == GFX_SPECIAL_ARG_EDITOR ||
-	 special == GFX_SPECIAL_ARG_PANEL))
-      printf("::: SPECIAL DYNAMIC: %d, %d -> %d [%d]\n",
-	     element, special, graphic, property_mapping[i].ext1_index);
-#endif
-
-#if 0
-    if (element == EL_CONVEYOR_BELT_1_MIDDLE &&
-	action == ACTION_ACTIVE)
-    {
-      element = EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE;
-      action = -1;
-    }
-#endif
-
-#if 0
-    if (element == EL_MAGIC_WALL &&
-	action == ACTION_ACTIVE)
-    {
-      element = EL_MAGIC_WALL_ACTIVE;
-      action = -1;
-    }
-#endif
-
-#if 1
     /* for action ".active", replace element with active element, if exists */
     if (action == ACTION_ACTIVE && element != ELEMENT_ACTIVE(element))
     {
       element = ELEMENT_ACTIVE(element);
       action = -1;
     }
-#endif
 
     if (element >= MAX_NUM_ELEMENTS)
       continue;
@@ -1196,49 +1158,41 @@ static int get_graphic_parameter_value(char *value_raw, char *suffix, int type)
   if (strEqual(value_raw, ARG_UNDEFINED))
     return ARG_UNDEFINED_VALUE;
 
-#if 1
   if (type == TYPE_ELEMENT)
   {
     char *value = getHashEntry(element_token_hash, value_raw);
 
+    if (value == NULL)
+    {
+      Error(ERR_INFO_LINE, "-");
+      Error(ERR_INFO, "warning: error found in config file:");
+      Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
+      Error(ERR_INFO, "error: invalid element token '%s'", value_raw);
+      Error(ERR_INFO, "custom graphic rejected for this element/action");
+      Error(ERR_INFO, "fallback done to undefined element for this graphic");
+      Error(ERR_INFO_LINE, "-");
+    }
+
     return (value != NULL ? atoi(value) : EL_UNDEFINED);
   }
   else if (type == TYPE_GRAPHIC)
   {
     char *value = getHashEntry(graphic_token_hash, value_raw);
+    int fallback_graphic = IMG_CHAR_EXCLAM;
 
-    return (value != NULL ? atoi(value) : IMG_UNDEFINED);
-  }
-
-#else
-
-  int i;
-  int x = 0;
-
-  /* !!! THIS IS BUGGY !!! NOT SURE IF YOU GET ELEMENT ID OR GRAPHIC ID !!! */
-  /* !!! (possible reason why ".clone_from" with elements doesn't work) !!! */
-
-  /* !!! OPTIMIZE THIS BY USING HASH !!! */
-  for (i = 0; i < MAX_NUM_ELEMENTS; i++)
-    if (strEqual(element_info[i].token_name, value_raw))
-      return i;
-
-  /* !!! OPTIMIZE THIS BY USING HASH !!! */
-  for (i = 0; image_config[i].token != NULL; i++)
-  {
-    int len_config_value = strlen(image_config[i].value);
-
-    if (!strEqual(&image_config[i].value[len_config_value - 4], ".pcx") &&
-	!strEqual(&image_config[i].value[len_config_value - 4], ".wav") &&
-	!strEqual(image_config[i].value, UNDEFINED_FILENAME))
-      continue;
-
-    if (strEqual(image_config[i].token, value_raw))
-      return x;
+    if (value == NULL)
+    {
+      Error(ERR_INFO_LINE, "-");
+      Error(ERR_INFO, "warning: error found in config file:");
+      Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
+      Error(ERR_INFO, "error: invalid graphic token '%s'", value_raw);
+      Error(ERR_INFO, "custom graphic rejected for this element/action");
+      Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
+      Error(ERR_INFO_LINE, "-");
+    }
 
-    x++;
+    return (value != NULL ? atoi(value) : fallback_graphic);
   }
-#endif
 
   return -1;
 }
@@ -1260,9 +1214,10 @@ static int get_scaled_graphic_height(int graphic)
 }
 
 static void set_graphic_parameters_ext(int graphic, int *parameter,
-				       Bitmap *src_bitmap)
+				       Bitmap **src_bitmaps)
 {
   struct GraphicInfo *g = &graphic_info[graphic];
+  Bitmap *src_bitmap = (src_bitmaps ? src_bitmaps[IMG_BITMAP_STANDARD] : NULL);
   int anim_frames_per_row = 1, anim_frames_per_col = 1;
   int anim_frames_per_line = 1;
 
@@ -1282,11 +1237,15 @@ static void set_graphic_parameters_ext(int graphic, int *parameter,
   g->diggable_like = -1;		/* do not use clone element */
   g->border_size = TILEX / 8;		/* "CRUMBLED" border size */
   g->scale_up_factor = 1;		/* default: no scaling up */
+  g->tile_size = TILESIZE;		/* default: standard tile size */
   g->clone_from = -1;			/* do not use clone graphic */
+  g->init_delay_fixed = 0;
+  g->init_delay_random = 0;
   g->anim_delay_fixed = 0;
   g->anim_delay_random = 0;
   g->post_delay_fixed = 0;
   g->post_delay_random = 0;
+  g->draw_order = 0;
   g->fade_mode = FADE_MODE_DEFAULT;
   g->fade_delay = -1;
   g->post_delay = -1;
@@ -1297,30 +1256,49 @@ static void set_graphic_parameters_ext(int graphic, int *parameter,
   g->class = 0;
   g->style = STYLE_DEFAULT;
 
+  g->bitmaps = src_bitmaps;
   g->bitmap = src_bitmap;
 
-#if 1
   /* optional zoom factor for scaling up the image to a larger size */
   if (parameter[GFX_ARG_SCALE_UP_FACTOR] != ARG_UNDEFINED_VALUE)
     g->scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR];
   if (g->scale_up_factor < 1)
     g->scale_up_factor = 1;		/* no scaling */
+
+  /* optional tile size for using non-standard image size */
+  if (parameter[GFX_ARG_TILE_SIZE] != ARG_UNDEFINED_VALUE)
+  {
+    g->tile_size = parameter[GFX_ARG_TILE_SIZE];
+
+#if 0
+    // CHECK: should tile sizes less than standard tile size be allowed?
+    if (g->tile_size < TILESIZE)
+      g->tile_size = TILESIZE;		/* standard tile size */
 #endif
 
-#if 1
+    // when setting tile size, also set width and height accordingly
+    g->width  = g->tile_size;
+    g->height = g->tile_size;
+  }
+
   if (g->use_image_size)
   {
     /* set new default bitmap size (with scaling, but without small images) */
     g->width  = get_scaled_graphic_width(graphic);
     g->height = get_scaled_graphic_height(graphic);
   }
-#endif
+
+  /* optional width and height of each animation frame */
+  if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
+    g->width = parameter[GFX_ARG_WIDTH];
+  if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
+    g->height = parameter[GFX_ARG_HEIGHT];
 
   /* optional x and y tile position of animation frame sequence */
   if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE)
-    g->src_x = parameter[GFX_ARG_XPOS] * TILEX;
+    g->src_x = parameter[GFX_ARG_XPOS] * g->width;
   if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE)
-    g->src_y = parameter[GFX_ARG_YPOS] * TILEY;
+    g->src_y = parameter[GFX_ARG_YPOS] * g->height;
 
   /* optional x and y pixel position of animation frame sequence */
   if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE)
@@ -1328,19 +1306,28 @@ static void set_graphic_parameters_ext(int graphic, int *parameter,
   if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE)
     g->src_y = parameter[GFX_ARG_Y];
 
-  /* optional width and height of each animation frame */
-  if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
-    g->width = parameter[GFX_ARG_WIDTH];
-  if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
-    g->height = parameter[GFX_ARG_HEIGHT];
+  if (src_bitmap)
+  {
+    if (g->width <= 0)
+    {
+      Error(ERR_INFO_LINE, "-");
+      Error(ERR_WARN, "invalid value %d for '%s.width' (fallback done to %d)",
+	    g->width, getTokenFromImageID(graphic), TILEX);
+      Error(ERR_INFO_LINE, "-");
 
-#if 0
-  /* optional zoom factor for scaling up the image to a larger size */
-  if (parameter[GFX_ARG_SCALE_UP_FACTOR] != ARG_UNDEFINED_VALUE)
-    g->scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR];
-  if (g->scale_up_factor < 1)
-    g->scale_up_factor = 1;		/* no scaling */
-#endif
+      g->width = TILEX;		/* will be checked to be inside bitmap later */
+    }
+
+    if (g->height <= 0)
+    {
+      Error(ERR_INFO_LINE, "-");
+      Error(ERR_WARN, "invalid value %d for '%s.height' (fallback done to %d)",
+	    g->height, getTokenFromImageID(graphic), TILEY);
+      Error(ERR_INFO_LINE, "-");
+
+      g->height = TILEY;	/* will be checked to be inside bitmap later */
+    }
+  }
 
   if (src_bitmap)
   {
@@ -1355,8 +1342,16 @@ static void set_graphic_parameters_ext(int graphic, int *parameter,
       src_image_height = src_bitmap->height;
     }
 
-    anim_frames_per_row = src_image_width  / g->width;
-    anim_frames_per_col = src_image_height / g->height;
+    if (parameter[GFX_ARG_TILE_SIZE] != ARG_UNDEFINED_VALUE)
+    {
+      anim_frames_per_row = MAX(1, src_image_width  / g->tile_size);
+      anim_frames_per_col = MAX(1, src_image_height / g->tile_size);
+    }
+    else
+    {
+      anim_frames_per_row = MAX(1, src_image_width  / g->width);
+      anim_frames_per_col = MAX(1, src_image_height / g->height);
+    }
 
     g->src_image_width  = src_image_width;
     g->src_image_height = src_image_height;
@@ -1428,10 +1423,6 @@ static void set_graphic_parameters_ext(int graphic, int *parameter,
     g->anim_delay = 1;
 
   g->anim_mode = parameter[GFX_ARG_ANIM_MODE];
-#if 0
-  if (g->anim_frames == 1)
-    g->anim_mode = ANIM_NONE;
-#endif
 
   /* automatically determine correct start frame, if not defined */
   if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
@@ -1456,7 +1447,11 @@ static void set_graphic_parameters_ext(int graphic, int *parameter,
   if (parameter[GFX_ARG_BORDER_SIZE] != ARG_UNDEFINED_VALUE)
     g->border_size = parameter[GFX_ARG_BORDER_SIZE];
 
-  /* this is only used for player "boring" and "sleeping" actions */
+  /* used for global animations and player "boring" and "sleeping" actions */
+  if (parameter[GFX_ARG_INIT_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
+    g->init_delay_fixed = parameter[GFX_ARG_INIT_DELAY_FIXED];
+  if (parameter[GFX_ARG_INIT_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
+    g->init_delay_random = parameter[GFX_ARG_INIT_DELAY_RANDOM];
   if (parameter[GFX_ARG_ANIM_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
     g->anim_delay_fixed = parameter[GFX_ARG_ANIM_DELAY_FIXED];
   if (parameter[GFX_ARG_ANIM_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
@@ -1466,9 +1461,15 @@ static void set_graphic_parameters_ext(int graphic, int *parameter,
   if (parameter[GFX_ARG_POST_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
     g->post_delay_random = parameter[GFX_ARG_POST_DELAY_RANDOM];
 
-  /* this is only used for toon animations */
-  g->step_offset = parameter[GFX_ARG_STEP_OFFSET];
-  g->step_delay  = parameter[GFX_ARG_STEP_DELAY];
+  /* used for toon animations and global animations */
+  g->step_offset  = parameter[GFX_ARG_STEP_OFFSET];
+  g->step_xoffset = parameter[GFX_ARG_STEP_XOFFSET];
+  g->step_yoffset = parameter[GFX_ARG_STEP_YOFFSET];
+  g->step_delay   = parameter[GFX_ARG_STEP_DELAY];
+  g->direction    = parameter[GFX_ARG_DIRECTION];
+  g->position     = parameter[GFX_ARG_POSITION];
+  g->x            = parameter[GFX_ARG_X];	// (may be uninitialized,
+  g->y            = parameter[GFX_ARG_Y];	// unlike src_x and src_y)
 
   /* this is only used for drawing font characters */
   g->draw_xoffset = parameter[GFX_ARG_DRAW_XOFFSET];
@@ -1477,6 +1478,10 @@ static void set_graphic_parameters_ext(int graphic, int *parameter,
   /* this is only used for drawing envelope graphics */
   g->draw_masked = parameter[GFX_ARG_DRAW_MASKED];
 
+  /* used for toon animations and global animations */
+  if (parameter[GFX_ARG_DRAW_ORDER] != ARG_UNDEFINED_VALUE)
+    g->draw_order = parameter[GFX_ARG_DRAW_ORDER];
+
   /* optional graphic for cloning all graphics settings */
   if (parameter[GFX_ARG_CLONE_FROM] != ARG_UNDEFINED_VALUE)
     g->clone_from = parameter[GFX_ARG_CLONE_FROM];
@@ -1501,37 +1506,20 @@ static void set_graphic_parameters_ext(int graphic, int *parameter,
     g->class = parameter[GFX_ARG_CLASS];
   if (parameter[GFX_ARG_STYLE] != ARG_UNDEFINED_VALUE)
     g->style = parameter[GFX_ARG_STYLE];
+
+  /* this is only used for drawing menu buttons and text */
+  g->active_xoffset = parameter[GFX_ARG_ACTIVE_XOFFSET];
+  g->active_yoffset = parameter[GFX_ARG_ACTIVE_YOFFSET];
+  g->pressed_xoffset = parameter[GFX_ARG_PRESSED_XOFFSET];
+  g->pressed_yoffset = parameter[GFX_ARG_PRESSED_YOFFSET];
 }
 
 static void set_graphic_parameters(int graphic)
 {
-#if 1
-  struct FileInfo *image = getImageListEntryFromImageID(graphic);
-  char **parameter_raw = image->parameter;
-  Bitmap *src_bitmap = getBitmapFromImageID(graphic);
-  int parameter[NUM_GFX_ARGS];
-  int i;
-
-  /* if fallback to default artwork is done, also use the default parameters */
-  if (image->fallback_to_default)
-    parameter_raw = image->default_parameter;
-
-  /* get integer values from string parameters */
-  for (i = 0; i < NUM_GFX_ARGS; i++)
-    parameter[i] = get_graphic_parameter_value(parameter_raw[i],
-					       image_config_suffix[i].token,
-					       image_config_suffix[i].type);
-
-  set_graphic_parameters_ext(graphic, parameter, src_bitmap);
-
-#else
-
   struct FileInfo *image = getImageListEntryFromImageID(graphic);
   char **parameter_raw = image->parameter;
-  Bitmap *src_bitmap = getBitmapFromImageID(graphic);
+  Bitmap **src_bitmaps = getBitmapsFromImageID(graphic);
   int parameter[NUM_GFX_ARGS];
-  int anim_frames_per_row = 1, anim_frames_per_col = 1;
-  int anim_frames_per_line = 1;
   int i;
 
   /* if fallback to default artwork is done, also use the default parameters */
@@ -1544,237 +1532,7 @@ static void set_graphic_parameters(int graphic)
 					       image_config_suffix[i].token,
 					       image_config_suffix[i].type);
 
-  graphic_info[graphic].bitmap = src_bitmap;
-
-  /* always start with reliable default values */
-  graphic_info[graphic].src_image_width = 0;
-  graphic_info[graphic].src_image_height = 0;
-  graphic_info[graphic].src_x = 0;
-  graphic_info[graphic].src_y = 0;
-  graphic_info[graphic].width  = TILEX;	/* default for element graphics */
-  graphic_info[graphic].height = TILEY;	/* default for element graphics */
-  graphic_info[graphic].offset_x = 0;	/* one or both of these values ... */
-  graphic_info[graphic].offset_y = 0;	/* ... will be corrected later */
-  graphic_info[graphic].offset2_x = 0;	/* one or both of these values ... */
-  graphic_info[graphic].offset2_y = 0;	/* ... will be corrected later */
-  graphic_info[graphic].swap_double_tiles = -1;	/* auto-detect tile swapping */
-  graphic_info[graphic].crumbled_like = -1;	/* do not use clone element */
-  graphic_info[graphic].diggable_like = -1;	/* do not use clone element */
-  graphic_info[graphic].border_size = TILEX / 8;  /* "CRUMBLED" border size */
-  graphic_info[graphic].scale_up_factor = 1;	/* default: no scaling up */
-  graphic_info[graphic].clone_from = -1;	/* do not use clone graphic */
-  graphic_info[graphic].anim_delay_fixed = 0;
-  graphic_info[graphic].anim_delay_random = 0;
-  graphic_info[graphic].post_delay_fixed = 0;
-  graphic_info[graphic].post_delay_random = 0;
-  graphic_info[graphic].fade_mode = FADE_MODE_DEFAULT;
-  graphic_info[graphic].fade_delay = -1;
-  graphic_info[graphic].post_delay = -1;
-  graphic_info[graphic].auto_delay = -1;
-  graphic_info[graphic].align = ALIGN_CENTER;	/* default for title screens */
-  graphic_info[graphic].valign = VALIGN_MIDDLE;	/* default for title screens */
-  graphic_info[graphic].sort_priority = 0;	/* default for title screens */
-
-#if 1
-  /* optional zoom factor for scaling up the image to a larger size */
-  if (parameter[GFX_ARG_SCALE_UP_FACTOR] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR];
-  if (graphic_info[graphic].scale_up_factor < 1)
-    graphic_info[graphic].scale_up_factor = 1;		/* no scaling */
-#endif
-
-#if 1
-  if (graphic_info[graphic].use_image_size)
-  {
-    /* set new default bitmap size (with scaling, but without small images) */
-    graphic_info[graphic].width  = get_scaled_graphic_width(graphic);
-    graphic_info[graphic].height = get_scaled_graphic_height(graphic);
-  }
-#endif
-
-  /* optional x and y tile position of animation frame sequence */
-  if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].src_x = parameter[GFX_ARG_XPOS] * TILEX;
-  if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].src_y = parameter[GFX_ARG_YPOS] * TILEY;
-
-  /* optional x and y pixel position of animation frame sequence */
-  if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].src_x = parameter[GFX_ARG_X];
-  if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].src_y = parameter[GFX_ARG_Y];
-
-  /* optional width and height of each animation frame */
-  if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].width = parameter[GFX_ARG_WIDTH];
-  if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT];
-
-#if 0
-  /* optional zoom factor for scaling up the image to a larger size */
-  if (parameter[GFX_ARG_SCALE_UP_FACTOR] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR];
-  if (graphic_info[graphic].scale_up_factor < 1)
-    graphic_info[graphic].scale_up_factor = 1;		/* no scaling */
-#endif
-
-  if (src_bitmap)
-  {
-    /* get final bitmap size (with scaling, but without small images) */
-    int src_image_width  = get_scaled_graphic_width(graphic);
-    int src_image_height = get_scaled_graphic_height(graphic);
-
-    anim_frames_per_row = src_image_width  / graphic_info[graphic].width;
-    anim_frames_per_col = src_image_height / graphic_info[graphic].height;
-
-    graphic_info[graphic].src_image_width  = src_image_width;
-    graphic_info[graphic].src_image_height = src_image_height;
-  }
-
-  /* correct x or y offset dependent of vertical or horizontal frame order */
-  if (parameter[GFX_ARG_VERTICAL])	/* frames are ordered vertically */
-  {
-    graphic_info[graphic].offset_y =
-      (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
-       parameter[GFX_ARG_OFFSET] : graphic_info[graphic].height);
-    anim_frames_per_line = anim_frames_per_col;
-  }
-  else					/* frames are ordered horizontally */
-  {
-    graphic_info[graphic].offset_x =
-      (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
-       parameter[GFX_ARG_OFFSET] : graphic_info[graphic].width);
-    anim_frames_per_line = anim_frames_per_row;
-  }
-
-  /* optionally, the x and y offset of frames can be specified directly */
-  if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].offset_x = parameter[GFX_ARG_XOFFSET];
-  if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].offset_y = parameter[GFX_ARG_YOFFSET];
-
-  /* optionally, moving animations may have separate start and end graphics */
-  graphic_info[graphic].double_movement = parameter[GFX_ARG_2ND_MOVEMENT_TILE];
-
-  if (parameter[GFX_ARG_2ND_VERTICAL] == ARG_UNDEFINED_VALUE)
-    parameter[GFX_ARG_2ND_VERTICAL] = !parameter[GFX_ARG_VERTICAL];
-
-  /* correct x or y offset2 dependent of vertical or horizontal frame order */
-  if (parameter[GFX_ARG_2ND_VERTICAL])	/* frames are ordered vertically */
-    graphic_info[graphic].offset2_y =
-      (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
-       parameter[GFX_ARG_2ND_OFFSET] : graphic_info[graphic].height);
-  else					/* frames are ordered horizontally */
-    graphic_info[graphic].offset2_x =
-      (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
-       parameter[GFX_ARG_2ND_OFFSET] : graphic_info[graphic].width);
-
-  /* optionally, the x and y offset of 2nd graphic can be specified directly */
-  if (parameter[GFX_ARG_2ND_XOFFSET] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].offset2_x = parameter[GFX_ARG_2ND_XOFFSET];
-  if (parameter[GFX_ARG_2ND_YOFFSET] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].offset2_y = parameter[GFX_ARG_2ND_YOFFSET];
-
-  /* optionally, the second movement tile can be specified as start tile */
-  if (parameter[GFX_ARG_2ND_SWAP_TILES] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].swap_double_tiles= parameter[GFX_ARG_2ND_SWAP_TILES];
-
-  /* automatically determine correct number of frames, if not defined */
-  if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].anim_frames = parameter[GFX_ARG_FRAMES];
-  else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
-    graphic_info[graphic].anim_frames =	anim_frames_per_row;
-  else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
-    graphic_info[graphic].anim_frames =	anim_frames_per_col;
-  else
-    graphic_info[graphic].anim_frames = 1;
-
-  if (graphic_info[graphic].anim_frames == 0)	/* frames must be at least 1 */
-    graphic_info[graphic].anim_frames = 1;
-
-  graphic_info[graphic].anim_frames_per_line =
-    (parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ?
-     parameter[GFX_ARG_FRAMES_PER_LINE] : anim_frames_per_line);
-
-  graphic_info[graphic].anim_delay = parameter[GFX_ARG_DELAY];
-  if (graphic_info[graphic].anim_delay == 0)	/* delay must be at least 1 */
-    graphic_info[graphic].anim_delay = 1;
-
-  graphic_info[graphic].anim_mode = parameter[GFX_ARG_ANIM_MODE];
-#if 0
-  if (graphic_info[graphic].anim_frames == 1)
-    graphic_info[graphic].anim_mode = ANIM_NONE;
-#endif
-
-  /* automatically determine correct start frame, if not defined */
-  if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].anim_start_frame = 0;
-  else if (graphic_info[graphic].anim_mode & ANIM_REVERSE)
-    graphic_info[graphic].anim_start_frame =
-      graphic_info[graphic].anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
-  else
-    graphic_info[graphic].anim_start_frame = parameter[GFX_ARG_START_FRAME];
-
-  /* animation synchronized with global frame counter, not move position */
-  graphic_info[graphic].anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
-
-  /* optional element for cloning crumble graphics */
-  if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
-
-  /* optional element for cloning digging graphics */
-  if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
-
-  /* optional border size for "crumbling" diggable graphics */
-  if (parameter[GFX_ARG_BORDER_SIZE] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].border_size = parameter[GFX_ARG_BORDER_SIZE];
-
-  /* this is only used for player "boring" and "sleeping" actions */
-  if (parameter[GFX_ARG_ANIM_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].anim_delay_fixed =
-      parameter[GFX_ARG_ANIM_DELAY_FIXED];
-  if (parameter[GFX_ARG_ANIM_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].anim_delay_random =
-      parameter[GFX_ARG_ANIM_DELAY_RANDOM];
-  if (parameter[GFX_ARG_POST_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].post_delay_fixed =
-      parameter[GFX_ARG_POST_DELAY_FIXED];
-  if (parameter[GFX_ARG_POST_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].post_delay_random =
-      parameter[GFX_ARG_POST_DELAY_RANDOM];
-
-  /* this is only used for toon animations */
-  graphic_info[graphic].step_offset = parameter[GFX_ARG_STEP_OFFSET];
-  graphic_info[graphic].step_delay  = parameter[GFX_ARG_STEP_DELAY];
-
-  /* this is only used for drawing font characters */
-  graphic_info[graphic].draw_xoffset = parameter[GFX_ARG_DRAW_XOFFSET];
-  graphic_info[graphic].draw_yoffset = parameter[GFX_ARG_DRAW_YOFFSET];
-
-  /* this is only used for drawing envelope graphics */
-  graphic_info[graphic].draw_masked = parameter[GFX_ARG_DRAW_MASKED];
-
-  /* optional graphic for cloning all graphics settings */
-  if (parameter[GFX_ARG_CLONE_FROM] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].clone_from = parameter[GFX_ARG_CLONE_FROM];
-
-  /* optional settings for drawing title screens and title messages */
-  if (parameter[GFX_ARG_FADE_MODE] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].fade_mode = parameter[GFX_ARG_FADE_MODE];
-  if (parameter[GFX_ARG_FADE_DELAY] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].fade_delay = parameter[GFX_ARG_FADE_DELAY];
-  if (parameter[GFX_ARG_POST_DELAY] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].post_delay = parameter[GFX_ARG_POST_DELAY];
-  if (parameter[GFX_ARG_AUTO_DELAY] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].auto_delay = parameter[GFX_ARG_AUTO_DELAY];
-  if (parameter[GFX_ARG_ALIGN] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].align = parameter[GFX_ARG_ALIGN];
-  if (parameter[GFX_ARG_VALIGN] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].valign = parameter[GFX_ARG_VALIGN];
-  if (parameter[GFX_ARG_SORT_PRIORITY] != ARG_UNDEFINED_VALUE)
-    graphic_info[graphic].sort_priority = parameter[GFX_ARG_SORT_PRIORITY];
-#endif
+  set_graphic_parameters_ext(graphic, parameter, src_bitmaps);
 
   UPDATE_BUSY_STATE();
 }
@@ -1804,7 +1562,7 @@ static void set_cloned_graphic_parameters(int graphic)
     Error(ERR_INFO, "custom graphic rejected for this element/action");
 
     if (graphic == fallback_graphic)
-      Error(ERR_EXIT, "fatal error: no fallback graphic available");
+      Error(ERR_EXIT, "no fallback graphic available");
 
     Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
     Error(ERR_INFO_LINE, "-");
@@ -1824,30 +1582,28 @@ static void InitGraphicInfo()
   int num_images = getImageListSize();
   int i;
 
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
-  static boolean clipmasks_initialized = FALSE;
-  Pixmap src_pixmap;
-  XGCValues clip_gc_values;
-  unsigned long clip_gc_valuemask;
-  GC copy_clipmask_gc = None;
-#endif
-
   /* use image size as default values for width and height for these images */
   static int full_size_graphics[] =
   {
     IMG_GLOBAL_BORDER,
+    IMG_GLOBAL_BORDER_MAIN,
+    IMG_GLOBAL_BORDER_SCORES,
+    IMG_GLOBAL_BORDER_EDITOR,
+    IMG_GLOBAL_BORDER_PLAYING,
     IMG_GLOBAL_DOOR,
 
     IMG_BACKGROUND_ENVELOPE_1,
     IMG_BACKGROUND_ENVELOPE_2,
     IMG_BACKGROUND_ENVELOPE_3,
     IMG_BACKGROUND_ENVELOPE_4,
+    IMG_BACKGROUND_REQUEST,
 
     IMG_BACKGROUND,
     IMG_BACKGROUND_TITLE_INITIAL,
     IMG_BACKGROUND_TITLE,
     IMG_BACKGROUND_MAIN,
     IMG_BACKGROUND_LEVELS,
+    IMG_BACKGROUND_LEVELNR,
     IMG_BACKGROUND_SCORES,
     IMG_BACKGROUND_EDITOR,
     IMG_BACKGROUND_INFO,
@@ -1855,9 +1611,15 @@ static void InitGraphicInfo()
     IMG_BACKGROUND_INFO_MUSIC,
     IMG_BACKGROUND_INFO_CREDITS,
     IMG_BACKGROUND_INFO_PROGRAM,
+    IMG_BACKGROUND_INFO_VERSION,
     IMG_BACKGROUND_INFO_LEVELSET,
     IMG_BACKGROUND_SETUP,
+    IMG_BACKGROUND_PLAYING,
     IMG_BACKGROUND_DOOR,
+    IMG_BACKGROUND_TAPE,
+    IMG_BACKGROUND_PANEL,
+    IMG_BACKGROUND_PALETTE,
+    IMG_BACKGROUND_TOOLBOX,
 
     IMG_TITLESCREEN_INITIAL_1,
     IMG_TITLESCREEN_INITIAL_2,
@@ -1870,6 +1632,17 @@ static void InitGraphicInfo()
     IMG_TITLESCREEN_4,
     IMG_TITLESCREEN_5,
 
+    IMG_BACKGROUND_TITLEMESSAGE_INITIAL_1,
+    IMG_BACKGROUND_TITLEMESSAGE_INITIAL_2,
+    IMG_BACKGROUND_TITLEMESSAGE_INITIAL_3,
+    IMG_BACKGROUND_TITLEMESSAGE_INITIAL_4,
+    IMG_BACKGROUND_TITLEMESSAGE_INITIAL_5,
+    IMG_BACKGROUND_TITLEMESSAGE_1,
+    IMG_BACKGROUND_TITLEMESSAGE_2,
+    IMG_BACKGROUND_TITLEMESSAGE_3,
+    IMG_BACKGROUND_TITLEMESSAGE_4,
+    IMG_BACKGROUND_TITLEMESSAGE_5,
+
     -1
   };
 
@@ -1877,7 +1650,6 @@ static void InitGraphicInfo()
 
   graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
 
-#if 1
   /* initialize "use_image_size" flag with default value */
   for (i = 0; i < num_images; i++)
     graphic_info[i].use_image_size = FALSE;
@@ -1885,23 +1657,6 @@ static void InitGraphicInfo()
   /* initialize "use_image_size" flag from static configuration above */
   for (i = 0; full_size_graphics[i] != -1; i++)
     graphic_info[full_size_graphics[i]].use_image_size = TRUE;
-#endif
-
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
-  if (clipmasks_initialized)
-  {
-    for (i = 0; i < num_images; i++)
-    {
-      if (graphic_info[i].clip_mask)
-	XFreePixmap(display, graphic_info[i].clip_mask);
-      if (graphic_info[i].clip_gc)
-	XFreeGC(display, graphic_info[i].clip_gc);
-
-      graphic_info[i].clip_mask = None;
-      graphic_info[i].clip_gc = None;
-    }
-  }
-#endif
 
   /* first set all graphic paramaters ... */
   for (i = 0; i < num_images; i++)
@@ -1936,13 +1691,11 @@ static void InitGraphicInfo()
     /* check if first animation frame is inside specified bitmap */
 
     first_frame = 0;
-    getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
+    getFixedGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
 
-#if 1
     /* this avoids calculating wrong start position for out-of-bounds frame */
     src_x = graphic_info[i].src_x;
     src_y = graphic_info[i].src_y;
-#endif
 
     if (src_x < 0 || src_y < 0 ||
 	src_x + width  > src_bitmap_width ||
@@ -1953,13 +1706,14 @@ static void InitGraphicInfo()
       Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
       Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(i));
       Error(ERR_INFO, "- image file: '%s'", src_bitmap->source_filename);
+      Error(ERR_INFO, "- frame size: %d, %d", width, height);
       Error(ERR_INFO,
 	    "error: first animation frame out of bounds (%d, %d) [%d, %d]",
 	    src_x, src_y, src_bitmap_width, src_bitmap_height);
       Error(ERR_INFO, "custom graphic rejected for this element/action");
 
       if (i == fallback_graphic)
-	Error(ERR_EXIT, "fatal error: no fallback graphic available");
+	Error(ERR_EXIT, "no fallback graphic available");
 
       Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
       Error(ERR_INFO_LINE, "-");
@@ -1970,7 +1724,7 @@ static void InitGraphicInfo()
     /* check if last animation frame is inside specified bitmap */
 
     last_frame = graphic_info[i].anim_frames - 1;
-    getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
+    getFixedGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
 
     if (src_x < 0 || src_y < 0 ||
 	src_x + width  > src_bitmap_width ||
@@ -1981,54 +1735,63 @@ static void InitGraphicInfo()
       Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
       Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(i));
       Error(ERR_INFO, "- image file: '%s'", src_bitmap->source_filename);
+      Error(ERR_INFO, "- frame size: %d, %d", width, height);
       Error(ERR_INFO,
 	    "error: last animation frame (%d) out of bounds (%d, %d) [%d, %d]",
 	    last_frame, src_x, src_y, src_bitmap_width, src_bitmap_height);
       Error(ERR_INFO, "custom graphic rejected for this element/action");
 
       if (i == fallback_graphic)
-	Error(ERR_EXIT, "fatal error: no fallback graphic available");
+	Error(ERR_EXIT, "no fallback graphic available");
 
       Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
       Error(ERR_INFO_LINE, "-");
 
       graphic_info[i] = graphic_info[fallback_graphic];
     }
+  }
+}
 
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
-    /* currently we only need a tile clip mask from the first frame */
-    getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
-
-    if (copy_clipmask_gc == None)
-    {
-      clip_gc_values.graphics_exposures = False;
-      clip_gc_valuemask = GCGraphicsExposures;
-      copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
-				   clip_gc_valuemask, &clip_gc_values);
-    }
+static void InitGraphicCompatibilityInfo()
+{
+  struct FileInfo *fi_global_door =
+    getImageListEntryFromImageID(IMG_GLOBAL_DOOR);
+  int num_images = getImageListSize();
+  int i;
 
-    graphic_info[i].clip_mask =
-      XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
+  /* the following compatibility handling is needed for the following case:
+     versions up to 3.3.0.0 used one large bitmap "global.door" for various
+     graphics mainly used for door and panel graphics, like editor, tape and
+     in-game buttons with hard-coded bitmap positions and button sizes; as
+     these graphics now have individual definitions, redefining "global.door"
+     to change all these graphics at once like before does not work anymore
+     (because all those individual definitions still have their default values);
+     to solve this, remap all those individual definitions that are not
+     redefined to the new bitmap of "global.door" if it was redefined */
 
-    src_pixmap = src_bitmap->clip_mask;
-    XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
-	      copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
+  /* special compatibility handling if image "global.door" was redefined */
+  if (fi_global_door->redefined)
+  {
+    for (i = 0; i < num_images; i++)
+    {
+      struct FileInfo *fi = getImageListEntryFromImageID(i);
 
-    clip_gc_values.graphics_exposures = False;
-    clip_gc_values.clip_mask = graphic_info[i].clip_mask;
-    clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
+      /* process only those images that still use the default settings */
+      if (!fi->redefined)
+      {
+	/* process all images which default to same image as "global.door" */
+	if (strEqual(fi->default_filename, fi_global_door->default_filename))
+	{
+	  // printf("::: special treatment needed for token '%s'\n", fi->token);
 
-    graphic_info[i].clip_gc =
-      XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
-#endif
+	  graphic_info[i].bitmaps = graphic_info[IMG_GLOBAL_DOOR].bitmaps;
+	  graphic_info[i].bitmap  = graphic_info[IMG_GLOBAL_DOOR].bitmap;
+	}
+      }
+    }
   }
 
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
-  if (copy_clipmask_gc)
-    XFreeGC(display, copy_clipmask_gc);
-
-  clipmasks_initialized = TRUE;
-#endif
+  InitGraphicCompatibilityInfo_Doors();
 }
 
 static void InitElementSoundInfo()
@@ -2113,19 +1876,10 @@ static void InitElementSoundInfo()
       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
 	default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
 
-      /* !!! there's no such thing as a "default action sound" !!! */
-#if 0
-      /* look for element specific default sound (independent from action) */
-      if (element_info[i].sound[ACTION_DEFAULT] != -1)
-	default_action_sound = element_info[i].sound[ACTION_DEFAULT];
-#endif
-
-#if 1
       /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
       /* !!! make this better !!! */
       if (i == EL_EMPTY_SPACE)
 	default_action_sound = element_info[EL_DEFAULT].sound[act];
-#endif
 
       /* no sound for this specific action -- use default action sound */
       if (element_info[i].sound[act] == -1)
@@ -2166,12 +1920,6 @@ static void InitGameModeSoundInfo()
   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
     if (menu.sound[i] == -1)
       menu.sound[i] = menu.sound[GAME_MODE_DEFAULT];
-
-#if 0
-  for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
-    if (menu.sound[i] != -1)
-      printf("::: menu.sound[%d] == %d\n", i, menu.sound[i]);
-#endif
 }
 
 static void set_sound_parameters(int sound, char **parameter_raw)
@@ -2221,10 +1969,6 @@ static void InitSoundInfo()
     sound_effect_properties[i] = ACTION_OTHER;
     sound_info[i].loop = FALSE;		/* default: play sound only once */
 
-#if 0
-    printf("::: sound %d: '%s'\n", i, sound->token);
-#endif
-
     /* determine all loop sounds and identify certain sound classes */
 
     for (j = 0; element_action_info[j].suffix; j++)
@@ -2287,10 +2031,6 @@ static void InitGameModeMusicInfo()
     int gamemode = gamemode_to_music[i].gamemode;
     int music    = gamemode_to_music[i].music;
 
-#if 0
-    printf("::: gamemode == %d, music == %d\n", gamemode, music);
-#endif
-
     if (gamemode < 0)
       gamemode = GAME_MODE_DEFAULT;
 
@@ -2301,15 +2041,10 @@ static void InitGameModeMusicInfo()
   for (i = 0; i < num_property_mappings; i++)
   {
     int prefix   = property_mapping[i].base_index;
-    int gamemode = property_mapping[i].ext1_index;
-    int level    = property_mapping[i].ext2_index;
+    int gamemode = property_mapping[i].ext2_index;
+    int level    = property_mapping[i].ext3_index;
     int music    = property_mapping[i].artwork_index;
 
-#if 0
-    printf("::: prefix == %d, gamemode == %d, level == %d, music == %d\n",
-	   prefix, gamemode, level, music);
-#endif
-
     if (prefix < 0 || prefix >= NUM_MUSIC_PREFIXES)
       continue;
 
@@ -2340,16 +2075,7 @@ static void InitGameModeMusicInfo()
       levelset.music[i] = default_levelset_music;
   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
     if (menu.music[i] == -1)
-      menu.music[i] = menu.music[GAME_MODE_DEFAULT];
-
-#if 0
-  for (i = 0; i < MAX_LEVELS; i++)
-    if (levelset.music[i] != -1)
-      printf("::: levelset.music[%d] == %d\n", i, levelset.music[i]);
-  for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
-    if (menu.music[i] != -1)
-      printf("::: menu.music[%d] == %d\n", i, menu.music[i]);
-#endif
+      menu.music[i] = menu.music[GAME_MODE_DEFAULT];
 }
 
 static void set_music_parameters(int music, char **parameter_raw)
@@ -2409,6 +2135,8 @@ static void ReinitializeGraphics()
 {
   print_timestamp_init("ReinitializeGraphics");
 
+  InitGfxTileSizeInfo(game.tile_size, TILESIZE);
+
   InitGraphicInfo();			/* graphic properties mapping */
   print_timestamp_time("InitGraphicInfo");
   InitElementGraphicInfo();		/* element game graphic mapping */
@@ -2420,12 +2148,22 @@ static void ReinitializeGraphics()
   print_timestamp_time("InitElementSmallImages");
   InitScaledImages();			/* scale all other images, if needed */
   print_timestamp_time("InitScaledImages");
+  InitBitmapPointers();			/* set standard size bitmap pointers */
+  print_timestamp_time("InitBitmapPointers");
   InitFontGraphicInfo();		/* initialize text drawing functions */
   print_timestamp_time("InitFontGraphicInfo");
+  InitGlobalAnimGraphicInfo();		/* initialize global animation config */
+  print_timestamp_time("InitGlobalAnimGraphicInfo");
+
+  InitImageTextures();			/* create textures for certain images */
+  print_timestamp_time("InitImageTextures");
 
   InitGraphicInfo_EM();			/* graphic mapping for EM engine */
   print_timestamp_time("InitGraphicInfo_EM");
 
+  InitGraphicCompatibilityInfo();
+  print_timestamp_time("InitGraphicCompatibilityInfo");
+
   SetMainBackgroundImage(IMG_BACKGROUND);
   print_timestamp_time("SetMainBackgroundImage");
   SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
@@ -2433,8 +2171,8 @@ static void ReinitializeGraphics()
 
   InitGadgets();
   print_timestamp_time("InitGadgets");
-  InitToons();
-  print_timestamp_time("InitToons");
+  InitDoors();
+  print_timestamp_time("InitDoors");
 
   print_timestamp_done("ReinitializeGraphics");
 }
@@ -2444,6 +2182,7 @@ static void ReinitializeSounds()
   InitSoundInfo();		/* sound properties mapping */
   InitElementSoundInfo();	/* element game sound mapping */
   InitGameModeSoundInfo();	/* game mode sound mapping */
+  InitGlobalAnimSoundInfo();	/* global animation sound settings */
 
   InitPlayLevelSound();		/* internal game sound settings */
 }
@@ -2452,6 +2191,7 @@ static void ReinitializeMusic()
 {
   InitMusicInfo();		/* music properties mapping */
   InitGameModeMusicInfo();	/* game mode music mapping */
+  InitGlobalAnimMusicInfo();	/* global animation music settings */
 }
 
 static int get_special_property_bit(int element, int property_bit_nr)
@@ -2910,18 +2650,14 @@ void InitElementPropertiesStatic()
     EL_SWITCHGATE_OPENING,
     EL_SWITCHGATE_CLOSED,
     EL_SWITCHGATE_CLOSING,
-#if 1
     EL_DC_SWITCHGATE_SWITCH_UP,
     EL_DC_SWITCHGATE_SWITCH_DOWN,
-#endif
     EL_TIMEGATE_OPEN,
     EL_TIMEGATE_OPENING,
     EL_TIMEGATE_CLOSED,
     EL_TIMEGATE_CLOSING,
-#if 1
     EL_DC_TIMEGATE_SWITCH,
     EL_DC_TIMEGATE_SWITCH_ACTIVE,
-#endif
     EL_TUBE_ANY,
     EL_TUBE_VERTICAL,
     EL_TUBE_HORIZONTAL,
@@ -3160,16 +2896,12 @@ void InitElementPropertiesStatic()
     EL_SOKOBAN_FIELD_EMPTY,
     EL_EXIT_OPEN,
     EL_EM_EXIT_OPEN,
-#if 1
     EL_EM_EXIT_OPENING,
-#endif
     EL_SP_EXIT_OPEN,
     EL_SP_EXIT_OPENING,
     EL_STEEL_EXIT_OPEN,
     EL_EM_STEEL_EXIT_OPEN,
-#if 1
     EL_EM_STEEL_EXIT_OPENING,
-#endif
     EL_GATE_1,
     EL_GATE_2,
     EL_GATE_3,
@@ -4840,15 +4572,9 @@ void InitElementPropertiesEngine(int engine_version)
 						  HAS_ACTION(i)));
 
     /* ---------- GFX_CRUMBLED --------------------------------------------- */
-#if 1
     SET_PROPERTY(i, EP_GFX_CRUMBLED,
 		 element_info[i].crumbled[ACTION_DEFAULT] !=
 		 element_info[i].graphic[ACTION_DEFAULT]);
-#else
-    /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
-    SET_PROPERTY(i, EP_GFX_CRUMBLED,
-		 element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
-#endif
 
     /* ---------- EDITOR_CASCADE ------------------------------------------- */
     SET_PROPERTY(i, EP_EDITOR_CASCADE, (IS_EDITOR_CASCADE_ACTIVE(i) ||
@@ -4946,10 +4672,6 @@ static void InitGlobal()
     element_info[i].token_name = element_name_info[i].token_name;
     element_info[i].class_name = element_name_info[i].class_name;
     element_info[i].editor_description= element_name_info[i].editor_description;
-
-#if 0
-    printf("%04d: %s\n", i, element_name_info[i].token_name);
-#endif
   }
 
   /* create hash from image config list */
@@ -4969,7 +4691,8 @@ static void InitGlobal()
   /* create hash from graphic token list */
   graphic_token_hash = newSetupFileHash();
   for (graphic = 0, i = 0; image_config[i].token != NULL; i++)
-    if (strSuffix(image_config[i].value, ".pcx") ||
+    if (strSuffix(image_config[i].value, ".png") ||
+	strSuffix(image_config[i].value, ".pcx") ||
 	strSuffix(image_config[i].value, ".wav") ||
 	strEqual(image_config[i].value, UNDEFINED_FILENAME))
       setHashEntry(graphic_token_hash,
@@ -4983,6 +4706,33 @@ static void InitGlobal()
 		 font_info[i].token_name,
 		 int2str(i, 0));
 
+  /* set default filenames for all cloned graphics in static configuration */
+  for (i = 0; image_config[i].token != NULL; i++)
+  {
+    if (strEqual(image_config[i].value, UNDEFINED_FILENAME))
+    {
+      char *token = image_config[i].token;
+      char *token_clone_from = getStringCat2(token, ".clone_from");
+      char *token_cloned = getHashEntry(image_config_hash, token_clone_from);
+
+      if (token_cloned != NULL)
+      {
+	char *value_cloned = getHashEntry(image_config_hash, token_cloned);
+
+	if (value_cloned != NULL)
+	{
+	  /* set default filename in static configuration */
+	  image_config[i].value = value_cloned;
+
+	  /* set default filename in image config hash */
+	  setHashEntry(image_config_hash, token, value_cloned);
+	}
+      }
+
+      free(token_clone_from);
+    }
+  }
+
   /* always start with reliable default values (all elements) */
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
     ActiveElement[i] = i;
@@ -5027,14 +4777,11 @@ static void InitGlobal()
   global.create_images_dir = NULL;
 
   global.frames_per_second = 0;
-  global.fps_slowdown = FALSE;
-  global.fps_slowdown_factor = 1;
 
-  global.border_status = GAME_MODE_MAIN;
-#if 0
-  global.fading_status = GAME_MODE_MAIN;
-  global.fading_type = TYPE_ENTER_MENU;
-#endif
+  global.border_status = GAME_MODE_LOADING;
+  global.anim_status = global.anim_status_next = GAME_MODE_LOADING;
+
+  global.use_envelope_request = FALSE;
 }
 
 void Execute_Command(char *command)
@@ -5043,57 +4790,57 @@ void Execute_Command(char *command)
 
   if (strEqual(command, "print graphicsinfo.conf"))
   {
-    printf("# You can configure additional/alternative image files here.\n");
-    printf("# (The entries below are default and therefore commented out.)\n");
-    printf("\n");
-    printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
-    printf("\n");
-    printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
-    printf("\n");
+    Print("# You can configure additional/alternative image files here.\n");
+    Print("# (The entries below are default and therefore commented out.)\n");
+    Print("\n");
+    Print("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
+    Print("\n");
+    Print("%s\n", getFormattedSetupEntry("sort_priority", "100"));
+    Print("\n");
 
     for (i = 0; image_config[i].token != NULL; i++)
-      printf("# %s\n", getFormattedSetupEntry(image_config[i].token,
-					      image_config[i].value));
+      Print("# %s\n", getFormattedSetupEntry(image_config[i].token,
+					     image_config[i].value));
 
     exit(0);
   }
   else if (strEqual(command, "print soundsinfo.conf"))
   {
-    printf("# You can configure additional/alternative sound files here.\n");
-    printf("# (The entries below are default and therefore commented out.)\n");
-    printf("\n");
-    printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
-    printf("\n");
-    printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
-    printf("\n");
+    Print("# You can configure additional/alternative sound files here.\n");
+    Print("# (The entries below are default and therefore commented out.)\n");
+    Print("\n");
+    Print("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
+    Print("\n");
+    Print("%s\n", getFormattedSetupEntry("sort_priority", "100"));
+    Print("\n");
 
     for (i = 0; sound_config[i].token != NULL; i++)
-      printf("# %s\n", getFormattedSetupEntry(sound_config[i].token,
-					      sound_config[i].value));
+      Print("# %s\n", getFormattedSetupEntry(sound_config[i].token,
+					     sound_config[i].value));
 
     exit(0);
   }
   else if (strEqual(command, "print musicinfo.conf"))
   {
-    printf("# You can configure additional/alternative music files here.\n");
-    printf("# (The entries below are default and therefore commented out.)\n");
-    printf("\n");
-    printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
-    printf("\n");
-    printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
-    printf("\n");
+    Print("# You can configure additional/alternative music files here.\n");
+    Print("# (The entries below are default and therefore commented out.)\n");
+    Print("\n");
+    Print("%s\n", getFormattedSetupEntry("name", "Classic Music"));
+    Print("\n");
+    Print("%s\n", getFormattedSetupEntry("sort_priority", "100"));
+    Print("\n");
 
     for (i = 0; music_config[i].token != NULL; i++)
-      printf("# %s\n", getFormattedSetupEntry(music_config[i].token,
-					      music_config[i].value));
+      Print("# %s\n", getFormattedSetupEntry(music_config[i].token,
+					     music_config[i].value));
 
     exit(0);
   }
   else if (strEqual(command, "print editorsetup.conf"))
   {
-    printf("# You can configure your personal editor element list here.\n");
-    printf("# (The entries below are default and therefore commented out.)\n");
-    printf("\n");
+    Print("# You can configure your personal editor element list here.\n");
+    Print("# (The entries below are default and therefore commented out.)\n");
+    Print("\n");
 
     /* this is needed to be able to check element list for cascade elements */
     InitElementPropertiesStatic();
@@ -5105,30 +4852,30 @@ void Execute_Command(char *command)
   }
   else if (strEqual(command, "print helpanim.conf"))
   {
-    printf("# You can configure different element help animations here.\n");
-    printf("# (The entries below are default and therefore commented out.)\n");
-    printf("\n");
+    Print("# You can configure different element help animations here.\n");
+    Print("# (The entries below are default and therefore commented out.)\n");
+    Print("\n");
 
     for (i = 0; helpanim_config[i].token != NULL; i++)
     {
-      printf("# %s\n", getFormattedSetupEntry(helpanim_config[i].token,
-					      helpanim_config[i].value));
+      Print("# %s\n", getFormattedSetupEntry(helpanim_config[i].token,
+					     helpanim_config[i].value));
 
       if (strEqual(helpanim_config[i].token, "end"))
-	printf("#\n");
+	Print("#\n");
     }
 
     exit(0);
   }
   else if (strEqual(command, "print helptext.conf"))
   {
-    printf("# You can configure different element help text here.\n");
-    printf("# (The entries below are default and therefore commented out.)\n");
-    printf("\n");
+    Print("# You can configure different element help text here.\n");
+    Print("# (The entries below are default and therefore commented out.)\n");
+    Print("\n");
 
     for (i = 0; helptext_config[i].token != NULL; i++)
-      printf("# %s\n", getFormattedSetupEntry(helptext_config[i].token,
-					      helptext_config[i].value));
+      Print("# %s\n", getFormattedSetupEntry(helptext_config[i].token,
+					     helptext_config[i].value));
 
     exit(0);
   }
@@ -5156,10 +4903,20 @@ void Execute_Command(char *command)
 
     exit(0);
   }
-  else if (strPrefix(command, "autoplay "))
+  else if (strPrefix(command, "autotest ") ||
+	   strPrefix(command, "autoplay ") ||
+	   strPrefix(command, "autoffwd ") ||
+	   strPrefix(command, "autowarp "))
   {
     char *str_ptr = getStringCopy(&command[9]);	/* read command parameters */
 
+    global.autoplay_mode =
+      (strPrefix(command, "autotest") ? AUTOPLAY_MODE_TEST :
+       strPrefix(command, "autoplay") ? AUTOPLAY_MODE_PLAY :
+       strPrefix(command, "autoffwd") ? AUTOPLAY_MODE_FFWD :
+       strPrefix(command, "autowarp") ? AUTOPLAY_MODE_WARP :
+       AUTOPLAY_MODE_NONE);
+
     while (*str_ptr != '\0')			/* continue parsing string */
     {
       /* cut leading whitespace from string, replace it by string terminator */
@@ -5208,55 +4965,18 @@ void Execute_Command(char *command)
   }
   else if (strPrefix(command, "create images "))
   {
-#if defined(TARGET_SDL)
     global.create_images_dir = getStringCopy(&command[14]);
 
     if (access(global.create_images_dir, W_OK) != 0)
       Error(ERR_EXIT, "image target directory '%s' not found or not writable",
 	    global.create_images_dir);
-#else
-    Error(ERR_EXIT, "command only available for SDL target");
-#endif
   }
-
-#if DEBUG
-#if defined(TARGET_SDL)
-  else if (strEqual(command, "SDL_ListModes"))
+  else if (strPrefix(command, "create CE image "))
   {
-    SDL_Rect **modes;
-    int i;
-
-    SDL_Init(SDL_INIT_VIDEO);
-
-    /* get available fullscreen/hardware modes */
-    modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
-
-    /* check if there are any modes available */
-    if (modes == NULL)
-    {
-      printf("No modes available!\n");
-
-      exit(-1);
-    }
-
-    /* check if our resolution is restricted */
-    if (modes == (SDL_Rect **)-1)
-    {
-      printf("All resolutions available.\n");
-    }
-    else
-    {
-      printf("Available Modes:\n");
-
-      for(i = 0; modes[i]; i++)
-	printf("  %d x %d\n", modes[i]->w, modes[i]->h);
-    }
+    CreateCustomElementImages(&command[16]);
 
     exit(0);
   }
-#endif
-#endif
-
   else
   {
     Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
@@ -5317,33 +5037,15 @@ static char *get_level_id_suffix(int id_nr)
   return id_suffix;
 }
 
-#if 0
-static char *get_element_class_token(int element)
-{
-  char *element_class_name = element_info[element].class_name;
-  char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
-
-  sprintf(element_class_token, "[%s]", element_class_name);
-
-  return element_class_token;
-}
-
-static char *get_action_class_token(int action)
-{
-  char *action_class_name = &element_action_info[action].suffix[1];
-  char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
-
-  sprintf(action_class_token, "[%s]", action_class_name);
-
-  return action_class_token;
-}
-#endif
-
 static void InitArtworkConfig()
 {
-  static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
-  static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
-  static char *music_id_prefix[NUM_MUSIC_PREFIXES + 1];
+  static char *image_id_prefix[MAX_NUM_ELEMENTS +
+			       NUM_FONTS +
+			       NUM_GLOBAL_ANIM_TOKENS + 1];
+  static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS +
+			       NUM_GLOBAL_ANIM_TOKENS + 1];
+  static char *music_id_prefix[NUM_MUSIC_PREFIXES +
+			       NUM_GLOBAL_ANIM_TOKENS + 1];
   static char *action_id_suffix[NUM_ACTIONS + 1];
   static char *direction_id_suffix[NUM_DIRECTIONS_FULL + 1];
   static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
@@ -5402,18 +5104,27 @@ static void InitArtworkConfig()
     image_id_prefix[i] = element_info[i].token_name;
   for (i = 0; i < NUM_FONTS; i++)
     image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
-  image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
+  for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
+    image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + i] =
+      global_anim_info[i].token_name;
+  image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + NUM_GLOBAL_ANIM_TOKENS] = NULL;
 
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
     sound_id_prefix[i] = element_info[i].token_name;
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
     sound_id_prefix[MAX_NUM_ELEMENTS + i] =
       get_string_in_brackets(element_info[i].class_name);
-  sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
+  for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
+    sound_id_prefix[2 * MAX_NUM_ELEMENTS + i] =
+      global_anim_info[i].token_name;
+  sound_id_prefix[2 * MAX_NUM_ELEMENTS + NUM_GLOBAL_ANIM_TOKENS] = NULL;
 
   for (i = 0; i < NUM_MUSIC_PREFIXES; i++)
     music_id_prefix[i] = music_prefix_info[i].prefix;
-  music_id_prefix[NUM_MUSIC_PREFIXES] = NULL;
+  for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
+    music_id_prefix[NUM_MUSIC_PREFIXES + i] =
+      global_anim_info[i].token_name;
+  music_id_prefix[NUM_MUSIC_PREFIXES + NUM_GLOBAL_ANIM_TOKENS] = NULL;
 
   for (i = 0; i < NUM_ACTIONS; i++)
     action_id_suffix[i] = element_action_info[i].suffix;
@@ -5438,8 +5149,8 @@ static void InitArtworkConfig()
 		sound_id_prefix, action_id_suffix, dummy,
 		special_id_suffix, ignore_sound_tokens);
   InitMusicList(music_config, NUM_MUSIC_FILES, music_config_suffix,
-		music_id_prefix, special_id_suffix, level_id_suffix,
-		dummy, ignore_music_tokens);
+		music_id_prefix, action_id_suffix, special_id_suffix,
+		level_id_suffix, ignore_music_tokens);
 }
 
 static void InitMixer()
@@ -5451,12 +5162,25 @@ static void InitMixer()
 
 void InitGfxBuffers()
 {
-  ReCreateBitmap(&bitmap_db_store, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
-  ReCreateBitmap(&bitmap_db_cross, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
-  ReCreateBitmap(&bitmap_db_field, FXSIZE, FYSIZE, DEFAULT_DEPTH);
-  ReCreateBitmap(&bitmap_db_panel, DXSIZE, DYSIZE, DEFAULT_DEPTH);
-  ReCreateBitmap(&bitmap_db_door, 3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
-  ReCreateBitmap(&bitmap_db_toons, FULL_SXSIZE, FULL_SYSIZE, DEFAULT_DEPTH);
+  static int win_xsize_last = -1;
+  static int win_ysize_last = -1;
+
+  /* create additional image buffers for double-buffering and cross-fading */
+
+  if (WIN_XSIZE != win_xsize_last || WIN_YSIZE != win_ysize_last)
+  {
+    /* used to temporarily store the backbuffer -- only re-create if changed */
+    ReCreateBitmap(&bitmap_db_store_1, WIN_XSIZE, WIN_YSIZE);
+    ReCreateBitmap(&bitmap_db_store_2, WIN_XSIZE, WIN_YSIZE);
+
+    win_xsize_last = WIN_XSIZE;
+    win_ysize_last = WIN_YSIZE;
+  }
+
+  ReCreateBitmap(&bitmap_db_field, FXSIZE, FYSIZE);
+  ReCreateBitmap(&bitmap_db_panel, DXSIZE, DYSIZE);
+  ReCreateBitmap(&bitmap_db_door_1, 3 * DXSIZE, DYSIZE);
+  ReCreateBitmap(&bitmap_db_door_2, 3 * VXSIZE, VYSIZE);
 
   /* initialize screen properties */
   InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
@@ -5464,10 +5188,15 @@ void InitGfxBuffers()
 		   bitmap_db_field);
   InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
   InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
+  InitGfxDoor3Info(EX, EY, EXSIZE, EYSIZE);
   InitGfxWindowInfo(WIN_XSIZE, WIN_YSIZE);
   InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
   InitGfxClipRegion(FALSE, -1, -1, -1, -1);
 
+  /* required if door size definitions have changed */
+  InitGraphicCompatibilityInfo_Doors();
+
+  InitGfxBuffers_EM();
   InitGfxBuffers_SP();
 }
 
@@ -5517,28 +5246,9 @@ void InitGfx()
   if (filename_font_initial == NULL)	/* should not happen */
     Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
 
-#if 1
   InitGfxBuffers();
-#else
-  /* create additional image buffers for double-buffering and cross-fading */
-  bitmap_db_store = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
-  bitmap_db_cross = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
-  bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
-  bitmap_db_panel = CreateBitmap(DXSIZE, DYSIZE, DEFAULT_DEPTH);
-  bitmap_db_door  = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
-  bitmap_db_toons = CreateBitmap(FULL_SXSIZE, FULL_SYSIZE, DEFAULT_DEPTH);
-
-  /* initialize screen properties */
-  InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
-		   REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
-		   bitmap_db_field);
-  InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
-  InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
-  InitGfxWindowInfo(WIN_XSIZE, WIN_YSIZE);
-  InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
-#endif
-
   InitGfxCustomArtworkInfo();
+  InitGfxOtherSettings();
 
   bitmap_font_initial = LoadCustomImage(filename_font_initial);
 
@@ -5549,100 +5259,95 @@ void InitGfx()
 
   font_height = getFontHeight(FC_RED);
 
-#if 1
-  DrawInitText(getWindowTitleString(), 20, FC_YELLOW);
-#else
   DrawInitText(getProgramInitString(), 20, FC_YELLOW);
-#endif
-  DrawInitText(PROGRAM_COPYRIGHT_STRING, 50, FC_RED);
-  DrawInitText(PROGRAM_WEBSITE_STRING, WIN_YSIZE - 20 - font_height, FC_RED);
+  DrawInitText(setup.internal.program_copyright, 50, FC_RED);
+  DrawInitText(setup.internal.program_website, WIN_YSIZE - 20 - font_height,
+	       FC_RED);
 
   DrawInitText("Loading graphics", 120, FC_GREEN);
 
-#if 1
-#if 1
-  /* initialize busy animation with default values */
+  /* initialize settings for busy animation with default values */
   int parameter[NUM_GFX_ARGS];
   for (i = 0; i < NUM_GFX_ARGS; i++)
     parameter[i] = get_graphic_parameter_value(image_config_suffix[i].value,
                                                image_config_suffix[i].token,
                                                image_config_suffix[i].type);
-#if 0
-  for (i = 0; i < NUM_GFX_ARGS; i++)
-    printf("::: '%s' => %d\n", image_config_suffix[i].token, parameter[i]);
-#endif
-#endif
 
-  /* determine settings for busy animation (when displaying startup messages) */
-  for (i = 0; image_config[i].token != NULL; i++)
+  char *anim_token = CONFIG_TOKEN_GLOBAL_BUSY;
+  int len_anim_token = strlen(anim_token);
+
+  /* read settings for busy animation from default custom artwork config */
+  char *gfx_config_filename = getPath3(options.graphics_directory,
+				       GFX_DEFAULT_SUBDIR,
+				       GRAPHICSINFO_FILENAME);
+
+  if (fileExists(gfx_config_filename))
   {
-    char *anim_token = CONFIG_TOKEN_GLOBAL_BUSY;
-    int len_anim_token = strlen(anim_token);
+    SetupFileHash *setup_file_hash = loadSetupFileHash(gfx_config_filename);
 
-    if (strEqual(image_config[i].token, anim_token))
-      filename_anim_initial = image_config[i].value;
-    else if (strlen(image_config[i].token) > len_anim_token &&
-	     strncmp(image_config[i].token, anim_token, len_anim_token) == 0)
+    if (setup_file_hash)
     {
-#if 1
-      for (j = 0; image_config_suffix[j].token != NULL; j++)
+      char *filename = getHashEntry(setup_file_hash, anim_token);
+
+      if (filename)
       {
-	if (strEqual(&image_config[i].token[len_anim_token],
-		     image_config_suffix[j].token))
-	  parameter[j] =
-	    get_graphic_parameter_value(image_config[i].value,
-					image_config_suffix[j].token,
-					image_config_suffix[j].type);
+	filename_anim_initial = getStringCopy(filename);
+
+	for (j = 0; image_config_suffix[j].token != NULL; j++)
+	{
+	  int type = image_config_suffix[j].type;
+	  char *suffix = image_config_suffix[j].token;
+	  char *token = getStringCat2(anim_token, suffix);
+	  char *value = getHashEntry(setup_file_hash, token);
+
+	  checked_free(token);
+
+	  if (value)
+	    parameter[j] = get_graphic_parameter_value(value, suffix, type);
+	}
       }
-#else
-      if (strEqual(&image_config[i].token[len_anim_token], ".x"))
-	anim_initial.src_x = atoi(image_config[i].value);
-      else if (strEqual(&image_config[i].token[len_anim_token], ".y"))
-	anim_initial.src_y = atoi(image_config[i].value);
-      else if (strEqual(&image_config[i].token[len_anim_token], ".width"))
-	anim_initial.width = atoi(image_config[i].value);
-      else if (strEqual(&image_config[i].token[len_anim_token], ".height"))
-	anim_initial.height = atoi(image_config[i].value);
-      else if (strEqual(&image_config[i].token[len_anim_token], ".frames"))
-	anim_initial.anim_frames = atoi(image_config[i].value);
-      else if (strEqual(&image_config[i].token[len_anim_token],
-			".frames_per_line"))
-	anim_initial.anim_frames_per_line = atoi(image_config[i].value);
-      else if (strEqual(&image_config[i].token[len_anim_token], ".delay"))
-	anim_initial.anim_delay = atoi(image_config[i].value);
-#endif
+
+      freeSetupFileHash(setup_file_hash);
     }
   }
 
-#if defined(CREATE_SPECIAL_EDITION_RND_JUE)
-  filename_anim_initial = "loading.pcx";
-
-  parameter[GFX_ARG_X] = 0;
-  parameter[GFX_ARG_Y] = 0;
-  parameter[GFX_ARG_WIDTH] = 128;
-  parameter[GFX_ARG_HEIGHT] = 40;
-  parameter[GFX_ARG_FRAMES] = 32;
-  parameter[GFX_ARG_DELAY] = 4;
-  parameter[GFX_ARG_FRAMES_PER_LINE] = ARG_UNDEFINED_VALUE;
-#endif
+  if (filename_anim_initial == NULL)
+  {
+    /* read settings for busy animation from static default artwork config */
+    for (i = 0; image_config[i].token != NULL; i++)
+    {
+      if (strEqual(image_config[i].token, anim_token))
+	filename_anim_initial = getStringCopy(image_config[i].value);
+      else if (strlen(image_config[i].token) > len_anim_token &&
+	       strncmp(image_config[i].token, anim_token, len_anim_token) == 0)
+      {
+	for (j = 0; image_config_suffix[j].token != NULL; j++)
+	{
+	  if (strEqual(&image_config[i].token[len_anim_token],
+		       image_config_suffix[j].token))
+	    parameter[j] =
+	      get_graphic_parameter_value(image_config[i].value,
+					  image_config_suffix[j].token,
+					  image_config_suffix[j].type);
+	}
+      }
+    }
+  }
 
   if (filename_anim_initial == NULL)	/* should not happen */
     Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_GLOBAL_BUSY);
 
-  anim_initial.bitmap = LoadCustomImage(filename_anim_initial);
+  anim_initial.bitmaps =
+    checked_calloc(sizeof(Bitmap *) * NUM_IMG_BITMAP_POINTERS);
 
-  graphic_info = &anim_initial;		/* graphic == 0 => anim_initial */
+  anim_initial.bitmaps[IMG_BITMAP_STANDARD] =
+    LoadCustomImage(filename_anim_initial);
 
-  set_graphic_parameters_ext(0, parameter, anim_initial.bitmap);
+  checked_free(filename_anim_initial);
 
-#if 0
-  printf("::: INIT_GFX: anim_frames_per_line == %d [%d / %d] [%d, %d]\n",
-	 graphic_info[0].anim_frames_per_line,
-	 get_scaled_graphic_width(0),
-	 graphic_info[0].width,
-	 getOriginalImageWidthFromImageID(0),
-	 graphic_info[0].scale_up_factor);
-#endif
+  graphic_info = &anim_initial;		/* graphic == 0 => anim_initial */
+
+  set_graphic_parameters_ext(0, parameter, anim_initial.bitmaps);
 
   graphic_info = graphic_info_last;
 
@@ -5650,41 +5355,26 @@ void InitGfx()
   init.busy.height = anim_initial.height;
 
   InitMenuDesignSettings_Static();
+
   InitGfxDrawBusyAnimFunction(DrawInitAnim);
+  InitGfxDrawGlobalAnimFunction(DrawGlobalAnimations);
+  InitGfxDrawGlobalBorderFunction(DrawMaskedBorderToTarget);
+
+  gfx.fade_border_source_status = global.border_status;
+  gfx.fade_border_target_status = global.border_status;
+  gfx.masked_border_bitmap_ptr = backbuffer;
 
   /* use copy of busy animation to prevent change while reloading artwork */
   init_last = init;
-#endif
-}
-
-void RedrawBackground()
-{
-  BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
-	     0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
-
-  redraw_mask = REDRAW_ALL;
 }
 
 void InitGfxBackground()
 {
-  int x, y;
-
   fieldbuffer = bitmap_db_field;
-  SetDrawtoField(DRAW_BACKBUFFER);
+  SetDrawtoField(DRAW_TO_BACKBUFFER);
 
-#if 1
   ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
-#else
-  RedrawBackground();
-
-  ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
-  ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
-#endif
 
-  for (x = 0; x < MAX_BUF_XSIZE; x++)
-    for (y = 0; y < MAX_BUF_YSIZE; y++)
-      redraw[x][y] = 0;
-  redraw_tiles = 0;
   redraw_mask = REDRAW_ALL;
 }
 
@@ -5693,6 +5383,15 @@ static void InitLevelInfo()
   LoadLevelInfo();				/* global level info */
   LoadLevelSetup_LastSeries();			/* last played series info */
   LoadLevelSetup_SeriesInfo();			/* last played level info */
+
+  if (global.autoplay_leveldir &&
+      global.autoplay_mode != AUTOPLAY_MODE_TEST)
+  {
+    leveldir_current = getTreeInfoFromIdentifier(leveldir_first,
+                                                 global.autoplay_leveldir);
+    if (leveldir_current == NULL)
+      leveldir_current = getFirstValidTreeInfoEntry(leveldir_first);
+  }
 }
 
 static void InitLevelArtworkInfo()
@@ -5757,6 +5456,9 @@ static void InitImages()
   ReinitializeGraphics();
   print_timestamp_time("ReinitializeGraphics");
 
+  LoadMenuDesignSettings_AfterGraphics();
+  print_timestamp_time("LoadMenuDesignSettings_AfterGraphics");
+
   UPDATE_BUSY_STATE();
 
   print_timestamp_done("InitImages");
@@ -5800,6 +5502,11 @@ static void InitMusic(char *identifier)
   print_timestamp_done("InitMusic");
 }
 
+static void InitArtworkDone()
+{
+  InitGlobalAnimations();
+}
+
 void InitNetworkServer()
 {
 #if defined(NETWORK_AVALIABLE)
@@ -5948,19 +5655,11 @@ static char *getNewArtworkIdentifier(int type)
   static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
   static boolean initialized[3] = { FALSE, FALSE, FALSE };
   TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
-#if 1
   boolean setup_override_artwork = GFX_OVERRIDE_ARTWORK(type);
-#else
-  boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
-#endif
   char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
   char *leveldir_identifier = leveldir_current->identifier;
-#if 1
   /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
   char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
-#else
-  char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
-#endif
   boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
   char *artwork_current_identifier;
   char *artwork_new_identifier = NULL;	/* default: nothing has changed */
@@ -5990,16 +5689,6 @@ static char *getNewArtworkIdentifier(int type)
   /* 2nd step: check if it is really needed to reload artwork set
      ------------------------------------------------------------ */
 
-#if 0
-  if (type == ARTWORK_TYPE_GRAPHICS)
-    printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
-	   artwork_new_identifier,
-	   ARTWORK_CURRENT_IDENTIFIER(artwork, type),
-	   artwork_current_identifier,
-	   leveldir_current->graphics_set,
-	   leveldir_current->identifier);
-#endif
-
   /* ---------- reload if level set and also artwork set has changed ------- */
   if (leveldir_current_identifier[type] != leveldir_identifier &&
       (last_has_level_artwork_set[type] || has_level_artwork_set))
@@ -6008,22 +5697,12 @@ static char *getNewArtworkIdentifier(int type)
   leveldir_current_identifier[type] = leveldir_identifier;
   last_has_level_artwork_set[type] = has_level_artwork_set;
 
-#if 0
-  if (type == ARTWORK_TYPE_GRAPHICS)
-    printf("::: 1: '%s'\n", artwork_new_identifier);
-#endif
-
   /* ---------- reload if "override artwork" setting has changed ----------- */
   if (last_override_level_artwork[type] != setup_override_artwork)
     artwork_new_identifier = artwork_current_identifier;
 
   last_override_level_artwork[type] = setup_override_artwork;
 
-#if 0
-  if (type == ARTWORK_TYPE_GRAPHICS)
-    printf("::: 2: '%s'\n", artwork_new_identifier);
-#endif
-
   /* ---------- reload if current artwork identifier has changed ----------- */
   if (!strEqual(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
 		artwork_current_identifier))
@@ -6031,30 +5710,12 @@ static char *getNewArtworkIdentifier(int type)
 
   *(ARTWORK_CURRENT_IDENTIFIER_PTR(artwork, type))= artwork_current_identifier;
 
-#if 0
-  if (type == ARTWORK_TYPE_GRAPHICS)
-    printf("::: 3: '%s'\n", artwork_new_identifier);
-#endif
-
   /* ---------- do not reload directly after starting ---------------------- */
   if (!initialized[type])
     artwork_new_identifier = NULL;
 
   initialized[type] = TRUE;
 
-#if 0
-  if (type == ARTWORK_TYPE_GRAPHICS)
-    printf("::: 4: '%s'\n", artwork_new_identifier);
-#endif
-
-#if 0
-  if (type == ARTWORK_TYPE_GRAPHICS)
-    printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
-	   artwork.gfx_current_identifier, artwork_current_identifier,
-	   artwork.gfx_current->identifier, leveldir_current->graphics_set,
-	   artwork_new_identifier);
-#endif
-
   return artwork_new_identifier;
 }
 
@@ -6086,24 +5747,14 @@ void ReloadCustomArtwork(int force_reload)
 
   print_timestamp_init("ReloadCustomArtwork");
 
-  game_status = GAME_MODE_LOADING;
+  SetGameStatus(GAME_MODE_LOADING);
 
   FadeOut(REDRAW_ALL);
 
-#if 1
   ClearRectangle(drawto, 0, 0, WIN_XSIZE, WIN_YSIZE);
-#else
-  ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
-#endif
   print_timestamp_time("ClearRectangle");
 
-#if 0
-  printf("::: fading in ... %d\n", fading.fade_mode);
-#endif
   FadeIn(REDRAW_ALL);
-#if 0
-  printf("::: done\n");
-#endif
 
   if (gfx_new_identifier != NULL || force_reload_gfx)
   {
@@ -6131,48 +5782,26 @@ void ReloadCustomArtwork(int force_reload)
     print_timestamp_time("InitMusic");
   }
 
-  game_status = last_game_status;	/* restore current game status */
+  InitArtworkDone();
 
-  init_last = init;			/* switch to new busy animation */
+  SetGameStatus(last_game_status);	/* restore current game status */
 
-#if 0
-  printf("::: ----------------DELAY 1 ...\n");
-  Delay(3000);
-#endif
+  init_last = init;			/* switch to new busy animation */
 
-#if 0
-  printf("::: FadeOut @ ReloadCustomArtwork ...\n");
-#endif
   FadeOut(REDRAW_ALL);
-#if 0
-  printf("::: FadeOut @ ReloadCustomArtwork done\n");
-#endif
 
-  RedrawBackground();
+  RedrawGlobalBorder();
 
   /* force redraw of (open or closed) door graphics */
   SetDoorState(DOOR_OPEN_ALL);
   CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
 
-#if 1
-#if 1
-#if 1
   FadeSetEnterScreen();
   FadeSkipNextFadeOut();
-  // FadeSetDisabled();
-#else
-  FadeSkipNext();
-#endif
-#else
-  fading = fading_none;
-#endif
-#endif
-
-#if 0
-  redraw_mask = REDRAW_ALL;
-#endif
 
   print_timestamp_done("ReloadCustomArtwork");
+
+  LimitScreenUpdates(FALSE);
 }
 
 void KeyboardAutoRepeatOffUnlessAutoplay()
@@ -6181,6 +5810,66 @@ void KeyboardAutoRepeatOffUnlessAutoplay()
     KeyboardAutoRepeatOff();
 }
 
+void DisplayExitMessage(char *format, va_list ap)
+{
+  // check if draw buffer and fonts for exit message are already available
+  if (drawto == NULL || font_initial[NUM_INITIAL_FONTS - 1].bitmap == NULL)
+    return;
+
+  int font_1 = FC_RED;
+  int font_2 = FC_YELLOW;
+  int font_3 = FC_BLUE;
+  int font_width = getFontWidth(font_2);
+  int font_height = getFontHeight(font_2);
+  int sx = SX;
+  int sy = SY;
+  int sxsize = WIN_XSIZE - 2 * sx;
+  int sysize = WIN_YSIZE - 2 * sy;
+  int line_length = sxsize / font_width;
+  int max_lines = sysize / font_height;
+  int num_lines_printed;
+
+  gfx.sx = sx;
+  gfx.sy = sy;
+  gfx.sxsize = sxsize;
+  gfx.sysize = sysize;
+
+  sy = 20;
+
+  ClearRectangle(drawto, 0, 0, WIN_XSIZE, WIN_YSIZE);
+
+  DrawTextSCentered(sy, font_1, "Fatal error:");
+  sy += 3 * font_height;;
+
+  num_lines_printed =
+    DrawTextBufferVA(sx, sy, format, ap, font_2,
+		     line_length, line_length, max_lines,
+		     0, BLIT_ON_BACKGROUND, TRUE, TRUE, FALSE);
+  sy += (num_lines_printed + 3) * font_height;
+
+  DrawTextSCentered(sy, font_1, "For details, see the following error file:");
+  sy += 3 * font_height;
+
+  num_lines_printed =
+    DrawTextBuffer(sx, sy, program.log_filename[LOG_ERR_ID], font_2,
+		   line_length, line_length, max_lines,
+		   0, BLIT_ON_BACKGROUND, TRUE, TRUE, FALSE);
+
+  DrawTextSCentered(SYSIZE - 20, font_3, "Press any key or button to exit");
+
+  redraw_mask = REDRAW_ALL;
+
+  /* force drawing exit message even if screen updates are currently limited */
+  LimitScreenUpdates(FALSE);
+
+  BackToFront();
+
+  /* deactivate toons on error message screen */
+  setup.toons = FALSE;
+
+  WaitForEventToContinue();
+}
+
 
 /* ========================================================================= */
 /* OpenAll()                                                                 */
@@ -6190,16 +5879,20 @@ void OpenAll()
 {
   print_timestamp_init("OpenAll");
 
-  game_status = GAME_MODE_LOADING;
+  SetGameStatus(GAME_MODE_LOADING);
 
-#if 1
   InitCounter();
-#endif
 
   InitGlobal();			/* initialize some global variables */
 
   print_timestamp_time("[init global stuff]");
 
+  InitSetup();
+
+  print_timestamp_time("[init setup/config stuff (1)]");
+
+  InitScoresInfo();
+
   if (options.execute_command)
     Execute_Command(options.execute_command);
 
@@ -6214,17 +5907,16 @@ void OpenAll()
     exit(0);			/* never reached, server loops forever */
   }
 
-  InitSetup();
-
   InitGameInfo();
+  print_timestamp_time("[init setup/config stuff (2)]");
   InitPlayerInfo();
+  print_timestamp_time("[init setup/config stuff (3)]");
   InitArtworkInfo();		/* needed before loading gfx, sound & music */
+  print_timestamp_time("[init setup/config stuff (4)]");
   InitArtworkConfig();		/* needed before forking sound child process */
+  print_timestamp_time("[init setup/config stuff (5)]");
   InitMixer();
-
-#if 0
-  InitCounter();
-#endif
+  print_timestamp_time("[init setup/config stuff (6)]");
 
   InitRND(NEW_RANDOMIZE);
   InitSimpleRandom(NEW_RANDOMIZE);
@@ -6236,7 +5928,7 @@ void OpenAll()
   InitVideoDisplay();
   InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
 
-  InitEventFilter(FilterMouseMotionEvents);
+  InitOverlayInfo();
 
   print_timestamp_time("[init video stuff]");
 
@@ -6268,15 +5960,12 @@ void OpenAll()
   InitMusic(NULL);		/* needs to know current level directory */
   print_timestamp_time("InitMusic");
 
+  InitArtworkDone();
+
   InitGfxBackground();
 
-#if 1
   em_open_all();
-#endif
-
-#if 1
   sp_open_all();
-#endif
 
   if (global.autoplay_leveldir)
   {
@@ -6294,16 +5983,11 @@ void OpenAll()
     return;
   }
 
-  game_status = GAME_MODE_MAIN;
+  SetGameStatus(GAME_MODE_MAIN);
 
-#if 1
   FadeSetEnterScreen();
   if (!(fading.fade_mode & FADE_TYPE_TRANSFORM))
     FadeSkipNextFadeOut();
-  // FadeSetDisabled();
-#else
-  fading = fading_none;
-#endif
 
   print_timestamp_time("[post-artwork]");
 
@@ -6312,6 +5996,24 @@ void OpenAll()
   DrawMainMenu();
 
   InitNetworkServer();
+
+#if 0
+  Error(ERR_DEBUG, "::: SDL_GetBasePath() == '%s'",
+	SDL_GetBasePath());
+  Error(ERR_DEBUG, "::: SDL_GetPrefPath() == '%s'",
+	SDL_GetPrefPath("artsoft", "rocksndiamonds"));
+#if defined(PLATFORM_ANDROID)
+  Error(ERR_DEBUG, "::: SDL_AndroidGetInternalStoragePath() == '%s'",
+	SDL_AndroidGetInternalStoragePath());
+  Error(ERR_DEBUG, "::: SDL_AndroidGetExternalStoragePath() == '%s'",
+	SDL_AndroidGetExternalStoragePath());
+  Error(ERR_DEBUG, "::: SDL_AndroidGetExternalStorageState() == '%s'",
+	(SDL_AndroidGetExternalStorageState() ==
+	 SDL_ANDROID_EXTERNAL_STORAGE_READ ? "read" :
+	 SDL_AndroidGetExternalStorageState() ==
+	 SDL_ANDROID_EXTERNAL_STORAGE_WRITE ? "write" : "not available"));
+#endif
+#endif
 }
 
 void CloseAllAndExit(int exit_value)
@@ -6321,26 +6023,34 @@ void CloseAllAndExit(int exit_value)
   FreeAllMusic();
   CloseAudio();		/* called after freeing sounds (needed for SDL) */
 
-#if 1
   em_close_all();
-#endif
-
-#if 1
   sp_close_all();
-#endif
 
   FreeAllImages();
 
 #if defined(TARGET_SDL)
+#if defined(TARGET_SDL2)
+  // !!! TODO !!!
+  // set a flag to tell the network server thread to quit and wait for it
+  // using SDL_WaitThread()
+#else
   if (network_server)	/* terminate network server */
     SDL_KillThread(server_thread);
 #endif
+#endif
 
   CloseVideoDisplay();
   ClosePlatformDependentStuff();
 
   if (exit_value != 0)
-    NotifyUserAboutErrorFile();
+  {
+    /* fall back to default level set (current set may have caused an error) */
+    SaveLevelSetup_LastSeries_Deactivate();
+
+    /* tell user where to find error log file which may contain more details */
+    // (error notification now directly displayed on screen inside R'n'D
+    // NotifyUserAboutErrorFile();	/* currently only works for Windows */
+  }
 
   exit(exit_value);
 }
diff --git a/src/init.h b/src/init.h
index 42bc9f7..ab14b75 100644
--- a/src/init.h
+++ b/src/init.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* init.h                                                   *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// init.h
+// ============================================================================
 
 #ifndef INIT_H
 #define INIT_H
@@ -39,12 +37,15 @@ void InitElementPropertiesAfterLoading(int);
 void InitElementPropertiesGfxElement();
 
 void ReloadCustomArtwork(int);
-void RedrawBackground();
+void RedrawGlobalBorder();
 
 void KeyboardAutoRepeatOffUnlessAutoplay();
 
 void InitGfxBuffers();
 void InitGadgets();
+void InitImageTextures();
+
+void DisplayExitMessage(char *, va_list);
 
 void OpenAll(void);
 void CloseAllAndExit(int);
diff --git a/src/libgame/Makefile b/src/libgame/Makefile
index 140e9fd..4693c22 100644
--- a/src/libgame/Makefile
+++ b/src/libgame/Makefile
@@ -1,7 +1,12 @@
 # =============================================================================
-# Rocks'n'Diamonds Makefile (libgame)
+# Rocks'n'Diamonds - McDuffin Strikes Back!
 # -----------------------------------------------------------------------------
-# (c) 1995-2006 Holger Schemel <info at artsoft.org>
+# (c) 1995-2014 by Artsoft Entertainment
+#                  Holger Schemel
+#                  info at artsoft.org
+#                  http://www.artsoft.org/
+# -----------------------------------------------------------------------------
+# src/libgame/Makefile
 # =============================================================================
 
 # -----------------------------------------------------------------------------
@@ -14,15 +19,11 @@ SRCS =	system.c	\
 	sound.c		\
 	joystick.c	\
 	snapshot.c	\
-	toons.c		\
-	pcx.c		\
 	image.c		\
 	random.c	\
 	hash.c		\
 	setup.c		\
 	misc.c		\
-	msdos.c		\
-	x11.c		\
 	sdl.c
 
 OBJS =	system.o	\
@@ -31,15 +32,11 @@ OBJS =	system.o	\
 	sound.o		\
 	snapshot.o	\
 	joystick.o	\
-	toons.o		\
-	pcx.o		\
 	image.o		\
 	random.o	\
 	hash.o		\
 	setup.o		\
 	misc.o		\
-	msdos.o		\
-	x11.o		\
 	sdl.o
 
 LIBGAME = libgame.a
diff --git a/src/libgame/android.h b/src/libgame/android.h
new file mode 100644
index 0000000..fc47768
--- /dev/null
+++ b/src/libgame/android.h
@@ -0,0 +1,18 @@
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// android.h
+// ============================================================================
+
+#ifndef ANDROID_H
+#define ANDROID_H
+
+#include <android/log.h>
+
+
+#endif /* ANDROID_H */
diff --git a/src/libgame/gadgets.c b/src/libgame/gadgets.c
index 4ac2a29..98e46a5 100644
--- a/src/libgame/gadgets.c
+++ b/src/libgame/gadgets.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* gadgets.c                                                *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// gadgets.c
+// ============================================================================
 
 #include <stdarg.h>
 #include <string.h>
@@ -26,6 +24,14 @@
 #define DG_BUFFERED		0
 #define DG_DIRECT		1
 
+#define OPTION_TEXT_SELECTABLE(g, t)					\
+  (t[0] != g->selectbox.char_unselectable &&				\
+   t[0] != '\0' &&							\
+   !strEqual(t, " "))
+#define CURRENT_OPTION_SELECTABLE(g)					\
+  OPTION_TEXT_SELECTABLE(g, g->selectbox.options[g->selectbox.current_index].text)
+
+
 static struct GadgetInfo *gadget_list_first_entry = NULL;
 static struct GadgetInfo *gadget_list_last_entry = NULL;
 static struct GadgetInfo *last_info_gi = NULL;
@@ -88,6 +94,16 @@ static struct GadgetInfo *getGadgetInfoFromMousePosition(int mx, int my,
     boolean check_horizontal = (IS_WHEEL_BUTTON_HORIZONTAL(button) ||
 				GetKeyModState() & KMOD_Shift);
 
+    /* check for the first active scrollbar directly under the mouse pointer */
+    for (gi = gadget_list_first_entry; gi != NULL; gi = gi->next)
+    {
+      if (gi->mapped && gi->active &&
+	  (gi->type & GD_TYPE_SCROLLBAR) &&
+	  mx >= gi->x && mx < gi->x + gi->width &&
+	  my >= gi->y && my < gi->y + gi->height)
+	return gi;
+    }
+
     /* check for the first active scrollbar with matching mouse wheel area */
     for (gi = gadget_list_first_entry; gi != NULL; gi = gi->next)
     {
@@ -202,7 +218,7 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
   int state = (pressed ? GD_BUTTON_PRESSED : GD_BUTTON_UNPRESSED);
   boolean redraw_selectbox = FALSE;
 
-  if (gi == NULL)
+  if (gi == NULL || gi->deactivated)
     return;
 
   gd = (!gi->active ? &gi->alt_design[state] :
@@ -213,15 +229,31 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
     case GD_TYPE_NORMAL_BUTTON:
     case GD_TYPE_CHECK_BUTTON:
     case GD_TYPE_RADIO_BUTTON:
+
       BlitBitmapOnBackground(gd->bitmap, drawto,
 			     gd->x, gd->y, gi->width, gi->height,
 			     gi->x, gi->y);
+
       if (gi->deco.design.bitmap)
-	BlitBitmap(gi->deco.design.bitmap, drawto,
-		   gi->deco.design.x, gi->deco.design.y,
-		   gi->deco.width, gi->deco.height,
-		   gi->x + gi->deco.x + (pressed ? gi->deco.xshift : 0),
-		   gi->y + gi->deco.y + (pressed ? gi->deco.yshift : 0));
+      {
+	// make sure that decoration does not overlap gadget border
+	int deco_x = gi->deco.x + (pressed ? gi->deco.xshift : 0);
+	int deco_y = gi->deco.y + (pressed ? gi->deco.yshift : 0);
+	int deco_width  = MIN(gi->deco.width,  gi->width  - deco_x);
+	int deco_height = MIN(gi->deco.height, gi->height - deco_y);
+
+	if (gi->deco.masked)
+	  BlitBitmapMasked(gi->deco.design.bitmap, drawto,
+			   gi->deco.design.x, gi->deco.design.y,
+			   deco_width, deco_height,
+			   gi->x + deco_x, gi->y + deco_y);
+	else
+	  BlitBitmap(gi->deco.design.bitmap, drawto,
+		     gi->deco.design.x, gi->deco.design.y,
+		     deco_width, deco_height,
+		     gi->x + deco_x, gi->y + deco_y);
+      }
+
       break;
 
     case GD_TYPE_TEXT_BUTTON:
@@ -381,16 +413,9 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
 				   gi->height - 2 * border_y);
 
 	/* gadget text value */
-#if 1
 	DrawTextBuffer(gi->x + border_x, gi->y + border_y, gi->textarea.value,
-		       font_nr, gi->textarea.xsize, 0, -1, gi->textarea.ysize,
+		       font_nr, gi->textarea.xsize, -1, gi->textarea.ysize, 0,
 		       BLIT_ON_BACKGROUND, FALSE, FALSE, FALSE);
-#else
-	DrawTextToTextArea(gi->x + border_x, gi->y + border_y,
-			   gi->textarea.value, font_nr, gi->textarea.xsize,
-			   gi->textarea.xsize, gi->textarea.ysize,
-			   BLIT_ON_BACKGROUND);
-#endif
 
 	cursor_letter = gi->textarea.value[gi->textarea.cursor_position];
 	cursor_string[0] = (cursor_letter != '\0' ? cursor_letter : ' ');
@@ -410,7 +435,8 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
       {
 	int i;
 	char text[MAX_GADGET_TEXTSIZE + 1];
-	int font_nr = (pressed ? gi->font_active : gi->font);
+	int font_nr_default = (pressed ? gi->font_active : gi->font);
+	int font_nr = font_nr_default;
 	int font_width = getFontWidth(font_nr);
 	int font_height = getFontHeight(font_nr);
 	int border_x = gi->border.xsize;
@@ -447,6 +473,10 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
 		gi->selectbox.size);
 	text[gi->selectbox.size] = '\0';
 
+	/* set font value */
+	font_nr = (OPTION_TEXT_SELECTABLE(gi, text) ? font_nr_default :
+		   gi->font_unselectable);
+
 	/* gadget text value */
 	DrawTextExt(drawto, gi->x + border_x, gi->y + border_y, text,
 		    font_nr, BLIT_MASKED);
@@ -555,7 +585,11 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
 	    strncpy(text, gi->selectbox.options[i].text, gi->selectbox.size);
 	    text[gi->selectbox.size] = '\0';
 
-	    if (i == gi->selectbox.current_index)
+	    font_nr = (OPTION_TEXT_SELECTABLE(gi, text) ? font_nr_default :
+		       gi->font_unselectable);
+
+	    if (i == gi->selectbox.current_index &&
+		OPTION_TEXT_SELECTABLE(gi, text))
 	    {
 	      FillRectangle(drawto,
 			    gi->selectbox.x + border_x,
@@ -694,6 +728,10 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
       return;
   }
 
+  // do not use direct gadget drawing anymore; this worked as a speed-up once,
+  // but would slow things down a lot now the screen is always fully redrawn
+  direct = FALSE;
+
   if (direct)
   {
     BlitBitmap(drawto, window,
@@ -706,9 +744,15 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
 		 gi->selectbox.x,     gi->selectbox.y);
   }
   else
-    redraw_mask |= (gi->x < gfx.sx + gfx.sxsize ? REDRAW_FIELD :
-		    gi->y < gfx.dy + gfx.dysize ? REDRAW_DOOR_1 :
-		    gi->y > gfx.vy ? REDRAW_DOOR_2 : REDRAW_DOOR_3);
+  {
+    int x = gi->x;
+    int y = gi->y;
+
+    redraw_mask |= (IN_GFX_FIELD_FULL(x, y) ? REDRAW_FIELD :
+		    IN_GFX_DOOR_1(x, y) ? REDRAW_DOOR_1 :
+		    IN_GFX_DOOR_2(x, y) ? REDRAW_DOOR_2 :
+		    IN_GFX_DOOR_3(x, y) ? REDRAW_DOOR_3 : REDRAW_ALL);
+  }
 }
 
 static int get_minimal_size_for_numeric_input(int minmax_value)
@@ -731,7 +775,7 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
 {
   int tag = first_tag;
 
-  if (gi == NULL)
+  if (gi == NULL || gi->deactivated)
     return;
 
   while (tag != GDI_END)
@@ -873,12 +917,18 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
 	gi->font = va_arg(ap, int);
 	if (gi->font_active == 0)
 	  gi->font_active = gi->font;
+	if (gi->font_unselectable == 0)
+	  gi->font_unselectable = gi->font;
 	break;
 
       case GDI_TEXT_FONT_ACTIVE:
 	gi->font_active = va_arg(ap, int);
 	break;
 
+      case GDI_TEXT_FONT_UNSELECTABLE:
+	gi->font_unselectable = va_arg(ap, int);
+	break;
+
       case GDI_SELECTBOX_OPTIONS:
 	gi->selectbox.options = va_arg(ap, struct ValueTextInfo *);
 	break;
@@ -887,6 +937,10 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
 	gi->selectbox.index = va_arg(ap, int);
 	break;
 
+      case GDI_SELECTBOX_CHAR_UNSELECTABLE:
+	gi->selectbox.char_unselectable = (char)va_arg(ap, int);
+	break;
+
       case GDI_DESIGN_UNPRESSED:
 	gi->design[GD_BUTTON_UNPRESSED].bitmap = va_arg(ap, Bitmap *);
 	gi->design[GD_BUTTON_UNPRESSED].x = va_arg(ap, int);
@@ -945,6 +999,10 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
 	gi->deco.yshift = va_arg(ap, int);
 	break;
 
+      case GDI_DECORATION_MASKED:
+	gi->deco.masked = (boolean)va_arg(ap, int);
+	break;
+
       case GDI_EVENT_MASK:
 	gi->event_mask = va_arg(ap, unsigned int);
 	break;
@@ -954,14 +1012,12 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
 	gi->drawing.area_ysize = va_arg(ap, int);
 
 	/* determine dependent values for drawing area gadget, if needed */
-	if (gi->width == 0 && gi->height == 0 &&
-	    gi->drawing.item_xsize !=0 && gi->drawing.item_ysize !=0)
+	if (gi->drawing.item_xsize != 0 && gi->drawing.item_ysize != 0)
 	{
 	  gi->width = gi->drawing.area_xsize * gi->drawing.item_xsize;
 	  gi->height = gi->drawing.area_ysize * gi->drawing.item_ysize;
 	}
-	else if (gi->drawing.item_xsize == 0 && gi->drawing.item_ysize == 0 &&
-		 gi->width != 0 && gi->height != 0)
+	else if (gi->width != 0 && gi->height != 0)
 	{
 	  gi->drawing.item_xsize = gi->width / gi->drawing.area_xsize;
 	  gi->drawing.item_ysize = gi->height / gi->drawing.area_ysize;
@@ -984,14 +1040,12 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
 	gi->drawing.item_ysize = va_arg(ap, int);
 
 	/* determine dependent values for drawing area gadget, if needed */
-	if (gi->width == 0 && gi->height == 0 &&
-	    gi->drawing.area_xsize !=0 && gi->drawing.area_ysize !=0)
+	if (gi->drawing.area_xsize != 0 && gi->drawing.area_ysize != 0)
 	{
 	  gi->width = gi->drawing.area_xsize * gi->drawing.item_xsize;
 	  gi->height = gi->drawing.area_ysize * gi->drawing.item_ysize;
 	}
-	else if (gi->drawing.area_xsize == 0 && gi->drawing.area_ysize == 0 &&
-		 gi->width != 0 && gi->height != 0)
+	else if (gi->width != 0 && gi->height != 0)
 	{
 	  gi->drawing.area_xsize = gi->width / gi->drawing.item_xsize;
 	  gi->drawing.area_ysize = gi->height / gi->drawing.item_ysize;
@@ -1041,11 +1095,17 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
     tag = va_arg(ap, int);	/* read next tag */
   }
 
-  /* check if gadget is complete */
+  gi->deactivated = FALSE;
+
+  /* check if gadget has undefined bitmaps */
   if (gi->type != GD_TYPE_DRAWING_AREA &&
-      (!gi->design[GD_BUTTON_UNPRESSED].bitmap ||
-       !gi->design[GD_BUTTON_PRESSED].bitmap))
-    Error(ERR_EXIT, "gadget incomplete (missing Bitmap)");
+      (gi->design[GD_BUTTON_UNPRESSED].bitmap == NULL ||
+       gi->design[GD_BUTTON_PRESSED].bitmap == NULL))
+    gi->deactivated = TRUE;
+
+  /* check if gadget is placed off-screen */
+  if (gi->x < 0 || gi->y < 0)
+    gi->deactivated = TRUE;
 
   /* adjust gadget values in relation to other gadget values */
 
@@ -1207,7 +1267,7 @@ void ModifyGadget(struct GadgetInfo *gi, int first_tag, ...)
 
 void RedrawGadget(struct GadgetInfo *gi)
 {
-  if (gi == NULL)
+  if (gi == NULL || gi->deactivated)
     return;
 
   if (gi->mapped)
@@ -1248,6 +1308,9 @@ void FreeGadget(struct GadgetInfo *gi)
 {
   struct GadgetInfo *gi_previous = gadget_list_first_entry;
 
+  if (gi == NULL)
+    return;
+
   /* prevent "last_info_gi" from pointing to memory that will be freed */
   if (last_info_gi == gi)
     last_info_gi = NULL;
@@ -1292,7 +1355,7 @@ static struct GadgetInfo *last_gi = NULL;
 
 static void MapGadgetExt(struct GadgetInfo *gi, boolean redraw)
 {
-  if (gi == NULL || gi->mapped)
+  if (gi == NULL || gi->deactivated || gi->mapped)
     return;
 
   gi->mapped = TRUE;
@@ -1308,7 +1371,7 @@ void MapGadget(struct GadgetInfo *gi)
 
 void UnmapGadget(struct GadgetInfo *gi)
 {
-  if (gi == NULL || !gi->mapped)
+  if (gi == NULL || gi->deactivated || !gi->mapped)
     return;
 
   gi->mapped = FALSE;
@@ -1324,9 +1387,11 @@ void UnmapGadget(struct GadgetInfo *gi)
 #define MULTIMAP_PLAYFIELD	(1 << 3)
 #define MULTIMAP_DOOR_1		(1 << 4)
 #define MULTIMAP_DOOR_2		(1 << 5)
+#define MULTIMAP_DOOR_3		(1 << 6)
 #define MULTIMAP_ALL		(MULTIMAP_PLAYFIELD | \
-				 MULTIMAP_DOOR_1 | \
-				 MULTIMAP_DOOR_2)
+				 MULTIMAP_DOOR_1    | \
+				 MULTIMAP_DOOR_2    | \
+				 MULTIMAP_DOOR_3)
 
 static void MultiMapGadgets(int mode)
 {
@@ -1336,12 +1401,13 @@ static void MultiMapGadgets(int mode)
 
   while (gi != NULL)
   {
-    if ((mode & MULTIMAP_PLAYFIELD &&
-	 gi->x < gfx.sx + gfx.sxsize) ||
-	(mode & MULTIMAP_DOOR_1 &&
-	 gi->x >= gfx.dx && gi->y < gfx.dy + gfx.dysize) ||
-	(mode & MULTIMAP_DOOR_2 &&
-	 gi->x >= gfx.dx && gi->y > gfx.dy + gfx.dysize) ||
+    int x = gi->x;
+    int y = gi->y;
+
+    if ((mode & MULTIMAP_PLAYFIELD && IN_GFX_FIELD_FULL(x, y)) ||
+	(mode & MULTIMAP_DOOR_1 && IN_GFX_DOOR_1(x, y)) ||
+	(mode & MULTIMAP_DOOR_2 && IN_GFX_DOOR_2(x, y)) ||
+	(mode & MULTIMAP_DOOR_3 && IN_GFX_DOOR_3(x, y)) ||
 	(mode & MULTIMAP_ALL) == MULTIMAP_ALL)
     {
       if (mode & MULTIMAP_UNMAP)
@@ -1399,18 +1465,18 @@ boolean anyTextGadgetActive()
 
 static boolean insideSelectboxLine(struct GadgetInfo *gi, int mx, int my)
 {
-  return(gi != NULL &&
-	 gi->type & GD_TYPE_SELECTBOX &&
-	 mx >= gi->x && mx < gi->x + gi->width &&
-	 my >= gi->y && my < gi->y + gi->height);
+  return (gi != NULL &&
+	  gi->type & GD_TYPE_SELECTBOX &&
+	  mx >= gi->x && mx < gi->x + gi->width &&
+	  my >= gi->y && my < gi->y + gi->height);
 }
 
 static boolean insideSelectboxArea(struct GadgetInfo *gi, int mx, int my)
 {
-  return(gi != NULL &&
-	 gi->type & GD_TYPE_SELECTBOX &&
-	 mx >= gi->selectbox.x && mx < gi->selectbox.x + gi->selectbox.width &&
-	 my >= gi->selectbox.y && my < gi->selectbox.y + gi->selectbox.height);
+  return (gi != NULL &&
+	  gi->type & GD_TYPE_SELECTBOX &&
+	  mx >= gi->selectbox.x && mx < gi->selectbox.x + gi->selectbox.width &&
+	  my >= gi->selectbox.y && my < gi->selectbox.y + gi->selectbox.height);
 }
 
 void ClickOnGadget(struct GadgetInfo *gi, int button)
@@ -1431,8 +1497,8 @@ void ClickOnGadget(struct GadgetInfo *gi, int button)
 
 boolean HandleGadgets(int mx, int my, int button)
 {
-  static unsigned long pressed_delay = 0;
-  static unsigned long pressed_delay_value = GADGET_FRAME_DELAY;
+  static unsigned int pressed_delay = 0;
+  static unsigned int pressed_delay_value = GADGET_FRAME_DELAY;
   static int last_button = 0;
   static int last_mx = 0, last_my = 0;
   static int pressed_mx = 0, pressed_my = 0;
@@ -1458,7 +1524,6 @@ boolean HandleGadgets(int mx, int my, int button)
   boolean gadget_dragging;
   boolean gadget_released;
   boolean gadget_released_inside;
-  boolean gadget_released_inside_select_line;
   boolean gadget_released_inside_select_area;
   boolean gadget_released_off_borders;
   boolean changed_position = FALSE;
@@ -1540,6 +1605,8 @@ boolean HandleGadgets(int mx, int my, int button)
 
     if (gadget_pressed_inside_select_line)
       new_gi = NULL;
+
+    StopTextInput();
   }
 
   gadget_pressed =
@@ -1560,15 +1627,9 @@ boolean HandleGadgets(int mx, int my, int button)
 
   /* when handling selectbox, set additional state values */
   if (gadget_released_inside && (last_gi->type & GD_TYPE_SELECTBOX))
-  {
-    gadget_released_inside_select_line = insideSelectboxLine(last_gi, mx, my);
     gadget_released_inside_select_area = insideSelectboxArea(last_gi, mx, my);
-  }
   else
-  {
-    gadget_released_inside_select_line = FALSE;
     gadget_released_inside_select_area = FALSE;
-  }
 
   /* setting state for handling over-large selectbox */
   if (keep_selectbox_open && (press_event || !mouse_inside_select_line))
@@ -1592,7 +1653,8 @@ boolean HandleGadgets(int mx, int my, int button)
     if (gi->type & GD_TYPE_SELECTBOX &&
 	(keep_selectbox_open ||
 	 mouse_released_where_pressed ||
-	 !gadget_released_inside_select_area))	     /* selectbox stays open */
+	 !gadget_released_inside_select_area ||
+	 !CURRENT_OPTION_SELECTABLE(gi)))	    /* selectbox stays open */
     {
       gi->selectbox.stay_open = TRUE;
       pressed_mx = 0;
@@ -1646,6 +1708,9 @@ boolean HandleGadgets(int mx, int my, int button)
 
       if (gi->textinput.cursor_position != old_cursor_position)
 	DrawGadget(gi, DG_PRESSED, gi->direct_draw);
+
+      if (press_event)
+	StartTextInput(gi->x, gi->y, gi->width, gi->height);
     }
     else if (gi->type & GD_TYPE_TEXT_AREA && button != 0 && !motion_status)
     {
@@ -1660,6 +1725,9 @@ boolean HandleGadgets(int mx, int my, int button)
 
       if (gi->textarea.cursor_position != old_cursor_position)
 	DrawGadget(gi, DG_PRESSED, gi->direct_draw);
+
+      if (press_event)
+	StartTextInput(gi->x, gi->y, gi->width, gi->height);
     }
     else if (gi->type & GD_TYPE_SELECTBOX && gi->selectbox.open &&
 	     !keep_selectbox_open)
@@ -1753,7 +1821,7 @@ boolean HandleGadgets(int mx, int my, int button)
 	{
 	  boolean scroll_single_step = ((GetKeyModState() & KMOD_Alt) != 0);
 
-	  item_steps = (scroll_single_step ? 1 : DEFAULT_WHEEL_STEPS);
+	  item_steps = (scroll_single_step ? 1 : wheel_steps);
 	  item_direction = (button == MB_WHEEL_UP ||
 			    button == MB_WHEEL_LEFT ? -1 : +1);
 	}
@@ -1950,7 +2018,8 @@ boolean HandleGadgets(int mx, int my, int button)
     {
       if (keep_selectbox_open ||
 	  mouse_released_where_pressed ||
-	  !gadget_released_inside_select_area)	     /* selectbox stays open */
+	  !gadget_released_inside_select_area ||
+	  !CURRENT_OPTION_SELECTABLE(gi))	    /* selectbox stays open */
       {
 	deactivate_gadget = FALSE;
 	gadget_changed = FALSE;
@@ -2015,13 +2084,17 @@ boolean HandleGadgetsKeyInput(Key key)
 {
   struct GadgetInfo *gi = last_gi;
 
-  if (gi == NULL || !gi->mapped ||
+  if (gi == NULL || gi->deactivated || !gi->mapped ||
       !(gi->type & GD_TYPE_TEXT_INPUT ||
 	gi->type & GD_TYPE_TEXT_AREA ||
 	gi->type & GD_TYPE_SELECTBOX))
     return FALSE;
 
-  if (key == KSYM_Return)	/* valid for both text input and selectbox */
+  if (key == KSYM_Escape)
+  {
+    StopTextInput();
+  }
+  else if (key == KSYM_Return)	/* valid for both text input and selectbox */
   {
     boolean gadget_changed = ((gi->event_mask & GD_EVENT_TEXT_RETURN) != 0);
 
@@ -2033,6 +2106,8 @@ boolean HandleGadgetsKeyInput(Key key)
 	strcpy(gi->textinput.last_value, gi->textinput.value);
       else
 	gadget_changed = FALSE;
+
+      StopTextInput();
     }
     else if (gi->type & GD_TYPE_SELECTBOX)
     {
diff --git a/src/libgame/gadgets.h b/src/libgame/gadgets.h
index 43125d6..8cd4716 100644
--- a/src/libgame/gadgets.h
+++ b/src/libgame/gadgets.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* gadgets.h                                                *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// gadgets.h
+// ============================================================================
 
 #ifndef GADGETS_H
 #define GADGETS_H
@@ -80,35 +78,42 @@
 #define GDI_TEXT_SIZE			15
 #define GDI_TEXT_FONT			16
 #define GDI_TEXT_FONT_ACTIVE		17
-#define GDI_SELECTBOX_OPTIONS		18
-#define GDI_SELECTBOX_INDEX		19
-#define GDI_DESIGN_UNPRESSED		20
-#define GDI_DESIGN_PRESSED		21
-#define GDI_ALT_DESIGN_UNPRESSED	22
-#define GDI_ALT_DESIGN_PRESSED		23
-#define GDI_BORDER_SIZE			24
-#define GDI_BORDER_SIZE_SELECTBUTTON	25
-#define GDI_DESIGN_WIDTH		26
-#define GDI_DECORATION_DESIGN		27
-#define GDI_DECORATION_POSITION		28
-#define GDI_DECORATION_SIZE		29
-#define GDI_DECORATION_SHIFTING		30
-#define GDI_EVENT_MASK			31
-#define GDI_EVENT			32
-#define GDI_CALLBACK_INFO		33
-#define GDI_CALLBACK_ACTION		34
-#define GDI_AREA_SIZE			35
-#define GDI_ITEM_SIZE			36
-#define GDI_SCROLLBAR_ITEMS_MAX		37
-#define GDI_SCROLLBAR_ITEMS_VISIBLE	38
-#define GDI_SCROLLBAR_ITEM_POSITION	39
-#define GDI_WHEEL_AREA_X		40
-#define GDI_WHEEL_AREA_Y		41
-#define GDI_WHEEL_AREA_WIDTH		42
-#define GDI_WHEEL_AREA_HEIGHT		43
-#define GDI_INFO_TEXT			44
-#define GDI_ACTIVE			45
-#define GDI_DIRECT_DRAW			46
+#define GDI_TEXT_FONT_UNSELECTABLE	18
+#define GDI_SELECTBOX_OPTIONS		19
+#define GDI_SELECTBOX_INDEX		20
+#define GDI_SELECTBOX_CHAR_UNSELECTABLE	21
+#define GDI_DESIGN_UNPRESSED		22
+#define GDI_DESIGN_PRESSED		23
+#define GDI_ALT_DESIGN_UNPRESSED	24
+#define GDI_ALT_DESIGN_PRESSED		25
+#define GDI_BORDER_SIZE			26
+#define GDI_BORDER_SIZE_SELECTBUTTON	27
+#define GDI_DESIGN_WIDTH		28
+#define GDI_DECORATION_DESIGN		29
+#define GDI_DECORATION_POSITION		30
+#define GDI_DECORATION_SIZE		31
+#define GDI_DECORATION_SHIFTING		32
+#define GDI_DECORATION_MASKED		33
+#define GDI_EVENT_MASK			34
+#define GDI_EVENT			35
+#define GDI_CALLBACK_INFO		36
+#define GDI_CALLBACK_ACTION		37
+#define GDI_AREA_SIZE			38
+#define GDI_ITEM_SIZE			39
+#define GDI_SCROLLBAR_ITEMS_MAX		40
+#define GDI_SCROLLBAR_ITEMS_VISIBLE	41
+#define GDI_SCROLLBAR_ITEM_POSITION	42
+#define GDI_WHEEL_AREA_X		43
+#define GDI_WHEEL_AREA_Y		44
+#define GDI_WHEEL_AREA_WIDTH		45
+#define GDI_WHEEL_AREA_HEIGHT		46
+#define GDI_INFO_TEXT			47
+#define GDI_ACTIVE			48
+#define GDI_DIRECT_DRAW			49
+
+/* gadget deactivation hack */
+#define GDI_ACTIVE_POS(a)		((a) < 0 ? POS_OFFSCREEN : (a))
+
 
 typedef void (*gadget_function)(void *);
 
@@ -131,11 +136,12 @@ struct GadgetDecoration
   int x, y;				/* position of deco on the gadget */
   int width, height;			/* width and height of decoration */
   int xshift, yshift;			/* deco shifting when gadget pressed */
+  boolean masked;			/* draw decoration masked over button */
 };
 
 struct GadgetEvent
 {
-  unsigned long type;			/* event type */
+  unsigned int type;			/* event type */
   int button;				/* button number for button events */
   int x, y;				/* gadget position at event time */
   boolean off_borders;			/* mouse pointer outside gadget? */
@@ -182,6 +188,7 @@ struct GadgetSelectbox
   struct ValueTextInfo *options;	/* pointer to text/value array */
   int index;				/* index of actual text string */
   int size;				/* maximal size of text strings */
+  char char_unselectable;		/* first char of unselectable options */
 
   /* automatically determined values */
   int x, y;				/* open selectbox position */
@@ -218,6 +225,8 @@ struct GadgetWheelArea
 
 struct GadgetInfo
 {
+  boolean deactivated;			/* flag to deactivate gadget */
+
   int id;				/* internal gadget identifier */
   int custom_id;			/* custom gadget identifier */
   int custom_type_id;			/* custom gadget type identifier */
@@ -233,6 +242,7 @@ struct GadgetInfo
   boolean direct_draw;			/* directly draw to frontbuffer */
   int font;				/* font to use when inactive */
   int font_active;			/* font to use when active */
+  int font_unselectable;		/* font to use when unselectable */
   struct GadgetBorder border;		/* gadget border design */
   struct GadgetDesign design[2];	/* 0: normal; 1: pressed */
   struct GadgetDesign alt_design[2];	/* alternative design */
diff --git a/src/libgame/hash.c b/src/libgame/hash.c
index 65f4270..fbf61ff 100644
--- a/src/libgame/hash.c
+++ b/src/libgame/hash.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* hash.c                                                   *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// hash.c
+// ============================================================================
 
 /*
  * Copyright (C) 2002 Christopher Clark <firstname.lastname at cl.cam.ac.uk>
diff --git a/src/libgame/hash.h b/src/libgame/hash.h
index 17e511e..90c5896 100644
--- a/src/libgame/hash.h
+++ b/src/libgame/hash.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* hash.h                                                   *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// hash.h
+// ============================================================================
 
 /*
  * Copyright (C) 2002 Christopher Clark <firstname.lastname at cl.cam.ac.uk>
diff --git a/src/libgame/image.c b/src/libgame/image.c
index 8ccf1fc..699093b 100644
--- a/src/libgame/image.c
+++ b/src/libgame/image.c
@@ -1,875 +1,84 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* image.c                                                  *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// image.c
+// ============================================================================
 
 #include "image.h"
-#include "pcx.h"
 #include "misc.h"
 #include "setup.h"
 
 
-/* ========================================================================= */
-/* PLATFORM SPECIFIC IMAGE FUNCTIONS                                         */
-/* ========================================================================= */
-
-#if defined(TARGET_X11)
-
-/* for MS-DOS/Allegro, exclude all except newImage() and freeImage() */
-
-Image *newImage(unsigned int width, unsigned int height, unsigned int depth)
-{
-  Image *image;
-  unsigned int bytes_per_pixel = (depth + 7) / 8;
-  int i;
-
-  image = checked_calloc(sizeof(Image));
-  image->data = checked_calloc(width * height * bytes_per_pixel);
-  image->width = width;
-  image->height = height;
-  image->depth = depth;
-  image->bytes_per_pixel = bytes_per_pixel;
-  image->bytes_per_row = width * bytes_per_pixel;
-
-  image->rgb.used = 0;
-  for (i = 0; i < MAX_COLORS; i++)
-    image->rgb.color_used[i] = FALSE;
-
-  image->type = (depth < 8 ? IMAGETYPE_BITMAP :
-		 depth > 8 ? IMAGETYPE_TRUECOLOR : IMAGETYPE_RGB);
-
-  return image;
-}
-
-void freeImage(Image *image)
-{
-  free(image->data);
-  free(image);
-}
-
-#if defined(PLATFORM_UNIX)
-
-/* extra colors to try allocating in private color maps to minimize flashing */
-#define NOFLASH_COLORS 256
-
-/* architecture independent value <-> memory conversions;
-   note: the internal format is big endian */
-
-#define memory_to_value(ptr, len) (					    \
-(len) == 1 ? (unsigned long)(                 *( (byte *)(ptr))         ) : \
-(len) == 2 ? (unsigned long)(((unsigned long)(*( (byte *)(ptr))   ))<< 8)   \
-			  + (                 *(((byte *)(ptr))+1)      ) : \
-(len) == 3 ? (unsigned long)(((unsigned long)(*( (byte *)(ptr))   ))<<16)   \
-			  + (((unsigned long)(*(((byte *)(ptr))+1)))<< 8)   \
-			  + (                 *(((byte *)(ptr))+2)      ) : \
-	     (unsigned long)(((unsigned long)(*( (byte *)(ptr))   ))<<24)   \
-			  + (((unsigned long)(*(((byte *)(ptr))+1)))<<16)   \
-			  + (((unsigned long)(*(((byte *)(ptr))+2)))<< 8)   \
-			  + (                 *(((byte *)(ptr))+3)      ) )
-
-
-#define value_to_memory(value, ptr, len) (				\
-(len) == 1 ? (*( (byte *)(ptr)   ) = ( value     ) ) :			\
-(len) == 2 ? (*( (byte *)(ptr)   ) = (((unsigned long)(value))>> 8),	\
-	      *(((byte *)(ptr))+1) = ( value     ) ) :			\
-(len) == 3 ? (*( (byte *)(ptr)   ) = (((unsigned long)(value))>>16),	\
-	      *(((byte *)(ptr))+1) = (((unsigned long)(value))>> 8),	\
-	      *(((byte *)(ptr))+2) = ( value     ) ) :			\
-             (*( (byte *)(ptr)   ) = (((unsigned long)(value))>>24),	\
-	      *(((byte *)(ptr))+1) = (((unsigned long)(value))>>16),	\
-	      *(((byte *)(ptr))+2) = (((unsigned long)(value))>> 8),	\
-	      *(((byte *)(ptr))+3) = ( value     ) ))
-
-static Pixmap Image_to_Mask(Image *image, Display *display, Window window)
-{
-  byte *src_ptr, *dst_ptr, *dst_ptr2;
-  unsigned int bytes_per_row;
-  unsigned int x, y, i;
-  byte bitmask;
-  byte *mask_data;
-  Pixmap mask_pixmap;
-
-  bytes_per_row = (image->width + 7) / 8;
-  mask_data = checked_calloc(bytes_per_row * image->height);
-
-  src_ptr = image->data;
-  dst_ptr = mask_data;
-
-  /* create bitmap data which can be used by 'XCreateBitmapFromData()'
-   * directly to create a pixmap of depth 1 for use as a clip mask for
-   * the corresponding image pixmap
-   */
-
-  for (y = 0; y < image->height; y++)
-  {
-    bitmask = 0x01;		/* start with leftmost bit in the byte     */
-    dst_ptr2 = dst_ptr;		/* start with leftmost byte in the row     */
-
-    for (x = 0; x < image->width; x++)
-    {
-      for (i = 0; i < image->bytes_per_pixel; i++)
-	if (*src_ptr++)		/* source pixel solid? (pixel index != 0)  */
-	  *dst_ptr2 |= bitmask;	/* then write a bit into the image mask    */
-
-      if ((bitmask <<= 1) == 0)	/* bit at rightmost byte position reached? */
-      {
-	bitmask = 0x01;		/* start again with leftmost bit position  */
-	dst_ptr2++;		/* continue with next byte in image mask   */
-      }
-    }
-
-    dst_ptr += bytes_per_row;	/* continue with leftmost byte of next row */
-  }
-
-  if ((mask_pixmap = XCreateBitmapFromData(display, window, (char *)mask_data,
-					   image->width, image->height))
-      == None)
-    Error(ERR_EXIT, "Image_to_Mask(): XCreateBitmapFromData() failed");
-
-  free(mask_data);
-
-  return mask_pixmap;
-}
-
-Pixmap Pixmap_to_Mask(Pixmap src_pixmap, int src_width, int src_height)
-{
-  XImage *src_ximage;
-  byte *src_ptr, *dst_ptr, *dst_ptr2;
-  int bits_per_pixel;
-  int bytes_per_pixel;
-  unsigned int bytes_per_row;
-  unsigned int x, y, i;
-  byte bitmask;
-  byte *mask_data;
-  Pixmap mask_pixmap;
-
-  /* copy source pixmap to temporary image */
-  if ((src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height,
-			      AllPlanes, ZPixmap)) == NULL)
-    Error(ERR_EXIT, "Pixmap_to_Mask(): XGetImage() failed");
-
-  bits_per_pixel = src_ximage->bits_per_pixel;
-  bytes_per_pixel = (bits_per_pixel + 7) / 8;
-
-  bytes_per_row = (src_width + 7) / 8;
-  mask_data = checked_calloc(bytes_per_row * src_height);
-
-  src_ptr = (byte *)src_ximage->data;
-  dst_ptr = mask_data;
-
-  /* create bitmap data which can be used by 'XCreateBitmapFromData()'
-   * directly to create a pixmap of depth 1 for use as a clip mask for
-   * the corresponding image pixmap
-   */
-
-  for (y = 0; y < src_height; y++)
-  {
-    bitmask = 0x01;		/* start with leftmost bit in the byte     */
-    dst_ptr2 = dst_ptr;		/* start with leftmost byte in the row     */
-
-    for (x = 0; x < src_width; x++)
-    {
-      for (i = 0; i < bytes_per_pixel; i++)
-	if (*src_ptr++)		/* source pixel solid? (pixel index != 0)  */
-	  *dst_ptr2 |= bitmask;	/* then write a bit into the image mask    */
-
-      if ((bitmask <<= 1) == 0)	/* bit at rightmost byte position reached? */
-      {
-	bitmask = 0x01;		/* start again with leftmost bit position  */
-	dst_ptr2++;		/* continue with next byte in image mask   */
-      }
-    }
-
-    dst_ptr += bytes_per_row;	/* continue with leftmost byte of next row */
-  }
-
-  if ((mask_pixmap = XCreateBitmapFromData(display, window->drawable,
-					   (char *)mask_data,
-					   src_width, src_height)) == None)
-    Error(ERR_EXIT, "Pixmap_to_Mask(): XCreateBitmapFromData() failed");
-
-  free(mask_data);
-
-  return mask_pixmap;
-}
-
-static int bitsPerPixelAtDepth(Display *display, int screen, int depth)
-{
-  XPixmapFormatValues *pixmap_format;
-  int i, num_pixmap_formats, bits_per_pixel = -1;
-
-  /* get Pixmap formats supported by the X server */
-  pixmap_format = XListPixmapFormats(display, &num_pixmap_formats);
-
-  /* find format that matches the given depth */
-  for (i = 0; i < num_pixmap_formats; i++)
-    if (pixmap_format[i].depth == depth)
-      bits_per_pixel = pixmap_format[i].bits_per_pixel;
-
-  XFree(pixmap_format);
-
-  if (bits_per_pixel == -1)
-    Error(ERR_EXIT, "cannot find pixmap format for depth %d", depth);
-
-  return bits_per_pixel;
-}
-
-XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual,
-			    Window window, GC gc, int depth, Image *image)
-{
-  static XColor xcolor_private[NOFLASH_COLORS];
-  static int colorcell_used[NOFLASH_COLORS];
-  static Colormap global_cmap = 0;
-  static Pixel *global_cmap_index;
-  static int num_cmap_entries, free_cmap_entries;
-  static boolean private_cmap = FALSE;
-  Pixel *redvalue, *greenvalue, *bluevalue;
-  unsigned int display_bytes_per_pixel, display_bits_per_pixel;
-  unsigned int a, c = 0, x, y;
-  XColor xcolor;
-  XImage *ximage;
-  XImageInfo *ximageinfo;
-  byte *src_ptr, *dst_ptr;
-  char *error = "Image_to_Pixmap(): %s";
-
-  if (image->type == IMAGETYPE_TRUECOLOR && depth == 8)
-  {
-    SetError(error, "cannot handle true-color images on 8-bit display");
-    return NULL;
-  }
-
-  if (!global_cmap)
-  {
-    if (visual == DefaultVisual(display, screen))
-      global_cmap = DefaultColormap(display, screen);
-    else
-    {
-      global_cmap = XCreateColormap(display, RootWindow(display, screen),
-				    visual, AllocNone);
-      private_cmap = TRUE;
-    }
-  }
-
-  xcolor.flags = DoRed | DoGreen | DoBlue;
-  redvalue = greenvalue = bluevalue = NULL;
-  ximageinfo = checked_malloc(sizeof(XImageInfo));
-  ximageinfo->display = display;
-  ximageinfo->depth = depth;
-
-  switch (visual->class)
-  {
-    case TrueColor:
-    case DirectColor:
-    {
-      Pixel pixval;
-      unsigned int redcolors, greencolors, bluecolors;
-      unsigned int redstep, greenstep, bluestep;
-      unsigned int redbottom, greenbottom, bluebottom;
-      unsigned int redtop, greentop, bluetop;
-
-      redvalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
-      greenvalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
-      bluevalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
-
-      ximageinfo->cmap = global_cmap;
-
-      retry_direct: /* tag we hit if a DirectColor allocation fails on
-		     * default colormap */
-
-      /* calculate number of distinct colors in each band */
-
-      redcolors = greencolors = bluecolors = 1;
-      for (pixval = 1; pixval; pixval <<= 1)
-      {
-	if (pixval & visual->red_mask)
-	  redcolors <<= 1;
-	if (pixval & visual->green_mask)
-	  greencolors <<= 1;
-	if (pixval & visual->blue_mask)
-	  bluecolors <<= 1;
-      }
-      
-      /* consistency check */
-      if (redcolors > visual->map_entries ||
-	  greencolors > visual->map_entries ||
-	  bluecolors > visual->map_entries)
-	Error(ERR_WARN, "inconsistency in color information");
-
-      redstep = 256 / redcolors;
-      greenstep = 256 / greencolors;
-      bluestep = 256 / bluecolors;
-      redbottom = greenbottom = bluebottom = 0;
-      redtop = greentop = bluetop = 0;
-
-      for (a = 0; a < visual->map_entries; a++)
-      {
-	if (redbottom < 256)
-	  redtop = redbottom + redstep;
-	if (greenbottom < 256)
-	  greentop = greenbottom + greenstep;
-	if (bluebottom < 256)
-	  bluetop = bluebottom + bluestep;
-
-	xcolor.red = (redtop - 1) << 8;
-	xcolor.green = (greentop - 1) << 8;
-	xcolor.blue = (bluetop - 1) << 8;
-	if (!XAllocColor(display, ximageinfo->cmap, &xcolor))
-	{
-	  /* if an allocation fails for a DirectColor default visual then
-	     we should create a private colormap and try again. */
-
-	  if ((visual->class == DirectColor) &&
-	      (visual == DefaultVisual(display, screen)))
-	  {
-	    global_cmap = XCopyColormapAndFree(display, global_cmap);
-	    ximageinfo->cmap = global_cmap;
-	    private_cmap = TRUE;
-
-	    goto retry_direct;
-	  }
-
-	  /* something completely unexpected happened */
-
-	  fprintf(stderr, "Image_to_Pixmap: XAllocColor failed on a TrueColor/Directcolor visual\n");
-
-          free(redvalue);
-          free(greenvalue);
-          free(bluevalue);
-          free(ximageinfo);
-
-	  return NULL;
-	}
-
-	/* fill in pixel values for each band at this intensity */
-
-	while ((redbottom < 256) && (redbottom < redtop))
-	  redvalue[redbottom++] = xcolor.pixel & visual->red_mask;
-	while ((greenbottom < 256) && (greenbottom < greentop))
-	  greenvalue[greenbottom++] = xcolor.pixel & visual->green_mask;
-	while ((bluebottom < 256) && (bluebottom < bluetop))
-	  bluevalue[bluebottom++] = xcolor.pixel & visual->blue_mask;
-      }
-
-      break;
-    }
-
-    case PseudoColor:
-
-      ximageinfo->cmap = global_cmap;
-
-      for (a = 0; a < MAX_COLORS; a++)
-      {
-	XColor xcolor2;
-	unsigned short mask;
-	int color_found;
-  	int i;
-
-	if (!image->rgb.color_used[a])
-	  continue;
-
-  	xcolor.red = *(image->rgb.red + a);
-  	xcolor.green = *(image->rgb.green + a);
-  	xcolor.blue = *(image->rgb.blue + a);
-  
-  	/* look if this color already exists in our colormap */
-	if (!XAllocColor(display, ximageinfo->cmap, &xcolor))
-	{
-	  if (!private_cmap)
-	  {
-	    if (options.verbose)
-	      Error(ERR_INFO, "switching to private colormap");
-
-	    /* we just filled up the default colormap -- get a private one
-	       which contains all already allocated colors */
-
-	    global_cmap = XCopyColormapAndFree(display, global_cmap);
-	    ximageinfo->cmap = global_cmap;
-	    private_cmap = TRUE;
-
-	    /* allocate the rest of the color cells read/write */
-	    global_cmap_index =
-	      (Pixel *)checked_malloc(sizeof(Pixel) * NOFLASH_COLORS);
-	    for (i = 0; i < NOFLASH_COLORS; i++)
-	      if (!XAllocColorCells(display, global_cmap, FALSE, NULL, 0,
-				    global_cmap_index + i, 1))
-		break;
-	    num_cmap_entries = free_cmap_entries = i;
-
-	    /*
-	    printf("We've got %d free colormap entries.\n", free_cmap_entries);
-	    */
-
-	    /* to minimize colormap flashing, copy default colors and try
-	       to keep them as near as possible to the old values */
-
-	    for (i = 0; i < num_cmap_entries; i++)
-	    {
-	      xcolor2.pixel = *(global_cmap_index + i);
-	      XQueryColor(display, DefaultColormap(display, screen), &xcolor2);
-	      XStoreColor(display, global_cmap, &xcolor2);
-	      xcolor_private[xcolor2.pixel] = xcolor2;
-	      colorcell_used[xcolor2.pixel] = FALSE;
-	    }
-
-	    /* now we have the default colormap private: all colors we
-	       successfully allocated so far are read-only, which is okay,
-	       because we don't want to change them anymore -- if we need
-	       an existing color again, we get it by XAllocColor; all other
-	       colors are read/write and we can set them by XStoreColor,
-	       but we will try to overwrite those color cells with our new
-	       color which are as close as possible to our new color */
-	  }
-
-  	  /* look for an existing default color close the one we want */
-
-	  mask = 0xf000;
-	  color_found = FALSE;
-
-	  while (!color_found)
-	  {
-	    for (i = num_cmap_entries - 1; i >= 0; i--)
-	    {
-	      xcolor2.pixel = *(global_cmap_index + i);
-	      xcolor2 = xcolor_private[xcolor2.pixel];
-
-	      if (colorcell_used[xcolor2.pixel])
-		continue;
-
-	      if ((xcolor.red & mask) == (xcolor2.red & mask) &&
-		  (xcolor.green & mask) == (xcolor2.green & mask) &&
-		  (xcolor.blue & mask) == (xcolor2.blue & mask))
-	      {
-		/*
-		printf("replacing color cell %ld with a close color\n",
-		       xcolor2.pixel);
-		       */
-		color_found = TRUE;
-		break;
-	      }
-	    }
-
-	    if (mask == 0x0000)
-	      break;
-
-	    mask = (mask << 1) & 0xffff;
-	  }
-
-	  if (!color_found)		/* no more free color cells */
-	  {
-	    SetError(error, "cannot allocate enough color cells");
-	    return NULL;
-	  }
-
-	  xcolor.pixel = xcolor2.pixel;
-	  xcolor_private[xcolor.pixel] = xcolor;
-	  colorcell_used[xcolor.pixel] = TRUE;
-	  XStoreColor(display, ximageinfo->cmap, &xcolor);
-	  free_cmap_entries--;
-	}
-
-	*(ximageinfo->index + a) = xcolor.pixel;
-      }
-
-      /*
-      printf("still %d free colormap entries\n", free_cmap_entries);
-      */
-
-      ximageinfo->no = a;	/* number of pixels allocated for this image */
-      break;
-  
-    default:
-      Error(ERR_INFO,"DirectColor, TrueColor or PseudoColor display needed");
-      SetError(error, "display class not supported");
-
-      return NULL;
-  }
-
-#if DEBUG_TIMING
-  debug_print_timestamp(2, "   ALLOCATING IMAGE COLORS:   ");
-#endif
-
-  /* create XImage from internal image structure and convert it to Pixmap */
-
-  display_bits_per_pixel = bitsPerPixelAtDepth(display, screen, depth);
-  display_bytes_per_pixel = (display_bits_per_pixel + 7) / 8;
-
-  ximage = XCreateImage(display, visual, depth, ZPixmap,
-			0, NULL, image->width, image->height,
-			8, image->width * display_bytes_per_pixel);
-  ximage->data =
-    checked_malloc(image->width * image->height * display_bytes_per_pixel);
-  ximage->byte_order = MSBFirst;
-
-  src_ptr = image->data;
-  dst_ptr = (byte *)ximage->data;
-
-  switch (visual->class)
-  {
-    case DirectColor:
-    case TrueColor:
-    {
-      Pixel pixval;
-
-      switch (image->type)
-      {
-        case IMAGETYPE_RGB:
-	{
-	  for (y = 0; y < image->height; y++)		/* general case */
-	  {
-	    for (x = 0; x < image->width; x++)
-	    {
-	      pixval = *src_ptr++;
-	      pixval =
-		redvalue[image->rgb.red[pixval] >> 8] |
-		greenvalue[image->rgb.green[pixval] >> 8] |
-		bluevalue[image->rgb.blue[pixval] >> 8];
-	      value_to_memory(pixval, dst_ptr, display_bytes_per_pixel);
-	      dst_ptr += display_bytes_per_pixel;
-	    }
-	  }
-
-	  break;
-	}
-
-        case IMAGETYPE_TRUECOLOR:
-	{
-	  for (y = 0; y < image->height; y++)		/* general case */
-	  {
-	    for (x = 0; x < image->width; x++)
-	    {
-	      pixval = memory_to_value(src_ptr, image->bytes_per_pixel);
-	      pixval =
-		redvalue[TRUECOLOR_RED(pixval)] |
-		greenvalue[TRUECOLOR_GREEN(pixval)] |
-		bluevalue[TRUECOLOR_BLUE(pixval)];
-	      value_to_memory(pixval, dst_ptr, display_bytes_per_pixel);
-	      src_ptr += image->bytes_per_pixel;
-	      dst_ptr += display_bytes_per_pixel;
-	    }
-	  }
-
-	  break;
-	}
-
-        default:
-	  Error(ERR_INFO, "RGB or TrueColor image needed");
-	  SetError(error, "image type not supported");
-
-	  return NULL;
-      }
-
-      break;
-    }
-
-    case PseudoColor:
-    {
-      if (display_bytes_per_pixel == 1)		/* special case */
-      {
-	for (y = 0; y < image->height; y++)
-	  for (x = 0; x < image->width; x++)
-	    *dst_ptr++ = ximageinfo->index[c + *src_ptr++];
-      }
-      else					/* general case */
-      {
-	for (y = 0; y < image->height; y++)
-	{
-	  for (x = 0; x < image->width; x++)
-	  {
-	    value_to_memory(ximageinfo->index[c + *src_ptr++],
-			    dst_ptr, display_bytes_per_pixel);
-	    dst_ptr += display_bytes_per_pixel;
-	  }
-	}
-      }
-
-      break;
-    }
-
-    default:
-      Error(ERR_INFO,"DirectColor, TrueColor or PseudoColor display needed");
-      SetError(error, "display class not supported");
-
-      return NULL;
-  }
-
-  if (redvalue)
-  {
-    free((byte *)redvalue);
-    free((byte *)greenvalue);
-    free((byte *)bluevalue);
-  }
-
-#if DEBUG_TIMING
-  debug_print_timestamp(2, "   CONVERTING IMAGE TO XIMAGE:");
-#endif
-
-  ximageinfo->pixmap = XCreatePixmap(display, window,
-				     ximage->width, ximage->height,
-				     ximageinfo->depth);
-
-  XPutImage(ximageinfo->display, ximageinfo->pixmap, gc,
-	    ximage, 0, 0, 0, 0, ximage->width, ximage->height);
-
-  X11DestroyImage(ximage);
-
-  return ximageinfo;
-}
-
-/*
-  -----------------------------------------------------------------------------
-  ZoomPixmap
-
-  Important note: The scaling code currently only supports scaling of the image
-  up or down by a power of 2 -- other scaling factors currently not supported!
-  Also not supported is scaling of pixmap masks (with depth 1); to scale them,
-  better use Pixmap_to_Mask() for now.
-  -----------------------------------------------------------------------------
-*/
-
-void ZoomPixmap(Display *display, GC gc, Pixmap src_pixmap, Pixmap dst_pixmap,
-		int src_width, int src_height,
-		int dst_width, int dst_height)
-{
-  XImage *src_ximage, *dst_ximage;
-  byte *src_ptr, *dst_ptr;
-  int bits_per_pixel;
-  int bytes_per_pixel;
-  int x, y, xx, yy, i;
-  int row_skip, col_skip;
-  int zoom_factor;
-  boolean scale_down = (src_width > dst_width);
-
-  if (scale_down)
-  {
-#if 1
-    zoom_factor = MIN(src_width / dst_width, src_height / dst_height);
-#else
-    zoom_factor = src_width / dst_width;
-#endif
-
-    /* adjust source image size to integer multiple of destination size */
-    src_width  = dst_width  * zoom_factor;
-    src_height = dst_height * zoom_factor;
-  }
-  else
-  {
-#if 1
-    zoom_factor = MIN(dst_width / src_width, dst_height / src_height);
-#else
-    zoom_factor = dst_width / src_width;
-#endif
-
-    /* no adjustment needed when scaling up (some pixels may be left blank) */
-  }
-
-  /* copy source pixmap to temporary image */
-  if ((src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height,
-			      AllPlanes, ZPixmap)) == NULL)
-    Error(ERR_EXIT, "ZoomPixmap(): XGetImage() failed");
-
-  bits_per_pixel = src_ximage->bits_per_pixel;
-  bytes_per_pixel = (bits_per_pixel + 7) / 8;
-
-  if ((dst_ximage = XCreateImage(display, visual, src_ximage->depth, ZPixmap,
-				 0, NULL, dst_width, dst_height,
-				 8, dst_width * bytes_per_pixel)) == NULL)
-    Error(ERR_EXIT, "ZoomPixmap(): XCreateImage() failed");
-
-  dst_ximage->data =
-    checked_malloc(dst_width * dst_height * bytes_per_pixel);
-  dst_ximage->byte_order = src_ximage->byte_order;
-
-  src_ptr = (byte *)src_ximage->data;
-  dst_ptr = (byte *)dst_ximage->data;
-
-  if (scale_down)
-  {
-    col_skip = (zoom_factor - 1) * bytes_per_pixel;
-    row_skip = col_skip * src_width;
-
-    /* scale image down by scaling factor 'zoom_factor' */
-    for (y = 0; y < src_height; y += zoom_factor, src_ptr += row_skip)
-      for (x = 0; x < src_width; x += zoom_factor, src_ptr += col_skip)
-	for (i = 0; i < bytes_per_pixel; i++)
-	  *dst_ptr++ = *src_ptr++;
-  }
-  else
-  {
-    row_skip = src_width * bytes_per_pixel;
-
-    /* scale image up by scaling factor 'zoom_factor' */
-    for (y = 0; y < src_height; y++)
-    {
-      for (yy = 0; yy < zoom_factor; yy++)
-      {
-	if (yy > 0)
-	  src_ptr -= row_skip;
-
-	for (x = 0; x < src_width; x++)
-	{
-	  for (xx = 0; xx < zoom_factor; xx++)
-	    for (i = 0; i < bytes_per_pixel; i++)
-	      *dst_ptr++ = *(src_ptr + i);
-
-	  src_ptr += bytes_per_pixel;
-	}
-      }
-    }
-  }
-
-  /* copy scaled image to destination pixmap */
-  XPutImage(display, dst_pixmap, gc, dst_ximage, 0, 0, 0, 0,
-	    dst_width, dst_height);
-
-  /* free temporary images */
-  X11DestroyImage(src_ximage);
-  X11DestroyImage(dst_ximage);
-}
-
-void freeXImage(Image *image, XImageInfo *ximageinfo)
-{
-  if (ximageinfo->index != NULL && ximageinfo->no > 0)
-    XFreeColors(ximageinfo->display, ximageinfo->cmap, ximageinfo->index,
-		ximageinfo->no, 0);
-  /* this       ^^^^^^^^^^^^^^ is wrong, because the used color cells
-   * are somewhere between 0 and MAX_COLORS; there are indeed 'ximageinfo->no'
-   * used color cells, but they are not at array position 0 - 'ximageinfo->no'
-   */
-
-  free(ximageinfo);
-}
-
-int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename,
-		       Pixmap *pixmap, Pixmap *pixmap_mask)
-{
-  Image *image;
-  XImageInfo *ximageinfo;
-  int screen;
-  Visual *visual;
-  int depth;
-
-#if DEBUG_TIMING
-  debug_print_timestamp(2, NULL);	/* initialize timestamp function */
-#endif
-
-  /* read the graphic file in PCX format to image structure */
-  if ((image = Read_PCX_to_Image(filename)) == NULL)
-    return errno_pcx;
-
-#if DEBUG_TIMING
-  printf("%s:\n", filename);
-  debug_print_timestamp(2, "   READING PCX FILE TO IMAGE: ");
-#endif
-
-  screen = DefaultScreen(display);
-  visual = DefaultVisual(display, screen);
-  depth = DefaultDepth(display, screen);
-
-  /* convert image structure to X11 Pixmap */
-  if (!(ximageinfo = Image_to_Pixmap(display, screen, visual,
-				     window, gc, depth, image)))
-  {
-    freeImage(image);
-
-    return PCX_OtherError;
-  }
-
-  /* if a private colormap has been created, install it */
-  if (ximageinfo->cmap != DefaultColormap(display, screen))
-    XSetWindowColormap(display, window, ximageinfo->cmap);
-
-#if DEBUG_TIMING
-  debug_print_timestamp(2, "   CONVERTING IMAGE TO PIXMAP:");
-#endif
-
-  /* create clip mask for the image */
-  ximageinfo->pixmap_mask = Image_to_Mask(image, display, window);
-
-#if DEBUG_TIMING
-  debug_print_timestamp(2, "   CONVERTING IMAGE TO MASK:  ");
-#endif
-
-  *pixmap = ximageinfo->pixmap;
-  *pixmap_mask = ximageinfo->pixmap_mask;
-
-  /* free generic image and ximageinfo after native Pixmap has been created */
-  free(ximageinfo);
-  freeImage(image);
-
-  return PCX_Success;
-}
-
-#endif	/* PLATFORM_UNIX */
-#endif	/* TARGET_X11 */
-
-
-/* ========================================================================= */
-/* PLATFORM INDEPENDENT IMAGE FUNCTIONS                                      */
-/* ========================================================================= */
-
 struct ImageInfo
 {
   char *source_filename;
   int num_references;
 
-  Bitmap *bitmap;
+  Bitmap *bitmaps[NUM_IMG_BITMAP_POINTERS];
 
   int original_width;			/* original image file width */
   int original_height;			/* original image file height */
 
   boolean contains_small_images;	/* set after adding small images */
+  boolean contains_textures;		/* set after adding GPU textures */
   boolean scaled_up;			/* set after scaling up */
+
+  int conf_tile_size;			/* tile size as defined in config */
+  int game_tile_size;			/* tile size as resized for game */
+
+  char *leveldir;			/* level set when image was loaded */
 };
 typedef struct ImageInfo ImageInfo;
 
 static struct ArtworkListInfo *image_info = NULL;
 
-static void *Load_PCX(char *filename)
+static void *Load_Image(char *filename)
 {
-  ImageInfo *img_info;
-
-#if 0
-  printf("::: loading PCX file '%s'\n", filename);
-#endif
+  ImageInfo *img_info = checked_calloc(sizeof(ImageInfo));
 
-  img_info = checked_calloc(sizeof(ImageInfo));
-
-  if ((img_info->bitmap = LoadImage(filename)) == NULL)
+  if ((img_info->bitmaps[IMG_BITMAP_STANDARD] = LoadImage(filename)) == NULL)
   {
     Error(ERR_WARN, "cannot load image file '%s': LoadImage() failed: %s",
 	  filename, GetError());
+
     free(img_info);
+
     return NULL;
   }
 
   img_info->source_filename = getStringCopy(filename);
 
-  img_info->original_width  = img_info->bitmap->width;
-  img_info->original_height = img_info->bitmap->height;
+  img_info->original_width  = img_info->bitmaps[IMG_BITMAP_STANDARD]->width;
+  img_info->original_height = img_info->bitmaps[IMG_BITMAP_STANDARD]->height;
 
   img_info->contains_small_images = FALSE;
+  img_info->contains_textures = FALSE;
   img_info->scaled_up = FALSE;
 
+  img_info->conf_tile_size = 0;		// will be set later
+  img_info->game_tile_size = 0;		// will be set later
+
+  img_info->leveldir = NULL;		// will be set later
+
   return img_info;
 }
 
 static void FreeImage(void *ptr)
 {
   ImageInfo *image = (ImageInfo *)ptr;
+  int i;
 
   if (image == NULL)
     return;
 
-  if (image->bitmap)
-    FreeBitmap(image->bitmap);
+  for (i = 0; i < NUM_IMG_BITMAPS; i++)
+    if (image->bitmaps[i])
+      FreeBitmap(image->bitmaps[i]);
 
   if (image->source_filename)
     free(image->source_filename);
@@ -903,11 +112,11 @@ static ImageInfo *getImageInfoEntryFromImageID(int pos)
   return img_info[list_pos];
 }
 
-Bitmap *getBitmapFromImageID(int pos)
+Bitmap **getBitmapsFromImageID(int pos)
 {
   ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
 
-  return (img_info != NULL ? img_info->bitmap : NULL);
+  return (img_info != NULL ? img_info->bitmaps : NULL);
 }
 
 int getOriginalImageWidthFromImageID(int pos)
@@ -931,6 +140,13 @@ char *getTokenFromImageID(int graphic)
   return (file_list != NULL ? file_list->token : NULL);
 }
 
+char *getFilenameFromImageID(int graphic)
+{
+  struct FileInfo *file_list = getImageListEntryFromImageID(graphic);
+
+  return (file_list != NULL ? file_list->filename : NULL);
+}
+
 int getImageIDFromToken(char *token)
 {
   struct FileInfo *file_list = image_info->file_list;
@@ -1030,31 +246,149 @@ void InitImageList(struct ConfigInfo *config_list, int num_file_list_entries,
 
   /* ---------- initialize artwork loading/freeing functions ---------- */
 
-  image_info->load_artwork = Load_PCX;
+  image_info->load_artwork = Load_Image;
   image_info->free_artwork = FreeImage;
 }
 
 void ReloadCustomImages()
 {
-#if 0
-  printf("::: reloading images '%s' ...\n", artwork.gfx_current_identifier);
-#endif
+  print_timestamp_init("ReloadCustomImages");
 
   LoadArtworkConfig(image_info);
+  print_timestamp_time("LoadArtworkConfig");
+
   ReloadCustomArtworkList(image_info);
+  print_timestamp_time("ReloadCustomArtworkList");
+
+  print_timestamp_done("ReloadCustomImages");
 }
 
-void CreateImageWithSmallImages(int pos, int zoom_factor)
+static boolean CheckIfImageContainsSmallImages(ImageInfo *img_info,
+					       int tile_size)
+{
+  if (!img_info->contains_small_images)
+    return FALSE;
+
+  // at this point, small images already exist for this image;
+  // now do some checks that may require re-creating small (or in-game) images
+
+  // special case 1:
+  //
+  // check if the configured tile size for an already loaded image has changed
+  // from one level set to another; this should usually not happen, but if a
+  // custom artwork set redefines classic (or default) graphics with wrong tile
+  // size (by mistake or by intention), it will be corrected to its original
+  // tile size here by forcing complete re-creation of all small images again
+
+  if (!strEqual(img_info->leveldir, leveldir_current->identifier) &&
+      img_info->conf_tile_size != tile_size)
+  {
+    int bitmap_nr = GET_BITMAP_ID_FROM_TILESIZE(img_info->conf_tile_size);
+    int i;
+
+    // free all calculated, resized bitmaps, but keep last configured size
+    for (i = 0; i < NUM_IMG_BITMAPS; i++)
+    {
+      if (i == bitmap_nr)
+	continue;
+
+      if (img_info->bitmaps[i])
+      {
+	FreeBitmap(img_info->bitmaps[i]);
+
+	img_info->bitmaps[i] = NULL;
+      }
+    }
+
+    // re-create small bitmaps from last configured size as new default size
+    if (bitmap_nr != IMG_BITMAP_STANDARD)
+    {
+      img_info->bitmaps[IMG_BITMAP_STANDARD] = img_info->bitmaps[bitmap_nr];
+      img_info->bitmaps[bitmap_nr] = NULL;
+    }
+
+    img_info->contains_small_images = FALSE;
+
+    return FALSE;
+  }
+
+  // special case 1 (continued):
+  //
+  // if different tile sizes are used in same image file (usually by mistake,
+  // like forgetting option ".tile_size" for one or more graphic definitions),
+  // make sure to use only the first tile size that is processed for this image
+  // (and ignore all subsequent, potentially different tile size definitions
+  // for this image within the current level set by disabling the above check)
+
+  setString(&img_info->leveldir, leveldir_current->identifier);
+
+  // special case 2:
+  //
+  // graphic config setting "game.tile_size" has changed since last level set;
+  // this may require resizing image to new size required for in-game graphics
+
+  if (img_info->game_tile_size != gfx.game_tile_size)
+  {
+    ReCreateGameTileSizeBitmap(img_info->bitmaps);
+
+    img_info->game_tile_size = gfx.game_tile_size;
+  }
+
+  return TRUE;
+}
+
+void CreateImageWithSmallImages(int pos, int zoom_factor, int tile_size)
 {
   ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
 
-  if (img_info == NULL || img_info->contains_small_images)
+  if (img_info == NULL)
+    return;
+
+  if (CheckIfImageContainsSmallImages(img_info, tile_size))
     return;
 
-  CreateBitmapWithSmallBitmaps(img_info->bitmap, zoom_factor);
+  CreateBitmapWithSmallBitmaps(img_info->bitmaps, zoom_factor, tile_size);
 
   img_info->contains_small_images = TRUE;
-  img_info->scaled_up = TRUE;
+  img_info->scaled_up = TRUE;			// scaling was also done here
+
+  img_info->conf_tile_size = tile_size;
+  img_info->game_tile_size = gfx.game_tile_size;
+
+  setString(&img_info->leveldir, leveldir_current->identifier);
+}
+
+void CreateImageTextures(int pos)
+{
+  ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
+
+  if (img_info == NULL || img_info->contains_textures)
+    return;
+
+  CreateBitmapTextures(img_info->bitmaps);
+
+  img_info->contains_textures = TRUE;
+}
+
+void FreeImageTextures(int pos)
+{
+  ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
+
+  if (img_info == NULL || !img_info->contains_textures)
+    return;
+
+  FreeBitmapTextures(img_info->bitmaps);
+
+  img_info->contains_textures = FALSE;
+}
+
+void FreeAllImageTextures()
+{
+  int num_images = getImageListSize();
+  int i;
+
+  for (i = 0; i < num_images; i++)
+    FreeImageTextures(i);
 }
 
 void ScaleImage(int pos, int zoom_factor)
@@ -1065,7 +399,7 @@ void ScaleImage(int pos, int zoom_factor)
     return;
 
   if (zoom_factor != 1)
-    ScaleBitmap(img_info->bitmap, zoom_factor);
+    ScaleBitmap(img_info->bitmaps, zoom_factor);
 
   img_info->scaled_up = TRUE;
 }
diff --git a/src/libgame/image.h b/src/libgame/image.h
index 89f4f7c..25b83ce 100644
--- a/src/libgame/image.h
+++ b/src/libgame/image.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* image.h                                                  *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// image.h
+// ============================================================================
 
 #ifndef IMAGE_H
 #define IMAGE_H
@@ -17,71 +15,50 @@
 #include "system.h"
 
 
-#if defined(TARGET_X11)
+// these bitmap pointers either point to allocated bitmaps or are NULL
+#define IMG_BITMAP_32x32	0
+#define IMG_BITMAP_16x16	1
+#define IMG_BITMAP_8x8		2
+#define IMG_BITMAP_4x4		3
+#define IMG_BITMAP_2x2		4
+#define IMG_BITMAP_1x1		5
+#define IMG_BITMAP_CUSTOM	6
 
-#define MAX_COLORS	256	/* maximal number of colors for each image */
+#define NUM_IMG_BITMAPS		7
 
-typedef unsigned short Intensity;	/* RGB intensity for X11 */
+// this bitmap pointer points to one of the above bitmaps (do not free it)
+#define IMG_BITMAP_GAME		7
 
-typedef struct
-{
-  Display  *display;		/* destination display             */
-  int       depth;		/* depth of destination drawable   */
-  Pixel     index[MAX_COLORS];	/* array of pixel values           */
-  int       no;			/* number of pixels in the array   */
-  Colormap  cmap;		/* colormap used for image         */
-  Pixmap   pixmap;		/* final pixmap                    */
-  Pixmap   pixmap_mask;		/* final pixmap of mask            */
-} XImageInfo;
+#define NUM_IMG_BITMAP_POINTERS	8
 
-struct RGBMap
-{
-  unsigned int used;			/* number of colors used in RGB map */
-  Intensity    red[MAX_COLORS];		/* color values in X style          */
-  Intensity    green[MAX_COLORS];
-  Intensity    blue[MAX_COLORS];
-  boolean      color_used[MAX_COLORS];	/* flag if color cell is used       */
-};
+// this bitmap pointer points to the bitmap with default image size
+#define IMG_BITMAP_STANDARD	IMG_BITMAP_32x32
 
-typedef struct
-{
-  unsigned int  type;		/* type of image (True-Color etc.)     */
-  struct RGBMap rgb;		/* RGB map of image if IRGB type       */
-  unsigned int  width;		/* width of image in pixels            */
-  unsigned int  height;		/* height of image in pixels           */
-  unsigned int  depth;		/* depth of image in bits if IRGB type */
-  unsigned int  bytes_per_pixel;/* (depth + 7) / 8                     */
-  unsigned int  bytes_per_row;	/* width * bytes_per_pixel             */
-  byte         *data;		/* image data                          */
-} Image;
 
-#define IMAGETYPE_BITMAP	0	/* monochrome bitmap       */
-#define IMAGETYPE_RGB		1	/* RGB image with colormap */
-#define IMAGETYPE_TRUECOLOR	2	/* true-color image        */
+#define GET_BITMAP_ID_FROM_TILESIZE(x)	((x) ==  1 ? IMG_BITMAP_1x1   :	\
+					 (x) ==  2 ? IMG_BITMAP_2x2   :	\
+					 (x) ==  4 ? IMG_BITMAP_4x4   :	\
+					 (x) ==  8 ? IMG_BITMAP_8x8   :	\
+					 (x) == 16 ? IMG_BITMAP_16x16 :	\
+					 (x) == 32 ? IMG_BITMAP_32x32 : \
+					 IMG_BITMAP_CUSTOM)
 
-#define TRUECOLOR_RED(pixel)	(((unsigned long)((pixel) & 0xff0000)) >> 16)
-#define TRUECOLOR_GREEN(pixel)	(((unsigned long)((pixel) & 0xff00)) >> 8)
-#define TRUECOLOR_BLUE(pixel)	( (unsigned long)((pixel) & 0xff))
-#define RGB_TO_TRUECOLOR(r,g,b)	((((unsigned long)((r) & 0xff00)) << 8) | ((g) & 0xff00) | (((unsigned short)(b)) >> 8))
+#define GET_TILESIZE_FROM_BITMAP_ID(x)	((x) == IMG_BITMAP_1x1   ? 1  :	\
+					 (x) == IMG_BITMAP_2x2   ? 2  :	\
+					 (x) == IMG_BITMAP_4x4   ? 4  :	\
+					 (x) == IMG_BITMAP_8x8   ? 8  :	\
+					 (x) == IMG_BITMAP_16x16 ? 16 :	\
+					 (x) == IMG_BITMAP_32x32 ? 32 :	\
+					 0)
 
-Image *newImage(unsigned int, unsigned int, unsigned int);
-void freeImage(Image *);
-void freeXImage(Image *, XImageInfo *);
-
-Pixmap Pixmap_to_Mask(Pixmap, int, int);
-
-void ZoomPixmap(Display *, GC, Pixmap, Pixmap, int, int, int, int);
-
-int Read_PCX_to_Pixmap(Display *, Window, GC, char *, Pixmap *, Pixmap *);
-
-#endif /* TARGET_X11 */
 
 int getImageListSize();
 struct FileInfo *getImageListEntryFromImageID(int);
-Bitmap *getBitmapFromImageID(int);
+Bitmap **getBitmapsFromImageID(int);
 int getOriginalImageWidthFromImageID(int);
 int getOriginalImageHeightFromImageID(int);
 char *getTokenFromImageID(int);
+char *getFilenameFromImageID(int);
 int getImageIDFromToken(char *);
 char *getImageConfigFilename();
 int getImageListPropertyMappingSize();
@@ -90,7 +67,9 @@ void InitImageList(struct ConfigInfo *, int, struct ConfigTypeInfo *,
 		   char **, char **, char **, char **, char **);
 
 void ReloadCustomImages();
-void CreateImageWithSmallImages(int, int);
+void CreateImageWithSmallImages(int, int, int);
+void CreateImageTextures(int);
+void FreeAllImageTextures();
 void ScaleImage(int, int);
 
 void FreeAllImages();
diff --git a/src/libgame/joystick.c b/src/libgame/joystick.c
index b286de2..92eec0e 100644
--- a/src/libgame/joystick.c
+++ b/src/libgame/joystick.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* joystick.c                                               *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// joystick.c
+// ============================================================================
 
 #if defined(PLATFORM_FREEBSD)
 #include <machine/joystick.h>
@@ -20,91 +18,6 @@
 
 
 /* ========================================================================= */
-/* platform dependent joystick functions                                     */
-/* ========================================================================= */
-
-#if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
-void UnixInitJoysticks()
-{
-  static boolean unix_joystick_subsystem_initialized = FALSE;
-  boolean print_warning = !unix_joystick_subsystem_initialized;
-  int i;
-
-  for (i = 0; i < MAX_PLAYERS; i++)
-  {
-    char *device_name = setup.input[i].joy.device_name;
-
-    /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
-    if (joystick.fd[i] != -1)
-    {
-      close(joystick.fd[i]);
-      joystick.fd[i] = -1;
-    }
-
-    if (!setup.input[i].use_joystick)
-      continue;
-
-    if (access(device_name, R_OK) != 0)
-    {
-      if (print_warning)
-	Error(ERR_WARN, "cannot access joystick device '%s'", device_name);
-
-      continue;
-    }
-
-    if ((joystick.fd[i] = open(device_name, O_RDONLY)) < 0)
-    {
-      if (print_warning)
-	Error(ERR_WARN, "cannot open joystick device '%s'", device_name);
-
-      continue;
-    }
-
-    joystick.status = JOYSTICK_ACTIVATED;
-  }
-
-  unix_joystick_subsystem_initialized = TRUE;
-}
-
-boolean UnixReadJoystick(int fd, int *x, int *y, boolean *b1, boolean *b2)
-{
-#if defined(PLATFORM_FREEBSD)
-  struct joystick joy_ctrl;
-#else
-  struct joystick_control
-  {
-    int buttons;
-    int x;
-    int y;
-  } joy_ctrl;
-#endif
-
-  if (read(fd, &joy_ctrl, sizeof(joy_ctrl)) != sizeof(joy_ctrl))
-    return FALSE;
-
-  if (x != NULL)
-    *x = joy_ctrl.x;
-  if (y != NULL)
-    *y = joy_ctrl.y;
-
-#if defined(PLATFORM_FREEBSD)
-  if (b1 != NULL)
-    *b1 = joy_ctrl.b1;
-  if (b2 != NULL)
-    *b2 = joy_ctrl.b2;
-#else
-  if (b1 != NULL)
-    *b1 = joy_ctrl.buttons & 1;
-  if (b2 != NULL)
-    *b2 = joy_ctrl.buttons & 2;
-#endif
-
-  return TRUE;
-}
-#endif /* PLATFORM_UNIX && !TARGET_SDL */
-
-
-/* ========================================================================= */
 /* platform independent joystick functions                                   */
 /* ========================================================================= */
 
@@ -208,7 +121,7 @@ char *getDeviceNameFromJoystickNr(int joystick_nr)
 
 static int JoystickPositionPercent(int center, int border, int actual)
 {
-  long range, position;
+  int range, position;
   int percent;
 
   if (border < center && actual > center)
diff --git a/src/libgame/joystick.h b/src/libgame/joystick.h
index dfc3089..c7f65fe 100644
--- a/src/libgame/joystick.h
+++ b/src/libgame/joystick.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* joystick.h                                               *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// joystick.h
+// ============================================================================
 
 #ifndef JOYSTICK_H
 #define JOYSTICK_H
@@ -36,7 +34,7 @@
 /* get these values from the program 'js' from the joystick package, */
 /* set JOYSTICK_PERCENT to a threshold appropriate for your joystick */
 
-#ifdef TARGET_SDL
+#if defined(TARGET_SDL)
 #define JOYSTICK_XLEFT		-32767
 #define JOYSTICK_XMIDDLE	0
 #define JOYSTICK_XRIGHT		32767
@@ -72,11 +70,6 @@
 #define JOY_BUTTON_NEW_PRESSED	2
 #define JOY_BUTTON_NEW_RELEASED	3
 
-#if defined(PLATFORM_UNIX)
-void UnixInitJoysticks(void);
-boolean UnixReadJoystick(int, int *, int *, boolean *, boolean *);
-#endif
-
 char *getJoyNameFromJoySymbol(int);
 int getJoySymbolFromJoyName(char *);
 int getJoystickNrFromDeviceName(char *);
diff --git a/src/libgame/libgame.h b/src/libgame/libgame.h
index d1f05c8..a3a3c80 100644
--- a/src/libgame/libgame.h
+++ b/src/libgame/libgame.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* libgame.h                                                *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// libgame.h
+// ============================================================================
 
 #ifndef LIBGAME_H
 #define LIBGAME_H
@@ -25,9 +23,7 @@
 #include "sound.h"
 #include "snapshot.h"
 #include "joystick.h"
-#include "toons.h"
 #include "image.h"
-#include "pcx.h"
 #include "setup.h"
 #include "misc.h"
 
diff --git a/src/libgame/macosx.h b/src/libgame/macosx.h
index c4818e7..236becc 100644
--- a/src/libgame/macosx.h
+++ b/src/libgame/macosx.h
@@ -1,20 +1,24 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* macosx.h                                                 *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// macosx.h
+// ============================================================================
 
 #ifndef MACOSX_H
 #define MACOSX_H
 
 
+/* define some Mac OS X specific paths */
+
+#define MAC_APP_BINARY_SUBDIR	"Contents/MacOS"
+#define MAC_APP_FILES_SUBDIR	"Contents/Resources"
+
+
 /* some symbols are already defined on Mac OS X */
 #define Delay Delay_internal
 #define DrawLine DrawLine_internal
diff --git a/src/libgame/misc.c b/src/libgame/misc.c
index b8f2fe5..4ffb51c 100644
--- a/src/libgame/misc.c
+++ b/src/libgame/misc.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* misc.c                                                   *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// misc.c
+// ============================================================================
 
 #include <time.h>
 #include <sys/time.h>
@@ -19,6 +17,7 @@
 #include <ctype.h>
 #include <string.h>
 #include <unistd.h>
+#include <errno.h>
 
 #include "platform.h"
 
@@ -39,38 +38,150 @@
 /* ========================================================================= */
 
 /* ------------------------------------------------------------------------- */
-/* platform independent wrappers for printf() et al. (newline aware)         */
+/* logging functions                                                         */
 /* ------------------------------------------------------------------------- */
 
-static void vfprintf_newline(FILE *stream, char *format, va_list ap)
+#define DUPLICATE_LOG_OUT_TO_STDOUT		TRUE
+#define DUPLICATE_LOG_ERR_TO_STDERR		TRUE
+
+
+#if defined(PLATFORM_ANDROID)
+static int android_log_prio = ANDROID_LOG_INFO;
+static char *android_log_buffer = NULL;
+
+static void append_to_android_log_buffer(char *format, va_list ap)
 {
-  char *newline = STRING_NEWLINE;
+  char text_new[MAX_OUTPUT_LINESIZE];
+
+  // print text to temporary string
+  vsnprintf(text_new, MAX_OUTPUT_LINESIZE, format, ap);
+
+  if (android_log_buffer == NULL)
+  {
+    android_log_buffer = getStringCopy(text_new);
+  }
+  else
+  {
+    char *android_log_buffer_old = android_log_buffer;
 
-  vfprintf(stream, format, ap);
+    // append new text to existing text
+    android_log_buffer = getStringCat2(android_log_buffer, text_new);
 
-  fprintf(stream, "%s", newline);
+    checked_free(android_log_buffer_old);
+  }
 }
 
-static void fprintf_newline(FILE *stream, char *format, ...)
+static void vprintf_log_nonewline(char *format, va_list ap)
 {
-  if (format)
+  // add log output to buffer until text with newline is printed
+  append_to_android_log_buffer(format, ap);
+}
+
+static void vprintf_log(char *format, va_list ap)
+{
+  // add log output to buffer
+  append_to_android_log_buffer(format, ap);
+
+  // __android_log_vprint(android_log_prio, program.program_title, format, ap);
+  __android_log_write(android_log_prio, program.program_title,
+		      android_log_buffer);
+
+  checked_free(android_log_buffer);
+  android_log_buffer = NULL;
+}
+
+#else
+
+static void vprintf_log_nonewline(char *format, va_list ap)
+{
+  FILE *file = program.log_file[LOG_ERR_ID];
+
+#if DUPLICATE_LOG_ERR_TO_STDERR
+  if (file != program.log_file_default[LOG_ERR_ID])
   {
-    va_list ap;
+    va_list ap2;
+    va_copy(ap2, ap);
 
-    va_start(ap, format);
-    vfprintf_newline(stream, format, ap);
-    va_end(ap);
+    vfprintf(program.log_file_default[LOG_ERR_ID], format, ap2);
+
+    va_end(ap2);
+  }
+#endif
+
+  vfprintf(file, format, ap);
+}
+
+static void vprintf_log(char *format, va_list ap)
+{
+  FILE *file = program.log_file[LOG_ERR_ID];
+  char *newline = STRING_NEWLINE;
+
+#if DUPLICATE_LOG_ERR_TO_STDERR
+  if (file != program.log_file_default[LOG_ERR_ID])
+  {
+    va_list ap2;
+    va_copy(ap2, ap);
+
+    vfprintf(program.log_file_default[LOG_ERR_ID], format, ap2);
+    fprintf(program.log_file_default[LOG_ERR_ID], "%s", newline);
+
+    va_end(ap2);
   }
+#endif
+
+  vfprintf(file, format, ap);
+  fprintf(file, "%s", newline);
 }
+#endif
 
-void fprintf_line(FILE *stream, char *line_chars, int line_length)
+static void printf_log_nonewline(char *format, ...)
+{
+  va_list ap;
+
+  va_start(ap, format);
+  vprintf_log_nonewline(format, ap);
+  va_end(ap);
+}
+
+static void printf_log(char *format, ...)
+{
+  va_list ap;
+
+  va_start(ap, format);
+  vprintf_log(format, ap);
+  va_end(ap);
+}
+
+static void printf_log_line(char *line_chars, int line_length)
 {
   int i;
 
   for (i = 0; i < line_length; i++)
-    fprintf(stream, "%s", line_chars);
+    printf_log_nonewline("%s", line_chars);
 
-  fprintf_newline(stream, "");
+  printf_log("");
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* platform independent wrappers for printf() et al.                         */
+/* ------------------------------------------------------------------------- */
+
+void fprintf_line(FILE *file, char *line_chars, int line_length)
+{
+  int i;
+
+  for (i = 0; i < line_length; i++)
+    fprintf(file, "%s", line_chars);
+
+  fprintf(file, "\n");
+}
+
+void fprintf_line_with_prefix(FILE *file, char *prefix, char *line_chars,
+			      int line_length)
+{
+  fprintf(file, "%s", prefix);
+  fprintf_line(file, line_chars, line_length);
 }
 
 void printf_line(char *line_chars, int line_length)
@@ -80,8 +191,51 @@ void printf_line(char *line_chars, int line_length)
 
 void printf_line_with_prefix(char *prefix, char *line_chars, int line_length)
 {
-  fprintf(stdout, "%s", prefix);
-  fprintf_line(stdout, line_chars, line_length);
+  fprintf_line_with_prefix(stdout, prefix, line_chars, line_length);
+}
+
+static void vPrint(char *format, va_list ap)
+{
+  FILE *file = program.log_file[LOG_OUT_ID];
+
+#if DUPLICATE_LOG_OUT_TO_STDOUT
+  if (file != program.log_file_default[LOG_OUT_ID])
+  {
+    va_list ap2;
+    va_copy(ap2, ap);
+
+    vfprintf(program.log_file_default[LOG_OUT_ID], format, ap2);
+
+    va_end(ap2);
+  }
+#endif
+
+  vfprintf(file, format, ap);
+}
+
+void Print(char *format, ...)
+{
+  va_list ap;
+
+  va_start(ap, format);
+  vPrint(format, ap);
+  va_end(ap);
+}
+
+void PrintLine(char *line_chars, int line_length)
+{
+  int i;
+
+  for (i = 0; i < line_length; i++)
+    Print(line_chars);
+
+  Print("\n");
+}
+
+void PrintLineWithPrefix(char *prefix, char *line_chars, int line_length)
+{
+  Print(prefix);
+  PrintLine(line_chars, line_length);
 }
 
 
@@ -167,47 +321,18 @@ boolean getTokenValueFromString(char *string, char **token, char **value)
 /* counter functions                                                         */
 /* ------------------------------------------------------------------------- */
 
-#if defined(PLATFORM_MSDOS)
-volatile unsigned long counter = 0;
-
-void increment_counter()
-{
-  counter++;
-}
-
-END_OF_FUNCTION(increment_counter);
-#endif
-
-
 /* maximal allowed length of a command line option */
 #define MAX_OPTION_LEN		256
 
-#if 1
-
-#ifdef TARGET_SDL
-static unsigned long getCurrentMS()
+static unsigned int getCurrentMS()
 {
   return SDL_GetTicks();
 }
 
-#else /* !TARGET_SDL */
-
-#if defined(PLATFORM_UNIX)
-static unsigned long getCurrentMS()
+static unsigned int mainCounter(int mode)
 {
-  struct timeval current_time;
-
-  gettimeofday(&current_time, NULL);
-
-  return current_time.tv_sec * 1000 + current_time.tv_usec / 1000;
-}
-#endif /* PLATFORM_UNIX */
-#endif /* !TARGET_SDL */
-
-static unsigned long mainCounter(int mode)
-{
-  static unsigned long base_ms = 0;
-  unsigned long current_ms;
+  static unsigned int base_ms = 0;
+  unsigned int current_ms;
 
   /* get current system milliseconds */
   current_ms = getCurrentMS();
@@ -220,142 +345,68 @@ static unsigned long mainCounter(int mode)
   return current_ms - base_ms;
 }
 
-#else
-
-#ifdef TARGET_SDL
-static unsigned long mainCounter(int mode)
-{
-  static unsigned long base_ms = 0;
-  unsigned long current_ms;
-  unsigned long counter_ms;
-
-  current_ms = SDL_GetTicks();
-
-  /* reset base time in case of counter initializing or wrap-around */
-  if (mode == INIT_COUNTER || current_ms < base_ms)
-    base_ms = current_ms;
-
-  counter_ms = current_ms - base_ms;
-
-  return counter_ms;		/* return milliseconds since last init */
-}
-
-#else /* !TARGET_SDL */
-
-#if defined(PLATFORM_UNIX)
-static unsigned long mainCounter(int mode)
-{
-  static struct timeval base_time = { 0, 0 };
-  struct timeval current_time;
-  unsigned long counter_ms;
-
-  gettimeofday(&current_time, NULL);
-
-  /* reset base time in case of counter initializing or wrap-around */
-  if (mode == INIT_COUNTER || current_time.tv_sec < base_time.tv_sec)
-    base_time = current_time;
-
-  counter_ms = (current_time.tv_sec  - base_time.tv_sec)  * 1000
-             + (current_time.tv_usec - base_time.tv_usec) / 1000;
-
-  return counter_ms;		/* return milliseconds since last init */
-}
-#endif /* PLATFORM_UNIX */
-#endif /* !TARGET_SDL */
-
-#endif
-
 void InitCounter()		/* set counter back to zero */
 {
-#if !defined(PLATFORM_MSDOS)
   mainCounter(INIT_COUNTER);
-#else
-  LOCK_VARIABLE(counter);
-  LOCK_FUNCTION(increment_counter);
-  install_int_ex(increment_counter, BPS_TO_TIMER(100));
-#endif
 }
 
-unsigned long Counter()	/* get milliseconds since last call of InitCounter() */
+unsigned int Counter()	/* get milliseconds since last call of InitCounter() */
 {
-#if !defined(PLATFORM_MSDOS)
   return mainCounter(READ_COUNTER);
-#else
-  return (counter * 10);
-#endif
 }
 
-static void sleep_milliseconds(unsigned long milliseconds_delay)
+static void sleep_milliseconds(unsigned int milliseconds_delay)
 {
-  boolean do_busy_waiting = (milliseconds_delay < 5 ? TRUE : FALSE);
-
-  if (do_busy_waiting)
-  {
-    /* we want to wait only a few ms -- if we assume that we have a
-       kernel timer resolution of 10 ms, we would wait far to long;
-       therefore it's better to do a short interval of busy waiting
-       to get our sleeping time more accurate */
-
-    unsigned long base_counter = Counter(), actual_counter = Counter();
-
-    while (actual_counter < base_counter + milliseconds_delay &&
-	   actual_counter >= base_counter)
-      actual_counter = Counter();
-  }
-  else
-  {
-#if defined(TARGET_SDL)
-    SDL_Delay(milliseconds_delay);
-#elif defined(TARGET_ALLEGRO)
-    rest(milliseconds_delay);
-#else
-    struct timeval delay;
-
-    delay.tv_sec  = milliseconds_delay / 1000;
-    delay.tv_usec = 1000 * (milliseconds_delay % 1000);
-
-    if (select(0, NULL, NULL, NULL, &delay) != 0)
-      Error(ERR_WARN, "sleep_milliseconds(): select() failed");
-#endif
-  }
+  SDL_Delay(milliseconds_delay);
 }
 
-void Delay(unsigned long delay)	/* Sleep specified number of milliseconds */
+void Delay(unsigned int delay)	/* Sleep specified number of milliseconds */
 {
   sleep_milliseconds(delay);
 }
 
-boolean FrameReached(unsigned long *frame_counter_var,
-		     unsigned long frame_delay)
+boolean DelayReachedExt(unsigned int *counter_var, unsigned int delay,
+			unsigned int actual_counter)
 {
-  unsigned long actual_frame_counter = FrameCounter;
-
-  if (actual_frame_counter >= *frame_counter_var &&
-      actual_frame_counter < *frame_counter_var + frame_delay)
+  if (actual_counter >= *counter_var &&
+      actual_counter < *counter_var + delay)
     return FALSE;
 
-  *frame_counter_var = actual_frame_counter;
+  *counter_var = actual_counter;
 
   return TRUE;
 }
 
-boolean DelayReached(unsigned long *counter_var,
-		     unsigned long delay)
+boolean FrameReached(unsigned int *frame_counter_var, unsigned int frame_delay)
 {
-  unsigned long actual_counter = Counter();
+  return DelayReachedExt(frame_counter_var, frame_delay, FrameCounter);
+}
 
-  if (actual_counter >= *counter_var &&
-      actual_counter < *counter_var + delay)
-    return FALSE;
+boolean DelayReached(unsigned int *counter_var, unsigned int delay)
+{
+  return DelayReachedExt(counter_var, delay, Counter());
+}
 
-  *counter_var = actual_counter;
+void ResetDelayCounterExt(unsigned int *counter_var,
+			  unsigned int actual_counter)
+{
+  DelayReachedExt(counter_var, 0, actual_counter);
+}
 
-  return TRUE;
+void ResetFrameCounter(unsigned int *frame_counter_var)
+{
+  FrameReached(frame_counter_var, 0);
 }
 
-void WaitUntilDelayReached(unsigned long *counter_var, unsigned long delay)
+void ResetDelayCounter(unsigned int *counter_var)
 {
-  unsigned long actual_counter;
+  DelayReached(counter_var, 0);
+}
+
+int WaitUntilDelayReached(unsigned int *counter_var, unsigned int delay)
+{
+  unsigned int actual_counter;
+  int skip_frames = 0;
 
   while (1)
   {
@@ -368,7 +419,55 @@ void WaitUntilDelayReached(unsigned long *counter_var, unsigned long delay)
       break;
   }
 
+  if (*counter_var != 0 &&
+      delay != 0 &&
+      actual_counter >= *counter_var + delay)
+  {
+    int lag = actual_counter - (*counter_var + delay);
+    int delay2 = (delay + 1) / 2;
+
+    if (lag >= delay2)
+      skip_frames = (lag + delay2) / delay;
+  }
+
   *counter_var = actual_counter;
+
+  return skip_frames;
+}
+
+void SkipUntilDelayReached(unsigned int *counter_var, unsigned int delay,
+			   int *loop_var, int last_loop_value)
+{
+  int skip_frames = WaitUntilDelayReached(counter_var, delay);
+
+#if 0
+#if DEBUG
+  printf("::: %d: %d ms", *loop_var, delay);
+  if (skip_frames)
+    printf(" -> SKIP %d FRAME(S) [%d ms]", skip_frames, skip_frames * delay);
+  printf("\n");
+#endif
+#endif
+
+  if (skip_frames == 0)
+    return;
+
+  // when skipping frames, make sure to never skip the last frame, as
+  // this may be needed for animations to reach a defined end state;
+  // furthermore, we assume that this function is called at the end
+  // of a "for" loop, which continues by incrementing the loop variable
+  // by one before checking the loop condition again; therefore we have
+  // to check against the last loop value minus one here
+
+  last_loop_value--;
+
+  if (*loop_var < last_loop_value)	// never skip the last frame
+  {
+    *loop_var += skip_frames;
+
+    if (*loop_var > last_loop_value)	// never skip the last frame
+      *loop_var = last_loop_value;
+  }
 }
 
 
@@ -376,12 +475,12 @@ void WaitUntilDelayReached(unsigned long *counter_var, unsigned long delay)
 /* random generator functions                                                */
 /* ------------------------------------------------------------------------- */
 
-unsigned int init_random_number(int nr, long seed)
+unsigned int init_random_number(int nr, int seed)
 {
   if (seed == NEW_RANDOMIZE)
   {
     /* default random seed */
-    seed = (long)time(NULL);			// seconds since the epoch
+    seed = (int)time(NULL);			// seconds since the epoch
 
 #if !defined(PLATFORM_WIN32)
     /* add some more randomness */
@@ -389,18 +488,14 @@ unsigned int init_random_number(int nr, long seed)
 
     gettimeofday(&current_time, NULL);
 
-    seed += (long)current_time.tv_usec;		// microseconds since the epoch
+    seed += (int)current_time.tv_usec;		// microseconds since the epoch
 #endif
 
-#if defined(TARGET_SDL)
     /* add some more randomness */
-    seed += (long)SDL_GetTicks();		// milliseconds since SDL init
-#endif
+    seed += (int)SDL_GetTicks();		// milliseconds since SDL init
 
-#if 1
     /* add some more randomness */
     seed += GetSimpleRandom(1000000);
-#endif
   }
 
   srandom_linux_libc(nr, (unsigned int) seed);
@@ -418,7 +513,7 @@ unsigned int get_random_number(int nr, int max)
 /* system info functions                                                     */
 /* ------------------------------------------------------------------------- */
 
-#if !defined(PLATFORM_MSDOS)
+#if !defined(PLATFORM_ANDROID)
 static char *get_corrected_real_name(char *real_name)
 {
   char *real_name_new = checked_malloc(MAX_USERNAME_LEN + 1);
@@ -426,16 +521,16 @@ static char *get_corrected_real_name(char *real_name)
   char *to_ptr   = real_name_new;
 
   /* copy the name string, but not more than MAX_USERNAME_LEN characters */
-  while (*from_ptr && (long)(to_ptr - real_name_new) < MAX_USERNAME_LEN - 1)
+  while (*from_ptr && (int)(to_ptr - real_name_new) < MAX_USERNAME_LEN - 1)
   {
     /* the name field read from "passwd" file may also contain additional
        user information, separated by commas, which will be removed here */
     if (*from_ptr == ',')
       break;
 
-    /* the user's real name may contain '�' characters (german sharp s),
+    /* the user's real name may contain 'german sharp s' characters,
        which have no equivalent in upper case letters (used by our fonts) */
-    if (*from_ptr == '�')
+    if (*from_ptr == CHAR_BYTE_SHARP_S)
     {
       from_ptr++;
       *to_ptr++ = 's';
@@ -494,7 +589,7 @@ char *getRealName()
     else
       real_name = ANONYMOUS_NAME;
   }
-#elif defined(PLATFORM_UNIX)
+#elif defined(PLATFORM_UNIX) && !defined(PLATFORM_ANDROID)
   if (real_name == NULL)
   {
     struct passwd *pwd;
@@ -551,6 +646,23 @@ char *getBaseName(char *filename)
   return getStringCopy(getBaseNamePtr(filename));
 }
 
+char *getBaseNameNoSuffix(char *filename)
+{
+  char *basename = getStringCopy(getBaseNamePtr(filename));
+
+  // remove trailing suffix (separated by dot or hyphen)
+  if (basename[0] != '.' && basename[0] != '-')
+  {
+    if (strchr(basename, '.') != NULL)
+      *strchr(basename, '.') = '\0';
+
+    if (strchr(basename, '-') != NULL)
+      *strchr(basename, '-') = '\0';
+  }
+
+  return basename;
+}
+
 char *getBasePath(char *filename)
 {
   char *basepath = getStringCopy(filename);
@@ -564,6 +676,52 @@ char *getBasePath(char *filename)
   return basepath;
 }
 
+static char *getProgramMainDataPath()
+{
+  char *main_data_path = getStringCopy(program.command_basepath);
+
+#if defined(PLATFORM_MACOSX)
+  static char *main_data_binary_subdir = NULL;
+  static char *main_data_files_subdir = NULL;
+
+  if (main_data_binary_subdir == NULL)
+  {
+    main_data_binary_subdir = checked_malloc(strlen(program.program_title) + 1 +
+					     strlen("app") + 1 +
+					     strlen(MAC_APP_BINARY_SUBDIR) + 1);
+
+    sprintf(main_data_binary_subdir, "%s.app/%s",
+	    program.program_title, MAC_APP_BINARY_SUBDIR);
+  }
+
+  if (main_data_files_subdir == NULL)
+  {
+    main_data_files_subdir = checked_malloc(strlen(program.program_title) + 1 +
+					    strlen("app") + 1 +
+					    strlen(MAC_APP_FILES_SUBDIR) + 1);
+
+    sprintf(main_data_files_subdir, "%s.app/%s",
+	    program.program_title, MAC_APP_FILES_SUBDIR);
+  }
+
+  if (strSuffix(main_data_path, main_data_binary_subdir))
+  {
+    char *main_data_path_old = main_data_path;
+
+    // cut relative path to Mac OS X application binary directory from path
+    main_data_path_old[strlen(main_data_path_old) -
+		       strlen(main_data_binary_subdir)] = '\0';
+
+    // add relative path to Mac OS X application resources directory to path
+    main_data_path = getPath2(main_data_path_old, main_data_files_subdir);
+
+    free(main_data_path_old);
+  }
+#endif
+
+  return main_data_path;
+}
+
 
 /* ------------------------------------------------------------------------- */
 /* various string functions                                                  */
@@ -571,6 +729,9 @@ char *getBasePath(char *filename)
 
 char *getStringCat2WithSeparator(char *s1, char *s2, char *sep)
 {
+  if (s1 == NULL || s2 == NULL || sep == NULL)
+    return NULL;
+
   char *complete_string = checked_malloc(strlen(s1) + strlen(sep) +
 					 strlen(s2) + 1);
 
@@ -581,6 +742,9 @@ char *getStringCat2WithSeparator(char *s1, char *s2, char *sep)
 
 char *getStringCat3WithSeparator(char *s1, char *s2, char *s3, char *sep)
 {
+  if (s1 == NULL || s2 == NULL || s3 == NULL || sep == NULL)
+    return NULL;
+
   char *complete_string = checked_malloc(strlen(s1) + strlen(sep) +
 					 strlen(s2) + strlen(sep) +
 					 strlen(s3) + 1);
@@ -602,15 +766,56 @@ char *getStringCat3(char *s1, char *s2, char *s3)
 
 char *getPath2(char *path1, char *path2)
 {
+#if defined(PLATFORM_ANDROID)
+  // workaround for reading from assets directory -- skip "." subdirs in path
+  if (strEqual(path1, "."))
+    return getStringCopy(path2);
+  else if (strEqual(path2, "."))
+    return getStringCopy(path1);
+#endif
+
   return getStringCat2WithSeparator(path1, path2, STRING_PATH_SEPARATOR);
 }
 
 char *getPath3(char *path1, char *path2, char *path3)
 {
+#if defined(PLATFORM_ANDROID)
+  // workaround for reading from assets directory -- skip "." subdirs in path
+  if (strEqual(path1, "."))
+    return getStringCat2WithSeparator(path2, path3, STRING_PATH_SEPARATOR);
+  else if (strEqual(path2, "."))
+    return getStringCat2WithSeparator(path1, path3, STRING_PATH_SEPARATOR);
+  else if (strEqual(path3, "."))
+    return getStringCat2WithSeparator(path1, path2, STRING_PATH_SEPARATOR);
+#endif
+
   return getStringCat3WithSeparator(path1, path2, path3, STRING_PATH_SEPARATOR);
 }
 
-char *getStringCopy(char *s)
+static char *getPngOrPcxIfNotExists(char *filename)
+{
+  // switch from PNG to PCX file and vice versa, if file does not exist
+  // (backwards compatibility with PCX files used in previous versions)
+
+  if (!fileExists(filename) && strSuffix(filename, ".png"))
+    strcpy(&filename[strlen(filename) - 3], "pcx");
+  else if (!fileExists(filename) && strSuffix(filename, ".pcx"))
+    strcpy(&filename[strlen(filename) - 3], "png");
+
+  return filename;
+}
+
+char *getImg2(char *path1, char *path2)
+{
+  return getPngOrPcxIfNotExists(getPath2(path1, path2));
+}
+
+char *getImg3(char *path1, char *path2, char *path3)
+{
+  return getPngOrPcxIfNotExists(getPath3(path1, path2, path3));
+}
+
+char *getStringCopy(const char *s)
 {
   char *s_copy;
 
@@ -623,7 +828,7 @@ char *getStringCopy(char *s)
   return s_copy;
 }
 
-char *getStringCopyN(char *s, int n)
+char *getStringCopyN(const char *s, int n)
 {
   char *s_copy;
   int s_len = MAX(0, n);
@@ -638,7 +843,18 @@ char *getStringCopyN(char *s, int n)
   return s_copy;
 }
 
-char *getStringToLower(char *s)
+char *getStringCopyNStatic(const char *s, int n)
+{
+  static char *s_copy = NULL;
+
+  checked_free(s_copy);
+
+  s_copy = getStringCopyN(s, n);
+
+  return s_copy;
+}
+
+char *getStringToLower(const char *s)
 {
   char *s_copy = checked_malloc(strlen(s) + 1);
   char *s_ptr = s_copy;
@@ -715,27 +931,30 @@ boolean strSuffixLower(char *s, char *suffix)
 /* command line option handling functions                                    */
 /* ------------------------------------------------------------------------- */
 
-void GetOptions(char *argv[], void (*print_usage_function)(void))
+void GetOptions(int argc, char *argv[],
+		void (*print_usage_function)(void),
+		void (*print_version_function)(void))
 {
   char *ro_base_path = RO_BASE_PATH;
   char *rw_base_path = RW_BASE_PATH;
-  char **options_left = &argv[1];
+  char **argvplus = checked_calloc((argc + 1) * sizeof(char **));
+  char **options_left = &argvplus[1];
+
+  /* replace original "argv" with null-terminated array of string pointers */
+  while (argc--)
+    argvplus[argc] = argv[argc];
 
-#if !defined(PLATFORM_MACOSX)
   /* if the program is configured to start from current directory (default),
-     determine program package directory (KDE/Konqueror does not do this by
-     itself and fails otherwise); on Mac OS X, the program binary is stored
-     in an application package directory -- do not try to use this directory
-     as the program data directory (Mac OS X handles this correctly anyway) */
+     determine program package directory from program binary (some versions
+     of KDE/Konqueror and Mac OS X (especially "Mavericks") apparently do not
+     set the current working directory to the program package directory) */
 
   if (strEqual(ro_base_path, "."))
-    ro_base_path = program.command_basepath;
+    ro_base_path = getProgramMainDataPath();
   if (strEqual(rw_base_path, "."))
-    rw_base_path = program.command_basepath;
-#endif
+    rw_base_path = getProgramMainDataPath();
 
   /* initialize global program options */
-  options.display_name = NULL;
   options.server_host = NULL;
   options.server_port = 0;
 
@@ -750,16 +969,20 @@ void GetOptions(char *argv[], void (*print_usage_function)(void))
   options.execute_command = NULL;
   options.special_flags = NULL;
 
+  options.mytapes = FALSE;
   options.serveronly = FALSE;
   options.network = FALSE;
   options.verbose = FALSE;
   options.debug = FALSE;
-  options.debug_x11_sync = FALSE;
 
+#if 1
+  options.verbose = TRUE;
+#else
 #if !defined(PLATFORM_UNIX)
   if (*options_left == NULL)	/* no options given -- enable verbose mode */
     options.verbose = TRUE;
 #endif
+#endif
 
   while (*options_left)
   {
@@ -794,22 +1017,15 @@ void GetOptions(char *argv[], void (*print_usage_function)(void))
     option_len = strlen(option);
 
     if (strEqual(option, "-"))
+    {
       Error(ERR_EXIT_HELP, "unrecognized option '%s'", option);
+    }
     else if (strncmp(option, "-help", option_len) == 0)
     {
       print_usage_function();
 
       exit(0);
     }
-    else if (strncmp(option, "-display", option_len) == 0)
-    {
-      if (option_arg == NULL)
-	Error(ERR_EXIT_HELP, "option '%s' requires an argument", option_str);
-
-      options.display_name = option_arg;
-      if (option_arg == next_option)
-	options_left++;
-    }
     else if (strncmp(option, "-basepath", option_len) == 0)
     {
       if (option_arg == NULL)
@@ -864,6 +1080,10 @@ void GetOptions(char *argv[], void (*print_usage_function)(void))
       if (option_arg == next_option)
 	options_left++;
     }
+    else if (strncmp(option, "-mytapes", option_len) == 0)
+    {
+      options.mytapes = TRUE;
+    }
     else if (strncmp(option, "-network", option_len) == 0)
     {
       options.network = TRUE;
@@ -872,36 +1092,24 @@ void GetOptions(char *argv[], void (*print_usage_function)(void))
     {
       options.serveronly = TRUE;
     }
-    else if (strncmp(option, "-verbose", option_len) == 0)
-    {
-      options.verbose = TRUE;
-    }
     else if (strncmp(option, "-debug", option_len) == 0)
     {
       options.debug = TRUE;
     }
-    else if (strncmp(option, "-debug-x11-sync", option_len) == 0)
+    else if (strncmp(option, "-verbose", option_len) == 0)
     {
-      options.debug_x11_sync = TRUE;
+      options.verbose = TRUE;
+    }
+    else if (strncmp(option, "-version", option_len) == 0 ||
+	     strncmp(option, "-V", option_len) == 0)
+    {
+      print_version_function();
+
+      exit(0);
     }
     else if (strPrefix(option, "-D"))
     {
-#if 1
       options.special_flags = getStringCopy(&option[2]);
-#else
-      char *flags_string = &option[2];
-      unsigned long flags_value;
-
-      if (*flags_string == '\0')
-	Error(ERR_EXIT_HELP, "empty flag ignored");
-
-      flags_value = get_special_flags_function(flags_string);
-
-      if (flags_value == 0)
-	Error(ERR_EXIT_HELP, "unknown flag '%s'", flags_string);
-
-      options.special_flags |= flags_value;
-#endif
     }
     else if (strncmp(option, "-execute", option_len) == 0)
     {
@@ -915,6 +1123,12 @@ void GetOptions(char *argv[], void (*print_usage_function)(void))
       /* when doing batch processing, always enable verbose mode (warnings) */
       options.verbose = TRUE;
     }
+#if defined(PLATFORM_MACOSX)
+    else if (strPrefix(option, "-psn"))
+    {
+      /* ignore process serial number when launched via GUI on Mac OS X */
+    }
+#endif
     else if (*option == '-')
     {
       Error(ERR_EXIT_HELP, "unrecognized option '%s'", option_str);
@@ -941,15 +1155,17 @@ void GetOptions(char *argv[], void (*print_usage_function)(void))
 /* error handling functions                                                  */
 /* ------------------------------------------------------------------------- */
 
+#define MAX_INTERNAL_ERROR_SIZE		1024
+
 /* used by SetError() and GetError() to store internal error messages */
-static char internal_error[1024];	/* this is bad */
+static char internal_error[MAX_INTERNAL_ERROR_SIZE];
 
 void SetError(char *format, ...)
 {
   va_list ap;
 
   va_start(ap, format);
-  vsprintf(internal_error, format, ap);
+  vsnprintf(internal_error, MAX_INTERNAL_ERROR_SIZE, format, ap);
   va_end(ap);
 }
 
@@ -963,6 +1179,17 @@ void Error(int mode, char *format, ...)
   static boolean last_line_was_separator = FALSE;
   char *process_name = "";
 
+  if (program.log_file[LOG_ERR_ID] == NULL)
+    return;
+
+#if defined(PLATFORM_ANDROID)
+  android_log_prio = (mode & ERR_DEBUG ? ANDROID_LOG_DEBUG :
+		      mode & ERR_INFO ? ANDROID_LOG_INFO :
+		      mode & ERR_WARN ? ANDROID_LOG_WARN :
+		      mode & ERR_EXIT ? ANDROID_LOG_FATAL :
+		      ANDROID_LOG_UNKNOWN);
+#endif
+
   /* display warnings only when running in verbose mode */
   if (mode & ERR_WARN && !options.verbose)
     return;
@@ -970,7 +1197,7 @@ void Error(int mode, char *format, ...)
   if (mode == ERR_INFO_LINE)
   {
     if (!last_line_was_separator)
-      fprintf_line(program.error_file, format, 79);
+      printf_log_line(format, 79);
 
     last_line_was_separator = TRUE;
 
@@ -988,27 +1215,36 @@ void Error(int mode, char *format, ...)
 
   if (format)
   {
-    va_list ap;
-
-    fprintf(program.error_file, "%s%s: ", program.command_basename,
-	    process_name);
+#if !defined(PLATFORM_ANDROID)
+    printf_log_nonewline("%s%s: ", program.command_basename, process_name);
+#endif
 
     if (mode & ERR_WARN)
-      fprintf(program.error_file, "warning: ");
+      printf_log_nonewline("warning: ");
+
+    if (mode & ERR_EXIT)
+      printf_log_nonewline("fatal error: ");
+
+    va_list ap;
 
     va_start(ap, format);
-    vfprintf_newline(program.error_file, format, ap);
+    vprintf_log(format, ap);
     va_end(ap);
+
+    if ((mode & ERR_EXIT) && !(mode & ERR_FROM_SERVER))
+    {
+      va_start(ap, format);
+      program.exit_message_function(format, ap);
+      va_end(ap);
+    }
   }
   
   if (mode & ERR_HELP)
-    fprintf_newline(program.error_file,
-		    "%s: Try option '--help' for more information.",
-		    program.command_basename);
+    printf_log("%s: Try option '--help' for more information.",
+	       program.command_basename);
 
   if (mode & ERR_EXIT)
-    fprintf_newline(program.error_file, "%s%s: aborting",
-		    program.command_basename, process_name);
+    printf_log("%s%s: aborting", program.command_basename, process_name);
 
   if (mode & ERR_EXIT)
   {
@@ -1024,7 +1260,7 @@ void Error(int mode, char *format, ...)
 /* checked memory allocation and freeing functions                           */
 /* ------------------------------------------------------------------------- */
 
-void *checked_malloc(unsigned long size)
+void *checked_malloc(unsigned int size)
 {
   void *ptr;
 
@@ -1036,7 +1272,7 @@ void *checked_malloc(unsigned long size)
   return ptr;
 }
 
-void *checked_calloc(unsigned long size)
+void *checked_calloc(unsigned int size)
 {
   void *ptr;
 
@@ -1048,7 +1284,7 @@ void *checked_calloc(unsigned long size)
   return ptr;
 }
 
-void *checked_realloc(void *ptr, unsigned long size)
+void *checked_realloc(void *ptr, unsigned int size)
 {
   ptr = realloc(ptr, size);
 
@@ -1064,7 +1300,7 @@ void checked_free(void *ptr)
     free(ptr);
 }
 
-void clear_mem(void *ptr, unsigned long size)
+void clear_mem(void *ptr, unsigned int size)
 {
 #if defined(PLATFORM_WIN32)
   /* for unknown reason, memset() sometimes crashes when compiled with MinGW */
@@ -1082,7 +1318,7 @@ void clear_mem(void *ptr, unsigned long size)
 /* various helper functions                                                  */
 /* ------------------------------------------------------------------------- */
 
-inline void swap_numbers(int *i1, int *i2)
+void swap_numbers(int *i1, int *i2)
 {
   int help = *i1;
 
@@ -1090,7 +1326,7 @@ inline void swap_numbers(int *i1, int *i2)
   *i2 = help;
 }
 
-inline void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
+void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
 {
   int help_x = *x1;
   int help_y = *y1;
@@ -1108,9 +1344,9 @@ inline void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
    of the (not yet written) chunk, write the correct chunk size and finally
    write the chunk itself */
 
-int getFile8BitInteger(FILE *file)
+int getFile8BitInteger(File *file)
 {
-  return fgetc(file);
+  return getByteFromFile(file);
 }
 
 int putFile8BitInteger(FILE *file, int value)
@@ -1121,14 +1357,14 @@ int putFile8BitInteger(FILE *file, int value)
   return 1;
 }
 
-int getFile16BitInteger(FILE *file, int byte_order)
+int getFile16BitInteger(File *file, int byte_order)
 {
   if (byte_order == BYTE_ORDER_BIG_ENDIAN)
-    return ((fgetc(file) << 8) |
-	    (fgetc(file) << 0));
+    return ((getByteFromFile(file) << 8) |
+	    (getByteFromFile(file) << 0));
   else		 /* BYTE_ORDER_LITTLE_ENDIAN */
-    return ((fgetc(file) << 0) |
-	    (fgetc(file) << 8));
+    return ((getByteFromFile(file) << 0) |
+	    (getByteFromFile(file) << 8));
 }
 
 int putFile16BitInteger(FILE *file, int value, int byte_order)
@@ -1150,18 +1386,18 @@ int putFile16BitInteger(FILE *file, int value, int byte_order)
   return 2;
 }
 
-int getFile32BitInteger(FILE *file, int byte_order)
+int getFile32BitInteger(File *file, int byte_order)
 {
   if (byte_order == BYTE_ORDER_BIG_ENDIAN)
-    return ((fgetc(file) << 24) |
-	    (fgetc(file) << 16) |
-	    (fgetc(file) <<  8) |
-	    (fgetc(file) <<  0));
+    return ((getByteFromFile(file) << 24) |
+	    (getByteFromFile(file) << 16) |
+	    (getByteFromFile(file) <<  8) |
+	    (getByteFromFile(file) <<  0));
   else		 /* BYTE_ORDER_LITTLE_ENDIAN */
-    return ((fgetc(file) <<  0) |
-	    (fgetc(file) <<  8) |
-	    (fgetc(file) << 16) |
-	    (fgetc(file) << 24));
+    return ((getByteFromFile(file) <<  0) |
+	    (getByteFromFile(file) <<  8) |
+	    (getByteFromFile(file) << 16) |
+	    (getByteFromFile(file) << 24));
 }
 
 int putFile32BitInteger(FILE *file, int value, int byte_order)
@@ -1187,13 +1423,14 @@ int putFile32BitInteger(FILE *file, int value, int byte_order)
   return 4;
 }
 
-boolean getFileChunk(FILE *file, char *chunk_name, int *chunk_size,
+boolean getFileChunk(File *file, char *chunk_name, int *chunk_size,
 		     int byte_order)
 {
   const int chunk_name_length = 4;
 
   /* read chunk name */
-  fgets(chunk_name, chunk_name_length + 1, file);
+  if (getStringFromFile(file, chunk_name, chunk_name_length + 1) == NULL)
+    return FALSE;
 
   if (chunk_size != NULL)
   {
@@ -1201,7 +1438,7 @@ boolean getFileChunk(FILE *file, char *chunk_name, int *chunk_size,
     *chunk_size = getFile32BitInteger(file, byte_order);
   }
 
-  return (feof(file) || ferror(file) ? FALSE : TRUE);
+  return (checkEndOfFile(file) ? FALSE : TRUE);
 }
 
 int putFileChunk(FILE *file, char *chunk_name, int chunk_size,
@@ -1227,12 +1464,12 @@ int putFileChunk(FILE *file, char *chunk_name, int chunk_size,
   return num_bytes;
 }
 
-int getFileVersion(FILE *file)
+int getFileVersion(File *file)
 {
-  int version_major = fgetc(file);
-  int version_minor = fgetc(file);
-  int version_patch = fgetc(file);
-  int version_build = fgetc(file);
+  int version_major = getByteFromFile(file);
+  int version_minor = getByteFromFile(file);
+  int version_patch = getByteFromFile(file);
+  int version_build = getByteFromFile(file);
 
   return VERSION_IDENT(version_major, version_minor, version_patch,
 		       version_build);
@@ -1256,15 +1493,15 @@ int putFileVersion(FILE *file, int version)
   return 4;
 }
 
-void ReadBytesFromFile(FILE *file, byte *buffer, unsigned long bytes)
+void ReadBytesFromFile(File *file, byte *buffer, unsigned int bytes)
 {
   int i;
 
-  for(i = 0; i < bytes && !feof(file); i++)
-    buffer[i] = fgetc(file);
+  for (i = 0; i < bytes && !checkEndOfFile(file); i++)
+    buffer[i] = getByteFromFile(file);
 }
 
-void WriteBytesToFile(FILE *file, byte *buffer, unsigned long bytes)
+void WriteBytesToFile(FILE *file, byte *buffer, unsigned int bytes)
 {
   int i;
 
@@ -1272,13 +1509,13 @@ void WriteBytesToFile(FILE *file, byte *buffer, unsigned long bytes)
     fputc(buffer[i], file);
 }
 
-void ReadUnusedBytesFromFile(FILE *file, unsigned long bytes)
+void ReadUnusedBytesFromFile(File *file, unsigned int bytes)
 {
-  while (bytes-- && !feof(file))
-    fgetc(file);
+  while (bytes-- && !checkEndOfFile(file))
+    getByteFromFile(file);
 }
 
-void WriteUnusedBytesToFile(FILE *file, unsigned long bytes)
+void WriteUnusedBytesToFile(FILE *file, unsigned int bytes)
 {
   while (bytes--)
     fputc(0, file);
@@ -1336,8 +1573,10 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
     { KSYM_Meta_R,	"XK_Meta_R",		"right meta" },
     { KSYM_Alt_L,	"XK_Alt_L",		"left alt" },
     { KSYM_Alt_R,	"XK_Alt_R",		"right alt" },
+#if !defined(TARGET_SDL2)
     { KSYM_Super_L,	"XK_Super_L",		"left super" },	 /* Win-L */
     { KSYM_Super_R,	"XK_Super_R",		"right super" }, /* Win-R */
+#endif
     { KSYM_Mode_switch,	"XK_Mode_switch",	"mode switch" }, /* Alt-R */
     { KSYM_Multi_key,	"XK_Multi_key",		"multi key" },	 /* Ctrl-R */
 
@@ -1350,7 +1589,11 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
     { KSYM_End,		"XK_End",		"end" },
     { KSYM_Page_Up,	"XK_Page_Up",		"page up" },
     { KSYM_Page_Down,	"XK_Page_Down",		"page down" },
-    { KSYM_Menu,	"XK_Menu",		"menu" },	 /* Win-Menu */
+
+#if defined(TARGET_SDL2)
+    { KSYM_Menu,	"XK_Menu",		"menu" },	 /* menu key */
+    { KSYM_Back,	"XK_Back",		"back" },	 /* back key */
+#endif
 
     /* ASCII 0x20 to 0x40 keys (except numbers) */
     { KSYM_space,	"XK_space",		"space" },
@@ -1391,15 +1634,44 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
     { KSYM_asciitilde,	"XK_asciitilde",	"~" },
 
     /* special (non-ASCII) keys */
-    { KSYM_degree,	"XK_degree",		"�" },
-    { KSYM_Adiaeresis,	"XK_Adiaeresis",	"�" },
-    { KSYM_Odiaeresis,	"XK_Odiaeresis",	"�" },
-    { KSYM_Udiaeresis,	"XK_Udiaeresis",	"�" },
-    { KSYM_adiaeresis,	"XK_adiaeresis",	"�" },
-    { KSYM_odiaeresis,	"XK_odiaeresis",	"�" },
-    { KSYM_udiaeresis,	"XK_udiaeresis",	"�" },
+    { KSYM_degree,	"XK_degree",		"degree" },
+    { KSYM_Adiaeresis,	"XK_Adiaeresis",	"A umlaut" },
+    { KSYM_Odiaeresis,	"XK_Odiaeresis",	"O umlaut" },
+    { KSYM_Udiaeresis,	"XK_Udiaeresis",	"U umlaut" },
+    { KSYM_adiaeresis,	"XK_adiaeresis",	"a umlaut" },
+    { KSYM_odiaeresis,	"XK_odiaeresis",	"o umlaut" },
+    { KSYM_udiaeresis,	"XK_udiaeresis",	"u umlaut" },
     { KSYM_ssharp,	"XK_ssharp",		"sharp s" },
 
+#if defined(TARGET_SDL2)
+    /* special (non-ASCII) keys (UTF-8, for reverse mapping only) */
+    { KSYM_degree,	"XK_degree",		"\xc2\xb0" },
+    { KSYM_Adiaeresis,	"XK_Adiaeresis",	"\xc3\x84" },
+    { KSYM_Odiaeresis,	"XK_Odiaeresis",	"\xc3\x96" },
+    { KSYM_Udiaeresis,	"XK_Udiaeresis",	"\xc3\x9c" },
+    { KSYM_adiaeresis,	"XK_adiaeresis",	"\xc3\xa4" },
+    { KSYM_odiaeresis,	"XK_odiaeresis",	"\xc3\xb6" },
+    { KSYM_udiaeresis,	"XK_udiaeresis",	"\xc3\xbc" },
+    { KSYM_ssharp,	"XK_ssharp",		"\xc3\x9f" },
+
+    /* other keys (for reverse mapping only) */
+    { KSYM_space,	"XK_space",		" " },
+#endif
+
+#if defined(TARGET_SDL2)
+    /* keypad keys are not in numerical order in SDL2 */
+    { KSYM_KP_0,	"XK_KP_0",		"keypad 0" },
+    { KSYM_KP_1,	"XK_KP_1",		"keypad 1" },
+    { KSYM_KP_2,	"XK_KP_2",		"keypad 2" },
+    { KSYM_KP_3,	"XK_KP_3",		"keypad 3" },
+    { KSYM_KP_4,	"XK_KP_4",		"keypad 4" },
+    { KSYM_KP_5,	"XK_KP_5",		"keypad 5" },
+    { KSYM_KP_6,	"XK_KP_6",		"keypad 6" },
+    { KSYM_KP_7,	"XK_KP_7",		"keypad 7" },
+    { KSYM_KP_8,	"XK_KP_8",		"keypad 8" },
+    { KSYM_KP_9,	"XK_KP_9",		"keypad 9" },
+#endif
+
     /* end-of-array identifier */
     { 0,                NULL,			NULL }
   };
@@ -1417,8 +1689,10 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
       sprintf(name_buffer, "%c", 'a' + (char)(key - KSYM_a));
     else if (key >= KSYM_0 && key <= KSYM_9)
       sprintf(name_buffer, "%c", '0' + (char)(key - KSYM_0));
+#if !defined(TARGET_SDL2)
     else if (key >= KSYM_KP_0 && key <= KSYM_KP_9)
       sprintf(name_buffer, "keypad %c", '0' + (char)(key - KSYM_KP_0));
+#endif
     else if (key >= KSYM_FKEY_FIRST && key <= KSYM_FKEY_LAST)
       sprintf(name_buffer, "F%d", (int)(key - KSYM_FKEY_FIRST + 1));
     else if (key == KSYM_UNDEFINED)
@@ -1454,8 +1728,10 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
       sprintf(name_buffer, "XK_%c", 'a' + (char)(key - KSYM_a));
     else if (key >= KSYM_0 && key <= KSYM_9)
       sprintf(name_buffer, "XK_%c", '0' + (char)(key - KSYM_0));
+#if !defined(TARGET_SDL2)
     else if (key >= KSYM_KP_0 && key <= KSYM_KP_9)
       sprintf(name_buffer, "XK_KP_%c", '0' + (char)(key - KSYM_KP_0));
+#endif
     else if (key >= KSYM_FKEY_FIRST && key <= KSYM_FKEY_LAST)
       sprintf(name_buffer, "XK_F%d", (int)(key - KSYM_FKEY_FIRST + 1));
     else if (key == KSYM_UNDEFINED)
@@ -1475,7 +1751,7 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
       while (translate_key[++i].x11name);
 
       if (!translate_key[i].x11name)
-	sprintf(name_buffer, "0x%04lx", (unsigned long)key);
+	sprintf(name_buffer, "0x%04x", (unsigned int)key);
     }
 
     *x11name = name_buffer;
@@ -1483,17 +1759,34 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
   else if (mode == TRANSLATE_KEYNAME_TO_KEYSYM)
   {
     Key key = KSYM_UNDEFINED;
+    char *name_ptr = *name;
 
-    i = 0;
-    do
+    if (strlen(*name) == 1)
+    {
+      char c = name_ptr[0];
+
+      if (c >= 'A' && c <= 'Z')
+	key = KSYM_A + (Key)(c - 'A');
+      else if (c >= 'a' && c <= 'z')
+	key = KSYM_a + (Key)(c - 'a');
+      else if (c >= '0' && c <= '9')
+	key = KSYM_0 + (Key)(c - '0');
+    }
+
+    if (key == KSYM_UNDEFINED)
     {
-      if (strEqual(translate_key[i].name, *name))
+      i = 0;
+
+      do
       {
-	key = translate_key[i].key;
-	break;
+	if (strEqual(translate_key[i].name, *name))
+	{
+	  key = translate_key[i].key;
+	  break;
+	}
       }
+      while (translate_key[++i].x11name);
     }
-    while (translate_key[++i].x11name);
 
     if (key == KSYM_UNDEFINED)
       Error(ERR_WARN, "getKeyFromKeyName(): not completely implemented");
@@ -1516,6 +1809,7 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
       else if (c >= '0' && c <= '9')
 	key = KSYM_0 + (Key)(c - '0');
     }
+#if !defined(TARGET_SDL2)
     else if (strPrefix(name_ptr, "XK_KP_") && strlen(name_ptr) == 7)
     {
       char c = name_ptr[6];
@@ -1523,6 +1817,7 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
       if (c >= '0' && c <= '9')
 	key = KSYM_KP_0 + (Key)(c - '0');
     }
+#endif
     else if (strPrefix(name_ptr, "XK_F") && strlen(name_ptr) <= 6)
     {
       char c1 = name_ptr[4];
@@ -1552,7 +1847,7 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
     }
     else if (strPrefix(name_ptr, "0x"))
     {
-      unsigned long value = 0;
+      unsigned int value = 0;
 
       name_ptr += 2;
 
@@ -1619,6 +1914,26 @@ Key getKeyFromX11KeyName(char *x11name)
 
 char getCharFromKey(Key key)
 {
+  static struct
+  {
+    Key key;
+    byte key_char;
+  } translate_key_char[] =
+  {
+    /* special (non-ASCII) keys (ISO-8859-1) */
+    { KSYM_degree,	CHAR_BYTE_DEGREE	},
+    { KSYM_Adiaeresis,	CHAR_BYTE_UMLAUT_A	},
+    { KSYM_Odiaeresis,	CHAR_BYTE_UMLAUT_O	},
+    { KSYM_Udiaeresis,	CHAR_BYTE_UMLAUT_U	},
+    { KSYM_adiaeresis,	CHAR_BYTE_UMLAUT_a	},
+    { KSYM_odiaeresis,	CHAR_BYTE_UMLAUT_o	},
+    { KSYM_udiaeresis,	CHAR_BYTE_UMLAUT_u	},
+    { KSYM_ssharp,	CHAR_BYTE_SHARP_S	},
+
+    /* end-of-array identifier */
+    { 0,                0			}
+  };
+
   char *keyname = getKeyNameFromKey(key);
   char c = 0;
 
@@ -1626,6 +1941,21 @@ char getCharFromKey(Key key)
     c = keyname[0];
   else if (strEqual(keyname, "space"))
     c = ' ';
+  else
+  {
+    int i = 0;
+
+    do
+    {
+      if (key == translate_key_char[i].key)
+      {
+	c = translate_key_char[i].key_char;
+
+	break;
+      }
+    }
+    while (translate_key_char[++i].key_char);
+  }
 
   return c;
 }
@@ -1741,70 +2071,429 @@ void addNodeToList(ListNode **node_first, char *key, void *content)
 {
   ListNode *node_new = newListNode();
 
-  node_new->key = getStringCopy(key);
-  node_new->content = content;
-  node_new->next = *node_first;
-  *node_first = node_new;
+  node_new->key = getStringCopy(key);
+  node_new->content = content;
+  node_new->next = *node_first;
+
+  if (*node_first)
+    (*node_first)->prev = node_new;
+
+  *node_first = node_new;
+}
+
+void deleteNodeFromList(ListNode **node_first, char *key,
+			void (*destructor_function)(void *))
+{
+  if (node_first == NULL || *node_first == NULL)
+    return;
+
+  if (strEqual((*node_first)->key, key))
+  {
+    // after first recursion, (*node_first)->prev->next == *node_first,
+    // so *node_first would be overwritten with (*node_first)->next
+    // => use a copy of *node_first (and later of (*node_first)->next)
+    ListNode *node = *node_first;
+    ListNode *node_next = node->next;
+
+    checked_free(node->key);
+
+    if (destructor_function)
+      destructor_function(node->content);
+
+    if (node->prev)
+      node->prev->next = node->next;
+
+    if (node->next)
+      node->next->prev = node->prev;
+
+    checked_free(node);
+
+    // after removing node, set list pointer to next valid list node
+    // (this is important if the first node of the list was deleted)
+    *node_first = node_next;
+  }
+  else
+  {
+    deleteNodeFromList(&(*node_first)->next, key, destructor_function);
+  }
+}
+
+ListNode *getNodeFromKey(ListNode *node_first, char *key)
+{
+  if (node_first == NULL)
+    return NULL;
+
+  if (strEqual(node_first->key, key))
+    return node_first;
+  else
+    return getNodeFromKey(node_first->next, key);
+}
+
+int getNumNodes(ListNode *node_first)
+{
+  return (node_first ? 1 + getNumNodes(node_first->next) : 0);
+}
+
+void dumpList(ListNode *node_first)
+{
+  ListNode *node = node_first;
+
+  while (node)
+  {
+    printf("['%s' (%d)]\n", node->key,
+	   ((struct ListNodeInfo *)node->content)->num_references);
+    node = node->next;
+  }
+
+  printf("[%d nodes]\n", getNumNodes(node_first));
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* functions for file handling                                               */
+/* ------------------------------------------------------------------------- */
+
+File *openFile(char *filename, char *mode)
+{
+  File *file = checked_calloc(sizeof(File));
+
+  file->file = fopen(filename, mode);
+
+  if (file->file != NULL)
+  {
+    file->filename = getStringCopy(filename);
+
+    return file;
+  }
+
+#if defined(PLATFORM_ANDROID)
+  file->asset_file = SDL_RWFromFile(filename, mode);
+
+  if (file->asset_file != NULL)
+  {
+    file->file_is_asset = TRUE;
+    file->filename = getStringCopy(filename);
+
+    return file;
+  }
+#endif
+
+  checked_free(file);
+
+  return NULL;
+}
+
+int closeFile(File *file)
+{
+  if (file == NULL)
+    return -1;
+
+  int result = 0;
+
+#if defined(PLATFORM_ANDROID)
+  if (file->asset_file)
+    result = SDL_RWclose(file->asset_file);
+#endif
+
+  if (file->file)
+    result = fclose(file->file);
+
+  checked_free(file->filename);
+  checked_free(file);
+
+  return result;
+}
+
+int checkEndOfFile(File *file)
+{
+#if defined(PLATFORM_ANDROID)
+  if (file->file_is_asset)
+    return file->end_of_file;
+#endif
+
+  return feof(file->file);
+}
+
+size_t readFile(File *file, void *buffer, size_t item_size, size_t num_items)
+{
+#if defined(PLATFORM_ANDROID)
+  if (file->file_is_asset)
+  {
+    if (file->end_of_file)
+      return 0;
+
+    size_t num_items_read =
+      SDL_RWread(file->asset_file, buffer, item_size, num_items);
+
+    if (num_items_read < num_items)
+      file->end_of_file = TRUE;
+
+    return num_items_read;
+  }
+#endif
+
+  return fread(buffer, item_size, num_items, file->file);
+}
+
+int seekFile(File *file, long offset, int whence)
+{
+#if defined(PLATFORM_ANDROID)
+  if (file->file_is_asset)
+  {
+    int sdl_whence = (whence == SEEK_SET ? RW_SEEK_SET :
+		      whence == SEEK_CUR ? RW_SEEK_CUR :
+		      whence == SEEK_END ? RW_SEEK_END : 0);
+
+    return (SDL_RWseek(file->asset_file, offset, sdl_whence) == -1 ? -1 : 0);
+  }
+#endif
+
+  return fseek(file->file, offset, whence);
+}
+
+int getByteFromFile(File *file)
+{
+#if defined(PLATFORM_ANDROID)
+  if (file->file_is_asset)
+  {
+    if (file->end_of_file)
+      return EOF;
+
+    byte c;
+    size_t num_bytes_read = SDL_RWread(file->asset_file, &c, 1, 1);
+
+    if (num_bytes_read < 1)
+      file->end_of_file = TRUE;
+
+    return (file->end_of_file ? EOF : (int)c);
+  }
+#endif
+
+  return fgetc(file->file);
+}
+
+char *getStringFromFile(File *file, char *line, int size)
+{
+#if defined(PLATFORM_ANDROID)
+  if (file->file_is_asset)
+  {
+    if (file->end_of_file)
+      return NULL;
+
+    char *line_ptr = line;
+    int num_bytes_read = 0;
+
+    while (num_bytes_read < size - 1 &&
+	   SDL_RWread(file->asset_file, line_ptr, 1, 1) == 1 &&
+	   *line_ptr++ != '\n')
+      num_bytes_read++;
+
+    *line_ptr = '\0';
+
+    if (strlen(line) == 0)
+    {
+      file->end_of_file = TRUE;
+
+      return NULL;
+    }
+
+    return line;
+  }
+#endif
+
+  return fgets(line, size, file->file);
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* functions for directory handling                                          */
+/* ------------------------------------------------------------------------- */
+
+Directory *openDirectory(char *dir_name)
+{
+  Directory *dir = checked_calloc(sizeof(Directory));
+
+  dir->dir = opendir(dir_name);
+
+  if (dir->dir != NULL)
+  {
+    dir->filename = getStringCopy(dir_name);
+
+    return dir;
+  }
+
+#if defined(PLATFORM_ANDROID)
+  char *asset_toc_filename = getPath2(dir_name, ASSET_TOC_BASENAME);
+
+  dir->asset_toc_file = SDL_RWFromFile(asset_toc_filename, MODE_READ);
+
+  checked_free(asset_toc_filename);
+
+  if (dir->asset_toc_file != NULL)
+  {
+    dir->directory_is_asset = TRUE;
+    dir->filename = getStringCopy(dir_name);
+
+    return dir;
+  }
+#endif
+
+  checked_free(dir);
+
+  return NULL;
+}
+
+int closeDirectory(Directory *dir)
+{
+  if (dir == NULL)
+    return -1;
+
+  int result = 0;
+
+#if defined(PLATFORM_ANDROID)
+  if (dir->asset_toc_file)
+    result = SDL_RWclose(dir->asset_toc_file);
+#endif
+
+  if (dir->dir)
+    result = closedir(dir->dir);
+
+  if (dir->dir_entry)
+    freeDirectoryEntry(dir->dir_entry);
+
+  checked_free(dir->filename);
+  checked_free(dir);
+
+  return result;
+}
+
+DirectoryEntry *readDirectory(Directory *dir)
+{
+  if (dir->dir_entry)
+    freeDirectoryEntry(dir->dir_entry);
+
+  dir->dir_entry = NULL;
+
+#if defined(PLATFORM_ANDROID)
+  if (dir->directory_is_asset)
+  {
+    char line[MAX_LINE_LEN];
+    char *line_ptr = line;
+    int num_bytes_read = 0;
+
+    while (num_bytes_read < MAX_LINE_LEN - 1 &&
+	   SDL_RWread(dir->asset_toc_file, line_ptr, 1, 1) == 1 &&
+	   *line_ptr != '\n')
+    {
+      line_ptr++;
+      num_bytes_read++;
+    }
+
+    *line_ptr = '\0';
+
+    if (strlen(line) == 0)
+      return NULL;
+
+    dir->dir_entry = checked_calloc(sizeof(DirectoryEntry));
+
+    dir->dir_entry->is_directory = FALSE;
+    if (line[strlen(line) - 1] == '/')
+    {
+      dir->dir_entry->is_directory = TRUE;
+
+      line[strlen(line) - 1] = '\0';
+    }
+
+    dir->dir_entry->basename = getStringCopy(line);
+    dir->dir_entry->filename = getPath2(dir->filename, line);
+
+    return dir->dir_entry;
+  }
+#endif
+
+  struct dirent *dir_entry = readdir(dir->dir);
+
+  if (dir_entry == NULL)
+    return NULL;
+
+  dir->dir_entry = checked_calloc(sizeof(DirectoryEntry));
+
+  dir->dir_entry->basename = getStringCopy(dir_entry->d_name);
+  dir->dir_entry->filename = getPath2(dir->filename, dir_entry->d_name);
+
+  struct stat file_status;
+
+  dir->dir_entry->is_directory =
+    (stat(dir->dir_entry->filename, &file_status) == 0 &&
+     S_ISDIR(file_status.st_mode));
+
+  return dir->dir_entry;
 }
 
-void deleteNodeFromList(ListNode **node_first, char *key,
-			void (*destructor_function)(void *))
+void freeDirectoryEntry(DirectoryEntry *dir_entry)
 {
-  if (node_first == NULL || *node_first == NULL)
+  if (dir_entry == NULL)
     return;
 
-  if (strEqual((*node_first)->key, key))
-  {
-    checked_free((*node_first)->key);
-    if (destructor_function)
-      destructor_function((*node_first)->content);
-    *node_first = (*node_first)->next;
-  }
-  else
-    deleteNodeFromList(&(*node_first)->next, key, destructor_function);
+  checked_free(dir_entry->basename);
+  checked_free(dir_entry->filename);
+  checked_free(dir_entry);
 }
 
-ListNode *getNodeFromKey(ListNode *node_first, char *key)
-{
-  if (node_first == NULL)
-    return NULL;
 
-  if (strEqual(node_first->key, key))
-    return node_first;
-  else
-    return getNodeFromKey(node_first->next, key);
-}
+/* ------------------------------------------------------------------------- */
+/* functions for checking files and filenames                                */
+/* ------------------------------------------------------------------------- */
 
-int getNumNodes(ListNode *node_first)
+boolean directoryExists(char *dir_name)
 {
-  return (node_first ? 1 + getNumNodes(node_first->next) : 0);
-}
+  if (dir_name == NULL)
+    return FALSE;
 
-void dumpList(ListNode *node_first)
-{
-  ListNode *node = node_first;
+  struct stat file_status;
+  boolean success = (stat(dir_name, &file_status) == 0 &&
+		     S_ISDIR(file_status.st_mode));
 
-  while (node)
+#if defined(PLATFORM_ANDROID)
+  if (!success)
   {
-    printf("['%s' (%d)]\n", node->key,
-	   ((struct ListNodeInfo *)node->content)->num_references);
-    node = node->next;
-  }
+    // this might be an asset directory; check by trying to open toc file
+    char *asset_toc_filename = getPath2(dir_name, ASSET_TOC_BASENAME);
+    SDL_RWops *file = SDL_RWFromFile(asset_toc_filename, MODE_READ);
 
-  printf("[%d nodes]\n", getNumNodes(node_first));
-}
+    checked_free(asset_toc_filename);
 
+    success = (file != NULL);
 
-/* ------------------------------------------------------------------------- */
-/* functions for checking files and filenames                                */
-/* ------------------------------------------------------------------------- */
+    if (success)
+      SDL_RWclose(file);
+  }
+#endif
+
+  return success;
+}
 
 boolean fileExists(char *filename)
 {
   if (filename == NULL)
     return FALSE;
 
-  return (access(filename, F_OK) == 0);
+  boolean success = (access(filename, F_OK) == 0);
+
+#if defined(PLATFORM_ANDROID)
+  if (!success)
+  {
+    // this might be an asset file; check by trying to open it
+    SDL_RWops *file = SDL_RWFromFile(filename, MODE_READ);
+
+    success = (file != NULL);
+
+    if (success)
+      SDL_RWclose(file);
+  }
+#endif
+
+  return success;
 }
 
 boolean fileHasPrefix(char *basename, char *prefix)
@@ -1851,48 +2540,37 @@ boolean fileHasSuffix(char *basename, char *suffix)
   return FALSE;
 }
 
-boolean FileIsGraphic(char *filename)
+static boolean FileCouldBeArtwork(char *filename)
 {
   char *basename = getBaseNamePtr(filename);
 
-  return fileHasSuffix(basename, "pcx");
+  return (!strEqual(basename, ".") &&
+	  !strEqual(basename, "..") &&
+	  !fileHasSuffix(basename, "txt") &&
+	  !fileHasSuffix(basename, "conf") &&
+	  !directoryExists(filename));
 }
 
-boolean FileIsSound(char *filename)
+boolean FileIsGraphic(char *filename)
 {
-  char *basename = getBaseNamePtr(filename);
+  return FileCouldBeArtwork(filename);
+}
 
-  return fileHasSuffix(basename, "wav");
+boolean FileIsSound(char *filename)
+{
+  return FileCouldBeArtwork(filename);
 }
 
 boolean FileIsMusic(char *filename)
 {
-  char *basename = getBaseNamePtr(filename);
-
-  if (FileIsSound(basename))
-    return TRUE;
-
-#if defined(TARGET_SDL)
-  if ((fileHasPrefix(basename, "mod") && !fileHasSuffix(basename, "txt")) ||
-      fileHasSuffix(basename, "mod") ||
-      fileHasSuffix(basename, "s3m") ||
-      fileHasSuffix(basename, "it") ||
-      fileHasSuffix(basename, "xm") ||
-      fileHasSuffix(basename, "midi") ||
-      fileHasSuffix(basename, "mid") ||
-      fileHasSuffix(basename, "mp3") ||
-      fileHasSuffix(basename, "ogg"))
-    return TRUE;
-#endif
-
-  return FALSE;
+  return FileCouldBeArtwork(filename);
 }
 
-boolean FileIsArtworkType(char *basename, int type)
+boolean FileIsArtworkType(char *filename, int type)
 {
-  if ((type == TREE_TYPE_GRAPHICS_DIR && FileIsGraphic(basename)) ||
-      (type == TREE_TYPE_SOUNDS_DIR && FileIsSound(basename)) ||
-      (type == TREE_TYPE_MUSIC_DIR && FileIsMusic(basename)))
+  if ((type == TREE_TYPE_GRAPHICS_DIR && FileIsGraphic(filename)) ||
+      (type == TREE_TYPE_SOUNDS_DIR && FileIsSound(filename)) ||
+      (type == TREE_TYPE_MUSIC_DIR && FileIsMusic(filename)))
     return TRUE;
 
   return FALSE;
@@ -1920,9 +2598,67 @@ char *get_mapped_token(char *token)
       return getStringCat2(map_token_prefix[i][1], &token[len_token_prefix]);
   }
 
+  // change tokens containing ".gfx" by moving the "gfx" part to the very left
+  char *gfx_substring = ".gfx";
+  char *gfx_prefix = "gfx.";
+  if (strstr(token, gfx_substring) != NULL)
+  {
+    char *token_prefix = getStringCopy(token);
+    char *token_gfx_pos = strstr(token_prefix, gfx_substring);
+    char *token_suffix = &token_gfx_pos[strlen(gfx_substring)];
+    char *mapped_token;
+
+    // cut off token string at ".gfx" substring position
+    *token_gfx_pos = '\0';
+
+    // put together prefix "gfx." and token prefix and suffix without ".gfx"
+    mapped_token = getStringCat3(gfx_prefix, token_prefix, token_suffix);
+
+    free(token_prefix);
+
+    return mapped_token;
+  }
+
   return NULL;
 }
 
+char *get_special_base_token(struct ArtworkListInfo *artwork_info, char *token)
+{
+  /* !!! make this dynamically configurable (init.c:InitArtworkConfig) !!! */
+  static struct ConfigTypeInfo prefix_list[] =
+  {
+    { "global.anim_1"	},
+    { "global.anim_2"	},
+    { "global.anim_3"	},
+    { "global.anim_4"	},
+    { "global.anim_5"	},
+    { "global.anim_6"	},
+    { "global.anim_7"	},
+    { "global.anim_8"	},
+
+    { NULL		}
+  };
+  struct ConfigTypeInfo *suffix_list = artwork_info->suffix_list;
+  boolean prefix_found = FALSE;
+  int len_suffix = 0;
+  int i;
+
+  /* search for prefix to check if base token has to be created */
+  for (i = 0; prefix_list[i].token != NULL; i++)
+    if (strPrefix(token, prefix_list[i].token))
+      prefix_found = TRUE;
+
+  if (!prefix_found)
+    return NULL;
+
+  /* search for suffix (parameter) to determine base token length */
+  for (i = 0; suffix_list[i].token != NULL; i++)
+    if (strSuffix(token, suffix_list[i].token))
+      len_suffix = strlen(suffix_list[i].token);
+
+  return getStringCopyN(token, strlen(token) - len_suffix);
+}
+
 /* This function checks if a string <s> of the format "string1, string2, ..."
    exactly contains a string <s_contained>. */
 
@@ -1972,6 +2708,17 @@ int get_parameter_value(char *value_raw, char *suffix, int type)
 	      strEqual(value, "up")    ? MV_UP :
 	      strEqual(value, "down")  ? MV_DOWN : MV_NONE);
   }
+  else if (strEqual(suffix, ".position"))
+  {
+    result = (strEqual(value, "left")   ? POS_LEFT :
+	      strEqual(value, "right")  ? POS_RIGHT :
+	      strEqual(value, "top")    ? POS_TOP :
+	      strEqual(value, "upper")  ? POS_UPPER :
+	      strEqual(value, "middle") ? POS_MIDDLE :
+	      strEqual(value, "lower")  ? POS_LOWER :
+	      strEqual(value, "bottom") ? POS_BOTTOM :
+	      strEqual(value, "any")    ? POS_ANY : POS_UNDEFINED);
+  }
   else if (strEqual(suffix, ".align"))
   {
     result = (strEqual(value, "left")   ? ALIGN_LEFT :
@@ -2000,8 +2747,12 @@ int get_parameter_value(char *value_raw, char *suffix, int type)
 	      string_has_parameter(value, "horizontal")	? ANIM_HORIZONTAL :
 	      string_has_parameter(value, "vertical")	? ANIM_VERTICAL :
 	      string_has_parameter(value, "centered")	? ANIM_CENTERED :
+	      string_has_parameter(value, "all")	? ANIM_ALL :
 	      ANIM_DEFAULT);
 
+    if (string_has_parameter(value, "once"))
+      result |= ANIM_ONCE;
+
     if (string_has_parameter(value, "reverse"))
       result |= ANIM_REVERSE;
 
@@ -2013,7 +2764,8 @@ int get_parameter_value(char *value_raw, char *suffix, int type)
   }
   else if (strEqual(suffix, ".class"))
   {
-    result = get_hash_from_key(value);
+    result = (strEqual(value, ARG_UNDEFINED) ? ARG_UNDEFINED_VALUE :
+	      get_hash_from_key(value));
   }
   else if (strEqual(suffix, ".style"))
   {
@@ -2031,13 +2783,10 @@ int get_parameter_value(char *value_raw, char *suffix, int type)
 	      string_has_parameter(value, "fade")	? FADE_MODE_FADE :
 	      string_has_parameter(value, "crossfade")	? FADE_MODE_CROSSFADE :
 	      string_has_parameter(value, "melt")	? FADE_MODE_MELT :
+	      string_has_parameter(value, "curtain")	? FADE_MODE_CURTAIN :
 	      FADE_MODE_DEFAULT);
   }
-#if 1
   else if (strPrefix(suffix, ".font"))		/* (may also be ".font_xyz") */
-#else
-  else if (strEqualN(suffix, ".font", 5))	/* (may also be ".font_xyz") */
-#endif
   {
     result = gfx.get_font_from_token_function(value);
   }
@@ -2054,48 +2803,6 @@ int get_parameter_value(char *value_raw, char *suffix, int type)
   return result;
 }
 
-struct ScreenModeInfo *get_screen_mode_from_string(char *screen_mode_string)
-{
-  static struct ScreenModeInfo screen_mode;
-  char *screen_mode_string_x = strchr(screen_mode_string, 'x');
-  char *screen_mode_string_copy;
-  char *screen_mode_string_pos_w;
-  char *screen_mode_string_pos_h;
-
-  if (screen_mode_string_x == NULL)	/* invalid screen mode format */
-    return NULL;
-
-  screen_mode_string_copy = getStringCopy(screen_mode_string);
-
-  screen_mode_string_pos_w = screen_mode_string_copy;
-  screen_mode_string_pos_h = strchr(screen_mode_string_copy, 'x');
-  *screen_mode_string_pos_h++ = '\0';
-
-  screen_mode.width  = atoi(screen_mode_string_pos_w);
-  screen_mode.height = atoi(screen_mode_string_pos_h);
-
-  return &screen_mode;
-}
-
-void get_aspect_ratio_from_screen_mode(struct ScreenModeInfo *screen_mode,
-				       int *x, int *y)
-{
-  float aspect_ratio = (float)screen_mode->width / (float)screen_mode->height;
-  float aspect_ratio_new;
-  int i = 1;
-
-  do
-  {
-    *x = i * aspect_ratio + 0.000001;
-    *y = i;
-
-    aspect_ratio_new = (float)*x / (float)*y;
-
-    i++;
-  }
-  while (aspect_ratio_new != aspect_ratio && *y < screen_mode->height);
-}
-
 static void FreeCustomArtworkList(struct ArtworkListInfo *,
 				  struct ListNodeInfo ***, int *);
 
@@ -2104,12 +2811,18 @@ struct FileInfo *getFileListFromConfigList(struct ConfigInfo *config_list,
 					   char **ignore_tokens,
 					   int num_file_list_entries)
 {
+  SetupFileHash *ignore_tokens_hash;
   struct FileInfo *file_list;
   int num_file_list_entries_found = 0;
   int num_suffix_list_entries = 0;
   int list_pos;
   int i, j;
 
+  /* create hash from list of tokens to be ignored (for quick access) */
+  ignore_tokens_hash = newSetupFileHash();
+  for (i = 0; ignore_tokens[i] != NULL; i++)
+    setHashEntry(ignore_tokens_hash, ignore_tokens[i], "");
+
   file_list = checked_calloc(num_file_list_entries * sizeof(struct FileInfo));
 
   for (i = 0; suffix_list[i].token != NULL; i++)
@@ -2143,10 +2856,10 @@ struct FileInfo *getFileListFromConfigList(struct ConfigInfo *config_list,
   }
 
   list_pos = 0;
+
   for (i = 0; config_list[i].token != NULL; i++)
   {
     int len_config_token = strlen(config_list[i].token);
-    int len_config_value = strlen(config_list[i].value);
     boolean is_file_entry = TRUE;
 
     for (j = 0; suffix_list[j].token != NULL; j++)
@@ -2161,14 +2874,14 @@ struct FileInfo *getFileListFromConfigList(struct ConfigInfo *config_list,
 		  config_list[i].value);
 
 	is_file_entry = FALSE;
+
 	break;
       }
     }
 
     /* the following tokens are no file definitions, but other config tokens */
-    for (j = 0; ignore_tokens[j] != NULL; j++)
-      if (strEqual(config_list[i].token, ignore_tokens[j]))
-	is_file_entry = FALSE;
+    if (getHashEntry(ignore_tokens_hash, config_list[i].token) != NULL)
+      is_file_entry = FALSE;
 
     if (is_file_entry)
     {
@@ -2178,22 +2891,8 @@ struct FileInfo *getFileListFromConfigList(struct ConfigInfo *config_list,
       if (list_pos >= num_file_list_entries)
 	break;
 
-      /* simple sanity check if this is really a file definition */
-      if (!strEqual(&config_list[i].value[len_config_value - 4], ".pcx") &&
-	  !strEqual(&config_list[i].value[len_config_value - 4], ".wav") &&
-	  !strEqual(config_list[i].value, UNDEFINED_FILENAME))
-      {
-	Error(ERR_INFO, "Configuration directive '%s' -> '%s':",
-	      config_list[i].token, config_list[i].value);
-	Error(ERR_EXIT, "This seems to be no valid definition -- please fix");
-      }
-
       file_list[list_pos].token = config_list[i].token;
       file_list[list_pos].default_filename = config_list[i].value;
-
-#if 0
-      printf("::: '%s' => '%s'\n", config_list[i].token, config_list[i].value);
-#endif
     }
 
     if (strSuffix(config_list[i].token, ".clone_from"))
@@ -2212,9 +2911,7 @@ struct FileInfo *getFileListFromConfigList(struct ConfigInfo *config_list,
     Error(ERR_EXIT,   "please fix");
   }
 
-#if 0
-  printf("::: ---------- DONE ----------\n");
-#endif
+  freeSetupFileHash(ignore_tokens_hash);
 
   return file_list;
 }
@@ -2349,18 +3046,15 @@ static void LoadArtworkConfigFromFilename(struct ArtworkListInfo *artwork_info,
   int num_ext2_suffixes = artwork_info->num_ext2_suffixes;
   int num_ext3_suffixes = artwork_info->num_ext3_suffixes;
   int num_ignore_tokens = artwork_info->num_ignore_tokens;
-  SetupFileHash *setup_file_hash, *valid_file_hash;
+  SetupFileHash *setup_file_hash, *valid_file_hash, *valid_file_hash_tmp;
   SetupFileHash *extra_file_hash, *empty_file_hash;
   char *known_token_value = KNOWN_TOKEN_VALUE;
+  char *base_token_value = UNDEFINED_FILENAME;
   int i, j, k, l;
 
   if (filename == NULL)
     return;
 
-#if 0
-  printf("LoadArtworkConfigFromFilename '%s' ...\n", filename);
-#endif
-
   if ((setup_file_hash = loadSetupFileHash(filename)) == NULL)
     return;
 
@@ -2379,9 +3073,21 @@ static void LoadArtworkConfigFromFilename(struct ArtworkListInfo *artwork_info,
   /* at this point, we do not need the setup file hash anymore -- free it */
   freeSetupFileHash(setup_file_hash);
 
-  /* map deprecated to current tokens (using prefix match and replace) */
+  /* prevent changing hash while iterating over it by using a temporary copy */
+  valid_file_hash_tmp = newSetupFileHash();
   BEGIN_HASH_ITERATION(valid_file_hash, itr)
   {
+    setHashEntry(valid_file_hash_tmp,
+		 HASH_ITERATION_TOKEN(itr),
+		 HASH_ITERATION_VALUE(itr));
+  }
+  END_HASH_ITERATION(valid_file_hash, itr)
+
+  /* (iterate over same temporary hash, as modifications are independent) */
+
+  /* map deprecated to current tokens (using prefix match and replace) */
+  BEGIN_HASH_ITERATION(valid_file_hash_tmp, itr)
+  {
     char *token = HASH_ITERATION_TOKEN(itr);
     char *mapped_token = get_mapped_token(token);
 
@@ -2398,7 +3104,27 @@ static void LoadArtworkConfigFromFilename(struct ArtworkListInfo *artwork_info,
       free(mapped_token);
     }
   }
-  END_HASH_ITERATION(valid_file_hash, itr)
+  END_HASH_ITERATION(valid_file_hash_tmp, itr)
+
+  /* add special base tokens (using prefix match and replace) */
+  BEGIN_HASH_ITERATION(valid_file_hash_tmp, itr)
+  {
+    char *token = HASH_ITERATION_TOKEN(itr);
+    char *base_token = get_special_base_token(artwork_info, token);
+
+    if (base_token != NULL)
+    {
+      /* add base token only if it does not already exist */
+      if (getHashEntry(valid_file_hash, base_token) == NULL)
+	setHashEntry(valid_file_hash, base_token, base_token_value);
+
+      free(base_token);
+    }
+  }
+  END_HASH_ITERATION(valid_file_hash_tmp, itr)
+
+  /* free temporary hash used for iteration */
+  freeSetupFileHash(valid_file_hash_tmp);
 
   /* read parameters for all known config file tokens */
   for (i = 0; i < num_file_list_entries; i++)
@@ -2443,10 +3169,6 @@ static void LoadArtworkConfigFromFilename(struct ArtworkListInfo *artwork_info,
     boolean base_prefix_found = FALSE;
     boolean parameter_suffix_found = FALSE;
 
-#if 0
-    printf("::: examining '%s' -> '%s'\n", token, HASH_ITERATION_VALUE(itr));
-#endif
-
     /* skip all parameter definitions (handled by read_token_parameters()) */
     for (i = 0; i < num_suffix_list_entries && !parameter_suffix_found; i++)
     {
@@ -2482,20 +3204,10 @@ static void LoadArtworkConfigFromFilename(struct ArtworkListInfo *artwork_info,
 
       base_index = i;
 
-#if 0
-      if (IS_PARENT_PROCESS())
-	printf("===> MATCH: '%s', '%s'\n", token, base_prefix);
-#endif
-
       if (start_pos + len_base_prefix == len_token)	/* exact match */
       {
 	exact_match = TRUE;
 
-#if 0
-	if (IS_PARENT_PROCESS())
-	  printf("===> EXACT MATCH: '%s', '%s'\n", token, base_prefix);
-#endif
-
 	add_dynamic_file_list_entry(dynamic_file_list,
 				    num_dynamic_file_list_entries,
 				    extra_file_hash,
@@ -2509,11 +3221,6 @@ static void LoadArtworkConfigFromFilename(struct ArtworkListInfo *artwork_info,
 	continue;
       }
 
-#if 0
-      if (IS_PARENT_PROCESS())
-	printf("---> examining token '%s': search 1st suffix ...\n", token);
-#endif
-
       /* ---------- step 1: search for matching first suffix ---------- */
 
       start_pos += len_base_prefix;
@@ -2529,20 +3236,10 @@ static void LoadArtworkConfigFromFilename(struct ArtworkListInfo *artwork_info,
 
 	ext1_index = j;
 
-#if 0
-	if (IS_PARENT_PROCESS())
-	  printf("===> MATCH: '%s', '%s'\n", token, ext1_suffix);
-#endif
-
 	if (start_pos + len_ext1_suffix == len_token)	/* exact match */
 	{
 	  exact_match = TRUE;
 
-#if 0
-	if (IS_PARENT_PROCESS())
-	  printf("===> EXACT MATCH: '%s', '%s'\n", token, ext1_suffix);
-#endif
-
 	  add_dynamic_file_list_entry(dynamic_file_list,
 				      num_dynamic_file_list_entries,
 				      extra_file_hash,
@@ -2562,11 +3259,6 @@ static void LoadArtworkConfigFromFilename(struct ArtworkListInfo *artwork_info,
       if (exact_match)
 	break;
 
-#if 0
-      if (IS_PARENT_PROCESS())
-	printf("---> examining token '%s': search 2nd suffix ...\n", token);
-#endif
-
       /* ---------- step 2: search for matching second suffix ---------- */
 
       for (k = 0; k < num_ext2_suffixes && !ext2_suffix_found; k++)
@@ -2581,20 +3273,10 @@ static void LoadArtworkConfigFromFilename(struct ArtworkListInfo *artwork_info,
 
 	ext2_index = k;
 
-#if 0
-	if (IS_PARENT_PROCESS())
-	  printf("===> MATCH: '%s', '%s'\n", token, ext2_suffix);
-#endif
-
 	if (start_pos + len_ext2_suffix == len_token)	/* exact match */
 	{
 	  exact_match = TRUE;
 
-#if 0
-	  if (IS_PARENT_PROCESS())
-	    printf("===> EXACT MATCH: '%s', '%s'\n", token, ext2_suffix);
-#endif
-
 	  add_dynamic_file_list_entry(dynamic_file_list,
 				      num_dynamic_file_list_entries,
 				      extra_file_hash,
@@ -2614,11 +3296,6 @@ static void LoadArtworkConfigFromFilename(struct ArtworkListInfo *artwork_info,
       if (exact_match)
 	break;
 
-#if 0
-      if (IS_PARENT_PROCESS())
-	printf("---> examining token '%s': search 3rd suffix ...\n",token);
-#endif
-
       /* ---------- step 3: search for matching third suffix ---------- */
 
       for (l = 0; l < num_ext3_suffixes && !ext3_suffix_found; l++)
@@ -2633,20 +3310,10 @@ static void LoadArtworkConfigFromFilename(struct ArtworkListInfo *artwork_info,
 
 	ext3_index = l;
 
-#if 0
-	if (IS_PARENT_PROCESS())
-	  printf("===> MATCH: '%s', '%s'\n", token, ext3_suffix);
-#endif
-
 	if (start_pos + len_ext3_suffix == len_token) /* exact match */
 	{
 	  exact_match = TRUE;
 
-#if 0
-	  if (IS_PARENT_PROCESS())
-	    printf("===> EXACT MATCH: '%s', '%s'\n", token, ext3_suffix);
-#endif
-
 	  add_dynamic_file_list_entry(dynamic_file_list,
 				      num_dynamic_file_list_entries,
 				      extra_file_hash,
@@ -2678,8 +3345,8 @@ static void LoadArtworkConfigFromFilename(struct ArtworkListInfo *artwork_info,
     boolean unknown_tokens_found = FALSE;
     boolean undefined_values_found = (hashtable_count(empty_file_hash) != 0);
 
-    if ((setup_file_list = loadSetupFileList(filename)) == NULL)
-      Error(ERR_EXIT, "loadSetupFileHash works, but loadSetupFileList fails");
+    /* list may be NULL for empty artwork config files */
+    setup_file_list = loadSetupFileList(filename);
 
     BEGIN_HASH_ITERATION(extra_file_hash, itr)
     {
@@ -2746,17 +3413,6 @@ static void LoadArtworkConfigFromFilename(struct ArtworkListInfo *artwork_info,
 
   freeSetupFileHash(extra_file_hash);
   freeSetupFileHash(empty_file_hash);
-
-#if 0
-  for (i = 0; i < num_file_list_entries; i++)
-  {
-    printf("'%s' ", file_list[i].token);
-    if (file_list[i].filename)
-      printf("-> '%s'\n", file_list[i].filename);
-    else
-      printf("-> UNDEFINED [-> '%s']\n", file_list[i].default_filename);
-  }
-#endif
 }
 
 void LoadArtworkConfig(struct ArtworkListInfo *artwork_info)
@@ -2808,21 +3464,11 @@ void LoadArtworkConfig(struct ArtworkListInfo *artwork_info)
     artwork_info->num_property_mapping_entries = 0;
   }
 
-#if 1
   if (!GFX_OVERRIDE_ARTWORK(artwork_info->type))
-#else
-  if (!SETUP_OVERRIDE_ARTWORK(setup, artwork_info->type))
-#endif
   {
     /* first look for special artwork configured in level series config */
     filename_base = getCustomArtworkLevelConfigFilename(artwork_info->type);
 
-#if 0
-    printf("::: filename_base == '%s' [%s, %s]\n", filename_base,
-	   leveldir_current->graphics_set,
-	   leveldir_current->graphics_path);
-#endif
-
     if (fileExists(filename_base))
       LoadArtworkConfigFromFilename(artwork_info, filename_base);
   }
@@ -2916,23 +3562,15 @@ static void replaceArtworkListEntry(struct ArtworkListInfo *artwork_info,
        This usually means that this artwork does not exist in this artwork set
        and a fallback to the existing artwork is done. */
 
-#if 0
-    printf("[artwork '%s' already exists (same list entry)]\n", filename);
-#endif
-
     return;
   }
 
   /* delete existing artwork file entry */
   deleteArtworkListEntry(artwork_info, listnode);
 
-  /* check if the new artwork file already exists in the list of artworks */
+  /* check if the new artwork file already exists in the list of artwork */
   if ((node = getNodeFromKey(artwork_info->content_list, filename)) != NULL)
   {
-#if 0
-      printf("[artwork '%s' already exists (other list entry)]\n", filename);
-#endif
-
       *listnode = (struct ListNodeInfo *)node->content;
       (*listnode)->num_references++;
 
@@ -2944,10 +3582,7 @@ static void replaceArtworkListEntry(struct ArtworkListInfo *artwork_info,
 
   if ((*listnode = artwork_info->load_artwork(filename)) != NULL)
   {
-#if 0
-      printf("[adding new artwork '%s']\n", filename);
-#endif
-
+    /* add new artwork file entry to the list of artwork files */
     (*listnode)->num_references = 1;
     addNodeToList(&artwork_info->content_list, (*listnode)->source_filename,
 		  *listnode);
@@ -2970,13 +3605,10 @@ static void LoadCustomArtwork(struct ArtworkListInfo *artwork_info,
 			      struct ListNodeInfo **listnode,
 			      struct FileInfo *file_list_entry)
 {
-#if 0
-  printf("GOT CUSTOM ARTWORK FILE '%s'\n", file_list_entry->filename);
-#endif
-
   if (strEqual(file_list_entry->filename, UNDEFINED_FILENAME))
   {
     deleteArtworkListEntry(artwork_info, listnode);
+
     return;
   }
 
@@ -2992,6 +3624,8 @@ void ReloadCustomArtworkList(struct ArtworkListInfo *artwork_info)
     artwork_info->num_dynamic_file_list_entries;
   int i;
 
+  print_timestamp_init("ReloadCustomArtworkList");
+
   for (i = 0; i < num_file_list_entries; i++)
     LoadCustomArtwork(artwork_info, &artwork_info->artwork_list[i],
 		      &file_list[i]);
@@ -3000,6 +3634,8 @@ void ReloadCustomArtworkList(struct ArtworkListInfo *artwork_info)
     LoadCustomArtwork(artwork_info, &artwork_info->dynamic_artwork_list[i],
 		      &dynamic_file_list[i]);
 
+  print_timestamp_done("ReloadCustomArtworkList");
+
 #if 0
   dumpList(artwork_info->content_list);
 #endif
@@ -3041,37 +3677,53 @@ void FreeCustomArtworkLists(struct ArtworkListInfo *artwork_info)
 /* (now also added for Windows, to create files in user data directory)      */
 /* ------------------------------------------------------------------------- */
 
-char *getErrorFilename(char *basename)
+char *getLogFilename(char *basename)
 {
   return getPath2(getUserGameDataDir(), basename);
 }
 
-void openErrorFile()
+void OpenLogFiles()
 {
+  int i;
+
   InitUserDataDirectory();
 
-  if ((program.error_file = fopen(program.error_filename, MODE_WRITE)) == NULL)
-    fprintf_newline(stderr, "ERROR: cannot open file '%s' for writing!",
-		    program.error_filename);
+  for (i = 0; i < NUM_LOGS; i++)
+  {
+    if ((program.log_file[i] = fopen(program.log_filename[i], MODE_WRITE))
+	== NULL)
+    {
+      program.log_file[i] = program.log_file_default[i];   // reset to default
+
+      Error(ERR_WARN, "cannot open file '%s' for writing: %s",
+	    program.log_filename[i], strerror(errno));
+    }
+
+    /* output should be unbuffered so it is not truncated in a crash */
+    setbuf(program.log_file[i], NULL);
+  }
 }
 
-void closeErrorFile()
+void CloseLogFiles()
 {
-  if (program.error_file != stderr)	/* do not close stream 'stderr' */
-    fclose(program.error_file);
+  int i;
+
+  for (i = 0; i < NUM_LOGS; i++)
+    if (program.log_file[i] != program.log_file_default[i])
+      fclose(program.log_file[i]);
 }
 
-void dumpErrorFile()
+void DumpLogFile(int nr)
 {
-  FILE *error_file = fopen(program.error_filename, MODE_READ);
+  FILE *log_file = fopen(program.log_filename[nr], MODE_READ);
 
-  if (error_file != NULL)
-  {
-    while (!feof(error_file))
-      fputc(fgetc(error_file), stderr);
+  if (log_file == NULL)
+    return;
 
-    fclose(error_file);
-  }
+  while (!feof(log_file))
+    fputc(fgetc(log_file), stdout);
+
+  fclose(log_file);
 }
 
 void NotifyUserAboutErrorFile()
@@ -3080,7 +3732,8 @@ void NotifyUserAboutErrorFile()
   char *title_text = getStringCat2(program.program_title, " Error Message");
   char *error_text = getStringCat2("The program was aborted due to an error; "
 				   "for details, see the following error file:"
-				   STRING_NEWLINE, program.error_filename);
+				   STRING_NEWLINE,
+				   program.log_filename[LOG_ERR_ID]);
 
   MessageBox(NULL, error_text, title_text, MB_OK);
 #endif
@@ -3093,8 +3746,11 @@ void NotifyUserAboutErrorFile()
 
 #if DEBUG
 
-#define DEBUG_NUM_TIMESTAMPS		5
-#define DEBUG_TIME_IN_MICROSECONDS	0
+#define DEBUG_PRINT_INIT_TIMESTAMPS		FALSE
+#define DEBUG_PRINT_INIT_TIMESTAMPS_DEPTH	10
+
+#define DEBUG_NUM_TIMESTAMPS			10
+#define DEBUG_TIME_IN_MICROSECONDS		0
 
 #if DEBUG_TIME_IN_MICROSECONDS
 static double Counter_Microseconds()
@@ -3148,7 +3804,7 @@ void debug_print_timestamp(int counter_nr, char *message)
 
   counter[counter_nr][0] = Counter_Microseconds();
 #else
-  static long counter[DEBUG_NUM_TIMESTAMPS][2];
+  static int counter[DEBUG_NUM_TIMESTAMPS][2];
   char *unit = "s";
 
   counter[counter_nr][0] = Counter();
@@ -3158,7 +3814,7 @@ void debug_print_timestamp(int counter_nr, char *message)
   counter[counter_nr][1] = counter[counter_nr][0];
 
   if (message)
-    printf("%s%s%s %.3f %s\n",
+    Error(ERR_DEBUG, "%s%s%s %.3f %s",
 	   debug_print_timestamp_get_padding(counter_nr * indent_size),
 	   message,
 	   debug_print_timestamp_get_padding(padding_size - strlen(message)),
@@ -3182,4 +3838,69 @@ void debug_print_parent_only(char *format, ...)
     printf("\n");
   }
 }
+
+#endif	/* DEBUG */
+
+void print_timestamp_ext(char *message, char *mode)
+{
+#if DEBUG_PRINT_INIT_TIMESTAMPS
+  static char *debug_message = NULL;
+  static char *last_message = NULL;
+  static int counter_nr = 0;
+  int max_depth = DEBUG_PRINT_INIT_TIMESTAMPS_DEPTH;
+
+  checked_free(debug_message);
+  debug_message = getStringCat3(mode, " ", message);
+
+  if (strEqual(mode, "INIT"))
+  {
+    debug_print_timestamp(counter_nr, NULL);
+
+    if (counter_nr + 1 < max_depth)
+      debug_print_timestamp(counter_nr, debug_message);
+
+    counter_nr++;
+
+    debug_print_timestamp(counter_nr, NULL);
+  }
+  else if (strEqual(mode, "DONE"))
+  {
+    counter_nr--;
+
+    if (counter_nr + 1 < max_depth ||
+	(counter_nr == 0 && max_depth == 1))
+    {
+      last_message = message;
+
+      if (counter_nr == 0 && max_depth == 1)
+      {
+	checked_free(debug_message);
+	debug_message = getStringCat3("TIME", " ", message);
+      }
+
+      debug_print_timestamp(counter_nr, debug_message);
+    }
+  }
+  else if (!strEqual(mode, "TIME") ||
+	   !strEqual(message, last_message))
+  {
+    if (counter_nr < max_depth)
+      debug_print_timestamp(counter_nr, debug_message);
+  }
 #endif
+}
+
+void print_timestamp_init(char *message)
+{
+  print_timestamp_ext(message, "INIT");
+}
+
+void print_timestamp_time(char *message)
+{
+  print_timestamp_ext(message, "TIME");
+}
+
+void print_timestamp_done(char *message)
+{
+  print_timestamp_ext(message, "DONE");
+}
diff --git a/src/libgame/misc.h b/src/libgame/misc.h
index 3449961..1e8f039 100644
--- a/src/libgame/misc.h
+++ b/src/libgame/misc.h
@@ -1,21 +1,20 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* misc.h                                                   *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// misc.h
+// ============================================================================
 
 #ifndef MISC_H
 #define MISC_H
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <dirent.h>
 
 #include "system.h"
 
@@ -36,14 +35,16 @@
 #define GetSimpleRandom(max)		get_random_number(RANDOM_SIMPLE, max)
 
 /* values for Error() */
-#define ERR_INFO			0
-#define ERR_INFO_LINE			(1 << 0)
-#define ERR_WARN			(1 << 1)
-#define ERR_EXIT			(1 << 2)
-#define ERR_HELP			(1 << 3)
-#define ERR_SOUND_SERVER		(1 << 4)
-#define ERR_NETWORK_SERVER		(1 << 5)
-#define ERR_NETWORK_CLIENT		(1 << 6)
+#define ERR_UNKNOWN			0
+#define ERR_DEBUG			(1 << 0)
+#define ERR_INFO			(1 << 1)
+#define ERR_INFO_LINE			(1 << 2)
+#define ERR_WARN			(1 << 3)
+#define ERR_EXIT			(1 << 4)
+#define ERR_HELP			(1 << 5)
+#define ERR_SOUND_SERVER		(1 << 6)
+#define ERR_NETWORK_SERVER		(1 << 7)
+#define ERR_NETWORK_CLIENT		(1 << 8)
 #define ERR_FROM_SERVER			(ERR_SOUND_SERVER | ERR_NETWORK_SERVER)
 #define ERR_EXIT_HELP			(ERR_EXIT | ERR_HELP)
 #define ERR_EXIT_SOUND_SERVER		(ERR_EXIT | ERR_SOUND_SERVER)
@@ -69,10 +70,58 @@
 /* values for general username handling stuff */
 #define MAX_USERNAME_LEN		1024
 
+#if defined(PLATFORM_ANDROID)
+/* values for Android asset handling */
+#define ASSET_TOC_BASENAME		".toc"
+#endif
+
+
+/* structure definitions */
+
+typedef struct
+{
+  char *filename;
+  FILE *file;
+  boolean end_of_file;
+
+#if defined(PLATFORM_ANDROID)
+  boolean file_is_asset;
+  SDL_RWops *asset_file;
+#endif
+} File;
+
+typedef struct
+{
+  boolean is_directory;
+  char *basename;
+  char *filename;
+} DirectoryEntry;
+
+typedef struct
+{
+  char *filename;
+  DIR *dir;
+  DirectoryEntry *dir_entry;
+
+#if defined(PLATFORM_ANDROID)
+  boolean directory_is_asset;
+  SDL_RWops *asset_toc_file;
+  char *current_entry;
+#endif
+} Directory;
+
+
+/* function definitions */
 
 void fprintf_line(FILE *, char *, int);
+void fprintf_line_with_prefix(FILE *, char *, char *, int);
 void printf_line(char *, int);
 void printf_line_with_prefix(char *, char *, int);
+
+void Print(char *, ...);
+void PrintLine(char *, int);
+void PrintLineWithPrefix(char *, char *, int);
+
 char *int2str(int, int);
 char *i_to_a(unsigned int);
 int log_2(unsigned int);
@@ -80,13 +129,18 @@ int log_2(unsigned int);
 boolean getTokenValueFromString(char *, char **, char **);
 
 void InitCounter(void);
-unsigned long Counter(void);
-void Delay(unsigned long);
-boolean FrameReached(unsigned long *, unsigned long);
-boolean DelayReached(unsigned long *, unsigned long);
-void WaitUntilDelayReached(unsigned long *, unsigned long);
-
-unsigned int init_random_number(int, long);
+unsigned int Counter(void);
+void Delay(unsigned int);
+boolean DelayReachedExt(unsigned int *, unsigned int, unsigned int);
+boolean FrameReached(unsigned int *, unsigned int);
+boolean DelayReached(unsigned int *, unsigned int);
+void ResetDelayCounterExt(unsigned int *, unsigned int);
+void ResetFrameCounter(unsigned int *);
+void ResetDelayCounter(unsigned int *);
+int WaitUntilDelayReached(unsigned int *, unsigned int);
+void SkipUntilDelayReached(unsigned int *, unsigned int, int *, int);
+
+unsigned int init_random_number(int, int);
 unsigned int get_random_number(int, int);
 
 char *getLoginName(void);
@@ -97,6 +151,7 @@ time_t getFileTimestampEpochSeconds(char *);
 char *getBasePath(char *);
 char *getBaseName(char *);
 char *getBaseNamePtr(char *);
+char *getBaseNameNoSuffix(char *);
 
 char *getStringCat2WithSeparator(char *, char *, char *);
 char *getStringCat3WithSeparator(char *, char *, char *, char *);
@@ -104,9 +159,12 @@ char *getStringCat2(char *, char *);
 char *getStringCat3(char *, char *, char *);
 char *getPath2(char *, char *);
 char *getPath3(char *, char *, char*);
-char *getStringCopy(char *);
-char *getStringCopyN(char *, int);
-char *getStringToLower(char *);
+char *getImg2(char *, char *);
+char *getImg3(char *, char *, char*);
+char *getStringCopy(const char *);
+char *getStringCopyN(const char *, int);
+char *getStringCopyNStatic(const char *, int);
+char *getStringToLower(const char *);
 void setString(char **, char *);
 boolean strEqual(char *, char *);
 boolean strEqualN(char *, char *, int);
@@ -115,38 +173,40 @@ boolean strSuffix(char *, char *);
 boolean strPrefixLower(char *, char *);
 boolean strSuffixLower(char *, char *);
 
-void GetOptions(char **, void (*print_usage_function)(void));
+void GetOptions(int, char **,
+		void (*print_usage_function)(void),
+		void (*print_version_function)(void));
 
 void SetError(char *, ...);
 char *GetError(void);
 void Error(int, char *, ...);
 
-void *checked_malloc(unsigned long);
-void *checked_calloc(unsigned long);
-void *checked_realloc(void *, unsigned long);
+void *checked_malloc(unsigned int);
+void *checked_calloc(unsigned int);
+void *checked_realloc(void *, unsigned int);
 void checked_free(void *);
-void clear_mem(void *, unsigned long);
+void clear_mem(void *, unsigned int);
 
 void swap_numbers(int *, int *);
 void swap_number_pairs(int *, int *, int *, int *);
 
-int getFile8BitInteger(FILE *);
+int getFile8BitInteger(File *);
 int putFile8BitInteger(FILE *, int);
-int getFile16BitInteger(FILE *, int);
+int getFile16BitInteger(File *, int);
 int putFile16BitInteger(FILE *, int, int);
-int getFile32BitInteger(FILE *, int);
+int getFile32BitInteger(File *, int);
 int putFile32BitInteger(FILE *, int, int);
 
-boolean getFileChunk(FILE *, char *, int *, int);
+boolean getFileChunk(File *, char *, int *, int);
 int putFileChunk(FILE *, char *, int, int);
-int getFileVersion(FILE *);
+int getFileVersion(File *);
 int putFileVersion(FILE *, int);
 
-void ReadBytesFromFile(FILE *, byte *, unsigned long);
-void WriteBytesToFile(FILE *, byte *, unsigned long);
+void ReadBytesFromFile(File *, byte *, unsigned int);
+void WriteBytesToFile(FILE *, byte *, unsigned int);
 
-void ReadUnusedBytesFromFile(FILE *, unsigned long);
-void WriteUnusedBytesToFile(FILE *, unsigned long);
+void ReadUnusedBytesFromFile(File *, unsigned int);
+void WriteUnusedBytesToFile(FILE *, unsigned int);
 
 #define getFile8Bit(f)        getFile8BitInteger(f)
 #define putFile8Bit(f,x)      putFile8BitInteger(f,x)
@@ -181,6 +241,20 @@ void deleteNodeFromList(ListNode **, char *, void (*function)(void *));
 ListNode *getNodeFromKey(ListNode *, char *);
 int getNumNodes(ListNode *);
 
+File *openFile(char *, char *);
+int closeFile(File *);
+int checkEndOfFile(File *);
+size_t readFile(File *, void *, size_t, size_t);
+int seekFile(File *, long, int);
+int getByteFromFile(File *);
+char *getStringFromFile(File *, char *, int);
+
+Directory *openDirectory(char *);
+int closeDirectory(Directory *);
+DirectoryEntry *readDirectory(Directory *);
+void freeDirectoryEntry(DirectoryEntry *);
+
+boolean directoryExists(char *);
 boolean fileExists(char *);
 boolean FileIsGraphic(char *);
 boolean FileIsSound(char *);
@@ -191,9 +265,6 @@ char *get_mapped_token(char *);
 
 int get_parameter_value(char *, char *, int);
 
-struct ScreenModeInfo *get_screen_mode_from_string(char *);
-void get_aspect_ratio_from_screen_mode(struct ScreenModeInfo *, int *x, int *y);
-
 struct FileInfo *getFileListFromConfigList(struct ConfigInfo *,
 					   struct ConfigTypeInfo *,
 					   char **, int);
@@ -201,12 +272,19 @@ void LoadArtworkConfig(struct ArtworkListInfo *);
 void ReloadCustomArtworkList(struct ArtworkListInfo *);
 void FreeCustomArtworkLists(struct ArtworkListInfo *);
 
-char *getErrorFilename(char *);
-void openErrorFile();
-void closeErrorFile();
-void dumpErrorFile();
+char *getLogFilename(char *);
+void OpenLogFiles();
+void CloseLogFiles();
+void DumpLogFile(int);
+
 void NotifyUserAboutErrorFile();
 
+#if DEBUG
 void debug_print_timestamp(int, char *);
+#endif
+void print_timestamp_init(char *);
+void print_timestamp_time(char *);
+void print_timestamp_done(char *);
+
 
 #endif /* MISC_H */
diff --git a/src/libgame/msdos.c b/src/libgame/msdos.c
deleted file mode 100644
index 407752b..0000000
--- a/src/libgame/msdos.c
+++ /dev/null
@@ -1,1002 +0,0 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* msdos.c                                                  *
-***********************************************************/
-
-#include "system.h"
-
-
-#if defined(PLATFORM_MSDOS)
-
-#include "sound.h"
-#include "joystick.h"
-#include "misc.h"
-#include "setup.h"
-#include "pcx.h"
-
-#define AllegroDefaultScreen() (display->screens[display->default_screen])
-
-/* allegro driver declarations */
-DECLARE_GFX_DRIVER_LIST(GFX_DRIVER_VBEAF GFX_DRIVER_VESA2L GFX_DRIVER_VESA1)
-DECLARE_COLOR_DEPTH_LIST(COLOR_DEPTH_8)
-DECLARE_DIGI_DRIVER_LIST(DIGI_DRIVER_SB)
-DECLARE_MIDI_DRIVER_LIST()
-DECLARE_JOYSTICK_DRIVER_LIST(JOYSTICK_DRIVER_STANDARD)
-
-/* allegro global variables */
-extern volatile int key_shifts;
-extern int num_joysticks;
-extern JOYSTICK_INFO joy[];
-extern int i_love_bill;
-
-/* internal variables of msdos.c */
-static boolean keyboard_auto_repeat = TRUE;
-static int key_press_state[MAX_SCANCODES];
-static XEvent event_buffer[MAX_EVENT_BUFFER];
-static int pending_events;
-static boolean joystick_event;
-static boolean mouse_installed = FALSE;
-static int last_mouse_pos;
-static int last_mouse_b;
-static int last_joystick_state;
-static BITMAP* video_bitmap;
-
-static RGB global_colormap[MAX_COLORS];
-static int global_colormap_entries_used = 0;
-
-boolean wait_for_vsync;
-
-static BITMAP *Read_PCX_to_AllegroBitmap(char *);
-
-static void allegro_init_drivers()
-{
-  int i;
-
-  for (i = 0; i < MAX_EVENT_BUFFER; i++)
-    event_buffer[i].type = 0;
-
-  for (i = 0; i < MAX_SCANCODES; i++)
-    key_press_state[i] = KeyReleaseMask;
-
-  last_mouse_pos = mouse_pos;
-  last_mouse_b = 0;
-
-  pending_events = 0;
-  clear_keybuf();
-
-  /* enable Windows friendly timer mode (already default under Windows) */
-  i_love_bill = TRUE;
-
-  install_keyboard();
-  install_timer();
-  if (install_mouse() > 0)
-    mouse_installed = TRUE;
-
-  last_joystick_state = 0;
-  joystick_event = FALSE;
-}
-
-static boolean allegro_init_audio()
-{
-  reserve_voices(NUM_MIXER_CHANNELS, 0);
-
-  if (install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL) == -1)
-    if (install_sound(DIGI_SB, MIDI_NONE, NULL) == -1)
-      return FALSE;
-
-  return TRUE;
-}
-
-static boolean hide_mouse(Display *display, int x, int y,
-			  unsigned int width, unsigned int height)
-{
-  if (mouse_x + display->mouse_ptr->w < x || mouse_x > x + width)
-    return FALSE;
-  if (mouse_y + display->mouse_ptr->h < y || mouse_y > y + height)
-    return FALSE;
-
-  show_mouse(NULL);
-
-  return TRUE;
-}
-
-static void unhide_mouse(Display *display)
-{
-  if (mouse_installed)
-    show_mouse(video_bitmap);
-}
-
-static KeySym ScancodeToKeySym(byte scancode)
-{
-  switch(scancode)
-  {
-    case KEY_ESC:		return XK_Escape;
-    case KEY_1:			return XK_1;
-    case KEY_2:			return XK_2;
-    case KEY_3:			return XK_3;
-    case KEY_4:			return XK_4;
-    case KEY_5:			return XK_5;
-    case KEY_6:			return XK_6;
-    case KEY_7:			return XK_7;
-    case KEY_8:			return XK_8;
-    case KEY_9:			return XK_9;
-    case KEY_0:			return XK_0;
-    case KEY_MINUS:		return XK_minus;
-    case KEY_EQUALS:		return XK_equal;
-    case KEY_BACKSPACE:		return XK_BackSpace;
-    case KEY_TAB:		return XK_Tab;
-    case KEY_Q:			return XK_q;
-    case KEY_W:			return XK_w;
-    case KEY_E:			return XK_e;
-    case KEY_R:			return XK_r;
-    case KEY_T:			return XK_t;
-    case KEY_Y:			return XK_y;
-    case KEY_U:			return XK_u;
-    case KEY_I:			return XK_i;
-    case KEY_O:			return XK_o;
-    case KEY_P:			return XK_p;
-    case KEY_OPENBRACE:		return XK_braceleft;
-    case KEY_CLOSEBRACE:	return XK_braceright;
-    case KEY_ENTER:		return XK_Return;
-    case KEY_LCONTROL:		return XK_Control_L;
-    case KEY_A:			return XK_a;
-    case KEY_S:			return XK_s;
-    case KEY_D:			return XK_d;
-    case KEY_F:			return XK_f;
-    case KEY_G:			return XK_g;
-    case KEY_H:			return XK_h;
-    case KEY_J:			return XK_j;
-    case KEY_K:			return XK_k;
-    case KEY_L:			return XK_l;
-    case KEY_COLON:		return XK_colon;
-    case KEY_QUOTE:		return XK_apostrophe;
-    case KEY_TILDE:		return XK_asciitilde;
-    case KEY_LSHIFT:		return XK_Shift_L;
-    case KEY_BACKSLASH:		return XK_backslash;
-    case KEY_Z:			return XK_z;
-    case KEY_X:			return XK_x;
-    case KEY_C:			return XK_c;
-    case KEY_V:			return XK_v;
-    case KEY_B:			return XK_b;
-    case KEY_N:			return XK_n;
-    case KEY_M:			return XK_m;
-    case KEY_COMMA:		return XK_comma;
-    case KEY_STOP:		return XK_period;
-    case KEY_SLASH:		return XK_slash;
-    case KEY_RSHIFT:		return XK_Shift_R;
-    case KEY_ASTERISK:		return XK_KP_Multiply;
-    case KEY_ALT:		return XK_Alt_L;
-    case KEY_SPACE:		return XK_space;
-    case KEY_CAPSLOCK:		return XK_Caps_Lock;
-    case KEY_F1:		return XK_F1;
-    case KEY_F2:		return XK_F2;
-    case KEY_F3:		return XK_F3;
-    case KEY_F4:		return XK_F4;
-    case KEY_F5:		return XK_F5;
-    case KEY_F6:		return XK_F6;
-    case KEY_F7:		return XK_F7;
-    case KEY_F8:		return XK_F8;
-    case KEY_F9:		return XK_F9;
-    case KEY_F10:		return XK_F10;
-    case KEY_NUMLOCK:		return XK_Num_Lock;
-    case KEY_SCRLOCK:		return XK_Scroll_Lock;
-    case KEY_HOME:		return XK_Home;
-    case KEY_UP:		return XK_Up;
-    case KEY_PGUP:		return XK_Page_Up;
-    case KEY_MINUS_PAD:		return XK_KP_Subtract;
-    case KEY_LEFT:		return XK_Left;
-    case KEY_5_PAD:		return XK_KP_5;
-    case KEY_RIGHT:		return XK_Right;
-    case KEY_PLUS_PAD:		return XK_KP_Add;
-    case KEY_END:		return XK_End;
-    case KEY_DOWN:		return XK_Down;
-    case KEY_PGDN:		return XK_Page_Down;
-    case KEY_INSERT:		return XK_Insert;
-    case KEY_DEL:		return XK_Delete;
-    case KEY_PRTSCR:		return XK_Print;
-    case KEY_F11:		return XK_F11;
-    case KEY_F12:		return XK_F12;
-    case KEY_LWIN:		return XK_Meta_L;
-    case KEY_RWIN:		return XK_Meta_R;
-    case KEY_MENU:		return XK_Menu;
-    case KEY_PAD:		return XK_VoidSymbol;
-    case KEY_RCONTROL:		return XK_Control_R;
-    case KEY_ALTGR:		return XK_Alt_R;
-    case KEY_SLASH2:		return XK_KP_Divide;
-    case KEY_PAUSE:		return XK_Pause;
-
-    case NEW_KEY_BACKSLASH:	return XK_backslash;
-    case NEW_KEY_1_PAD:		return XK_KP_1;
-    case NEW_KEY_2_PAD:		return XK_KP_2;
-    case NEW_KEY_3_PAD:		return XK_KP_3;
-    case NEW_KEY_4_PAD:		return XK_KP_4;
-    case NEW_KEY_5_PAD:		return XK_KP_5;
-    case NEW_KEY_6_PAD:		return XK_KP_6;
-    case NEW_KEY_7_PAD:		return XK_KP_7;
-    case NEW_KEY_8_PAD:		return XK_KP_8;
-    case NEW_KEY_9_PAD:		return XK_KP_9;
-    case NEW_KEY_0_PAD:		return XK_KP_0;
-    case NEW_KEY_STOP_PAD:	return XK_KP_Separator;
-    case NEW_KEY_EQUALS_PAD:	return XK_KP_Equal;
-    case NEW_KEY_SLASH_PAD:	return XK_KP_Divide;
-    case NEW_KEY_ASTERISK_PAD:	return XK_KP_Multiply;
-    case NEW_KEY_ENTER_PAD:	return XK_KP_Enter;
-
-    default:			return XK_VoidSymbol;
-  }
-}
-
-Pixel AllegroAllocColorCell(int r, int g, int b)
-{
-  byte pixel_mapping = 0;
-  int i;
-
-  r >>= 10;
-  g >>= 10;
-  b >>= 10;
-
-  /* try to use existing colors from the global colormap */
-  for (i = 0; i < global_colormap_entries_used; i++)
-  {
-    if (r == global_colormap[i].r &&
-	g == global_colormap[i].g &&
-	b == global_colormap[i].b)		/* color found */
-    {
-      pixel_mapping = i;
-      break;
-    }
-  }
-
-  if (i == global_colormap_entries_used)	/* color not found */
-  {
-    if (global_colormap_entries_used < MAX_COLORS)
-      global_colormap_entries_used++;
-
-    i = global_colormap_entries_used - 1;
-
-    global_colormap[i].r = r;
-    global_colormap[i].g = g;
-    global_colormap[i].b = b;
-
-    set_palette(global_colormap);
-
-    pixel_mapping = i;
-  }
-
-  return pixel_mapping;
-}
-
-void XMapWindow(Display *display, Window window)
-{
-  int x, y;
-  unsigned int width, height;
-  boolean mouse_off;
-
-  x = AllegroDefaultScreen().x;
-  y = AllegroDefaultScreen().y;
-  width = AllegroDefaultScreen().width;
-  height = AllegroDefaultScreen().height;
-
-  mouse_off = hide_mouse(display, x, y, width, height);
-  blit((BITMAP *)window, video_bitmap, 0, 0, x, y, width, height);
-
-  if (mouse_off)
-    unhide_mouse(display);
-}
-
-Display *XOpenDisplay(char *display_name)
-{
-  Screen *screen;
-  Display *display;
-  BITMAP *mouse_bitmap = NULL;
-  char *mouse_filename = getCustomImageFilename(program.msdos_cursor_filename);
-
-  if ((mouse_bitmap = Read_PCX_to_AllegroBitmap(mouse_filename)) == NULL)
-    return NULL;
-
-  screen = malloc(sizeof(Screen));
-  display = malloc(sizeof(Display));
-
-  screen[0].cmap = 0;
-  screen[0].root = 0;
-  screen[0].white_pixel = AllegroAllocColorCell(0xFFFF, 0xFFFF, 0xFFFF);
-  screen[0].black_pixel = AllegroAllocColorCell(0x0000, 0x0000, 0x0000);
-  screen[0].video_bitmap = NULL;
-
-  display->default_screen = 0;
-  display->screens = screen;
-  display->mouse_ptr = mouse_bitmap;
-
-  allegro_init();
-  allegro_init_drivers();
-  set_color_depth(8);
-
-  /* force Windows 95 to switch to fullscreen mode */
-  set_gfx_mode(GFX_AUTODETECT, 320, 200, 0, 0);
-  rest(200);
-  set_gfx_mode(GFX_AUTODETECT, XRES, YRES, 0, 0);
-
-  return display;
-}
-
-Window XCreateSimpleWindow(Display *display, Window parent, int x, int y,
-			   unsigned int width, unsigned int height,
-			   unsigned int border_width, unsigned long border,
-			   unsigned long background)
-{
-  video_bitmap = create_video_bitmap(XRES, YRES);
-  clear_to_color(video_bitmap, background);
-
-  AllegroDefaultScreen().video_bitmap = video_bitmap;
-  AllegroDefaultScreen().x = x;
-  AllegroDefaultScreen().y = y;
-  AllegroDefaultScreen().width = XRES;
-  AllegroDefaultScreen().height = YRES;
-
-  set_mouse_sprite(display->mouse_ptr);
-
-#if 0
-  set_mouse_sprite_focus(1, 1);
-#endif
-
-  set_mouse_speed(1, 1);
-  set_mouse_range(AllegroDefaultScreen().x + 1,
-		  AllegroDefaultScreen().y + 1,
-		  AllegroDefaultScreen().x + video.width + 1,
-		  AllegroDefaultScreen().y + video.height + 1);
-
-  show_video_bitmap(video_bitmap);
-
-  return (Window)video_bitmap;
-}
-
-Status XStringListToTextProperty(char **list, int count,
-				 XTextProperty *text_prop_return)
-{
-  char *string;
-
-  if (count >= 1)
-  {
-    string = malloc(strlen(list[0] + 1));
-    strcpy(string, list[0]);
-    text_prop_return->value = (unsigned char *)string;
-    return 1;
-  }
-  else
-    text_prop_return = NULL;
-
-  return 0;
-}
-
-void XFree(void *data)
-{
-  checked_free(data);
-}
-
-GC XCreateGC(Display *display, Drawable d, unsigned long value_mask,
-	     XGCValues *values)
-{
-  XGCValues *gcv;
-  gcv = malloc(sizeof(XGCValues));
-  gcv->foreground = values->foreground;
-  gcv->background = values->background;
-  gcv->graphics_exposures = values->graphics_exposures;
-  gcv->clip_mask = values->clip_mask;
-  gcv->clip_x_origin = values->clip_x_origin;
-  gcv->clip_y_origin = values->clip_y_origin;
-  gcv->value_mask = value_mask;
-  return (GC)gcv;
-}
-
-void XSetClipMask(Display *display, GC gc, Pixmap pixmap)
-{
-  XGCValues *gcv = (XGCValues *)gc;
-
-  gcv->clip_mask = pixmap;
-  gcv->value_mask |= GCClipMask;
-}
-
-void XSetClipOrigin(Display *display, GC gc, int x, int y)
-{
-  XGCValues *gcv = (XGCValues *)gc;
-
-  gcv->clip_x_origin = x;
-  gcv->clip_x_origin = y;
-}
-
-void XFillRectangle(Display *display, Drawable d, GC gc, int x, int y,
-		    unsigned int width, unsigned int height)
-{
-  boolean mouse_off = FALSE;
-
-  if ((BITMAP *)d == video_bitmap)
-  {
-    x += AllegroDefaultScreen().x;
-    y += AllegroDefaultScreen().y;
-    freeze_mouse_flag = TRUE;
-    mouse_off = hide_mouse(display, x, y, width, height);
-  }
-
-  rectfill((BITMAP *)d, x, y, x + width - 1, y + height - 1,
-	   ((XGCValues *)gc)->foreground);
-
-  if (mouse_off)
-    unhide_mouse(display);
-
-  freeze_mouse_flag = FALSE;
-}
-
-Pixmap XCreatePixmap(Display *display, Drawable d, unsigned int width,
-		     unsigned int height, unsigned int depth)
-{
-  BITMAP *bitmap = NULL;
-
-  if (gfx_capabilities & GFX_HW_VRAM_BLIT &&
-      width == gfx.scrollbuffer_width && height == gfx.scrollbuffer_height)
-    bitmap = create_video_bitmap(width, height);
-
-  if (bitmap == NULL)
-    bitmap = create_bitmap(width, height);
-
-  return (Pixmap)bitmap;
-}
-
-void XSync(Display *display, Bool discard_events)
-{
-  wait_for_vsync = TRUE;
-}
-
-inline void XCopyArea(Display *display, Drawable src, Drawable dest, GC gc,
-		      int src_x, int src_y,
-		      unsigned int width, unsigned int height,
-		      int dest_x, int dest_y)
-{
-  boolean mouse_off = FALSE;
-
-  if ((BITMAP *)src == video_bitmap)
-  {
-    src_x += AllegroDefaultScreen().x;
-    src_y += AllegroDefaultScreen().y;
-  }
-
-  if ((BITMAP *)dest == video_bitmap)
-  {
-    dest_x += AllegroDefaultScreen().x;
-    dest_y += AllegroDefaultScreen().y;
-    freeze_mouse_flag = TRUE;
-    mouse_off = hide_mouse(display, dest_x, dest_y, width, height);
-  }
-
-  if (wait_for_vsync)
-  {
-    wait_for_vsync = FALSE;
-    vsync();
-  }
-
-  if (((XGCValues *)gc)->value_mask & GCClipMask)
-    masked_blit((BITMAP *)src, (BITMAP *)dest, src_x, src_y, dest_x, dest_y,
-		width, height);
-  else
-    blit((BITMAP *)src, (BITMAP *)dest, src_x, src_y, dest_x, dest_y,
-	 width, height);
-
-  if (mouse_off)
-    unhide_mouse(display);
-
-  freeze_mouse_flag = FALSE;
-}
-
-static BITMAP *Image_to_AllegroBitmap(Image *image)
-{
-  BITMAP *bitmap;
-  byte *src_ptr = image->data;
-  byte pixel_mapping[MAX_COLORS];
-  unsigned int depth = 8;
-  int i, x, y;
-
-  if (image->type == IMAGETYPE_TRUECOLOR && depth == 8)
-    Error(ERR_EXIT, "cannot handle true-color images on 8-bit display");
-
-  /* allocate new allegro bitmap structure */
-  if ((bitmap = create_bitmap_ex(depth, image->width, image->height)) == NULL)
-  {
-    errno_pcx = PCX_NoMemory;
-    return NULL;
-  }
-
-  clear(bitmap);
-
-  /* try to use existing colors from the global colormap */
-  for (i = 0; i < MAX_COLORS; i++)
-  {
-    if (!image->rgb.color_used[i])
-      continue;
-
-    pixel_mapping[i] = AllegroAllocColorCell(image->rgb.red[i],
-					     image->rgb.green[i],
-					     image->rgb.blue[i]);
-  }
-
-  /* copy bitmap data */
-  for (y = 0; y < image->height; y++)
-    for (x = 0; x < image->width; x++)
-      putpixel(bitmap, x, y, pixel_mapping[*src_ptr++]);
-
-  return bitmap;
-}
-
-static BITMAP *Read_PCX_to_AllegroBitmap(char *filename)
-{
-  BITMAP *bitmap;
-  Image *image;
-
-  /* read the graphic file in PCX format to internal image structure */
-  if ((image = Read_PCX_to_Image(filename)) == NULL)
-    return NULL;
-
-  /* convert internal image structure to allegro bitmap structure */
-  if ((bitmap = Image_to_AllegroBitmap(image)) == NULL)
-    return NULL;
-
-  set_palette(global_colormap);
-
-  return bitmap;
-}
-
-int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename,
-		       Pixmap *pixmap, Pixmap *pixmap_mask)
-{
-  BITMAP *bitmap;
-
-  if ((bitmap = Read_PCX_to_AllegroBitmap(filename)) == NULL)
-    return errno_pcx;
-
-  *pixmap = (Pixmap)bitmap;
-
-  /* pixmap_mask will never be used in Allegro (which uses masked_blit()),
-     so use non-NULL dummy pointer to empty Pixmap */
-  *pixmap_mask = (Pixmap)DUMMY_MASK;
-
-  return PCX_Success;
-}
-
-int XReadBitmapFile(Display *display, Drawable d, char *filename,
-		    unsigned int *width_return, unsigned int *height_return,
-		    Pixmap *bitmap_return,
-		    int *x_hot_return, int *y_hot_return)
-{
-  BITMAP *bitmap;
-
-  if ((bitmap = Read_PCX_to_AllegroBitmap(filename)) == NULL)
-    return BitmapOpenFailed;
-
-  *width_return = bitmap->w;
-  *height_return = bitmap->h;
-  *x_hot_return = -1;
-  *y_hot_return = -1;
-  *bitmap_return = (Pixmap)bitmap;
-
-  return BitmapSuccess;
-}
-
-void XFreePixmap(Display *display, Pixmap pixmap)
-{
-  if (pixmap != DUMMY_MASK &&
-      (is_memory_bitmap((BITMAP *)pixmap) ||
-       is_screen_bitmap((BITMAP *)pixmap)))
-    destroy_bitmap((BITMAP *)pixmap);
-}
-
-void XFreeGC(Display *display, GC gc)
-{
-  XGCValues *gcv = (XGCValues *)gc;
-
-  checked_free(gcv);
-}
-
-void XUnmapWindow(Display *display, Window window)
-{
-}
-
-void XCloseDisplay(Display *display)
-{
-  BITMAP *bitmap = video_bitmap;
-
-  if (is_screen_bitmap(bitmap))
-    destroy_bitmap(bitmap);
-
-  checked_free(display->screens);
-  checked_free(display);
-
-  /* return to text mode (or DOS box on Windows screen) */
-  set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
-}
-
-void XNextEvent(Display *display, XEvent *event_return)
-{
-  while (!pending_events)
-    XPending(display);
-
-  memcpy(event_return, &event_buffer[pending_events], sizeof(XEvent));
-  pending_events--;
-}
-
-static void NewKeyEvent(int key_press_state, KeySym keysym)
-{
-  XKeyEvent *xkey;
-
-  if (pending_events >= MAX_EVENT_BUFFER)
-    return;
-
-  pending_events++;
-  xkey = (XKeyEvent *)&event_buffer[pending_events];
-  xkey->type = key_press_state;
-  xkey->state = (unsigned int)keysym;
-}
-
-#define HANDLE_RAW_KB_ALL_KEYS			0
-#define HANDLE_RAW_KB_MODIFIER_KEYS_ONLY	1
-
-static int modifier_scancode[] =
-{
-  KEY_LSHIFT,
-  KEY_RSHIFT,
-  KEY_LCONTROL,
-  KEY_RCONTROL,
-  KEY_ALT,
-  KEY_ALTGR,
-  KEY_LWIN,
-  KEY_RWIN,
-  KEY_CAPSLOCK,
-  KEY_NUMLOCK,
-  KEY_SCRLOCK,
-  -1
-};
-
-static void HandleKeyboardRaw(int mode)
-{
-  int i;
-
-  for (i = 0; i < MAX_SCANCODES; i++)
-  {
-    int scancode, new_state, event_type;
-    char key_pressed;
-
-    if (mode == HANDLE_RAW_KB_MODIFIER_KEYS_ONLY)
-    {
-      if ((scancode = modifier_scancode[i]) == -1)
-	return;
-    }
-    else
-      scancode = i;
-
-    key_pressed = key[scancode];
-    new_state = (key_pressed ? KeyPressMask : KeyReleaseMask);
-    event_type = (key_pressed ? KeyPress : KeyRelease);
-
-    if (key_press_state[i] == new_state)	/* state not changed */
-      continue;
-
-    key_press_state[i] = new_state;
-
-    NewKeyEvent(event_type, ScancodeToKeySym(scancode));
-  }
-}
-
-static void HandleKeyboardEvent()
-{
-  if (keypressed())
-  {
-    int key_info = readkey();
-    int scancode = (key_info >> 8);
-    int ascii = (key_info & 0xff);
-    KeySym keysym = ScancodeToKeySym(scancode);
-
-    if (scancode == KEY_PAD)
-    {
-      /* keys on the numeric keypad return just scancode 'KEY_PAD'
-	 for some reason, so we must handle them separately */
-
-      if (ascii >= '0' && ascii <= '9')
-	keysym = XK_KP_0 + (KeySym)(ascii - '0');
-      else if (ascii == '.')
-	keysym = XK_KP_Separator;
-    }
-    else if (ascii >= ' ' && ascii <= 'Z')
-      keysym = XK_space + (KeySym)(ascii - ' ');
-    else if (ascii == '^')
-      keysym = XK_asciicircum;
-    else if (ascii == '_')
-      keysym = XK_underscore;
-    else if (ascii == '�')
-      keysym = XK_Adiaeresis;
-    else if (ascii == '�')
-      keysym = XK_Odiaeresis;
-    else if (ascii == '�')
-      keysym = XK_Udiaeresis;
-    else if (ascii == '�')
-      keysym = XK_adiaeresis;
-    else if (ascii == '�')
-      keysym = XK_odiaeresis;
-    else if (ascii == '�')
-      keysym = XK_udiaeresis;
-    else if (ascii == '�')
-      keysym = XK_ssharp;
-
-    NewKeyEvent(KeyPress, keysym);
-  }
-  else if (key_shifts & (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG))
-  {
-    /* the allegro function keypressed() does not give us single pressed
-       modifier keys, so we must detect them with the internal global
-       allegro variable 'key_shifts' and then handle them separately */
-
-    HandleKeyboardRaw(HANDLE_RAW_KB_MODIFIER_KEYS_ONLY);
-  }
-}
-
-int XPending(Display *display)
-{
-  XButtonEvent *xbutton;
-  XMotionEvent *xmotion;
-  int i;
-
-  /* When using 'HandleKeyboardRaw()', keyboard input is also stored in
-     the allegro keyboard input buffer and would be available a second
-     time by calling 'HandleKeyboardEvent()'. To avoid double keyboard
-     events, the allegro function 'clear_keybuf()' must be called each
-     time when switching from calling 'HandleKeyboardRaw()' to calling
-     'HandleKeyboardEvent()' to get keyboard input, which is actually
-     done by 'XAutoRepeatOn()' which sets keyboard_auto_repeat to TRUE. */
-
-  /* keyboard event */
-  if (keyboard_auto_repeat)
-    HandleKeyboardEvent();
-  else
-    HandleKeyboardRaw(HANDLE_RAW_KB_ALL_KEYS);
-
-  /* mouse motion event */
-  if (mouse_pos != last_mouse_pos)
-  {
-    last_mouse_pos = mouse_pos;
-    pending_events++;
-    xmotion = (XMotionEvent *)&event_buffer[pending_events];
-    xmotion->type = MotionNotify;
-    xmotion->x = mouse_x - AllegroDefaultScreen().x;
-    xmotion->y = mouse_y - AllegroDefaultScreen().y;
-  }
-
-  /* mouse button event */
-  if (mouse_b != last_mouse_b)
-  {
-    for (i = 0; i < 3; i++)	/* check all three mouse buttons */
-    {
-      int bitmask = (1 << i);
-
-      if ((last_mouse_b & bitmask) != (mouse_b & bitmask))
-      {
-	int mapping[3] = { 1, 3, 2 };
-
-	pending_events++;
-        xbutton = (XButtonEvent *)&event_buffer[pending_events];
-        xbutton->type = (mouse_b & bitmask ? ButtonPress : ButtonRelease);
-        xbutton->button = mapping[i];
-	xbutton->x = mouse_x - AllegroDefaultScreen().x;
-	xbutton->y = mouse_y - AllegroDefaultScreen().y;
-      }
-    }
-    last_mouse_b = mouse_b;
-  }
-
-  return pending_events;
-}
-
-KeySym XLookupKeysym(XKeyEvent *key_event, int index)
-{
-  return key_event->state;
-}
-
-int XLookupString(XKeyEvent *key_event, char *buffer, int buffer_size,
-		  KeySym *key, XComposeStatus *compose)
-{
-  *key = key_event->state;
-  return 0;
-}
-
-void XSetForeground(Display *display, GC gc, unsigned long pixel)
-{
-  XGCValues *gcv = (XGCValues *)gc;
-
-  gcv->foreground = pixel;
-}
-
-void XDrawLine(Display *display, Drawable d, GC gc,
-	       int x1, int y1, int x2, int y2)
-{
-  XGCValues *gcv = (XGCValues *)gc;
-  boolean mouse_off = FALSE;
-
-  if ((BITMAP *)d == video_bitmap)
-  {
-    x1 += AllegroDefaultScreen().x;
-    y1 += AllegroDefaultScreen().y;
-    x2 += AllegroDefaultScreen().x;
-    y2 += AllegroDefaultScreen().y;
-    freeze_mouse_flag = TRUE;
-    mouse_off = hide_mouse(display, MIN(x1, x2), MIN(y1, y2),
-			   MAX(x1, x2) - MIN(x1, x2),
-			   MAX(y1, y2) - MIN(y1, y2));
-  }
-
-  line((BITMAP *)d, x1, y1, x2, y2, gcv->foreground);
-
-  if (mouse_off)
-    unhide_mouse(display);
-
-  freeze_mouse_flag = FALSE;
-}
-
-void XDestroyImage(XImage *ximage)
-{
-}
-
-void XDestroyWindow(Display *display, Window window)
-{
-}
-
-Bool XQueryPointer(Display *display, Window window,
-		   Window *root, Window *child, int *root_x, int *root_y,
-		   int *win_x, int *win_y, unsigned int *mask)
-{
-  *win_x = mouse_x - AllegroDefaultScreen().x;
-  *win_y = mouse_y - AllegroDefaultScreen().y;
-
-  return True;
-}
-
-void XAutoRepeatOn(Display *display)
-{
-  keyboard_auto_repeat = TRUE;
-  clear_keybuf();
-}
-
-void XAutoRepeatOff(Display *display)
-{
-  keyboard_auto_repeat = FALSE;
-}
-
-void AllegroDrawLine(Drawable d, int from_x, int from_y, int to_x, int to_y,
-		     Pixel color)
-{
-  boolean mouse_off = FALSE;
-
-  if ((BITMAP *)d == video_bitmap)
-  {
-    int dx = AllegroDefaultScreen().x;
-    int dy = AllegroDefaultScreen().y;
-    int x1, y1, x2, y2;
-
-    from_x += dx;
-    from_y += dy;
-    to_x += dx;
-    to_y += dy;
-
-    x1 = (from_x < to_x ? from_x : to_x);
-    y1 = (from_y < to_y ? from_y : to_y);
-    x2 = (from_x < to_x ? to_x : from_x);
-    y2 = (from_y < to_y ? to_y : from_y);
-
-    freeze_mouse_flag = TRUE;
-    mouse_off = hide_mouse(display, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
-  }
-
-  line((BITMAP *)d, from_x, from_y, to_x, to_y, color);
-
-  if (mouse_off)
-    unhide_mouse(display);
-
-  freeze_mouse_flag = FALSE;
-}
-
-Pixel AllegroGetPixel(Drawable d, int x, int y)
-{
-  return getpixel((BITMAP *)d, x, y);
-}
-
-void AllegroZoomBitmap(Drawable src, Drawable dst,
-		       int src_width, int src_height,
-		       int dst_width, int dst_height)
-{
-  stretch_blit((BITMAP *)src, (BITMAP *)dst,
-	       0, 0, src_width, src_height, 0, 0, dst_width, dst_height);
-}
-
-void MSDOSOpenAudio(void)
-{
-  if (allegro_init_audio())
-  {
-    audio.sound_available = TRUE;
-    audio.music_available = TRUE;
-    audio.loops_available = TRUE;
-    audio.sound_enabled = TRUE;
-
-    audio.num_channels = NUM_MIXER_CHANNELS;
-    audio.music_channel = MUSIC_CHANNEL;
-    audio.first_sound_channel = FIRST_SOUND_CHANNEL;
-
-    Mixer_InitChannels();
-  }
-}
-
-void MSDOSCloseAudio(void)
-{
-  /* nothing to be done here */
-}
-
-void NetworkServer(int port, int serveronly)
-{
-  Error(ERR_WARN, "networking not supported in DOS version");
-}
-
-
-/* ========================================================================= */
-/* joystick functions                                                        */
-/* ========================================================================= */
-
-void MSDOSInitJoysticks()
-{
-  int i;
-
-  /* start from scratch */
-  remove_joystick();
-
-  /* try to access two joysticks; if that fails, try to access just one */
-  if (install_joystick(JOY_TYPE_2PADS) == 0 ||
-      install_joystick(JOY_TYPE_AUTODETECT) == 0)
-    joystick.status = JOYSTICK_ACTIVATED;
-
-  for (i = 0; i < MAX_PLAYERS; i++)
-  {
-    char *device_name = setup.input[i].joy.device_name;
-    int joystick_nr = getJoystickNrFromDeviceName(device_name);
-
-    if (joystick_nr >= num_joysticks)
-      joystick_nr = -1;
-
-    /* misuse joystick file descriptor variable to store joystick number */
-    joystick.fd[i] = joystick_nr;
-  }
-}
-
-boolean MSDOSReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
-{
-  /* the allegro global variable 'num_joysticks' contains the number
-     of joysticks found at initialization under MS-DOS / Windows */
-
-  if (nr < 0 || nr >= num_joysticks)
-    return FALSE;
-
-  poll_joystick();
-
-  if (x != NULL)
-    *x = joy[nr].stick[0].axis[0].pos;
-  if (y != NULL)
-    *y = joy[nr].stick[0].axis[1].pos;
-
-  if (b1 != NULL)
-    *b1 = joy[nr].button[0].b;
-  if (b2 != NULL)
-    *b2 = joy[nr].button[1].b;
-
-  return TRUE;
-}
-
-#endif /* PLATFORM_MSDOS */
diff --git a/src/libgame/msdos.h b/src/libgame/msdos.h
deleted file mode 100644
index 95e0dbc..0000000
--- a/src/libgame/msdos.h
+++ /dev/null
@@ -1,760 +0,0 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* msdos.h                                                  *
-***********************************************************/
-
-#ifndef MSDOS_H
-#define MSDOS_H
-
-#include <time.h>
-#include "allegro.h"
-
-
-/* symbol 'window' is defined in DJGPP cross-compiler in libc.a(conio.o) */
-#define window window_internal
-
-/* symbol 'font' is defined in "allegro.h" */
-#define font font_internal
-
-/* system dependent definitions */
-
-#define TARGET_STRING		"DOS"
-
-/* allegro defines TRUE as -1 */
-#ifdef TRUE
-#undef TRUE
-#undef FALSE
-#endif
-
-#define TRUE	1
-#define FALSE	0
-
-#define XRES	800
-#define YRES	600
-
-/* allegro defines some macros that bother the rest of the program */
-#ifdef joy_x
-#undef joy_x
-#undef joy_y
-#undef joy_left
-#undef joy_right
-#undef joy_up
-#undef joy_down
-#undef joy_b1
-#undef joy_b2
-#endif
-
-/* additional Allegro keyboard mapping */
-
-/* The following are all undefined in Allegro */
-#define NEW_KEY_BACKSLASH	86
-#define NEW_KEY_1_PAD		101
-#define NEW_KEY_2_PAD		102
-#define NEW_KEY_3_PAD		103
-#define NEW_KEY_4_PAD		104
-#define NEW_KEY_5_PAD		105
-#define NEW_KEY_6_PAD		106
-#define NEW_KEY_7_PAD		107
-#define NEW_KEY_8_PAD		108
-#define NEW_KEY_9_PAD		109
-#define NEW_KEY_0_PAD		110
-#define NEW_KEY_STOP_PAD	111
-#define NEW_KEY_EQUALS_PAD	112
-#define NEW_KEY_SLASH_PAD	113
-#define NEW_KEY_ASTERISK_PAD	114
-#define NEW_KEY_ENTER_PAD	115
-
-/* X11 keyboard mapping (from 'keysymdef.h') */
-
-#define XK_VoidSymbol		0xFFFFFF	/* void symbol */
-
-/*
- * TTY Functions, cleverly chosen to map to ascii, for convenience of
- * programming, but could have been arbitrary (at the cost of lookup
- * tables in client code.
- */
-
-#define XK_BackSpace		0xFF08	/* back space, back char */
-#define XK_Tab			0xFF09
-#define XK_Linefeed		0xFF0A	/* Linefeed, LF */
-#define XK_Clear		0xFF0B
-#define XK_Return		0xFF0D	/* Return, enter */
-#define XK_Pause		0xFF13	/* Pause, hold */
-#define XK_Scroll_Lock		0xFF14
-#define XK_Sys_Req		0xFF15
-#define XK_Escape		0xFF1B
-#define XK_Delete		0xFFFF	/* Delete, rubout */
-
-/* International & multi-key character composition */
-
-#define XK_Multi_key		0xFF20  /* Multi-key character compose */
-#define XK_SingleCandidate	0xFF3C
-#define XK_MultipleCandidate	0xFF3D
-#define XK_PreviousCandidate	0xFF3E
-
-/* Cursor control & motion */
-
-#define XK_Home			0xFF50
-#define XK_Left			0xFF51	/* Move left, left arrow */
-#define XK_Up			0xFF52	/* Move up, up arrow */
-#define XK_Right		0xFF53	/* Move right, right arrow */
-#define XK_Down			0xFF54	/* Move down, down arrow */
-#define XK_Prior		0xFF55	/* Prior, previous */
-#define XK_Page_Up		0xFF55
-#define XK_Next			0xFF56	/* Next */
-#define XK_Page_Down		0xFF56
-#define XK_End			0xFF57	/* EOL */
-#define XK_Begin		0xFF58	/* BOL */
-
-/* Misc Functions */
-
-#define XK_Select		0xFF60	/* Select, mark */
-#define XK_Print		0xFF61
-#define XK_Execute		0xFF62	/* Execute, run, do */
-#define XK_Insert		0xFF63	/* Insert, insert here */
-#define XK_Undo			0xFF65	/* Undo, oops */
-#define XK_Redo			0xFF66	/* redo, again */
-#define XK_Menu			0xFF67
-#define XK_Find			0xFF68	/* Find, search */
-#define XK_Cancel		0xFF69	/* Cancel, stop, abort, exit */
-#define XK_Help			0xFF6A	/* Help */
-#define XK_Break		0xFF6B
-#define XK_Mode_switch		0xFF7E	/* Character set switch */
-#define XK_script_switch        0xFF7E  /* Alias for mode_switch */
-#define XK_Num_Lock		0xFF7F
-
-/* Keypad Functions, keypad numbers cleverly chosen to map to ascii */
-
-#define XK_KP_Space		0xFF80	/* space */
-#define XK_KP_Tab		0xFF89
-#define XK_KP_Enter		0xFF8D	/* enter */
-#define XK_KP_F1		0xFF91	/* PF1, KP_A, ... */
-#define XK_KP_F2		0xFF92
-#define XK_KP_F3		0xFF93
-#define XK_KP_F4		0xFF94
-#define XK_KP_Home		0xFF95
-#define XK_KP_Left		0xFF96
-#define XK_KP_Up		0xFF97
-#define XK_KP_Right		0xFF98
-#define XK_KP_Down		0xFF99
-#define XK_KP_Prior		0xFF9A
-#define XK_KP_Page_Up		0xFF9A
-#define XK_KP_Next		0xFF9B
-#define XK_KP_Page_Down		0xFF9B
-#define XK_KP_End		0xFF9C
-#define XK_KP_Begin		0xFF9D
-#define XK_KP_Insert		0xFF9E
-#define XK_KP_Delete		0xFF9F
-#define XK_KP_Equal		0xFFBD	/* equals */
-#define XK_KP_Multiply		0xFFAA
-#define XK_KP_Add		0xFFAB
-#define XK_KP_Separator		0xFFAC	/* separator, often comma */
-#define XK_KP_Subtract		0xFFAD
-#define XK_KP_Decimal		0xFFAE
-#define XK_KP_Divide		0xFFAF
-
-#define XK_KP_0			0xFFB0
-#define XK_KP_1			0xFFB1
-#define XK_KP_2			0xFFB2
-#define XK_KP_3			0xFFB3
-#define XK_KP_4			0xFFB4
-#define XK_KP_5			0xFFB5
-#define XK_KP_6			0xFFB6
-#define XK_KP_7			0xFFB7
-#define XK_KP_8			0xFFB8
-#define XK_KP_9			0xFFB9
-
-/*
- * Auxilliary Functions; note the duplicate definitions for left and right
- * function keys;  Sun keyboards and a few other manufactures have such
- * function key groups on the left and/or right sides of the keyboard.
- * We've not found a keyboard with more than 35 function keys total.
- */
-
-#define XK_F1			0xFFBE
-#define XK_F2			0xFFBF
-#define XK_F3			0xFFC0
-#define XK_F4			0xFFC1
-#define XK_F5			0xFFC2
-#define XK_F6			0xFFC3
-#define XK_F7			0xFFC4
-#define XK_F8			0xFFC5
-#define XK_F9			0xFFC6
-#define XK_F10			0xFFC7
-#define XK_F11			0xFFC8
-#define XK_L1			0xFFC8
-#define XK_F12			0xFFC9
-#define XK_L2			0xFFC9
-#define XK_F13			0xFFCA
-#define XK_L3			0xFFCA
-#define XK_F14			0xFFCB
-#define XK_L4			0xFFCB
-#define XK_F15			0xFFCC
-#define XK_L5			0xFFCC
-#define XK_F16			0xFFCD
-#define XK_L6			0xFFCD
-#define XK_F17			0xFFCE
-#define XK_L7			0xFFCE
-#define XK_F18			0xFFCF
-#define XK_L8			0xFFCF
-#define XK_F19			0xFFD0
-#define XK_L9			0xFFD0
-#define XK_F20			0xFFD1
-#define XK_L10			0xFFD1
-#define XK_F21			0xFFD2
-#define XK_R1			0xFFD2
-#define XK_F22			0xFFD3
-#define XK_R2			0xFFD3
-#define XK_F23			0xFFD4
-#define XK_R3			0xFFD4
-#define XK_F24			0xFFD5
-#define XK_R4			0xFFD5
-#define XK_F25			0xFFD6
-#define XK_R5			0xFFD6
-#define XK_F26			0xFFD7
-#define XK_R6			0xFFD7
-#define XK_F27			0xFFD8
-#define XK_R7			0xFFD8
-#define XK_F28			0xFFD9
-#define XK_R8			0xFFD9
-#define XK_F29			0xFFDA
-#define XK_R9			0xFFDA
-#define XK_F30			0xFFDB
-#define XK_R10			0xFFDB
-#define XK_F31			0xFFDC
-#define XK_R11			0xFFDC
-#define XK_F32			0xFFDD
-#define XK_R12			0xFFDD
-#define XK_F33			0xFFDE
-#define XK_R13			0xFFDE
-#define XK_F34			0xFFDF
-#define XK_R14			0xFFDF
-#define XK_F35			0xFFE0
-#define XK_R15			0xFFE0
-
-/* Modifiers */
-
-#define XK_Shift_L		0xFFE1	/* Left shift */
-#define XK_Shift_R		0xFFE2	/* Right shift */
-#define XK_Control_L		0xFFE3	/* Left control */
-#define XK_Control_R		0xFFE4	/* Right control */
-#define XK_Caps_Lock		0xFFE5	/* Caps lock */
-#define XK_Shift_Lock		0xFFE6	/* Shift lock */
-
-#define XK_Meta_L		0xFFE7	/* Left meta */
-#define XK_Meta_R		0xFFE8	/* Right meta */
-#define XK_Alt_L		0xFFE9	/* Left alt */
-#define XK_Alt_R		0xFFEA	/* Right alt */
-#define XK_Super_L		0xFFEB	/* Left super */
-#define XK_Super_R		0xFFEC	/* Right super */
-#define XK_Hyper_L		0xFFED	/* Left hyper */
-#define XK_Hyper_R		0xFFEE	/* Right hyper */
-
-/*
- *  Latin 1
- *  Byte 3 = 0
- */
-
-#define XK_space               0x020
-#define XK_exclam              0x021
-#define XK_quotedbl            0x022
-#define XK_numbersign          0x023
-#define XK_dollar              0x024
-#define XK_percent             0x025
-#define XK_ampersand           0x026
-#define XK_apostrophe          0x027
-#define XK_quoteright          0x027	/* deprecated */
-#define XK_parenleft           0x028
-#define XK_parenright          0x029
-#define XK_asterisk            0x02a
-#define XK_plus                0x02b
-#define XK_comma               0x02c
-#define XK_minus               0x02d
-#define XK_period              0x02e
-#define XK_slash               0x02f
-#define XK_0                   0x030
-#define XK_1                   0x031
-#define XK_2                   0x032
-#define XK_3                   0x033
-#define XK_4                   0x034
-#define XK_5                   0x035
-#define XK_6                   0x036
-#define XK_7                   0x037
-#define XK_8                   0x038
-#define XK_9                   0x039
-#define XK_colon               0x03a
-#define XK_semicolon           0x03b
-#define XK_less                0x03c
-#define XK_equal               0x03d
-#define XK_greater             0x03e
-#define XK_question            0x03f
-#define XK_at                  0x040
-#define XK_A                   0x041
-#define XK_B                   0x042
-#define XK_C                   0x043
-#define XK_D                   0x044
-#define XK_E                   0x045
-#define XK_F                   0x046
-#define XK_G                   0x047
-#define XK_H                   0x048
-#define XK_I                   0x049
-#define XK_J                   0x04a
-#define XK_K                   0x04b
-#define XK_L                   0x04c
-#define XK_M                   0x04d
-#define XK_N                   0x04e
-#define XK_O                   0x04f
-#define XK_P                   0x050
-#define XK_Q                   0x051
-#define XK_R                   0x052
-#define XK_S                   0x053
-#define XK_T                   0x054
-#define XK_U                   0x055
-#define XK_V                   0x056
-#define XK_W                   0x057
-#define XK_X                   0x058
-#define XK_Y                   0x059
-#define XK_Z                   0x05a
-#define XK_bracketleft         0x05b
-#define XK_backslash           0x05c
-#define XK_bracketright        0x05d
-#define XK_asciicircum         0x05e
-#define XK_underscore          0x05f
-#define XK_grave               0x060
-#define XK_quoteleft           0x060	/* deprecated */
-#define XK_a                   0x061
-#define XK_b                   0x062
-#define XK_c                   0x063
-#define XK_d                   0x064
-#define XK_e                   0x065
-#define XK_f                   0x066
-#define XK_g                   0x067
-#define XK_h                   0x068
-#define XK_i                   0x069
-#define XK_j                   0x06a
-#define XK_k                   0x06b
-#define XK_l                   0x06c
-#define XK_m                   0x06d
-#define XK_n                   0x06e
-#define XK_o                   0x06f
-#define XK_p                   0x070
-#define XK_q                   0x071
-#define XK_r                   0x072
-#define XK_s                   0x073
-#define XK_t                   0x074
-#define XK_u                   0x075
-#define XK_v                   0x076
-#define XK_w                   0x077
-#define XK_x                   0x078
-#define XK_y                   0x079
-#define XK_z                   0x07a
-#define XK_braceleft           0x07b
-#define XK_bar                 0x07c
-#define XK_braceright          0x07d
-#define XK_asciitilde          0x07e
-
-#define XK_nobreakspace        0x0a0
-#define XK_exclamdown          0x0a1
-#define XK_cent        	       0x0a2
-#define XK_sterling            0x0a3
-#define XK_currency            0x0a4
-#define XK_yen                 0x0a5
-#define XK_brokenbar           0x0a6
-#define XK_section             0x0a7
-#define XK_diaeresis           0x0a8
-#define XK_copyright           0x0a9
-#define XK_ordfeminine         0x0aa
-#define XK_guillemotleft       0x0ab	/* left angle quotation mark */
-#define XK_notsign             0x0ac
-#define XK_hyphen              0x0ad
-#define XK_registered          0x0ae
-#define XK_macron              0x0af
-#define XK_degree              0x0b0
-#define XK_plusminus           0x0b1
-#define XK_twosuperior         0x0b2
-#define XK_threesuperior       0x0b3
-#define XK_acute               0x0b4
-#define XK_mu                  0x0b5
-#define XK_paragraph           0x0b6
-#define XK_periodcentered      0x0b7
-#define XK_cedilla             0x0b8
-#define XK_onesuperior         0x0b9
-#define XK_masculine           0x0ba
-#define XK_guillemotright      0x0bb	/* right angle quotation mark */
-#define XK_onequarter          0x0bc
-#define XK_onehalf             0x0bd
-#define XK_threequarters       0x0be
-#define XK_questiondown        0x0bf
-#define XK_Agrave              0x0c0
-#define XK_Aacute              0x0c1
-#define XK_Acircumflex         0x0c2
-#define XK_Atilde              0x0c3
-#define XK_Adiaeresis          0x0c4
-#define XK_Aring               0x0c5
-#define XK_AE                  0x0c6
-#define XK_Ccedilla            0x0c7
-#define XK_Egrave              0x0c8
-#define XK_Eacute              0x0c9
-#define XK_Ecircumflex         0x0ca
-#define XK_Ediaeresis          0x0cb
-#define XK_Igrave              0x0cc
-#define XK_Iacute              0x0cd
-#define XK_Icircumflex         0x0ce
-#define XK_Idiaeresis          0x0cf
-#define XK_ETH                 0x0d0
-#define XK_Eth                 0x0d0	/* deprecated */
-#define XK_Ntilde              0x0d1
-#define XK_Ograve              0x0d2
-#define XK_Oacute              0x0d3
-#define XK_Ocircumflex         0x0d4
-#define XK_Otilde              0x0d5
-#define XK_Odiaeresis          0x0d6
-#define XK_multiply            0x0d7
-#define XK_Ooblique            0x0d8
-#define XK_Ugrave              0x0d9
-#define XK_Uacute              0x0da
-#define XK_Ucircumflex         0x0db
-#define XK_Udiaeresis          0x0dc
-#define XK_Yacute              0x0dd
-#define XK_THORN               0x0de
-#define XK_Thorn               0x0de	/* deprecated */
-#define XK_ssharp              0x0df
-#define XK_agrave              0x0e0
-#define XK_aacute              0x0e1
-#define XK_acircumflex         0x0e2
-#define XK_atilde              0x0e3
-#define XK_adiaeresis          0x0e4
-#define XK_aring               0x0e5
-#define XK_ae                  0x0e6
-#define XK_ccedilla            0x0e7
-#define XK_egrave              0x0e8
-#define XK_eacute              0x0e9
-#define XK_ecircumflex         0x0ea
-#define XK_ediaeresis          0x0eb
-#define XK_igrave              0x0ec
-#define XK_iacute              0x0ed
-#define XK_icircumflex         0x0ee
-#define XK_idiaeresis          0x0ef
-#define XK_eth                 0x0f0
-#define XK_ntilde              0x0f1
-#define XK_ograve              0x0f2
-#define XK_oacute              0x0f3
-#define XK_ocircumflex         0x0f4
-#define XK_otilde              0x0f5
-#define XK_odiaeresis          0x0f6
-#define XK_division            0x0f7
-#define XK_oslash              0x0f8
-#define XK_ugrave              0x0f9
-#define XK_uacute              0x0fa
-#define XK_ucircumflex         0x0fb
-#define XK_udiaeresis          0x0fc
-#define XK_yacute              0x0fd
-#define XK_thorn               0x0fe
-#define XK_ydiaeresis          0x0ff
-
-/* end of X11 keyboard mapping */
-
-
-#define screen myscreen
-
-#define XFlush(a)
-#define XGetImage(a,b,c,d,e,f,g,h)		((XImage *) NULL)
-#define XDisplayName(a)				((char *) NULL)
-#define XFreeColors(a,b,c,d,e)
-#define XSelectInput(a,b,c)
-#define XDefaultDepth(a,b)			(8)
-#define XSetWMProperties(a,b,c,d,e,f,g,h,i)
-
-#define MAX_EVENT_BUFFER	256
-#define MAX_SCANCODES		128
-
-#define True			1
-#define False			0
-#define None			0L
-
-#define DUMMY_FILE		((void *) -1)
-#define DUMMY_MASK		(-1)
-
-#define KeyPressMask		(1L << 0)  
-#define KeyReleaseMask		(1L << 1)  
-#define ButtonPressMask		(1L << 2)  
-#define ButtonReleaseMask	(1L << 3)  
-#define ButtonMotionMask	(1L << 13) 
-#define ExposureMask		(1L << 15) 
-#define StructureNotifyMask	(1L << 17) 
-#define FocusChangeMask		(1L << 21) 
-
-#define KeyPress		2
-#define KeyRelease		3
-#define ButtonPress		4
-#define ButtonRelease		5
-#define MotionNotify		6
-#define FocusIn			9
-#define FocusOut		10
-#define Expose			12
-#define UnmapNotify		18
-#define MapNotify		19
-#define ClientMessage		33
-
-#define LineSolid               0
-#define LineOnOffDash           1
-#define LineDoubleDash          2
-
-#define CapNotLast              0
-#define CapButt                 1
-#define CapRound                2
-#define CapProjecting           3
-
-#define JoinMiter               0
-#define JoinRound               1
-#define JoinBevel               2
-
-#define GCForeground            (1L << 2)
-#define GCBackground            (1L << 3)
-#define GCLineWidth             (1L << 4)
-#define GCLineStyle             (1L << 5)
-#define GCCapStyle              (1L << 6)
-#define GCJoinStyle             (1L << 7)
-#define GCGraphicsExposures     (1L << 16)
-#define GCClipMask		(1L << 19)
-
-#define NormalState	1	/* most applications want to start this way */
-#define InputHint 		(1L << 0)
-#define StateHint 		(1L << 1)
-#define IconPixmapHint		(1L << 2)
-#define IconMaskHint		(1L << 5)
-#define PSize			(1L << 3) /* program specified size */
-#define PMinSize		(1L << 4) /* program specified minimum size */
-#define PMaxSize		(1L << 5) /* program specified maximum size */
-
-#define PCX_Success		 0
-#define PCX_OpenFailed		-1
-#define PCX_ReadFailed		-2
-#define	PCX_FileInvalid		-3
-#define PCX_NoMemory		-4
-#define PCX_ColorFailed		-5
-
-#define BitmapSuccess		0
-#define BitmapOpenFailed 	1
-#define BitmapFileInvalid 	2
-#define BitmapNoMemory		3
-
-#define ZPixmap			2	/* depth == drawable depth */
-
-#define DefaultScreen(dpy) 	  (((_XPrivDisplay)dpy)->default_screen)
-#define DefaultColormap(dpy, scr) (ScreenOfDisplay(dpy,scr)->cmap)
-#define ScreenOfDisplay(dpy, scr) (&((_XPrivDisplay)dpy)->screens[scr])
-#define BlackPixel(dpy, scr) 	  (ScreenOfDisplay(dpy,scr)->black_pixel)
-#define WhitePixel(dpy, scr) 	  (ScreenOfDisplay(dpy,scr)->white_pixel)
-#define RootWindow(dpy, scr) 	  (ScreenOfDisplay(dpy,scr)->root)
-#define AllPlanes 		  ((unsigned long)~0L)
-
-#define DefaultVisual(dpy, scr)	  (NULL)
-#define DefaultDepth(dpy, scr)	  (NULL)
-#define XDisplayWidth(dpy, scr)	  (XRES)
-#define XDisplayHeight(dpy, scr)  (YRES)
-
-#define XGetPixel(ximage, x, y) \
-        ((*((ximage)->f.get_pixel))((ximage), (x), (y)))
-
-typedef unsigned long Pixel;	/* Index into colormap */
-typedef unsigned long XID;
-typedef XID Window;
-typedef XID Drawable;
-typedef XID Pixmap;
-typedef XID Colormap;
-typedef XID KeySym;
-typedef XID GContext;
-typedef struct _XDisplay Display;
-typedef long Visual;
-typedef long XVisualInfo;
-typedef long Atom;
-typedef int Status;
-typedef int Bool;
-typedef int XComposeStatus;	/* we don't need the real type */
-
-typedef struct _XGC
-{
-  GContext gid;			/* protocol ID for graphics context */
-} *GC;
-
-typedef struct
-{
-  Colormap cmap;		/* default color map */
-  Window root;			/* root window id */
-  unsigned long white_pixel;	/* white pixel value */
-  unsigned long black_pixel;	/* black pixel value */
-  int x;
-  int y;
-  unsigned int width;
-  unsigned int height;
-  BITMAP *video_bitmap;
-} Screen;
-
-typedef struct _XDisplay
-{
-  int default_screen;		/* default screen for operations */
-  Screen *screens;		/* pointer to list of screens */
-  BITMAP *mouse_ptr;
-} *_XPrivDisplay;
-
-typedef struct _XImage
-{
-  struct funcs
-  {
-    unsigned long (*get_pixel) (struct _XImage *, int, int);
-  } f;
-} XImage;
-
-typedef struct
-{
-  long flags;		/* marks which fields in this structure are defined */
-  int width, height;	/* should set so old wm's don't mess up */
-  int min_width, min_height;
-  int max_width, max_height;
-} XSizeHints;
-
-typedef struct
-{
-  long flags;		/* marks which fields in this structure are defined */
-  Bool input;		/* does this application rely on the window manager to
-			   get keyboard input? */
-  int initial_state;	/* see below */
-  Pixmap icon_pixmap;	/* pixmap to be used as icon */
-  Pixmap icon_mask;	/* icon mask bitmap */
-} XWMHints;
-
-typedef struct
-{
-  char *res_name;
-  char *res_class;
-} XClassHint;
-
-typedef struct
-{
-  unsigned char *value;		/* same as Property routines */
-} XTextProperty;
-
-typedef struct
-{
-  unsigned long foreground;	/* foreground pixel */
-  unsigned long background;	/* background pixel */
-  Bool graphics_exposures;	/* boolean, should exposures be generated */
-  Pixmap clip_mask;		/* bitmap clipping; other calls for rects */
-  int clip_x_origin;		/* x origin for clipping */
-  int clip_y_origin;		/* y origin for clipping */
-  unsigned long value_mask;
-  int line_width;		/* line width */
-  int line_style;		/* LineSolid, LineOnOffDash, LineDoubleDash */
-  int cap_style;		/* CapNotLast, CapButt, 
-				   CapRound, CapProjecting */
-  int join_style;		/* JoinMiter, JoinRound, JoinBevel */
-
-} XGCValues;
-
-typedef struct
-{
-  int type;
-  int x, y;
-  int width, height;
-} XExposeEvent;
-
-typedef struct
-{
-  int type;			/* of event */
-  int x, y;			/* pointer x, y coordinates in event window */
-  unsigned int button;		/* detail */
-} XButtonEvent;
-
-typedef struct
-{
-  int type;
-  int x, y;			/* pointer x, y coordinates in event window */
-} XMotionEvent;
-
-typedef struct
-{
-  int type;			/* of event */
-  unsigned int state;		/* key or button mask */
-} XKeyEvent;
-
-typedef struct
-{
-  int type;			/* FocusIn or FocusOut */
-} XFocusChangeEvent;
-
-typedef struct
-{
-  int type;			/* ClientMessage */
-} XClientMessageEvent;
-
-typedef union _XEvent
-{
-  int type;			/* must not be changed; first element */
-  XExposeEvent xexpose;
-  XButtonEvent xbutton;
-  XMotionEvent xmotion;
-  XKeyEvent xkey;
-} XEvent;
-
-Pixel AllegroAllocColorCell(int, int, int);
-
-void XMapWindow(Display *, Window);
-Display *XOpenDisplay(char *);
-Window XCreateSimpleWindow(Display *, Window, int, int,
-			   unsigned int, unsigned int, unsigned int,
-			   unsigned long, unsigned long);
-Status XStringListToTextProperty(char **, int, XTextProperty *);
-void XFree(void *);
-GC XCreateGC(Display *, Drawable, unsigned long, XGCValues *);
-void XSetClipMask(Display *, GC, Pixmap);
-void XSetClipOrigin(Display *, GC, int, int);
-void XFillRectangle(Display *, Drawable, GC, int, int,
-		    unsigned int, unsigned int);
-Pixmap XCreatePixmap(Display *, Drawable, unsigned int, unsigned int,
-		     unsigned int);
-void XSync(Display *, Bool);
-void XCopyArea(Display *, Drawable, Drawable, GC, int, int,
-	       unsigned int, unsigned int, int, int);
-int Read_PCX_to_Pixmap(Display *, Window, GC, char *, Pixmap *, Pixmap *);
-int XReadBitmapFile(Display *, Drawable, char *,
-		    unsigned int *, unsigned int *, Pixmap *, int *, int *);
-void XFreePixmap(Display *, Pixmap);
-void XFreeGC(Display *, GC);
-void XUnmapWindow(Display *, Window);
-void XCloseDisplay(Display *);
-void XNextEvent(Display *, XEvent *);
-int XPending(Display *);
-KeySym XLookupKeysym(XKeyEvent *, int);
-int XLookupString(XKeyEvent *, char *, int, KeySym *, XComposeStatus *);
-void XSetForeground(Display *, GC, unsigned long);
-void XDrawLine(Display *, Drawable, GC, int, int, int, int);
-void XDestroyImage(XImage *);
-void XDestroyWindow(Display *, Window);
-Bool XQueryPointer(Display *, Window, Window *, Window *, int *, int *,
-		   int *, int *, unsigned int *);
-void XAutoRepeatOn(Display *);
-void XAutoRepeatOff(Display *);
-
-void AllegroDrawLine(Drawable, int, int, int, int, Pixel);
-Pixel AllegroGetPixel(Drawable, int, int);
-
-void AllegroZoomBitmap(Drawable, Drawable, int, int, int, int);
-
-void MSDOSOpenAudio(void);
-void MSDOSCloseAudio(void);
-
-void NetworkServer(int, int);
-
-void MSDOSInitJoysticks();
-boolean MSDOSReadJoystick(int, int *, int *, boolean *, boolean *);
-
-#endif /* MSDOS_H */
diff --git a/src/libgame/pcx.c b/src/libgame/pcx.c
deleted file mode 100644
index 4c93e39..0000000
--- a/src/libgame/pcx.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* pcx.c                                                    *
-***********************************************************/
-
-#ifndef TARGET_SDL
-
-#include <stdio.h>
-
-#include "pcx.h"
-#include "misc.h"
-
-
-#define PCX_DEBUG		0
-
-#define PCX_MAGIC		0x0a	/* first byte in a PCX image file    */
-#define PCX_SUPPORTED_VERSION	5	/* last acceptable version number    */
-#define PCX_ENCODING		1	/* PCX encoding method               */
-#define PCX_256COLORS_MAGIC	0x0c	/* first byte of a PCX 256 color map */
-#define PCX_MAXCOLORS		256	/* maximum number of colors          */
-
-#define PCX_HEADER_SIZE		128
-#define PCX_COLORMAP_SIZE	(3 * PCX_MAXCOLORS)
-
-struct PCX_Header
-{
-  unsigned char signature;	/* PCX file identifier                 */
-  unsigned char version;	/* version compatibility level         */
-  unsigned char encoding;	/* encoding method                     */
-  unsigned char bits_per_pixel;	/* bits per pixel (not depth!)         */
-  unsigned short xmin;		/* X position of left edge             */
-  unsigned short ymin;		/* Y position of top edge              */
-  unsigned short xmax;		/* X position of right edge            */
-  unsigned short ymax;		/* Y position of bottom edge           */
-  unsigned short hres;		/* X screen resolution of source image */
-  unsigned short vres;		/* Y screen resolution of source image */
-  unsigned char palette[16][3];	/* PCX color map                       */
-  unsigned char reserved;	/* should be 0, 1 if std res fax       */
-  unsigned char color_planes;	/* "color planes" in image             */
-  unsigned short bytes_per_line;/* byte delta between scanlines        */
-  unsigned short palette_type;	/* 0 = undef, 1 = color, 2 = grayscale */
-  unsigned char filler[58];	/* fill to struct size of 128          */
-};
-
-/* global PCX error value */
-int errno_pcx = PCX_Success;
-
-static boolean PCX_ReadBitmap(FILE *file, struct PCX_Header *pcx, Image *image)
-{
-  int width = image->width;
-  int height = image->height;
-  int pcx_depth = pcx->bits_per_pixel * pcx->color_planes;
-  int bytes_per_row = pcx->color_planes * pcx->bytes_per_line;
-  byte *row_buffer = checked_malloc(bytes_per_row);
-  byte *bitmap_ptr = image->data;
-  int y;
-
-  for (y = 0; y < height; y++)
-  {
-    /* decode a scan line into a temporary buffer first */
-    byte *dst_ptr = (pcx_depth == 8 ? bitmap_ptr : row_buffer);
-    byte value = 0, count = 0;
-    int value_int;
-    int i;
-
-    for (i = 0; i < bytes_per_row; i++)
-    {
-      if (count == 0)
-      {
-	if ((value_int = fgetc(file)) == EOF)
-	{
-	  free(row_buffer);
-	  return FALSE;
-	}
-
-	value = (byte)value_int;
-
-	if ((value & 0xc0) == 0xc0)	/* this is a repeat count byte */
-	{
-	  count = value & 0x3f;		/* extract repeat count from byte */
-
-	  if ((value_int = fgetc(file)) == EOF)
-	  {
-	    free(row_buffer);
-	    return FALSE;
-	  }
-
-	  value = (byte)value_int;
-	}
-	else
-	  count = 1;
-      }
-
-      dst_ptr[i] = value;
-      count--;
-
-      if (pcx_depth == 8)
-	image->rgb.color_used[value] = TRUE;
-    }
-
-    if (pcx_depth <= 4)			/* expand planes to 1 byte/pixel */
-    {
-      byte *src_ptr = row_buffer;
-      int plane;
-
-      for (plane = 0; plane < pcx->color_planes; plane++)
-      {
-	int i, j, x = 0;
-
-	for (i = 0; i < pcx->bytes_per_line; i++)
-	{
-	  byte value = *src_ptr++;
-
-	  for (j = 7; j >= 0; j--)
-	  {
-	    byte bit = (value >> j) & 1;
-
-	    if (i * 8 + j >= width)	/* skip padding bits */
-	      continue;
-
-	    bitmap_ptr[x++] |= bit << plane;
-	  }
-	}
-      }
-    }
-    else if (pcx_depth == 24)		/* de-interlace planes */
-    {
-      byte *src_ptr = row_buffer;
-      int plane;
-
-      for (plane = 0; plane < pcx->color_planes; plane++)
-      {
-	int x;
-
-	dst_ptr = bitmap_ptr + plane;
-	for (x = 0; x < width; x++)
-	{
-	  *dst_ptr = *src_ptr++;
-	  dst_ptr += pcx->color_planes;
-	}
-      }
-    }
-
-    bitmap_ptr += image->bytes_per_row;
-  }
-
-  free(row_buffer);
-
-  return TRUE;
-}
-
-static boolean PCX_ReadColormap(FILE *file,struct PCX_Header *pcx,Image *image)
-{
-  int pcx_depth = pcx->bits_per_pixel * pcx->color_planes;
-  int num_colors = (1 << pcx_depth);
-  int i;
-
-  if (image->depth != 8)
-    return TRUE;
-
-  if (pcx_depth == 8)
-  {
-    byte value;
-    int value_int;
-
-    /* look for a 256-colour palette */
-    do
-    {
-      if ((value_int = fgetc(file)) == EOF)
-	return FALSE;
-      value = (byte)value_int;
-    }
-    while (value != PCX_256COLORS_MAGIC);
-
-    /* read 256 colors from PCX colormap */
-    for (i = 0; i < PCX_MAXCOLORS; i++)
-    {
-      image->rgb.red[i]   = (byte)fgetc(file) << 8;
-      image->rgb.green[i] = (byte)fgetc(file) << 8;
-      image->rgb.blue[i]  = (byte)fgetc(file) << 8;
-    }
-  }
-  else
-  {
-    for (i = 0; i < num_colors; i++)
-    {
-      image->rgb.red[i]   = pcx->palette[i][0] << 8;
-      image->rgb.green[i] = pcx->palette[i][1] << 8;
-      image->rgb.blue[i]  = pcx->palette[i][2] << 8;
-    }
-  }
-
-  return TRUE;
-}
-
-Image *Read_PCX_to_Image(char *filename)
-{
-  FILE *file;
-  byte header_buffer[PCX_HEADER_SIZE];
-  struct PCX_Header pcx;
-  Image *image;
-  int width, height, depth, pcx_depth;
-  int i;
-
-  errno_pcx = PCX_Success;
-
-  if (!(file = fopen(filename, MODE_READ)))
-  {
-    errno_pcx = PCX_OpenFailed;
-    return NULL;
-  }
-
-  if (fread(header_buffer, 1, PCX_HEADER_SIZE, file) != PCX_HEADER_SIZE)
-  {
-    fclose(file);
-
-    errno_pcx = PCX_ReadFailed;
-    return NULL;
-  }
-
-  pcx.signature      = header_buffer[0];
-  pcx.version        = header_buffer[1];
-  pcx.encoding       = header_buffer[2];
-  pcx.bits_per_pixel = header_buffer[3];
-  pcx.xmin           = (header_buffer[5]  << 8) | header_buffer[4];
-  pcx.ymin           = (header_buffer[7]  << 8) | header_buffer[6];
-  pcx.xmax           = (header_buffer[9]  << 8) | header_buffer[8];
-  pcx.ymax           = (header_buffer[11] << 8) | header_buffer[10];
-  pcx.color_planes   = header_buffer[65];
-  pcx.bytes_per_line = (header_buffer[67] << 8) | header_buffer[66];
-  pcx.palette_type   = (header_buffer[69] << 8) | header_buffer[68];
-
-  for (i = 0; i < 48; i++)
-    pcx.palette[i / 3][i % 3] = header_buffer[16 + i];
-
-  width  = pcx.xmax - pcx.xmin + 1;
-  height = pcx.ymax - pcx.ymin + 1;
-  pcx_depth = pcx.bits_per_pixel * pcx.color_planes;
-  depth = ((pcx_depth + 7) / 8) * 8;
-
-  if (pcx.signature != PCX_MAGIC ||
-      pcx.version != PCX_SUPPORTED_VERSION ||
-      pcx.encoding != PCX_ENCODING ||
-      width < 0 || height < 0)
-  {
-    fclose(file);
-
-    errno_pcx = PCX_FileInvalid;
-    return NULL;
-  }
-
-#if PCX_DEBUG
-  if (options.verbose)
-  {
-    printf("\n");
-    printf("%s is a %dx%d PC Paintbrush image\n", filename, width, height);
-    printf("depth: %d\n", depth);
-    printf("bits_per_pixel: %d\n", pcx.bits_per_pixel);
-    printf("color_planes: %d\n", pcx.color_planes);
-    printf("bytes_per_line: %d\n", pcx.bytes_per_line);
-    printf("palette type: %s\n",
-	   (pcx.palette_type == 1 ? "color" :
-	    pcx.palette_type == 2 ? "grayscale" : "undefined"));
-  }
-#endif
-
-  /* allocate new image structure */
-  image = newImage(width, height, depth);
-
-  /* read compressed bitmap data */
-  if (!PCX_ReadBitmap(file, &pcx, image))
-  {
-    fclose(file);
-    freeImage(image);
-
-    errno_pcx = PCX_FileInvalid;
-    return NULL;
-  }
-
-  /* read colormap data */
-  if (!PCX_ReadColormap(file, &pcx, image))
-  {
-    fclose(file);
-    freeImage(image);
-
-    errno_pcx = PCX_ColorFailed;
-    return NULL;
-  }
-
-  fclose(file);
-
-  if (pcx_depth == 8)
-  {
-    /* determine number of used colormap entries for 8-bit PCX images */
-    for (i = 0; i < PCX_MAXCOLORS; i++)
-      if (image->rgb.color_used[i])
-	image->rgb.used++;
-  }
-
-#if PCX_DEBUG
-  if (options.verbose)
-    printf("Read_PCX_to_Image: %d colors in colormap\n", image->rgb.used);
-#endif
-
-  return image;
-}
-
-#endif /* !TARGET_SDL */
diff --git a/src/libgame/pcx.h b/src/libgame/pcx.h
deleted file mode 100644
index 566c28d..0000000
--- a/src/libgame/pcx.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* pcx.h                                                    *
-***********************************************************/
-
-#ifndef PCX_H
-#define PCX_H
-
-#include "system.h"
-#include "image.h"
-
-
-#if !defined(TARGET_SDL)
-
-#define PCX_Success		 0
-#define PCX_OpenFailed		-1
-#define PCX_ReadFailed		-2
-#define	PCX_FileInvalid		-3
-#define PCX_NoMemory		-4
-#define PCX_ColorFailed		-5
-#define PCX_OtherError		-6
-
-/* global PCX error value */
-extern int errno_pcx;
-
-Image *Read_PCX_to_Image(char *);
-
-#endif /* !TARGET_SDL */
-#endif	/* PCX_H */
diff --git a/src/libgame/platform.h b/src/libgame/platform.h
index 1e6d1c0..2fe3be7 100644
--- a/src/libgame/platform.h
+++ b/src/libgame/platform.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* platform.h                                               *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// platform.h
+// ============================================================================
 
 #ifndef PLATFORM_H
 #define PLATFORM_H
@@ -18,10 +16,7 @@
 /* define main platform keywords                                             */
 /* ========================================================================= */
 
-#if defined(MSDOS)
-#define PLATFORM_MSDOS
-#define PLATFORM_STRING "DOS"
-#elif defined(WIN32) || defined(_WIN32)
+#if defined(WIN32) || defined(_WIN32)
 #define PLATFORM_WIN32
 #define PLATFORM_STRING "Windows"
 #else
@@ -152,22 +147,21 @@
 #define PLATFORM_STRING "Windows CE"
 #endif
 
+#if defined(__ANDROID__)
+#define PLATFORM_ANDROID
+#undef  PLATFORM_STRING
+#define PLATFORM_STRING "Android"
+#endif
+
 
 /* ========================================================================= */
 /* define additional target keywords                                         */
 /* ========================================================================= */
 
-#if defined(PLATFORM_MSDOS)
-#ifndef TARGET_ALLEGRO
-#define TARGET_ALLEGRO
+#if defined(TARGET_SDL2)
+#ifndef TARGET_SDL
+#define TARGET_SDL
 #endif
-#ifndef TARGET_X11
-#define TARGET_X11
-#endif
-#endif
-
-#if defined(PLATFORM_UNIX) && defined(TARGET_X11)
-#define TARGET_X11_NATIVE
 #endif
 
 
diff --git a/src/libgame/random.c b/src/libgame/random.c
index 92f6ca3..6a5b610 100644
--- a/src/libgame/random.c
+++ b/src/libgame/random.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* random.c                                                 *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// random.c
+// ============================================================================
 
 /*
  * Copyright (c) 1983 Regents of the University of California.
@@ -129,7 +127,7 @@
    position of the rear pointer is just
 	(MAX_TYPES * (rptr - state)) + TYPE_3 == TYPE_3.  */
 
-static long int randtbl_0[DEG_3 + 1] =
+static int randtbl_0[DEG_3 + 1] =
 {
   TYPE_3,
   -851904987, -43806228, -2029755270, 1390239686, -1912102820,
@@ -139,7 +137,7 @@ static long int randtbl_0[DEG_3 + 1] =
   -607508183, -205999574, -1696891592, 1492211999, -1528267240,
   -952028296, -189082757, 362343714, 1424981831, 2039449641,
 };
-static long int randtbl_1[DEG_3 + 1] =
+static int randtbl_1[DEG_3 + 1] =
 {
   TYPE_3,
   -851904987, -43806228, -2029755270, 1390239686, -1912102820,
@@ -161,8 +159,8 @@ static long int randtbl_1[DEG_3 + 1] =
    in the initialization of randtbl) because the state table pointer is set
    to point to randtbl[1] (as explained below).)  */
 
-static long int *fptr[2] = { &randtbl_0[SEP_3 + 1], &randtbl_1[SEP_3 + 1] };
-static long int *rptr[2] = { &randtbl_0[1],         &randtbl_1[1]         };
+static int *fptr[2] = { &randtbl_0[SEP_3 + 1], &randtbl_1[SEP_3 + 1] };
+static int *rptr[2] = { &randtbl_0[1],         &randtbl_1[1]         };
 
 
 
@@ -176,13 +174,13 @@ static long int *rptr[2] = { &randtbl_0[1],         &randtbl_1[1]         };
    indexing every time to find the address of the last element to see if
    the front and rear pointers have wrapped.  */
 
-static long int *state[2] = { &randtbl_0[1], &randtbl_1[1] };
+static int *state[2] = { &randtbl_0[1], &randtbl_1[1] };
 
 static int rand_type[2] = { TYPE_3,	TYPE_3	};
 static int rand_deg[2]  = { DEG_3,	DEG_3	};
 static int rand_sep[2]  = { SEP_3,	SEP_3	};
 
-static long int *end_ptr[2] =
+static int *end_ptr[2] =
 {
   &randtbl_0[sizeof(randtbl_0) / sizeof(randtbl_0[0])],
   &randtbl_1[sizeof(randtbl_1) / sizeof(randtbl_1[0])]
@@ -203,7 +201,7 @@ void srandom_linux_libc(int nr, unsigned int x)
 
   if (rand_type[nr] != TYPE_0)
   {
-    register long int i;
+    register int i;
 
     for (i = 1; i < rand_deg[nr]; ++i)
       state[nr][i] = (1103515145 * state[nr][i - 1]) + 12345;
@@ -227,21 +225,21 @@ void srandom_linux_libc(int nr, unsigned int x)
    rear pointers can't wrap on the same call by not testing the rear
    pointer if the front one has wrapped.  Returns a 31-bit random number.  */
 
-long int random_linux_libc(int nr)
+int random_linux_libc(int nr)
 {
   if (rand_type[nr] == TYPE_0)
   {
-    state[nr][0] = ((state[nr][0] * 1103515245) + 12345) & LONG_MAX;
+    state[nr][0] = ((state[nr][0] * 1103515245) + 12345) & INT_MAX;
     return state[nr][0];
   }
   else
   {
-    long int i;
+    int i;
 
     *fptr[nr] += *rptr[nr];
 
     /* Chucking least random bit.  */
-    i = (*fptr[nr] >> 1) & LONG_MAX;
+    i = (*fptr[nr] >> 1) & INT_MAX;
     fptr[nr]++;
 
     if (fptr[nr] >= end_ptr[nr])
diff --git a/src/libgame/random.h b/src/libgame/random.h
index bde1214..8c951c3 100644
--- a/src/libgame/random.h
+++ b/src/libgame/random.h
@@ -1,20 +1,18 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* random.h                                                 *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// random.h
+// ============================================================================
 
 #ifndef RANDOM_H
 #define RANDOM_H
 
 void srandom_linux_libc(int, unsigned int);
-long int random_linux_libc(int);
+int random_linux_libc(int);
 
 #endif
diff --git a/src/libgame/sdl.c b/src/libgame/sdl.c
index 4c48424..a11452b 100644
--- a/src/libgame/sdl.c
+++ b/src/libgame/sdl.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* sdl.c                                                    *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// sdl.c
+// ============================================================================
 
 #include "system.h"
 #include "sound.h"
@@ -17,48 +15,228 @@
 #include "misc.h"
 #include "setup.h"
 
+#define ENABLE_UNUSED_CODE	0	/* currently unused functions */
 
-#if defined(TARGET_SDL)
 
 /* ========================================================================= */
 /* video functions                                                           */
 /* ========================================================================= */
 
+/* SDL internal variables */
+#if defined(TARGET_SDL2)
+static SDL_Window *sdl_window = NULL;
+static SDL_Renderer *sdl_renderer = NULL;
+static SDL_Texture *sdl_texture_stream = NULL;
+static SDL_Texture *sdl_texture_target = NULL;
+static boolean fullscreen_enabled = FALSE;
+#endif
+
+static boolean limit_screen_updates = FALSE;
+
+
 /* functions from SGE library */
 void sge_Line(SDL_Surface *, Sint16, Sint16, Sint16, Sint16, Uint32);
 
-/* stuff needed to work around SDL/Windows fullscreen drawing bug */
-static int fullscreen_width;
-static int fullscreen_height;
-static int fullscreen_xoffset;
-static int fullscreen_yoffset;
-static int video_xoffset;
-static int video_yoffset;
+#if defined(USE_TOUCH_INPUT_OVERLAY)
+/* functions to draw overlay graphics for touch device input */
+static void DrawTouchInputOverlay();
+#endif
 
-static void setFullscreenParameters(char *fullscreen_mode_string)
+void SDLLimitScreenUpdates(boolean enable)
 {
-  struct ScreenModeInfo *fullscreen_mode;
-  int i;
+  limit_screen_updates = enable;
+}
+
+static void FinalizeScreen(int draw_target)
+{
+  // copy global animations to render target buffer, if defined (below border)
+  if (gfx.draw_global_anim_function != NULL)
+    gfx.draw_global_anim_function(draw_target, DRAW_GLOBAL_ANIM_STAGE_1);
+
+  // copy global masked border to render target buffer, if defined
+  if (gfx.draw_global_border_function != NULL)
+    gfx.draw_global_border_function(draw_target);
+
+  // copy global animations to render target buffer, if defined (above border)
+  if (gfx.draw_global_anim_function != NULL)
+    gfx.draw_global_anim_function(draw_target, DRAW_GLOBAL_ANIM_STAGE_2);
+}
 
-  fullscreen_mode = get_screen_mode_from_string(fullscreen_mode_string);
+static void UpdateScreenExt(SDL_Rect *rect, boolean with_frame_delay)
+{
+  static unsigned int update_screen_delay = 0;
+  unsigned int update_screen_delay_value = 50;		/* (milliseconds) */
+  SDL_Surface *screen = backbuffer->surface;
 
-  if (fullscreen_mode == NULL)
+  if (limit_screen_updates &&
+      !DelayReached(&update_screen_delay, update_screen_delay_value))
     return;
 
-  for (i = 0; video.fullscreen_modes[i].width != -1; i++)
+  LimitScreenUpdates(FALSE);
+
+#if 0
+  {
+    static int LastFrameCounter = 0;
+    boolean changed = (FrameCounter != LastFrameCounter);
+
+    printf("::: FrameCounter == %d [%s]\n", FrameCounter,
+	   (changed ? "-" : "SAME FRAME UPDATED"));
+
+    LastFrameCounter = FrameCounter;
+
+    /*
+    if (FrameCounter % 2)
+      return;
+    */
+  }
+#endif
+
+  if (video.screen_rendering_mode == SPECIAL_RENDERING_BITMAP &&
+      gfx.final_screen_bitmap != NULL)	// may not be initialized yet
+  {
+    // draw global animations using bitmaps instead of using textures
+    // to prevent texture scaling artefacts (this is potentially slower)
+
+    BlitBitmap(backbuffer, gfx.final_screen_bitmap, 0, 0,
+	       gfx.win_xsize, gfx.win_ysize, 0, 0);
+
+    FinalizeScreen(DRAW_TO_SCREEN);
+
+    screen = gfx.final_screen_bitmap->surface;
+
+    // force full window redraw
+    rect = NULL;
+  }
+
+#if defined(TARGET_SDL2)
+  SDL_Texture *sdl_texture = sdl_texture_stream;
+
+  // deactivate use of target texture if render targets are not supported
+  if ((video.screen_rendering_mode == SPECIAL_RENDERING_TARGET ||
+       video.screen_rendering_mode == SPECIAL_RENDERING_DOUBLE) &&
+      sdl_texture_target == NULL)
+    video.screen_rendering_mode = SPECIAL_RENDERING_OFF;
+
+  if (video.screen_rendering_mode == SPECIAL_RENDERING_TARGET)
+    sdl_texture = sdl_texture_target;
+
+  if (rect)
   {
-    if (fullscreen_mode->width  == video.fullscreen_modes[i].width &&
-	fullscreen_mode->height == video.fullscreen_modes[i].height)
+    int bytes_x = screen->pitch / video.width;
+    int bytes_y = screen->pitch;
+
+    SDL_UpdateTexture(sdl_texture, rect,
+		      screen->pixels + rect->x * bytes_x + rect->y * bytes_y,
+		      screen->pitch);
+  }
+  else
+  {
+    SDL_UpdateTexture(sdl_texture, NULL, screen->pixels, screen->pitch);
+  }
+
+  int xoff = video.screen_xoffset;
+  int yoff = video.screen_yoffset;
+  SDL_Rect dst_rect_screen = { xoff, yoff, video.width, video.height };
+  SDL_Rect *src_rect1 = NULL, *dst_rect1 = NULL;
+  SDL_Rect *src_rect2 = NULL, *dst_rect2 = NULL;
+
+  if (video.screen_rendering_mode == SPECIAL_RENDERING_TARGET ||
+      video.screen_rendering_mode == SPECIAL_RENDERING_DOUBLE)
+    dst_rect2 = &dst_rect_screen;
+  else
+    dst_rect1 = &dst_rect_screen;
+
+#if defined(HAS_SCREEN_KEYBOARD)
+  if (video.shifted_up || video.shifted_up_delay)
+  {
+    int time_current = SDL_GetTicks();
+    int pos = video.shifted_up_pos;
+    int pos_last = video.shifted_up_pos_last;
+
+    if (!DelayReachedExt(&video.shifted_up_delay, video.shifted_up_delay_value,
+			 time_current))
     {
-      fullscreen_width  = fullscreen_mode->width;
-      fullscreen_height = fullscreen_mode->height;
+      int delay = time_current - video.shifted_up_delay;
+      int delay_value = video.shifted_up_delay_value;
 
-      fullscreen_xoffset = (fullscreen_width  - video.width)  / 2;
-      fullscreen_yoffset = (fullscreen_height - video.height) / 2;
+      pos = pos_last + (pos - pos_last) * delay / delay_value;
+    }
+    else
+    {
+      video.shifted_up_pos_last = pos;
+      video.shifted_up_delay = 0;
+    }
 
-      break;
+    SDL_Rect src_rect_up = { 0,    pos,  video.width, video.height - pos };
+    SDL_Rect dst_rect_up = { xoff, yoff, video.width, video.height - pos };
+
+    if (video.screen_rendering_mode == SPECIAL_RENDERING_TARGET ||
+	video.screen_rendering_mode == SPECIAL_RENDERING_DOUBLE)
+    {
+      src_rect2 = &src_rect_up;
+      dst_rect2 = &dst_rect_up;
     }
+    else
+    {
+      src_rect1 = &src_rect_up;
+      dst_rect1 = &dst_rect_up;
+    }
+  }
+#endif
+
+  // clear render target buffer
+  SDL_RenderClear(sdl_renderer);
+
+  // set renderer to use target texture for rendering
+  if (video.screen_rendering_mode == SPECIAL_RENDERING_TARGET ||
+      video.screen_rendering_mode == SPECIAL_RENDERING_DOUBLE)
+    SDL_SetRenderTarget(sdl_renderer, sdl_texture_target);
+
+  // copy backbuffer texture to render target buffer
+  if (video.screen_rendering_mode != SPECIAL_RENDERING_TARGET)
+    SDL_RenderCopy(sdl_renderer, sdl_texture_stream, src_rect1, dst_rect1);
+
+  if (video.screen_rendering_mode != SPECIAL_RENDERING_BITMAP)
+    FinalizeScreen(DRAW_TO_SCREEN);
+
+  // when using target texture, copy it to screen buffer
+  if (video.screen_rendering_mode == SPECIAL_RENDERING_TARGET ||
+      video.screen_rendering_mode == SPECIAL_RENDERING_DOUBLE)
+  {
+    SDL_SetRenderTarget(sdl_renderer, NULL);
+    SDL_RenderCopy(sdl_renderer, sdl_texture_target, src_rect2, dst_rect2);
   }
+
+#if defined(USE_TOUCH_INPUT_OVERLAY)
+  // draw overlay graphics for touch device input, if needed
+  DrawTouchInputOverlay();
+#endif
+
+#endif
+
+  // global synchronization point of the game to align video frame delay
+  if (with_frame_delay)
+    WaitUntilDelayReached(&video.frame_delay, video.frame_delay_value);
+
+#if defined(TARGET_SDL2)
+ // show render target buffer on screen
+  SDL_RenderPresent(sdl_renderer);
+#else	// TARGET_SDL
+  if (rect)
+    SDL_UpdateRects(screen, 1, rect);
+  else
+    SDL_UpdateRect(screen, 0, 0, 0, 0);
+#endif
+}
+
+static void UpdateScreen_WithFrameDelay(SDL_Rect *rect)
+{
+  UpdateScreenExt(rect, TRUE);
+}
+
+static void UpdateScreen_WithoutFrameDelay(SDL_Rect *rect)
+{
+  UpdateScreenExt(rect, FALSE);
 }
 
 static void SDLSetWindowIcon(char *basename)
@@ -85,271 +263,735 @@ static void SDLSetWindowIcon(char *basename)
   }
 
   /* set transparent color */
-  SDL_SetColorKey(surface, SDL_SRCCOLORKEY,
+  SDL_SetColorKey(surface, SET_TRANSPARENT_PIXEL,
 		  SDL_MapRGB(surface->format, 0x00, 0x00, 0x00));
 
+#if defined(TARGET_SDL2)
+  SDL_SetWindowIcon(sdl_window, surface);
+#else
   SDL_WM_SetIcon(surface, NULL);
 #endif
+#endif
+}
+
+#if defined(TARGET_SDL2)
+
+static boolean equalSDLPixelFormat(SDL_PixelFormat *format1,
+				   SDL_PixelFormat *format2)
+{
+  return (format1->format	 == format2->format &&
+	  format1->BitsPerPixel	 == format2->BitsPerPixel &&
+	  format1->BytesPerPixel == format2->BytesPerPixel &&
+	  format1->Rmask	 == format2->Rmask &&
+	  format1->Gmask	 == format2->Gmask &&
+	  format1->Bmask	 == format2->Bmask);
+}
+
+static Pixel SDLGetColorKey(SDL_Surface *surface)
+{
+  Pixel color_key;
+
+  if (SDL_GetColorKey(surface, &color_key) != 0)
+    return -1;
+
+  return color_key;
+}
+
+static boolean SDLHasColorKey(SDL_Surface *surface)
+{
+  return (SDLGetColorKey(surface) != -1);
+}
+
+static boolean SDLHasAlpha(SDL_Surface *surface)
+{
+  SDL_BlendMode blend_mode;
+
+  if (SDL_GetSurfaceBlendMode(surface, &blend_mode) != 0)
+    return FALSE;
+
+  return (blend_mode == SDL_BLENDMODE_BLEND);
+}
+
+static void SDLSetAlpha(SDL_Surface *surface, boolean set, int alpha)
+{
+  SDL_BlendMode blend_mode = (set ? SDL_BLENDMODE_BLEND : SDL_BLENDMODE_NONE);
+
+  SDL_SetSurfaceBlendMode(surface, blend_mode);
+  SDL_SetSurfaceAlphaMod(surface, alpha);
+}
+
+SDL_Surface *SDLGetNativeSurface(SDL_Surface *surface)
+{
+  SDL_PixelFormat format;
+  SDL_Surface *new_surface;
+
+  if (surface == NULL)
+    return NULL;
+
+  if (backbuffer && backbuffer->surface)
+  {
+    format = *backbuffer->surface->format;
+    format.Amask = surface->format->Amask;	// keep alpha channel
+  }
+  else
+  {
+    format = *surface->format;
+  }
+
+  new_surface = SDL_ConvertSurface(surface, &format, 0);
+
+  if (new_surface == NULL)
+    Error(ERR_EXIT, "SDL_ConvertSurface() failed: %s", SDL_GetError());
+
+  return new_surface;
+}
+
+boolean SDLSetNativeSurface(SDL_Surface **surface)
+{
+  SDL_Surface *new_surface;
+
+  if (surface == NULL ||
+      *surface == NULL ||
+      backbuffer == NULL ||
+      backbuffer->surface == NULL)
+    return FALSE;
+
+  // if pixel format already optimized for destination surface, do nothing
+  if (equalSDLPixelFormat((*surface)->format, backbuffer->surface->format))
+    return FALSE;
+
+  new_surface = SDLGetNativeSurface(*surface);
+
+  SDL_FreeSurface(*surface);
+
+  *surface = new_surface;
+
+  return TRUE;
+}
+
+#else
+
+static Pixel SDLGetColorKey(SDL_Surface *surface)
+{
+  if ((surface->flags & SDL_SRCCOLORKEY) == 0)
+    return -1;
+
+  return surface->format->colorkey;
+}
+
+static boolean SDLHasColorKey(SDL_Surface *surface)
+{
+  return (SDLGetColorKey(surface) != -1);
+}
+
+static boolean SDLHasAlpha(SDL_Surface *surface)
+{
+  return ((surface->flags & SDL_SRCALPHA) != 0);
+}
+
+static void SDLSetAlpha(SDL_Surface *surface, boolean set, int alpha)
+{
+  SDL_SetAlpha(surface, (set ? SDL_SRCALPHA : 0), alpha);
+}
+
+SDL_Surface *SDLGetNativeSurface(SDL_Surface *surface)
+{
+  SDL_Surface *new_surface;
+
+  if (surface == NULL)
+    return NULL;
+
+  if (!video.initialized)
+    new_surface = SDL_ConvertSurface(surface, surface->format, SURFACE_FLAGS);
+  else if (SDLHasAlpha(surface))
+    new_surface = SDL_DisplayFormatAlpha(surface);
+  else
+    new_surface = SDL_DisplayFormat(surface);
+
+  if (new_surface == NULL)
+    Error(ERR_EXIT, "%s() failed: %s",
+	  (video.initialized ? "SDL_DisplayFormat" : "SDL_ConvertSurface"),
+	  SDL_GetError());
+
+  return new_surface;
+}
+
+boolean SDLSetNativeSurface(SDL_Surface **surface)
+{
+  SDL_Surface *new_surface;
+
+  if (surface == NULL ||
+      *surface == NULL ||
+      !video.initialized)
+    return FALSE;
+
+  new_surface = SDLGetNativeSurface(*surface);
+
+  SDL_FreeSurface(*surface);
+
+  *surface = new_surface;
+
+  return TRUE;
+}
+
+#endif
+
+#if defined(TARGET_SDL2)
+static SDL_Texture *SDLCreateTextureFromSurface(SDL_Surface *surface)
+{
+  SDL_Texture *texture = SDL_CreateTextureFromSurface(sdl_renderer, surface);
+
+  if (texture == NULL)
+    Error(ERR_EXIT, "SDL_CreateTextureFromSurface() failed: %s",
+	  SDL_GetError());
+
+  return texture;
+}
+#endif
+
+void SDLCreateBitmapTextures(Bitmap *bitmap)
+{
+#if defined(TARGET_SDL2)
+  if (bitmap == NULL)
+    return;
+
+  if (bitmap->texture)
+    SDL_DestroyTexture(bitmap->texture);
+  if (bitmap->texture_masked)
+    SDL_DestroyTexture(bitmap->texture_masked);
+
+  bitmap->texture        = SDLCreateTextureFromSurface(bitmap->surface);
+  bitmap->texture_masked = SDLCreateTextureFromSurface(bitmap->surface_masked);
+#endif
+}
+
+void SDLFreeBitmapTextures(Bitmap *bitmap)
+{
+#if defined(TARGET_SDL2)
+  if (bitmap == NULL)
+    return;
+
+  if (bitmap->texture)
+    SDL_DestroyTexture(bitmap->texture);
+  if (bitmap->texture_masked)
+    SDL_DestroyTexture(bitmap->texture_masked);
+
+  bitmap->texture = NULL;
+  bitmap->texture_masked = NULL;
+#endif
 }
 
 void SDLInitVideoDisplay(void)
 {
+#if !defined(TARGET_SDL2)
   if (!strEqual(setup.system.sdl_videodriver, ARG_DEFAULT))
     SDL_putenv(getStringCat2("SDL_VIDEODRIVER=", setup.system.sdl_videodriver));
 
   SDL_putenv("SDL_VIDEO_CENTERED=1");
+#endif
 
   /* initialize SDL video */
   if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
     Error(ERR_EXIT, "SDL_InitSubSystem() failed: %s", SDL_GetError());
 
   /* set default SDL depth */
+#if !defined(TARGET_SDL2)
   video.default_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
+#else
+  video.default_depth = 32;	// (how to determine video depth in SDL2?)
+#endif
+}
+
+void SDLInitVideoBuffer(boolean fullscreen)
+{
+  video.window_scaling_percent = setup.window_scaling_percent;
+  video.window_scaling_quality = setup.window_scaling_quality;
+
+  SDLSetScreenRenderingMode(setup.screen_rendering_mode);
+
+#if defined(TARGET_SDL2)
+  // SDL 2.0: support for (desktop) fullscreen mode available
+  video.fullscreen_available = TRUE;
+#else
+  // SDL 1.2: no support for fullscreen mode in R'n'D anymore
+  video.fullscreen_available = FALSE;
+#endif
+
+  /* open SDL video output device (window or fullscreen mode) */
+  if (!SDLSetVideoMode(fullscreen))
+    Error(ERR_EXIT, "setting video mode failed");
+
+  /* !!! SDL2 can only set the window icon if the window already exists !!! */
+  /* set window icon */
+  SDLSetWindowIcon(program.icon_filename);
+
+  /* set window and icon title */
+#if defined(TARGET_SDL2)
+  SDL_SetWindowTitle(sdl_window, program.window_title);
+#else
+  SDL_WM_SetCaption(program.window_title, program.window_title);
+#endif
+
+  /* SDL cannot directly draw to the visible video framebuffer like X11,
+     but always uses a backbuffer, which is then blitted to the visible
+     video framebuffer with 'SDL_UpdateRect' (or replaced with the current
+     visible video framebuffer with 'SDL_Flip', if the hardware supports
+     this). Therefore do not use an additional backbuffer for drawing, but
+     use a symbolic buffer (distinguishable from the SDL backbuffer) called
+     'window', which indicates that the SDL backbuffer should be updated to
+     the visible video framebuffer when attempting to blit to it.
+
+     For convenience, it seems to be a good idea to create this symbolic
+     buffer 'window' at the same size as the SDL backbuffer. Although it
+     should never be drawn to directly, it would do no harm nevertheless. */
+
+  /* create additional (symbolic) buffer for double-buffering */
+  ReCreateBitmap(&window, video.width, video.height);
 }
 
-void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
-			boolean fullscreen)
+static boolean SDLCreateScreen(boolean fullscreen)
 {
-  static int screen_xy[][2] =
+  SDL_Surface *new_surface = NULL;
+
+#if defined(TARGET_SDL2)
+  int surface_flags_window     = SURFACE_FLAGS | SDL_WINDOW_RESIZABLE;
+  int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN_DESKTOP;
+#else
+  int surface_flags_window     = SURFACE_FLAGS;
+  int surface_flags_fullscreen = SURFACE_FLAGS;	// (no fullscreen in SDL 1.2)
+#endif
+
+#if defined(TARGET_SDL2)
+#if 1
+  int renderer_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE;
+#else
+  /* If SDL_CreateRenderer() is called from within a VirtualBox Windows VM
+     _without_ enabling 2D/3D acceleration and/or guest additions installed,
+     it will crash if flags are *not* set to SDL_RENDERER_SOFTWARE (because
+     it will try to use accelerated graphics and apparently fails miserably) */
+  int renderer_flags = SDL_RENDERER_SOFTWARE;
+#endif
+
+  SDLSetScreenSizeAndOffsets(video.width, video.height);
+#endif
+
+  int width  = video.width;
+  int height = video.height;
+  int screen_width  = video.screen_width;
+  int screen_height = video.screen_height;
+  int surface_flags = (fullscreen ? surface_flags_fullscreen :
+		       surface_flags_window);
+
+  // default window size is unscaled
+  video.window_width  = screen_width;
+  video.window_height = screen_height;
+
+#if defined(TARGET_SDL2)
+
+  // store if initial screen mode is fullscreen mode when changing screen size
+  video.fullscreen_initial = fullscreen;
+
+  float window_scaling_factor = (float)setup.window_scaling_percent / 100;
+
+  video.window_width  = window_scaling_factor * screen_width;
+  video.window_height = window_scaling_factor * screen_height;
+
+  if (sdl_texture_stream)
   {
-    {  640, 480 },
-    {  800, 600 },
-    { 1024, 768 },
-    {   -1,  -1 }
-  };
-  SDL_Rect **modes;
-  int i, j;
+    SDL_DestroyTexture(sdl_texture_stream);
+    sdl_texture_stream = NULL;
+  }
 
-  /* default: normal game window size */
-  fullscreen_width = video.width;
-  fullscreen_height = video.height;
-  fullscreen_xoffset = 0;
-  fullscreen_yoffset = 0;
+  if (sdl_texture_target)
+  {
+    SDL_DestroyTexture(sdl_texture_target);
+    sdl_texture_target = NULL;
+  }
 
-  for (i = 0; screen_xy[i][0] != -1; i++)
+  if (!(fullscreen && fullscreen_enabled))
   {
-    if (screen_xy[i][0] >= video.width && screen_xy[i][1] >= video.height)
+    if (sdl_renderer)
     {
-      fullscreen_width  = screen_xy[i][0];
-      fullscreen_height = screen_xy[i][1];
+      SDL_DestroyRenderer(sdl_renderer);
+      sdl_renderer = NULL;
+    }
 
-      break;
+    if (sdl_window)
+    {
+      SDL_DestroyWindow(sdl_window);
+      sdl_window = NULL;
     }
   }
 
-  fullscreen_xoffset = (fullscreen_width  - video.width)  / 2;
-  fullscreen_yoffset = (fullscreen_height - video.height) / 2;
-
-#if 1
-  checked_free(video.fullscreen_modes);
+  if (sdl_window == NULL)
+    sdl_window = SDL_CreateWindow(program.window_title,
+				  SDL_WINDOWPOS_CENTERED,
+				  SDL_WINDOWPOS_CENTERED,
+				  video.window_width,
+				  video.window_height,
+				  surface_flags);
 
-  video.fullscreen_modes = NULL;
-  video.fullscreen_mode_current = NULL;
-#endif
+  if (sdl_window != NULL)
+  {
+    if (sdl_renderer == NULL)
+      sdl_renderer = SDL_CreateRenderer(sdl_window, -1, renderer_flags);
 
-  /* get available hardware supported fullscreen modes */
-  modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
+    if (sdl_renderer != NULL)
+    {
+      SDL_RenderSetLogicalSize(sdl_renderer, screen_width, screen_height);
+      // SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
+      SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, setup.window_scaling_quality);
+
+      sdl_texture_stream = SDL_CreateTexture(sdl_renderer,
+					     SDL_PIXELFORMAT_ARGB8888,
+					     SDL_TEXTUREACCESS_STREAMING,
+					     width, height);
+
+      if (SDL_RenderTargetSupported(sdl_renderer))
+	sdl_texture_target = SDL_CreateTexture(sdl_renderer,
+					       SDL_PIXELFORMAT_ARGB8888,
+					       SDL_TEXTUREACCESS_TARGET,
+					       width, height);
+
+      if (sdl_texture_stream != NULL)
+      {
+	// use SDL default values for RGB masks and no alpha channel
+	new_surface = SDL_CreateRGBSurface(0, width, height, 32, 0,0,0, 0);
 
-  if (modes == NULL)
+	if (new_surface == NULL)
+	  Error(ERR_WARN, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
+      }
+      else
+      {
+	Error(ERR_WARN, "SDL_CreateTexture() failed: %s", SDL_GetError());
+      }
+    }
+    else
+    {
+      Error(ERR_WARN, "SDL_CreateRenderer() failed: %s", SDL_GetError());
+    }
+  }
+  else
   {
-    /* no screen modes available => no fullscreen mode support */
-    video.fullscreen_available = FALSE;
+    Error(ERR_WARN, "SDL_CreateWindow() failed: %s", SDL_GetError());
   }
-  else if (modes == (SDL_Rect **)-1)
+
+#else	// TARGET_SDL
+
+  if (gfx.final_screen_bitmap == NULL)
+    gfx.final_screen_bitmap = CreateBitmapStruct();
+
+  gfx.final_screen_bitmap->width = width;
+  gfx.final_screen_bitmap->height = height;
+
+  gfx.final_screen_bitmap->surface =
+    SDL_SetVideoMode(width, height, video.depth, surface_flags);
+
+  if (gfx.final_screen_bitmap->surface != NULL)
   {
-    /* fullscreen resolution is not restricted -- all resolutions available */
-    video.fullscreen_modes = checked_calloc(2 * sizeof(struct ScreenModeInfo));
+    new_surface =
+      SDL_CreateRGBSurface(surface_flags, width, height, video.depth, 0,0,0, 0);
+
+    if (new_surface == NULL)
+      Error(ERR_WARN, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
 
-    /* use native video buffer size for fullscreen mode */
-    video.fullscreen_modes[0].width  = video.width;
-    video.fullscreen_modes[0].height = video.height;
+#if 0
+    new_surface = gfx.final_screen_bitmap->surface;
+    gfx.final_screen_bitmap = NULL;
+#endif
 
-    video.fullscreen_modes[1].width  = -1;
-    video.fullscreen_modes[1].height = -1;
   }
   else
   {
-    /* in this case, a certain number of screen modes is available */
-    int num_modes = 0;
+    Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
+  }
+#endif
 
-    for(i = 0; modes[i] != NULL; i++)
-    {
-      boolean found_mode = FALSE;
+#if defined(TARGET_SDL2)
+  // store fullscreen state ("video.fullscreen_enabled" may not reflect this!)
+  if (new_surface != NULL)
+    fullscreen_enabled = fullscreen;
+#endif
 
-      /* screen mode is smaller than video buffer size -- skip it */
-      if (modes[i]->w < video.width || modes[i]->h < video.height)
-	continue;
+  if (backbuffer == NULL)
+    backbuffer = CreateBitmapStruct();
 
-      if (video.fullscreen_modes != NULL)
-	for (j = 0; video.fullscreen_modes[j].width != -1; j++)
-	  if (modes[i]->w == video.fullscreen_modes[j].width &&
-	      modes[i]->h == video.fullscreen_modes[j].height)
-	    found_mode = TRUE;
+  backbuffer->width  = video.width;
+  backbuffer->height = video.height;
 
-      if (found_mode)		/* screen mode already stored -- skip it */
-	continue;
+  if (backbuffer->surface)
+    SDL_FreeSurface(backbuffer->surface);
 
-      /* new mode found; add it to list of available fullscreen modes */
+  backbuffer->surface = new_surface;
 
-      num_modes++;
+  return (new_surface != NULL);
+}
 
-      video.fullscreen_modes = checked_realloc(video.fullscreen_modes,
-					       (num_modes + 1) *
-					       sizeof(struct ScreenModeInfo));
+boolean SDLSetVideoMode(boolean fullscreen)
+{
+  boolean success = FALSE;
 
-      video.fullscreen_modes[num_modes - 1].width  = modes[i]->w;
-      video.fullscreen_modes[num_modes - 1].height = modes[i]->h;
+  SetWindowTitle();
 
-      video.fullscreen_modes[num_modes].width  = -1;
-      video.fullscreen_modes[num_modes].height = -1;
-    }
+  if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
+  {
+    /* switch display to fullscreen mode, if available */
+    success = SDLCreateScreen(TRUE);
 
-    if (num_modes == 0)
+    if (!success)
     {
-      /* no appropriate screen modes available => no fullscreen mode support */
+      /* switching display to fullscreen mode failed -- do not try it again */
       video.fullscreen_available = FALSE;
     }
+    else
+    {
+      video.fullscreen_enabled = TRUE;
+    }
   }
 
-  /* set window icon */
-  SDLSetWindowIcon(program.sdl_icon_filename);
+  if ((!fullscreen && video.fullscreen_enabled) || !success)
+  {
+    /* switch display to window mode */
+    success = SDLCreateScreen(FALSE);
 
-  /* open SDL video output device (window or fullscreen mode) */
-  if (!SDLSetVideoMode(backbuffer, fullscreen))
-    Error(ERR_EXIT, "setting video mode failed");
+    if (!success)
+    {
+      /* switching display to window mode failed -- should not happen */
+    }
+    else
+    {
+      video.fullscreen_enabled = FALSE;
+      video.window_scaling_percent = setup.window_scaling_percent;
+      video.window_scaling_quality = setup.window_scaling_quality;
 
-  /* set window and icon title */
-  SDL_WM_SetCaption(program.window_title, program.window_title);
+      SDLSetScreenRenderingMode(setup.screen_rendering_mode);
+    }
+  }
 
-  /* SDL cannot directly draw to the visible video framebuffer like X11,
-     but always uses a backbuffer, which is then blitted to the visible
-     video framebuffer with 'SDL_UpdateRect' (or replaced with the current
-     visible video framebuffer with 'SDL_Flip', if the hardware supports
-     this). Therefore do not use an additional backbuffer for drawing, but
-     use a symbolic buffer (distinguishable from the SDL backbuffer) called
-     'window', which indicates that the SDL backbuffer should be updated to
-     the visible video framebuffer when attempting to blit to it.
+#if defined(TARGET_SDL2)
+  SDLRedrawWindow();			// map window
+#endif
 
-     For convenience, it seems to be a good idea to create this symbolic
-     buffer 'window' at the same size as the SDL backbuffer. Although it
-     should never be drawn to directly, it would do no harm nevertheless. */
+#ifdef DEBUG
+#if defined(PLATFORM_WIN32)
+  // experimental drag and drop code
 
-  /* create additional (symbolic) buffer for double-buffering */
-#if 1
-  ReCreateBitmap(window, video.width, video.height, video.depth);
+  SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
+
+  {
+    SDL_SysWMinfo wminfo;
+    HWND hwnd;
+    boolean wminfo_success = FALSE;
+
+    SDL_VERSION(&wminfo.version);
+#if defined(TARGET_SDL2)
+    if (sdl_window)
+      wminfo_success = SDL_GetWindowWMInfo(sdl_window, &wminfo);
+#else
+    wminfo_success = (SDL_GetWMInfo(&wminfo) == 1);
+#endif
+
+    if (wminfo_success)
+    {
+#if defined(TARGET_SDL2)
+      hwnd = wminfo.info.win.window;
 #else
-  *window = CreateBitmap(video.width, video.height, video.depth);
+      hwnd = wminfo.window;
 #endif
+
+      DragAcceptFiles(hwnd, TRUE);
+    }
+  }
+#endif
+#endif
+
+  return success;
 }
 
-boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
+void SDLSetWindowTitle()
 {
-  boolean success = TRUE;
-  int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
-  int surface_flags_window = SURFACE_FLAGS;
-  SDL_Surface *new_surface = NULL;
+#if defined(TARGET_SDL2)
+  SDL_SetWindowTitle(sdl_window, program.window_title);
+#else
+  SDL_WM_SetCaption(program.window_title, program.window_title);
+#endif
+}
+
+#if defined(TARGET_SDL2)
+void SDLSetWindowScaling(int window_scaling_percent)
+{
+  if (sdl_window == NULL)
+    return;
+
+  float window_scaling_factor = (float)window_scaling_percent / 100;
+  int new_window_width  = (int)(window_scaling_factor * video.screen_width);
+  int new_window_height = (int)(window_scaling_factor * video.screen_height);
+
+  SDL_SetWindowSize(sdl_window, new_window_width, new_window_height);
+
+  video.window_scaling_percent = window_scaling_percent;
+  video.window_width  = new_window_width;
+  video.window_height = new_window_height;
+
+  SetWindowTitle();
+}
+
+void SDLSetWindowScalingQuality(char *window_scaling_quality)
+{
+  SDL_Texture *new_texture;
+
+  if (sdl_texture_stream == NULL)
+    return;
+
+  SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, window_scaling_quality);
+
+  new_texture = SDL_CreateTexture(sdl_renderer,
+				  SDL_PIXELFORMAT_ARGB8888,
+				  SDL_TEXTUREACCESS_STREAMING,
+				  video.width, video.height);
+
+  if (new_texture != NULL)
+  {
+    SDL_DestroyTexture(sdl_texture_stream);
+
+    sdl_texture_stream = new_texture;
+  }
+
+  if (SDL_RenderTargetSupported(sdl_renderer))
+    new_texture = SDL_CreateTexture(sdl_renderer,
+				    SDL_PIXELFORMAT_ARGB8888,
+				    SDL_TEXTUREACCESS_TARGET,
+				    video.width, video.height);
+  else
+    new_texture = NULL;
 
-  if (*backbuffer == NULL)
-    *backbuffer = CreateBitmapStruct();
+  if (new_texture != NULL)
+  {
+    SDL_DestroyTexture(sdl_texture_target);
 
-  /* (real bitmap might be larger in fullscreen mode with video offsets) */
-  (*backbuffer)->width  = video.width;
-  (*backbuffer)->height = video.height;
+    sdl_texture_target = new_texture;
+  }
 
-  if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
-  {
-    setFullscreenParameters(setup.fullscreen_mode);
+  SDLRedrawWindow();
 
-    video_xoffset = fullscreen_xoffset;
-    video_yoffset = fullscreen_yoffset;
+  video.window_scaling_quality = window_scaling_quality;
+}
 
-    /* switch display to fullscreen mode, if available */
-    if ((new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height,
-					video.depth, surface_flags_fullscreen))
-	== NULL)
-    {
-      /* switching display to fullscreen mode failed */
-      Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
+void SDLSetWindowFullscreen(boolean fullscreen)
+{
+  if (sdl_window == NULL)
+    return;
 
-      /* do not try it again */
-      video.fullscreen_available = FALSE;
+  int flags = (fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
 
-      success = FALSE;
-    }
-    else
-    {
-      (*backbuffer)->surface = new_surface;
+  if (SDL_SetWindowFullscreen(sdl_window, flags) == 0)
+    video.fullscreen_enabled = fullscreen_enabled = fullscreen;
 
-      video.fullscreen_enabled = TRUE;
-      video.fullscreen_mode_current = setup.fullscreen_mode;
+  // if screen size was changed in fullscreen mode, correct desktop window size
+  if (!fullscreen && video.fullscreen_initial)
+  {
+    SDLSetWindowScaling(setup.window_scaling_percent);
+    SDL_SetWindowPosition(sdl_window,
+			  SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
 
-      success = TRUE;
-    }
+    video.fullscreen_initial = FALSE;
   }
+}
 
-  if ((!fullscreen && video.fullscreen_enabled) || new_surface == NULL)
-  {
-    video_xoffset = 0;
-    video_yoffset = 0;
+void SDLSetDisplaySize()
+{
+  SDL_Rect display_bounds;
 
-    /* switch display to window mode */
-    if ((new_surface = SDL_SetVideoMode(video.width, video.height,
-					video.depth, surface_flags_window))
-	== NULL)
-    {
-      /* switching display to window mode failed -- should not happen */
-      Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
+  SDL_GetDisplayBounds(0, &display_bounds);
 
-      success = FALSE;
-    }
-    else
-    {
-      (*backbuffer)->surface = new_surface;
+  video.display_width  = display_bounds.w;
+  video.display_height = display_bounds.h;
 
-      video.fullscreen_enabled = FALSE;
+#if 0
+  Error(ERR_DEBUG, "SDL real screen size: %d x %d",
+	video.display_width, video.display_height);
+#endif
+}
 
-      success = TRUE;
-    }
-  }
+void SDLSetScreenSizeAndOffsets(int width, int height)
+{
+  // set default video screen size and offsets
+  video.screen_width = width;
+  video.screen_height = height;
+  video.screen_xoffset = 0;
+  video.screen_yoffset = 0;
 
-#if 1
-  SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
+#if defined(USE_COMPLETE_DISPLAY)
+  float ratio_video   = (float) width / height;
+  float ratio_display = (float) video.display_width / video.display_height;
 
-#if defined(PLATFORM_WIN32)
+  if (ratio_video != ratio_display)
   {
-    SDL_SysWMinfo wminfo;
-    HWND hwnd;
+    // adjust drawable screen size to cover the whole device display
 
-    SDL_VERSION(&wminfo.version);
-    SDL_GetWMInfo(&wminfo);
+    if (ratio_video < ratio_display)
+      video.screen_width  *= ratio_display / ratio_video;
+    else
+      video.screen_height *= ratio_video / ratio_display;
 
-    hwnd = wminfo.window;
+    video.screen_xoffset = (video.screen_width  - width)  / 2;
+    video.screen_yoffset = (video.screen_height - height) / 2;
 
-    DragAcceptFiles(hwnd, TRUE);
+#if 0
+    Error(ERR_DEBUG, "Changing screen from %dx%d to %dx%d (%.2f to %.2f)",
+	  width, height,
+	  video.screen_width, video.screen_height,
+	  ratio_video, ratio_display);
+#endif
   }
 #endif
+}
+
+void SDLSetScreenSizeForRenderer(int width, int height)
+{
+  SDL_RenderSetLogicalSize(sdl_renderer, width, height);
+}
+
+void SDLSetScreenProperties()
+{
+  SDLSetScreenSizeAndOffsets(video.width, video.height);
+  SDLSetScreenSizeForRenderer(video.screen_width, video.screen_height);
+}
+
 #endif
 
+void SDLSetScreenRenderingMode(char *screen_rendering_mode)
+{
+#if defined(TARGET_SDL2)
+  video.screen_rendering_mode =
+    (strEqual(screen_rendering_mode, STR_SPECIAL_RENDERING_BITMAP) ?
+     SPECIAL_RENDERING_BITMAP :
+     strEqual(screen_rendering_mode, STR_SPECIAL_RENDERING_TARGET) ?
+     SPECIAL_RENDERING_TARGET:
+     strEqual(screen_rendering_mode, STR_SPECIAL_RENDERING_DOUBLE) ?
+     SPECIAL_RENDERING_DOUBLE : SPECIAL_RENDERING_OFF);
+#else
+  video.screen_rendering_mode = SPECIAL_RENDERING_BITMAP;
+#endif
+}
 
-  return success;
+void SDLRedrawWindow()
+{
+  UpdateScreen_WithoutFrameDelay(NULL);
 }
 
-void SDLCreateBitmapContent(Bitmap *new_bitmap, int width, int height,
+void SDLCreateBitmapContent(Bitmap *bitmap, int width, int height,
 			    int depth)
 {
-  SDL_Surface *surface_tmp, *surface_native;
+  SDL_Surface *surface =
+    SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth, 0,0,0, 0);
 
-  if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth,
-					  0, 0, 0, 0))
-      == NULL)
+  if (surface == NULL)
     Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
 
-  if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
-    Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
-
-  SDL_FreeSurface(surface_tmp);
+  SDLSetNativeSurface(&surface);
 
-  new_bitmap->surface = surface_native;
+  bitmap->surface = surface;
 }
 
 void SDLFreeBitmapPointers(Bitmap *bitmap)
@@ -358,8 +1000,19 @@ void SDLFreeBitmapPointers(Bitmap *bitmap)
     SDL_FreeSurface(bitmap->surface);
   if (bitmap->surface_masked)
     SDL_FreeSurface(bitmap->surface_masked);
+
   bitmap->surface = NULL;
   bitmap->surface_masked = NULL;
+
+#if defined(TARGET_SDL2)
+  if (bitmap->texture)
+    SDL_DestroyTexture(bitmap->texture);
+  if (bitmap->texture_masked)
+    SDL_DestroyTexture(bitmap->texture_masked);
+
+  bitmap->texture = NULL;
+  bitmap->texture_masked = NULL;
+#endif
 }
 
 void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
@@ -369,35 +1022,53 @@ void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
   Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
   SDL_Rect src_rect, dst_rect;
 
-  if (src_bitmap == backbuffer)
-  {
-    src_x += video_xoffset;
-    src_y += video_yoffset;
-  }
-
   src_rect.x = src_x;
   src_rect.y = src_y;
   src_rect.w = width;
   src_rect.h = height;
 
-  if (dst_bitmap == backbuffer || dst_bitmap == window)
-  {
-    dst_x += video_xoffset;
-    dst_y += video_yoffset;
-  }
-
   dst_rect.x = dst_x;
   dst_rect.y = dst_y;
   dst_rect.w = width;
   dst_rect.h = height;
 
-  if (src_bitmap != backbuffer || dst_bitmap != window)
+  // if (src_bitmap != backbuffer || dst_bitmap != window)
+  if (!(src_bitmap == backbuffer && dst_bitmap == window))
     SDL_BlitSurface((mask_mode == BLIT_MASKED ?
 		     src_bitmap->surface_masked : src_bitmap->surface),
 		    &src_rect, real_dst_bitmap->surface, &dst_rect);
 
   if (dst_bitmap == window)
-    SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
+    UpdateScreen_WithFrameDelay(&dst_rect);
+}
+
+void SDLBlitTexture(Bitmap *bitmap,
+		    int src_x, int src_y, int width, int height,
+		    int dst_x, int dst_y, int mask_mode)
+{
+#if defined(TARGET_SDL2)
+  SDL_Texture *texture;
+  SDL_Rect src_rect;
+  SDL_Rect dst_rect;
+
+  texture =
+    (mask_mode == BLIT_MASKED ? bitmap->texture_masked : bitmap->texture);
+
+  if (texture == NULL)
+    return;
+
+  src_rect.x = src_x;
+  src_rect.y = src_y;
+  src_rect.w = width;
+  src_rect.h = height;
+
+  dst_rect.x = dst_x;
+  dst_rect.y = dst_y;
+  dst_rect.w = width;
+  dst_rect.h = height;
+
+  SDL_RenderCopy(sdl_renderer, texture, &src_rect, &dst_rect);
+#endif
 }
 
 void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height,
@@ -406,12 +1077,6 @@ void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height,
   Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
   SDL_Rect rect;
 
-  if (dst_bitmap == backbuffer || dst_bitmap == window)
-  {
-    x += video_xoffset;
-    y += video_yoffset;
-  }
-
   rect.x = x;
   rect.y = y;
   rect.w = width;
@@ -420,115 +1085,76 @@ void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height,
   SDL_FillRect(real_dst_bitmap->surface, &rect, color);
 
   if (dst_bitmap == window)
-    SDL_UpdateRect(backbuffer->surface, x, y, width, height);
+    UpdateScreen_WithFrameDelay(&rect);
+}
+
+void PrepareFadeBitmap(int draw_target)
+{
+  Bitmap *fade_bitmap =
+    (draw_target == DRAW_TO_FADE_SOURCE ? gfx.fade_bitmap_source :
+     draw_target == DRAW_TO_FADE_TARGET ? gfx.fade_bitmap_target : NULL);
+
+  if (fade_bitmap == NULL)
+    return;
+
+  // copy backbuffer to fading buffer
+  BlitBitmap(backbuffer, fade_bitmap, 0, 0, gfx.win_xsize, gfx.win_ysize, 0, 0);
+
+  // add border and animations to fading buffer
+  FinalizeScreen(draw_target);
 }
 
-void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
+void SDLFadeRectangle(int x, int y, int width, int height,
 		      int fade_mode, int fade_delay, int post_delay,
 		      void (*draw_border_function)(void))
 {
-  static boolean initialization_needed = TRUE;
-  static SDL_Surface *surface_source = NULL;
-  static SDL_Surface *surface_target = NULL;
-  static SDL_Surface *surface_black = NULL;
+  SDL_Surface *surface_backup = gfx.fade_bitmap_backup->surface;
+  SDL_Surface *surface_source = gfx.fade_bitmap_source->surface;
+  SDL_Surface *surface_target = gfx.fade_bitmap_target->surface;
+  SDL_Surface *surface_black  = gfx.fade_bitmap_black->surface;
   SDL_Surface *surface_screen = backbuffer->surface;
-  SDL_Surface *surface_cross = (bitmap_cross ? bitmap_cross->surface : NULL);
   SDL_Rect src_rect, dst_rect;
+  SDL_Rect dst_rect2;
   int src_x = x, src_y = y;
   int dst_x = x, dst_y = y;
   unsigned int time_last, time_current;
 
-  /* check if screen size has changed */
-  if (surface_source != NULL && (video.width  != surface_source->w ||
-				 video.height != surface_source->h))
-  {
-    SDL_FreeSurface(surface_source);
-    SDL_FreeSurface(surface_target);
-    SDL_FreeSurface(surface_black);
+  // store function for drawing global masked border
+  void (*draw_global_border_function)(int) = gfx.draw_global_border_function;
 
-    initialization_needed = TRUE;
-  }
+  // deactivate drawing of global border while fading, if needed
+  if (draw_border_function == NULL)
+    gfx.draw_global_border_function = NULL;
 
   src_rect.x = src_x;
   src_rect.y = src_y;
   src_rect.w = width;
   src_rect.h = height;
 
-  dst_x += video_xoffset;
-  dst_y += video_yoffset;
-
   dst_rect.x = dst_x;
   dst_rect.y = dst_y;
   dst_rect.w = width;		/* (ignored) */
   dst_rect.h = height;		/* (ignored) */
 
-  if (initialization_needed)
-  {
-    unsigned int flags = SDL_SRCALPHA;
+  dst_rect2 = dst_rect;
 
-    /* use same surface type as screen surface */
-    if ((surface_screen->flags & SDL_HWSURFACE))
-      flags |= SDL_HWSURFACE;
-    else
-      flags |= SDL_SWSURFACE;
-
-    /* create surface for temporary copy of screen buffer (source) */
-    if ((surface_source =
-	 SDL_CreateRGBSurface(flags,
-			      video.width,
-			      video.height,
-			      surface_screen->format->BitsPerPixel,
-			      surface_screen->format->Rmask,
-			      surface_screen->format->Gmask,
-			      surface_screen->format->Bmask,
-			      surface_screen->format->Amask)) == NULL)
-      Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
-
-    /* create surface for cross-fading screen buffer (target) */
-    if ((surface_target =
-	 SDL_CreateRGBSurface(flags,
-			      video.width,
-			      video.height,
-			      surface_screen->format->BitsPerPixel,
-			      surface_screen->format->Rmask,
-			      surface_screen->format->Gmask,
-			      surface_screen->format->Bmask,
-			      surface_screen->format->Amask)) == NULL)
-      Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
-
-    /* create black surface for fading from/to black */
-    if ((surface_black =
-	 SDL_CreateRGBSurface(flags,
-			      video.width,
-			      video.height,
-			      surface_screen->format->BitsPerPixel,
-			      surface_screen->format->Rmask,
-			      surface_screen->format->Gmask,
-			      surface_screen->format->Bmask,
-			      surface_screen->format->Amask)) == NULL)
-      Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
-
-    /* completely fill the surface with black color pixels */
-    SDL_FillRect(surface_black, NULL,
-		 SDL_MapRGB(surface_screen->format, 0, 0, 0));
-
-    initialization_needed = FALSE;
-  }
+  // before fading in, store backbuffer (without animation graphics)
+  if (fade_mode & (FADE_TYPE_FADE_IN | FADE_TYPE_TRANSFORM))
+    SDL_BlitSurface(surface_screen, &dst_rect, surface_backup, &src_rect);
 
   /* copy source and target surfaces to temporary surfaces for fading */
   if (fade_mode & FADE_TYPE_TRANSFORM)
   {
-    SDL_BlitSurface(surface_cross,  &src_rect, surface_source, &src_rect);
-    SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
+    // (source and target fading buffer already prepared)
   }
   else if (fade_mode & FADE_TYPE_FADE_IN)
   {
+    // (target fading buffer already prepared)
     SDL_BlitSurface(surface_black,  &src_rect, surface_source, &src_rect);
-    SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
   }
   else		/* FADE_TYPE_FADE_OUT */
   {
-    SDL_BlitSurface(surface_screen, &dst_rect, surface_source, &src_rect);
+    // (source fading buffer already prepared)
     SDL_BlitSurface(surface_black,  &src_rect, surface_target, &src_rect);
   }
 
@@ -546,7 +1172,8 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
     int i;
 
     SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
-    SDL_SetAlpha(surface_target, 0, 0);		/* disable alpha blending */
+
+    SDLSetAlpha(surface_target, FALSE, 0);	/* disable alpha blending */
 
     ypos[0] = -GetSimpleRandom(16);
 
@@ -648,11 +1275,66 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
 	if (draw_border_function != NULL)
 	  draw_border_function();
 
-	SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
+	UpdateScreen_WithFrameDelay(&dst_rect2);
       }
     }
   }
-  else
+  else if (fade_mode == FADE_MODE_CURTAIN)
+  {
+    float xx;
+    int xx_final;
+    int xx_size = width / 2;
+
+    SDL_BlitSurface(surface_target, &src_rect, surface_screen, &dst_rect);
+
+    SDLSetAlpha(surface_source, FALSE, 0);	/* disable alpha blending */
+
+    for (xx = 0; xx < xx_size;)
+    {
+      time_last = time_current;
+      time_current = SDL_GetTicks();
+      xx += xx_size * ((float)(time_current - time_last) / fade_delay);
+      xx_final = MIN(MAX(0, xx), xx_size);
+
+      src_rect.x = src_x;
+      src_rect.y = src_y;
+      src_rect.w = width;
+      src_rect.h = height;
+
+      dst_rect.x = dst_x;
+      dst_rect.y = dst_y;
+
+      /* draw new (target) image to screen buffer */
+      SDL_BlitSurface(surface_target, &src_rect, surface_screen, &dst_rect);
+
+      if (xx_final < xx_size)
+      {
+	src_rect.w = xx_size - xx_final;
+	src_rect.h = height;
+
+	/* draw old (source) image to screen buffer (left side) */
+
+	src_rect.x = src_x + xx_final;
+	dst_rect.x = dst_x;
+
+	SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
+
+	/* draw old (source) image to screen buffer (right side) */
+
+	src_rect.x = src_x + xx_size;
+	dst_rect.x = dst_x + xx_size + xx_final;
+
+	SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
+      }
+
+      if (draw_border_function != NULL)
+	draw_border_function();
+
+      /* only update the region of the screen that is affected from fading */
+      UpdateScreen_WithFrameDelay(&dst_rect2);
+    }
+  }
+  else		/* fading in, fading out or cross-fading */
   {
     float alpha;
     int alpha_final;
@@ -668,22 +1350,39 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
       SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
 
       /* draw new (target) image to screen buffer using alpha blending */
-      SDL_SetAlpha(surface_target, SDL_SRCALPHA, alpha_final);
+      SDLSetAlpha(surface_target, TRUE, alpha_final);
       SDL_BlitSurface(surface_target, &src_rect, surface_screen, &dst_rect);
 
       if (draw_border_function != NULL)
 	draw_border_function();
 
-#if 1
       /* only update the region of the screen that is affected from fading */
-      SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
-#else
-      SDL_Flip(surface_screen);
-#endif
+      UpdateScreen_WithFrameDelay(&dst_rect);
+    }
+  }
+
+  if (post_delay > 0)
+  {
+    unsigned int time_post_delay;
+
+    time_current = SDL_GetTicks();
+    time_post_delay = time_current + post_delay;
+
+    while (time_current < time_post_delay)
+    {
+      // updating the screen contains waiting for frame delay (non-busy)
+      UpdateScreen_WithFrameDelay(NULL);
+
+      time_current = SDL_GetTicks();
     }
   }
 
-  Delay(post_delay);
+  // restore function for drawing global masked border
+  gfx.draw_global_border_function = draw_global_border_function;
+
+  // after fading in, restore backbuffer (without animation graphics)
+  if (fade_mode & (FADE_TYPE_FADE_IN | FADE_TYPE_TRANSFORM))
+    SDL_BlitSurface(surface_backup, &dst_rect, surface_screen, &src_rect);
 }
 
 void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
@@ -703,30 +1402,16 @@ void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
   rect.w = (to_x - from_x + 1);
   rect.h = (to_y - from_y + 1);
 
-  if (dst_bitmap == backbuffer || dst_bitmap == window)
-  {
-    rect.x += video_xoffset;
-    rect.y += video_yoffset;
-  }
-
   SDL_FillRect(surface, &rect, color);
 }
 
 void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
 		 int to_x, int to_y, Uint32 color)
 {
-  if (dst_bitmap == backbuffer || dst_bitmap == window)
-  {
-    from_x += video_xoffset;
-    from_y += video_yoffset;
-    to_x += video_xoffset;
-    to_y += video_yoffset;
-  }
-
   sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
 }
 
-#if 0
+#if ENABLE_UNUSED_CODE
 void SDLDrawLines(SDL_Surface *surface, struct XY *points,
 		  int num_points, Uint32 color)
 {
@@ -760,12 +1445,6 @@ Pixel SDLGetPixel(Bitmap *src_bitmap, int x, int y)
 {
   SDL_Surface *surface = src_bitmap->surface;
 
-  if (src_bitmap == backbuffer || src_bitmap == window)
-  {
-    x += video_xoffset;
-    y += video_yoffset;
-  }
-
   switch (surface->format->BytesPerPixel)
   {
     case 1:		/* assuming 8-bpp */
@@ -811,7 +1490,7 @@ Pixel SDLGetPixel(Bitmap *src_bitmap, int x, int y)
 
 /* ========================================================================= */
 /* The following functions were taken from the SGE library                   */
-/* (SDL Graphics Extension Library) by Anders Lindstr�m                      */
+/* (SDL Graphics Extension Library) by Anders Lindström                      */
 /* http://www.etek.chalmers.se/~e8cal1/sge/index.html                        */
 /* ========================================================================= */
 
@@ -1257,12 +1936,6 @@ void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
 
 void SDLPutPixel(Bitmap *dst_bitmap, int x, int y, Pixel pixel)
 {
-  if (dst_bitmap == backbuffer || dst_bitmap == window)
-  {
-    x += video_xoffset;
-    y += video_yoffset;
-  }
-
   sge_PutPixel(dst_bitmap->surface, x, y, pixel);
 }
 
@@ -1334,12 +2007,11 @@ int zoomSurfaceRGBA_scaleDownBy2(SDL_Surface *src, SDL_Surface *dst)
 {
   int x, y;
   tColorRGBA *sp, *csp, *dp;
-  int sgap, dgap;
+  int dgap;
 
   /* pointer setup */
   sp = csp = (tColorRGBA *) src->pixels;
   dp = (tColorRGBA *) dst->pixels;
-  sgap = src->pitch - src->w * 4;
   dgap = dst->pitch - dst->w * 4;
 
   for (y = 0; y < dst->h; y++)
@@ -1384,9 +2056,10 @@ int zoomSurfaceRGBA_scaleDownBy2(SDL_Surface *src, SDL_Surface *dst)
 
 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
 {
-  int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
-  tColorRGBA *sp, *csp, *dp;
-  int sgap, dgap;
+  int x, y, *sax, *say, *csax, *csay;
+  float sx, sy;
+  tColorRGBA *sp, *csp, *csp0, *dp;
+  int dgap;
 
   /* use specialized zoom function when scaling down to exactly half size */
   if (src->w == 2 * dst->w &&
@@ -1394,38 +2067,23 @@ int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
     return zoomSurfaceRGBA_scaleDownBy2(src, dst);
 
   /* variable setup */
-  sx = (int) (65536.0 * (float) src->w / (float) dst->w);
-  sy = (int) (65536.0 * (float) src->h / (float) dst->h);
+  sx = (float) src->w / (float) dst->w;
+  sy = (float) src->h / (float) dst->h;
 
   /* allocate memory for row increments */
-  sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
-  say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
+  csax = sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
+  csay = say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
 
   /* precalculate row increments */
-  csx = 0;
-  csax = sax;
   for (x = 0; x <= dst->w; x++)
-  {
-    *csax = csx;
-    csax++;
-    csx &= 0xffff;
-    csx += sx;
-  }
+    *csax++ = (int)(sx * x);
 
-  csy = 0;
-  csay = say;
   for (y = 0; y <= dst->h; y++)
-  {
-    *csay = csy;
-    csay++;
-    csy &= 0xffff;
-    csy += sy;
-  }
+    *csay++ = (int)(sy * y);
 
   /* pointer setup */
-  sp = csp = (tColorRGBA *) src->pixels;
+  sp = csp = csp0 = (tColorRGBA *) src->pixels;
   dp = (tColorRGBA *) dst->pixels;
-  sgap = src->pitch - src->w * 4;
   dgap = dst->pitch - dst->w * 4;
 
   csay = say;
@@ -1441,7 +2099,7 @@ int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
 
       /* advance source pointers */
       csax++;
-      sp += (*csax >> 16);
+      sp = csp + *csax;
 
       /* advance destination pointer */
       dp++;
@@ -1449,7 +2107,7 @@ int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
 
     /* advance source pointer */
     csay++;
-    csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
+    csp = (tColorRGBA *) ((Uint8 *) csp0 + *csay * src->pitch);
 
     /* advance destination pointers */
     dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
@@ -1591,8 +2249,9 @@ SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
   else
   {
     /* new source surface is 32 bit with a defined RGB ordering */
-    zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
-				    0x000000ff, 0x0000ff00, 0x00ff0000, 0);
+    zoom_src = SDL_CreateRGBSurface(SURFACE_FLAGS, src->w, src->h, 32,
+				    0x000000ff, 0x0000ff00, 0x00ff0000,
+				    (src->format->Amask ? 0xff000000 : 0));
     SDL_BlitSurface(src, NULL, zoom_src, NULL);
     is_32bit = TRUE;
     is_converted = TRUE;
@@ -1602,15 +2261,16 @@ SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
   if (is_32bit)
   {
     /* target surface is 32 bit with source RGBA/ABGR ordering */
-    zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
+    zoom_dst = SDL_CreateRGBSurface(SURFACE_FLAGS, dst_width, dst_height, 32,
 				    zoom_src->format->Rmask,
 				    zoom_src->format->Gmask,
-				    zoom_src->format->Bmask, 0);
+				    zoom_src->format->Bmask,
+				    zoom_src->format->Amask);
   }
   else
   {
     /* target surface is 8 bit */
-    zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
+    zoom_dst = SDL_CreateRGBSurface(SURFACE_FLAGS, dst_width, dst_height, 8,
 				    0, 0, 0, 0);
   }
 
@@ -1646,23 +2306,55 @@ SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
   return zoom_dst;
 }
 
-void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
+static SDL_Surface *SDLGetOpaqueSurface(SDL_Surface *surface)
+{
+  SDL_Surface *new_surface;
+
+  if (surface == NULL)
+    return NULL;
+
+  if ((new_surface = SDLGetNativeSurface(surface)) == NULL)
+    Error(ERR_EXIT, "SDLGetNativeSurface() failed");
+
+  /* remove alpha channel from native non-transparent surface, if defined */
+  SDLSetAlpha(new_surface, FALSE, 0);
+
+  /* remove transparent color from native non-transparent surface, if defined */
+  SDL_SetColorKey(new_surface, UNSET_TRANSPARENT_PIXEL, 0);
+
+  return new_surface;
+}
+
+Bitmap *SDLZoomBitmap(Bitmap *src_bitmap, int dst_width, int dst_height)
 {
-  SDL_Surface *sdl_surface_tmp;
-  int dst_width = dst_bitmap->width;
-  int dst_height = dst_bitmap->height;
+  Bitmap *dst_bitmap = CreateBitmapStruct();
+  SDL_Surface *src_surface = src_bitmap->surface_masked;
+  SDL_Surface *dst_surface;
 
-  /* throw away old destination surface */
-  SDL_FreeSurface(dst_bitmap->surface);
+  dst_width  = MAX(1, dst_width);	/* prevent zero bitmap width */
+  dst_height = MAX(1, dst_height);	/* prevent zero bitmap height */
+
+  dst_bitmap->width  = dst_width;
+  dst_bitmap->height = dst_height;
 
   /* create zoomed temporary surface from source surface */
-  sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
+  dst_surface = zoomSurface(src_surface, dst_width, dst_height);
 
   /* create native format destination surface from zoomed temporary surface */
-  dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
+  SDLSetNativeSurface(&dst_surface);
 
-  /* free temporary surface */
-  SDL_FreeSurface(sdl_surface_tmp);
+  /* set color key for zoomed surface from source surface, if defined */
+  if (SDLHasColorKey(src_surface))
+    SDL_SetColorKey(dst_surface, SET_TRANSPARENT_PIXEL,
+		    SDLGetColorKey(src_surface));
+
+  /* create native non-transparent surface for opaque blitting */
+  dst_bitmap->surface = SDLGetOpaqueSurface(dst_surface);
+
+  /* set native transparent surface for masked blitting */
+  dst_bitmap->surface_masked = dst_surface;
+
+  return dst_bitmap;
 }
 
 
@@ -1675,35 +2367,37 @@ Bitmap *SDLLoadImage(char *filename)
   Bitmap *new_bitmap = CreateBitmapStruct();
   SDL_Surface *sdl_image_tmp;
 
+  print_timestamp_init("SDLLoadImage");
+
+  print_timestamp_time(getBaseNamePtr(filename));
+
   /* load image to temporary surface */
   if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
-  {
-    SetError("IMG_Load(): %s", SDL_GetError());
+    Error(ERR_EXIT, "IMG_Load() failed: %s", SDL_GetError());
 
-    return NULL;
-  }
+  print_timestamp_time("IMG_Load");
 
   UPDATE_BUSY_STATE();
 
   /* create native non-transparent surface for current image */
-  if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
-  {
-    SetError("SDL_DisplayFormat(): %s", SDL_GetError());
+  if ((new_bitmap->surface = SDLGetOpaqueSurface(sdl_image_tmp)) == NULL)
+    Error(ERR_EXIT, "SDLGetOpaqueSurface() failed");
 
-    return NULL;
-  }
+  print_timestamp_time("SDLGetNativeSurface (opaque)");
 
   UPDATE_BUSY_STATE();
 
+  /* set black pixel to transparent if no alpha channel / transparent color */
+  if (!SDLHasAlpha(sdl_image_tmp) &&
+      !SDLHasColorKey(sdl_image_tmp))
+    SDL_SetColorKey(sdl_image_tmp, SET_TRANSPARENT_PIXEL,
+		    SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
+
   /* create native transparent surface for current image */
-  SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
-		  SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
-  if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
-  {
-    SetError("SDL_DisplayFormat(): %s", SDL_GetError());
+  if ((new_bitmap->surface_masked = SDLGetNativeSurface(sdl_image_tmp)) == NULL)
+    Error(ERR_EXIT, "SDLGetNativeSurface() failed");
 
-    return NULL;
-  }
+  print_timestamp_time("SDLGetNativeSurface (masked)");
 
   UPDATE_BUSY_STATE();
 
@@ -1713,6 +2407,8 @@ Bitmap *SDLLoadImage(char *filename)
   new_bitmap->width = new_bitmap->surface->w;
   new_bitmap->height = new_bitmap->surface->h;
 
+  print_timestamp_done("SDLLoadImage");
+
   return new_bitmap;
 }
 
@@ -1760,8 +2456,10 @@ void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info)
 
 void SDLOpenAudio(void)
 {
+#if !defined(TARGET_SDL2)
   if (!strEqual(setup.system.sdl_audiodriver, ARG_DEFAULT))
     SDL_putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
+#endif
 
   if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
   {
@@ -1807,41 +2505,28 @@ void SDLCloseAudio(void)
 void SDLNextEvent(Event *event)
 {
   SDL_WaitEvent(event);
-
-  if (event->type == EVENT_BUTTONPRESS ||
-      event->type == EVENT_BUTTONRELEASE)
-  {
-    if (((ButtonEvent *)event)->x > video_xoffset)
-      ((ButtonEvent *)event)->x -= video_xoffset;
-    else
-      ((ButtonEvent *)event)->x = 0;
-    if (((ButtonEvent *)event)->y > video_yoffset)
-      ((ButtonEvent *)event)->y -= video_yoffset;
-    else
-      ((ButtonEvent *)event)->y = 0;
-  }
-  else if (event->type == EVENT_MOTIONNOTIFY)
-  {
-    if (((MotionEvent *)event)->x > video_xoffset)
-      ((MotionEvent *)event)->x -= video_xoffset;
-    else
-      ((MotionEvent *)event)->x = 0;
-    if (((MotionEvent *)event)->y > video_yoffset)
-      ((MotionEvent *)event)->y -= video_yoffset;
-    else
-      ((MotionEvent *)event)->y = 0;
-  }
 }
 
 void SDLHandleWindowManagerEvent(Event *event)
 {
+#ifdef DEBUG
 #if defined(PLATFORM_WIN32)
+  // experimental drag and drop code
+
   SDL_SysWMEvent *syswmevent = (SDL_SysWMEvent *)event;
   SDL_SysWMmsg *syswmmsg = (SDL_SysWMmsg *)(syswmevent->msg);
 
+#if defined(TARGET_SDL2)
+  if (syswmmsg->msg.win.msg == WM_DROPFILES)
+#else
   if (syswmmsg->msg == WM_DROPFILES)
+#endif
   {
+#if defined(TARGET_SDL2)
+    HDROP hdrop = (HDROP)syswmmsg->msg.win.wParam;
+#else
     HDROP hdrop = (HDROP)syswmmsg->wParam;
+#endif
     int i, num_files;
 
     printf("::: SDL_SYSWMEVENT:\n");
@@ -1858,9 +2543,14 @@ void SDLHandleWindowManagerEvent(Event *event)
       printf("::: - '%s'\n", buffer);
     }
 
+#if defined(TARGET_SDL2)
+    DragFinish((HDROP)syswmmsg->msg.win.wParam);
+#else
     DragFinish((HDROP)syswmmsg->wParam);
+#endif
   }
 #endif
+#endif
 }
 
 
@@ -1886,6 +2576,8 @@ static void SDLCloseJoystick(int nr)
     return;
 
   SDL_JoystickClose(sdl_joystick[nr]);
+
+  sdl_joystick[nr] = NULL;
 }
 
 static boolean SDLCheckJoystickOpened(int nr)
@@ -1893,7 +2585,11 @@ static boolean SDLCheckJoystickOpened(int nr)
   if (nr < 0 || nr > MAX_PLAYERS)
     return FALSE;
 
+#if defined(TARGET_SDL2)
+  return (sdl_joystick[nr] != NULL ? TRUE : FALSE);
+#else
   return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
+#endif
 }
 
 void HandleJoystickEvent(Event *event)
@@ -1930,7 +2626,7 @@ void SDLInitJoysticks()
   {
     sdl_joystick_subsystem_initialized = TRUE;
 
-    if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
+    if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
     {
       Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
       return;
@@ -1994,4 +2690,97 @@ boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
   return TRUE;
 }
 
-#endif /* TARGET_SDL */
+#if defined(USE_TOUCH_INPUT_OVERLAY)
+static void DrawTouchInputOverlay()
+{
+  static SDL_Texture *texture = NULL;
+  static boolean initialized = FALSE;
+  static boolean deactivated = TRUE;
+  static int width = 0, height = 0;
+  static int alpha_max = SDL_ALPHA_OPAQUE / 2;
+  static int alpha_step = 5;
+  static int alpha_last = 0;
+  static int alpha = 0;
+
+  if (!overlay.active && deactivated)
+    return;
+
+  if (overlay.active)
+  {
+    if (alpha < alpha_max)
+      alpha = MIN(alpha + alpha_step, alpha_max);
+
+    deactivated = FALSE;
+  }
+  else
+  {
+    alpha = MAX(0, alpha - alpha_step);
+
+    if (alpha == 0)
+      deactivated = TRUE;
+  }
+
+  if (!initialized)
+  {
+    char *basename = "overlay/VirtualButtons.png";
+    char *filename = getCustomImageFilename(basename);
+
+    if (filename == NULL)
+      Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
+
+    SDL_Surface *surface;
+
+    if ((surface = IMG_Load(filename)) == NULL)
+      Error(ERR_EXIT, "IMG_Load() failed: %s", SDL_GetError());
+
+    width  = surface->w;
+    height = surface->h;
+
+    /* set black pixel to transparent if no alpha channel / transparent color */
+    if (!SDLHasAlpha(surface) &&
+	!SDLHasColorKey(surface))
+      SDL_SetColorKey(surface, SET_TRANSPARENT_PIXEL,
+		      SDL_MapRGB(surface->format, 0x00, 0x00, 0x00));
+
+    if ((texture = SDLCreateTextureFromSurface(surface)) == NULL)
+      Error(ERR_EXIT, "SDLCreateTextureFromSurface() failed");
+
+    SDL_FreeSurface(surface);
+
+    SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
+    SDL_SetTextureAlphaMod(texture, alpha_max);
+
+    initialized = TRUE;
+  }
+
+  if (alpha != alpha_last)
+    SDL_SetTextureAlphaMod(texture, alpha);
+
+  alpha_last = alpha;
+
+  float ratio_overlay = (float) width / height;
+  float ratio_screen = (float) video.screen_width / video.screen_height;
+  int width_scaled, height_scaled;
+  int xpos, ypos;
+
+  if (ratio_overlay > ratio_screen)
+  {
+    width_scaled = video.screen_width;
+    height_scaled = video.screen_height * ratio_screen / ratio_overlay;
+    xpos = 0;
+    ypos = video.screen_height - height_scaled;
+  }
+  else
+  {
+    width_scaled = video.screen_width * ratio_overlay / ratio_screen;
+    height_scaled = video.screen_height;
+    xpos = (video.screen_width - width_scaled) / 2;
+    ypos = 0;
+  }
+
+  SDL_Rect src_rect = { 0, 0, width, height };
+  SDL_Rect dst_rect = { xpos, ypos, width_scaled, height_scaled };
+
+  SDL_RenderCopy(sdl_renderer, texture, &src_rect, &dst_rect);
+}
+#endif
diff --git a/src/libgame/sdl.h b/src/libgame/sdl.h
index 62196e1..c88b6a8 100644
--- a/src/libgame/sdl.h
+++ b/src/libgame/sdl.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* sdl.h                                                    *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// sdl.h
+// ============================================================================
 
 #ifndef SDL_H
 #define SDL_H
@@ -25,12 +23,38 @@
 
 /* definitions needed for "system.c" */
 
+#if defined(TARGET_SDL2)
+#define SURFACE_FLAGS		(0)
+#else
 #define SURFACE_FLAGS		(SDL_SWSURFACE)
+#endif
+
+#if defined(TARGET_SDL2)
+#define SET_TRANSPARENT_PIXEL	(SDL_TRUE)
+#define UNSET_TRANSPARENT_PIXEL	(SDL_FALSE)
+#else
+#define SET_TRANSPARENT_PIXEL	(SDL_SRCCOLORKEY)
+#define UNSET_TRANSPARENT_PIXEL	(0)
+#endif
 
 /* system dependent definitions */
 
+#if defined(TARGET_SDL2)
+#define TARGET_STRING		"SDL2"
+#else
 #define TARGET_STRING		"SDL"
+#endif
+
+#if defined(PLATFORM_ANDROID)
+#define WINDOW_SCALING_STATUS	WINDOW_SCALING_NOT_AVAILABLE
+#define FULLSCREEN_STATUS	FULLSCREEN_AVAILABLE
+#elif defined(TARGET_SDL2)
+#define WINDOW_SCALING_STATUS	WINDOW_SCALING_AVAILABLE
 #define FULLSCREEN_STATUS	FULLSCREEN_AVAILABLE
+#else	// SDL 1.2
+#define WINDOW_SCALING_STATUS	WINDOW_SCALING_NOT_AVAILABLE
+#define FULLSCREEN_STATUS	FULLSCREEN_AVAILABLE
+#endif
 
 #define CURSOR_MAX_WIDTH	32
 #define CURSOR_MAX_HEIGHT	32
@@ -44,23 +68,29 @@ typedef struct SDLSurfaceInfo	DrawWindow;
 typedef Uint32			Pixel;
 typedef SDL_Cursor	       *Cursor;
 
+#if defined(TARGET_SDL2)
+typedef SDL_Keycode		Key;
+typedef SDL_Keymod		KeyMod;
+#else
 typedef SDLKey			Key;
 typedef unsigned int		KeyMod;
+#endif
 
 typedef SDL_Event		Event;
 typedef SDL_MouseButtonEvent	ButtonEvent;
 typedef SDL_MouseMotionEvent	MotionEvent;
+#if defined(TARGET_SDL2)
+typedef SDL_MouseWheelEvent	WheelEvent;
+typedef SDL_TouchFingerEvent	FingerEvent;
+typedef SDL_TextInputEvent	TextEvent;
+typedef SDL_Event		PauseResumeEvent;
+typedef SDL_WindowEvent		WindowEvent;
+#endif
 typedef SDL_KeyboardEvent	KeyEvent;
 typedef SDL_Event		ExposeEvent;
 typedef SDL_Event		FocusChangeEvent;
 typedef SDL_Event		ClientMessageEvent;
 
-typedef int			GC;
-typedef int			Pixmap;
-typedef int			Display;
-typedef int			Visual;
-typedef int			Colormap;
-
 
 /* structure definitions */
 
@@ -71,8 +101,10 @@ struct SDLSurfaceInfo
   int width, height;
   SDL_Surface *surface;
   SDL_Surface *surface_masked;
-  GC gc;
-  GC stored_clip_gc;
+#if defined(TARGET_SDL2)
+  SDL_Texture *texture;
+  SDL_Texture *texture_masked;
+#endif
 };
 
 struct MouseCursorInfo
@@ -95,6 +127,13 @@ struct MouseCursorInfo
 #define EVENT_BUTTONPRESS	SDL_MOUSEBUTTONDOWN
 #define EVENT_BUTTONRELEASE	SDL_MOUSEBUTTONUP
 #define EVENT_MOTIONNOTIFY	SDL_MOUSEMOTION
+#if defined(TARGET_SDL2)
+#define	EVENT_WHEELMOTION	SDL_MOUSEWHEEL
+#define	EVENT_FINGERPRESS	SDL_FINGERDOWN
+#define EVENT_FINGERRELEASE	SDL_FINGERUP
+#define EVENT_FINGERMOTION	SDL_FINGERMOTION
+#define EVENT_TEXTINPUT		SDL_TEXTINPUT
+#endif
 #define EVENT_KEYPRESS		SDL_KEYDOWN
 #define EVENT_KEYRELEASE	SDL_KEYUP
 #define EVENT_EXPOSE		SDL_USEREVENT + 0
@@ -132,12 +171,21 @@ struct MouseCursorInfo
 #define KSYM_Shift_R		SDLK_RSHIFT
 #define KSYM_Control_L		SDLK_LCTRL
 #define KSYM_Control_R		SDLK_RCTRL
+
+#if defined(TARGET_SDL2)
+#define KSYM_Meta_L		SDLK_LGUI
+#define KSYM_Meta_R		SDLK_RGUI
+#else
 #define KSYM_Meta_L		SDLK_LMETA
 #define KSYM_Meta_R		SDLK_RMETA
+#endif
+
 #define KSYM_Alt_L		SDLK_LALT
 #define KSYM_Alt_R		SDLK_RALT
+#if !defined(TARGET_SDL2)
 #define KSYM_Super_L		SDLK_LSUPER
 #define KSYM_Super_R		SDLK_RSUPER
+#endif
 #define KSYM_Mode_switch	SDLK_MODE
 #define KSYM_Multi_key		SDLK_RCTRL
 
@@ -149,14 +197,24 @@ struct MouseCursorInfo
 #define KSYM_End		SDLK_END
 #define KSYM_Page_Up		SDLK_PAGEUP
 #define KSYM_Page_Down		SDLK_PAGEDOWN
+
+#if defined(TARGET_SDL2)
 #define KSYM_Menu		SDLK_MENU
+#define KSYM_Back		SDLK_AC_BACK
+#endif
 
 #define KSYM_space		SDLK_SPACE
 #define KSYM_exclam		SDLK_EXCLAIM
 #define KSYM_quotedbl		SDLK_QUOTEDBL
 #define KSYM_numbersign		SDLK_HASH
 #define KSYM_dollar		SDLK_DOLLAR
-#define KSYM_percent		KSYM_UNDEFINED		/* undefined */
+
+#if defined(TARGET_SDL2)
+#define KSYM_percent		SDLK_PERCENT
+#else
+#define KSYM_percent		37			/* undefined in SDL */
+#endif
+
 #define KSYM_ampersand		SDLK_AMPERSAND
 #define KSYM_apostrophe		SDLK_QUOTE
 #define KSYM_parenleft		SDLK_LEFTPAREN
@@ -189,6 +247,16 @@ struct MouseCursorInfo
 #define KSYM_braceright		KSYM_UNDEFINED		/* undefined */
 #define KSYM_asciitilde		KSYM_UNDEFINED		/* undefined */
 
+#if defined(TARGET_SDL2)
+#define KSYM_degree		176
+#define KSYM_Adiaeresis		196
+#define KSYM_Odiaeresis		214
+#define KSYM_Udiaeresis		220
+#define KSYM_adiaeresis		228
+#define KSYM_odiaeresis		246
+#define KSYM_udiaeresis		252
+#define KSYM_ssharp		223
+#else
 #define KSYM_degree		SDLK_WORLD_16
 #define KSYM_Adiaeresis		SDLK_WORLD_36
 #define KSYM_Odiaeresis		SDLK_WORLD_54
@@ -197,6 +265,7 @@ struct MouseCursorInfo
 #define KSYM_odiaeresis		SDLK_WORLD_86
 #define KSYM_udiaeresis		SDLK_WORLD_92
 #define KSYM_ssharp		SDLK_WORLD_63
+#endif
 
 #ifndef SDLK_A
 #define SDLK_A			65
@@ -292,6 +361,18 @@ struct MouseCursorInfo
 #define KSYM_8			SDLK_8
 #define KSYM_9			SDLK_9
 
+#if defined(TARGET_SDL2)
+#define KSYM_KP_0		SDLK_KP_0
+#define KSYM_KP_1		SDLK_KP_1
+#define KSYM_KP_2		SDLK_KP_2
+#define KSYM_KP_3		SDLK_KP_3
+#define KSYM_KP_4		SDLK_KP_4
+#define KSYM_KP_5		SDLK_KP_5
+#define KSYM_KP_6		SDLK_KP_6
+#define KSYM_KP_7		SDLK_KP_7
+#define KSYM_KP_8		SDLK_KP_8
+#define KSYM_KP_9		SDLK_KP_9
+#else
 #define KSYM_KP_0		SDLK_KP0
 #define KSYM_KP_1		SDLK_KP1
 #define KSYM_KP_2		SDLK_KP2
@@ -302,6 +383,7 @@ struct MouseCursorInfo
 #define KSYM_KP_7		SDLK_KP7
 #define KSYM_KP_8		SDLK_KP8
 #define KSYM_KP_9		SDLK_KP9
+#endif
 
 #define KSYM_F1			SDLK_F1
 #define KSYM_F2			SDLK_F2
@@ -315,30 +397,25 @@ struct MouseCursorInfo
 #define KSYM_F10		SDLK_F10
 #define KSYM_F11		SDLK_F11
 #define KSYM_F12		SDLK_F12
-#define KSYM_F13		SDLK_F13
-#define KSYM_F14		SDLK_F14
-#define KSYM_F15		SDLK_F15
-#define KSYM_F16		KSYM_UNDEFINED
-#define KSYM_F17		KSYM_UNDEFINED
-#define KSYM_F18		KSYM_UNDEFINED
-#define KSYM_F19		KSYM_UNDEFINED
-#define KSYM_F20		KSYM_UNDEFINED
-#define KSYM_F21		KSYM_UNDEFINED
-#define KSYM_F22		KSYM_UNDEFINED
-#define KSYM_F23		KSYM_UNDEFINED
-#define KSYM_F24		KSYM_UNDEFINED
 
 #define KSYM_FKEY_FIRST		KSYM_F1
-#define KSYM_FKEY_LAST		KSYM_F15
+#define KSYM_FKEY_LAST		KSYM_F12
 #define KSYM_NUM_FKEYS		(KSYM_FKEY_LAST - KSYM_FKEY_FIRST + 1)
 
-#define KMOD_None		None
+#define KMOD_None		KMOD_NONE
 #define KMOD_Shift_L		KMOD_LSHIFT
 #define KMOD_Shift_R		KMOD_RSHIFT
 #define KMOD_Control_L		KMOD_LCTRL
 #define KMOD_Control_R		KMOD_RCTRL
+
+#if defined(TARGET_SDL2)
+#define KMOD_Meta_L		KMOD_LGUI
+#define KMOD_Meta_R		KMOD_RGUI
+#else
 #define KMOD_Meta_L		KMOD_LMETA
 #define KMOD_Meta_R		KMOD_RMETA
+#endif
+
 #define KMOD_Alt_L		KMOD_LALT
 #define KMOD_Alt_R		KMOD_RALT
 
@@ -347,17 +424,42 @@ struct MouseCursorInfo
 #define KMOD_Meta		(KMOD_Meta_L    | KMOD_Meta_R)
 #define KMOD_Alt		(KMOD_Alt_L     | KMOD_Alt_R)
 
+#if defined(TARGET_SDL2)
+#define KMOD_TextInput		(KMOD_Shift | KMOD_Alt_R)
+#endif
 
 /* SDL function definitions */
 
+boolean SDLSetNativeSurface(SDL_Surface **);
+SDL_Surface *SDLGetNativeSurface(SDL_Surface *);
+void SDLCreateBitmapTextures(Bitmap *);
+void SDLFreeBitmapTextures(Bitmap *);
+
+#if defined(TARGET_SDL2)
+SDL_Surface *SDL_DisplayFormat(SDL_Surface *);
+void SDLSetWindowScaling(int);
+void SDLSetWindowScalingQuality(char *);
+void SDLSetWindowFullscreen(boolean);
+void SDLSetDisplaySize(void);
+void SDLSetScreenSizeAndOffsets(int, int);
+void SDLSetScreenSizeForRenderer(int, int);
+void SDLSetScreenProperties(void);
+#endif
+
+void SDLSetScreenRenderingMode(char *);
+void SDLRedrawWindow();
+void SDLSetWindowTitle(void);
+
+void SDLLimitScreenUpdates(boolean);
 void SDLInitVideoDisplay(void);
-void SDLInitVideoBuffer(DrawBuffer **, DrawWindow **, boolean);
-boolean SDLSetVideoMode(DrawBuffer **, boolean);
+void SDLInitVideoBuffer(boolean);
+boolean SDLSetVideoMode(boolean);
 void SDLCreateBitmapContent(Bitmap *, int, int, int);
 void SDLFreeBitmapPointers(Bitmap *);
 void SDLCopyArea(Bitmap *, Bitmap *, int, int, int, int, int, int, int);
+void SDLBlitTexture(Bitmap *, int, int, int, int, int, int, int);
 void SDLFillRectangle(Bitmap *, int, int, int, int, Uint32);
-void SDLFadeRectangle(Bitmap *, int, int, int, int, int, int, int,
+void SDLFadeRectangle(int, int, int, int, int, int, int,
 		      void (*draw_border_function)(void));
 void SDLDrawSimpleLine(Bitmap *, int, int, int, int, Uint32);
 void SDLDrawLine(Bitmap *, int, int, int, int, Uint32);
@@ -367,7 +469,7 @@ void SDLPutPixel(Bitmap *, int, int, Pixel);
 void SDLInvertArea(Bitmap *, int, int, int, int, Uint32);
 void SDLCopyInverseMasked(Bitmap *, Bitmap *, int, int, int, int, int, int);
 
-void SDLZoomBitmap(Bitmap *, Bitmap *);
+Bitmap *SDLZoomBitmap(Bitmap *, int, int);
 
 Bitmap *SDLLoadImage(char *);
 
@@ -383,4 +485,6 @@ void HandleJoystickEvent(Event *);
 void SDLInitJoysticks(void);
 boolean SDLReadJoystick(int, int *, int *, boolean *, boolean *);
 
+void PrepareFadeBitmap(int);
+
 #endif /* SDL_H */
diff --git a/src/libgame/setup.c b/src/libgame/setup.c
index b7e34ad..03d9bfd 100644
--- a/src/libgame/setup.c
+++ b/src/libgame/setup.c
@@ -1,21 +1,20 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* setup.c                                                  *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// setup.c
+// ============================================================================
 
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <dirent.h>
 #include <string.h>
 #include <unistd.h>
+#include <errno.h>
 
 #include "platform.h"
 
@@ -31,6 +30,8 @@
 #include "hash.h"
 
 
+#define ENABLE_UNUSED_CODE	FALSE	/* for currently unused functions */
+
 #define NUM_LEVELCLASS_DESC	8
 
 static char *levelclass_desc[NUM_LEVELCLASS_DESC] =
@@ -132,15 +133,25 @@ static char *getUserLevelDir(char *level_subdir)
 static char *getScoreDir(char *level_subdir)
 {
   static char *score_dir = NULL;
-  char *data_dir = getCommonDataDir();
+  static char *score_level_dir = NULL;
   char *score_subdir = SCORES_DIRECTORY;
 
-  checked_free(score_dir);
+  if (score_dir == NULL)
+  {
+    if (program.global_scores)
+      score_dir = getPath2(getCommonDataDir(),   score_subdir);
+    else
+      score_dir = getPath2(getUserGameDataDir(), score_subdir);
+  }
 
   if (level_subdir != NULL)
-    score_dir = getPath3(data_dir, score_subdir, level_subdir);
-  else
-    score_dir = getPath2(data_dir, score_subdir);
+  {
+    checked_free(score_level_dir);
+
+    score_level_dir = getPath2(score_dir, level_subdir);
+
+    return score_level_dir;
+  }
 
   return score_dir;
 }
@@ -313,6 +324,9 @@ static char *getSetupArtworkDir(TreeInfo *ti)
 {
   static char *artwork_dir = NULL;
 
+  if (ti == NULL)
+    return NULL;
+
   checked_free(artwork_dir);
 
   artwork_dir = getPath2(ti->basepath, ti->fullpath);
@@ -356,7 +370,7 @@ char *setLevelArtworkDir(TreeInfo *ti)
 
     checked_free(*artwork_set_ptr);
 
-    if (fileExists(dir))
+    if (directoryExists(dir))
     {
       *artwork_path_ptr = getStringCopy(getClassicArtworkDir(ti->type));
       *artwork_set_ptr = getStringCopy(getClassicArtworkSet(ti->type));
@@ -389,6 +403,29 @@ inline static char *getLevelArtworkDir(int type)
   return LEVELDIR_ARTWORK_PATH(leveldir_current, type);
 }
 
+char *getProgramConfigFilename(char *command_filename_ptr)
+{
+  char *command_filename_1 = getStringCopy(command_filename_ptr);
+
+  // strip trailing executable suffix from command filename
+  if (strSuffix(command_filename_1, ".exe"))
+    command_filename_1[strlen(command_filename_1) - 4] = '\0';
+
+  char *command_basepath = getBasePath(command_filename_ptr);
+  char *command_basename = getBaseNameNoSuffix(command_filename_ptr);
+  char *command_filename_2 = getPath2(command_basepath, command_basename);
+
+  char *config_filename_1 = getStringCat2(command_filename_1, ".conf");
+  char *config_filename_2 = getStringCat2(command_filename_2, ".conf");
+
+  // 1st try: look for config file that exactly matches the binary filename
+  if (fileExists(config_filename_1))
+    return config_filename_1;
+
+  // 2nd try: return config filename that matches binary filename without suffix
+  return config_filename_2;
+}
+
 char *getTapeFilename(int nr)
 {
   static char *filename = NULL;
@@ -452,6 +489,11 @@ char *getSetupFilename()
   return filename;
 }
 
+char *getDefaultSetupFilename()
+{
+  return program.config_filename;
+}
+
 char *getEditorSetupFilename()
 {
   static char *filename = NULL;
@@ -597,34 +639,7 @@ char *getLevelSetTitleMessageFilename(int nr, boolean initial)
 
 static char *getCorrectedArtworkBasename(char *basename)
 {
-  char *basename_corrected = basename;
-
-#if defined(PLATFORM_MSDOS)
-  if (program.filename_prefix != NULL)
-  {
-    int prefix_len = strlen(program.filename_prefix);
-
-    if (strncmp(basename, program.filename_prefix, prefix_len) == 0)
-      basename_corrected = &basename[prefix_len];
-
-    /* if corrected filename is still longer than standard MS-DOS filename
-       size (8 characters + 1 dot + 3 characters file extension), shorten
-       filename by writing file extension after 8th basename character */
-    if (strlen(basename_corrected) > 8 + 1 + 3)
-    {
-      static char *msdos_filename = NULL;
-
-      checked_free(msdos_filename);
-
-      msdos_filename = getStringCopy(basename_corrected);
-      strncpy(&msdos_filename[8], &basename[strlen(basename) - (1+3)], 1+3 +1);
-
-      basename_corrected = msdos_filename;
-    }
-  }
-#endif
-
-  return basename_corrected;
+  return basename;
 }
 
 char *getCustomImageFilename(char *basename)
@@ -639,7 +654,7 @@ char *getCustomImageFilename(char *basename)
   if (!gfx.override_level_graphics)
   {
     /* 1st try: look for special artwork in current level series directory */
-    filename = getPath3(getCurrentLevelDir(), GRAPHICS_DIRECTORY, basename);
+    filename = getImg3(getCurrentLevelDir(), GRAPHICS_DIRECTORY, basename);
     if (fileExists(filename))
       return filename;
 
@@ -649,7 +664,7 @@ char *getCustomImageFilename(char *basename)
     if (getLevelArtworkSet(ARTWORK_TYPE_GRAPHICS) != NULL)
     {
       /* 2nd try: look for special artwork configured in level series config */
-      filename = getPath2(getLevelArtworkDir(ARTWORK_TYPE_GRAPHICS), basename);
+      filename = getImg2(getLevelArtworkDir(ARTWORK_TYPE_GRAPHICS), basename);
       if (fileExists(filename))
 	return filename;
 
@@ -663,7 +678,7 @@ char *getCustomImageFilename(char *basename)
   if (!skip_setup_artwork)
   {
     /* 3rd try: look for special artwork in configured artwork directory */
-    filename = getPath2(getSetupArtworkDir(artwork.gfx_current), basename);
+    filename = getImg2(getSetupArtworkDir(artwork.gfx_current), basename);
     if (fileExists(filename))
       return filename;
 
@@ -671,29 +686,31 @@ char *getCustomImageFilename(char *basename)
   }
 
   /* 4th try: look for default artwork in new default artwork directory */
-  filename = getPath2(getDefaultGraphicsDir(GFX_DEFAULT_SUBDIR), basename);
+  filename = getImg2(getDefaultGraphicsDir(GFX_DEFAULT_SUBDIR), basename);
   if (fileExists(filename))
     return filename;
 
   free(filename);
 
   /* 5th try: look for default artwork in old default artwork directory */
-  filename = getPath2(options.graphics_directory, basename);
+  filename = getImg2(options.graphics_directory, basename);
   if (fileExists(filename))
     return filename;
 
-#if defined(CREATE_SPECIAL_EDITION)
-  free(filename);
+  if (!strEqual(GFX_FALLBACK_FILENAME, UNDEFINED_FILENAME))
+  {
+    free(filename);
 
-  if (options.debug)
-    Error(ERR_WARN, "cannot find artwork file '%s' (using fallback)", basename);
+    if (options.debug)
+      Error(ERR_WARN, "cannot find artwork file '%s' (using fallback)",
+	    basename);
 
-  /* 6th try: look for fallback artwork in old default artwork directory */
-  /* (needed to prevent errors when trying to access unused artwork files) */
-  filename = getPath2(options.graphics_directory, GFX_FALLBACK_FILENAME);
-  if (fileExists(filename))
-    return filename;
-#endif
+    /* 6th try: look for fallback artwork in old default artwork directory */
+    /* (needed to prevent errors when trying to access unused artwork files) */
+    filename = getImg2(options.graphics_directory, GFX_FALLBACK_FILENAME);
+    if (fileExists(filename))
+      return filename;
+  }
 
   return NULL;		/* cannot find specified artwork file anywhere */
 }
@@ -753,18 +770,20 @@ char *getCustomSoundFilename(char *basename)
   if (fileExists(filename))
     return filename;
 
-#if defined(CREATE_SPECIAL_EDITION)
-  free(filename);
+  if (!strEqual(SND_FALLBACK_FILENAME, UNDEFINED_FILENAME))
+  {
+    free(filename);
 
-  if (options.debug)
-    Error(ERR_WARN, "cannot find artwork file '%s' (using fallback)", basename);
+    if (options.debug)
+      Error(ERR_WARN, "cannot find artwork file '%s' (using fallback)",
+	    basename);
 
-  /* 6th try: look for fallback artwork in old default artwork directory */
-  /* (needed to prevent errors when trying to access unused artwork files) */
-  filename = getPath2(options.sounds_directory, SND_FALLBACK_FILENAME);
-  if (fileExists(filename))
-    return filename;
-#endif
+    /* 6th try: look for fallback artwork in old default artwork directory */
+    /* (needed to prevent errors when trying to access unused artwork files) */
+    filename = getPath2(options.sounds_directory, SND_FALLBACK_FILENAME);
+    if (fileExists(filename))
+      return filename;
+  }
 
   return NULL;		/* cannot find specified artwork file anywhere */
 }
@@ -824,18 +843,20 @@ char *getCustomMusicFilename(char *basename)
   if (fileExists(filename))
     return filename;
 
-#if defined(CREATE_SPECIAL_EDITION)
-  free(filename);
+  if (!strEqual(MUS_FALLBACK_FILENAME, UNDEFINED_FILENAME))
+  {
+    free(filename);
 
-  if (options.debug)
-    Error(ERR_WARN, "cannot find artwork file '%s' (using fallback)", basename);
+    if (options.debug)
+      Error(ERR_WARN, "cannot find artwork file '%s' (using fallback)",
+	    basename);
 
-  /* 6th try: look for fallback artwork in old default artwork directory */
-  /* (needed to prevent errors when trying to access unused artwork files) */
-  filename = getPath2(options.music_directory, MUS_FALLBACK_FILENAME);
-  if (fileExists(filename))
-    return filename;
-#endif
+    /* 6th try: look for fallback artwork in old default artwork directory */
+    /* (needed to prevent errors when trying to access unused artwork files) */
+    filename = getPath2(options.music_directory, MUS_FALLBACK_FILENAME);
+    if (fileExists(filename))
+      return filename;
+  }
 
   return NULL;		/* cannot find specified artwork file anywhere */
 }
@@ -879,7 +900,7 @@ char *getCustomMusicDirectory(void)
   {
     /* 1st try: look for special artwork in current level series directory */
     directory = getPath2(getCurrentLevelDir(), MUSIC_DIRECTORY);
-    if (fileExists(directory))
+    if (directoryExists(directory))
       return directory;
 
     free(directory);
@@ -889,7 +910,7 @@ char *getCustomMusicDirectory(void)
     {
       /* 2nd try: look for special artwork configured in level series config */
       directory = getStringCopy(getLevelArtworkDir(TREE_TYPE_MUSIC_DIR));
-      if (fileExists(directory))
+      if (directoryExists(directory))
 	return directory;
 
       free(directory);
@@ -903,7 +924,7 @@ char *getCustomMusicDirectory(void)
   {
     /* 3rd try: look for special artwork in configured artwork directory */
     directory = getStringCopy(getSetupArtworkDir(artwork.mus_current));
-    if (fileExists(directory))
+    if (directoryExists(directory))
       return directory;
 
     free(directory);
@@ -911,14 +932,14 @@ char *getCustomMusicDirectory(void)
 
   /* 4th try: look for default artwork in new default artwork directory */
   directory = getStringCopy(getDefaultMusicDir(MUS_DEFAULT_SUBDIR));
-  if (fileExists(directory))
+  if (directoryExists(directory))
     return directory;
 
   free(directory);
 
   /* 5th try: look for default artwork in old default artwork directory */
   directory = getStringCopy(options.music_directory);
-  if (fileExists(directory))
+  if (directoryExists(directory))
     return directory;
 
   return NULL;		/* cannot find specified artwork file anywhere */
@@ -933,16 +954,22 @@ void InitTapeDirectory(char *level_subdir)
 
 void InitScoreDirectory(char *level_subdir)
 {
-  createDirectory(getCommonDataDir(), "common data", PERMS_PUBLIC);
-  createDirectory(getScoreDir(NULL), "main score", PERMS_PUBLIC);
-  createDirectory(getScoreDir(level_subdir), "level score", PERMS_PUBLIC);
+  int permissions = (program.global_scores ? PERMS_PUBLIC : PERMS_PRIVATE);
+
+  if (program.global_scores)
+    createDirectory(getCommonDataDir(), "common data", permissions);
+  else
+    createDirectory(getUserGameDataDir(), "user data", permissions);
+
+  createDirectory(getScoreDir(NULL), "main score", permissions);
+  createDirectory(getScoreDir(level_subdir), "level score", permissions);
 }
 
 static void SaveUserLevelInfo();
 
 void InitUserLevelDirectory(char *level_subdir)
 {
-  if (!fileExists(getUserLevelDir(level_subdir)))
+  if (!directoryExists(getUserLevelDir(level_subdir)))
   {
     createDirectory(getUserGameDataDir(), "user data", PERMS_PRIVATE);
     createDirectory(getUserLevelDir(NULL), "main user level", PERMS_PRIVATE);
@@ -1117,13 +1144,7 @@ TreeInfo *cloneTreeNode(TreeInfo **node_top, TreeInfo *node_parent,
     return cloneTreeNode(node_top, node_parent, node->next,
 			 skip_sets_without_levels);
 
-#if 1
   node_new = getTreeInfoCopy(node);		/* copy complete node */
-#else
-  node_new = newTreeInfo();
-
-  *node_new = *node;				/* copy complete node */
-#endif
 
   node_new->node_top = node_top;		/* correct top node link */
   node_new->node_parent = node_parent;		/* correct parent node link */
@@ -1184,8 +1205,13 @@ void dumpTreeInfo(TreeInfo *node, int depth)
     for (i = 0; i < (depth + 1) * 3; i++)
       printf(" ");
 
+    printf("'%s' / '%s'\n", node->identifier, node->name);
+
+    /*
+    // use for dumping artwork info tree
     printf("subdir == '%s' ['%s', '%s'] [%d])\n",
 	   node->subdir, node->fullpath, node->basepath, node->in_user_dir);
+    */
 
     if (node->node_group != NULL)
       dumpTreeInfo(node->node_group, depth + 1);
@@ -1286,14 +1312,17 @@ void sortTreeInfo(TreeInfo **node_first)
 #define MODE_X_ALL		(S_IXUSR | S_IXGRP | S_IXOTH)
 
 #define MODE_W_PRIVATE		(S_IWUSR)
-#define MODE_W_PUBLIC		(S_IWUSR | S_IWGRP)
+#define MODE_W_PUBLIC_FILE	(S_IWUSR | S_IWGRP)
 #define MODE_W_PUBLIC_DIR	(S_IWUSR | S_IWGRP | S_ISGID)
 
 #define DIR_PERMS_PRIVATE	(MODE_R_ALL | MODE_X_ALL | MODE_W_PRIVATE)
 #define DIR_PERMS_PUBLIC	(MODE_R_ALL | MODE_X_ALL | MODE_W_PUBLIC_DIR)
+#define DIR_PERMS_PUBLIC_ALL	(MODE_R_ALL | MODE_X_ALL | MODE_W_ALL)
 
 #define FILE_PERMS_PRIVATE	(MODE_R_ALL | MODE_W_PRIVATE)
-#define FILE_PERMS_PUBLIC	(MODE_R_ALL | MODE_W_PUBLIC)
+#define FILE_PERMS_PUBLIC	(MODE_R_ALL | MODE_W_PUBLIC_FILE)
+#define FILE_PERMS_PUBLIC_ALL	(MODE_R_ALL | MODE_W_ALL)
+
 
 char *getHomeDir()
 {
@@ -1369,37 +1398,18 @@ char *getUserGameDataDir(void)
 {
   static char *user_game_data_dir = NULL;
 
+#if defined(PLATFORM_ANDROID)
+  if (user_game_data_dir == NULL)
+    user_game_data_dir = (char *)SDL_AndroidGetInternalStoragePath();
+#else
   if (user_game_data_dir == NULL)
     user_game_data_dir = getPath2(getPersonalDataDir(),
 				  program.userdata_subdir);
+#endif
 
   return user_game_data_dir;
 }
 
-void updateUserGameDataDir()
-{
-#if defined(PLATFORM_MACOSX)
-  char *userdata_dir_old = getPath2(getHomeDir(), program.userdata_subdir_unix);
-  char *userdata_dir_new = getUserGameDataDir();	/* do not free() this */
-
-  /* convert old Unix style game data directory to Mac OS X style, if needed */
-  if (fileExists(userdata_dir_old) && !fileExists(userdata_dir_new))
-  {
-    if (rename(userdata_dir_old, userdata_dir_new) != 0)
-    {
-      Error(ERR_WARN, "cannot move game data directory '%s' to '%s'",
-	    userdata_dir_old, userdata_dir_new);
-
-      /* continue using Unix style data directory -- this should not happen */
-      program.userdata_path = getPath2(getPersonalDataDir(),
-				       program.userdata_subdir_unix);
-    }
-  }
-
-  free(userdata_dir_old);
-#endif
-}
-
 char *getSetupDir()
 {
   return getUserGameDataDir();
@@ -1434,6 +1444,9 @@ static boolean posix_process_running_setgid()
 
 void createDirectory(char *dir, char *text, int permission_class)
 {
+  if (directoryExists(dir))
+    return;
+
   /* leave "other" permissions in umask untouched, but ensure group parts
      of USERDATA_DIR_MODE are not masked */
   mode_t dir_mode = (permission_class == PERMS_PRIVATE ?
@@ -1442,17 +1455,20 @@ void createDirectory(char *dir, char *text, int permission_class)
   mode_t group_umask = ~(dir_mode & S_IRWXG);
   int running_setgid = posix_process_running_setgid();
 
-  /* if we're setgid, protect files against "other" */
-  /* else keep umask(0) to make the dir world-writable */
+  if (permission_class == PERMS_PUBLIC)
+  {
+    /* if we're setgid, protect files against "other" */
+    /* else keep umask(0) to make the dir world-writable */
 
-  if (running_setgid)
-    posix_umask(last_umask & group_umask);
-  else
-    dir_mode |= MODE_W_ALL;
+    if (running_setgid)
+      posix_umask(last_umask & group_umask);
+    else
+      dir_mode = DIR_PERMS_PUBLIC_ALL;
+  }
 
-  if (!fileExists(dir))
-    if (posix_mkdir(dir, dir_mode) != 0)
-      Error(ERR_WARN, "cannot create %s directory '%s'", text, dir);
+  if (posix_mkdir(dir, dir_mode) != 0)
+    Error(ERR_WARN, "cannot create %s directory '%s': %s",
+	  text, dir, strerror(errno));
 
   if (permission_class == PERMS_PUBLIC && !running_setgid)
     chmod(dir, dir_mode);
@@ -1472,7 +1488,7 @@ void SetFilePermissions(char *filename, int permission_class)
 	       FILE_PERMS_PRIVATE : FILE_PERMS_PUBLIC);
 
   if (permission_class == PERMS_PUBLIC && !running_setgid)
-    perms |= MODE_W_ALL;
+    perms = FILE_PERMS_PUBLIC_ALL;
 
   chmod(filename, perms);
 }
@@ -1492,6 +1508,17 @@ char *getCookie(char *file_type)
   return cookie;
 }
 
+void fprintFileHeader(FILE *file, char *basename)
+{
+  char *prefix = "# ";
+  char *sep1 = "=";
+
+  fprintf_line_with_prefix(file, prefix, sep1, 77);
+  fprintf(file, "%s%s\n", prefix, basename);
+  fprintf_line_with_prefix(file, prefix, sep1, 77);
+  fprintf(file, "\n");
+}
+
 int getFileVersionFromCookieString(const char *cookie)
 {
   const char *ptr_cookie1, *ptr_cookie2;
@@ -1539,6 +1566,7 @@ boolean checkCookieString(const char *cookie, const char *template)
   return TRUE;
 }
 
+
 /* ------------------------------------------------------------------------- */
 /* setup file list and hash handling functions                               */
 /* ------------------------------------------------------------------------- */
@@ -1630,6 +1658,7 @@ SetupFileList *addListEntry(SetupFileList *list, char *token, char *value)
     return addListEntry(list->next, token, value);
 }
 
+#if ENABLE_UNUSED_CODE
 #ifdef DEBUG
 static void printSetupFileList(SetupFileList *list)
 {
@@ -1642,6 +1671,7 @@ static void printSetupFileList(SetupFileList *list)
   printSetupFileList(list->next);
 }
 #endif
+#endif
 
 #ifdef DEBUG
 DEFINE_HASHTABLE_INSERT(insert_hash_entry, char, char);
@@ -1740,7 +1770,8 @@ char *removeHashEntry(SetupFileHash *hash, char *token)
   return remove_hash_entry(hash, token);
 }
 
-#if 0
+#if ENABLE_UNUSED_CODE
+#if DEBUG
 static void printSetupFileHash(SetupFileHash *hash)
 {
   BEGIN_HASH_ITERATION(hash, itr)
@@ -1751,6 +1782,7 @@ static void printSetupFileHash(SetupFileHash *hash)
   END_HASH_ITERATION(hash, itr)
 }
 #endif
+#endif
 
 #define ALLOW_TOKEN_VALUE_SEPARATOR_BEING_WHITESPACE		1
 #define CHECK_TOKEN_VALUE_SEPARATOR__WARN_IF_MISSING		0
@@ -1816,12 +1848,8 @@ static boolean getTokenValueFromSetupLineExt(char *line,
   /* find end of token to determine start of value */
   for (line_ptr = token; *line_ptr; line_ptr++)
   {
-#if 1
     /* first look for an explicit token/value separator, like ':' or '=' */
     if (*line_ptr == ':' || *line_ptr == '=')
-#else
-    if (*line_ptr == ' ' || *line_ptr == '\t' || *line_ptr == ':')
-#endif
     {
       *line_ptr = '\0';			/* terminate token string */
       value = line_ptr + 1;		/* set beginning of value */
@@ -1888,11 +1916,6 @@ static boolean getTokenValueFromSetupLineExt(char *line,
     if (*value != ' ' && *value != '\t')
       break;
 
-#if 0
-  if (*value == '\0')
-    value = "true";	/* treat tokens without value as "true" */
-#endif
-
   *token_ptr = token;
   *value_ptr = value;
 
@@ -1908,7 +1931,6 @@ boolean getTokenValueFromSetupLine(char *line, char **token, char **value)
   return getTokenValueFromSetupLineExt(line, token, value, NULL, NULL, 0, TRUE);
 }
 
-#if 1
 static boolean loadSetupFileData(void *setup_file_data, char *filename,
 				 boolean top_recursion_level, boolean is_hash)
 {
@@ -1917,7 +1939,7 @@ static boolean loadSetupFileData(void *setup_file_data, char *filename,
   char *token, *value, *line_ptr;
   void *insert_ptr = NULL;
   boolean read_continued_line = FALSE;
-  FILE *file;
+  File *file;
   int line_nr = 0, token_count = 0, include_count = 0;
 
 #if CHECK_TOKEN_VALUE_SEPARATOR__WARN_IF_MISSING
@@ -1928,7 +1950,7 @@ static boolean loadSetupFileData(void *setup_file_data, char *filename,
   token_already_exists_warning = FALSE;
 #endif
 
-  if (!(file = fopen(filename, MODE_READ)))
+  if (!(file = openFile(filename, MODE_READ)))
   {
     Error(ERR_WARN, "cannot open configuration file '%s'", filename);
 
@@ -1946,10 +1968,10 @@ static boolean loadSetupFileData(void *setup_file_data, char *filename,
   /* mark this file as already included (to prevent including it again) */
   setHashEntry(include_filename_hash, getBaseNamePtr(filename), "true");
 
-  while (!feof(file))
+  while (!checkEndOfFile(file))
   {
     /* read next line of input file */
-    if (!fgets(line, MAX_LINE_LEN, file))
+    if (!getStringFromFile(file, line, MAX_LINE_LEN))
       break;
 
     /* check if line was completely read and is terminated by line break */
@@ -1966,14 +1988,6 @@ static boolean loadSetupFileData(void *setup_file_data, char *filename,
 
     if (read_continued_line)
     {
-#if 0
-      /* !!! ??? WHY ??? !!! */
-      /* cut leading whitespaces from input line */
-      for (line_ptr = line; *line_ptr; line_ptr++)
-	if (*line_ptr != ' ' && *line_ptr != '\t')
-	  break;
-#endif
-
       /* append new line to existing line, if there is enough space */
       if (strlen(previous_line) + strlen(line_ptr) < MAX_LINE_LEN)
 	strcat(previous_line, line_ptr);
@@ -2008,10 +2022,6 @@ static boolean loadSetupFileData(void *setup_file_data, char *filename,
 	  char *basename = getBaseName(value);
 	  char *filename_include = getPath2(basepath, basename);
 
-#if 0
-	  Error(ERR_INFO, "[including file '%s']", filename_include);
-#endif
-
 	  loadSetupFileData(setup_file_data, filename_include, FALSE, is_hash);
 
 	  free(basepath);
@@ -2062,7 +2072,7 @@ static boolean loadSetupFileData(void *setup_file_data, char *filename,
     }
   }
 
-  fclose(file);
+  closeFile(file);
 
 #if CHECK_TOKEN_VALUE_SEPARATOR__WARN_IF_MISSING
   if (token_value_separator_warning)
@@ -2083,239 +2093,6 @@ static boolean loadSetupFileData(void *setup_file_data, char *filename,
   return TRUE;
 }
 
-#else
-
-static boolean loadSetupFileData(void *setup_file_data, char *filename,
-				 boolean top_recursion_level, boolean is_hash)
-{
-  static SetupFileHash *include_filename_hash = NULL;
-  char line[MAX_LINE_LEN], line_raw[MAX_LINE_LEN], previous_line[MAX_LINE_LEN];
-  char *token, *value, *line_ptr;
-  void *insert_ptr = NULL;
-  boolean read_continued_line = FALSE;
-  FILE *file;
-  int line_nr = 0;
-  int token_count = 0;
-
-#if CHECK_TOKEN_VALUE_SEPARATOR__WARN_IF_MISSING
-  token_value_separator_warning = FALSE;
-#endif
-
-  if (!(file = fopen(filename, MODE_READ)))
-  {
-    Error(ERR_WARN, "cannot open configuration file '%s'", filename);
-
-    return FALSE;
-  }
-
-  /* use "insert pointer" to store list end for constant insertion complexity */
-  if (!is_hash)
-    insert_ptr = setup_file_data;
-
-  /* on top invocation, create hash to mark included files (to prevent loops) */
-  if (top_recursion_level)
-    include_filename_hash = newSetupFileHash();
-
-  /* mark this file as already included (to prevent including it again) */
-  setHashEntry(include_filename_hash, getBaseNamePtr(filename), "true");
-
-  while (!feof(file))
-  {
-    /* read next line of input file */
-    if (!fgets(line, MAX_LINE_LEN, file))
-      break;
-
-    /* check if line was completely read and is terminated by line break */
-    if (strlen(line) > 0 && line[strlen(line) - 1] == '\n')
-      line_nr++;
-
-    /* cut trailing line break (this can be newline and/or carriage return) */
-    for (line_ptr = &line[strlen(line)]; line_ptr >= line; line_ptr--)
-      if ((*line_ptr == '\n' || *line_ptr == '\r') && *(line_ptr + 1) == '\0')
-	*line_ptr = '\0';
-
-    /* copy raw input line for later use (mainly debugging output) */
-    strcpy(line_raw, line);
-
-    if (read_continued_line)
-    {
-      /* cut leading whitespaces from input line */
-      for (line_ptr = line; *line_ptr; line_ptr++)
-	if (*line_ptr != ' ' && *line_ptr != '\t')
-	  break;
-
-      /* append new line to existing line, if there is enough space */
-      if (strlen(previous_line) + strlen(line_ptr) < MAX_LINE_LEN)
-	strcat(previous_line, line_ptr);
-
-      strcpy(line, previous_line);	/* copy storage buffer to line */
-
-      read_continued_line = FALSE;
-    }
-
-    /* if the last character is '\', continue at next line */
-    if (strlen(line) > 0 && line[strlen(line) - 1] == '\\')
-    {
-      line[strlen(line) - 1] = '\0';	/* cut off trailing backslash */
-      strcpy(previous_line, line);	/* copy line to storage buffer */
-
-      read_continued_line = TRUE;
-
-      continue;
-    }
-
-    /* cut trailing comment from input line */
-    for (line_ptr = line; *line_ptr; line_ptr++)
-    {
-      if (*line_ptr == '#')
-      {
-	*line_ptr = '\0';
-	break;
-      }
-    }
-
-    /* cut trailing whitespaces from input line */
-    for (line_ptr = &line[strlen(line)]; line_ptr >= line; line_ptr--)
-      if ((*line_ptr == ' ' || *line_ptr == '\t') && *(line_ptr + 1) == '\0')
-	*line_ptr = '\0';
-
-    /* ignore empty lines */
-    if (*line == '\0')
-      continue;
-
-    /* cut leading whitespaces from token */
-    for (token = line; *token; token++)
-      if (*token != ' ' && *token != '\t')
-	break;
-
-    /* start with empty value as reliable default */
-    value = "";
-
-    token_value_separator_found = FALSE;
-
-    /* find end of token to determine start of value */
-    for (line_ptr = token; *line_ptr; line_ptr++)
-    {
-#if 1
-      /* first look for an explicit token/value separator, like ':' or '=' */
-      if (*line_ptr == ':' || *line_ptr == '=')
-#else
-      if (*line_ptr == ' ' || *line_ptr == '\t' || *line_ptr == ':')
-#endif
-      {
-	*line_ptr = '\0';		/* terminate token string */
-	value = line_ptr + 1;		/* set beginning of value */
-
-	token_value_separator_found = TRUE;
-
-	break;
-      }
-    }
-
-#if ALLOW_TOKEN_VALUE_SEPARATOR_BEING_WHITESPACE
-    /* fallback: if no token/value separator found, also allow whitespaces */
-    if (!token_value_separator_found)
-    {
-      for (line_ptr = token; *line_ptr; line_ptr++)
-      {
-	if (*line_ptr == ' ' || *line_ptr == '\t')
-	{
-	  *line_ptr = '\0';		/* terminate token string */
-	  value = line_ptr + 1;		/* set beginning of value */
-
-	  token_value_separator_found = TRUE;
-
-	  break;
-	}
-      }
-
-#if CHECK_TOKEN_VALUE_SEPARATOR__WARN_IF_MISSING
-      if (token_value_separator_found)
-      {
-	if (!token_value_separator_warning)
-	{
-	  Error(ERR_INFO_LINE, "-");
-	  Error(ERR_WARN, "missing token/value separator(s) in config file:");
-	  Error(ERR_INFO, "- config file: '%s'", filename);
-
-	  token_value_separator_warning = TRUE;
-	}
-
-	Error(ERR_INFO, "- line %d: '%s'", line_nr, line_raw);
-      }
-#endif
-    }
-#endif
-
-    /* cut trailing whitespaces from token */
-    for (line_ptr = &token[strlen(token)]; line_ptr >= token; line_ptr--)
-      if ((*line_ptr == ' ' || *line_ptr == '\t') && *(line_ptr + 1) == '\0')
-	*line_ptr = '\0';
-
-    /* cut leading whitespaces from value */
-    for (; *value; value++)
-      if (*value != ' ' && *value != '\t')
-	break;
-
-#if 0
-    if (*value == '\0')
-      value = "true";	/* treat tokens without value as "true" */
-#endif
-
-    if (*token)
-    {
-      if (strEqual(token, "include"))
-      {
-	if (getHashEntry(include_filename_hash, value) == NULL)
-	{
-	  char *basepath = getBasePath(filename);
-	  char *basename = getBaseName(value);
-	  char *filename_include = getPath2(basepath, basename);
-
-#if 0
-	  Error(ERR_INFO, "[including file '%s']", filename_include);
-#endif
-
-	  loadSetupFileData(setup_file_data, filename_include, FALSE, is_hash);
-
-	  free(basepath);
-	  free(basename);
-	  free(filename_include);
-	}
-	else
-	{
-	  Error(ERR_WARN, "ignoring already processed file '%s'", value);
-	}
-      }
-      else
-      {
-	if (is_hash)
-	  setHashEntry((SetupFileHash *)setup_file_data, token, value);
-	else
-	  insert_ptr = addListEntry((SetupFileList *)insert_ptr, token, value);
-
-	token_count++;
-      }
-    }
-  }
-
-  fclose(file);
-
-#if CHECK_TOKEN_VALUE_SEPARATOR__WARN_IF_MISSING
-  if (token_value_separator_warning)
-    Error(ERR_INFO_LINE, "-");
-#endif
-
-  if (token_count == 0)
-    Error(ERR_WARN, "configuration file '%s' is empty", filename);
-
-  if (top_recursion_level)
-    freeSetupFileHash(include_filename_hash);
-
-  return TRUE;
-}
-#endif
-
 void saveSetupFileHash(SetupFileHash *hash, char *filename)
 {
   FILE *file;
@@ -2372,17 +2149,6 @@ SetupFileHash *loadSetupFileHash(char *filename)
   return setup_file_hash;
 }
 
-void checkSetupFileHashIdentifier(SetupFileHash *setup_file_hash,
-				  char *filename, char *identifier)
-{
-  char *value = getHashEntry(setup_file_hash, TOKEN_STR_FILE_IDENTIFIER);
-
-  if (value == NULL)
-    Error(ERR_WARN, "config file '%s' has no file identifier", filename);
-  else if (!checkCookieString(value, identifier))
-    Error(ERR_WARN, "config file '%s' has wrong file identifier", filename);
-}
-
 
 /* ========================================================================= */
 /* setup file stuff                                                          */
@@ -2603,11 +2369,7 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ti, TreeInfo *parent)
     ti->last_level = 0;
     ti->level_group = FALSE;
     ti->handicap_level = 0;
-#if 1
     ti->readonly = parent->readonly;
-#else
-    ti->readonly = TRUE;
-#endif
     ti->handicap = TRUE;
     ti->skip_levels = FALSE;
   }
@@ -2679,7 +2441,7 @@ static TreeInfo *getTreeInfoCopy(TreeInfo *ti)
   return ti_copy;
 }
 
-static void freeTreeInfo(TreeInfo *ti)
+void freeTreeInfo(TreeInfo *ti)
 {
   if (ti == NULL)
     return;
@@ -2720,6 +2482,14 @@ static void freeTreeInfo(TreeInfo *ti)
     checked_free(ti->special_flags);
   }
 
+  // recursively free child node
+  if (ti->node_group)
+    freeTreeInfo(ti->node_group);
+
+  // recursively free next node
+  if (ti->next)
+    freeTreeInfo(ti->next);
+
   checked_free(ti);
 }
 
@@ -2770,7 +2540,7 @@ static int compareTreeInfoEntries(const void *object1, const void *object2)
 {
   const TreeInfo *entry1 = *((TreeInfo **)object1);
   const TreeInfo *entry2 = *((TreeInfo **)object2);
-  int class_sorting1, class_sorting2;
+  int class_sorting1 = 0, class_sorting2 = 0;
   int compare_result;
 
   if (entry1->type == TREE_TYPE_LEVEL_DIR)
@@ -2778,7 +2548,9 @@ static int compareTreeInfoEntries(const void *object1, const void *object2)
     class_sorting1 = LEVELSORTING(entry1);
     class_sorting2 = LEVELSORTING(entry2);
   }
-  else
+  else if (entry1->type == TREE_TYPE_GRAPHICS_DIR ||
+	   entry1->type == TREE_TYPE_SOUNDS_DIR ||
+	   entry1->type == TREE_TYPE_MUSIC_DIR)
   {
     class_sorting1 = ARTWORKSORTING(entry1);
     class_sorting2 = ARTWORKSORTING(entry2);
@@ -2804,12 +2576,12 @@ static int compareTreeInfoEntries(const void *object1, const void *object2)
   return compare_result;
 }
 
-static void createParentTreeInfoNode(TreeInfo *node_parent)
+static TreeInfo *createParentTreeInfoNode(TreeInfo *node_parent)
 {
   TreeInfo *ti_new;
 
   if (node_parent == NULL)
-    return;
+    return NULL;
 
   ti_new = newTreeInfo();
   setTreeInfoToDefaults(ti_new, node_parent->type);
@@ -2821,7 +2593,7 @@ static void createParentTreeInfoNode(TreeInfo *node_parent)
   setString(&ti_new->name, ".. (parent directory)");
   setString(&ti_new->name_sorting, ti_new->name);
 
-  setString(&ti_new->subdir, "..");
+  setString(&ti_new->subdir, STRING_PARENT_DIRECTORY);
   setString(&ti_new->fullpath, node_parent->fullpath);
 
   ti_new->sort_priority = node_parent->sort_priority;
@@ -2830,6 +2602,44 @@ static void createParentTreeInfoNode(TreeInfo *node_parent)
   setString(&ti_new->class_desc, getLevelClassDescription(ti_new));
 
   pushTreeInfo(&node_parent->node_group, ti_new);
+
+  return ti_new;
+}
+
+static TreeInfo *createTopTreeInfoNode(TreeInfo *node_first)
+{
+  TreeInfo *ti_new, *ti_new2;
+
+  if (node_first == NULL)
+    return NULL;
+
+  ti_new = newTreeInfo();
+  setTreeInfoToDefaults(ti_new, TREE_TYPE_LEVEL_DIR);
+
+  ti_new->node_parent = NULL;
+  ti_new->parent_link = FALSE;
+
+  setString(&ti_new->identifier, node_first->identifier);
+  setString(&ti_new->name, "level sets");
+  setString(&ti_new->name_sorting, ti_new->name);
+
+  setString(&ti_new->subdir, STRING_TOP_DIRECTORY);
+  setString(&ti_new->fullpath, node_first->fullpath);
+
+  ti_new->sort_priority = node_first->sort_priority;;
+  ti_new->latest_engine = node_first->latest_engine;
+
+  setString(&ti_new->class_desc, "level sets");
+
+  ti_new->node_group = node_first;
+  ti_new->level_group = TRUE;
+
+  ti_new2 = createParentTreeInfoNode(ti_new);
+
+  setString(&ti_new2->name, ".. (main menu)");
+  setString(&ti_new2->name_sorting, ti_new2->name);
+
+  return ti_new;
 }
 
 
@@ -2895,16 +2705,7 @@ static char *getCacheToken(char *prefix, char *suffix)
 
 static char *getFileTimestampString(char *filename)
 {
-#if 1
   return getStringCopy(i_to_a(getFileTimestampEpochSeconds(filename)));
-#else
-  struct stat file_status;
-
-  if (stat(filename, &file_status) != 0)	/* cannot stat file */
-    return getStringCopy(i_to_a(0));
-
-  return getStringCopy(i_to_a(file_status.st_mtime));
-#endif
 }
 
 static boolean modifiedFileTimestamp(char *filename, char *timestamp_string)
@@ -2952,9 +2753,7 @@ static TreeInfo *getArtworkInfoCacheEntry(LevelDirTree *level_node, int type)
       /* check if cache entry for this item is invalid or incomplete */
       if (value == NULL)
       {
-#if 1
 	Error(ERR_WARN, "cache entry '%s' invalid", token);
-#endif
 
 	cached = FALSE;
       }
@@ -2984,11 +2783,6 @@ static TreeInfo *getArtworkInfoCacheEntry(LevelDirTree *level_node, int type)
     if (modifiedFileTimestamp(filename_artworkinfo, cache_entry))
       cached = FALSE;
 
-#if 0
-    if (!cached)
-      printf("::: '%s': INVALIDATED FROM CACHE BY TIMESTAMP\n", identifier);
-#endif
-
     checked_free(filename_levelinfo);
     checked_free(filename_artworkinfo);
   }
@@ -3060,10 +2854,6 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
 					  char *level_directory,
 					  char *directory_name)
 {
-#if 0
-  static unsigned long progress_delay = 0;
-  unsigned long progress_delay_value = 100;	/* (in milliseconds) */
-#endif
   char *directory_path = getPath2(level_directory, directory_name);
   char *filename = getPath2(directory_path, LEVELINFO_FILENAME);
   SetupFileHash *setup_file_hash;
@@ -3100,9 +2890,6 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
 
   leveldir_new->subdir = getStringCopy(directory_name);
 
-  checkSetupFileHashIdentifier(setup_file_hash, filename,
-			       getCookie("LEVELINFO"));
-
   /* set all structure fields according to the token/value pairs */
   ldi = *leveldir_new;
   for (i = 0; i < NUM_LEVELINFO_TOKENS; i++)
@@ -3130,23 +2917,12 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
     leveldir_new->fullpath = getPath2(node_parent->fullpath, directory_name);
   }
 
-#if 0
-  if (leveldir_new->levels < 1)
-    leveldir_new->levels = 1;
-#endif
-
   leveldir_new->last_level =
     leveldir_new->first_level + leveldir_new->levels - 1;
 
   leveldir_new->in_user_dir =
     (!strEqual(leveldir_new->basepath, options.level_directory));
 
-#if 0
-  printf("::: '%s' -> %d\n",
-	 leveldir_new->identifier,
-	 leveldir_new->in_user_dir);
-#endif
-
   /* adjust some settings if user's private level directory was detected */
   if (leveldir_new->sort_priority == LEVELCLASS_UNDEFINED &&
       leveldir_new->in_user_dir &&
@@ -3169,34 +2945,7 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
     (leveldir_new->user_defined || !leveldir_new->handicap ?
      leveldir_new->last_level : leveldir_new->first_level);
 
-#if 1
-#if 1
-  DrawInitTextExt(leveldir_new->name, 150, FC_YELLOW,
-		  leveldir_new->level_group);
-#else
-  if (leveldir_new->level_group ||
-      DelayReached(&progress_delay, progress_delay_value))
-    DrawInitText(leveldir_new->name, 150, FC_YELLOW);
-#endif
-#else
   DrawInitText(leveldir_new->name, 150, FC_YELLOW);
-#endif
-
-#if 0
-  /* !!! don't skip sets without levels (else artwork base sets are missing) */
-#if 1
-  if (leveldir_new->levels < 1 && !leveldir_new->level_group)
-  {
-    /* skip level sets without levels (which are probably artwork base sets) */
-
-    freeSetupFileHash(setup_file_hash);
-    free(directory_path);
-    free(filename);
-
-    return FALSE;
-  }
-#endif
-#endif
 
   pushTreeInfo(node_first, leveldir_new);
 
@@ -3222,20 +2971,20 @@ static void LoadLevelInfoFromLevelDir(TreeInfo **node_first,
 				      TreeInfo *node_parent,
 				      char *level_directory)
 {
-  DIR *dir;
-  struct dirent *dir_entry;
+  Directory *dir;
+  DirectoryEntry *dir_entry;
   boolean valid_entry_found = FALSE;
 
-  if ((dir = opendir(level_directory)) == NULL)
+  if ((dir = openDirectory(level_directory)) == NULL)
   {
     Error(ERR_WARN, "cannot read level directory '%s'", level_directory);
+
     return;
   }
 
-  while ((dir_entry = readdir(dir)) != NULL)	/* loop until last dir entry */
+  while ((dir_entry = readDirectory(dir)) != NULL)	/* loop all entries */
   {
-    struct stat file_status;
-    char *directory_name = dir_entry->d_name;
+    char *directory_name = dir_entry->basename;
     char *directory_path = getPath2(level_directory, directory_name);
 
     /* skip entries for current and parent directory */
@@ -3243,14 +2992,15 @@ static void LoadLevelInfoFromLevelDir(TreeInfo **node_first,
 	strEqual(directory_name, ".."))
     {
       free(directory_path);
+
       continue;
     }
 
     /* find out if directory entry is itself a directory */
-    if (stat(directory_path, &file_status) != 0 ||	/* cannot stat file */
-	(file_status.st_mode & S_IFMT) != S_IFDIR)	/* not a directory */
+    if (!dir_entry->is_directory)			/* not a directory */
     {
       free(directory_path);
+
       continue;
     }
 
@@ -3266,7 +3016,7 @@ static void LoadLevelInfoFromLevelDir(TreeInfo **node_first,
 						    directory_name);
   }
 
-  closedir(dir);
+  closeDirectory(dir);
 
   /* special case: top level directory may directly contain "levelinfo.conf" */
   if (node_parent == NULL && !valid_entry_found)
@@ -3300,6 +3050,8 @@ void LoadLevelInfo()
   LoadLevelInfoFromLevelDir(&leveldir_first, NULL, options.level_directory);
   LoadLevelInfoFromLevelDir(&leveldir_first, NULL, getUserLevelDir(NULL));
 
+  leveldir_first = createTopTreeInfoNode(leveldir_first);
+
   /* after loading all level set information, clone the level directory tree
      and remove all level sets without levels (these may still contain artwork
      to be offered in the setup menu as "custom artwork", and are therefore
@@ -3317,7 +3069,7 @@ void LoadLevelInfo()
 
   sortTreeInfo(&leveldir_first);
 
-#if 0
+#if ENABLE_UNUSED_CODE
   dumpTreeInfo(leveldir_first, 0);
 #endif
 }
@@ -3338,24 +3090,23 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first,
 
   if (setup_file_hash == NULL)	/* no config file -- look for artwork files */
   {
-    DIR *dir;
-    struct dirent *dir_entry;
+    Directory *dir;
+    DirectoryEntry *dir_entry;
     boolean valid_file_found = FALSE;
 
-    if ((dir = opendir(directory_path)) != NULL)
+    if ((dir = openDirectory(directory_path)) != NULL)
     {
-      while ((dir_entry = readdir(dir)) != NULL)
+      while ((dir_entry = readDirectory(dir)) != NULL)
       {
-	char *entry_name = dir_entry->d_name;
-
-	if (FileIsArtworkType(entry_name, type))
+	if (FileIsArtworkType(dir_entry->filename, type))
 	{
 	  valid_file_found = TRUE;
+
 	  break;
 	}
       }
 
-      closedir(dir);
+      closeDirectory(dir);
     }
 
     if (!valid_file_found)
@@ -3381,10 +3132,6 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first,
 
   if (setup_file_hash)	/* (before defining ".color" and ".class_desc") */
   {
-#if 0
-    checkSetupFileHashIdentifier(setup_file_hash, filename, getCookie("..."));
-#endif
-
     /* set all structure fields according to the token/value pairs */
     ldi = *artwork_new;
     for (i = 0; i < NUM_LEVELINFO_TOKENS; i++)
@@ -3451,10 +3198,6 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first,
     setString(&artwork_new->name_sorting, artwork_new->name);
   }
 
-#if 0
-  DrawInitText(artwork_new->name, 150, FC_YELLOW);
-#endif
-
   pushTreeInfo(node_first, artwork_new);
 
   freeSetupFileHash(setup_file_hash);
@@ -3469,11 +3212,11 @@ static void LoadArtworkInfoFromArtworkDir(TreeInfo **node_first,
 					  TreeInfo *node_parent,
 					  char *base_directory, int type)
 {
-  DIR *dir;
-  struct dirent *dir_entry;
+  Directory *dir;
+  DirectoryEntry *dir_entry;
   boolean valid_entry_found = FALSE;
 
-  if ((dir = opendir(base_directory)) == NULL)
+  if ((dir = openDirectory(base_directory)) == NULL)
   {
     /* display error if directory is main "options.graphics_directory" etc. */
     if (base_directory == OPTIONS_ARTWORK_DIRECTORY(type))
@@ -3482,10 +3225,9 @@ static void LoadArtworkInfoFromArtworkDir(TreeInfo **node_first,
     return;
   }
 
-  while ((dir_entry = readdir(dir)) != NULL)	/* loop until last dir entry */
+  while ((dir_entry = readDirectory(dir)) != NULL)	/* loop all entries */
   {
-    struct stat file_status;
-    char *directory_name = dir_entry->d_name;
+    char *directory_name = dir_entry->basename;
     char *directory_path = getPath2(base_directory, directory_name);
 
     /* skip directory entries for current and parent directory */
@@ -3493,14 +3235,15 @@ static void LoadArtworkInfoFromArtworkDir(TreeInfo **node_first,
 	strEqual(directory_name, ".."))
     {
       free(directory_path);
+
       continue;
     }
 
-    /* skip directory entries which are not a directory or are not accessible */
-    if (stat(directory_path, &file_status) != 0 ||	/* cannot stat file */
-	(file_status.st_mode & S_IFMT) != S_IFDIR)	/* not a directory */
+    /* skip directory entries which are not a directory */
+    if (!dir_entry->is_directory)			/* not a directory */
     {
       free(directory_path);
+
       continue;
     }
 
@@ -3512,7 +3255,7 @@ static void LoadArtworkInfoFromArtworkDir(TreeInfo **node_first,
 							directory_name, type);
   }
 
-  closedir(dir);
+  closeDirectory(dir);
 
   /* check if this directory directly contains artwork itself */
   valid_entry_found |= LoadArtworkInfoFromArtworkConf(node_first, node_parent,
@@ -3604,7 +3347,7 @@ void LoadArtworkInfo()
   artwork.snd_current_identifier = artwork.snd_current->identifier;
   artwork.mus_current_identifier = artwork.mus_current->identifier;
 
-#if 0
+#if ENABLE_UNUSED_CODE
   printf("graphics set == %s\n\n", artwork.gfx_current_identifier);
   printf("sounds set == %s\n\n", artwork.snd_current_identifier);
   printf("music set == %s\n\n", artwork.mus_current_identifier);
@@ -3614,7 +3357,7 @@ void LoadArtworkInfo()
   sortTreeInfo(&artwork.snd_first);
   sortTreeInfo(&artwork.mus_first);
 
-#if 0
+#if ENABLE_UNUSED_CODE
   dumpTreeInfo(artwork.gfx_first, 0);
   dumpTreeInfo(artwork.snd_first, 0);
   dumpTreeInfo(artwork.mus_first, 0);
@@ -3624,10 +3367,6 @@ void LoadArtworkInfo()
 void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node,
 				  LevelDirTree *level_node)
 {
-#if 0
-  static unsigned long progress_delay = 0;
-  unsigned long progress_delay_value = 100;	/* (in milliseconds) */
-#endif
   int type = (*artwork_node)->type;
 
   /* recursively check all level directories for artwork sub-directories */
@@ -3672,14 +3411,7 @@ void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node,
 	setArtworkInfoCacheEntry(artwork_new, level_node, type);
     }
 
-#if 1
-    DrawInitTextExt(level_node->name, 150, FC_YELLOW,
-		    level_node->level_group);
-#else
-    if (level_node->level_group ||
-	DelayReached(&progress_delay, progress_delay_value))
-      DrawInitText(level_node->name, 150, FC_YELLOW);
-#endif
+    DrawInitText(level_node->name, 150, FC_YELLOW);
 
     if (level_node->node_group != NULL)
       LoadArtworkInfoFromLevelInfo(artwork_node, level_node->node_group);
@@ -3690,14 +3422,23 @@ void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node,
 
 void LoadLevelArtworkInfo()
 {
+  print_timestamp_init("LoadLevelArtworkInfo");
+
   DrawInitText("Looking for custom level artwork", 120, FC_GREEN);
 
+  print_timestamp_time("DrawTimeText");
+
   LoadArtworkInfoFromLevelInfo(&artwork.gfx_first, leveldir_first_all);
+  print_timestamp_time("LoadArtworkInfoFromLevelInfo (gfx)");
   LoadArtworkInfoFromLevelInfo(&artwork.snd_first, leveldir_first_all);
+  print_timestamp_time("LoadArtworkInfoFromLevelInfo (snd)");
   LoadArtworkInfoFromLevelInfo(&artwork.mus_first, leveldir_first_all);
+  print_timestamp_time("LoadArtworkInfoFromLevelInfo (mus)");
 
   SaveArtworkInfoCache();
 
+  print_timestamp_time("SaveArtworkInfoCache");
+
   /* needed for reloading level artwork not known at ealier stage */
 
   if (!strEqual(artwork.gfx_current_identifier, setup.graphics_set))
@@ -3733,15 +3474,21 @@ void LoadLevelArtworkInfo()
       artwork.mus_current = getFirstValidTreeInfoEntry(artwork.mus_first);
   }
 
+  print_timestamp_time("getTreeInfoFromIdentifier");
+
   sortTreeInfo(&artwork.gfx_first);
   sortTreeInfo(&artwork.snd_first);
   sortTreeInfo(&artwork.mus_first);
 
-#if 0
+  print_timestamp_time("sortTreeInfo");
+
+#if ENABLE_UNUSED_CODE
   dumpTreeInfo(artwork.gfx_first, 0);
   dumpTreeInfo(artwork.snd_first, 0);
   dumpTreeInfo(artwork.mus_first, 0);
 #endif
+
+  print_timestamp_done("LoadLevelArtworkInfo");
 }
 
 static void SaveUserLevelInfo()
@@ -3772,8 +3519,7 @@ static void SaveUserLevelInfo()
 
   token_value_position = TOKEN_VALUE_POSITION_SHORT;
 
-  fprintf(file, "%s\n\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER,
-						 getCookie("LEVELINFO")));
+  fprintFileHeader(file, LEVELINFO_FILENAME);
 
   ldi = *level_info;
   for (i = 0; i < NUM_LEVELINFO_TOKENS; i++)
@@ -3914,12 +3660,13 @@ void LoadLevelSetup_LastSeries()
   /* always start with reliable default values */
   leveldir_current = getFirstValidTreeInfoEntry(leveldir_first);
 
-#if defined(CREATE_SPECIAL_EDITION_RND_JUE)
-  leveldir_current = getTreeInfoFromIdentifier(leveldir_first,
-					       "jue_start");
-  if (leveldir_current == NULL)
-    leveldir_current = getFirstValidTreeInfoEntry(leveldir_first);
-#endif
+  if (!strEqual(DEFAULT_LEVELSET, UNDEFINED_LEVELSET))
+  {
+    leveldir_current = getTreeInfoFromIdentifier(leveldir_first,
+						 DEFAULT_LEVELSET);
+    if (leveldir_current == NULL)
+      leveldir_current = getFirstValidTreeInfoEntry(leveldir_first);
+  }
 
   if ((level_setup_hash = loadSetupFileHash(filename)))
   {
@@ -3931,9 +3678,6 @@ void LoadLevelSetup_LastSeries()
     if (leveldir_current == NULL)
       leveldir_current = getFirstValidTreeInfoEntry(leveldir_first);
 
-    checkSetupFileHashIdentifier(level_setup_hash, filename,
-				 getCookie("LEVELSETUP"));
-
     freeSetupFileHash(level_setup_hash);
   }
   else
@@ -3942,12 +3686,16 @@ void LoadLevelSetup_LastSeries()
   free(filename);
 }
 
-void SaveLevelSetup_LastSeries()
+static void SaveLevelSetup_LastSeries_Ext(boolean deactivate_last_level_series)
 {
   /* ----------------------------------------------------------------------- */
   /* ~/.<program>/levelsetup.conf                                            */
   /* ----------------------------------------------------------------------- */
 
+  // check if the current level directory structure is available at this point
+  if (leveldir_current == NULL)
+    return;
+
   char *filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME);
   char *level_subdir = leveldir_current->subdir;
   FILE *file;
@@ -3957,12 +3705,17 @@ void SaveLevelSetup_LastSeries()
   if (!(file = fopen(filename, MODE_WRITE)))
   {
     Error(ERR_WARN, "cannot write setup file '%s'", filename);
+
     free(filename);
+
     return;
   }
 
-  fprintf(file, "%s\n\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER,
-						 getCookie("LEVELSETUP")));
+  fprintFileHeader(file, LEVELSETUP_FILENAME);
+
+  if (deactivate_last_level_series)
+    fprintf(file, "# %s\n# ", "the following level set may have caused a problem and was deactivated");
+
   fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_LAST_LEVEL_SERIES,
 					       level_subdir));
 
@@ -3973,11 +3726,20 @@ void SaveLevelSetup_LastSeries()
   free(filename);
 }
 
+void SaveLevelSetup_LastSeries()
+{
+  SaveLevelSetup_LastSeries_Ext(FALSE);
+}
+
+void SaveLevelSetup_LastSeries_Deactivate()
+{
+  SaveLevelSetup_LastSeries_Ext(TRUE);
+}
+
 static void checkSeriesInfo()
 {
   static char *level_directory = NULL;
-  DIR *dir;
-  struct dirent *dir_entry;
+  Directory *dir;
 
   /* check for more levels besides the 'levels' field of 'levelinfo.conf' */
 
@@ -3986,42 +3748,14 @@ static void checkSeriesInfo()
 			      options.level_directory),
 			     leveldir_current->fullpath);
 
-  if ((dir = opendir(level_directory)) == NULL)
+  if ((dir = openDirectory(level_directory)) == NULL)
   {
     Error(ERR_WARN, "cannot read level directory '%s'", level_directory);
-    return;
-  }
-
-  while ((dir_entry = readdir(dir)) != NULL)	/* last directory entry */
-  {
-    if (strlen(dir_entry->d_name) > 4 &&
-	dir_entry->d_name[3] == '.' &&
-	strEqual(&dir_entry->d_name[4], LEVELFILE_EXTENSION))
-    {
-      char levelnum_str[4];
-      int levelnum_value;
-
-      strncpy(levelnum_str, dir_entry->d_name, 3);
-      levelnum_str[3] = '\0';
-
-      levelnum_value = atoi(levelnum_str);
 
-#if 0
-      if (levelnum_value < leveldir_current->first_level)
-      {
-	Error(ERR_WARN, "additional level %d found", levelnum_value);
-	leveldir_current->first_level = levelnum_value;
-      }
-      else if (levelnum_value > leveldir_current->last_level)
-      {
-	Error(ERR_WARN, "additional level %d found", levelnum_value);
-	leveldir_current->last_level = levelnum_value;
-      }
-#endif
-    }
+    return;
   }
 
-  closedir(dir);
+  closeDirectory(dir);
 }
 
 void LoadLevelSetup_SeriesInfo()
@@ -4029,11 +3763,18 @@ void LoadLevelSetup_SeriesInfo()
   char *filename;
   SetupFileHash *level_setup_hash = NULL;
   char *level_subdir = leveldir_current->subdir;
+  int i;
 
   /* always start with reliable default values */
   level_nr = leveldir_current->first_level;
 
-  checkSeriesInfo(leveldir_current);
+  for (i = 0; i < MAX_LEVELS; i++)
+  {
+    LevelStats_setPlayed(i, 0);
+    LevelStats_setSolved(i, 0);
+  }
+
+  checkSeriesInfo();
 
   /* ----------------------------------------------------------------------- */
   /* ~/.<program>/levelsetup/<level series>/levelsetup.conf                  */
@@ -4047,6 +3788,8 @@ void LoadLevelSetup_SeriesInfo()
   {
     char *token_value;
 
+    /* get last played level in this level set */
+
     token_value = getHashEntry(level_setup_hash, TOKEN_STR_LAST_PLAYED_LEVEL);
 
     if (token_value)
@@ -4059,6 +3802,8 @@ void LoadLevelSetup_SeriesInfo()
 	level_nr = leveldir_current->last_level;
     }
 
+    /* get handicap level in this level set */
+
     token_value = getHashEntry(level_setup_hash, TOKEN_STR_HANDICAP_LEVEL);
 
     if (token_value)
@@ -4076,8 +3821,30 @@ void LoadLevelSetup_SeriesInfo()
       leveldir_current->handicap_level = level_nr;
     }
 
-    checkSetupFileHashIdentifier(level_setup_hash, filename,
-				 getCookie("LEVELSETUP"));
+    /* get number of played and solved levels in this level set */
+
+    BEGIN_HASH_ITERATION(level_setup_hash, itr)
+    {
+      char *token = HASH_ITERATION_TOKEN(itr);
+      char *value = HASH_ITERATION_VALUE(itr);
+
+      if (strlen(token) == 3 &&
+	  token[0] >= '0' && token[0] <= '9' &&
+	  token[1] >= '0' && token[1] <= '9' &&
+	  token[2] >= '0' && token[2] <= '9')
+      {
+	int level_nr = atoi(token);
+
+	if (value != NULL)
+	  LevelStats_setPlayed(level_nr, atoi(value));	/* read 1st column */
+
+	value = strchr(value, ' ');
+
+	if (value != NULL)
+	  LevelStats_setSolved(level_nr, atoi(value));	/* read 2nd column */
+      }
+    }
+    END_HASH_ITERATION(hash, itr)
 
     freeSetupFileHash(level_setup_hash);
   }
@@ -4094,6 +3861,7 @@ void SaveLevelSetup_SeriesInfo()
   char *level_nr_str = int2str(level_nr, 0);
   char *handicap_level_str = int2str(leveldir_current->handicap_level, 0);
   FILE *file;
+  int i;
 
   /* ----------------------------------------------------------------------- */
   /* ~/.<program>/levelsetup/<level series>/levelsetup.conf                  */
@@ -4110,12 +3878,28 @@ void SaveLevelSetup_SeriesInfo()
     return;
   }
 
-  fprintf(file, "%s\n\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER,
-						 getCookie("LEVELSETUP")));
+  fprintFileHeader(file, LEVELSETUP_FILENAME);
+
   fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_LAST_PLAYED_LEVEL,
 					       level_nr_str));
-  fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_HANDICAP_LEVEL,
-					       handicap_level_str));
+  fprintf(file, "%s\n\n", getFormattedSetupEntry(TOKEN_STR_HANDICAP_LEVEL,
+						 handicap_level_str));
+
+  for (i = leveldir_current->first_level; i <= leveldir_current->last_level;
+       i++)
+  {
+    if (LevelStats_getPlayed(i) > 0 ||
+	LevelStats_getSolved(i) > 0)
+    {
+      char token[16];
+      char value[16];
+
+      sprintf(token, "%03d", i);
+      sprintf(value, "%d %d", LevelStats_getPlayed(i), LevelStats_getSolved(i));
+
+      fprintf(file, "%s\n", getFormattedSetupEntry(token, value));
+    }
+  }
 
   fclose(file);
 
@@ -4123,3 +3907,37 @@ void SaveLevelSetup_SeriesInfo()
 
   free(filename);
 }
+
+int LevelStats_getPlayed(int nr)
+{
+  return (nr >= 0 && nr < MAX_LEVELS ? level_stats[nr].played : 0);
+}
+
+int LevelStats_getSolved(int nr)
+{
+  return (nr >= 0 && nr < MAX_LEVELS ? level_stats[nr].solved : 0);
+}
+
+void LevelStats_setPlayed(int nr, int value)
+{
+  if (nr >= 0 && nr < MAX_LEVELS)
+    level_stats[nr].played = value;
+}
+
+void LevelStats_setSolved(int nr, int value)
+{
+  if (nr >= 0 && nr < MAX_LEVELS)
+    level_stats[nr].solved = value;
+}
+
+void LevelStats_incPlayed(int nr)
+{
+  if (nr >= 0 && nr < MAX_LEVELS)
+    level_stats[nr].played++;
+}
+
+void LevelStats_incSolved(int nr)
+{
+  if (nr >= 0 && nr < MAX_LEVELS)
+    level_stats[nr].solved++;
+}
diff --git a/src/libgame/setup.h b/src/libgame/setup.h
index b0b6a8d..1e837a5 100644
--- a/src/libgame/setup.h
+++ b/src/libgame/setup.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* setup.h                                                  *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// setup.h
+// ============================================================================
 
 #ifndef SETUP_H
 #define SETUP_H
@@ -83,9 +81,6 @@
 
 #define TYPE_ENTER_OR_LEAVE		(TYPE_ENTER | TYPE_LEAVE)
 
-/* cookie token for file identifier and version number */
-#define TOKEN_STR_FILE_IDENTIFIER	"file_identifier"
-
 struct TokenInfo
 {
   int type;
@@ -227,10 +222,12 @@ typedef struct hashtable     SetupFileHash;
 
 
 char *setLevelArtworkDir(TreeInfo *);
+char *getProgramConfigFilename(char *);
 char *getTapeFilename(int);
 char *getSolutionTapeFilename(int);
 char *getScoreFilename(int);
 char *getSetupFilename(void);
+char *getDefaultSetupFilename(void);
 char *getEditorSetupFilename(void);
 char *getHelpAnimFilename(void);
 char *getHelpTextFilename(void);
@@ -266,6 +263,7 @@ void sortTreeInfoBySortFunction(TreeInfo **,
 				int (*compare_function)(const void *,
 							const void *));
 void sortTreeInfo(TreeInfo **);
+void freeTreeInfo(TreeInfo *);
 
 char *getHomeDir(void);
 char *getCommonDataDir(void);
@@ -274,13 +272,12 @@ char *getUserGameDataDir(void);
 char *getSetupDir(void);
 char *getCurrentLevelDir(void);
 
-void updateUserGameDataDir(void);
-
 void createDirectory(char *, char *, int);
 void InitUserDataDirectory(void);
 void SetFilePermissions(char *, int);
 
 char *getCookie(char *);
+void fprintFileHeader(FILE *, char *);
 int getFileVersionFromCookieString(const char *);
 boolean checkCookieString(const char *, const char *);
 
@@ -301,7 +298,6 @@ char *getHashEntry(SetupFileHash *, char *);
 void setHashEntry(SetupFileHash *, char *, char *);
 char *removeHashEntry(SetupFileHash *, char *);
 SetupFileHash *loadSetupFileHash(char *);
-void checkSetupFileHashIdentifier(SetupFileHash *, char *, char *);
 void setSetupInfo(struct TokenInfo *, int, char *);
 char *getSetupValue(int, void *);
 char *getSetupLine(struct TokenInfo *, char *, int);
@@ -316,7 +312,15 @@ void LoadLevelArtworkInfo(void);
 
 void LoadLevelSetup_LastSeries(void);
 void SaveLevelSetup_LastSeries(void);
+void SaveLevelSetup_LastSeries_Deactivate();
 void LoadLevelSetup_SeriesInfo(void);
 void SaveLevelSetup_SeriesInfo(void);
 
+int LevelStats_getPlayed(int);
+int LevelStats_getSolved(int);
+void LevelStats_setPlayed(int, int);
+void LevelStats_setSolved(int, int);
+void LevelStats_incPlayed(int);
+void LevelStats_incSolved(int);
+
 #endif /* MISC_H */
diff --git a/src/libgame/snapshot.c b/src/libgame/snapshot.c
index d28ae34..a3c2162 100644
--- a/src/libgame/snapshot.c
+++ b/src/libgame/snapshot.c
@@ -1,25 +1,39 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* snapshot.c                                               *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// snapshot.c
+// ============================================================================
 
 #include "snapshot.h"
 
 
-static ListNode *engine_snapshot_list = NULL;
+#ifdef DEBUG
+#define DEBUG_SNAPSHOTS			0
+#endif
 
-void SaveEngineSnapshotBuffer(void *buffer, int size)
+static ListNode *snapshot_single = NULL;
+static ListNode *snapshot_list = NULL;
+static ListNode *snapshot_current = NULL;
+
+static int num_snapshots = 0;
+static int num_snapshot_buffers = 0;
+static int num_snapshot_bytes = 0;
+static int next_snapshot_key = 0;
+
+
+// -----------------------------------------------------------------------------
+// functions for handling buffers for a single snapshot
+// -----------------------------------------------------------------------------
+
+void SaveSnapshotBuffer(ListNode **snapshot_buffers, void *buffer, int size)
 {
-  struct EngineSnapshotNodeInfo *bi =
-    checked_calloc(sizeof(struct EngineSnapshotNodeInfo));
+  struct SnapshotNodeInfo *bi =
+    checked_calloc(sizeof(struct SnapshotNodeInfo));
 
   bi->buffer_orig = buffer;
   bi->buffer_copy = checked_malloc(size);
@@ -27,29 +41,218 @@ void SaveEngineSnapshotBuffer(void *buffer, int size)
 
   memcpy(bi->buffer_copy, buffer, size);
 
-  addNodeToList(&engine_snapshot_list, NULL, bi);
+  addNodeToList(snapshot_buffers, NULL, bi);
+
+  num_snapshot_buffers++;
+  num_snapshot_bytes += size;
 }
 
-static void LoadEngineSnapshotBuffer(struct EngineSnapshotNodeInfo *bi)
+static void LoadSnapshotBuffer(struct SnapshotNodeInfo *bi)
 {
   memcpy(bi->buffer_orig, bi->buffer_copy, bi->size);
 }
 
-void LoadEngineSnapshotBuffers()
+void LoadSnapshotBuffers(ListNode *snapshot_buffers)
+{
+  while (snapshot_buffers != NULL)
+  {
+    LoadSnapshotBuffer((struct SnapshotNodeInfo *)snapshot_buffers->content);
+
+    snapshot_buffers = snapshot_buffers->next;
+  }
+}
+
+static void FreeSnapshotBuffer(void *bi_raw)
 {
-  ListNode *node = engine_snapshot_list;
+  struct SnapshotNodeInfo *bi = (struct SnapshotNodeInfo *)bi_raw;
+
+  num_snapshot_buffers--;
+  num_snapshot_bytes -= bi->size;
+
+  checked_free(bi->buffer_copy);
+  checked_free(bi);
+}
+
+void FreeSnapshotBuffers(ListNode *snapshot_buffers)
+{
+  while (snapshot_buffers != NULL)
+    deleteNodeFromList(&snapshot_buffers, NULL, FreeSnapshotBuffer);
+}
+
+// -----------------------------------------------------------------------------
+// functions for handling single shapshot or list of snapshots
+// -----------------------------------------------------------------------------
+
+static void FreeSnapshot(void *snapshot_buffers_ptr)
+{
+  FreeSnapshotBuffers(snapshot_buffers_ptr);
+}
+
+void FreeSnapshotSingle()
+{
+  FreeSnapshotBuffers(snapshot_single);
+
+  snapshot_single = NULL;
+}
+
+static void FreeSnapshotList_UpToNode(ListNode *node)
+{
+  while (snapshot_list != node)
+  {
+#if DEBUG_SNAPSHOTS
+    printf("::: FreeSnapshotList_*() [%s, %d, %d]\n",
+	   snapshot_list->key, num_snapshot_buffers, num_snapshot_bytes);
+#endif
+
+    deleteNodeFromList(&snapshot_list, snapshot_list->key, FreeSnapshot);
+
+    num_snapshots--;
+    next_snapshot_key = (snapshot_list ? atoi(snapshot_list->key) + 1 : 0);
+  }
+}
+
+void FreeSnapshotList()
+{
+#if DEBUG_SNAPSHOTS
+  printf("::: FreeSnapshotList()\n");
+#endif
+
+  FreeSnapshotList_UpToNode(NULL);
+
+  num_snapshots = 0;
+  num_snapshot_buffers = 0;
+  num_snapshot_bytes = 0;
+  next_snapshot_key = 0;
+
+  snapshot_current = NULL;
+}
+
+void ReduceSnapshotList()
+{
+#if DEBUG_SNAPSHOTS
+  printf("::: (Reducing number of snapshots from %d ",
+	 num_snapshots);
+#endif
+
+  // maximum number of snapshots exceeded -- thin out list of snapshots
+  ListNode *node = snapshot_list;
+  int num_snapshots_to_skip = num_snapshots / 10;
+
+  // do not remove the newest snapshots from the list
+  while (node && num_snapshots_to_skip--)
+    node = node->next;
 
-  while (node != NULL)
+  // remove every second snapshot from the remaining list
+  while (node)
   {
-    LoadEngineSnapshotBuffer((struct EngineSnapshotNodeInfo *)node->content);
+    // never delete the first list node (snapshot at game start)
+    if (node->next == NULL)
+      break;
 
+    // in alternation, delete one node from the list ...
+    deleteNodeFromList(&node, node->key, FreeSnapshot);
+    num_snapshots--;
+
+    // ... and keep one node (which always exists here)
+    node = node->next;
+  }
+
+#if DEBUG_SNAPSHOTS
+  printf("to %d.)\n", num_snapshots);
+
+#if 0
+  node = snapshot_list;
+  while (node)
+  {
+    printf("::: key: %s\n", node->key);
     node = node->next;
   }
+#endif
+#endif
+}
+
+void SaveSnapshotSingle(ListNode *snapshot_buffers)
+{
+  if (snapshot_single)
+    FreeSnapshotSingle();
+
+  snapshot_single = snapshot_buffers;
+}
+
+void SaveSnapshotToList(ListNode *snapshot_buffers)
+{
+  if (snapshot_current != snapshot_list)
+    FreeSnapshotList_UpToNode(snapshot_current);
+
+#if DEBUG_SNAPSHOTS
+  printf("::: SaveSnapshotToList() [%d] [%d snapshots, %d buffers, %d bytes]\n",
+	 next_snapshot_key, num_snapshots,
+	 num_snapshot_buffers, num_snapshot_bytes);
+#endif
+
+  addNodeToList(&snapshot_list, i_to_a(next_snapshot_key),
+		snapshot_buffers);
+
+  snapshot_current = snapshot_list;
+
+  num_snapshots++;
+  next_snapshot_key++;
+
+  if (num_snapshot_bytes > setup.engine_snapshot_memory)
+    ReduceSnapshotList();
+}
+
+boolean LoadSnapshotSingle()
+{
+  if (snapshot_single)
+  {
+    LoadSnapshotBuffers(snapshot_single);
+
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+boolean LoadSnapshotFromList_Older(int steps)
+{
+  if (snapshot_current && snapshot_current->next)
+  {
+    while (snapshot_current->next && steps--)
+      snapshot_current = snapshot_current->next;
+
+    LoadSnapshotBuffers(snapshot_current->content);
+
+#if DEBUG_SNAPSHOTS
+    printf("::: LoadSnapshotFromList_Older() [%s]\n", snapshot_current->key);
+#endif
+
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+boolean LoadSnapshotFromList_Newer(int steps)
+{
+  if (snapshot_current && snapshot_current->prev)
+  {
+    while (snapshot_current->prev && steps--)
+      snapshot_current = snapshot_current->prev;
+
+    LoadSnapshotBuffers(snapshot_current->content);
+
+#if DEBUG_SNAPSHOTS
+    printf("::: LoadSnapshotFromList_Newer() [%s]\n", snapshot_current->key);
+#endif
+
+    return TRUE;
+  }
+
+  return FALSE;
 }
 
-void FreeEngineSnapshotBuffers()
+boolean CheckSnapshotList()
 {
-  while (engine_snapshot_list != NULL)
-    deleteNodeFromList(&engine_snapshot_list, engine_snapshot_list->key,
-		       checked_free);
+  return (snapshot_list ? TRUE : FALSE);
 }
diff --git a/src/libgame/snapshot.h b/src/libgame/snapshot.h
index 706fc05..54ce381 100644
--- a/src/libgame/snapshot.h
+++ b/src/libgame/snapshot.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* snapshot.h                                               *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// snapshot.h
+// ============================================================================
 
 #ifndef SNAPSHOT_H
 #define SNAPSHOT_H
@@ -18,10 +16,12 @@
 #include "misc.h"
 
 
+#define SNAPSHOT_MEMORY_DEFAULT		(512 * 1024 * 1024)
+
 /* needed for comfortably saving engine snapshot buffers */
-#define ARGS_ADDRESS_AND_SIZEOF(x)		(&(x)), (sizeof(x))
+#define ARGS_ADDRESS_AND_SIZEOF(x)	(&(x)), (sizeof(x))
 
-struct EngineSnapshotNodeInfo
+struct SnapshotNodeInfo
 {
   void *buffer_orig;
   void *buffer_copy;
@@ -29,8 +29,17 @@ struct EngineSnapshotNodeInfo
 };
 
 
-void SaveEngineSnapshotBuffer(void *buffer, int size);
-void LoadEngineSnapshotBuffers();
-void FreeEngineSnapshotBuffers();
+void SaveSnapshotBuffer(ListNode **, void *, int);
+void LoadSnapshotBuffers(ListNode *);
+void FreeSnapshotBuffers(ListNode *);
+
+void SaveSnapshotSingle(ListNode *);
+void SaveSnapshotToList(ListNode *);
+boolean LoadSnapshotSingle();
+boolean LoadSnapshotFromList_Older(int);
+boolean LoadSnapshotFromList_Newer(int);
+boolean CheckSnapshotList();
+void FreeSnapshotSingle();
+void FreeSnapshotList();
 
 #endif	/* SNAPSHOT_H */
diff --git a/src/libgame/sound.c b/src/libgame/sound.c
index d620dd9..cb788e7 100644
--- a/src/libgame/sound.c
+++ b/src/libgame/sound.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* sound.c                                                  *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// sound.c
+// ============================================================================
 
 #include <sys/types.h>
 #include <sys/time.h>
@@ -19,21 +17,9 @@
 #include <dirent.h>
 #include <signal.h>
 #include <math.h>
+#include <errno.h>
 
 #include "platform.h"
-
-#if defined(PLATFORM_LINUX)
-#include <sys/ioctl.h>
-#include <linux/soundcard.h>
-#elif defined(PLATFORM_FREEBSD)
-#include <machine/soundcard.h>
-#elif defined(PLATFORM_NETBSD)
-#include <sys/ioctl.h>
-#include <sys/audioio.h>
-#elif defined(PLATFORM_HPUX)
-#include <sys/audio.h>
-#endif
-
 #include "system.h"
 #include "sound.h"
 #include "misc.h"
@@ -47,11 +33,6 @@
 /* one second fading interval == 1000 ticks (milliseconds) */
 #define SOUND_FADING_INTERVAL		1000
 
-#if defined(AUDIO_STREAMING_DSP)
-#define SOUND_FADING_VOLUME_STEP	(SOUND_MAX_VOLUME / 40)
-#define SOUND_FADING_VOLUME_THRESHOLD	(SOUND_FADING_VOLUME_STEP * 2)
-#endif
-
 #define SND_TYPE_NONE			0
 #define SND_TYPE_WAV			1
 
@@ -70,17 +51,19 @@
 #define SAME_SOUND_NR(x,y)		((x).nr == (y).nr)
 #define SAME_SOUND_DATA(x,y)		((x).data_ptr == (y).data_ptr)
 
-#if defined(AUDIO_UNIX_NATIVE)
-struct SoundHeader_WAV
-{
-  unsigned short compression_code;
-  unsigned short num_channels;
-  unsigned long  sample_rate;
-  unsigned long  bytes_per_second;
-  unsigned short block_align;
-  unsigned short bits_per_sample;
-};
-#endif
+#define SOUND_VOLUME_FROM_PERCENT(v,p)	((p) < 0   ? SOUND_MIN_VOLUME :	\
+					 (p) > 100 ? (v) :		\
+					 (p) * (v) / 100)
+
+#define SOUND_VOLUME_SIMPLE(v) SOUND_VOLUME_FROM_PERCENT(v, setup.volume_simple)
+#define SOUND_VOLUME_LOOPS(v)  SOUND_VOLUME_FROM_PERCENT(v, setup.volume_loops)
+#define SOUND_VOLUME_MUSIC(v)  SOUND_VOLUME_FROM_PERCENT(v, setup.volume_music)
+
+#define SETUP_SOUND_VOLUME(v,s)		((s) == SND_CTRL_PLAY_MUSIC ?	\
+					 SOUND_VOLUME_MUSIC(v) :	\
+					 (s) == SND_CTRL_PLAY_LOOP ?	\
+					 SOUND_VOLUME_LOOPS(v) :	\
+					 SOUND_VOLUME_SIMPLE(v))
 
 struct AudioFormatInfo
 {
@@ -98,7 +81,7 @@ struct SampleInfo
   int type;
   int format;
   void *data_ptr;		/* pointer to first sample (8 or 16 bit) */
-  long data_len;		/* number of samples, NOT number of bytes */
+  int data_len;			/* number of samples, NOT number of bytes */
   int num_channels;		/* mono: 1 channel, stereo: 2 channels */
 };
 typedef struct SampleInfo SoundInfo;
@@ -114,18 +97,14 @@ struct SoundControl
 
   int state;
 
-  unsigned long playing_starttime;
-  unsigned long playing_pos;
+  unsigned int playing_starttime;
+  unsigned int playing_pos;
 
   int type;
   int format;
   void *data_ptr;		/* pointer to first sample (8 or 16 bit) */
-  long data_len;		/* number of samples, NOT number of bytes */
+  int data_len;		/* number of samples, NOT number of bytes */
   int num_channels;		/* mono: 1 channel, stereo: 2 channels */
-
-#if defined(TARGET_ALLEGRO)
-  int voice;
-#endif
 };
 typedef struct SoundControl SoundControl;
 
@@ -137,22 +116,15 @@ static MusicInfo **Music_NoConf = NULL;
 static int num_music_noconf = 0;
 static int stereo_volume[SOUND_MAX_LEFT2RIGHT + 1];
 
+static char *currently_playing_music_filename = NULL;
+
 
 /* ========================================================================= */
 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS            */
 
 static struct SoundControl mixer[NUM_MIXER_CHANNELS];
 static int mixer_active_channels = 0;
-
-#if defined(AUDIO_UNIX_NATIVE)
-static struct AudioFormatInfo afmt;
-
-static void Mixer_Main(void);
-#if !defined(AUDIO_STREAMING_DSP)
-static unsigned char linear_to_ulaw(int);
-static int ulaw_to_linear(unsigned char);
-#endif
-#endif
+static boolean expire_loop_sounds = FALSE;
 
 static void ReloadCustomSounds();
 static void ReloadCustomMusic();
@@ -165,442 +137,6 @@ static MusicInfo *getMusicInfoEntryFromMusicID(int);
 
 
 /* ------------------------------------------------------------------------- */
-/* functions for native (non-SDL) Unix audio/mixer support                   */
-/* ------------------------------------------------------------------------- */
-
-#if defined(AUDIO_UNIX_NATIVE)
-
-static int OpenAudioDevice(char *audio_device_name)
-{
-  int audio_device_fd;
-
-  /* check if desired audio device is accessible */
-  if (access(audio_device_name, W_OK) != 0)
-    return -1;
-
-  /* try to open audio device in non-blocking mode */
-  if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
-    return audio_device_fd;
-
-  /* re-open audio device in blocking mode */
-  close(audio_device_fd);
-  audio_device_fd = open(audio_device_name, O_WRONLY);
-
-  return audio_device_fd;
-}
-
-static void CloseAudioDevice(int *audio_device_fd)
-{
-  if (*audio_device_fd == 0)
-    return;
-
-  close(*audio_device_fd);
-  *audio_device_fd = -1;
-}
-
-static boolean TestAudioDevices(void)
-{
-  static char *audio_device_name[] =
-  {
-    DEVICENAME_DSP,
-    DEVICENAME_SOUND_DSP,
-    DEVICENAME_AUDIO
-  };
-  int audio_device_fd = -1;
-  int i;
-
-  /* look for available audio devices, starting with preferred ones */
-  for (i = 0; i < sizeof(audio_device_name)/sizeof(char *); i++)
-    if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
-      break;
-
-  if (audio_device_fd < 0)
-  {
-    Error(ERR_WARN, "cannot open audio device -- no sound");
-    return FALSE;
-  }
-
-  close(audio_device_fd);
-
-  audio.device_name = audio_device_name[i];
-
-  return TRUE;
-}
-
-static boolean ForkAudioProcess(void)
-{
-  if (pipe(audio.mixer_pipe) < 0)
-  {
-    Error(ERR_WARN, "cannot create pipe -- no sounds");
-    return FALSE;
-  }
-
-  if ((audio.mixer_pid = fork()) < 0)
-  {       
-    Error(ERR_WARN, "cannot create sound server process -- no sounds");
-    return FALSE;
-  }
-
-  if (audio.mixer_pid == 0)		/* we are the child process */
-    audio.mixer_pid = getpid();
-
-  if (IS_CHILD_PROCESS())
-    Mixer_Main();			/* this function never returns */
-  else
-    close(audio.mixer_pipe[0]);		/* no reading from pipe needed */
-
-  return TRUE;
-}
-
-void UnixOpenAudio(void)
-{
-  if (!TestAudioDevices())
-    return;
-
-  audio.sound_available = TRUE;
-  audio.sound_enabled = TRUE;
-
-#if defined(AUDIO_STREAMING_DSP)
-  audio.music_available = TRUE;
-  audio.loops_available = TRUE;
-#endif
-
-  audio.num_channels = NUM_MIXER_CHANNELS;
-  audio.music_channel = MUSIC_CHANNEL;
-  audio.first_sound_channel = FIRST_SOUND_CHANNEL;
-}
-
-void UnixCloseAudio(void)
-{
-  if (audio.device_fd)
-    close(audio.device_fd);
-
-  if (IS_PARENT_PROCESS() && HAS_CHILD_PROCESS())
-    kill(audio.mixer_pid, SIGTERM);
-}
-
-
-/* ------------------------------------------------------------------------- */
-/* functions for platform specific audio device initialization               */
-/* ------------------------------------------------------------------------- */
-
-#if defined(AUDIO_LINUX_IOCTL)
-static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
-{
-  /* "ioctl()" expects pointer to 'int' value for stereo flag
-     (boolean is defined as 'char', which will not work here) */
-  unsigned int fragment_spec = 0;
-  int fragment_size_query = -1;
-  int stereo = TRUE;
-  struct
-  {
-    int format_ioctl;
-    int format_result;
-  }
-  formats[] =
-  {
-    /* supported audio format in preferred order */
-    { AFMT_S16_LE,	AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
-    { AFMT_S16_BE,	AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
-    { AFMT_U8,		AUDIO_FORMAT_U8                    },
-    { -1,		-1 }
-  };
-  int i;
-
-  /* determine logarithm (log2) of the fragment size */
-  while ((1 << fragment_spec) < afmt->fragment_size)
-    fragment_spec++;
-
-  /* use two fragments (play one fragment, prepare the other);
-     one fragment would result in interrupted audio output, more
-     than two fragments would raise audio output latency to much */
-  fragment_spec |= 0x00020000;
-
-  /* Example for fragment specification:
-     - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
-     - (with stereo the effective buffer size will shrink to 256)
-     => fragment_size = 0x00020009 */
-
-  if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
-    Error(ERR_EXIT_SOUND_SERVER,
-	  "cannot set fragment size of audio device -- no sounds");
-
-  i = 0;
-  afmt->format = 0;
-  while (formats[i].format_result != -1)
-  {
-    unsigned int audio_format = formats[i].format_ioctl;
-    if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
-    {
-      afmt->format = formats[i].format_result;
-      break;
-    }
-  }
-
-  if (afmt->format == 0)	/* no supported audio format found */
-    Error(ERR_EXIT_SOUND_SERVER,
-	  "cannot set audio format of audio device -- no sounds");
-
-  /* try if we can use stereo sound */
-  afmt->stereo = TRUE;
-  if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
-    afmt->stereo = FALSE;
-
-  if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
-    Error(ERR_EXIT_SOUND_SERVER,
-	  "cannot set sample rate of audio device -- no sounds");
-
-  /* get the real fragmentation size; this should return 512 */
-  if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
-    Error(ERR_EXIT_SOUND_SERVER,
-	  "cannot get fragment size of audio device -- no sounds");
-  if (fragment_size_query != afmt->fragment_size)
-    Error(ERR_EXIT_SOUND_SERVER,
-	  "cannot set fragment size of audio device -- no sounds");
-}
-#endif	/* AUDIO_LINUX_IOCTL */
-
-#if defined(PLATFORM_NETBSD)
-static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
-{
-  audio_info_t a_info;
-  boolean stereo = TRUE;
-
-  AUDIO_INITINFO(&a_info);
-  a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
-  a_info.play.precision = 8;
-  a_info.play.channels = 2;
-  a_info.play.sample_rate = afmt->sample_rate;
-  a_info.blocksize = afmt->fragment_size;
-
-  afmt->format = AUDIO_FORMAT_U8;
-  afmt->stereo = TRUE;
-
-  if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
-  {
-    /* try to disable stereo */
-    a_info.play.channels = 1;
-
-    afmt->stereo = FALSE;
-
-    if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
-      Error(ERR_EXIT_SOUND_SERVER,
-	    "cannot set sample rate of audio device -- no sounds");
-  }
-}
-#endif /* PLATFORM_NETBSD */
-
-#if defined(PLATFORM_HPUX)
-static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
-{
-  struct audio_describe ainfo;
-  int audio_ctl;
-
-  audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
-  if (audio_ctl == -1)
-    Error(ERR_EXIT_SOUND_SERVER, "cannot open audio device -- no sounds");
-
-  if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
-    Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
-
-  if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
-    Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
-
-  ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
-  ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
-
-  afmt->format = AUDIO_FORMAT_U8;
-  afmt->stereo = FALSE;
-  afmt->sample_rate = 8000;
-
-  close(audio_ctl);
-}
-#endif /* PLATFORM_HPUX */
-
-static void InitAudioDevice(struct AudioFormatInfo *afmt)
-{
-  afmt->stereo = TRUE;
-  afmt->format = AUDIO_FORMAT_UNKNOWN;
-  afmt->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
-  afmt->fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
-
-#if defined(AUDIO_LINUX_IOCTL)
-  InitAudioDevice_Linux(afmt);
-#elif defined(PLATFORM_NETBSD)
-  InitAudioDevice_NetBSD(afmt);
-#elif defined(PLATFORM_HPUX)
-  InitAudioDevice_HPUX(afmt);
-#else
-  /* generic /dev/audio stuff might be placed here */
-#endif
-}
-
-
-/* ------------------------------------------------------------------------- */
-/* functions for communication between main process and sound mixer process  */
-/* ------------------------------------------------------------------------- */
-
-static void SendSoundControlToMixerProcess(SoundControl *snd_ctrl)
-{
-  if (IS_CHILD_PROCESS())
-    return;
-
-  if (write(audio.mixer_pipe[1], snd_ctrl, sizeof(SoundControl)) < 0)
-  {
-    Error(ERR_WARN, "cannot pipe to child process -- no sounds");
-    audio.sound_available = audio.sound_enabled = FALSE;
-    return;
-  }
-}
-
-static void ReadSoundControlFromMainProcess(SoundControl *snd_ctrl)
-{
-  if (IS_PARENT_PROCESS())
-    return;
-
-  if (read(audio.mixer_pipe[0], snd_ctrl, sizeof(SoundControl))
-      != sizeof(SoundControl))
-    Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
-}
-
-static void WriteReloadInfoToPipe(char *set_identifier, int type)
-{
-  SoundControl snd_ctrl;
-  TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
-		  artwork.mus_current);
-  unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
-  unsigned long str_size2 = strlen(leveldir_current->sounds_path) + 1;
-  unsigned long str_size3 = strlen(leveldir_current->music_path) + 1;
-  unsigned long str_size4 = strlen(ti->basepath) + 1;
-  unsigned long str_size5 = strlen(ti->fullpath) + 1;
-  boolean override_level_artwork = (type == SND_CTRL_RELOAD_SOUNDS ?
-				    gfx.override_level_sounds :
-				    gfx.override_level_music);
-
-  if (IS_CHILD_PROCESS())
-    return;
-
-  if (leveldir_current == NULL)		/* should never happen */
-    Error(ERR_EXIT, "leveldir_current == NULL");
-
-  clear_mem(&snd_ctrl, sizeof(SoundControl));	/* to make valgrind happy */
-
-  snd_ctrl.active = FALSE;
-  snd_ctrl.state = type;
-  snd_ctrl.data_len = strlen(set_identifier) + 1;
-
-  if (write(audio.mixer_pipe[1], &snd_ctrl,
-	    sizeof(snd_ctrl)) < 0 ||
-      write(audio.mixer_pipe[1], set_identifier,
-	    snd_ctrl.data_len) < 0 ||
-      write(audio.mixer_pipe[1], &override_level_artwork,
-	    sizeof(boolean)) < 0 ||
-      write(audio.mixer_pipe[1], leveldir_current,
-	    sizeof(TreeInfo)) < 0 ||
-      write(audio.mixer_pipe[1], ti,
-	    sizeof(TreeInfo)) < 0 ||
-      write(audio.mixer_pipe[1], &str_size1,
-	    sizeof(unsigned long)) < 0 ||
-      write(audio.mixer_pipe[1], &str_size2,
-	    sizeof(unsigned long)) < 0 ||
-      write(audio.mixer_pipe[1], &str_size3,
-	    sizeof(unsigned long)) < 0 ||
-      write(audio.mixer_pipe[1], &str_size4,
-	    sizeof(unsigned long)) < 0 ||
-      write(audio.mixer_pipe[1], &str_size5,
-	    sizeof(unsigned long)) < 0 ||
-      write(audio.mixer_pipe[1], leveldir_current->fullpath,
-	    str_size1) < 0 ||
-      write(audio.mixer_pipe[1], leveldir_current->sounds_path,
-	    str_size2) < 0 ||
-      write(audio.mixer_pipe[1], leveldir_current->music_path,
-	    str_size3) < 0 ||
-      write(audio.mixer_pipe[1], ti->basepath,
-	    str_size4) < 0 ||
-      write(audio.mixer_pipe[1], ti->fullpath,
-	    str_size5) < 0)
-  {
-    Error(ERR_WARN, "cannot pipe to child process -- no sounds");
-    audio.sound_available = audio.sound_enabled = FALSE;
-    return;
-  }
-}
-
-static void ReadReloadInfoFromPipe(SoundControl *snd_ctrl)
-{
-  TreeInfo **ti_ptr = ((snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS) ?
-		       &artwork.snd_current : &artwork.mus_current);
-  TreeInfo *ti = *ti_ptr;
-  unsigned long str_size1, str_size2, str_size3, str_size4, str_size5;
-  static char *set_identifier = NULL;
-  boolean *override_level_artwork = (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS ?
-				     &gfx.override_level_sounds :
-				     &gfx.override_level_music);
-
-  checked_free(set_identifier);
-
-  set_identifier = checked_malloc(snd_ctrl->data_len);
-
-  if (leveldir_current == NULL)
-    leveldir_current = checked_calloc(sizeof(TreeInfo));
-
-  if (ti == NULL)
-    ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
-
-  checked_free(leveldir_current->fullpath);
-  checked_free(leveldir_current->sounds_path);
-  checked_free(leveldir_current->music_path);
-  checked_free(ti->basepath);
-  checked_free(ti->fullpath);
-
-  if (read(audio.mixer_pipe[0], set_identifier,
-	   snd_ctrl->data_len) != snd_ctrl->data_len ||
-      read(audio.mixer_pipe[0], override_level_artwork,
-	   sizeof(boolean)) != sizeof(boolean) ||
-      read(audio.mixer_pipe[0], leveldir_current,
-	   sizeof(TreeInfo)) != sizeof(TreeInfo) ||
-      read(audio.mixer_pipe[0], ti,
-	   sizeof(TreeInfo)) != sizeof(TreeInfo) ||
-      read(audio.mixer_pipe[0], &str_size1,
-	   sizeof(unsigned long)) != sizeof(unsigned long) ||
-      read(audio.mixer_pipe[0], &str_size2,
-	   sizeof(unsigned long)) != sizeof(unsigned long) ||
-      read(audio.mixer_pipe[0], &str_size3,
-	   sizeof(unsigned long)) != sizeof(unsigned long) ||
-      read(audio.mixer_pipe[0], &str_size4,
-	   sizeof(unsigned long)) != sizeof(unsigned long) ||
-      read(audio.mixer_pipe[0], &str_size5,
-	   sizeof(unsigned long)) != sizeof(unsigned long))
-    Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
-
-  leveldir_current->fullpath = checked_calloc(str_size1);
-  leveldir_current->sounds_path = checked_calloc(str_size2);
-  leveldir_current->music_path = checked_calloc(str_size3);
-  ti->basepath = checked_calloc(str_size4);
-  ti->fullpath = checked_calloc(str_size5);
-
-  if (read(audio.mixer_pipe[0], leveldir_current->fullpath,
-	   str_size1) != str_size1 ||
-      read(audio.mixer_pipe[0], leveldir_current->sounds_path,
-	   str_size2) != str_size2 ||
-      read(audio.mixer_pipe[0], leveldir_current->music_path,
-	   str_size3) != str_size3 ||
-      read(audio.mixer_pipe[0], ti->basepath,
-	   str_size4) != str_size4 ||
-      read(audio.mixer_pipe[0], ti->fullpath,
-	   str_size5) != str_size5)
-    Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
-
-  if (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS)
-    artwork.snd_current_identifier = set_identifier;
-  else
-    artwork.mus_current_identifier = set_identifier;
-}
-
-#endif /* AUDIO_UNIX_NATIVE */
-
-
-/* ------------------------------------------------------------------------- */
 /* mixer functions                                                           */
 /* ------------------------------------------------------------------------- */
 
@@ -617,10 +153,9 @@ static void Mixer_ResetChannelExpiration(int channel)
 {
   mixer[channel].playing_starttime = Counter();
 
-#if defined(TARGET_SDL)
-  if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]))
+  if (expire_loop_sounds &&
+      IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]))
     Mix_ExpireChannel(channel, SOUND_LOOP_EXPIRATION_TIME);
-#endif
 }
 
 static boolean Mixer_ChannelExpired(int channel)
@@ -628,65 +163,35 @@ static boolean Mixer_ChannelExpired(int channel)
   if (!mixer[channel].active)
     return TRUE;
 
-  if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]) &&
+  if (expire_loop_sounds &&
+      IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]) &&
       DelayReached(&mixer[channel].playing_starttime,
 		   SOUND_LOOP_EXPIRATION_TIME))
     return TRUE;
 
-#if defined(TARGET_SDL)
-
   if (!Mix_Playing(channel))
     return TRUE;
 
-#elif defined(TARGET_ALLEGRO)
-
-  mixer[channel].playing_pos = voice_get_position(mixer[channel].voice);
-  mixer[channel].volume = voice_get_volume(mixer[channel].voice);
-
-  /* sound sample has completed playing or was completely faded out */
-  if (mixer[channel].playing_pos == -1 || mixer[channel].volume == 0)
-    return TRUE;
-
-#endif /* TARGET_ALLEGRO */
-
   return FALSE;
 }
 
 static boolean Mixer_AllocateChannel(int channel)
 {
-#if defined(TARGET_ALLEGRO)
-  mixer[channel].voice = allocate_voice((SAMPLE *)mixer[channel].data_ptr);
-  if (mixer[channel].voice < 0)
-    return FALSE;
-#endif
-
   return TRUE;
 }
 
 static void Mixer_SetChannelProperties(int channel)
 {
-#if defined(TARGET_SDL)
   Mix_Volume(channel, mixer[channel].volume);
   Mix_SetPanning(channel,
 		 SOUND_VOLUME_LEFT(mixer[channel].stereo_position),
 		 SOUND_VOLUME_RIGHT(mixer[channel].stereo_position));
-#elif defined(TARGET_ALLEGRO)
-  voice_set_volume(mixer[channel].voice, mixer[channel].volume);
-  voice_set_pan(mixer[channel].voice, mixer[channel].stereo_position);
-#endif
 }
 
 static void Mixer_StartChannel(int channel)
 {
-#if defined(TARGET_SDL)
   Mix_PlayChannel(channel, mixer[channel].data_ptr,
 		  IS_LOOP(mixer[channel]) ? -1 : 0);
-#elif defined(TARGET_ALLEGRO)
-  if (IS_LOOP(mixer[channel]))
-    voice_set_playmode(mixer[channel].voice, PLAYMODE_LOOP);
-
-  voice_start(mixer[channel].voice);       
-#endif
 }
 
 static void Mixer_PlayChannel(int channel)
@@ -714,15 +219,13 @@ static void Mixer_PlayMusicChannel()
 {
   Mixer_PlayChannel(audio.music_channel);
 
-#if defined(TARGET_SDL)
   if (mixer[audio.music_channel].type != MUS_TYPE_WAV)
   {
-    /* Mix_VolumeMusic() must be called _after_ Mix_PlayMusic() --
-       this looks like a bug in the SDL_mixer library */
-    Mix_PlayMusic(mixer[audio.music_channel].data_ptr, -1);
-    Mix_VolumeMusic(SOUND_MAX_VOLUME);
+    // use short fade-in to prevent "plop" sound for certain music files
+    // (this may happen when switching on music while playing the game)
+    Mix_VolumeMusic(mixer[audio.music_channel].volume);
+    Mix_FadeInMusic(mixer[audio.music_channel].data_ptr, -1, 100);
   }
-#endif
 }
 
 static void Mixer_StopChannel(int channel)
@@ -730,12 +233,7 @@ static void Mixer_StopChannel(int channel)
   if (!mixer[channel].active)
     return;
 
-#if defined(TARGET_SDL)
   Mix_HaltChannel(channel);
-#elif defined(TARGET_ALLEGRO)
-  voice_set_volume(mixer[channel].voice, 0);
-  deallocate_voice(mixer[channel].voice);
-#endif
 
   mixer[channel].active = FALSE;
   mixer_active_channels--;
@@ -745,9 +243,9 @@ static void Mixer_StopMusicChannel()
 {
   Mixer_StopChannel(audio.music_channel);
 
-#if defined(TARGET_SDL)
   Mix_HaltMusic();
-#endif
+
+  setString(&currently_playing_music_filename, NULL);
 }
 
 static void Mixer_FadeChannel(int channel)
@@ -757,21 +255,16 @@ static void Mixer_FadeChannel(int channel)
 
   mixer[channel].state |= SND_CTRL_FADE;
 
-#if defined(TARGET_SDL)
   Mix_FadeOutChannel(channel, SOUND_FADING_INTERVAL);
-#elif defined(TARGET_ALLEGRO)
-  if (voice_check(mixer[channel].voice))
-    voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL, 0);
-#endif
 }
 
 static void Mixer_FadeMusicChannel()
 {
   Mixer_FadeChannel(audio.music_channel);
 
-#if defined(TARGET_SDL)
   Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
-#endif
+
+  setString(&currently_playing_music_filename, NULL);
 }
 
 static void Mixer_UnFadeChannel(int channel)
@@ -782,14 +275,8 @@ static void Mixer_UnFadeChannel(int channel)
   mixer[channel].state &= ~SND_CTRL_FADE;
   mixer[channel].volume = SOUND_MAX_VOLUME;
 
-#if defined(TARGET_SDL)
   Mix_ExpireChannel(channel, -1);
   Mix_Volume(channel, mixer[channel].volume);
-#elif defined(TARGET_ALLEGRO)
-  voice_stop_volumeramp(mixer[channel].voice);
-  voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL,
-		    mixer[channel].volume);
-#endif
 }
 
 static void Mixer_InsertSound(SoundControl snd_ctrl)
@@ -841,6 +328,9 @@ static void Mixer_InsertSound(SoundControl snd_ctrl)
     mixer[audio.music_channel] = snd_ctrl;
     Mixer_PlayMusicChannel();
 
+    setString(&currently_playing_music_filename,
+	      getBaseNamePtr(snd_info->source_filename));
+
     return;
   }
 
@@ -874,7 +364,7 @@ static void Mixer_InsertSound(SoundControl snd_ctrl)
   /* don't play sound more than n times simultaneously (with n == 2 for now) */
   if (k >= 2)
   {
-    unsigned long playing_current = Counter();
+    unsigned int playing_current = Counter();
     int longest = 0, longest_nr = audio.first_sound_channel;
 
     /* look for oldest equal sound */
@@ -925,20 +415,9 @@ static void Mixer_InsertSound(SoundControl snd_ctrl)
   if (mixer_active_channels ==
       audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
   {
-    unsigned long playing_current = Counter();
+    unsigned int playing_current = Counter();
     int longest = 0, longest_nr = audio.first_sound_channel;
 
-#if 0
-#if DEBUG
-    /* print some debugging information about audio channel usage */
-    for (i = audio.first_sound_channel; i < audio.num_channels; i++)
-    {
-      Error(ERR_INFO, "Mixer_InsertSound: %d [%d]: %ld (%ld)",
-	    i, mixer[i].active, mixer[i].data_len, (long)mixer[i].data_ptr);
-    }
-#endif
-#endif
-
     for (i = audio.first_sound_channel; i < audio.num_channels; i++)
     {
       int playing_time = playing_current - mixer[i].playing_starttime;
@@ -959,13 +438,6 @@ static void Mixer_InsertSound(SoundControl snd_ctrl)
   {
     if (!mixer[i].active)
     {
-#if defined(AUDIO_UNIX_NATIVE)
-      if (snd_info->data_len == 0)
-      {
-	printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
-      }
-#endif
-
       mixer[i] = snd_ctrl;
       Mixer_PlayChannel(i);
 
@@ -978,14 +450,6 @@ static void HandleSoundRequest(SoundControl snd_ctrl)
 {
   int i;
 
-#if defined(AUDIO_UNIX_NATIVE)
-  if (IS_PARENT_PROCESS())
-  {
-    SendSoundControlToMixerProcess(&snd_ctrl);
-    return;
-  }
-#endif
-
   /* deactivate channels that have expired since the last request */
   for (i = 0; i < audio.num_channels; i++)
     if (mixer[i].active && Mixer_ChannelExpired(i))
@@ -997,11 +461,6 @@ static void HandleSoundRequest(SoundControl snd_ctrl)
     for (i = audio.first_sound_channel; i < audio.num_channels; i++)
       Mixer_StopChannel(i);
 
-#if defined(AUDIO_UNIX_NATIVE)
-    CloseAudioDevice(&audio.device_fd);
-    ReadReloadInfoFromPipe(&snd_ctrl);
-#endif
-
     if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
       ReloadCustomSounds();
     else
@@ -1030,11 +489,10 @@ static void HandleSoundRequest(SoundControl snd_ctrl)
     for (i = audio.first_sound_channel; i < audio.num_channels; i++)
       if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
 	Mixer_StopChannel(i);
-
-#if defined(AUDIO_UNIX_NATIVE)
-    if (!mixer_active_channels)
-      CloseAudioDevice(&audio.device_fd);
-#endif
+  }
+  else if (SET_EXPIRE_LOOPS(snd_ctrl))	/* set loop expiration on or off */
+  {
+    expire_loop_sounds = snd_ctrl.active;
   }
   else if (snd_ctrl.active)		/* add new sound to mixer */
   {
@@ -1046,21 +504,6 @@ void StartMixer(void)
 {
   int i;
 
-#if 0
-  SDL_version compile_version;
-  const SDL_version *link_version;
-  MIX_VERSION(&compile_version);
-  printf("compiled with SDL_mixer version: %d.%d.%d\n", 
-	 compile_version.major,
-	 compile_version.minor,
-	 compile_version.patch);
-  link_version = Mix_Linked_Version();
-  printf("running with SDL_mixer version: %d.%d.%d\n", 
-	 link_version->major,
-	 link_version->minor,
-	 link_version->patch);
-#endif
-
   if (!audio.sound_available)
     return;
 
@@ -1068,445 +511,8 @@ void StartMixer(void)
   for (i = 0; i <= SOUND_MAX_LEFT2RIGHT; i++)
     stereo_volume[i] =
       (int)sqrt((float)(SOUND_MAX_LEFT2RIGHT * SOUND_MAX_LEFT2RIGHT - i * i));
-
-#if defined(AUDIO_UNIX_NATIVE)
-  if (!ForkAudioProcess())
-    audio.sound_available = FALSE;
-#endif
 }
 
-#if defined(AUDIO_UNIX_NATIVE)
-
-static void CopySampleToMixingBuffer(SoundControl *snd_ctrl,
-				     int sample_pos, int sample_size,
-				     short *buffer_base_ptr, int buffer_pos,
-				     int num_output_channels)
-{
-  short *buffer_ptr = buffer_base_ptr + num_output_channels * buffer_pos;
-  int num_channels = snd_ctrl->num_channels;
-  int stepsize = num_channels;
-  int output_stepsize = num_output_channels;
-  int i, j;
-
-  if (snd_ctrl->format == AUDIO_FORMAT_U8)
-  {
-    byte *sample_ptr = (byte *)snd_ctrl->data_ptr + num_channels * sample_pos;
-
-    for (i = 0; i < num_output_channels; i++)
-    {
-      int offset = (snd_ctrl->num_channels == 1 ? 0 : i);
-
-      for (j = 0; j < sample_size; j++)
-	buffer_ptr[output_stepsize * j + i] =
-	  ((short)(sample_ptr[stepsize * j + offset] ^ 0x80)) << 8;
-    }
-  }
-  else	/* AUDIO_FORMAT_S16 */
-  {
-    short *sample_ptr= (short *)snd_ctrl->data_ptr + num_channels * sample_pos;
-
-    for (i = 0; i < num_output_channels; i++)
-    {
-      int offset = (snd_ctrl->num_channels == 1 ? 0 : i);
-
-      for (j = 0; j < sample_size; j++)
-	buffer_ptr[output_stepsize * j + i] =
-	  sample_ptr[stepsize * j + offset];
-    }
-  }
-}
-
-#if defined(AUDIO_STREAMING_DSP)
-static void Mixer_Main_DSP()
-{
-  static short premix_first_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
-  static long premix_last_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
-  static byte playing_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
-  boolean stereo;
-  int fragment_size;
-  int sample_bytes;
-  int max_sample_size;
-  int num_output_channels;
-  int i, j;
-
-  if (!mixer_active_channels)
-    return;
-
-  if (audio.device_fd < 0)
-  {
-    if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
-      return;
-
-    InitAudioDevice(&afmt);
-  }
-
-  stereo = afmt.stereo;
-  fragment_size = afmt.fragment_size;
-  sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
-  num_output_channels = (stereo ? 2 : 1);
-  max_sample_size = fragment_size / (num_output_channels * sample_bytes);
-
-  /* first clear the last premixing buffer */
-  clear_mem(premix_last_buffer,
-	    max_sample_size * num_output_channels * sizeof(long));
-
-  for (i = 0; i < audio.num_channels; i++)
-  {
-    void *sample_ptr;
-    int sample_len;
-    int sample_pos;
-    int sample_size;
-
-    if (!mixer[i].active)
-      continue;
-
-    if (Mixer_ChannelExpired(i))
-    {
-      Mixer_StopChannel(i);
-      continue;
-    }
-
-    /* pointer, lenght and actual playing position of sound sample */
-    sample_ptr = mixer[i].data_ptr;
-    sample_len = mixer[i].data_len;
-    sample_pos = mixer[i].playing_pos;
-    sample_size = MIN(max_sample_size, sample_len - sample_pos);
-    mixer[i].playing_pos += sample_size;
-
-    /* copy original sample to first mixing buffer */
-    CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
-			     premix_first_buffer, 0, num_output_channels);
-
-    /* are we about to restart a looping sound? */
-    if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
-    {
-      while (sample_size < max_sample_size)
-      {
-	int restarted_sample_size =
-	  MIN(max_sample_size - sample_size, sample_len);
-
-	CopySampleToMixingBuffer(&mixer[i], 0, restarted_sample_size,
-				 premix_first_buffer, sample_size,
-				 num_output_channels);
-
-	mixer[i].playing_pos = restarted_sample_size;
-	sample_size += restarted_sample_size;
-      }
-    }
-
-    /* decrease volume if sound is fading out */
-    if (IS_FADING(mixer[i]) &&
-	mixer[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
-      mixer[i].volume -= SOUND_FADING_VOLUME_STEP;
-
-    /* adjust volume of actual sound sample */
-    if (mixer[i].volume != SOUND_MAX_VOLUME)
-      for (j = 0; j < sample_size * num_output_channels; j++)
-	premix_first_buffer[j] =
-	  mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
-
-    /* adjust left and right channel volume due to stereo sound position */
-    if (stereo)
-    {
-      int left_volume  = SOUND_VOLUME_LEFT(mixer[i].stereo_position);
-      int right_volume = SOUND_VOLUME_RIGHT(mixer[i].stereo_position);
-
-      for (j = 0; j < sample_size; j++)
-      {
-	premix_first_buffer[2 * j + 0] =
-	  left_volume  * premix_first_buffer[2 * j + 0] / SOUND_MAX_LEFT2RIGHT;
-	premix_first_buffer[2 * j + 1] =
-	  right_volume * premix_first_buffer[2 * j + 1] / SOUND_MAX_LEFT2RIGHT;
-      }
-    }
-
-    /* fill the last mixing buffer with stereo or mono sound */
-    for (j = 0; j < sample_size * num_output_channels; j++)
-      premix_last_buffer[j] += premix_first_buffer[j];
-
-    /* delete completed sound entries from the mixer */
-    if (mixer[i].playing_pos >= mixer[i].data_len)
-    {
-      if (IS_LOOP(mixer[i]))
-	mixer[i].playing_pos = 0;
-      else
-	Mixer_StopChannel(i);
-    }
-    else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
-      Mixer_StopChannel(i);
-  }
-
-  /* prepare final playing buffer according to system audio format */
-  for (i = 0; i < max_sample_size * num_output_channels; i++)
-  {
-    /* cut off at 17 bit value */
-    if (premix_last_buffer[i] < -65535)
-      premix_last_buffer[i] = -65535;
-    else if (premix_last_buffer[i] > 65535)
-      premix_last_buffer[i] = 65535;
-
-    /* shift to 16 bit value */
-    premix_last_buffer[i] >>= 1;
-
-    if (afmt.format & AUDIO_FORMAT_U8)
-    {
-      playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
-    }
-    else if (afmt.format & AUDIO_FORMAT_LE)	/* 16 bit */
-    {
-      playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
-      playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
-    }
-    else					/* big endian */
-    {
-      playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
-      playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
-    }
-  }
-
-  /* finally play the sound fragment */
-  write(audio.device_fd, playing_buffer, fragment_size);
-
-  if (!mixer_active_channels)
-    CloseAudioDevice(&audio.device_fd);
-}
-
-#else /* !AUDIO_STREAMING_DSP */
-
-static int Mixer_Main_SimpleAudio(SoundControl snd_ctrl)
-{
-  static short premix_first_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
-  static byte playing_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
-  int max_sample_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
-  int num_output_channels = 1;
-  void *sample_ptr;
-  int sample_len;
-  int sample_pos;
-  int sample_size;
-  int i, j;
-
-  i = 1;
-
-  /* pointer, lenght and actual playing position of sound sample */
-  sample_ptr = mixer[i].data_ptr;
-  sample_len = mixer[i].data_len;
-  sample_pos = mixer[i].playing_pos;
-  sample_size = MIN(max_sample_size, sample_len - sample_pos);
-  mixer[i].playing_pos += sample_size;
-
-  /* copy original sample to first mixing buffer */
-  CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
-			   premix_first_buffer, 0, num_output_channels);
-
-  /* adjust volume of actual sound sample */
-  if (mixer[i].volume != SOUND_MAX_VOLUME)
-    for (j = 0; j < sample_size; j++)
-      premix_first_buffer[j] =
-	mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
-
-  /* might be needed for u-law /dev/audio */
-  for (j = 0; j < sample_size; j++)
-    playing_buffer[j] =
-      linear_to_ulaw(premix_first_buffer[j]);
-
-  /* delete completed sound entries from the mixer */
-  if (mixer[i].playing_pos >= mixer[i].data_len)
-    Mixer_StopChannel(i);
-
-  for (i = 0; i < sample_size; i++)
-    playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
-
-  /* finally play the sound fragment */
-  write(audio.device_fd, playing_buffer, sample_size);
-
-  return sample_size;
-}
-#endif /* !AUDIO_STREAMING_DSP */
-
-void Mixer_Main()
-{
-  SoundControl snd_ctrl;
-  fd_set mixer_fdset;
-
-  close(audio.mixer_pipe[1]);	/* no writing into pipe needed */
-
-  Mixer_InitChannels();
-
-#if defined(PLATFORM_HPUX)
-  InitAudioDevice(&afmt);
-#endif
-
-  FD_ZERO(&mixer_fdset); 
-  FD_SET(audio.mixer_pipe[0], &mixer_fdset);
-
-  while (1)	/* wait for sound playing commands from client */
-  {
-    struct timeval delay = { 0, 0 };
-
-    FD_SET(audio.mixer_pipe[0], &mixer_fdset);
-    select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
-    if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
-      continue;
-
-    ReadSoundControlFromMainProcess(&snd_ctrl);
-
-    HandleSoundRequest(snd_ctrl);
-
-#if defined(AUDIO_STREAMING_DSP)
-
-    while (mixer_active_channels &&
-	   select(audio.mixer_pipe[0] + 1,
-		  &mixer_fdset, NULL, NULL, &delay) < 1)
-    {
-      FD_SET(audio.mixer_pipe[0], &mixer_fdset);
-
-      Mixer_Main_DSP();
-    }
-
-#else /* !AUDIO_STREAMING_DSP */
-
-    if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
-	(audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
-      continue;
-
-    InitAudioDevice(&afmt);
-
-    delay.tv_sec = 0;
-    delay.tv_usec = 0;
-
-    while (mixer_active_channels &&
-	   select(audio.mixer_pipe[0] + 1,
-		  &mixer_fdset, NULL, NULL, &delay) < 1)
-    {
-      int wait_percent = 90;	/* wait 90% of the real playing time */
-      int sample_size;
-
-      FD_SET(audio.mixer_pipe[0], &mixer_fdset);
-
-      sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
-
-      delay.tv_sec = 0;
-      delay.tv_usec =
-	((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
-    }
-
-    CloseAudioDevice(&audio.device_fd);
-
-    Mixer_InitChannels();	/* remove all sounds from mixer */
-
-#endif /* !AUDIO_STREAMING_DSP */
-  }
-}
-#endif /* AUDIO_UNIX_NATIVE */
-
-
-#if defined(AUDIO_UNIX_NATIVE) && !defined(AUDIO_STREAMING_DSP)
-
-/* these two are stolen from "sox"... :) */
-
-/*
-** This routine converts from linear to ulaw.
-**
-** Craig Reese: IDA/Supercomputing Research Center
-** Joe Campbell: Department of Defense
-** 29 September 1989
-**
-** References:
-** 1) CCITT Recommendation G.711  (very difficult to follow)
-** 2) "A New Digital Technique for Implementation of Any
-**     Continuous PCM Companding Law," Villeret, Michel,
-**     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
-**     1973, pg. 11.12-11.17
-** 3) MIL-STD-188-113,"Interoperability and Performance Standards
-**     for Analog-to_Digital Conversion Techniques,"
-**     17 February 1987
-**
-** Input: Signed 16 bit linear sample
-** Output: 8 bit ulaw sample
-*/
-
-#define ZEROTRAP    /* turn on the trap as per the MIL-STD */
-#define BIAS 0x84   /* define the add-in bias for 16 bit samples */
-#define CLIP 32635
-
-static unsigned char linear_to_ulaw(int sample)
-{
-  static int exp_lut[256] =
-  {
-    0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
-    4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
-    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
-  };
-
-  int sign, exponent, mantissa;
-  unsigned char ulawbyte;
-
-  /* Get the sample into sign-magnitude. */
-  sign = (sample >> 8) & 0x80;		/* set aside the sign */
-  if (sign != 0)
-    sample = -sample;			/* get magnitude */
-  if (sample > CLIP)
-    sample = CLIP;			/* clip the magnitude */
-
-  /* Convert from 16 bit linear to ulaw. */
-  sample = sample + BIAS;
-  exponent = exp_lut[( sample >> 7 ) & 0xFF];
-  mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
-  ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
-#ifdef ZEROTRAP
-  if (ulawbyte == 0)
-    ulawbyte = 0x02;			/* optional CCITT trap */
-#endif
-
-  return(ulawbyte);
-}
-
-/*
-** This routine converts from ulaw to 16 bit linear.
-**
-** Craig Reese: IDA/Supercomputing Research Center
-** 29 September 1989
-**
-** References:
-** 1) CCITT Recommendation G.711  (very difficult to follow)
-** 2) MIL-STD-188-113,"Interoperability and Performance Standards
-**     for Analog-to_Digital Conversion Techniques,"
-**     17 February 1987
-**
-** Input: 8 bit ulaw sample
-** Output: signed 16 bit linear sample
-*/
-
-static int ulaw_to_linear(unsigned char ulawbyte)
-{
-  static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
-  int sign, exponent, mantissa, sample;
-
-  ulawbyte = ~ ulawbyte;
-  sign = ( ulawbyte & 0x80 );
-  exponent = ( ulawbyte >> 4 ) & 0x07;
-  mantissa = ulawbyte & 0x0F;
-  sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
-  if (sign != 0)
-    sample = -sample;
-
-  return(sample);
-}
-#endif /* AUDIO_UNIX_NATIVE && !AUDIO_STREAMING_DSP */
-
 
 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS            */
 /* ========================================================================= */
@@ -1518,210 +524,21 @@ static int ulaw_to_linear(unsigned char ulawbyte)
 static void *Load_WAV(char *filename)
 {
   SoundInfo *snd_info;
-#if defined(AUDIO_UNIX_NATIVE)
-  struct SoundHeader_WAV header;
-#if 0
-  byte sound_header_buffer[WAV_HEADER_SIZE];
-  int i;
-#endif
-  char chunk_name[CHUNK_ID_LEN + 1];
-  int chunk_size;
-  int data_byte_len;
-  FILE *file;
-#endif
 
   if (!audio.sound_available)
     return NULL;
 
   snd_info = checked_calloc(sizeof(SoundInfo));
 
-#if defined(TARGET_SDL)
-
   if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
   {
-    Error(ERR_WARN, "cannot read sound file '%s'", filename);
+    Error(ERR_WARN, "cannot read sound file '%s': %s", filename, Mix_GetError());
     free(snd_info);
     return NULL;
   }
 
   snd_info->data_len = ((Mix_Chunk *)snd_info->data_ptr)->alen;
 
-#elif defined(TARGET_ALLEGRO)
-
-  if ((snd_info->data_ptr = load_sample(filename)) == NULL)
-  {
-    Error(ERR_WARN, "cannot read sound file '%s'", filename);
-    free(snd_info);
-    return NULL;
-  }
-
-  snd_info->data_len = ((SAMPLE *)snd_info->data_ptr)->len;
-
-#else /* AUDIO_UNIX_NATIVE */
-
-  clear_mem(&header, sizeof(struct SoundHeader_WAV));	/* to make gcc happy */
-
-  if ((file = fopen(filename, MODE_READ)) == NULL)
-  {
-    Error(ERR_WARN, "cannot open sound file '%s'", filename);
-    free(snd_info);
-    return NULL;
-  }
-
-  /* read chunk id "RIFF" */
-  getFileChunkLE(file, chunk_name, &chunk_size);
-  if (!strEqual(chunk_name, "RIFF"))
-  {
-    Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
-    fclose(file);
-    free(snd_info);
-    return NULL;
-  }
-
-  /* read "RIFF" type id "WAVE" */
-  getFileChunkLE(file, chunk_name, NULL);
-  if (!strEqual(chunk_name, "WAVE"))
-  {
-    Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
-    fclose(file);
-    free(snd_info);
-    return NULL;
-  }
-
-  while (getFileChunkLE(file, chunk_name, &chunk_size))
-  {
-    if (strEqual(chunk_name, "fmt "))
-    {
-      if (chunk_size < WAV_HEADER_SIZE)
-      {
-	Error(ERR_WARN, "sound file '%s': chunk 'fmt ' too short", filename);
-	fclose(file);
-	free(snd_info);
-	return NULL;
-      }
-
-      header.compression_code = getFile16BitLE(file);
-      header.num_channels = getFile16BitLE(file);
-      header.sample_rate = getFile32BitLE(file);
-      header.bytes_per_second = getFile32BitLE(file);
-      header.block_align = getFile16BitLE(file);
-      header.bits_per_sample = getFile16BitLE(file);
-
-      if (chunk_size > WAV_HEADER_SIZE)
-	ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
-
-      if (header.compression_code != 1)
-      {
-	Error(ERR_WARN, "sound file '%s': compression code %d not supported",
-	      filename, header.compression_code);
-	fclose(file);
-	free(snd_info);
-	return NULL;
-      }
-
-      if (header.num_channels != 1 &&
-	  header.num_channels != 2)
-      {
-	Error(ERR_WARN, "sound file '%s': number of %d channels not supported",
-	      filename, header.num_channels);
-	fclose(file);
-	free(snd_info);
-	return NULL;
-      }
-
-      if (header.bits_per_sample != 8 &&
-	  header.bits_per_sample != 16)
-      {
-	Error(ERR_WARN, "sound file '%s': %d bits per sample not supported",
-	      filename, header.bits_per_sample);
-	fclose(file);
-	free(snd_info);
-	return NULL;
-      }
-
-      /* warn, but accept wrong sample rate (may be only slightly different) */
-      if (header.sample_rate != DEFAULT_AUDIO_SAMPLE_RATE)
-	Error(ERR_WARN, "sound file '%s': wrong sample rate %d instead of %d",
-	      filename, header.sample_rate, DEFAULT_AUDIO_SAMPLE_RATE);
-
-#if 0
-      printf("WAV file: '%s'\n", filename);
-      printf("  Compression code: %d'\n", header.compression_code);
-      printf("  Number of channels: %d'\n", header.num_channels);
-      printf("  Sample rate: %ld'\n", header.sample_rate);
-      printf("  Average bytes per second: %ld'\n", header.bytes_per_second);
-      printf("  Block align: %d'\n", header.block_align);
-      printf("  Significant bits per sample: %d'\n", header.bits_per_sample);
-#endif
-    }
-    else if (strEqual(chunk_name, "data"))
-    {
-      data_byte_len = chunk_size;
-
-      snd_info->data_len = data_byte_len;
-      snd_info->data_ptr = checked_malloc(snd_info->data_len);
-
-      /* read sound data */
-      if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
-	  snd_info->data_len)
-      {
-	Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
-	fclose(file);
-	free(snd_info->data_ptr);
-	free(snd_info);
-	return NULL;
-      }
-
-      /* check for odd number of data bytes (data chunk is word aligned) */
-      if ((data_byte_len % 2) == 1)
-	ReadUnusedBytesFromFile(file, 1);
-    }
-    else	/* unknown chunk -- ignore */
-      ReadUnusedBytesFromFile(file, chunk_size);
-  }
-
-  fclose(file);
-
-  if (snd_info->data_ptr == NULL)
-  {
-    Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
-    free(snd_info);
-    return NULL;
-  }
-
-  if (header.bits_per_sample == 8)
-    snd_info->format = AUDIO_FORMAT_U8;
-  else					/* header.bits_per_sample == 16 */
-  {
-    snd_info->format = AUDIO_FORMAT_S16;
-    snd_info->data_len /= 2;		/* correct number of samples */
-  }
-
-  snd_info->num_channels = header.num_channels;
-  if (header.num_channels == 2)
-    snd_info->data_len /= 2;		/* correct number of samples */
-
-#if 0
-  if (header.num_channels == 1)		/* convert mono sound to stereo */
-  {
-    void *buffer_ptr = checked_malloc(data_byte_len * 2);
-    void *sample_ptr = snd_info->data_ptr;
-    int sample_size = snd_info->data_len;
-    int i;
-
-    if (snd_ctrl->format == AUDIO_FORMAT_U8)
-      for (i = 0; i < sample_size; i++)
-	*buffer_ptr++ =
-	  ((short)(((byte *)sample_ptr)[i] ^ 0x80)) << 8;
-    else	/* AUDIO_FORMAT_S16 */
-      for (i = 0; i < sample_size; i++)
-	*buffer_ptr++ =
-	  ((short *)sample_ptr)[i];
-  }
-#endif
-
-#endif	/* AUDIO_UNIX_NATIVE */
-
   snd_info->type = SND_TYPE_WAV;
   snd_info->source_filename = getStringCopy(filename);
 
@@ -1730,7 +547,6 @@ static void *Load_WAV(char *filename)
 
 static void *Load_MOD(char *filename)
 {
-#if defined(TARGET_SDL)
   MusicInfo *mod_info;
 
   if (!audio.sound_available)
@@ -1740,7 +556,7 @@ static void *Load_MOD(char *filename)
 
   if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
   {
-    Error(ERR_WARN, "cannot read music file '%s'", filename);
+    Error(ERR_WARN, "cannot read music file '%s': %s", filename, Mix_GetError());
     free(mod_info);
     return NULL;
   }
@@ -1749,17 +565,14 @@ static void *Load_MOD(char *filename)
   mod_info->source_filename = getStringCopy(filename);
 
   return mod_info;
-#else
-  return NULL;
-#endif
 }
 
 static void *Load_WAV_or_MOD(char *filename)
 {
-  if (FileIsSound(filename))
-    return Load_WAV(filename);
-  else if (FileIsMusic(filename))
+  if (FileIsMusic(filename))
     return Load_MOD(filename);
+  else if (FileIsSound(filename))
+    return Load_WAV(filename);
   else
     return NULL;
 }
@@ -1769,8 +582,8 @@ void LoadCustomMusic_NoConf(void)
   static boolean draw_init_text = TRUE;		/* only draw at startup */
   static char *last_music_directory = NULL;
   char *music_directory = getCustomMusicDirectory();
-  DIR *dir;
-  struct dirent *dir_entry;
+  Directory *dir;
+  DirectoryEntry *dir_entry;
   int num_music = getMusicListSize();
 
   if (!audio.sound_available)
@@ -1786,20 +599,21 @@ void LoadCustomMusic_NoConf(void)
 
   FreeAllMusic_NoConf();
 
-  if ((dir = opendir(music_directory)) == NULL)
+  if ((dir = openDirectory(music_directory)) == NULL)
   {
     Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
+
     audio.music_available = FALSE;
+
     return;
   }
 
   if (draw_init_text)
     DrawInitText("Loading music", 120, FC_GREEN);
 
-  while ((dir_entry = readdir(dir)) != NULL)	/* loop until last dir entry */
+  while ((dir_entry = readDirectory(dir)) != NULL)	/* loop all entries */
   {
-    char *basename = dir_entry->d_name;
-    char *filename = NULL;
+    char *basename = dir_entry->basename;
     MusicInfo *mus_info = NULL;
     boolean music_already_used = FALSE;
     int i;
@@ -1822,12 +636,8 @@ void LoadCustomMusic_NoConf(void)
     if (draw_init_text)
       DrawInitText(basename, 150, FC_YELLOW);
 
-    filename = getPath2(music_directory, basename);
-
-    if (FileIsMusic(basename))
-      mus_info = Load_WAV_or_MOD(filename);
-
-    free(filename);
+    if (FileIsMusic(dir_entry->filename))
+      mus_info = Load_WAV_or_MOD(dir_entry->filename);
 
     if (mus_info)
     {
@@ -1838,7 +648,7 @@ void LoadCustomMusic_NoConf(void)
     }
   }
 
-  closedir(dir);
+  closeDirectory(dir);
 
   draw_init_text = FALSE;
 }
@@ -1895,6 +705,11 @@ static MusicInfo *getMusicInfoEntryFromMusicID(int pos)
   return mus_info[list_pos];
 }
 
+char *getCurrentlyPlayingMusicFilename()
+{
+  return currently_playing_music_filename;
+}
+
 int getSoundListPropertyMappingSize()
 {
   return sound_info->num_property_mapping_entries;
@@ -2075,21 +890,33 @@ void PlayMusic(int nr)
 
 void PlaySound(int nr)
 {
+  if (!setup.sound_simple)
+    return;
+
   PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
 }
 
 void PlaySoundStereo(int nr, int stereo_position)
 {
+  if (!setup.sound_simple)
+    return;
+
   PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
 }
 
 void PlaySoundLoop(int nr)
 {
+  if (!setup.sound_loops)
+    return;
+
   PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
 }
 
 void PlaySoundMusic(int nr)
 {
+  if (!setup.sound_music)
+    return;
+
   PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
 }
 
@@ -2102,6 +929,8 @@ void PlaySoundExt(int nr, int volume, int stereo_position, int state)
       audio.sound_deactivated)
     return;
 
+  volume = SETUP_SOUND_VOLUME(volume, state);
+
   if (volume < SOUND_MIN_VOLUME)
     volume = SOUND_MIN_VOLUME;
   else if (volume > SOUND_MAX_VOLUME)
@@ -2182,22 +1011,29 @@ void StopSoundExt(int nr, int state)
   HandleSoundRequest(snd_ctrl);
 }
 
-static void ReloadCustomSounds()
+void ExpireSoundLoops(boolean active)
 {
-#if 0
-  printf("::: reloading sounds '%s' ...\n", artwork.snd_current_identifier);
-#endif
+  SoundControl snd_ctrl;
 
+  if (!audio.sound_available)
+    return;
+
+  clear_mem(&snd_ctrl, sizeof(SoundControl));	/* to make valgrind happy */
+
+  snd_ctrl.active = active;
+  snd_ctrl.state = SND_CTRL_EXPIRE_LOOPS;
+
+  HandleSoundRequest(snd_ctrl);
+}
+
+static void ReloadCustomSounds()
+{
   LoadArtworkConfig(sound_info);
   ReloadCustomArtworkList(sound_info);
 }
 
 static void ReloadCustomMusic()
 {
-#if 0
-  printf("::: reloading music '%s' ...\n", artwork.mus_current_identifier);
-#endif
-
   LoadArtworkConfig(music_info);
   ReloadCustomArtworkList(music_info);
 
@@ -2210,12 +1046,7 @@ void InitReloadCustomSounds(char *set_identifier)
   if (!audio.sound_available)
     return;
 
-#if defined(AUDIO_UNIX_NATIVE)
-  LoadArtworkConfig(sound_info);	/* also load config on sound client */
-  WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_SOUNDS);
-#else
   ReloadCustomSounds();
-#endif
 }
 
 void InitReloadCustomMusic(char *set_identifier)
@@ -2223,12 +1054,7 @@ void InitReloadCustomMusic(char *set_identifier)
   if (!audio.music_available)
     return;
 
-#if defined(AUDIO_UNIX_NATIVE)
-  LoadArtworkConfig(music_info);	/* also load config on sound client */
-  WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_MUSIC);
-#else
   ReloadCustomMusic();
-#endif
 }
 
 void FreeSound(void *ptr)
@@ -2240,13 +1066,7 @@ void FreeSound(void *ptr)
 
   if (sound->data_ptr)
   {
-#if defined(TARGET_SDL)
     Mix_FreeChunk(sound->data_ptr);
-#elif defined(TARGET_ALLEGRO)
-    destroy_sample(sound->data_ptr);
-#else /* AUDIO_UNIX_NATIVE */
-    free(sound->data_ptr);
-#endif
   }
 
   checked_free(sound->source_filename);
@@ -2263,16 +1083,10 @@ void FreeMusic(void *ptr)
 
   if (music->data_ptr)
   {
-#if defined(TARGET_SDL)
     if (music->type == MUS_TYPE_MOD)
       Mix_FreeMusic(music->data_ptr);
     else
       Mix_FreeChunk(music->data_ptr);
-#elif defined(TARGET_ALLEGRO)
-    destroy_sample(music->data_ptr);
-#else /* AUDIO_UNIX_NATIVE */
-    free(music->data_ptr);
-#endif
   }
 
   free(music);
diff --git a/src/libgame/sound.h b/src/libgame/sound.h
index fc111e9..8eb344e 100644
--- a/src/libgame/sound.h
+++ b/src/libgame/sound.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* sound.h                                                  *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// sound.h
+// ============================================================================
 
 #ifndef SOUND_H
 #define SOUND_H
@@ -17,20 +15,7 @@
 #include "system.h"
 
 
-#if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
-#define AUDIO_UNIX_NATIVE
-#endif
-
-#if defined(PLATFORM_LINUX) || defined(PLATFORM_FREEBSD) || defined(VOXWARE)
-#define AUDIO_LINUX_IOCTL
-#endif
-
-#if defined(AUDIO_LINUX_IOCTL) || defined(PLATFORM_NETBSD)
-#define AUDIO_STREAMING_DSP
-#endif
-
 /* values for platform specific sound initialization */
-#define AUDIO_SAMPLE_RATE_8000		8000
 #define AUDIO_SAMPLE_RATE_22050		22050
 
 #define AUDIO_FRAGMENT_SIZE_512		512
@@ -48,25 +33,15 @@
 #define AUDIO_FORMAT_LE			(1 << 2)
 #define AUDIO_FORMAT_BE			(1 << 3)
 
-#if defined(AUDIO_UNIX_NATIVE) && !defined(AUDIO_STREAMING_DSP)
-#define DEFAULT_AUDIO_SAMPLE_RATE	AUDIO_SAMPLE_RATE_8000
-#else
 #define DEFAULT_AUDIO_SAMPLE_RATE	AUDIO_SAMPLE_RATE_22050
-#endif
 
-#if defined(PLATFORM_HPUX)
-#define DEFAULT_AUDIO_FRAGMENT_SIZE	AUDIO_FRAGMENT_SIZE_32768
-#elif defined(PLATFORM_WIN32)
+#if defined(PLATFORM_WIN32)
 #define DEFAULT_AUDIO_FRAGMENT_SIZE	AUDIO_FRAGMENT_SIZE_1024
 #else
 #define DEFAULT_AUDIO_FRAGMENT_SIZE	AUDIO_FRAGMENT_SIZE_512
 #endif
 
-#if defined(TARGET_SDL)
 #define NUM_MIXER_CHANNELS		MIX_CHANNELS
-#else
-#define NUM_MIXER_CHANNELS		8
-#endif
 
 #define MUSIC_CHANNEL			0
 #define FIRST_SOUND_CHANNEL		1
@@ -81,6 +56,7 @@
 #define SND_CTRL_ALL_SOUNDS		(1 << 4)
 #define SND_CTRL_RELOAD_SOUNDS		(1 << 5)
 #define SND_CTRL_RELOAD_MUSIC		(1 << 6)
+#define SND_CTRL_EXPIRE_LOOPS		(1 << 7)
 
 #define SND_CTRL_PLAY_SOUND		(SND_CTRL_NONE)
 #define SND_CTRL_PLAY_LOOP		(SND_CTRL_LOOP)
@@ -101,19 +77,14 @@
 #define IS_RELOADING(x)			((x).state & (SND_CTRL_RELOAD_SOUNDS |\
 						      SND_CTRL_RELOAD_MUSIC))
 #define ALL_SOUNDS(x)			((x).state & SND_CTRL_ALL_SOUNDS)
+#define SET_EXPIRE_LOOPS(x)		((x).state & SND_CTRL_EXPIRE_LOOPS)
 
 #define MAP_NOCONF_MUSIC(x)		(-((x) + 1))
 #define UNMAP_NOCONF_MUSIC(x)		MAP_NOCONF_MUSIC(x)
 
 
 #define SOUND_MIN_VOLUME		0
-#if defined(TARGET_SDL)
 #define SOUND_MAX_VOLUME		SDL_MIX_MAXVOLUME
-#elif defined(TARGET_ALLEGRO)
-#define SOUND_MAX_VOLUME		255
-#else
-#define SOUND_MAX_VOLUME		128
-#endif
 
 #define SOUND_MAX_LEFT			0
 #define SOUND_MAX_RIGHT			255
@@ -144,11 +115,13 @@ void StopMusic(void);
 void StopSound(int);
 void StopSounds(void);
 void StopSoundExt(int, int);
+void ExpireSoundLoops(boolean);
 
 int getSoundListSize();
 int getMusicListSize();
 struct FileInfo *getSoundListEntry(int);
 struct FileInfo *getMusicListEntry(int);
+char *getCurrentlyPlayingMusicFilename();
 int getSoundListPropertyMappingSize();
 int getMusicListPropertyMappingSize();
 struct PropertyMapping *getSoundListPropertyMapping();
diff --git a/src/libgame/system.c b/src/libgame/system.c
index 4b7a3ca..00e9c72 100644
--- a/src/libgame/system.c
+++ b/src/libgame/system.c
@@ -1,25 +1,19 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* system.c                                                 *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// system.c
+// ============================================================================
 
 #include <string.h>
 #include <signal.h>
 
 #include "platform.h"
 
-#if defined(PLATFORM_MSDOS)
-#include <fcntl.h>
-#endif
-
 #include "system.h"
 #include "image.h"
 #include "sound.h"
@@ -27,6 +21,8 @@
 #include "joystick.h"
 #include "misc.h"
 
+#define ENABLE_UNUSED_CODE	0	/* currently unused functions */
+
 
 /* ========================================================================= */
 /* exported variables                                                        */
@@ -37,6 +33,7 @@ struct OptionInfo	options;
 struct VideoSystemInfo	video;
 struct AudioSystemInfo	audio;
 struct GfxInfo		gfx;
+struct OverlayInfo	overlay;
 struct ArtworkInfo	artwork;
 struct JoystickInfo	joystick;
 struct SetupInfo	setup;
@@ -46,10 +43,7 @@ LevelDirTree	       *leveldir_first = NULL;
 LevelDirTree	       *leveldir_current = NULL;
 int			level_nr;
 
-Display		       *display = NULL;
-Visual		       *visual = NULL;
-int			screen = 0;
-Colormap		cmap = None;
+struct LevelStats	level_stats[MAX_LEVELS];
 
 DrawWindow	       *window = NULL;
 DrawBuffer	       *backbuffer = NULL;
@@ -57,9 +51,12 @@ DrawBuffer	       *drawto = NULL;
 
 int			button_status = MB_NOT_PRESSED;
 boolean			motion_status = FALSE;
+int			wheel_steps = DEFAULT_WHEEL_STEPS;
+#if defined(TARGET_SDL2)
+boolean			keyrepeat_status = TRUE;
+#endif
 
 int			redraw_mask = REDRAW_NONE;
-int			redraw_tiles = 0;
 
 int			FrameCounter = 0;
 
@@ -68,39 +65,64 @@ int			FrameCounter = 0;
 /* init/close functions                                                      */
 /* ========================================================================= */
 
-void InitProgramInfo(char *argv0,
-		     char *userdata_subdir, char *userdata_subdir_unix,
-		     char *program_title, char *window_title, char *icon_title,
-		     char *x11_icon_filename, char *x11_iconmask_filename,
-		     char *sdl_icon_filename, char *msdos_cursor_filename,
-		     char *cookie_prefix, char *filename_prefix,
+void InitProgramInfo(char *argv0, char *config_filename, char *userdata_subdir,
+		     char *program_title, char *icon_title,
+		     char *icon_filename, char *cookie_prefix,
 		     int program_version)
 {
   program.command_basepath = getBasePath(argv0);
   program.command_basename = getBaseName(argv0);
 
+  program.config_filename = config_filename;
+
   program.userdata_subdir = userdata_subdir;
-  program.userdata_subdir_unix = userdata_subdir_unix;
   program.userdata_path = getUserGameDataDir();
 
   program.program_title = program_title;
-  program.window_title = window_title;
+  program.window_title = "(undefined)";
   program.icon_title = icon_title;
 
-  program.x11_icon_filename = x11_icon_filename;
-  program.x11_iconmask_filename = x11_iconmask_filename;
-  program.sdl_icon_filename = sdl_icon_filename;
-  program.msdos_cursor_filename = msdos_cursor_filename;
+  program.icon_filename = icon_filename;
 
   program.cookie_prefix = cookie_prefix;
-  program.filename_prefix = filename_prefix;
 
   program.version_major = VERSION_MAJOR(program_version);
   program.version_minor = VERSION_MINOR(program_version);
   program.version_patch = VERSION_PATCH(program_version);
+  program.version_build = VERSION_BUILD(program_version);
+  program.version_ident = program_version;
+
+  program.log_filename[LOG_OUT_ID] = getLogFilename(LOG_OUT_BASENAME);
+  program.log_filename[LOG_ERR_ID] = getLogFilename(LOG_ERR_BASENAME);
+  program.log_file[LOG_OUT_ID] = program.log_file_default[LOG_OUT_ID] = stdout;
+  program.log_file[LOG_ERR_ID] = program.log_file_default[LOG_ERR_ID] = stderr;
+}
+
+void InitScoresInfo()
+{
+  char *global_scores_dir = getPath2(getCommonDataDir(), SCORES_DIRECTORY);
+
+  program.global_scores = directoryExists(global_scores_dir);
+  program.many_scores_per_name = !program.global_scores;
+
+  free(global_scores_dir);
+}
 
-  program.error_filename = getErrorFilename(ERROR_BASENAME);
-  program.error_file = stderr;
+void SetWindowTitle()
+{
+  program.window_title = program.window_title_function();
+
+  SDLSetWindowTitle();
+}
+
+void InitWindowTitleFunction(char *(*window_title_function)(void))
+{
+  program.window_title_function = window_title_function;
+}
+
+void InitExitMessageFunction(void (*exit_message_function)(char *, va_list))
+{
+  program.exit_message_function = exit_message_function;
 }
 
 void InitExitFunction(void (*exit_function)(int))
@@ -108,46 +130,35 @@ void InitExitFunction(void (*exit_function)(int))
   program.exit_function = exit_function;
 
   /* set signal handlers to custom exit function */
-  signal(SIGINT, exit_function);
+  // signal(SIGINT, exit_function);
   signal(SIGTERM, exit_function);
 
-#if defined(TARGET_SDL)
   /* set exit function to automatically cleanup SDL stuff after exit() */
   atexit(SDL_Quit);
-#endif
 }
 
 void InitPlatformDependentStuff(void)
 {
-#if defined(PLATFORM_MSDOS)
-  _fmode = O_BINARY;
-#endif
+  // this is initialized in GetOptions(), but may already be used before
+  options.verbose = TRUE;
 
-#if defined(PLATFORM_MACOSX)
-  updateUserGameDataDir();
-#endif
+  OpenLogFiles();
 
-#if !defined(PLATFORM_UNIX) || defined(PLATFORM_MACOSX)
-  openErrorFile();
+#if defined(TARGET_SDL2)
+  int sdl_init_flags = SDL_INIT_EVENTS      | SDL_INIT_NOPARACHUTE;
+#else
+  int sdl_init_flags = SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE;
 #endif
 
-#if defined(TARGET_SDL)
-  if (SDL_Init(SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE) < 0)
+  if (SDL_Init(sdl_init_flags) < 0)
     Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
 
   SDLNet_Init();
-#endif
 }
 
 void ClosePlatformDependentStuff(void)
 {
-#if defined(PLATFORM_WIN32) || defined(PLATFORM_MSDOS)
-  closeErrorFile();
-#endif
-
-#if defined(PLATFORM_MSDOS)
-  dumpErrorFile();
-#endif
+  CloseLogFiles();
 }
 
 void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize,
@@ -166,15 +177,16 @@ void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize,
 
   gfx.field_save_buffer = field_save_buffer;
 
-#if 0
-  gfx.background_bitmap = NULL;
-  gfx.background_bitmap_mask = REDRAW_NONE;
-#endif
-
   SetDrawDeactivationMask(REDRAW_NONE);		/* do not deactivate drawing */
   SetDrawBackgroundMask(REDRAW_NONE);		/* deactivate masked drawing */
 }
 
+void InitGfxTileSizeInfo(int game_tile_size, int standard_tile_size)
+{
+  gfx.game_tile_size = game_tile_size;
+  gfx.standard_tile_size = standard_tile_size;
+}
+
 void InitGfxDoor1Info(int dx, int dy, int dxsize, int dysize)
 {
   gfx.dx = dx;
@@ -191,16 +203,36 @@ void InitGfxDoor2Info(int vx, int vy, int vxsize, int vysize)
   gfx.vysize = vysize;
 }
 
+void InitGfxDoor3Info(int ex, int ey, int exsize, int eysize)
+{
+  gfx.ex = ex;
+  gfx.ey = ey;
+  gfx.exsize = exsize;
+  gfx.eysize = eysize;
+}
+
 void InitGfxWindowInfo(int win_xsize, int win_ysize)
 {
+  if (win_xsize != gfx.win_xsize || win_ysize != gfx.win_ysize)
+  {
+    ReCreateBitmap(&gfx.background_bitmap, win_xsize, win_ysize);
+
+#if defined(TARGET_SDL2)
+    ReCreateBitmap(&gfx.final_screen_bitmap, win_xsize, win_ysize);
+#endif
+
+    ReCreateBitmap(&gfx.fade_bitmap_backup, win_xsize, win_ysize);
+    ReCreateBitmap(&gfx.fade_bitmap_source, win_xsize, win_ysize);
+    ReCreateBitmap(&gfx.fade_bitmap_target, win_xsize, win_ysize);
+    ReCreateBitmap(&gfx.fade_bitmap_black,  win_xsize, win_ysize);
+
+    ClearRectangle(gfx.fade_bitmap_black, 0, 0, win_xsize, win_ysize);
+  }
+
   gfx.win_xsize = win_xsize;
   gfx.win_ysize = win_ysize;
 
-#if 1
   gfx.background_bitmap_mask = REDRAW_NONE;
-
-  ReCreateBitmap(&gfx.background_bitmap, win_xsize, win_ysize, DEFAULT_DEPTH);
-#endif
 }
 
 void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height)
@@ -225,6 +257,16 @@ void InitGfxDrawBusyAnimFunction(void (*draw_busy_anim_function)(void))
   gfx.draw_busy_anim_function = draw_busy_anim_function;
 }
 
+void InitGfxDrawGlobalAnimFunction(void (*draw_global_anim_function)(int, int))
+{
+  gfx.draw_global_anim_function = draw_global_anim_function;
+}
+
+void InitGfxDrawGlobalBorderFunction(void (*draw_global_border_function)(int))
+{
+  gfx.draw_global_border_function = draw_global_border_function;
+}
+
 void InitGfxCustomArtworkInfo()
 {
   gfx.override_level_graphics = FALSE;
@@ -234,39 +276,34 @@ void InitGfxCustomArtworkInfo()
   gfx.draw_init_text = TRUE;
 }
 
-void SetDrawDeactivationMask(int draw_deactivation_mask)
+void InitGfxOtherSettings()
 {
-  gfx.draw_deactivation_mask = draw_deactivation_mask;
+  gfx.cursor_mode = CURSOR_DEFAULT;
 }
 
-void SetDrawBackgroundMask(int draw_background_mask)
+void InitOverlayInfo()
 {
-  gfx.draw_background_mask = draw_background_mask;
+  overlay.active = FALSE;
 }
 
-static void DrawBitmapFromTile(Bitmap *bitmap, Bitmap *tile,
-			       int dest_x, int dest_y, int width, int height)
+void SetOverlayActive(boolean active)
 {
-  int bitmap_xsize = width;
-  int bitmap_ysize = height;
-  int tile_xsize = tile->width;
-  int tile_ysize = tile->height;
-  int tile_xsteps = (bitmap_xsize + tile_xsize - 1) / tile_xsize;
-  int tile_ysteps = (bitmap_ysize + tile_ysize - 1) / tile_ysize;
-  int x, y;
+  overlay.active = active;
+}
 
-  for (y = 0; y < tile_ysteps; y++)
-  {
-    for (x = 0; x < tile_xsteps; x++)
-    {
-      int draw_x = dest_x + x * tile_xsize;
-      int draw_y = dest_y + y * tile_ysize;
-      int draw_xsize = MIN(tile_xsize, bitmap_xsize - x * tile_xsize);
-      int draw_ysize = MIN(tile_ysize, bitmap_ysize - y * tile_ysize);
+boolean GetOverlayActive()
+{
+  return overlay.active;
+}
 
-      BlitBitmap(tile, bitmap, 0, 0, draw_xsize, draw_ysize, draw_x, draw_y);
-    }
-  }
+void SetDrawDeactivationMask(int draw_deactivation_mask)
+{
+  gfx.draw_deactivation_mask = draw_deactivation_mask;
+}
+
+void SetDrawBackgroundMask(int draw_background_mask)
+{
+  gfx.draw_background_mask = draw_background_mask;
 }
 
 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
@@ -276,28 +313,18 @@ void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
   else
     gfx.background_bitmap_mask &= ~mask;
 
-#if 0
-  if (gfx.background_bitmap == NULL)
-    gfx.background_bitmap = CreateBitmap(video.width, video.height,
-					 DEFAULT_DEPTH);
-#endif
-
   if (background_bitmap_tile == NULL)	/* empty background requested */
     return;
 
   if (mask == REDRAW_ALL)
-    DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
-		       0, 0, video.width, video.height);
+    BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
+		    0, 0, video.width, video.height);
   else if (mask == REDRAW_FIELD)
-    DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
-		       gfx.real_sx, gfx.real_sy,
-		       gfx.full_sxsize, gfx.full_sysize);
+    BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
+		    gfx.real_sx, gfx.real_sy, gfx.full_sxsize, gfx.full_sysize);
   else if (mask == REDRAW_DOOR_1)
-  {
-    DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
-		       gfx.dx, gfx.dy,
-		       gfx.dxsize, gfx.dysize);
-  }
+    BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
+		    gfx.dx, gfx.dy, gfx.dxsize, gfx.dysize);
 }
 
 void SetWindowBackgroundBitmap(Bitmap *background_bitmap_tile)
@@ -335,34 +362,35 @@ inline static int GetRealDepth(int depth)
 }
 
 inline static void sysFillRectangle(Bitmap *bitmap, int x, int y,
-			       int width, int height, Pixel color)
+				    int width, int height, Pixel color)
 {
-#if defined(TARGET_SDL)
   SDLFillRectangle(bitmap, x, y, width, height, color);
-#else
-  X11FillRectangle(bitmap, x, y, width, height, color);
-#endif
+
+  if (bitmap == backbuffer)
+    SetRedrawMaskFromArea(x, y, width, height);
 }
 
 inline static void sysCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
 			       int src_x, int src_y, int width, int height,
 			       int dst_x, int dst_y, int mask_mode)
 {
-#if defined(TARGET_SDL)
   SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
 	      dst_x, dst_y, mask_mode);
-#else
-  X11CopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
-	      dst_x, dst_y, mask_mode);
-#endif
+
+  if (dst_bitmap == backbuffer)
+    SetRedrawMaskFromArea(dst_x, dst_y, width, height);
+}
+
+void LimitScreenUpdates(boolean enable)
+{
+  SDLLimitScreenUpdates(enable);
 }
 
 void InitVideoDisplay(void)
 {
-#if defined(TARGET_SDL)
   SDLInitVideoDisplay();
-#else
-  X11InitVideoDisplay();
+#if defined(TARGET_SDL2)
+  SDLSetDisplaySize();
 #endif
 }
 
@@ -370,12 +398,7 @@ void CloseVideoDisplay(void)
 {
   KeyboardAutoRepeatOn();
 
-#if defined(TARGET_SDL)
   SDL_QuitSubSystem(SDL_INIT_VIDEO);
-#else
-  if (display)
-    XCloseDisplay(display);
-#endif
 }
 
 void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
@@ -384,18 +407,28 @@ void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
   video.height = height;
   video.depth = GetRealDepth(depth);
 
+  video.screen_width = width;
+  video.screen_height = height;
+  video.screen_xoffset = 0;
+  video.screen_yoffset = 0;
+
   video.fullscreen_available = FULLSCREEN_STATUS;
   video.fullscreen_enabled = FALSE;
-#if 0
-  video.fullscreen_mode_current = NULL;
-  video.fullscreen_modes = NULL;
-#endif
 
-#if defined(TARGET_SDL)
-  SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
-#else
-  X11InitVideoBuffer(&backbuffer, &window);
-#endif
+  video.window_scaling_available = WINDOW_SCALING_STATUS;
+
+  video.frame_delay = 0;
+  video.frame_delay_value = GAME_FRAME_DELAY;
+
+  video.shifted_up = FALSE;
+  video.shifted_up_pos = 0;
+  video.shifted_up_pos_last = 0;
+  video.shifted_up_delay = 0;
+  video.shifted_up_delay_value = ONE_SECOND_DELAY / 4;
+
+  SDLInitVideoBuffer(fullscreen);
+
+  video.initialized = TRUE;
 
   drawto = backbuffer;
 }
@@ -405,11 +438,7 @@ inline static void FreeBitmapPointers(Bitmap *bitmap)
   if (bitmap == NULL)
     return;
 
-#if defined(TARGET_SDL)
   SDLFreeBitmapPointers(bitmap);
-#else
-  X11FreeBitmapPointers(bitmap);
-#endif
 
   checked_free(bitmap->source_filename);
   bitmap->source_filename = NULL;
@@ -438,11 +467,7 @@ void FreeBitmap(Bitmap *bitmap)
 
 Bitmap *CreateBitmapStruct(void)
 {
-#if defined(TARGET_SDL)
-  return checked_calloc(sizeof(struct SDLSurfaceInfo));
-#else
-  return checked_calloc(sizeof(struct X11DrawableInfo));
-#endif
+  return checked_calloc(sizeof(Bitmap));
 }
 
 Bitmap *CreateBitmap(int width, int height, int depth)
@@ -452,11 +477,7 @@ Bitmap *CreateBitmap(int width, int height, int depth)
   int real_height = MAX(1, height);	/* prevent zero bitmap height */
   int real_depth  = GetRealDepth(depth);
 
-#if defined(TARGET_SDL)
   SDLCreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
-#else
-  X11CreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
-#endif
 
   new_bitmap->width  = real_width;
   new_bitmap->height = real_height;
@@ -464,9 +485,9 @@ Bitmap *CreateBitmap(int width, int height, int depth)
   return new_bitmap;
 }
 
-void ReCreateBitmap(Bitmap **bitmap, int width, int height, int depth)
+void ReCreateBitmap(Bitmap **bitmap, int width, int height)
 {
-  Bitmap *new_bitmap = CreateBitmap(width, height, depth);
+  Bitmap *new_bitmap = CreateBitmap(width, height, DEFAULT_DEPTH);
 
   if (*bitmap == NULL)
   {
@@ -481,9 +502,28 @@ void ReCreateBitmap(Bitmap **bitmap, int width, int height, int depth)
 
 void CloseWindow(DrawWindow *window)
 {
-#if defined(TARGET_X11)
-  X11CloseWindow(window);
-#endif
+}
+
+void SetRedrawMaskFromArea(int x, int y, int width, int height)
+{
+  int x1 = x;
+  int y1 = y;
+  int x2 = x + width - 1;
+  int y2 = y + height - 1;
+
+  if (width == 0 || height == 0)
+    return;
+
+  if (IN_GFX_FIELD_FULL(x1, y1) && IN_GFX_FIELD_FULL(x2, y2))
+    redraw_mask |= REDRAW_FIELD;
+  else if (IN_GFX_DOOR_1(x1, y1) && IN_GFX_DOOR_1(x2, y2))
+    redraw_mask |= REDRAW_DOOR_1;
+  else if (IN_GFX_DOOR_2(x1, y1) && IN_GFX_DOOR_2(x2, y2))
+    redraw_mask |= REDRAW_DOOR_2;
+  else if (IN_GFX_DOOR_3(x1, y1) && IN_GFX_DOOR_3(x2, y2))
+    redraw_mask |= REDRAW_DOOR_3;
+  else
+    redraw_mask = REDRAW_ALL;
 }
 
 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
@@ -495,16 +535,16 @@ inline static boolean CheckDrawingArea(int x, int y, int width, int height,
   if (draw_mask & REDRAW_ALL)
     return TRUE;
 
-  if ((draw_mask & REDRAW_FIELD) &&
-      x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
+  if ((draw_mask & REDRAW_FIELD) && IN_GFX_FIELD_FULL(x, y))
+    return TRUE;
+
+  if ((draw_mask & REDRAW_DOOR_1) && IN_GFX_DOOR_1(x, y))
     return TRUE;
 
-  if ((draw_mask & REDRAW_DOOR_1) &&
-      x >= gfx.dx && y < gfx.dy + gfx.dysize)
+  if ((draw_mask & REDRAW_DOOR_2) && IN_GFX_DOOR_2(x, y))
     return TRUE;
 
-  if ((draw_mask & REDRAW_DOOR_2) &&
-      x >= gfx.dx && y >= gfx.vy)
+  if ((draw_mask & REDRAW_DOOR_3) && IN_GFX_DOOR_3(x, y))
     return TRUE;
 
   return FALSE;
@@ -524,7 +564,6 @@ boolean DrawingOnBackground(int x, int y)
 static boolean InClippedRectangle(Bitmap *bitmap, int *x, int *y,
 				  int *width, int *height, boolean is_dest)
 {
-#if 1
   int clip_x, clip_y, clip_width, clip_height;
 
   if (gfx.clipping_enabled && is_dest)	/* only clip destination bitmap */
@@ -573,41 +612,6 @@ static boolean InClippedRectangle(Bitmap *bitmap, int *x, int *y,
   }
 
   return TRUE;
-
-#else
-
-  /* skip if rectangle completely outside bitmap */
-
-  if (*x + *width <= 0 ||
-      *y + *height <= 0 ||
-      *x >= bitmap->width ||
-      *y >= bitmap->height)
-    return FALSE;
-
-  /* clip if rectangle overlaps bitmap */
-
-  if (*x < 0)
-  {
-    *width += *x;
-    *x = 0;
-  }
-  else if (*x + *width > bitmap->width)
-  {
-    *width = bitmap->width - *x;
-  }
-
-  if (*y < 0)
-  {
-    *height += *y;
-    *y = 0;
-  }
-  else if (*y + *height > bitmap->height)
-  {
-    *height = bitmap->height - *y;
-  }
-
-  return TRUE;
-#endif
 }
 
 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
@@ -617,10 +621,12 @@ void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
   int dst_x_unclipped = dst_x;
   int dst_y_unclipped = dst_y;
 
+  if (src_bitmap == NULL || dst_bitmap == NULL)
+    return;
+
   if (DrawingDeactivated(dst_x, dst_y, width, height))
     return;
 
-#if 1
   if (!InClippedRectangle(src_bitmap, &src_x, &src_y, &width, &height, FALSE) ||
       !InClippedRectangle(dst_bitmap, &dst_x, &dst_y, &width, &height, TRUE))
     return;
@@ -629,37 +635,16 @@ void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
   src_x += dst_x - dst_x_unclipped;
   src_y += dst_y - dst_y_unclipped;
 
-#else
-  /* skip if rectangle starts outside bitmap */
-  if (src_x >= src_bitmap->width ||
-      src_y >= src_bitmap->height ||
-      dst_x >= dst_bitmap->width ||
-      dst_y >= dst_bitmap->height)
-    return;
-
-  /* clip if rectangle overlaps bitmap */
-  if (src_x + width > src_bitmap->width)
-    width = src_bitmap->width - src_x;
-  if (src_y + height > src_bitmap->height)
-    height = src_bitmap->height - src_y;
-  if (dst_x + width > dst_bitmap->width)
-    width = dst_bitmap->width - dst_x;
-  if (dst_y + height > dst_bitmap->height)
-    height = dst_bitmap->height - dst_y;
-#endif
-
-#if 0
+#if defined(TARGET_SDL2)
+  /* !!! 2013-12-11: An "old friend" is back. Same bug in SDL2 2.0.1 !!! */
   /* !!! 2009-03-30: Fixed by using self-compiled, patched SDL.dll !!! */
   /* (This bug still exists in the actual (as of 2009-06-15) version 1.2.13,
      but is already fixed in SVN and should therefore finally be fixed with
      the next official SDL release, which is probably version 1.2.14.) */
-#if 1
   /* !!! 2009-03-24: It seems that this problem still exists in 1.2.12 !!! */
-#if defined(TARGET_SDL) && defined(PLATFORM_WIN32)
+
   if (src_bitmap == dst_bitmap)
   {
-    /* !!! THIS IS A BUG (IN THE SDL LIBRARY?) AND SHOULD BE FIXED !!! */
-
     /* needed when blitting directly to same bitmap -- should not be needed with
        recent SDL libraries, but apparently does not work in 1.2.11 directly */
 
@@ -698,30 +683,48 @@ void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
     return;
   }
 #endif
-#endif
-#endif
 
   sysCopyArea(src_bitmap, dst_bitmap,
 	      src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
 }
 
-void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
+void BlitBitmapTiled(Bitmap *src_bitmap, Bitmap *dst_bitmap,
+		     int src_x, int src_y, int src_width, int src_height,
+		     int dst_x, int dst_y, int dst_width, int dst_height)
+{
+  int src_xsize = (src_width  == 0 ? src_bitmap->width  : src_width);
+  int src_ysize = (src_height == 0 ? src_bitmap->height : src_height);
+  int dst_xsize = dst_width;
+  int dst_ysize = dst_height;
+  int src_xsteps = (dst_xsize + src_xsize - 1) / src_xsize;
+  int src_ysteps = (dst_ysize + src_ysize - 1) / src_ysize;
+  int x, y;
+
+  for (y = 0; y < src_ysteps; y++)
+  {
+    for (x = 0; x < src_xsteps; x++)
+    {
+      int draw_x = dst_x + x * src_xsize;
+      int draw_y = dst_y + y * src_ysize;
+      int draw_xsize = MIN(src_xsize, dst_xsize - x * src_xsize);
+      int draw_ysize = MIN(src_ysize, dst_ysize - y * src_ysize);
+
+      BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, draw_xsize, draw_ysize,
+		 draw_x, draw_y);
+    }
+  }
+}
+
+void FadeRectangle(int x, int y, int width, int height,
 		   int fade_mode, int fade_delay, int post_delay,
 		   void (*draw_border_function)(void))
 {
-#if 1
   /* (use destination bitmap "backbuffer" -- "bitmap_cross" may be undefined) */
   if (!InClippedRectangle(backbuffer, &x, &y, &width, &height, TRUE))
     return;
-#endif
 
-#if defined(TARGET_SDL)
-  SDLFadeRectangle(bitmap_cross, x, y, width, height,
-		   fade_mode, fade_delay, post_delay, draw_border_function);
-#else
-  X11FadeRectangle(bitmap_cross, x, y, width, height,
+  SDLFadeRectangle(x, y, width, height,
 		   fade_mode, fade_delay, post_delay, draw_border_function);
-#endif
 }
 
 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
@@ -730,21 +733,8 @@ void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
   if (DrawingDeactivated(x, y, width, height))
     return;
 
-#if 1
   if (!InClippedRectangle(bitmap, &x, &y, &width, &height, TRUE))
     return;
-#else
-  /* skip if rectangle starts outside bitmap */
-  if (x >= bitmap->width ||
-      y >= bitmap->height)
-    return;
-
-  /* clip if rectangle overlaps bitmap */
-  if (x + width > bitmap->width)
-    width = bitmap->width - x;
-  if (y + height > bitmap->height)
-    height = bitmap->height - y;
-#endif
 
   sysFillRectangle(bitmap, x, y, width, height, color);
 }
@@ -763,28 +753,6 @@ void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
     ClearRectangle(bitmap, x, y, width, height);
 }
 
-void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
-{
-#if defined(TARGET_X11)
-  if (clip_gc)
-  {
-    bitmap->clip_gc = clip_gc;
-    XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
-  }
-#endif
-}
-
-void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
-{
-#if defined(TARGET_X11)
-  if (clip_gc)
-  {
-    bitmap->clip_gc = clip_gc;
-    XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
-  }
-#endif
-}
-
 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
 		      int src_x, int src_y, int width, int height,
 		      int dst_x, int dst_y)
@@ -807,8 +775,6 @@ void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
 	       dst_x, dst_y);
 
     /* draw foreground */
-    SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
-		  dst_x - src_x, dst_y - src_y);
     BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
 		     dst_x, dst_y);
   }
@@ -817,27 +783,68 @@ void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
 	       dst_x, dst_y);
 }
 
+void BlitTexture(Bitmap *bitmap,
+		int src_x, int src_y, int width, int height,
+		int dst_x, int dst_y)
+{
+  if (bitmap == NULL)
+    return;
+
+  SDLBlitTexture(bitmap, src_x, src_y, width, height, dst_x, dst_y,
+		 BLIT_OPAQUE);
+}
+
+void BlitTextureMasked(Bitmap *bitmap,
+		       int src_x, int src_y, int width, int height,
+		       int dst_x, int dst_y)
+{
+  if (bitmap == NULL)
+    return;
+
+  SDLBlitTexture(bitmap, src_x, src_y, width, height, dst_x, dst_y,
+		 BLIT_MASKED);
+}
+
+void BlitToScreen(Bitmap *bitmap,
+		  int src_x, int src_y, int width, int height,
+		  int dst_x, int dst_y)
+{
+  if (bitmap == NULL)
+    return;
+
+  if (video.screen_rendering_mode == SPECIAL_RENDERING_BITMAP)
+    BlitBitmap(bitmap, gfx.final_screen_bitmap, src_x, src_y,
+	       width, height, dst_x, dst_y);
+  else
+    BlitTexture(bitmap, src_x, src_y, width, height, dst_x, dst_y);
+}
+
+void BlitToScreenMasked(Bitmap *bitmap,
+			int src_x, int src_y, int width, int height,
+			int dst_x, int dst_y)
+{
+  if (bitmap == NULL)
+    return;
+
+  if (video.screen_rendering_mode == SPECIAL_RENDERING_BITMAP)
+    BlitBitmapMasked(bitmap, gfx.final_screen_bitmap, src_x, src_y,
+		     width, height, dst_x, dst_y);
+  else
+    BlitTextureMasked(bitmap, src_x, src_y, width, height, dst_x, dst_y);
+}
+
 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
 			 int to_x, int to_y)
 {
-#if defined(TARGET_SDL)
   SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
-#else
-  X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
-#endif
 }
 
 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
 			 int to_x, int to_y)
 {
-#if defined(TARGET_SDL)
   SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
-#else
-  X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
-#endif
 }
 
-#if !defined(TARGET_X11_NATIVE)
 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
 	      int to_x, int to_y, Pixel pixel, int line_width)
 {
@@ -856,21 +863,14 @@ void DrawLine(Bitmap *bitmap, int from_x, int from_y,
 	  (x == line_width - 1 && y == line_width - 1))
 	continue;
 
-#if defined(TARGET_SDL)
       SDLDrawLine(bitmap,
 		  from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
-#elif defined(TARGET_ALLEGRO)
-      AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
-		      to_x + dx, to_y + dy, pixel);
-#endif
     }
   }
 }
-#endif
 
 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
 {
-#if !defined(TARGET_X11_NATIVE)
   int line_width = 4;
   int i;
 
@@ -881,11 +881,6 @@ void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
   /*
   SDLDrawLines(bitmap->surface, points, num_points, pixel);
   */
-#else
-  XSetForeground(display, bitmap->line_gc[1], pixel);
-  XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
-	     (XPoint *)points, num_points, CoordModeOrigin);
-#endif
 }
 
 Pixel GetPixel(Bitmap *bitmap, int x, int y)
@@ -894,25 +889,13 @@ Pixel GetPixel(Bitmap *bitmap, int x, int y)
       y < 0 || y >= bitmap->height)
     return BLACK_PIXEL;
 
-#if defined(TARGET_SDL)
   return SDLGetPixel(bitmap, x, y);
-#elif defined(TARGET_ALLEGRO)
-  return AllegroGetPixel(bitmap->drawable, x, y);
-#else
-  return X11GetPixel(bitmap, x, y);
-#endif
 }
 
 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
 		      unsigned int color_g, unsigned int color_b)
 {
-#if defined(TARGET_SDL)
   return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
-#elif defined(TARGET_ALLEGRO)
-  return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
-#else
-  return X11GetPixelFromRGB(color_r, color_g, color_b);
-#endif
 }
 
 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
@@ -924,90 +907,47 @@ Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
   return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
 }
 
-/* execute all pending screen drawing operations */
-void FlushDisplay(void)
-{
-#ifndef TARGET_SDL
-  XFlush(display);
-#endif
-}
-
-/* execute and wait for all pending screen drawing operations */
-void SyncDisplay(void)
-{
-#ifndef TARGET_SDL
-  XSync(display, FALSE);
-#endif
-}
-
 void KeyboardAutoRepeatOn(void)
 {
-#if defined(TARGET_SDL)
+#if defined(TARGET_SDL2)
+  keyrepeat_status = TRUE;
+#else
   SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
 		      SDL_DEFAULT_REPEAT_INTERVAL / 2);
   SDL_EnableUNICODE(1);
-#else
-  if (display)
-    XAutoRepeatOn(display);
 #endif
 }
 
 void KeyboardAutoRepeatOff(void)
 {
-#if defined(TARGET_SDL)
+#if defined(TARGET_SDL2)
+  keyrepeat_status = FALSE;
+#else
   SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
   SDL_EnableUNICODE(0);
-#else
-  if (display)
-    XAutoRepeatOff(display);
 #endif
 }
 
-boolean PointerInWindow(DrawWindow *window)
+boolean SetVideoMode(boolean fullscreen)
 {
-#if defined(TARGET_SDL)
-  return TRUE;
-#else
-  Window root, child;
-  int root_x, root_y;
-  unsigned int mask;
-  int win_x, win_y;
-
-  /* if XQueryPointer() returns False, the pointer
-     is not on the same screen as the specified window */
-  return XQueryPointer(display, window->drawable, &root, &child,
-		       &root_x, &root_y, &win_x, &win_y, &mask);
-#endif
+  return SDLSetVideoMode(fullscreen);
 }
 
-boolean SetVideoMode(boolean fullscreen)
+void SetVideoFrameDelay(unsigned int frame_delay_value)
 {
-#if defined(TARGET_SDL)
-  return SDLSetVideoMode(&backbuffer, fullscreen);
-#else
-  boolean success = TRUE;
-
-  if (fullscreen && video.fullscreen_available)
-  {
-    Error(ERR_WARN, "fullscreen not available in X11 version");
-
-    /* display error message only once */
-    video.fullscreen_available = FALSE;
-
-    success = FALSE;
-  }
+  video.frame_delay_value = frame_delay_value;
+}
 
-  return success;
-#endif
+unsigned int GetVideoFrameDelay()
+{
+  return video.frame_delay_value;
 }
 
 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
 {
-#if defined(TARGET_SDL)
   if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
       (!fullscreen && video.fullscreen_enabled))
     fullscreen = SetVideoMode(fullscreen);
-#endif
 
   return fullscreen;
 }
@@ -1016,11 +956,7 @@ Bitmap *LoadImage(char *filename)
 {
   Bitmap *new_bitmap;
 
-#if defined(TARGET_SDL)
   new_bitmap = SDLLoadImage(filename);
-#else
-  new_bitmap = X11LoadImage(filename);
-#endif
 
   if (new_bitmap)
     new_bitmap->source_filename = getStringCopy(filename);
@@ -1037,7 +973,7 @@ Bitmap *LoadCustomImage(char *basename)
     Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
 
   if ((new_bitmap = LoadImage(filename)) == NULL)
-    Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
+    Error(ERR_EXIT, "LoadImage('%s') failed: %s", basename, GetError());
 
   return new_bitmap;
 }
@@ -1064,7 +1000,7 @@ void ReloadCustomImage(Bitmap *bitmap, char *basename)
 
   if ((new_bitmap = LoadImage(filename)) == NULL)
   {
-    Error(ERR_WARN, "LoadImage() failed: %s", GetError());
+    Error(ERR_WARN, "LoadImage('%s') failed: %s", basename, GetError());
     return;
   }
 
@@ -1081,57 +1017,121 @@ void ReloadCustomImage(Bitmap *bitmap, char *basename)
   free(new_bitmap);
 }
 
-Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
+static Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
 {
-  Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
+  return SDLZoomBitmap(src_bitmap, zoom_width, zoom_height);
+}
 
-#if defined(TARGET_SDL)
-  SDLZoomBitmap(src_bitmap, dst_bitmap);
-#else
-  X11ZoomBitmap(src_bitmap, dst_bitmap);
-#endif
+void ReCreateGameTileSizeBitmap(Bitmap **bitmaps)
+{
+  if (bitmaps[IMG_BITMAP_CUSTOM])
+  {
+    FreeBitmap(bitmaps[IMG_BITMAP_CUSTOM]);
+
+    bitmaps[IMG_BITMAP_CUSTOM] = NULL;
+  }
+
+  if (gfx.game_tile_size == gfx.standard_tile_size)
+  {
+    bitmaps[IMG_BITMAP_GAME] = bitmaps[IMG_BITMAP_STANDARD];
+
+    return;
+  }
+
+  Bitmap *bitmap = bitmaps[IMG_BITMAP_STANDARD];
+  int width  = bitmap->width  * gfx.game_tile_size / gfx.standard_tile_size;;
+  int height = bitmap->height * gfx.game_tile_size / gfx.standard_tile_size;;
+
+  Bitmap *bitmap_new = ZoomBitmap(bitmap, width, height);
 
-  return dst_bitmap;
+  bitmaps[IMG_BITMAP_CUSTOM] = bitmap_new;
+  bitmaps[IMG_BITMAP_GAME]   = bitmap_new;
 }
 
-static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
-				boolean create_small_bitmaps)
+static void CreateScaledBitmaps(Bitmap **bitmaps, int zoom_factor,
+				int tile_size, boolean create_small_bitmaps)
 {
-  Bitmap swap_bitmap;
-  Bitmap *new_bitmap;
-  Bitmap *tmp_bitmap_1;
-  Bitmap *tmp_bitmap_2;
-  Bitmap *tmp_bitmap_4;
-  Bitmap *tmp_bitmap_8;
-  Bitmap *tmp_bitmap_16;
-  Bitmap *tmp_bitmap_32;
+  Bitmap *old_bitmap = bitmaps[IMG_BITMAP_STANDARD];
+  Bitmap *tmp_bitmap_final = NULL;
+  Bitmap *tmp_bitmap_0 = NULL;
+  Bitmap *tmp_bitmap_1 = NULL;
+  Bitmap *tmp_bitmap_2 = NULL;
+  Bitmap *tmp_bitmap_4 = NULL;
+  Bitmap *tmp_bitmap_8 = NULL;
+  Bitmap *tmp_bitmap_16 = NULL;
+  Bitmap *tmp_bitmap_32 = NULL;
+  int width_final, height_final;
+  int width_0, height_0;
   int width_1, height_1;
   int width_2, height_2;
   int width_4, height_4;
   int width_8, height_8;
   int width_16, height_16;
   int width_32, height_32;
-  int new_width, new_height;
+  int old_width, old_height;
+  int i;
+
+  print_timestamp_init("CreateScaledBitmaps");
 
-  /* calculate new image dimensions for normal sized image */
-  width_1  = old_bitmap->width  * zoom_factor;
-  height_1 = old_bitmap->height * zoom_factor;
+  old_width  = old_bitmap->width;
+  old_height = old_bitmap->height;
 
-  /* get image with normal size (this might require scaling up) */
+  /* calculate new image dimensions for final image size */
+  width_final  = old_width  * zoom_factor;
+  height_final = old_height * zoom_factor;
+
+  /* get image with final size (this might require scaling up) */
+  /* ("final" size may result in non-standard tile size image) */
   if (zoom_factor != 1)
-    tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
+    tmp_bitmap_final = ZoomBitmap(old_bitmap, width_final, height_final);
   else
-    tmp_bitmap_1 = old_bitmap;
+    tmp_bitmap_final = old_bitmap;
+
+  UPDATE_BUSY_STATE();
 
-  /* this is only needed to make compilers happy */
-  tmp_bitmap_2 = NULL;
-  tmp_bitmap_4 = NULL;
-  tmp_bitmap_8 = NULL;
-  tmp_bitmap_16 = NULL;
-  tmp_bitmap_32 = NULL;
+  width_0  = width_1  = width_final;
+  height_0 = height_1 = height_final;
+
+  tmp_bitmap_0 = tmp_bitmap_1 = tmp_bitmap_final;
 
   if (create_small_bitmaps)
   {
+    /* check if we have a non-gameplay tile size image */
+    if (tile_size != gfx.game_tile_size)
+    {
+      /* get image with gameplay tile size */
+      width_0  = width_final  * gfx.game_tile_size / tile_size;
+      height_0 = height_final * gfx.game_tile_size / tile_size;
+
+      if (width_0 == old_width)
+	tmp_bitmap_0 = old_bitmap;
+      else if (width_0 == width_final)
+	tmp_bitmap_0 = tmp_bitmap_final;
+      else
+	tmp_bitmap_0 = ZoomBitmap(old_bitmap, width_0, height_0);
+
+      UPDATE_BUSY_STATE();
+    }
+
+    /* check if we have a non-standard tile size image */
+    if (tile_size != gfx.standard_tile_size)
+    {
+      /* get image with standard tile size */
+      width_1  = width_final  * gfx.standard_tile_size / tile_size;
+      height_1 = height_final * gfx.standard_tile_size / tile_size;
+
+      if (width_1 == old_width)
+	tmp_bitmap_1 = old_bitmap;
+      else if (width_1 == width_final)
+	tmp_bitmap_1 = tmp_bitmap_final;
+      else if (width_1 == width_0)
+	tmp_bitmap_1 = tmp_bitmap_0;
+      else
+	tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
+
+      UPDATE_BUSY_STATE();
+    }
+
     /* calculate new image dimensions for small images */
     width_2  = width_1  / 2;
     height_2 = height_1 / 2;
@@ -1144,180 +1144,99 @@ static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
     width_32  = width_1  / 32;
     height_32 = height_1 / 32;
 
-    UPDATE_BUSY_STATE();
-
     /* get image with 1/2 of normal size (for use in the level editor) */
-    if (zoom_factor != 2)
-      tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
-    else
+    if (width_2 == old_width)
       tmp_bitmap_2 = old_bitmap;
+    else
+      tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_2, height_2);
 
     UPDATE_BUSY_STATE();
 
     /* get image with 1/4 of normal size (for use in the level editor) */
-    if (zoom_factor != 4)
-      tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
-    else
+    if (width_4 == old_width)
       tmp_bitmap_4 = old_bitmap;
+    else
+      tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_4, height_4);
 
     UPDATE_BUSY_STATE();
 
     /* get image with 1/8 of normal size (for use on the preview screen) */
-    if (zoom_factor != 8)
-      tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
-    else
+    if (width_8 == old_width)
       tmp_bitmap_8 = old_bitmap;
+    else
+      tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_8, height_8);
 
     UPDATE_BUSY_STATE();
 
     /* get image with 1/16 of normal size (for use on the preview screen) */
-    if (zoom_factor != 16)
-      tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
-    else
+    if (width_16 == old_width)
       tmp_bitmap_16 = old_bitmap;
+    else
+      tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_16, height_16);
 
     UPDATE_BUSY_STATE();
 
     /* get image with 1/32 of normal size (for use on the preview screen) */
-    if (zoom_factor != 32)
-      tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
-    else
+    if (width_32 == old_width)
       tmp_bitmap_32 = old_bitmap;
+    else
+      tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_32, height_32);
 
     UPDATE_BUSY_STATE();
-  }
-
-#if 0
-  /* if image was scaled up, create new clipmask for normal size image */
-  if (zoom_factor != 1)
-  {
-#if defined(TARGET_X11)
-    if (old_bitmap->clip_mask)
-      XFreePixmap(display, old_bitmap->clip_mask);
 
-    old_bitmap->clip_mask =
-      Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
+    bitmaps[IMG_BITMAP_32x32] = tmp_bitmap_1;
+    bitmaps[IMG_BITMAP_16x16] = tmp_bitmap_2;
+    bitmaps[IMG_BITMAP_8x8]   = tmp_bitmap_4;
+    bitmaps[IMG_BITMAP_4x4]   = tmp_bitmap_8;
+    bitmaps[IMG_BITMAP_2x2]   = tmp_bitmap_16;
+    bitmaps[IMG_BITMAP_1x1]   = tmp_bitmap_32;
 
-    XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
-#else
-    SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
+    if (width_0 != width_1)
+      bitmaps[IMG_BITMAP_CUSTOM] = tmp_bitmap_0;
 
-    if (old_bitmap->surface_masked)
-      SDL_FreeSurface(old_bitmap->surface_masked);
+    if (bitmaps[IMG_BITMAP_CUSTOM])
+      bitmaps[IMG_BITMAP_GAME] = bitmaps[IMG_BITMAP_CUSTOM];
+    else
+      bitmaps[IMG_BITMAP_GAME] = bitmaps[IMG_BITMAP_STANDARD];
 
-    SDL_SetColorKey(tmp_surface_1, SDL_SRCCOLORKEY,
-		    SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
-    if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
-      Error(ERR_EXIT, "SDL_DisplayFormat() failed");
-    SDL_SetColorKey(tmp_surface_1, 0, 0);	/* reset transparent pixel */
-#endif
-  }
-#endif
+    boolean free_old_bitmap = TRUE;
 
-  if (create_small_bitmaps)
-  {
-    new_width  = width_1;
-    new_height = height_1 + (height_1 + 1) / 2;     /* prevent odd height */
-
-    new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
-
-    BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
-    BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
-	       0, height_1);
-    BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
-	       width_1 / 2, height_1);
-    BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
-	       3 * width_1 / 4, height_1);
-    BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
-	       7 * width_1 / 8, height_1);
-    BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
-	       15 * width_1 / 16, height_1);
+    for (i = 0; i < NUM_IMG_BITMAPS; i++)
+      if (bitmaps[i] == old_bitmap)
+	free_old_bitmap = FALSE;
 
-    UPDATE_BUSY_STATE();
+    if (free_old_bitmap)
+      FreeBitmap(old_bitmap);
   }
   else
   {
-    new_width  = width_1;
-    new_height = height_1;
-
-    new_bitmap = tmp_bitmap_1;	/* directly use tmp_bitmap_1 as new bitmap */
-  }
-
-  if (create_small_bitmaps)
-  {
-    /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
-    if (zoom_factor != 1)
-      FreeBitmap(tmp_bitmap_1);
-
-    if (zoom_factor != 2)
-      FreeBitmap(tmp_bitmap_2);
-
-    if (zoom_factor != 4)
-      FreeBitmap(tmp_bitmap_4);
-
-    if (zoom_factor != 8)
-      FreeBitmap(tmp_bitmap_8);
-
-    if (zoom_factor != 16)
-      FreeBitmap(tmp_bitmap_16);
-
-    if (zoom_factor != 32)
-      FreeBitmap(tmp_bitmap_32);
+    bitmaps[IMG_BITMAP_32x32] = tmp_bitmap_1;
   }
 
-  /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
-#if defined(TARGET_SDL)
-  swap_bitmap.surface = old_bitmap->surface;
-  old_bitmap->surface = new_bitmap->surface;
-  new_bitmap->surface = swap_bitmap.surface;
-#else
-  swap_bitmap.drawable = old_bitmap->drawable;
-  old_bitmap->drawable = new_bitmap->drawable;
-  new_bitmap->drawable = swap_bitmap.drawable;
-#endif
-
-  old_bitmap->width  = new_bitmap->width;
-  old_bitmap->height = new_bitmap->height;
-
-#if 1
-  /* this replaces all blit masks created when loading -- maybe optimize this */
-  {
-#if defined(TARGET_X11)
-    if (old_bitmap->clip_mask)
-      XFreePixmap(display, old_bitmap->clip_mask);
-
-    old_bitmap->clip_mask =
-      Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
-
-    XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
-#else
-    SDL_Surface *old_surface = old_bitmap->surface;
-
-    if (old_bitmap->surface_masked)
-      SDL_FreeSurface(old_bitmap->surface_masked);
+  UPDATE_BUSY_STATE();
 
-    SDL_SetColorKey(old_surface, SDL_SRCCOLORKEY,
-		    SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
-    if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
-      Error(ERR_EXIT, "SDL_DisplayFormat() failed");
-    SDL_SetColorKey(old_surface, 0, 0);		/* reset transparent pixel */
-#endif
-  }
-#endif
+  print_timestamp_done("CreateScaledBitmaps");
+}
 
-  UPDATE_BUSY_STATE();
+void CreateBitmapWithSmallBitmaps(Bitmap **bitmaps, int zoom_factor,
+				  int tile_size)
+{
+  CreateScaledBitmaps(bitmaps, zoom_factor, tile_size, TRUE);
+}
 
-  FreeBitmap(new_bitmap);	/* this actually frees the _old_ bitmap now */
+void CreateBitmapTextures(Bitmap **bitmaps)
+{
+  SDLCreateBitmapTextures(bitmaps[IMG_BITMAP_STANDARD]);
 }
 
-void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
+void FreeBitmapTextures(Bitmap **bitmaps)
 {
-  CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
+  SDLFreeBitmapTextures(bitmaps[IMG_BITMAP_STANDARD]);
 }
 
-void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
+void ScaleBitmap(Bitmap **bitmaps, int zoom_factor)
 {
-  CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
+  CreateScaledBitmaps(bitmaps, zoom_factor, 0, FALSE);
 }
 
 
@@ -1325,8 +1244,8 @@ void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
 /* mouse pointer functions                                                   */
 /* ------------------------------------------------------------------------- */
 
-#if !defined(PLATFORM_MSDOS)
 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER		0
+
 /* XPM image definitions */
 static const char *cursor_image_none[] =
 {
@@ -1359,6 +1278,7 @@ static const char *cursor_image_none[] =
   /* hot spot */
   "0,0"
 };
+
 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
 static const char *cursor_image_dot[] =
 {
@@ -1398,11 +1318,7 @@ static const char **cursor_image_playfield = cursor_image_dot;
 static const char **cursor_image_playfield = cursor_image_none;
 #endif
 
-#if defined(TARGET_SDL)
 static const int cursor_bit_order = BIT_ORDER_MSB;
-#elif defined(TARGET_X11_NATIVE)
-static const int cursor_bit_order = BIT_ORDER_LSB;
-#endif
 
 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
 {
@@ -1450,11 +1366,9 @@ static struct MouseCursorInfo *get_cursor_from_image(const char **image)
 
   return cursor;
 }
-#endif	/* !PLATFORM_MSDOS */
 
 void SetMouseCursor(int mode)
 {
-#if !defined(PLATFORM_MSDOS)
   static struct MouseCursorInfo *cursor_none = NULL;
   static struct MouseCursorInfo *cursor_playfield = NULL;
   struct MouseCursorInfo *cursor_new;
@@ -1469,12 +1383,9 @@ void SetMouseCursor(int mode)
 		mode == CURSOR_NONE      ? cursor_none :
 		mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
 
-#if defined(TARGET_SDL)
   SDLSetMouseCursor(cursor_new);
-#elif defined(TARGET_X11_NATIVE)
-  X11SetMouseCursor(cursor_new);
-#endif
-#endif
+
+  gfx.cursor_mode = mode;
 }
 
 
@@ -1501,24 +1412,12 @@ void OpenAudio(void)
   audio.music_channel = 0;
   audio.first_sound_channel = 0;
 
-#if defined(TARGET_SDL)
   SDLOpenAudio();
-#elif defined(PLATFORM_UNIX)
-  UnixOpenAudio();
-#elif defined(PLATFORM_MSDOS)
-  MSDOSOpenAudio();
-#endif
 }
 
 void CloseAudio(void)
 {
-#if defined(TARGET_SDL)
   SDLCloseAudio();
-#elif defined(PLATFORM_UNIX)
-  UnixCloseAudio();
-#elif defined(PLATFORM_MSDOS)
-  MSDOSCloseAudio();
-#endif
 
   audio.sound_enabled = FALSE;
 }
@@ -1536,46 +1435,33 @@ void SetAudioMode(boolean enabled)
 /* event functions                                                           */
 /* ========================================================================= */
 
-void InitEventFilter(EventFilter filter_function)
-{
-#if defined(TARGET_SDL)
-  /* set event filter to filter out certain events */
-  SDL_SetEventFilter(filter_function);
-#endif
-}
-
 boolean PendingEvent(void)
 {
-#if defined(TARGET_SDL)
   return (SDL_PollEvent(NULL) ? TRUE : FALSE);
-#else
-  return (XPending(display) ? TRUE : FALSE);
-#endif
 }
 
 void NextEvent(Event *event)
 {
-#if defined(TARGET_SDL)
   SDLNextEvent(event);
-#else
-  XNextEvent(display, event);
-#endif
 }
 
 void PeekEvent(Event *event)
 {
-#if defined(TARGET_SDL)
-  SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
+#if defined(TARGET_SDL2)
+  SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
 #else
-  XPeekEvent(display, event);
+  SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
 #endif
 }
 
 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
 {
-#if defined(TARGET_SDL)
+#if defined(TARGET_SDL2)
+  /* key up/down events in SDL2 do not return text characters anymore */
+  return event->keysym.sym;
+#else
 
-#if 0
+#if ENABLE_UNUSED_CODE
   printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
 	 (int)event->keysym.unicode,
 	 (int)event->keysym.sym,
@@ -1589,18 +1475,6 @@ Key GetEventKey(KeyEvent *event, boolean with_modifiers)
   else
     return event->keysym.sym;
 
-#else
-
-#if 0
-  printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
-	 (int)XLookupKeysym(event, event->state),
-	 (int)XLookupKeysym(event, 0));
-#endif
-
-  if (with_modifiers)
-    return XLookupKeysym(event, event->state);
-  else
-    return XLookupKeysym(event, 0);
 #endif
 }
 
@@ -1653,11 +1527,7 @@ KeyMod HandleKeyModState(Key key, int key_status)
 
 KeyMod GetKeyModState()
 {
-#if defined(TARGET_SDL)
   return (KeyMod)SDL_GetModState();
-#else
-  return HandleKeyModState(KSYM_UNDEFINED, 0);
-#endif
 }
 
 KeyMod GetKeyModStateFromEvents()
@@ -1671,20 +1541,44 @@ KeyMod GetKeyModStateFromEvents()
   return HandleKeyModState(KSYM_UNDEFINED, 0);
 }
 
+void StartTextInput(int x, int y, int width, int height)
+{
+#if defined(TARGET_SDL2)
+  SDL_StartTextInput();
+
+#if defined(HAS_SCREEN_KEYBOARD)
+  if (y + height > SCREEN_KEYBOARD_POS(video.height))
+  {
+    video.shifted_up_pos = y + height - SCREEN_KEYBOARD_POS(video.height);
+    video.shifted_up_delay = SDL_GetTicks();
+    video.shifted_up = TRUE;
+  }
+#endif
+#endif
+}
+
+void StopTextInput()
+{
+#if defined(TARGET_SDL2)
+  SDL_StopTextInput();
+
+#if defined(HAS_SCREEN_KEYBOARD)
+  if (video.shifted_up)
+  {
+    video.shifted_up_pos = 0;
+    video.shifted_up_delay = SDL_GetTicks();
+    video.shifted_up = FALSE;
+  }
+#endif
+#endif
+}
+
 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
 {
   if (event->type != EVENT_CLIENTMESSAGE)
     return FALSE;
 
-#if defined(TARGET_SDL)
   return TRUE;		/* the only possible message here is SDL_QUIT */
-#elif defined(PLATFORM_UNIX)
-  if ((event->window == window->drawable) &&
-      (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
-    return TRUE;
-#endif
-
-  return FALSE;
 }
 
 
@@ -1705,27 +1599,10 @@ void InitJoysticks()
   for (i = 0; i < MAX_PLAYERS; i++)
     joystick.fd[i] = -1;		/* joystick device closed */
 
-#if defined(TARGET_SDL)
   SDLInitJoysticks();
-#elif defined(PLATFORM_UNIX)
-  UnixInitJoysticks();
-#elif defined(PLATFORM_MSDOS)
-  MSDOSInitJoysticks();
-#endif
-
-#if 0
-  for (i = 0; i < MAX_PLAYERS; i++)
-    printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
-#endif
 }
 
 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
 {
-#if defined(TARGET_SDL)
   return SDLReadJoystick(nr, x, y, b1, b2);
-#elif defined(PLATFORM_UNIX)
-  return UnixReadJoystick(nr, x, y, b1, b2);
-#elif defined(PLATFORM_MSDOS)
-  return MSDOSReadJoystick(nr, x, y, b1, b2);
-#endif
 }
diff --git a/src/libgame/system.h b/src/libgame/system.h
index 4383b60..fb209d3 100644
--- a/src/libgame/system.h
+++ b/src/libgame/system.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* system.h                                                 *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// system.h
+// ============================================================================
 
 #ifndef SYSTEM_H
 #define SYSTEM_H
@@ -22,15 +20,11 @@
 #include "macosx.h"
 #elif defined(PLATFORM_WIN32)
 #include "windows.h"
-#elif defined(PLATFORM_MSDOS)
-#include "msdos.h"
+#elif defined(PLATFORM_ANDROID)
+#include "android.h"
 #endif
 
-#if defined(TARGET_SDL)
 #include "sdl.h"
-#elif defined(TARGET_X11)
-#include "x11.h"
-#endif
 
 
 /* the additional 'b' is needed for Win32 to open files in binary mode */
@@ -45,9 +39,69 @@
 #define BLIT_INVERSE			2
 #define BLIT_ON_BACKGROUND		3
 
+/* values for fullscreen status */
 #define FULLSCREEN_NOT_AVAILABLE	FALSE
 #define FULLSCREEN_AVAILABLE		TRUE
 
+/* values for window scaling */
+#define WINDOW_SCALING_NOT_AVAILABLE	FALSE
+#define WINDOW_SCALING_AVAILABLE	TRUE
+
+#define MIN_WINDOW_SCALING_PERCENT	30
+#define STD_WINDOW_SCALING_PERCENT	100
+#define MAX_WINDOW_SCALING_PERCENT	400
+#define STEP_WINDOW_SCALING_PERCENT	10
+
+/* values for window scaling quality */
+#define SCALING_QUALITY_NEAREST		"nearest"
+#define SCALING_QUALITY_LINEAR		"linear"
+#define SCALING_QUALITY_BEST		"best"
+
+#define SCALING_QUALITY_DEFAULT		SCALING_QUALITY_LINEAR
+
+/* values for screen rendering mode */
+#define STR_SPECIAL_RENDERING_OFF	"stream_texture_only"
+#define STR_SPECIAL_RENDERING_BITMAP	"bitmap_and_stream_texture"
+#define STR_SPECIAL_RENDERING_TARGET	"target_texture_only"
+#define STR_SPECIAL_RENDERING_DOUBLE	"stream_and_target_texture"
+
+#if defined(TARGET_SDL2)
+#define STR_SPECIAL_RENDERING_DEFAULT	STR_SPECIAL_RENDERING_DOUBLE
+#else
+#define STR_SPECIAL_RENDERING_DEFAULT	STR_SPECIAL_RENDERING_BITMAP
+#endif
+
+#define SPECIAL_RENDERING_OFF		0
+#define SPECIAL_RENDERING_BITMAP	1
+#define SPECIAL_RENDERING_TARGET	2
+#define SPECIAL_RENDERING_DOUBLE	3
+
+#if defined(TARGET_SDL2)
+#define SPECIAL_RENDERING_DEFAULT	SPECIAL_RENDERING_DOUBLE
+#else
+#define SPECIAL_RENDERING_DEFAULT	SPECIAL_RENDERING_BITMAP
+#endif
+
+/* values for touch control */
+#define TOUCH_CONTROL_VIRTUAL_BUTTONS	"virtual_buttons"
+#define TOUCH_CONTROL_WIPE_GESTURES	"wipe_gestures"
+#define TOUCH_CONTROL_FOLLOW_FINGER	"follow_finger"
+
+#define TOUCH_CONTROL_DEFAULT		TOUCH_CONTROL_VIRTUAL_BUTTONS
+
+#define TOUCH_MOVE_DISTANCE_DEFAULT	2
+#define TOUCH_DROP_DISTANCE_DEFAULT	5
+
+
+/* values for special settings for mobile devices */
+#if defined(PLATFORM_ANDROID)
+#define USE_TOUCH_INPUT_OVERLAY
+#define USE_COMPLETE_DISPLAY
+#define HAS_SCREEN_KEYBOARD
+#define SCREEN_KEYBOARD_POS(h)		((h) / 2)
+#endif
+
+
 /* default input keys */
 #define DEFAULT_KEY_LEFT		KSYM_Left
 #define DEFAULT_KEY_RIGHT		KSYM_Right
@@ -73,6 +127,7 @@
 #define DEFAULT_KEY_FOCUS_PLAYER_4	KSYM_F8
 #define DEFAULT_KEY_FOCUS_PLAYER_ALL	KSYM_F9
 #define DEFAULT_KEY_TAPE_EJECT		KSYM_UNDEFINED
+#define DEFAULT_KEY_TAPE_EXTRA		KSYM_UNDEFINED
 #define DEFAULT_KEY_TAPE_STOP		KSYM_UNDEFINED
 #define DEFAULT_KEY_TAPE_PAUSE		KSYM_UNDEFINED
 #define DEFAULT_KEY_TAPE_RECORD		KSYM_UNDEFINED
@@ -85,6 +140,34 @@
 #define DEFAULT_KEY_SNAP_UP		KSYM_UNDEFINED
 #define DEFAULT_KEY_SNAP_DOWN		KSYM_UNDEFINED
 
+/* default debug setup keys and values */
+#define DEFAULT_FRAME_DELAY_0		20		// 100 % speed
+#define DEFAULT_FRAME_DELAY_1		500		// 4 % speed
+#define DEFAULT_FRAME_DELAY_2		250		// 8 % speed
+#define DEFAULT_FRAME_DELAY_3		125		// 16 % speed
+#define DEFAULT_FRAME_DELAY_4		60		// 33 % speed
+#define DEFAULT_FRAME_DELAY_5		40		// 50 % speed
+#define DEFAULT_FRAME_DELAY_6		30		// 66 % speed
+#define DEFAULT_FRAME_DELAY_7		10		// 200 % speed
+#define DEFAULT_FRAME_DELAY_8		5		// 400 % speed
+#define DEFAULT_FRAME_DELAY_9		0		// maximum speed
+
+#define DEFAULT_KEY_FRAME_DELAY_0	KSYM_0
+#define DEFAULT_KEY_FRAME_DELAY_1	KSYM_1
+#define DEFAULT_KEY_FRAME_DELAY_2	KSYM_2
+#define DEFAULT_KEY_FRAME_DELAY_3	KSYM_3
+#define DEFAULT_KEY_FRAME_DELAY_4	KSYM_4
+#define DEFAULT_KEY_FRAME_DELAY_5	KSYM_5
+#define DEFAULT_KEY_FRAME_DELAY_6	KSYM_6
+#define DEFAULT_KEY_FRAME_DELAY_7	KSYM_7
+#define DEFAULT_KEY_FRAME_DELAY_8	KSYM_8
+#define DEFAULT_KEY_FRAME_DELAY_9	KSYM_9
+
+#define NUM_DEBUG_FRAME_DELAY_KEYS	10
+
+#define DEFAULT_FRAME_DELAY_USE_MOD_KEY	FALSE
+#define DEFAULT_FRAME_DELAY_GAME_ONLY	TRUE
+
 /* values for key_status */
 #define KEY_NOT_PRESSED			FALSE
 #define KEY_RELEASED			FALSE
@@ -106,14 +189,18 @@
 #define MB_WHEEL_DOWN			5
 #define MB_WHEEL_LEFT			6
 #define MB_WHEEL_RIGHT			7
-#define IS_WHEEL_BUTTON_VERTICAL(b)	((b) >= MB_WHEEL_UP &&		\
-					 (b) <= MB_WHEEL_DOWN)
-#define IS_WHEEL_BUTTON_HORIZONTAL(b)	((b) >= MB_WHEEL_LEFT &&	\
-					 (b) <= MB_WHEEL_RIGHT)
-#define IS_WHEEL_BUTTON(b)		((b) >= MB_WHEEL_UP &&		\
-					 (b) <= MB_WHEEL_DOWN)
+#define IS_WHEEL_BUTTON_VERTICAL(b)	((b) == MB_WHEEL_UP ||		\
+					 (b) == MB_WHEEL_DOWN)
+#define IS_WHEEL_BUTTON_HORIZONTAL(b)	((b) == MB_WHEEL_LEFT ||	\
+					 (b) == MB_WHEEL_RIGHT)
+#define IS_WHEEL_BUTTON(b)		(IS_WHEEL_BUTTON_VERTICAL(b) ||	\
+					 IS_WHEEL_BUTTON_HORIZONTAL(b))
 #define DEFAULT_WHEEL_STEPS		3
 
+#define BUTTON_STEPSIZE(b)		((b) == MB_LEFTBUTTON   ?  1 :	\
+					 (b) == MB_MIDDLEBUTTON ?  5 :	\
+					 (b) == MB_RIGHTBUTTON  ? 10 : 1)
+
 /* values for move directions */
 #define MV_BIT_LEFT			0
 #define MV_BIT_RIGHT			1
@@ -139,6 +226,17 @@
 /* values for special "focus player" bitmasks */
 #define BIT_SET_FOCUS			6
 
+/* values for drawing stages for global animations */
+#define DRAW_GLOBAL_ANIM_STAGE_1	1
+#define DRAW_GLOBAL_ANIM_STAGE_2	2
+
+/* values for drawing target (various functions) */
+#define DRAW_TO_BACKBUFFER		0
+#define DRAW_TO_FIELDBUFFER		1
+#define DRAW_TO_SCREEN			2
+#define DRAW_TO_FADE_SOURCE		3
+#define DRAW_TO_FADE_TARGET		4
+
 /* values for move directions and special "button" key bitmasks */
 #define MV_NONE			0
 #define MV_LEFT			(1 << MV_BIT_LEFT)
@@ -195,6 +293,7 @@
 				 MV_NONE)
 
 /* values for animation mode (frame order and direction) */
+/* (stored in level files -- never change existing values) */
 #define ANIM_NONE		0
 #define ANIM_LOOP		(1 << 0)
 #define ANIM_LINEAR		(1 << 1)
@@ -208,10 +307,13 @@
 #define ANIM_OPAQUE_PLAYER	(1 << 9)
 
 /* values for special (non game element) animation modes */
+/* (not stored in level files -- can be changed, if needed) */
 #define ANIM_HORIZONTAL		(1 << 10)
 #define ANIM_VERTICAL		(1 << 11)
 #define ANIM_CENTERED		(1 << 12)
 #define ANIM_STATIC_PANEL	(1 << 13)
+#define ANIM_ALL		(1 << 14)
+#define ANIM_ONCE		(1 << 15)
 
 #define ANIM_DEFAULT		ANIM_LOOP
 
@@ -229,7 +331,8 @@
 #define FADE_TYPE_TRANSFORM	(1 << 2)
 #define FADE_TYPE_CROSSFADE	(1 << 3)
 #define FADE_TYPE_MELT		(1 << 4)
-#define FADE_TYPE_SKIP		(1 << 5)
+#define FADE_TYPE_CURTAIN	(1 << 5)
+#define FADE_TYPE_SKIP		(1 << 6)
 
 #define FADE_MODE_NONE		(FADE_TYPE_NONE)
 #define FADE_MODE_FADE_IN	(FADE_TYPE_FADE_IN)
@@ -238,11 +341,23 @@
 #define FADE_MODE_TRANSFORM	(FADE_TYPE_TRANSFORM | FADE_TYPE_FADE_IN)
 #define FADE_MODE_CROSSFADE	(FADE_MODE_TRANSFORM | FADE_TYPE_CROSSFADE)
 #define FADE_MODE_MELT		(FADE_MODE_TRANSFORM | FADE_TYPE_MELT)
+#define FADE_MODE_CURTAIN	(FADE_MODE_TRANSFORM | FADE_TYPE_CURTAIN)
 #define FADE_MODE_SKIP_FADE_IN	(FADE_TYPE_SKIP | FADE_TYPE_FADE_IN)
 #define FADE_MODE_SKIP_FADE_OUT	(FADE_TYPE_SKIP | FADE_TYPE_FADE_OUT)
 
 #define FADE_MODE_DEFAULT	FADE_MODE_FADE
 
+/* values for toon positions */
+#define POS_UNDEFINED		-1
+#define POS_LEFT		0
+#define POS_RIGHT		1
+#define POS_TOP			2
+#define POS_UPPER		3
+#define POS_MIDDLE		4
+#define POS_LOWER		5
+#define POS_BOTTOM		6
+#define POS_ANY			7
+
 /* values for text alignment */
 #define ALIGN_LEFT		(1 << 0)
 #define ALIGN_RIGHT		(1 << 1)
@@ -265,33 +380,27 @@
 #define REDRAW_NONE		(0)
 #define REDRAW_ALL		(1 << 0)
 #define REDRAW_FIELD		(1 << 1)
-#define REDRAW_TILES		(1 << 2)
-#define REDRAW_DOOR_1		(1 << 3)
-#define REDRAW_VIDEO_1		(1 << 4)
-#define REDRAW_VIDEO_2		(1 << 5)
-#define REDRAW_VIDEO_3		(1 << 6)
-#define REDRAW_MICROLEVEL	(1 << 7)
-#define REDRAW_MICROLABEL	(1 << 8)
-#define REDRAW_FROM_BACKBUFFER	(1 << 9)
-#define REDRAW_DOOR_2		(REDRAW_VIDEO_1 | \
-				 REDRAW_VIDEO_2 | \
-				 REDRAW_VIDEO_3)
-#define REDRAW_DOOR_3		(1 << 10)
+#define REDRAW_DOOR_1		(1 << 2)
+#define REDRAW_DOOR_2		(1 << 3)
+#define REDRAW_DOOR_3		(1 << 4)
+#define REDRAW_FPS		(1 << 5)
+
 #define REDRAW_DOORS		(REDRAW_DOOR_1 | \
 				 REDRAW_DOOR_2 | \
 				 REDRAW_DOOR_3)
-#define REDRAW_MAIN		(REDRAW_FIELD | \
-				 REDRAW_TILES | \
-				 REDRAW_MICROLEVEL)
-#define REDRAW_FPS		(1 << 11)
-#define REDRAWTILES_THRESHOLD	(SCR_FIELDX * SCR_FIELDY / 2)
 
-#define IN_GFX_SCREEN(x, y)	(x >= gfx.sx && x < gfx.sx + gfx.sxsize && \
+#define IN_GFX_FIELD_PLAY(x, y)	(x >= gfx.sx && x < gfx.sx + gfx.sxsize && \
 				 y >= gfx.sy && y < gfx.sy + gfx.sysize)
-#define IN_GFX_DOOR(x, y)	(x >= gfx.dx && x < gfx.dx + gfx.dxsize && \
+#define IN_GFX_FIELD_FULL(x, y)	(x >= gfx.real_sx && \
+				 x <  gfx.real_sx + gfx.full_sxsize && \
+				 y >= gfx.real_sy && \
+				 y <  gfx.real_sy + gfx.full_sysize)
+#define IN_GFX_DOOR_1(x, y)	(x >= gfx.dx && x < gfx.dx + gfx.dxsize && \
 				 y >= gfx.dy && y < gfx.dy + gfx.dysize)
-#define IN_GFX_VIDEO(x, y)	(x >= gfx.vx && x < gfx.vx + gfx.vxsize && \
+#define IN_GFX_DOOR_2(x, y)	(x >= gfx.vx && x < gfx.vx + gfx.vxsize && \
 				 y >= gfx.vy && y < gfx.vy + gfx.vysize)
+#define IN_GFX_DOOR_3(x, y)	(x >= gfx.ex && x < gfx.ex + gfx.exsize && \
+				 y >= gfx.ey && y < gfx.ey + gfx.eysize)
 
 /* values for mouse cursor */
 #define CURSOR_DEFAULT		0
@@ -300,9 +409,11 @@
 
 /* fundamental game speed values */
 #define ONE_SECOND_DELAY	1000	/* delay value for one second */
+#define MENU_FRAME_DELAY	20	/* frame delay in milliseconds */
 #define GAME_FRAME_DELAY	20	/* frame delay in milliseconds */
 #define FFWD_FRAME_DELAY	10	/* 200% speed for fast forward */
 #define FRAMES_PER_SECOND	(ONE_SECOND_DELAY / GAME_FRAME_DELAY)
+#define FRAMES_PER_SECOND_SP	35
 
 /* maximum playfield size supported by libgame functions */
 #define MAX_PLAYFIELD_WIDTH	128
@@ -314,6 +425,9 @@
 /* maximum allowed length of player name */
 #define MAX_PLAYER_NAME_LEN	10
 
+/* maximum number of levels in a level set */
+#define MAX_LEVELS		1000
+
 /* default name for empty highscore entry */
 #define EMPTY_PLAYER_NAME	"no name"
 
@@ -332,12 +446,18 @@
 /* default value for undefined filename */
 #define UNDEFINED_FILENAME	"[NONE]"
 
+/* default value for undefined levelset */
+#define UNDEFINED_LEVELSET	"[NONE]"
+
 /* default value for undefined parameter */
 #define ARG_DEFAULT		"[DEFAULT]"
 
 /* default values for undefined configuration file parameters */
 #define ARG_UNDEFINED		"-1000000"
-#define ARG_UNDEFINED_VALUE	(atoi(ARG_UNDEFINED))
+#define ARG_UNDEFINED_VALUE	(-1000000)
+
+/* default value for off-screen positions */
+#define POS_OFFSCREEN		(-1000000)
 
 /* definitions for game sub-directories */
 #ifndef RO_GAME_DIR
@@ -361,34 +481,21 @@
 #define DOCS_DIRECTORY		"docs"
 #define CACHE_DIRECTORY		"cache"
 
-#if !defined(PLATFORM_MSDOS)
 #define GFX_CLASSIC_SUBDIR	"gfx_classic"
 #define SND_CLASSIC_SUBDIR	"snd_classic"
 #define MUS_CLASSIC_SUBDIR	"mus_classic"
-#else
-#define GFX_CLASSIC_SUBDIR	"gfx_orig"
-#define SND_CLASSIC_SUBDIR	"snd_orig"
-#define MUS_CLASSIC_SUBDIR	"mus_orig"
-#endif
 
-#if defined(CREATE_SPECIAL_EDITION_RND_JUE)
-#define GFX_DEFAULT_SUBDIR	"jue0"
-#define SND_DEFAULT_SUBDIR	"jue0"
-#define MUS_DEFAULT_SUBDIR	"jue0"
-#else
-#define GFX_DEFAULT_SUBDIR	GFX_CLASSIC_SUBDIR
-#define SND_DEFAULT_SUBDIR	SND_CLASSIC_SUBDIR
-#define MUS_DEFAULT_SUBDIR	MUS_CLASSIC_SUBDIR
-#endif
+#define GFX_DEFAULT_SUBDIR	(setup.internal.default_graphics_set)
+#define SND_DEFAULT_SUBDIR	(setup.internal.default_sounds_set)
+#define MUS_DEFAULT_SUBDIR	(setup.internal.default_music_set)
 
-#if defined(CREATE_SPECIAL_EDITION)
-#define GFX_FALLBACK_FILENAME	"fallback.pcx"
-#define SND_FALLBACK_FILENAME	"fallback.wav"
-#define MUS_FALLBACK_FILENAME	"fallback.wav"
-#endif
+#define GFX_FALLBACK_FILENAME	(setup.internal.fallback_graphics_file)
+#define SND_FALLBACK_FILENAME	(setup.internal.fallback_sounds_file)
+#define MUS_FALLBACK_FILENAME	(setup.internal.fallback_music_file)
+
+#define DEFAULT_LEVELSET	(setup.internal.default_level_series)
 
 /* file names and filename extensions */
-#if !defined(PLATFORM_MSDOS)
 #define LEVELSETUP_DIRECTORY	"levelsetup"
 #define SETUP_FILENAME		"setup.conf"
 #define LEVELSETUP_FILENAME	"levelsetup.conf"
@@ -404,25 +511,16 @@
 #define LEVELFILE_EXTENSION	"level"
 #define TAPEFILE_EXTENSION	"tape"
 #define SCOREFILE_EXTENSION	"score"
-#else
-#define LEVELSETUP_DIRECTORY	"lvlsetup"
-#define SETUP_FILENAME		"setup.cnf"
-#define LEVELSETUP_FILENAME	"lvlsetup.cnf"
-#define EDITORSETUP_FILENAME	"edsetup.cnf"
-#define EDITORCASCADE_FILENAME	"edcascad.conf"
-#define HELPANIM_FILENAME	"helpanim.cnf"
-#define HELPTEXT_FILENAME	"helptext.cnf"
-#define LEVELINFO_FILENAME	"lvlinfo.cnf"
-#define GRAPHICSINFO_FILENAME	"gfxinfo.cnf"
-#define SOUNDSINFO_FILENAME	"sndinfo.cnf"
-#define MUSICINFO_FILENAME	"musinfo.cnf"
-#define ARTWORKINFO_CACHE_FILE	"artinfo.cac"
-#define LEVELFILE_EXTENSION	"lvl"
-#define TAPEFILE_EXTENSION	"tap"
-#define SCOREFILE_EXTENSION	"sco"
-#endif
 
-#define ERROR_BASENAME		"stderr.txt"
+#define LOG_OUT_BASENAME	"stdout.txt"
+#define LOG_ERR_BASENAME	"stderr.txt"
+
+#define LOG_OUT_ID		0
+#define LOG_ERR_ID		1
+#define NUM_LOGS		2
+
+#define STRING_PARENT_DIRECTORY		".."
+#define STRING_TOP_DIRECTORY		"/"
 
 #define CHAR_PATH_SEPARATOR_UNIX	'/'
 #define CHAR_PATH_SEPARATOR_DOS		'\\'
@@ -433,7 +531,7 @@
 #define STRING_NEWLINE_UNIX		"\n"
 #define STRING_NEWLINE_DOS		"\r\n"
 
-#if defined(PLATFORM_WIN32) || defined(PLATFORM_MSDOS)
+#if defined(PLATFORM_WIN32)
 #define CHAR_PATH_SEPARATOR	CHAR_PATH_SEPARATOR_DOS
 #define STRING_PATH_SEPARATOR	STRING_PATH_SEPARATOR_DOS
 #define STRING_NEWLINE		STRING_NEWLINE_DOS
@@ -502,16 +600,20 @@
 #define TREE_TYPE_SOUNDS_DIR	ARTWORK_TYPE_SOUNDS
 #define TREE_TYPE_MUSIC_DIR	ARTWORK_TYPE_MUSIC
 #define TREE_TYPE_LEVEL_DIR	3
+#define TREE_TYPE_LEVEL_NR	4
 
-#define NUM_TREE_TYPES		4
+#define NUM_TREE_TYPES		5
 
 #define INFOTEXT_UNDEFINED	""
 #define INFOTEXT_GRAPHICS_DIR	"Custom Graphics"
 #define INFOTEXT_SOUNDS_DIR	"Custom Sounds"
 #define INFOTEXT_MUSIC_DIR	"Custom Music"
 #define INFOTEXT_LEVEL_DIR	"Level Sets"
+#define INFOTEXT_LEVEL_NR	"Levels"
 
-#define TREE_INFOTEXT(t)	((t) == TREE_TYPE_LEVEL_DIR ?		\
+#define TREE_INFOTEXT(t)	((t) == TREE_TYPE_LEVEL_NR ?		\
+				 INFOTEXT_LEVEL_NR :			\
+				 (t) == TREE_TYPE_LEVEL_DIR ?		\
 				 INFOTEXT_LEVEL_DIR :			\
 				 (t) == TREE_TYPE_GRAPHICS_DIR ?	\
 				 INFOTEXT_GRAPHICS_DIR :		\
@@ -623,46 +725,48 @@
 }
 
 
-/* type definitions */
-typedef int (*EventFilter)(const Event *);
-
-
 /* structure definitions */
 
 struct ProgramInfo
 {
-  char *command_basepath;	/* directory that contains the program */
+  char *command_basepath;	/* path to the program binary */
   char *command_basename;	/* base filename of the program binary */
 
+  char *config_filename;	/* optional global program config filename */
+
+  char *maindata_path;		/* main game data (installation) directory */
+
   char *userdata_subdir;	/* personal user game data directory */
-  char *userdata_subdir_unix;	/* personal user game data directory (Unix) */
   char *userdata_path;		/* resulting full path to game data directory */
 
   char *program_title;
   char *window_title;
   char *icon_title;
 
-  char *x11_icon_filename;
-  char *x11_iconmask_filename;
-  char *sdl_icon_filename;
-  char *msdos_cursor_filename;
+  char *icon_filename;
 
   char *cookie_prefix;
-  char *filename_prefix;	/* prefix to cut off from DOS filenames */
 
-  char *error_filename;		/* filename where to write error messages to */
-  FILE *error_file;		/* (used instead of 'stderr' on some systems) */
+  char *log_filename[NUM_LOGS];		/* log filenames for out/err messages */
+  FILE *log_file[NUM_LOGS];		/* log file handles for out/err files */
+  FILE *log_file_default[NUM_LOGS];	/* default log file handles (out/err) */
 
   int version_major;
   int version_minor;
   int version_patch;
+  int version_build;
+  int version_ident;
 
+  char *(*window_title_function)(void);
+  void (*exit_message_function)(char *, va_list);
   void (*exit_function)(int);
+
+  boolean global_scores;
+  boolean many_scores_per_name;
 };
 
 struct OptionInfo
 {
-  char *display_name;
   char *server_host;
   int server_port;
 
@@ -678,27 +782,41 @@ struct OptionInfo
 
   char *special_flags;
 
+  boolean mytapes;
   boolean serveronly;
   boolean network;
   boolean verbose;
   boolean debug;
-  boolean debug_x11_sync;
-};
-
-struct ScreenModeInfo
-{
-  int width, height;
 };
 
 struct VideoSystemInfo
 {
   int default_depth;
   int width, height, depth;
+  int window_width, window_height;
+  int display_width, display_height;
+  int screen_width, screen_height;
+  int screen_xoffset, screen_yoffset;
 
   boolean fullscreen_available;
   boolean fullscreen_enabled;
-  struct ScreenModeInfo *fullscreen_modes;
-  char *fullscreen_mode_current;
+  boolean fullscreen_initial;
+
+  boolean window_scaling_available;
+  int window_scaling_percent;
+  char *window_scaling_quality;
+  int screen_rendering_mode;
+
+  unsigned int frame_delay;
+  unsigned int frame_delay_value;
+
+  boolean shifted_up;
+  int shifted_up_pos;
+  int shifted_up_pos_last;
+  unsigned int shifted_up_delay;
+  unsigned int shifted_up_delay_value;
+
+  boolean initialized;
 };
 
 struct AudioSystemInfo
@@ -732,10 +850,6 @@ struct FontBitmapInfo
 
   int num_chars;
   int num_chars_per_line;
-
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
-  Pixmap *clip_mask;		/* single-char-only clip mask array for X11 */
-#endif
 };
 
 struct GfxInfo
@@ -746,12 +860,17 @@ struct GfxInfo
   int full_sxsize, full_sysize;
   int scrollbuffer_width, scrollbuffer_height;
 
+  int game_tile_size, standard_tile_size;
+
   int dx, dy;
   int dxsize, dysize;
 
   int vx, vy;
   int vxsize, vysize;
 
+  int ex, ey;
+  int exsize, eysize;
+
   int win_xsize, win_ysize;
 
   int draw_deactivation_mask;
@@ -762,6 +881,17 @@ struct GfxInfo
   Bitmap *background_bitmap;
   int background_bitmap_mask;
 
+  Bitmap *fade_bitmap_backup;
+  Bitmap *fade_bitmap_source;
+  Bitmap *fade_bitmap_target;
+  Bitmap *fade_bitmap_black;
+
+  int fade_border_source_status;
+  int fade_border_target_status;
+  Bitmap *masked_border_bitmap_ptr;
+
+  Bitmap *final_screen_bitmap;
+
   boolean clipping_enabled;
   int clip_x, clip_y;
   int clip_width, clip_height;
@@ -780,6 +910,15 @@ struct GfxInfo
   int anim_random_frame;
 
   void (*draw_busy_anim_function)(void);
+  void (*draw_global_anim_function)(int, int);
+  void (*draw_global_border_function)(int);
+
+  int cursor_mode;
+};
+
+struct OverlayInfo
+{
+  boolean active;
 };
 
 struct JoystickInfo
@@ -803,6 +942,13 @@ struct SetupKeyboardInfo
   Key snap, drop;
 };
 
+struct SetupTouchInfo
+{
+  char *control_type;
+  int move_distance;
+  int drop_distance;
+};
+
 struct SetupInputInfo
 {
   boolean use_joystick;
@@ -863,6 +1009,7 @@ struct SetupShortcutInfo
   Key focus_player_all;
 
   Key tape_eject;
+  Key tape_extra;
   Key tape_stop;
   Key tape_pause;
   Key tape_record;
@@ -885,6 +1032,41 @@ struct SetupSystemInfo
   int audio_fragment_size;
 };
 
+struct SetupInternalInfo
+{
+  char *program_title;
+  char *program_author;
+  char *program_email;
+  char *program_website;
+  char *program_copyright;
+  char *program_company;
+
+  char *program_icon_file;
+
+  char *default_graphics_set;
+  char *default_sounds_set;
+  char *default_music_set;
+
+  char *fallback_graphics_file;
+  char *fallback_sounds_file;
+  char *fallback_music_file;
+
+  char *default_level_series;
+
+  int default_window_width;
+  int default_window_height;
+
+  boolean choose_from_top_leveldir;
+};
+
+struct SetupDebugInfo
+{
+  int frame_delay[10];
+  Key frame_delay_key[10];
+  boolean frame_delay_use_mod_key;
+  boolean frame_delay_game_only;
+};
+
 struct SetupInfo
 {
   char *player_name;
@@ -896,7 +1078,8 @@ struct SetupInfo
   boolean toons;
   boolean scroll_delay;
   boolean scroll_delay_value;
-  boolean soft_scrolling;
+  char *engine_snapshot_mode;
+  int engine_snapshot_memory;
   boolean fade_screens;
   boolean autorecord;
   boolean show_titlescreen;
@@ -906,7 +1089,9 @@ struct SetupInfo
   boolean skip_levels;
   boolean time_limit;
   boolean fullscreen;
-  char *fullscreen_mode;
+  int window_scaling_percent;
+  char *window_scaling_quality;
+  char *screen_rendering_mode;
   boolean ask_on_escape;
   boolean ask_on_escape_editor;
   boolean quick_switch;
@@ -914,6 +1099,8 @@ struct SetupInfo
   boolean prefer_aga_graphics;
   int game_frame_delay;
   boolean sp_show_border_elements;
+  boolean small_game_graphics;
+  boolean show_snapshot_buttons;
 
   char *graphics_set;
   char *sounds_set;
@@ -922,11 +1109,19 @@ struct SetupInfo
   int override_level_sounds;		/* not boolean -- can also be "AUTO" */
   int override_level_music;		/* not boolean -- can also be "AUTO" */
 
+  int volume_simple;
+  int volume_loops;
+  int volume_music;
+
   struct SetupEditorInfo editor;
   struct SetupEditorCascadeInfo editor_cascade;
   struct SetupShortcutInfo shortcut;
   struct SetupInputInfo input[MAX_PLAYERS];
+  struct SetupTouchInfo touch;
   struct SetupSystemInfo system;
+  struct SetupInternalInfo internal;
+  struct SetupDebugInfo debug;
+
   struct OptionInfo options;
 };
 
@@ -1119,6 +1314,12 @@ struct XY
   int x, y;
 };
 
+struct XYTileSize
+{
+  int x, y;
+  int tile_size;
+};
+
 struct Rect
 {
   int x, y;
@@ -1139,18 +1340,40 @@ struct MenuPosInfo
   int align, valign;
 };
 
+struct DoorPartPosInfo
+{
+  int x, y;
+  int step_xoffset;
+  int step_yoffset;
+  int step_delay;
+  int start_step;
+  int start_step_opening;
+  int start_step_closing;
+  boolean draw_masked;
+  int sort_priority;
+};
+
 struct TextPosInfo
 {
   int x, y;
+  int xoffset;			/* special case for tape date and time */
+  int xoffset2;			/* special case for tape date */
   int width, height;
   int align, valign;
-  int size;
+  int size;			/* also used for suffix ".digits" */
   int font, font_alt;
   boolean draw_masked;
-  int sort_priority;
+  boolean draw_player;		/* special case for network player buttons */
+  int sort_priority;		/* also used for suffix ".draw_order" */
   int id;
 };
 
+struct LevelStats
+{
+  int played;
+  int solved;
+};
+
 
 /* ========================================================================= */
 /* exported variables                                                        */
@@ -1161,6 +1384,7 @@ extern struct OptionInfo	options;
 extern struct VideoSystemInfo	video;
 extern struct AudioSystemInfo	audio;
 extern struct GfxInfo		gfx;
+extern struct OverlayInfo	overlay;
 extern struct AnimInfo		anim;
 extern struct ArtworkInfo	artwork;
 extern struct JoystickInfo	joystick;
@@ -1171,10 +1395,7 @@ extern LevelDirTree	       *leveldir_first;
 extern LevelDirTree	       *leveldir_current;
 extern int			level_nr;
 
-extern Display		       *display;
-extern Visual		       *visual;
-extern int			screen;
-extern Colormap			cmap;
+extern struct LevelStats	level_stats[];
 
 extern DrawWindow	       *window;
 extern DrawBuffer	       *backbuffer;
@@ -1182,9 +1403,12 @@ extern DrawBuffer	       *drawto;
 
 extern int			button_status;
 extern boolean			motion_status;
+extern int			wheel_steps;
+#if defined(TARGET_SDL2)
+extern boolean			keyrepeat_status;
+#endif
 
 extern int			redraw_mask;
-extern int			redraw_tiles;
 
 extern int			FrameCounter;
 
@@ -1192,44 +1416,65 @@ extern int			FrameCounter;
 /* function definitions */
 
 void InitProgramInfo(char *, char *, char *, char *, char *, char *, char *,
-		     char *, char *, char *, char *, char *, int);
+		     int);
+
+void InitScoresInfo();
+void SetWindowTitle();
 
+void InitWindowTitleFunction(char *(*window_title_function)(void));
+void InitExitMessageFunction(void (*exit_message_function)(char *, va_list));
 void InitExitFunction(void (*exit_function)(int));
 void InitPlatformDependentStuff(void);
 void ClosePlatformDependentStuff(void);
 
 void InitGfxFieldInfo(int, int, int, int, int, int, int, int, Bitmap *);
+void InitGfxTileSizeInfo(int, int);
 void InitGfxDoor1Info(int, int, int, int);
 void InitGfxDoor2Info(int, int, int, int);
+void InitGfxDoor3Info(int, int, int, int);
 void InitGfxWindowInfo(int, int);
 void InitGfxScrollbufferInfo(int, int);
 void InitGfxClipRegion(boolean, int, int, int, int);
 void InitGfxDrawBusyAnimFunction(void (*draw_busy_anim_function)(void));
+void InitGfxDrawGlobalAnimFunction(void (*draw_global_anim_function)(int, int));
+void InitGfxDrawGlobalBorderFunction(void (*draw_global_border_function)(int));
 void InitGfxCustomArtworkInfo();
+void InitGfxOtherSettings();
+void InitOverlayInfo();
+void SetOverlayActive(boolean);
+boolean GetOverlayActive();
 void SetDrawDeactivationMask(int);
 void SetDrawBackgroundMask(int);
 void SetWindowBackgroundBitmap(Bitmap *);
 void SetMainBackgroundBitmap(Bitmap *);
 void SetDoorBackgroundBitmap(Bitmap *);
+void SetRedrawMaskFromArea(int, int, int, int);
+
+void LimitScreenUpdates(boolean);
 
 void InitVideoDisplay(void);
 void CloseVideoDisplay(void);
 void InitVideoBuffer(int, int, int, boolean);
 Bitmap *CreateBitmapStruct(void);
 Bitmap *CreateBitmap(int, int, int);
-void ReCreateBitmap(Bitmap **, int, int, int);
+void ReCreateBitmap(Bitmap **, int, int);
 void FreeBitmap(Bitmap *);
 void BlitBitmap(Bitmap *, Bitmap *, int, int, int, int, int, int);
-void FadeRectangle(Bitmap *bitmap, int, int, int, int, int, int, int,
+void BlitBitmapTiled(Bitmap *, Bitmap *, int, int, int, int, int, int, int,int);
+void FadeRectangle(int, int, int, int, int, int, int,
 		   void (*draw_border_function)(void));
 void FillRectangle(Bitmap *, int, int, int, int, Pixel);
 void ClearRectangle(Bitmap *, int, int, int, int);
 void ClearRectangleOnBackground(Bitmap *, int, int, int, int);
-void SetClipMask(Bitmap *, GC, Pixmap);
-void SetClipOrigin(Bitmap *, GC, int, int);
 void BlitBitmapMasked(Bitmap *, Bitmap *, int, int, int, int, int, int);
+boolean DrawingDeactivated(int, int, int, int);
 boolean DrawingOnBackground(int, int);
+boolean DrawingAreaChanged();
 void BlitBitmapOnBackground(Bitmap *, Bitmap *, int, int, int, int, int, int);
+void BlitTexture(Bitmap *, int, int, int, int, int, int);
+void BlitTextureMasked(Bitmap *, int, int, int, int, int, int);
+void BlitToScreen(Bitmap *, int, int, int, int, int, int);
+void BlitToScreenMasked(Bitmap *, int, int, int, int, int, int);
 void DrawSimpleBlackLine(Bitmap *, int, int, int, int);
 void DrawSimpleWhiteLine(Bitmap *, int, int, int, int);
 void DrawLines(Bitmap *, struct XY *, int, Pixel);
@@ -1237,21 +1482,22 @@ Pixel GetPixel(Bitmap *, int, int);
 Pixel GetPixelFromRGB(Bitmap *, unsigned int,unsigned int,unsigned int);
 Pixel GetPixelFromRGBcompact(Bitmap *, unsigned int);
 
-void FlushDisplay(void);
-void SyncDisplay(void);
 void KeyboardAutoRepeatOn(void);
 void KeyboardAutoRepeatOff(void);
-boolean PointerInWindow(DrawWindow *);
 boolean SetVideoMode(boolean);
+void SetVideoFrameDelay(unsigned int);
+unsigned int GetVideoFrameDelay();
 boolean ChangeVideoModeIfNeeded(boolean);
 
 Bitmap *LoadImage(char *);
 Bitmap *LoadCustomImage(char *);
 void ReloadCustomImage(Bitmap *, char *);
 
-Bitmap *ZoomBitmap(Bitmap *, int, int);
-void CreateBitmapWithSmallBitmaps(Bitmap *, int);
-void ScaleBitmap(Bitmap *, int);
+void ReCreateGameTileSizeBitmap(Bitmap **);
+void CreateBitmapWithSmallBitmaps(Bitmap **, int, int);
+void CreateBitmapTextures(Bitmap **);
+void FreeBitmapTextures(Bitmap **);
+void ScaleBitmap(Bitmap **, int);
 
 void SetMouseCursor(int);
 
@@ -1259,7 +1505,6 @@ void OpenAudio(void);
 void CloseAudio(void);
 void SetAudioMode(boolean);
 
-void InitEventFilter(EventFilter);
 boolean PendingEvent(void);
 void NextEvent(Event *event);
 void PeekEvent(Event *event);
@@ -1267,6 +1512,8 @@ Key GetEventKey(KeyEvent *, boolean);
 KeyMod HandleKeyModState(Key, int);
 KeyMod GetKeyModState();
 KeyMod GetKeyModStateFromEvents();
+void StartTextInput(int, int, int, int);
+void StopTextInput();
 boolean CheckCloseWindowEvent(ClientMessageEvent *);
 
 void InitJoysticks();
diff --git a/src/libgame/text.c b/src/libgame/text.c
index 23de7ca..eb755ba 100644
--- a/src/libgame/text.c
+++ b/src/libgame/text.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* text.c                                                   *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// text.c
+// ============================================================================
 
 #include <stdio.h>
 #include <stdarg.h>
@@ -22,90 +20,6 @@
 /* font functions                                                            */
 /* ========================================================================= */
 
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
-static GC	font_clip_gc = None;
-
-static void InitFontClipmasks()
-{
-  XGCValues clip_gc_values;
-  unsigned long clip_gc_valuemask;
-  GC copy_clipmask_gc;
-  int i, j;
-
-  /* This stuff is needed because X11 (XSetClipOrigin(), to be precise) is
-     often very slow when preparing a masked XCopyArea() for big Pixmaps.
-     To prevent this, create small (tile-sized) mask Pixmaps which will then
-     be set much faster with XSetClipOrigin() and speed things up a lot. */
-
-  clip_gc_values.graphics_exposures = False;
-  clip_gc_valuemask = GCGraphicsExposures;
-  font_clip_gc = XCreateGC(display, window->drawable,
-			   clip_gc_valuemask, &clip_gc_values);
-
-  /* create graphic context structures needed for clipping */
-  clip_gc_values.graphics_exposures = False;
-  clip_gc_valuemask = GCGraphicsExposures;
-  copy_clipmask_gc = XCreateGC(display,
-			       gfx.font_bitmap_info[0].bitmap->clip_mask,
-			       clip_gc_valuemask, &clip_gc_values);
-
-  /* create only those clipping Pixmaps we really need */
-  for (i = 0; i < gfx.num_fonts; i++)
-  {
-    if (gfx.font_bitmap_info[i].bitmap == NULL)
-      continue;
-
-    gfx.font_bitmap_info[i].clip_mask =
-      checked_calloc(gfx.font_bitmap_info[i].num_chars * sizeof(Pixmap));
-
-    for (j = 0; j < gfx.font_bitmap_info[i].num_chars; j++)
-    {
-      Bitmap *src_bitmap = gfx.font_bitmap_info[i].bitmap;
-      Pixmap src_pixmap = src_bitmap->clip_mask;
-      int xpos = j % gfx.font_bitmap_info[i].num_chars_per_line;
-      int ypos = j / gfx.font_bitmap_info[i].num_chars_per_line;
-      int width  = gfx.font_bitmap_info[i].width;
-      int height = gfx.font_bitmap_info[i].height;
-      int src_x = gfx.font_bitmap_info[i].src_x + xpos * width;
-      int src_y = gfx.font_bitmap_info[i].src_y + ypos * height;
-
-      gfx.font_bitmap_info[i].clip_mask[j] =
-	XCreatePixmap(display, window->drawable, width, height, 1);
-
-      XCopyArea(display, src_pixmap, gfx.font_bitmap_info[i].clip_mask[j],
-		copy_clipmask_gc, src_x, src_y, width, height, 0, 0);
-    }
-  }
-
-  XFreeGC(display, copy_clipmask_gc);
-}
-
-static void FreeFontClipmasks()
-{
-  int i, j;
-
-  if (gfx.num_fonts == 0 || gfx.font_bitmap_info[0].bitmap == NULL)
-    return;
-
-  for (i = 0; i < gfx.num_fonts; i++)
-  {
-    if (gfx.font_bitmap_info[i].clip_mask)
-    {
-      for (j = 0; j < gfx.font_bitmap_info[i].num_chars; j++)
-	XFreePixmap(display, gfx.font_bitmap_info[i].clip_mask[j]);
-      free(gfx.font_bitmap_info[i].clip_mask);
-    }
-
-    gfx.font_bitmap_info[i].clip_mask = NULL;
-    gfx.font_bitmap_info[i].num_chars = 0;
-  }
-
-  if (font_clip_gc)
-    XFreeGC(display, font_clip_gc);
-  font_clip_gc = None;
-}
-#endif /* TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND */
-
 void InitFontInfo(struct FontBitmapInfo *font_bitmap_info, int num_fonts,
 		  int (*select_font_function)(int),
 		  int (*get_font_from_token_function)(char *))
@@ -114,10 +28,6 @@ void InitFontInfo(struct FontBitmapInfo *font_bitmap_info, int num_fonts,
   gfx.font_bitmap_info = font_bitmap_info;
   gfx.select_font_function = select_font_function;
   gfx.get_font_from_token_function = get_font_from_token_function;
-
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
-  InitFontClipmasks();
-#endif
 }
 
 void FreeFontInfo(struct FontBitmapInfo *font_bitmap_info)
@@ -125,10 +35,6 @@ void FreeFontInfo(struct FontBitmapInfo *font_bitmap_info)
   if (font_bitmap_info == NULL)
     return;
 
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
-  FreeFontClipmasks();
-#endif
-
   free(font_bitmap_info);
 }
 
@@ -153,6 +59,20 @@ int getFontHeight(int font_nr)
   return gfx.font_bitmap_info[font_bitmap_id].height;
 }
 
+int getFontDrawOffsetX(int font_nr)
+{
+  int font_bitmap_id = gfx.select_font_function(font_nr);
+
+  return gfx.font_bitmap_info[font_bitmap_id].draw_xoffset;
+}
+
+int getFontDrawOffsetY(int font_nr)
+{
+  int font_bitmap_id = gfx.select_font_function(font_nr);
+
+  return gfx.font_bitmap_info[font_bitmap_id].draw_yoffset;
+}
+
 int getTextWidth(char *text, int font_nr)
 {
   return (text != NULL ? strlen(text) * getFontWidth(font_nr) : 0);
@@ -195,10 +115,14 @@ void getFontCharSource(int font_nr, char c, Bitmap **bitmap, int *x, int *y)
 int maxWordLengthInString(char *text)
 {
   char *text_ptr;
-  int max_word_len = 0;
+  int word_len = 0, max_word_len = 0;
 
   for (text_ptr = text; *text_ptr; text_ptr++)
-    max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
+  {
+    word_len = (*text_ptr != ' ' ? word_len + 1 : 0);
+
+    max_word_len = MAX(word_len, max_word_len);
+  }
 
   return max_word_len;
 }
@@ -208,16 +132,12 @@ int maxWordLengthInString(char *text)
 /* simple text drawing functions                                             */
 /* ========================================================================= */
 
-void DrawInitTextExt(char *text, int ypos, int font_nr, boolean force)
+void DrawInitText(char *text, int ypos, int font_nr)
 {
-  static unsigned long progress_delay = 0;
-  unsigned long progress_delay_value = 100;	/* (in milliseconds) */
+  LimitScreenUpdates(TRUE);
 
   UPDATE_BUSY_STATE();
 
-  if (!force && !DelayReached(&progress_delay, progress_delay_value))
-    return;
-
   if (window != NULL &&
       gfx.draw_init_text &&
       gfx.num_fonts > 0 &&
@@ -231,21 +151,10 @@ void DrawInitTextExt(char *text, int ypos, int font_nr, boolean force)
     ClearRectangle(drawto, 0, y, width, height);
     DrawTextExt(drawto, x, y, text, font_nr, BLIT_OPAQUE);
 
-    /* this makes things significantly faster than directly drawing to window */
-    BlitBitmap(drawto, window, 0, y, width, height, 0, y);
+    BlitBitmap(drawto, window, 0, 0, video.width, video.height, 0, 0);
   }
 }
 
-void DrawInitText(char *text, int ypos, int font_nr)
-{
-  DrawInitTextExt(text, ypos, font_nr, TRUE);
-}
-
-void DrawInitTextIfNeeded(char *text, int ypos, int font_nr)
-{
-  DrawInitTextExt(text, ypos, font_nr, FALSE);
-}
-
 void DrawTextF(int x, int y, int font_nr, char *format, ...)
 {
   char buffer[MAX_OUTPUT_LINESIZE + 1];
@@ -288,11 +197,6 @@ void DrawTextSCentered(int y, int font_nr, char *text)
 	   gfx.sy + y, text, font_nr);
 }
 
-void DrawTextCentered(int y, int font_nr, char *text)
-{
-  DrawText((gfx.sxsize - getTextWidth(text, font_nr)) / 2, y, text, font_nr);
-}
-
 void DrawTextSAligned(int x, int y, char *text, int font_nr, int align)
 {
   DrawText(gfx.sx + ALIGNED_XPOS(x, getTextWidth(text, font_nr), align),
@@ -314,28 +218,24 @@ void DrawText(int x, int y, char *text, int font_nr)
 
   DrawTextExt(drawto, x, y, text, font_nr, mask_mode);
 
-  if (x < gfx.dx)
+  if (IN_GFX_FIELD_FULL(x, y))
     redraw_mask |= REDRAW_FIELD;
-  else if (y < gfx.vy || gfx.vy == 0)
+  else if (IN_GFX_DOOR_1(x, y))
     redraw_mask |= REDRAW_DOOR_1;
+  else if (IN_GFX_DOOR_2(x, y))
+    redraw_mask |= REDRAW_DOOR_2;
+  else if (IN_GFX_DOOR_3(x, y))
+    redraw_mask |= REDRAW_DOOR_3;
+  else
+    redraw_mask |= REDRAW_ALL;
 }
 
 void DrawTextExt(DrawBuffer *dst_bitmap, int dst_x, int dst_y, char *text,
 		 int font_nr, int mask_mode)
 {
-#if 1
   struct FontBitmapInfo *font = getFontBitmapInfo(font_nr);
-#else
-  int font_bitmap_id = gfx.select_font_function(font_nr);
-  struct FontBitmapInfo *font = &gfx.font_bitmap_info[font_bitmap_id];
-#endif
   int font_width = getFontWidth(font_nr);
   int font_height = getFontHeight(font_nr);
-#if 0
-  int border_1 = gfx.sx + gfx.sxsize;
-  int border_2 = gfx.dx + gfx.dxsize;
-  int dst_x_start = dst_x;
-#endif
   Bitmap *src_bitmap;
   int src_x, src_y;
   char *text_ptr = text;
@@ -369,15 +269,8 @@ void DrawTextExt(DrawBuffer *dst_bitmap, int dst_x, int dst_y, char *text,
     }
 
     /* clip text at the right side of the window */
-#if 1
     if (dst_x + font_width > video.width)
       break;
-#else
-    /* (this does not work well when trying to print text to whole screen) */
-    if ((dst_x_start < border_1 && dst_x + font_width > border_1) ||
-	(dst_x_start < border_2 && dst_x + font_width > border_2))
-      break;
-#endif
 
     if (mask_mode == BLIT_INVERSE)	/* special mode for text gadgets */
     {
@@ -394,17 +287,9 @@ void DrawTextExt(DrawBuffer *dst_bitmap, int dst_x, int dst_y, char *text,
 		   font_width, font_height, dst_x, dst_y);
       }
 
-#if defined(TARGET_SDL)
       /* second step: draw masked inverted character */
       SDLCopyInverseMasked(src_bitmap, dst_bitmap, src_x, src_y,
 			   font_width, font_height, dst_x, dst_y);
-#else
-      /* second step: draw masked black rectangle (use "space" character) */
-      SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
-		    dst_x - src_x, dst_y - src_y);
-      BlitBitmapMasked(src_bitmap, dst_bitmap, 0, 0,
-		       font_width, font_height, dst_x, dst_y);
-#endif
     }
     else if (mask_mode == BLIT_MASKED || mask_mode == BLIT_ON_BACKGROUND)
     {
@@ -415,19 +300,6 @@ void DrawTextExt(DrawBuffer *dst_bitmap, int dst_x, int dst_y, char *text,
 				   font_width, font_height);
       }
 
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
-      /* use special font tile clipmasks */
-      {
-	int font_pos = getFontCharPosition(font_nr, c);
-
-	SetClipMask(src_bitmap, font_clip_gc, font->clip_mask[font_pos]);
-	SetClipOrigin(src_bitmap, font_clip_gc, dst_x, dst_y);
-      }
-#else
-      SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
-		    dst_x - src_x, dst_y - src_y);
-#endif
-
       BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y,
 		       font_width, font_height, dst_x, dst_y);
     }
@@ -450,24 +322,24 @@ void DrawTextExt(DrawBuffer *dst_bitmap, int dst_x, int dst_y, char *text,
 
 char *GetTextBufferFromFile(char *filename, int max_lines)
 {
-  FILE *file;
+  File *file;
   char *buffer;
   int num_lines = 0;
 
   if (filename == NULL)
     return NULL;
 
-  if (!(file = fopen(filename, MODE_READ)))
+  if (!(file = openFile(filename, MODE_READ)))
     return NULL;
 
   buffer = checked_calloc(1);	/* start with valid, but empty text buffer */
 
-  while (!feof(file) && num_lines < max_lines)
+  while (!checkEndOfFile(file) && num_lines < max_lines)
   {
     char line[MAX_LINE_LEN];
 
     /* read next line of input file */
-    if (!fgets(line, MAX_LINE_LEN, file))
+    if (!getStringFromFile(file, line, MAX_LINE_LEN))
       break;
 
     buffer = checked_realloc(buffer, strlen(buffer) + strlen(line) + 1);
@@ -477,39 +349,11 @@ char *GetTextBufferFromFile(char *filename, int max_lines)
     num_lines++;
   }
 
-  fclose(file);
+  closeFile(file);
 
   return buffer;
 }
 
-void DrawTextToTextArea_OLD(int x, int y, char *text, int font_nr, int line_length,
-			    int area_xsize, int area_ysize, int mask_mode)
-{
-  int area_line = 0;
-  int font_height = getFontHeight(font_nr);
-
-  if (text == NULL)
-    return;
-
-  while (*text && area_line < area_ysize)
-  {
-    char buffer[MAX_OUTPUT_LINESIZE + 1];
-    int i;
-
-    for (i = 0; i < line_length && *text; i++)
-      if ((buffer[i] = *text++) == '\n')
-	break;
-    buffer[MIN(i, area_xsize)] = '\0';
-
-    DrawTextExt(drawto, x, y + area_line * font_height, buffer, font_nr,
-		mask_mode);
-
-    area_line++;
-  }
-
-  redraw_mask |= REDRAW_FIELD;
-}
-
 static boolean RenderLineToBuffer(char **src_buffer_ptr, char *dst_buffer,
 				  int *dst_buffer_len, int line_length,
 				  boolean last_line_was_empty)
@@ -589,138 +433,6 @@ static boolean RenderLineToBuffer(char **src_buffer_ptr, char *dst_buffer,
   return buffer_filled;
 }
 
-#if 0
-void DrawTextWrapped_OLD(int x, int y, char *text, int font_nr, int line_length,
-			 int max_lines)
-{
-  char *text_ptr = text;
-  int current_line = 0;
-  int font_height = getFontHeight(font_nr);
-
-  while (*text_ptr && current_line < max_lines)
-  {
-    char buffer[line_length + 1];
-    int buffer_len = 0;
-
-    buffer[0] = '\0';
-
-    RenderLineToBuffer(&text_ptr, buffer, &buffer_len, line_length, TRUE);
-
-    DrawText(x, y + current_line * font_height, buffer, font_nr);
-    current_line++;
-  }
-}
-#endif
-
-#if 0
-int DrawTextFromFile_OLD(int x, int y, char *filename, int font_nr,
-			 int line_length, int max_lines, boolean wrap_text)
-{
-  int font_height = getFontHeight(font_nr);
-  char line[MAX_LINE_LEN];
-  char buffer[line_length + 1];
-  int buffer_len;
-  int current_line = 0;
-  FILE *file;
-
-  if (current_line >= max_lines)
-    return 0;
-
-  if (filename == NULL)
-    return 0;
-
-  if (!(file = fopen(filename, MODE_READ)))
-    return 0;
-
-  buffer[0] = '\0';
-  buffer_len = 0;
-
-  while (!feof(file) && current_line < max_lines)
-  {
-    char *line_ptr;
-    boolean last_line_was_empty = TRUE;
-
-    /* read next line of input file */
-    if (!fgets(line, MAX_LINE_LEN, file))
-      break;
-
-    /* skip comments (lines directly beginning with '#') */
-    if (line[0] == '#')
-      continue;
-
-    /* cut trailing newline from input line */
-    for (line_ptr = line; *line_ptr; line_ptr++)
-    {
-      if (*line_ptr == '\n' || *line_ptr == '\r')
-      {
-	*line_ptr = '\0';
-	break;
-      }
-    }
-
-    if (strlen(line) == 0)		/* special case: force empty line */
-      strcpy(line, "\n");
-
-    line_ptr = line;
-
-    while (*line_ptr && current_line < max_lines)
-    {
-#if 1
-      boolean buffer_filled;
-
-      if (wrap_text)
-      {
-	buffer_filled = RenderLineToBuffer(&line_ptr, buffer, &buffer_len,
-					   line_length, last_line_was_empty);
-      }
-      else
-      {
-	if (strlen(line_ptr) <= line_length)
-	{
-	  buffer_len = strlen(line_ptr);
-	  strcpy(buffer, line_ptr);
-	}
-	else
-	{
-	  buffer_len = line_length;
-	  strncpy(buffer, line_ptr, line_length);
-	}
-
-	buffer[buffer_len] = '\0';
-	line_ptr += buffer_len;
-
-	buffer_filled = TRUE;
-      }
-#else
-      boolean buffer_filled = RenderLineToBuffer(&line_ptr, buffer, &buffer_len,
-						 line_length, last_line_was_empty);
-#endif
-
-      if (buffer_filled)
-      {
-	DrawText(x, y + current_line * font_height, buffer, font_nr);
-	current_line++;
-
-	last_line_was_empty = (buffer_len == 0);
-
-	buffer[0] = '\0';
-	buffer_len = 0;
-      }
-    }
-  }
-
-  fclose(file);
-
-  if (buffer_len > 0 && current_line < max_lines)
-  {
-    DrawText(x, y + current_line * font_height, buffer, font_nr);
-    current_line++;
-  }
-
-  return current_line;
-}
-#endif
-
 static boolean getCheckedTokenValueFromString(char *string, char **token,
 					      char **value)
 {
@@ -771,10 +483,6 @@ int DrawTextBuffer(int x, int y, char *text_buffer, int font_nr,
 		   int line_spacing, int mask_mode, boolean autowrap,
 		   boolean centered, boolean parse_comments)
 {
-#if 0
-  int font_width = getFontWidth(font_nr);
-  int font_height = getFontHeight(font_nr);
-#endif
   char buffer[line_length + 1];
   int buffer_len;
   int current_line = 0;
@@ -796,11 +504,7 @@ int DrawTextBuffer(int x, int y, char *text_buffer, int font_nr,
     char line[MAX_LINE_LEN + 1];
     char *line_ptr;
     boolean last_line_was_empty = TRUE;
-#if 1
     int num_line_chars = MAX_LINE_LEN;
-#else
-    int num_line_chars = (autowrap ? MAX_LINE_LEN : line_length);
-#endif
     int i;
 
     /* copy next line from text buffer to line buffer (nearly fgets() style) */
@@ -891,25 +595,8 @@ int DrawTextBuffer(int x, int y, char *text_buffer, int font_nr,
 
       if (buffer_filled)
       {
-#if 1
 	DrawTextBuffer_Flush(x, y, buffer, font_nr, line_length, cut_length,
 			     line_spacing, mask_mode, centered, current_line);
-#else
-	int offset_chars = (centered ? (line_length - buffer_len) / 2 : 0);
-	int offset_xsize =
-	  (centered ?  font_width * (line_length - buffer_len) / 2 : 0);
-	int final_cut_length = MAX(0, cut_length - offset_chars);
-	int xx = x + offset_xsize;
-
-	buffer[final_cut_length] = '\0';
-
-	if (mask_mode != -1)
-	  DrawTextExt(drawto, xx, y + current_line * font_height, buffer,
-		      font_nr, mask_mode);
-	else
-	  DrawText(xx, y + current_line * font_height, buffer, font_nr);
-#endif
-
 	current_line++;
 
 	last_line_was_empty = (buffer_len == 0);
@@ -922,31 +609,32 @@ int DrawTextBuffer(int x, int y, char *text_buffer, int font_nr,
 
   if (buffer_len > 0 && current_line < max_lines)
   {
-#if 1
     DrawTextBuffer_Flush(x, y, buffer, font_nr, line_length, cut_length,
 			 line_spacing, mask_mode, centered, current_line);
-#else
-    int offset_chars = (centered ? (line_length - buffer_len) / 2 : 0);
-	int offset_xsize =
-	  (centered ?  font_width * (line_length - buffer_len) / 2 : 0);
-    int final_cut_length = MAX(0, cut_length - offset_chars);
-    int xx = x + offset_xsize;
-
-    buffer[final_cut_length] = '\0';
-
-    if (mask_mode != -1)
-      DrawTextExt(drawto, xx, y + current_line * font_height, buffer,
-		  font_nr, mask_mode);
-    else
-      DrawText(xx, y + current_line * font_height, buffer, font_nr);
-#endif
-
     current_line++;
   }
 
   return current_line;
 }
 
+int DrawTextBufferVA(int x, int y, char *format, va_list ap, int font_nr,
+		     int line_length, int cut_length, int max_lines,
+		     int line_spacing, int mask_mode, boolean autowrap,
+		     boolean centered, boolean parse_comments)
+{
+  char text_buffer[MAX_OUTPUT_LINESIZE];
+  int text_length = vsnprintf(text_buffer, MAX_OUTPUT_LINESIZE, format, ap);
+
+  if (text_length >= MAX_OUTPUT_LINESIZE)
+    Error(ERR_WARN, "string too long in DrawTextBufferVA() -- truncated");
+
+  int num_lines_printed = DrawTextBuffer(x, y, text_buffer, font_nr,
+					 line_length, cut_length, max_lines,
+					 line_spacing, mask_mode, autowrap,
+					 centered, parse_comments);
+  return num_lines_printed;
+}
+
 int DrawTextFile(int x, int y, char *filename, int font_nr,
 		 int line_length, int cut_length, int max_lines,
 		 int line_spacing, int mask_mode, boolean autowrap,
@@ -961,19 +649,3 @@ int DrawTextFile(int x, int y, char *filename, int font_nr,
 
   return num_lines_printed;
 }
-
-#if 0
-void DrawTextWrapped(int x, int y, char *text, int font_nr, int line_length,
-		     int max_lines)
-{
-  DrawTextBuffer(x, y, text, font_nr, line_length, -1, max_lines, -1, TRUE,
-		 FALSE, FALSE);
-}
-
-void DrawTextToTextArea(int x, int y, char *text, int font_nr, int line_length,
-			int cut_length, int max_lines, int mask_mode)
-{
-  DrawTextBuffer(x, y, text, font_nr, line_length, cut_length, max_lines,
-		 mask_mode, FALSE, FALSE, FALSE);
-}
-#endif
diff --git a/src/libgame/text.h b/src/libgame/text.h
index 1d54a71..0a45204 100644
--- a/src/libgame/text.h
+++ b/src/libgame/text.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* text.h                                                   *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// text.h
+// ============================================================================
 
 #ifndef TEXT_H
 #define TEXT_H
@@ -32,6 +30,19 @@
 /* text output definitions */
 #define MAX_OUTPUT_LINESIZE	1024
 
+/* special constants for old ISO-8859-1 character byte values */
+#define CHAR_BYTE_UMLAUT_A	((char)0xc4)
+#define CHAR_BYTE_UMLAUT_O	((char)0xd6)
+#define CHAR_BYTE_UMLAUT_U	((char)0xdc)
+#define CHAR_BYTE_UMLAUT_a	((char)0xe4)
+#define CHAR_BYTE_UMLAUT_o	((char)0xf6)
+#define CHAR_BYTE_UMLAUT_u	((char)0xfc)
+#define CHAR_BYTE_SHARP_S	((char)0xdf)
+#define CHAR_BYTE_COPYRIGHT	((char)0xa9)
+#define CHAR_BYTE_REGISTERED	((char)0xae)
+#define CHAR_BYTE_DEGREE	((char)0xb0)
+#define CHAR_BYTE_CURSOR	((char)0xa0)
+
 /* special character mapping for default fonts */
 #define FONT_ASCII_CURSOR	((char)160)
 #define FONT_ASCII_BUTTON	((char)128)
@@ -41,16 +52,19 @@
 #define FONT_ASCII_RIGHT	((char)'>')
 
 #define MAP_FONT_ASCII(c)	((c) >= 'a' && (c) <= 'z' ? 'A' + (c) - 'a' : \
-				 (c) == '�'		  ? 96  :	      \
-				 (c) == '�' || (c) == '�' ? 97  :	      \
-				 (c) == '�' || (c) == '�' ? 98  :	      \
-				 (c) == '�' || (c) == '�' ? 99  :	      \
-				 (c) == '�'		  ? 100 :	      \
-				 (c) == '�'		  ? 101 :	      \
-				 (c) == FONT_ASCII_CURSOR ? 102 :	      \
-				 (c) == FONT_ASCII_BUTTON ? 109 :	      \
-				 (c) == FONT_ASCII_UP	  ? 110 :	      \
-				 (c) == FONT_ASCII_DOWN	  ? 111 :	      \
+				 (c) == CHAR_BYTE_COPYRIGHT  ?  96 :	\
+				 (c) == CHAR_BYTE_UMLAUT_a   ?  97 :	\
+				 (c) == CHAR_BYTE_UMLAUT_A   ?  97 :	\
+				 (c) == CHAR_BYTE_UMLAUT_o   ?  98 :	\
+				 (c) == CHAR_BYTE_UMLAUT_O   ?  98 :	\
+				 (c) == CHAR_BYTE_UMLAUT_u   ?  99 :	\
+				 (c) == CHAR_BYTE_UMLAUT_U   ?  99 :	\
+				 (c) == CHAR_BYTE_DEGREE     ? 100 :	\
+				 (c) == CHAR_BYTE_REGISTERED ? 101 :	\
+				 (c) == FONT_ASCII_CURSOR    ? 102 :	\
+				 (c) == FONT_ASCII_BUTTON    ? 109 :	\
+				 (c) == FONT_ASCII_UP	     ? 110 :	\
+				 (c) == FONT_ASCII_DOWN	     ? 111 :	\
 				 (c))
 
 /* 64 regular ordered ASCII characters, 6 special characters, 1 cursor char. */
@@ -69,6 +83,8 @@ struct FontBitmapInfo *getFontBitmapInfo(int);
 
 int getFontWidth(int);
 int getFontHeight(int);
+int getFontDrawOffsetX(int);
+int getFontDrawOffsetY(int);
 int getTextWidth(char *, int);
 
 void getFontCharSource(int, char, Bitmap **, int *, int *);
@@ -76,13 +92,11 @@ void getFontCharSource(int, char, Bitmap **, int *, int *);
 int maxWordLengthInString(char *);
 
 void DrawInitText(char *, int, int);
-void DrawInitTextIfNeeded(char *, int, int);
-void DrawInitTextExt(char *, int, int, boolean);
+
 void DrawTextF(int, int, int, char *, ...);
 void DrawTextFCentered(int, int, char *, ...);
 void DrawTextS(int, int, int, char *);
 void DrawTextSCentered(int, int, char *);
-void DrawTextCentered(int, int, char *);
 void DrawTextSAligned(int, int, char *, int, int);
 void DrawTextAligned(int, int, char *, int, int);
 void DrawText(int, int, char *, int);
@@ -91,6 +105,8 @@ void DrawTextExt(DrawBuffer *, int, int, char *, int, int);
 char *GetTextBufferFromFile(char *, int);
 int DrawTextBuffer(int, int, char *, int, int, int, int, int, int,
 		   boolean, boolean, boolean);
+int DrawTextBufferVA(int, int, char *, va_list, int, int, int, int, int, int,
+		     boolean, boolean, boolean);
 int DrawTextFile(int, int, char *, int, int, int, int, int, int,
 		 boolean, boolean, boolean);
 
diff --git a/src/libgame/toons.c b/src/libgame/toons.c
deleted file mode 100644
index 300ae70..0000000
--- a/src/libgame/toons.c
+++ /dev/null
@@ -1,425 +0,0 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* toons.c                                                  *
-***********************************************************/
-
-#include "toons.h"
-#include "misc.h"
-
-
-/* values for toon animation */
-#define ANIM_START	0
-#define ANIM_CONTINUE	1
-#define ANIM_STOP	2
-
-
-static struct ToonScreenInfo screen_info;
-
-
-/* ========================================================================= */
-/* generic animation frame calculation                                       */
-/* ========================================================================= */
-
-int getAnimationFrame(int num_frames, int delay, int mode, int start_frame,
-		      int sync_frame)
-{
-  int frame = 0;
-
-  sync_frame += start_frame * delay;
-
-  if (mode & ANIM_LOOP)			/* looping animation */
-  {
-    frame = (sync_frame % (delay * num_frames)) / delay;
-  }
-  else if (mode & ANIM_LINEAR)		/* linear (non-looping) animation */
-  {
-    frame = sync_frame / delay;
-
-    if (frame > num_frames - 1)
-      frame = num_frames - 1;
-  }
-  else if (mode & ANIM_PINGPONG)	/* oscillate (border frames once) */
-  {
-    int max_anim_frames = (num_frames > 1 ? 2 * num_frames - 2 : 1);
-
-    frame = (sync_frame % (delay * max_anim_frames)) / delay;
-    frame = (frame < num_frames ? frame : max_anim_frames - frame);
-  }
-  else if (mode & ANIM_PINGPONG2)	/* oscillate (border frames twice) */
-  {
-    int max_anim_frames = 2 * num_frames;
-
-    frame = (sync_frame % (delay * max_anim_frames)) / delay;
-    frame = (frame < num_frames ? frame : max_anim_frames - frame - 1);
-  }
-  else if (mode & ANIM_RANDOM)		/* play frames in random order */
-  {
-    /* note: expect different frames for the same delay cycle! */
-
-    if (gfx.anim_random_frame < 0)
-      frame = GetSimpleRandom(num_frames);
-    else
-      frame = gfx.anim_random_frame % num_frames;
-  }
-  else if (mode & (ANIM_CE_VALUE | ANIM_CE_SCORE | ANIM_CE_DELAY))
-  {
-    frame = sync_frame % num_frames;
-  }
-
-  if (mode & ANIM_REVERSE)		/* use reverse animation direction */
-    frame = num_frames - frame - 1;
-
-  return frame;
-}
-
-
-/* ========================================================================= */
-/* toon animation functions                                                  */
-/* ========================================================================= */
-
-static int get_toon_direction(char *direction_string_raw)
-{
-  char *direction_string = getStringToLower(direction_string_raw);
-  int direction = (strEqual(direction_string, "left")  ? MV_LEFT :
-		   strEqual(direction_string, "right") ? MV_RIGHT :
-		   strEqual(direction_string, "up")    ? MV_UP :
-		   strEqual(direction_string, "down")  ? MV_DOWN :
-		   MV_NONE);
-
-  free(direction_string);
-
-  return direction;
-}
-
-void InitToonScreen(Bitmap *save_buffer,
-		    void (*update_function)(void),
-		    void (*prepare_backbuffer_function)(void),
-		    boolean (*redraw_needed_function)(void),
-		    struct ToonInfo *toons, int num_toons,
-		    int startx, int starty,
-		    int width, int height,
-		    int frame_delay_value)
-{
-  screen_info.save_buffer = save_buffer;
-  screen_info.update_function = update_function;
-  screen_info.prepare_backbuffer_function = prepare_backbuffer_function;
-  screen_info.redraw_needed_function = redraw_needed_function;
-  screen_info.toons = toons;
-  screen_info.num_toons = num_toons;
-  screen_info.startx = startx;
-  screen_info.starty = starty;
-  screen_info.width = width;
-  screen_info.height = height;
-  screen_info.frame_delay_value = frame_delay_value;
-}
-
-void DrawAnim(Bitmap *toon_bitmap, GC toon_clip_gc,
-	      int src_x, int src_y, int width, int height,
-	      int dest_x, int dest_y, int pad_x, int pad_y)
-{
-  int pad_dest_x = dest_x - pad_x;
-  int pad_dest_y = dest_y - pad_y;
-  int pad_width  = width  + 2 * pad_x;
-  int pad_height = height + 2 * pad_y;
-#if 1
-  int buffer_x = 0;
-  int buffer_y = 0;
-#else
-  int buffer_x = DOOR_GFX_PAGEX3;
-  int buffer_y = DOOR_GFX_PAGEY1;
-#endif
-
-#if 0
-  printf("::: (%d, %d), (%d, %d), (%d, %d), (%d, %d) -> (%d, %d), (%d, %d), (%d, %d)\n",
-	 src_x, src_y,
-	 width, height,
-	 dest_x, dest_y,
-	 pad_x, pad_y,
-
-	 pad_dest_x, pad_dest_y,
-	 pad_width, pad_height,
-	 buffer_x, buffer_y);
-#endif
-
-  /* correct values to avoid off-screen blitting (start position) */
-  if (pad_dest_x < screen_info.startx)
-  {
-    pad_width -= (screen_info.startx - pad_dest_x);
-    pad_dest_x = screen_info.startx;
-  }
-  if (pad_dest_y < screen_info.starty)
-  {
-    pad_height -= (screen_info.starty - pad_dest_y);
-    pad_dest_y = screen_info.starty;
-  }
-
-  /* correct values to avoid off-screen blitting (blit size) */
-  if (pad_width > screen_info.width)
-    pad_width = screen_info.width;
-  if (pad_height > screen_info.height)
-    pad_height = screen_info.height;
-
-  /* special method to avoid flickering interference with BackToFront() */
-  BlitBitmap(backbuffer, screen_info.save_buffer, pad_dest_x, pad_dest_y,
-	     pad_width, pad_height, buffer_x, buffer_y);
-  SetClipOrigin(toon_bitmap, toon_clip_gc, dest_x - src_x, dest_y - src_y);
-  BlitBitmapMasked(toon_bitmap, backbuffer, src_x, src_y, width, height,
-		   dest_x, dest_y);
-  BlitBitmap(backbuffer, window, pad_dest_x, pad_dest_y, pad_width, pad_height,
-	     pad_dest_x, pad_dest_y);
-
-  screen_info.update_function();
-
-  BlitBitmap(screen_info.save_buffer, backbuffer, buffer_x, buffer_y,
-	     pad_width, pad_height, pad_dest_x, pad_dest_y);
-
-  FlushDisplay();
-}
-
-boolean AnimateToon(int toon_nr, boolean restart)
-{
-  static unsigned long animation_frame_counter = 0;
-  static int pos_x = 0, pos_y = 0;
-  static int delta_x = 0, delta_y = 0;
-  static int frame = 0;
-  static boolean horiz_move, vert_move;
-  static unsigned long anim_delay = 0;
-  static unsigned long anim_delay_value = 0;
-  static int width,height;
-  static int pad_x,pad_y;
-  static int cut_x,cut_y;
-  static int src_x, src_y;
-  static int dest_x, dest_y;
-  struct ToonInfo *anim = &screen_info.toons[toon_nr];
-  Bitmap *anim_bitmap = screen_info.toons[toon_nr].bitmap;
-  GC anim_clip_gc = anim_bitmap->stored_clip_gc;
-  int direction = get_toon_direction(anim->direction);
-
-  if (restart)
-  {
-    horiz_move = (direction & (MV_LEFT | MV_RIGHT));
-    vert_move = (direction & (MV_UP | MV_DOWN));
-    anim_delay_value = anim->step_delay * screen_info.frame_delay_value;
-
-    frame = getAnimationFrame(anim->anim_frames, anim->anim_delay,
-			      anim->anim_mode, anim->anim_start_frame,
-			      animation_frame_counter++);
-
-    if (horiz_move)
-    {
-      int pos_bottom = screen_info.height - anim->height;
-
-      if (strEqual(anim->position, "top"))
-	pos_y = 0;
-      else if (strEqual(anim->position, "bottom"))
-	pos_y = pos_bottom;
-      else if (strEqual(anim->position, "upper"))
-	pos_y = GetSimpleRandom(pos_bottom / 2);
-      else if (strEqual(anim->position, "lower"))
-	pos_y = pos_bottom / 2 + GetSimpleRandom(pos_bottom / 2);
-      else
-	pos_y = GetSimpleRandom(pos_bottom);
-
-      if (direction == MV_RIGHT)
-      {
-	delta_x = anim->step_offset;
-	pos_x = -anim->width + delta_x;
-      }
-      else
-      {
-	delta_x = -anim->step_offset;
-	pos_x = screen_info.width + delta_x;
-      }
-
-      delta_y = 0;
-    }
-    else
-    {
-      int pos_right = screen_info.width - anim->width;
-
-      if (strEqual(anim->position, "left"))
-	pos_x = 0;
-      else if (strEqual(anim->position, "right"))
-	pos_x = pos_right;
-      else
-	pos_x = GetSimpleRandom(pos_right);
-
-      if (direction == MV_DOWN)
-      {
-	delta_y = anim->step_offset;
-	pos_y = -anim->height + delta_y;
-      }
-      else
-      {
-	delta_y = -anim->step_offset;
-	pos_y = screen_info.height + delta_y;
-      }
-
-      delta_x = 0;
-    }
-  }
-
-  if (pos_x <= -anim->width        - anim->step_offset ||
-      pos_x >=  screen_info.width  + anim->step_offset ||
-      pos_y <= -anim->height       - anim->step_offset ||
-      pos_y >=  screen_info.height + anim->step_offset)
-    return TRUE;
-
-  if (!DelayReached(&anim_delay, anim_delay_value))
-  {
-    if (screen_info.redraw_needed_function() && !restart)
-      DrawAnim(anim_bitmap, anim_clip_gc,
-	       src_x + cut_x, src_y + cut_y,
-	       width, height,
-	       screen_info.startx + dest_x,
-	       screen_info.starty + dest_y,
-	       pad_x, pad_y);
-
-    return FALSE;
-  }
-
-  if (pos_x < -anim->width)
-    pos_x = -anim->width;
-  else if (pos_x > screen_info.width)
-    pos_x = screen_info.width;
-  if (pos_y < -anim->height)
-    pos_y = -anim->height;
-  else if (pos_y > screen_info.height)
-    pos_y = screen_info.height;
-
-  pad_x = (horiz_move ? anim->step_offset : 0);
-  pad_y = (vert_move  ? anim->step_offset : 0);
-  src_x = anim->src_x + frame * anim->width;
-  src_y = anim->src_y;
-  dest_x = pos_x;
-  dest_y = pos_y;
-  cut_x = cut_y = 0;
-  width  = anim->width;
-  height = anim->height;
-
-  if (pos_x < 0)
-  {
-    dest_x = 0;
-    width += pos_x;
-    cut_x = -pos_x;
-  }
-  else if (pos_x > screen_info.width - anim->width)
-    width -= (pos_x - (screen_info.width - anim->width));
-
-  if (pos_y < 0)
-  {
-    dest_y = 0;
-    height += pos_y;
-    cut_y = -pos_y;
-  }
-  else if (pos_y > screen_info.height - anim->height)
-    height -= (pos_y - (screen_info.height - anim->height));
-
-  DrawAnim(anim_bitmap, anim_clip_gc,
-	   src_x + cut_x, src_y + cut_y,
-	   width, height,
-	   screen_info.startx + dest_x,
-	   screen_info.starty + dest_y,
-	   pad_x, pad_y);
-
-  pos_x += delta_x;
-  pos_y += delta_y;
-
-  frame = getAnimationFrame(anim->anim_frames, anim->anim_delay,
-			    anim->anim_mode, anim->anim_start_frame,
-			    animation_frame_counter++);
-
-  return FALSE;
-}
-
-void HandleAnimation(int mode)
-{
-  static unsigned long animstart_delay = -1;
-  static unsigned long animstart_delay_value = 0;
-  static boolean anim_running = FALSE;
-  static boolean anim_restart = TRUE;
-  static boolean reset_delay = TRUE;
-  static int toon_nr = 0;
-
-  if (!setup.toons || screen_info.num_toons == 0)
-    return;
-
-  /* this may happen after reloading graphics and redefining "num_toons" */
-  if (toon_nr >= screen_info.num_toons)
-    anim_restart = TRUE;
-
-  switch(mode)
-  {
-    case ANIM_START:
-      screen_info.prepare_backbuffer_function();
-
-      anim_running = TRUE;
-      anim_restart = TRUE;
-      reset_delay = TRUE;
-
-      return;
-
-    case ANIM_CONTINUE:
-      if (!anim_running)
-	return;
-
-      break;
-
-    case ANIM_STOP:
-      if (anim_running)
-      {
-#if 1
-	redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
-
-	screen_info.update_function();
-#endif
-
-	anim_running = FALSE;
-      }
-
-      return;
-
-    default:
-      break;
-  }
-
-  if (reset_delay)
-  {
-    animstart_delay = Counter();
-    animstart_delay_value = GetSimpleRandom(3000);
-    reset_delay = FALSE;
-  }
-
-  if (anim_restart)
-  {
-    if (!DelayReached(&animstart_delay, animstart_delay_value))
-      return;
-
-    toon_nr = GetSimpleRandom(screen_info.num_toons);
-  }
-
-  anim_restart = reset_delay = AnimateToon(toon_nr, anim_restart);
-}
-
-void InitAnimation()
-{
-  HandleAnimation(ANIM_START);
-}
-
-void StopAnimation()
-{
-  HandleAnimation(ANIM_STOP);
-}
-
-void DoAnimation()
-{
-  HandleAnimation(ANIM_CONTINUE);
-}
diff --git a/src/libgame/toons.h b/src/libgame/toons.h
deleted file mode 100644
index 2f1044b..0000000
--- a/src/libgame/toons.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* toons.h                                                  *
-***********************************************************/
-
-#ifndef TOONS_H
-#define TOONS_H
-
-#include "system.h"
-
-
-struct ToonScreenInfo
-{
-  Bitmap *save_buffer;
-  void (*update_function)(void);
-  void (*prepare_backbuffer_function)(void);
-  boolean (*redraw_needed_function)(void);
-
-  struct ToonInfo *toons;
-  int num_toons;
-
-  int startx, starty;
-  int width, height;
-
-  int frame_delay_value;
-};
-
-struct ToonInfo
-{
-  Bitmap *bitmap;
-
-  int src_x, src_y;
-  int width, height;
-  int anim_frames;
-  int anim_start_frame;
-  int anim_delay;
-  int anim_mode;
-  int step_offset;
-  int step_delay;
-
-  char *direction;
-  char *position;
-};
-
-
-int getAnimationFrame(int, int, int, int, int);
-
-void InitToonScreen(Bitmap *, void (*update_function)(void),
-		    void (*prepare_backbuffer_function)(void),
-		    boolean (*redraw_needed_function)(void),
-		    struct ToonInfo *, int, int, int, int, int, int);
-void InitAnimation(void);
-void StopAnimation(void);
-void DoAnimation(void);
-
-#endif	/* TOONS_H */
diff --git a/src/libgame/types.h b/src/libgame/types.h
index 6e55364..acc2c23 100644
--- a/src/libgame/types.h
+++ b/src/libgame/types.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* types.h                                                  *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// types.h
+// ============================================================================
 
 #ifndef TYPES_H
 #define TYPES_H
@@ -74,6 +72,7 @@ struct ListNode
 {
   char *key;
   void *content;
+  struct ListNode *prev;
   struct ListNode *next;
 };
 typedef struct ListNode ListNode;
diff --git a/src/libgame/windows.h b/src/libgame/windows.h
index 7aaa69a..3027348 100644
--- a/src/libgame/windows.h
+++ b/src/libgame/windows.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* windows.h                                                *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// windows.h
+// ============================================================================
 
 #ifndef WINDOWS_H
 #define WINDOWS_H
diff --git a/src/libgame/x11.c b/src/libgame/x11.c
deleted file mode 100644
index f95c3da..0000000
--- a/src/libgame/x11.c
+++ /dev/null
@@ -1,526 +0,0 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* x11.c                                                    *
-***********************************************************/
-
-#include "system.h"
-#include "pcx.h"
-#include "misc.h"
-#include "setup.h"
-
-
-#if defined(TARGET_X11)
-
-static void X11InitDisplay();
-static DrawWindow *X11InitWindow();
-
-static int X11DebugErrorHandler(Display *display, XErrorEvent *event)
-{
-  int x = 0;
-
-  return 1 / x;		/* !!! crash program to give backtrace in gdb !!! */
-}
-
-void X11InitVideoDisplay(void)
-{
-  /* initialize X11 video */
-  X11InitDisplay();
-
-  /* set default X11 depth */
-  video.default_depth = XDefaultDepth(display, screen);
-}
-
-void X11InitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window)
-{
-  if (*window != NULL)
-    X11CloseWindow(*window);
-
-  *window = X11InitWindow();
-
-  XMapWindow(display, (*window)->drawable);
-
-  FlushDisplay();
-
-  /* create additional (off-screen) buffer for double-buffering */
-#if 1
-  ReCreateBitmap(backbuffer, video.width, video.height, video.depth);
-#else
-  *backbuffer = CreateBitmap(video.width, video.height, video.depth);
-#endif
-}
-
-static void X11InitDisplay()
-{
-#if !defined(PLATFORM_MSDOS)
-  XVisualInfo vinfo_template, *vinfo;
-  int num_visuals;
-#endif
-  unsigned int depth;
-
-  /* connect to X server */
-  if (!(display = XOpenDisplay(options.display_name)))
-    Error(ERR_EXIT, "cannot connect to X server %s",
-	  XDisplayName(options.display_name));
-
-  if (options.debug_x11_sync)
-  {
-    Error(ERR_WARN, "running in X11 synchronous mode (debug only)");
-
-    XSynchronize(display, True);
-    XSetErrorHandler(X11DebugErrorHandler);
-  }
-
-  screen = DefaultScreen(display);
-  visual = DefaultVisual(display, screen);
-  depth  = DefaultDepth(display, screen);
-  cmap   = DefaultColormap(display, screen);
-
-#if !defined(PLATFORM_MSDOS)
-  /* look for good enough visual */
-  vinfo_template.screen = screen;
-  vinfo_template.class = (depth == 8 ? PseudoColor : TrueColor);
-  vinfo_template.depth = depth;
-  if ((vinfo = XGetVisualInfo(display, VisualScreenMask | VisualClassMask |
-			      VisualDepthMask, &vinfo_template, &num_visuals)))
-  {
-    visual = vinfo->visual;
-    XFree((void *)vinfo);
-  }
-
-  /* got appropriate visual? */
-  if (depth < 8)
-    Error(ERR_EXIT, "X11 display not supported (less than 8 bits per pixel)");
-  else if ((depth ==8 && visual->class != PseudoColor) ||
-	   (depth > 8 && visual->class != TrueColor &&
-	    visual->class != DirectColor))
-    Error(ERR_EXIT, "X11 display not supported (inappropriate visual)");
-#endif /* !PLATFORM_MSDOS */
-}
-
-static DrawWindow *X11InitWindow()
-{
-  DrawWindow *new_window = CreateBitmapStruct();
-  unsigned int border_width = 4;
-  XGCValues gc_values;
-  unsigned long gc_valuemask;
-#if !defined(PLATFORM_MSDOS)
-  XTextProperty windowName, iconName;
-  Pixmap icon_pixmap, iconmask_pixmap;
-  unsigned int icon_width, icon_height;
-  int icon_hot_x, icon_hot_y;
-  XSizeHints size_hints;
-  XWMHints wm_hints;
-  XClassHint class_hints;
-  char *window_name = program.window_title;
-  char *icon_name = program.window_title;
-  long window_event_mask;
-  Atom proto_atom = None, delete_atom = None;
-#endif
-  int screen_width, screen_height;
-  int win_xpos, win_ypos;
-  unsigned long pen_fg = WhitePixel(display, screen);
-  unsigned long pen_bg = BlackPixel(display, screen);
-  const int width = video.width, height = video.height;
-  int i;
-
-  screen_width = XDisplayWidth(display, screen);
-  screen_height = XDisplayHeight(display, screen);
-
-  win_xpos = (screen_width - width) / 2;
-  win_ypos = (screen_height - height) / 2;
-
-  new_window->width = width;
-  new_window->height = height;
-
-  new_window->drawable = XCreateSimpleWindow(display,
-					     RootWindow(display, screen),
-					     win_xpos, win_ypos,
-					     width, height, border_width,
-					     pen_fg, pen_bg);
-
-#if !defined(PLATFORM_MSDOS)
-  proto_atom = XInternAtom(display, "WM_PROTOCOLS", FALSE);
-  delete_atom = XInternAtom(display, "WM_DELETE_WINDOW", FALSE);
-  if ((proto_atom != None) && (delete_atom != None))
-    XChangeProperty(display, new_window->drawable, proto_atom, XA_ATOM, 32,
-		    PropModePrepend, (unsigned char *) &delete_atom, 1);
-
-  if (XReadBitmapFile(display, new_window->drawable,
-		      getCustomImageFilename(program.x11_icon_filename),
-		      &icon_width, &icon_height, &icon_pixmap,
-		      &icon_hot_x, &icon_hot_y) != BitmapSuccess)
-    Error(ERR_EXIT, "cannot read icon bitmap file '%s'",
-	  program.x11_icon_filename);
-
-  if (XReadBitmapFile(display, new_window->drawable,
-		      getCustomImageFilename(program.x11_iconmask_filename),
-		      &icon_width, &icon_height, &iconmask_pixmap,
-		      &icon_hot_x, &icon_hot_y) != BitmapSuccess)
-    Error(ERR_EXIT, "cannot read icon bitmap file '%s'",
-	  program.x11_iconmask_filename);
-
-  size_hints.width  = size_hints.min_width  = size_hints.max_width  = width;
-  size_hints.height = size_hints.min_height = size_hints.max_height = height;
-  size_hints.flags = PSize | PMinSize | PMaxSize;
-
-  if (win_xpos || win_ypos)
-  {
-    size_hints.x = win_xpos;
-    size_hints.y = win_ypos;
-    size_hints.flags |= PPosition;
-  }
-
-  if (!XStringListToTextProperty(&window_name, 1, &windowName))
-    Error(ERR_EXIT, "structure allocation for windowName failed");
-
-  if (!XStringListToTextProperty(&icon_name, 1, &iconName))
-    Error(ERR_EXIT, "structure allocation for iconName failed");
-
-  wm_hints.initial_state = NormalState;
-  wm_hints.input = True;
-  wm_hints.icon_pixmap = icon_pixmap;
-  wm_hints.icon_mask = iconmask_pixmap;
-  wm_hints.flags = StateHint | IconPixmapHint | IconMaskHint | InputHint;
-
-  class_hints.res_name = program.command_basename;
-  class_hints.res_class = program.program_title;
-
-  XSetWMProperties(display, new_window->drawable, &windowName, &iconName, 
-		   NULL, 0, &size_hints, &wm_hints, 
-		   &class_hints);
-
-  XFree(windowName.value);
-  XFree(iconName.value);
-
-  /* Select event types wanted */
-  window_event_mask =
-    ExposureMask | StructureNotifyMask | FocusChangeMask |
-    ButtonPressMask | ButtonReleaseMask |
-    PointerMotionMask | PointerMotionHintMask |
-    KeyPressMask | KeyReleaseMask;
-
-  XSelectInput(display, new_window->drawable, window_event_mask);
-#endif
-
-  /* create GC for drawing with window depth and background color (black) */
-  gc_values.graphics_exposures = False;
-  gc_values.foreground = pen_bg;
-  gc_values.background = pen_bg;
-  gc_valuemask = GCGraphicsExposures | GCForeground | GCBackground;
-  new_window->gc =
-    XCreateGC(display, new_window->drawable, gc_valuemask, &gc_values);
-
-  /* create GCs for line drawing (black and white) */
-  for (i = 0; i < 2; i++)
-  {
-    gc_values.graphics_exposures = False;
-    gc_values.foreground = (i ? pen_fg : pen_bg);
-    gc_values.background = pen_bg;
-    gc_values.line_width = 4;
-    gc_values.line_style = LineSolid;
-    gc_values.cap_style = CapRound;
-    gc_values.join_style = JoinRound;
-
-    gc_valuemask = GCGraphicsExposures | GCForeground | GCBackground |
-                   GCLineWidth | GCLineStyle | GCCapStyle | GCJoinStyle;
-    new_window->line_gc[i] =
-      XCreateGC(display, new_window->drawable, gc_valuemask, &gc_values);
-  }
-
-  return new_window;
-}
-
-void X11CloseWindow(DrawWindow *window)
-{
-  if (window->drawable)
-  {
-    XUnmapWindow(display, window->drawable);
-    XDestroyWindow(display, window->drawable);
-  }
-
-  if (window->gc)
-    XFreeGC(display, window->gc);
-
-  free(window);
-}
-
-void X11ZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
-{
-#if defined(TARGET_ALLEGRO)
-  AllegroZoomBitmap(src_bitmap->drawable, dst_bitmap->drawable,
-		    src_bitmap->width, src_bitmap->height,
-		    dst_bitmap->width, dst_bitmap->height);
-#else
-  ZoomPixmap(display, src_bitmap->gc,
-	     src_bitmap->drawable, dst_bitmap->drawable,
-	     src_bitmap->width, src_bitmap->height,
-	     dst_bitmap->width, dst_bitmap->height);
-#endif
-}
-
-static void SetImageDimensions(Bitmap *bitmap)
-{
-#if defined(TARGET_ALLEGRO)
-  BITMAP *allegro_bitmap = (BITMAP *)(bitmap->drawable);
-
-  bitmap->width  = allegro_bitmap->w;
-  bitmap->height = allegro_bitmap->h;
-#else
-  Window root;
-  int x, y;
-  unsigned int border_width, depth;
-
-  XGetGeometry(display, bitmap->drawable, &root, &x, &y,
-	       &bitmap->width, &bitmap->height, &border_width, &depth);
-#endif
-}
-
-Bitmap *X11LoadImage(char *filename)
-{
-  Bitmap *new_bitmap = CreateBitmapStruct();
-  char *error = "Read_PCX_to_Pixmap(): %s '%s'";
-  int pcx_err;
-  XGCValues clip_gc_values;
-  unsigned long clip_gc_valuemask;
-
-  pcx_err = Read_PCX_to_Pixmap(display, window->drawable, window->gc, filename,
-			       &new_bitmap->drawable, &new_bitmap->clip_mask);
-  switch(pcx_err)
-  {
-    case PCX_Success:
-      break;
-    case PCX_OpenFailed:
-      SetError(error, "cannot open PCX file", filename);
-      return NULL;
-    case PCX_ReadFailed:
-      SetError(error, "cannot read PCX file", filename);
-      return NULL;
-    case PCX_FileInvalid:
-      SetError(error, "invalid PCX file", filename);
-      return NULL;
-    case PCX_NoMemory:
-      SetError(error, "not enough memory for PCX file", filename);
-      return NULL;
-    case PCX_ColorFailed:
-      SetError(error, "cannot get colors for PCX file", filename);
-      return NULL;
-    case PCX_OtherError:
-      /* this should already have called SetError() */
-      return NULL;
-    default:
-      SetError(error, "unknown error reading PCX file", filename);
-      return NULL;
-  }
-
-  if (!new_bitmap->drawable)
-  {
-    SetError("X11LoadImage(): cannot get graphics for '%s'", filename);
-    return NULL;
-  }
-
-  if (!new_bitmap->clip_mask)
-  {
-    SetError("X11LoadImage(): cannot get clipmask for '%s'", filename);
-    return NULL;
-  }
-
-  clip_gc_values.graphics_exposures = False;
-  clip_gc_values.clip_mask = new_bitmap->clip_mask;
-  clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
-  new_bitmap->stored_clip_gc = XCreateGC(display, window->drawable,
-					 clip_gc_valuemask, &clip_gc_values);
-
-  /* set GraphicContext inheritated from Window */
-  new_bitmap->gc = window->gc;
-
-  /* set image width and height */
-  SetImageDimensions(new_bitmap);
-
-  return new_bitmap;
-}
-
-void X11CreateBitmapContent(Bitmap *new_bitmap,
-			    int width, int height, int depth)
-{
-  Pixmap pixmap;
-
-  if ((pixmap = XCreatePixmap(display, window->drawable, width, height, depth))
-      == None)
-    Error(ERR_EXIT, "cannot create pixmap");
-
-  new_bitmap->drawable = pixmap;
-
-  if (window == NULL)
-    Error(ERR_EXIT, "Window GC needed for Bitmap -- create Window first");
-
-  new_bitmap->gc = window->gc;
-
-  new_bitmap->line_gc[0] = window->line_gc[0];
-  new_bitmap->line_gc[1] = window->line_gc[1];
-}
-
-void X11FreeBitmapPointers(Bitmap *bitmap)
-{
-  /* The X11 version seems to have a memory leak here -- although
-     "XFreePixmap()" is called, the corresponding memory seems not
-     to be freed (according to "ps"). The SDL version apparently
-     does not have this problem. */
-
-  if (bitmap->drawable)
-    XFreePixmap(display, bitmap->drawable);
-  if (bitmap->clip_mask)
-    XFreePixmap(display, bitmap->clip_mask);
-  if (bitmap->stored_clip_gc)
-    XFreeGC(display, bitmap->stored_clip_gc);
-  /* the other GCs are only pointers to GCs used elsewhere */
-  bitmap->drawable = None;
-  bitmap->clip_mask = None;
-  bitmap->stored_clip_gc = None;
-}
-
-void X11CopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
-		 int src_x, int src_y, int width, int height,
-		 int dst_x, int dst_y, int mask_mode)
-{
-  XCopyArea(display, src_bitmap->drawable, dst_bitmap->drawable,
-	    (mask_mode == BLIT_MASKED ? src_bitmap->clip_gc : dst_bitmap->gc),
-	    src_x, src_y, width, height, dst_x, dst_y);
-}
-
-void X11FillRectangle(Bitmap *bitmap, int x, int y,
-		      int width, int height, Pixel color)
-{
-  XSetForeground(display, bitmap->gc, color);
-  XFillRectangle(display, bitmap->drawable, bitmap->gc, x, y, width, height);
-}
-
-void X11FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
-		      int fade_mode, int fade_delay, int post_delay,
-		      void (*draw_border_function)(void))
-{
-  /* fading currently not supported -- simply copy backbuffer to screen */
-
-  if (fade_mode == FADE_MODE_FADE_OUT)
-    X11FillRectangle(backbuffer, x, y, width, height, BLACK_PIXEL);
-
-  if (draw_border_function != NULL)
-    draw_border_function();
-
-  X11CopyArea(backbuffer, window, x, y, width, height, x, y, BLIT_OPAQUE);
-
-  /* as we currently cannot use the fade delay, also do not use post delay */
-}
-
-void X11DrawSimpleLine(Bitmap *bitmap, int from_x, int from_y,
-		       int to_x, int to_y, Pixel color)
-{
-  XSetForeground(display, bitmap->gc, color);
-  XDrawLine(display, bitmap->drawable, bitmap->gc, from_x, from_y, to_x, to_y);
-}
-
-Pixel X11GetPixel(Bitmap *bitmap, int x, int y)
-{
-  XImage *pixel_image;
-  Pixel pixel_value;
-
-  pixel_image = XGetImage(display, bitmap->drawable, x, y, 1, 1,
-			  AllPlanes, ZPixmap);
-  pixel_value = XGetPixel(pixel_image, 0, 0);
-
-  X11DestroyImage(pixel_image);
-
-  return pixel_value;
-}
-
-#if defined(TARGET_X11_NATIVE)
-Pixel X11GetPixelFromRGB(unsigned int color_r, unsigned int color_g,
-			 unsigned int color_b)
-{
-  XColor xcolor;
-  Pixel pixel;
-
-  xcolor.flags = DoRed | DoGreen | DoBlue;
-  xcolor.red = (color_r << 8);
-  xcolor.green = (color_g << 8);
-  xcolor.blue = (color_b << 8);
-
-  XAllocColor(display, cmap, &xcolor);
-  pixel = xcolor.pixel;
-
-  return pixel;
-}
-#endif	/* TARGET_X11_NATIVE */
-
-void X11DestroyImage(XImage *ximage)
-{
-#if defined(TARGET_X11_NATIVE)
-  /* this seems to be needed for OS/2, but does not hurt on other platforms */
-  if (ximage->data != NULL)
-  {
-    free(ximage->data);
-    ximage->data = NULL;
-  }
-#endif	/* TARGET_X11_NATIVE */
-
-  XDestroyImage(ximage);
-}
-
-
-/* ------------------------------------------------------------------------- */
-/* mouse pointer functions                                                   */
-/* ------------------------------------------------------------------------- */
-
-#if defined(TARGET_X11_NATIVE)
-
-static Cursor create_cursor(struct MouseCursorInfo *cursor_info)
-{
-  Pixmap pixmap_data, pixmap_mask;
-  XColor color_fg, color_bg;
-  Cursor cursor;
-
-  /* shape and mask are single plane pixmaps */
-  pixmap_data =
-    XCreatePixmapFromBitmapData(display, window->drawable, cursor_info->data,
-				cursor_info->width, cursor_info->height,
-				1, 0, 1);
-  pixmap_mask =
-    XCreatePixmapFromBitmapData(display, window->drawable, cursor_info->mask,
-				cursor_info->width, cursor_info->height,
-				1, 0, 1);
-
-  XParseColor(display, cmap, "black", &color_fg);
-  XParseColor(display, cmap, "white", &color_bg);
-
-  cursor = XCreatePixmapCursor(display, pixmap_data, pixmap_mask,
-			       &color_fg, &color_bg,
-			       cursor_info->hot_x, cursor_info->hot_y);
-
-  return cursor;
-}
-
-void X11SetMouseCursor(struct MouseCursorInfo *cursor_info)
-{
-  static struct MouseCursorInfo *last_cursor_info = NULL;
-  static Cursor cursor_default = None;
-  static Cursor cursor_current = None;
-
-  if (cursor_info != NULL && cursor_info != last_cursor_info)
-  {
-    cursor_current = create_cursor(cursor_info);
-    last_cursor_info = cursor_info;
-  }
-
-  XDefineCursor(display, window->drawable,
-		cursor_info ? cursor_current : cursor_default);
-}
-#endif	/* TARGET_X11_NATIVE */
-
-#endif /* TARGET_X11 */
diff --git a/src/libgame/x11.h b/src/libgame/x11.h
deleted file mode 100644
index 9f2efee..0000000
--- a/src/libgame/x11.h
+++ /dev/null
@@ -1,356 +0,0 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* x11.h                                                    *
-***********************************************************/
-
-#ifndef X11_H
-#define X11_H
-
-#if !defined(PLATFORM_MSDOS)
-#define XK_MISCELLANY
-#define XK_LATIN1
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#include <X11/Xos.h>
-#include <X11/Intrinsic.h>
-#include <X11/keysymdef.h>
-#endif
-
-
-/* system dependent definitions */
-
-/* MS-DOS header file also defines "TARGET_STRING" */
-#ifndef TARGET_STRING
-#define TARGET_STRING		"X11"
-#endif
-
-#if defined(PLATFORM_UNIX)
-/* This triggers some stuff that is needed because X11 (XSetClipOrigin(),
-   to be precise) is often very slow when preparing a masked XCopyArea()
-   for big Pixmaps.
-   To prevent this, small (tile-sized) mask Pixmaps are created which will
-   then be set much faster with XSetClipOrigin() and speed things up a lot. */
-#define TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND
-#endif
-
-#define FULLSCREEN_STATUS	FULLSCREEN_NOT_AVAILABLE
-
-#define CURSOR_MAX_WIDTH	32
-#define CURSOR_MAX_HEIGHT	32
-
-
-/* X11 type definitions */
-
-typedef struct X11DrawableInfo	Bitmap;
-typedef struct X11DrawableInfo	DrawWindow;
-typedef struct X11DrawableInfo	DrawBuffer;
-/* "Pixel" is already defined */
-/* "Cursor" is already defined */
-
-typedef KeySym			Key;
-typedef unsigned int		KeyMod;
-
-typedef XEvent			Event;
-typedef XButtonEvent		ButtonEvent;
-typedef XMotionEvent		MotionEvent;
-typedef XKeyEvent		KeyEvent;
-typedef XExposeEvent		ExposeEvent;
-typedef XFocusChangeEvent	FocusChangeEvent;
-typedef XClientMessageEvent	ClientMessageEvent;
-
-
-/* structure definitions */
-
-struct X11DrawableInfo
-{
-  char *source_filename;
-
-  unsigned int width, height;
-  Drawable drawable;
-  Drawable clip_mask;
-  GC gc;		/* GC for normal drawing (inheritated from 'window') */
-  GC line_gc[2];	/* GC for foreground and background line drawing     */
-  GC stored_clip_gc;	/* GC for masked drawing (used for whole Pixmap)     */
-  GC clip_gc;		/* can be 'stored_clip_gc' or one-tile-only clip GC  */
-};
-
-struct MouseCursorInfo
-{
-  int width, height;
-  int hot_x, hot_y;
-
-  char data[CURSOR_MAX_WIDTH * CURSOR_MAX_HEIGHT / 8];
-  char mask[CURSOR_MAX_WIDTH * CURSOR_MAX_HEIGHT / 8];
-};
-
-
-/* X11 symbol definitions */
-
-#define BLACK_PIXEL		BlackPixel(display, screen)
-#define WHITE_PIXEL		WhitePixel(display, screen)
-
-#define EVENT_BUTTONPRESS	ButtonPress
-#define EVENT_BUTTONRELEASE	ButtonRelease
-#define EVENT_MOTIONNOTIFY	MotionNotify
-#define EVENT_KEYPRESS		KeyPress
-#define EVENT_KEYRELEASE	KeyRelease
-#define EVENT_EXPOSE		Expose
-#define EVENT_FOCUSIN		FocusIn
-#define EVENT_FOCUSOUT		FocusOut
-#define EVENT_CLIENTMESSAGE	ClientMessage
-#define EVENT_MAPNOTIFY		MapNotify
-#define EVENT_UNMAPNOTIFY	UnmapNotify
-
-#define KSYM_UNDEFINED		XK_VoidSymbol
-
-#define KSYM_Return		XK_Return
-#define KSYM_Escape		XK_Escape
-
-#define KSYM_Left		XK_Left
-#define KSYM_Right		XK_Right
-#define KSYM_Up			XK_Up
-#define KSYM_Down		XK_Down
-
-#ifdef XK_KP_Left
-#define KSYM_KP_Left		XK_KP_Left
-#define KSYM_KP_Right		XK_KP_Right
-#define KSYM_KP_Up		XK_KP_Up
-#define KSYM_KP_Down		XK_KP_Down
-#endif
-
-#ifdef XK_KP_Enter
-#define KSYM_KP_Enter		XK_KP_Enter
-#define KSYM_KP_Add		XK_KP_Add
-#define KSYM_KP_Subtract	XK_KP_Subtract
-#define KSYM_KP_Multiply	XK_KP_Multiply
-#define KSYM_KP_Divide		XK_KP_Divide
-#define KSYM_KP_Separator	XK_KP_Separator
-#endif
-
-#define KSYM_Shift_L		XK_Shift_L
-#define KSYM_Shift_R		XK_Shift_R
-#define KSYM_Control_L		XK_Control_L
-#define KSYM_Control_R		XK_Control_R
-#define KSYM_Meta_L		XK_Meta_L
-#define KSYM_Meta_R		XK_Meta_R
-#define KSYM_Alt_L		XK_Alt_L
-#define KSYM_Alt_R		XK_Alt_R
-#define KSYM_Super_L		XK_Super_L
-#define KSYM_Super_R		XK_Super_R
-#define KSYM_Mode_switch	XK_Mode_switch
-#define KSYM_Multi_key		XK_Multi_key
-
-#define KSYM_BackSpace		XK_BackSpace
-#define KSYM_Delete		XK_Delete
-#define KSYM_Insert		XK_Insert
-#define KSYM_Tab		XK_Tab
-#define KSYM_Home		XK_Home
-#define KSYM_End		XK_End
-#define KSYM_Page_Up		XK_Page_Up
-#define KSYM_Page_Down		XK_Page_Down
-#define KSYM_Menu		XK_Menu
-
-#define KSYM_space		XK_space
-#define KSYM_exclam		XK_exclam
-#define KSYM_quotedbl		XK_quotedbl
-#define KSYM_numbersign		XK_numbersign
-#define KSYM_dollar		XK_dollar
-#define KSYM_percent		XK_percent
-#define KSYM_ampersand		XK_ampersand
-#define KSYM_apostrophe		XK_apostrophe
-#define KSYM_parenleft		XK_parenleft
-#define KSYM_parenright		XK_parenright
-#define KSYM_asterisk		XK_asterisk
-#define KSYM_plus		XK_plus
-#define KSYM_comma		XK_comma
-#define KSYM_minus		XK_minus
-#define KSYM_period		XK_period
-#define KSYM_slash		XK_slash
-
-#define KSYM_colon		XK_colon
-#define KSYM_semicolon		XK_semicolon
-#define KSYM_less		XK_less
-#define KSYM_equal		XK_equal
-#define KSYM_greater		XK_greater
-#define KSYM_question		XK_question
-#define KSYM_at			XK_at
-
-#define KSYM_bracketleft	XK_bracketleft
-#define KSYM_backslash		XK_backslash
-#define KSYM_bracketright	XK_bracketright
-#define KSYM_asciicircum	XK_asciicircum
-#define KSYM_underscore		XK_underscore
-#define KSYM_grave		XK_grave
-
-#define KSYM_quoteleft		XK_quoteleft
-#define KSYM_braceleft		XK_braceleft
-#define KSYM_bar		XK_bar
-#define KSYM_braceright		XK_braceright
-#define KSYM_asciitilde		XK_asciitilde
-
-#define KSYM_degree		XK_degree
-#define KSYM_Adiaeresis		XK_Adiaeresis
-#define KSYM_Odiaeresis		XK_Odiaeresis
-#define KSYM_Udiaeresis		XK_Udiaeresis
-#define KSYM_adiaeresis		XK_adiaeresis
-#define KSYM_odiaeresis		XK_odiaeresis
-#define KSYM_udiaeresis		XK_udiaeresis
-#define KSYM_ssharp		XK_ssharp
-
-#define KSYM_A			XK_A
-#define KSYM_B			XK_B
-#define KSYM_C			XK_C
-#define KSYM_D			XK_D
-#define KSYM_E			XK_E
-#define KSYM_F			XK_F
-#define KSYM_G			XK_G
-#define KSYM_H			XK_H
-#define KSYM_I			XK_I
-#define KSYM_J			XK_J
-#define KSYM_K			XK_K
-#define KSYM_L			XK_L
-#define KSYM_M			XK_M
-#define KSYM_N			XK_N
-#define KSYM_O			XK_O
-#define KSYM_P			XK_P
-#define KSYM_Q			XK_Q
-#define KSYM_R			XK_R
-#define KSYM_S			XK_S
-#define KSYM_T			XK_T
-#define KSYM_U			XK_U
-#define KSYM_V			XK_V
-#define KSYM_W			XK_W
-#define KSYM_X			XK_X
-#define KSYM_Y			XK_Y
-#define KSYM_Z			XK_Z
-
-#define KSYM_a			XK_a
-#define KSYM_b			XK_b
-#define KSYM_c			XK_c
-#define KSYM_d			XK_d
-#define KSYM_e			XK_e
-#define KSYM_f			XK_f
-#define KSYM_g			XK_g
-#define KSYM_h			XK_h
-#define KSYM_i			XK_i
-#define KSYM_j			XK_j
-#define KSYM_k			XK_k
-#define KSYM_l			XK_l
-#define KSYM_m			XK_m
-#define KSYM_n			XK_n
-#define KSYM_o			XK_o
-#define KSYM_p			XK_p
-#define KSYM_q			XK_q
-#define KSYM_r			XK_r
-#define KSYM_s			XK_s
-#define KSYM_t			XK_t
-#define KSYM_u			XK_u
-#define KSYM_v			XK_v
-#define KSYM_w			XK_w
-#define KSYM_x			XK_x
-#define KSYM_y			XK_y
-#define KSYM_z			XK_z
-
-#define KSYM_0			XK_0
-#define KSYM_1			XK_1
-#define KSYM_2			XK_2
-#define KSYM_3			XK_3
-#define KSYM_4			XK_4
-#define KSYM_5			XK_5
-#define KSYM_6			XK_6
-#define KSYM_7			XK_7
-#define KSYM_8			XK_8
-#define KSYM_9			XK_9
-
-#define KSYM_KP_0		XK_KP_0
-#define KSYM_KP_1		XK_KP_1
-#define KSYM_KP_2		XK_KP_2
-#define KSYM_KP_3		XK_KP_3
-#define KSYM_KP_4		XK_KP_4
-#define KSYM_KP_5		XK_KP_5
-#define KSYM_KP_6		XK_KP_6
-#define KSYM_KP_7		XK_KP_7
-#define KSYM_KP_8		XK_KP_8
-#define KSYM_KP_9		XK_KP_9
-
-#define KSYM_F1			XK_F1
-#define KSYM_F2			XK_F2
-#define KSYM_F3			XK_F3
-#define KSYM_F4			XK_F4
-#define KSYM_F5			XK_F5
-#define KSYM_F6			XK_F6
-#define KSYM_F7			XK_F7
-#define KSYM_F8			XK_F8
-#define KSYM_F9			XK_F9
-#define KSYM_F10		XK_F10
-#define KSYM_F11		XK_F11
-#define KSYM_F12		XK_F12
-#define KSYM_F13		XK_F13
-#define KSYM_F14		XK_F14
-#define KSYM_F15		XK_F15
-#define KSYM_F16		XK_F16
-#define KSYM_F17		XK_F17
-#define KSYM_F18		XK_F18
-#define KSYM_F19		XK_F19
-#define KSYM_F20		XK_F20
-#define KSYM_F21		XK_F21
-#define KSYM_F22		XK_F22
-#define KSYM_F23		XK_F23
-#define KSYM_F24		XK_F24
-
-#define KSYM_FKEY_FIRST		KSYM_F1
-#define KSYM_FKEY_LAST		KSYM_F24
-#define KSYM_NUM_FKEYS		(KSYM_FKEY_LAST - KSYM_FKEY_FIRST + 1)
-
-#define KMOD_None		None
-#define KMOD_Shift_L		0x0001
-#define KMOD_Shift_R		0x0002
-#define KMOD_Control_L		0x0040
-#define KMOD_Control_R		0x0080
-#define KMOD_Meta_L		0x0400
-#define KMOD_Meta_R		0x0800
-#define KMOD_Alt_L		0x0100
-#define KMOD_Alt_R		0x0200
-
-#define KMOD_Shift		(KMOD_Shift_L   | KMOD_Shift_R)
-#define KMOD_Control		(KMOD_Control_L | KMOD_Control_R)
-#define KMOD_Meta		(KMOD_Meta_L    | KMOD_Meta_R)
-#define KMOD_Alt		(KMOD_Alt_L     | KMOD_Alt_R)
-
-
-/* X11 function definitions */
-
-void X11InitVideoDisplay(void);
-void X11InitVideoBuffer(DrawBuffer **, DrawWindow **);
-
-void X11CloseWindow(DrawWindow *);
-
-void X11ZoomBitmap(Bitmap *, Bitmap *);
-Bitmap *X11LoadImage(char *);
-
-void X11CreateBitmapContent(Bitmap *, int, int, int);
-void X11FreeBitmapPointers(Bitmap *);
-void X11CopyArea(Bitmap *, Bitmap *, int, int, int, int, int, int, int);
-void X11FillRectangle(Bitmap *, int, int, int, int, Pixel);
-void X11FadeRectangle(Bitmap *, int, int, int, int, int, int, int,
-		      void (*draw_border_function)(void));
-void X11DrawSimpleLine(Bitmap *, int, int, int, int, Pixel);
-Pixel X11GetPixel(Bitmap *, int, int);
-Pixel X11GetPixelFromRGB(unsigned int, unsigned int, unsigned int);
-void X11DestroyImage(XImage *);
-
-#if defined(TARGET_X11_NATIVE)
-void X11SetMouseCursor(struct MouseCursorInfo *);
-#endif
-
-#endif /* X11_H */
diff --git a/src/main.c b/src/main.c
index d5dbe91..141a00a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* main.c                                                   *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// main.c
+// ============================================================================
 
 #include "libgame/libgame.h"
 
@@ -17,19 +15,22 @@
 #include "init.h"
 #include "game.h"
 #include "tape.h"
+#include "tools.h"
+#include "files.h"
 #include "events.h"
 #include "config.h"
 
-Bitmap		       *bitmap_db_store;
-Bitmap		       *bitmap_db_cross;
 Bitmap		       *bitmap_db_field;
 Bitmap		       *bitmap_db_panel;
-Bitmap		       *bitmap_db_door;
-Bitmap		       *bitmap_db_toons;
+Bitmap		       *bitmap_db_door_1;
+Bitmap		       *bitmap_db_door_2;
+Bitmap		       *bitmap_db_store_1;
+Bitmap		       *bitmap_db_store_2;
 DrawBuffer	       *fieldbuffer;
 DrawBuffer	       *drawto_field;
 
 int			game_status = -1;
+boolean			game_status_last_screen = -1;
 boolean			level_editor_test_game = FALSE;
 boolean			network_playing = FALSE;
 
@@ -40,13 +41,6 @@ SDL_Thread	       *server_thread;
 
 int			key_joystick_mapping = 0;
 
-#if 1
-boolean			redraw[MAX_LEV_FIELDX + 2][MAX_LEV_FIELDY + 2];
-#else
-boolean			redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
-#endif
-int			redraw_x1 = 0, redraw_y1 = 0;
-
 short			Feld[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 short			MovPos[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 short			MovDir[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
@@ -89,33 +83,46 @@ int			ActiveFont[NUM_FONTS];
 int			lev_fieldx, lev_fieldy;
 int			scroll_x, scroll_y;
 
-int			WIN_XSIZE = 672, WIN_YSIZE = 560;
-int			SCR_FIELDX = 17, SCR_FIELDY = 17;
-int			SX = 8, SY = 8;
+int			WIN_XSIZE = WIN_XSIZE_DEFAULT;
+int			WIN_YSIZE = WIN_YSIZE_DEFAULT;
+
+int			SCR_FIELDX = SCR_FIELDX_DEFAULT;
+int			SCR_FIELDY = SCR_FIELDY_DEFAULT;
+
 int			REAL_SX = 6, REAL_SY = 6;
+int			SX = 8, SY = 8;
 int			DX = 566, DY = 60;
 int			VX = 566, VY = 400;
 int			EX = 566, EY = 356;
 int			dDX, dDY;
 
-#if 1
+int			FULL_SXSIZE = 2 + SXSIZE_DEFAULT + 2;
+int			FULL_SYSIZE = 2 + SYSIZE_DEFAULT + 2;
+int			SXSIZE = SXSIZE_DEFAULT;
+int			SYSIZE = SYSIZE_DEFAULT;
+
+int			FADE_SX = 6, FADE_SY = 6;
+int			FADE_SXSIZE = 2 + SXSIZE_DEFAULT + 2;
+int			FADE_SYSIZE = 2 + SXSIZE_DEFAULT + 2;
+
+int			DXSIZE = 100;
+int			DYSIZE = 280;
+int			VXSIZE = 100;
+int			VYSIZE = 100;
+int			EXSIZE = 100;
+int			EYSIZE = 144;
+int			TILESIZE_VAR = TILESIZE;
+
 int			FX, FY;
-#else
-int			FX = SX, FY = SY;
-#endif
 int			ScrollStepSize;
 int			ScreenMovDir = MV_NONE, ScreenMovPos = 0;
 int			ScreenGfxPos = 0;
 int			BorderElement = EL_STEELWALL;
+int			MenuFrameDelay = MENU_FRAME_DELAY;
 int			GameFrameDelay = GAME_FRAME_DELAY;
 int			FfwdFrameDelay = FFWD_FRAME_DELAY;
-#if 1
 int			BX1, BY1;
 int			BX2, BY2;
-#else
-int			BX1 = 0, BY1 = 0;
-int			BX2 = SCR_FIELDX - 1, BY2 = SCR_FIELDY - 1;
-#endif
 int			SBX_Left, SBX_Right;
 int			SBY_Upper, SBY_Lower;
 int			ZX, ZY;
@@ -137,22 +144,40 @@ struct GlobalInfo	global;
 struct BorderInfo	border;
 struct ViewportInfo	viewport;
 struct TitleFadingInfo	fading;
+struct TitleFadingInfo	title_initial_first_default;
 struct TitleFadingInfo	title_initial_default;
+struct TitleFadingInfo	title_first_default;
 struct TitleFadingInfo	title_default;
+struct TitleMessageInfo	titlescreen_initial_first_default;
+struct TitleMessageInfo	titlescreen_initial_first[MAX_NUM_TITLE_IMAGES];
+struct TitleMessageInfo	titlescreen_initial_default;
+struct TitleMessageInfo	titlescreen_initial[MAX_NUM_TITLE_IMAGES];
+struct TitleMessageInfo	titlescreen_first_default;
+struct TitleMessageInfo	titlescreen_first[MAX_NUM_TITLE_IMAGES];
+struct TitleMessageInfo	titlescreen_default;
+struct TitleMessageInfo	titlescreen[MAX_NUM_TITLE_IMAGES];
+struct TitleMessageInfo	titlemessage_initial_first_default;
+struct TitleMessageInfo	titlemessage_initial_first[MAX_NUM_TITLE_MESSAGES];
 struct TitleMessageInfo	titlemessage_initial_default;
 struct TitleMessageInfo	titlemessage_initial[MAX_NUM_TITLE_MESSAGES];
+struct TitleMessageInfo	titlemessage_first_default;
+struct TitleMessageInfo	titlemessage_first[MAX_NUM_TITLE_MESSAGES];
 struct TitleMessageInfo	titlemessage_default;
 struct TitleMessageInfo	titlemessage[MAX_NUM_TITLE_MESSAGES];
 struct TitleMessageInfo	readme;
 struct InitInfo		init, init_last;
 struct MenuInfo		menu;
 struct DoorInfo		door_1, door_2;
+struct RequestInfo	request;
 struct PreviewInfo	preview;
+struct EditorInfo	editor;
+
 struct GraphicInfo     *graphic_info = NULL;
 struct SoundInfo       *sound_info = NULL;
 struct MusicInfo       *music_info = NULL;
 struct MusicFileInfo   *music_file_info = NULL;
 struct HelpAnimInfo    *helpanim_info = NULL;
+
 SetupFileHash          *helptext_info = NULL;
 SetupFileHash	       *image_config_hash = NULL;
 SetupFileHash	       *element_token_hash = NULL;
@@ -1092,37 +1117,37 @@ struct ElementNameInfo element_name_info[MAX_NUM_ELEMENTS + 1] =
   {
     "char_copyright",
     "char",
-    "letter '�'"
+    "letter '\xa9'"
   },
   {
     "char_aumlaut",
     "char",
-    "letter '�'"
+    "letter '\xc4'"
   },
   {
     "char_oumlaut",
     "char",
-    "letter '�'"
+    "letter '\xd6'"
   },
   {
     "char_uumlaut",
     "char",
-    "letter '�'"
+    "letter '\xdc'"
   },
   {
     "char_degree",
     "char",
-    "letter '�'"
+    "letter '\xb0'"
   },
   {
     "char_trademark",
     "char",
-    "letter '�'"
+    "letter '\xae'"
   },
   {
     "char_cursor",
     "char",
-    "letter '�'"
+    "letter '\xa0'"
   },
   {
     "char_unused",
@@ -4152,37 +4177,37 @@ struct ElementNameInfo element_name_info[MAX_NUM_ELEMENTS + 1] =
   {
     "steel_char_copyright",
     "steel_char",
-    "steel letter '�'"
+    "steel letter '\xa9'"
   },
   {
     "steel_char_aumlaut",
     "steel_char",
-    "steel letter '�'"
+    "steel letter '\xc4'"
   },
   {
     "steel_char_oumlaut",
     "steel_char",
-    "steel letter '�'"
+    "steel letter '\xd6'"
   },
   {
     "steel_char_uumlaut",
     "steel_char",
-    "steel letter '�'"
+    "steel letter '\xdc'"
   },
   {
     "steel_char_degree",
     "steel_char",
-    "steel letter '�'"
+    "steel letter '\xb0'"
   },
   {
     "steel_char_trademark",
     "steel_char",
-    "steel letter '�'"
+    "steel letter '\xae'"
   },
   {
     "steel_char_cursor",
     "steel_char",
-    "steel letter '�'"
+    "steel letter '\xa0'"
   },
   {
     "steel_char_unused",
@@ -5421,6 +5446,14 @@ struct ElementActionInfo element_action_info[NUM_ACTIONS + 1 + 1] =
   { ".page[30]",		ACTION_PAGE_30,			FALSE	},
   { ".page[31]",		ACTION_PAGE_31,			FALSE	},
   { ".page[32]",		ACTION_PAGE_32,			FALSE	},
+  { ".part_1",			ACTION_PART_1,			FALSE	},
+  { ".part_2",			ACTION_PART_2,			FALSE	},
+  { ".part_3",			ACTION_PART_3,			FALSE	},
+  { ".part_4",			ACTION_PART_4,			FALSE	},
+  { ".part_5",			ACTION_PART_5,			FALSE	},
+  { ".part_6",			ACTION_PART_6,			FALSE	},
+  { ".part_7",			ACTION_PART_7,			FALSE	},
+  { ".part_8",			ACTION_PART_8,			FALSE	},
   { ".other",			ACTION_OTHER,			FALSE	},
 
   /* empty suffix always matches -- check as last entry in InitSoundInfo() */
@@ -5448,18 +5481,37 @@ struct SpecialSuffixInfo special_suffix_info[NUM_SPECIAL_GFX_ARGS + 1 + 1] =
   { ".[DEFAULT]",		GFX_SPECIAL_ARG_DEFAULT,		},
   { ".LOADING",			GFX_SPECIAL_ARG_LOADING,		},
   { ".TITLE_INITIAL",		GFX_SPECIAL_ARG_TITLE_INITIAL,		},
+  { ".TITLE_INITIAL_1",		GFX_SPECIAL_ARG_TITLE_INITIAL_1,	},
+  { ".TITLE_INITIAL_2",		GFX_SPECIAL_ARG_TITLE_INITIAL_2,	},
+  { ".TITLE_INITIAL_3",		GFX_SPECIAL_ARG_TITLE_INITIAL_3,	},
+  { ".TITLE_INITIAL_4",		GFX_SPECIAL_ARG_TITLE_INITIAL_4,	},
+  { ".TITLE_INITIAL_5",		GFX_SPECIAL_ARG_TITLE_INITIAL_5,	},
   { ".TITLE",			GFX_SPECIAL_ARG_TITLE,			},
+  { ".TITLE_1",			GFX_SPECIAL_ARG_TITLE_1,		},
+  { ".TITLE_2",			GFX_SPECIAL_ARG_TITLE_2,		},
+  { ".TITLE_3",			GFX_SPECIAL_ARG_TITLE_3,		},
+  { ".TITLE_4",			GFX_SPECIAL_ARG_TITLE_4,		},
+  { ".TITLE_5",			GFX_SPECIAL_ARG_TITLE_5,		},
   { ".MAIN",			GFX_SPECIAL_ARG_MAIN,			},
   { ".LEVELS",			GFX_SPECIAL_ARG_LEVELS			},
+  { ".LEVELNR",			GFX_SPECIAL_ARG_LEVELNR			},
   { ".SCORES",			GFX_SPECIAL_ARG_SCORES,			},
   { ".EDITOR",			GFX_SPECIAL_ARG_EDITOR,			},
   { ".INFO",			GFX_SPECIAL_ARG_INFO,			},
   { ".SETUP",			GFX_SPECIAL_ARG_SETUP,			},
   { ".PLAYING",			GFX_SPECIAL_ARG_PLAYING,		},
   { ".DOOR",			GFX_SPECIAL_ARG_DOOR,			},
+  { ".TAPE",			GFX_SPECIAL_ARG_TAPE,			},
   { ".PANEL",			GFX_SPECIAL_ARG_PANEL,			},
   { ".PREVIEW",			GFX_SPECIAL_ARG_PREVIEW,		},
   { ".CRUMBLED",		GFX_SPECIAL_ARG_CRUMBLED,		},
+  { ".MAINONLY",		GFX_SPECIAL_ARG_MAINONLY,		},
+  { ".TYPENAME",		GFX_SPECIAL_ARG_TYPENAME,		},
+  { ".SUBMENU",			GFX_SPECIAL_ARG_SUBMENU,		},
+  { ".MENU",			GFX_SPECIAL_ARG_MENU,			},
+  { ".TOONS",			GFX_SPECIAL_ARG_TOONS,			},
+  { ".FADING",			GFX_SPECIAL_ARG_FADING,			},
+  { ".QUIT",			GFX_SPECIAL_ARG_QUIT,			},
 
   /* empty suffix always matches -- check as last entry in InitMusicInfo() */
   { "",				GFX_SPECIAL_ARG_DEFAULT,		},
@@ -5502,15 +5554,19 @@ struct FontInfo font_info[NUM_FONTS + 1] =
   { "font.envelope_2"		},
   { "font.envelope_3"		},
   { "font.envelope_4"		},
+  { "font.request"		},
   { "font.input_1.active"	},
   { "font.input_2.active"	},
   { "font.input_1"		},
   { "font.input_2"		},
+  { "font.option_off_narrow"	},
   { "font.option_off"		},
+  { "font.option_on_narrow"	},
   { "font.option_on"		},
   { "font.value_1"		},
   { "font.value_2"		},
   { "font.value_old"		},
+  { "font.value_narrow"		},
   { "font.level_number.active"	},
   { "font.level_number"		},
   { "font.tape_recorder"	},
@@ -5521,6 +5577,31 @@ struct FontInfo font_info[NUM_FONTS + 1] =
   { NULL			}
 };
 
+struct GlobalAnimInfo global_anim_info[NUM_GLOBAL_ANIM_TOKENS + 1] =
+{
+  /* (real) graphic definitions used to define animation graphics */
+  { "gfx.global.anim_1",	},
+  { "gfx.global.anim_2",	},
+  { "gfx.global.anim_3",	},
+  { "gfx.global.anim_4",	},
+  { "gfx.global.anim_5",	},
+  { "gfx.global.anim_6",	},
+  { "gfx.global.anim_7",	},
+  { "gfx.global.anim_8",	},
+
+  /* (dummy) graphic definitions used to define animation controls */
+  { "global.anim_1",		},
+  { "global.anim_2",		},
+  { "global.anim_3",		},
+  { "global.anim_4",		},
+  { "global.anim_5",		},
+  { "global.anim_6",		},
+  { "global.anim_7",		},
+  { "global.anim_8",		},
+
+  { NULL			}
+};
+
 
 /* ------------------------------------------------------------------------- */
 /* music token prefix definitions                                            */
@@ -5540,53 +5621,153 @@ struct MusicPrefixInfo music_prefix_info[NUM_MUSIC_PREFIXES + 1] =
 
 static void print_usage()
 {
-  printf("\n"
-	 "Usage: %s [OPTION]... [HOSTNAME [PORT]]\n"
-	 "\n"
-	 "Options:\n"
-	 "  -d, --display HOSTNAME[:SCREEN]  specify X server display\n"
-	 "  -b, --basepath DIRECTORY         alternative base DIRECTORY\n"
-	 "  -l, --level DIRECTORY            alternative level DIRECTORY\n"
-	 "  -g, --graphics DIRECTORY         alternative graphics DIRECTORY\n"
-	 "  -s, --sounds DIRECTORY           alternative sounds DIRECTORY\n"
-	 "  -m, --music DIRECTORY            alternative music DIRECTORY\n"
-	 "  -n, --network                    network multiplayer game\n"
-	 "      --serveronly                 only start network server\n"
-	 "  -v, --verbose                    verbose mode\n"
-	 "      --debug                      display debugging information\n"
-	 "      --debug-x11-sync             enable X11 synchronous mode\n"
-	 "  -e, --execute COMMAND            execute batch COMMAND\n"
-	 "\n"
-	 "Valid commands for '--execute' option:\n"
-	 "  \"print graphicsinfo.conf\"        print default graphics config\n"
-	 "  \"print soundsinfo.conf\"          print default sounds config\n"
-	 "  \"print musicinfo.conf\"           print default music config\n"
-	 "  \"print editorsetup.conf\"         print default editor config\n"
-	 "  \"print helpanim.conf\"            print default helpanim config\n"
-	 "  \"print helptext.conf\"            print default helptext config\n"
-	 "  \"dump level FILE\"                dump level data from FILE\n"
-	 "  \"dump tape FILE\"                 dump tape data from FILE\n"
-	 "  \"autoplay LEVELDIR [NR ...]\"     play level tapes for LEVELDIR\n"
-	 "  \"convert LEVELDIR [NR]\"          convert levels in LEVELDIR\n"
-	 "  \"create images DIRECTORY\"        write BMP images to DIRECTORY\n"
-	 "\n",
-	 program.command_basename);
+  Print("\n"
+	"Usage: %s [OPTION]... [HOSTNAME [PORT]]\n"
+	"\n"
+	"Options:\n"
+	"  -b, --basepath DIRECTORY         alternative base DIRECTORY\n"
+	"  -l, --level DIRECTORY            alternative level DIRECTORY\n"
+	"  -g, --graphics DIRECTORY         alternative graphics DIRECTORY\n"
+	"  -s, --sounds DIRECTORY           alternative sounds DIRECTORY\n"
+	"  -m, --music DIRECTORY            alternative music DIRECTORY\n"
+	"      --mytapes                    use private tapes for tape tests\n"
+	"  -n, --network                    network multiplayer game\n"
+	"      --serveronly                 only start network server\n"
+	"  -v, --verbose                    verbose mode\n"
+	"  -V, --version                    show program version\n"
+	"      --debug                      display debugging information\n"
+	"  -e, --execute COMMAND            execute batch COMMAND\n"
+	"\n"
+	"Valid commands for '--execute' option:\n"
+	"  \"print graphicsinfo.conf\"        print default graphics config\n"
+	"  \"print soundsinfo.conf\"          print default sounds config\n"
+	"  \"print musicinfo.conf\"           print default music config\n"
+	"  \"print editorsetup.conf\"         print default editor config\n"
+	"  \"print helpanim.conf\"            print default helpanim config\n"
+	"  \"print helptext.conf\"            print default helptext config\n"
+	"  \"dump level FILE\"                dump level data from FILE\n"
+	"  \"dump tape FILE\"                 dump tape data from FILE\n"
+	"  \"autotest LEVELDIR [NR ...]\"     test level tapes for LEVELDIR\n"
+	"  \"autoplay LEVELDIR [NR ...]\"     play level tapes for LEVELDIR\n"
+	"  \"autoffwd LEVELDIR [NR ...]\"     ffwd level tapes for LEVELDIR\n"
+	"  \"autowarp LEVELDIR [NR ...]\"     warp level tapes for LEVELDIR\n"
+	"  \"convert LEVELDIR [NR]\"          convert levels in LEVELDIR\n"
+	"  \"create images DIRECTORY\"        write BMP images to DIRECTORY\n"
+	"  \"create CE image DIRECTORY\"      write BMP image to DIRECTORY\n"
+	"\n",
+	program.command_basename);
 }
 
-int main(int argc, char *argv[])
+static void print_version()
 {
-  char * window_title_string = getWindowTitleString();
+  Print("%s %d.%d.%d.%d%s\n",
+	PROGRAM_TITLE_STRING,
+	PROGRAM_VERSION_MAJOR,
+	PROGRAM_VERSION_MINOR,
+	PROGRAM_VERSION_PATCH,
+	PROGRAM_VERSION_BUILD,
+	PROGRAM_VERSION_EXTRA);
+
+  if (options.debug)
+  {
+    SDL_version sdl_version;
+
+    SDL_VERSION(&sdl_version);
+    Print("- SDL %d.%d.%d\n",
+	  sdl_version.major,
+	  sdl_version.minor,
+	  sdl_version.patch);
 
-  InitProgramInfo(argv[0], USERDATA_DIRECTORY, USERDATA_DIRECTORY_UNIX,
-		  PROGRAM_TITLE_STRING, window_title_string, ICON_TITLE_STRING,
-		  X11_ICON_FILENAME, X11_ICONMASK_FILENAME, SDL_ICON_FILENAME,
-		  MSDOS_POINTER_FILENAME,
-		  COOKIE_PREFIX, FILENAME_PREFIX, GAME_VERSION_ACTUAL);
+    SDL_IMAGE_VERSION(&sdl_version);
+    Print("- SDL_image %d.%d.%d\n",
+	  sdl_version.major,
+	  sdl_version.minor,
+	  sdl_version.patch);
+
+    SDL_MIXER_VERSION(&sdl_version);
+    Print("- SDL_mixer %d.%d.%d\n",
+	  sdl_version.major,
+	  sdl_version.minor,
+	  sdl_version.patch);
+
+    SDL_NET_VERSION(&sdl_version);
+    Print("- SDL_net %d.%d.%d\n",
+	  sdl_version.major,
+	  sdl_version.minor,
+	  sdl_version.patch);
+  }
+}
+
+static void InitProgramConfig(char *command_filename)
+{
+  char *program_title = PROGRAM_TITLE_STRING;
+  char *program_icon_file = PROGRAM_ICON_FILENAME;
+  char *config_filename = getProgramConfigFilename(command_filename);
+  char *userdata_basename = getBaseNameNoSuffix(command_filename);
+  char *userdata_subdir;
+  char *userdata_subdir_unix;
+
+  // read default program config, if existing
+  if (fileExists(config_filename))
+  {
+    // if program config file exists, derive Unix user data directory from it
+    userdata_basename = getBaseName(config_filename);
+
+    if (strSuffix(userdata_basename, ".conf"))
+      userdata_basename[strlen(userdata_basename) - 5] = '\0';
+
+    LoadSetupFromFilename(config_filename);
+  }
+
+  // set user data directory for Linux/Unix (but not Mac OS X)
+  userdata_subdir_unix = getStringCat2(".", userdata_basename);
+
+  // set program title from potentially redefined program title
+  if (setup.internal.program_title != NULL &&
+      strlen(setup.internal.program_title) > 0)
+    program_title = getStringCopy(setup.internal.program_title);
+
+  // set program icon file from potentially redefined program icon file
+  if (setup.internal.program_icon_file != NULL &&
+      strlen(setup.internal.program_icon_file) > 0)
+    program_icon_file = getStringCopy(setup.internal.program_icon_file);
+
+#if defined(PLATFORM_WIN32) || defined(PLATFORM_MACOSX)
+  userdata_subdir = program_title;
+#elif defined(PLATFORM_UNIX)
+  userdata_subdir = userdata_subdir_unix;
+#else
+  userdata_subdir = USERDATA_DIRECTORY_OTHER;
+#endif
+
+  // set default window size (only relevant on program startup)
+  if (setup.internal.default_window_width  != 0 &&
+      setup.internal.default_window_height != 0)
+  {
+    WIN_XSIZE = setup.internal.default_window_width;
+    WIN_YSIZE = setup.internal.default_window_height;
+  }
+
+  InitProgramInfo(command_filename,
+		  config_filename,
+		  userdata_subdir,
+		  program_title,
+		  program_title,
+		  program_icon_file,
+		  COOKIE_PREFIX,
+		  GAME_VERSION_ACTUAL);
+}
+
+int main(int argc, char *argv[])
+{
+  InitProgramConfig(argv[0]);
 
+  InitWindowTitleFunction(getWindowTitleString);
+  InitExitMessageFunction(DisplayExitMessage);
   InitExitFunction(CloseAllAndExit);
   InitPlatformDependentStuff();
 
-  GetOptions(argv, print_usage);
+  GetOptions(argc, argv, print_usage, print_version);
   OpenAll();
 
   EventLoop();
diff --git a/src/main.h b/src/main.h
index d16f5bc..36bc42d 100644
--- a/src/main.h
+++ b/src/main.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* main.h                                                   *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// main.h
+// ============================================================================
 
 #ifndef MAIN_H
 #define MAIN_H
@@ -43,17 +41,15 @@
 #define SND_UNDEFINED			(-1)
 #define MUS_UNDEFINED			(-1)
 
-#if 0
-#define WIN_XSIZE			672
-#define WIN_YSIZE			560
-#endif
+#define WIN_XSIZE_DEFAULT		672
+#define WIN_YSIZE_DEFAULT		560
 
-#define DEFAULT_FULLSCREEN_MODE		"800x600"
+#define SCR_FIELDX_DEFAULT		17
+#define SCR_FIELDY_DEFAULT		17
+
+#define SXSIZE_DEFAULT			(SCR_FIELDX_DEFAULT * TILEX)
+#define SYSIZE_DEFAULT			(SCR_FIELDY_DEFAULT * TILEY)
 
-#if 0
-#define SCR_FIELDX			17
-#define SCR_FIELDY			17
-#endif
 #define MAX_BUF_XSIZE			(SCR_FIELDX + 2)
 #define MAX_BUF_YSIZE			(SCR_FIELDY + 2)
 #define MIN_LEV_FIELDX			3
@@ -766,27 +762,7 @@
 #define IS_DC_STEELWALL_2(e)	((e) >= EL_DC_STEELWALL_2_LEFT &&	\
 				 (e) <= EL_DC_STEELWALL_2_SINGLE)
 
-#if 1
-
-#if 1
 #define GFX_ELEMENT(e)		(element_info[e].gfx_element)
-#else
-#define GFX_ELEMENT(e)		(element_info[e].gfx_element ==		\
-				 (element_info[e].use_gfx_element ?	\
-				  element_info[e].gfx_element : e)  ?	\
-				 element_info[e].gfx_element :		\
-				 element_info[e].gfx_element +		\
-				 0 * printf("::: %d: %d <-> %d\n",	\
-					    e,				\
-					    element_info[e].gfx_element,      \
-					    element_info[e].use_gfx_element ? \
-					    element_info[e].gfx_element : e))
-#endif
-
-#else
-#define GFX_ELEMENT(e)		(element_info[e].use_gfx_element ?	\
-				 element_info[e].gfx_element : e)
-#endif
 
 /* !!! CHECK THIS !!! */
 #if 1
@@ -892,6 +868,8 @@
 
 #define IS_SPECIAL_GFX_ARG(a)	((a) >= 0 && (a) < NUM_SPECIAL_GFX_ARGS)
 
+#define IS_GLOBAL_ANIM_PART(a)	((a) >= 0 && (a) < NUM_GLOBAL_ANIM_PARTS)
+
 #define EL_CASCADE_ACTIVE(e)	(IS_EDITOR_CASCADE_INACTIVE(e) ? (e) + 1 : (e))
 #define EL_CASCADE_INACTIVE(e)	(IS_EDITOR_CASCADE_ACTIVE(e)   ? (e) - 1 : (e))
 #define EL_CASCADE_TOGGLE(e)	(IS_EDITOR_CASCADE_INACTIVE(e) ? (e) + 1 :    \
@@ -908,7 +886,6 @@
 #define BUTTON_ACTIVE(b)	(ActiveButton[b])
 #define FONT_ACTIVE(f)		(ActiveFont[f])
 
-
 /* fundamental game speed values */
 #define MICROLEVEL_SCROLL_DELAY	50	/* delay for scrolling micro level */
 #define MICROLEVEL_LABEL_DELAY	250	/* delay for micro level label */
@@ -947,21 +924,11 @@
 #define MAX_INITIAL_INVENTORY_SIZE	8
 
 /* often used screen positions */
-#if 0
-#define SX			8
-#define SY			8
-#define REAL_SX			(SX - 2)
-#define REAL_SY			(SY - 2)
-#define DX			566
-#define DY			60
-#define VX			DX
-#define VY			400
-#define EX			DX
-#define EY			(VY - 44)
-#endif
 #define TILESIZE		32
 #define TILEX			TILESIZE
 #define TILEY			TILESIZE
+#define TILEX_VAR		TILESIZE_VAR
+#define TILEY_VAR		TILESIZE_VAR
 #define MINI_TILESIZE		(TILESIZE / 2)
 #define MINI_TILEX		MINI_TILESIZE
 #define MINI_TILEY		MINI_TILESIZE
@@ -970,18 +937,9 @@
 #define MICRO_TILEY		MICRO_TILESIZE
 #define MIDPOSX			(SCR_FIELDX / 2)
 #define MIDPOSY			(SCR_FIELDY / 2)
-#define SXSIZE			(SCR_FIELDX * TILEX)
-#define SYSIZE			(SCR_FIELDY * TILEY)
-#define FXSIZE			((SCR_FIELDX + 2) * TILEX)
-#define FYSIZE			((SCR_FIELDY + 2) * TILEY)
-#define DXSIZE			100
-#define DYSIZE			280
-#define VXSIZE			DXSIZE
-#define VYSIZE			100
-#define EXSIZE			DXSIZE
-#define EYSIZE			(VYSIZE + 44)
-#define FULL_SXSIZE		(2 + SXSIZE + 2)
-#define FULL_SYSIZE		(2 + SYSIZE + 2)
+#define FXSIZE			((2 + SCR_FIELDX + 2) * TILEX_VAR)
+#define FYSIZE			((2 + SCR_FIELDY + 2) * TILEY_VAR)
+
 #define MICROLEVEL_XSIZE	((STD_LEV_FIELDX + 2) * MICRO_TILEX)
 #define MICROLEVEL_YSIZE	((STD_LEV_FIELDY + 2) * MICRO_TILEY)
 #define MICROLEVEL_XPOS		(SX + (SXSIZE - MICROLEVEL_XSIZE) / 2)
@@ -1807,9 +1765,17 @@
 #define ACTION_PAGE_30			81
 #define ACTION_PAGE_31			82
 #define ACTION_PAGE_32			83
-#define ACTION_OTHER			84
-
-#define NUM_ACTIONS			85
+#define ACTION_PART_1			84
+#define ACTION_PART_2			85
+#define ACTION_PART_3			86
+#define ACTION_PART_4			87
+#define ACTION_PART_5			88
+#define ACTION_PART_6			89
+#define ACTION_PART_7			90
+#define ACTION_PART_8			91
+#define ACTION_OTHER			92
+
+#define NUM_ACTIONS			93
 
 #define ACTION_BORING_LAST		ACTION_BORING_10
 #define ACTION_SLEEPING_LAST		ACTION_SLEEPING_3
@@ -1819,20 +1785,39 @@
 #define GFX_SPECIAL_ARG_DEFAULT		0
 #define GFX_SPECIAL_ARG_LOADING		1
 #define GFX_SPECIAL_ARG_TITLE_INITIAL	2
-#define GFX_SPECIAL_ARG_TITLE		3
-#define GFX_SPECIAL_ARG_MAIN		4
-#define GFX_SPECIAL_ARG_LEVELS		5
-#define GFX_SPECIAL_ARG_SCORES		6
-#define GFX_SPECIAL_ARG_EDITOR		7
-#define GFX_SPECIAL_ARG_INFO		8
-#define GFX_SPECIAL_ARG_SETUP		9
-#define GFX_SPECIAL_ARG_PLAYING		10
-#define GFX_SPECIAL_ARG_DOOR		11
-#define GFX_SPECIAL_ARG_PANEL		12
-#define GFX_SPECIAL_ARG_PREVIEW		13
-#define GFX_SPECIAL_ARG_CRUMBLED	14
-
-#define NUM_SPECIAL_GFX_ARGS		15
+#define GFX_SPECIAL_ARG_TITLE_INITIAL_1	3
+#define GFX_SPECIAL_ARG_TITLE_INITIAL_2	4
+#define GFX_SPECIAL_ARG_TITLE_INITIAL_3	5
+#define GFX_SPECIAL_ARG_TITLE_INITIAL_4	6
+#define GFX_SPECIAL_ARG_TITLE_INITIAL_5	7
+#define GFX_SPECIAL_ARG_TITLE		8
+#define GFX_SPECIAL_ARG_TITLE_1		9
+#define GFX_SPECIAL_ARG_TITLE_2		10
+#define GFX_SPECIAL_ARG_TITLE_3		11
+#define GFX_SPECIAL_ARG_TITLE_4		12
+#define GFX_SPECIAL_ARG_TITLE_5		13
+#define GFX_SPECIAL_ARG_MAIN		14
+#define GFX_SPECIAL_ARG_LEVELS		15
+#define GFX_SPECIAL_ARG_LEVELNR		16
+#define GFX_SPECIAL_ARG_SCORES		17
+#define GFX_SPECIAL_ARG_EDITOR		18
+#define GFX_SPECIAL_ARG_INFO		19
+#define GFX_SPECIAL_ARG_SETUP		20
+#define GFX_SPECIAL_ARG_PLAYING		21
+#define GFX_SPECIAL_ARG_DOOR		22
+#define GFX_SPECIAL_ARG_TAPE		23
+#define GFX_SPECIAL_ARG_PANEL		24
+#define GFX_SPECIAL_ARG_PREVIEW		25
+#define GFX_SPECIAL_ARG_CRUMBLED	26
+#define GFX_SPECIAL_ARG_MAINONLY	27
+#define GFX_SPECIAL_ARG_TYPENAME	28
+#define GFX_SPECIAL_ARG_SUBMENU		29
+#define GFX_SPECIAL_ARG_MENU		30
+#define GFX_SPECIAL_ARG_TOONS		31
+#define GFX_SPECIAL_ARG_FADING		32
+#define GFX_SPECIAL_ARG_QUIT		33
+
+#define NUM_SPECIAL_GFX_ARGS		34
 
 /* these additional definitions are currently only used for draw offsets */
 #define GFX_SPECIAL_ARG_INFO_MAIN	0
@@ -1847,6 +1832,8 @@
 #define NUM_SPECIAL_GFX_INFO_ARGS	8
 
 /* these additional definitions are currently only used for draw offsets */
+/* (must match SETUP_MODE_* values as defined in src/screens.c) */
+/* (should also match corresponding entries in src/conf_gfx.c) */
 #define GFX_SPECIAL_ARG_SETUP_MAIN		0
 #define GFX_SPECIAL_ARG_SETUP_GAME		1
 #define GFX_SPECIAL_ARG_SETUP_EDITOR		2
@@ -1854,15 +1841,17 @@
 #define GFX_SPECIAL_ARG_SETUP_SOUND		4
 #define GFX_SPECIAL_ARG_SETUP_ARTWORK		5
 #define GFX_SPECIAL_ARG_SETUP_INPUT		6
-#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS		7
-#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_1	8
-#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_2	9
-#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_3	10
-#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_4	11
-#define GFX_SPECIAL_ARG_SETUP_CHOOSE_ARTWORK	12
-#define GFX_SPECIAL_ARG_SETUP_CHOOSE_OTHER	13
+#define GFX_SPECIAL_ARG_SETUP_TOUCH		7
+#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS		8
+#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_1	9
+#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_2	10
+#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_3	11
+#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_4	12
+#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_5	13
+#define GFX_SPECIAL_ARG_SETUP_CHOOSE_ARTWORK	14
+#define GFX_SPECIAL_ARG_SETUP_CHOOSE_OTHER	15
 
-#define NUM_SPECIAL_GFX_SETUP_ARGS		14
+#define NUM_SPECIAL_GFX_SETUP_ARGS		16
 
 
 /* values for image configuration suffixes */
@@ -1892,30 +1881,40 @@
 #define GFX_ARG_DIGGABLE_LIKE		23
 #define GFX_ARG_BORDER_SIZE		24
 #define GFX_ARG_STEP_OFFSET		25
-#define GFX_ARG_STEP_DELAY		26
-#define GFX_ARG_DIRECTION		27
-#define GFX_ARG_POSITION		28
-#define GFX_ARG_DRAW_XOFFSET		29
-#define GFX_ARG_DRAW_YOFFSET		30
-#define GFX_ARG_DRAW_MASKED		31
-#define GFX_ARG_ANIM_DELAY_FIXED	32
-#define GFX_ARG_ANIM_DELAY_RANDOM	33
-#define GFX_ARG_POST_DELAY_FIXED	34
-#define GFX_ARG_POST_DELAY_RANDOM	35
-#define GFX_ARG_NAME			36
-#define GFX_ARG_SCALE_UP_FACTOR		37
-#define GFX_ARG_CLONE_FROM		38
-#define GFX_ARG_FADE_MODE		39
-#define GFX_ARG_FADE_DELAY		40
-#define GFX_ARG_POST_DELAY		41
-#define GFX_ARG_AUTO_DELAY		42
-#define GFX_ARG_ALIGN			43
-#define GFX_ARG_VALIGN			44
-#define GFX_ARG_SORT_PRIORITY		45
-#define GFX_ARG_CLASS			46
-#define GFX_ARG_STYLE			47
-
-#define NUM_GFX_ARGS			48
+#define GFX_ARG_STEP_XOFFSET		26
+#define GFX_ARG_STEP_YOFFSET		27
+#define GFX_ARG_STEP_DELAY		28
+#define GFX_ARG_DIRECTION		29
+#define GFX_ARG_POSITION		30
+#define GFX_ARG_DRAW_XOFFSET		31
+#define GFX_ARG_DRAW_YOFFSET		32
+#define GFX_ARG_DRAW_MASKED		33
+#define GFX_ARG_DRAW_ORDER		34
+#define GFX_ARG_INIT_DELAY_FIXED	35
+#define GFX_ARG_INIT_DELAY_RANDOM	36
+#define GFX_ARG_ANIM_DELAY_FIXED	37
+#define GFX_ARG_ANIM_DELAY_RANDOM	38
+#define GFX_ARG_POST_DELAY_FIXED	39
+#define GFX_ARG_POST_DELAY_RANDOM	40
+#define GFX_ARG_NAME			41
+#define GFX_ARG_SCALE_UP_FACTOR		42
+#define GFX_ARG_TILE_SIZE		43
+#define GFX_ARG_CLONE_FROM		44
+#define GFX_ARG_FADE_MODE		45
+#define GFX_ARG_FADE_DELAY		46
+#define GFX_ARG_POST_DELAY		47
+#define GFX_ARG_AUTO_DELAY		48
+#define GFX_ARG_ALIGN			49
+#define GFX_ARG_VALIGN			50
+#define GFX_ARG_SORT_PRIORITY		51
+#define GFX_ARG_CLASS			52
+#define GFX_ARG_STYLE			53
+#define GFX_ARG_ACTIVE_XOFFSET		54
+#define GFX_ARG_ACTIVE_YOFFSET		55
+#define GFX_ARG_PRESSED_XOFFSET		56
+#define GFX_ARG_PRESSED_YOFFSET		57
+
+#define NUM_GFX_ARGS			58
 
 
 /* values for sound configuration suffixes */
@@ -1955,64 +1954,92 @@
 #define FONT_ENVELOPE_2			19
 #define FONT_ENVELOPE_3			20
 #define FONT_ENVELOPE_4			21
-#define FONT_INPUT_1_ACTIVE		22
-#define FONT_INPUT_2_ACTIVE		23
-#define FONT_INPUT_1			24
-#define FONT_INPUT_2			25
-#define FONT_OPTION_OFF			26
-#define FONT_OPTION_ON			27
-#define FONT_VALUE_1			28
-#define FONT_VALUE_2			29
-#define FONT_VALUE_OLD			30
-#define FONT_LEVEL_NUMBER_ACTIVE	31
-#define FONT_LEVEL_NUMBER		32
-#define FONT_TAPE_RECORDER		33
-#define FONT_GAME_INFO			34
-#define FONT_INFO_ELEMENTS		35
-#define FONT_INFO_LEVELSET		36
-
-#define NUM_FONTS			37
+#define FONT_REQUEST			22
+#define FONT_INPUT_1_ACTIVE		23
+#define FONT_INPUT_2_ACTIVE		24
+#define FONT_INPUT_1			25
+#define FONT_INPUT_2			26
+#define FONT_OPTION_OFF_NARROW		27
+#define FONT_OPTION_OFF			28
+#define FONT_OPTION_ON_NARROW		29
+#define FONT_OPTION_ON			30
+#define FONT_VALUE_1			31
+#define FONT_VALUE_2			32
+#define FONT_VALUE_OLD			33
+#define FONT_VALUE_NARROW		34
+#define FONT_LEVEL_NUMBER_ACTIVE	35
+#define FONT_LEVEL_NUMBER		36
+#define FONT_TAPE_RECORDER		37
+#define FONT_GAME_INFO			38
+#define FONT_INFO_ELEMENTS		39
+#define FONT_INFO_LEVELSET		40
+
+#define NUM_FONTS			41
 #define NUM_INITIAL_FONTS		4
 
-#if 0
-#define FONT_ACTIVE(f)							  \
-	((f) == FONT_MENU_1		? FONT_MENU_1_ACTIVE		: \
-	 (f) == FONT_MENU_2		? FONT_MENU_2_ACTIVE		: \
-	 (f) == FONT_TEXT_1		? FONT_TEXT_1_ACTIVE		: \
-	 (f) == FONT_TEXT_2		? FONT_TEXT_2_ACTIVE		: \
-	 (f) == FONT_TEXT_3		? FONT_TEXT_3_ACTIVE		: \
-	 (f) == FONT_TEXT_4		? FONT_TEXT_4_ACTIVE		: \
-	 (f) == FONT_INPUT_1		? FONT_INPUT_1_ACTIVE		: \
-	 (f) == FONT_INPUT_2		? FONT_INPUT_2_ACTIVE		: \
-	 (f) == FONT_LEVEL_NUMBER	? FONT_LEVEL_NUMBER_ACTIVE	: \
-	 (f))
-#endif
+/* values for toon animation configuration */
+#define MAX_NUM_TOONS			20
+
+/* values for global animation configuration (must match those from main.c) */
+#define NUM_GLOBAL_ANIMS		8
+#define NUM_GLOBAL_ANIM_PARTS		8
+#define NUM_GLOBAL_ANIM_PARTS_ALL	(NUM_GLOBAL_ANIM_PARTS + 1)
+#define NUM_GLOBAL_ANIM_TOKENS		(2 * NUM_GLOBAL_ANIMS)
+
+#define GLOBAL_ANIM_ID_GRAPHIC_FIRST	0
+#define GLOBAL_ANIM_ID_GRAPHIC_LAST	7
+#define GLOBAL_ANIM_ID_CONTROL_FIRST	(NUM_GLOBAL_ANIMS + 0)
+#define GLOBAL_ANIM_ID_CONTROL_LAST	(NUM_GLOBAL_ANIMS + 7)
+
+#define GLOBAL_ANIM_ID_PART_FIRST	0
+#define GLOBAL_ANIM_ID_PART_LAST	7
+#define GLOBAL_ANIM_ID_PART_BASE	8
+
+/* values for global border graphics */
+#define IMG_GLOBAL_BORDER_FIRST		IMG_GLOBAL_BORDER
+#define IMG_GLOBAL_BORDER_LAST		IMG_GLOBAL_BORDER_PLAYING
 
 /* values for game_status (must match special image configuration suffixes) */
 #define GAME_MODE_DEFAULT		0
 #define GAME_MODE_LOADING		1
 #define GAME_MODE_TITLE_INITIAL		2
-#define GAME_MODE_TITLE			3
-#define GAME_MODE_MAIN			4
-#define GAME_MODE_LEVELS		5
-#define GAME_MODE_SCORES		6
-#define GAME_MODE_EDITOR		7
-#define GAME_MODE_INFO			8
-#define GAME_MODE_SETUP			9
-#define GAME_MODE_PLAYING		10
-#define GAME_MODE_PSEUDO_DOOR		11
-#define GAME_MODE_PSEUDO_PANEL		12
-#define GAME_MODE_PSEUDO_PREVIEW	13
-#define GAME_MODE_PSEUDO_CRUMBLED	14
-
-/* there are no special config file suffixes for these modes */
-#define GAME_MODE_PSEUDO_TYPENAME	15
-#define GAME_MODE_QUIT			16
+#define GAME_MODE_TITLE_INITIAL_1	3
+#define GAME_MODE_TITLE_INITIAL_2	4
+#define GAME_MODE_TITLE_INITIAL_3	5
+#define GAME_MODE_TITLE_INITIAL_4	6
+#define GAME_MODE_TITLE_INITIAL_5	7
+#define GAME_MODE_TITLE			8
+#define GAME_MODE_TITLE_1		9
+#define GAME_MODE_TITLE_2		10
+#define GAME_MODE_TITLE_3		11
+#define GAME_MODE_TITLE_4		12
+#define GAME_MODE_TITLE_5		13
+#define GAME_MODE_MAIN			14
+#define GAME_MODE_LEVELS		15
+#define GAME_MODE_LEVELNR		16
+#define GAME_MODE_SCORES		17
+#define GAME_MODE_EDITOR		18
+#define GAME_MODE_INFO			19
+#define GAME_MODE_SETUP			20
+#define GAME_MODE_PLAYING		21
+#define GAME_MODE_PSEUDO_DOOR		22
+#define GAME_MODE_PSEUDO_TAPE		23
+#define GAME_MODE_PSEUDO_PANEL		24
+#define GAME_MODE_PSEUDO_PREVIEW	25
+#define GAME_MODE_PSEUDO_CRUMBLED	26
+#define GAME_MODE_PSEUDO_MAINONLY	27
+#define GAME_MODE_PSEUDO_TYPENAME	28
+#define GAME_MODE_PSEUDO_SUBMENU	29
+#define GAME_MODE_PSEUDO_MENU		30
+#define GAME_MODE_PSEUDO_TOONS		31
+#define GAME_MODE_PSEUDO_FADING		32
+#define GAME_MODE_QUIT			33
+
+#define NUM_GAME_MODES			34
 
 /* special definitions currently only used for custom artwork configuration */
 #define MUSIC_PREFIX_BACKGROUND		0
 #define NUM_MUSIC_PREFIXES		1
-#define MAX_LEVELS			1000
 
 /* definitions for demo animation lists */
 #define HELPANIM_LIST_NEXT		-1
@@ -2020,49 +2047,24 @@
 
 
 /* program information and versioning definitions */
-#define PROGRAM_VERSION_MAJOR		3
-#define PROGRAM_VERSION_MINOR		3
+#define PROGRAM_VERSION_MAJOR		4
+#define PROGRAM_VERSION_MINOR		0
 #define PROGRAM_VERSION_PATCH		0
 #define PROGRAM_VERSION_BUILD		1
+#define PROGRAM_VERSION_EXTRA		""
 
 #define PROGRAM_TITLE_STRING		"Rocks'n'Diamonds"
 #define PROGRAM_AUTHOR_STRING		"Holger Schemel"
-#define PROGRAM_COPYRIGHT_STRING	"Copyright �1995-2010 by Holger Schemel"
 #define PROGRAM_EMAIL_STRING		"info at artsoft.org"
 #define PROGRAM_WEBSITE_STRING		"http://www.artsoft.org/"
-#define PROGRAM_GAME_BY_STRING		"A Game by Artsoft Entertainment"
-#define PROGRAM_UNIX_DATADIR_STRING	".rocksndiamonds"
-
-#if defined(CREATE_SPECIAL_EDITION_RND_JUE)
-#undef  PROGRAM_TITLE_STRING
-#define PROGRAM_TITLE_STRING		"R'n'D jue"
-#undef  PROGRAM_UNIX_DATADIR_STRING
-#define PROGRAM_UNIX_DATADIR_STRING	".rnd_jue"
-#endif
+#define PROGRAM_COPYRIGHT_STRING	"Copyright \xa9""1995-2016 by Holger Schemel"
+#define PROGRAM_COMPANY_STRING		"A Game by Artsoft Entertainment"
+
+#define PROGRAM_ICON_FILENAME		"RocksIcon32x32.png"
 
-#define ICON_TITLE_STRING		PROGRAM_TITLE_STRING
 #define COOKIE_PREFIX			"ROCKSNDIAMONDS"
-#define FILENAME_PREFIX			"Rocks"
-
-#define USERDATA_DIRECTORY_WIN32	PROGRAM_TITLE_STRING
-#define USERDATA_DIRECTORY_MACOSX	PROGRAM_TITLE_STRING
-#define USERDATA_DIRECTORY_UNIX		PROGRAM_UNIX_DATADIR_STRING
-#define USERDATA_DIRECTORY_DOS		"userdata"
-
-#if defined(PLATFORM_WIN32)
-#define USERDATA_DIRECTORY		USERDATA_DIRECTORY_WIN32
-#elif defined(PLATFORM_MACOSX)
-#define USERDATA_DIRECTORY		USERDATA_DIRECTORY_MACOSX
-#elif defined(PLATFORM_UNIX)
-#define USERDATA_DIRECTORY		USERDATA_DIRECTORY_UNIX
-#else
-#define USERDATA_DIRECTORY		USERDATA_DIRECTORY_DOS
-#endif
 
-#define X11_ICON_FILENAME		"rocks_icon.xbm"
-#define X11_ICONMASK_FILENAME		"rocks_iconmask.xbm"
-#define SDL_ICON_FILENAME		"rocks_icon_32x32.pcx"
-#define MSDOS_POINTER_FILENAME		"mouse.pcx"
+#define USERDATA_DIRECTORY_OTHER	"userdata"
 
 /* file version numbers for resource files (levels, tapes, score, setup, etc.)
 ** currently supported/known file version numbers:
@@ -2119,6 +2121,21 @@
 
 #define NUM_ENGINE_TYPES		4
 
+/* values for automatically playing tapes */
+#define AUTOPLAY_NONE			0
+#define AUTOPLAY_PLAY			(1 << 0)
+#define AUTOPLAY_FFWD			(1 << 1)
+#define AUTOPLAY_WARP			(1 << 2)
+#define AUTOPLAY_TEST			(1 << 3)
+#define AUTOPLAY_WARP_NO_DISPLAY	AUTOPLAY_TEST
+
+#define AUTOPLAY_MODE_NONE		0
+#define AUTOPLAY_MODE_PLAY		(AUTOPLAY_MODE_NONE | AUTOPLAY_PLAY)
+#define AUTOPLAY_MODE_FFWD		(AUTOPLAY_MODE_PLAY | AUTOPLAY_FFWD)
+#define AUTOPLAY_MODE_WARP		(AUTOPLAY_MODE_FFWD | AUTOPLAY_WARP)
+#define AUTOPLAY_MODE_TEST		(AUTOPLAY_MODE_WARP | AUTOPLAY_TEST)
+#define AUTOPLAY_MODE_WARP_NO_DISPLAY	AUTOPLAY_MODE_TEST
+
 
 struct BorderInfo
 {
@@ -2126,6 +2143,17 @@ struct BorderInfo
   boolean draw_masked_when_fading;
 };
 
+struct RequestButtonInfo
+{
+  struct TextPosInfo yes;
+  struct TextPosInfo no;
+  struct TextPosInfo confirm;
+  struct TextPosInfo player_1;
+  struct TextPosInfo player_2;
+  struct TextPosInfo player_3;
+  struct TextPosInfo player_4;
+};
+
 struct MenuMainButtonInfo
 {
   struct MenuPosInfo name;
@@ -2223,12 +2251,13 @@ struct MenuInfo
   int scrollbar_xoffset;
 
   int list_size[NUM_SPECIAL_GFX_ARGS];
+  int list_size_info[NUM_SPECIAL_GFX_INFO_ARGS];
 
   struct TitleFadingInfo enter_menu;
   struct TitleFadingInfo leave_menu;
   struct TitleFadingInfo enter_screen[NUM_SPECIAL_GFX_ARGS];
   struct TitleFadingInfo leave_screen[NUM_SPECIAL_GFX_ARGS];
-  struct TitleFadingInfo next_screen;
+  struct TitleFadingInfo next_screen[NUM_SPECIAL_GFX_ARGS];
 
   int sound[NUM_SPECIAL_GFX_ARGS];
   int music[NUM_SPECIAL_GFX_ARGS];
@@ -2238,6 +2267,17 @@ struct MenuInfo
 
 struct DoorInfo
 {
+  struct DoorPartPosInfo part_1;
+  struct DoorPartPosInfo part_2;
+  struct DoorPartPosInfo part_3;
+  struct DoorPartPosInfo part_4;
+  struct DoorPartPosInfo part_5;
+  struct DoorPartPosInfo part_6;
+  struct DoorPartPosInfo part_7;
+  struct DoorPartPosInfo part_8;
+
+  struct DoorPartPosInfo panel;
+
   int width;
   int height;
   int step_offset;
@@ -2245,6 +2285,23 @@ struct DoorInfo
   int anim_mode;
 };
 
+struct RequestInfo
+{
+  struct RequestButtonInfo button;
+  int x, y;
+  int width, height;
+  int border_size;
+  int line_spacing;
+  int step_offset;
+  int step_delay;
+  int anim_mode;
+  int align;
+  int valign;
+  boolean autowrap;
+  boolean centered;
+  boolean wrap_single_words;
+};
+
 struct PreviewInfo
 {
   int x, y;
@@ -2257,9 +2314,117 @@ struct PreviewInfo
   int anim_mode;
 };
 
+struct EditorTabsInfo
+{
+  int x;
+  int y;
+  int yoffset2;
+  int width;
+  int height;
+  int draw_xoffset;
+  int draw_yoffset;
+};
+
+struct EditorSettingsInfo
+{
+  struct MenuPosInfo headline;
+
+  struct XY element_graphic;
+  struct XY element_name;
+
+  struct EditorTabsInfo tabs;
+};
+
+struct EditorGadgetInfo
+{
+  int normal_spacing;
+  int small_spacing;
+  int tiny_spacing;
+  int line_spacing;
+  int text_spacing;
+  int tab_spacing;
+
+  struct Rect separator_line;
+};
+
+struct EditorButtonInfo
+{
+  struct XYTileSize prev_level;
+  struct XYTileSize next_level;
+
+  struct XYTileSize properties;
+  struct XYTileSize element_left;
+  struct XYTileSize element_middle;
+  struct XYTileSize element_right;
+  struct XYTileSize palette;
+
+  struct XYTileSize draw_single;
+  struct XYTileSize draw_connected;
+  struct XYTileSize draw_line;
+  struct XYTileSize draw_arc;
+  struct XYTileSize draw_rectangle;
+  struct XYTileSize draw_filled_box;
+  struct XYTileSize rotate_up;
+  struct XYTileSize draw_text;
+  struct XYTileSize flood_fill;
+  struct XYTileSize rotate_left;
+  struct XYTileSize zoom_level;
+  struct XYTileSize rotate_right;
+  struct XYTileSize draw_random;
+  struct XYTileSize grab_brush;
+  struct XYTileSize rotate_down;
+  struct XYTileSize pick_element;
+
+  struct XYTileSize ce_copy_from;
+  struct XYTileSize ce_copy_to;
+  struct XYTileSize ce_swap;
+  struct XYTileSize ce_copy;
+  struct XYTileSize ce_paste;
+
+  struct XYTileSize undo;
+  struct XYTileSize conf;
+  struct XYTileSize save;
+  struct XYTileSize clear;
+  struct XYTileSize test;
+  struct XYTileSize exit;
+};
+
+struct EditorInputInfo
+{
+  struct XY level_number;
+};
+
+struct EditorPaletteInfo
+{
+  int x, y;
+  int cols, rows;
+  int tile_size;
+  boolean show_as_separate_screen;
+  boolean show_on_element_buttons;
+
+  struct XYTileSize element_left;
+  struct XYTileSize element_middle;
+  struct XYTileSize element_right;
+};
+
+struct EditorDrawingAreaInfo
+{
+  int tile_size;
+};
+
+struct EditorInfo
+{
+  struct EditorSettingsInfo settings;
+  struct EditorGadgetInfo gadget;
+  struct EditorButtonInfo button;
+  struct EditorInputInfo input;
+  struct EditorPaletteInfo palette;
+  struct EditorDrawingAreaInfo drawingarea;
+};
+
 struct ViewportInfo
 {
-  struct RectWithBorder window;
+  struct RectWithBorder window[NUM_SPECIAL_GFX_ARGS];
   struct RectWithBorder playfield[NUM_SPECIAL_GFX_ARGS];
   struct RectWithBorder door_1[NUM_SPECIAL_GFX_ARGS];
   struct RectWithBorder door_2[NUM_SPECIAL_GFX_ARGS];
@@ -2413,6 +2578,7 @@ struct LevelInfo
   boolean use_time_orb_bug;	/* for compatibility with old levels */
   boolean instant_relocation;	/* no visual delay when relocating player */
   boolean shifted_relocation;	/* no level centering when relocating player */
+  boolean lazy_relocation;	/* only redraw off-screen player relocation */
   boolean can_pass_to_walkable;	/* player can pass to empty or walkable tile */
   boolean grow_into_diggable;	/* amoeba can grow into anything diggable */
   boolean auto_exit_sokoban;	/* automatically finish solved Sokoban levels */
@@ -2442,6 +2608,7 @@ struct GlobalInfo
   char *autoplay_leveldir;
   int autoplay_level[MAX_TAPES_PER_SET];
   boolean autoplay_all;
+  boolean autoplay_mode;
 
   char *convert_leveldir;
   int convert_level_nr;
@@ -2451,15 +2618,15 @@ struct GlobalInfo
   int num_toons;
 
   float frames_per_second;
-  boolean fps_slowdown;
-  int fps_slowdown_factor;
 
   /* global values for fading screens and masking borders */
   int border_status;
-#if 0
-  int fading_status;
-  int fading_type;
-#endif
+
+  /* values for global animations */
+  int anim_status;
+  int anim_status_next;
+
+  boolean use_envelope_request;
 };
 
 struct ElementChangeInfo
@@ -2573,7 +2740,7 @@ struct ElementInfo
 
   /* ---------- special element property values ---------- */
 
-  unsigned long properties[NUM_EP_BITFIELDS];	/* element base properties */
+  unsigned int properties[NUM_EP_BITFIELDS];	/* element base properties */
 
   boolean use_gfx_element;	/* use custom graphic element */
   int gfx_element_initial;	/* initial optional custom graphic element */
@@ -2661,9 +2828,23 @@ struct FontInfo
   				/* internal bitmap ID for special graphics */
 };
 
+struct GlobalAnimInfo
+{
+  char *token_name;		/* global animation token in config files */
+
+  /* global animation graphic and control definitions */
+  int graphic[NUM_GLOBAL_ANIM_PARTS_ALL][NUM_SPECIAL_GFX_ARGS];
+
+  /* global animation sound and music definitions */
+  int sound[NUM_GLOBAL_ANIM_PARTS_ALL][NUM_SPECIAL_GFX_ARGS];
+  int music[NUM_GLOBAL_ANIM_PARTS_ALL][NUM_SPECIAL_GFX_ARGS];
+};
+
 struct GraphicInfo
 {
-  Bitmap *bitmap;
+  Bitmap **bitmaps;		/* bitmaps in all required sizes */
+  Bitmap *bitmap;		/* bitmap in default size */
+
   int src_image_width;		/* scaled bitmap size, but w/o small images */
   int src_image_height;		/* scaled bitmap size, but w/o small images */
 
@@ -2690,21 +2871,31 @@ struct GraphicInfo
   int border_size;		/* border size for "crumbled" graphics */
 
   int scale_up_factor;		/* optional factor for scaling image up */
+  int tile_size;		/* optional explicitly defined tile size */
 
   int clone_from;		/* graphic for cloning *all* settings */
 
-  int anim_delay_fixed;		/* optional delay values for bored and   */
-  int anim_delay_random;	/* sleeping player animations (animation */
-  int post_delay_fixed;		/* intervall and following pause before  */
-  int post_delay_random;	/* next intervall (bored animation only) */
+  int init_delay_fixed;		/* optional initial delay values for global */
+  int init_delay_random;	/* animations (pause interval before start) */
+  int anim_delay_fixed;		/* optional delay values for bored/sleeping */
+  int anim_delay_random;	/* and global animations (animation length) */
+  int post_delay_fixed;		/* optional delay values after bored/global */
+  int post_delay_random;	/* animations (pause before next animation) */
 
   int step_offset;		/* optional step offset of toon animations */
+  int step_xoffset;		/* optional step offset of toon animations */
+  int step_yoffset;		/* optional step offset of toon animations */
   int step_delay;		/* optional step delay of toon animations */
+  int direction;		/* optional move direction of toon animations */
+  int position;			/* optional draw position of toon animations */
+  int x;			/* optional draw position of toon animations */
+  int y;			/* optional draw position of toon animations */
 
   int draw_xoffset;		/* optional offset for drawing font chars */
   int draw_yoffset;		/* optional offset for drawing font chars */
 
   int draw_masked;		/* optional setting for drawing envelope gfx */
+  int draw_order;		/* optional draw order for global animations */
 
   int fade_mode;		/* optional setting for drawing title screens */
   int fade_delay;		/* optional setting for drawing title screens */
@@ -2716,12 +2907,12 @@ struct GraphicInfo
   int class;
   int style;
 
-  boolean use_image_size;	/* use image size as default width and height */
+  int active_xoffset;
+  int active_yoffset;
+  int pressed_xoffset;
+  int pressed_yoffset;
 
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
-  Pixmap clip_mask;		/* single-graphic-only clip mask for X11 */
-  GC clip_gc;			/* single-graphic-only clip gc for X11 */
-#endif
+  boolean use_image_size;	/* use image size as default width and height */
 };
 
 struct SoundInfo
@@ -2792,17 +2983,17 @@ struct HelpAnimInfo
 };
 
 
-extern Bitmap		       *bitmap_db_store;
-extern Bitmap		       *bitmap_db_cross;
 extern Bitmap		       *bitmap_db_field;
 extern Bitmap		       *bitmap_db_panel;
-extern Bitmap		       *bitmap_db_door;
-extern Bitmap		       *bitmap_db_toons;
-extern Pixmap			tile_clipmask[];
+extern Bitmap		       *bitmap_db_door_1;
+extern Bitmap		       *bitmap_db_door_2;
+extern Bitmap		       *bitmap_db_store_1;
+extern Bitmap		       *bitmap_db_store_2;
 extern DrawBuffer	       *fieldbuffer;
 extern DrawBuffer	       *drawto_field;
 
 extern int			game_status;
+extern boolean			game_status_last_screen;
 extern boolean			level_editor_test_game;
 extern boolean			network_playing;
 
@@ -2813,13 +3004,6 @@ extern SDL_Thread	       *server_thread;
 
 extern int			key_joystick_mapping;
 
-#if 1
-extern boolean			redraw[MAX_LEV_FIELDX + 2][MAX_LEV_FIELDY + 2];
-#else
-extern boolean			redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
-#endif
-extern int			redraw_x1, redraw_y1;
-
 extern short			Feld[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 extern short			MovPos[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 extern short			MovDir[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
@@ -2864,17 +3048,27 @@ extern int			scroll_x, scroll_y;
 
 extern int			WIN_XSIZE, WIN_YSIZE;
 extern int			SCR_FIELDX, SCR_FIELDY;
-extern int			SX, SY;
 extern int			REAL_SX, REAL_SY;
+extern int			SX, SY;
 extern int			DX, DY;
 extern int			VX, VY;
 extern int			EX, EY;
 extern int			dDX, dDY;
+extern int			FULL_SXSIZE, FULL_SYSIZE;
+extern int			SXSIZE, SYSIZE;
+extern int			DXSIZE, DYSIZE;
+extern int			VXSIZE, VYSIZE;
+extern int			EXSIZE, EYSIZE;
+extern int			TILESIZE_VAR;
+
+extern int			FADE_SX, FADE_SY;
+extern int			FADE_SXSIZE, FADE_SYSIZE;
 
 extern int			FX, FY;
 extern int			ScrollStepSize;
 extern int			ScreenMovDir, ScreenMovPos, ScreenGfxPos;
 extern int			BorderElement;
+extern int			MenuFrameDelay;
 extern int			GameFrameDelay;
 extern int			FfwdFrameDelay;
 extern int			BX1, BY1;
@@ -2900,17 +3094,33 @@ extern struct BorderInfo	border;
 extern struct ViewportInfo	viewport;
 extern struct TitleFadingInfo	fading;
 extern struct TitleFadingInfo	fading_none;
+extern struct TitleFadingInfo	title_initial_first_default;
 extern struct TitleFadingInfo	title_initial_default;
+extern struct TitleFadingInfo	title_first_default;
 extern struct TitleFadingInfo	title_default;
+extern struct TitleMessageInfo	titlescreen_initial_first_default;
+extern struct TitleMessageInfo	titlescreen_initial_first[];
+extern struct TitleMessageInfo	titlescreen_initial_default;
+extern struct TitleMessageInfo	titlescreen_initial[];
+extern struct TitleMessageInfo	titlescreen_first_default;
+extern struct TitleMessageInfo	titlescreen_first[];
+extern struct TitleMessageInfo	titlescreen_default;
+extern struct TitleMessageInfo	titlescreen[];
+extern struct TitleMessageInfo	titlemessage_initial_first_default;
+extern struct TitleMessageInfo	titlemessage_initial_first[];
 extern struct TitleMessageInfo	titlemessage_initial_default;
 extern struct TitleMessageInfo	titlemessage_initial[];
+extern struct TitleMessageInfo	titlemessage_first_default;
+extern struct TitleMessageInfo	titlemessage_first[];
 extern struct TitleMessageInfo	titlemessage_default;
 extern struct TitleMessageInfo	titlemessage[];
 extern struct TitleMessageInfo	readme;
 extern struct InitInfo		init, init_last;
 extern struct MenuInfo		menu;
 extern struct DoorInfo		door_1, door_2;
+extern struct RequestInfo	request;
 extern struct PreviewInfo	preview;
+extern struct EditorInfo	editor;
 extern struct ElementInfo	element_info[];
 extern struct ElementNameInfo	element_name_info[];
 extern struct ElementActionInfo	element_action_info[];
@@ -2918,6 +3128,7 @@ extern struct ElementDirectionInfo element_direction_info[];
 extern struct SpecialSuffixInfo special_suffix_info[];
 extern struct TokenIntPtrInfo	image_config_vars[];
 extern struct FontInfo		font_info[];
+extern struct GlobalAnimInfo	global_anim_info[];
 extern struct MusicPrefixInfo	music_prefix_info[];
 extern struct GraphicInfo      *graphic_info;
 extern struct SoundInfo	       *sound_info;
diff --git a/src/netserv.c b/src/netserv.c
index ac1b71c..6555e04 100644
--- a/src/netserv.c
+++ b/src/netserv.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* netserv.c                                                *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// netserv.c
+// ============================================================================
 
 #include "libgame/platform.h"
 
@@ -20,16 +18,7 @@
 #include <signal.h>
 #include <errno.h>
 
-#if defined(TARGET_SDL)
 #include "main.h"
-#else
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <sys/select.h>			/* apparently needed for OS/2 port */
-#endif
 
 #include "libgame/libgame.h"
 
@@ -40,12 +29,7 @@ static int onceonly = 0;
 
 struct NetworkServerPlayerInfo
 {
-#if defined(TARGET_SDL)
   TCPsocket fd;
-#else
-  int fd;
-#endif
-
   char player_name[16];
   unsigned char number;
   struct NetworkServerPlayerInfo *next;
@@ -62,22 +46,15 @@ static struct NetworkServerPlayerInfo *first_player = NULL;
 
 #define NEXT(player) ((player)->next ? (player)->next : first_player)
 
-#if defined(TARGET_SDL)
 /* TODO: peer address */
 static TCPsocket lfd;		/* listening socket */
 static SDLNet_SocketSet fds;	/* socket set */
-#else
-static struct sockaddr_in saddr;
-static int lfd;			/* listening socket */
-static fd_set fds;		/* socket set */
-static int tcp = -1;
-#endif
 
 static unsigned char realbuffer[512], *buffer = realbuffer + 4;
 
 static int interrupt;
 
-static unsigned long ServerFrameCounter = 0;
+static unsigned int ServerFrameCounter = 0;
 
 static void addtobuffer(struct NetworkServerPlayerInfo *player,
 			unsigned char *b, int len)
@@ -94,11 +71,8 @@ static void flushuser(struct NetworkServerPlayerInfo *player)
 {
   if (player->nwrite)
   {
-#if defined(TARGET_SDL)
     SDLNet_TCP_Send(player->fd, player->writbuffer, player->nwrite);
-#else
-    write(player->fd, player->writbuffer, player->nwrite);
-#endif
+
     player->nwrite = 0;
   }
 }
@@ -145,12 +119,8 @@ static void RemovePlayer(struct NetworkServerPlayerInfo *player)
     }
   }
 
-#if defined(TARGET_SDL)
   SDLNet_TCP_DelSocket(fds, player->fd);
   SDLNet_TCP_Close(player->fd);
-#else
-  close(player->fd);
-#endif
 
   if (player->introduced)
   {
@@ -173,11 +143,7 @@ static void RemovePlayer(struct NetworkServerPlayerInfo *player)
   }
 }
 
-#if defined(TARGET_SDL)
 static void AddPlayer(TCPsocket fd)
-#else
-static void AddPlayer(int fd)
-#endif
 {
   struct NetworkServerPlayerInfo *player, *v;
   unsigned char nxn;
@@ -195,9 +161,7 @@ static void AddPlayer(int fd)
   player->action = 0;
   player->action_received = FALSE;
 
-#if defined(TARGET_SDL)
   SDLNet_TCP_AddSocket(fds, fd);
-#endif
 
   first_player = player;
 
@@ -222,11 +186,6 @@ static void AddPlayer(int fd)
   }
 
   player->number = nxn;
-#if !defined(TARGET_SDL)
-  if (options.verbose)
-    Error(ERR_NETWORK_SERVER, "client %d connecting from %s",
-	  nxn, inet_ntoa(saddr.sin_addr));
-#endif
   clients++;
 
   buffer[0] = 0;
@@ -471,15 +430,9 @@ static void Handle_OP_MOVE_PLAYER(struct NetworkServerPlayerInfo *player)
 
   broadcast(NULL, 6 + last_client_nr, 0);
 
-#if 0
-  Error(ERR_NETWORK_SERVER, "sending ServerFrameCounter value %d",
-	ServerFrameCounter);
-#endif
-
   ServerFrameCounter++;
 }
 
-#if defined(TARGET_SDL)
 /* the following is not used for a standalone server;
    the pointer points to an integer containing the port-number */
 int NetworkServerThread(void *ptr)
@@ -489,7 +442,6 @@ int NetworkServerThread(void *ptr)
   /* should never be reached */
   return 0;
 }
-#endif
 
 void NetworkServer(int port, int serveronly)
 {
@@ -497,15 +449,7 @@ void NetworkServer(int port, int serveronly)
   struct NetworkServerPlayerInfo *player;
   int r; 
   unsigned int len;
-#if defined(TARGET_SDL)
   IPaddress ip;
-#else
-  int i, on;
-  int is_daemon = 0;
-  struct protoent *tcpproto;
-  struct timeval tv;
-  int mfd;
-#endif
 
 #if defined(PLATFORM_UNIX) && !defined(PLATFORM_NEXT)
   struct sigaction sact;
@@ -517,11 +461,6 @@ void NetworkServer(int port, int serveronly)
   if (!serveronly)
     onceonly = 1;
 
-#if !defined(TARGET_SDL)
-  if ((tcpproto = getprotobyname("tcp")) != NULL)
-    tcp = tcpproto->p_proto;
-#endif
-
 #if defined(PLATFORM_UNIX)
 #if defined(PLATFORM_NEXT)
   signal(SIGPIPE, SIG_IGN);
@@ -533,15 +472,6 @@ void NetworkServer(int port, int serveronly)
 #endif
 #endif
 
-#if defined(TARGET_SDL)
-
-  /* assume that SDL is already initialized */
-#if 0
-  if (SDLNet_Init() == -1)
-    Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_Init() failed");
-  atexit(SDLNet_Quit);
-#endif
-
   if (SDLNet_ResolveHost(&ip, NULL, port) == -1)
     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_ResolveHost() failed");
 
@@ -552,49 +482,6 @@ void NetworkServer(int port, int serveronly)
   fds = SDLNet_AllocSocketSet(MAX_PLAYERS+1);
   SDLNet_TCP_AddSocket(fds, lfd);
 
-#else
-
-  if ((lfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
-    Error(ERR_EXIT_NETWORK_SERVER, "socket() failed");
-
-  saddr.sin_family = AF_INET;
-  saddr.sin_addr.s_addr = htonl(INADDR_ANY);
-  saddr.sin_port = htons(port);
-
-  on = 1;
-
-  setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(int));
-  if (bind(lfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
-    Error(ERR_EXIT_NETWORK_SERVER, "bind() failed");
-
-  listen(lfd, 5);
-#endif
-
-#if !defined(TARGET_SDL)
-  if (is_daemon)
-  {
-    /* become a daemon, breaking all ties with the controlling terminal */
-    options.verbose = FALSE;
-    for (i = 0; i < 255; i++)
-    {
-      if (i != lfd)
-	close(i);
-    }
-
-    if (fork())
-      exit(0);
-    setsid();
-    if (fork())
-      exit(0);
-    chdir("/");
-
-    /* open a fake stdin, stdout, stderr, just in case */
-    open("/dev/null", O_RDONLY);
-    open("/dev/null", O_WRONLY);
-    open("/dev/null", O_WRONLY);
-  }
-#endif
-
   if (options.verbose)
   {
     Error(ERR_NETWORK_SERVER, "started up, listening on port %d", port);
@@ -609,37 +496,13 @@ void NetworkServer(int port, int serveronly)
     for (player = first_player; player; player = player->next)
       flushuser(player);
 
-#if defined(TARGET_SDL)
     if ((sl = SDLNet_CheckSockets(fds, 500000)) < 1)
     {
-      Error(ERR_NETWORK_SERVER, SDLNet_GetError());
+      Error(ERR_NETWORK_SERVER, "SDLNet_CheckSockets failed: %s",
+	    SDLNet_GetError());
       perror("SDLNet_CheckSockets");
     }
 
-#else
-
-    FD_ZERO(&fds);
-    mfd = lfd;
-    player = first_player;
-    while (player)
-    {
-      FD_SET(player->fd, &fds);
-      if (player->fd > mfd)
-	mfd = player->fd;
-      player = player->next;
-    }
-    FD_SET(lfd, &fds);
-    tv.tv_sec = 0;
-    tv.tv_usec = 500000;
-    if ((sl = select(mfd + 1, &fds, NULL, NULL, &tv)) < 0)
-    {
-      if (errno != EINTR)
-	Error(ERR_EXIT_NETWORK_SERVER, "select() failed");
-      else
-	continue;
-    }
-#endif
-
     if (sl < 0)
       continue;
     
@@ -647,7 +510,6 @@ void NetworkServer(int port, int serveronly)
       continue;
 
     /* accept incoming connections */
-#if defined(TARGET_SDL)
     if (SDLNet_SocketReady(lfd))
     {
       TCPsocket newsock;
@@ -658,51 +520,15 @@ void NetworkServer(int port, int serveronly)
 	AddPlayer(newsock);
     }
 
-#else
-
-    if (FD_ISSET(lfd, &fds))
-    {
-      int newfd;
-      socklen_t slen;
-
-      slen = sizeof(saddr);
-      newfd = accept(lfd, (struct sockaddr *)&saddr, &slen);
-      if (newfd < 0)
-      {
-	if (errno != EINTR)
-	  Error(ERR_EXIT_NETWORK_SERVER, "accept() failed");
-      }
-      else
-      {
-	if (tcp != -1)
-	{
-	  on = 1;
-	  setsockopt(newfd, tcp, TCP_NODELAY, (char *)&on, sizeof(int));
-	}
-	AddPlayer(newfd);
-      }
-      continue;
-    }
-#endif
-
     player = first_player;
 
     do
     {
-#if defined(TARGET_SDL)
       if (SDLNet_SocketReady(player->fd))
-#else
-      if (FD_ISSET(player->fd, &fds))
-#endif
       {
-#if defined(TARGET_SDL)
 	/* read only 1 byte, because SDLNet blocks when we want more than is
 	   in the buffer */
 	r = SDLNet_TCP_Recv(player->fd, player->readbuffer + player->nread, 1);
-#else
-	r = read(player->fd, player->readbuffer + player->nread,
-		 MAX_BUFFER_SIZE - player->nread);
-#endif
 
 	if (r <= 0)
 	{
diff --git a/src/netserv.h b/src/netserv.h
index 69eeaef..53d9627 100644
--- a/src/netserv.h
+++ b/src/netserv.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* netserv.h                                                *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// netserv.h
+// ============================================================================
 
 #ifndef NETSERV_H
 #define NETSERV_H
@@ -38,10 +36,7 @@
 
 #define MAX_BUFFER_SIZE		4096
 
-#if defined(TARGET_SDL)
 int NetworkServerThread(void *);
-#endif
-
 void NetworkServer(int, int);
 
 #endif
diff --git a/src/network.c b/src/network.c
index fd98b62..56d6bc6 100644
--- a/src/network.c
+++ b/src/network.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* network.c                                                *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// network.c
+// ============================================================================
 
 #include "libgame/platform.h"
 
@@ -18,16 +16,7 @@
 #include <signal.h>
 #include <sys/time.h>
 
-#if defined(TARGET_SDL)
 #include "main.h"
-#else
-#include <sys/wait.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#endif
 
 #include "libgame/libgame.h"
 
@@ -55,12 +44,8 @@ static struct NetworkClientPlayerInfo first_player =
 
 /* server stuff */
 
-#if defined(TARGET_SDL)
 static TCPsocket sfd;		/* server socket */
 static SDLNet_SocketSet rfds;	/* socket set */
-#else
-static int sfd;			/* server socket */
-#endif
 
 static byte realbuffer[512];
 static byte readbuffer[MAX_BUFFER_SIZE], writbuffer[MAX_BUFFER_SIZE];
@@ -84,11 +69,7 @@ static void SendBufferToServer(int size)
   nwrite += 4 + size;
 
   /* directly send the buffer to the network server */
-#if defined(TARGET_SDL)
   SDLNet_TCP_Send(sfd, writbuffer, nwrite);
-#else
-  write(sfd, writbuffer, nwrite);
-#endif
   nwrite = 0;
 }
 
@@ -117,7 +98,7 @@ char *getNetworkPlayerName(int player_nr)
     return("you");
   else
     for (player = &first_player; player; player = player->next)
-      if (player->nr == player_nr && player->name && strlen(player->name))
+      if (player->nr == player_nr && strlen(player->name) > 0)
 	return(player->name);
 
   return(EMPTY_PLAYER_NAME);
@@ -125,37 +106,18 @@ char *getNetworkPlayerName(int player_nr)
 
 static void StartNetworkServer(int port)
 {
-#if defined(TARGET_SDL)
   static int p;
 
   p = port;
-  server_thread = SDL_CreateThread(NetworkServerThread, &p);
-  network_server = TRUE;
-
+#if defined(TARGET_SDL2)
+  server_thread = SDL_CreateThread(NetworkServerThread,
+				   "NetworkServerThread", &p);
 #else
-
-  switch (fork())
-  {
-    case 0:
-      NetworkServer(port, options.serveronly);
-
-      /* never reached */
-      exit(0);
-
-    case -1:
-      Error(ERR_WARN,
-	    "cannot create network server process - no network playing");
-      options.network = FALSE;
-      return;
-
-    default:
-      /* we are parent process -- resume normal operation */
-      return;
-  }
+  server_thread = SDL_CreateThread(NetworkServerThread, &p);
 #endif
+  network_server = TRUE;
 }
 
-#if defined(TARGET_SDL)
 boolean ConnectToServer(char *hostname, int port)
 {
   IPaddress ip;
@@ -212,72 +174,6 @@ boolean ConnectToServer(char *hostname, int port)
   return FALSE;
 }
 
-#else
-
-boolean ConnectToServer(char *hostname, int port)
-{
-  struct sockaddr_in s;
-  struct protoent *tcpproto;
-  int on = 1, i;
-
-  if (hostname)
-  {
-    if ((s.sin_addr.s_addr = inet_addr(hostname)) == -1)
-    {
-      struct hostent *host;
-
-      if ((host = gethostbyname(hostname)) == NULL)
-	Error(ERR_EXIT, "cannot locate host '%s'", hostname);
-
-      s.sin_addr = *(struct in_addr *)(host->h_addr_list[0]);
-    }
-  }
-  else
-    s.sin_addr.s_addr = inet_addr("127.0.0.1");		/* localhost */
-
-  if (port == 0)
-    port = DEFAULT_SERVER_PORT;
-
-  s.sin_port = htons(port);
-  s.sin_family = AF_INET;
-
-  sfd = socket(PF_INET, SOCK_STREAM, 0);
-  if (sfd < 0)
-    Error(ERR_EXIT, "out of file descriptors");
-
-  if ((tcpproto = getprotobyname("tcp")) != NULL)
-    setsockopt(sfd, tcpproto->p_proto, TCP_NODELAY, (char *)&on, sizeof(int));
-
-  if (connect(sfd, (struct sockaddr *)&s, sizeof(s)) == 0)	/* connected */
-    return TRUE;
-
-  if (hostname)	/* connect to specified server failed */
-    return FALSE;
-
-  printf("No rocksndiamonds server on localhost -- starting up one ...\n");
-  StartNetworkServer(port);
-
-  /* wait for server to start up and try connecting several times */
-  for (i = 0; i < 6; i++)
-  {
-    Delay(500);		/* wait 500 ms == 0.5 seconds */
-    close(sfd);
-
-    sfd = socket(PF_INET, SOCK_STREAM, 0);
-    if (sfd < 0)
-      Error(ERR_EXIT, "out of file descriptors");
-
-    setsockopt(sfd, tcpproto->p_proto, TCP_NODELAY, (char *)&on, sizeof(int));
-
-    if (connect(sfd, (struct sockaddr *)&s, sizeof(s)) >= 0)	/* connected */
-      return TRUE;
-  }
-
-  /* when reaching this point, connect to newly started server has failed */
-  return FALSE;
-}
-#endif	/* defined(TARGET_SDL) */
-
 void SendToServer_PlayerName(char *player_name)
 {
   int len_player_name = strlen(player_name);
@@ -308,7 +204,7 @@ void SendToServer_NrWanted(int nr_wanted)
 
 void SendToServer_StartPlaying()
 {
-  unsigned long new_random_seed = InitRND(level.random_seed);
+  unsigned int new_random_seed = InitRND(level.random_seed);
 
   int dummy = 0;		/* !!! HAS NO MEANING ANYMORE !!! */
 				/* the name of the level must be enough */
@@ -433,7 +329,7 @@ static void Handle_OP_NUMBER_WANTED()
   {
     char request[100];
 
-    sprintf(request, "Sorry ! Player %d already exists ! You are player %d !",
+    sprintf(request, "Sorry! Player %d already exists! You are player %d!",
 	    index_nr_wanted + 1, new_index_nr + 1);
 
     Request(request, REQ_CONFIRM);
@@ -502,12 +398,10 @@ static void Handle_OP_START_PLAYING()
 {
   LevelDirTree *new_leveldir;
   int new_level_nr;
-  int dummy;
-  unsigned long new_random_seed;
+  unsigned int new_random_seed;
   char *new_leveldir_identifier;
 
   new_level_nr = (buffer[2] << 8) + buffer[3];
-  dummy = (buffer[4] << 8) + buffer[5];			/* (obsolete) */
   new_random_seed =
     (buffer[6] << 24) | (buffer[7] << 16) | (buffer[8] << 8) | (buffer[9]);
   new_leveldir_identifier = (char *)&buffer[10];
@@ -567,10 +461,11 @@ static void Handle_OP_STOP_PLAYING()
     else if (buffer[2] == NETWORK_STOP_BY_ERROR)
       Request("Network game stopped due to internal error!", REQ_CONFIRM);
     else
-      Request("Network game stopped !", REQ_CONFIRM);
+      Request("Network game stopped!", REQ_CONFIRM);
   }
 
-  game_status = GAME_MODE_MAIN;
+  SetGameStatus(GAME_MODE_MAIN);
+
   DrawMainMenu();
 }
 
@@ -585,11 +480,6 @@ static void Handle_OP_MOVE_PLAYER(unsigned int len)
   server_frame_counter =
     (buffer[2] << 24) | (buffer[3] << 16) | (buffer[4] << 8) | (buffer[5]);
 
-#if 0
-  Error(ERR_NETWORK_CLIENT, "receiving server frame counter value %d [%d]",
-	server_frame_counter, FrameCounter);
-#endif
-
   if (server_frame_counter != FrameCounter)
   {
     Error(ERR_INFO, "client and servers frame counters out of sync");
@@ -690,43 +580,16 @@ static void HandleNetworkingMessages()
 
 void HandleNetworking()
 {
-#if !defined(TARGET_SDL)
-  static struct timeval tv = { 0, 0 };
-  fd_set rfds;
-#endif
   int r = 0;
 
   do
   {
-#if defined(TARGET_SDL)
     if ((r = SDLNet_CheckSockets(rfds, 1)) < 0)
       Error(ERR_EXIT, "HandleNetworking(): SDLNet_CheckSockets() failed");
 
-#else
-
-    FD_ZERO(&rfds);
-    FD_SET(sfd, &rfds);
-
-    r = select(sfd + 1, &rfds, NULL, NULL, &tv);
-
-    if (r < 0 && errno != EINTR)
-      Error(ERR_EXIT, "HandleNetworking(): select() failed");
-
-    if (r < 0)
-      FD_ZERO(&rfds);
-#endif
-
-#if defined(TARGET_SDL)
     if (r > 0)
-#else
-    if (FD_ISSET(sfd, &rfds))
-#endif
     {
-#if defined(TARGET_SDL)
       r = SDLNet_TCP_Recv(sfd, readbuffer + nread, 1);
-#else
-      r = read(sfd, readbuffer + nread, MAX_BUFFER_SIZE - nread);
-#endif
 
       if (r < 0)
 	Error(ERR_EXIT, "error reading from network server");
@@ -742,4 +605,4 @@ void HandleNetworking()
   while (r > 0);
 }
 
-#endif /* PLATFORM_UNIX */
+#endif /* NETWORK_AVALIABLE */
diff --git a/src/network.h b/src/network.h
index 569ad5b..23b3307 100644
--- a/src/network.h
+++ b/src/network.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* network.h                                                *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// network.h
+// ============================================================================
 
 #ifndef NETWORK_H
 #define NETWORK_H
diff --git a/src/screens.c b/src/screens.c
index de24626..a2f63bc 100644
--- a/src/screens.c
+++ b/src/screens.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* screens.c                                                *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// screens.c
+// ============================================================================
 
 #include "libgame/libgame.h"
 
@@ -20,7 +18,7 @@
 #include "editor.h"
 #include "files.h"
 #include "tape.h"
-#include "cartoons.h"
+#include "anim.h"
 #include "network.h"
 #include "init.h"
 #include "config.h"
@@ -38,6 +36,8 @@
 #define MAX_INFO_MODES			8
 
 /* screens on the setup screen */
+/* (must match GFX_SPECIAL_ARG_SETUP_* values as defined in src/main.h) */
+/* (should also match corresponding entries in src/conf_gfx.c) */
 #define SETUP_MODE_MAIN			0
 #define SETUP_MODE_GAME			1
 #define SETUP_MODE_EDITOR		2
@@ -45,26 +45,38 @@
 #define SETUP_MODE_SOUND		4
 #define SETUP_MODE_ARTWORK		5
 #define SETUP_MODE_INPUT		6
-#define SETUP_MODE_SHORTCUTS		7
-#define SETUP_MODE_SHORTCUTS_1		8
-#define SETUP_MODE_SHORTCUTS_2		9
-#define SETUP_MODE_SHORTCUTS_3		10
-#define SETUP_MODE_SHORTCUTS_4		11
-#define SETUP_MODE_SHORTCUTS_5		12
+#define SETUP_MODE_TOUCH		7
+#define SETUP_MODE_SHORTCUTS		8
+#define SETUP_MODE_SHORTCUTS_1		9
+#define SETUP_MODE_SHORTCUTS_2		10
+#define SETUP_MODE_SHORTCUTS_3		11
+#define SETUP_MODE_SHORTCUTS_4		12
+#define SETUP_MODE_SHORTCUTS_5		13
 
 /* sub-screens on the setup screen (generic) */
-#define SETUP_MODE_CHOOSE_ARTWORK	13
-#define SETUP_MODE_CHOOSE_OTHER		14
+#define SETUP_MODE_CHOOSE_ARTWORK	14
+#define SETUP_MODE_CHOOSE_OTHER		15
 
 /* sub-screens on the setup screen (specific) */
-#define SETUP_MODE_CHOOSE_GAME_SPEED	15
-#define SETUP_MODE_CHOOSE_SCREEN_MODE	16
+#define SETUP_MODE_CHOOSE_GAME_SPEED	16
 #define SETUP_MODE_CHOOSE_SCROLL_DELAY	17
-#define SETUP_MODE_CHOOSE_GRAPHICS	18
-#define SETUP_MODE_CHOOSE_SOUNDS	19
-#define SETUP_MODE_CHOOSE_MUSIC		20
-
-#define MAX_SETUP_MODES			21
+#define SETUP_MODE_CHOOSE_SNAPSHOT_MODE	18
+#define SETUP_MODE_CHOOSE_WINDOW_SIZE	19
+#define SETUP_MODE_CHOOSE_SCALING_TYPE	20
+#define SETUP_MODE_CHOOSE_RENDERING	21
+#define SETUP_MODE_CHOOSE_GRAPHICS	22
+#define SETUP_MODE_CHOOSE_SOUNDS	23
+#define SETUP_MODE_CHOOSE_MUSIC		24
+#define SETUP_MODE_CHOOSE_VOLUME_SIMPLE	25
+#define SETUP_MODE_CHOOSE_VOLUME_LOOPS	26
+#define SETUP_MODE_CHOOSE_VOLUME_MUSIC	27
+#define SETUP_MODE_CHOOSE_TOUCH_CONTROL	28
+#define SETUP_MODE_CHOOSE_MOVE_DISTANCE	29
+#define SETUP_MODE_CHOOSE_DROP_DISTANCE	30
+
+#define MAX_SETUP_MODES			31
+
+#define MAX_MENU_MODES			MAX(MAX_INFO_MODES, MAX_SETUP_MODES)
 
 /* for input setup functions */
 #define SETUPINPUT_SCREEN_POS_START	0
@@ -75,14 +87,30 @@
 /* for various menu stuff  */
 #define MENU_SCREEN_START_XPOS		1
 #define MENU_SCREEN_START_YPOS		2
-#define MENU_SCREEN_VALUE_XPOS		14
+#define MENU_SCREEN_VALUE_XPOS		(SCR_FIELDX - 3)
 #define MENU_SCREEN_MAX_XPOS		(SCR_FIELDX - 1)
 #define MENU_TITLE1_YPOS		8
 #define MENU_TITLE2_YPOS		46
-#define MAX_INFO_ELEMENTS_ON_SCREEN	10
+#define MENU_SCREEN_INFO_XSTART		16
+#define MENU_SCREEN_INFO_YSTART1	100
+#define MENU_SCREEN_INFO_YSTART2	128
+#define MENU_SCREEN_INFO_YSTEP		(TILEY + 4)
+#define MENU_SCREEN_INFO_YBOTTOM	(SYSIZE - 20)
+#define MENU_SCREEN_INFO_YSIZE		(MENU_SCREEN_INFO_YBOTTOM -	\
+					 MENU_SCREEN_INFO_YSTART2 -	\
+					 TILEY / 2)
+#define MAX_INFO_ELEMENTS_ON_SCREEN	128
+#define STD_INFO_ELEMENTS_ON_SCREEN	(MENU_SCREEN_INFO_YSIZE /	\
+					 MENU_SCREEN_INFO_YSTEP)
+#define NUM_INFO_ELEMENTS_FROM_CONF	\
+  (menu.list_size_info[GFX_SPECIAL_ARG_INFO_ELEMENTS] > 0 ?		\
+   menu.list_size_info[GFX_SPECIAL_ARG_INFO_ELEMENTS] :			\
+   MAX_MENU_ENTRIES_ON_SCREEN)
+#define NUM_INFO_ELEMENTS_ON_SCREEN	MIN(MIN(STD_INFO_ELEMENTS_ON_SCREEN, \
+                                                MAX_INFO_ELEMENTS_ON_SCREEN), \
+					    NUM_INFO_ELEMENTS_FROM_CONF)
 #define MAX_MENU_ENTRIES_ON_SCREEN	(SCR_FIELDY - MENU_SCREEN_START_YPOS)
-#define MAX_MENU_TEXT_LENGTH_BIG	(MENU_SCREEN_VALUE_XPOS -	\
-					 MENU_SCREEN_START_XPOS)
+#define MAX_MENU_TEXT_LENGTH_BIG	13
 #define MAX_MENU_TEXT_LENGTH_MEDIUM	(MAX_MENU_TEXT_LENGTH_BIG * 2)
 
 /* buttons and scrollbars identifiers */
@@ -138,15 +166,16 @@ static void CustomizeKeyboard(int);
 static void CalibrateJoystick(int);
 static void execSetupGame(void);
 static void execSetupGraphics(void);
+static void execSetupSound(void);
+static void execSetupTouch(void);
 static void execSetupArtwork(void);
 static void HandleChooseTree(int, int, int, int, int, TreeInfo **);
 
-static void DrawChooseLevel(void);
+static void DrawChooseLevelSet(void);
+static void DrawChooseLevelNr(void);
 static void DrawInfoScreen(void);
-static void DrawAndFadeInInfoScreen(int);
 static void DrawSetupScreen(void);
 
-static void DrawInfoScreenExt(int, int);
 static void DrawInfoScreen_NotAvailable(char *, char *);
 static void DrawInfoScreen_HelpAnim(int, int, boolean);
 static void DrawInfoScreen_HelpText(int, int, int, int);
@@ -159,6 +188,7 @@ static void HandleInfoScreen_Program(int);
 static void HandleInfoScreen_Version(int);
 
 static void MapScreenMenuGadgets(int);
+static void MapScreenGadgets(int);
 static void MapScreenTreeGadgets(TreeInfo *);
 
 static struct GadgetInfo *screen_gadget[NUM_SCREEN_GADGETS];
@@ -166,15 +196,97 @@ static struct GadgetInfo *screen_gadget[NUM_SCREEN_GADGETS];
 static int info_mode = INFO_MODE_MAIN;
 static int setup_mode = SETUP_MODE_MAIN;
 
-static TreeInfo *screen_modes = NULL;
-static TreeInfo *screen_mode_current = NULL;
+static TreeInfo *window_sizes = NULL;
+static TreeInfo *window_size_current = NULL;
+
+static TreeInfo *scaling_types = NULL;
+static TreeInfo *scaling_type_current = NULL;
+
+static TreeInfo *rendering_modes = NULL;
+static TreeInfo *rendering_mode_current = NULL;
 
 static TreeInfo *scroll_delays = NULL;
 static TreeInfo *scroll_delay_current = NULL;
 
+static TreeInfo *snapshot_modes = NULL;
+static TreeInfo *snapshot_mode_current = NULL;
+
 static TreeInfo *game_speeds = NULL;
 static TreeInfo *game_speed_current = NULL;
 
+static TreeInfo *volumes_simple = NULL;
+static TreeInfo *volume_simple_current = NULL;
+
+static TreeInfo *volumes_loops = NULL;
+static TreeInfo *volume_loops_current = NULL;
+
+static TreeInfo *volumes_music = NULL;
+static TreeInfo *volume_music_current = NULL;
+
+static TreeInfo *touch_controls = NULL;
+static TreeInfo *touch_control_current = NULL;
+
+static TreeInfo *move_distances = NULL;
+static TreeInfo *move_distance_current = NULL;
+
+static TreeInfo *drop_distances = NULL;
+static TreeInfo *drop_distance_current = NULL;
+
+static TreeInfo *level_number = NULL;
+static TreeInfo *level_number_current = NULL;
+
+static struct
+{
+  int value;
+  char *text;
+} window_sizes_list[] =
+{
+  {	50,	"50 %"				},
+  {	80,	"80 %"				},
+  {	90,	"90 %"				},
+  {	100,	"100 % (Default)"		},
+  {	110,	"110 %"				},
+  {	120,	"120 %"				},
+  {	130,	"130 %"				},
+  {	140,	"140 %"				},
+  {	150,	"150 %"				},
+  {	200,	"200 %"				},
+  {	250,	"250 %"				},
+  {	300,	"300 %"				},
+
+  {	-1,	NULL				},
+};
+
+static struct
+{
+  char *value;
+  char *text;
+} scaling_types_list[] =
+{
+  {	SCALING_QUALITY_NEAREST, "None"		},
+  {	SCALING_QUALITY_LINEAR,	 "Linear"	},
+  {	SCALING_QUALITY_BEST,	 "Anisotropic"	},
+
+  {	NULL,			 NULL		},
+};
+
+static struct
+{
+  char *value;
+  char *text;
+} rendering_modes_list[] =
+{
+  {	STR_SPECIAL_RENDERING_OFF,	"Off (May show artifacts, fast)" },
+  {	STR_SPECIAL_RENDERING_BITMAP,	"Bitmap/Texture mode (slower)"	 },
+#if DEBUG
+  // this mode may work under certain conditions, but does not work on Windows
+  {	STR_SPECIAL_RENDERING_TARGET,	"Target Texture mode (slower)"	 },
+#endif
+  {	STR_SPECIAL_RENDERING_DOUBLE,	"Double Texture mode (slower)"	 },
+
+  {	NULL,				 NULL				 },
+};
+
 static struct
 {
   int value;
@@ -225,6 +337,76 @@ static struct
   {	-1,	NULL				},
 };
 
+static struct
+{
+  char *value;
+  char *text;
+} snapshot_modes_list[] =
+{
+  {	STR_SNAPSHOT_MODE_OFF,			"Off"		},
+  {	STR_SNAPSHOT_MODE_EVERY_STEP,		"Every Step"	},
+  {	STR_SNAPSHOT_MODE_EVERY_MOVE,		"Every Move"	},
+  {	STR_SNAPSHOT_MODE_EVERY_COLLECT,	"Every Collect"	},
+
+  {	NULL,			 		NULL		},
+};
+
+static struct
+{
+  int value;
+  char *text;
+} volumes_list[] =
+{
+  {	0,	"0 %"				},
+  {	1,	"1 %"				},
+  {	2,	"2 %"				},
+  {	5,	"5 %"				},
+  {	10,	"10 %"				},
+  {	20,	"20 %"				},
+  {	30,	"30 %"				},
+  {	40,	"40 %"				},
+  {	50,	"50 %"				},
+  {	60,	"60 %"				},
+  {	70,	"70 %"				},
+  {	80,	"80 %"				},
+  {	90,	"90 %"				},
+  {	100,	"100 %"				},
+
+  {	-1,	NULL				},
+};
+
+static struct
+{
+  char *value;
+  char *text;
+} touch_controls_list[] =
+{
+  {	TOUCH_CONTROL_VIRTUAL_BUTTONS,	"Virtual Buttons"	},
+  {	TOUCH_CONTROL_WIPE_GESTURES,	"Wipe Gestures"		},
+  {	TOUCH_CONTROL_FOLLOW_FINGER,	"Follow Finger"		},
+
+  {	NULL,			 	NULL			},
+};
+
+static struct
+{
+  int value;
+  char *text;
+} distances_list[] =
+{
+  {	1,	"1 %"				},
+  {	2,	"2 %"				},
+  {	3,	"3 %"				},
+  {	4,	"4 %"				},
+  {	5,	"5 %"				},
+  {	10,	"10 %"				},
+  {	15,	"15 %"				},
+  {	20,	"20 %"				},
+  {	25,	"25 %"				},
+
+  {	-1,	NULL				},
+};
+
 #define DRAW_MODE(s)		((s) >= GAME_MODE_MAIN &&		\
 				 (s) <= GAME_MODE_SETUP ? (s) :		\
 				 (s) == GAME_MODE_PSEUDO_TYPENAME ?	\
@@ -274,10 +456,8 @@ static struct
 				    menu.list_size[game_status] :	\
 				    MAX_MENU_ENTRIES_ON_SCREEN)
 
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
-#define NUM_SCROLLBAR_BITMAPS		2
-static Bitmap *scrollbar_bitmap[NUM_SCROLLBAR_BITMAPS];
-#endif
+#define IN_VIS_MENU(x, y)	IN_FIELD(x, y, SCR_FIELDX,		\
+					 NUM_MENU_ENTRIES_ON_SCREEN)
 
 
 /* title display and control definitions */
@@ -285,12 +465,16 @@ static Bitmap *scrollbar_bitmap[NUM_SCROLLBAR_BITMAPS];
 #define MAX_NUM_TITLE_SCREENS	(2 * MAX_NUM_TITLE_IMAGES +		\
 				 2 * MAX_NUM_TITLE_MESSAGES)
 
+#define NO_DIRECT_LEVEL_SELECT	(-1)
+
+
 static int num_title_screens = 0;
 
 struct TitleControlInfo
 {
   boolean is_image;
   boolean initial;
+  boolean first;
   int local_nr;
   int sort_priority;
 };
@@ -346,9 +530,6 @@ static char *main_text_level_year		= NULL;
 static char *main_text_level_imported_from	= NULL;
 static char *main_text_level_imported_by	= NULL;
 static char *main_text_level_tested_by		= NULL;
-static char *main_text_title_1			= PROGRAM_TITLE_STRING;
-static char *main_text_title_2			= PROGRAM_COPYRIGHT_STRING;
-static char *main_text_title_3			= PROGRAM_GAME_BY_STRING;
 
 struct MainControlInfo
 {
@@ -498,19 +679,19 @@ static struct MainControlInfo main_controls[] =
   {
     MAIN_CONTROL_TITLE_1,
     NULL,				-1,
-    &menu.main.text.title_1,		&main_text_title_1,
+    &menu.main.text.title_1,		&setup.internal.program_title,
     NULL,				NULL,
   },
   {
     MAIN_CONTROL_TITLE_2,
     NULL,				-1,
-    &menu.main.text.title_2,		&main_text_title_2,
+    &menu.main.text.title_2,		&setup.internal.program_copyright,
     NULL,				NULL,
   },
   {
     MAIN_CONTROL_TITLE_3,
     NULL,				-1,
-    &menu.main.text.title_3,		&main_text_title_3,
+    &menu.main.text.title_3,		&setup.internal.program_company,
     NULL,				NULL,
   },
 
@@ -545,6 +726,13 @@ static int getTitleMessageGameMode(boolean initial)
   return (initial ? GAME_MODE_TITLE_INITIAL : GAME_MODE_TITLE);
 }
 
+static int getTitleAnimMode(struct TitleControlInfo *tci)
+{
+  int base = (tci->initial ? GAME_MODE_TITLE_INITIAL_1 : GAME_MODE_TITLE_1);
+
+  return base + tci->local_nr;
+}
+
 #if 0
 static int getTitleScreenBackground(boolean initial)
 {
@@ -642,49 +830,29 @@ static int getTitleMusic(struct TitleControlInfo *tci)
 static struct TitleFadingInfo getTitleFading(struct TitleControlInfo *tci)
 {
   boolean is_image = tci->is_image;
-  int initial = tci->initial;
+  boolean initial = tci->initial;
+  boolean first = tci->first;
   int nr = tci->local_nr;
+  struct TitleMessageInfo tmi;
   struct TitleFadingInfo ti;
 
-  if (is_image)
-  {
-    int graphic = getTitleScreenGraphic(nr, initial);
-
-    /* initialize fading control values to default title config settings */
-    ti = (initial ? title_initial_default : title_default);
-
-    /* override default settings with image config settings, if defined */
-    if (graphic_info[graphic].fade_mode != FADE_MODE_DEFAULT)
-      ti.fade_mode = graphic_info[graphic].fade_mode;
-    if (graphic_info[graphic].fade_delay > -1)
-      ti.fade_delay = graphic_info[graphic].fade_delay;
-    if (graphic_info[graphic].post_delay > -1)
-      ti.post_delay = graphic_info[graphic].post_delay;
-    if (graphic_info[graphic].auto_delay > -1)
-      ti.auto_delay = graphic_info[graphic].auto_delay;
-  }
-  else
-  {
-    if (initial)
-    {
-      ti.fade_mode  = titlemessage_initial[nr].fade_mode;
-      ti.fade_delay = titlemessage_initial[nr].fade_delay;
-      ti.post_delay = titlemessage_initial[nr].post_delay;
-      ti.auto_delay = titlemessage_initial[nr].auto_delay;
-    }
-    else
-    {
-      ti.fade_mode  = titlemessage[nr].fade_mode;
-      ti.fade_delay = titlemessage[nr].fade_delay;
-      ti.post_delay = titlemessage[nr].post_delay;
-      ti.auto_delay = titlemessage[nr].auto_delay;
-    }
-  }
-
-#if 0
-  if (ti.anim_mode == ANIM_NONE)
-    ti.fade_delay = ti.post_delay = 0;
-#endif
+  tmi = (is_image ? (initial ? (first ?
+				titlescreen_initial_first[nr] :
+				titlescreen_initial[nr])
+		             : (first ?
+				titlescreen_first[nr] :
+				titlescreen[nr]))
+	          : (initial ? (first ?
+				titlemessage_initial_first[nr] :
+				titlemessage_initial[nr])
+		             : (first ?
+				titlemessage_first[nr] :
+				titlemessage[nr])));
+
+  ti.fade_mode  = tmi.fade_mode;
+  ti.fade_delay = tmi.fade_delay;
+  ti.post_delay = tmi.post_delay;
+  ti.auto_delay = tmi.auto_delay;
 
   return ti;
 }
@@ -716,6 +884,8 @@ static void InitializeTitleControlsExt_AddTitleInfo(boolean is_image,
   title_controls[num_title_screens].local_nr = nr;
   title_controls[num_title_screens].sort_priority = sort_priority;
 
+  title_controls[num_title_screens].first = FALSE;	/* will be set later */
+
   num_title_screens++;
 }
 
@@ -729,12 +899,6 @@ static void InitializeTitleControls_CheckTitleInfo(boolean initial)
     Bitmap *bitmap = graphic_info[graphic].bitmap;
     int sort_priority = graphic_info[graphic].sort_priority;
 
-#if 0
-    /* skip images and messages (fonts!) when using forced custom graphics */
-    if (setup.override_level_graphics && !initial)
-      continue;
-#endif
-
     if (bitmap != NULL)
       InitializeTitleControlsExt_AddTitleInfo(TRUE, initial, i, sort_priority);
   }
@@ -745,12 +909,6 @@ static void InitializeTitleControls_CheckTitleInfo(boolean initial)
     char *filename = getLevelSetTitleMessageFilename(i, initial);
     int sort_priority = tmi->sort_priority;
 
-#if 0
-    /* skip images and messages (fonts!) when using forced custom graphics */
-    if (setup.override_level_graphics)
-      continue;
-#endif
-
     if (filename != NULL)
       InitializeTitleControlsExt_AddTitleInfo(FALSE, initial, i, sort_priority);
   }
@@ -760,11 +918,9 @@ static void InitializeTitleControls(boolean show_title_initial)
 {
   num_title_screens = 0;
 
-#if 1
   /* 1st step: initialize title screens for game start (only when starting) */
   if (show_title_initial)
     InitializeTitleControls_CheckTitleInfo(TRUE);
-#endif
 
   /* 2nd step: initialize title screens for current level set */
   InitializeTitleControls_CheckTitleInfo(FALSE);
@@ -772,6 +928,9 @@ static void InitializeTitleControls(boolean show_title_initial)
   /* sort title screens according to sort_priority and title number */
   qsort(title_controls, num_title_screens, sizeof(struct TitleControlInfo),
 	compareTitleControlInfo);
+
+  /* mark first title screen */
+  title_controls[0].first = TRUE;
 }
 
 static boolean visibleMenuPos(struct MenuPosInfo *pos)
@@ -815,13 +974,8 @@ static void InitializeMainControls()
     char *text                     = (mci->text  ? *mci->text  : NULL);
     char *input                    = (mci->input ? *mci->input : NULL);
     int button_graphic             = mci->button_graphic;
-#if 1
     int font_text                  = (pos_text  ? pos_text->font  : -1);
     int font_input                 = (pos_input ? pos_input->font : -1);
-#else
-    int font_text                  = mci->font_text;
-    int font_input                 = mci->font_input;
-#endif
 
     int font_text_width   = (font_text  != -1 ? getFontWidth(font_text)   : 0);
     int font_text_height  = (font_text  != -1 ? getFontHeight(font_text)  : 0);
@@ -841,47 +995,34 @@ static void InitializeMainControls()
 
     if (nr == MAIN_CONTROL_NAME)
     {
-#if 0
-      if (menu.main.input.name.x == -1)
-	menu.main.input.name.x = menu.main.text.name.x + text_width;
-      if (menu.main.input.name.y == -1)
-	menu.main.input.name.y = menu.main.text.name.y;
-#endif
-
-#if 1
       menu.main.input.name.width  = input_width;
       menu.main.input.name.height = input_height;
-#else
-      menu.main.input.name.width  = font_input_width * MAX_PLAYER_NAME_LEN;
-      menu.main.input.name.height = font_input_height;
-#endif
     }
 
     if (pos_button != NULL)		/* (x/y may be -1/-1 here) */
     {
-      if (pos_button->width == 0)
-	pos_button->width = button_width;
-      if (pos_button->height == 0)
-	pos_button->height = button_height;
+      pos_button->width  = button_width;
+      pos_button->height = button_height;
     }
 
     if (pos_text != NULL)		/* (x/y may be -1/-1 here) */
     {
-      /* calculate width for non-clickable text -- needed for text alignment */
-      boolean calculate_text_width = (pos_button == NULL && text != NULL);
+      /* calculate size for non-clickable text -- needed for text alignment */
+      boolean calculate_text_size = (pos_button == NULL && text != NULL);
+
+      if (pos_text->width == -1 || calculate_text_size)
+	pos_text->width = text_width;
+      if (pos_text->height == -1 || calculate_text_size)
+	pos_text->height = text_height;
 
       if (visibleMenuPos(pos_button))
       {
 	if (pos_text->x == -1)
 	  pos_text->x = pos_button->x + pos_button->width;
 	if (pos_text->y == -1)
-	  pos_text->y = pos_button->y;
+	  pos_text->y =
+	    pos_button->y + (pos_button->height - pos_text->height) / 2;
       }
-
-      if (pos_text->width == -1 || calculate_text_width)
-	pos_text->width = text_width;
-      if (pos_text->height == -1)
-	pos_text->height = text_height;
     }
 
     if (pos_input != NULL)		/* (x/y may be -1/-1 here) */
@@ -902,8 +1043,24 @@ static void InitializeMainControls()
   }
 }
 
+static void DrawPressedGraphicThruMask(int dst_x, int dst_y,
+				       int graphic, boolean pressed)
+{
+  struct GraphicInfo *g = &graphic_info[graphic];
+  Bitmap *src_bitmap;
+  int src_x, src_y;
+  int xoffset = (pressed ? g->pressed_xoffset : 0);
+  int yoffset = (pressed ? g->pressed_yoffset : 0);
+
+  getFixedGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
+
+  BlitBitmapMasked(src_bitmap, drawto, src_x + xoffset, src_y + yoffset,
+		   g->width, g->height, dst_x, dst_y);
+}
+
 static void DrawCursorAndText_Main_Ext(int nr, boolean active_text,
-				       boolean active_input)
+				       boolean active_input,
+				       boolean pressed_button)
 {
   int i;
 
@@ -919,13 +1076,8 @@ static void DrawCursorAndText_Main_Ext(int nr, boolean active_text,
       char *text                     = (mci->text  ? *mci->text  : NULL);
       char *input                    = (mci->input ? *mci->input : NULL);
       int button_graphic             = mci->button_graphic;
-#if 1
       int font_text                  = (pos_text  ? pos_text->font  : -1);
       int font_input                 = (pos_input ? pos_input->font : -1);
-#else
-      int font_text                  = mci->font_text;
-      int font_input                 = mci->font_input;
-#endif
 
       if (active_text)
       {
@@ -945,7 +1097,7 @@ static void DrawCursorAndText_Main_Ext(int nr, boolean active_text,
 	int y = mSY + pos->y;
 
 	DrawBackgroundForGraphic(x, y, pos->width, pos->height, button_graphic);
-	DrawGraphicThruMaskExt(drawto, x, y, button_graphic, 0);
+	DrawPressedGraphicThruMask(x, y, button_graphic, pressed_button);
       }
 
       if (visibleTextPos(pos_text) && text != NULL)
@@ -977,15 +1129,17 @@ static void DrawCursorAndText_Main_Ext(int nr, boolean active_text,
   }
 }
 
-static void DrawCursorAndText_Main(int nr, boolean active_text)
+static void DrawCursorAndText_Main(int nr, boolean active_text,
+				   boolean pressed_button)
 {
-  DrawCursorAndText_Main_Ext(nr, active_text, FALSE);
+  DrawCursorAndText_Main_Ext(nr, active_text, FALSE, pressed_button);
 }
 
 #if 0
-static void DrawCursorAndText_Main_Input(int nr, boolean active_text)
+static void DrawCursorAndText_Main_Input(int nr, boolean active_text,
+					 boolean pressed_button)
 {
-  DrawCursorAndText_Main_Ext(nr, active_text, TRUE);
+  DrawCursorAndText_Main_Ext(nr, active_text, TRUE, pressed_button);
 }
 #endif
 
@@ -1020,17 +1174,63 @@ static boolean insideTextPosRect(struct TextPosInfo *rect, int x, int y)
   int rect_x = ALIGNED_TEXT_XPOS(rect);
   int rect_y = ALIGNED_TEXT_YPOS(rect);
 
+#if 0
+  printf("::: insideTextPosRect: (%d, %d), (%d, %d) [%d, %d] (%d, %d) => %d\n",
+	 x, y, rect_x, rect_y, rect->x, rect->y, rect->width, rect->height,
+	 (x >= rect_x && x < rect_x + rect->width &&
+	  y >= rect_y && y < rect_y + rect->height));
+#endif
+
   return (x >= rect_x && x < rect_x + rect->width &&
 	  y >= rect_y && y < rect_y + rect->height);
 }
 
+static boolean insidePreviewRect(struct PreviewInfo *preview, int x, int y)
+{
+  int rect_width  = preview->xsize * preview->tile_size;
+  int rect_height = preview->ysize * preview->tile_size;
+  int rect_x = ALIGNED_XPOS(preview->x, rect_width,  preview->align);
+  int rect_y = ALIGNED_YPOS(preview->y, rect_height, preview->valign);
+
+  return (x >= rect_x && x < rect_x + rect_width &&
+	  y >= rect_y && y < rect_y + rect_height);
+}
+
+static void AdjustScrollbar(int id, int items_max, int items_visible,
+			    int item_position)
+{
+  struct GadgetInfo *gi = screen_gadget[id];
+
+  if (item_position > items_max - items_visible)
+    item_position = items_max - items_visible;
+
+  ModifyGadget(gi, GDI_SCROLLBAR_ITEMS_MAX, items_max,
+	       GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible,
+	       GDI_SCROLLBAR_ITEM_POSITION, item_position, GDI_END);
+}
+
+static void AdjustChooseTreeScrollbar(int id, int first_entry, TreeInfo *ti)
+{
+  AdjustScrollbar(id, numTreeInfoInGroup(ti), NUM_MENU_ENTRIES_ON_SCREEN,
+		  first_entry);
+}
+
+static void clearMenuListArea()
+{
+  int scrollbar_xpos = mSX + SC_SCROLLBAR_XPOS + menu.scrollbar_xoffset;
+
+  /* correct scrollbar position if placed outside menu (playfield) area */
+  if (scrollbar_xpos > SX + SC_SCROLLBAR_XPOS)
+    scrollbar_xpos = SX + SC_SCROLLBAR_XPOS;
+
+  /* clear menu list area, but not title or scrollbar */
+  DrawBackground(mSX, mSY + MENU_SCREEN_START_YPOS * 32,
+                 scrollbar_xpos - mSX, NUM_MENU_ENTRIES_ON_SCREEN * 32);
+}
+
 static void drawCursorExt(int xpos, int ypos, boolean active, int graphic)
 {
-#if 1
   static int cursor_array[MAX_LEV_FIELDY];
-#else
-  static int cursor_array[SCR_FIELDY];
-#endif
   int x = mSX + TILEX * xpos;
   int y = mSY + TILEY * (MENU_SCREEN_START_YPOS + ypos);
 
@@ -1046,7 +1246,7 @@ static void drawCursorExt(int xpos, int ypos, boolean active, int graphic)
     graphic = BUTTON_ACTIVE(graphic);
 
   DrawBackgroundForGraphic(x, y, TILEX, TILEY, graphic);
-  DrawGraphicThruMaskExt(drawto, x, y, graphic, 0);
+  DrawFixedGraphicThruMaskExt(drawto, x, y, graphic, 0);
 }
 
 static void initCursor(int ypos, int graphic)
@@ -1066,52 +1266,14 @@ static void drawCursorXY(int xpos, int ypos, int graphic)
 
 static void drawChooseTreeCursor(int ypos, boolean active)
 {
-  int last_game_status = game_status;	/* save current game status */
-
-#if 0
-  /* force LEVELS draw offset on artwork setup screen */
-  game_status = GAME_MODE_LEVELS;
-#endif
-
   drawCursorExt(0, ypos, active, -1);
-
-  game_status = last_game_status;	/* restore current game status */
 }
 
 void DrawHeadline()
 {
-  DrawTextSCentered(MENU_TITLE1_YPOS, FONT_TITLE_1, PROGRAM_TITLE_STRING);
-  DrawTextSCentered(MENU_TITLE2_YPOS, FONT_TITLE_2, PROGRAM_COPYRIGHT_STRING);
-}
-
-#if 0
-static int getPrevlevelButtonPos()
-{
-  return 10;
-}
-
-static int getCurrentLevelTextPos()
-{
-  return (getPrevlevelButtonPos() + 1);
-}
-
-static int getNextLevelButtonPos()
-{
-  return getPrevlevelButtonPos() + 3 + 1;
-}
-
-static int getLevelRangeTextPos()
-{
-  return getNextLevelButtonPos() + 1;
-}
-#endif
-
-int effectiveGameStatus()
-{
-  if (game_status == GAME_MODE_INFO && info_mode == INFO_MODE_TITLE)
-    return GAME_MODE_TITLE;
-
-  return game_status;
+  DrawTextSCentered(MENU_TITLE1_YPOS, FONT_TITLE_1, getProgramTitleString());
+  DrawTextSCentered(MENU_TITLE2_YPOS, FONT_TITLE_2,
+		    setup.internal.program_copyright);
 }
 
 void DrawTitleScreenImage(int nr, boolean initial)
@@ -1151,10 +1313,7 @@ void DrawTitleScreenImage(int nr, boolean initial)
   ClearRectangleOnBackground(drawto, 0, 0, WIN_XSIZE, WIN_YSIZE);
 
   if (DrawingOnBackground(dst_x, dst_y))
-  {
-    SetClipOrigin(bitmap, bitmap->stored_clip_gc, dst_x - src_x, dst_y - src_y);
     BlitBitmapMasked(bitmap, drawto, src_x, src_y, width, height, dst_x, dst_y);
-  }
   else
     BlitBitmap(bitmap, drawto, src_x, src_y, width, height, dst_x, dst_y);
 
@@ -1165,13 +1324,20 @@ void DrawTitleScreenMessage(int nr, boolean initial)
 {
   char *filename = getLevelSetTitleMessageFilename(nr, initial);
   struct TitleMessageInfo *tmi = getTitleMessageInfo(nr, initial);
-  int last_game_status = game_status;	/* save current game status */
 
   if (filename == NULL)
     return;
 
   /* force TITLE font on title message screen */
-  game_status = getTitleMessageGameMode(initial);
+  SetFontStatus(getTitleMessageGameMode(initial));
+
+  /* if chars *and* width set to "-1", automatically determine width */
+  if (tmi->chars == -1 && tmi->width == -1)
+    tmi->width = viewport.window[game_status].width;
+
+  /* if lines *and* height set to "-1", automatically determine height */
+  if (tmi->lines == -1 && tmi->height == -1)
+    tmi->height = viewport.window[game_status].height;
 
   /* if chars set to "-1", automatically determine by text and font width */
   if (tmi->chars == -1)
@@ -1185,6 +1351,14 @@ void DrawTitleScreenMessage(int nr, boolean initial)
   else
     tmi->height = tmi->lines * getFontHeight(tmi->font);
 
+  /* if x set to "-1", automatically determine by width and alignment */
+  if (tmi->x == -1)
+    tmi->x = -1 * ALIGNED_XPOS(0, tmi->width, tmi->align);
+
+  /* if y set to "-1", automatically determine by height and alignment */
+  if (tmi->y == -1)
+    tmi->y = -1 * ALIGNED_YPOS(0, tmi->height, tmi->valign);
+
   SetDrawBackgroundMask(REDRAW_ALL);
   SetWindowBackgroundImage(getTitleBackground(nr, initial, FALSE));
 
@@ -1194,20 +1368,14 @@ void DrawTitleScreenMessage(int nr, boolean initial)
 	       filename, tmi->font, tmi->chars, -1, tmi->lines, 0, -1,
 	       tmi->autowrap, tmi->centered, tmi->parse_comments);
 
-  game_status = last_game_status;	/* restore current game status */
+  ResetFontStatus();
 }
 
 void DrawTitleScreen()
 {
   KeyboardAutoRepeatOff();
 
-#if 0
-  SetMainBackgroundImage(IMG_BACKGROUND_TITLE);
-#endif
-
   HandleTitleScreen(0, 0, 0, 0, MB_MENU_INITIALIZE);
-
-  StopAnimation();
 }
 
 boolean CheckTitleScreen(boolean levelset_has_changed)
@@ -1227,24 +1395,26 @@ boolean CheckTitleScreen(boolean levelset_has_changed)
   return (show_titlescreen && num_title_screens > 0);
 }
 
-void DrawMainMenuExt(int fade_mask, boolean do_fading)
+void DrawMainMenu()
 {
   static LevelDirTree *leveldir_last_valid = NULL;
   boolean levelset_has_changed = FALSE;
+  int fade_mask = REDRAW_FIELD;
+
+  LimitScreenUpdates(FALSE);
 
   FadeSetLeaveScreen();
 
   /* do not fade out here -- function may continue and fade on editor screen */
 
   UnmapAllGadgets();
-  FadeSoundsAndMusic();
+  FadeMenuSoundsAndMusic();
+
+  ExpireSoundLoops(FALSE);
 
   KeyboardAutoRepeatOn();
   ActivateJoystick();
 
-  SetDrawDeactivationMask(REDRAW_NONE);
-  SetDrawBackgroundMask(REDRAW_FIELD);
-
   audio.sound_deactivated = FALSE;
 
   GetPlayerConfig();
@@ -1252,14 +1422,18 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading)
   /* needed if last screen was the playing screen, invoked from level editor */
   if (level_editor_test_game)
   {
-    game_status = GAME_MODE_EDITOR;
+    CloseDoor(DOOR_CLOSE_ALL);
+
+    SetGameStatus(GAME_MODE_EDITOR);
+
     DrawLevelEd();
 
     return;
   }
 
   /* needed if last screen was the setup screen and fullscreen state changed */
-  ToggleFullscreenIfNeeded();
+  // (moved to "execSetupGraphics()" to change fullscreen state directly)
+  // ToggleFullscreenOrChangeWindowScalingIfNeeded();
 
   /* leveldir_current may be invalid (level group, parent link) */
   if (!validLevelSeries(leveldir_current))
@@ -1276,37 +1450,27 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading)
   /* needed if last screen (level choice) changed graphics, sounds or music */
   ReloadCustomArtwork(0);
 
+  if (CheckTitleScreen(levelset_has_changed))
+  {
+    SetGameStatus(GAME_MODE_TITLE);
+
+    DrawTitleScreen();
+
+    return;
+  }
+
   if (redraw_mask & REDRAW_ALL)
     fade_mask = REDRAW_ALL;
 
-#if 1
-  FadeOut(fade_mask);
+  if (CheckIfGlobalBorderHasChanged())
+    fade_mask = REDRAW_ALL;
 
-  /* needed if last screen was the editor screen */
-  UndrawSpecialEditorDoor();
-#if 0
-  if (fade_mask == REDRAW_FIELD)
-    BackToFront();
-#endif
-#endif
+  FadeOut(fade_mask);
 
-#if 1
   /* needed if different viewport properties defined for menues */
   ChangeViewportPropertiesIfNeeded();
-#endif
-
-#if defined(TARGET_SDL)
-  SetDrawtoField(DRAW_BACKBUFFER);
-#endif
-
-  if (CheckTitleScreen(levelset_has_changed))
-  {
-    game_status = GAME_MODE_TITLE;
-
-    DrawTitleScreen();
 
-    return;
-  }
+  SetDrawtoField(DRAW_TO_BACKBUFFER);
 
   /* level_nr may have been set to value over handicap with level editor */
   if (setup.handicap && level_nr > leveldir_current->handicap_level)
@@ -1315,25 +1479,23 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading)
   LoadLevel(level_nr);
   LoadScore(level_nr);
 
+  // set this after "ChangeViewportPropertiesIfNeeded()" (which may reset it)
+  SetDrawDeactivationMask(REDRAW_NONE);
+  SetDrawBackgroundMask(REDRAW_FIELD);
+
   SetMainBackgroundImage(IMG_BACKGROUND_MAIN);
 
-#if 1
+#if 0
   if (fade_mask == REDRAW_ALL)
-  {
-    // int door_state = GetDoorState();
-
-    RedrawBackground();
-
-    // OpenDoor(door_state | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
-  }
+    RedrawGlobalBorder();
 #endif
 
   ClearField();
 
   InitializeMainControls();
 
-  DrawCursorAndText_Main(-1, FALSE);
-  DrawPreviewLevel(TRUE);
+  DrawCursorAndText_Main(-1, FALSE, FALSE);
+  DrawPreviewLevelInitial();
 
   HandleMainMenu(0, 0, 0, 0, MB_MENU_INITIALIZE);
 
@@ -1342,8 +1504,7 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading)
     LoadTape(level_nr);
   DrawCompleteVideoDisplay();
 
-  PlayMenuSound();
-  PlayMenuMusic();
+  PlayMenuSoundsAndMusic();
 
   /* create gadgets for main menu screen */
   FreeScreenGadgets();
@@ -1353,50 +1514,31 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading)
   MapTapeButtons();
   MapScreenMenuGadgets(SCREEN_MASK_MAIN);
 
-#if 1
-  if (fade_mask == REDRAW_ALL)
-  {
-    int door_state = GetDoorState();
-
-    // RedrawBackground();
+  /* copy actual game door content to door double buffer for OpenDoor() */
+  BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0);
+  BlitBitmap(drawto, bitmap_db_door_2, VX, VY, VXSIZE, VYSIZE, 0, 0);
 
-    OpenDoor(door_state | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
-  }
-#endif
+  OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
 
-  DrawMaskedBorder(REDRAW_ALL);
+  DrawMaskedBorder(fade_mask);
 
   FadeIn(fade_mask);
   FadeSetEnterMenu();
 
-#if 1
   /* update screen area with special editor door */
   redraw_mask |= REDRAW_ALL;
   BackToFront();
-#endif
 
   SetMouseCursor(CURSOR_DEFAULT);
 
-  InitAnimation();
-
   OpenDoor(DOOR_CLOSE_1 | DOOR_OPEN_2);
 }
 
-void DrawAndFadeInMainMenu(int fade_mask)
-{
-  DrawMainMenuExt(fade_mask, TRUE);
-}
-
-void DrawMainMenu()
-{
-  DrawMainMenuExt(REDRAW_ALL, FALSE);
-}
-
-#if defined(CREATE_SPECIAL_EDITION_RND_JUE)
 static void gotoTopLevelDir()
 {
-  /* move upwards to top level directory */
-  while (leveldir_current->node_parent)
+  /* move upwards until inside (but not above) top level directory */
+  while (leveldir_current->node_parent &&
+	 !strEqual(leveldir_current->node_parent->subdir, STRING_TOP_DIRECTORY))
   {
     /* write a "path" into level tree for easy navigation to last level */
     if (leveldir_current->node_parent->node_group->cl_first == -1)
@@ -1421,19 +1563,14 @@ static void gotoTopLevelDir()
     leveldir_current = leveldir_current->node_parent;
   }
 }
-#endif
 
 void HandleTitleScreen(int mx, int my, int dx, int dy, int button)
 {
-  static unsigned long title_delay = 0;
+  static unsigned int title_delay = 0;
   static int title_screen_nr = 0;
   static int last_sound = -1, last_music = -1;
   boolean return_to_main_menu = FALSE;
-  boolean use_fading_main_menu = TRUE;
   struct TitleControlInfo *tci;
-  struct TitleFadingInfo fading_default;
-  struct TitleFadingInfo fading_last = fading;
-  struct TitleFadingInfo fading_next;
   int sound, music;
 
   if (button == MB_MENU_INITIALIZE)
@@ -1442,51 +1579,50 @@ void HandleTitleScreen(int mx, int my, int dx, int dy, int button)
     title_screen_nr = 0;
     tci = &title_controls[title_screen_nr];
 
+    SetAnimStatus(getTitleAnimMode(tci));
+
     last_sound = SND_UNDEFINED;
     last_music = MUS_UNDEFINED;
 
-    if (game_status == GAME_MODE_INFO)
+    if (num_title_screens != 0)
+    {
+      FadeSetEnterScreen();
+
+      /* use individual title fading instead of global "enter screen" fading */
+      fading = getTitleFading(tci);
+    }
+
+    if (game_status_last_screen == GAME_MODE_INFO)
     {
       if (num_title_screens == 0)
       {
+	/* switch game mode from title screen mode back to info screen mode */
+	SetGameStatus(GAME_MODE_INFO);
+
+	/* store that last screen was info screen, not main menu screen */
+	game_status_last_screen = GAME_MODE_INFO;
+
 	DrawInfoScreen_NotAvailable("Title screen information:",
 				    "No title screen for this level set.");
-
 	return;
       }
 
-      FadeSoundsAndMusic();
-
-#if 1
-      FadeOut(REDRAW_ALL);
-#endif
+      FadeMenuSoundsAndMusic();
     }
 
+    FadeOut(REDRAW_ALL);
+
+    /* title screens may have different window size */
+    ChangeViewportPropertiesIfNeeded();
+
+    /* only required to update logic for redrawing global border */
+    ClearField();
+
     if (tci->is_image)
       DrawTitleScreenImage(tci->local_nr, tci->initial);
     else
       DrawTitleScreenMessage(tci->local_nr, tci->initial);
 
-    fading_default = (tci->initial ? title_initial_default : title_default);
-
-    fading = fading_next = getTitleFading(tci);
-
-#if 1
-#if 1
-    if (!(fading_last.fade_mode & FADE_TYPE_TRANSFORM) &&
-	fading_next.fade_mode & FADE_TYPE_TRANSFORM)
-    {
-      fading.fade_mode = FADE_MODE_FADE;
-      fading.fade_delay = fading_default.fade_delay;
-    }
-#else
-    if (fading_last.fade_mode != FADE_MODE_CROSSFADE &&
-	fading_next.fade_mode == FADE_MODE_CROSSFADE)
-      fading.fade_mode = FADE_MODE_FADE;
-#endif
-#endif
-
-#if 1
     sound = getTitleSound(tci);
     music = getTitleMusic(tci);
 
@@ -1497,75 +1633,61 @@ void HandleTitleScreen(int mx, int my, int dx, int dy, int button)
 
     last_sound = sound;
     last_music = music;
-#endif
 
     SetMouseCursor(CURSOR_NONE);
 
-#if 1
     FadeIn(REDRAW_ALL);
-#endif
-
-    fading = fading_next;
 
     DelayReached(&title_delay, 0);	/* reset delay counter */
 
     return;
   }
 
-#if 1
   if (fading.auto_delay > 0 && DelayReached(&title_delay, fading.auto_delay))
     button = MB_MENU_CHOICE;
-#else
-  if (fading.auto_delay > -1 && DelayReached(&title_delay, fading.auto_delay))
-    button = MB_MENU_CHOICE;
-#endif
 
   if (button == MB_MENU_LEAVE)
   {
     return_to_main_menu = TRUE;
-    use_fading_main_menu = FALSE;
   }
   else if (button == MB_MENU_CHOICE)
   {
-    if (game_status == GAME_MODE_INFO && num_title_screens == 0)
+    if (game_status_last_screen == GAME_MODE_INFO && num_title_screens == 0)
     {
-#if 0
-      FadeOut(REDRAW_FIELD);
-#endif
-
-      FadeSetEnterScreen();
+      SetGameStatus(GAME_MODE_INFO);
 
       info_mode = INFO_MODE_MAIN;
-      DrawAndFadeInInfoScreen(REDRAW_FIELD);
+
+      DrawInfoScreen();
 
       return;
     }
 
     title_screen_nr++;
-    tci = &title_controls[title_screen_nr];
 
     if (title_screen_nr < num_title_screens)
     {
+      tci = &title_controls[title_screen_nr];
+
+      SetAnimStatus(getTitleAnimMode(tci));
+
       sound = getTitleSound(tci);
       music = getTitleMusic(tci);
 
-      if (sound == SND_UNDEFINED || sound != last_sound)
-	FadeSounds();
-      if (music == MUS_UNDEFINED || music != last_music)
+      if (last_sound != SND_UNDEFINED && sound != last_sound)
+	FadeSound(last_sound);
+      if (last_music != MUS_UNDEFINED && music != last_music)
 	FadeMusic();
 
-#if 1
+      fading = getTitleFading(tci);
+
       FadeOut(REDRAW_ALL);
-#endif
 
       if (tci->is_image)
 	DrawTitleScreenImage(tci->local_nr, tci->initial);
       else
 	DrawTitleScreenMessage(tci->local_nr, tci->initial);
 
-      fading_next = getTitleFading(tci);
-
-#if 1
       sound = getTitleSound(tci);
       music = getTitleMusic(tci);
 
@@ -1576,31 +1698,14 @@ void HandleTitleScreen(int mx, int my, int dx, int dy, int button)
 
       last_sound = sound;
       last_music = music;
-#endif
-
-#if 1
-      /* last screen already faded out, next screen has no animation */
-      if (!(fading.fade_mode & FADE_TYPE_TRANSFORM) &&
-	  fading_next.fade_mode == FADE_MODE_NONE)
-	fading = fading_next;
-#else
-      /* last screen already faded out, next screen has no animation */
-      if (fading.fade_mode      != FADE_MODE_CROSSFADE &&
-	  fading_next.fade_mode == FADE_MODE_NONE)
-	fading = fading_next;
-#endif
 
-#if 1
       FadeIn(REDRAW_ALL);
-#endif
-
-      fading = fading_next;
 
       DelayReached(&title_delay, 0);	/* reset delay counter */
     }
     else
     {
-      FadeSoundsAndMusic();
+      FadeMenuSoundsAndMusic();
 
       return_to_main_menu = TRUE;
     }
@@ -1608,39 +1713,38 @@ void HandleTitleScreen(int mx, int my, int dx, int dy, int button)
 
   if (return_to_main_menu)
   {
-#if 0
-    RedrawBackground();
-#endif
-
     SetMouseCursor(CURSOR_DEFAULT);
 
-    if (game_status == GAME_MODE_INFO)
+    /* force full menu screen redraw after displaying title screens */
+    redraw_mask = REDRAW_ALL;
+
+    if (game_status_last_screen == GAME_MODE_INFO)
     {
-#if 0
-      OpenDoor(DOOR_CLOSE_1 | DOOR_CLOSE_2 | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
-#endif
+      SetGameStatus(GAME_MODE_INFO);
 
       info_mode = INFO_MODE_MAIN;
-      DrawInfoScreenExt(REDRAW_ALL, use_fading_main_menu);
+
+      DrawInfoScreen();
     }
     else	/* default: return to main menu */
     {
-#if 0
-      OpenDoor(DOOR_CLOSE_1 | DOOR_OPEN_2 | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
-#endif
+      SetGameStatus(GAME_MODE_MAIN);
 
-      game_status = GAME_MODE_MAIN;
-      DrawMainMenuExt(REDRAW_ALL, use_fading_main_menu);
+      DrawMainMenu();
     }
   }
 }
 
-void HandleMainMenu_SelectLevel(int step, int direction)
+void HandleMainMenu_SelectLevel(int step, int direction, int selected_level_nr)
 {
   int old_level_nr = level_nr;
   int new_level_nr;
 
-  new_level_nr = old_level_nr + step * direction;
+  if (selected_level_nr != NO_DIRECT_LEVEL_SELECT)
+    new_level_nr = selected_level_nr;
+  else
+    new_level_nr = old_level_nr + step * direction;
+
   if (new_level_nr < leveldir_current->first_level)
     new_level_nr = leveldir_current->first_level;
   if (new_level_nr > leveldir_current->last_level)
@@ -1649,8 +1753,8 @@ void HandleMainMenu_SelectLevel(int step, int direction)
   if (setup.handicap && new_level_nr > leveldir_current->handicap_level)
   {
     /* skipping levels is only allowed when trying to skip single level */
-    if (setup.skip_levels && step == 1 &&
-	Request("Level still unsolved ! Skip despite handicap ?", REQ_ASK))
+    if (setup.skip_levels && new_level_nr == old_level_nr + 1 &&
+	Request("Level still unsolved! Skip despite handicap?", REQ_ASK))
     {
       leveldir_current->handicap_level++;
       SaveLevelSetup_SeriesInfo();
@@ -1672,27 +1776,29 @@ void HandleMainMenu_SelectLevel(int step, int direction)
 	     mci->pos_text->font);
 
     LoadLevel(level_nr);
-    DrawPreviewLevel(TRUE);
+    DrawPreviewLevelInitial();
 
     TapeErase();
     LoadTape(level_nr);
     DrawCompleteVideoDisplay();
 
-    /* needed because DrawPreviewLevel() takes some time */
+    /* needed because DrawPreviewLevelInitial() takes some time */
     BackToFront();
-    SyncDisplay();
+    /* SyncDisplay(); */
   }
 }
 
 void HandleMainMenu(int mx, int my, int dx, int dy, int button)
 {
   static int choice = MAIN_CONTROL_GAME;
+  static boolean button_pressed_last = FALSE;
+  boolean button_pressed = FALSE;
   int pos = choice;
   int i;
 
   if (button == MB_MENU_INITIALIZE)
   {
-    DrawCursorAndText_Main(choice, TRUE);
+    DrawCursorAndText_Main(choice, TRUE, FALSE);
 
     return;
   }
@@ -1712,6 +1818,27 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
 	break;
       }
     }
+
+    /* check if level preview was clicked */
+    if (insidePreviewRect(&preview, mx - SX, my - SY))
+      pos = MAIN_CONTROL_GAME;
+
+    // handle pressed/unpressed state for active/inactive menu buttons
+    // (if pos != -1, "i" contains index position corresponding to "pos")
+    if (button &&
+	pos >= MAIN_CONTROL_NAME && pos <= MAIN_CONTROL_QUIT &&
+	insideMenuPosRect(main_controls[i].pos_button, mx - mSX, my - mSY))
+      button_pressed = TRUE;
+
+    if (button_pressed != button_pressed_last)
+    {
+      DrawCursorAndText_Main(choice, TRUE, button_pressed);
+
+      if (button_pressed)
+	PlaySound(SND_MENU_BUTTON_PRESSING);
+      else
+	PlaySound(SND_MENU_BUTTON_RELEASING);
+    }
   }
   else if (dx || dy)	/* keyboard input */
   {
@@ -1724,7 +1851,23 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
 
   if (pos == MAIN_CONTROL_LEVELS && dx != 0 && button)
   {
-    HandleMainMenu_SelectLevel(1, dx < 0 ? -1 : +1);
+    HandleMainMenu_SelectLevel(1, (dx < 0 ? -1 : +1), NO_DIRECT_LEVEL_SELECT);
+  }
+  else if (pos == MAIN_CONTROL_FIRST_LEVEL && !button)
+  {
+    HandleMainMenu_SelectLevel(MAX_LEVELS, -1, NO_DIRECT_LEVEL_SELECT);
+  }
+  else if (pos == MAIN_CONTROL_LAST_LEVEL && !button)
+  {
+    HandleMainMenu_SelectLevel(MAX_LEVELS, +1, NO_DIRECT_LEVEL_SELECT);
+  }
+  else if (pos == MAIN_CONTROL_LEVEL_NUMBER && !button)
+  {
+    CloseDoor(DOOR_CLOSE_2);
+
+    SetGameStatus(GAME_MODE_LEVELNR);
+
+    DrawChooseLevelNr();
   }
   else if (pos >= MAIN_CONTROL_NAME && pos <= MAIN_CONTROL_QUIT)
   {
@@ -1734,8 +1877,8 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
       {
 	PlaySound(SND_MENU_ITEM_ACTIVATING);
 
-	DrawCursorAndText_Main(choice, FALSE);
-	DrawCursorAndText_Main(pos, TRUE);
+	DrawCursorAndText_Main(choice, FALSE, FALSE);
+	DrawCursorAndText_Main(pos, TRUE, button_pressed);
 
 	choice = pos;
       }
@@ -1746,7 +1889,7 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
 
       if (pos == MAIN_CONTROL_NAME)
       {
-	game_status = GAME_MODE_PSEUDO_TYPENAME;
+	SetGameStatus(GAME_MODE_PSEUDO_TYPENAME);
 
 	HandleTypeName(strlen(setup.player_name), 0);
       }
@@ -1754,21 +1897,24 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
       {
 	if (leveldir_first)
 	{
-	  game_status = GAME_MODE_LEVELS;
+	  CloseDoor(DOOR_CLOSE_2);
+
+	  SetGameStatus(GAME_MODE_LEVELS);
 
 	  SaveLevelSetup_LastSeries();
 	  SaveLevelSetup_SeriesInfo();
 
-#if defined(CREATE_SPECIAL_EDITION_RND_JUE)
-	  gotoTopLevelDir();
-#endif
+	  if (setup.internal.choose_from_top_leveldir)
+	    gotoTopLevelDir();
 
-	  DrawChooseLevel();
+	  DrawChooseLevelSet();
 	}
       }
       else if (pos == MAIN_CONTROL_SCORES)
       {
-	game_status = GAME_MODE_SCORES;
+	CloseDoor(DOOR_CLOSE_2);
+
+	SetGameStatus(GAME_MODE_SCORES);
 
 	DrawHallOfFame(-1);
       }
@@ -1776,22 +1922,22 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
       {
 	if (leveldir_current->readonly &&
 	    !strEqual(setup.player_name, "Artsoft"))
-	  Request("This level is read only !", REQ_CONFIRM);
+	  Request("This level is read only!", REQ_CONFIRM);
 
-	game_status = GAME_MODE_EDITOR;
+	CloseDoor(DOOR_CLOSE_2);
 
-	FadeSetEnterScreen();
+	SetGameStatus(GAME_MODE_EDITOR);
 
-#if 0
-	/* needed if different viewport properties defined for editor */
-	ChangeViewportPropertiesIfNeeded();
-#endif
+	FadeSetEnterScreen();
 
 	DrawLevelEd();
       }
       else if (pos == MAIN_CONTROL_INFO)
       {
-	game_status = GAME_MODE_INFO;
+	CloseDoor(DOOR_CLOSE_2);
+
+	SetGameStatus(GAME_MODE_INFO);
+
 	info_mode = INFO_MODE_MAIN;
 
 	DrawInfoScreen();
@@ -1802,7 +1948,10 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
       }
       else if (pos == MAIN_CONTROL_SETUP)
       {
-	game_status = GAME_MODE_SETUP;
+	CloseDoor(DOOR_CLOSE_2);
+
+	SetGameStatus(GAME_MODE_SETUP);
+
 	setup_mode = SETUP_MODE_MAIN;
 
 	DrawSetupScreen();
@@ -1812,17 +1961,13 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
 	SaveLevelSetup_LastSeries();
 	SaveLevelSetup_SeriesInfo();
 
-        if (Request("Do you really want to quit ?", REQ_ASK | REQ_STAY_CLOSED))
-	  game_status = GAME_MODE_QUIT;
+        if (Request("Do you really want to quit?", REQ_ASK | REQ_STAY_CLOSED))
+	  SetGameStatus(GAME_MODE_QUIT);
       }
     }
   }
 
-  if (game_status == GAME_MODE_MAIN)
-  {
-    DrawPreviewLevel(FALSE);
-    DoAnimation();
-  }
+  button_pressed_last = button_pressed;
 }
 
 
@@ -1831,7 +1976,8 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
 /* ========================================================================= */
 
 static struct TokenInfo *info_info;
-static int num_info_info;
+static int num_info_info;	/* number of info entries shown on screen */
+static int max_info_info;	/* total number of info entries in list */
 
 static void execInfoTitleScreen()
 {
@@ -1884,9 +2030,9 @@ static void execInfoLevelSet()
 
 static void execExitInfo()
 {
-  game_status = GAME_MODE_MAIN;
+  SetGameStatus(GAME_MODE_MAIN);
 
-  DrawMainMenuExt(REDRAW_FIELD, FALSE);
+  DrawMainMenu();
 }
 
 static struct TokenInfo info_info_main[] =
@@ -1904,115 +2050,246 @@ static struct TokenInfo info_info_main[] =
   { 0,			NULL,			NULL			}
 };
 
-static void DrawCursorAndText_Info(int pos, boolean active)
+static int getMenuTextFont(int type)
+{
+  if (type & (TYPE_SWITCH	|
+	      TYPE_YES_NO	|
+	      TYPE_YES_NO_AUTO	|
+	      TYPE_STRING	|
+	      TYPE_ECS_AGA	|
+	      TYPE_KEYTEXT	|
+	      TYPE_ENTER_LIST))
+    return FONT_MENU_2;
+  else
+    return FONT_MENU_1;
+}
+
+static struct TokenInfo *setup_info;
+static struct TokenInfo setup_info_input[];
+
+static struct TokenInfo *menu_info;
+
+static void DrawCursorAndText_Menu_Ext(struct TokenInfo *token_info,
+				       int screen_pos, int menu_info_pos_raw,
+				       boolean active)
 {
+  int pos = (menu_info_pos_raw < 0 ? screen_pos : menu_info_pos_raw);
+  struct TokenInfo *ti = &token_info[pos];
   int xpos = MENU_SCREEN_START_XPOS;
-  int ypos = MENU_SCREEN_START_YPOS + pos;
-  int font_nr = FONT_MENU_1;
+  int ypos = MENU_SCREEN_START_YPOS + screen_pos;
+  int font_nr = getMenuTextFont(ti->type);
+
+  if (token_info == setup_info_input)
+    font_nr = FONT_MENU_1;
 
   if (active)
     font_nr = FONT_ACTIVE(font_nr);
 
-  DrawText(mSX + xpos * 32, mSY + ypos * 32, info_info[pos].text, font_nr);
+  DrawText(mSX + xpos * 32, mSY + ypos * 32, ti->text, font_nr);
+
+  if (ti->type & ~TYPE_SKIP_ENTRY)
+    drawCursor(screen_pos, active);
+}
+
+static void DrawCursorAndText_Menu(int screen_pos, int menu_info_pos_raw,
+				   boolean active)
+{
+  DrawCursorAndText_Menu_Ext(menu_info, screen_pos, menu_info_pos_raw, active);
+}
+
+static void DrawCursorAndText_Setup(int screen_pos, int menu_info_pos_raw,
+				    boolean active)
+{
+  DrawCursorAndText_Menu_Ext(setup_info, screen_pos, menu_info_pos_raw, active);
+}
+
+static char *window_size_text;
+static char *scaling_type_text;
+
+static void drawSetupValue(int, int);
+
+static void drawMenuInfoList(int first_entry, int num_page_entries,
+			     int max_page_entries)
+{
+  int i;
+
+  if (first_entry + num_page_entries > max_page_entries)
+    first_entry = 0;
+
+  clearMenuListArea();
+
+  for (i = 0; i < num_page_entries; i++)
+  {
+    int menu_info_pos = first_entry + i;
+    struct TokenInfo *si = &menu_info[menu_info_pos];
+    void *value_ptr = si->value;
+
+    /* set some entries to "unchangeable" according to other variables */
+    if ((value_ptr == &setup.sound_simple && !audio.sound_available) ||
+	(value_ptr == &setup.sound_loops  && !audio.loops_available) ||
+	(value_ptr == &setup.sound_music  && !audio.music_available) ||
+	(value_ptr == &setup.fullscreen   && !video.fullscreen_available) ||
+	(value_ptr == &window_size_text   && !video.window_scaling_available) ||
+	(value_ptr == &scaling_type_text  && !video.window_scaling_available))
+      si->type |= TYPE_GHOSTED;
+
+    if (si->type & (TYPE_ENTER_MENU|TYPE_ENTER_LIST))
+      initCursor(i, IMG_MENU_BUTTON_ENTER_MENU);
+    else if (si->type & (TYPE_LEAVE_MENU|TYPE_LEAVE_LIST))
+      initCursor(i, IMG_MENU_BUTTON_LEAVE_MENU);
+    else if (si->type & ~TYPE_SKIP_ENTRY)
+      initCursor(i, IMG_MENU_BUTTON);
+
+    DrawCursorAndText_Menu(i, menu_info_pos, FALSE);
 
-  if (info_info[pos].type & ~TYPE_SKIP_ENTRY)
-    drawCursor(pos, active);
+    if (si->type & TYPE_VALUE &&
+	menu_info == setup_info)
+      drawSetupValue(i, menu_info_pos);
+  }
 }
 
-static void DrawInfoScreen_Main(int fade_mask, boolean do_fading)
+static void DrawInfoScreen_Main()
 {
+  int fade_mask = REDRAW_FIELD;
   int i;
 
+  if (redraw_mask & REDRAW_ALL)
+    fade_mask = REDRAW_ALL;
+
+  if (CheckIfGlobalBorderHasChanged())
+    fade_mask = REDRAW_ALL;
+
   UnmapAllGadgets();
-  CloseDoor(DOOR_CLOSE_2);
+  FadeMenuSoundsAndMusic();
+
+  FreeScreenGadgets();
+  CreateScreenGadgets();
 
   /* (needed after displaying title screens which disable auto repeat) */
   KeyboardAutoRepeatOn();
 
   FadeSetLeaveScreen();
 
-#if 1
   FadeOut(fade_mask);
-#endif
 
-#if 1
-  if (fade_mask == REDRAW_ALL)
-  {
-    RedrawBackground();
+  /* needed if different viewport properties defined for info screen */
+  ChangeViewportPropertiesIfNeeded();
 
-    OpenDoor(DOOR_CLOSE_1 | DOOR_CLOSE_2 | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
-  }
-#endif
+  SetMainBackgroundImage(IMG_BACKGROUND_INFO);
 
   ClearField();
 
+  OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
+
   DrawTextSCentered(mSY - SY + 16, FONT_TITLE_1, "Info Screen");
 
   info_info = info_info_main;
-  num_info_info = 0;
 
-#if 1
-  for (i = 0; info_info[i].type != 0 && i < MAX_MENU_ENTRIES_ON_SCREEN; i++)
-#else
+  // determine maximal number of info entries that can be displayed on screen
+  num_info_info = 0;
   for (i = 0; info_info[i].type != 0 && i < NUM_MENU_ENTRIES_ON_SCREEN; i++)
-#endif
-  {
-    if (info_info[i].type & (TYPE_ENTER_MENU|TYPE_ENTER_LIST))
-      initCursor(i, IMG_MENU_BUTTON_ENTER_MENU);
-    else if (info_info[i].type & (TYPE_LEAVE_MENU|TYPE_LEAVE_LIST))
-      initCursor(i, IMG_MENU_BUTTON_LEAVE_MENU);
-    else if (info_info[i].type & ~TYPE_SKIP_ENTRY)
-      initCursor(i, IMG_MENU_BUTTON);
-
-    DrawCursorAndText_Info(i, FALSE);
-
     num_info_info++;
-  }
+
+  // determine maximal number of info entries available for menu of info screen
+  max_info_info = 0;
+  for (i = 0; info_info[i].type != 0; i++)
+    max_info_info++;
 
   HandleInfoScreen_Main(0, 0, 0, 0, MB_MENU_INITIALIZE);
 
-  PlayMenuSound();
-  PlayMenuMusic();
+  MapScreenGadgets(max_info_info);
+
+  PlayMenuSoundsAndMusic();
 
   DrawMaskedBorder(fade_mask);
 
   FadeIn(fade_mask);
-
-  InitAnimation();
 }
 
-void HandleInfoScreen_Main(int mx, int my, int dx, int dy, int button)
+static void changeSetupValue(int, int, int);
+
+void HandleMenuScreen(int mx, int my, int dx, int dy, int button,
+		      int mode, int num_page_entries, int max_page_entries)
 {
-  static int choice_store[MAX_INFO_MODES];
-  int choice = choice_store[info_mode];		/* always starts with 0 */
+  static int num_page_entries_all_last[NUM_SPECIAL_GFX_ARGS][MAX_MENU_MODES];
+  static int choice_stores[NUM_SPECIAL_GFX_ARGS][MAX_MENU_MODES];
+  static int first_entry_stores[NUM_SPECIAL_GFX_ARGS][MAX_MENU_MODES];
+  int *num_page_entries_last = num_page_entries_all_last[game_status];
+  int *choice_store = choice_stores[game_status];
+  int *first_entry_store = first_entry_stores[game_status];
+  int choice = choice_store[mode];		/* starts with 0 */
+  int first_entry = first_entry_store[mode];	/* starts with 0 */
   int x = 0;
-  int y = choice;
+  int y = choice - first_entry;
+  int y_old = y;
+  boolean position_set_by_scrollbar = (dx == 999);
+  int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
+  int i;
 
   if (button == MB_MENU_INITIALIZE)
   {
+    // check if number of menu page entries has changed (may happen by change
+    // of custom artwork definition value for 'list_size' for this menu screen)
+    // (in this case, the last menu position most probably has to be corrected)
+    if (num_page_entries != num_page_entries_last[mode])
+    {
+      choice_store[mode] = first_entry_store[mode] = 0;
+
+      choice = first_entry = 0;
+      y = y_old = 0;
+
+      num_page_entries_last[mode] = num_page_entries;
+    }
+
     /* advance to first valid menu entry */
-    while (choice < num_info_info &&
-	   info_info[choice].type & TYPE_SKIP_ENTRY)
+    while (choice < num_page_entries &&
+	   menu_info[choice].type & TYPE_SKIP_ENTRY)
       choice++;
-    choice_store[info_mode] = choice;
 
-    DrawCursorAndText_Info(choice, TRUE);
+    if (position_set_by_scrollbar)
+      first_entry = first_entry_store[mode] = dy;
+    else
+      AdjustScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL, max_page_entries,
+		      NUM_MENU_ENTRIES_ON_SCREEN, first_entry);
+
+    drawMenuInfoList(first_entry, num_page_entries, max_page_entries);
+
+    if (choice < first_entry)
+    {
+      choice = first_entry;
+
+      if (menu_info[choice].type & TYPE_SKIP_ENTRY)
+	choice++;
+    }
+    else if (choice > first_entry + num_page_entries - 1)
+    {
+      choice = first_entry + num_page_entries - 1;
+
+      if (menu_info[choice].type & TYPE_SKIP_ENTRY)
+	choice--;
+    }
+
+    choice_store[mode] = choice;
+
+    DrawCursorAndText_Menu(choice - first_entry, choice, TRUE);
 
     return;
   }
   else if (button == MB_MENU_LEAVE)
   {
-    for (y = 0; y < num_info_info; y++)
+    PlaySound(SND_MENU_ITEM_SELECTING);
+
+    for (i = 0; i < max_page_entries; i++)
     {
-      if (info_info[y].type & TYPE_LEAVE_MENU)
+      if (menu_info[i].type & TYPE_LEAVE_MENU)
       {
-	void (*menu_callback_function)(void) = info_info[y].value;
+	void (*menu_callback_function)(void) = menu_info[i].value;
 
 	FadeSetLeaveMenu();
 
 	menu_callback_function();
 
-	break;	/* absolutely needed because function changes 'info_info'! */
+	break;	/* absolutely needed because function changes 'menu_info'! */
       }
     }
 
@@ -2024,89 +2301,226 @@ void HandleInfoScreen_Main(int mx, int my, int dx, int dy, int button)
     x = (mx - mSX) / 32;
     y = (my - mSY) / 32 - MENU_SCREEN_START_YPOS;
   }
-  else if (dx || dy)	/* keyboard input */
+  else if (dx || dy)	/* keyboard or scrollbar/scrollbutton input */
   {
-    if (dx)
-    {
-      int menu_navigation_type = (dx < 0 ? TYPE_LEAVE : TYPE_ENTER);
+    /* move cursor instead of scrolling when already at start/end of list */
+    if (dy == -1 * SCROLL_LINE && first_entry == 0)
+      dy = -1;
+    else if (dy == +1 * SCROLL_LINE &&
+	     first_entry + num_page_entries == max_page_entries)
+      dy = 1;
 
-      if (info_info[choice].type & menu_navigation_type ||
-	  info_info[choice].type & TYPE_ENTER_SCREEN ||
-	  info_info[choice].type & TYPE_BOOLEAN_STYLE ||
-	  info_info[choice].type & TYPE_YES_NO_AUTO)
-	button = MB_MENU_CHOICE;
-    }
-    else if (dy)
-      y = choice + dy;
+    /* handle scrolling screen one line or page */
+    if (y + dy < 0 ||
+	y + dy > num_page_entries - 1)
+    {
+      boolean redraw = FALSE;
 
-    /* jump to next non-empty menu entry (up or down) */
-    while (y > 0 && y < num_info_info - 1 &&
-	   info_info[y].type & TYPE_SKIP_ENTRY)
-      y += dy;
-  }
+      if (ABS(dy) == SCROLL_PAGE)
+	step = num_page_entries - 1;
 
-  if (IN_VIS_FIELD(x, y) &&
-      y >= 0 && y < num_info_info && info_info[y].type & ~TYPE_SKIP_ENTRY)
-  {
-    if (button)
-    {
-      if (y != choice)
+      if (dy < 0 && first_entry > 0)
       {
-	PlaySound(SND_MENU_ITEM_ACTIVATING);
+	/* scroll page/line up */
 
-	DrawCursorAndText_Info(choice, FALSE);
-	DrawCursorAndText_Info(y, TRUE);
+	first_entry -= step;
+	if (first_entry < 0)
+	  first_entry = 0;
 
-	choice = choice_store[info_mode] = y;
+	redraw = TRUE;
       }
-    }
-    else if (!(info_info[y].type & TYPE_GHOSTED))
-    {
-      PlaySound(SND_MENU_ITEM_SELECTING);
-
-      if (info_info[y].type & TYPE_ENTER_OR_LEAVE)
+      else if (dy > 0 && first_entry + num_page_entries < max_page_entries)
       {
-	void (*menu_callback_function)(void) = info_info[choice].value;
+	/* scroll page/line down */
 
-	FadeSetFromType(info_info[y].type);
+	first_entry += step;
+	if (first_entry + num_page_entries > max_page_entries)
+	  first_entry = MAX(0, max_page_entries - num_page_entries);
 
-	menu_callback_function();
+	redraw = TRUE;
       }
-    }
-  }
-}
 
-void DrawInfoScreen_NotAvailable(char *text_title, char *text_error)
-{
-  int ystart1 = mSY - SY + 100;
-  int ystart2 = mSY - SY + 150;
-  int ybottom = mSY - SY + SYSIZE - 20;
+      if (redraw)
+      {
+	choice += first_entry - first_entry_store[mode];
 
-  SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_LEVELSET);
+	if (choice < first_entry)
+	{
+	  choice = first_entry;
 
-  FadeOut(REDRAW_FIELD);
+	  if (menu_info[choice].type & TYPE_SKIP_ENTRY)
+	    choice++;
+	}
+	else if (choice > first_entry + num_page_entries - 1)
+	{
+	  choice = first_entry + num_page_entries - 1;
 
-  ClearField();
-  DrawHeadline();
+	  if (menu_info[choice].type & TYPE_SKIP_ENTRY)
+	    choice--;
+	}
+	else if (menu_info[choice].type & TYPE_SKIP_ENTRY)
+	{
+	  choice += SIGN(dy);
 
-  DrawTextSCentered(ystart1, FONT_TEXT_1, text_title);
-  DrawTextSCentered(ystart2, FONT_TEXT_2, text_error);
+	  if (choice < first_entry ||
+	      choice > first_entry + num_page_entries - 1)
+	  first_entry += SIGN(dy);
+	}
 
-  DrawTextSCentered(ybottom, FONT_TEXT_4,
-		    "Press any key or button for info menu");
+	first_entry_store[mode] = first_entry;
+	choice_store[mode] = choice;
 
-  FadeIn(REDRAW_FIELD);
-}
+	drawMenuInfoList(first_entry, num_page_entries, max_page_entries);
 
-void DrawInfoScreen_HelpAnim(int start, int max_anims, boolean init)
-{
-  static int infoscreen_step[MAX_INFO_ELEMENTS_ON_SCREEN];
-  static int infoscreen_frame[MAX_INFO_ELEMENTS_ON_SCREEN];
-  int xstart = mSX + 16;
+	DrawCursorAndText_Menu(choice - first_entry, choice, TRUE);
+
+	AdjustScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL, max_page_entries,
+			NUM_MENU_ENTRIES_ON_SCREEN, first_entry);
+      }
+
+      return;
+    }
+
+    if (dx)
+    {
+      int menu_navigation_type = (dx < 0 ? TYPE_LEAVE : TYPE_ENTER);
+
+      if (menu_info[choice].type & menu_navigation_type ||
+	  menu_info[choice].type & TYPE_BOOLEAN_STYLE ||
+	  menu_info[choice].type & TYPE_YES_NO_AUTO)
+	button = MB_MENU_CHOICE;
+    }
+    else if (dy)
+      y += dy;
+
+    /* jump to next non-empty menu entry (up or down) */
+    while (first_entry + y > 0 &&
+	   first_entry + y < max_page_entries - 1 &&
+	   menu_info[first_entry + y].type & TYPE_SKIP_ENTRY)
+      y += dy;
+
+    if (!IN_VIS_MENU(x, y))
+    {
+      choice += y - y_old;
+
+      if (choice < first_entry)
+	first_entry = choice;
+      else if (choice > first_entry + num_page_entries - 1)
+	first_entry = choice - num_page_entries + 1;
+
+      if (first_entry >= 0 &&
+	  first_entry + num_page_entries <= max_page_entries)
+      {
+	first_entry_store[mode] = first_entry;
+
+	if (choice < first_entry)
+	  choice = first_entry;
+	else if (choice > first_entry + num_page_entries - 1)
+	  choice = first_entry + num_page_entries - 1;
+
+	choice_store[mode] = choice;
+
+	drawMenuInfoList(first_entry, num_page_entries, max_page_entries);
+
+	DrawCursorAndText_Menu(choice - first_entry, choice, TRUE);
+
+	AdjustScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL, max_page_entries,
+			NUM_MENU_ENTRIES_ON_SCREEN, first_entry);
+      }
+
+      return;
+    }
+  }
+
+  if (!anyScrollbarGadgetActive() &&
+      IN_VIS_MENU(x, y) &&
+      mx < screen_gadget[SCREEN_CTRL_ID_SCROLL_VERTICAL]->x &&
+      y >= 0 && y < num_page_entries)
+  {
+    if (button)
+    {
+      if (first_entry + y != choice &&
+	  menu_info[first_entry + y].type & ~TYPE_SKIP_ENTRY)
+      {
+	PlaySound(SND_MENU_ITEM_ACTIVATING);
+
+	DrawCursorAndText_Menu(choice - first_entry, choice, FALSE);
+	DrawCursorAndText_Menu(y, first_entry + y, TRUE);
+
+	choice = choice_store[mode] = first_entry + y;
+      }
+    }
+    else if (!(menu_info[first_entry + y].type & TYPE_GHOSTED))
+    {
+      PlaySound(SND_MENU_ITEM_SELECTING);
+
+      /* when selecting key headline, execute function for key value change */
+      if (menu_info[first_entry + y].type & TYPE_KEYTEXT &&
+	  menu_info[first_entry + y + 1].type & TYPE_KEY)
+	y++;
+
+      /* when selecting string value, execute function for list selection */
+      if (menu_info[first_entry + y].type & TYPE_STRING && y > 0 &&
+	  menu_info[first_entry + y - 1].type & TYPE_ENTER_LIST)
+	y--;
+
+      if (menu_info[first_entry + y].type & TYPE_ENTER_OR_LEAVE)
+      {
+	void (*menu_callback_function)(void) =
+	  menu_info[first_entry + y].value;
+
+	FadeSetFromType(menu_info[first_entry + y].type);
+
+	menu_callback_function();
+      }
+      else if (menu_info[first_entry + y].type & TYPE_VALUE &&
+	       menu_info == setup_info)
+      {
+	changeSetupValue(y, first_entry + y, dx);
+      }
+    }
+  }
+}
+
+void HandleInfoScreen_Main(int mx, int my, int dx, int dy, int button)
+{
+  menu_info = info_info;
+
+  HandleMenuScreen(mx, my, dx, dy, button,
+		   info_mode, num_info_info, max_info_info);
+}
+
+void DrawInfoScreen_NotAvailable(char *text_title, char *text_error)
+{
   int ystart1 = mSY - SY + 100;
-  int ystart2 = mSY + 64 + 2 * 32;
+  int ystart2 = mSY - SY + 150;
   int ybottom = mSY - SY + SYSIZE - 20;
-  int ystep = TILEY + 4;
+
+  SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO);
+
+  FadeOut(REDRAW_FIELD);
+
+  ClearField();
+  DrawHeadline();
+
+  DrawTextSCentered(ystart1, FONT_TEXT_1, text_title);
+  DrawTextSCentered(ystart2, FONT_TEXT_2, text_error);
+
+  DrawTextSCentered(ybottom, FONT_TEXT_4,
+		    "Press any key or button for info menu");
+
+  FadeIn(REDRAW_FIELD);
+}
+
+void DrawInfoScreen_HelpAnim(int start, int max_anims, boolean init)
+{
+  static int infoscreen_step[MAX_INFO_ELEMENTS_ON_SCREEN];
+  static int infoscreen_frame[MAX_INFO_ELEMENTS_ON_SCREEN];
+  int xstart = mSX + MENU_SCREEN_INFO_XSTART;
+  int ystart1 = mSY - SY + MENU_SCREEN_INFO_YSTART1;
+  int ystart2 = mSY + MENU_SCREEN_INFO_YSTART2;
+  int ybottom = mSY - SY + MENU_SCREEN_INFO_YBOTTOM;
+  int ystep = MENU_SCREEN_INFO_YSTEP;
   int element, action, direction;
   int graphic;
   int delay;
@@ -2115,7 +2529,7 @@ void DrawInfoScreen_HelpAnim(int start, int max_anims, boolean init)
 
   if (init)
   {
-    for (i = 0; i < MAX_INFO_ELEMENTS_ON_SCREEN; i++)
+    for (i = 0; i < NUM_INFO_ELEMENTS_ON_SCREEN; i++)
       infoscreen_step[i] = infoscreen_frame[i] = 0;
 
     ClearField();
@@ -2132,7 +2546,7 @@ void DrawInfoScreen_HelpAnim(int start, int max_anims, boolean init)
   i = j = 0;
   while (helpanim_info[j].element != HELPANIM_LIST_END)
   {
-    if (i >= start + MAX_INFO_ELEMENTS_ON_SCREEN ||
+    if (i >= start + NUM_INFO_ELEMENTS_ON_SCREEN ||
 	i >= max_anims)
       break;
     else if (i < start)
@@ -2197,8 +2611,8 @@ void DrawInfoScreen_HelpAnim(int start, int max_anims, boolean init)
 
     ClearRectangleOnBackground(drawto, xstart, ystart2 + (i - start) * ystep,
 			       TILEX, TILEY);
-    DrawGraphicAnimationExt(drawto, xstart, ystart2 + (i - start) * ystep,
-			    graphic, sync_frame, USE_MASKING);
+    DrawFixedGraphicAnimationExt(drawto, xstart, ystart2 + (i - start) * ystep,
+				 graphic, sync_frame, USE_MASKING);
 
     if (init)
       DrawInfoScreen_HelpText(element, action, direction, i - start);
@@ -2263,6 +2677,8 @@ void DrawInfoScreen_HelpText(int element, int action, int direction, int ypos)
 
 void DrawInfoScreen_TitleScreen()
 {
+  SetGameStatus(GAME_MODE_TITLE);
+
   DrawTitleScreen();
 }
 
@@ -2283,17 +2699,15 @@ void DrawInfoScreen_Elements()
   HandleInfoScreen_Elements(MB_MENU_INITIALIZE);
 
   FadeIn(REDRAW_FIELD);
-
-  InitAnimation();
 }
 
 void HandleInfoScreen_Elements(int button)
 {
-  static unsigned long info_delay = 0;
+  static unsigned int info_delay = 0;
   static int num_anims;
   static int num_pages;
   static int page;
-  int anims_per_page = MAX_INFO_ELEMENTS_ON_SCREEN;
+  int anims_per_page = NUM_INFO_ELEMENTS_ON_SCREEN;
   int i;
 
   if (button == MB_MENU_INITIALIZE)
@@ -2337,18 +2751,16 @@ void HandleInfoScreen_Elements(int button)
 
     if (page >= num_pages)
     {
-      FadeSoundsAndMusic();
+      FadeMenuSoundsAndMusic();
 
       info_mode = INFO_MODE_MAIN;
-      DrawAndFadeInInfoScreen(REDRAW_FIELD);
+      DrawInfoScreen();
 
       return;
     }
 
-#if 1
     if (page > 0)
       FadeSetNextScreen();
-#endif
 
     if (button != MB_MENU_INITIALIZE)
       FadeOut(REDRAW_FIELD);
@@ -2372,9 +2784,7 @@ void DrawInfoScreen_Music()
 {
   SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_MUSIC);
 
-#if 1
   FadeOut(REDRAW_FIELD);
-#endif
 
   ClearField();
   DrawHeadline();
@@ -2383,9 +2793,7 @@ void DrawInfoScreen_Music()
 
   HandleInfoScreen_Music(MB_MENU_INITIALIZE);
 
-#if 1
   FadeIn(REDRAW_FIELD);
-#endif
 }
 
 void HandleInfoScreen_Music(int button)
@@ -2402,7 +2810,7 @@ void HandleInfoScreen_Music(int button)
 
     if (list == NULL)
     {
-      FadeSoundsAndMusic();
+      FadeMenuSoundsAndMusic();
 
       ClearField();
       DrawHeadline();
@@ -2421,7 +2829,7 @@ void HandleInfoScreen_Music(int button)
   {
     PlaySound(SND_MENU_ITEM_SELECTING);
 
-    FadeSoundsAndMusic();
+    FadeMenuSoundsAndMusic();
 
     info_mode = INFO_MODE_MAIN;
     DrawInfoScreen();
@@ -2442,20 +2850,18 @@ void HandleInfoScreen_Music(int button)
 
     if (list == NULL)
     {
-      FadeSoundsAndMusic();
+      FadeMenuSoundsAndMusic();
 
       info_mode = INFO_MODE_MAIN;
-      DrawAndFadeInInfoScreen(REDRAW_FIELD);
+      DrawInfoScreen();
 
       return;
     }
 
-    FadeSoundsAndMusic();
+    FadeMenuSoundsAndMusic();
 
-#if 1
     if (list != music_file_info)
       FadeSetNextScreen();
-#endif
 
     if (button != MB_MENU_INITIALIZE)
       FadeOut(REDRAW_FIELD);
@@ -2627,7 +3033,7 @@ static void DrawInfoScreen_CreditsScreen(int screen_nr)
     DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_2,
 		      "and");
     DrawTextSCentered(ystart2 + 3 * ystep, FONT_TEXT_3,
-		      "J�rgen Bonhagen");
+		      "J\xfcrgen Bonhagen");
     DrawTextSCentered(ystart2 + 4 * ystep, FONT_TEXT_2,
 		      "for the continuous creation");
     DrawTextSCentered(ystart2 + 5 * ystep, FONT_TEXT_2,
@@ -2681,7 +3087,7 @@ static void DrawInfoScreen_CreditsScreen(int screen_nr)
     DrawTextSCentered(ystart2 + 4 * ystep, FONT_TEXT_2,
 		      "Thanks to");
     DrawTextSCentered(ystart2 + 5 * ystep, FONT_TEXT_3,
-		      "Karl H�rnell");
+		      "Karl H\xf6rnell");
     DrawTextSCentered(ystart2 + 6 * ystep, FONT_TEXT_2,
 		      "for some additional toons");
   }
@@ -2707,17 +3113,13 @@ void DrawInfoScreen_Credits()
 {
   SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_CREDITS);
 
-  FadeSoundsAndMusic();
+  FadeMenuSoundsAndMusic();
 
-#if 1
   FadeOut(REDRAW_FIELD);
-#endif
 
   HandleInfoScreen_Credits(MB_MENU_INITIALIZE);
 
-#if 1
   FadeIn(REDRAW_FIELD);
-#endif
 }
 
 void HandleInfoScreen_Credits(int button)
@@ -2752,18 +3154,16 @@ void HandleInfoScreen_Credits(int button)
 
     if (screen_nr >= num_screens)
     {
-      FadeSoundsAndMusic();
+      FadeMenuSoundsAndMusic();
 
       info_mode = INFO_MODE_MAIN;
-      DrawAndFadeInInfoScreen(REDRAW_FIELD);
+      DrawInfoScreen();
 
       return;
     }
 
-#if 1
     if (screen_nr > 0)
       FadeSetNextScreen();
-#endif
 
     if (button != MB_MENU_INITIALIZE)
       FadeOut(REDRAW_FIELD);
@@ -2788,9 +3188,7 @@ void DrawInfoScreen_Program()
 
   SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_PROGRAM);
 
-#if 1
   FadeOut(REDRAW_FIELD);
-#endif
 
   ClearField();
   DrawHeadline();
@@ -2802,34 +3200,22 @@ void DrawInfoScreen_Program()
   DrawTextSCentered(ystart2 + 1 * ystep, FONT_TEXT_2,
 		    "If you like it, send e-mail to:");
   DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_3,
-		    PROGRAM_EMAIL_STRING);
-  DrawTextSCentered(ystart2 + 3 * ystep, FONT_TEXT_2,
-		    "or SnailMail to:");
-  DrawTextSCentered(ystart2 + 4 * ystep + 0, FONT_TEXT_3,
-		    "Holger Schemel");
-  DrawTextSCentered(ystart2 + 4 * ystep + 20, FONT_TEXT_3,
-		    "Detmolder Strasse 189");
-  DrawTextSCentered(ystart2 + 4 * ystep + 40, FONT_TEXT_3,
-		    "33604 Bielefeld");
-  DrawTextSCentered(ystart2 + 4 * ystep + 60, FONT_TEXT_3,
-		    "Germany");
-  DrawTextSCentered(ystart2 + 7 * ystep, FONT_TEXT_2,
+		    setup.internal.program_email);
+  DrawTextSCentered(ystart2 + 4 * ystep, FONT_TEXT_2,
 		    "More information and levels:");
-  DrawTextSCentered(ystart2 + 8 * ystep, FONT_TEXT_3,
-		    PROGRAM_WEBSITE_STRING);
-  DrawTextSCentered(ystart2 + 9 * ystep, FONT_TEXT_2,
+  DrawTextSCentered(ystart2 + 5 * ystep, FONT_TEXT_3,
+		    setup.internal.program_website);
+  DrawTextSCentered(ystart2 + 7 * ystep, FONT_TEXT_2,
 		    "If you have created new levels,");
-  DrawTextSCentered(ystart2 + 10 * ystep, FONT_TEXT_2,
+  DrawTextSCentered(ystart2 + 8 * ystep, FONT_TEXT_2,
 		    "send them to me to include them!");
-  DrawTextSCentered(ystart2 + 11 * ystep, FONT_TEXT_2,
+  DrawTextSCentered(ystart2 + 9 * ystep, FONT_TEXT_2,
 		    ":-)");
 
   DrawTextSCentered(ybottom, FONT_TEXT_4,
 		    "Press any key or button for info menu");
 
-#if 1
   FadeIn(REDRAW_FIELD);
-#endif
 }
 
 void HandleInfoScreen_Program(int button)
@@ -2847,14 +3233,10 @@ void HandleInfoScreen_Program(int button)
   {
     PlaySound(SND_MENU_ITEM_SELECTING);
 
-    FadeSoundsAndMusic();
-
-#if 0
-    FadeOut(REDRAW_FIELD);
-#endif
+    FadeMenuSoundsAndMusic();
 
     info_mode = INFO_MODE_MAIN;
-    DrawAndFadeInInfoScreen(REDRAW_FIELD);
+    DrawInfoScreen();
   }
   else
   {
@@ -2871,21 +3253,22 @@ void DrawInfoScreen_Version()
   int ystart1 = mSY - SY + 100;
   int ystart2 = mSY - SY + 150;
   int ybottom = mSY - SY + SYSIZE - 20;
-  int xstart1 = mSX + 2 * xstep;
-  int xstart2 = mSX + 19 * xstep;
-#if defined(TARGET_SDL)
-  int xstart3 = mSX + 29 * xstep;
+  int xstart1 = mSX - SX + 2 * xstep;
+  int xstart2 = mSX - SX + 18 * xstep;
+  int xstart3 = mSX - SX + 28 * xstep;
   SDL_version sdl_version_compiled;
   const SDL_version *sdl_version_linked;
-  int driver_name_len = 8;
+  int driver_name_len = 10;
+#if defined(TARGET_SDL2)
+  SDL_version sdl_version_linked_ext;
+  const char *driver_name = NULL;
+#else
   char driver_name[driver_name_len];
 #endif
 
   SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_VERSION);
 
-#if 1
   FadeOut(REDRAW_FIELD);
-#endif
 
   ClearField();
   DrawHeadline();
@@ -2893,11 +3276,11 @@ void DrawInfoScreen_Version()
   DrawTextSCentered(ystart1, FONT_TEXT_1, "Version Information:");
 
   DrawTextF(xstart1, ystart2, font_header, "Name");
-  DrawTextF(xstart2, ystart2, font_text, PROGRAM_TITLE_STRING);
+  DrawTextF(xstart2, ystart2, font_text, getProgramTitleString());
 
   ystart2 += ystep;
   DrawTextF(xstart1, ystart2, font_header, "Version");
-  DrawTextF(xstart2, ystart2, font_text, getProgramFullVersionString());
+  DrawTextF(xstart2, ystart2, font_text, getProgramVersionString());
 
   ystart2 += ystep;
   DrawTextF(xstart1, ystart2, font_header, "Platform");
@@ -2908,17 +3291,21 @@ void DrawInfoScreen_Version()
   DrawTextF(xstart2, ystart2, font_text, TARGET_STRING);
 
   ystart2 += ystep;
-  DrawTextF(xstart1, ystart2, font_header, "Compile time");
-  DrawTextF(xstart2, ystart2, font_text, getCompileDateString());
+  DrawTextF(xstart1, ystart2, font_header, "Source date");
+  DrawTextF(xstart2, ystart2, font_text, getSourceDateString());
 
-#if defined(TARGET_SDL)
   ystart2 += 3 * ystep;
   DrawTextF(xstart1, ystart2, font_header, "Library");
   DrawTextF(xstart2, ystart2, font_header, "compiled");
   DrawTextF(xstart3, ystart2, font_header, "linked");
 
   SDL_VERSION(&sdl_version_compiled);
+#if defined(TARGET_SDL2)
+  SDL_GetVersion(&sdl_version_linked_ext);
+  sdl_version_linked = &sdl_version_linked_ext;
+#else
   sdl_version_linked = SDL_Linked_Version();
+#endif
 
   ystart2 += 2 * ystep;
   DrawTextF(xstart1, ystart2, font_text, "SDL");
@@ -2978,27 +3365,32 @@ void DrawInfoScreen_Version()
   DrawTextF(xstart2, ystart2, font_header, "Requested");
   DrawTextF(xstart3, ystart2, font_header, "Used");
 
+#if defined(TARGET_SDL2)
+  driver_name = getStringCopyNStatic(SDL_GetVideoDriver(0), driver_name_len);
+#else
   SDL_VideoDriverName(driver_name, driver_name_len);
+#endif
 
   ystart2 += 2 * ystep;
   DrawTextF(xstart1, ystart2, font_text, "SDL_VideoDriver");
   DrawTextF(xstart2, ystart2, font_text, "%s", setup.system.sdl_videodriver);
   DrawTextF(xstart3, ystart2, font_text, "%s", driver_name);
 
+#if defined(TARGET_SDL2)
+  driver_name = getStringCopyNStatic(SDL_GetAudioDriver(0), driver_name_len);
+#else
   SDL_AudioDriverName(driver_name, driver_name_len);
+#endif
 
   ystart2 += ystep;
   DrawTextF(xstart1, ystart2, font_text, "SDL_AudioDriver");
   DrawTextF(xstart2, ystart2, font_text, "%s", setup.system.sdl_audiodriver);
   DrawTextF(xstart3, ystart2, font_text, "%s", driver_name);
-#endif
 
   DrawTextSCentered(ybottom, FONT_TEXT_4,
 		    "Press any key or button for info menu");
 
-#if 1
   FadeIn(REDRAW_FIELD);
-#endif
 }
 
 void HandleInfoScreen_Version(int button)
@@ -3016,14 +3408,10 @@ void HandleInfoScreen_Version(int button)
   {
     PlaySound(SND_MENU_ITEM_SELECTING);
 
-    FadeSoundsAndMusic();
-
-#if 0
-    FadeOut(REDRAW_FIELD);
-#endif
+    FadeMenuSoundsAndMusic();
 
     info_mode = INFO_MODE_MAIN;
-    DrawAndFadeInInfoScreen(REDRAW_FIELD);
+    DrawInfoScreen();
   }
   else
   {
@@ -3035,6 +3423,41 @@ void DrawInfoScreen_LevelSet()
 {
   struct TitleMessageInfo *tmi = &readme;
   char *filename = getLevelSetInfoFilename();
+  char *title = "Level Set Information:";
+  int ystart1 = mSY - SY + 100;
+  int ybottom = mSY - SY + SYSIZE - 20;
+
+  if (filename == NULL)
+  {
+    DrawInfoScreen_NotAvailable(title, "No information for this level set.");
+
+    return;
+  }
+
+  SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_LEVELSET);
+
+  FadeOut(REDRAW_FIELD);
+
+  ClearField();
+  DrawHeadline();
+
+  DrawTextSCentered(ystart1, FONT_TEXT_1, title);
+
+  /* if x position set to "-1", automatically determine by playfield width */
+  if (tmi->x == -1)
+    tmi->x = SXSIZE / 2;
+
+  /* if y position set to "-1", use static default value */
+  if (tmi->y == -1)
+    tmi->y = 150;
+
+  /* if width set to "-1", automatically determine by playfield width */
+  if (tmi->width == -1)
+    tmi->width = SXSIZE - 2 * TILEX;
+
+  /* if height set to "-1", automatically determine by playfield height */
+  if (tmi->height == -1)
+    tmi->height = SYSIZE - 20 - tmi->y - 10;
 
   /* if chars set to "-1", automatically determine by text and font width */
   if (tmi->chars == -1)
@@ -3048,31 +3471,14 @@ void DrawInfoScreen_LevelSet()
   else
     tmi->height = tmi->lines * getFontHeight(tmi->font);
 
-  SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_LEVELSET);
-
-#if 1
-  FadeOut(REDRAW_FIELD);
-#endif
-
-  ClearField();
-  DrawHeadline();
-
-  DrawTextCentered(mSY + 100, FONT_TEXT_1, "Level Set Information:");
-
-  if (filename != NULL)
-    DrawTextFile(mSX + ALIGNED_TEXT_XPOS(tmi), mSY + ALIGNED_TEXT_YPOS(tmi),
-		 filename, tmi->font, tmi->chars, -1, tmi->lines, 0, -1,
-		 tmi->autowrap, tmi->centered, tmi->parse_comments);
-  else
-    DrawTextCentered(mSY + ALIGNED_TEXT_YPOS(tmi), FONT_TEXT_2,
-		     "No information for this level set.");
+  DrawTextFile(mSX + ALIGNED_TEXT_XPOS(tmi), mSY + ALIGNED_TEXT_YPOS(tmi),
+	       filename, tmi->font, tmi->chars, -1, tmi->lines, 0, -1,
+	       tmi->autowrap, tmi->centered, tmi->parse_comments);
 
-  DrawTextCentered(mSY + SYSIZE - 20, FONT_TEXT_4,
-		   "Press any key or button for info menu");
+  DrawTextSCentered(ybottom, FONT_TEXT_4,
+		    "Press any key or button for info menu");
 
-#if 1
   FadeIn(REDRAW_FIELD);
-#endif
 }
 
 void HandleInfoScreen_LevelSet(int button)
@@ -3090,14 +3496,10 @@ void HandleInfoScreen_LevelSet(int button)
   {
     PlaySound(SND_MENU_ITEM_SELECTING);
 
-    FadeSoundsAndMusic();
-
-#if 0
-    FadeOut(REDRAW_FIELD);
-#endif
+    FadeMenuSoundsAndMusic();
 
     info_mode = INFO_MODE_MAIN;
-    DrawAndFadeInInfoScreen(REDRAW_FIELD);
+    DrawInfoScreen();
   }
   else
   {
@@ -3105,10 +3507,8 @@ void HandleInfoScreen_LevelSet(int button)
   }
 }
 
-static void DrawInfoScreenExt(int fade_mask, boolean do_fading)
+static void DrawInfoScreen()
 {
-  SetMainBackgroundImage(IMG_BACKGROUND_INFO);
-
   if (info_mode == INFO_MODE_TITLE)
     DrawInfoScreen_TitleScreen();
   else if (info_mode == INFO_MODE_ELEMENTS)
@@ -3124,25 +3524,12 @@ static void DrawInfoScreenExt(int fade_mask, boolean do_fading)
   else if (info_mode == INFO_MODE_LEVELSET)
     DrawInfoScreen_LevelSet();
   else
-    DrawInfoScreen_Main(fade_mask, do_fading);
+    DrawInfoScreen_Main();
 
   if (info_mode != INFO_MODE_MAIN &&
       info_mode != INFO_MODE_TITLE &&
       info_mode != INFO_MODE_MUSIC)
-  {
-    PlayMenuSound();
-    PlayMenuMusic();
-  }
-}
-
-void DrawAndFadeInInfoScreen(int fade_mask)
-{
-  DrawInfoScreenExt(fade_mask, TRUE);
-}
-
-void DrawInfoScreen()
-{
-  DrawInfoScreenExt(REDRAW_FIELD, FALSE);
+    PlayMenuSoundsAndMusic();
 }
 
 void HandleInfoScreen(int mx, int my, int dx, int dy, int button)
@@ -3163,8 +3550,6 @@ void HandleInfoScreen(int mx, int my, int dx, int dy, int button)
     HandleInfoScreen_LevelSet(button);
   else
     HandleInfoScreen_Main(mx, my, dx, dy, button);
-
-  DoAnimation();
 }
 
 
@@ -3194,6 +3579,8 @@ void HandleTypeName(int newxpos, Key key)
     strcpy(last_player_name, setup.player_name);
 
     xpos = newxpos;
+
+    StartTextInput(startx, starty, pos->width, pos->height);
   }
   else if (is_valid_key_char && xpos < MAX_PLAYER_NAME_LEN)
   {
@@ -3214,7 +3601,7 @@ void HandleTypeName(int newxpos, Key key)
 
     is_active = FALSE;
 
-    game_status = GAME_MODE_MAIN;
+    SetGameStatus(GAME_MODE_MAIN);
   }
   else if (key == KSYM_Escape)
   {
@@ -3222,7 +3609,7 @@ void HandleTypeName(int newxpos, Key key)
 
     is_active = FALSE;
 
-    game_status = GAME_MODE_MAIN;
+    SetGameStatus(GAME_MODE_MAIN);
   }
 
   if (is_active)
@@ -3239,6 +3626,8 @@ void HandleTypeName(int newxpos, Key key)
     startx = mSX + ALIGNED_TEXT_XPOS(pos);
 
     DrawText(startx, starty, setup.player_name, font_nr);
+
+    StopTextInput();
   }
 }
 
@@ -3249,44 +3638,45 @@ void HandleTypeName(int newxpos, Key key)
 
 static void DrawChooseTree(TreeInfo **ti_ptr)
 {
+  int fade_mask = REDRAW_FIELD;
+
+  if (CheckIfGlobalBorderHasChanged())
+    fade_mask = REDRAW_ALL;
+
+  if (strEqual((*ti_ptr)->subdir, STRING_TOP_DIRECTORY))
+  {
+    SetGameStatus(GAME_MODE_MAIN);
+
+    DrawMainMenu();
+
+    return;
+  }
+
   UnmapAllGadgets();
 
   FreeScreenGadgets();
   CreateScreenGadgets();
 
-  CloseDoor(DOOR_CLOSE_2);
+  FadeOut(fade_mask);
 
-#if 1
-  FadeOut(REDRAW_FIELD);
-#endif
+  /* needed if different viewport properties defined for choosing level (set) */
+  ChangeViewportPropertiesIfNeeded();
+
+  if (game_status == GAME_MODE_LEVELNR)
+    SetMainBackgroundImage(IMG_BACKGROUND_LEVELNR);
+  else if (game_status == GAME_MODE_LEVELS)
+    SetMainBackgroundImage(IMG_BACKGROUND_LEVELS);
 
   ClearField();
 
+  OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
+
   HandleChooseTree(0, 0, 0, 0, MB_MENU_INITIALIZE, ti_ptr);
   MapScreenTreeGadgets(*ti_ptr);
 
-#if 1
-  FadeIn(REDRAW_FIELD);
-#endif
-
-  InitAnimation();
-}
-
-static void AdjustChooseTreeScrollbar(int id, int first_entry, TreeInfo *ti)
-{
-  struct GadgetInfo *gi = screen_gadget[id];
-  int items_max, items_visible, item_position;
-
-  items_max = numTreeInfoInGroup(ti);
-  items_visible = NUM_MENU_ENTRIES_ON_SCREEN;
-  item_position = first_entry;
-
-  if (item_position > items_max - items_visible)
-    item_position = items_max - items_visible;
+  DrawMaskedBorder(fade_mask);
 
-  ModifyGadget(gi, GDI_SCROLLBAR_ITEMS_MAX, items_max,
-	       GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible,
-	       GDI_SCROLLBAR_ITEM_POSITION, item_position, GDI_END);
+  FadeIn(fade_mask);
 }
 
 static void drawChooseTreeList(int first_entry, int num_page_entries,
@@ -3296,30 +3686,14 @@ static void drawChooseTreeList(int first_entry, int num_page_entries,
   char *title_string = NULL;
   int yoffset_sets = MENU_TITLE1_YPOS;
   int yoffset_setup = 16;
-  int yoffset = (ti->type == TREE_TYPE_LEVEL_DIR ? yoffset_sets :
-		 yoffset_setup);
-  int last_game_status = game_status;	/* save current game status */
+  int yoffset = (ti->type == TREE_TYPE_LEVEL_DIR ||
+		 ti->type == TREE_TYPE_LEVEL_NR ? yoffset_sets : yoffset_setup);
 
   title_string = ti->infotext;
 
   DrawTextSCentered(mSY - SY + yoffset, FONT_TITLE_1, title_string);
 
-#if 0
-  /* force LEVELS font on artwork setup screen */
-  game_status = GAME_MODE_LEVELS;
-#endif
-
-#if 1
-  /* clear tree list area, but not title or scrollbar */
-  DrawBackground(mSX, mSY + MENU_SCREEN_START_YPOS * 32,
-		 SC_SCROLLBAR_XPOS + menu.scrollbar_xoffset,
-		 NUM_MENU_ENTRIES_ON_SCREEN * 32);
-#else
-  /* clear tree list area, but not title or scrollbar */
-  DrawBackground(mSX, mSY + MENU_SCREEN_START_YPOS * 32,
-		 SC_SCROLLBAR_XPOS + menu.scrollbar_xoffset,
-		 MAX_MENU_ENTRIES_ON_SCREEN * 32);
-#endif
+  clearMenuListArea();
 
   for (i = 0; i < num_page_entries; i++)
   {
@@ -3353,8 +3727,6 @@ static void drawChooseTreeList(int first_entry, int num_page_entries,
       initCursor(i, IMG_MENU_BUTTON);
   }
 
-  game_status = last_game_status;	/* restore current game status */
-
   redraw_mask |= REDRAW_FIELD;
 }
 
@@ -3365,6 +3737,9 @@ static void drawChooseTreeInfo(int entry_pos, TreeInfo *ti)
   int ypos = MENU_TITLE2_YPOS;
   int font_nr = FONT_TITLE_2;
 
+  if (ti->type == TREE_TYPE_LEVEL_NR)
+    DrawTextFCentered(ypos, font_nr, leveldir_current->name);
+
   if (ti->type != TREE_TYPE_LEVEL_DIR)
     return;
 
@@ -3374,17 +3749,18 @@ static void drawChooseTreeInfo(int entry_pos, TreeInfo *ti)
   DrawBackgroundForFont(SX, SY + ypos, SXSIZE, getFontHeight(font_nr), font_nr);
 
   if (node->parent_link)
-    DrawTextFCentered(ypos, font_nr, "leave group \"%s\"",
-		      node->class_desc);
+    DrawTextFCentered(ypos, font_nr, "leave \"%s\"",
+		      node->node_parent->name);
   else if (node->level_group)
-    DrawTextFCentered(ypos, font_nr, "enter group \"%s\"",
-		      node->class_desc);
+    DrawTextFCentered(ypos, font_nr, "enter \"%s\"",
+		      node->name);
   else if (ti->type == TREE_TYPE_LEVEL_DIR)
-    DrawTextFCentered(ypos, font_nr, "%3d levels (%s)",
-		      node->levels, node->class_desc);
+    DrawTextFCentered(ypos, font_nr, "%3d %s (%s)",
+		      node->levels, (node->levels > 1 ? "levels" : "level"),
+		      node->class_desc);
 
   /* let BackToFront() redraw only what is needed */
-  redraw_mask = last_redraw_mask | REDRAW_TILES;
+  redraw_mask = last_redraw_mask;
   for (x = 0; x < SCR_FIELDX; x++)
     MarkTileDirty(x, 1);
 }
@@ -3398,21 +3774,13 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
   int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
   int num_entries = numTreeInfoInGroup(ti);
   int num_page_entries;
-  int last_game_status = game_status;	/* save current game status */
   boolean position_set_by_scrollbar = (dx == 999);
 
-#if 0
-  /* force LEVELS draw offset on choose level and artwork setup screen */
-  game_status = GAME_MODE_LEVELS;
-#endif
-
   if (num_entries <= NUM_MENU_ENTRIES_ON_SCREEN)
     num_page_entries = num_entries;
   else
     num_page_entries = NUM_MENU_ENTRIES_ON_SCREEN;
 
-  game_status = last_game_status;	/* restore current game status */
-
   if (button == MB_MENU_INITIALIZE)
   {
     int num_entries = numTreeInfoInGroup(ti);
@@ -3458,19 +3826,37 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
     }
     else if (game_status == GAME_MODE_SETUP)
     {
-      if (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED)
+      if (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED ||
+	  setup_mode == SETUP_MODE_CHOOSE_SCROLL_DELAY ||
+	  setup_mode == SETUP_MODE_CHOOSE_SNAPSHOT_MODE)
 	execSetupGame();
-      else if (setup_mode == SETUP_MODE_CHOOSE_SCREEN_MODE ||
-	       setup_mode == SETUP_MODE_CHOOSE_SCROLL_DELAY)
+      else if (setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE ||
+	       setup_mode == SETUP_MODE_CHOOSE_SCALING_TYPE ||
+	       setup_mode == SETUP_MODE_CHOOSE_RENDERING)
 	execSetupGraphics();
+      else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_SIMPLE ||
+	       setup_mode == SETUP_MODE_CHOOSE_VOLUME_LOOPS ||
+	       setup_mode == SETUP_MODE_CHOOSE_VOLUME_MUSIC)
+	execSetupSound();
+      else if (setup_mode == SETUP_MODE_CHOOSE_TOUCH_CONTROL ||
+	       setup_mode == SETUP_MODE_CHOOSE_MOVE_DISTANCE ||
+	       setup_mode == SETUP_MODE_CHOOSE_DROP_DISTANCE)
+	execSetupTouch();
       else
 	execSetupArtwork();
     }
     else
     {
-      game_status = GAME_MODE_MAIN;
+      if (game_status == GAME_MODE_LEVELNR)
+      {
+	int new_level_nr = atoi(level_number_current->identifier);
+
+	HandleMainMenu_SelectLevel(0, 0, new_level_nr);
+      }
+
+      SetGameStatus(GAME_MODE_MAIN);
 
-      DrawMainMenuExt(REDRAW_FIELD, FALSE);
+      DrawMainMenu();
     }
 
     return;
@@ -3478,17 +3864,8 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
 
   if (mx || my)		/* mouse input */
   {
-    int last_game_status = game_status;	/* save current game status */
-
-#if 0
-    /* force LEVELS draw offset on artwork setup screen */
-    game_status = GAME_MODE_LEVELS;
-#endif
-
     x = (mx - mSX) / 32;
     y = (my - mSY) / 32 - MENU_SCREEN_START_YPOS;
-
-    game_status = last_game_status;	/* restore current game status */
   }
   else if (dx || dy)	/* keyboard or scrollbar/scrollbutton input */
   {
@@ -3503,6 +3880,8 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
     if (ti->cl_cursor + dy < 0 ||
 	ti->cl_cursor + dy > num_page_entries - 1)
     {
+      boolean redraw = FALSE;
+
       if (ABS(dy) == SCROLL_PAGE)
 	step = num_page_entries - 1;
 
@@ -3514,12 +3893,7 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
 	if (ti->cl_first < 0)
 	  ti->cl_first = 0;
 
-	drawChooseTreeList(ti->cl_first, num_page_entries, ti);
-	drawChooseTreeInfo(ti->cl_first + ti->cl_cursor, ti);
-	drawChooseTreeCursor(ti->cl_cursor, TRUE);
-
-	AdjustChooseTreeScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL,
-				  ti->cl_first, ti);
+	redraw = TRUE;
       }
       else if (dy > 0 && ti->cl_first + num_page_entries < num_entries)
       {
@@ -3529,6 +3903,11 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
 	if (ti->cl_first + num_page_entries > num_entries)
 	  ti->cl_first = MAX(0, num_entries - num_page_entries);
 
+	redraw = TRUE;
+      }
+
+      if (redraw)
+      {
 	drawChooseTreeList(ti->cl_first, num_page_entries, ti);
 	drawChooseTreeInfo(ti->cl_first + ti->cl_cursor, ti);
 	drawChooseTreeCursor(ti->cl_cursor, TRUE);
@@ -3579,7 +3958,7 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
   }
 
   if (!anyScrollbarGadgetActive() &&
-      IN_VIS_FIELD(x, y) &&
+      IN_VIS_MENU(x, y) &&
       mx < screen_gadget[SCREEN_CTRL_ID_SCROLL_VERTICAL]->x &&
       y >= 0 && y < num_page_entries)
   {
@@ -3624,7 +4003,7 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
       }
       else
       {
-	FadeSetEnterScreen();
+	FadeSetEnterMenu();
 
 	node_cursor->cl_first = ti->cl_first;
 	node_cursor->cl_cursor = ti->cl_cursor;
@@ -3641,17 +4020,36 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
 
 	if (game_status == GAME_MODE_SETUP)
 	{
-	  if (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED)
+	  if (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED ||
+	      setup_mode == SETUP_MODE_CHOOSE_SCROLL_DELAY ||
+	      setup_mode == SETUP_MODE_CHOOSE_SNAPSHOT_MODE)
 	    execSetupGame();
-	  else if (setup_mode == SETUP_MODE_CHOOSE_SCREEN_MODE ||
-		   setup_mode == SETUP_MODE_CHOOSE_SCROLL_DELAY)
+	  else if (setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE ||
+		   setup_mode == SETUP_MODE_CHOOSE_SCALING_TYPE ||
+		   setup_mode == SETUP_MODE_CHOOSE_RENDERING)
 	    execSetupGraphics();
+	  else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_SIMPLE ||
+		   setup_mode == SETUP_MODE_CHOOSE_VOLUME_LOOPS ||
+		   setup_mode == SETUP_MODE_CHOOSE_VOLUME_MUSIC)
+	    execSetupSound();
+	  else if (setup_mode == SETUP_MODE_CHOOSE_TOUCH_CONTROL ||
+		   setup_mode == SETUP_MODE_CHOOSE_MOVE_DISTANCE ||
+		   setup_mode == SETUP_MODE_CHOOSE_DROP_DISTANCE)
+	    execSetupTouch();
 	  else
 	    execSetupArtwork();
 	}
 	else
 	{
-	  game_status = GAME_MODE_MAIN;
+	  if (game_status == GAME_MODE_LEVELNR)
+	  {
+	    int new_level_nr = atoi(level_number_current->identifier);
+
+	    HandleMainMenu_SelectLevel(0, 0, new_level_nr);
+	  }
+
+	  SetGameStatus(GAME_MODE_MAIN);
+
 	  DrawMainMenu();
 	}
       }
@@ -3659,27 +4057,89 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
   }
 }
 
-void DrawChooseLevel()
+void DrawChooseLevelSet()
 {
-  SetMainBackgroundImage(IMG_BACKGROUND_LEVELS);
+  FadeMenuSoundsAndMusic();
 
   DrawChooseTree(&leveldir_current);
 
-  PlayMenuSound();
-  PlayMenuMusic();
+  PlayMenuSoundsAndMusic();
 }
 
-void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
+void HandleChooseLevelSet(int mx, int my, int dx, int dy, int button)
 {
   HandleChooseTree(mx, my, dx, dy, button, &leveldir_current);
+}
+
+void DrawChooseLevelNr()
+{
+  int i;
+
+  FadeMenuSoundsAndMusic();
+
+  if (level_number != NULL)
+  {
+    freeTreeInfo(level_number);
+
+    level_number = NULL;
+  }
+
+  for (i = leveldir_current->first_level; i <= leveldir_current->last_level;i++)
+  {
+    TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_LEVEL_NR);
+    char identifier[32], name[32];
+    int value = i;
+
+    /* temporarily load level info to get level name */
+    LoadLevelInfoOnly(i);
+
+    ti->node_top = &level_number;
+    ti->sort_priority = 10000 + value;
+    ti->color = (level.no_valid_file ? FC_BLUE :
+		 LevelStats_getSolved(i) ? FC_GREEN :
+		 LevelStats_getPlayed(i) ? FC_YELLOW : FC_RED);
+
+    sprintf(identifier, "%d", value);
+    sprintf(name, "%03d: %s", value,
+	    (level.no_valid_file ? "(no file)" : level.name));
 
-  DoAnimation();
+    setString(&ti->identifier, identifier);
+    setString(&ti->name, name);
+    setString(&ti->name_sorting, name);
+
+    pushTreeInfo(&level_number, ti);
+  }
+
+  /* sort level number values to start with lowest level number */
+  sortTreeInfo(&level_number);
+
+  /* set current level number to current level number */
+  level_number_current =
+    getTreeInfoFromIdentifier(level_number, i_to_a(level_nr));
+
+  /* if that also fails, set current level number to first available level */
+  if (level_number_current == NULL)
+    level_number_current = level_number;
+
+  DrawChooseTree(&level_number_current);
+
+  PlayMenuSoundsAndMusic();
+}
+
+void HandleChooseLevelNr(int mx, int my, int dx, int dy, int button)
+{
+  HandleChooseTree(mx, my, dx, dy, button, &level_number_current);
 }
 
 void DrawHallOfFame(int highlight_position)
 {
+  int fade_mask = REDRAW_FIELD;
+
+  if (CheckIfGlobalBorderHasChanged())
+    fade_mask = REDRAW_ALL;
+
   UnmapAllGadgets();
-  FadeSoundsAndMusic();
+  FadeMenuSoundsAndMusic();
 
   /* (this is needed when called from GameEnd() after winning a game) */
   KeyboardAutoRepeatOn();
@@ -3689,34 +4149,30 @@ void DrawHallOfFame(int highlight_position)
   SetDrawDeactivationMask(REDRAW_NONE);
   SetDrawBackgroundMask(REDRAW_FIELD);
 
-  CloseDoor(DOOR_CLOSE_2);
-
   if (highlight_position < 0) 
     LoadScore(level_nr);
 
   FadeSetEnterScreen();
 
-  // printf("::: %d: %d\n", game_status, menu.enter_screen[game_status]);
+  FadeOut(fade_mask);
 
-#if 1
-  FadeOut(REDRAW_FIELD);
-#endif
+  /* needed if different viewport properties defined for scores */
+  ChangeViewportPropertiesIfNeeded();
 
-  InitAnimation();
+  PlayMenuSoundsAndMusic();
 
-  PlayMenuSound();
-  PlayMenuMusic();
+  OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
 
   HandleHallOfFame(highlight_position, 0, 0, 0, MB_MENU_INITIALIZE);
 
-#if 1
-  FadeIn(REDRAW_FIELD);
-#endif
+  DrawMaskedBorder(fade_mask);
+
+  FadeIn(fade_mask);
 }
 
 static void drawHallOfFameList(int first_entry, int highlight_position)
 {
-  int i;
+  int i, j;
 
   SetMainBackgroundImage(IMG_BACKGROUND_SCORES);
   ClearField();
@@ -3733,14 +4189,18 @@ static void drawHallOfFameList(int first_entry, int highlight_position)
     int font_nr2 = (active ? FONT_TEXT_2_ACTIVE : FONT_TEXT_2);
     int font_nr3 = (active ? FONT_TEXT_3_ACTIVE : FONT_TEXT_3);
     int font_nr4 = (active ? FONT_TEXT_4_ACTIVE : FONT_TEXT_4);
+    int dxoff = getFontDrawOffsetX(font_nr1);
     int dx1 = 3 * getFontWidth(font_nr1);
     int dx2 = dx1 + getFontWidth(font_nr1);
-    int dx3 = dx2 + 25 * getFontWidth(font_nr3);
+    int dx3 = SXSIZE - 2 * (mSX - SX + dxoff) - 5 * getFontWidth(font_nr4);
+    int num_dots = (dx3 - dx2) / getFontWidth(font_nr3);
     int sy = mSY + 64 + i * 32;
 
     DrawText(mSX, sy, int2str(entry + 1, 3), font_nr1);
     DrawText(mSX + dx1, sy, ".", font_nr1);
-    DrawText(mSX + dx2, sy, ".........................", font_nr3);
+
+    for (j = 0; j < num_dots; j++)
+      DrawText(mSX + dx2 + j * getFontWidth(font_nr3), sy, ".", font_nr3);
 
     if (!strEqual(highscore[entry].Name, EMPTY_PLAYER_NAME))
       DrawText(mSX + dx2, sy, highscore[entry].Name, font_nr2);
@@ -3757,108 +4217,699 @@ void HandleHallOfFame(int mx, int my, int dx, int dy, int button)
   static int highlight_position = 0;
   int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
 
-  if (button == MB_MENU_INITIALIZE)
-  {
-    first_entry = 0;
-    highlight_position = mx;
-    drawHallOfFameList(first_entry, highlight_position);
+  if (button == MB_MENU_INITIALIZE)
+  {
+    first_entry = 0;
+    highlight_position = mx;
+    drawHallOfFameList(first_entry, highlight_position);
+
+    return;
+  }
+
+  if (ABS(dy) == SCROLL_PAGE)		/* handle scrolling one page */
+    step = NUM_MENU_ENTRIES_ON_SCREEN - 1;
+
+  if (dy < 0)
+  {
+    if (first_entry > 0)
+    {
+      first_entry -= step;
+      if (first_entry < 0)
+	first_entry = 0;
+
+      drawHallOfFameList(first_entry, highlight_position);
+    }
+  }
+  else if (dy > 0)
+  {
+    if (first_entry + NUM_MENU_ENTRIES_ON_SCREEN < MAX_SCORE_ENTRIES)
+    {
+      first_entry += step;
+      if (first_entry + NUM_MENU_ENTRIES_ON_SCREEN > MAX_SCORE_ENTRIES)
+	first_entry = MAX(0, MAX_SCORE_ENTRIES - NUM_MENU_ENTRIES_ON_SCREEN);
+
+      drawHallOfFameList(first_entry, highlight_position);
+    }
+  }
+  else if (button == MB_MENU_LEAVE)
+  {
+    PlaySound(SND_MENU_ITEM_SELECTING);
+
+    FadeSound(SND_BACKGROUND_SCORES);
+
+    SetGameStatus(GAME_MODE_MAIN);
+
+    DrawMainMenu();
+  }
+  else if (button == MB_MENU_CHOICE)
+  {
+    PlaySound(SND_MENU_ITEM_SELECTING);
+
+    FadeSound(SND_BACKGROUND_SCORES);
+
+    SetGameStatus(GAME_MODE_MAIN);
+
+    DrawMainMenu();
+  }
+
+  if (game_status == GAME_MODE_SCORES)
+    PlayMenuSoundIfLoop();
+}
+
+
+/* ========================================================================= */
+/* setup screen functions                                                    */
+/* ========================================================================= */
+
+static struct TokenInfo *setup_info;
+static int num_setup_info;	/* number of setup entries shown on screen */
+static int max_setup_info;	/* total number of setup entries in list */
+
+static char *window_size_text;
+static char *scaling_type_text;
+static char *rendering_mode_text;
+static char *scroll_delay_text;
+static char *snapshot_mode_text;
+static char *game_speed_text;
+static char *graphics_set_name;
+static char *sounds_set_name;
+static char *music_set_name;
+static char *volume_simple_text;
+static char *volume_loops_text;
+static char *volume_music_text;
+static char *touch_controls_text;
+static char *move_distance_text;
+static char *drop_distance_text;
+
+static void execSetupMain()
+{
+  setup_mode = SETUP_MODE_MAIN;
+
+  DrawSetupScreen();
+}
+
+static void execSetupGame_setGameSpeeds()
+{
+  if (game_speeds == NULL)
+  {
+    int i;
+
+    for (i = 0; game_speeds_list[i].value != -1; i++)
+    {
+      TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+      char identifier[32], name[32];
+      int value = game_speeds_list[i].value;
+      char *text = game_speeds_list[i].text;
+
+      ti->node_top = &game_speeds;
+      ti->sort_priority = 10000 - value;
+
+      sprintf(identifier, "%d", value);
+      sprintf(name, "%s", text);
+
+      setString(&ti->identifier, identifier);
+      setString(&ti->name, name);
+      setString(&ti->name_sorting, name);
+      setString(&ti->infotext, "Game Speed");
+
+      pushTreeInfo(&game_speeds, ti);
+    }
+
+    /* sort game speed values to start with slowest game speed */
+    sortTreeInfo(&game_speeds);
+
+    /* set current game speed to configured game speed value */
+    game_speed_current =
+      getTreeInfoFromIdentifier(game_speeds, i_to_a(setup.game_frame_delay));
+
+    /* if that fails, set current game speed to reliable default value */
+    if (game_speed_current == NULL)
+      game_speed_current =
+	getTreeInfoFromIdentifier(game_speeds, i_to_a(GAME_FRAME_DELAY));
+
+    /* if that also fails, set current game speed to first available speed */
+    if (game_speed_current == NULL)
+      game_speed_current = game_speeds;
+  }
+
+  setup.game_frame_delay = atoi(game_speed_current->identifier);
+
+  /* needed for displaying game speed text instead of identifier */
+  game_speed_text = game_speed_current->name;
+}
+
+static void execSetupGame_setScrollDelays()
+{
+  if (scroll_delays == NULL)
+  {
+    int i;
+
+    for (i = 0; scroll_delays_list[i].value != -1; i++)
+    {
+      TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+      char identifier[32], name[32];
+      int value = scroll_delays_list[i].value;
+      char *text = scroll_delays_list[i].text;
+
+      ti->node_top = &scroll_delays;
+      ti->sort_priority = value;
+
+      sprintf(identifier, "%d", value);
+      sprintf(name, "%s", text);
+
+      setString(&ti->identifier, identifier);
+      setString(&ti->name, name);
+      setString(&ti->name_sorting, name);
+      setString(&ti->infotext, "Scroll Delay");
+
+      pushTreeInfo(&scroll_delays, ti);
+    }
+
+    /* sort scroll delay values to start with lowest scroll delay value */
+    sortTreeInfo(&scroll_delays);
+
+    /* set current scroll delay value to configured scroll delay value */
+    scroll_delay_current =
+      getTreeInfoFromIdentifier(scroll_delays,i_to_a(setup.scroll_delay_value));
+
+    /* if that fails, set current scroll delay to reliable default value */
+    if (scroll_delay_current == NULL)
+      scroll_delay_current =
+	getTreeInfoFromIdentifier(scroll_delays, i_to_a(STD_SCROLL_DELAY));
+
+    /* if that also fails, set current scroll delay to first available value */
+    if (scroll_delay_current == NULL)
+      scroll_delay_current = scroll_delays;
+  }
+
+  setup.scroll_delay_value = atoi(scroll_delay_current->identifier);
+
+  /* needed for displaying scroll delay text instead of identifier */
+  scroll_delay_text = scroll_delay_current->name;
+}
+
+static void execSetupGame_setSnapshotModes()
+{
+  if (snapshot_modes == NULL)
+  {
+    int i;
+
+    for (i = 0; snapshot_modes_list[i].value != NULL; i++)
+    {
+      TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+      char identifier[32], name[32];
+      char *value = snapshot_modes_list[i].value;
+      char *text = snapshot_modes_list[i].text;
+
+      ti->node_top = &snapshot_modes;
+      ti->sort_priority = i;
+
+      sprintf(identifier, "%s", value);
+      sprintf(name, "%s", text);
+
+      setString(&ti->identifier, identifier);
+      setString(&ti->name, name);
+      setString(&ti->name_sorting, name);
+      setString(&ti->infotext, "Snapshot Mode");
+
+      pushTreeInfo(&snapshot_modes, ti);
+    }
+
+    /* sort snapshot mode values to start with lowest snapshot mode value */
+    sortTreeInfo(&snapshot_modes);
+
+    /* set current snapshot mode value to configured snapshot mode value */
+    snapshot_mode_current =
+      getTreeInfoFromIdentifier(snapshot_modes, setup.engine_snapshot_mode);
+
+    /* if that fails, set current snapshot mode to reliable default value */
+    if (snapshot_mode_current == NULL)
+      snapshot_mode_current =
+	getTreeInfoFromIdentifier(snapshot_modes, STR_SNAPSHOT_MODE_DEFAULT);
+
+    /* if that also fails, set current snapshot mode to first available value */
+    if (snapshot_mode_current == NULL)
+      snapshot_mode_current = snapshot_modes;
+  }
+
+  setup.engine_snapshot_mode = snapshot_mode_current->identifier;
+
+  /* needed for displaying snapshot mode text instead of identifier */
+  snapshot_mode_text = snapshot_mode_current->name;
+}
+
+static void execSetupGame()
+{
+  execSetupGame_setGameSpeeds();
+  execSetupGame_setScrollDelays();
+  execSetupGame_setSnapshotModes();
+
+  setup_mode = SETUP_MODE_GAME;
+
+  DrawSetupScreen();
+}
+
+static void execSetupChooseGameSpeed()
+{
+  setup_mode = SETUP_MODE_CHOOSE_GAME_SPEED;
+
+  DrawSetupScreen();
+}
+
+static void execSetupChooseScrollDelay()
+{
+  setup_mode = SETUP_MODE_CHOOSE_SCROLL_DELAY;
+
+  DrawSetupScreen();
+}
+
+static void execSetupChooseSnapshotMode()
+{
+  setup_mode = SETUP_MODE_CHOOSE_SNAPSHOT_MODE;
+
+  DrawSetupScreen();
+}
+
+static void execSetupEditor()
+{
+  setup_mode = SETUP_MODE_EDITOR;
+
+  DrawSetupScreen();
+}
+
+static void execSetupGraphics_setWindowSizes(boolean update_list)
+{
+  if (window_sizes != NULL && update_list)
+  {
+    freeTreeInfo(window_sizes);
+
+    window_sizes = NULL;
+  }
+
+  if (window_sizes == NULL)
+  {
+    boolean current_window_size_found = FALSE;
+    int i;
+
+    for (i = 0; window_sizes_list[i].value != -1; i++)
+    {
+      TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+      char identifier[32], name[32];
+      int value = window_sizes_list[i].value;
+      char *text = window_sizes_list[i].text;
+
+      ti->node_top = &window_sizes;
+      ti->sort_priority = value;
+
+      sprintf(identifier, "%d", value);
+      sprintf(name, "%s", text);
+
+      setString(&ti->identifier, identifier);
+      setString(&ti->name, name);
+      setString(&ti->name_sorting, name);
+      setString(&ti->infotext, "Window Scaling");
+
+      pushTreeInfo(&window_sizes, ti);
+
+      if (value == setup.window_scaling_percent)
+	current_window_size_found = TRUE;
+    }
+
+    if (!current_window_size_found)
+    {
+      // add entry for non-preset window scaling value
+
+      TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+      char identifier[32], name[32];
+      int value = setup.window_scaling_percent;
+
+      ti->node_top = &window_sizes;
+      ti->sort_priority = value;
+
+      sprintf(identifier, "%d", value);
+      sprintf(name, "%d %% (Current)", value);
+
+      setString(&ti->identifier, identifier);
+      setString(&ti->name, name);
+      setString(&ti->name_sorting, name);
+      setString(&ti->infotext, "Window Scaling");
+
+      pushTreeInfo(&window_sizes, ti);
+    }
+
+    /* sort window size values to start with lowest window size value */
+    sortTreeInfo(&window_sizes);
+
+    /* set current window size value to configured window size value */
+    window_size_current =
+      getTreeInfoFromIdentifier(window_sizes,
+				i_to_a(setup.window_scaling_percent));
+
+    /* if that fails, set current window size to reliable default value */
+    if (window_size_current == NULL)
+      window_size_current =
+	getTreeInfoFromIdentifier(window_sizes,
+				  i_to_a(STD_WINDOW_SCALING_PERCENT));
+
+    /* if that also fails, set current window size to first available value */
+    if (window_size_current == NULL)
+      window_size_current = window_sizes;
+  }
+
+  setup.window_scaling_percent = atoi(window_size_current->identifier);
+
+  /* needed for displaying window size text instead of identifier */
+  window_size_text = window_size_current->name;
+}
+
+static void execSetupGraphics_setScalingTypes()
+{
+  if (scaling_types == NULL)
+  {
+    int i;
+
+    for (i = 0; scaling_types_list[i].value != NULL; i++)
+    {
+      TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+      char identifier[32], name[32];
+      char *value = scaling_types_list[i].value;
+      char *text = scaling_types_list[i].text;
+
+      ti->node_top = &scaling_types;
+      ti->sort_priority = i;
+
+      sprintf(identifier, "%s", value);
+      sprintf(name, "%s", text);
+
+      setString(&ti->identifier, identifier);
+      setString(&ti->name, name);
+      setString(&ti->name_sorting, name);
+      setString(&ti->infotext, "Anti-Aliasing");
+
+      pushTreeInfo(&scaling_types, ti);
+    }
+
+    /* sort scaling type values to start with lowest scaling type value */
+    sortTreeInfo(&scaling_types);
+
+    /* set current scaling type value to configured scaling type value */
+    scaling_type_current =
+      getTreeInfoFromIdentifier(scaling_types, setup.window_scaling_quality);
+
+    /* if that fails, set current scaling type to reliable default value */
+    if (scaling_type_current == NULL)
+      scaling_type_current =
+	getTreeInfoFromIdentifier(scaling_types, SCALING_QUALITY_DEFAULT);
+
+    /* if that also fails, set current scaling type to first available value */
+    if (scaling_type_current == NULL)
+      scaling_type_current = scaling_types;
+  }
+
+  setup.window_scaling_quality = scaling_type_current->identifier;
+
+  /* needed for displaying scaling type text instead of identifier */
+  scaling_type_text = scaling_type_current->name;
+}
+
+static void execSetupGraphics_setRenderingModes()
+{
+  if (rendering_modes == NULL)
+  {
+    int i;
+
+    for (i = 0; rendering_modes_list[i].value != NULL; i++)
+    {
+      TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+      char identifier[32], name[32];
+      char *value = rendering_modes_list[i].value;
+      char *text = rendering_modes_list[i].text;
+
+      ti->node_top = &rendering_modes;
+      ti->sort_priority = i;
+
+      sprintf(identifier, "%s", value);
+      sprintf(name, "%s", text);
+
+      setString(&ti->identifier, identifier);
+      setString(&ti->name, name);
+      setString(&ti->name_sorting, name);
+      setString(&ti->infotext, "Special Rendering");
+
+      pushTreeInfo(&rendering_modes, ti);
+    }
+
+    /* sort rendering mode values to start with lowest rendering mode value */
+    sortTreeInfo(&rendering_modes);
+
+    /* set current rendering mode value to configured rendering mode value */
+    rendering_mode_current =
+      getTreeInfoFromIdentifier(rendering_modes, setup.screen_rendering_mode);
+
+    /* if that fails, set current rendering mode to reliable default value */
+    if (rendering_mode_current == NULL)
+      rendering_mode_current =
+	getTreeInfoFromIdentifier(rendering_modes,
+				  STR_SPECIAL_RENDERING_DEFAULT);
+
+    /* if that also fails, set current rendering mode to first available one */
+    if (rendering_mode_current == NULL)
+      rendering_mode_current = rendering_modes;
+  }
+
+  setup.screen_rendering_mode = rendering_mode_current->identifier;
+
+  /* needed for displaying rendering mode text instead of identifier */
+  rendering_mode_text = rendering_mode_current->name;
+}
+
+static void execSetupGraphics()
+{
+  // update "setup.window_scaling_percent" from list selection
+  // (in this case, window scaling was changed on setup screen)
+  if (setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE)
+    execSetupGraphics_setWindowSizes(FALSE);
+
+  // update list selection from "setup.window_scaling_percent"
+  // (window scaling may have changed by resizing the window)
+  execSetupGraphics_setWindowSizes(TRUE);
+
+  execSetupGraphics_setScalingTypes();
+  execSetupGraphics_setRenderingModes();
+
+  setup_mode = SETUP_MODE_GRAPHICS;
+
+  DrawSetupScreen();
+
+#if defined(TARGET_SDL2)
+  // window scaling may have changed at this point
+  ToggleFullscreenOrChangeWindowScalingIfNeeded();
+
+  // window scaling quality may have changed at this point
+  if (!strEqual(setup.window_scaling_quality, video.window_scaling_quality))
+    SDLSetWindowScalingQuality(setup.window_scaling_quality);
+
+  // screen rendering mode may have changed at this point
+  SDLSetScreenRenderingMode(setup.screen_rendering_mode);
+#endif
+}
+
+#if defined(TARGET_SDL2) && !defined(PLATFORM_ANDROID)
+static void execSetupChooseWindowSize()
+{
+  setup_mode = SETUP_MODE_CHOOSE_WINDOW_SIZE;
+
+  DrawSetupScreen();
+}
+
+static void execSetupChooseScalingType()
+{
+  setup_mode = SETUP_MODE_CHOOSE_SCALING_TYPE;
+
+  DrawSetupScreen();
+}
+
+static void execSetupChooseRenderingMode()
+{
+  setup_mode = SETUP_MODE_CHOOSE_RENDERING;
+
+  DrawSetupScreen();
+}
+#endif
+
+static void execSetupChooseVolumeSimple()
+{
+  setup_mode = SETUP_MODE_CHOOSE_VOLUME_SIMPLE;
+
+  DrawSetupScreen();
+}
+
+static void execSetupChooseVolumeLoops()
+{
+  setup_mode = SETUP_MODE_CHOOSE_VOLUME_LOOPS;
+
+  DrawSetupScreen();
+}
+
+static void execSetupChooseVolumeMusic()
+{
+  setup_mode = SETUP_MODE_CHOOSE_VOLUME_MUSIC;
+
+  DrawSetupScreen();
+}
+
+static void execSetupSound()
+{
+  if (volumes_simple == NULL)
+  {
+    boolean current_volume_simple_found = FALSE;
+    int i;
+
+    for (i = 0; volumes_list[i].value != -1; i++)
+    {
+      TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+      char identifier[32], name[32];
+      int value = volumes_list[i].value;
+      char *text = volumes_list[i].text;
+
+      ti->node_top = &volumes_simple;
+      ti->sort_priority = value;
+
+      sprintf(identifier, "%d", value);
+      sprintf(name, "%s", text);
+
+      setString(&ti->identifier, identifier);
+      setString(&ti->name, name);
+      setString(&ti->name_sorting, name);
+      setString(&ti->infotext, "Sound Volume");
+
+      pushTreeInfo(&volumes_simple, ti);
+
+      if (value == setup.volume_simple)
+        current_volume_simple_found = TRUE;
+    }
+
+    if (!current_volume_simple_found)
+    {
+      // add entry for non-preset volume value
+
+      TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+      char identifier[32], name[32];
+      int value = setup.volume_simple;
+
+      ti->node_top = &volumes_simple;
+      ti->sort_priority = value;
+
+      sprintf(identifier, "%d", value);
+      sprintf(name, "%d %% (Current)", value);
+
+      setString(&ti->identifier, identifier);
+      setString(&ti->name, name);
+      setString(&ti->name_sorting, name);
+      setString(&ti->infotext, "Sound Volume");
+
+      pushTreeInfo(&volumes_simple, ti);
+    }
 
-    return;
-  }
+    /* sort volume values to start with lowest volume value */
+    sortTreeInfo(&volumes_simple);
 
-  if (ABS(dy) == SCROLL_PAGE)		/* handle scrolling one page */
-    step = NUM_MENU_ENTRIES_ON_SCREEN - 1;
+    /* set current volume value to configured volume value */
+    volume_simple_current =
+      getTreeInfoFromIdentifier(volumes_simple,i_to_a(setup.volume_simple));
 
-  if (dy < 0)
-  {
-    if (first_entry > 0)
-    {
-      first_entry -= step;
-      if (first_entry < 0)
-	first_entry = 0;
+    /* if that fails, set current volume to reliable default value */
+    if (volume_simple_current == NULL)
+      volume_simple_current =
+	getTreeInfoFromIdentifier(volumes_simple, i_to_a(100));
 
-      drawHallOfFameList(first_entry, highlight_position);
-    }
+    /* if that also fails, set current volume to first available value */
+    if (volume_simple_current == NULL)
+      volume_simple_current = volumes_simple;
   }
-  else if (dy > 0)
-  {
-    if (first_entry + NUM_MENU_ENTRIES_ON_SCREEN < MAX_SCORE_ENTRIES)
-    {
-      first_entry += step;
-      if (first_entry + NUM_MENU_ENTRIES_ON_SCREEN > MAX_SCORE_ENTRIES)
-	first_entry = MAX(0, MAX_SCORE_ENTRIES - NUM_MENU_ENTRIES_ON_SCREEN);
 
-      drawHallOfFameList(first_entry, highlight_position);
-    }
-  }
-  else if (button == MB_MENU_LEAVE)
+  if (volumes_loops == NULL)
   {
-    PlaySound(SND_MENU_ITEM_SELECTING);
+    boolean current_volume_loops_found = FALSE;
+    int i;
 
-    FadeSound(SND_BACKGROUND_SCORES);
+    for (i = 0; volumes_list[i].value != -1; i++)
+    {
+      TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+      char identifier[32], name[32];
+      int value = volumes_list[i].value;
+      char *text = volumes_list[i].text;
 
-    game_status = GAME_MODE_MAIN;
+      ti->node_top = &volumes_loops;
+      ti->sort_priority = value;
 
-    DrawMainMenu();
-  }
-  else if (button == MB_MENU_CHOICE)
-  {
-    PlaySound(SND_MENU_ITEM_SELECTING);
+      sprintf(identifier, "%d", value);
+      sprintf(name, "%s", text);
 
-    FadeSound(SND_BACKGROUND_SCORES);
+      setString(&ti->identifier, identifier);
+      setString(&ti->name, name);
+      setString(&ti->name_sorting, name);
+      setString(&ti->infotext, "Loops Volume");
 
-#if 0
-    FadeOut(REDRAW_FIELD);
-#endif
+      pushTreeInfo(&volumes_loops, ti);
 
-    game_status = GAME_MODE_MAIN;
+      if (value == setup.volume_loops)
+        current_volume_loops_found = TRUE;
+    }
 
-    DrawAndFadeInMainMenu(REDRAW_FIELD);
-  }
+    if (!current_volume_loops_found)
+    {
+      // add entry for non-preset volume value
 
-  if (game_status == GAME_MODE_SCORES)
-    PlayMenuSoundIfLoop();
+      TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+      char identifier[32], name[32];
+      int value = setup.volume_loops;
 
-  DoAnimation();
-}
+      ti->node_top = &volumes_loops;
+      ti->sort_priority = value;
 
+      sprintf(identifier, "%d", value);
+      sprintf(name, "%d %% (Current)", value);
 
-/* ========================================================================= */
-/* setup screen functions                                                    */
-/* ========================================================================= */
+      setString(&ti->identifier, identifier);
+      setString(&ti->name, name);
+      setString(&ti->name_sorting, name);
+      setString(&ti->infotext, "Loops Volume");
 
-static struct TokenInfo *setup_info;
-static int num_setup_info;
+      pushTreeInfo(&volumes_loops, ti);
+    }
 
-static char *screen_mode_text;
-static char *scroll_delay_text;
-static char *game_speed_text;
-static char *graphics_set_name;
-static char *sounds_set_name;
-static char *music_set_name;
+    /* sort volume values to start with lowest volume value */
+    sortTreeInfo(&volumes_loops);
 
-static void execSetupMain()
-{
-  setup_mode = SETUP_MODE_MAIN;
+    /* set current volume value to configured volume value */
+    volume_loops_current =
+      getTreeInfoFromIdentifier(volumes_loops,i_to_a(setup.volume_loops));
 
-  DrawSetupScreen();
-}
+    /* if that fails, set current volume to reliable default value */
+    if (volume_loops_current == NULL)
+      volume_loops_current =
+	getTreeInfoFromIdentifier(volumes_loops, i_to_a(100));
 
-static void execSetupGame()
-{
-  if (game_speeds == NULL)
+    /* if that also fails, set current volume to first available value */
+    if (volume_loops_current == NULL)
+      volume_loops_current = volumes_loops;
+  }
+
+  if (volumes_music == NULL)
   {
+    boolean current_volume_music_found = FALSE;
     int i;
 
-    for (i = 0; game_speeds_list[i].value != -1; i++)
+    for (i = 0; volumes_list[i].value != -1; i++)
     {
       TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
       char identifier[32], name[32];
-      int value = game_speeds_list[i].value;
-      char *text = game_speeds_list[i].text;
+      int value = volumes_list[i].value;
+      char *text = volumes_list[i].text;
 
-      ti->node_top = &game_speeds;
-      ti->sort_priority = 10000 - value;
+      ti->node_top = &volumes_music;
+      ti->sort_priority = value;
 
       sprintf(identifier, "%d", value);
       sprintf(name, "%s", text);
@@ -3866,123 +4917,144 @@ static void execSetupGame()
       setString(&ti->identifier, identifier);
       setString(&ti->name, name);
       setString(&ti->name_sorting, name);
-      setString(&ti->infotext, "Game Speed");
+      setString(&ti->infotext, "Music Volume");
 
-      pushTreeInfo(&game_speeds, ti);
+      pushTreeInfo(&volumes_music, ti);
+
+      if (value == setup.volume_music)
+        current_volume_music_found = TRUE;
     }
 
-    /* sort game speed values to start with slowest game speed */
-    sortTreeInfo(&game_speeds);
+    if (!current_volume_music_found)
+    {
+      // add entry for non-preset volume value
 
-    /* set current game speed to configured game speed value */
-    game_speed_current =
-      getTreeInfoFromIdentifier(game_speeds, i_to_a(setup.game_frame_delay));
+      TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+      char identifier[32], name[32];
+      int value = setup.volume_music;
 
-    /* if that fails, set current game speed to reliable default value */
-    if (game_speed_current == NULL)
-      game_speed_current =
-	getTreeInfoFromIdentifier(game_speeds, i_to_a(GAME_FRAME_DELAY));
+      ti->node_top = &volumes_music;
+      ti->sort_priority = value;
 
-    /* if that also fails, set current game speed to first available speed */
-    if (game_speed_current == NULL)
-      game_speed_current = game_speeds;
+      sprintf(identifier, "%d", value);
+      sprintf(name, "%d %% (Current)", value);
+
+      setString(&ti->identifier, identifier);
+      setString(&ti->name, name);
+      setString(&ti->name_sorting, name);
+      setString(&ti->infotext, "Music Volume");
+
+      pushTreeInfo(&volumes_music, ti);
+    }
+
+    /* sort volume values to start with lowest volume value */
+    sortTreeInfo(&volumes_music);
+
+    /* set current volume value to configured volume value */
+    volume_music_current =
+      getTreeInfoFromIdentifier(volumes_music,i_to_a(setup.volume_music));
+
+    /* if that fails, set current volume to reliable default value */
+    if (volume_music_current == NULL)
+      volume_music_current =
+	getTreeInfoFromIdentifier(volumes_music, i_to_a(100));
+
+    /* if that also fails, set current volume to first available value */
+    if (volume_music_current == NULL)
+      volume_music_current = volumes_music;
   }
 
-  setup.game_frame_delay = atoi(game_speed_current->identifier);
+  setup.volume_simple = atoi(volume_simple_current->identifier);
+  setup.volume_loops  = atoi(volume_loops_current->identifier);
+  setup.volume_music  = atoi(volume_music_current->identifier);
 
-  /* needed for displaying game speed text instead of identifier */
-  game_speed_text = game_speed_current->name;
+  /* needed for displaying volume text instead of identifier */
+  volume_simple_text = volume_simple_current->name;
+  volume_loops_text = volume_loops_current->name;
+  volume_music_text = volume_music_current->name;
 
-  setup_mode = SETUP_MODE_GAME;
+  setup_mode = SETUP_MODE_SOUND;
 
   DrawSetupScreen();
 }
 
-static void execSetupChooseGameSpeed()
+static void execSetupChooseTouchControls()
 {
-  setup_mode = SETUP_MODE_CHOOSE_GAME_SPEED;
+  setup_mode = SETUP_MODE_CHOOSE_TOUCH_CONTROL;
 
   DrawSetupScreen();
 }
 
-static void execSetupEditor()
+static void execSetupChooseMoveDistance()
 {
-  setup_mode = SETUP_MODE_EDITOR;
+  setup_mode = SETUP_MODE_CHOOSE_MOVE_DISTANCE;
 
   DrawSetupScreen();
 }
 
-static void execSetupGraphics()
+static void execSetupChooseDropDistance()
+{
+  setup_mode = SETUP_MODE_CHOOSE_DROP_DISTANCE;
+
+  DrawSetupScreen();
+}
+
+static void execSetupTouch()
 {
-  if (video.fullscreen_available && screen_modes == NULL)
+  if (touch_controls == NULL)
   {
     int i;
 
-    for (i = 0; video.fullscreen_modes[i].width != -1; i++)
+    for (i = 0; touch_controls_list[i].value != NULL; i++)
     {
       TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
       char identifier[32], name[32];
-      int x = video.fullscreen_modes[i].width;
-      int y = video.fullscreen_modes[i].height;
-      int xx, yy;
+      char *value = touch_controls_list[i].value;
+      char *text = touch_controls_list[i].text;
 
-      get_aspect_ratio_from_screen_mode(&video.fullscreen_modes[i], &xx, &yy);
+      ti->node_top = &touch_controls;
+      ti->sort_priority = i;
 
-      ti->node_top = &screen_modes;
-      ti->sort_priority = x * 10000 + y;
-
-      sprintf(identifier, "%dx%d", x, y);
-      sprintf(name, "%d x %d [%d:%d]", x, y, xx, yy);
+      sprintf(identifier, "%s", value);
+      sprintf(name, "%s", text);
 
       setString(&ti->identifier, identifier);
       setString(&ti->name, name);
       setString(&ti->name_sorting, name);
-      setString(&ti->infotext, "Fullscreen Mode");
+      setString(&ti->infotext, "Control Type");
 
-      pushTreeInfo(&screen_modes, ti);
+      pushTreeInfo(&touch_controls, ti);
     }
 
-    /* sort fullscreen modes to start with lowest available screen resolution */
-    sortTreeInfo(&screen_modes);
+    /* sort touch control values to start with lowest touch control value */
+    sortTreeInfo(&touch_controls);
 
-    /* set current screen mode for fullscreen mode to configured setup value */
-    screen_mode_current = getTreeInfoFromIdentifier(screen_modes,
-						    setup.fullscreen_mode);
+    /* set current touch control value to configured touch control value */
+    touch_control_current =
+      getTreeInfoFromIdentifier(touch_controls, setup.touch.control_type);
 
-    /* if that fails, set current screen mode to reliable default value */
-    if (screen_mode_current == NULL)
-      screen_mode_current = getTreeInfoFromIdentifier(screen_modes,
-						      DEFAULT_FULLSCREEN_MODE);
+    /* if that fails, set current touch control to reliable default value */
+    if (touch_control_current == NULL)
+      touch_control_current =
+	getTreeInfoFromIdentifier(touch_controls, TOUCH_CONTROL_DEFAULT);
 
-    /* if that also fails, set current screen mode to first available mode */
-    if (screen_mode_current == NULL)
-      screen_mode_current = screen_modes;
-
-    if (screen_mode_current == NULL)
-      video.fullscreen_available = FALSE;
-  }
-
-  if (video.fullscreen_available)
-  {
-    setup.fullscreen_mode = screen_mode_current->identifier;
-
-    /* needed for displaying screen mode name instead of identifier */
-    screen_mode_text = screen_mode_current->name;
+    /* if that also fails, set current touch control to first available value */
+    if (touch_control_current == NULL)
+      touch_control_current = touch_controls;
   }
 
-#if 1
-  if (scroll_delays == NULL)
+  if (move_distances == NULL)
   {
     int i;
 
-    for (i = 0; scroll_delays_list[i].value != -1; i++)
+    for (i = 0; distances_list[i].value != -1; i++)
     {
       TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
       char identifier[32], name[32];
-      int value = scroll_delays_list[i].value;
-      char *text = scroll_delays_list[i].text;
+      int value = distances_list[i].value;
+      char *text = distances_list[i].text;
 
-      ti->node_top = &scroll_delays;
+      ti->node_top = &move_distances;
       ti->sort_priority = value;
 
       sprintf(identifier, "%d", value);
@@ -3991,58 +5063,82 @@ static void execSetupGraphics()
       setString(&ti->identifier, identifier);
       setString(&ti->name, name);
       setString(&ti->name_sorting, name);
-      setString(&ti->infotext, "Scroll Delay");
+      setString(&ti->infotext, "Move Distance");
 
-      pushTreeInfo(&scroll_delays, ti);
+      pushTreeInfo(&move_distances, ti);
     }
 
-    /* sort scroll delay values to start with lowest scroll delay value */
-    sortTreeInfo(&scroll_delays);
+    /* sort distance values to start with lowest distance value */
+    sortTreeInfo(&move_distances);
 
-    /* set current scroll delay value to configured scroll delay value */
-    scroll_delay_current =
-      getTreeInfoFromIdentifier(scroll_delays,i_to_a(setup.scroll_delay_value));
+    /* set current distance value to configured distance value */
+    move_distance_current =
+      getTreeInfoFromIdentifier(move_distances,
+				i_to_a(setup.touch.move_distance));
 
-    /* if that fails, set current scroll delay to reliable default value */
-    if (scroll_delay_current == NULL)
-      scroll_delay_current =
-	getTreeInfoFromIdentifier(scroll_delays, i_to_a(STD_SCROLL_DELAY));
+    /* if that fails, set current distance to reliable default value */
+    if (move_distance_current == NULL)
+      move_distance_current =
+	getTreeInfoFromIdentifier(move_distances, i_to_a(1));
 
-    /* if that also fails, set current scroll delay to first available value */
-    if (scroll_delay_current == NULL)
-      scroll_delay_current = scroll_delays;
+    /* if that also fails, set current distance to first available value */
+    if (move_distance_current == NULL)
+      move_distance_current = move_distances;
   }
 
-  setup.scroll_delay_value = atoi(scroll_delay_current->identifier);
+  if (drop_distances == NULL)
+  {
+    int i;
 
-  /* needed for displaying scroll delay text instead of identifier */
-  scroll_delay_text = scroll_delay_current->name;
-#endif
+    for (i = 0; distances_list[i].value != -1; i++)
+    {
+      TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+      char identifier[32], name[32];
+      int value = distances_list[i].value;
+      char *text = distances_list[i].text;
 
-  setup_mode = SETUP_MODE_GRAPHICS;
-  DrawSetupScreen();
-}
+      ti->node_top = &drop_distances;
+      ti->sort_priority = value;
 
-static void execSetupChooseScreenMode()
-{
-  if (!video.fullscreen_available)
-    return;
+      sprintf(identifier, "%d", value);
+      sprintf(name, "%s", text);
 
-  setup_mode = SETUP_MODE_CHOOSE_SCREEN_MODE;
+      setString(&ti->identifier, identifier);
+      setString(&ti->name, name);
+      setString(&ti->name_sorting, name);
+      setString(&ti->infotext, "Drop Distance");
 
-  DrawSetupScreen();
-}
+      pushTreeInfo(&drop_distances, ti);
+    }
 
-static void execSetupChooseScrollDelay()
-{
-  setup_mode = SETUP_MODE_CHOOSE_SCROLL_DELAY;
+    /* sort distance values to start with lowest distance value */
+    sortTreeInfo(&drop_distances);
 
-  DrawSetupScreen();
-}
+    /* set current distance value to configured distance value */
+    drop_distance_current =
+      getTreeInfoFromIdentifier(drop_distances,
+				i_to_a(setup.touch.drop_distance));
 
-static void execSetupSound()
-{
-  setup_mode = SETUP_MODE_SOUND;
+    /* if that fails, set current distance to reliable default value */
+    if (drop_distance_current == NULL)
+      drop_distance_current =
+	getTreeInfoFromIdentifier(drop_distances, i_to_a(1));
+
+    /* if that also fails, set current distance to first available value */
+    if (drop_distance_current == NULL)
+      drop_distance_current = drop_distances;
+  }
+
+  setup.touch.control_type = touch_control_current->identifier;
+  setup.touch.move_distance = atoi(move_distance_current->identifier);
+  setup.touch.drop_distance = atoi(drop_distance_current->identifier);
+
+  /* needed for displaying volume text instead of identifier */
+  touch_controls_text = touch_control_current->name;
+  move_distance_text = move_distance_current->name;
+  drop_distance_text = drop_distance_current->name;
+
+  setup_mode = SETUP_MODE_TOUCH;
 
   DrawSetupScreen();
 }
@@ -4094,12 +5190,14 @@ static void execSetupChooseMusic()
   DrawSetupScreen();
 }
 
+#if !defined(PLATFORM_ANDROID)
 static void execSetupInput()
 {
   setup_mode = SETUP_MODE_INPUT;
 
   DrawSetupScreen();
 }
+#endif
 
 static void execSetupShortcuts()
 {
@@ -4145,9 +5243,9 @@ static void execSetupShortcuts5()
 
 static void execExitSetup()
 {
-  game_status = GAME_MODE_MAIN;
+  SetGameStatus(GAME_MODE_MAIN);
 
-  DrawMainMenuExt(REDRAW_FIELD, FALSE);
+  DrawMainMenu();
 }
 
 static void execSaveAndExitSetup()
@@ -4163,7 +5261,12 @@ static struct TokenInfo setup_info_main[] =
   { TYPE_ENTER_MENU,	execSetupGraphics,	"Graphics"		},
   { TYPE_ENTER_MENU,	execSetupSound,		"Sound & Music"		},
   { TYPE_ENTER_MENU,	execSetupArtwork,	"Custom Artwork"	},
+#if !defined(PLATFORM_ANDROID)
   { TYPE_ENTER_MENU,	execSetupInput,		"Input Devices"		},
+  { TYPE_ENTER_MENU,	execSetupTouch,		"Touch Controls"	},
+#else
+  { TYPE_ENTER_MENU,	execSetupTouch,		"Touch Controls"	},
+#endif
   { TYPE_ENTER_MENU,	execSetupShortcuts,	"Key Shortcuts"		},
   { TYPE_EMPTY,		NULL,			""			},
   { TYPE_LEAVE_MENU,	execExitSetup, 		"Exit"			},
@@ -4182,6 +5285,13 @@ static struct TokenInfo setup_info_game[] =
   { TYPE_SWITCH,	&setup.autorecord,	"Auto-Record Tapes:"	},
   { TYPE_ENTER_LIST,	execSetupChooseGameSpeed, "Game Speed:"		},
   { TYPE_STRING,	&game_speed_text,	""			},
+#if 1
+  { TYPE_ENTER_LIST,	execSetupChooseScrollDelay, "Scroll Delay:"	},
+  { TYPE_STRING,	&scroll_delay_text,	""			},
+#endif
+  { TYPE_ENTER_LIST, execSetupChooseSnapshotMode,"Game Engine Snapshot Mode:" },
+  { TYPE_STRING,	&snapshot_mode_text,	""			},
+  { TYPE_SWITCH,	&setup.show_snapshot_buttons,"Show Snapshot Buttons:" },
   { TYPE_EMPTY,		NULL,			""			},
   { TYPE_LEAVE_MENU,	execSetupMain, 		"Back"			},
 
@@ -4223,24 +5333,27 @@ static struct TokenInfo setup_info_editor[] =
 
 static struct TokenInfo setup_info_graphics[] =
 {
+#if defined(TARGET_SDL2) && !defined(PLATFORM_ANDROID)
   { TYPE_SWITCH,	&setup.fullscreen,	"Fullscreen:"		},
-  { TYPE_ENTER_LIST,	execSetupChooseScreenMode, "Fullscreen Mode:"	},
-  { TYPE_STRING,	&screen_mode_text,	""			},
-#if 0
-  { TYPE_SWITCH,	&setup.scroll_delay,	"Scroll Delay:"		},
+  { TYPE_ENTER_LIST,	execSetupChooseWindowSize, "Window Scaling:"	},
+  { TYPE_STRING,	&window_size_text,	""			},
+  { TYPE_ENTER_LIST,	execSetupChooseScalingType, "Anti-Aliasing:"	},
+  { TYPE_STRING,	&scaling_type_text,	""			},
+  { TYPE_ENTER_LIST,	execSetupChooseRenderingMode, "Special Rendering:" },
+  { TYPE_STRING,	&rendering_mode_text,	""			},
 #endif
-  { TYPE_ENTER_LIST,	execSetupChooseScrollDelay, "Scroll Delay Value:" },
-  { TYPE_STRING,	&scroll_delay_text,	""			},
 #if 0
-  { TYPE_SWITCH,	&setup.soft_scrolling,	"Soft Scrolling:"	},
+  { TYPE_ENTER_LIST,	execSetupChooseScrollDelay, "Scroll Delay:"	},
+  { TYPE_STRING,	&scroll_delay_text,	""			},
 #endif
   { TYPE_SWITCH,	&setup.fade_screens,	"Fade Screens:"		},
   { TYPE_SWITCH,	&setup.quick_switch,	"Quick Player Focus Switch:" },
   { TYPE_SWITCH,	&setup.quick_doors,	"Quick Menu Doors:"	},
   { TYPE_SWITCH,	&setup.show_titlescreen,"Show Title Screens:"	},
-  { TYPE_SWITCH,	&setup.toons,		"Show Toons:"		},
+  { TYPE_SWITCH,	&setup.toons,		"Show Menu Animations:"	},
   { TYPE_ECS_AGA,	&setup.prefer_aga_graphics,"EMC graphics preference:" },
   { TYPE_SWITCH, &setup.sp_show_border_elements,"Supaplex Border Elements:" },
+  { TYPE_SWITCH,	&setup.small_game_graphics, "Small Game Graphics:" },
   { TYPE_EMPTY,		NULL,			""			},
   { TYPE_LEAVE_MENU,	execSetupMain, 		"Back"			},
 
@@ -4253,6 +5366,13 @@ static struct TokenInfo setup_info_sound[] =
   { TYPE_SWITCH,	&setup.sound_loops,	"Sound Effects (Looping):" },
   { TYPE_SWITCH,	&setup.sound_music,	"Music:"		},
   { TYPE_EMPTY,		NULL,			""			},
+  { TYPE_ENTER_LIST,	execSetupChooseVolumeSimple, "Sound Volume (Normal):" },
+  { TYPE_STRING,	&volume_simple_text,	""			},
+  { TYPE_ENTER_LIST,	execSetupChooseVolumeLoops, "Sound Volume (Looping):" },
+  { TYPE_STRING,	&volume_loops_text,	""			},
+  { TYPE_ENTER_LIST,	execSetupChooseVolumeMusic, "Music Volume:"	},
+  { TYPE_STRING,	&volume_music_text,	""			},
+  { TYPE_EMPTY,		NULL,			""			},
   { TYPE_LEAVE_MENU,	execSetupMain, 		"Back"			},
 
   { 0,			NULL,			NULL			}
@@ -4267,23 +5387,9 @@ static struct TokenInfo setup_info_artwork[] =
   { TYPE_ENTER_LIST,	execSetupChooseMusic,	"Custom Music:"		},
   { TYPE_STRING,	&music_set_name,	""			},
   { TYPE_EMPTY,		NULL,			""			},
-#if 1
-#if 1
   { TYPE_YES_NO_AUTO,&setup.override_level_graphics,"Override Level Graphics:"},
   { TYPE_YES_NO_AUTO,&setup.override_level_sounds,  "Override Level Sounds:"  },
   { TYPE_YES_NO_AUTO,&setup.override_level_music,   "Override Level Music:"   },
-#else
-  { TYPE_YES_NO, &setup.override_level_graphics,"Override Level Graphics:" },
-  { TYPE_YES_NO, &setup.override_level_sounds,	"Override Level Sounds:"   },
-  { TYPE_YES_NO, &setup.override_level_music,	"Override Level Music:"    },
-  { TYPE_YES_NO, &setup.auto_override_artwork,	"Auto-Override Non-CE Sets:" },
-#endif
-#else
-  { TYPE_STRING,	NULL,			"Override Level Artwork:"},
-  { TYPE_YES_NO,	&setup.override_level_graphics,	"Graphics:"	},
-  { TYPE_YES_NO,	&setup.override_level_sounds,	"Sounds:"	},
-  { TYPE_YES_NO,	&setup.override_level_music,	"Music:"	},
-#endif
   { TYPE_EMPTY,		NULL,			""			},
   { TYPE_LEAVE_MENU,	execSetupMain, 		"Back"			},
 
@@ -4310,13 +5416,38 @@ static struct TokenInfo setup_info_input[] =
   { 0,			NULL,			NULL			}
 };
 
+static struct TokenInfo setup_info_touch[] =
+{
+  { TYPE_ENTER_LIST,	execSetupChooseTouchControls, "Touch Control Type:" },
+  { TYPE_STRING,	&touch_controls_text,	""			},
+  { TYPE_EMPTY,		NULL,			""			},
+  { TYPE_LEAVE_MENU,	execSetupMain, 		"Back"			},
+
+  { 0,			NULL,			NULL			}
+};
+
+static struct TokenInfo setup_info_touch_wipe_gestures[] =
+{
+  { TYPE_ENTER_LIST,	execSetupChooseTouchControls, "Touch Control Type:" },
+  { TYPE_STRING,	&touch_controls_text,	""			},
+  { TYPE_EMPTY,		NULL,			""			},
+  { TYPE_ENTER_LIST,	execSetupChooseMoveDistance, "Move Trigger Distance:" },
+  { TYPE_STRING,	&move_distance_text,	""			},
+  { TYPE_ENTER_LIST,	execSetupChooseDropDistance, "Drop Trigger Distance:" },
+  { TYPE_STRING,	&drop_distance_text,	""			},
+  { TYPE_EMPTY,		NULL,			""			},
+  { TYPE_LEAVE_MENU,	execSetupMain, 		"Back"			},
+
+  { 0,			NULL,			NULL			}
+};
+
 static struct TokenInfo setup_info_shortcuts[] =
 {
-  { TYPE_ENTER_MENU,	execSetupShortcuts1,	"Various Keys"	},
-  { TYPE_ENTER_MENU,	execSetupShortcuts2,	"Player Focus"	},
-  { TYPE_ENTER_MENU,	execSetupShortcuts3,	"Tape Buttons"	},
-  { TYPE_ENTER_MENU,	execSetupShortcuts4,	"Sound & Music"	},
-  { TYPE_ENTER_MENU,	execSetupShortcuts5,	"TAS Snap Keys"	},
+  { TYPE_ENTER_MENU,	execSetupShortcuts1,	"Various Keys"		},
+  { TYPE_ENTER_MENU,	execSetupShortcuts2,	"Player Focus"		},
+  { TYPE_ENTER_MENU,	execSetupShortcuts3,	"Tape Buttons"		},
+  { TYPE_ENTER_MENU,	execSetupShortcuts4,	"Sound & Music"		},
+  { TYPE_ENTER_MENU,	execSetupShortcuts5,	"TAS Snap Keys"		},
   { TYPE_EMPTY,		NULL,			""			},
   { TYPE_LEAVE_MENU,	execSetupMain, 		"Back"			},
 
@@ -4360,15 +5491,17 @@ static struct TokenInfo setup_info_shortcuts_2[] =
 
 static struct TokenInfo setup_info_shortcuts_3[] =
 {
-  { TYPE_KEYTEXT,	NULL,			"Tape Eject:",		},
+  { TYPE_KEYTEXT,	NULL,			"Eject Tape:",		},
   { TYPE_KEY,		&setup.shortcut.tape_eject, ""			},
-  { TYPE_KEYTEXT,	NULL,			"Tape Stop:",		},
+  { TYPE_KEYTEXT,	NULL,			"Warp / Single Step:",	},
+  { TYPE_KEY,		&setup.shortcut.tape_extra, ""			},
+  { TYPE_KEYTEXT,	NULL,			"Stop Tape:",		},
   { TYPE_KEY,		&setup.shortcut.tape_stop, ""			},
-  { TYPE_KEYTEXT,	NULL,			"Tape Pause:",		},
+  { TYPE_KEYTEXT,	NULL,			"Pause / Unpause Tape:",},
   { TYPE_KEY,		&setup.shortcut.tape_pause, ""			},
-  { TYPE_KEYTEXT,	NULL,			"Tape Record:",		},
+  { TYPE_KEYTEXT,	NULL,			"Record Tape:",		},
   { TYPE_KEY,		&setup.shortcut.tape_record, ""			},
-  { TYPE_KEYTEXT,	NULL,			"Tape Play:",		},
+  { TYPE_KEYTEXT,	NULL,			"Play Tape:",		},
   { TYPE_KEY,		&setup.shortcut.tape_play, ""			},
   { TYPE_EMPTY,		NULL,			""			},
   { TYPE_LEAVE_MENU,	execSetupShortcuts,	"Back"			},
@@ -4378,11 +5511,11 @@ static struct TokenInfo setup_info_shortcuts_3[] =
 
 static struct TokenInfo setup_info_shortcuts_4[] =
 {
-  { TYPE_KEYTEXT,	NULL,		"Sound Effects (Normal):",	},
+  { TYPE_KEYTEXT,	NULL,		"Toggle Sound Effects (Normal):", },
   { TYPE_KEY,		&setup.shortcut.sound_simple, ""		},
-  { TYPE_KEYTEXT,	NULL,		"Sound Effects (Looping):",	},
+  { TYPE_KEYTEXT,	NULL,		"Toggle Sound Effects (Looping):", },
   { TYPE_KEY,		&setup.shortcut.sound_loops, ""			},
-  { TYPE_KEYTEXT,	NULL,		"Music:",			},
+  { TYPE_KEYTEXT,	NULL,		"Toggle Music:",		},
   { TYPE_KEY,		&setup.shortcut.sound_music, ""			},
   { TYPE_EMPTY,		NULL,			""			},
   { TYPE_LEAVE_MENU,	execSetupShortcuts,	"Back"			},
@@ -4443,30 +5576,12 @@ static Key getSetupKey()
       }
     }
 
-    DoAnimation();
     BackToFront();
-
-    /* don't eat all CPU time */
-    Delay(10);
   }
 
   return key;
 }
 
-static int getSetupTextFont(int type)
-{
-  if (type & (TYPE_SWITCH	|
-	      TYPE_YES_NO	|
-	      TYPE_YES_NO_AUTO	|
-	      TYPE_STRING	|
-	      TYPE_ECS_AGA	|
-	      TYPE_KEYTEXT	|
-	      TYPE_ENTER_LIST))
-    return FONT_MENU_2;
-  else
-    return FONT_MENU_1;
-}
-
 static int getSetupValueFont(int type, void *value)
 {
   if (type & TYPE_KEY)
@@ -4484,21 +5599,33 @@ static int getSetupValueFont(int type, void *value)
     return FONT_VALUE_1;
 }
 
-static void drawSetupValue(int pos)
+static int getSetupValueFontNarrow(int type, int font_nr)
+{
+  return (font_nr == FONT_VALUE_1    ? FONT_VALUE_NARROW :
+	  font_nr == FONT_OPTION_ON  ? FONT_OPTION_ON_NARROW :
+	  font_nr == FONT_OPTION_OFF ? FONT_OPTION_OFF_NARROW :
+	  font_nr);
+}
+
+static void drawSetupValue(int screen_pos, int setup_info_pos_raw)
 {
+  int si_pos = (setup_info_pos_raw < 0 ? screen_pos : setup_info_pos_raw);
+  struct TokenInfo *si = &setup_info[si_pos];
   boolean font_draw_xoffset_modified = FALSE;
+  boolean scrollbar_needed = (num_setup_info < max_setup_info);
   int font_draw_xoffset_old = -1;
-  int xpos = MENU_SCREEN_VALUE_XPOS;
-  int ypos = MENU_SCREEN_START_YPOS + pos;
+  int xoffset = (scrollbar_needed ? -1 : 0);
+  int menu_screen_value_xpos = MENU_SCREEN_VALUE_XPOS + xoffset;
+  int menu_screen_max_xpos = MENU_SCREEN_MAX_XPOS + xoffset;
+  int xpos = menu_screen_value_xpos;
+  int ypos = MENU_SCREEN_START_YPOS + screen_pos;
   int startx = mSX + xpos * 32;
   int starty = mSY + ypos * 32;
-  int font_nr, font_width, font_height;
-  int type = setup_info[pos].type;
-  void *value = setup_info[pos].value;
+  int font_nr, font_nr_default, font_width_default;
+  int type = si->type;
+  void *value = si->value;
   char *value_string = getSetupValue(type, value);
-#if 1
   int i;
-#endif
 
   if (value_string == NULL)
     return;
@@ -4521,32 +5648,55 @@ static void drawSetupValue(int pos)
   }
   else if (type & TYPE_YES_NO_AUTO)
   {
-    xpos = MENU_SCREEN_VALUE_XPOS - 1;
+    xpos = menu_screen_value_xpos - 1;
   }
 
   startx = mSX + xpos * 32;
   starty = mSY + ypos * 32;
-  font_nr = getSetupValueFont(type, value);
-  font_width = getFontWidth(font_nr);
-  font_height = getFontHeight(font_nr);
+  font_nr_default = getSetupValueFont(type, value);
+  font_width_default = getFontWidth(font_nr_default);
+
+  font_nr = font_nr_default;
+
+  // special check if right-side setup values moved left due to scrollbar
+  if (scrollbar_needed && xpos > MENU_SCREEN_START_XPOS)
+  {
+    int max_menu_text_length = 26;	// maximum text length for classic menu
+    int font_xoffset = getFontBitmapInfo(font_nr)->draw_xoffset;
+    int text_startx = mSX + MENU_SCREEN_START_XPOS * 32;
+    int text_font_nr = getMenuTextFont(FONT_MENU_2);
+    int text_font_xoffset = getFontBitmapInfo(text_font_nr)->draw_xoffset;
+    int text_width = max_menu_text_length * getFontWidth(text_font_nr);
+
+    if (startx + font_xoffset < text_startx + text_width + text_font_xoffset)
+    {
+      xpos += 1;
+      startx = mSX + xpos * 32;
+
+      font_nr = getSetupValueFontNarrow(type, font_nr);
+    }
+  }
 
   /* downward compatibility correction for Juergen Bonhagen's menu settings */
   if (setup_mode != SETUP_MODE_INPUT)
   {
+    int max_menu_text_length_big = (menu_screen_value_xpos -
+				    MENU_SCREEN_START_XPOS);
+    int max_menu_text_length_medium = max_menu_text_length_big * 2;
     int check_font_nr = FONT_OPTION_ON; /* known font that needs correction */
     int font1_xoffset = getFontBitmapInfo(font_nr)->draw_xoffset;
     int font2_xoffset = getFontBitmapInfo(check_font_nr)->draw_xoffset;
     int text_startx = mSX + MENU_SCREEN_START_XPOS * 32;
-    int text_font_nr = getSetupTextFont(FONT_MENU_2);
+    int text_font_nr = getMenuTextFont(FONT_MENU_2);
     int text_font_xoffset = getFontBitmapInfo(text_font_nr)->draw_xoffset;
-    int text_width = MAX_MENU_TEXT_LENGTH_MEDIUM * getFontWidth(text_font_nr);
+    int text_width = max_menu_text_length_medium * getFontWidth(text_font_nr);
     boolean correct_font_draw_xoffset = FALSE;
 
     if (xpos == MENU_SCREEN_START_XPOS &&
 	startx + font1_xoffset < text_startx + text_font_xoffset)
       correct_font_draw_xoffset = TRUE;
 
-    if (xpos == MENU_SCREEN_VALUE_XPOS &&
+    if (xpos == menu_screen_value_xpos &&
 	startx + font2_xoffset < text_startx + text_width + text_font_xoffset)
       correct_font_draw_xoffset = TRUE;
 
@@ -4561,16 +5711,12 @@ static void drawSetupValue(int pos)
 	getFontBitmapInfo(font_nr)->draw_xoffset += 2 * getFontWidth(font_nr);
       else if (!(type & TYPE_STRING))
 	getFontBitmapInfo(font_nr)->draw_xoffset = text_font_xoffset + 20 -
-	  MAX_MENU_TEXT_LENGTH_MEDIUM * (16 - getFontWidth(text_font_nr));
+	  max_menu_text_length_medium * (16 - getFontWidth(text_font_nr));
     }
   }
 
-#if 0
-  DrawBackground(startx, starty, SX + SXSIZE - startx, font_height);
-#else
-  for (i = 0; i <= MENU_SCREEN_MAX_XPOS - xpos; i++)
-    DrawText(startx + i * font_width, starty, " ", font_nr);
-#endif
+  for (i = 0; i <= menu_screen_max_xpos - xpos; i++)
+    DrawText(startx + i * font_width_default, starty, " ", font_nr_default);
 
   DrawText(startx, starty, value_string, font_nr);
 
@@ -4578,82 +5724,74 @@ static void drawSetupValue(int pos)
     getFontBitmapInfo(font_nr)->draw_xoffset = font_draw_xoffset_old;
 }
 
-static void changeSetupValue(int pos, int dx)
+static void changeSetupValue(int screen_pos, int setup_info_pos_raw, int dx)
 {
-  if (setup_info[pos].type & TYPE_BOOLEAN_STYLE)
+  int si_pos = (setup_info_pos_raw < 0 ? screen_pos : setup_info_pos_raw);
+  struct TokenInfo *si = &setup_info[si_pos];
+
+  if (si->type & TYPE_BOOLEAN_STYLE)
   {
-    *(boolean *)setup_info[pos].value ^= TRUE;
+    *(boolean *)si->value ^= TRUE;
   }
-  else if (setup_info[pos].type & TYPE_YES_NO_AUTO)
+  else if (si->type & TYPE_YES_NO_AUTO)
   {
-    *(int *)setup_info[pos].value =
+    *(int *)si->value =
       (dx == -1 ?
-       (*(int *)setup_info[pos].value == AUTO ? TRUE :
-	*(int *)setup_info[pos].value == TRUE ? FALSE : AUTO) :
-       (*(int *)setup_info[pos].value == TRUE ? AUTO :
-	*(int *)setup_info[pos].value == AUTO ? FALSE : TRUE));
+       (*(int *)si->value == AUTO ? TRUE :
+	*(int *)si->value == TRUE ? FALSE : AUTO) :
+       (*(int *)si->value == TRUE ? AUTO :
+	*(int *)si->value == AUTO ? FALSE : TRUE));
   }
-  else if (setup_info[pos].type & TYPE_KEY)
+  else if (si->type & TYPE_KEY)
   {
     Key key;
 
-    setup_info[pos].type |= TYPE_QUERY;
-    drawSetupValue(pos);
-    setup_info[pos].type &= ~TYPE_QUERY;
+    si->type |= TYPE_QUERY;
+    drawSetupValue(screen_pos, setup_info_pos_raw);
+    si->type &= ~TYPE_QUERY;
 
     key = getSetupKey();
     if (key != KSYM_UNDEFINED)
-      *(Key *)setup_info[pos].value = key;
+      *(Key *)si->value = key;
   }
 
-  drawSetupValue(pos);
-}
-
-static void DrawCursorAndText_Setup(int pos, boolean active)
-{
-  int xpos = MENU_SCREEN_START_XPOS;
-  int ypos = MENU_SCREEN_START_YPOS + pos;
-  int font_nr = getSetupTextFont(setup_info[pos].type);
-
-  if (setup_info == setup_info_input)
-    font_nr = FONT_MENU_1;
-
-  if (active)
-    font_nr = FONT_ACTIVE(font_nr);
-
-  DrawText(mSX + xpos * 32, mSY + ypos * 32, setup_info[pos].text, font_nr);
+  drawSetupValue(screen_pos, setup_info_pos_raw);
 
-  if (setup_info[pos].type & ~TYPE_SKIP_ENTRY)
-    drawCursor(pos, active);
+  // fullscreen state may have changed at this point
+  if (si->value == &setup.fullscreen)
+    ToggleFullscreenOrChangeWindowScalingIfNeeded();
 }
 
 static void DrawSetupScreen_Generic()
 {
+  int fade_mask = REDRAW_FIELD;
   boolean redraw_all = FALSE;
   char *title_string = NULL;
   int i;
 
+  if (CheckIfGlobalBorderHasChanged())
+    fade_mask = REDRAW_ALL;
+
   UnmapAllGadgets();
-  CloseDoor(DOOR_CLOSE_2);
+  FadeMenuSoundsAndMusic();
+
+  FreeScreenGadgets();
+  CreateScreenGadgets();
 
   if (redraw_mask & REDRAW_ALL)
     redraw_all = TRUE;
 
-#if 0
-  printf("::: %s\n", (redraw_mask & REDRAW_FIELD ? "REDRAW_FIELD" :
-		      redraw_mask & REDRAW_ALL ? "REDRAW_ALL" :
-		      int2str(0, redraw_mask)));
-#endif
+  FadeOut(fade_mask);
 
-#if 0
-  /* !!! usually REDRAW_NONE => DOES NOT WORK (with fade) => CHECK THIS !!! */
-  FadeOut(redraw_mask);
-#else
-  FadeOut(REDRAW_FIELD);
-#endif
+  /* needed if different viewport properties defined for setup screen */
+  ChangeViewportPropertiesIfNeeded();
+
+  SetMainBackgroundImage(IMG_BACKGROUND_SETUP);
 
   ClearField();
 
+  OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
+
   if (setup_mode == SETUP_MODE_MAIN)
   {
     setup_info = setup_info_main;
@@ -4684,6 +5822,14 @@ static void DrawSetupScreen_Generic()
     setup_info = setup_info_artwork;
     title_string = "Custom Artwork";
   }
+  else if (setup_mode == SETUP_MODE_TOUCH)
+  {
+    setup_info = setup_info_touch;
+    title_string = "Setup Touch Ctrls";
+
+    if (strEqual(setup.touch.control_type, TOUCH_CONTROL_WIPE_GESTURES))
+      setup_info = setup_info_touch_wipe_gestures;
+  }
   else if (setup_mode == SETUP_MODE_SHORTCUTS)
   {
     setup_info = setup_info_shortcuts;
@@ -4717,203 +5863,52 @@ static void DrawSetupScreen_Generic()
 
   DrawTextSCentered(mSY - SY + 16, FONT_TITLE_1, title_string);
 
+  // determine maximal number of setup entries that can be displayed on screen
   num_setup_info = 0;
-#if 1
-  for (i = 0; setup_info[i].type != 0 && i < MAX_MENU_ENTRIES_ON_SCREEN; i++)
-#else
   for (i = 0; setup_info[i].type != 0 && i < NUM_MENU_ENTRIES_ON_SCREEN; i++)
-#endif
-  {
-    void *value_ptr = setup_info[i].value;
-
-    /* set some entries to "unchangeable" according to other variables */
-    if ((value_ptr == &setup.sound_simple && !audio.sound_available) ||
-	(value_ptr == &setup.sound_loops  && !audio.loops_available) ||
-	(value_ptr == &setup.sound_music  && !audio.music_available) ||
-	(value_ptr == &setup.fullscreen   && !video.fullscreen_available) ||
-	(value_ptr == &screen_mode_text   && !video.fullscreen_available))
-      setup_info[i].type |= TYPE_GHOSTED;
-
-    if (setup_info[i].type & (TYPE_ENTER_MENU|TYPE_ENTER_LIST))
-      initCursor(i, IMG_MENU_BUTTON_ENTER_MENU);
-    else if (setup_info[i].type & (TYPE_LEAVE_MENU|TYPE_LEAVE_LIST))
-      initCursor(i, IMG_MENU_BUTTON_LEAVE_MENU);
-    else if (setup_info[i].type & ~TYPE_SKIP_ENTRY)
-      initCursor(i, IMG_MENU_BUTTON);
-
-    DrawCursorAndText_Setup(i, FALSE);
-
-    if (setup_info[i].type & TYPE_VALUE)
-      drawSetupValue(i);
-
     num_setup_info++;
-  }
 
-#if 0
-  DrawTextSCentered(SYSIZE - 20, FONT_TEXT_4,
-		    "Joysticks deactivated in setup menu");
-#endif
+  // determine maximal number of setup entries available for this setup screen
+  max_setup_info = 0;
+  for (i = 0; setup_info[i].type != 0; i++)
+    max_setup_info++;
 
-#if 1
   HandleSetupScreen_Generic(0, 0, 0, 0, MB_MENU_INITIALIZE);
-#endif
+
+  MapScreenGadgets(max_setup_info);
 
   if (redraw_all)
-    redraw_mask = REDRAW_ALL;
+    redraw_mask = fade_mask = REDRAW_ALL;
 
-#if 1
-  FadeIn(redraw_mask);
-#else
-  FadeIn(REDRAW_FIELD);
-#endif
+  DrawMaskedBorder(fade_mask);
 
-  InitAnimation();
-#if 0
-  HandleSetupScreen_Generic(0, 0, 0, 0, MB_MENU_INITIALIZE);
-#endif
+  FadeIn(fade_mask);
 }
 
 void HandleSetupScreen_Generic(int mx, int my, int dx, int dy, int button)
 {
-  static int choice_store[MAX_SETUP_MODES];
-  int choice = choice_store[setup_mode];	/* always starts with 0 */
-  int x = 0;
-  int y = choice;
-
-  if (button == MB_MENU_INITIALIZE)
-  {
-    /* advance to first valid menu entry */
-    while (choice < num_setup_info &&
-	   setup_info[choice].type & TYPE_SKIP_ENTRY)
-      choice++;
-    choice_store[setup_mode] = choice;
-
-    DrawCursorAndText_Setup(choice, TRUE);
-
-    return;
-  }
-  else if (button == MB_MENU_LEAVE)
-  {
-    PlaySound(SND_MENU_ITEM_SELECTING);
-
-    for (y = 0; y < num_setup_info; y++)
-    {
-      if (setup_info[y].type & TYPE_LEAVE_MENU)
-      {
-	void (*menu_callback_function)(void) = setup_info[y].value;
-
-	FadeSetLeaveMenu();
-
-	menu_callback_function();
-
-	break;	/* absolutely needed because function changes 'setup_info'! */
-      }
-    }
-
-    return;
-  }
-
-  if (mx || my)		/* mouse input */
-  {
-    x = (mx - mSX) / 32;
-    y = (my - mSY) / 32 - MENU_SCREEN_START_YPOS;
-  }
-  else if (dx || dy)	/* keyboard input */
-  {
-    if (dx)
-    {
-      int menu_navigation_type = (dx < 0 ? TYPE_LEAVE : TYPE_ENTER);
-
-      if (setup_info[choice].type & menu_navigation_type ||
-	  setup_info[choice].type & TYPE_BOOLEAN_STYLE ||
-	  setup_info[choice].type & TYPE_YES_NO_AUTO)
-	button = MB_MENU_CHOICE;
-    }
-    else if (dy)
-      y = choice + dy;
-
-    /* jump to next non-empty menu entry (up or down) */
-    while (y > 0 && y < num_setup_info - 1 &&
-	   setup_info[y].type & TYPE_SKIP_ENTRY)
-      y += dy;
-  }
-
-  if (IN_VIS_FIELD(x, y) && y >= 0 && y < num_setup_info)
-  {
-    if (button)
-    {
-      if (y != choice && setup_info[y].type & ~TYPE_SKIP_ENTRY)
-      {
-	PlaySound(SND_MENU_ITEM_ACTIVATING);
-
-	DrawCursorAndText_Setup(choice, FALSE);
-	DrawCursorAndText_Setup(y, TRUE);
-
-	choice = choice_store[setup_mode] = y;
-      }
-    }
-    else if (!(setup_info[y].type & TYPE_GHOSTED))
-    {
-      PlaySound(SND_MENU_ITEM_SELECTING);
-
-      /* when selecting key headline, execute function for key value change */
-      if (setup_info[y].type & TYPE_KEYTEXT &&
-	  setup_info[y + 1].type & TYPE_KEY)
-	y++;
-
-      /* when selecting string value, execute function for list selection */
-      if (setup_info[y].type & TYPE_STRING && y > 0 &&
-	  setup_info[y - 1].type & TYPE_ENTER_LIST)
-	y--;
-
-      if (setup_info[y].type & TYPE_ENTER_OR_LEAVE)
-      {
-	void (*menu_callback_function)(void) = setup_info[y].value;
-
-	FadeSetFromType(setup_info[y].type);
+  menu_info = setup_info;
 
-	menu_callback_function();
-      }
-      else
-      {
-	if (setup_info[y].type & TYPE_VALUE)
-	  changeSetupValue(y, dx);
-      }
-    }
-  }
+  HandleMenuScreen(mx, my, dx, dy, button,
+		   setup_mode, num_setup_info, max_setup_info);
 }
 
 void DrawSetupScreen_Input()
 {
   int i;
 
-#if 1
   FadeOut(REDRAW_FIELD);
-#endif
 
   ClearField();
 
-#if 1
   setup_info = setup_info_input;
-#endif
 
   DrawTextSCentered(mSY - SY + 16, FONT_TITLE_1, "Setup Input");
 
-#if 1
-#if 1
   DrawTextSCentered(SYSIZE - 20, FONT_TITLE_2,
 		    "Joysticks deactivated on this screen");
-#else
-  DrawTextSCentered(SYSIZE - 20, FONT_TEXT_4,
-		    "Joysticks deactivated on this screen");
-#endif
-#endif
 
-#if 1
   for (i = 0; setup_info[i].type != 0 && i < MAX_MENU_ENTRIES_ON_SCREEN; i++)
-#else
-  for (i = 0; setup_info[i].type != 0 && i < NUM_MENU_ENTRIES_ON_SCREEN; i++)
-#endif
   {
     if (setup_info[i].type & (TYPE_ENTER_MENU|TYPE_ENTER_LIST))
       initCursor(i, IMG_MENU_BUTTON_ENTER_MENU);
@@ -4922,23 +5917,9 @@ void DrawSetupScreen_Input()
     else if (setup_info[i].type & ~TYPE_SKIP_ENTRY)
       initCursor(i, IMG_MENU_BUTTON);
 
-    DrawCursorAndText_Setup(i, FALSE);
+    DrawCursorAndText_Setup(i, -1, FALSE);
   }
 
-#if 0
-  DeactivateJoystickForCalibration();
-#endif
-
-#if 0
-#if 1
-  DrawTextSCentered(SYSIZE - 20, FONT_TITLE_2,
-		    "Joysticks deactivated on this screen");
-#else
-  DrawTextSCentered(SYSIZE - 20, FONT_TEXT_4,
-		    "Joysticks deactivated on this screen");
-#endif
-#endif
-
   /* create gadgets for setup input menu screen */
   FreeScreenGadgets();
   CreateScreenGadgets();
@@ -4948,11 +5929,7 @@ void DrawSetupScreen_Input()
 
   HandleSetupScreen_Input(0, 0, 0, 0, MB_MENU_INITIALIZE);
 
-#if 1
   FadeIn(REDRAW_FIELD);
-#endif
-
-  InitAnimation();
 }
 
 static void setJoystickDeviceToNr(char *device_name, int device_nr)
@@ -5011,8 +5988,8 @@ static void drawPlayerSetupInputInfo(int player_nr, boolean active)
 
   ClearRectangleOnBackground(drawto, mSX + 8 * TILEX, mSY + 2 * TILEY,
 			     TILEX, TILEY);
-  DrawGraphicThruMaskExt(drawto, mSX + 8 * TILEX, mSY + 2 * TILEY,
-			 PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0);
+  DrawFixedGraphicThruMaskExt(drawto, mSX + 8 * TILEX, mSY + 2 * TILEY,
+			      PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0);
 
   if (setup.input[player_nr].use_joystick)
   {
@@ -5091,7 +6068,7 @@ void HandleSetupScreen_Input(int mx, int my, int dx, int dy, int button)
   {
     drawPlayerSetupInputInfo(input_player_nr, (choice == 2));
 
-    DrawCursorAndText_Setup(choice, TRUE);
+    DrawCursorAndText_Setup(choice, -1, TRUE);
 
     return;
   }
@@ -5128,7 +6105,7 @@ void HandleSetupScreen_Input(int mx, int my, int dx, int dy, int button)
   {
     HandleSetupScreen_Input_Player(1, dx < 0 ? -1 : +1);
   }
-  else if (IN_VIS_FIELD(x, y) &&
+  else if (IN_VIS_FIELD(x, y) &&	// (does not use "IN_VIS_MENU()" yet)
 	   y >= pos_start && y <= pos_end &&
 	   !(y >= pos_empty1 && y <= pos_empty2))
   {
@@ -5136,8 +6113,8 @@ void HandleSetupScreen_Input(int mx, int my, int dx, int dy, int button)
     {
       if (y != choice)
       {
-	DrawCursorAndText_Setup(choice, FALSE);
-	DrawCursorAndText_Setup(y, TRUE);
+	DrawCursorAndText_Setup(choice, -1, FALSE);
+	DrawCursorAndText_Setup(y, -1, TRUE);
 
 	drawPlayerSetupInputInfo(input_player_nr, (y == 2));
 
@@ -5223,11 +6200,6 @@ void CustomizeKeyboard(int player_nr)
 
   DrawTextSCentered(mSY - SY + 16, FONT_TITLE_1, "Keyboard Input");
 
-#if 0
-  BackToFront();
-  InitAnimation();
-#endif
-
   step_nr = 0;
   DrawText(mSX, mSY + (2 + 2 * step_nr) * 32,
 	   customize_step[step_nr].text, FONT_INPUT_1_ACTIVE);
@@ -5236,12 +6208,8 @@ void CustomizeKeyboard(int player_nr)
   DrawText(mSX + 4 * 32, mSY + (2 + 2 * step_nr + 1) * 32,
 	   getKeyNameFromKey(*customize_step[step_nr].key), FONT_VALUE_OLD);
 
-#if 1
   FadeIn(REDRAW_FIELD);
 
-  InitAnimation();
-#endif
-
   while (!finished)
   {
     if (PendingEvent())		/* got event */
@@ -5323,17 +6291,12 @@ void CustomizeKeyboard(int player_nr)
       }
     }
 
-    DoAnimation();
     BackToFront();
-
-    /* don't eat all CPU time */
-    Delay(10);
   }
 
   /* write new key bindings back to player setup */
   setup.input[player_nr].key = custom_key;
 
-  StopAnimation();
   DrawSetupScreen_Input();
 }
 
@@ -5368,7 +6331,7 @@ static boolean CalibrateJoystickMain(int player_nr)
   {
     for (x = 0; x < 3; x++)
     {
-      DrawGraphic(xpos + x - 1, ypos + y - 1, IMG_MENU_CALIBRATE_BLUE, 0);
+      DrawFixedGraphic(xpos + x - 1, ypos + y - 1, IMG_MENU_CALIBRATE_BLUE, 0);
       check[x][y] = FALSE;
     }
   }
@@ -5392,12 +6355,11 @@ static boolean CalibrateJoystickMain(int player_nr)
   new_joystick_xmiddle = joy_x;
   new_joystick_ymiddle = joy_y;
 
-  DrawGraphic(xpos + last_x, ypos + last_y, IMG_MENU_CALIBRATE_RED, 0);
+  DrawFixedGraphic(xpos + last_x, ypos + last_y, IMG_MENU_CALIBRATE_RED, 0);
 
   FadeIn(REDRAW_FIELD);
 
   while (Joystick(player_nr) & JOY_BUTTON);	/* wait for released button */
-  InitAnimation();
 
   while (result < 0)
   {
@@ -5464,8 +6426,10 @@ static boolean CalibrateJoystickMain(int player_nr)
 
     if (x != last_x || y != last_y)
     {
-      DrawGraphic(xpos + last_x, ypos + last_y, IMG_MENU_CALIBRATE_YELLOW, 0);
-      DrawGraphic(xpos + x,      ypos + y,      IMG_MENU_CALIBRATE_RED,    0);
+      DrawFixedGraphic(xpos + last_x, ypos + last_y,
+		       IMG_MENU_CALIBRATE_YELLOW, 0);
+      DrawFixedGraphic(xpos + x,      ypos + y,
+		       IMG_MENU_CALIBRATE_RED,    0);
 
       last_x = x;
       last_y = y;
@@ -5475,27 +6439,9 @@ static boolean CalibrateJoystickMain(int player_nr)
 	check[x+1][y+1] = TRUE;
 	check_remaining--;
       }
-
-#if 0
-#ifdef DEBUG
-      printf("LEFT / MIDDLE / RIGHT == %d / %d / %d\n",
-	     setup.input[player_nr].joy.xleft,
-	     setup.input[player_nr].joy.xmiddle,
-	     setup.input[player_nr].joy.xright);
-      printf("UP / MIDDLE / DOWN == %d / %d / %d\n",
-	     setup.input[player_nr].joy.yupper,
-	     setup.input[player_nr].joy.ymiddle,
-	     setup.input[player_nr].joy.ylower);
-#endif
-#endif
-
     }
 
-    DoAnimation();
     BackToFront();
-
-    /* don't eat all CPU time */
-    Delay(10);
   }
 
   /* calibrated center position (joystick should now be centered) */
@@ -5505,12 +6451,6 @@ static boolean CalibrateJoystickMain(int player_nr)
   new_joystick_xmiddle = joy_x;
   new_joystick_ymiddle = joy_y;
 
-  StopAnimation();
-
-#if 0
-  DrawSetupScreen_Input();
-#endif
-
   /* wait until the last pressed button was released */
   while (Joystick(player_nr) & JOY_BUTTON)
   {
@@ -5521,7 +6461,7 @@ static boolean CalibrateJoystickMain(int player_nr)
       NextEvent(&event);
       HandleOtherEvents(&event);
 
-      Delay(10);
+      BackToFront();
     }
   }
 
@@ -5548,42 +6488,61 @@ void CalibrateJoystick(int player_nr)
     ClearEventQueue();
   }
 
-#if 1
   DrawSetupScreen_Input();
-#endif
 }
 
 void DrawSetupScreen()
 {
   DeactivateJoystick();
 
-  SetMainBackgroundImage(IMG_BACKGROUND_SETUP);
-
   if (setup_mode == SETUP_MODE_INPUT)
     DrawSetupScreen_Input();
   else if (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED)
     DrawChooseTree(&game_speed_current);
-  else if (setup_mode == SETUP_MODE_CHOOSE_SCREEN_MODE)
-    DrawChooseTree(&screen_mode_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_SCROLL_DELAY)
     DrawChooseTree(&scroll_delay_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_SNAPSHOT_MODE)
+    DrawChooseTree(&snapshot_mode_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE)
+    DrawChooseTree(&window_size_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_SCALING_TYPE)
+    DrawChooseTree(&scaling_type_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_RENDERING)
+    DrawChooseTree(&rendering_mode_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_GRAPHICS)
     DrawChooseTree(&artwork.gfx_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_SOUNDS)
     DrawChooseTree(&artwork.snd_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_MUSIC)
     DrawChooseTree(&artwork.mus_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_SIMPLE)
+    DrawChooseTree(&volume_simple_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_LOOPS)
+    DrawChooseTree(&volume_loops_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_MUSIC)
+    DrawChooseTree(&volume_music_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_TOUCH_CONTROL)
+    DrawChooseTree(&touch_control_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_MOVE_DISTANCE)
+    DrawChooseTree(&move_distance_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_DROP_DISTANCE)
+    DrawChooseTree(&drop_distance_current);
   else
     DrawSetupScreen_Generic();
 
-  PlayMenuSound();
-  PlayMenuMusic();
+  PlayMenuSoundsAndMusic();
 }
 
 void RedrawSetupScreenAfterFullscreenToggle()
 {
-  if (setup_mode == SETUP_MODE_GRAPHICS)
+  if (setup_mode == SETUP_MODE_GRAPHICS ||
+      setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE)
+  {
+    // update list selection from "setup.window_scaling_percent"
+    execSetupGraphics_setWindowSizes(TRUE);
+
     DrawSetupScreen();
+  }
 }
 
 void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
@@ -5592,20 +6551,36 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
     HandleSetupScreen_Input(mx, my, dx, dy, button);
   else if (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED)
     HandleChooseTree(mx, my, dx, dy, button, &game_speed_current);
-  else if (setup_mode == SETUP_MODE_CHOOSE_SCREEN_MODE)
-    HandleChooseTree(mx, my, dx, dy, button, &screen_mode_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_SCROLL_DELAY)
     HandleChooseTree(mx, my, dx, dy, button, &scroll_delay_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_SNAPSHOT_MODE)
+    HandleChooseTree(mx, my, dx, dy, button, &snapshot_mode_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE)
+    HandleChooseTree(mx, my, dx, dy, button, &window_size_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_SCALING_TYPE)
+    HandleChooseTree(mx, my, dx, dy, button, &scaling_type_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_RENDERING)
+    HandleChooseTree(mx, my, dx, dy, button, &rendering_mode_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_GRAPHICS)
     HandleChooseTree(mx, my, dx, dy, button, &artwork.gfx_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_SOUNDS)
     HandleChooseTree(mx, my, dx, dy, button, &artwork.snd_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_MUSIC)
     HandleChooseTree(mx, my, dx, dy, button, &artwork.mus_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_SIMPLE)
+    HandleChooseTree(mx, my, dx, dy, button, &volume_simple_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_LOOPS)
+    HandleChooseTree(mx, my, dx, dy, button, &volume_loops_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_MUSIC)
+    HandleChooseTree(mx, my, dx, dy, button, &volume_music_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_TOUCH_CONTROL)
+    HandleChooseTree(mx, my, dx, dy, button, &touch_control_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_MOVE_DISTANCE)
+    HandleChooseTree(mx, my, dx, dy, button, &move_distance_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_DROP_DISTANCE)
+    HandleChooseTree(mx, my, dx, dy, button, &drop_distance_current);
   else
     HandleSetupScreen_Generic(mx, my, dx, dy, button);
-
-  DoAnimation();
 }
 
 void HandleGameActions()
@@ -5626,27 +6601,15 @@ static void getScreenMenuButtonPos(int *x, int *y, int gadget_id)
 {
   switch (gadget_id)
   {
-#if 1
-    case SCREEN_CTRL_ID_PREV_LEVEL:
-      *x = mSX + menu.main.button.prev_level.x;
-      *y = mSY + menu.main.button.prev_level.y;
-      break;
-
-    case SCREEN_CTRL_ID_NEXT_LEVEL:
-      *x = mSX + menu.main.button.next_level.x;
-      *y = mSY + menu.main.button.next_level.y;
-      break;
-#else
     case SCREEN_CTRL_ID_PREV_LEVEL:
-      *x = mSX + TILEX * getPrevlevelButtonPos();
-      *y = mSY + TILEY * (MENU_SCREEN_START_YPOS + 1);
+      *x = mSX + GDI_ACTIVE_POS(menu.main.button.prev_level.x);
+      *y = mSY + GDI_ACTIVE_POS(menu.main.button.prev_level.y);
       break;
 
     case SCREEN_CTRL_ID_NEXT_LEVEL:
-      *x = mSX + TILEX * getNextLevelButtonPos();
-      *y = mSY + TILEY * (MENU_SCREEN_START_YPOS + 1);
+      *x = mSX + GDI_ACTIVE_POS(menu.main.button.next_level.x);
+      *y = mSY + GDI_ACTIVE_POS(menu.main.button.next_level.y);
       break;
-#endif
 
     case SCREEN_CTRL_ID_PREV_PLAYER:
       *x = mSX + TILEX * 10;
@@ -5712,21 +6675,13 @@ static struct
 {
   {
     IMG_MENU_BUTTON_UP, IMG_MENU_BUTTON_UP_ACTIVE,
-#if 1
     -1, -1,	/* these values are not constant, but can change at runtime */
-#else
-    SC_SCROLL_UP_XPOS, SC_SCROLL_UP_YPOS,
-#endif
     SCREEN_CTRL_ID_SCROLL_UP,
     "scroll up"
   },
   {
     IMG_MENU_BUTTON_DOWN, IMG_MENU_BUTTON_DOWN_ACTIVE,
-#if 1
     -1, -1,	/* these values are not constant, but can change at runtime */
-#else
-    SC_SCROLL_DOWN_XPOS, SC_SCROLL_DOWN_YPOS,
-#endif
     SCREEN_CTRL_ID_SCROLL_DOWN,
     "scroll down"
   }
@@ -5734,11 +6689,7 @@ static struct
 
 static struct
 {
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
-  Bitmap **gfx_unpressed, **gfx_pressed;
-#else
   int gfx_unpressed, gfx_pressed;
-#endif
   int x, y;
   int width, height;
   int type;
@@ -5747,18 +6698,9 @@ static struct
 } scrollbar_info[NUM_SCREEN_SCROLLBARS] =
 {
   {
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
-    &scrollbar_bitmap[0], &scrollbar_bitmap[1],
-#else
     IMG_MENU_SCROLLBAR, IMG_MENU_SCROLLBAR_ACTIVE,
-#endif
-#if 1
     -1, -1,	/* these values are not constant, but can change at runtime */
     -1, -1,	/* these values are not constant, but can change at runtime */
-#else
-    SC_SCROLL_VERTICAL_XPOS, SC_SCROLL_VERTICAL_YPOS,
-    SC_SCROLL_VERTICAL_XSIZE, SC_SCROLL_VERTICAL_YSIZE,
-#endif
     GD_TYPE_SCROLLBAR_VERTICAL,
     SCREEN_CTRL_ID_SCROLL_VERTICAL,
     "scroll level series vertically"
@@ -5768,7 +6710,7 @@ static struct
 static void CreateScreenMenubuttons()
 {
   struct GadgetInfo *gi;
-  unsigned long event_mask;
+  unsigned int event_mask;
   int i;
 
   for (i = 0; i < NUM_SCREEN_MENUBUTTONS; i++)
@@ -5821,7 +6763,7 @@ static void CreateScreenMenubuttons()
 static void CreateScreenScrollbuttons()
 {
   struct GadgetInfo *gi;
-  unsigned long event_mask;
+  unsigned int event_mask;
   int i;
 
   /* these values are not constant, but can change at runtime */
@@ -5845,6 +6787,10 @@ static void CreateScreenScrollbuttons()
     width = SC_SCROLLBUTTON_XSIZE;
     height = SC_SCROLLBUTTON_YSIZE;
 
+    /* correct scrollbar position if placed outside menu (playfield) area */
+    if (x > SX + SC_SCROLL_UP_XPOS)
+      x = SX + SC_SCROLL_UP_XPOS;
+
     if (id == SCREEN_CTRL_ID_SCROLL_DOWN)
       y = mSY + (SC_SCROLL_VERTICAL_YPOS +
 		 (NUM_MENU_ENTRIES_ON_SCREEN - 2) * SC_SCROLLBUTTON_YSIZE);
@@ -5894,14 +6840,12 @@ static void CreateScreenScrollbars()
   for (i = 0; i < NUM_SCREEN_SCROLLBARS; i++)
   {
     Bitmap *gd_bitmap_unpressed, *gd_bitmap_pressed;
-#if !defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
     int gfx_unpressed, gfx_pressed;
-#endif
     int x, y, width, height;
     int gd_x1, gd_x2, gd_y1, gd_y2;
     struct GadgetInfo *gi;
     int items_max, items_visible, item_position;
-    unsigned long event_mask;
+    unsigned int event_mask;
     int num_page_entries = NUM_MENU_ENTRIES_ON_SCREEN;
     int id = scrollbar_info[i].gadget_id;
 
@@ -5912,6 +6856,10 @@ static void CreateScreenScrollbars()
     width  = scrollbar_info[i].width;
     height = scrollbar_info[i].height;
 
+    /* correct scrollbar position if placed outside menu (playfield) area */
+    if (x > SX + SC_SCROLL_VERTICAL_XPOS)
+      x = SX + SC_SCROLL_VERTICAL_XPOS;
+
     if (id == SCREEN_CTRL_ID_SCROLL_VERTICAL)
       height = (NUM_MENU_ENTRIES_ON_SCREEN - 2) * SC_SCROLLBUTTON_YSIZE;
 
@@ -5919,14 +6867,6 @@ static void CreateScreenScrollbars()
     items_visible = num_page_entries;
     item_position = 0;
 
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
-    gd_bitmap_unpressed = *scrollbar_info[i].gfx_unpressed;
-    gd_bitmap_pressed   = *scrollbar_info[i].gfx_pressed;
-    gd_x1 = 0;
-    gd_y1 = 0;
-    gd_x2 = 0;
-    gd_y2 = 0;
-#else
     gfx_unpressed = scrollbar_info[i].gfx_unpressed;
     gfx_pressed   = scrollbar_info[i].gfx_pressed;
     gd_bitmap_unpressed = graphic_info[gfx_unpressed].bitmap;
@@ -5935,7 +6875,6 @@ static void CreateScreenScrollbars()
     gd_y1 = graphic_info[gfx_unpressed].src_y;
     gd_x2 = graphic_info[gfx_pressed].src_x;
     gd_y2 = graphic_info[gfx_pressed].src_y;
-#endif
 
     gi = CreateGadget(GDI_CUSTOM_ID, id,
 		      GDI_CUSTOM_TYPE_ID, i,
@@ -5948,17 +6887,10 @@ static void CreateScreenScrollbars()
 		      GDI_SCROLLBAR_ITEMS_MAX, items_max,
 		      GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible,
 		      GDI_SCROLLBAR_ITEM_POSITION, item_position,
-#if 1
 		      GDI_WHEEL_AREA_X, SX,
 		      GDI_WHEEL_AREA_Y, SY,
 		      GDI_WHEEL_AREA_WIDTH, SXSIZE,
 		      GDI_WHEEL_AREA_HEIGHT, SYSIZE,
-#else
-		      GDI_WHEEL_AREA_X, 0,
-		      GDI_WHEEL_AREA_Y, 0,
-		      GDI_WHEEL_AREA_WIDTH, WIN_XSIZE,
-		      GDI_WHEEL_AREA_HEIGHT, WIN_YSIZE,
-#endif
 		      GDI_STATE, GD_BUTTON_UNPRESSED,
 		      GDI_DESIGN_UNPRESSED, gd_bitmap_unpressed, gd_x1, gd_y1,
 		      GDI_DESIGN_PRESSED, gd_bitmap_pressed, gd_x2, gd_y2,
@@ -5977,57 +6909,16 @@ static void CreateScreenScrollbars()
 
 void CreateScreenGadgets()
 {
-  int last_game_status = game_status;	/* save current game status */
-
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
-  int i;
-
-  for (i = 0; i < NUM_SCROLLBAR_BITMAPS; i++)
-  {
-    scrollbar_bitmap[i] = CreateBitmap(TILEX, TILEY, DEFAULT_DEPTH);
-
-    /* copy pointers to clip mask and GC */
-    scrollbar_bitmap[i]->clip_mask =
-      graphic_info[IMG_MENU_SCROLLBAR + i].clip_mask;
-    scrollbar_bitmap[i]->stored_clip_gc =
-      graphic_info[IMG_MENU_SCROLLBAR + i].clip_gc;
-
-    BlitBitmap(graphic_info[IMG_MENU_SCROLLBAR + i].bitmap,
-	       scrollbar_bitmap[i],
-	       graphic_info[IMG_MENU_SCROLLBAR + i].src_x,
-	       graphic_info[IMG_MENU_SCROLLBAR + i].src_y,
-	       TILEX, TILEY, 0, 0);
-  }
-#endif
-
   CreateScreenMenubuttons();
 
-#if 0
-  /* force LEVELS draw offset for scrollbar / scrollbutton gadgets */
-  game_status = GAME_MODE_LEVELS;
-#endif
-
   CreateScreenScrollbuttons();
   CreateScreenScrollbars();
-
-  game_status = last_game_status;	/* restore current game status */
 }
 
 void FreeScreenGadgets()
 {
   int i;
 
-#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
-  for (i = 0; i < NUM_SCROLLBAR_BITMAPS; i++)
-  {
-    /* prevent freeing clip mask and GC twice */
-    scrollbar_bitmap[i]->clip_mask = None;
-    scrollbar_bitmap[i]->stored_clip_gc = None;
-
-    FreeBitmap(scrollbar_bitmap[i]);
-  }
-#endif
-
   for (i = 0; i < NUM_SCREEN_GADGETS; i++)
     FreeGadget(screen_gadget[i]);
 }
@@ -6041,9 +6932,8 @@ void MapScreenMenuGadgets(int screen_mask)
       MapGadget(screen_gadget[menubutton_info[i].gadget_id]);
 }
 
-void MapScreenTreeGadgets(TreeInfo *ti)
+void MapScreenGadgets(int num_entries)
 {
-  int num_entries = numTreeInfoInGroup(ti);
   int i;
 
   if (num_entries <= NUM_MENU_ENTRIES_ON_SCREEN)
@@ -6056,6 +6946,11 @@ void MapScreenTreeGadgets(TreeInfo *ti)
     MapGadget(screen_gadget[scrollbar_info[i].gadget_id]);
 }
 
+void MapScreenTreeGadgets(TreeInfo *ti)
+{
+  MapScreenGadgets(numTreeInfoInGroup(ti));
+}
+
 static void HandleScreenGadgets(struct GadgetInfo *gi)
 {
   int id = gi->custom_id;
@@ -6065,11 +6960,11 @@ static void HandleScreenGadgets(struct GadgetInfo *gi)
   switch (id)
   {
     case SCREEN_CTRL_ID_PREV_LEVEL:
-      HandleMainMenu_SelectLevel(step, -1);
+      HandleMainMenu_SelectLevel(step, -1, NO_DIRECT_LEVEL_SELECT);
       break;
 
     case SCREEN_CTRL_ID_NEXT_LEVEL:
-      HandleMainMenu_SelectLevel(step, +1);
+      HandleMainMenu_SelectLevel(step, +1, NO_DIRECT_LEVEL_SELECT);
       break;
 
     case SCREEN_CTRL_ID_PREV_PLAYER:
@@ -6082,23 +6977,35 @@ static void HandleScreenGadgets(struct GadgetInfo *gi)
 
     case SCREEN_CTRL_ID_SCROLL_UP:
       if (game_status == GAME_MODE_LEVELS)
-	HandleChooseLevel(0,0, 0, -1 * SCROLL_LINE, MB_MENU_MARK);
+	HandleChooseLevelSet(0,0, 0, -1 * SCROLL_LINE, MB_MENU_MARK);
+      else if (game_status == GAME_MODE_LEVELNR)
+	HandleChooseLevelNr(0,0, 0, -1 * SCROLL_LINE, MB_MENU_MARK);
       else if (game_status == GAME_MODE_SETUP)
 	HandleSetupScreen(0,0, 0, -1 * SCROLL_LINE, MB_MENU_MARK);
+      else if (game_status == GAME_MODE_INFO)
+	HandleInfoScreen(0,0, 0, -1 * SCROLL_LINE, MB_MENU_MARK);
       break;
 
     case SCREEN_CTRL_ID_SCROLL_DOWN:
       if (game_status == GAME_MODE_LEVELS)
-	HandleChooseLevel(0,0, 0, +1 * SCROLL_LINE, MB_MENU_MARK);
+	HandleChooseLevelSet(0,0, 0, +1 * SCROLL_LINE, MB_MENU_MARK);
+      else if (game_status == GAME_MODE_LEVELNR)
+	HandleChooseLevelNr(0,0, 0, +1 * SCROLL_LINE, MB_MENU_MARK);
       else if (game_status == GAME_MODE_SETUP)
 	HandleSetupScreen(0,0, 0, +1 * SCROLL_LINE, MB_MENU_MARK);
+      else if (game_status == GAME_MODE_INFO)
+	HandleInfoScreen(0,0, 0, +1 * SCROLL_LINE, MB_MENU_MARK);
       break;
 
     case SCREEN_CTRL_ID_SCROLL_VERTICAL:
       if (game_status == GAME_MODE_LEVELS)
-	HandleChooseLevel(0,0, 999,gi->event.item_position,MB_MENU_INITIALIZE);
+	HandleChooseLevelSet(0,0,999,gi->event.item_position,MB_MENU_INITIALIZE);
+      else if (game_status == GAME_MODE_LEVELNR)
+	HandleChooseLevelNr(0,0,999,gi->event.item_position,MB_MENU_INITIALIZE);
       else if (game_status == GAME_MODE_SETUP)
 	HandleSetupScreen(0,0, 999,gi->event.item_position,MB_MENU_INITIALIZE);
+      else if (game_status == GAME_MODE_INFO)
+	HandleInfoScreen(0,0, 999,gi->event.item_position,MB_MENU_INITIALIZE);
       break;
 
     default:
diff --git a/src/screens.h b/src/screens.h
index e08e1be..c5e9ea0 100644
--- a/src/screens.h
+++ b/src/screens.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* screens.h                                                *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// screens.h
+// ============================================================================
 
 #ifndef SCREENS_H
 #define SCREENS_H
@@ -21,9 +19,7 @@
 #define SCROLL_PAGE	(2 * SCR_FIELDY)
 
 
-int effectiveGameStatus();
-
-void DrawMainMenuExt(int, boolean);
+void DrawMainMenuExt(int);
 void DrawAndFadeInMainMenu(int);
 void DrawMainMenu(void);
 void DrawHallOfFame(int);
@@ -32,7 +28,8 @@ void RedrawSetupScreenAfterFullscreenToggle();
 
 void HandleTitleScreen(int, int, int, int, int);
 void HandleMainMenu(int, int, int, int, int);
-void HandleChooseLevel(int, int, int, int, int);
+void HandleChooseLevelSet(int, int, int, int, int);
+void HandleChooseLevelNr(int, int, int, int, int);
 void HandleHallOfFame(int, int, int, int, int);
 void HandleInfoScreen(int, int, int, int, int);
 void HandleSetupScreen(int, int, int, int, int);
diff --git a/src/tape.c b/src/tape.c
index 5c90cb4..5a879d1 100644
--- a/src/tape.c
+++ b/src/tape.c
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* tape.c                                                   *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// tape.c
+// ============================================================================
 
 #include "libgame/libgame.h"
 
@@ -19,7 +17,9 @@
 #include "tools.h"
 #include "files.h"
 #include "network.h"
-#include "cartoons.h"
+#include "anim.h"
+
+#define DEBUG_TAPE_WHEN_PLAYING			FALSE
 
 /* tape button identifiers */
 #define TAPE_CTRL_ID_EJECT			0
@@ -45,105 +45,15 @@ static struct GadgetInfo *tape_gadget[NUM_TAPE_BUTTONS];
 /* video tape definitions                                                    */
 /* ========================================================================= */
 
-/* some positions in the video tape control window */
-#define VIDEO_DATE_LABEL_XPOS		(VIDEO_DISPLAY1_XPOS)
-#define VIDEO_DATE_LABEL_YPOS		(VIDEO_DISPLAY1_YPOS)
-#define VIDEO_DATE_LABEL_XSIZE		(VIDEO_DISPLAY_XSIZE)
-#define VIDEO_DATE_LABEL_YSIZE		(VIDEO_DISPLAY_YSIZE)
-#define VIDEO_DATE_XPOS			(VIDEO_DISPLAY1_XPOS + 2)
-#define VIDEO_DATE_YPOS			(VIDEO_DISPLAY1_YPOS + 14)
-#define VIDEO_DATE_XSIZE		(VIDEO_DISPLAY_XSIZE)
-#define VIDEO_DATE_YSIZE		16
-#define VIDEO_REC_LABEL_XPOS		(VIDEO_DISPLAY2_XPOS)
-#define VIDEO_REC_LABEL_YPOS		(VIDEO_DISPLAY2_YPOS)
-#define VIDEO_REC_LABEL_XSIZE		20
-#define VIDEO_REC_LABEL_YSIZE		12
-#define VIDEO_REC_SYMBOL_XPOS		(VIDEO_DISPLAY2_XPOS + 20)
-#define VIDEO_REC_SYMBOL_YPOS		(VIDEO_DISPLAY2_YPOS)
-#define VIDEO_REC_SYMBOL_XSIZE		16
-#define VIDEO_REC_SYMBOL_YSIZE		16
-#define VIDEO_PLAY_LABEL_XPOS		(VIDEO_DISPLAY2_XPOS + 65)
-#define VIDEO_PLAY_LABEL_YPOS		(VIDEO_DISPLAY2_YPOS)
-#define VIDEO_PLAY_LABEL_XSIZE		22
-#define VIDEO_PLAY_LABEL_YSIZE		12
-#define VIDEO_PLAY_SYMBOL_XPOS		(VIDEO_DISPLAY2_XPOS + 52)
-#define VIDEO_PLAY_SYMBOL_YPOS		(VIDEO_DISPLAY2_YPOS)
-#define VIDEO_PLAY_SYMBOL_XSIZE		11
-#define VIDEO_PLAY_SYMBOL_YSIZE		13
-#define VIDEO_PAUSE_LABEL_XPOS		(VIDEO_DISPLAY2_XPOS)
-#define VIDEO_PAUSE_LABEL_YPOS		(VIDEO_DISPLAY2_YPOS + 20)
-#define VIDEO_PAUSE_LABEL_XSIZE		35
-#define VIDEO_PAUSE_LABEL_YSIZE		8
-#define VIDEO_PAUSE_SYMBOL_XPOS		(VIDEO_DISPLAY2_XPOS + 35)
-#define VIDEO_PAUSE_SYMBOL_YPOS		(VIDEO_DISPLAY2_YPOS)
-#define VIDEO_PAUSE_SYMBOL_XSIZE	17
-#define VIDEO_PAUSE_SYMBOL_YSIZE	13
-#define VIDEO_TIME_XPOS			(VIDEO_DISPLAY2_XPOS + 39)
-#define VIDEO_TIME_YPOS			(VIDEO_DISPLAY2_YPOS + 14)
-#define VIDEO_TIME_XSIZE		50
-#define VIDEO_TIME_YSIZE		16
-
-/* some default values for tape labels and symbols */
-#define VIDEO_LABEL_XPOS		5
-#define VIDEO_LABEL_YPOS		42
-#define VIDEO_LABEL_XSIZE		40
-#define VIDEO_LABEL_YSIZE		28
-#define VIDEO_SYMBOL_XPOS		39
-#define VIDEO_SYMBOL_YPOS		42
-#define VIDEO_SYMBOL_XSIZE		56
-#define VIDEO_SYMBOL_YSIZE		13
-
-/* values for certain tape labels and symbols */
-#define VIDEO_FFWD_LABEL_XPOS		VIDEO_LABEL_XPOS
-#define VIDEO_FFWD_LABEL_YPOS		193
-#define VIDEO_FFWD_LABEL_XSIZE		VIDEO_LABEL_XSIZE
-#define VIDEO_FFWD_LABEL_YSIZE		VIDEO_LABEL_YSIZE
-#define VIDEO_FFWD_SYMBOL_XPOS		VIDEO_SYMBOL_XPOS
-#define VIDEO_FFWD_SYMBOL_YPOS		193
-#define VIDEO_FFWD_SYMBOL_XSIZE		27
-#define VIDEO_FFWD_SYMBOL_YSIZE		VIDEO_SYMBOL_YSIZE
-
-#define VIDEO_PBEND_LABEL_XPOS		VIDEO_LABEL_XPOS
-#define VIDEO_PBEND_LABEL_YPOS		221
-#define VIDEO_PBEND_LABEL_XSIZE		VIDEO_LABEL_XSIZE
-#define VIDEO_PBEND_LABEL_YSIZE		VIDEO_LABEL_YSIZE
-#define VIDEO_PBEND_SYMBOL_XPOS		VIDEO_SYMBOL_XPOS
-#define VIDEO_PBEND_SYMBOL_YPOS		221
-#define VIDEO_PBEND_SYMBOL_XSIZE	27
-#define VIDEO_PBEND_SYMBOL_YSIZE	VIDEO_SYMBOL_YSIZE
-
-#define VIDEO_WARP_LABEL_XPOS		VIDEO_LABEL_XPOS
-#define VIDEO_WARP_LABEL_YPOS		165
-#define VIDEO_WARP_LABEL_XSIZE		VIDEO_LABEL_XSIZE
-#define VIDEO_WARP_LABEL_YSIZE		VIDEO_LABEL_YSIZE
-#define VIDEO_WARP_SYMBOL_XPOS		VIDEO_SYMBOL_XPOS
-#define VIDEO_WARP_SYMBOL_YPOS		165
-#define VIDEO_WARP_SYMBOL_XSIZE		27
-#define VIDEO_WARP_SYMBOL_YSIZE		VIDEO_SYMBOL_YSIZE
-#define VIDEO_WARP2_SYMBOL_XPOS		VIDEO_SYMBOL_XPOS
-#define VIDEO_WARP2_SYMBOL_YPOS		152
-#define VIDEO_WARP2_SYMBOL_XSIZE	27
-#define VIDEO_WARP2_SYMBOL_YSIZE	VIDEO_SYMBOL_YSIZE
-
-#define VIDEO_1STEP_SYMBOL_XPOS		(VIDEO_SYMBOL_XPOS + 18)
-#define VIDEO_1STEP_SYMBOL_YPOS		139
-#define VIDEO_1STEP_SYMBOL_XSIZE	(VIDEO_SYMBOL_XSIZE - 18)
-#define VIDEO_1STEP_SYMBOL_YSIZE	VIDEO_SYMBOL_YSIZE
-
-#define PG_X3(x)			(DOOR_GFX_PAGEX3 + (x))
-#define PG_X4(x)			(DOOR_GFX_PAGEX4 + (x))
-#define PG_X5(x)			(DOOR_GFX_PAGEX5 + (x))
-#define PG_X6(x)			(DOOR_GFX_PAGEX6 + (x))
-
-#define PG_Y1(y)			(DOOR_GFX_PAGEY1 + (y))
-#define PG_Y2(y)			(DOOR_GFX_PAGEY2 + (y))
-
 #define VIDEO_INFO_OFF			(VIDEO_STATE_DATE_OFF	|	\
-					 VIDEO_STATE_TIME_OFF)
+					 VIDEO_STATE_TIME_OFF	|	\
+					 VIDEO_STATE_FRAME_OFF)
 #define VIDEO_STATE_OFF			(VIDEO_STATE_PLAY_OFF	|	\
 					 VIDEO_STATE_REC_OFF	|	\
 					 VIDEO_STATE_PAUSE_OFF	|	\
 					 VIDEO_STATE_FFWD_OFF	|	\
+					 VIDEO_STATE_WARP_OFF	|	\
+					 VIDEO_STATE_WARP2_OFF	|	\
 					 VIDEO_STATE_PBEND_OFF	|	\
 					 VIDEO_STATE_1STEP_OFF)
 #define VIDEO_PRESS_OFF			(VIDEO_PRESS_PLAY_OFF	|	\
@@ -156,11 +66,14 @@ static struct GadgetInfo *tape_gadget[NUM_TAPE_BUTTONS];
 	 				 VIDEO_PRESS_OFF)
 
 #define VIDEO_INFO_ON			(VIDEO_STATE_DATE_ON	|	\
-					 VIDEO_STATE_TIME_ON)
+					 VIDEO_STATE_TIME_ON	|	\
+					 VIDEO_STATE_FRAME_ON)
 #define VIDEO_STATE_ON			(VIDEO_STATE_PLAY_ON	|	\
 					 VIDEO_STATE_REC_ON	|	\
 					 VIDEO_STATE_PAUSE_ON	|	\
 					 VIDEO_STATE_FFWD_ON	|	\
+					 VIDEO_STATE_WARP_ON	|	\
+					 VIDEO_STATE_WARP2_ON	|	\
 					 VIDEO_STATE_PBEND_ON	|	\
 					 VIDEO_STATE_1STEP_ON)
 #define VIDEO_PRESS_ON			(VIDEO_PRESS_PLAY_ON	|	\
@@ -177,7 +90,7 @@ static struct GadgetInfo *tape_gadget[NUM_TAPE_BUTTONS];
 #define VIDEO_PRESS			(VIDEO_PRESS_ON | VIDEO_PRESS_OFF)
 #define VIDEO_ALL			(VIDEO_ALL_ON | VIDEO_ALL_OFF)
 
-#define NUM_TAPE_FUNCTIONS		10
+#define NUM_TAPE_FUNCTIONS		11
 #define NUM_TAPE_FUNCTION_PARTS		2
 #define NUM_TAPE_FUNCTION_STATES	2
 
@@ -186,162 +99,61 @@ static struct GadgetInfo *tape_gadget[NUM_TAPE_BUTTONS];
 /* video display functions                                                   */
 /* ========================================================================= */
 
-void DrawVideoDisplay(unsigned long state, unsigned long value)
+static void DrawVideoDisplay_Graphics(unsigned int state, unsigned int value)
 {
   int i, j, k;
-  static char *monatsname[12] =
-  {
-    "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
-    "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
-  };
+
   static struct
   {
-    int gd_x1, gd_y1;
-    int gd_x2, gd_y2;
-    int x, y;
-    int width, height;
+    int graphic;
+    struct XY *pos;
   }
   video_pos[NUM_TAPE_FUNCTIONS][NUM_TAPE_FUNCTION_PARTS] =
   {
     {
-      {
-	PG_X4(VIDEO_PLAY_LABEL_XPOS),	PG_Y2(VIDEO_PLAY_LABEL_YPOS),
-	PG_X3(VIDEO_PLAY_LABEL_XPOS),	PG_Y2(VIDEO_PLAY_LABEL_YPOS),
-	VIDEO_PLAY_LABEL_XPOS,		VIDEO_PLAY_LABEL_YPOS,
-	VIDEO_PLAY_LABEL_XSIZE,		VIDEO_PLAY_LABEL_YSIZE
-      },
-      {
-	PG_X4(VIDEO_PLAY_SYMBOL_XPOS),	PG_Y2(VIDEO_PLAY_SYMBOL_YPOS),
-	PG_X3(VIDEO_PLAY_SYMBOL_XPOS),	PG_Y2(VIDEO_PLAY_SYMBOL_YPOS),
-	VIDEO_PLAY_SYMBOL_XPOS,		VIDEO_PLAY_SYMBOL_YPOS,
-	VIDEO_PLAY_SYMBOL_XSIZE,	VIDEO_PLAY_SYMBOL_YSIZE
-      }
+      { IMG_GFX_TAPE_LABEL_PLAY,		&tape.label.play	},
+      { IMG_GFX_TAPE_SYMBOL_PLAY,		&tape.symbol.play	},
     },
     {
-      {
-	PG_X4(VIDEO_REC_LABEL_XPOS),	PG_Y2(VIDEO_REC_LABEL_YPOS),
-	PG_X3(VIDEO_REC_LABEL_XPOS),	PG_Y2(VIDEO_REC_LABEL_YPOS),
-	VIDEO_REC_LABEL_XPOS,		VIDEO_REC_LABEL_YPOS,
-	VIDEO_REC_LABEL_XSIZE,		VIDEO_REC_LABEL_YSIZE
-      },
-      {
-	PG_X4(VIDEO_REC_SYMBOL_XPOS),	PG_Y2(VIDEO_REC_SYMBOL_YPOS),
-	PG_X3(VIDEO_REC_SYMBOL_XPOS),	PG_Y2(VIDEO_REC_SYMBOL_YPOS),
-	VIDEO_REC_SYMBOL_XPOS,		VIDEO_REC_SYMBOL_YPOS,
-	VIDEO_REC_SYMBOL_XSIZE,		VIDEO_REC_SYMBOL_YSIZE
-      }
+      { IMG_GFX_TAPE_LABEL_RECORD,		&tape.label.record	},
+      { IMG_GFX_TAPE_SYMBOL_RECORD,		&tape.symbol.record	},
     },
     {
-      {
-	PG_X4(VIDEO_PAUSE_LABEL_XPOS),	PG_Y2(VIDEO_PAUSE_LABEL_YPOS),
-	PG_X3(VIDEO_PAUSE_LABEL_XPOS),	PG_Y2(VIDEO_PAUSE_LABEL_YPOS),
-	VIDEO_PAUSE_LABEL_XPOS,		VIDEO_PAUSE_LABEL_YPOS,
-	VIDEO_PAUSE_LABEL_XSIZE,	VIDEO_PAUSE_LABEL_YSIZE
-      },
-      {
-	PG_X4(VIDEO_PAUSE_SYMBOL_XPOS),	PG_Y2(VIDEO_PAUSE_SYMBOL_YPOS),
-	PG_X3(VIDEO_PAUSE_SYMBOL_XPOS),	PG_Y2(VIDEO_PAUSE_SYMBOL_YPOS),
-	VIDEO_PAUSE_SYMBOL_XPOS,	VIDEO_PAUSE_SYMBOL_YPOS,
-	VIDEO_PAUSE_SYMBOL_XSIZE,	VIDEO_PAUSE_SYMBOL_YSIZE
-      }
+      { IMG_GFX_TAPE_LABEL_PAUSE,		&tape.label.pause	},
+      { IMG_GFX_TAPE_SYMBOL_PAUSE,		&tape.symbol.pause	},
     },
     {
-      {
-	PG_X4(VIDEO_DATE_LABEL_XPOS),	PG_Y2(VIDEO_DATE_LABEL_YPOS),
-	PG_X3(VIDEO_DATE_LABEL_XPOS),	PG_Y2(VIDEO_DATE_LABEL_YPOS),
-	VIDEO_DATE_LABEL_XPOS,		VIDEO_DATE_LABEL_YPOS,
-	VIDEO_DATE_LABEL_XSIZE,		VIDEO_DATE_LABEL_YSIZE
-      },
-      {
-	PG_X4(VIDEO_DATE_XPOS),		PG_Y2(VIDEO_DATE_YPOS),
-	PG_X3(VIDEO_DATE_XPOS),		PG_Y2(VIDEO_DATE_YPOS),
-	VIDEO_DATE_XPOS,		VIDEO_DATE_YPOS,
-	VIDEO_DATE_XSIZE,		VIDEO_DATE_YSIZE
-      }
+      { IMG_GFX_TAPE_LABEL_DATE,		&tape.label.date	},
+      { -1,					NULL			},
     },
     {
-      {
-	-1,				-1,
-	-1,				-1,
-	-1,				-1,
-	-1,				-1
-      },
-      {
-	PG_X4(VIDEO_TIME_XPOS),		PG_Y2(VIDEO_TIME_YPOS),
-	PG_X3(VIDEO_TIME_XPOS),		PG_Y2(VIDEO_TIME_YPOS),
-	VIDEO_TIME_XPOS,		VIDEO_TIME_YPOS,
-	VIDEO_TIME_XSIZE,		VIDEO_TIME_YSIZE
-      }
+      { IMG_GFX_TAPE_LABEL_TIME,		&tape.label.time	},
+      { -1,					NULL			},
     },
     {
-      {
-	PG_X6(VIDEO_FFWD_LABEL_XPOS),	PG_Y1(VIDEO_FFWD_LABEL_YPOS),
-	PG_X3(VIDEO_LABEL_XPOS),	PG_Y2(VIDEO_LABEL_YPOS),
-	VIDEO_LABEL_XPOS,		VIDEO_LABEL_YPOS,
-	VIDEO_LABEL_XSIZE,		VIDEO_LABEL_YSIZE
-      },
-      {
-	PG_X6(VIDEO_FFWD_SYMBOL_XPOS),	PG_Y1(VIDEO_FFWD_SYMBOL_YPOS),
-	PG_X3(VIDEO_FFWD_SYMBOL_XPOS),	PG_Y2(VIDEO_SYMBOL_YPOS),
-	VIDEO_SYMBOL_XPOS,		VIDEO_SYMBOL_YPOS,
-	VIDEO_FFWD_SYMBOL_XSIZE,	VIDEO_FFWD_SYMBOL_YSIZE
-      }
+      /* (no label for displaying optional frame) */
+      { -1,					NULL			},
+      { -1,					NULL			},
     },
     {
-      {
-	PG_X6(VIDEO_PBEND_LABEL_XPOS),	PG_Y1(VIDEO_PBEND_LABEL_YPOS),
-	PG_X3(VIDEO_LABEL_XPOS),	PG_Y2(VIDEO_LABEL_YPOS),
-	VIDEO_LABEL_XPOS,		VIDEO_LABEL_YPOS,
-	VIDEO_LABEL_XSIZE,		VIDEO_LABEL_YSIZE
-      },
-      {
-	PG_X6(VIDEO_PBEND_SYMBOL_XPOS),	PG_Y1(VIDEO_PBEND_SYMBOL_YPOS),
-	PG_X3(VIDEO_PBEND_SYMBOL_XPOS),	PG_Y2(VIDEO_SYMBOL_YPOS),
-	VIDEO_SYMBOL_XPOS,		VIDEO_SYMBOL_YPOS,
-	VIDEO_PBEND_SYMBOL_XSIZE,	VIDEO_PBEND_SYMBOL_YSIZE
-      }
+      { IMG_GFX_TAPE_LABEL_FAST_FORWARD,	&tape.label.fast_forward  },
+      { IMG_GFX_TAPE_SYMBOL_FAST_FORWARD,	&tape.symbol.fast_forward },
     },
     {
-      {
-	PG_X6(VIDEO_WARP_LABEL_XPOS),	PG_Y1(VIDEO_WARP_LABEL_YPOS),
-	PG_X3(VIDEO_LABEL_XPOS),	PG_Y2(VIDEO_LABEL_YPOS),
-	VIDEO_LABEL_XPOS,		VIDEO_LABEL_YPOS,
-	VIDEO_LABEL_XSIZE,		VIDEO_LABEL_YSIZE
-      },
-      {
-	PG_X6(VIDEO_WARP_SYMBOL_XPOS),	PG_Y1(VIDEO_WARP_SYMBOL_YPOS),
-	PG_X3(VIDEO_WARP_SYMBOL_XPOS),	PG_Y2(VIDEO_SYMBOL_YPOS),
-	VIDEO_SYMBOL_XPOS,		VIDEO_SYMBOL_YPOS,
-	VIDEO_WARP_SYMBOL_XSIZE,	VIDEO_WARP_SYMBOL_YSIZE
-      }
+      { IMG_GFX_TAPE_LABEL_WARP_FORWARD,	&tape.label.warp_forward  },
+      { IMG_GFX_TAPE_SYMBOL_WARP_FORWARD,	&tape.symbol.warp_forward },
     },
     {
-      {
-	-1,				-1,
-	-1,				-1,
-	-1,				-1,
-	-1,				-1
-      },
-      {
-	PG_X6(VIDEO_WARP2_SYMBOL_XPOS),	PG_Y1(VIDEO_WARP2_SYMBOL_YPOS),
-	PG_X3(VIDEO_WARP2_SYMBOL_XPOS),	PG_Y2(VIDEO_SYMBOL_YPOS),
-	VIDEO_SYMBOL_XPOS,		VIDEO_SYMBOL_YPOS,
-	VIDEO_WARP2_SYMBOL_XSIZE,	VIDEO_WARP2_SYMBOL_YSIZE
-      }
+      { IMG_GFX_TAPE_LABEL_WARP_FORWARD_BLIND,	&tape.label.warp_forward_blind},
+      { IMG_GFX_TAPE_SYMBOL_WARP_FORWARD_BLIND, &tape.symbol.warp_forward_blind},
     },
     {
-      {
-	-1,				-1,
-	-1,				-1,
-	-1,				-1,
-	-1,				-1
-      },
-      {
-	PG_X6(VIDEO_1STEP_SYMBOL_XPOS),	PG_Y1(VIDEO_1STEP_SYMBOL_YPOS),
-	PG_X3(VIDEO_1STEP_SYMBOL_XPOS),	PG_Y2(VIDEO_SYMBOL_YPOS),
-	VIDEO_1STEP_SYMBOL_XPOS,	VIDEO_SYMBOL_YPOS,
-	VIDEO_1STEP_SYMBOL_XSIZE,	VIDEO_1STEP_SYMBOL_YSIZE
-      }
+      { IMG_GFX_TAPE_LABEL_PAUSE_BEFORE_END,	&tape.label.pause_before_end  },
+      { IMG_GFX_TAPE_SYMBOL_PAUSE_BEFORE_END,	&tape.symbol.pause_before_end },
+    },
+    {
+      { IMG_GFX_TAPE_LABEL_SINGLE_STEP,		&tape.label.single_step	 },
+      { IMG_GFX_TAPE_SYMBOL_SINGLE_STEP,	&tape.symbol.single_step },
     },
   };
 
@@ -351,88 +163,255 @@ void DrawVideoDisplay(unsigned long state, unsigned long value)
     {
       for (j = 0; j < NUM_TAPE_FUNCTION_PARTS; j++)	/* label or symbol */
       {
+	int graphic = video_pos[i][j].graphic;
+	struct XY *pos = video_pos[i][j].pos;
+
+	if (graphic == -1 ||
+	    pos->x == -1 ||
+	    pos->y == -1)
+	  continue;
+
 	if (state & (1 << (i * 2 + k)))
 	{
+	  struct GraphicInfo *gfx_bg = &graphic_info[IMG_BACKGROUND_TAPE];
+	  struct GraphicInfo *gfx = &graphic_info[graphic];
+	  Bitmap *gd_bitmap;
 	  int gd_x, gd_y;
 	  int skip_value =
 	    (j == 0 ? VIDEO_DISPLAY_SYMBOL_ONLY : VIDEO_DISPLAY_LABEL_ONLY);
 
+	  if (value == skip_value)
+	    continue;
+
 	  if (k == 1)		/* on */
 	  {
-	    gd_x = video_pos[i][j].gd_x1;
-	    gd_y = video_pos[i][j].gd_y1;
+	    gd_bitmap = gfx->bitmap;
+	    gd_x = gfx->src_x;
+	    gd_y = gfx->src_y;
 	  }
 	  else			/* off */
 	  {
-	    gd_x = video_pos[i][j].gd_x2;
-	    gd_y = video_pos[i][j].gd_y2;
+	    gd_bitmap = gfx_bg->bitmap;
+	    gd_x = gfx_bg->src_x + pos->x;
+	    gd_y = gfx_bg->src_y + pos->y;
 	  }
 
-	  if (video_pos[i][j].x != -1 && value != skip_value)
-	    BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
-		       gd_x, gd_y,
-		       video_pos[i][j].width,
-		       video_pos[i][j].height,
-		       VX + video_pos[i][j].x,
-		       VY + video_pos[i][j].y);
+	  /* some tape graphics may be undefined -- only draw if defined */
+	  if (gd_bitmap != NULL)
+	    BlitBitmap(gd_bitmap, drawto, gd_x, gd_y, gfx->width, gfx->height,
+		       VX + pos->x, VY + pos->y);
+
+	  redraw_mask |= REDRAW_DOOR_2;
 	}
       }
     }
   }
+}
+
+
+#define DATETIME_NONE			(0)
+
+#define DATETIME_DATE_YYYY		(1 << 0)
+#define DATETIME_DATE_YY		(1 << 1)
+#define DATETIME_DATE_MON		(1 << 2)
+#define DATETIME_DATE_MM		(1 << 3)
+#define DATETIME_DATE_DD		(1 << 4)
+
+#define DATETIME_TIME_HH		(1 << 5)
+#define DATETIME_TIME_MIN		(1 << 6)
+#define DATETIME_TIME_MM		(1 << 7)
+#define DATETIME_TIME_SS		(1 << 8)
+
+#define DATETIME_FRAME			(1 << 9)
+
+#define DATETIME_XOFFSET_1		(1 << 10)
+#define DATETIME_XOFFSET_2		(1 << 11)
+
+#define DATETIME_DATE			(DATETIME_DATE_YYYY	|	\
+					 DATETIME_DATE_YY	|	\
+					 DATETIME_DATE_MON	|	\
+					 DATETIME_DATE_MM	|	\
+					 DATETIME_DATE_DD)
+
+#define DATETIME_TIME			(DATETIME_TIME_HH	|	\
+					 DATETIME_TIME_MIN	|	\
+					 DATETIME_TIME_MM	|	\
+					 DATETIME_TIME_SS)
+
+#define MAX_DATETIME_STRING_SIZE	32
+
+static void DrawVideoDisplay_DateTime(unsigned int state, unsigned int value)
+{
+  int i;
+
+  static char *month_shortnames[] =
+  {
+    "JAN",
+    "FEB",
+    "MAR",
+    "APR",
+    "MAY",
+    "JUN",
+    "JUL",
+    "AUG",
+    "SEP",
+    "OCT",
+    "NOV",
+    "DEC"
+  };
+
+  static struct
+  {
+    struct TextPosInfo *pos;
+    int type;
+  }
+  datetime_info[] =
+  {
+    { &tape.text.date,		DATETIME_DATE_DD			},
+    { &tape.text.date,		DATETIME_DATE_MON | DATETIME_XOFFSET_1	},
+    { &tape.text.date,		DATETIME_DATE_YY  | DATETIME_XOFFSET_2	},
+    { &tape.text.date_yyyy,	DATETIME_DATE_YYYY			},
+    { &tape.text.date_yy,	DATETIME_DATE_YY			},
+    { &tape.text.date_mon,	DATETIME_DATE_MON			},
+    { &tape.text.date_mm,	DATETIME_DATE_MM			},
+    { &tape.text.date_dd,	DATETIME_DATE_DD			},
+
+    { &tape.text.time,		DATETIME_TIME_MIN			},
+    { &tape.text.time,		DATETIME_TIME_SS  | DATETIME_XOFFSET_1	},
+    { &tape.text.time_hh,	DATETIME_TIME_HH			},
+    { &tape.text.time_mm,	DATETIME_TIME_MM			},
+    { &tape.text.time_ss,	DATETIME_TIME_SS			},
+
+    { &tape.text.frame,		DATETIME_FRAME				},
+
+    { NULL,			DATETIME_NONE				},
+  };
 
-  if (state & VIDEO_STATE_DATE_ON)
+  for (i = 0; datetime_info[i].pos != NULL; i++)
   {
-    int tag = value % 100;
-    int monat = (value/100) % 100;
-    int jahr = (value/10000);
-
-    DrawText(VX + VIDEO_DATE_XPOS, VY + VIDEO_DATE_YPOS,
-	     int2str(tag, 2), FONT_TAPE_RECORDER);
-    DrawText(VX + VIDEO_DATE_XPOS + 27, VY + VIDEO_DATE_YPOS,
-	     monatsname[monat], FONT_TAPE_RECORDER);
-    DrawText(VX + VIDEO_DATE_XPOS + 64, VY + VIDEO_DATE_YPOS,
-	     int2str(jahr, 2), FONT_TAPE_RECORDER);
+    struct TextPosInfo *pos = datetime_info[i].pos;
+    int type = datetime_info[i].type;
+    int xpos, ypos;
+
+    if (pos->x == -1 &&
+	pos->y == -1)
+      continue;
+
+    xpos = VX + pos->x + (type & DATETIME_XOFFSET_1 ? pos->xoffset  :
+			  type & DATETIME_XOFFSET_2 ? pos->xoffset2 : 0);
+    ypos = VY + pos->y;
+
+    if ((type & DATETIME_DATE) && (state & VIDEO_STATE_DATE_ON))
+    {
+      char s[MAX_DATETIME_STRING_SIZE];
+      int year2 = value / 10000;
+      int year4 = (year2 < 70 ? 2000 + year2 : 1900 + year2);
+      int month_index = (value / 100) % 100;
+      int month = month_index + 1;
+      int day = value % 100;
+
+      strcpy(s, (type & DATETIME_DATE_YYYY ? int2str(year4, 4) :
+		 type & DATETIME_DATE_YY   ? int2str(year2, 2) :
+		 type & DATETIME_DATE_MON  ? month_shortnames[month_index] :
+		 type & DATETIME_DATE_MM   ? int2str(month, 2) :
+		 type & DATETIME_DATE_DD   ? int2str(day, 2) : ""));
+
+      DrawText(xpos, ypos, s, pos->font);
+    }
+    else if ((type & DATETIME_TIME) && (state & VIDEO_STATE_TIME_ON))
+    {
+      char s[MAX_DATETIME_STRING_SIZE];
+      int hh = (value / 3600) % 100;
+      int min = value / 60;
+      int mm = (value / 60) % 60;
+      int ss = value % 60;
+
+      strcpy(s, (type & DATETIME_TIME_HH  ? int2str(hh, 2) :
+		 type & DATETIME_TIME_MIN ? int2str(min, 2) :
+		 type & DATETIME_TIME_MM  ? int2str(mm, 2) :
+		 type & DATETIME_TIME_SS  ? int2str(ss, 2) : ""));
+
+      DrawText(xpos, ypos, s, pos->font);
+    }
+    else if ((type & DATETIME_FRAME) && (state & VIDEO_STATE_FRAME_ON))
+    {
+      DrawText(xpos, ypos, int2str(value, pos->size), pos->font);
+    }
   }
+}
+
+void DrawVideoDisplay(unsigned int state, unsigned int value)
+{
+  DrawVideoDisplay_Graphics(state, value);
+  DrawVideoDisplay_DateTime(state, value);
+}
+
+void DrawVideoDisplayLabel(unsigned int state)
+{
+  DrawVideoDisplay(state, VIDEO_DISPLAY_LABEL_ONLY);
+}
+
+void DrawVideoDisplaySymbol(unsigned int state)
+{
+  DrawVideoDisplay(state, VIDEO_DISPLAY_SYMBOL_ONLY);
+}
+
+void DrawVideoDisplayCurrentState()
+{
+  int state = 0;
+
+  DrawVideoDisplay(VIDEO_STATE_OFF, 0);
+
+  if (tape.pausing)
+    state |= VIDEO_STATE_PAUSE_ON;
+
+  if (tape.recording)
+  {
+    state |= VIDEO_STATE_REC_ON;
 
-  if (state & VIDEO_STATE_TIME_ON)
+    if (tape.single_step)
+      state |= VIDEO_STATE_1STEP_ON;
+  }
+  else if (tape.playing)
   {
-    int min = value / 60;
-    int sec = value % 60;
+    state |= VIDEO_STATE_PLAY_ON;
 
-    DrawText(VX + VIDEO_TIME_XPOS, VY + VIDEO_TIME_YPOS,
-	     int2str(min, 2), FONT_TAPE_RECORDER);
-    DrawText(VX + VIDEO_TIME_XPOS + 27, VY + VIDEO_TIME_YPOS,
-	     int2str(sec, 2), FONT_TAPE_RECORDER);
+    if (tape.deactivate_display)
+      state |= VIDEO_STATE_WARP2_ON;
+    else if (tape.warp_forward)
+      state |= VIDEO_STATE_WARP_ON;
+    else if (tape.fast_forward)
+      state |= VIDEO_STATE_FFWD_ON;
+
+    if (tape.pause_before_end)
+      state |= VIDEO_STATE_PBEND_ON;
   }
 
-  redraw_mask |= REDRAW_DOOR_2;
+  // draw labels and symbols separately to prevent labels overlapping symbols
+  DrawVideoDisplayLabel(state);
+  DrawVideoDisplaySymbol(state);
 }
 
 void DrawCompleteVideoDisplay()
 {
-#if 0
-  printf("::: %d, %d  /  %d, %d [%d] [%d, %d] [%d/%d]\n",
-	 VX, VY, EX, EY, game_status, gfx.vx, gfx.vy,
-	 tape.date, tape.length);
-#endif
+  struct GraphicInfo *g_tape = &graphic_info[IMG_BACKGROUND_TAPE];
 
-  BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
-	     DOOR_GFX_PAGEX3, DOOR_GFX_PAGEY2,
+  /* draw tape background */
+  BlitBitmap(g_tape->bitmap, drawto, g_tape->src_x, g_tape->src_y,
 	     gfx.vxsize, gfx.vysize, gfx.vx, gfx.vy);
-  BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
-	     DOOR_GFX_PAGEX4 + VIDEO_CONTROL_XPOS,
-	     DOOR_GFX_PAGEY2 + VIDEO_CONTROL_YPOS,
-	     VIDEO_CONTROL_XSIZE, VIDEO_CONTROL_YSIZE,
-	     gfx.vx + VIDEO_CONTROL_XPOS, gfx.vy + VIDEO_CONTROL_YPOS);
+
+  /* draw tape buttons (forced) */
+  UnmapTapeButtons();
+  MapTapeButtons();
 
   DrawVideoDisplay(VIDEO_ALL_OFF, 0);
 
-#if 1
   if (tape.recording)
   {
     DrawVideoDisplay(VIDEO_STATE_REC_ON, 0);
     DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
     DrawVideoDisplay(VIDEO_STATE_TIME_ON, tape.length_seconds);
+    DrawVideoDisplay(VIDEO_STATE_FRAME_ON, tape.length_frames);
 
     if (tape.pausing)
       DrawVideoDisplay(VIDEO_STATE_PAUSE_ON, 0);
@@ -442,6 +421,7 @@ void DrawCompleteVideoDisplay()
     DrawVideoDisplay(VIDEO_STATE_PLAY_ON, 0);
     DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
     DrawVideoDisplay(VIDEO_STATE_TIME_ON, 0);
+    DrawVideoDisplay(VIDEO_STATE_FRAME_ON, 0);
 
     if (tape.pausing)
       DrawVideoDisplay(VIDEO_STATE_PAUSE_ON, 0);
@@ -450,17 +430,11 @@ void DrawCompleteVideoDisplay()
   {
     DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
     DrawVideoDisplay(VIDEO_STATE_TIME_ON, tape.length_seconds);
+    DrawVideoDisplay(VIDEO_STATE_FRAME_ON, tape.length_frames);
   }
-#else
-  if (tape.date && tape.length)
-  {
-    DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
-    DrawVideoDisplay(VIDEO_STATE_TIME_ON, tape.length_seconds);
-  }
-#endif
 
-  BlitBitmap(drawto, bitmap_db_door, gfx.vx, gfx.vy, gfx.vxsize, gfx.vysize,
-	     DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
+  BlitBitmap(drawto, bitmap_db_door_2, gfx.vx, gfx.vy, gfx.vxsize, gfx.vysize,
+	     0, 0);
 }
 
 void TapeDeactivateDisplayOn()
@@ -476,7 +450,7 @@ void TapeDeactivateDisplayOff(boolean redraw_display)
 
   if (redraw_display)
   {
-    RedrawPlayfield(TRUE, 0,0,0,0);
+    RedrawPlayfield();
     DrawGameDoorValues();
   }
 }
@@ -504,6 +478,7 @@ void TapeErase()
 
   tape.counter = 0;
   tape.length = 0;
+  tape.length_frames = 0;
   tape.length_seconds = 0;
 
   if (leveldir_current)
@@ -532,7 +507,7 @@ static void TapeRewind()
 {
   tape.counter = 0;
   tape.delay_played = 0;
-  tape.pause_before_death = FALSE;
+  tape.pause_before_end = FALSE;
   tape.recording = FALSE;
   tape.playing = FALSE;
   tape.fast_forward = FALSE;
@@ -549,12 +524,12 @@ static void TapeRewind()
   InitRND(tape.random_seed);
 }
 
-static void TapeSetRandomSeed(long random_seed)
+static void TapeSetRandomSeed(int random_seed)
 {
   tape.random_seed = InitRND(random_seed);
 }
 
-void TapeStartRecording(long random_seed)
+void TapeStartRecording(int random_seed)
 {
   if (!TAPE_IS_STOPPED(tape))
     TapeStop();
@@ -568,6 +543,7 @@ void TapeStartRecording(long random_seed)
   DrawVideoDisplay(VIDEO_STATE_REC_ON, 0);
   DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
   DrawVideoDisplay(VIDEO_STATE_TIME_ON, 0);
+  DrawVideoDisplay(VIDEO_STATE_FRAME_ON, 0);
 
   MapTapeWarpButton();
 
@@ -596,19 +572,27 @@ static void TapeAppendRecording()
   if (!tape.playing || !tape.pausing)
     return;
 
-  tape.pos[tape.counter].delay = tape.delay_played;
+  // stop playing
   tape.playing = FALSE;
+  tape.fast_forward = FALSE;
+  tape.warp_forward = FALSE;
+  tape.pause_before_end = FALSE;
+  tape.deactivate_display = FALSE;
+
+  // start recording
   tape.recording = TRUE;
   tape.changed = TRUE;
 
+  // set current delay (for last played move)
+  tape.pos[tape.counter].delay = tape.delay_played;
+
+  // set current date
   TapeSetDateFromNow();
 
   DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
   DrawVideoDisplay(VIDEO_STATE_PLAY_OFF | VIDEO_STATE_REC_ON, 0);
 
-#if 1
   UpdateAndDisplayGameControlValues();
-#endif
 }
 
 void TapeHaltRecording()
@@ -620,7 +604,8 @@ void TapeHaltRecording()
   tape.pos[tape.counter].delay = 0;
 
   tape.length = tape.counter;
-  tape.length_seconds = GetTapeLength();
+  tape.length_frames = GetTapeLengthFrames();
+  tape.length_seconds = GetTapeLengthSeconds();
 }
 
 void TapeStopRecording()
@@ -687,43 +672,55 @@ void TapeRecordAction(byte action_raw[MAX_PLAYERS])
   }
 }
 
-void TapeTogglePause(boolean toggle_manual)
+void TapeTogglePause(boolean toggle_mode)
 {
-  int state = 0;
+  if (tape.playing && tape.pausing && (toggle_mode & TAPE_TOGGLE_PLAY_PAUSE))
+  {
+    // continue playing in normal mode
+    tape.fast_forward = FALSE;
+    tape.warp_forward = FALSE;
+    tape.deactivate_display = FALSE;
 
-  if (tape.pause_before_death)
-    state |= VIDEO_STATE_PBEND_OFF;
-  else if (tape.fast_forward)
-    state |= VIDEO_STATE_FFWD_OFF;
+    tape.pause_before_end = FALSE;
+  }
 
   tape.pausing = !tape.pausing;
-  tape.fast_forward = FALSE;
-  tape.pause_before_death = FALSE;
 
-  if (tape.single_step && toggle_manual)
+  if (tape.single_step && (toggle_mode & TAPE_TOGGLE_MANUAL))
     tape.single_step = FALSE;
 
-  state |= (tape.pausing ? VIDEO_STATE_PAUSE_ON : VIDEO_STATE_PAUSE_OFF);
-  if (tape.playing)
-    state |= VIDEO_STATE_PLAY_ON;
-  else
-    state |= (tape.single_step ? VIDEO_STATE_1STEP_ON : VIDEO_STATE_1STEP_OFF);
+  DrawVideoDisplayCurrentState();
 
-  DrawVideoDisplay(state, 0);
+  if (tape.deactivate_display)
+  {
+    if (tape.pausing)
+      TapeDeactivateDisplayOff(game_status == GAME_MODE_PLAYING);
+    else
+      TapeDeactivateDisplayOn();
+  }
 
-  if (tape.warp_forward)
+  if (tape.quick_resume)
   {
+    tape.quick_resume = FALSE;
+
     TapeStopWarpForward();
+    TapeAppendRecording();
 
-    if (tape.quick_resume)
-    {
-      tape.quick_resume = FALSE;
+    if (!CheckEngineSnapshotSingle())
+      SaveEngineSnapshotSingle();
 
-      TapeAppendRecording();
+    // restart step/move snapshots after quick loading tape
+    SaveEngineSnapshotToListInitial();
+  }
 
-      if (!CheckEngineSnapshot())
-	SaveEngineSnapshot();
-    }
+  if (setup.show_snapshot_buttons &&
+      game_status == GAME_MODE_PLAYING &&
+      CheckEngineSnapshotList())
+  {
+    if (tape.pausing)
+      MapUndoRedoButtons();
+    else if (!tape.single_step)
+      UnmapUndoRedoButtons();
   }
 }
 
@@ -742,6 +739,7 @@ void TapeStartPlaying()
   DrawVideoDisplay(VIDEO_STATE_PLAY_ON, 0);
   DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
   DrawVideoDisplay(VIDEO_STATE_TIME_ON, 0);
+  DrawVideoDisplay(VIDEO_STATE_FRAME_ON, 0);
 
   MapTapeWarpButton();
 
@@ -770,79 +768,68 @@ void TapeStopPlaying()
 
 byte *TapePlayAction()
 {
+  int update_delay = FRAMES_PER_SECOND / 2;
+  boolean update_video_display = (FrameCounter % update_delay == 0);
+  boolean update_draw_label_on = ((FrameCounter / update_delay) % 2 == 1);
   static byte action[MAX_PLAYERS];
   int i;
 
   if (!tape.playing || tape.pausing)
     return NULL;
 
-  if (tape.pause_before_death)	/* stop 10 seconds before player gets killed */
+  if (tape.pause_before_end)  // stop some seconds before end of tape
   {
-    if (!(FrameCounter % 20))
-    {
-      if ((FrameCounter / 20) % 2)
-	DrawVideoDisplay(VIDEO_STATE_PBEND_ON, VIDEO_DISPLAY_LABEL_ONLY);
-      else
-	DrawVideoDisplay(VIDEO_STATE_PBEND_OFF, VIDEO_DISPLAY_LABEL_ONLY);
-    }
-
-    if (tape.warp_forward)
-    {
-      if (tape.deactivate_display)
-	DrawVideoDisplay(VIDEO_STATE_WARP_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
-      else
-	DrawVideoDisplay(VIDEO_STATE_WARP2_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
-    }
-
     if (TapeTime > tape.length_seconds - TAPE_PAUSE_SECONDS_BEFORE_DEATH)
     {
+      TapeStopWarpForward();
       TapeTogglePause(TAPE_TOGGLE_MANUAL);
 
       return NULL;
     }
   }
-  else if (tape.fast_forward)
+
+  if (tape.counter >= tape.length)	/* end of tape reached */
   {
-    if ((FrameCounter / 20) % 2)
-      DrawVideoDisplay(VIDEO_STATE_FFWD_ON, VIDEO_DISPLAY_LABEL_ONLY);
+    if (tape.warp_forward && !tape.auto_play)
+    {
+      TapeStopWarpForward();
+      TapeTogglePause(TAPE_TOGGLE_MANUAL);
+    }
     else
-      DrawVideoDisplay(VIDEO_STATE_FFWD_OFF, VIDEO_DISPLAY_LABEL_ONLY);
-
-    if (tape.warp_forward)
     {
-      if (tape.deactivate_display)
-	DrawVideoDisplay(VIDEO_STATE_WARP_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
-      else
-	DrawVideoDisplay(VIDEO_STATE_WARP2_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
+      TapeStop();
     }
+
+    return NULL;
   }
 
-#if 0
-  /* !!! this makes things much slower !!! */
-  else if (tape.warp_forward)
+  if (update_video_display && !tape.deactivate_display)
   {
-    if ((FrameCounter / 20) % 2)
-      DrawVideoDisplay(VIDEO_STATE_WARP_ON, VIDEO_DISPLAY_LABEL_ONLY);
-    else
-      DrawVideoDisplay(VIDEO_STATE_WARP_OFF, VIDEO_DISPLAY_LABEL_ONLY);
+    int state = 0;
 
-    DrawVideoDisplay(VIDEO_STATE_WARP_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
-  }
-#endif
+    if (tape.warp_forward)
+      state |= VIDEO_STATE_WARP(update_draw_label_on);
+    else if (tape.fast_forward)
+      state |= VIDEO_STATE_FFWD(update_draw_label_on);
 
-  if (tape.counter >= tape.length)	/* end of tape reached */
-  {
-    if (tape.warp_forward && !tape.auto_play)
-      TapeTogglePause(TAPE_TOGGLE_MANUAL);
-    else
-      TapeStop();
+    if (tape.pause_before_end)
+      state |= VIDEO_STATE_PBEND(update_draw_label_on);
 
-    return NULL;
+    // draw labels and symbols separately to prevent labels overlapping symbols
+    DrawVideoDisplayLabel(state);
+    DrawVideoDisplaySymbol(state);
   }
 
   for (i = 0; i < MAX_PLAYERS; i++)
     action[i] = tape.pos[tape.counter].action[i];
 
+#if DEBUG_TAPE_WHEN_PLAYING
+  printf("%05d", FrameCounter);
+  for (i = 0; i < MAX_PLAYERS; i++)
+    printf("   %08x", action[i]);
+  printf("\n");
+#endif
+
   tape.set_centered_player = FALSE;
   tape.centered_player_nr_next = -999;
 
@@ -879,58 +866,54 @@ void TapeStop()
   {
     DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
     DrawVideoDisplay(VIDEO_STATE_TIME_ON, tape.length_seconds);
+    DrawVideoDisplay(VIDEO_STATE_FRAME_ON, tape.length_frames);
   }
 }
 
-unsigned int GetTapeLength()
+unsigned int GetTapeLengthFrames()
 {
-  unsigned int tape_length = 0;
+  unsigned int tape_length_frames = 0;
   int i;
 
   if (TAPE_IS_EMPTY(tape))
     return(0);
 
   for (i = 0; i < tape.length; i++)
-    tape_length += tape.pos[i].delay;
+    tape_length_frames += tape.pos[i].delay;
 
-  return(tape_length * GAME_FRAME_DELAY / 1000);
+  return tape_length_frames;
 }
 
-static void TapeStartWarpForward()
+unsigned int GetTapeLengthSeconds()
 {
-  tape.warp_forward = TRUE;
+  return (GetTapeLengthFrames() * GAME_FRAME_DELAY / 1000);
+}
 
-  if (!tape.fast_forward && !tape.pause_before_death)
-  {
-    tape.pausing = FALSE;
-    tape.deactivate_display = TRUE;
+static void TapeStartWarpForward(int mode)
+{
+  tape.fast_forward = (mode & AUTOPLAY_FFWD);
+  tape.warp_forward = (mode & AUTOPLAY_WARP);
+  tape.deactivate_display = (mode & AUTOPLAY_WARP_NO_DISPLAY);
 
+  tape.pausing = FALSE;
+
+  if (tape.deactivate_display)
     TapeDeactivateDisplayOn();
-  }
 
-  if (tape.fast_forward || tape.pause_before_death)
-    DrawVideoDisplay(VIDEO_STATE_WARP_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
-  else
-    DrawVideoDisplay(VIDEO_STATE_WARP_ON, 0);
+  DrawVideoDisplayCurrentState();
 }
 
 static void TapeStopWarpForward()
 {
-  int state = (tape.pausing ? VIDEO_STATE_PAUSE_ON : VIDEO_STATE_PAUSE_OFF);
-
+  tape.fast_forward = FALSE;
   tape.warp_forward = FALSE;
   tape.deactivate_display = FALSE;
 
-  TapeDeactivateDisplayOff(game_status == GAME_MODE_PLAYING);
+  tape.pause_before_end = FALSE;
 
-  if (tape.pause_before_death)
-    state |= VIDEO_STATE_WARP_OFF | VIDEO_STATE_PBEND_ON;
-  else if (tape.fast_forward)
-    state |= VIDEO_STATE_WARP_OFF | VIDEO_STATE_FFWD_ON;
-  else
-    state |= VIDEO_STATE_WARP_OFF | VIDEO_STATE_PLAY_ON;
+  TapeDeactivateDisplayOff(game_status == GAME_MODE_PLAYING);
 
-  DrawVideoDisplay(state, 0);
+  DrawVideoDisplayCurrentState();
 }
 
 static void TapeSingleStep()
@@ -943,15 +926,14 @@ static void TapeSingleStep()
 
   tape.single_step = !tape.single_step;
 
-  DrawVideoDisplay((tape.single_step ? VIDEO_STATE_1STEP_ON :
-		    VIDEO_STATE_1STEP_OFF), 0);
+  DrawVideoDisplay(VIDEO_STATE_1STEP(tape.single_step), 0);
 }
 
 void TapeQuickSave()
 {
   if (game_status == GAME_MODE_MAIN)
   {
-    Request("No game that can be saved !", REQ_CONFIRM);
+    Request("No game that can be saved!", REQ_CONFIRM);
 
     return;
   }
@@ -964,13 +946,13 @@ void TapeQuickSave()
 
   if (TAPE_IS_EMPTY(tape))
   {
-    Request("No tape that can be saved !", REQ_CONFIRM);
+    Request("No tape that can be saved!", REQ_CONFIRM);
 
     return;
   }
 
   if (SaveTapeChecked(tape.level_nr))
-    SaveEngineSnapshot();
+    SaveEngineSnapshotSingle();
 }
 
 void TapeQuickLoad()
@@ -979,12 +961,12 @@ void TapeQuickLoad()
 
   if (!fileExists(filename))
   {
-    Request("No tape for this level !", REQ_CONFIRM);
+    Request("No tape for this level!", REQ_CONFIRM);
 
     return;
   }
 
-  if (tape.recording && !Request("Stop recording and load tape ?",
+  if (tape.recording && !Request("Stop recording and load tape?",
 				 REQ_ASK | REQ_STAY_CLOSED))
   {
     OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
@@ -995,11 +977,11 @@ void TapeQuickLoad()
   if (game_status != GAME_MODE_PLAYING && game_status != GAME_MODE_MAIN)
     return;
 
-  if (CheckEngineSnapshot())
+  if (CheckEngineSnapshotSingle())
   {
     TapeStartGamePlaying();
 
-    LoadEngineSnapshot();
+    LoadEngineSnapshotSingle();
 
     DrawCompleteVideoDisplay();
 
@@ -1009,6 +991,9 @@ void TapeQuickLoad()
     TapeStopWarpForward();
     TapeAppendRecording();
 
+    // restart step/move snapshots after quick loading tape
+    SaveEngineSnapshotToListInitial();
+
     if (FrameCounter > 0)
       return;
   }
@@ -1021,7 +1006,7 @@ void TapeQuickLoad()
   if (!TAPE_IS_EMPTY(tape))
   {
     TapeStartGamePlaying();
-    TapeStartWarpForward();
+    TapeStartWarpForward(AUTOPLAY_MODE_WARP_NO_DISPLAY);
 
     tape.quick_resume = TRUE;
   }
@@ -1029,7 +1014,7 @@ void TapeQuickLoad()
   {
     int reopen_door = (game_status == GAME_MODE_PLAYING ? REQ_REOPEN : 0);
 
-    Request("No tape for this level !", REQ_CONFIRM | reopen_door);
+    Request("No tape for this level!", REQ_CONFIRM | reopen_door);
   }
 }
 
@@ -1041,7 +1026,7 @@ void InsertSolutionTape()
   LoadSolutionTape(level_nr);
 
   if (TAPE_IS_EMPTY(tape))
-    Request("No solution tape for this level !", REQ_CONFIRM);
+    Request("No solution tape for this level!", REQ_CONFIRM);
 
   DrawCompleteVideoDisplay();
 }
@@ -1060,13 +1045,12 @@ void AutoPlayTape()
   static int num_levels_solved = 0;
   static int num_tape_missing = 0;
   static boolean level_failed[MAX_TAPES_PER_SET];
-  static boolean tape_missing[MAX_TAPES_PER_SET];
   int i;
 
   if (autoplay_initialized)
   {
     /* just finished auto-playing tape */
-    printf("%s.\n", tape.auto_play_level_solved ? "solved" : "NOT SOLVED");
+    Print("%s.\n", tape.auto_play_level_solved ? "solved" : "NOT SOLVED");
 
     num_levels_played++;
 
@@ -1078,7 +1062,9 @@ void AutoPlayTape()
   else
   {
     DrawCompleteVideoDisplay();
+
     audio.sound_enabled = FALSE;
+    setup.engine_snapshot_mode = getStringCopy(STR_SNAPSHOT_MODE_OFF);
 
     autoplay_leveldir = getTreeInfoFromIdentifier(leveldir_first,
 						  global.autoplay_leveldir);
@@ -1096,21 +1082,18 @@ void AutoPlayTape()
 
     autoplay_level_nr = autoplay_leveldir->first_level;
 
-    printf_line("=", 79);
-    printf("Automatically playing level tapes\n");
-    printf_line("-", 79);
-    printf("Level series identifier: '%s'\n", autoplay_leveldir->identifier);
-    printf("Level series name:       '%s'\n", autoplay_leveldir->name);
-    printf("Level series author:     '%s'\n", autoplay_leveldir->author);
-    printf("Number of levels:        %d\n",   autoplay_leveldir->levels);
-    printf_line("=", 79);
-    printf("\n");
+    PrintLine("=", 79);
+    Print("Automatically playing level tapes\n");
+    PrintLine("-", 79);
+    Print("Level series identifier: '%s'\n", autoplay_leveldir->identifier);
+    Print("Level series name:       '%s'\n", autoplay_leveldir->name);
+    Print("Level series author:     '%s'\n", autoplay_leveldir->author);
+    Print("Number of levels:        %d\n",   autoplay_leveldir->levels);
+    PrintLine("=", 79);
+    Print("\n");
 
     for (i = 0; i < MAX_TAPES_PER_SET; i++)
-    {
       level_failed[i] = FALSE;
-      tape_missing[i] = FALSE;
-    }
 
     autoplay_initialized = TRUE;
   }
@@ -1124,72 +1107,64 @@ void AutoPlayTape()
 
     TapeErase();
 
-    printf("Level %03d: ", level_nr);
+    Print("Level %03d: ", level_nr);
 
     LoadLevel(level_nr);
     if (level.no_valid_file)
     {
-      printf("(no level)\n");
+      Print("(no level)\n");
       continue;
     }
 
 #if 0
     /* ACTIVATE THIS FOR LOADING/TESTING OF LEVELS ONLY */
-    printf("(only testing level)\n");
+    Print("(only testing level)\n");
     continue;
 #endif
 
-    LoadSolutionTape(level_nr);
+    if (options.mytapes)
+      LoadTape(level_nr);
+    else
+      LoadSolutionTape(level_nr);
 
     if (tape.no_valid_file)
     {
       num_tape_missing++;
-      if (level_nr >= 0 && level_nr < MAX_TAPES_PER_SET)
-	tape_missing[level_nr] = TRUE;
 
-      printf("(no tape)\n");
+      Print("(no tape)\n");
+
       continue;
     }
 
-    printf("playing tape ... ");
+    Print("playing tape ... ");
 
     TapeStartGamePlaying();
-    TapeStartWarpForward();
+    TapeStartWarpForward(global.autoplay_mode);
 
     return;
   }
 
-  printf("\n");
-  printf_line("=", 79);
-  printf("Number of levels played: %d\n", num_levels_played);
-  printf("Number of levels solved: %d (%d%%)\n", num_levels_solved,
+  Print("\n");
+  PrintLine("=", 79);
+  Print("Number of levels played: %d\n", num_levels_played);
+  Print("Number of levels solved: %d (%d%%)\n", num_levels_solved,
 	 (num_levels_played ? num_levels_solved * 100 / num_levels_played :0));
-  printf_line("-", 79);
-  printf("Summary (for automatic parsing by scripts):\n");
-  printf("LEVELDIR '%s', SOLVED %d/%d (%d%%)",
+  PrintLine("-", 79);
+  Print("Summary (for automatic parsing by scripts):\n");
+  Print("LEVELDIR '%s', SOLVED %d/%d (%d%%)",
 	 autoplay_leveldir->identifier, num_levels_solved, num_levels_played,
 	 (num_levels_played ? num_levels_solved * 100 / num_levels_played :0));
 
   if (num_levels_played != num_levels_solved)
   {
-    printf(", FAILED:");
+    Print(", FAILED:");
     for (i = 0; i < MAX_TAPES_PER_SET; i++)
       if (level_failed[i])
-	printf(" %03d", i);
-  }
-
-#if 0
-  if (num_tape_missing > 0)
-  {
-    printf(", NO TAPE:");
-    for (i = 0; i < MAX_TAPES_PER_SET; i++)
-      if (tape_missing[i])
-	printf(" %03d", i);
+	Print(" %03d", i);
   }
-#endif
 
-  printf("\n");
-  printf_line("=", 79);
+  Print("\n");
+  PrintLine("=", 79);
 
   CloseAllAndExit(0);
 }
@@ -1197,55 +1172,38 @@ void AutoPlayTape()
 
 /* ---------- new tape button stuff ---------------------------------------- */
 
-/* graphic position values for tape buttons */
-#define TAPE_BUTTON_XSIZE	18
-#define TAPE_BUTTON_YSIZE	18
-#define TAPE_BUTTON_XPOS	5
-#define TAPE_BUTTON_YPOS	77
-
-#define TAPE_BUTTON_EJECT_XPOS	(TAPE_BUTTON_XPOS + 0 * TAPE_BUTTON_XSIZE)
-#define TAPE_BUTTON_EXTRA_XPOS	(TAPE_BUTTON_XPOS + 0 * TAPE_BUTTON_XSIZE)
-#define TAPE_BUTTON_STOP_XPOS	(TAPE_BUTTON_XPOS + 1 * TAPE_BUTTON_XSIZE)
-#define TAPE_BUTTON_PAUSE_XPOS	(TAPE_BUTTON_XPOS + 2 * TAPE_BUTTON_XSIZE)
-#define TAPE_BUTTON_RECORD_XPOS	(TAPE_BUTTON_XPOS + 3 * TAPE_BUTTON_XSIZE)
-#define TAPE_BUTTON_PLAY_XPOS	(TAPE_BUTTON_XPOS + 4 * TAPE_BUTTON_XSIZE)
-
 static struct
 {
-  int x, y;
+  int graphic;
+  struct XY *pos;
   int gadget_id;
   char *infotext;
 } tapebutton_info[NUM_TAPE_BUTTONS] =
 {
   {
-    TAPE_BUTTON_EJECT_XPOS,	TAPE_BUTTON_YPOS,
-    TAPE_CTRL_ID_EJECT,
-    "eject tape"
+    IMG_GFX_TAPE_BUTTON_EJECT,		&tape.button.eject,
+    TAPE_CTRL_ID_EJECT,			"eject tape"
   },
   {
-    TAPE_BUTTON_EXTRA_XPOS,	TAPE_BUTTON_YPOS,
-    TAPE_CTRL_ID_EXTRA,
-    "extra functions"
+    /* (same position as "eject" button) */
+    IMG_GFX_TAPE_BUTTON_EXTRA,		&tape.button.eject,
+    TAPE_CTRL_ID_EXTRA,			"extra functions"
   },
   {
-    TAPE_BUTTON_STOP_XPOS,	TAPE_BUTTON_YPOS,
-    TAPE_CTRL_ID_STOP,
-    "stop tape"
+    IMG_GFX_TAPE_BUTTON_STOP,		&tape.button.stop,
+    TAPE_CTRL_ID_STOP,			"stop tape"
   },
   {
-    TAPE_BUTTON_PAUSE_XPOS,	TAPE_BUTTON_YPOS,
-    TAPE_CTRL_ID_PAUSE,
-    "pause tape"
+    IMG_GFX_TAPE_BUTTON_PAUSE,		&tape.button.pause,
+    TAPE_CTRL_ID_PAUSE,			"pause tape"
   },
   {
-    TAPE_BUTTON_RECORD_XPOS,	TAPE_BUTTON_YPOS,
-    TAPE_CTRL_ID_RECORD,
-    "record tape"
+    IMG_GFX_TAPE_BUTTON_RECORD,		&tape.button.record,
+    TAPE_CTRL_ID_RECORD,		"record tape"
   },
   {
-    TAPE_BUTTON_PLAY_XPOS,	TAPE_BUTTON_YPOS,
-    TAPE_CTRL_ID_PLAY,
-    "play tape"
+    IMG_GFX_TAPE_BUTTON_PLAY,		&tape.button.play,
+    TAPE_CTRL_ID_PLAY,			"play tape"
   }
 };
 
@@ -1255,34 +1213,25 @@ void CreateTapeButtons()
 
   for (i = 0; i < NUM_TAPE_BUTTONS; i++)
   {
-    Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
+    struct GraphicInfo *gfx = &graphic_info[tapebutton_info[i].graphic];
+    struct XY *pos = tapebutton_info[i].pos;
     struct GadgetInfo *gi;
-    int gd_xoffset, gd_yoffset;
-    int gd_x1, gd_x2, gd_y;
+    int gd_x = gfx->src_x;
+    int gd_y = gfx->src_y;
+    int gd_xp = gfx->src_x + gfx->pressed_xoffset;
+    int gd_yp = gfx->src_y + gfx->pressed_yoffset;
     int id = i;
 
-    gd_xoffset = tapebutton_info[i].x;
-    gd_yoffset = tapebutton_info[i].y;
-    gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
-    gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
-    gd_y  = DOOR_GFX_PAGEY2 + gd_yoffset;
-
-    if (i == TAPE_CTRL_ID_EXTRA)
-    {
-      gd_x1 = DOOR_GFX_PAGEX6 + gd_xoffset;
-      gd_x2 = DOOR_GFX_PAGEX5 + gd_xoffset;
-    }
-
     gi = CreateGadget(GDI_CUSTOM_ID, id,
 		      GDI_INFO_TEXT, tapebutton_info[i].infotext,
-		      GDI_X, VX + gd_xoffset,
-		      GDI_Y, VY + gd_yoffset,
-		      GDI_WIDTH, TAPE_BUTTON_XSIZE,
-		      GDI_HEIGHT, TAPE_BUTTON_YSIZE,
+		      GDI_X, VX + pos->x,
+		      GDI_Y, VY + pos->y,
+		      GDI_WIDTH, gfx->width,
+		      GDI_HEIGHT, gfx->height,
 		      GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
 		      GDI_STATE, GD_BUTTON_UNPRESSED,
-		      GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
-		      GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
+		      GDI_DESIGN_UNPRESSED, gfx->bitmap, gd_x, gd_y,
+		      GDI_DESIGN_PRESSED, gfx->bitmap, gd_xp, gd_yp,
 		      GDI_DIRECT_DRAW, FALSE,
 		      GDI_EVENT_MASK, GD_EVENT_RELEASED,
 		      GDI_CALLBACK_ACTION, HandleTapeButtons,
@@ -1325,6 +1274,9 @@ void MapTapeButtons()
 
   if (tape.recording || tape.playing)
     MapTapeWarpButton();
+
+  if (tape.show_game_buttons)
+    MapGameButtons();
 }
 
 void UnmapTapeButtons()
@@ -1333,6 +1285,9 @@ void UnmapTapeButtons()
 
   for (i = 0; i < NUM_TAPE_BUTTONS; i++)
     UnmapGadget(tape_gadget[i]);
+
+  if (tape.show_game_buttons)
+    UnmapGameButtons();
 }
 
 static void HandleTapeButtonsExt(int id)
@@ -1350,7 +1305,7 @@ static void HandleTapeButtonsExt(int id)
 	LoadTape(level_nr);
 
 	if (TAPE_IS_EMPTY(tape))
-	  Request("No tape for this level !", REQ_CONFIRM);
+	  Request("No tape for this level!", REQ_CONFIRM);
       }
       else
       {
@@ -1366,31 +1321,32 @@ static void HandleTapeButtonsExt(int id)
     case TAPE_CTRL_ID_EXTRA:
       if (tape.playing)
       {
-	if (!tape.warp_forward)			/* PLAY -> WARP FORWARD PLAY */
-	{
-	  TapeStartWarpForward();
-	}
-	else					/* WARP FORWARD PLAY -> PLAY */
-	{
-	  TapeStopWarpForward();
-	}
+	tape.pause_before_end = !tape.pause_before_end;
+
+	DrawVideoDisplayCurrentState();
       }
       else if (tape.recording)
+      {
 	TapeSingleStep();
+      }
 
       break;
 
     case TAPE_CTRL_ID_STOP:
       TapeStop();
+
       break;
 
     case TAPE_CTRL_ID_PAUSE:
       TapeTogglePause(TAPE_TOGGLE_MANUAL);
+
       break;
 
     case TAPE_CTRL_ID_RECORD:
       if (TAPE_IS_STOPPED(tape))
+      {
 	TapeStartGameRecording();
+      }
       else if (tape.pausing)
       {
 	if (tape.playing)			/* PLAY -> PAUSE -> RECORD */
@@ -1398,9 +1354,17 @@ static void HandleTapeButtonsExt(int id)
 	else
 	  TapeTogglePause(TAPE_TOGGLE_MANUAL);
       }
+
       break;
 
     case TAPE_CTRL_ID_PLAY:
+      if (tape.recording && tape.pausing)	/* PAUSE -> RECORD */
+      {
+	// ("TAPE_IS_EMPTY(tape)" is TRUE here -- probably fix this)
+
+	TapeTogglePause(TAPE_TOGGLE_MANUAL);
+      }
+
       if (TAPE_IS_EMPTY(tape))
 	break;
 
@@ -1412,29 +1376,34 @@ static void HandleTapeButtonsExt(int id)
       {
 	if (tape.pausing)			/* PAUSE -> PLAY */
 	{
-	  TapeTogglePause(TAPE_TOGGLE_MANUAL);
+	  TapeTogglePause(TAPE_TOGGLE_MANUAL | TAPE_TOGGLE_PLAY_PAUSE);
 	}
-	else if (!tape.fast_forward)		/* PLAY -> FAST FORWARD PLAY */
+	else if (!tape.fast_forward)		/* PLAY -> FFWD */
 	{
 	  tape.fast_forward = TRUE;
-	  DrawVideoDisplay(VIDEO_STATE_FFWD_ON, 0);
 	}
-	else if (!tape.pause_before_death)	/* FFWD PLAY -> AUTO PAUSE */
+	else if (!tape.warp_forward)		/* FFWD -> WARP */
 	{
-	  tape.pause_before_death = TRUE;
-	  DrawVideoDisplay(VIDEO_STATE_FFWD_OFF | VIDEO_STATE_PBEND_ON, 0);
+	  tape.warp_forward = TRUE;
 	}
-	else					/* AUTO PAUSE -> NORMAL PLAY */
+	else if (!tape.deactivate_display)	/* WARP -> WARP BLIND */
 	{
-	  if (tape.warp_forward)
-	    TapeStopWarpForward();
+	  tape.deactivate_display = TRUE;
 
+	  TapeDeactivateDisplayOn();
+	}
+	else					/* WARP BLIND -> PLAY */
+	{
 	  tape.fast_forward = FALSE;
-	  tape.pause_before_death = FALSE;
+	  tape.warp_forward = FALSE;
+	  tape.deactivate_display = FALSE;
 
-	  DrawVideoDisplay(VIDEO_STATE_PBEND_OFF | VIDEO_STATE_PLAY_ON, 0);
+	  TapeDeactivateDisplayOff(game_status == GAME_MODE_PLAYING);
 	}
+
+	DrawVideoDisplayCurrentState();
       }
+
       break;
 
     default:
@@ -1449,10 +1418,13 @@ static void HandleTapeButtons(struct GadgetInfo *gi)
 
 void HandleTapeButtonKeys(Key key)
 {
-  boolean use_extra = (tape.recording || tape.playing);
+  boolean eject_button_is_active = TAPE_IS_STOPPED(tape);
+  boolean extra_button_is_active = !eject_button_is_active;
 
-  if (key == setup.shortcut.tape_eject)
-    HandleTapeButtonsExt(use_extra ? TAPE_CTRL_ID_EXTRA : TAPE_CTRL_ID_EJECT);
+  if (key == setup.shortcut.tape_eject && eject_button_is_active)
+    HandleTapeButtonsExt(TAPE_CTRL_ID_EJECT);
+  else if (key == setup.shortcut.tape_extra && extra_button_is_active)
+    HandleTapeButtonsExt(TAPE_CTRL_ID_EXTRA);
   else if (key == setup.shortcut.tape_stop)
     HandleTapeButtonsExt(TAPE_CTRL_ID_STOP);
   else if (key == setup.shortcut.tape_pause)
diff --git a/src/tape.h b/src/tape.h
index cafa235..cf6f4df 100644
--- a/src/tape.h
+++ b/src/tape.h
@@ -1,23 +1,22 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* tape.h                                                   *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// tape.h
+// ============================================================================
 
 #ifndef TAPE_H
 #define TAPE_H
 
 
 /* values for TapeTogglePause() */
-#define	TAPE_TOGGLE_MANUAL	TRUE
-#define	TAPE_TOGGLE_AUTOMATIC	FALSE
+#define	TAPE_TOGGLE_AUTOMATIC	0
+#define	TAPE_TOGGLE_MANUAL	(1 << 0)
+#define	TAPE_TOGGLE_PLAY_PAUSE	(1 << 1)
 
 /* values for tape properties */
 #define MAX_TAPE_LEN		(1000 * FRAMES_PER_SECOND) /* max.time x fps */
@@ -39,51 +38,55 @@
 /* values for video tape control */
 #define VIDEO_STATE_PLAY_OFF	(1 << 0)
 #define VIDEO_STATE_PLAY_ON	(1 << 1)
-#define VIDEO_STATE_PLAY	(VIDEO_STATE_PLAY_OFF	| VIDEO_STATE_PLAY_ON)
 #define VIDEO_STATE_REC_OFF	(1 << 2)
 #define VIDEO_STATE_REC_ON	(1 << 3)
-#define VIDEO_STATE_REC		(VIDEO_STATE_REC_OFF	| VIDEO_STATE_REC_ON)
 #define VIDEO_STATE_PAUSE_OFF	(1 << 4)
 #define VIDEO_STATE_PAUSE_ON	(1 << 5)
-#define VIDEO_STATE_PAUSE	(VIDEO_STATE_PAUSE_OFF	| VIDEO_STATE_PAUSE_ON)
 #define VIDEO_STATE_DATE_OFF	(1 << 6)
 #define VIDEO_STATE_DATE_ON	(1 << 7)
-#define VIDEO_STATE_DATE	(VIDEO_STATE_DATE_OFF	| VIDEO_STATE_DATE_ON)
 #define VIDEO_STATE_TIME_OFF	(1 << 8)
 #define VIDEO_STATE_TIME_ON	(1 << 9)
-#define VIDEO_STATE_TIME	(VIDEO_STATE_TIME_OFF	| VIDEO_STATE_TIME_ON)
-
-#define VIDEO_STATE_FFWD_OFF	(1 << 10)
-#define VIDEO_STATE_FFWD_ON	(1 << 11)
-#define VIDEO_STATE_FFWD	(VIDEO_STATE_FFWD_OFF	| VIDEO_STATE_FFWD_ON)
-#define VIDEO_STATE_PBEND_OFF	(1 << 12)
-#define VIDEO_STATE_PBEND_ON	(1 << 13)
-#define VIDEO_STATE_PBEND	(VIDEO_STATE_PBEND_OFF	| VIDEO_STATE_PBEND_ON)
+#define VIDEO_STATE_FRAME_OFF	(1 << 10)
+#define VIDEO_STATE_FRAME_ON	(1 << 11)
+#define VIDEO_STATE_FFWD_OFF	(1 << 12)
+#define VIDEO_STATE_FFWD_ON	(1 << 13)
 #define VIDEO_STATE_WARP_OFF	(1 << 14)
 #define VIDEO_STATE_WARP_ON	(1 << 15)
-#define VIDEO_STATE_WARP	(VIDEO_STATE_WARP_OFF	| VIDEO_STATE_WARP_ON)
 #define VIDEO_STATE_WARP2_OFF	(1 << 16)
 #define VIDEO_STATE_WARP2_ON	(1 << 17)
-#define VIDEO_STATE_WARP2	(VIDEO_STATE_WARP_OFF	| VIDEO_STATE_WARP_ON)
-#define VIDEO_STATE_1STEP_OFF	(1 << 18)
-#define VIDEO_STATE_1STEP_ON	(1 << 19)
-#define VIDEO_STATE_1STEP	(VIDEO_STATE_1STEP_OFF	| VIDEO_STATE_1STEP_ON)
-
-#define VIDEO_PRESS_PLAY_ON	(1 << 20)
-#define VIDEO_PRESS_PLAY_OFF	(1 << 21)
-#define VIDEO_PRESS_PLAY	(VIDEO_PRESS_PLAY_OFF	| VIDEO_PRESS_PLAY_ON)
-#define VIDEO_PRESS_REC_ON	(1 << 22)
-#define VIDEO_PRESS_REC_OFF	(1 << 23)
-#define VIDEO_PRESS_REC		(VIDEO_PRESS_REC_OFF	| VIDEO_PRESS_REC_ON)
-#define VIDEO_PRESS_PAUSE_ON	(1 << 24)
-#define VIDEO_PRESS_PAUSE_OFF	(1 << 25)
-#define VIDEO_PRESS_PAUSE	(VIDEO_PRESS_PAUSE_OFF	| VIDEO_PRESS_PAUSE_ON)
-#define VIDEO_PRESS_STOP_ON	(1 << 26)
-#define VIDEO_PRESS_STOP_OFF	(1 << 27)
-#define VIDEO_PRESS_STOP	(VIDEO_PRESS_STOP_OFF	| VIDEO_PRESS_STOP_ON)
-#define VIDEO_PRESS_EJECT_ON	(1 << 28)
-#define VIDEO_PRESS_EJECT_OFF	(1 << 29)
-#define VIDEO_PRESS_EJECT	(VIDEO_PRESS_EJECT_OFF	| VIDEO_PRESS_EJECT_ON)
+#define VIDEO_STATE_PBEND_OFF	(1 << 18)
+#define VIDEO_STATE_PBEND_ON	(1 << 19)
+#define VIDEO_STATE_1STEP_OFF	(1 << 20)
+#define VIDEO_STATE_1STEP_ON	(1 << 21)
+
+#define VIDEO_PRESS_PLAY_ON	(1 << 22)
+#define VIDEO_PRESS_PLAY_OFF	(1 << 23)
+#define VIDEO_PRESS_REC_ON	(1 << 24)
+#define VIDEO_PRESS_REC_OFF	(1 << 25)
+#define VIDEO_PRESS_PAUSE_ON	(1 << 26)
+#define VIDEO_PRESS_PAUSE_OFF	(1 << 27)
+#define VIDEO_PRESS_STOP_ON	(1 << 28)
+#define VIDEO_PRESS_STOP_OFF	(1 << 29)
+#define VIDEO_PRESS_EJECT_ON	(1 << 30)
+#define VIDEO_PRESS_EJECT_OFF	(1 << 31)
+
+#define VIDEO_STATE_PLAY(x)  ((x) ? VIDEO_STATE_PLAY_ON : VIDEO_STATE_PLAY_OFF)
+#define VIDEO_STATE_REC(x)   ((x) ? VIDEO_STATE_REC_ON  : VIDEO_STATE_REC_OFF)
+#define VIDEO_STATE_PAUSE(x) ((x) ? VIDEO_STATE_PAUSE_ON: VIDEO_STATE_PAUSE_OFF)
+#define VIDEO_STATE_DATE(x)  ((x) ? VIDEO_STATE_DATE_ON : VIDEO_STATE_DATE_OFF)
+#define VIDEO_STATE_TIME(x)  ((x) ? VIDEO_STATE_TIME_ON : VIDEO_STATE_TIME_OFF)
+#define VIDEO_STATE_FRAME(x) ((x) ? VIDEO_STATE_FRAME_ON: VIDEO_STATE_FRAME_OFF)
+#define VIDEO_STATE_FFWD(x)  ((x) ? VIDEO_STATE_FFWD_ON : VIDEO_STATE_FFWD_OFF)
+#define VIDEO_STATE_WARP(x)  ((x) ? VIDEO_STATE_WARP_ON : VIDEO_STATE_WARP_OFF)
+#define VIDEO_STATE_WARP2(x) ((x) ? VIDEO_STATE_WARP2_ON: VIDEO_STATE_WARP2_OFF)
+#define VIDEO_STATE_PBEND(x) ((x) ? VIDEO_STATE_PBEND_ON: VIDEO_STATE_PBEND_OFF)
+#define VIDEO_STATE_1STEP(x) ((x) ? VIDEO_STATE_1STEP_ON: VIDEO_STATE_1STEP_OFF)
+
+#define VIDEO_PRESS_PLAY(x)  ((x) ? VIDEO_PRESS_PLAY_ON : VIDEO_PRESS_PLAY_OFF)
+#define VIDEO_PRESS_REC(x)   ((x) ? VIDEO_PRESS_REC_ON  : VIDEO_PRESS_REC_OFF)
+#define VIDEO_PRESS_PAUSE(x) ((x) ? VIDEO_PRESS_PAUSE_ON: VIDEO_PRESS_PAUSE_OFF)
+#define VIDEO_PRESS_STOP(x)  ((x) ? VIDEO_PRESS_STOP_ON : VIDEO_PRESS_STOP_OFF)
+#define VIDEO_PRESS_EJECT(x) ((x) ? VIDEO_PRESS_EJECT_ON: VIDEO_PRESS_EJECT_OFF)
 
 /* tags to draw video display labels or symbols only */
 /* (negative values to prevent misinterpretation in DrawVideoDisplay(), where
@@ -93,6 +96,62 @@
 #define VIDEO_DISPLAY_SYMBOL_ONLY	-2
 
 
+struct TapeButtonInfo
+{
+  struct XY eject;
+  struct XY stop;
+  struct XY pause;
+  struct XY record;
+  struct XY play;
+};
+
+struct TapeSymbolInfo
+{
+  struct XY eject;
+  struct XY stop;
+  struct XY pause;
+  struct XY record;
+  struct XY play;
+  struct XY fast_forward;
+  struct XY warp_forward;
+  struct XY warp_forward_blind;
+  struct XY pause_before_end;
+  struct XY single_step;
+};
+
+struct TapeLabelInfo
+{
+  struct XY eject;
+  struct XY stop;
+  struct XY pause;
+  struct XY record;
+  struct XY play;
+  struct XY fast_forward;
+  struct XY warp_forward;
+  struct XY warp_forward_blind;
+  struct XY pause_before_end;
+  struct XY single_step;
+  struct XY date;
+  struct XY time;
+};
+
+struct TapeTextInfo
+{
+  struct TextPosInfo date;
+  struct TextPosInfo date_yyyy;
+  struct TextPosInfo date_yy;
+  struct TextPosInfo date_mon;
+  struct TextPosInfo date_mm;
+  struct TextPosInfo date_dd;
+
+  struct TextPosInfo time;
+  struct TextPosInfo time_hh;
+  struct TextPosInfo time_mm;
+  struct TextPosInfo time_ss;
+
+  struct TextPosInfo frame;
+};
+
 struct TapeInfo
 {
   int file_version;	/* file format version the tape is stored with    */
@@ -101,13 +160,14 @@ struct TapeInfo
 
   char *level_identifier;
   int level_nr;
-  unsigned long random_seed;
-  unsigned long date;
-  unsigned long counter;
-  unsigned long length;
-  unsigned long length_seconds;
+  unsigned int random_seed;
+  unsigned int date;
+  unsigned int counter;
+  unsigned int length;
+  unsigned int length_frames;
+  unsigned int length_seconds;
   unsigned int delay_played;
-  boolean pause_before_death;
+  boolean pause_before_end;
   boolean recording, playing, pausing;
   boolean fast_forward;
   boolean warp_forward;
@@ -128,11 +188,18 @@ struct TapeInfo
     byte delay;
   } pos[MAX_TAPE_LEN];
 
+  struct TapeButtonInfo button;
+  struct TapeSymbolInfo symbol;
+  struct TapeLabelInfo label;
+  struct TapeTextInfo text;
+
+  boolean show_game_buttons;	/* show game buttons in tape viewport */
+
   boolean no_valid_file;	/* set when tape file missing or invalid */
 };
 
 
-void DrawVideoDisplay(unsigned long, unsigned long);
+void DrawVideoDisplay(unsigned int, unsigned int);
 void DrawCompleteVideoDisplay(void);
 
 void TapeDeactivateDisplayOn();
@@ -141,7 +208,7 @@ void TapeDeactivateDisplayOff(boolean);
 void TapeSetDateFromEpochSeconds(time_t);
 void TapeSetDateFromNow();
 
-void TapeStartRecording(long);
+void TapeStartRecording(int);
 void TapeHaltRecording(void);
 void TapeStopRecording(void);
 void TapeRecordAction(byte *);
@@ -151,7 +218,8 @@ void TapeStopPlaying(void);
 byte *TapePlayAction(void);
 void TapeStop(void);
 void TapeErase(void);
-unsigned int GetTapeLength(void);
+unsigned int GetTapeLengthFrames(void);
+unsigned int GetTapeLengthSeconds(void);
 void TapeQuickSave(void);
 void TapeQuickLoad(void);
 void InsertSolutionTape(void);
diff --git a/src/tools.c b/src/tools.c
index c26996b..b07e19d 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -1,15 +1,15 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* tools.c                                                  *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// tools.c
+// ============================================================================
+
+#include <math.h>
 
 #include "libgame/libgame.h"
 
@@ -17,14 +17,15 @@
 #include "init.h"
 #include "game.h"
 #include "events.h"
-#include "cartoons.h"
+#include "anim.h"
 #include "network.h"
 #include "tape.h"
 #include "screens.h"
 
 
 /* select level set with EMC X11 graphics before activating EM GFX debugging */
-#define DEBUG_EM_GFX	0
+#define DEBUG_EM_GFX		FALSE
+#define DEBUG_FRAME_TIME	FALSE
 
 /* tool button identifiers */
 #define TOOL_CTRL_ID_YES	0
@@ -37,6 +38,133 @@
 
 #define NUM_TOOL_BUTTONS	7
 
+/* constants for number of doors and door parts */
+#define NUM_DOORS		2
+#define NUM_PANELS		NUM_DOORS
+// #define NUM_PANELS		0
+#define MAX_PARTS_PER_DOOR	8
+#define MAX_DOOR_PARTS		(NUM_DOORS * MAX_PARTS_PER_DOOR + NUM_PANELS)
+#define DOOR_PART_IS_PANEL(i)	((i) >= NUM_DOORS * MAX_PARTS_PER_DOOR)
+
+
+struct DoorPartOrderInfo
+{
+  int nr;
+  int sort_priority;
+};
+
+static struct DoorPartOrderInfo door_part_order[MAX_DOOR_PARTS];
+
+struct DoorPartControlInfo
+{
+  int door_token;
+  int graphic;
+  struct DoorPartPosInfo *pos;
+};
+
+static struct DoorPartControlInfo door_part_controls[] =
+{
+  {
+    DOOR_1,
+    IMG_GFX_DOOR_1_PART_1,
+    &door_1.part_1
+  },
+  {
+    DOOR_1,
+    IMG_GFX_DOOR_1_PART_2,
+    &door_1.part_2
+  },
+  {
+    DOOR_1,
+    IMG_GFX_DOOR_1_PART_3,
+    &door_1.part_3
+  },
+  {
+    DOOR_1,
+    IMG_GFX_DOOR_1_PART_4,
+    &door_1.part_4
+  },
+  {
+    DOOR_1,
+    IMG_GFX_DOOR_1_PART_5,
+    &door_1.part_5
+  },
+  {
+    DOOR_1,
+    IMG_GFX_DOOR_1_PART_6,
+    &door_1.part_6
+  },
+  {
+    DOOR_1,
+    IMG_GFX_DOOR_1_PART_7,
+    &door_1.part_7
+  },
+  {
+    DOOR_1,
+    IMG_GFX_DOOR_1_PART_8,
+    &door_1.part_8
+  },
+
+  {
+    DOOR_2,
+    IMG_GFX_DOOR_2_PART_1,
+    &door_2.part_1
+  },
+  {
+    DOOR_2,
+    IMG_GFX_DOOR_2_PART_2,
+    &door_2.part_2
+  },
+  {
+    DOOR_2,
+    IMG_GFX_DOOR_2_PART_3,
+    &door_2.part_3
+  },
+  {
+    DOOR_2,
+    IMG_GFX_DOOR_2_PART_4,
+    &door_2.part_4
+  },
+  {
+    DOOR_2,
+    IMG_GFX_DOOR_2_PART_5,
+    &door_2.part_5
+  },
+  {
+    DOOR_2,
+    IMG_GFX_DOOR_2_PART_6,
+    &door_2.part_6
+  },
+  {
+    DOOR_2,
+    IMG_GFX_DOOR_2_PART_7,
+    &door_2.part_7
+  },
+  {
+    DOOR_2,
+    IMG_GFX_DOOR_2_PART_8,
+    &door_2.part_8
+  },
+
+  {
+    DOOR_1,
+    IMG_BACKGROUND_PANEL,
+    &door_1.panel
+  },
+  {
+    DOOR_2,
+    IMG_BACKGROUND_TAPE,
+    &door_2.panel
+  },
+
+  {
+    -1,
+    -1,
+    NULL
+  }
+};
+
+
 /* forward declaration for internal use */
 static void UnmapToolButtons();
 static void HandleToolButtons(struct GadgetInfo *);
@@ -64,17 +192,197 @@ static char *print_if_not_empty(int element)
   return s;
 }
 
-void DumpTile(int x, int y)
+int correctLevelPosX_EM(int lx)
 {
-  int sx = SCREENX(x);
-  int sy = SCREENY(y);
+  lx -= 1;
+  lx -= (BorderElement != EL_EMPTY ? 1 : 0);
 
-  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+  return lx;
+}
+
+int correctLevelPosY_EM(int ly)
+{
+  ly -= 1;
+  ly -= (BorderElement != EL_EMPTY ? 1 : 0);
+
+  return ly;
+}
+
+static int getFieldbufferOffsetX_RND()
+{
+  int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0);
+  int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
+  int dx_var = dx * TILESIZE_VAR / TILESIZE;
+  int fx = FX;
+
+  if (EVEN(SCR_FIELDX))
+  {
+    int ffx = (scroll_x - SBX_Left)  * TILEX_VAR + dx_var;
+
+    if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
+      fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
+    else
+      fx += (dx_var > 0 ? TILEX_VAR : 0);
+  }
+  else
+  {
+    fx += dx_var;
+  }
+
+  if (full_lev_fieldx <= SCR_FIELDX)
+  {
+    if (EVEN(SCR_FIELDX))
+      fx = 2 * TILEX_VAR - (ODD(lev_fieldx)  ? TILEX_VAR / 2 : 0);
+    else
+      fx = 2 * TILEX_VAR - (EVEN(lev_fieldx) ? TILEX_VAR / 2 : 0);
+  }
+
+  return fx;
+}
+
+static int getFieldbufferOffsetY_RND()
+{
+  int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0);
+  int dy = (ScreenMovDir & (MV_UP | MV_DOWN)    ? ScreenGfxPos : 0);
+  int dy_var = dy * TILESIZE_VAR / TILESIZE;
+  int fy = FY;
+
+  if (EVEN(SCR_FIELDY))
+  {
+    int ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
+
+    if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
+      fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
+    else
+      fy += (dy_var > 0 ? TILEY_VAR : 0);
+  }
+  else
   {
-    x--;
-    y--;
+    fy += dy_var;
   }
 
+  if (full_lev_fieldy <= SCR_FIELDY)
+  {
+    if (EVEN(SCR_FIELDY))
+      fy = 2 * TILEY_VAR - (ODD(lev_fieldy)  ? TILEY_VAR / 2 : 0);
+    else
+      fy = 2 * TILEY_VAR - (EVEN(lev_fieldy) ? TILEY_VAR / 2 : 0);
+  }
+
+  return fy;
+}
+
+static int getLevelFromScreenX_RND(int sx)
+{
+  int fx = getFieldbufferOffsetX_RND();
+  int dx = fx - FX;
+  int px = sx - SX;
+  int lx = LEVELX((px + dx) / TILESIZE_VAR);
+
+  return lx;
+}
+
+static int getLevelFromScreenY_RND(int sy)
+{
+  int fy = getFieldbufferOffsetY_RND();
+  int dy = fy - FY;
+  int py = sy - SY;
+  int ly = LEVELY((py + dy) / TILESIZE_VAR);
+
+  return ly;
+}
+
+static int getLevelFromScreenX_EM(int sx)
+{
+  int level_xsize = level.native_em_level->lev->width;
+  int full_xsize = level_xsize * TILESIZE_VAR;
+
+  sx -= (full_xsize < SXSIZE ? (SXSIZE - full_xsize) / 2 : 0);
+
+  int fx = getFieldbufferOffsetX_EM();
+  int dx = fx;
+  int px = sx - SX;
+  int lx = LEVELX((px + dx) / TILESIZE_VAR);
+
+  lx = correctLevelPosX_EM(lx);
+
+  return lx;
+}
+
+static int getLevelFromScreenY_EM(int sy)
+{
+  int level_ysize = level.native_em_level->lev->height;
+  int full_ysize = level_ysize * TILESIZE_VAR;
+
+  sy -= (full_ysize < SYSIZE ? (SYSIZE - full_ysize) / 2 : 0);
+
+  int fy = getFieldbufferOffsetY_EM();
+  int dy = fy;
+  int py = sy - SY;
+  int ly = LEVELY((py + dy) / TILESIZE_VAR);
+
+  ly = correctLevelPosY_EM(ly);
+
+  return ly;
+}
+
+static int getLevelFromScreenX_SP(int sx)
+{
+  int menBorder = setup.sp_show_border_elements;
+  int level_xsize = level.native_sp_level->width;
+  int full_xsize = (level_xsize - (menBorder ? 0 : 1)) * TILESIZE_VAR;
+
+  sx += (full_xsize < SXSIZE ? (SXSIZE - full_xsize) / 2 : 0);
+
+  int fx = getFieldbufferOffsetX_SP();
+  int dx = fx - FX;
+  int px = sx - SX;
+  int lx = LEVELX((px + dx) / TILESIZE_VAR);
+
+  return lx;
+}
+
+static int getLevelFromScreenY_SP(int sy)
+{
+  int menBorder = setup.sp_show_border_elements;
+  int level_ysize = level.native_sp_level->height;
+  int full_ysize = (level_ysize - (menBorder ? 0 : 1)) * TILESIZE_VAR;
+
+  sy += (full_ysize < SYSIZE ? (SYSIZE - full_ysize) / 2 : 0);
+
+  int fy = getFieldbufferOffsetY_SP();
+  int dy = fy - FY;
+  int py = sy - SY;
+  int ly = LEVELY((py + dy) / TILESIZE_VAR);
+
+  return ly;
+}
+
+int getLevelFromScreenX(int x)
+{
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+    return getLevelFromScreenX_EM(x);
+  if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+    return getLevelFromScreenX_SP(x);
+  else
+    return getLevelFromScreenX_RND(x);
+}
+
+int getLevelFromScreenY(int y)
+{
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+    return getLevelFromScreenY_EM(y);
+  if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+    return getLevelFromScreenY_SP(y);
+  else
+    return getLevelFromScreenY_RND(y);
+}
+
+void DumpTile(int x, int y)
+{
+  int sx = SCREENX(x);
+  int sy = SCREENY(y);
+
   printf_line("-", 79);
   printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
   printf_line("-", 79);
@@ -100,26 +408,33 @@ void DumpTile(int x, int y)
   printf("  CustomValue: %d\n", CustomValue[x][y]);
   printf("  GfxElement:  %d\n", GfxElement[x][y]);
   printf("  GfxAction:   %d\n", GfxAction[x][y]);
-  printf("  GfxFrame:    %d\n", GfxFrame[x][y]);
+  printf("  GfxFrame:    %d [%d]\n", GfxFrame[x][y], FrameCounter);
+  printf("  Player x/y:  %d, %d\n", local_player->jx, local_player->jy);
   printf("\n");
 }
 
+void DumpTileFromScreen(int sx, int sy)
+{
+  int lx = getLevelFromScreenX(sx);
+  int ly = getLevelFromScreenY(sy);
+
+  DumpTile(lx, ly);
+}
+
 void SetDrawtoField(int mode)
 {
-  if (mode == DRAW_BUFFERED && setup.soft_scrolling)
+  if (mode == DRAW_TO_FIELDBUFFER)
   {
-    FX = TILEX;
-    FY = TILEY;
-    BX1 = -1;
-    BY1 = -1;
-    BX2 = SCR_FIELDX;
-    BY2 = SCR_FIELDY;
-    redraw_x1 = 1;
-    redraw_y1 = 1;
+    FX = 2 * TILEX_VAR;
+    FY = 2 * TILEY_VAR;
+    BX1 = -2;
+    BY1 = -2;
+    BX2 = SCR_FIELDX + 1;
+    BY2 = SCR_FIELDY + 1;
 
     drawto_field = fieldbuffer;
   }
-  else	/* DRAW_BACKBUFFER */
+  else	/* DRAW_TO_BACKBUFFER */
   {
     FX = SX;
     FY = SY;
@@ -127,362 +442,349 @@ void SetDrawtoField(int mode)
     BY1 = 0;
     BX2 = SCR_FIELDX - 1;
     BY2 = SCR_FIELDY - 1;
-    redraw_x1 = 0;
-    redraw_y1 = 0;
 
     drawto_field = backbuffer;
   }
 }
 
-void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
+static void RedrawPlayfield_RND()
 {
-  if (game_status == GAME_MODE_PLAYING &&
-      level.game_engine_type == GAME_ENGINE_TYPE_EM)
-  {
-    /* currently there is no partial redraw -- always redraw whole playfield */
-    RedrawPlayfield_EM(TRUE);
-
-    /* blit playfield from scroll buffer to normal back buffer for fading in */
-    BlitScreenToBitmap_EM(backbuffer);
-  }
-  else if (game_status == GAME_MODE_PLAYING &&
-	   level.game_engine_type == GAME_ENGINE_TYPE_SP)
-  {
-    /* currently there is no partial redraw -- always redraw whole playfield */
-    RedrawPlayfield_SP(TRUE);
-
-    /* blit playfield from scroll buffer to normal back buffer for fading in */
-    BlitScreenToBitmap_SP(backbuffer);
-  }
-  else if (game_status == GAME_MODE_PLAYING &&
-	   !game.envelope_active)
-  {
-    if (force_redraw)
-    {
-      x = gfx.sx - TILEX;
-      y = gfx.sy - TILEY;
-      width = gfx.sxsize + 2 * TILEX;
-      height = gfx.sysize + 2 * TILEY;
-    }
-
-    if (force_redraw)
-    {
-      int xx, yy;
-      int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
-      int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
-
-      for (xx = BX1; xx <= BX2; xx++)
-	for (yy = BY1; yy <= BY2; yy++)
-	  if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
-	    DrawScreenField(xx, yy);
-      DrawAllPlayers();
-    }
+  if (game.envelope_active)
+    return;
 
-    if (setup.soft_scrolling)
-    {
-      int fx = FX, fy = FY;
+  DrawLevel(REDRAW_ALL);
+  DrawAllPlayers();
+}
 
-      fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
-      fy += (ScreenMovDir & (MV_UP|MV_DOWN)    ? ScreenGfxPos : 0);
+void RedrawPlayfield()
+{
+  if (game_status != GAME_MODE_PLAYING)
+    return;
 
-      BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
-    }
-  }
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+    RedrawPlayfield_EM(TRUE);
+  else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+    RedrawPlayfield_SP(TRUE);
+  else if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
+    RedrawPlayfield_RND();
 
-  if (force_redraw)
-  {
-    x = gfx.sx;
-    y = gfx.sy;
-    width = gfx.sxsize;
-    height = gfx.sysize;
-  }
+  BlitScreenToBitmap(backbuffer);
 
-  BlitBitmap(drawto, window, x, y, width, height, x, y);
+  BlitBitmap(drawto, window, gfx.sx, gfx.sy, gfx.sxsize, gfx.sysize,
+	     gfx.sx, gfx.sy);
 }
 
-void DrawMaskedBorder_Rect(int x, int y, int width, int height)
+static void DrawMaskedBorderExt_Rect(int x, int y, int width, int height,
+				     int draw_target)
 {
-  Bitmap *bitmap = graphic_info[IMG_GLOBAL_BORDER].bitmap;
+  Bitmap *src_bitmap = getGlobalBorderBitmapFromStatus(global.border_status);
+  Bitmap *dst_bitmap = gfx.masked_border_bitmap_ptr;
+
+  if (x == -1 && y == -1)
+    return;
 
-  SetClipOrigin(bitmap, bitmap->stored_clip_gc, 0, 0);
-  BlitBitmapMasked(bitmap, backbuffer, x, y, width, height, x, y);
+  if (draw_target == DRAW_TO_SCREEN)
+    BlitToScreenMasked(src_bitmap, x, y, width, height, x, y);
+  else
+    BlitBitmapMasked(src_bitmap, dst_bitmap, x, y, width, height, x, y);
 }
 
-void DrawMaskedBorder_FIELD()
+static void DrawMaskedBorderExt_FIELD(int draw_target)
 {
-  if (global.border_status >= GAME_MODE_TITLE &&
+  if (global.border_status >= GAME_MODE_MAIN &&
       global.border_status <= GAME_MODE_PLAYING &&
       border.draw_masked[global.border_status])
-    DrawMaskedBorder_Rect(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
+    DrawMaskedBorderExt_Rect(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
+			     draw_target);
 }
 
-void DrawMaskedBorder_DOOR_1()
+static void DrawMaskedBorderExt_DOOR_1(int draw_target)
 {
+  // when drawing to backbuffer, never draw border over open doors
+  if (draw_target == DRAW_TO_BACKBUFFER &&
+      (GetDoorState() & DOOR_OPEN_1))
+    return;
+
   if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
       (global.border_status != GAME_MODE_EDITOR ||
        border.draw_masked[GFX_SPECIAL_ARG_EDITOR]))
-    DrawMaskedBorder_Rect(DX, DY, DXSIZE, DYSIZE);
+    DrawMaskedBorderExt_Rect(DX, DY, DXSIZE, DYSIZE, draw_target);
 }
 
-void DrawMaskedBorder_DOOR_2()
+static void DrawMaskedBorderExt_DOOR_2(int draw_target)
 {
+  // when drawing to backbuffer, never draw border over open doors
+  if (draw_target == DRAW_TO_BACKBUFFER &&
+      (GetDoorState() & DOOR_OPEN_2))
+    return;
+
   if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
       global.border_status != GAME_MODE_EDITOR)
-    DrawMaskedBorder_Rect(VX, VY, VXSIZE, VYSIZE);
+    DrawMaskedBorderExt_Rect(VX, VY, VXSIZE, VYSIZE, draw_target);
 }
 
-void DrawMaskedBorder_DOOR_3()
+static void DrawMaskedBorderExt_DOOR_3(int draw_target)
 {
   /* currently not available */
 }
 
-void DrawMaskedBorder_ALL()
+static void DrawMaskedBorderExt_ALL(int draw_target)
 {
-  DrawMaskedBorder_FIELD();
-  DrawMaskedBorder_DOOR_1();
-  DrawMaskedBorder_DOOR_2();
-  DrawMaskedBorder_DOOR_3();
+  DrawMaskedBorderExt_FIELD(draw_target);
+  DrawMaskedBorderExt_DOOR_1(draw_target);
+  DrawMaskedBorderExt_DOOR_2(draw_target);
+  DrawMaskedBorderExt_DOOR_3(draw_target);
 }
 
-void DrawMaskedBorder(int redraw_mask)
+static void DrawMaskedBorderExt(int redraw_mask, int draw_target)
 {
   /* never draw masked screen borders on borderless screens */
-  if (effectiveGameStatus() == GAME_MODE_LOADING ||
-      effectiveGameStatus() == GAME_MODE_TITLE)
+  if (global.border_status == GAME_MODE_LOADING ||
+      global.border_status == GAME_MODE_TITLE)
     return;
 
   if (redraw_mask & REDRAW_ALL)
-    DrawMaskedBorder_ALL();
+    DrawMaskedBorderExt_ALL(draw_target);
   else
   {
     if (redraw_mask & REDRAW_FIELD)
-      DrawMaskedBorder_FIELD();
+      DrawMaskedBorderExt_FIELD(draw_target);
     if (redraw_mask & REDRAW_DOOR_1)
-      DrawMaskedBorder_DOOR_1();
+      DrawMaskedBorderExt_DOOR_1(draw_target);
     if (redraw_mask & REDRAW_DOOR_2)
-      DrawMaskedBorder_DOOR_2();
+      DrawMaskedBorderExt_DOOR_2(draw_target);
     if (redraw_mask & REDRAW_DOOR_3)
-      DrawMaskedBorder_DOOR_3();
+      DrawMaskedBorderExt_DOOR_3(draw_target);
   }
 }
 
-void BackToFront()
+void DrawMaskedBorder_FIELD()
 {
-  int x, y;
-  DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
-
-#if 0
-  printf("::: TILES TO REFRESH: %d\n", redraw_tiles);
-  for (x = 0; x < SCR_FIELDX; x++)
-    for (y = 0 ; y < SCR_FIELDY; y++)
-      if (redraw[redraw_x1 + x][redraw_y1 + y])
-	printf("::: - %d, %d [%s]\n",
-	       LEVELX(x), LEVELY(y),
-	       EL_NAME(Feld[LEVELX(x)][LEVELY(y)]));
-#endif
-
-  if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
-    redraw_mask |= REDRAW_FIELD;
-
-  if (redraw_mask & REDRAW_FIELD)
-    redraw_mask &= ~REDRAW_TILES;
-
-  if (redraw_mask == REDRAW_NONE)
-    return;
+  DrawMaskedBorderExt_FIELD(DRAW_TO_BACKBUFFER);
+}
 
-  if (redraw_mask & REDRAW_TILES &&
-      game_status == GAME_MODE_PLAYING &&
-      border.draw_masked[GAME_MODE_PLAYING])
-    redraw_mask |= REDRAW_FIELD;
+void DrawMaskedBorder(int redraw_mask)
+{
+  DrawMaskedBorderExt(redraw_mask, DRAW_TO_BACKBUFFER);
+}
 
-  if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
+void DrawMaskedBorderToTarget(int draw_target)
+{
+  if (draw_target == DRAW_TO_BACKBUFFER ||
+      draw_target == DRAW_TO_SCREEN)
+  {
+    DrawMaskedBorderExt(REDRAW_ALL, draw_target);
+  }
+  else
   {
-    static boolean last_frame_skipped = FALSE;
-    boolean skip_even_when_not_scrolling = TRUE;
-    boolean just_scrolling = (ScreenMovDir != 0);
-    boolean verbose = FALSE;
+    int last_border_status = global.border_status;
 
-    if (global.fps_slowdown_factor > 1 &&
-	(FrameCounter % global.fps_slowdown_factor) &&
-	(just_scrolling || skip_even_when_not_scrolling))
+    if (draw_target == DRAW_TO_FADE_SOURCE)
     {
-      redraw_mask &= ~REDRAW_MAIN;
-
-      last_frame_skipped = TRUE;
-
-      if (verbose)
-	printf("FRAME SKIPPED\n");
+      global.border_status = gfx.fade_border_source_status;
+      gfx.masked_border_bitmap_ptr = gfx.fade_bitmap_source;
     }
-    else
+    else if (draw_target == DRAW_TO_FADE_TARGET)
     {
-      if (last_frame_skipped)
-	redraw_mask |= REDRAW_FIELD;
+      global.border_status = gfx.fade_border_target_status;
+      gfx.masked_border_bitmap_ptr = gfx.fade_bitmap_target;
+    }
 
-      last_frame_skipped = FALSE;
+    DrawMaskedBorderExt(REDRAW_ALL, draw_target);
 
-      if (verbose)
-	printf("frame not skipped\n");
-    }
+    global.border_status = last_border_status;
+    gfx.masked_border_bitmap_ptr = backbuffer;
   }
+}
 
-  /* synchronize X11 graphics at this point; if we would synchronize the
-     display immediately after the buffer switching (after the XFlush),
-     this could mean that we have to wait for the graphics to complete,
-     although we could go on doing calculations for the next frame */
+void BlitScreenToBitmap_RND(Bitmap *target_bitmap)
+{
+  int fx = getFieldbufferOffsetX_RND();
+  int fy = getFieldbufferOffsetY_RND();
 
-  SyncDisplay();
+  BlitBitmap(drawto_field, target_bitmap, fx, fy, SXSIZE, SYSIZE, SX, SY);
+}
 
-  /* prevent drawing masked border to backbuffer when using playfield buffer */
-  if (game_status != GAME_MODE_PLAYING ||
-      redraw_mask & REDRAW_FROM_BACKBUFFER ||
-      buffer == backbuffer)
-    DrawMaskedBorder(redraw_mask);
-  else
-    DrawMaskedBorder(redraw_mask & REDRAW_DOORS);
+void BlitScreenToBitmap(Bitmap *target_bitmap)
+{
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+    BlitScreenToBitmap_EM(target_bitmap);
+  else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+    BlitScreenToBitmap_SP(target_bitmap);
+  else if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
+    BlitScreenToBitmap_RND(target_bitmap);
 
-  if (redraw_mask & REDRAW_ALL)
-  {
-    BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+  redraw_mask |= REDRAW_FIELD;
+}
 
-    redraw_mask = REDRAW_NONE;
-  }
+void DrawFramesPerSecond()
+{
+  char text[100];
+  int font_nr = FONT_TEXT_2;
+  int font_width = getFontWidth(font_nr);
 
-  if (redraw_mask & REDRAW_FIELD)
-  {
-#if 0
-    printf("::: REDRAW_FIELD\n");
-#endif
+  sprintf(text, "%04.1f fps", global.frames_per_second);
 
-    if (game_status != GAME_MODE_PLAYING ||
-	redraw_mask & REDRAW_FROM_BACKBUFFER)
-    {
-      BlitBitmap(backbuffer, window,
-		 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
-    }
-    else
-    {
-      int fx = FX, fy = FY;
+  DrawTextExt(backbuffer, WIN_XSIZE - font_width * strlen(text), 0, text,
+	      font_nr, BLIT_OPAQUE);
+}
 
-      if (setup.soft_scrolling)
-      {
-	fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
-	fy += (ScreenMovDir & (MV_UP | MV_DOWN)    ? ScreenGfxPos : 0);
-      }
+#if DEBUG_FRAME_TIME
+static void PrintFrameTimeDebugging()
+{
+  static unsigned int last_counter = 0;
+  unsigned int counter = Counter();
+  int diff_1 = counter - last_counter;
+  int diff_2 = diff_1 - GAME_FRAME_DELAY;
+  int diff_2_max = 20;
+  int diff_2_cut = MIN(ABS(diff_2), diff_2_max);
+  char diff_bar[2 * diff_2_max + 5];
+  int pos = 0;
+  int i;
 
-      if (setup.soft_scrolling ||
-	  ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
-	  ABS(ScreenMovPos) == ScrollStepSize ||
-	  redraw_tiles > REDRAWTILES_THRESHOLD)
-      {
-	if (border.draw_masked[GAME_MODE_PLAYING])
-	{
-	  if (buffer != backbuffer)
-	  {
-	    /* copy playfield buffer to backbuffer to add masked border */
-	    BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
-	    DrawMaskedBorder(REDRAW_FIELD);
-	  }
+  diff_bar[pos++] = (diff_2 < -diff_2_max ? '<' : ' ');
 
-	  BlitBitmap(backbuffer, window,
-		     REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
-		     REAL_SX, REAL_SY);
-	}
-	else
-	{
-	  BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
-	}
+  for (i = 0; i < diff_2_max; i++)
+    diff_bar[pos++] = (diff_2 >= 0 ? ' ' :
+		       i >= diff_2_max - diff_2_cut ? '-' : ' ');
 
-#if 0
-#ifdef DEBUG
-	printf("redrawing all (ScreenGfxPos == %d) because %s\n",
-	       ScreenGfxPos,
-	       (setup.soft_scrolling ?
-		"setup.soft_scrolling" :
-		ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
-		"ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
-		ABS(ScreenGfxPos) == ScrollStepSize ?
-		"ABS(ScreenGfxPos) == ScrollStepSize" :
-		"redraw_tiles > REDRAWTILES_THRESHOLD"));
-#endif
-#endif
-      }
-    }
+  diff_bar[pos++] = '|';
 
-    redraw_mask &= ~REDRAW_MAIN;
-  }
+  for (i = 0; i < diff_2_max; i++)
+    diff_bar[pos++] = (diff_2 <= 0 ? ' ' : i < diff_2_cut ? '+' : ' ');
 
-  if (redraw_mask & REDRAW_DOORS)
-  {
-    if (redraw_mask & REDRAW_DOOR_1)
-      BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
+  diff_bar[pos++] = (diff_2 > diff_2_max ? '>' : ' ');
 
-    if (redraw_mask & REDRAW_DOOR_2)
-      BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
+  diff_bar[pos++] = '\0';
 
-    if (redraw_mask & REDRAW_DOOR_3)
-      BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
+  Error(ERR_INFO, "%06d [%02d] [%c%02d] %s",
+	counter,
+	diff_1,
+	(diff_2 < 0 ? '-' : diff_2 > 0 ? '+' : ' '), ABS(diff_2),
+	diff_bar);
 
-    redraw_mask &= ~REDRAW_DOORS;
-  }
+  last_counter = counter;
+}
+#endif
 
-  if (redraw_mask & REDRAW_MICROLEVEL)
-  {
-    BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
-	       SX, SY + 10 * TILEY);
+static int unifiedRedrawMask(int mask)
+{
+  if (mask & REDRAW_ALL)
+    return REDRAW_ALL;
 
-    redraw_mask &= ~REDRAW_MICROLEVEL;
-  }
+  if (mask & REDRAW_FIELD && mask & REDRAW_DOORS)
+    return REDRAW_ALL;
 
-  if (redraw_mask & REDRAW_TILES)
-  {
-#if 0
-    printf("::: REDRAW_TILES\n");
-#endif
+  return mask;
+}
 
-    for (x = 0; x < SCR_FIELDX; x++)
-      for (y = 0 ; y < SCR_FIELDY; y++)
-	if (redraw[redraw_x1 + x][redraw_y1 + y])
-	  BlitBitmap(buffer, window,
-		     FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
-		     SX + x * TILEX, SY + y * TILEY);
-  }
+static boolean equalRedrawMasks(int mask_1, int mask_2)
+{
+  return unifiedRedrawMask(mask_1) == unifiedRedrawMask(mask_2);
+}
 
-  if (redraw_mask & REDRAW_FPS)		/* display frames per second */
-  {
-    char text[100];
-    char info1[100];
+void BackToFront()
+{
+  static int last_redraw_mask = REDRAW_NONE;
+
+  // force screen redraw in every frame to continue drawing global animations
+  // (but always use the last redraw mask to prevent unwanted side effects)
+  if (redraw_mask == REDRAW_NONE)
+    redraw_mask = last_redraw_mask;
 
-    sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
-    if (!global.fps_slowdown)
-      info1[0] = '\0';
+  last_redraw_mask = redraw_mask;
 
-    sprintf(text, "%04.1f fps%s", global.frames_per_second, info1);
 #if 1
-    DrawTextExt(window, SX + SXSIZE + SX, 0, text, FONT_TEXT_2, BLIT_OPAQUE);
+  // masked border now drawn immediately when blitting backbuffer to window
 #else
-    DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
+  // draw masked border to all viewports, if defined
+  DrawMaskedBorder(redraw_mask);
 #endif
+
+  // draw frames per second (only if debug mode is enabled)
+  if (redraw_mask & REDRAW_FPS)
+    DrawFramesPerSecond();
+
+  // remove playfield redraw before potentially merging with doors redraw
+  if (DrawingDeactivated(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE))
+    redraw_mask &= ~REDRAW_FIELD;
+
+  // redraw complete window if both playfield and (some) doors need redraw
+  if (redraw_mask & REDRAW_FIELD && redraw_mask & REDRAW_DOORS)
+    redraw_mask = REDRAW_ALL;
+
+  /* although redrawing the whole window would be fine for normal gameplay,
+     being able to only redraw the playfield is required for deactivating
+     certain drawing areas (mainly playfield) to work, which is needed for
+     warp-forward to be fast enough (by skipping redraw of most frames) */
+
+  if (redraw_mask & REDRAW_ALL)
+  {
+    BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
   }
+  else if (redraw_mask & REDRAW_FIELD)
+  {
+    BlitBitmap(backbuffer, window,
+	       REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
+  }
+  else if (redraw_mask & REDRAW_DOORS)
+  {
+    // merge door areas to prevent calling screen redraw more than once
+    int x1 = WIN_XSIZE;
+    int y1 = WIN_YSIZE;
+    int x2 = 0;
+    int y2 = 0;
+
+    if (redraw_mask & REDRAW_DOOR_1)
+    {
+      x1 = MIN(x1, DX);
+      y1 = MIN(y1, DY);
+      x2 = MAX(x2, DX + DXSIZE);
+      y2 = MAX(y2, DY + DYSIZE);
+    }
+
+    if (redraw_mask & REDRAW_DOOR_2)
+    {
+      x1 = MIN(x1, VX);
+      y1 = MIN(y1, VY);
+      x2 = MAX(x2, VX + VXSIZE);
+      y2 = MAX(y2, VY + VYSIZE);
+    }
+
+    if (redraw_mask & REDRAW_DOOR_3)
+    {
+      x1 = MIN(x1, EX);
+      y1 = MIN(y1, EY);
+      x2 = MAX(x2, EX + EXSIZE);
+      y2 = MAX(y2, EY + EYSIZE);
+    }
 
-  FlushDisplay();
+    BlitBitmap(backbuffer, window, x1, y1, x2 - x1, y2 - y1, x1, y1);
+  }
 
-  for (x = 0; x < MAX_BUF_XSIZE; x++)
-    for (y = 0; y < MAX_BUF_YSIZE; y++)
-      redraw[x][y] = 0;
-  redraw_tiles = 0;
   redraw_mask = REDRAW_NONE;
+
+#if DEBUG_FRAME_TIME
+  PrintFrameTimeDebugging();
+#endif
 }
 
-static void FadeCrossSaveBackbuffer()
+void BackToFront_WithFrameDelay(unsigned int frame_delay_value)
 {
-  BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+  unsigned int frame_delay_value_old = GetVideoFrameDelay();
+
+  SetVideoFrameDelay(frame_delay_value);
+
+  BackToFront();
+
+  SetVideoFrameDelay(frame_delay_value_old);
 }
 
+static int fade_type_skip = FADE_TYPE_NONE;
+
 static void FadeExt(int fade_mask, int fade_mode, int fade_type)
 {
-  static int fade_type_skip = FADE_TYPE_NONE;
   void (*draw_border_function)(void) = NULL;
-  Bitmap *bitmap = (fade_mode & FADE_TYPE_TRANSFORM ? bitmap_db_cross : NULL);
   int x, y, width, height;
   int fade_delay, post_delay;
 
@@ -490,10 +792,6 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type)
   {
     if (fade_type_skip != FADE_TYPE_NONE)
     {
-#if 0
-      printf("::: skipping %d ... [%d] (X)\n", fade_mode, fade_type_skip);
-#endif
-
       /* skip all fade operations until specified fade operation */
       if (fade_type & fade_type_skip)
 	fade_type_skip = FADE_TYPE_NONE;
@@ -502,94 +800,41 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type)
     }
 
     if (fading.fade_mode & FADE_TYPE_TRANSFORM)
-    {
-      FadeCrossSaveBackbuffer();
-
       return;
-    }
   }
 
   redraw_mask |= fade_mask;
 
   if (fade_type == FADE_TYPE_SKIP)
   {
-#if 0
-    printf("::: will skip %d ... [%d]\n", fade_mode, fade_type_skip);
-#endif
-
     fade_type_skip = fade_mode;
 
     return;
   }
 
-#if 0
-  printf("::: !!! FADING %d ... [%d] [%d]\n", fade_mode, fade_type,
-	 fade_type_skip);
-#endif
-
-#if 1
   fade_delay = fading.fade_delay;
   post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
-#endif
 
   if (fade_type_skip != FADE_TYPE_NONE)
   {
-#if 0
-    printf("::: skipping %d ... [%d]\n", fade_mode, fade_type_skip);
-#endif
-
     /* skip all fade operations until specified fade operation */
     if (fade_type & fade_type_skip)
       fade_type_skip = FADE_TYPE_NONE;
 
-#if 1
     fade_delay = 0;
-#else
-    return;
-#endif
   }
 
-#if 1
   if (global.autoplay_leveldir)
   {
-    // fading.fade_mode = FADE_MODE_NONE;
-
-    return;
-  }
-#endif
-
-#if 0
-  if (fading.fade_mode == FADE_MODE_NONE)
-  {
-    BackToFront();
-
     return;
   }
-#endif
-
-  /* !!! what about fade_mask == REDRAW_FIELD | REDRAW_ALL ??? !!! */
-
-#if 0
-  printf("::: NOW FADING %d ... [%d]\n", fade_mode, fade_type);
-#endif
-
-#if 0
-  if (fade_mask == REDRAW_NONE)
-    fade_mask = REDRAW_FIELD;
-#endif
 
-  // if (fade_mask & REDRAW_FIELD)
   if (fade_mask == REDRAW_FIELD)
   {
-    x = REAL_SX;
-    y = REAL_SY;
-    width  = FULL_SXSIZE;
-    height = FULL_SYSIZE;
-
-#if 0
-    fade_delay = fading.fade_delay;
-    post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
-#endif
+    x = FADE_SX;
+    y = FADE_SY;
+    width  = FADE_SXSIZE;
+    height = FADE_SYSIZE;
 
     if (border.draw_masked_when_fading)
       draw_border_function = DrawMaskedBorder_FIELD;	/* update when fading */
@@ -602,62 +847,116 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type)
     y = 0;
     width  = WIN_XSIZE;
     height = WIN_YSIZE;
-
-#if 0
-    fade_delay = fading.fade_delay;
-    post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
-#endif
   }
 
-#if 1
   if (!setup.fade_screens ||
       fade_delay == 0 ||
       fading.fade_mode == FADE_MODE_NONE)
-#else
-  if (!setup.fade_screens || fade_delay == 0)
-#endif
   {
     if (fade_mode == FADE_MODE_FADE_OUT)
       return;
 
-#if 0
-    if (fade_mode == FADE_MODE_FADE_OUT &&
-	fading.fade_mode != FADE_MODE_NONE)
-      ClearRectangle(backbuffer, x, y, width, height);
-#endif
-
-#if 1
     BlitBitmap(backbuffer, window, x, y, width, height, x, y);
-    redraw_mask = REDRAW_NONE;
-#else
-    BackToFront();
-#endif
+
+    redraw_mask &= ~fade_mask;
 
     return;
   }
 
-  FadeRectangle(bitmap, x, y, width, height, fade_mode, fade_delay, post_delay,
+  FadeRectangle(x, y, width, height, fade_mode, fade_delay, post_delay,
 		draw_border_function);
 
   redraw_mask &= ~fade_mask;
 }
 
+static void SetScreenStates_BeforeFadingIn()
+{
+  // temporarily set screen mode for animations to screen after fading in
+  global.anim_status = global.anim_status_next;
+
+  // store backbuffer with all animations that will be started after fading in
+  if (fade_type_skip != FADE_MODE_SKIP_FADE_IN)
+    PrepareFadeBitmap(DRAW_TO_FADE_TARGET);
+
+  // set screen mode for animations back to fading
+  global.anim_status = GAME_MODE_PSEUDO_FADING;
+}
+
+static void SetScreenStates_AfterFadingIn()
+{
+  // store new source screen (to use correct masked border for fading)
+  gfx.fade_border_source_status = global.border_status;
+
+  global.anim_status = global.anim_status_next;
+}
+
+static void SetScreenStates_BeforeFadingOut()
+{
+  // store new target screen (to use correct masked border for fading)
+  gfx.fade_border_target_status = game_status;
+
+  // set screen mode for animations to fading
+  global.anim_status = GAME_MODE_PSEUDO_FADING;
+
+  // store backbuffer with all animations that will be stopped for fading out
+  if (fade_type_skip != FADE_MODE_SKIP_FADE_OUT)
+    PrepareFadeBitmap(DRAW_TO_FADE_SOURCE);
+}
+
+static void SetScreenStates_AfterFadingOut()
+{
+  global.border_status = game_status;
+}
+
 void FadeIn(int fade_mask)
 {
+  SetScreenStates_BeforeFadingIn();
+
+#if 1
+  DrawMaskedBorder(REDRAW_ALL);
+#endif
+
   if (fading.fade_mode & FADE_TYPE_TRANSFORM)
     FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_IN);
   else
     FadeExt(fade_mask, FADE_MODE_FADE_IN, FADE_TYPE_FADE_IN);
+
+  FADE_SX = REAL_SX;
+  FADE_SY = REAL_SY;
+  FADE_SXSIZE = FULL_SXSIZE;
+  FADE_SYSIZE = FULL_SYSIZE;
+
+  if (game_status == GAME_MODE_PLAYING &&
+      strEqual(setup.touch.control_type, TOUCH_CONTROL_VIRTUAL_BUTTONS))
+    SetOverlayActive(TRUE);
+
+  SetScreenStates_AfterFadingIn();
+
+  // force update of global animation status in case of rapid screen changes
+  redraw_mask = REDRAW_ALL;
+  BackToFront();
 }
 
 void FadeOut(int fade_mask)
 {
+  // update screen if areas covered by "fade_mask" and "redraw_mask" differ
+  if (!equalRedrawMasks(fade_mask, redraw_mask))
+    BackToFront();
+
+  SetScreenStates_BeforeFadingOut();
+
+  SetOverlayActive(FALSE);
+
+#if 0
+  DrawMaskedBorder(REDRAW_ALL);
+#endif
+
   if (fading.fade_mode & FADE_TYPE_TRANSFORM)
     FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_OUT);
   else
     FadeExt(fade_mask, FADE_MODE_FADE_OUT, FADE_TYPE_FADE_OUT);
 
-  global.border_status = game_status;
+  SetScreenStates_AfterFadingOut();
 }
 
 static void FadeSetLeaveNext(struct TitleFadingInfo fading_leave, boolean set)
@@ -674,10 +973,6 @@ void FadeSetEnterMenu()
 {
   fading = menu.enter_menu;
 
-#if 0
-  printf("::: storing enter_menu\n");
-#endif
-
   FadeSetLeaveNext(fading, TRUE);	/* (keep same fade mode) */
 }
 
@@ -685,10 +980,6 @@ void FadeSetLeaveMenu()
 {
   fading = menu.leave_menu;
 
-#if 0
-  printf("::: storing leave_menu\n");
-#endif
-
   FadeSetLeaveNext(fading, TRUE);	/* (keep same fade mode) */
 }
 
@@ -696,20 +987,12 @@ void FadeSetEnterScreen()
 {
   fading = menu.enter_screen[game_status];
 
-#if 0
-  printf("::: storing leave_screen[%d]\n", game_status);
-#endif
-
   FadeSetLeaveNext(menu.leave_screen[game_status], TRUE);	/* store */
 }
 
 void FadeSetNextScreen()
 {
-  fading = menu.next_screen;
-
-#if 0
-  printf("::: storing next_screen\n");
-#endif
+  fading = menu.next_screen[game_status];
 
   // (do not overwrite fade mode set by FadeSetEnterScreen)
   // FadeSetLeaveNext(fading, TRUE);	/* (keep same fade mode) */
@@ -717,10 +1000,6 @@ void FadeSetNextScreen()
 
 void FadeSetLeaveScreen()
 {
-#if 0
-  printf("::: recalling last stored value\n");
-#endif
-
   FadeSetLeaveNext(menu.leave_screen[game_status], FALSE);	/* recall */
 }
 
@@ -751,6 +1030,39 @@ void FadeSkipNextFadeOut()
   FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
 }
 
+Bitmap *getBitmapFromGraphicOrDefault(int graphic, int default_graphic)
+{
+  boolean redefined = getImageListEntryFromImageID(graphic)->redefined;
+
+  return (graphic == IMG_UNDEFINED ? NULL :
+	  graphic_info[graphic].bitmap != NULL || redefined ?
+	  graphic_info[graphic].bitmap :
+	  graphic_info[default_graphic].bitmap);
+}
+
+Bitmap *getBackgroundBitmap(int graphic)
+{
+  return getBitmapFromGraphicOrDefault(graphic, IMG_BACKGROUND);
+}
+
+Bitmap *getGlobalBorderBitmap(int graphic)
+{
+  return getBitmapFromGraphicOrDefault(graphic, IMG_GLOBAL_BORDER);
+}
+
+Bitmap *getGlobalBorderBitmapFromStatus(int status)
+{
+  int graphic =
+    (status == GAME_MODE_MAIN ||
+     status == GAME_MODE_PSEUDO_TYPENAME	? IMG_GLOBAL_BORDER_MAIN :
+     status == GAME_MODE_SCORES			? IMG_GLOBAL_BORDER_SCORES :
+     status == GAME_MODE_EDITOR			? IMG_GLOBAL_BORDER_EDITOR :
+     status == GAME_MODE_PLAYING		? IMG_GLOBAL_BORDER_PLAYING :
+     IMG_GLOBAL_BORDER);
+
+  return getGlobalBorderBitmap(graphic);
+}
+
 void SetWindowBackgroundImageIfDefined(int graphic)
 {
   if (graphic_info[graphic].bitmap)
@@ -771,47 +1083,42 @@ void SetDoorBackgroundImageIfDefined(int graphic)
 
 void SetWindowBackgroundImage(int graphic)
 {
-  SetWindowBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
-			    graphic_info[graphic].bitmap ?
-			    graphic_info[graphic].bitmap :
-			    graphic_info[IMG_BACKGROUND].bitmap);
+  SetWindowBackgroundBitmap(getBackgroundBitmap(graphic));
 }
 
 void SetMainBackgroundImage(int graphic)
 {
-  SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
-			  graphic_info[graphic].bitmap ?
-			  graphic_info[graphic].bitmap :
-			  graphic_info[IMG_BACKGROUND].bitmap);
+  SetMainBackgroundBitmap(getBackgroundBitmap(graphic));
 }
 
 void SetDoorBackgroundImage(int graphic)
 {
-  SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
-			  graphic_info[graphic].bitmap ?
-			  graphic_info[graphic].bitmap :
-			  graphic_info[IMG_BACKGROUND].bitmap);
+  SetDoorBackgroundBitmap(getBackgroundBitmap(graphic));
 }
 
 void SetPanelBackground()
 {
-  BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, bitmap_db_panel,
-             DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, 0, 0);
+  struct GraphicInfo *gfx = &graphic_info[IMG_BACKGROUND_PANEL];
+
+  BlitBitmapTiled(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
+		  gfx->width, gfx->height, 0, 0, DXSIZE, DYSIZE);
 
   SetDoorBackgroundBitmap(bitmap_db_panel);
 }
 
 void DrawBackground(int x, int y, int width, int height)
 {
-  /* !!! "drawto" might still point to playfield buffer here (see below) !!! */
-  /* (when entering hall of fame after playing) */
-#if 0
-  ClearRectangleOnBackground(drawto, x, y, width, height);
-#else
+  /* "drawto" might still point to playfield buffer here (hall of fame) */
   ClearRectangleOnBackground(backbuffer, x, y, width, height);
-#endif
 
-  redraw_mask |= REDRAW_FIELD;
+  if (IN_GFX_FIELD_FULL(x, y))
+    redraw_mask |= REDRAW_FIELD;
+  else if (IN_GFX_DOOR_1(x, y))
+    redraw_mask |= REDRAW_DOOR_1;
+  else if (IN_GFX_DOOR_2(x, y))
+    redraw_mask |= REDRAW_DOOR_2;
+  else if (IN_GFX_DOOR_3(x, y))
+    redraw_mask |= REDRAW_DOOR_3;
 }
 
 void DrawBackgroundForFont(int x, int y, int width, int height, int font_nr)
@@ -834,32 +1141,157 @@ void DrawBackgroundForGraphic(int x, int y, int width, int height, int graphic)
   DrawBackground(x, y, width, height);
 }
 
+static int game_status_last = -1;
+static Bitmap *global_border_bitmap_last = NULL;
+static Bitmap *global_border_bitmap = NULL;
+static int real_sx_last = -1, real_sy_last = -1;
+static int full_sxsize_last = -1, full_sysize_last = -1;
+static int dx_last = -1, dy_last = -1;
+static int dxsize_last = -1, dysize_last = -1;
+static int vx_last = -1, vy_last = -1;
+static int vxsize_last = -1, vysize_last = -1;
+
+boolean CheckIfGlobalBorderHasChanged()
+{
+  // if game status has not changed, global border has not changed either
+  if (game_status == game_status_last)
+    return FALSE;
+
+  // determine and store new global border bitmap for current game status
+  global_border_bitmap = getGlobalBorderBitmapFromStatus(game_status);
+
+  return (global_border_bitmap_last != global_border_bitmap);
+}
+
+boolean CheckIfGlobalBorderRedrawIsNeeded()
+{
+  // if game status has not changed, nothing has to be redrawn
+  if (game_status == game_status_last)
+    return FALSE;
+
+  // redraw if last screen was title screen
+  if (game_status_last == GAME_MODE_TITLE)
+    return TRUE;
+
+  // redraw if global screen border has changed
+  if (CheckIfGlobalBorderHasChanged())
+    return TRUE;
+
+  // redraw if position or size of playfield area has changed
+  if (real_sx_last != REAL_SX || real_sy_last != REAL_SY ||
+      full_sxsize_last != FULL_SXSIZE || full_sysize_last != FULL_SYSIZE)
+    return TRUE;
+
+  // redraw if position or size of door area has changed
+  if (dx_last != DX || dy_last != DY ||
+      dxsize_last != DXSIZE || dysize_last != DYSIZE)
+    return TRUE;
+
+  // redraw if position or size of tape area has changed
+  if (vx_last != VX || vy_last != VY ||
+      vxsize_last != VXSIZE || vysize_last != VYSIZE)
+    return TRUE;
+
+  return FALSE;
+}
+
+void RedrawGlobalBorderFromBitmap(Bitmap *bitmap)
+{
+  if (bitmap)
+    BlitBitmap(bitmap, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+  else
+    ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
+}
+
+void RedrawGlobalBorder()
+{
+  Bitmap *bitmap = getGlobalBorderBitmapFromStatus(game_status);
+
+  RedrawGlobalBorderFromBitmap(bitmap);
+
+  redraw_mask = REDRAW_ALL;
+}
+
+static void RedrawGlobalBorderIfNeeded()
+{
+  if (game_status == game_status_last)
+    return;
+
+  // copy current draw buffer to later copy back areas that have not changed
+  if (game_status_last != GAME_MODE_TITLE)
+    BlitBitmap(backbuffer, bitmap_db_store_1, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+
+  if (CheckIfGlobalBorderRedrawIsNeeded())
+  {
+    // redraw global screen border (or clear, if defined to be empty)
+    RedrawGlobalBorderFromBitmap(global_border_bitmap);
+
+    // copy previous playfield and door areas, if they are defined on both
+    // previous and current screen and if they still have the same size
+
+    if (real_sx_last != -1 && real_sy_last != -1 &&
+	REAL_SX != -1 && REAL_SY != -1 &&
+	full_sxsize_last == FULL_SXSIZE && full_sysize_last == FULL_SYSIZE)
+      BlitBitmap(bitmap_db_store_1, backbuffer,
+		 real_sx_last, real_sy_last, FULL_SXSIZE, FULL_SYSIZE,
+		 REAL_SX, REAL_SY);
+
+    if (dx_last != -1 && dy_last != -1 &&
+	DX != -1 && DY != -1 &&
+	dxsize_last == DXSIZE && dysize_last == DYSIZE)
+      BlitBitmap(bitmap_db_store_1, backbuffer,
+		 dx_last, dy_last, DXSIZE, DYSIZE, DX, DY);
+
+    if (vx_last != -1 && vy_last != -1 &&
+	VX != -1 && VY != -1 &&
+	vxsize_last == VXSIZE && vysize_last == VYSIZE)
+      BlitBitmap(bitmap_db_store_1, backbuffer,
+		 vx_last, vy_last, VXSIZE, VYSIZE, VX, VY);
+
+    redraw_mask = REDRAW_ALL;
+  }
+
+  game_status_last = game_status;
+
+  global_border_bitmap_last = global_border_bitmap;
+
+  real_sx_last = REAL_SX;
+  real_sy_last = REAL_SY;
+  full_sxsize_last = FULL_SXSIZE;
+  full_sysize_last = FULL_SYSIZE;
+  dx_last = DX;
+  dy_last = DY;
+  dxsize_last = DXSIZE;
+  dysize_last = DYSIZE;
+  vx_last = VX;
+  vy_last = VY;
+  vxsize_last = VXSIZE;
+  vysize_last = VYSIZE;
+}
+
 void ClearField()
 {
+  RedrawGlobalBorderIfNeeded();
+
   /* !!! "drawto" might still point to playfield buffer here (see above) !!! */
   /* (when entering hall of fame after playing) */
   DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
 
   /* !!! maybe this should be done before clearing the background !!! */
-  if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
+  if (game_status == GAME_MODE_PLAYING)
   {
     ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
-    SetDrawtoField(DRAW_BUFFERED);
+    SetDrawtoField(DRAW_TO_FIELDBUFFER);
   }
   else
-    SetDrawtoField(DRAW_BACKBUFFER);
+  {
+    SetDrawtoField(DRAW_TO_BACKBUFFER);
+  }
 }
 
 void MarkTileDirty(int x, int y)
 {
-  int xx = redraw_x1 + x;
-  int yy = redraw_y1 + y;
-
-  if (!redraw[xx][yy])
-    redraw_tiles++;
-
-  redraw[xx][yy] = TRUE;
-  redraw_mask |= REDRAW_TILES;
+  redraw_mask |= REDRAW_FIELD;
 }
 
 void SetBorderElement()
@@ -919,7 +1351,7 @@ void SetRandomAnimationValue(int x, int y)
   gfx.anim_random_frame = GfxRandom[x][y];
 }
 
-inline int getGraphicAnimationFrame(int graphic, int sync_frame)
+int getGraphicAnimationFrame(int graphic, int sync_frame)
 {
   /* animation synchronized with global frame counter, not move position */
   if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
@@ -932,112 +1364,95 @@ inline int getGraphicAnimationFrame(int graphic, int sync_frame)
 			   sync_frame);
 }
 
-void getSizedGraphicSource(int graphic, int frame, int tilesize_raw,
-			   Bitmap **bitmap, int *x, int *y)
+void getGraphicSourceBitmap(int graphic, int tilesize, Bitmap **bitmap)
+{
+  struct GraphicInfo *g = &graphic_info[graphic];
+  int tilesize_capped = MIN(MAX(1, tilesize), TILESIZE);
+
+  if (tilesize == gfx.standard_tile_size)
+    *bitmap = g->bitmaps[IMG_BITMAP_STANDARD];
+  else if (tilesize == game.tile_size)
+    *bitmap = g->bitmaps[IMG_BITMAP_GAME];
+  else
+    *bitmap = g->bitmaps[IMG_BITMAP_1x1 - log_2(tilesize_capped)];
+}
+
+void getGraphicSourceXY(int graphic, int frame, int *x, int *y,
+			boolean get_backside)
 {
-  struct
-  {
-    int width_mult, width_div;
-    int height_mult, height_div;
-  }
-  offset_calc[6] =
-  {
-    { 15, 16,	2, 3	},	/* 1 x 1 */
-    { 7, 8,	2, 3	},	/* 2 x 2 */
-    { 3, 4,	2, 3	},	/* 4 x 4 */
-    { 1, 2,	2, 3	},	/* 8 x 8 */
-    { 0, 1,	2, 3	},	/* 16 x 16 */
-    { 0, 1,	0, 1	},	/* 32 x 32 */
-  };
   struct GraphicInfo *g = &graphic_info[graphic];
-  Bitmap *src_bitmap = g->bitmap;
-  int tilesize = MIN(MAX(1, tilesize_raw), TILESIZE);
-  int offset_calc_pos = log_2(tilesize);
-  int width_mult  = offset_calc[offset_calc_pos].width_mult;
-  int width_div   = offset_calc[offset_calc_pos].width_div;
-  int height_mult = offset_calc[offset_calc_pos].height_mult;
-  int height_div  = offset_calc[offset_calc_pos].height_div;
-  int startx = src_bitmap->width * width_mult / width_div;
-  int starty = src_bitmap->height * height_mult / height_div;
-  int src_x = g->src_x * tilesize / TILESIZE;
-  int src_y = g->src_y * tilesize / TILESIZE;
-  int width = g->width * tilesize / TILESIZE;
-  int height = g->height * tilesize / TILESIZE;
-  int offset_x = g->offset_x * tilesize / TILESIZE;
-  int offset_y = g->offset_y * tilesize / TILESIZE;
+  int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
+  int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
 
   if (g->offset_y == 0)		/* frames are ordered horizontally */
   {
-    int max_width = g->anim_frames_per_line * width;
-    int pos = (src_y / height) * max_width + src_x + frame * offset_x;
+    int max_width = g->anim_frames_per_line * g->width;
+    int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
 
-    src_x = pos % max_width;
-    src_y = src_y % height + pos / max_width * height;
+    *x = pos % max_width;
+    *y = src_y % g->height + pos / max_width * g->height;
   }
   else if (g->offset_x == 0)	/* frames are ordered vertically */
   {
-    int max_height = g->anim_frames_per_line * height;
-    int pos = (src_x / width) * max_height + src_y + frame * offset_y;
+    int max_height = g->anim_frames_per_line * g->height;
+    int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
 
-    src_x = src_x % width + pos / max_height * width;
-    src_y = pos % max_height;
+    *x = src_x % g->width + pos / max_height * g->width;
+    *y = pos % max_height;
   }
   else				/* frames are ordered diagonally */
   {
-    src_x = src_x + frame * offset_x;
-    src_y = src_y + frame * offset_y;
+    *x = src_x + frame * g->offset_x;
+    *y = src_y + frame * g->offset_y;
   }
-
-  *bitmap = src_bitmap;
-  *x = startx + src_x;
-  *y = starty + src_y;
 }
 
-void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
+void getSizedGraphicSourceExt(int graphic, int frame, int tilesize,
+			      Bitmap **bitmap, int *x, int *y,
+			      boolean get_backside)
 {
-#if 1
-  getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y);
-#else
   struct GraphicInfo *g = &graphic_info[graphic];
-  int mini_startx = 0;
-  int mini_starty = g->bitmap->height * 2 / 3;
 
-  *bitmap = g->bitmap;
-  *x = mini_startx + g->src_x / 2;
-  *y = mini_starty + g->src_y / 2;
-#endif
+  // if no in-game graphics defined, always use standard graphic size
+  if (g->bitmaps[IMG_BITMAP_GAME] == NULL)
+    tilesize = TILESIZE;
+
+  getGraphicSourceBitmap(graphic, tilesize, bitmap);
+  getGraphicSourceXY(graphic, frame, x, y, get_backside);
+
+  *x = *x * tilesize / g->tile_size;
+  *y = *y * tilesize / g->tile_size;
 }
 
-inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
-				int *x, int *y, boolean get_backside)
+void getFixedGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
+			      int *x, int *y, boolean get_backside)
 {
-  struct GraphicInfo *g = &graphic_info[graphic];
-  int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
-  int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
+  getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y,
+			   get_backside);
+}
 
-  *bitmap = g->bitmap;
+void getSizedGraphicSource(int graphic, int frame, int tilesize,
+			   Bitmap **bitmap, int *x, int *y)
+{
+  getSizedGraphicSourceExt(graphic, frame, tilesize, bitmap, x, y, FALSE);
+}
 
-  if (g->offset_y == 0)		/* frames are ordered horizontally */
-  {
-    int max_width = g->anim_frames_per_line * g->width;
-    int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
+void getFixedGraphicSource(int graphic, int frame,
+			   Bitmap **bitmap, int *x, int *y)
+{
+  getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y, FALSE);
+}
 
-    *x = pos % max_width;
-    *y = src_y % g->height + pos / max_width * g->height;
-  }
-  else if (g->offset_x == 0)	/* frames are ordered vertically */
-  {
-    int max_height = g->anim_frames_per_line * g->height;
-    int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
+void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
+{
+  getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y);
+}
 
-    *x = src_x % g->width + pos / max_height * g->width;
-    *y = pos % max_height;
-  }
-  else				/* frames are ordered diagonally */
-  {
-    *x = src_x + frame * g->offset_x;
-    *y = src_y + frame * g->offset_y;
-  }
+inline static void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
+				       int *x, int *y, boolean get_backside)
+{
+  getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y,
+			   get_backside);
 }
 
 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
@@ -1056,7 +1471,25 @@ void DrawGraphic(int x, int y, int graphic, int frame)
   }
 #endif
 
-  DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
+  DrawGraphicExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR, graphic,
+		 frame);
+
+  MarkTileDirty(x, y);
+}
+
+void DrawFixedGraphic(int x, int y, int graphic, int frame)
+{
+#if DEBUG
+  if (!IN_SCR_FIELD(x, y))
+  {
+    printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
+    printf("DrawGraphic(): This should never happen!\n");
+    return;
+  }
+#endif
+
+  DrawFixedGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
+		      frame);
   MarkTileDirty(x, y);
 }
 
@@ -1067,6 +1500,17 @@ void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
   int src_x, src_y;
 
   getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
+
+  BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX_VAR, TILEY_VAR, x, y);
+}
+
+void DrawFixedGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
+			 int frame)
+{
+  Bitmap *src_bitmap;
+  int src_x, src_y;
+
+  getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
   BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
 }
 
@@ -1081,8 +1525,25 @@ void DrawGraphicThruMask(int x, int y, int graphic, int frame)
   }
 #endif
 
-  DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
-			 frame);
+  DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
+			 graphic, frame);
+
+  MarkTileDirty(x, y);
+}
+
+void DrawFixedGraphicThruMask(int x, int y, int graphic, int frame)
+{
+#if DEBUG
+  if (!IN_SCR_FIELD(x, y))
+  {
+    printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
+    printf("DrawGraphicThruMask(): This should never happen!\n");
+    return;
+  }
+#endif
+
+  DrawFixedGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
+			      graphic, frame);
   MarkTileDirty(x, y);
 }
 
@@ -1094,9 +1555,20 @@ void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
 
   getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
 
-  SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
-		dst_x - src_x, dst_y - src_y);
-  BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
+  BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX_VAR, TILEY_VAR,
+		   dst_x, dst_y);
+}
+
+void DrawFixedGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y,
+				 int graphic, int frame)
+{
+  Bitmap *src_bitmap;
+  int src_x, src_y;
+
+  getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
+
+  BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY,
+		   dst_x, dst_y);
 }
 
 void DrawSizedGraphic(int x, int y, int graphic, int frame, int tilesize)
@@ -1156,20 +1628,20 @@ inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
       width = -dx;
       dx = TILEX + dx;
     }
-    else if (x==BX1 && dx < 0)	/* object leaves playfield to the left */
+    else if (x == BX1 && dx < 0) /* object leaves playfield to the left */
     {
       width += dx;
       cx = -dx;
       dx = 0;
     }
-    else if (x==BX2 && dx > 0)	/* object leaves playfield to the right */
+    else if (x == BX2 && dx > 0) /* object leaves playfield to the right */
       width -= dx;
     else if (dx)		/* general horizontal movement */
       MarkTileDirty(x + SIGN(dx), y);
 
     if (y < BY1)		/* object enters playfield from the top */
     {
-      if (cut_mode==CUT_BELOW)	/* object completely above top border */
+      if (cut_mode == CUT_BELOW) /* object completely above top border */
 	return;
 
       y = BY1;
@@ -1183,7 +1655,7 @@ inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
       height = -dy;
       dy = TILEY + dy;
     }
-    else if (y==BY1 && dy < 0)	/* object leaves playfield to the top */
+    else if (y == BY1 && dy < 0) /* object leaves playfield to the top */
     {
       height += dy;
       cy = -dy;
@@ -1214,6 +1686,13 @@ inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
   }
 #endif
 
+  width = width * TILESIZE_VAR / TILESIZE;
+  height = height * TILESIZE_VAR / TILESIZE;
+  cx = cx * TILESIZE_VAR / TILESIZE;
+  cy = cy * TILESIZE_VAR / TILESIZE;
+  dx = dx * TILESIZE_VAR / TILESIZE;
+  dy = dy * TILESIZE_VAR / TILESIZE;
+
   if (width > 0 && height > 0)
   {
     getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
@@ -1221,16 +1700,12 @@ inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
     src_x += cx;
     src_y += cy;
 
-    dst_x = FX + x * TILEX + dx;
-    dst_y = FY + y * TILEY + dy;
+    dst_x = FX + x * TILEX_VAR + dx;
+    dst_y = FY + y * TILEY_VAR + dy;
 
     if (mask_mode == USE_MASKING)
-    {
-      SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
-		    dst_x - src_x, dst_y - src_y);
       BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
 		       dst_x, dst_y);
-    }
     else
       BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
 		 dst_x, dst_y);
@@ -1246,63 +1721,38 @@ inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
   Bitmap *src_bitmap;
   int src_x, src_y;
   int dst_x, dst_y;
-  int width = TILEX, height = TILEY;
+  int width = TILEX_VAR, height = TILEY_VAR;
   int x1 = x;
   int y1 = y;
   int x2 = x + SIGN(dx);
   int y2 = y + SIGN(dy);
-#if 0
-  /* !!! DOES NOT WORK FOR SLOW MOVEMENT !!! */
-  int sync_frame = GfxFrame[LEVELX(x)][LEVELY(y)];
-#else
+
   /* movement with two-tile animations must be sync'ed with movement position,
      not with current GfxFrame (which can be higher when using slow movement) */
   int anim_pos = (dx ? ABS(dx) : ABS(dy));
   int anim_frames = graphic_info[graphic].anim_frames;
-#if 1
+
   /* (we also need anim_delay here for movement animations with less frames) */
   int anim_delay = graphic_info[graphic].anim_delay;
   int sync_frame = anim_pos * anim_frames * anim_delay / TILESIZE;
-#else
-  int sync_frame = anim_pos * anim_frames / TILESIZE;
-#endif
-#endif
+
   boolean draw_start_tile = (cut_mode != CUT_ABOVE);	/* only for falling! */
   boolean draw_end_tile   = (cut_mode != CUT_BELOW);	/* only for falling! */
 
   /* re-calculate animation frame for two-tile movement animation */
   frame = getGraphicAnimationFrame(graphic, sync_frame);
 
-#if 0
-#if 0
-  printf("::: %d, %d, %d => %d [%d]\n",
-	 anim_pos, anim_frames, anim_delay, sync_frame, graphic);
-#else
-  printf("::: %d, %d => %d\n",
-	 anim_pos, anim_frames, sync_frame);
-#endif
-#endif
-
-#if 0
-  printf("::: %d [%d, %d] [%d] [%d]\n", frame, sync_frame, dy,
-	 GfxFrame[LEVELX(x)][LEVELY(y)], mask_mode);
-#endif
-
   /* check if movement start graphic inside screen area and should be drawn */
   if (draw_start_tile && IN_SCR_FIELD(x1, y1))
   {
     getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
 
-    dst_x = FX + x1 * TILEX;
-    dst_y = FY + y1 * TILEY;
+    dst_x = FX + x1 * TILEX_VAR;
+    dst_y = FY + y1 * TILEY_VAR;
 
     if (mask_mode == USE_MASKING)
-    {
-      SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
-		    dst_x - src_x, dst_y - src_y);
       BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
 		       dst_x, dst_y);
-    }
     else
       BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
 		 dst_x, dst_y);
@@ -1315,16 +1765,12 @@ inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
   {
     getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
 
-    dst_x = FX + x2 * TILEX;
-    dst_y = FY + y2 * TILEY;
+    dst_x = FX + x2 * TILEX_VAR;
+    dst_y = FY + y2 * TILEY_VAR;
 
     if (mask_mode == USE_MASKING)
-    {
-      SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
-		    dst_x - src_x, dst_y - src_y);
       BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
 		       dst_x, dst_y);
-    }
     else
       BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
 		 dst_x, dst_y);
@@ -1459,6 +1905,9 @@ static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy,
   int width, height, cx, cy;
   int sx = SCREENX(x), sy = SCREENY(y);
   int crumbled_border_size = graphic_info[graphic].border_size;
+  int crumbled_tile_size = graphic_info[graphic].tile_size;
+  int crumbled_border_size_var =
+    crumbled_border_size * TILESIZE_VAR / crumbled_tile_size;
   int i;
 
   getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
@@ -1486,13 +1935,13 @@ static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy,
 
   getGraphicSource(graphic, 1, &src_bitmap, &src_x, &src_y);
 
-  width  = crumbled_border_size;
-  height = crumbled_border_size;
-  cx = (dx > 0 ? TILEX - crumbled_border_size : 0);
-  cy = (dy > 0 ? TILEY - crumbled_border_size : 0);
+  width  = crumbled_border_size_var;
+  height = crumbled_border_size_var;
+  cx = (dx > 0 ? TILESIZE_VAR - width  : 0);
+  cy = (dy > 0 ? TILESIZE_VAR - height : 0);
 
   BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
-	     width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
+	     width, height, FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
 }
 
 static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
@@ -1503,46 +1952,33 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
   int width, height, bx, by, cx, cy;
   int sx = SCREENX(x), sy = SCREENY(y);
   int crumbled_border_size = graphic_info[graphic].border_size;
+  int crumbled_tile_size = graphic_info[graphic].tile_size;
+  int crumbled_border_size_var =
+    crumbled_border_size * TILESIZE_VAR / crumbled_tile_size;
+  int crumbled_border_pos_var = TILESIZE_VAR - crumbled_border_size_var;
   int i;
 
   getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
 
   /* draw simple, sloppy, non-corner-accurate crumbled border */
 
-#if 1
-  width  = (dir == 1 || dir == 2 ? crumbled_border_size : TILEX);
-  height = (dir == 0 || dir == 3 ? crumbled_border_size : TILEY);
-  cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
-  cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
-#else
-  if (dir == 1 || dir == 2)		/* left or right crumbled border */
-  {
-    width = crumbled_border_size;
-    height = TILEY;
-    cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
-    cy = 0;
-  }
-  else					/* top or bottom crumbled border */
-  {
-    width = TILEX;
-    height = crumbled_border_size;
-    cx = 0;
-    cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
-  }
-#endif
+  width  = (dir == 1 || dir == 2 ? crumbled_border_size_var : TILESIZE_VAR);
+  height = (dir == 0 || dir == 3 ? crumbled_border_size_var : TILESIZE_VAR);
+  cx = (dir == 2 ? crumbled_border_pos_var : 0);
+  cy = (dir == 3 ? crumbled_border_pos_var : 0);
 
-  BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
-	     width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
+  BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy, width, height,
+	     FX + sx * TILEX_VAR + cx,
+	     FY + sy * TILEY_VAR + cy);
 
   /* (remaining middle border part must be at least as big as corner part) */
   if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
-      crumbled_border_size >= TILESIZE / 3)
+      crumbled_border_size_var >= TILESIZE_VAR / 3)
     return;
 
   /* correct corners of crumbled border, if needed */
 
-#if 1
-  for (i = -1; i <= 1; i+=2)
+  for (i = -1; i <= 1; i += 2)
   {
     int xx = x + (dir == 0 || dir == 3 ? i : 0);
     int yy = y + (dir == 1 || dir == 2 ? i : 0);
@@ -1556,13 +1992,13 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
     {
       /* no crumbled corner, but continued crumbled border */
 
-      int c1 = (dir == 2 || dir == 3 ? TILESIZE - crumbled_border_size : 0);
-      int c2 = (i == 1 ? TILESIZE - crumbled_border_size : 0);
-      int b1 = (i == 1 ? crumbled_border_size :
-		TILESIZE - 2 * crumbled_border_size);
+      int c1 = (dir == 2 || dir == 3 ? crumbled_border_pos_var : 0);
+      int c2 = (i == 1 ? crumbled_border_pos_var : 0);
+      int b1 = (i == 1 ? crumbled_border_size_var :
+		TILESIZE_VAR - 2 * crumbled_border_size_var);
 
-      width  = crumbled_border_size;
-      height = crumbled_border_size;
+      width  = crumbled_border_size_var;
+      height = crumbled_border_size_var;
 
       if (dir == 1 || dir == 2)
       {
@@ -1580,69 +2016,11 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
       }
 
       BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
-		 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
-    }
-  }
-#else
-  if (dir == 1 || dir == 2)		/* left or right crumbled border */
-  {
-    for (i = -1; i <= 1; i+=2)
-    {
-      int xx = x;
-      int yy = y + i;
-      int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
-		     BorderElement);
-
-      /* check if neighbour field is of same crumble type */
-      if (IS_CRUMBLED_TILE(xx, yy, element) &&
-	  graphic_info[graphic].class ==
-	  graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
-      {
-	/* no crumbled corner, but continued crumbled border */
-
-	width  = crumbled_border_size;
-	height = crumbled_border_size;
-	cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
-	cy = (i == 1 ? TILEY - crumbled_border_size : 0);
-	bx = cx;
-	by = (i == 1 ? crumbled_border_size :
-	      TILEY - 2 * crumbled_border_size);
-
-	BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
-		   width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
-      }
-    }
-  }
-  else				/* top or bottom crumbled border */
-  {
-    for (i = -1; i <= 1; i+=2)
-    {
-      int xx = x + i;
-      int yy = y;
-      int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
-		     BorderElement);
-
-      /* check if neighbour field is of same crumble type */
-      if (IS_CRUMBLED_TILE(xx, yy, element) &&
-	  graphic_info[graphic].class ==
-	  graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
-      {
-	/* no crumbled corner, but continued crumbled border */
-
-	width  = crumbled_border_size;
-	height = crumbled_border_size;
-	cx = (i == 1 ? TILEX - crumbled_border_size : 0);
-	cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
-	bx = (i == 1 ? crumbled_border_size :
-	      TILEX - 2 * crumbled_border_size);
-	by = cy;
-
-	BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
-		   width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
-      }
+		 width, height,
+		 FX + sx * TILEX_VAR + cx,
+		 FY + sy * TILEY_VAR + cy);
     }
   }
-#endif
 }
 
 static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
@@ -1663,12 +2041,12 @@ static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
 
   element = TILE_GFX_ELEMENT(x, y);
 
-  /* crumble field itself */
-  if (IS_CRUMBLED_TILE(x, y, element))
+  if (IS_CRUMBLED_TILE(x, y, element))		/* crumble field itself */
   {
     if (!IN_SCR_FIELD(sx, sy))
       return;
 
+    /* crumble field borders towards direct neighbour fields */
     for (i = 0; i < 4; i++)
     {
       int xx = x + xy[i][0];
@@ -1678,19 +2056,15 @@ static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
 		 BorderElement);
 
       /* check if neighbour field is of same crumble type */
-#if 1
       if (IS_CRUMBLED_TILE(xx, yy, element) &&
 	  graphic_info[graphic].class ==
 	  graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
 	continue;
-#else
-      if (IS_CRUMBLED_TILE(xx, yy, element))
-	continue;
-#endif
 
       DrawLevelFieldCrumbledBorders(x, y, graphic, frame, i);
     }
 
+    /* crumble inner field corners towards corner neighbour fields */
     if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
 	graphic_info[graphic].anim_frames == 2)
     {
@@ -1705,8 +2079,9 @@ static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
 
     MarkTileDirty(sx, sy);
   }
-  else		/* center field not crumbled -- crumble neighbour fields */
+  else		/* center field is not crumbled -- crumble neighbour fields */
   {
+    /* crumble field borders of direct neighbour fields */
     for (i = 0; i < 4; i++)
     {
       int xx = x + xy[i][0];
@@ -1732,6 +2107,37 @@ static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
 
       MarkTileDirty(sxx, syy);
     }
+
+    /* crumble inner field corners of corner neighbour fields */
+    for (i = 0; i < 4; i++)
+    {
+      int dx = (i & 1 ? +1 : -1);
+      int dy = (i & 2 ? +1 : -1);
+      int xx = x + dx;
+      int yy = y + dy;
+      int sxx = sx + dx;
+      int syy = sy + dy;
+
+      if (!IN_LEV_FIELD(xx, yy) ||
+	  !IN_SCR_FIELD(sxx, syy))
+	continue;
+
+      if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
+	continue;
+
+      element = TILE_GFX_ELEMENT(xx, yy);
+
+      if (!IS_CRUMBLED_TILE(xx, yy, element))
+	continue;
+
+      graphic = el_act2crm(element, ACTION_DEFAULT);
+
+      if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
+	  graphic_info[graphic].anim_frames == 2)
+	DrawLevelFieldCrumbledInnerCorners(xx, yy, -dx, -dy, graphic);
+
+      MarkTileDirty(sxx, syy);
+    }
   }
 }
 
@@ -1742,14 +2148,6 @@ void DrawLevelFieldCrumbled(int x, int y)
   if (!IN_LEV_FIELD(x, y))
     return;
 
-#if 1
-  /* !!! CHECK THIS !!! */
-
-  /*
-  if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
-      GFX_CRUMBLED(GfxElement[x][y]))
-  */
-
   if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
       GfxElement[x][y] != EL_UNDEFINED &&
       GFX_CRUMBLED(GfxElement[x][y]))
@@ -1758,13 +2156,8 @@ void DrawLevelFieldCrumbled(int x, int y)
 
     return;
   }
-#endif
 
-#if 1
   graphic = el_act2crm(TILE_GFX_ELEMENT(x, y), ACTION_DEFAULT);
-#else
-  graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
-#endif
 
   DrawLevelFieldCrumbledExt(x, y, graphic, 0);
 }
@@ -1794,6 +2187,7 @@ void DrawLevelFieldCrumbledNeighbours(int x, int y)
   };
   int i;
 
+  /* crumble direct neighbour fields (required for field borders) */
   for (i = 0; i < 4; i++)
   {
     int xx = x + xy[i][0];
@@ -1809,6 +2203,30 @@ void DrawLevelFieldCrumbledNeighbours(int x, int y)
 
     DrawLevelField(xx, yy);
   }
+
+  /* crumble corner neighbour fields (required for inner field corners) */
+  for (i = 0; i < 4; i++)
+  {
+    int dx = (i & 1 ? +1 : -1);
+    int dy = (i & 2 ? +1 : -1);
+    int xx = x + dx;
+    int yy = y + dy;
+    int sxx = sx + dx;
+    int syy = sy + dy;
+
+    if (!IN_LEV_FIELD(xx, yy) ||
+	!IN_SCR_FIELD(sxx, syy) ||
+	!GFX_CRUMBLED(Feld[xx][yy]) ||
+	IS_MOVING(xx, yy))
+      continue;
+
+    int element = TILE_GFX_ELEMENT(xx, yy);
+    int graphic = el_act2crm(element, ACTION_DEFAULT);
+
+    if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
+	graphic_info[graphic].anim_frames == 2)
+      DrawLevelField(xx, yy);
+  }
 }
 
 static int getBorderElement(int x, int y)
@@ -1885,22 +2303,8 @@ void DrawScreenField(int x, int y)
 	     element == EL_DC_MAGIC_WALL_FILLING)
       cut_mode = CUT_BELOW;
 
-#if 0
-    if (lx == 9 && ly == 1)
-      printf("::: %s [%d] [%d, %d] [%d]\n",
-	     EL_NAME(TILE_GFX_ELEMENT(lx, ly)),
-	     el_act2crm(TILE_GFX_ELEMENT(lx, ly), ACTION_DEFAULT),
-	     element_info[EL_QUICKSAND_EMPTYING].graphic[ACTION_DEFAULT],
-	     element_info[EL_QUICKSAND_EMPTYING].crumbled[ACTION_DEFAULT],
-	     GFX_CRUMBLED(TILE_GFX_ELEMENT(lx, ly)));
-#endif
-
     if (cut_mode == CUT_ABOVE)
-#if 1
       DrawScreenElement(x, y, element);
-#else
-      DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
-#endif
     else
       DrawScreenElement(x, y, EL_EMPTY);
 
@@ -1912,11 +2316,9 @@ void DrawScreenField(int x, int y)
     {
       DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
 
-#if 1
       if (cut_mode == CUT_BELOW &&
 	  IN_LEV_FIELD(lx, ly + 1) && IN_SCR_FIELD(x, y + 1))
 	DrawLevelElement(lx, ly + 1, element);
-#endif
     }
 
     if (content == EL_ACID)
@@ -1926,6 +2328,10 @@ void DrawScreenField(int x, int y)
       int newly = ly + (dir == MV_UP   ? -1 : dir == MV_DOWN  ? +1 : 0);
 
       DrawLevelElementThruMask(newlx, newly, EL_ACID);
+
+      // prevent target field from being drawn again (but without masking)
+      // (this would happen if target field is scanned after moving element)
+      Stop[newlx][newly] = TRUE;
     }
   }
   else if (IS_BLOCKED(lx, ly))
@@ -1993,6 +2399,14 @@ void DrawLevelField(int x, int y)
   }
 }
 
+void DrawSizedElement(int x, int y, int element, int tilesize)
+{
+  int graphic;
+
+  graphic = el2edimg(element);
+  DrawSizedGraphic(x, y, graphic, 0, tilesize);
+}
+
 void DrawMiniElement(int x, int y, int element)
 {
   int graphic;
@@ -2001,6 +2415,19 @@ void DrawMiniElement(int x, int y, int element)
   DrawMiniGraphic(x, y, graphic);
 }
 
+void DrawSizedElementOrWall(int sx, int sy, int scroll_x, int scroll_y,
+			    int tilesize)
+{
+  int x = sx + scroll_x, y = sy + scroll_y;
+
+  if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
+    DrawSizedElement(sx, sy, EL_EMPTY, tilesize);
+  else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
+    DrawSizedElement(sx, sy, Feld[x][y], tilesize);
+  else
+    DrawSizedGraphic(sx, sy, el2edimg(getBorderElement(x, y)), 0, tilesize);
+}
+
 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
 {
   int x = sx + scroll_x, y = sy + scroll_y;
@@ -2013,49 +2440,55 @@ void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
     DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
 }
 
-void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
-			    int x, int y, int xsize, int ysize, int font_nr)
+void DrawEnvelopeBackgroundTiles(int graphic, int startx, int starty,
+				 int x, int y, int xsize, int ysize,
+				 int tile_width, int tile_height)
 {
-  int font_width  = getFontWidth(font_nr);
-  int font_height = getFontHeight(font_nr);
-  int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
   Bitmap *src_bitmap;
   int src_x, src_y;
-  int dst_x = SX + startx + x * font_width;
-  int dst_y = SY + starty + y * font_height;
+  int dst_x = startx + x * tile_width;
+  int dst_y = starty + y * tile_height;
   int width  = graphic_info[graphic].width;
   int height = graphic_info[graphic].height;
-  int inner_width  = MAX(width  - 2 * font_width,  font_width);
-  int inner_height = MAX(height - 2 * font_height, font_height);
-  int inner_sx = (width >= 3 * font_width ? font_width : 0);
-  int inner_sy = (height >= 3 * font_height ? font_height : 0);
+  int inner_width_raw  = MAX(width  - 2 * tile_width,  tile_width);
+  int inner_height_raw = MAX(height - 2 * tile_height, tile_height);
+  int inner_width  = inner_width_raw  - (inner_width_raw  % tile_width);
+  int inner_height = inner_height_raw - (inner_height_raw % tile_height);
+  int inner_sx = (width  >= 3 * tile_width  ? tile_width  : 0);
+  int inner_sy = (height >= 3 * tile_height ? tile_height : 0);
   boolean draw_masked = graphic_info[graphic].draw_masked;
 
-  getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
+  getFixedGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
 
-  if (src_bitmap == NULL || width < font_width || height < font_height)
+  if (src_bitmap == NULL || width < tile_width || height < tile_height)
   {
-    ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
+    ClearRectangle(drawto, dst_x, dst_y, tile_width, tile_height);
     return;
   }
 
-  src_x += (x == 0 ? 0 : x == xsize - 1 ? width  - font_width  :
-	    inner_sx + (x - 1) * font_width  % inner_width);
-  src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
-	    inner_sy + (y - 1) * font_height % inner_height);
+  src_x += (x == 0 ? 0 : x == xsize - 1 ? width  - tile_width  :
+	    inner_sx + (x - 1) * tile_width  % inner_width);
+  src_y += (y == 0 ? 0 : y == ysize - 1 ? height - tile_height :
+	    inner_sy + (y - 1) * tile_height % inner_height);
 
   if (draw_masked)
-  {
-    SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
-		  dst_x - src_x, dst_y - src_y);
-    BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
+    BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, tile_width, tile_height,
 		     dst_x, dst_y);
-  }
   else
-    BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
+    BlitBitmap(src_bitmap, drawto, src_x, src_y, tile_width, tile_height,
 	       dst_x, dst_y);
 }
 
+void DrawEnvelopeBackground(int graphic, int startx, int starty,
+			    int x, int y, int xsize, int ysize, int font_nr)
+{
+  int font_width  = getFontWidth(font_nr);
+  int font_height = getFontHeight(font_nr);
+
+  DrawEnvelopeBackgroundTiles(graphic, startx, starty, x, y, xsize, ysize,
+			      font_width, font_height);
+}
+
 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
 {
   int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
@@ -2063,9 +2496,9 @@ void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
   int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
   boolean ffwd_delay = (tape.playing && tape.fast_forward);
   boolean no_delay = (tape.warp_forward);
-  unsigned long anim_delay = 0;
+  unsigned int anim_delay = 0;
   int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
-  int anim_delay_value = (no_delay ? 0 : frame_delay_value);
+  int anim_delay_value = (no_delay ? 0 : frame_delay_value) / 2;
   int font_nr = FONT_ENVELOPE_1 + envelope_nr;
   int font_width = getFontWidth(font_nr);
   int font_height = getFontHeight(font_nr);
@@ -2077,313 +2510,368 @@ void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
   int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
   int xstep = (xstart < xend ? 1 : 0);
   int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
-  int x, y;
+  int start = 0;
+  int end = MAX(xend - xstart, yend - ystart);
+  int i;
 
-  for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
+  for (i = start; i <= end; i++)
   {
+    int last_frame = end;	// last frame of this "for" loop
+    int x = xstart + i * xstep;
+    int y = ystart + i * ystep;
     int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
     int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
-    int sx = (SXSIZE - xsize * font_width)  / 2;
-    int sy = (SYSIZE - ysize * font_height) / 2;
+    int sx = SX + (SXSIZE - xsize * font_width)  / 2;
+    int sy = SY + (SYSIZE - ysize * font_height) / 2;
     int xx, yy;
 
-    SetDrawtoField(DRAW_BUFFERED);
+    SetDrawtoField(DRAW_TO_FIELDBUFFER);
 
-    BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
+    BlitScreenToBitmap(backbuffer);
 
-    SetDrawtoField(DRAW_BACKBUFFER);
+    SetDrawtoField(DRAW_TO_BACKBUFFER);
 
-    for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
-      DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
+    for (yy = 0; yy < ysize; yy++)
+      for (xx = 0; xx < xsize; xx++)
+	DrawEnvelopeBackground(graphic, sx, sy, xx, yy, xsize, ysize, font_nr);
 
-#if 1
-    DrawTextBuffer(SX + sx + font_width, SY + sy + font_height,
+    DrawTextBuffer(sx + font_width, sy + font_height,
 		   level.envelope[envelope_nr].text, font_nr, max_xsize,
 		   xsize - 2, ysize - 2, 0, mask_mode,
 		   level.envelope[envelope_nr].autowrap,
 		   level.envelope[envelope_nr].centered, FALSE);
-#else
-    DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
-		       level.envelope[envelope_nr].text, font_nr, max_xsize,
-		       xsize - 2, ysize - 2, mask_mode);
-#endif
 
-    redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
+    redraw_mask |= REDRAW_FIELD;
     BackToFront();
 
-    WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
+    SkipUntilDelayReached(&anim_delay, anim_delay_value, &i, last_frame);
   }
 }
 
-void AnimateEnvelopeDoor(char *text, int anim_mode, int action)
+void ShowEnvelope(int envelope_nr)
 {
-#if 1
-  int envelope_nr = 0;
-#endif
+  int element = EL_ENVELOPE_1 + envelope_nr;
   int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
-  Bitmap *src_bitmap = graphic_info[graphic].bitmap;
-  int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
+  int sound_opening = element_info[element].sound[ACTION_OPENING];
+  int sound_closing = element_info[element].sound[ACTION_CLOSING];
   boolean ffwd_delay = (tape.playing && tape.fast_forward);
   boolean no_delay = (tape.warp_forward);
-  unsigned long anim_delay = 0;
-  int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
-  int anim_delay_value = (no_delay ? 0 : frame_delay_value);
-#if 1
-  int max_word_len = maxWordLengthInString(text);
-  int font_nr = (max_word_len > 7 ? FONT_TEXT_1 : FONT_TEXT_2);
-#else
-  int font_nr = FONT_ENVELOPE_1 + envelope_nr;
-#endif
-  int font_width = getFontWidth(font_nr);
-  int font_height = getFontHeight(font_nr);
-#if 1
-
-#if 1
-  int max_xsize = DXSIZE / font_width;
-  int max_ysize = DYSIZE / font_height;
-#else
-  int max_xsize = 7;	/* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
-  int max_ysize = 13;	/* tools.c: MAX_REQUEST_LINES == 13 */
-#endif
-
-#else
-  int max_xsize = level.envelope[envelope_nr].xsize;
-  int max_ysize = level.envelope[envelope_nr].ysize;
-#endif
-  int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
-  int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
-  int xend = max_xsize;
-  int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
-  int xstep = (xstart < xend ? 1 : 0);
-  int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
-  int x, y;
+  int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
+  int wait_delay_value = (no_delay ? 0 : normal_delay_value);
+  int anim_mode = graphic_info[graphic].anim_mode;
+  int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
+			anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
 
-#if 1
-  char *text_ptr;
-  char *text_copy = getStringCopy(text);
-#else
-#if 1
-  font_nr = FONT_TEXT_2;
+  game.envelope_active = TRUE;	/* needed for RedrawPlayfield() events */
 
-  if (maxWordLengthInString(text) > 7)	/* MAX_REQUEST_LINE_FONT1_LEN == 7 */
-  {
-    max_xsize = 10;	/* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
-    font_nr = FONT_TEXT_1;
-  }
-#else
-  int max_word_len = 0;
-  char *text_ptr;
-  char *text_copy = getStringCopy(text);
+  PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
 
-  font_nr = FONT_TEXT_2;
+  if (anim_mode == ANIM_DEFAULT)
+    AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
 
-  for (text_ptr = text; *text_ptr; text_ptr++)
-  {
-    max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
+  AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
 
-    if (max_word_len > 7)	/* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
-    {
-      max_xsize = 10;	/* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
-      font_nr = FONT_TEXT_1;
+  if (tape.playing)
+    Delay(wait_delay_value);
+  else
+    WaitForEventToContinue();
 
-      break;
-    }
-  }
-#endif
-#endif
+  PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
 
-#if 1
-  for (text_ptr = text_copy; *text_ptr; text_ptr++)
-    if (*text_ptr == ' ')
-      *text_ptr = '\n';
-#endif
+  if (anim_mode != ANIM_NONE)
+    AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
 
-#if 1
-  dDX = SX + (SXSIZE - DXSIZE) / 2 - DX;
-  dDY = SY + (SYSIZE - DYSIZE) / 2 - DY;
-#else
-  dDX = SX + SXSIZE / 2 - max_xsize * font_width  / 2 - DX;
-  dDY = SY + SYSIZE / 2 - max_ysize * font_height / 2 - DY;
-#endif
+  if (anim_mode == ANIM_DEFAULT)
+    AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
 
-  for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
-  {
-    int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
-    int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
-    int sx = (SXSIZE - xsize * font_width)  / 2;
-    int sy = (SYSIZE - ysize * font_height) / 2;
-    int xx, yy;
+  game.envelope_active = FALSE;
 
-#if 1
-    BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
-#else
-    SetDrawtoField(DRAW_BUFFERED);
+  SetDrawtoField(DRAW_TO_FIELDBUFFER);
 
-    BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
+  redraw_mask |= REDRAW_FIELD;
+  BackToFront();
+}
 
-    SetDrawtoField(DRAW_BACKBUFFER);
-#endif
+static void setRequestBasePosition(int *x, int *y)
+{
+  int sx_base, sy_base;
 
-    for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
-      DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
+  if (request.x != -1)
+    sx_base = request.x;
+  else if (request.align == ALIGN_LEFT)
+    sx_base = SX;
+  else if (request.align == ALIGN_RIGHT)
+    sx_base = SX + SXSIZE;
+  else
+    sx_base = SX + SXSIZE / 2;
+
+  if (request.y != -1)
+    sy_base = request.y;
+  else if (request.valign == VALIGN_TOP)
+    sy_base = SY;
+  else if (request.valign == VALIGN_BOTTOM)
+    sy_base = SY + SYSIZE;
+  else
+    sy_base = SY + SYSIZE / 2;
 
-#if 1
+  *x = sx_base;
+  *y = sy_base;
+}
 
-#if 1
-    DrawTextBuffer(SX + sx + font_width, SY + sy + font_height + 8,
-		   text_copy, font_nr, max_xsize,
-		   xsize - 2, ysize - 2, 2, mask_mode,
-		   FALSE, TRUE, FALSE);
-#else
-    DrawTextBuffer(SX + sx + font_width, SY + sy + font_height,
-		   level.envelope[envelope_nr].text, font_nr, max_xsize,
-		   xsize - 2, ysize - 2, 0, mask_mode,
-		   level.envelope[envelope_nr].autowrap,
-		   level.envelope[envelope_nr].centered, FALSE);
-#endif
+static void setRequestPositionExt(int *x, int *y, int width, int height,
+				  boolean add_border_size)
+{
+  int border_size = request.border_size;
+  int sx_base, sy_base;
+  int sx, sy;
 
-#else
-    DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
-		       level.envelope[envelope_nr].text, font_nr, max_xsize,
-		       xsize - 2, ysize - 2, mask_mode);
-#endif
+  setRequestBasePosition(&sx_base, &sy_base);
 
-    /* copy request gadgets to door backbuffer */
-#if 1
-    if ((ysize - 2) > 13)
-      BlitBitmap(bitmap_db_door, drawto,
-		 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
-		 DOOR_GFX_PAGEY1 + 13 * font_height,
-		 (xsize - 2) * font_width,
-		 (ysize - 2 - 13) * font_height,
-		 SX + sx + font_width,
-		 SY + sy + font_height * (1 + 13));
-#else
-    if ((ysize - 2) > 13)
-      BlitBitmap(bitmap_db_door, drawto,
-		 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
-		 DOOR_GFX_PAGEY1 + 13 * font_height,
-		 (xsize - 2) * font_width,
-		 (ysize - 2 - 13) * font_height,
-		 SX + sx + font_width,
-		 SY + sy + font_height * (1 + 13));
-#endif
+  if (request.align == ALIGN_LEFT)
+    sx = sx_base;
+  else if (request.align == ALIGN_RIGHT)
+    sx = sx_base - width;
+  else
+    sx = sx_base - width  / 2;
 
-#if 1
-    redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
-    // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
-#else
-    redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
-#endif
+  if (request.valign == VALIGN_TOP)
+    sy = sy_base;
+  else if (request.valign == VALIGN_BOTTOM)
+    sy = sy_base - height;
+  else
+    sy = sy_base - height / 2;
 
-#if 1
-    DoAnimation();
-    BackToFront();
-#else
-    BackToFront();
-#endif
+  sx = MAX(0, MIN(sx, WIN_XSIZE - width));
+  sy = MAX(0, MIN(sy, WIN_YSIZE - height));
 
-    WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
+  if (add_border_size)
+  {
+    sx += border_size;
+    sy += border_size;
   }
 
-#if 1
-  free(text_copy);
-#endif
+  *x = sx;
+  *y = sy;
 }
 
-void ShowEnvelope(int envelope_nr)
+static void setRequestPosition(int *x, int *y, boolean add_border_size)
 {
-  int element = EL_ENVELOPE_1 + envelope_nr;
-  int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
-  int sound_opening = element_info[element].sound[ACTION_OPENING];
-  int sound_closing = element_info[element].sound[ACTION_CLOSING];
-  boolean ffwd_delay = (tape.playing && tape.fast_forward);
-  boolean no_delay = (tape.warp_forward);
-  int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
-  int wait_delay_value = (no_delay ? 0 : normal_delay_value);
-  int anim_mode = graphic_info[graphic].anim_mode;
-  int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
-			anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
+  setRequestPositionExt(x, y, request.width, request.height, add_border_size);
+}
 
-  game.envelope_active = TRUE;	/* needed for RedrawPlayfield() events */
+void DrawEnvelopeRequest(char *text)
+{
+  char *text_final = text;
+  char *text_door_style = NULL;
+  int graphic = IMG_BACKGROUND_REQUEST;
+  Bitmap *src_bitmap = graphic_info[graphic].bitmap;
+  int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
+  int font_nr = FONT_REQUEST;
+  int font_width = getFontWidth(font_nr);
+  int font_height = getFontHeight(font_nr);
+  int border_size = request.border_size;
+  int line_spacing = request.line_spacing;
+  int line_height = font_height + line_spacing;
+  int max_text_width  = request.width  - 2 * border_size;
+  int max_text_height = request.height - 2 * border_size;
+  int line_length = max_text_width  / font_width;
+  int max_lines   = max_text_height / line_height;
+  int text_width = line_length * font_width;
+  int width = request.width;
+  int height = request.height;
+  int tile_size = MAX(request.step_offset, 1);
+  int x_steps = width  / tile_size;
+  int y_steps = height / tile_size;
+  int sx_offset = border_size;
+  int sy_offset = border_size;
+  int sx, sy;
+  int i, x, y;
+
+  if (request.centered)
+    sx_offset = (request.width - text_width) / 2;
+
+  if (request.wrap_single_words && !request.autowrap)
+  {
+    char *src_text_ptr, *dst_text_ptr;
+
+    text_door_style = checked_malloc(2 * strlen(text) + 1);
+
+    src_text_ptr = text;
+    dst_text_ptr = text_door_style;
+
+    while (*src_text_ptr)
+    {
+      if (*src_text_ptr == ' ' ||
+	  *src_text_ptr == '?' ||
+	  *src_text_ptr == '!')
+	*dst_text_ptr++ = '\n';
 
-  PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
+      if (*src_text_ptr != ' ')
+	*dst_text_ptr++ = *src_text_ptr;
 
-  if (anim_mode == ANIM_DEFAULT)
-    AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
+      src_text_ptr++;
+    }
 
-  AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
+    *dst_text_ptr = '\0';
 
-  if (tape.playing)
-    Delay(wait_delay_value);
-  else
-    WaitForEventToContinue();
+    text_final = text_door_style;
+  }
 
-  PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
+  setRequestPosition(&sx, &sy, FALSE);
 
-  if (anim_mode != ANIM_NONE)
-    AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
+  ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
 
-  if (anim_mode == ANIM_DEFAULT)
-    AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
+  for (y = 0; y < y_steps; y++)
+    for (x = 0; x < x_steps; x++)
+      DrawEnvelopeBackgroundTiles(graphic, sx, sy,
+				  x, y, x_steps, y_steps,
+				  tile_size, tile_size);
 
-  game.envelope_active = FALSE;
+  /* force DOOR font inside door area */
+  SetFontStatus(GAME_MODE_PSEUDO_DOOR);
 
-  SetDrawtoField(DRAW_BUFFERED);
+  DrawTextBuffer(sx + sx_offset, sy + sy_offset, text_final, font_nr,
+		 line_length, -1, max_lines, line_spacing, mask_mode,
+		 request.autowrap, request.centered, FALSE);
 
-  redraw_mask |= REDRAW_FIELD;
-  BackToFront();
+  ResetFontStatus();
+
+  for (i = 0; i < NUM_TOOL_BUTTONS; i++)
+    RedrawGadget(tool_gadget[i]);
+
+  // store readily prepared envelope request for later use when animating
+  BlitBitmap(backbuffer, bitmap_db_store_2, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+
+  if (text_door_style)
+    free(text_door_style);
 }
 
-void ShowEnvelopeDoor(char *text, int action)
+void AnimateEnvelopeRequest(int anim_mode, int action)
 {
-#if 1
-  int last_game_status = game_status;	/* save current game status */
-  // int last_draw_background_mask = gfx.draw_background_mask;
-  int envelope_nr = 0;
-#endif
-  int element = EL_ENVELOPE_1 + envelope_nr;
-  int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
-  int sound_opening = element_info[element].sound[ACTION_OPENING];
-  int sound_closing = element_info[element].sound[ACTION_CLOSING];
-#if 0
+  int graphic = IMG_BACKGROUND_REQUEST;
+  boolean draw_masked = graphic_info[graphic].draw_masked;
+  int delay_value_normal = request.step_delay;
+  int delay_value_fast = delay_value_normal / 2;
   boolean ffwd_delay = (tape.playing && tape.fast_forward);
   boolean no_delay = (tape.warp_forward);
-  int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
-  int wait_delay_value = (no_delay ? 0 : normal_delay_value);
-#endif
-  int anim_mode = graphic_info[graphic].anim_mode;
-  int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
-			anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
+  int delay_value = (ffwd_delay ? delay_value_fast : delay_value_normal);
+  int anim_delay_value = (no_delay ? 0 : delay_value + 500 * 0) / 2;
+  unsigned int anim_delay = 0;
+
+  int tile_size = MAX(request.step_offset, 1);
+  int max_xsize = request.width  / tile_size;
+  int max_ysize = request.height / tile_size;
+  int max_xsize_inner = max_xsize - 2;
+  int max_ysize_inner = max_ysize - 2;
+
+  int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize_inner : 0);
+  int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize_inner : 0);
+  int xend = max_xsize_inner;
+  int yend = (anim_mode != ANIM_DEFAULT ? max_ysize_inner : 0);
+  int xstep = (xstart < xend ? 1 : 0);
+  int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
+  int start = 0;
+  int end = MAX(xend - xstart, yend - ystart);
+  int i;
 
-#if 1
-  if (game_status == GAME_MODE_PLAYING)
+  if (setup.quick_doors)
   {
-    if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
-      BlitScreenToBitmap_EM(backbuffer);
-    else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
-      BlitScreenToBitmap_SP(backbuffer);
-    else
+    xstart = xend;
+    ystart = yend;
+    end = 0;
+  }
+
+  for (i = start; i <= end; i++)
+  {
+    int last_frame = end;	// last frame of this "for" loop
+    int x = xstart + i * xstep;
+    int y = ystart + i * ystep;
+    int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
+    int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
+    int xsize_size_left = (xsize - 1) * tile_size;
+    int ysize_size_top  = (ysize - 1) * tile_size;
+    int max_xsize_pos = (max_xsize - 1) * tile_size;
+    int max_ysize_pos = (max_ysize - 1) * tile_size;
+    int width  = xsize * tile_size;
+    int height = ysize * tile_size;
+    int src_x, src_y;
+    int dst_x, dst_y;
+    int xx, yy;
+
+    setRequestPosition(&src_x, &src_y, FALSE);
+    setRequestPositionExt(&dst_x, &dst_y, width, height, FALSE);
+
+    BlitBitmap(bitmap_db_store_1, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+
+    for (yy = 0; yy < 2; yy++)
     {
-      BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
+      for (xx = 0; xx < 2; xx++)
+      {
+	int src_xx = src_x + xx * max_xsize_pos;
+	int src_yy = src_y + yy * max_ysize_pos;
+	int dst_xx = dst_x + xx * xsize_size_left;
+	int dst_yy = dst_y + yy * ysize_size_top;
+	int xx_size = (xx ? tile_size : xsize_size_left);
+	int yy_size = (yy ? tile_size : ysize_size_top);
+
+	if (draw_masked)
+	  BlitBitmapMasked(bitmap_db_store_2, backbuffer,
+			   src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
+	else
+	  BlitBitmap(bitmap_db_store_2, backbuffer,
+		     src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
+      }
     }
+
+    redraw_mask |= REDRAW_FIELD;
+
+    BackToFront();
+
+    SkipUntilDelayReached(&anim_delay, anim_delay_value, &i, last_frame);
   }
+}
+
+void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
+{
+  int graphic = IMG_BACKGROUND_REQUEST;
+  int sound_opening = SND_REQUEST_OPENING;
+  int sound_closing = SND_REQUEST_CLOSING;
+  int anim_mode_1 = request.anim_mode;			/* (higher priority) */
+  int anim_mode_2 = graphic_info[graphic].anim_mode;	/* (lower priority) */
+  int anim_mode = (anim_mode_1 != ANIM_DEFAULT ? anim_mode_1 : anim_mode_2);
+  int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
+			anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
+
+  if (game_status == GAME_MODE_PLAYING)
+    BlitScreenToBitmap(backbuffer);
 
-  SetDrawtoField(DRAW_BACKBUFFER);
+  SetDrawtoField(DRAW_TO_BACKBUFFER);
 
   // SetDrawBackgroundMask(REDRAW_NONE);
 
   if (action == ACTION_OPENING)
   {
-    BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+    BlitBitmap(backbuffer, bitmap_db_store_1, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
 
-    if (game_status != GAME_MODE_MAIN)
-      InitAnimation();
-  }
+    if (req_state & REQ_ASK)
+    {
+      MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
+      MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
+    }
+    else if (req_state & REQ_CONFIRM)
+    {
+      MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
+    }
+    else if (req_state & REQ_PLAYER)
+    {
+      MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
+      MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
+      MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
+      MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
+    }
 
-  /* force DOOR font inside door area */
-  game_status = GAME_MODE_PSEUDO_DOOR;
-#endif
+    DrawEnvelopeRequest(text);
+  }
 
   game.envelope_active = TRUE;	/* needed for RedrawPlayfield() events */
 
@@ -2392,65 +2880,36 @@ void ShowEnvelopeDoor(char *text, int action)
     PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
 
     if (anim_mode == ANIM_DEFAULT)
-      AnimateEnvelopeDoor(text, ANIM_DEFAULT, ACTION_OPENING);
+      AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_OPENING);
 
-    AnimateEnvelopeDoor(text, main_anim_mode, ACTION_OPENING);
-
-#if 0
-    if (tape.playing)
-      Delay(wait_delay_value);
-    else
-      WaitForEventToContinue();
-#endif
+    AnimateEnvelopeRequest(main_anim_mode, ACTION_OPENING);
   }
   else
   {
     PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
 
     if (anim_mode != ANIM_NONE)
-      AnimateEnvelopeDoor(text, main_anim_mode, ACTION_CLOSING);
+      AnimateEnvelopeRequest(main_anim_mode, ACTION_CLOSING);
 
     if (anim_mode == ANIM_DEFAULT)
-      AnimateEnvelopeDoor(text, ANIM_DEFAULT, ACTION_CLOSING);
+      AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_CLOSING);
   }
 
   game.envelope_active = FALSE;
 
-#if 1
-  game_status = last_game_status;	/* restore current game status */
-
   if (action == ACTION_CLOSING)
-  {
-    if (game_status != GAME_MODE_MAIN)
-      StopAnimation();
-
-    BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
-  }
-#else
-  SetDrawtoField(DRAW_BUFFERED);
-#endif
+    BlitBitmap(bitmap_db_store_1, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
 
   // SetDrawBackgroundMask(last_draw_background_mask);
 
-#if 1
-  redraw_mask = REDRAW_FIELD;
-  // redraw_mask |= REDRAW_ALL;
-#else
   redraw_mask |= REDRAW_FIELD;
-#endif
-
-#if 1
-  if (game_status == GAME_MODE_MAIN)
-    DoAnimation();
 
   BackToFront();
 
-  if (game_status == GAME_MODE_PLAYING &&
+  if (action == ACTION_CLOSING &&
+      game_status == GAME_MODE_PLAYING &&
       level.game_engine_type == GAME_ENGINE_TYPE_RND)
-    SetDrawtoField(DRAW_BUFFERED);
-#else
-  BackToFront();
-#endif
+    SetDrawtoField(DRAW_TO_FIELDBUFFER);
 }
 
 void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
@@ -2463,16 +2922,12 @@ void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
   BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x,dst_y);
 }
 
-void DrawLevel()
+void DrawLevel(int draw_background_mask)
 {
   int x,y;
 
-#if 1
   SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
-  SetDrawBackgroundMask(REDRAW_FIELD);
-#else
-  SetDrawBackgroundMask(REDRAW_NONE);
-#endif
+  SetDrawBackgroundMask(draw_background_mask);
 
   ClearField();
 
@@ -2483,6 +2938,18 @@ void DrawLevel()
   redraw_mask |= REDRAW_FIELD;
 }
 
+void DrawSizedLevel(int size_x, int size_y, int scroll_x, int scroll_y,
+		    int tilesize)
+{
+  int x,y;
+
+  for (x = 0; x < size_x; x++)
+    for (y = 0; y < size_y; y++)
+      DrawSizedElementOrWall(x, y, scroll_x, scroll_y, tilesize);
+
+  redraw_mask |= REDRAW_FIELD;
+}
+
 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
 {
   int x,y;
@@ -2494,7 +2961,7 @@ void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
   redraw_mask |= REDRAW_FIELD;
 }
 
-static void DrawPreviewLevelExt(int from_x, int from_y)
+static void DrawPreviewLevelPlayfieldExt(int from_x, int from_y)
 {
   boolean show_level_border = (BorderElement != EL_EMPTY);
   int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
@@ -2504,14 +2971,19 @@ static void DrawPreviewLevelExt(int from_x, int from_y)
   int preview_height = preview.ysize * tile_size;
   int real_preview_xsize = MIN(level_xsize, preview.xsize);
   int real_preview_ysize = MIN(level_ysize, preview.ysize);
+  int real_preview_width  = real_preview_xsize * tile_size;
+  int real_preview_height = real_preview_ysize * tile_size;
   int dst_x = SX + ALIGNED_XPOS(preview.x, preview_width, preview.align);
   int dst_y = SY + ALIGNED_YPOS(preview.y, preview_height, preview.valign);
   int x, y;
 
+  if (!IN_GFX_FIELD_FULL(dst_x, dst_y + preview_height - 1))
+    return;
+
   DrawBackground(dst_x, dst_y, preview_width, preview_height);
 
-  dst_x += (preview_width  - real_preview_xsize * tile_size) / 2;
-  dst_y += (preview_height - real_preview_ysize * tile_size) / 2;
+  dst_x += (preview_width  - real_preview_width)  / 2;
+  dst_y += (preview_height - real_preview_height) / 2;
 
   for (x = 0; x < real_preview_xsize; x++)
   {
@@ -2527,7 +2999,7 @@ static void DrawPreviewLevelExt(int from_x, int from_y)
     }
   }
 
-  redraw_mask |= REDRAW_MICROLEVEL;
+  redraw_mask |= REDRAW_FIELD;
 }
 
 #define MICROLABEL_EMPTY		0
@@ -2559,50 +3031,28 @@ static void DrawPreviewLevelLabelExt(int mode)
   struct TextPosInfo *pos = &menu.main.text.level_info_2;
   char label_text[MAX_OUTPUT_LINESIZE + 1];
   int max_len_label_text;
-#if 1
   int font_nr = pos->font;
   int i;
 
-  if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
-      mode == MICROLABEL_IMPORTED_FROM_HEAD ||
-      mode == MICROLABEL_IMPORTED_BY_HEAD)
-    font_nr = pos->font_alt;
-#else
-  int font_nr = FONT_TEXT_2;
-  int i;
+  if (!IN_GFX_FIELD_FULL(pos->x, pos->y + getFontHeight(pos->font)))
+    return;
 
   if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
       mode == MICROLABEL_IMPORTED_FROM_HEAD ||
       mode == MICROLABEL_IMPORTED_BY_HEAD)
-    font_nr = FONT_TEXT_3;
-#endif
+    font_nr = pos->font_alt;
 
-#if 1
   max_len_label_text = getMaxTextLength(pos, font_nr);
-#else
-  max_len_label_text = SXSIZE / getFontWidth(font_nr);
-#endif
 
-#if 1
   if (pos->size != -1)
     max_len_label_text = pos->size;
-#endif
 
   for (i = 0; i < max_len_label_text; i++)
     label_text[i] = ' ';
   label_text[max_len_label_text] = '\0';
 
   if (strlen(label_text) > 0)
-  {
-#if 1
     DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
-#else
-    int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
-    int lypos = MICROLABEL2_YPOS;
-
-    DrawText(lxpos, lypos, label_text, font_nr);
-#endif
-  }
 
   strncpy(label_text,
 	  (mode == MICROLABEL_LEVEL_NAME ? level.name :
@@ -2616,36 +3066,21 @@ static void DrawPreviewLevelLabelExt(int mode)
   label_text[max_len_label_text] = '\0';
 
   if (strlen(label_text) > 0)
-  {
-#if 1
     DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
-#else
-    int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
-    int lypos = MICROLABEL2_YPOS;
 
-    DrawText(lxpos, lypos, label_text, font_nr);
-#endif
-  }
-
-  redraw_mask |= REDRAW_MICROLEVEL;
+  redraw_mask |= REDRAW_FIELD;
 }
 
-void DrawPreviewLevel(boolean restart)
+static void DrawPreviewLevelExt(boolean restart)
 {
-  static unsigned long scroll_delay = 0;
-  static unsigned long label_delay = 0;
+  static unsigned int scroll_delay = 0;
+  static unsigned int label_delay = 0;
   static int from_x, from_y, scroll_direction;
   static int label_state, label_counter;
-  unsigned long scroll_delay_value = preview.step_delay;
+  unsigned int scroll_delay_value = preview.step_delay;
   boolean show_level_border = (BorderElement != EL_EMPTY);
   int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
   int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
-  int last_game_status = game_status;		/* save current game status */
-
-#if 0
-  /* force PREVIEW font on preview level */
-  game_status = GAME_MODE_PSEUDO_PREVIEW;
-#endif
 
   if (restart)
   {
@@ -2667,7 +3102,7 @@ void DrawPreviewLevel(boolean restart)
     label_state = 1;
     label_counter = 0;
 
-    DrawPreviewLevelExt(from_x, from_y);
+    DrawPreviewLevelPlayfieldExt(from_x, from_y);
     DrawPreviewLevelLabelExt(label_state);
 
     /* initialize delay counters */
@@ -2678,41 +3113,19 @@ void DrawPreviewLevel(boolean restart)
     {
       struct TextPosInfo *pos = &menu.main.text.level_info_1;
       char label_text[MAX_OUTPUT_LINESIZE + 1];
-#if 1
       int font_nr = pos->font;
-#else
-      int font_nr = FONT_TEXT_1;
-#endif
-#if 1
       int max_len_label_text = getMaxTextLength(pos, font_nr);
-#else
-      int max_len_label_text = SXSIZE / getFontWidth(font_nr);
-#endif
-#if 0
-      int text_width;
-      int lxpos, lypos;
-#endif
 
-#if 1
       if (pos->size != -1)
 	max_len_label_text = pos->size;
-#endif
 
       strncpy(label_text, leveldir_current->name, max_len_label_text);
       label_text[max_len_label_text] = '\0';
 
-#if 1
-      DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
-#else
-      lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
-      lypos = SY + MICROLABEL1_YPOS;
-
-      DrawText(lxpos, lypos, label_text, font_nr);
-#endif
+      if (IN_GFX_FIELD_FULL(pos->x, pos->y + getFontHeight(pos->font)))
+	DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
     }
 
-    game_status = last_game_status;	/* restore current game status */
-
     return;
   }
 
@@ -2769,7 +3182,7 @@ void DrawPreviewLevel(boolean restart)
 	break;
     }
 
-    DrawPreviewLevelExt(from_x, from_y);
+    DrawPreviewLevelPlayfieldExt(from_x, from_y);
   }
 
   /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
@@ -2812,12 +3225,21 @@ void DrawPreviewLevel(boolean restart)
 
     DrawPreviewLevelLabelExt(label_state);
   }
+}
+
+void DrawPreviewLevelInitial()
+{
+  DrawPreviewLevelExt(TRUE);
+}
 
-  game_status = last_game_status;	/* restore current game status */
+void DrawPreviewLevelAnimation()
+{
+  DrawPreviewLevelExt(FALSE);
 }
 
-inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
-				    int graphic, int sync_frame, int mask_mode)
+inline static void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
+					   int graphic, int sync_frame,
+					   int mask_mode)
 {
   int frame = getGraphicAnimationFrame(graphic, sync_frame);
 
@@ -2827,7 +3249,31 @@ inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
     DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
 }
 
-inline void DrawGraphicAnimation(int x, int y, int graphic)
+void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
+				  int graphic, int sync_frame, int mask_mode)
+{
+  int frame = getGraphicAnimationFrame(graphic, sync_frame);
+
+  if (mask_mode == USE_MASKING)
+    DrawFixedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
+  else
+    DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
+}
+
+inline static void DrawGraphicAnimation(int x, int y, int graphic)
+{
+  int lx = LEVELX(x), ly = LEVELY(y);
+
+  if (!IN_SCR_FIELD(x, y))
+    return;
+
+  DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
+			  graphic, GfxFrame[lx][ly], NO_MASKING);
+
+  MarkTileDirty(x, y);
+}
+
+void DrawFixedGraphicAnimation(int x, int y, int graphic)
 {
   int lx = LEVELX(x), ly = LEVELY(y);
 
@@ -2851,7 +3297,7 @@ void DrawLevelElementAnimation(int x, int y, int element)
   DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
 }
 
-inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
+void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
 {
   int sx = SCREENX(x), sy = SCREENY(y);
 
@@ -3072,15 +3518,10 @@ void DrawPlayer(struct PlayerInfo *player)
       GfxElement[jx][jy] = EL_UNDEFINED;
 
       /* make sure that pushed elements are drawn with correct frame rate */
-#if 1
       graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
 
       if (player->is_pushing && player->is_moving && !IS_ANIM_MODE_CE(graphic))
 	GfxFrame[jx][jy] = player->StepFrame;
-#else
-      if (player->is_pushing && player->is_moving)
-	GfxFrame[jx][jy] = player->StepFrame;
-#endif
 
       DrawLevelField(jx, jy);
     }
@@ -3108,9 +3549,6 @@ void DrawPlayer(struct PlayerInfo *player)
       syy = player->GfxPos;
   }
 
-  if (!setup.soft_scrolling && ScreenMovPos)
-    sxx = syy = 0;
-
   if (player_is_opaque)
     DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
   else
@@ -3140,13 +3578,6 @@ void DrawPlayer(struct PlayerInfo *player)
   /* draw things the player is pushing, if needed                            */
   /* ----------------------------------------------------------------------- */
 
-#if 0
-  printf("::: %d, %d [%d, %d] [%d]\n",
-	 player->is_pushing, player_is_moving, player->GfxAction,
-	 player->is_moving, player_is_moving);
-#endif
-
-#if 1
   if (player->is_pushing && player->is_moving)
   {
     int px = SCREENX(jx), py = SCREENY(jy);
@@ -3166,15 +3597,10 @@ void DrawPlayer(struct PlayerInfo *player)
 
     graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
 
-#if 1
     sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
     frame = getGraphicAnimationFrame(graphic, sync_frame);
-#else
-    frame = getGraphicAnimationFrame(graphic, player->StepFrame);
-#endif
 
     /* draw background element under pushed element (like the Sokoban field) */
-#if 1
     if (game.use_masked_pushing && IS_MOVING(jx, jy))
     {
       /* this allows transparent pushing animation over non-black background */
@@ -3191,20 +3617,6 @@ void DrawPlayer(struct PlayerInfo *player)
     }
     else if (Back[next_jx][next_jy])
       DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
-#else
-    if (Back[next_jx][next_jy])
-      DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
-#endif
-
-#if 0
-    printf("::: %d, %d, %d, %d [%d] [%d, %d, %d] [%d] [%d, %d] [%d, %d]\n",
-	   jx, px, player->GfxPos, player->StepFrame,
-	   player->is_pushing,
-	   dx, sxx, pxx,
-	   IS_MOVING(jx, jy),
-	   graphic, frame,
-	   GfxFrame[jx][jy], GfxFrame[next_jx][next_jy]);
-#endif
 
 #if 1
     /* do not draw (EM style) pushing animation when pushing is finished */
@@ -3219,7 +3631,6 @@ void DrawPlayer(struct PlayerInfo *player)
     DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
 #endif
   }
-#endif
 
 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
   /* ----------------------------------------------------------------------- */
@@ -3243,9 +3654,6 @@ void DrawPlayer(struct PlayerInfo *player)
       syy = player->GfxPos;
   }
 
-  if (!setup.soft_scrolling && ScreenMovPos)
-    sxx = syy = 0;
-
   if (player_is_opaque)
     DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
   else
@@ -3327,9 +3735,7 @@ void WaitForEventToContinue()
 
   button_status = MB_RELEASED;
 
-#if 1
   ClearEventQueue();
-#endif
 
   while (still_wait)
   {
@@ -3360,10 +3766,7 @@ void WaitForEventToContinue()
       still_wait = FALSE;
     }
 
-    DoAnimation();
-
-    /* don't eat all CPU time */
-    Delay(10);
+    BackToFront();
   }
 }
 
@@ -3371,52 +3774,196 @@ void WaitForEventToContinue()
 #define MAX_REQUEST_LINE_FONT1_LEN	7
 #define MAX_REQUEST_LINE_FONT2_LEN	10
 
-boolean Request(char *text, unsigned int req_state)
+static int RequestHandleEvents(unsigned int req_state)
+{
+  boolean level_solved = (game_status == GAME_MODE_PLAYING &&
+			  local_player->LevelSolved_GameEnd);
+  int width  = request.width;
+  int height = request.height;
+  int sx, sy;
+  int result;
+
+  setRequestPosition(&sx, &sy, FALSE);
+
+  button_status = MB_RELEASED;
+
+  request_gadget_id = -1;
+  result = -1;
+
+  while (result < 0)
+  {
+    if (level_solved)
+    {
+      SetDrawtoField(DRAW_TO_FIELDBUFFER);
+
+      HandleGameActions();
+
+      SetDrawtoField(DRAW_TO_BACKBUFFER);
+
+      if (global.use_envelope_request)
+      {
+	/* copy current state of request area to middle of playfield area */
+	BlitBitmap(bitmap_db_store_2, drawto, sx, sy, width, height, sx, sy);
+      }
+    }
+
+    if (PendingEvent())
+    {
+      Event event;
+
+      while (NextValidEvent(&event))
+      {
+	switch (event.type)
+	{
+	  case EVENT_BUTTONPRESS:
+	  case EVENT_BUTTONRELEASE:
+	  case EVENT_MOTIONNOTIFY:
+	  {
+	    int mx, my;
+
+	    if (event.type == EVENT_MOTIONNOTIFY)
+	    {
+	      if (!button_status)
+		continue;
+
+	      motion_status = TRUE;
+	      mx = ((MotionEvent *) &event)->x;
+	      my = ((MotionEvent *) &event)->y;
+	    }
+	    else
+	    {
+	      motion_status = FALSE;
+	      mx = ((ButtonEvent *) &event)->x;
+	      my = ((ButtonEvent *) &event)->y;
+	      if (event.type == EVENT_BUTTONPRESS)
+		button_status = ((ButtonEvent *) &event)->button;
+	      else
+		button_status = MB_RELEASED;
+	    }
+
+	    /* this sets 'request_gadget_id' */
+	    HandleGadgets(mx, my, button_status);
+
+	    switch (request_gadget_id)
+	    {
+	      case TOOL_CTRL_ID_YES:
+		result = TRUE;
+		break;
+	      case TOOL_CTRL_ID_NO:
+		result = FALSE;
+		break;
+	      case TOOL_CTRL_ID_CONFIRM:
+		result = TRUE | FALSE;
+		break;
+
+	      case TOOL_CTRL_ID_PLAYER_1:
+		result = 1;
+		break;
+	      case TOOL_CTRL_ID_PLAYER_2:
+		result = 2;
+		break;
+	      case TOOL_CTRL_ID_PLAYER_3:
+		result = 3;
+		break;
+	      case TOOL_CTRL_ID_PLAYER_4:
+		result = 4;
+		break;
+
+	      default:
+		break;
+	    }
+
+	    break;
+	  }
+
+	  case EVENT_KEYPRESS:
+	  {
+	    Key key = GetEventKey((KeyEvent *)&event, TRUE);
+
+	    switch (key)
+	    {
+	      case KSYM_space:
+		if (req_state & REQ_CONFIRM)
+		  result = 1;
+		break;
+
+	      case KSYM_Return:
+#if defined(TARGET_SDL2)
+	      case KSYM_Menu:
+#endif
+		result = 1;
+		break;
+
+	      case KSYM_Escape:
+#if defined(TARGET_SDL2)
+	      case KSYM_Back:
+#endif
+		result = 0;
+		break;
+
+	      default:
+		HandleKeysDebug(key);
+		break;
+	    }
+
+	    if (req_state & REQ_PLAYER)
+	      result = 0;
+
+	    break;
+	  }
+
+	  case EVENT_KEYRELEASE:
+	    ClearPlayerAction();
+	    break;
+
+	  default:
+	    HandleOtherEvents(&event);
+	    break;
+	}
+      }
+    }
+    else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
+    {
+      int joy = AnyJoystick();
+
+      if (joy & JOY_BUTTON_1)
+	result = 1;
+      else if (joy & JOY_BUTTON_2)
+	result = 0;
+    }
+
+    if (level_solved)
+    {
+      if (global.use_envelope_request)
+      {
+	/* copy back current state of pressed buttons inside request area */
+	BlitBitmap(drawto, bitmap_db_store_2, sx, sy, width, height, sx, sy);
+      }
+    }
+
+    BackToFront();
+  }
+
+  return result;
+}
+
+static boolean RequestDoor(char *text, unsigned int req_state)
 {
-  int mx, my, ty, result = -1;
   unsigned int old_door_state;
-  int last_game_status = game_status;	/* save current game status */
   int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
   int font_nr = FONT_TEXT_2;
-  boolean use_envelope_request = TRUE  * 0;
-#if 0
-  int max_word_len = 0;
-#endif
   char *text_ptr;
-  int i;
+  int result;
+  int ty;
 
-#if 1
   if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
   {
     max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
     font_nr = FONT_TEXT_1;
   }
-#else
-  for (text_ptr = text; *text_ptr; text_ptr++)
-  {
-    max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
-
-    if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
-    {
-      max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
-#if 1
-      font_nr = FONT_TEXT_1;
-#else
-      font_nr = FONT_LEVEL_NUMBER;
-#endif
-
-      break;
-    }
-  }
-#endif
 
   if (game_status == GAME_MODE_PLAYING)
-  {
-    if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
-      BlitScreenToBitmap_EM(backbuffer);
-    else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
-      BlitScreenToBitmap_SP(backbuffer);
-  }
+    BlitScreenToBitmap(backbuffer);
 
   /* disable deactivated drawing when quick-loading level tape recording */
   if (tape.playing && tape.deactivate_display)
@@ -3440,31 +3987,26 @@ boolean Request(char *text, unsigned int req_state)
 
   UnmapAllGadgets();
 
-#if 1
-  if (old_door_state & DOOR_OPEN_1 && !use_envelope_request)
-#else
+  /* draw released gadget before proceeding */
+  // BackToFront();
+
   if (old_door_state & DOOR_OPEN_1)
-#endif
   {
     CloseDoor(DOOR_CLOSE_1);
 
     /* save old door content */
-    BlitBitmap(bitmap_db_door, bitmap_db_door,
-	       DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
-	       DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
+    BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
+	       0 * DXSIZE, 0, DXSIZE, DYSIZE, 1 * DXSIZE, 0);
   }
 
-#if 1
   SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
-#endif
-
   SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
 
   /* clear door drawing field */
   DrawBackground(DX, DY, DXSIZE, DYSIZE);
 
   /* force DOOR font inside door area */
-  game_status = GAME_MODE_PSEUDO_DOOR;
+  SetFontStatus(GAME_MODE_PSEUDO_DOOR);
 
   /* write text for request */
   for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
@@ -3478,10 +4020,14 @@ boolean Request(char *text, unsigned int req_state)
     for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
     {
       tc = *(text_ptr + tx);
-      if (!tc || tc == ' ')
+      // if (!tc || tc == ' ')
+      if (!tc || tc == ' ' || tc == '?' || tc == '!')
 	break;
     }
 
+    if ((tc == '?' || tc == '!') && tl == 0)
+      tl = 1;
+
     if (!tl)
     { 
       text_ptr++; 
@@ -3497,18 +4043,10 @@ boolean Request(char *text, unsigned int req_state)
 	     text_line, font_nr);
 
     text_ptr += tl + (tc == ' ' ? 1 : 0);
+    // text_ptr += tl + (tc == ' ' || tc == '?' || tc == '!' ? 1 : 0);
   }
 
-  game_status = last_game_status;	/* restore current game status */
-
-#if 1
-  if (use_envelope_request)
-  {
-    /* !!! TMP !!! */
-    FreeToolButtons();
-    CreateToolButtons();
-  }
-#endif
+  ResetFontStatus();
 
   if (req_state & REQ_ASK)
   {
@@ -3528,40 +4066,9 @@ boolean Request(char *text, unsigned int req_state)
   }
 
   /* copy request gadgets to door backbuffer */
-  BlitBitmap(drawto, bitmap_db_door,
-	     DX, DY, DXSIZE, DYSIZE,
-	     DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
-
-#if 1
-  if (use_envelope_request)
-  {
-    ShowEnvelopeDoor(text, ACTION_OPENING);
-
-    for (i = 0; i < NUM_TOOL_BUTTONS; i++)
-    {
-      if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
-				   i == TOOL_CTRL_ID_NO)) ||
-	  (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
-	  (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
-				      i == TOOL_CTRL_ID_PLAYER_2 &&
-				      i == TOOL_CTRL_ID_PLAYER_3 &&
-				      i == TOOL_CTRL_ID_PLAYER_4)))
-      {
-	int x = tool_gadget[i]->x + dDX;
-	int y = tool_gadget[i]->y + dDY;
+  BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0);
 
-	ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
-      }
-    }
-  }
-#endif
-
-#if 1
-  if (!use_envelope_request)
-    OpenDoor(DOOR_OPEN_1);
-#else
   OpenDoor(DOOR_OPEN_1);
-#endif
 
   if (!(req_state & REQUEST_WAIT_FOR_INPUT))
   {
@@ -3578,188 +4085,108 @@ boolean Request(char *text, unsigned int req_state)
     return FALSE;
   }
 
-#if 1
-  if (game_status != GAME_MODE_MAIN && !use_envelope_request)
-    InitAnimation();
-#else
-  if (game_status != GAME_MODE_MAIN)
-    InitAnimation();
-#endif
-
-  button_status = MB_RELEASED;
-
-  request_gadget_id = -1;
-
   SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
 
-  while (result < 0)
-  {
-    if (PendingEvent())
-    {
-      Event event;
+  // ---------- handle request buttons ----------
+  result = RequestHandleEvents(req_state);
 
-      NextEvent(&event);
+  UnmapToolButtons();
 
-      switch (event.type)
-      {
-	case EVENT_BUTTONPRESS:
-	case EVENT_BUTTONRELEASE:
-	case EVENT_MOTIONNOTIFY:
-	{
-	  if (event.type == EVENT_MOTIONNOTIFY)
-	  {
-	    if (!PointerInWindow(window))
-	      continue;	/* window and pointer are on different screens */
+  if (!(req_state & REQ_STAY_OPEN))
+  {
+    CloseDoor(DOOR_CLOSE_1);
 
-	    if (!button_status)
-	      continue;
+    if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
+	(req_state & REQ_REOPEN))
+      OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
+  }
 
-	    motion_status = TRUE;
-	    mx = ((MotionEvent *) &event)->x;
-	    my = ((MotionEvent *) &event)->y;
-	  }
-	  else
-	  {
-	    motion_status = FALSE;
-	    mx = ((ButtonEvent *) &event)->x;
-	    my = ((ButtonEvent *) &event)->y;
-	    if (event.type == EVENT_BUTTONPRESS)
-	      button_status = ((ButtonEvent *) &event)->button;
-	    else
-	      button_status = MB_RELEASED;
-	  }
+  RemapAllGadgets();
 
-	  /* this sets 'request_gadget_id' */
-	  HandleGadgets(mx, my, button_status);
+  if (game_status == GAME_MODE_PLAYING)
+  {
+    SetPanelBackground();
+    SetDrawBackgroundMask(REDRAW_DOOR_1);
+  }
+  else
+  {
+    SetDrawBackgroundMask(REDRAW_FIELD);
+  }
 
-	  switch (request_gadget_id)
-	  {
-	    case TOOL_CTRL_ID_YES:
-	      result = TRUE;
-	      break;
-	    case TOOL_CTRL_ID_NO:
-	      result = FALSE;
-	      break;
-	    case TOOL_CTRL_ID_CONFIRM:
-	      result = TRUE | FALSE;
-	      break;
-
-	    case TOOL_CTRL_ID_PLAYER_1:
-	      result = 1;
-	      break;
-	    case TOOL_CTRL_ID_PLAYER_2:
-	      result = 2;
-	      break;
-	    case TOOL_CTRL_ID_PLAYER_3:
-	      result = 3;
-	      break;
-	    case TOOL_CTRL_ID_PLAYER_4:
-	      result = 4;
-	      break;
-
-	    default:
-	      break;
-	  }
+#if defined(NETWORK_AVALIABLE)
+  /* continue network game after request */
+  if (options.network &&
+      game_status == GAME_MODE_PLAYING &&
+      req_state & REQUEST_WAIT_FOR_INPUT)
+    SendToServer_ContinuePlaying();
+#endif
 
-	  break;
-	}
+  /* restore deactivated drawing when quick-loading level tape recording */
+  if (tape.playing && tape.deactivate_display)
+    TapeDeactivateDisplayOn();
 
-	case EVENT_KEYPRESS:
-	  switch (GetEventKey((KeyEvent *)&event, TRUE))
-	  {
-	    case KSYM_space:
-	      if (req_state & REQ_CONFIRM)
-		result = 1;
-	      break;
+  return result;
+}
 
-	    case KSYM_Return:
-	      result = 1;
-	      break;
+static boolean RequestEnvelope(char *text, unsigned int req_state)
+{
+  int result;
 
-	    case KSYM_Escape:
-	      result = 0;
-	      break;
+  if (game_status == GAME_MODE_PLAYING)
+    BlitScreenToBitmap(backbuffer);
 
-	    default:
-	      break;
-	  }
+  /* disable deactivated drawing when quick-loading level tape recording */
+  if (tape.playing && tape.deactivate_display)
+    TapeDeactivateDisplayOff(TRUE);
 
-	  if (req_state & REQ_PLAYER)
-	    result = 0;
-	  break;
+  SetMouseCursor(CURSOR_DEFAULT);
 
-	case EVENT_KEYRELEASE:
-	  ClearPlayerAction();
-	  break;
+#if defined(NETWORK_AVALIABLE)
+  /* pause network game while waiting for request to answer */
+  if (options.network &&
+      game_status == GAME_MODE_PLAYING &&
+      req_state & REQUEST_WAIT_FOR_INPUT)
+    SendToServer_PausePlaying();
+#endif
 
-	default:
-	  HandleOtherEvents(&event);
-	  break;
-      }
-    }
-    else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
-    {
-      int joy = AnyJoystick();
+  /* simulate releasing mouse button over last gadget, if still pressed */
+  if (button_status)
+    HandleGadgets(-1, -1, 0);
 
-      if (joy & JOY_BUTTON_1)
-	result = 1;
-      else if (joy & JOY_BUTTON_2)
-	result = 0;
-    }
+  UnmapAllGadgets();
 
-#if 1
+  // (replace with setting corresponding request background)
+  // SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
+  // SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
+
+  /* clear door drawing field */
+  // DrawBackground(DX, DY, DXSIZE, DYSIZE);
 
-    if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
+  ShowEnvelopeRequest(text, req_state, ACTION_OPENING);
+
+  if (!(req_state & REQUEST_WAIT_FOR_INPUT))
+  {
+    if (game_status == GAME_MODE_PLAYING)
     {
-      HandleGameActions();
+      SetPanelBackground();
+      SetDrawBackgroundMask(REDRAW_DOOR_1);
     }
     else
     {
-      DoAnimation();
-
-      if (!PendingEvent())	/* delay only if no pending events */
-	Delay(10);
+      SetDrawBackgroundMask(REDRAW_FIELD);
     }
 
-    BackToFront();
-
-#else
-
-    DoAnimation();
-
-#if 1
-    if (!PendingEvent())	/* delay only if no pending events */
-      Delay(10);
-#else
-    /* don't eat all CPU time */
-    Delay(10);
-#endif
-
-#endif
+    return FALSE;
   }
 
-  if (game_status != GAME_MODE_MAIN)
-    StopAnimation();
-
-  UnmapToolButtons();
+  SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
 
-#if 1
-  if (use_envelope_request)
-    ShowEnvelopeDoor(text, ACTION_CLOSING);
-#endif
+  // ---------- handle request buttons ----------
+  result = RequestHandleEvents(req_state);
 
-#if 1
-  if (!(req_state & REQ_STAY_OPEN) && !use_envelope_request)
-#else
-  if (!(req_state & REQ_STAY_OPEN))
-#endif
-  {
-    CloseDoor(DOOR_CLOSE_1);
+  UnmapToolButtons();
 
-    if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
-	(req_state & REQ_REOPEN))
-      OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
-  }
+  ShowEnvelopeRequest(text, req_state, ACTION_CLOSING);
 
   RemapAllGadgets();
 
@@ -3788,19 +4215,232 @@ boolean Request(char *text, unsigned int req_state)
   return result;
 }
 
+boolean Request(char *text, unsigned int req_state)
+{
+  boolean overlay_active = GetOverlayActive();
+  boolean result;
+
+  SetOverlayActive(FALSE);
+
+  if (global.use_envelope_request)
+    result = RequestEnvelope(text, req_state);
+  else
+    result = RequestDoor(text, req_state);
+
+  SetOverlayActive(overlay_active);
+
+  return result;
+}
+
+static int compareDoorPartOrderInfo(const void *object1, const void *object2)
+{
+  const struct DoorPartOrderInfo *dpo1 = (struct DoorPartOrderInfo *)object1;
+  const struct DoorPartOrderInfo *dpo2 = (struct DoorPartOrderInfo *)object2;
+  int compare_result;
+
+  if (dpo1->sort_priority != dpo2->sort_priority)
+    compare_result = dpo1->sort_priority - dpo2->sort_priority;
+  else
+    compare_result = dpo1->nr - dpo2->nr;
+
+  return compare_result;
+}
+
+void InitGraphicCompatibilityInfo_Doors()
+{
+  struct
+  {
+    int door_token;
+    int part_1, part_8;
+    struct DoorInfo *door;
+  }
+  doors[] =
+  {
+    { DOOR_1,	IMG_GFX_DOOR_1_PART_1,	IMG_GFX_DOOR_1_PART_8,	&door_1	},
+    { DOOR_2,	IMG_GFX_DOOR_2_PART_1,	IMG_GFX_DOOR_2_PART_8,	&door_2	},
+
+    { -1,	-1,			-1,			NULL	}
+  };
+  struct Rect door_rect_list[] =
+  {
+    { DX, DY, DXSIZE, DYSIZE },
+    { VX, VY, VXSIZE, VYSIZE }
+  };
+  int i, j;
+
+  for (i = 0; doors[i].door_token != -1; i++)
+  {
+    int door_token = doors[i].door_token;
+    int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
+    int part_1 = doors[i].part_1;
+    int part_8 = doors[i].part_8;
+    int part_2 = part_1 + 1;
+    int part_3 = part_1 + 2;
+    struct DoorInfo *door = doors[i].door;
+    struct Rect *door_rect = &door_rect_list[door_index];
+    boolean door_gfx_redefined = FALSE;
+
+    /* check if any door part graphic definitions have been redefined */
+
+    for (j = 0; door_part_controls[j].door_token != -1; j++)
+    {
+      struct DoorPartControlInfo *dpc = &door_part_controls[j];
+      struct FileInfo *fi = getImageListEntryFromImageID(dpc->graphic);
+
+      if (dpc->door_token == door_token && fi->redefined)
+	door_gfx_redefined = TRUE;
+    }
+
+    /* check for old-style door graphic/animation modifications */
+
+    if (!door_gfx_redefined)
+    {
+      if (door->anim_mode & ANIM_STATIC_PANEL)
+      {
+	door->panel.step_xoffset = 0;
+	door->panel.step_yoffset = 0;
+      }
+
+      if (door->anim_mode & (ANIM_HORIZONTAL | ANIM_VERTICAL))
+      {
+	struct GraphicInfo *g_part_1 = &graphic_info[part_1];
+	struct GraphicInfo *g_part_2 = &graphic_info[part_2];
+	int num_door_steps, num_panel_steps;
+
+	/* remove door part graphics other than the two default wings */
+
+	for (j = 0; door_part_controls[j].door_token != -1; j++)
+	{
+	  struct DoorPartControlInfo *dpc = &door_part_controls[j];
+	  struct GraphicInfo *g = &graphic_info[dpc->graphic];
+
+	  if (dpc->graphic >= part_3 &&
+	      dpc->graphic <= part_8)
+	    g->bitmap = NULL;
+	}
+
+	/* set graphics and screen positions of the default wings */
+
+	g_part_1->width  = door_rect->width;
+	g_part_1->height = door_rect->height;
+	g_part_2->width  = door_rect->width;
+	g_part_2->height = door_rect->height;
+	g_part_2->src_x = door_rect->width;
+	g_part_2->src_y = g_part_1->src_y;
+
+	door->part_2.x = door->part_1.x;
+	door->part_2.y = door->part_1.y;
+
+	if (door->width != -1)
+	{
+	  g_part_1->width = door->width;
+	  g_part_2->width = door->width;
+
+	  // special treatment for graphics and screen position of right wing
+	  g_part_2->src_x += door_rect->width - door->width;
+	  door->part_2.x  += door_rect->width - door->width;
+	}
+
+	if (door->height != -1)
+	{
+	  g_part_1->height = door->height;
+	  g_part_2->height = door->height;
+
+	  // special treatment for graphics and screen position of bottom wing
+	  g_part_2->src_y += door_rect->height - door->height;
+	  door->part_2.y  += door_rect->height - door->height;
+	}
+
+	/* set animation delays for the default wings and panels */
+
+	door->part_1.step_delay = door->step_delay;
+	door->part_2.step_delay = door->step_delay;
+	door->panel.step_delay  = door->step_delay;
+
+	/* set animation draw order for the default wings */
+
+	door->part_1.sort_priority = 2;	/* draw left wing over ... */
+	door->part_2.sort_priority = 1;	/*          ... right wing */
+
+	/* set animation draw offset for the default wings */
+
+	if (door->anim_mode & ANIM_HORIZONTAL)
+	{
+	  door->part_1.step_xoffset = door->step_offset;
+	  door->part_1.step_yoffset = 0;
+	  door->part_2.step_xoffset = door->step_offset * -1;
+	  door->part_2.step_yoffset = 0;
+
+	  num_door_steps = g_part_1->width / door->step_offset;
+	}
+	else	// ANIM_VERTICAL
+	{
+	  door->part_1.step_xoffset = 0;
+	  door->part_1.step_yoffset = door->step_offset;
+	  door->part_2.step_xoffset = 0;
+	  door->part_2.step_yoffset = door->step_offset * -1;
+
+	  num_door_steps = g_part_1->height / door->step_offset;
+	}
+
+	/* set animation draw offset for the default panels */
+
+	if (door->step_offset > 1)
+	{
+	  num_panel_steps = 2 * door_rect->height / door->step_offset;
+	  door->panel.start_step = num_panel_steps - num_door_steps;
+	  door->panel.start_step_closing = door->panel.start_step;
+	}
+	else
+	{
+	  num_panel_steps = door_rect->height / door->step_offset;
+	  door->panel.start_step = num_panel_steps - num_door_steps / 2;
+	  door->panel.start_step_closing = door->panel.start_step;
+	  door->panel.step_delay *= 2;
+	}
+      }
+    }
+  }
+}
+
+void InitDoors()
+{
+  int i;
+
+  for (i = 0; door_part_controls[i].door_token != -1; i++)
+  {
+    struct DoorPartControlInfo *dpc = &door_part_controls[i];
+    struct DoorPartOrderInfo *dpo = &door_part_order[i];
+
+    /* initialize "start_step_opening" and "start_step_closing", if needed */
+    if (dpc->pos->start_step_opening == 0 &&
+	dpc->pos->start_step_closing == 0)
+    {
+      // dpc->pos->start_step_opening = dpc->pos->start_step;
+      dpc->pos->start_step_closing = dpc->pos->start_step;
+    }
+
+    /* fill structure for door part draw order (sorted below) */
+    dpo->nr = i;
+    dpo->sort_priority = dpc->pos->sort_priority;
+  }
+
+  /* sort door part controls according to sort_priority and graphic number */
+  qsort(door_part_order, MAX_DOOR_PARTS,
+        sizeof(struct DoorPartOrderInfo), compareDoorPartOrderInfo);
+}
+
 unsigned int OpenDoor(unsigned int door_state)
 {
   if (door_state & DOOR_COPY_BACK)
   {
     if (door_state & DOOR_OPEN_1)
-      BlitBitmap(bitmap_db_door, bitmap_db_door,
-		 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
-		 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+      BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
+		 1 * DXSIZE, 0, DXSIZE, DYSIZE, 0 * DXSIZE, 0);
 
     if (door_state & DOOR_OPEN_2)
-      BlitBitmap(bitmap_db_door, bitmap_db_door,
-		 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
-		 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
+      BlitBitmap(bitmap_db_door_2, bitmap_db_door_2,
+		 1 * VXSIZE, 0, VXSIZE, VYSIZE, 0 * VXSIZE, 0);
 
     door_state &= ~DOOR_COPY_BACK;
   }
@@ -3815,12 +4455,12 @@ unsigned int CloseDoor(unsigned int door_state)
   if (!(door_state & DOOR_NO_COPY_BACK))
   {
     if (old_door_state & DOOR_OPEN_1)
-      BlitBitmap(backbuffer, bitmap_db_door,
-		 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+      BlitBitmap(backbuffer, bitmap_db_door_1,
+		 DX, DY, DXSIZE, DYSIZE, 0, 0);
 
     if (old_door_state & DOOR_OPEN_2)
-      BlitBitmap(backbuffer, bitmap_db_door,
-		 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
+      BlitBitmap(backbuffer, bitmap_db_door_2,
+		 VX, VY, VXSIZE, VYSIZE, 0, 0);
 
     door_state &= ~DOOR_NO_COPY_BACK;
   }
@@ -3838,22 +4478,23 @@ unsigned int SetDoorState(unsigned int door_state)
   return MoveDoor(door_state | DOOR_SET_STATE);
 }
 
+int euclid(int a, int b)
+{
+  return (b ? euclid(b, a % b) : a);
+}
+
 unsigned int MoveDoor(unsigned int door_state)
 {
-  static int door1 = DOOR_OPEN_1;
+  struct Rect door_rect_list[] =
+  {
+    { DX, DY, DXSIZE, DYSIZE },
+    { VX, VY, VXSIZE, VYSIZE }
+  };
+  static int door1 = DOOR_CLOSE_1;
   static int door2 = DOOR_CLOSE_2;
-  unsigned long door_delay = 0;
-  unsigned long door_delay_value;
-  int stepsize = 1;
-
-  if (door_1.width < 0 || door_1.width > DXSIZE)
-    door_1.width = DXSIZE;
-  if (door_1.height < 0 || door_1.height > DYSIZE)
-    door_1.height = DYSIZE;
-  if (door_2.width < 0 || door_2.width > VXSIZE)
-    door_2.width = VXSIZE;
-  if (door_2.height < 0 || door_2.height > VYSIZE)
-    door_2.height = VYSIZE;
+  unsigned int door_delay = 0;
+  unsigned int door_delay_value;
+  int i;
 
   if (door_state == DOOR_GET_STATE)
     return (door1 | door2);
@@ -3880,242 +4521,279 @@ unsigned int MoveDoor(unsigned int door_state)
       door_state &= ~DOOR_CLOSE_2;
   }
 
-  door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
-		      door_2.step_delay);
-
-  if (setup.quick_doors)
-  {
-    stepsize = 20;		/* must be chosen to always draw last frame */
-    door_delay_value = 0;
-  }
-
   if (global.autoplay_leveldir)
   {
     door_state |= DOOR_NO_DELAY;
     door_state &= ~DOOR_CLOSE_ALL;
   }
 
-#if 1
   if (game_status == GAME_MODE_EDITOR)
     door_state |= DOOR_NO_DELAY;
-#endif
 
   if (door_state & DOOR_ACTION)
   {
-    boolean handle_door_1 = (door_state & DOOR_ACTION_1);
-    boolean handle_door_2 = (door_state & DOOR_ACTION_2);
-    boolean door_1_done = (!handle_door_1);
-    boolean door_2_done = (!handle_door_2);
-    boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
-    boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
-    int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
-    int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
-    int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
-    int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
-    int door_size     = (handle_door_1 ? door_size_1     : door_size_2);
-    int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
-    int door_skip = max_door_size - door_size;
-    int end = door_size;
-    int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
+    boolean door_panel_drawn[NUM_DOORS];
+    boolean panel_has_doors[NUM_DOORS];
+    boolean door_part_skip[MAX_DOOR_PARTS];
+    boolean door_part_done[MAX_DOOR_PARTS];
+    boolean door_part_done_all;
+    int num_steps[MAX_DOOR_PARTS];
+    int max_move_delay = 0;	// delay for complete animations of all doors
+    int max_step_delay = 0;	// delay (ms) between two animation frames
+    int num_move_steps = 0;	// number of animation steps for all doors
+    int max_move_delay_doors_only = 0;	// delay for doors only (no panel)
+    int num_move_steps_doors_only = 0;	// steps for doors only (no panel)
+    int current_move_delay = 0;
+    int start = 0;
     int k;
 
-    if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
+    for (i = 0; i < NUM_DOORS; i++)
+      panel_has_doors[i] = FALSE;
+
+    for (i = 0; i < MAX_DOOR_PARTS; i++)
+    {
+      struct DoorPartControlInfo *dpc = &door_part_controls[i];
+      struct GraphicInfo *g = &graphic_info[dpc->graphic];
+      int door_token = dpc->door_token;
+
+      door_part_done[i] = FALSE;
+      door_part_skip[i] = (!(door_state & door_token) ||
+			   !g->bitmap);
+    }
+
+    for (i = 0; i < MAX_DOOR_PARTS; i++)
+    {
+      int nr = door_part_order[i].nr;
+      struct DoorPartControlInfo *dpc = &door_part_controls[nr];
+      struct DoorPartPosInfo *pos = dpc->pos;
+      struct GraphicInfo *g = &graphic_info[dpc->graphic];
+      int door_token = dpc->door_token;
+      int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
+      boolean is_panel = DOOR_PART_IS_PANEL(nr);
+      int step_xoffset = ABS(pos->step_xoffset);
+      int step_yoffset = ABS(pos->step_yoffset);
+      int step_delay = pos->step_delay;
+      int current_door_state = door_state & door_token;
+      boolean door_opening = ((current_door_state & DOOR_OPEN)  != 0);
+      boolean door_closing = ((current_door_state & DOOR_CLOSE) != 0);
+      boolean part_opening = (is_panel ? door_closing : door_opening);
+      int start_step = (part_opening ? pos->start_step_opening :
+			pos->start_step_closing);
+      float move_xsize = (step_xoffset ? g->width  : 0);
+      float move_ysize = (step_yoffset ? g->height : 0);
+      int move_xsteps = (step_xoffset ? ceil(move_xsize / step_xoffset) : 0);
+      int move_ysteps = (step_yoffset ? ceil(move_ysize / step_yoffset) : 0);
+      int move_steps = (move_xsteps && move_ysteps ?
+			MIN(move_xsteps, move_ysteps) :
+			move_xsteps ? move_xsteps : move_ysteps) - start_step;
+      int move_delay = move_steps * step_delay;
+
+      if (door_part_skip[nr])
+	continue;
+
+      max_move_delay = MAX(max_move_delay, move_delay);
+      max_step_delay = (max_step_delay == 0 ? step_delay :
+			euclid(max_step_delay, step_delay));
+      num_steps[nr] = move_steps;
+
+      if (!is_panel)
+      {
+	max_move_delay_doors_only = MAX(max_move_delay_doors_only, move_delay);
+
+	panel_has_doors[door_index] = TRUE;
+      }
+    }
+
+    max_step_delay = MAX(1, max_step_delay);	// prevent division by zero
+
+    num_move_steps = max_move_delay / max_step_delay;
+    num_move_steps_doors_only = max_move_delay_doors_only / max_step_delay;
+
+    door_delay_value = max_step_delay;
+
+    if ((door_state & DOOR_NO_DELAY) || setup.quick_doors)
+    {
+      start = num_move_steps - 1;
+    }
+    else
     {
       /* opening door sound has priority over simultaneously closing door */
       if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
-	PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
+        PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
       else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
-	PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
+        PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
     }
 
-    for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
+    for (k = start; k < num_move_steps; k++)
     {
-      int x = k;
-      Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
-      GC gc = bitmap->stored_clip_gc;
+      int last_frame = num_move_steps - 1;	// last frame of this "for" loop
+
+      door_part_done_all = TRUE;
 
-      if (door_state & DOOR_ACTION_1)
+      for (i = 0; i < NUM_DOORS; i++)
+	door_panel_drawn[i] = FALSE;
+
+      for (i = 0; i < MAX_DOOR_PARTS; i++)
       {
-	int a = MIN(x * door_1.step_offset, end);
-	int p = (door_state & DOOR_OPEN_1 ? end - a : a);
-	int i = p + door_skip;
+	int nr = door_part_order[i].nr;
+	struct DoorPartControlInfo *dpc = &door_part_controls[nr];
+	struct DoorPartPosInfo *pos = dpc->pos;
+	struct GraphicInfo *g = &graphic_info[dpc->graphic];
+	int door_token = dpc->door_token;
+	int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
+	boolean is_panel = DOOR_PART_IS_PANEL(nr);
+	boolean is_panel_and_door_has_closed = FALSE;
+	struct Rect *door_rect = &door_rect_list[door_index];
+	Bitmap *bitmap_db_door = (door_token == DOOR_1 ? bitmap_db_door_1 :
+				  bitmap_db_door_2);
+	Bitmap *bitmap = (is_panel ? bitmap_db_door : g->bitmap);
+	int current_door_state = door_state & door_token;
+	boolean door_opening = ((current_door_state & DOOR_OPEN)  != 0);
+	boolean door_closing = !door_opening;
+	boolean part_opening = (is_panel ? door_closing : door_opening);
+	boolean part_closing = !part_opening;
+	int start_step = (part_opening ? pos->start_step_opening :
+			  pos->start_step_closing);
+	int step_delay = pos->step_delay;
+	int step_factor = step_delay / max_step_delay;
+	int k1 = (step_factor ? k / step_factor + 1 : k);
+	int k2 = (part_opening ? k1 + start_step : num_steps[nr] - k1);
+	int kk = MAX(0, k2);
+	int g_src_x = 0;
+	int g_src_y = 0;
+	int src_x, src_y, src_xx, src_yy;
+	int dst_x, dst_y, dst_xx, dst_yy;
+	int width, height;
+
+	if (door_part_skip[nr])
+	  continue;
 
-	if (door_1.anim_mode & ANIM_STATIC_PANEL)
-	{
-	  BlitBitmap(bitmap_db_door, drawto,
-		     DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1,
-		     DXSIZE, DYSIZE, DX, DY);
-	}
-	else if (x <= a)
+	if (!(door_state & door_token))
+	  continue;
+
+	if (!g->bitmap)
+	  continue;
+
+	if (!is_panel)
 	{
-	  BlitBitmap(bitmap_db_door, drawto,
-		     DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
-		     DXSIZE, DYSIZE - p / 2, DX, DY);
+	  int k2_door = (door_opening ? k : num_move_steps_doors_only - k - 1);
+	  int kk_door = MAX(0, k2_door);
+	  int sync_frame = kk_door * door_delay_value;
+	  int frame = getGraphicAnimationFrame(dpc->graphic, sync_frame);
 
-	  ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
+	  getFixedGraphicSource(dpc->graphic, frame, &bitmap,
+				&g_src_x, &g_src_y);
 	}
 
-	if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
+	// draw door panel
+
+	if (!door_panel_drawn[door_index])
 	{
-	  int src1_x = DXSIZE,		src1_y = DOOR_GFX_PAGEY1;
-	  int dst1_x = DX + DXSIZE - i,	dst1_y = DY;
-	  int src2_x = DXSIZE - i,	src2_y = DOOR_GFX_PAGEY1;
-	  int dst2_x = DX,		dst2_y = DY;
-	  int width = i, height = DYSIZE;
-
-	  SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
-	  BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
-			   dst1_x, dst1_y);
-
-	  SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
-	  BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
-			   dst2_x, dst2_y);
+	  ClearRectangle(drawto, door_rect->x, door_rect->y,
+			 door_rect->width, door_rect->height);
+
+	  door_panel_drawn[door_index] = TRUE;
 	}
-	else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
+
+	// draw opening or closing door parts
+
+	if (pos->step_xoffset < 0)	// door part on right side
 	{
-	  int src1_x = DXSIZE,		src1_y = DOOR_GFX_PAGEY1;
-	  int dst1_x = DX,		dst1_y = DY + DYSIZE - i;
-	  int src2_x = 0,		src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
-	  int dst2_x = DX,		dst2_y = DY;
-	  int width = DXSIZE, height = i;
-
-	  SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
-	  BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
-			   dst1_x, dst1_y);
-
-	  SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
-	  BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
-			   dst2_x, dst2_y);
+	  src_xx = 0;
+	  dst_xx = pos->x + ABS(kk * pos->step_xoffset);
+	  width = g->width;
+
+	  if (dst_xx + width > door_rect->width)
+	    width = door_rect->width - dst_xx;
 	}
-	else if (x <= DXSIZE)	/* ANIM_DEFAULT */
+	else				// door part on left side
 	{
-	  int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
-
-	  SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
-	  BlitBitmapMasked(bitmap, drawto,
-			   DXSIZE, DOOR_GFX_PAGEY1, i, 77,
-			   DX + DXSIZE - i, DY + j);
-	  BlitBitmapMasked(bitmap, drawto,
-			   DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
-			   DX + DXSIZE - i, DY + 140 + j);
-	  SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
-			DY - (DOOR_GFX_PAGEY1 + j));
-	  BlitBitmapMasked(bitmap, drawto,
-			   DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
-			   DX, DY);
-	  BlitBitmapMasked(bitmap, drawto,
-			   DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
-			   DX, DY + 140 - j);
-
-	  BlitBitmapMasked(bitmap, drawto,
-			   DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
-			   DX, DY + 77 - j);
-	  BlitBitmapMasked(bitmap, drawto,
-			   DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
-			   DX, DY + 203 - j);
-	  SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
-	  BlitBitmapMasked(bitmap, drawto,
-			   DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
-			   DX + DXSIZE - i, DY + 77 + j);
-	  BlitBitmapMasked(bitmap, drawto,
-			   DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
-			   DX + DXSIZE - i, DY + 203 + j);
-	}
+	  src_xx = 0;
+	  dst_xx = pos->x - kk * pos->step_xoffset;
 
-	redraw_mask |= REDRAW_DOOR_1;
-	door_1_done = (a == end);
-      }
+	  if (dst_xx < 0)
+	  {
+	    src_xx = ABS(dst_xx);
+	    dst_xx = 0;
+	  }
 
-      if (door_state & DOOR_ACTION_2)
-      {
-	int a = MIN(x * door_2.step_offset, door_size);
-	int p = (door_state & DOOR_OPEN_2 ? door_size - a : a);
-	int i = p + door_skip;
+	  width = g->width - src_xx;
 
-	if (door_2.anim_mode & ANIM_STATIC_PANEL)
-	{
-	  BlitBitmap(bitmap_db_door, drawto,
-		     DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2,
-		     VXSIZE, VYSIZE, VX, VY);
-	}
-	else if (x <= VYSIZE)
-	{
-	  BlitBitmap(bitmap_db_door, drawto,
-		     DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + p / 2,
-		     VXSIZE, VYSIZE - p / 2, VX, VY);
+	  if (width > door_rect->width)
+	    width = door_rect->width;
 
-	  ClearRectangle(drawto, VX, VY + VYSIZE - p / 2, VXSIZE, p / 2);
+	  // printf("::: k == %d [%d] \n", k, start_step);
 	}
 
-	if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
+	if (pos->step_yoffset < 0)	// door part on bottom side
 	{
-	  int src1_x = VXSIZE,		src1_y = DOOR_GFX_PAGEY2;
-	  int dst1_x = VX + VXSIZE - i,	dst1_y = VY;
-	  int src2_x = VXSIZE - i,	src2_y = DOOR_GFX_PAGEY2;
-	  int dst2_x = VX,		dst2_y = VY;
-	  int width = i, height = VYSIZE;
-
-	  SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
-	  BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
-			   dst1_x, dst1_y);
-
-	  SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
-	  BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
-			   dst2_x, dst2_y);
+	  src_yy = 0;
+	  dst_yy = pos->y + ABS(kk * pos->step_yoffset);
+	  height = g->height;
+
+	  if (dst_yy + height > door_rect->height)
+	    height = door_rect->height - dst_yy;
 	}
-	else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
+	else				// door part on top side
 	{
-	  int src1_x = VXSIZE,		src1_y = DOOR_GFX_PAGEY2;
-	  int dst1_x = VX,		dst1_y = VY + VYSIZE - i;
-	  int src2_x = 0,		src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
-	  int dst2_x = VX,		dst2_y = VY;
-	  int width = VXSIZE, height = i;
-
-	  SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
-	  BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
-			   dst1_x, dst1_y);
-
-	  SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
-	  BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
-			   dst2_x, dst2_y);
+	  src_yy = 0;
+	  dst_yy = pos->y - kk * pos->step_yoffset;
+
+	  if (dst_yy < 0)
+	  {
+	    src_yy = ABS(dst_yy);
+	    dst_yy = 0;
+	  }
+
+	  height = g->height - src_yy;
 	}
-	else if (x <= VXSIZE)	/* ANIM_DEFAULT */
+
+	src_x = g_src_x + src_xx;
+	src_y = g_src_y + src_yy;
+
+	dst_x = door_rect->x + dst_xx;
+	dst_y = door_rect->y + dst_yy;
+
+	is_panel_and_door_has_closed =
+	  (is_panel &&
+	   door_closing &&
+	   panel_has_doors[door_index] &&
+	   k >= num_move_steps_doors_only - 1);
+
+	if (width  >= 0 && width  <= g->width &&
+	    height >= 0 && height <= g->height &&
+	    !is_panel_and_door_has_closed)
 	{
-	  int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
-
-	  SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
-	  BlitBitmapMasked(bitmap, drawto,
-			   VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
-			   VX + VXSIZE - i, VY + j);
-	  SetClipOrigin(bitmap, gc,
-			VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
-	  BlitBitmapMasked(bitmap, drawto,
-			   VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
-			   VX, VY);
-
-	  BlitBitmapMasked(bitmap, drawto,
-			   VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
-			   i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
-	  SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
-	  BlitBitmapMasked(bitmap, drawto,
-			   VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
-			   i, VYSIZE / 2 - j,
-			   VX + VXSIZE - i, VY + VYSIZE / 2 + j);
+	  if (is_panel || !pos->draw_masked)
+	    BlitBitmap(bitmap, drawto, src_x, src_y, width, height,
+		       dst_x, dst_y);
+	  else
+	    BlitBitmapMasked(bitmap, drawto, src_x, src_y, width, height,
+			     dst_x, dst_y);
 	}
 
-	redraw_mask |= REDRAW_DOOR_2;
-	door_2_done = (a == VXSIZE);
+	redraw_mask |= REDRAW_DOOR_FROM_TOKEN(door_token);
+
+	if ((part_opening && (width < 0         || height < 0)) ||
+	    (part_closing && (width >= g->width && height >= g->height)))
+	  door_part_done[nr] = TRUE;
+
+	// continue door part animations, but not panel after door has closed
+	if (!door_part_done[nr] && !is_panel_and_door_has_closed)
+	  door_part_done_all = FALSE;
       }
 
       if (!(door_state & DOOR_NO_DELAY))
       {
 	BackToFront();
 
-	if (game_status == GAME_MODE_MAIN)
-	  DoAnimation();
+	SkipUntilDelayReached(&door_delay, door_delay_value, &k, last_frame);
 
-	WaitUntilDelayReached(&door_delay, door_delay_value);
+	current_move_delay += max_step_delay;
       }
+
+      if (door_part_done_all)
+	break;
     }
   }
 
@@ -4124,28 +4802,89 @@ unsigned int MoveDoor(unsigned int door_state)
   if (door_state & DOOR_ACTION_2)
     door2 = door_state & DOOR_ACTION_2;
 
+  // draw masked border over door area
+  DrawMaskedBorder(REDRAW_DOOR_1);
+  DrawMaskedBorder(REDRAW_DOOR_2);
+
   return (door1 | door2);
 }
 
+static boolean useSpecialEditorDoor()
+{
+  int graphic = IMG_GLOBAL_BORDER_EDITOR;
+  boolean redefined = getImageListEntryFromImageID(graphic)->redefined;
+
+  // do not draw special editor door if editor border defined or redefined
+  if (graphic_info[graphic].bitmap != NULL || redefined)
+    return FALSE;
+
+  // do not draw special editor door if global border defined to be empty
+  if (graphic_info[IMG_GLOBAL_BORDER].bitmap == NULL)
+    return FALSE;
+
+  // do not draw special editor door if viewport definitions do not match
+  if (EX != VX ||
+      EY >= VY ||
+      EXSIZE != VXSIZE ||
+      EY + EYSIZE != VY + VYSIZE)
+    return FALSE;
+
+  return TRUE;
+}
+
 void DrawSpecialEditorDoor()
 {
-  /* draw bigger toolbox window */
-  BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
-	     DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
-	     EX - 4, EY - 12);
-  BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
-	     EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
-	     EX - 6, EY - 4);
+  struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
+  int top_border_width = gfx1->width;
+  int top_border_height = gfx1->height;
+  int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
+  int ex = EX - outer_border;
+  int ey = EY - outer_border;
+  int vy = VY - outer_border;
+  int exsize = EXSIZE + 2 * outer_border;
+
+  if (!useSpecialEditorDoor())
+    return;
+
+  /* draw bigger level editor toolbox window */
+  BlitBitmap(gfx1->bitmap, drawto, gfx1->src_x, gfx1->src_y,
+	     top_border_width, top_border_height, ex, ey - top_border_height);
+  BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto, ex, vy,
+	     exsize, EYSIZE - VYSIZE + outer_border, ex, ey);
 
   redraw_mask |= REDRAW_ALL;
 }
 
 void UndrawSpecialEditorDoor()
 {
+  struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
+  int top_border_width = gfx1->width;
+  int top_border_height = gfx1->height;
+  int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
+  int ex = EX - outer_border;
+  int ey = EY - outer_border;
+  int ey_top = ey - top_border_height;
+  int exsize = EXSIZE + 2 * outer_border;
+  int eysize = EYSIZE + 2 * outer_border;
+
+  if (!useSpecialEditorDoor())
+    return;
+
   /* draw normal tape recorder window */
-  BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
-	     EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
-	     EX - 6, EY - 12);
+  if (graphic_info[IMG_GLOBAL_BORDER].bitmap)
+  {
+    BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
+	       ex, ey_top, top_border_width, top_border_height,
+	       ex, ey_top);
+    BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
+	       ex, ey, exsize, eysize, ex, ey);
+  }
+  else
+  {
+    // if screen background is set to "[NONE]", clear editor toolbox window
+    ClearRectangle(drawto, ex, ey_top, top_border_width, top_border_height);
+    ClearRectangle(drawto, ex, ey, exsize, eysize);
+  }
 
   redraw_mask |= REDRAW_ALL;
 }
@@ -4153,102 +4892,41 @@ void UndrawSpecialEditorDoor()
 
 /* ---------- new tool button stuff ---------------------------------------- */
 
-/* graphic position values for tool buttons */
-#define TOOL_BUTTON_YES_XPOS		2
-#define TOOL_BUTTON_YES_YPOS		250
-#define TOOL_BUTTON_YES_GFX_YPOS	0
-#define TOOL_BUTTON_YES_XSIZE		46
-#define TOOL_BUTTON_YES_YSIZE		28
-#define TOOL_BUTTON_NO_XPOS		52
-#define TOOL_BUTTON_NO_YPOS		TOOL_BUTTON_YES_YPOS
-#define TOOL_BUTTON_NO_GFX_YPOS		TOOL_BUTTON_YES_GFX_YPOS
-#define TOOL_BUTTON_NO_XSIZE		TOOL_BUTTON_YES_XSIZE
-#define TOOL_BUTTON_NO_YSIZE		TOOL_BUTTON_YES_YSIZE
-#define TOOL_BUTTON_CONFIRM_XPOS	TOOL_BUTTON_YES_XPOS
-#define TOOL_BUTTON_CONFIRM_YPOS	TOOL_BUTTON_YES_YPOS
-#define TOOL_BUTTON_CONFIRM_GFX_YPOS	30
-#define TOOL_BUTTON_CONFIRM_XSIZE	96
-#define TOOL_BUTTON_CONFIRM_YSIZE	TOOL_BUTTON_YES_YSIZE
-#define TOOL_BUTTON_PLAYER_XSIZE	30
-#define TOOL_BUTTON_PLAYER_YSIZE	30
-#define TOOL_BUTTON_PLAYER_GFX_XPOS	5
-#define TOOL_BUTTON_PLAYER_GFX_YPOS	185
-#define TOOL_BUTTON_PLAYER_XPOS		(5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
-#define TOOL_BUTTON_PLAYER_YPOS		(215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
-#define TOOL_BUTTON_PLAYER1_XPOS	(TOOL_BUTTON_PLAYER_XPOS \
-					 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
-#define TOOL_BUTTON_PLAYER2_XPOS	(TOOL_BUTTON_PLAYER_XPOS \
-					 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
-#define TOOL_BUTTON_PLAYER3_XPOS	(TOOL_BUTTON_PLAYER_XPOS \
-					 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
-#define TOOL_BUTTON_PLAYER4_XPOS	(TOOL_BUTTON_PLAYER_XPOS \
-					 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
-#define TOOL_BUTTON_PLAYER1_YPOS	(TOOL_BUTTON_PLAYER_YPOS \
-					 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
-#define TOOL_BUTTON_PLAYER2_YPOS	(TOOL_BUTTON_PLAYER_YPOS \
-					 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
-#define TOOL_BUTTON_PLAYER3_YPOS	(TOOL_BUTTON_PLAYER_YPOS \
-					 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
-#define TOOL_BUTTON_PLAYER4_YPOS	(TOOL_BUTTON_PLAYER_YPOS \
-					 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
-
 static struct
 {
-  int xpos, ypos;
-  int x, y;
-  int width, height;
+  int graphic;
+  struct TextPosInfo *pos;
   int gadget_id;
   char *infotext;
 } toolbutton_info[NUM_TOOL_BUTTONS] =
 {
   {
-    TOOL_BUTTON_YES_XPOS,	TOOL_BUTTON_YES_GFX_YPOS,
-    TOOL_BUTTON_YES_XPOS,	TOOL_BUTTON_YES_YPOS,
-    TOOL_BUTTON_YES_XSIZE,	TOOL_BUTTON_YES_YSIZE,
-    TOOL_CTRL_ID_YES,
-    "yes"
+    IMG_GFX_REQUEST_BUTTON_YES,		&request.button.yes,
+    TOOL_CTRL_ID_YES,			"yes"
   },
   {
-    TOOL_BUTTON_NO_XPOS,	TOOL_BUTTON_NO_GFX_YPOS,
-    TOOL_BUTTON_NO_XPOS,	TOOL_BUTTON_NO_YPOS,
-    TOOL_BUTTON_NO_XSIZE,	TOOL_BUTTON_NO_YSIZE,
-    TOOL_CTRL_ID_NO,
-    "no"
+    IMG_GFX_REQUEST_BUTTON_NO,		&request.button.no,
+    TOOL_CTRL_ID_NO,			"no"
   },
   {
-    TOOL_BUTTON_CONFIRM_XPOS,	TOOL_BUTTON_CONFIRM_GFX_YPOS,
-    TOOL_BUTTON_CONFIRM_XPOS,	TOOL_BUTTON_CONFIRM_YPOS,
-    TOOL_BUTTON_CONFIRM_XSIZE,	TOOL_BUTTON_CONFIRM_YSIZE,
-    TOOL_CTRL_ID_CONFIRM,
-    "confirm"
+    IMG_GFX_REQUEST_BUTTON_CONFIRM,	&request.button.confirm,
+    TOOL_CTRL_ID_CONFIRM,		"confirm"
   },
   {
-    TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
-    TOOL_BUTTON_PLAYER1_XPOS,	TOOL_BUTTON_PLAYER1_YPOS,
-    TOOL_BUTTON_PLAYER_XSIZE,	TOOL_BUTTON_PLAYER_YSIZE,
-    TOOL_CTRL_ID_PLAYER_1,
-    "player 1"
+    IMG_GFX_REQUEST_BUTTON_PLAYER_1,	&request.button.player_1,
+    TOOL_CTRL_ID_PLAYER_1,		"player 1"
   },
   {
-    TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
-    TOOL_BUTTON_PLAYER2_XPOS,	TOOL_BUTTON_PLAYER2_YPOS,
-    TOOL_BUTTON_PLAYER_XSIZE,	TOOL_BUTTON_PLAYER_YSIZE,
-    TOOL_CTRL_ID_PLAYER_2,
-    "player 2"
+    IMG_GFX_REQUEST_BUTTON_PLAYER_2,	&request.button.player_2,
+    TOOL_CTRL_ID_PLAYER_2,		"player 2"
   },
   {
-    TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
-    TOOL_BUTTON_PLAYER3_XPOS,	TOOL_BUTTON_PLAYER3_YPOS,
-    TOOL_BUTTON_PLAYER_XSIZE,	TOOL_BUTTON_PLAYER_YSIZE,
-    TOOL_CTRL_ID_PLAYER_3,
-    "player 3"
+    IMG_GFX_REQUEST_BUTTON_PLAYER_3,	&request.button.player_3,
+    TOOL_CTRL_ID_PLAYER_3,		"player 3"
   },
   {
-    TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
-    TOOL_BUTTON_PLAYER4_XPOS,	TOOL_BUTTON_PLAYER4_YPOS,
-    TOOL_BUTTON_PLAYER_XSIZE,	TOOL_BUTTON_PLAYER_YSIZE,
-    TOOL_CTRL_ID_PLAYER_4,
-    "player 4"
+    IMG_GFX_REQUEST_BUTTON_PLAYER_4,	&request.button.player_4,
+    TOOL_CTRL_ID_PLAYER_4,		"player 4"
   }
 };
 
@@ -4258,46 +4936,46 @@ void CreateToolButtons()
 
   for (i = 0; i < NUM_TOOL_BUTTONS; i++)
   {
-    Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
+    struct GraphicInfo *gfx = &graphic_info[toolbutton_info[i].graphic];
+    struct TextPosInfo *pos = toolbutton_info[i].pos;
+    struct GadgetInfo *gi;
     Bitmap *deco_bitmap = None;
     int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
-    struct GadgetInfo *gi;
-    unsigned long event_mask;
-    int gd_xoffset, gd_yoffset;
-    int gd_x1, gd_x2, gd_y;
+    unsigned int event_mask = GD_EVENT_RELEASED;
+    int dx = DX;
+    int dy = DY;
+    int gd_x = gfx->src_x;
+    int gd_y = gfx->src_y;
+    int gd_xp = gfx->src_x + gfx->pressed_xoffset;
+    int gd_yp = gfx->src_y + gfx->pressed_yoffset;
     int id = i;
 
-    event_mask = GD_EVENT_RELEASED;
-
-    gd_xoffset = toolbutton_info[i].xpos;
-    gd_yoffset = toolbutton_info[i].ypos;
-    gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
-    gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
-    gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
+    if (global.use_envelope_request)
+      setRequestPosition(&dx, &dy, TRUE);
 
     if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
     {
       int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
 
-      getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
-			   &deco_bitmap, &deco_x, &deco_y);
-      deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
-      deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
+      getSizedGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0,
+			    pos->size, &deco_bitmap, &deco_x, &deco_y);
+      deco_xpos = (gfx->width  - pos->size) / 2;
+      deco_ypos = (gfx->height - pos->size) / 2;
     }
 
     gi = CreateGadget(GDI_CUSTOM_ID, id,
 		      GDI_INFO_TEXT, toolbutton_info[i].infotext,
-		      GDI_X, DX + toolbutton_info[i].x,
-		      GDI_Y, DY + toolbutton_info[i].y,
-		      GDI_WIDTH, toolbutton_info[i].width,
-		      GDI_HEIGHT, toolbutton_info[i].height,
+		      GDI_X, dx + GDI_ACTIVE_POS(pos->x),
+		      GDI_Y, dy + GDI_ACTIVE_POS(pos->y),
+		      GDI_WIDTH, gfx->width,
+		      GDI_HEIGHT, gfx->height,
 		      GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
 		      GDI_STATE, GD_BUTTON_UNPRESSED,
-		      GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
-		      GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
+		      GDI_DESIGN_UNPRESSED, gfx->bitmap, gd_x, gd_y,
+		      GDI_DESIGN_PRESSED, gfx->bitmap, gd_xp, gd_yp,
 		      GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
 		      GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
-		      GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
+		      GDI_DECORATION_SIZE, pos->size, pos->size,
 		      GDI_DECORATION_SHIFTING, 1, 1,
 		      GDI_DIRECT_DRAW, FALSE,
 		      GDI_EVENT_MASK, event_mask,
@@ -5548,7 +6226,6 @@ em_object_mapping_list[] =
     Xsand_stonein_4,			FALSE,	TRUE,
     EL_ROCK,				ACTION_FILLING, -1
   },
-#if 1
   {
     Xsand_stonesand_1,			FALSE,	FALSE,
     EL_QUICKSAND_EMPTYING,		-1, -1
@@ -5573,24 +6250,6 @@ em_object_mapping_list[] =
     Xsand_stonesand_quickout_2,		FALSE,	FALSE,
     EL_QUICKSAND_EMPTYING,		-1, -1
   },
-#else
-  {
-    Xsand_stonesand_1,			FALSE,	FALSE,
-    EL_QUICKSAND_FULL,			-1, -1
-  },
-  {
-    Xsand_stonesand_2,			FALSE,	FALSE,
-    EL_QUICKSAND_FULL,			-1, -1
-  },
-  {
-    Xsand_stonesand_3,			FALSE,	FALSE,
-    EL_QUICKSAND_FULL,			-1, -1
-  },
-  {
-    Xsand_stonesand_4,			FALSE,	FALSE,
-    EL_QUICKSAND_FULL,			-1, -1
-  },
-#endif
   {
     Xsand_stoneout_1,			FALSE,	FALSE,
     EL_ROCK,				ACTION_EMPTYING, -1
@@ -5599,7 +6258,6 @@ em_object_mapping_list[] =
     Xsand_stoneout_2,			FALSE,	FALSE,
     EL_ROCK,				ACTION_EMPTYING, -1
   },
-#if 1
   {
     Xsand_sandstone_1,			FALSE,	FALSE,
     EL_QUICKSAND_FILLING,		-1, -1
@@ -5616,24 +6274,6 @@ em_object_mapping_list[] =
     Xsand_sandstone_4,			FALSE,	FALSE,
     EL_QUICKSAND_FILLING,		-1, -1
   },
-#else
-  {
-    Xsand_sandstone_1,			FALSE,	FALSE,
-    EL_QUICKSAND_FULL,			-1, -1
-  },
-  {
-    Xsand_sandstone_2,			FALSE,	FALSE,
-    EL_QUICKSAND_FULL,			-1, -1
-  },
-  {
-    Xsand_sandstone_3,			FALSE,	FALSE,
-    EL_QUICKSAND_FULL,			-1, -1
-  },
-  {
-    Xsand_sandstone_4,			FALSE,	FALSE,
-    EL_QUICKSAND_FULL,			-1, -1
-  },
-#endif
   {
     Xplant,				TRUE,	FALSE,
     EL_EMC_PLANT,			-1, -1
@@ -6016,7 +6656,7 @@ em_object_mapping_list[] =
   },
   {
     Xalpha_copyr,			TRUE,	FALSE,
-    EL_CHAR('�'),			-1, -1
+    EL_CHAR(CHAR_BYTE_COPYRIGHT),	-1, -1
   },
 
   {
@@ -6489,19 +7129,6 @@ int get_next_element(int element)
   }
 }
 
-#if 0
-int el_act_dir2img(int element, int action, int direction)
-{
-  element = GFX_ELEMENT(element);
-
-  if (direction == MV_NONE)
-    return element_info[element].graphic[action];
-
-  direction = MV_DIR_TO_BIT(direction);
-
-  return element_info[element].direction_graphic[action][direction];
-}
-#else
 int el_act_dir2img(int element, int action, int direction)
 {
   element = GFX_ELEMENT(element);
@@ -6510,21 +7137,7 @@ int el_act_dir2img(int element, int action, int direction)
   /* direction_graphic[][] == graphic[] for undefined direction graphics */
   return element_info[element].direction_graphic[action][direction];
 }
-#endif
-
-#if 0
-static int el_act_dir2crm(int element, int action, int direction)
-{
-  element = GFX_ELEMENT(element);
-
-  if (direction == MV_NONE)
-    return element_info[element].crumbled[action];
 
-  direction = MV_DIR_TO_BIT(direction);
-
-  return element_info[element].direction_crumbled[action][direction];
-}
-#else
 static int el_act_dir2crm(int element, int action, int direction)
 {
   element = GFX_ELEMENT(element);
@@ -6533,7 +7146,6 @@ static int el_act_dir2crm(int element, int action, int direction)
   /* direction_graphic[][] == graphic[] for undefined direction graphics */
   return element_info[element].direction_crumbled[action][direction];
 }
-#endif
 
 int el_act2img(int element, int action)
 {
@@ -6715,19 +7327,9 @@ int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
   return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
 }
 
-int getNumActivePlayers_EM()
+boolean getTeamMode_EM()
 {
-  int num_players = 0;
-  int i;
-
-  if (!tape.playing)
-    return -1;
-
-  for (i = 0; i < MAX_PLAYERS; i++)
-    if (tape.player_participates[i])
-      num_players++;
-
-  return num_players;
+  return game.team_mode;
 }
 
 int getGameFrameDelay_EM(int native_em_game_frame_delay)
@@ -6745,7 +7347,7 @@ int getGameFrameDelay_EM(int native_em_game_frame_delay)
   return game_frame_delay_value;
 }
 
-unsigned int InitRND(long seed)
+unsigned int InitRND(int seed)
 {
   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
     return InitEngineRandom_EM(seed);
@@ -6755,10 +7357,8 @@ unsigned int InitRND(long seed)
     return InitEngineRandom_RND(seed);
 }
 
-#if 1
 static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
 static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
-#endif
 
 inline static int get_effective_element_EM(int tile, int frame_em)
 {
@@ -6777,12 +7377,6 @@ inline static int get_effective_element_EM(int tile, int frame_em)
       case Yacid_splash_wB:
 	return (frame_em > 5 ? EL_EMPTY : element);
 
-#if 0
-      case Ydiamond_stone:
-	//  if (!game.use_native_emc_graphics_engine)
-	return EL_ROCK;
-#endif
-
       default:
 	return element;
     }
@@ -6860,11 +7454,9 @@ inline static boolean check_linear_animation_EM(int tile)
     case Ytank_s_e:
     case Ytank_w_s:
     case Ytank_n_w:
-#if 1
     case Yacid_splash_eB:
     case Yacid_splash_wB:
     case Yemerald_stone:
-#endif
       return TRUE;
   }
 
@@ -6894,6 +7486,7 @@ inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
 		     &g_em->crumbled_src_x, &g_em->crumbled_src_y);
 
     g_em->crumbled_border_size = graphic_info[crumbled].border_size;
+    g_em->crumbled_tile_size = graphic_info[crumbled].tile_size;
 
     g_em->has_crumbled_graphics = TRUE;
   }
@@ -6903,6 +7496,7 @@ inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
     g_em->crumbled_src_x = 0;
     g_em->crumbled_src_y = 0;
     g_em->crumbled_border_size = 0;
+    g_em->crumbled_tile_size = 0;
 
     g_em->has_crumbled_graphics = FALSE;
   }
@@ -6917,7 +7511,6 @@ void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
 			int tile, int frame_em, int x, int y)
 {
   int action = object_mapping[tile].action;
-#if 1
   int direction = object_mapping[tile].direction;
   int effective_element = get_effective_element_EM(tile, frame_em);
   int graphic = (direction == MV_NONE ?
@@ -6925,7 +7518,6 @@ void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
 		 el_act_dir2img(effective_element, action, direction));
   struct GraphicInfo *g = &graphic_info[graphic];
   int sync_frame;
-#endif
   boolean action_removing = (action == ACTION_DIGGING ||
 			     action == ACTION_SNAPPING ||
 			     action == ACTION_COLLECTING);
@@ -6952,29 +7544,10 @@ void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
     g = &graphic_info[graphic];
   }
 
-#if 0
-  if (tile == Xsand_stonesand_1 ||
-      tile == Xsand_stonesand_2 ||
-      tile == Xsand_stonesand_3 ||
-      tile == Xsand_stonesand_4)
-    printf("::: 1: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
-#endif
-
-#if 1
   if ((action_removing || check_linear_animation_EM(tile)) && frame_em == 0)
   {
     GfxFrame[x][y] = 0;
-
-    // printf("::: resetting... [%d]\n", tile);
-  }
-#else
-  if (action_removing || check_linear_animation_EM(tile))
-  {
-    GfxFrame[x][y] = frame_em;
-
-    // printf("::: resetting... [%d]\n", tile);
   }
-#endif
   else if (action_moving)
   {
     boolean is_backside = object_mapping[tile].is_backside;
@@ -6989,11 +7562,7 @@ void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
 #if 1
       /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */
       if (g->double_movement && frame_em == 0)
-      {
 	GfxFrame[x][y] = 0;
-
-	// printf("::: resetting... [%d]\n", tile);
-      }
 #endif
 
       if (move_dir == MV_LEFT)
@@ -7016,15 +7585,6 @@ void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
       GfxFrame[x][y]++;
   }
 
-#if 0
-  if (tile == Xsand_stonesand_1 ||
-      tile == Xsand_stonesand_2 ||
-      tile == Xsand_stonesand_3 ||
-      tile == Xsand_stonesand_4)
-    printf("::: 2: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
-#endif
-
-#if 1
   if (graphic_info[graphic].anim_global_sync)
     sync_frame = FrameCounter;
   else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
@@ -7042,7 +7602,6 @@ void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
 
   g_em->unique_identifier =
     (graphic << 16) | ((frame % 8) << 12) | (g_em->width << 6) | g_em->height;
-#endif
 }
 
 void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
@@ -7052,580 +7611,61 @@ void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
   int direction = object_mapping[tile].direction;
   boolean is_backside = object_mapping[tile].is_backside;
   int effective_element = get_effective_element_EM(tile, frame_em);
-#if 1
   int effective_action = action;
-#else
-  int effective_action = (frame_em < 7 ? action : ACTION_DEFAULT);
-#endif
   int graphic = (direction == MV_NONE ?
 		 el_act2img(effective_element, effective_action) :
 		 el_act_dir2img(effective_element, effective_action,
 				direction));
   int crumbled = (direction == MV_NONE ?
 		  el_act2crm(effective_element, effective_action) :
-		  el_act_dir2crm(effective_element, effective_action,
-				 direction));
-  int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
-  int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
-  boolean has_crumbled_graphics = (base_crumbled != base_graphic);
-  struct GraphicInfo *g = &graphic_info[graphic];
-#if 0
-  struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
-#endif
-  int sync_frame;
-
-  /* special case: graphic uses "2nd movement tile" and has defined
-     7 frames for movement animation (or less) => use default graphic
-     for last (8th) frame which ends the movement animation */
-  if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
-  {
-    effective_action = ACTION_DEFAULT;
-    graphic = (direction == MV_NONE ?
-	       el_act2img(effective_element, effective_action) :
-	       el_act_dir2img(effective_element, effective_action,
-			      direction));
-    crumbled = (direction == MV_NONE ?
-		el_act2crm(effective_element, effective_action) :
-		el_act_dir2crm(effective_element, effective_action,
-			       direction));
-
-    g = &graphic_info[graphic];
-  }
-
-#if 0
-  if (frame_em == 7)
-    return;
-#endif
-
-
-#if 0
-  if (frame_em == 0)	/* reset animation frame for certain elements */
-  {
-    if (check_linear_animation_EM(tile))
-      GfxFrame[x][y] = 0;
-  }
-#endif
-
-  if (graphic_info[graphic].anim_global_sync)
-    sync_frame = FrameCounter;
-  else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
-    sync_frame = GfxFrame[x][y];
-  else
-    sync_frame = 0;	/* playfield border (pseudo steel) */
-
-  SetRandomAnimationValue(x, y);
-
-#if 0
-  int i = tile;
-  int j = frame_em;
-  int xxx_sync_frame = (i == Xdrip_stretch ? 7 :
-			i == Xdrip_stretchB ? 7 :
-			i == Ydrip_s2 ? j + 8 :
-			i == Ydrip_s2B ? j + 8 :
-			i == Xacid_1 ? 0 :
-			i == Xacid_2 ? 10 :
-			i == Xacid_3 ? 20 :
-			i == Xacid_4 ? 30 :
-			i == Xacid_5 ? 40 :
-			i == Xacid_6 ? 50 :
-			i == Xacid_7 ? 60 :
-			i == Xacid_8 ? 70 :
-			i == Xfake_acid_1 ? 0 :
-			i == Xfake_acid_2 ? 10 :
-			i == Xfake_acid_3 ? 20 :
-			i == Xfake_acid_4 ? 30 :
-			i == Xfake_acid_5 ? 40 :
-			i == Xfake_acid_6 ? 50 :
-			i == Xfake_acid_7 ? 60 :
-			i == Xfake_acid_8 ? 70 :
-			i == Xball_2 ? 7 :
-			i == Xball_2B ? j + 8 :
-			i == Yball_eat ? j + 1 :
-			i == Ykey_1_eat ? j + 1 :
-			i == Ykey_2_eat ? j + 1 :
-			i == Ykey_3_eat ? j + 1 :
-			i == Ykey_4_eat ? j + 1 :
-			i == Ykey_5_eat ? j + 1 :
-			i == Ykey_6_eat ? j + 1 :
-			i == Ykey_7_eat ? j + 1 :
-			i == Ykey_8_eat ? j + 1 :
-			i == Ylenses_eat ? j + 1 :
-			i == Ymagnify_eat ? j + 1 :
-			i == Ygrass_eat ? j + 1 :
-			i == Ydirt_eat ? j + 1 :
-			i == Xamoeba_1 ? 0 :
-			i == Xamoeba_2 ? 1 :
-			i == Xamoeba_3 ? 2 :
-			i == Xamoeba_4 ? 3 :
-			i == Xamoeba_5 ? 0 :
-			i == Xamoeba_6 ? 1 :
-			i == Xamoeba_7 ? 2 :
-			i == Xamoeba_8 ? 3 :
-			i == Xexit_2 ? j + 8 :
-			i == Xexit_3 ? j + 16 :
-			i == Xdynamite_1 ? 0 :
-			i == Xdynamite_2 ? 8 :
-			i == Xdynamite_3 ? 16 :
-			i == Xdynamite_4 ? 24 :
-			i == Xsand_stonein_1 ? j + 1 :
-			i == Xsand_stonein_2 ? j + 9 :
-			i == Xsand_stonein_3 ? j + 17 :
-			i == Xsand_stonein_4 ? j + 25 :
-			i == Xsand_stoneout_1 && j == 0 ? 0 :
-			i == Xsand_stoneout_1 && j == 1 ? 0 :
-			i == Xsand_stoneout_1 && j == 2 ? 1 :
-			i == Xsand_stoneout_1 && j == 3 ? 2 :
-			i == Xsand_stoneout_1 && j == 4 ? 2 :
-			i == Xsand_stoneout_1 && j == 5 ? 3 :
-			i == Xsand_stoneout_1 && j == 6 ? 4 :
-			i == Xsand_stoneout_1 && j == 7 ? 4 :
-			i == Xsand_stoneout_2 && j == 0 ? 5 :
-			i == Xsand_stoneout_2 && j == 1 ? 6 :
-			i == Xsand_stoneout_2 && j == 2 ? 7 :
-			i == Xsand_stoneout_2 && j == 3 ? 8 :
-			i == Xsand_stoneout_2 && j == 4 ? 9 :
-			i == Xsand_stoneout_2 && j == 5 ? 11 :
-			i == Xsand_stoneout_2 && j == 6 ? 13 :
-			i == Xsand_stoneout_2 && j == 7 ? 15 :
-			i == Xboom_bug && j == 1 ? 2 :
-			i == Xboom_bug && j == 2 ? 2 :
-			i == Xboom_bug && j == 3 ? 4 :
-			i == Xboom_bug && j == 4 ? 4 :
-			i == Xboom_bug && j == 5 ? 2 :
-			i == Xboom_bug && j == 6 ? 2 :
-			i == Xboom_bug && j == 7 ? 0 :
-			i == Xboom_bomb && j == 1 ? 2 :
-			i == Xboom_bomb && j == 2 ? 2 :
-			i == Xboom_bomb && j == 3 ? 4 :
-			i == Xboom_bomb && j == 4 ? 4 :
-			i == Xboom_bomb && j == 5 ? 2 :
-			i == Xboom_bomb && j == 6 ? 2 :
-			i == Xboom_bomb && j == 7 ? 0 :
-			i == Xboom_android && j == 7 ? 6 :
-			i == Xboom_1 && j == 1 ? 2 :
-			i == Xboom_1 && j == 2 ? 2 :
-			i == Xboom_1 && j == 3 ? 4 :
-			i == Xboom_1 && j == 4 ? 4 :
-			i == Xboom_1 && j == 5 ? 6 :
-			i == Xboom_1 && j == 6 ? 6 :
-			i == Xboom_1 && j == 7 ? 8 :
-			i == Xboom_2 && j == 0 ? 8 :
-			i == Xboom_2 && j == 1 ? 8 :
-			i == Xboom_2 && j == 2 ? 10 :
-			i == Xboom_2 && j == 3 ? 10 :
-			i == Xboom_2 && j == 4 ? 10 :
-			i == Xboom_2 && j == 5 ? 12 :
-			i == Xboom_2 && j == 6 ? 12 :
-			i == Xboom_2 && j == 7 ? 12 :
-#if 0
-			special_animation && j == 4 ? 3 :
-			effective_action != action ? 0 :
-#endif
-			j);
-#endif
-
-#if 0
-  int xxx_effective_action;
-  int xxx_has_action_graphics;
-
-  {
-    int element = object_mapping[i].element_rnd;
-    int action = object_mapping[i].action;
-    int direction = object_mapping[i].direction;
-    boolean is_backside = object_mapping[i].is_backside;
-#if 0
-    boolean action_removing = (action == ACTION_DIGGING ||
-			       action == ACTION_SNAPPING ||
-			       action == ACTION_COLLECTING);
-#endif
-    boolean action_exploding = ((action == ACTION_EXPLODING ||
-				 action == ACTION_SMASHED_BY_ROCK ||
-				 action == ACTION_SMASHED_BY_SPRING) &&
-				element != EL_DIAMOND);
-    boolean action_active = (action == ACTION_ACTIVE);
-    boolean action_other = (action == ACTION_OTHER);
-
-    {
-#if 1
-      int effective_element = get_effective_element_EM(i, j);
-#else
-      int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
-			       j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
-			       j < 7 ? element :
-			       i == Xdrip_stretch ? element :
-			       i == Xdrip_stretchB ? element :
-			       i == Ydrip_s1 ? element :
-			       i == Ydrip_s1B ? element :
-			       i == Xball_1B ? element :
-			       i == Xball_2 ? element :
-			       i == Xball_2B ? element :
-			       i == Yball_eat ? element :
-			       i == Ykey_1_eat ? element :
-			       i == Ykey_2_eat ? element :
-			       i == Ykey_3_eat ? element :
-			       i == Ykey_4_eat ? element :
-			       i == Ykey_5_eat ? element :
-			       i == Ykey_6_eat ? element :
-			       i == Ykey_7_eat ? element :
-			       i == Ykey_8_eat ? element :
-			       i == Ylenses_eat ? element :
-			       i == Ymagnify_eat ? element :
-			       i == Ygrass_eat ? element :
-			       i == Ydirt_eat ? element :
-			       i == Yemerald_stone ? EL_EMERALD :
-			       i == Ydiamond_stone ? EL_ROCK :
-			       i == Xsand_stonein_1 ? element :
-			       i == Xsand_stonein_2 ? element :
-			       i == Xsand_stonein_3 ? element :
-			       i == Xsand_stonein_4 ? element :
-			       is_backside ? EL_EMPTY :
-			       action_removing ? EL_EMPTY :
-			       element);
-#endif
-      int effective_action = (j < 7 ? action :
-			      i == Xdrip_stretch ? action :
-			      i == Xdrip_stretchB ? action :
-			      i == Ydrip_s1 ? action :
-			      i == Ydrip_s1B ? action :
-			      i == Xball_1B ? action :
-			      i == Xball_2 ? action :
-			      i == Xball_2B ? action :
-			      i == Yball_eat ? action :
-			      i == Ykey_1_eat ? action :
-			      i == Ykey_2_eat ? action :
-			      i == Ykey_3_eat ? action :
-			      i == Ykey_4_eat ? action :
-			      i == Ykey_5_eat ? action :
-			      i == Ykey_6_eat ? action :
-			      i == Ykey_7_eat ? action :
-			      i == Ykey_8_eat ? action :
-			      i == Ylenses_eat ? action :
-			      i == Ymagnify_eat ? action :
-			      i == Ygrass_eat ? action :
-			      i == Ydirt_eat ? action :
-			      i == Xsand_stonein_1 ? action :
-			      i == Xsand_stonein_2 ? action :
-			      i == Xsand_stonein_3 ? action :
-			      i == Xsand_stonein_4 ? action :
-			      i == Xsand_stoneout_1 ? action :
-			      i == Xsand_stoneout_2 ? action :
-			      i == Xboom_android ? ACTION_EXPLODING :
-			      action_exploding ? ACTION_EXPLODING :
-			      action_active ? action :
-			      action_other ? action :
-			      ACTION_DEFAULT);
-      int graphic = (el_act_dir2img(effective_element, effective_action,
-				    direction));
-      int crumbled = (el_act_dir2crm(effective_element, effective_action,
-				     direction));
-      int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
-      int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
-      boolean has_action_graphics = (graphic != base_graphic);
-      boolean has_crumbled_graphics = (base_crumbled != base_graphic);
-      struct GraphicInfo *g = &graphic_info[graphic];
-#if 0
-      struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
-#endif
-      struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
-      Bitmap *src_bitmap;
-      int src_x, src_y;
-      /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
-      boolean special_animation = (action != ACTION_DEFAULT &&
-				   g->anim_frames == 3 &&
-				   g->anim_delay == 2 &&
-				   g->anim_mode & ANIM_LINEAR);
-      xxx_sync_frame = (i == Xdrip_stretch ? 7 :
-			i == Xdrip_stretchB ? 7 :
-			i == Ydrip_s2 ? j + 8 :
-			i == Ydrip_s2B ? j + 8 :
-			i == Xacid_1 ? 0 :
-			i == Xacid_2 ? 10 :
-			i == Xacid_3 ? 20 :
-			i == Xacid_4 ? 30 :
-			i == Xacid_5 ? 40 :
-			i == Xacid_6 ? 50 :
-			i == Xacid_7 ? 60 :
-			i == Xacid_8 ? 70 :
-			i == Xfake_acid_1 ? 0 :
-			i == Xfake_acid_2 ? 10 :
-			i == Xfake_acid_3 ? 20 :
-			i == Xfake_acid_4 ? 30 :
-			i == Xfake_acid_5 ? 40 :
-			i == Xfake_acid_6 ? 50 :
-			i == Xfake_acid_7 ? 60 :
-			i == Xfake_acid_8 ? 70 :
-			i == Xball_2 ? 7 :
-			i == Xball_2B ? j + 8 :
-			i == Yball_eat ? j + 1 :
-			i == Ykey_1_eat ? j + 1 :
-			i == Ykey_2_eat ? j + 1 :
-			i == Ykey_3_eat ? j + 1 :
-			i == Ykey_4_eat ? j + 1 :
-			i == Ykey_5_eat ? j + 1 :
-			i == Ykey_6_eat ? j + 1 :
-			i == Ykey_7_eat ? j + 1 :
-			i == Ykey_8_eat ? j + 1 :
-			i == Ylenses_eat ? j + 1 :
-			i == Ymagnify_eat ? j + 1 :
-			i == Ygrass_eat ? j + 1 :
-			i == Ydirt_eat ? j + 1 :
-			i == Xamoeba_1 ? 0 :
-			i == Xamoeba_2 ? 1 :
-			i == Xamoeba_3 ? 2 :
-			i == Xamoeba_4 ? 3 :
-			i == Xamoeba_5 ? 0 :
-			i == Xamoeba_6 ? 1 :
-			i == Xamoeba_7 ? 2 :
-			i == Xamoeba_8 ? 3 :
-			i == Xexit_2 ? j + 8 :
-			i == Xexit_3 ? j + 16 :
-			i == Xdynamite_1 ? 0 :
-			i == Xdynamite_2 ? 8 :
-			i == Xdynamite_3 ? 16 :
-			i == Xdynamite_4 ? 24 :
-			i == Xsand_stonein_1 ? j + 1 :
-			i == Xsand_stonein_2 ? j + 9 :
-			i == Xsand_stonein_3 ? j + 17 :
-			i == Xsand_stonein_4 ? j + 25 :
-			i == Xsand_stoneout_1 && j == 0 ? 0 :
-			i == Xsand_stoneout_1 && j == 1 ? 0 :
-			i == Xsand_stoneout_1 && j == 2 ? 1 :
-			i == Xsand_stoneout_1 && j == 3 ? 2 :
-			i == Xsand_stoneout_1 && j == 4 ? 2 :
-			i == Xsand_stoneout_1 && j == 5 ? 3 :
-			i == Xsand_stoneout_1 && j == 6 ? 4 :
-			i == Xsand_stoneout_1 && j == 7 ? 4 :
-			i == Xsand_stoneout_2 && j == 0 ? 5 :
-			i == Xsand_stoneout_2 && j == 1 ? 6 :
-			i == Xsand_stoneout_2 && j == 2 ? 7 :
-			i == Xsand_stoneout_2 && j == 3 ? 8 :
-			i == Xsand_stoneout_2 && j == 4 ? 9 :
-			i == Xsand_stoneout_2 && j == 5 ? 11 :
-			i == Xsand_stoneout_2 && j == 6 ? 13 :
-			i == Xsand_stoneout_2 && j == 7 ? 15 :
-			i == Xboom_bug && j == 1 ? 2 :
-			i == Xboom_bug && j == 2 ? 2 :
-			i == Xboom_bug && j == 3 ? 4 :
-			i == Xboom_bug && j == 4 ? 4 :
-			i == Xboom_bug && j == 5 ? 2 :
-			i == Xboom_bug && j == 6 ? 2 :
-			i == Xboom_bug && j == 7 ? 0 :
-			i == Xboom_bomb && j == 1 ? 2 :
-			i == Xboom_bomb && j == 2 ? 2 :
-			i == Xboom_bomb && j == 3 ? 4 :
-			i == Xboom_bomb && j == 4 ? 4 :
-			i == Xboom_bomb && j == 5 ? 2 :
-			i == Xboom_bomb && j == 6 ? 2 :
-			i == Xboom_bomb && j == 7 ? 0 :
-			i == Xboom_android && j == 7 ? 6 :
-			i == Xboom_1 && j == 1 ? 2 :
-			i == Xboom_1 && j == 2 ? 2 :
-			i == Xboom_1 && j == 3 ? 4 :
-			i == Xboom_1 && j == 4 ? 4 :
-			i == Xboom_1 && j == 5 ? 6 :
-			i == Xboom_1 && j == 6 ? 6 :
-			i == Xboom_1 && j == 7 ? 8 :
-			i == Xboom_2 && j == 0 ? 8 :
-			i == Xboom_2 && j == 1 ? 8 :
-			i == Xboom_2 && j == 2 ? 10 :
-			i == Xboom_2 && j == 3 ? 10 :
-			i == Xboom_2 && j == 4 ? 10 :
-			i == Xboom_2 && j == 5 ? 12 :
-			i == Xboom_2 && j == 6 ? 12 :
-			i == Xboom_2 && j == 7 ? 12 :
-			special_animation && j == 4 ? 3 :
-			effective_action != action ? 0 :
-			j);
-
-      xxx_effective_action = effective_action;
-      xxx_has_action_graphics = has_action_graphics;
-    }
-  }
-#endif
-
-  int frame = getAnimationFrame(g->anim_frames,
-				g->anim_delay,
-				g->anim_mode,
-				g->anim_start_frame,
-				sync_frame);
-
-
-#if 0
-  return;
-#endif
-
-#if 0
-  if (frame_em == 7)
-    return;
-#endif
-
-#if 0
-  int old_src_x = g_em->src_x;
-  int old_src_y = g_em->src_y;
-#endif
-
-#if 1
-  getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
-		      g->double_movement && is_backside);
-#else
-  getGraphicSourceExt(graphic, frame, &g_em->bitmap,
-		      &g_em->src_x, &g_em->src_y, FALSE);
-#endif
-
-
-#if 0
-  if (tile == Ydiamond_stone)
-    printf("::: stone smashing diamond... %d: %d, %d, %d, %d, %d -> %d [%d, %d, %d, %d, %d, %d] [%d]\n",
-	   frame_em,
-	   g->anim_frames,
-	   g->anim_delay,
-	   g->anim_mode,
-	   g->anim_start_frame,
-	   sync_frame,
-	   frame,
-	   g_em->src_x, g_em->src_y,
-	   g_em->src_offset_x, g_em->src_offset_y,
-	   g_em->dst_offset_x, g_em->dst_offset_y,
-	   graphic);
-#endif
-
-
-#if 0
-  return;
-#endif
-
-#if 0
-  if (frame_em == 7)
-  {
-    if (graphic == IMG_BUG_MOVING_RIGHT)
-      printf("::: %d, %d, %d: %d, %d [%d, %d -> %d, %d]\n", graphic, x, y,
-	     g->double_movement, is_backside,
-	     old_src_x, old_src_y, g_em->src_x, g_em->src_y);
-
-    return;
-  }
-#endif
-
-
-#if 0
-  g_em->src_offset_x = 0;
-  g_em->src_offset_y = 0;
-  g_em->dst_offset_x = 0;
-  g_em->dst_offset_y = 0;
-  g_em->width  = TILEX;
-  g_em->height = TILEY;
-
-  g_em->preserve_background = FALSE;
-#endif
-
-  /* (updating the "crumbled" graphic definitions is probably not really needed,
-     as animations for crumbled graphics can't be longer than one EMC cycle) */
-#if 1
-  set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
-			   sync_frame);
-
-#else
-
-  g_em->crumbled_bitmap = NULL;
-  g_em->crumbled_src_x = 0;
-  g_em->crumbled_src_y = 0;
-
-  g_em->has_crumbled_graphics = FALSE;
-
-  if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
-  {
-    int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
-					   g_crumbled->anim_delay,
-					   g_crumbled->anim_mode,
-					   g_crumbled->anim_start_frame,
-					   sync_frame);
-
-    getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
-		     &g_em->crumbled_src_x, &g_em->crumbled_src_y);
-
-    g_em->has_crumbled_graphics = TRUE;
-  }
-#endif
-
-#if 0
- {
-   int effective_action = xxx_effective_action;
-   int has_action_graphics = xxx_has_action_graphics;
-
-      if ((!g->double_movement && (effective_action == ACTION_FALLING ||
-				   effective_action == ACTION_MOVING  ||
-				   effective_action == ACTION_PUSHING ||
-				   effective_action == ACTION_EATING)) ||
-	  (!has_action_graphics && (effective_action == ACTION_FILLING ||
-				    effective_action == ACTION_EMPTYING)))
-      {
-	int move_dir =
-	  (effective_action == ACTION_FALLING ||
-	   effective_action == ACTION_FILLING ||
-	   effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
-	int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
-	int dy = (move_dir == MV_UP   ? -1 : move_dir == MV_DOWN  ? 1 : 0);
-	int num_steps = (i == Ydrip_s1  ? 16 :
-			 i == Ydrip_s1B ? 16 :
-			 i == Ydrip_s2  ? 16 :
-			 i == Ydrip_s2B ? 16 :
-			 i == Xsand_stonein_1 ? 32 :
-			 i == Xsand_stonein_2 ? 32 :
-			 i == Xsand_stonein_3 ? 32 :
-			 i == Xsand_stonein_4 ? 32 :
-			 i == Xsand_stoneout_1 ? 16 :
-			 i == Xsand_stoneout_2 ? 16 : 8);
-	int cx = ABS(dx) * (TILEX / num_steps);
-	int cy = ABS(dy) * (TILEY / num_steps);
-	int step_frame = (i == Ydrip_s2         ? j + 8 :
-			  i == Ydrip_s2B        ? j + 8 :
-			  i == Xsand_stonein_2  ? j + 8 :
-			  i == Xsand_stonein_3  ? j + 16 :
-			  i == Xsand_stonein_4  ? j + 24 :
-			  i == Xsand_stoneout_2 ? j + 8 : j) + 1;
-	int step = (is_backside ? step_frame : num_steps - step_frame);
+		  el_act_dir2crm(effective_element, effective_action,
+				 direction));
+  int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
+  int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
+  boolean has_crumbled_graphics = (base_crumbled != base_graphic);
+  struct GraphicInfo *g = &graphic_info[graphic];
+  int sync_frame;
 
-	if (is_backside)	/* tile where movement starts */
-	{
-	  if (dx < 0 || dy < 0)
-	  {
-	    g_em->src_offset_x = cx * step;
-	    g_em->src_offset_y = cy * step;
-	  }
-	  else
-	  {
-	    g_em->dst_offset_x = cx * step;
-	    g_em->dst_offset_y = cy * step;
-	  }
-	}
-	else			/* tile where movement ends */
-	{
-	  if (dx < 0 || dy < 0)
-	  {
-	    g_em->dst_offset_x = cx * step;
-	    g_em->dst_offset_y = cy * step;
-	  }
-	  else
-	  {
-	    g_em->src_offset_x = cx * step;
-	    g_em->src_offset_y = cy * step;
-	  }
-	}
+  /* special case: graphic uses "2nd movement tile" and has defined
+     7 frames for movement animation (or less) => use default graphic
+     for last (8th) frame which ends the movement animation */
+  if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
+  {
+    effective_action = ACTION_DEFAULT;
+    graphic = (direction == MV_NONE ?
+	       el_act2img(effective_element, effective_action) :
+	       el_act_dir2img(effective_element, effective_action,
+			      direction));
+    crumbled = (direction == MV_NONE ?
+		el_act2crm(effective_element, effective_action) :
+		el_act_dir2crm(effective_element, effective_action,
+			       direction));
 
-	g_em->width  = TILEX - cx * step;
-	g_em->height = TILEY - cy * step;
-      }
+    g = &graphic_info[graphic];
+  }
 
-      /* create unique graphic identifier to decide if tile must be redrawn */
-      /* bit 31 - 16 (16 bit): EM style graphic
-	 bit 15 - 12 ( 4 bit): EM style frame
-	 bit 11 -  6 ( 6 bit): graphic width
-	 bit  5 -  0 ( 6 bit): graphic height */
-      g_em->unique_identifier =
-	(graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
- }
-#endif
+  if (graphic_info[graphic].anim_global_sync)
+    sync_frame = FrameCounter;
+  else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
+    sync_frame = GfxFrame[x][y];
+  else
+    sync_frame = 0;	/* playfield border (pseudo steel) */
+
+  SetRandomAnimationValue(x, y);
+
+  int frame = getAnimationFrame(g->anim_frames,
+				g->anim_delay,
+				g->anim_mode,
+				g->anim_start_frame,
+				sync_frame);
+
+  getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
+		      g->double_movement && is_backside);
 
+  /* (updating the "crumbled" graphic definitions is probably not really needed,
+     as animations for crumbled graphics can't be longer than one EMC cycle) */
+  set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
+			   sync_frame);
 }
 
 void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em,
@@ -7654,22 +7694,10 @@ void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em,
 
   getGraphicSourceExt(graphic, frame, &g_em->bitmap,
 		      &g_em->src_x, &g_em->src_y, FALSE);
-
-#if 0
-  printf("::: %d: %d, %d [%d]\n",
-	 player_nr,
-	 stored_player[player_nr].Frame,
-	 stored_player[player_nr].StepFrame,
-	 FrameCounter);
-#endif
 }
 
 void InitGraphicInfo_EM(void)
 {
-#if 0
-  struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
-  struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
-#endif
   int i, j, p;
 
 #if DEBUG_EM_GFX
@@ -7741,11 +7769,6 @@ void InitGraphicInfo_EM(void)
     int action = object_mapping[i].action;
     int direction = object_mapping[i].direction;
     boolean is_backside = object_mapping[i].is_backside;
-#if 0
-    boolean action_removing = (action == ACTION_DIGGING ||
-			       action == ACTION_SNAPPING ||
-			       action == ACTION_COLLECTING);
-#endif
     boolean action_exploding = ((action == ACTION_EXPLODING ||
 				 action == ACTION_SMASHED_BY_ROCK ||
 				 action == ACTION_SMASHED_BY_SPRING) &&
@@ -7755,42 +7778,7 @@ void InitGraphicInfo_EM(void)
 
     for (j = 0; j < 8; j++)
     {
-#if 1
       int effective_element = get_effective_element_EM(i, j);
-#else
-      int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
-			       j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
-			       j < 7 ? element :
-			       i == Xdrip_stretch ? element :
-			       i == Xdrip_stretchB ? element :
-			       i == Ydrip_s1 ? element :
-			       i == Ydrip_s1B ? element :
-			       i == Xball_1B ? element :
-			       i == Xball_2 ? element :
-			       i == Xball_2B ? element :
-			       i == Yball_eat ? element :
-			       i == Ykey_1_eat ? element :
-			       i == Ykey_2_eat ? element :
-			       i == Ykey_3_eat ? element :
-			       i == Ykey_4_eat ? element :
-			       i == Ykey_5_eat ? element :
-			       i == Ykey_6_eat ? element :
-			       i == Ykey_7_eat ? element :
-			       i == Ykey_8_eat ? element :
-			       i == Ylenses_eat ? element :
-			       i == Ymagnify_eat ? element :
-			       i == Ygrass_eat ? element :
-			       i == Ydirt_eat ? element :
-			       i == Yemerald_stone ? EL_EMERALD :
-			       i == Ydiamond_stone ? EL_ROCK :
-			       i == Xsand_stonein_1 ? element :
-			       i == Xsand_stonein_2 ? element :
-			       i == Xsand_stonein_3 ? element :
-			       i == Xsand_stonein_4 ? element :
-			       is_backside ? EL_EMPTY :
-			       action_removing ? EL_EMPTY :
-			       element);
-#endif
       int effective_action = (j < 7 ? action :
 			      i == Xdrip_stretch ? action :
 			      i == Xdrip_stretchB ? action :
@@ -7832,9 +7820,6 @@ void InitGraphicInfo_EM(void)
       boolean has_action_graphics = (graphic != base_graphic);
       boolean has_crumbled_graphics = (base_crumbled != base_graphic);
       struct GraphicInfo *g = &graphic_info[graphic];
-#if 0
-      struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
-#endif
       struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
       Bitmap *src_bitmap;
       int src_x, src_y;
@@ -7973,75 +7958,9 @@ void InitGraphicInfo_EM(void)
 
       g_em->preserve_background = FALSE;
 
-#if 1
       set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
 			       sync_frame);
 
-#else
-
-      g_em->crumbled_bitmap = NULL;
-      g_em->crumbled_src_x = 0;
-      g_em->crumbled_src_y = 0;
-      g_em->crumbled_border_size = 0;
-
-      g_em->has_crumbled_graphics = FALSE;
-
-#if 0
-      if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
-	printf("::: empty crumbled: %d [%s], %d, %d\n",
-	       effective_element, element_info[effective_element].token_name,
-	       effective_action, direction);
-#endif
-
-      /* if element can be crumbled, but certain action graphics are just empty
-	 space (like instantly snapping sand to empty space in 1 frame), do not
-	 treat these empty space graphics as crumbled graphics in EMC engine */
-      if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
-      {
-	int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
-					       g_crumbled->anim_delay,
-					       g_crumbled->anim_mode,
-					       g_crumbled->anim_start_frame,
-					       sync_frame);
-
-	getGraphicSource(crumbled, frame_crumbled, &src_bitmap, &src_x, &src_y);
-
-	g_em->has_crumbled_graphics = TRUE;
-	g_em->crumbled_bitmap = src_bitmap;
-	g_em->crumbled_src_x = src_x;
-	g_em->crumbled_src_y = src_y;
-	g_em->crumbled_border_size = graphic_info[crumbled].border_size;
-
-
-#if 0
-	if (g_em == &graphic_info_em_object[207][0])
-	  printf("... %d, %d [%d, %d, %d, %d] [%d, %d, %d, %d, %d, %d => %d]\n",
-		 graphic_info_em_object[207][0].crumbled_src_x,
-		 graphic_info_em_object[207][0].crumbled_src_y,
-
-		 crumbled, frame, src_x, src_y,
-
-		 g->anim_frames,
-		 g->anim_delay,
-		 g->anim_mode,
-		 g->anim_start_frame,
-		 sync_frame,
-		 gfx.anim_random_frame,
-		 frame);
-#endif
-
-#if 0
-	printf("::: EMC tile %d is crumbled\n", i);
-#endif
-      }
-#endif
-
-#if 0
-      if (element == EL_ROCK &&
-	  effective_action == ACTION_FILLING)
-	printf("::: has_action_graphics == %d\n", has_action_graphics);
-#endif
-
       if ((!g->double_movement && (effective_action == ACTION_FALLING ||
 				   effective_action == ACTION_MOVING  ||
 				   effective_action == ACTION_PUSHING ||
@@ -8332,31 +8251,67 @@ void InitGraphicInfo_EM(void)
 #endif
 }
 
-void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
-			    boolean any_player_moving)
+void CheckSaveEngineSnapshot_EM(byte action[MAX_PLAYERS], int frame,
+				boolean any_player_moving,
+				boolean any_player_snapping,
+				boolean any_player_dropping)
 {
-  int i;
+  if (frame == 0 && !any_player_dropping)
+  {
+    if (!local_player->was_waiting)
+    {
+      if (!CheckSaveEngineSnapshotToList())
+	return;
 
-  if (tape.single_step && tape.recording && !tape.pausing)
+      local_player->was_waiting = TRUE;
+    }
+  }
+  else if (any_player_moving || any_player_snapping || any_player_dropping)
+  {
+    local_player->was_waiting = FALSE;
+  }
+}
+
+void CheckSaveEngineSnapshot_SP(boolean murphy_is_waiting,
+				boolean murphy_is_dropping)
+{
+  if (murphy_is_waiting)
   {
-    boolean active_players = FALSE;
+    if (!local_player->was_waiting)
+    {
+      if (!CheckSaveEngineSnapshotToList())
+	return;
 
-    for (i = 0; i < MAX_PLAYERS; i++)
-      if (action[i] != JOY_NO_ACTION)
-	active_players = TRUE;
+      local_player->was_waiting = TRUE;
+    }
+  }
+  else
+  {
+    local_player->was_waiting = FALSE;
+  }
+}
 
-    if (frame == 0)
+void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
+			    boolean any_player_moving,
+			    boolean any_player_snapping,
+			    boolean any_player_dropping)
+{
+  if (tape.single_step && tape.recording && !tape.pausing)
+    if (frame == 0 && !any_player_dropping)
       TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
-  }
+
+  CheckSaveEngineSnapshot_EM(action, frame, any_player_moving,
+			     any_player_snapping, any_player_dropping);
 }
 
-void CheckSingleStepMode_SP(boolean murphy_is_moving)
+void CheckSingleStepMode_SP(boolean murphy_is_waiting,
+			    boolean murphy_is_dropping)
 {
   if (tape.single_step && tape.recording && !tape.pausing)
-  {
-    if (!murphy_is_moving)
+    if (murphy_is_waiting)
       TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
-  }
+
+  CheckSaveEngineSnapshot_SP(murphy_is_waiting, murphy_is_dropping);
 }
 
 void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
@@ -8443,7 +8398,37 @@ void PlayMenuMusicExt(int music)
 
 void PlayMenuMusic()
 {
-  PlayMenuMusicExt(menu.music[game_status]);
+  char *curr_music = getCurrentlyPlayingMusicFilename();
+  char *next_music = getMusicListEntry(menu.music[game_status])->filename;
+
+  if (!strEqual(curr_music, next_music))
+    PlayMenuMusicExt(menu.music[game_status]);
+}
+
+void PlayMenuSoundsAndMusic()
+{
+  PlayMenuSound();
+  PlayMenuMusic();
+}
+
+static void FadeMenuSounds()
+{
+  FadeSounds();
+}
+
+static void FadeMenuMusic()
+{
+  char *curr_music = getCurrentlyPlayingMusicFilename();
+  char *next_music = getMusicListEntry(menu.music[game_status])->filename;
+
+  if (!strEqual(curr_music, next_music))
+    FadeMusic();
+}
+
+void FadeMenuSoundsAndMusic()
+{
+  FadeMenuSounds();
+  FadeMenuMusic();
 }
 
 void PlaySoundActivating()
@@ -8460,33 +8445,56 @@ void PlaySoundSelecting()
 #endif
 }
 
-void ToggleFullscreenIfNeeded()
+void ToggleFullscreenOrChangeWindowScalingIfNeeded()
 {
   boolean change_fullscreen = (setup.fullscreen !=
 			       video.fullscreen_enabled);
-  boolean change_fullscreen_mode = (video.fullscreen_enabled &&
-				    !strEqual(setup.fullscreen_mode,
-					      video.fullscreen_mode_current));
+  boolean change_window_scaling_percent = (!video.fullscreen_enabled &&
+					   setup.window_scaling_percent !=
+					   video.window_scaling_percent);
+
+  if (change_window_scaling_percent && video.fullscreen_enabled)
+    return;
+
+  if (!change_window_scaling_percent && !video.fullscreen_available)
+    return;
+
+#if defined(TARGET_SDL2)
+  if (change_window_scaling_percent)
+  {
+    SDLSetWindowScaling(setup.window_scaling_percent);
+
+    return;
+  }
+  else if (change_fullscreen)
+  {
+    SDLSetWindowFullscreen(setup.fullscreen);
+
+    /* set setup value according to successfully changed fullscreen mode */
+    setup.fullscreen = video.fullscreen_enabled;
 
-  if (!video.fullscreen_available)
     return;
+  }
+#endif
 
-  if (change_fullscreen || change_fullscreen_mode)
+  if (change_fullscreen ||
+      change_window_scaling_percent)
   {
     Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
 
     /* save backbuffer content which gets lost when toggling fullscreen mode */
     BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
 
-    if (change_fullscreen_mode)
+    if (change_window_scaling_percent)
     {
-      /* keep fullscreen, but change fullscreen mode (screen resolution) */
-      video.fullscreen_enabled = FALSE;		/* force new fullscreen mode */
+      /* keep window mode, but change window scaling */
+      video.fullscreen_enabled = TRUE;		/* force new window scaling */
     }
 
     /* toggle fullscreen */
     ChangeVideoModeIfNeeded(setup.fullscreen);
 
+    /* set setup value according to successfully changed fullscreen mode */
     setup.fullscreen = video.fullscreen_enabled;
 
     /* restore backbuffer content from temporary backbuffer backup bitmap */
@@ -8494,89 +8502,281 @@ void ToggleFullscreenIfNeeded()
 
     FreeBitmap(tmp_backbuffer);
 
-#if 1
     /* update visible window/screen */
     BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
-#else
-    redraw_mask = REDRAW_ALL;
-#endif
   }
 }
 
-void ChangeViewportPropertiesIfNeeded()
+void JoinRectangles(int *x, int *y, int *width, int *height,
+		    int x2, int y2, int width2, int height2)
 {
-  int *door_1_x = &DX;
-  int *door_1_y = &DY;
-  int *door_2_x = (game_status == GAME_MODE_EDITOR ? &EX : &VX);
-  int *door_2_y = (game_status == GAME_MODE_EDITOR ? &EY : &VY);
-  int gfx_game_mode = (game_status == GAME_MODE_PLAYING ||
-		       game_status == GAME_MODE_EDITOR ? game_status :
-		       GAME_MODE_MAIN);
-  struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
-  struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode];
-  struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode];
-  int border_size = vp_playfield->border_size;
-  int new_sx = vp_playfield->x + border_size;
-  int new_sy = vp_playfield->y + border_size;
-  int new_scr_fieldx = (vp_playfield->width  - 2 * border_size) / TILESIZE;
-  int new_scr_fieldy = (vp_playfield->height - 2 * border_size) / TILESIZE;
+  // do not join with "off-screen" rectangle
+  if (x2 == -1 || y2 == -1)
+    return;
 
-#if 0
-  /* !!! TEST ONLY !!! */
-  // InitGfxBuffers();
-  return;
-#endif
+  *x = MIN(*x, x2);
+  *y = MIN(*y, y2);
+  *width = MAX(*width, width2);
+  *height = MAX(*height, height2);
+}
 
-  if (viewport.window.width  != WIN_XSIZE ||
-      viewport.window.height != WIN_YSIZE)
-  {
-    WIN_XSIZE = viewport.window.width;
-    WIN_YSIZE = viewport.window.height;
+void SetAnimStatus(int anim_status_new)
+{
+  if (anim_status_new == GAME_MODE_MAIN)
+    anim_status_new = GAME_MODE_PSEUDO_MAINONLY;
 
-    InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
-    InitGfxBuffers();
+  global.anim_status_next = anim_status_new;
 
-#if 1
-    SetDrawDeactivationMask(REDRAW_NONE);
-    SetDrawBackgroundMask(REDRAW_FIELD);
+  // directly set screen modes that are entered without fading
+  if ((global.anim_status      == GAME_MODE_PSEUDO_MAINONLY &&
+       global.anim_status_next == GAME_MODE_PSEUDO_TYPENAME) ||
+      (global.anim_status      == GAME_MODE_PSEUDO_TYPENAME &&
+       global.anim_status_next == GAME_MODE_PSEUDO_MAINONLY))
+    global.anim_status = global.anim_status_next;
+}
 
-    // RedrawBackground();
-#endif
+void SetGameStatus(int game_status_new)
+{
+  if (game_status_new != game_status)
+    game_status_last_screen = game_status;
+
+  game_status = game_status_new;
+
+  SetAnimStatus(game_status_new);
+}
+
+void SetFontStatus(int game_status_new)
+{
+  static int last_game_status = -1;
+
+  if (game_status_new != -1)
+  {
+    // set game status for font use after storing last game status
+    last_game_status = game_status;
+    game_status = game_status_new;
+  }
+  else
+  {
+    // reset game status after font use from last stored game status
+    game_status = last_game_status;
+  }
+}
+
+void ResetFontStatus()
+{
+  SetFontStatus(-1);
+}
+
+void ChangeViewportPropertiesIfNeeded()
+{
+  int gfx_game_mode = game_status;
+  int gfx_game_mode2 = (game_status == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
+			game_status);
+  struct RectWithBorder *vp_window    = &viewport.window[gfx_game_mode];
+  struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
+  struct RectWithBorder *vp_door_1    = &viewport.door_1[gfx_game_mode];
+  struct RectWithBorder *vp_door_2    = &viewport.door_2[gfx_game_mode2];
+  struct RectWithBorder *vp_door_3    = &viewport.door_2[GAME_MODE_EDITOR];
+  int new_win_xsize	= vp_window->width;
+  int new_win_ysize	= vp_window->height;
+  int border_size	= vp_playfield->border_size;
+  int new_sx		= vp_playfield->x + border_size;
+  int new_sy		= vp_playfield->y + border_size;
+  int new_sxsize	= vp_playfield->width  - 2 * border_size;
+  int new_sysize	= vp_playfield->height - 2 * border_size;
+  int new_real_sx	= vp_playfield->x;
+  int new_real_sy	= vp_playfield->y;
+  int new_full_sxsize	= vp_playfield->width;
+  int new_full_sysize	= vp_playfield->height;
+  int new_dx		= vp_door_1->x;
+  int new_dy		= vp_door_1->y;
+  int new_dxsize	= vp_door_1->width;
+  int new_dysize	= vp_door_1->height;
+  int new_vx		= vp_door_2->x;
+  int new_vy		= vp_door_2->y;
+  int new_vxsize	= vp_door_2->width;
+  int new_vysize	= vp_door_2->height;
+  int new_ex		= vp_door_3->x;
+  int new_ey		= vp_door_3->y;
+  int new_exsize	= vp_door_3->width;
+  int new_eysize	= vp_door_3->height;
+  int new_tilesize_var =
+    (setup.small_game_graphics ? MINI_TILESIZE : game.tile_size);
+
+  int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var :
+		  gfx_game_mode == GAME_MODE_EDITOR ? MINI_TILESIZE : TILESIZE);
+  int new_scr_fieldx = new_sxsize / tilesize;
+  int new_scr_fieldy = new_sysize / tilesize;
+  int new_scr_fieldx_buffers = new_sxsize / new_tilesize_var;
+  int new_scr_fieldy_buffers = new_sysize / new_tilesize_var;
+  boolean init_gfx_buffers = FALSE;
+  boolean init_video_buffer = FALSE;
+  boolean init_gadgets_and_anims = FALSE;
+  boolean init_em_graphics = FALSE;
+
+  if (new_win_xsize != WIN_XSIZE ||
+      new_win_ysize != WIN_YSIZE)
+  {
+    WIN_XSIZE = new_win_xsize;
+    WIN_YSIZE = new_win_ysize;
+
+    init_video_buffer = TRUE;
+    init_gfx_buffers = TRUE;
+    init_gadgets_and_anims = TRUE;
+
+    // printf("::: video: init_video_buffer, init_gfx_buffers\n");
   }
 
   if (new_scr_fieldx != SCR_FIELDX ||
-      new_scr_fieldy != SCR_FIELDY ||
-      new_sx != SX ||
-      new_sy != SY ||
-      vp_playfield->x != REAL_SX ||
-      vp_playfield->y != REAL_SY ||
-      vp_door_1->x != *door_1_x ||
-      vp_door_1->y != *door_1_y ||
-      vp_door_2->x != *door_2_x ||
-      vp_door_2->y != *door_2_y)
+      new_scr_fieldy != SCR_FIELDY)
   {
+    /* this always toggles between MAIN and GAME when using small tile size */
+
     SCR_FIELDX = new_scr_fieldx;
     SCR_FIELDY = new_scr_fieldy;
-    SX = new_sx;
-    SY = new_sy;
-    REAL_SX = vp_playfield->x;
-    REAL_SY = vp_playfield->y;
 
-    *door_1_x = vp_door_1->x;
-    *door_1_y = vp_door_1->y;
-    *door_2_x = vp_door_2->x;
-    *door_2_y = vp_door_2->y;
+    // printf("::: new_scr_fieldx != SCR_FIELDX ...\n");
+  }
 
-    InitGfxBuffers();
+  if (new_sx != SX ||
+      new_sy != SY ||
+      new_dx != DX ||
+      new_dy != DY ||
+      new_vx != VX ||
+      new_vy != VY ||
+      new_ex != EX ||
+      new_ey != EY ||
+      new_sxsize != SXSIZE ||
+      new_sysize != SYSIZE ||
+      new_dxsize != DXSIZE ||
+      new_dysize != DYSIZE ||
+      new_vxsize != VXSIZE ||
+      new_vysize != VYSIZE ||
+      new_exsize != EXSIZE ||
+      new_eysize != EYSIZE ||
+      new_real_sx != REAL_SX ||
+      new_real_sy != REAL_SY ||
+      new_full_sxsize != FULL_SXSIZE ||
+      new_full_sysize != FULL_SYSIZE ||
+      new_tilesize_var != TILESIZE_VAR
+      )
+  {
+    // ------------------------------------------------------------------------
+    // determine next fading area for changed viewport definitions
+    // ------------------------------------------------------------------------
+
+    // start with current playfield area (default fading area)
+    FADE_SX = REAL_SX;
+    FADE_SY = REAL_SY;
+    FADE_SXSIZE = FULL_SXSIZE;
+    FADE_SYSIZE = FULL_SYSIZE;
+
+    // add new playfield area if position or size has changed
+    if (new_real_sx != REAL_SX || new_real_sy != REAL_SY ||
+	new_full_sxsize != FULL_SXSIZE || new_full_sysize != FULL_SYSIZE)
+    {
+      JoinRectangles(&FADE_SX, &FADE_SY, &FADE_SXSIZE, &FADE_SYSIZE,
+		     new_real_sx, new_real_sy, new_full_sxsize,new_full_sysize);
+    }
+
+    // add current and new door 1 area if position or size has changed
+    if (new_dx != DX || new_dy != DY ||
+	new_dxsize != DXSIZE || new_dysize != DYSIZE)
+    {
+      JoinRectangles(&FADE_SX, &FADE_SY, &FADE_SXSIZE, &FADE_SYSIZE,
+		     DX, DY, DXSIZE, DYSIZE);
+      JoinRectangles(&FADE_SX, &FADE_SY, &FADE_SXSIZE, &FADE_SYSIZE,
+		     new_dx, new_dy, new_dxsize, new_dysize);
+    }
+
+    // add current and new door 2 area if position or size has changed
+    if (new_dx != VX || new_dy != VY ||
+	new_dxsize != VXSIZE || new_dysize != VYSIZE)
+    {
+      JoinRectangles(&FADE_SX, &FADE_SY, &FADE_SXSIZE, &FADE_SYSIZE,
+		     VX, VY, VXSIZE, VYSIZE);
+      JoinRectangles(&FADE_SX, &FADE_SY, &FADE_SXSIZE, &FADE_SYSIZE,
+		     new_vx, new_vy, new_vxsize, new_vysize);
+    }
+
+    // ------------------------------------------------------------------------
+    // handle changed tile size
+    // ------------------------------------------------------------------------
 
-    if (gfx_game_mode == GAME_MODE_MAIN)
+    if (new_tilesize_var != TILESIZE_VAR)
     {
-      InitGadgets();
-      InitToons();
+      // printf("::: new_tilesize_var != TILESIZE_VAR\n");
+
+      // changing tile size invalidates scroll values of engine snapshots
+      FreeEngineSnapshotSingle();
+
+      // changing tile size requires update of graphic mapping for EM engine
+      init_em_graphics = TRUE;
     }
+
+    SX = new_sx;
+    SY = new_sy;
+    DX = new_dx;
+    DY = new_dy;
+    VX = new_vx;
+    VY = new_vy;
+    EX = new_ex;
+    EY = new_ey;
+    SXSIZE = new_sxsize;
+    SYSIZE = new_sysize;
+    DXSIZE = new_dxsize;
+    DYSIZE = new_dysize;
+    VXSIZE = new_vxsize;
+    VYSIZE = new_vysize;
+    EXSIZE = new_exsize;
+    EYSIZE = new_eysize;
+    REAL_SX = new_real_sx;
+    REAL_SY = new_real_sy;
+    FULL_SXSIZE = new_full_sxsize;
+    FULL_SYSIZE = new_full_sysize;
+    TILESIZE_VAR = new_tilesize_var;
+
+    init_gfx_buffers = TRUE;
+    init_gadgets_and_anims = TRUE;
+
+    // printf("::: viewports: init_gfx_buffers\n");
+    // printf("::: viewports: init_gadgets_and_anims\n");
+  }
+
+  if (init_gfx_buffers)
+  {
+    // printf("::: init_gfx_buffers\n");
+
+    SCR_FIELDX = new_scr_fieldx_buffers;
+    SCR_FIELDY = new_scr_fieldy_buffers;
+
+    InitGfxBuffers();
+
+    SCR_FIELDX = new_scr_fieldx;
+    SCR_FIELDY = new_scr_fieldy;
+
+    SetDrawDeactivationMask(REDRAW_NONE);
+    SetDrawBackgroundMask(REDRAW_FIELD);
   }
 
-#if 0
-  printf("::: %d, %d  /  %d, %d [%d]\n", VX, VY, EX, EY, game_status);
-#endif
+  if (init_video_buffer)
+  {
+    // printf("::: init_video_buffer\n");
+
+    InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
+    InitImageTextures();
+  }
+
+  if (init_gadgets_and_anims)
+  {
+    // printf("::: init_gadgets_and_anims\n");
+
+    InitGadgets();
+    InitGlobalAnimations();
+  }
+
+  if (init_em_graphics)
+  {
+      InitGraphicInfo_EM();
+  }
 }
diff --git a/src/tools.h b/src/tools.h
index 510524a..b267c8b 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info at artsoft.org                   *
-*----------------------------------------------------------*
-* tools.h                                                  *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//     		    Holger Schemel
+//		    info at artsoft.org
+//		    http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// tools.h
+// ============================================================================
 
 #ifndef TOOLS_H
 #define TOOLS_H
@@ -17,9 +15,6 @@
 #include "main.h"
 #include "game.h"
 
-/* for SetDrawtoField */
-#define DRAW_BUFFERED		1
-#define DRAW_BACKBUFFER		2
 
 /* for DrawElementShifted */
 #define NO_CUTTING		0
@@ -49,6 +44,16 @@
 #define DOOR_GET_STATE		(1 << 8)
 #define DOOR_SET_STATE		(1 << 9)
 
+#define DOOR_1			(DOOR_ACTION_1)
+#define DOOR_2			(DOOR_ACTION_2)
+#define DOOR_OPEN		(DOOR_OPEN_ALL)
+#define DOOR_CLOSE		(DOOR_CLOSE_ALL)
+
+#define DOOR_INDEX_FROM_TOKEN(x)	((x) == DOOR_1 ? 0 : 1)
+#define DOOR_TOKEN_FROM_INDEX(x)	((x) == 0 ? DOOR_1 ? : DOOR_2)
+#define REDRAW_DOOR_FROM_TOKEN(x)	((x) == DOOR_1 ? REDRAW_DOOR_1 : \
+					 REDRAW_DOOR_2)
+
 /* for Request */
 #define REQ_ASK			(1 << 0)
 #define REQ_CONFIRM		(1 << 1)
@@ -59,7 +64,15 @@
 
 #define REQUEST_WAIT_FOR_INPUT	(REQ_ASK | REQ_CONFIRM | REQ_PLAYER)
 
+
+int correctLevelPosX_EM(int);
+int correctLevelPosY_EM(int);
+
+int getLevelFromScreenX(int);
+int getLevelFromScreenY(int);
+
 void DumpTile(int, int);
+void DumpTileFromScreen(int, int);
 
 void DrawMaskedBorder_FIELD();
 void DrawMaskedBorder_DOOR_1();
@@ -67,10 +80,14 @@ void DrawMaskedBorder_DOOR_2();
 void DrawMaskedBorder_DOOR_3();
 void DrawMaskedBorder_ALL();
 void DrawMaskedBorder(int);
+void DrawMaskedBorderToTarget(int);
 
 void SetDrawtoField(int);
-void RedrawPlayfield(boolean, int, int, int, int);
+void RedrawPlayfield();
+void BlitScreenToBitmap_RND(Bitmap *);
+void BlitScreenToBitmap(Bitmap *);
 void BackToFront();
+void BackToFront_WithFrameDelay(unsigned int);
 
 void FadeIn(int);
 void FadeOut(int);
@@ -84,6 +101,8 @@ void FadeSetDisabled();
 void FadeSkipNextFadeIn();
 void FadeSkipNextFadeOut();
 
+Bitmap *getGlobalBorderBitmapFromStatus(int);
+
 void ClearField();
 void SetWindowBackgroundImageIfDefined(int);
 void SetMainBackgroundImageIfDefined(int);
@@ -95,6 +114,8 @@ void SetPanelBackground();
 void DrawBackground(int, int, int, int);
 void DrawBackgroundForFont(int, int, int, int, int);
 void DrawBackgroundForGraphic(int, int, int, int, int);
+boolean CheckIfGlobalBorderHasChanged();
+void RedrawGlobalBorder();
 
 void MarkTileDirty(int, int);
 void SetBorderElement();
@@ -103,8 +124,10 @@ void FloodFillLevel(int, int, int, short[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
 
 void SetRandomAnimationValue(int, int);
 int getGraphicAnimationFrame(int, int);
-void DrawGraphicAnimationExt(DrawBuffer *, int, int, int, int, int);
-void DrawGraphicAnimation(int, int, int);
+
+void DrawFixedGraphicAnimation(int, int, int);
+void DrawFixedGraphicAnimationExt(DrawBuffer *, int, int, int, int, int);
+
 void DrawLevelGraphicAnimation(int, int, int);
 void DrawLevelElementAnimation(int, int, int);
 void DrawLevelGraphicAnimationIfNeeded(int, int, int);
@@ -114,17 +137,28 @@ void DrawAllPlayers(void);
 void DrawPlayerField(int, int);
 void DrawPlayer(struct PlayerInfo *);
 
+void getGraphicSourceBitmap(int, int, Bitmap **);
+void getGraphicSourceXY(int, int, int *, int *, boolean);
+void getSizedGraphicSourceExt(int, int, int, Bitmap **, int *, int *, boolean);
+void getFixedGraphicSourceExt(int, int, Bitmap **, int *, int *, boolean);
 void getSizedGraphicSource(int, int, int, Bitmap **, int *, int *);
+void getFixedGraphicSource(int, int, Bitmap **, int *, int *);
 void getMiniGraphicSource(int, Bitmap **, int *, int *);
-void getGraphicSourceExt(int, int, Bitmap **, int *, int *, boolean);
 void getGraphicSource(int, int, Bitmap **, int *, int *);
+
 void DrawGraphic(int, int, int, int);
 void DrawGraphicExt(DrawBuffer *, int, int, int, int);
 void DrawGraphicThruMask(int, int, int, int);
 void DrawGraphicThruMaskExt(DrawBuffer *, int, int, int, int);
 
+void DrawFixedGraphic(int, int, int, int);
+void DrawFixedGraphicExt(DrawBuffer *, int, int, int, int);
+void DrawFixedGraphicThruMask(int, int, int, int);
+void DrawFixedGraphicThruMaskExt(DrawBuffer *, int, int, int, int);
+
 void DrawSizedGraphic(int, int, int, int, int);
 void DrawSizedGraphicExt(DrawBuffer *, int, int, int, int, int);
+
 void DrawMiniGraphic(int, int, int);
 void DrawMiniGraphicExt(DrawBuffer *, int, int, int);
 
@@ -143,18 +177,25 @@ void DrawLevelElement(int, int, int);
 void DrawScreenField(int, int);
 void DrawLevelField(int, int);
 
+void DrawSizedElement(int, int, int, int);
+void DrawSizedElementOrWall(int, int, int, int, int);
+
 void DrawMiniElement(int, int, int);
 void DrawMiniElementOrWall(int, int, int, int);
 
 void ShowEnvelope(int);
 void ShowEnvelopeDoor(char *text, int);
 
-void DrawLevel(void);
+void DrawLevel(int);
+void DrawSizedLevel(int, int, int, int, int);
 void DrawMiniLevel(int, int, int, int);
-void DrawPreviewLevel(boolean);
+void DrawPreviewLevelInitial(void);
+void DrawPreviewLevelAnimation(void);
 
-void WaitForEventToContinue();
+void WaitForEventToContinue(void);
 boolean Request(char *, unsigned int);
+void InitGraphicCompatibilityInfo_Doors(void);
+void InitDoors(void);
 unsigned int OpenDoor(unsigned int);
 unsigned int CloseDoor(unsigned int);
 unsigned int GetDoorState(void);
@@ -202,7 +243,7 @@ int getBeltElementFromBeltNrAndBeltDir(int, int);
 int getBeltSwitchElementFromBeltNrAndBeltDirNr(int, int);
 int getBeltSwitchElementFromBeltNrAndBeltDir(int, int);
 
-unsigned int InitRND(long);
+unsigned int InitRND(int);
 void InitGraphicInfo_EM(void);
 
 void PlayMenuSoundExt(int);
@@ -212,10 +253,17 @@ void PlayMenuSoundIfLoopExt(int);
 void PlayMenuSoundIfLoop();
 void PlayMenuMusicExt(int);
 void PlayMenuMusic();
+void PlayMenuSoundsAndMusic();
+void FadeMenuSoundsAndMusic();
 void PlaySoundActivating();
 void PlaySoundSelecting();
 
-void ToggleFullscreenIfNeeded();
+void SetAnimStatus(int);
+void SetGameStatus(int);
+void SetFontStatus(int);
+void ResetFontStatus();
+
+void ToggleFullscreenOrChangeWindowScalingIfNeeded();
 void ChangeViewportPropertiesIfNeeded();
 
 #endif	/* TOOLS_H */

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/collab-maint/rocksndiamonds.git



More information about the Pkg-games-commits mailing list