Merge branch 'master' into releases 3.3.0.0
authorHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2014 08:59:16 +0000 (10:59 +0200)
committerHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2014 08:59:16 +0000 (10:59 +0200)
98 files changed:
CHANGES [deleted file]
CREDITS
ChangeLog
HARDWARE [deleted file]
Makefile
src/Makefile
src/cartoons.c
src/conf_e2g.c
src/conf_gfx.c
src/conf_gfx.h
src/conf_var.c
src/conftime.h
src/editor.c
src/engines.h
src/events.c
src/files.c
src/files.h
src/game.c
src/game.h
src/game_em/Makefile
src/game_em/graphics.c
src/game_em/input.c
src/game_em/main_em.h
src/game_sp/ASM.c [new file with mode: 0644]
src/game_sp/ASM.h [new file with mode: 0644]
src/game_sp/BugsTerminals.c [new file with mode: 0644]
src/game_sp/BugsTerminals.h [new file with mode: 0644]
src/game_sp/DDScrollBuffer.c [new file with mode: 0644]
src/game_sp/DDScrollBuffer.h [new file with mode: 0644]
src/game_sp/DDSpriteBuffer.c [new file with mode: 0644]
src/game_sp/DDSpriteBuffer.h [new file with mode: 0644]
src/game_sp/Display.c [new file with mode: 0644]
src/game_sp/Display.h [new file with mode: 0644]
src/game_sp/DoGameStuff.c [new file with mode: 0644]
src/game_sp/DoGameStuff.h [new file with mode: 0644]
src/game_sp/Electrons.c [new file with mode: 0644]
src/game_sp/Electrons.h [new file with mode: 0644]
src/game_sp/Explosions.c [new file with mode: 0644]
src/game_sp/Explosions.h [new file with mode: 0644]
src/game_sp/Globals.c [new file with mode: 0644]
src/game_sp/Globals.h [new file with mode: 0644]
src/game_sp/Infotrons.c [new file with mode: 0644]
src/game_sp/Infotrons.h [new file with mode: 0644]
src/game_sp/InitGameConditions.c [new file with mode: 0644]
src/game_sp/InitGameConditions.h [new file with mode: 0644]
src/game_sp/Input.c [new file with mode: 0644]
src/game_sp/Input.h [new file with mode: 0644]
src/game_sp/MainForm.c [new file with mode: 0644]
src/game_sp/MainForm.h [new file with mode: 0644]
src/game_sp/MainGameLoop.c [new file with mode: 0644]
src/game_sp/MainGameLoop.h [new file with mode: 0644]
src/game_sp/Makefile [new file with mode: 0644]
src/game_sp/Murphy.c [new file with mode: 0644]
src/game_sp/Murphy.h [new file with mode: 0644]
src/game_sp/OrangeDisk.c [new file with mode: 0644]
src/game_sp/OrangeDisk.h [new file with mode: 0644]
src/game_sp/SnikSnaks.c [new file with mode: 0644]
src/game_sp/SnikSnaks.h [new file with mode: 0644]
src/game_sp/Sound.c [new file with mode: 0644]
src/game_sp/Sound.h [new file with mode: 0644]
src/game_sp/Zonk.c [new file with mode: 0644]
src/game_sp/Zonk.h [new file with mode: 0644]
src/game_sp/export.h [new file with mode: 0644]
src/game_sp/file.c [new file with mode: 0644]
src/game_sp/game_sp.h [new file with mode: 0644]
src/game_sp/global.h [new file with mode: 0644]
src/game_sp/init.c [new file with mode: 0644]
src/game_sp/main.c [new file with mode: 0644]
src/game_sp/main_sp.h [new file with mode: 0644]
src/game_sp/vb_lib.c [new file with mode: 0644]
src/game_sp/vb_lib.h [new file with mode: 0644]
src/init.c
src/init.h
src/libgame/Makefile
src/libgame/gadgets.c
src/libgame/hash.h
src/libgame/libgame.h
src/libgame/misc.c
src/libgame/misc.h
src/libgame/sdl.c
src/libgame/setup.c
src/libgame/setup.h
src/libgame/snapshot.c [new file with mode: 0644]
src/libgame/snapshot.h [new file with mode: 0644]
src/libgame/system.c
src/libgame/system.h
src/libgame/text.c
src/libgame/text.h
src/libgame/types.h
src/libgame/x11.c
src/libgame/x11.h
src/main.c
src/main.h
src/screens.c
src/tape.c
src/tape.h
src/tools.c
src/tools.h

diff --git a/CHANGES b/CHANGES
deleted file mode 100644 (file)
index e7218e4..0000000
--- a/CHANGES
+++ /dev/null
@@ -1,437 +0,0 @@
-Release Version 3.1.1 [16 AUG 2005]
------------------------------------
-       - added tutorial level set created by Aaron Davidson
-       - added editor element descriptions written by Aaron Davidson
-       - added native game engine for Emerald Mine (Club) levels
-       - added level skipping functionality to main menu
-       - added support for dumping small-sized level sketches from editor
-       - added use of "editorsetup.conf" for different level sets
-       - lots of bugfixes and internal engine changes (see ChangeLog)
-
-Release Version 3.1.0 [07 JUN 2004]
------------------------------------
-       - fixed obvious bug with wrong "Murphy" graphics (when digging etc.)
-       - fixed a lot of Emerald Mine and Supaplex game engine emulation bugs
-       - re-converted Emerald Mine and Supaplex levels to apply engine fixes
-       - changed default snap/drop keys from left/right Shift to Control keys
-       - added level loader for loading native Emerald Mine levels
-       - added level loader for loading native Supaplex packed levels
-       - added group elements for multiple matches and random element creation
-       - added elements that can be digged or left behind by custom elements
-       - added element "Sokoban field with player" missing for Sokoban levels
-       - added custom element features to allow building of teleporters
-       - added option to use step limit instead of time limit for level
-       - added pressing "space" key as valid action to select menu options
-       - added clipboard (cut and paste buttons) for custom and group elements
-       - added shortcut to dump brush (type ":DB" in editor) for use in forum
-       - added network multiplayer code for Windows (still only command line)
-       - replaced old tutorial level set with far better one by Niko Böhm
-       - "contributions" levels now separate package to make base set smaller
-       - too many bugfixes and changes to list them all here (see ChangeLog)
-
-Release Version 3.0.8 [14 DEC 2003]
------------------------------------
-       - added "musicinfo.conf" for menu and level music configuration
-       - added "editorsetup.conf" for editor element list configuration
-       - added "copy" and "exchange" functions for custom elements to editor
-       - added configurable "bored" and "sleeping" animations for the player
-       - added "awakening" sound for player when waking up after sleeping
-       - added configurable element animations for info screen
-       - added configurable music credits for info screen
-       - added configurable level set information for info screen
-       - added warnings for undefined token values in artwork config files
-       - menu entries now also selectable by clicking on entry text
-       - better sniksnak turning movement (two steps instead of only one)
-       - fixed turning movement of butterflies and fireflies (no frame reset)
-       - fixed bug with wrong default impact sound for colored emeralds
-       - fixed bug with double nut cracking sound
-       - fixed a very nasty bug in dragon turning code in TurnRoundExt()
-       - finally fixed tape recording when player is created from CE change
-       - added new contributed levels from the following players:
-         + Audrius Saikunas (4 levels)
-         + Efraim Yawitz (20 levels)
-         + Krystian Abramowicz (100 levels)
-         + Paul E Collins (formerly known as Equinox Tetrachloride; 64 levels)
-         + Sebastian Simon (12 levels)
-       - amazing new level set:
-         + "BD2K3" from Alan Bond
-         + 43 levels full of BD nostalgia, action and fantastic effects
-         + overwhelming use of custom elements
-         + complete artwork set with graphics, sounds and music
-         + available as a separate download from www.artsoft.org
-       - another great level set was updated:
-         + "jue2" from Jürgen Bonhagen
-         + 15 new mind-boggling levels full of new challenges for your brain
-         + complete artwork set with graphics and sounds
-         + available for downloading from "http://www.jb-line.de/rnd.html"
-
-Release Version 3.0.7 [10 NOV 2003]
------------------------------------
-       - fixed incorrectly displayed animation for attacking dragon
-       - fixed bug with not setting initial gravity for each new game
-       - fixed bug with teleportation of player by custom element change
-       - fixed bug with player not getting smashed by rock sometimes
-       - fixed serious bug in code for delayed element pushing
-       - fixed little bug in animation frame selection for pushed elements
-       - fixed bug when pushing element that can move away to the side
-       - fixed tape recording when player is created from CE element change
-       - fixed player animation frame reset for identical animations
-       - unavailable setup options now marked as "n/a" instead of "off"
-       - prevent "extended" changed elements from delay change in same frame
-       - speed-up of reading config file for verbose output
-       - added configuration option for opening and closing Supaplex exit
-       - added configuration option for moving up/down animation for Murphy
-       - added animation for "turning" action (for elements with move delay)
-       - added turning animations for bug, spaceship and sniksnak
-
-Release Version 3.0.6 [06 OCT 2003]
------------------------------------
-       - fixed bug when initializing font graphic structure
-       - fixed bug with animation mode "pingpong" when using only 1 frame
-       - fixed bug with extended change target introduced in 3.0.5
-       - fixed bug where passing over moving element doubles player speed
-       - fixed bug with elements continuing to move into push direction
-       - fixed bug with duplicated player when dropping bomb with shield on
-       - fixed switching bug (resetting flag when not switching but not idle)
-       - fixed element tokens for certain file elements with ".active" etc.
-       - added "switching" event for custom elements ("pressing" only once)
-       - added support for MP3 music for SDL version through SMPEG library
-
-Release Version 3.0.5 [29 SEP 2003]
------------------------------------
-       - fixed bug in multiple config pages loader code that caused crashes
-       - enhanced (remaining low-resolution) Supaplex graphics
-       - active/inactive sides configurable for custom element changes
-       - new movement type "move when pushed" available for custom elements
-       - now four envelope elements available
-       - font, background, animation and sound for envelope now configurable
-       - main menu doors opening/closing animation type now configurable
-
-Release Version 3.0.4 [13 SEP 2003]
------------------------------------
-       - fixed bug in multiple config pages code that caused crashes
-       - fixed bug in custom definition of crumbled element graphics
-
-Release Version 3.0.3 [08 SEP 2003]
------------------------------------
-       - fixed bug (missing array boundary check) which could crash the game
-       - fixed problem with setting mouse cursor in SDL version in fullscreen
-       - fixed problem with flickering when drawing toon animations
-       - fixed problem with player animation when snapping and moving
-       - fixed several nasty bugs that may have caused crashes on some systems
-       - added envelope content which gets displayed when collecting envelope
-       - added multiple change event pages for custom elements
-       - added support for loading various music formats through SDL_mixer
-       - added music to Supaplex classic level set
-
-Release Version 3.0.2 [22 AUG 2003]
------------------------------------
-       - fixed bug with messing up custom element properties in 3.0.0 levels
-       - fixed bug with choosing wrong engine version when playing tapes
-       - fixed bug with creating inaccessible elements at player position
-       - fixed bug with not finding current level artwork directory
-
-Release Version 3.0.1 [18 AUG 2003]
------------------------------------
-       - fixed bug that caused a crash at startup under Solaris
-       - fixed bug that caused the DOS version not finding its files
-       - fixed bug with missing graphic for active red disk bomb
-       - added custom element property for dropping collected elements
-       - added another 128 custom elements for those who can't get enough
-       - fixed PCX files in the DOS version ("classic" graphics only)
-
-Release Version 3.0.0 [05 AUG 2003]
------------------------------------
-       - final version bumped to 3.0.0 due to the massive changes
-       - graphics and sounds now completely and dynamically customizable
-       - custom elements now have lots of configurable properties
-       - advanced custom element settings for powerful, self-created elements
-       - fixed Supaplex gravity tubes
-       - fixed very nasty bug in SDL_image (and X11) PCX loading routine
-       - fixed some very nasty bugs in bitmap zoom routine
-       - fixed very nasty bug in level/artwork loading routine
-       - added new contributed levels and artwork from the following players:
-         * in the section "Contributions - 2002":
-            + Abby King (14 levels)
-           + Alan Bond (30 levels, all solvable, BD style artwork set)
-           + David Hutchinson (25 levels, artwork set)
-           + Equinox Tetrachloride (50 levels + 100 levels, all solvable)
-           + Sylvan Hancock (39 levels)
-         * in the section "Contributions - 2003":
-           + Andreas Buschbeck (85 levels, all solvable, complete artwork set)
-           + Edward Leuf (10 levels, all solvable, artwork set)
-           + Emanuel Schmieg (22 levels, all solvable, complete artwork set)
-           + Gavin Davidson (47 levels)
-           + Jorge Jordan (17 levels)
-           + Rafael Gatti (17 levels)
-           + Randy Johannessen (17 levels)
-           + Richard Valvona (3 levels)
-           + Sam Bateman (35 levels)
-       - great new levels with full artwork are now available from:
-         + Juergen Bonhagen (with complete artwork set)
-           * download these levels from "http://www.jb-line.de/"
-         + Andreas Buschbeck (with complete artwork set)
-           * download these levels from "http://home.vr-web.de/~abuschbeck/"
-
-Pre-Release Version 2.2.0rc7 [17 JUL 2003]
-------------------------------------------
-       - fixed bug when picking element in the editor
-       - added more custom elements properties
-       - fixed bugs when smashing penguin
-
-Pre-Release Version 2.2.0rc6 [22 APR 2003]
-------------------------------------------
-       - fixed small font configuration directive bug
-       - tape recorder font slightly enhanced (now complete character set)
-       - added missing font configuration source file
-       - added updated CHANGES file ;-)
-
-Pre-Release Version 2.2.0rc5 [20 APR 2003]
-------------------------------------------
-       - added generic selectbox gadget
-       - added special mouse cursor for playfield while playing
-       - font handling now more flexible (support for ISO-Latin-1 fonts)
-       - font graphics adjusted accordingly
-
-Pre-Release Version 2.2.0rc4 [30 MAR 2003]
-------------------------------------------
-       - changes for menu configuration
-       - not officially announced pre-release version
-       - Emerald Mine text font now much better quality
-
-Pre-Release Version 2.2.0rc3 [11 FEB 2003]
-------------------------------------------
-       - first custom element properties
-       - animation configuration for dynamically defined element actions
-       - automatically downscaled graphics (small graphics not needed anymore)
-       - ".EDITOR" and ".PREVIEW" suffixes for special editor/preview graphics
-       - toon animations (and number of toons) now fully configurable
-
-Pre-Release Version 2.2.0rc2 [13 JAN 2003]
-------------------------------------------
-       - added support for stereo WAV sound files
-       - moving objects can now have arbitrary animation length
-       - new batch command for dumping level information
-       - added support for background images for all menu screens
-       - added 128 custom elements that can be decorated with own graphics
-       - added some example levels showing how to create custom artwork
-       - added new contributed levels from the following players:
-         + Emanuel Schmieg: "Into The Ice Caves" (22 levels + artwork)
-
-Pre-Release Version 2.2.0rc1 [31 DEC 2002]
-------------------------------------------
-       - level series artwork now configurable via level series config file
-       - single graphics and animations can now be replaced with different
-         ones (independantly from default image files which may be larger)
-         by defining and using additional image files
-       - element animation length, speed and mode now freely configurable
-       - automatic tape playing function for game engine and level testing
-       - missing steel wall graphic added (thanks to Equinox Tetrachloride)
-       - added new contributed levels from the following players:
-         + Abby King (14 levels)
-         + Andreas Buschbeck (80 levels with complete artwork set)
-         + David Hutchinson (25 levels with graphics set)
-         + Equinox Tetrachloride (150 levels guaranteed to be solvable)
-         + Sylvan Hancock (39 levels)
-
-Release Version 2.1.1 [13 AUG 2002]
------------------------------------
-       - sound bug (causing crashes) fixed (reported by Keith Peterston)
-       - support for /dev/sound/dsp (devfs) added (thanks to Christoph Bauer)
-       - small NetBSD compilation bug fixed (thanks to Adam Ciarcinski)
-       - default keys for "snap field" and "place bomb" fixed for Mac OS X
-       - added new contributed levels from the following players:
-         + Alan Bond
-         + Gerrit Holl and Timen van den Berg
-
-Release Version 2.1.0 [05 AUG 2002]
------------------------------------
-       - native Mac OS X port (finally!)
-       - graphics, sounds and music now fully configurable
-       - added support for TrueColor PCX graphics files
-       - added support for 16 bit WAV sound files
-       - enhanced sound system (especially regarding stereo and loop sounds)
-       - new structured setup menu (with sub-menues for graphics and sounds)
-       - added "quick save" and "quick load" functions with shortcut key
-       - added single-step playing mode (automatic pause after each step)
-       - behaviour of "Escape" key in level editor now more intuitive
-       - changed default slipping behaviour of gems back to 2.0.0 style;
-         this is now an element property for gems in the level editor,
-         although existing converted levels use the new EM gems behaviour
-       - bug fixed that prevented walking through tubes when gravity on
-       - added Boulder Dash style "snap-pushing" (thanks to Achim Härtel)
-       - fixed memory leak in image loading code
-       - fixed some "solid" elements that were accidentally destructible
-       - fixed some tape stuff
-       - added new contributed levels from the following players:
-         + Conor Mancone
-         + Gavin Davidson
-         + Jerome Kunegis
-         + Rüdiger Schäfer
-         + Flyboy: level group "Cops and Robbers", with own graphics set
-       - added custom graphics set "Animal Kingdom" by Flyboy
-
-Release Version 2.0.1 [19 MAR 2002]
------------------------------------
-       - bug in explosion code fixed that broke level 24 of "Baby Ghost Mine"
-       - several Supaplex emulation bugs fixed (thanks to Mihail Milushev):
-         + orange disk does not fall off from slippery elements
-         + infotrons kill electrons and snik snaks and trigger orange disks
-         + explosion chain reactions are now a bit slower than murphy
-       - behaviour of robots adjusted to make them less aggressive
-         (needed for quite some Emerald Mine Club levels)
-       - emeralds and diamonds now fall off normal, steel and growing walls,
-         as this is the correct behaviour in Emerald Mine; existing private
-         and contributed levels will still behave as before, unless saved
-         again (with or without modifications) from the level editor of the
-         current version of the game
-       - icon for Windows executable added
-       - bug when selecting default level series fixed
-       - new IFF style file format for level and tape files
-       - bug in storing amoeba content fixed
-       - nasty tape bugs fixed (completely reworked tape stuff)
-       - fullscreen mode now works with Windows (workaround for bug in SDL)
-       - /dev/dsp support for NetBSD added (thanks to Krister Walfridsson)
-       - file permissions when saving files and creating directories changed
-       - some small sound bugs fixed
-       - added new contributed levels from the following players:
-         + Arno Luppold
-         + Barak Shacked
-         + Ben Braithwaite
-         + Dominik Seichter
-         + Emilio Hemken
-         + Glenn Alexander
-         + Helge Hafting
-         + Paul Sutton
-
-Release Version 2.0.0 [01 JAN 2001]
------------------------------------
-       - major code redesign to maintain generic game functions in a separate
-         library and make it easier to port the game to new targets like SDL
-       - can be compiled with SDL library to build native Windows version
-       - DOS and Windows versions can be compiled with gcc cross-compiler
-       - trying to open already busy audio device does not block the game
-       - bug in network playing code fixed (patch from web site)
-       - SDL version can load and play music modules
-       - bug in level editor fixed for EM doors and keys element description
-       - sound sample frequency raised from 8 kHz to 22 kHz
-
-Release Version 1.4.0 [27 OCT 1999]
------------------------------------
-       - new Boulder Dash elements for better game emulation
-       - new cool medium-sized crystal font
-       - new elements and graphics for Diamond Caves II levels
-       - new elements and graphics for Emerald Mine Club levels
-       - brushed-up (higher resolution) graphics for Supaplex elements
-       - special oversized Supaplex levels included
-       - new elements for more authentic Emerald Mine elements (doors)
-       - more level editor enhancements:
-         element list scrollbar and level number selection within editor
-       - lots of new levels converted from Emerald Mine Club disks,
-         DX-Boulderdash and Supaplex
-       - new levels created and contributed by players
-       - now over 160 level series with over 14.000 levels
-       - high score list now scrollable to see all 100 entries
-       - new 16-bit elements level format to allow more than 256 elements
-       - re-introduced level handicap for more challange (levels must be
-         solved to be able to play the next one; can be disabled in setup)
-       - new setup option to disable time limit for relaxed playing :-)
-       - GAME_DIR path split into RO_GAME_DIR and RW_GAME_DIR to allow
-         distributors to separate read-only (levels, graphics, sounds)
-         from writable (hich scores) game data
-       - new personal level setup files to store level handicap and
-         last played level for each level series
-       - removed some 32-bit dependent code; should be 64-bit clean now
-       - some little bugs fixed
-
-Release Version 1.3.0 [5 FEB 1999]
-----------------------------------
-       - strongly enhanced level editor
-       - new elements, graphics and levels for Supaplex style games
-       - completely rewritten platform independent gadget code
-         (buttons, scrollbars, text and number input gadgets)
-       - nasty sound bug fixed (showed up with Linux kernel 2.2.x)
-
-Release Version 1.2.0 [5 DEC 1998]
-----------------------------------
-       - DOS/Windows version
-       - new WAV sound loader (to replace the old Amiga 8SVX files)
-       - new PCX graphics loader (to avoid GIF license problems)
-       - network multiplayer games with upto four players
-       - no separate network server needed; each client can
-         fork a network server at startup if there's no server
-         running at this moment
-       - possibility to invoke the game to act as a standalone
-         network server (on a separate machine, for example)
-       - local multiplayer games with upto four players
-       - support for upto four joysticks
-       - completely free customizable keyboard and joystick
-         for all four players individually
-       - new joystick calibration screen which can be left
-         (with Escape key) if no joystick is connected... ;-)
-       - new (working) GIF graphics loader (but still support
-         for the old XPM method)
-       - supports private colormap with extremely less flashing
-         on 8-bit (256 colors) displays
-       - soft-scrolling with 50 frames per second (which raises
-         the system requirements and makes it completely
-         unplayable on my "old reference" 486/33 (where 0.9b runs
-         smoothly) and running at 90% speed on my K6-200.
-       - completely new file format for personal setup data
-         in ASCII format which is human readable and easily
-         customizable even with a texteditor; stored in the
-         user's home directory and no longer somewhere in the
-         game's installation directory
-       - high score lists changed: now one file per level and
-         no longer one file per level series; now using readable
-         ASCII format
-       - useful command line options to specify the X11 display,
-         the game's base (installation) directory, an alternate
-         level directory, standalone server execution and verbose
-         execution
-
-Version 1.1 [???] [NOT RELEASED]
---------------------------------
-       - new (but broken) GIF graphics loader to be independent
-         from the XPM library and to replace all graphics by GIF files
-
-Version 1.0 [9 APR 1997] [NOT RELEASED]
----------------------------------------
-       - the game now contains many really playable levels,
-         not only a few levels for testing
-       - the game is now even better playable by keyboard
-         (now you have the same gameplay functionality
-         compared to playing with a joystick. Especially
-         there are diagonal directions with keyboard playing
-         and the fire buttons are mapped to the shift keys)
-       - a lot of new elements for better emulation of levels
-         from the games "Boulder Dash", "Emerald Mine" and
-         "Sokoban". New elements to build "Dynablaster" style
-         levels.
-       - enhanced functionality of the level tape recorder
-         to make it possible to go on with a game at any tape
-         position
-
-Version 0.9b2 [21 NOV 1995] [NOT RELEASED]
-------------------------------------------
-       - new game elements
-
-Pre-Release Version 0.9b [4 NOV 1995]
--------------------------------------
-       - the game is now completely Freeware
-       - the game is now better playable by keyboard
-         (in the last version, the player was making more than
-          one step for one keystroke in some cases -- thanks to
-         Warwick Allison for the hint with "XSync()"!)
-       - new amoeba type with configurable content (like in the
-         original C64 version, when aboeba cannot grow anymore
-         and explodes to diamonds or some other elements)
-       - compile error with ONE_PER_NAME in high score function
-         removed (thanks to Dmitry Kohmanyuk)
-       - little code cleanup (to get some new bugs ;)
-       - FreeBSD sound and joystick support (thanks to Jean-Marc
-         Zucconi)
-
-Pre-Release Version 0.9 [23 OCT 1995]
--------------------------------------
-       - first (pre)release version
diff --git a/CREDITS b/CREDITS
index bb187417c5b7aad432195ea1c084b0b336fa0790..601a4370293d461df9666a3a3f5bc8d980f137fe 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1,3 +1,55 @@
 
-[Credits file yet to be written.]
+Rocks'n'Diamonds contains a lot of inspiration, ideas, code and contributions
+by many people and projects, which are listed here in no particular order. If
+somebody should be added to this list of credits, please let me know!
 
+-------------------------------------------------------------------------------
+
+Special thanks to Peter Liepa for creating "Boulder Dash" that started it all!
+
+Special thanks to Klaus Heinz and Volker Wertich for creating "Emerald Mine",
+which took this kind of game to a new level!
+
+Special thanks to Michael Stopp and Philip Jespersen for creating "Supaplex"!
+
+Special thanks to Hiroyuki Imabayashi for creating "Sokoban"!
+
+Special thanks to Alan Bond and Jürgen Bonhagen for the continuous creation
+of outstanding level sets!
+
+Thanks to Peter Elzner for ideas and inspiration by Diamond Caves.
+
+Thanks to Steffest for ideas and inspiration by DX-Boulderdash.
+
+Thanks to Guido Schulz for the initial MS-DOS port of the game.
+
+The native Emerald mine engine was derived from Emerald Mine for X11
+which was developed by David Tritscher as a very compatible Emerald Mine clone.
+Thanks a lot for this contribution!
+
+The native Supaplex engine is based on MegaPlex by Frank Schindler, which is
+based on the Supaplex Speed Fix by Herman Perk, which is based on the original
+Supaplex game by Michael Stopp and Philip Jespersen. Thanks a lot for this
+contribution!
+
+Thanks to Karl Hörnell for some additional toon graphics taken from "Iceblox":
+The penguin, the mole, the pig and the dragon.
+
+Thanks to the composers of the included music modules: "mod.apoplexy" by
+bee hunter/jazz, "mod.chiptune" by 4-mat/anarchy and "mod.cream_of_the_earth"
+by romeoknight.
+
+Thanks to Christopher Clark for the hash functions.
+
+The random number generator was taken from the GNU C library.
+
+The networking code was derived from xtris. Thanks!
+
+Thanks to Francesco Carta for the comprehensive Rocks'n'Diamonds manual.
+
+Thanks to Niko Böhm for the Rocks'n'Diamonds documentation wiki.
+
+Thanks to Simon Forsberg for being the moderator of the R'n'D forum.
+
+And not to forget: Many thanks to all those who contributed levels to this game
+since 1995!
index 41f88faf0dd22234d59f47d5786559301f09af8d..945185889fcbf1d89ae14da6d22a205ba4cfc838 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,240 @@
+2010-05-22
+       * fixed missing memory allocation in SP engine when saving engine data
+         for non-SP game engine snapshots (which also stores SP engine part)
+
+2010-05-21
+       * fixed problem with scrolling in native EM engine in multi-user mode
+         (this bug was just introduced with the experimental viewport stuff)
+       * fixed animation of splashing acid in EM engine with classic artwork
+       * fixed animation of cracking nut in EM engine with classic artwork
+       * fixed (implemented) single step mode in native EM and SP engines
+       * fixed "latest_engine" flag in classic levels (moved to single sets)
+       * updated SDL library DLLs for Windows to the latest release versions
+         (this fixed some mysterious crashes of the game on Windows systems)
+       * replaced EM and SP set in classic level set with native level files
+       * finally added a newly written "CREDITS" file to the game package
+       * removed sampled music loops from classic music set
+
+2010-04-20
+       * changed native Emerald Mine engine to support different viewport sizes
+
+2010-04-19
+       * changed native Supaplex engine to support different viewport sizes
+
+2010-04-07
+       * added initial, experimental support for different viewport properties
+         (with "viewports" being menu/playfield area and doors; currently the
+         size of the menu/playfield area and door positions can be redefined)
+
+2010-04-02
+       * added initial, experimental support for different window sizes
+
+2010-03-27
+       * added support for native Sokoban solution files in pure 'udlrUDLR'
+         format with extension ".sln" instead of ".tape" for solution tapes
+
+2010-03-26
+       * added image config suffix ".class" to be able to define classes of
+         crumbled elements which are then separated against each others when
+         drawing crumbled borders (class names can freely be defined)
+         (Example: "sand.CRUMBLED.class: sand" and "emc_grass.CRUMBLED.class:
+         emc_grass" results in sand and emc_grass being crumbled separately,
+         even if directly adjacent on the playfield.)
+       * added image config suffix ".style" to use two new features for
+         crumbled graphics:
+         - "accurate_borders": try to draw correctly crumbled corners (which
+           means that a row of crumbled elements does not have two crumbled
+           corners for each element in the row, but only at the "real" corners
+           at the start and the end of the row of elements)
+         - "inner_corners": also draw inner corners in concave constructions
+           of several crumbled elements -- this is currently a big kludge: the
+           number of frames for crumbled graphic must be "2", with the first
+           frame as usual (crumbled graphic), while the second frame contains
+           the graphic with inner (crumbled) corners for the crumbled graphic
+         (These two features are mainly intended for bevelled walls, not for
+         diggable elements like sand; "inner_corners" only works reliably for
+         static walls, not for in-game dynamically changing walls using CEs.)
+
+2010-03-16
+       * finished code cleanup of native Supaplex game engine
+
+2010-03-14
+       * started code cleanup of native Supaplex game engine
+
+2010-03-13
+       * integrated playing sound effects into native Supaplex game engine
+
+2010-03-10
+       * added configurable key shortcuts for the tape recorder buttons
+
+2010-03-09
+       * added (hidden) function to save native Supaplex levels with tape as
+         native *.sp file containing level with demo (saved with a file name
+         similar to native R'n'D levels, but with ".sp" extension instead of
+         ".level"); to use this functionality, enter ":save-native-level" or
+         ":snl" from the main menu with the native Supaplex level loaded and
+         the appropriate tape loaded to the tape recorder
+       * fixed potential crash bug caused by illegal array access in engine
+         snapshot loading and saving code
+       * changed setting permissions of score files to be world-writable if
+         the program is not installed and running setgid to allow the program
+         to modify existing score files when run as a different user (which
+         allows cheating, of course, as the score files are not protected
+         against modification in this case)
+       * added (commented out) suggestions for RO_GAME_DIR and RW_GAME_DIR to
+         the top level Makefile for Debian / Ubuntu installations
+       * added saving read-only levels from editor into personal level set
+         (thanks to Bela Lubkin for the above four patches)
+
+2010-03-03
+       * added updating of game values on the panel to Supaplex game engine
+
+2010-02-23
+       * finished integrating R'n'D graphics engine into Supaplex game engine
+         (although some animations do not support full customizability yet)
+
+2010-02-22
+       * done integrating R'n'D graphics engine into file "Infotron.c"
+       * done integrating R'n'D graphics engine into file "OrangeDisk.c"
+
+2010-02-19
+       * integrated engine snapshot functionality into Supaplex game engine
+
+2010-02-16
+       * fixed bug in native Supaplex engine that broke several demo solutions
+       * fixed bug with re-initializing already existing elements in function
+         RelocatePlayer() in src/game.c (causing problems with Sokoban fields
+         counted a second time, making the currently playing level unsolvable)
+       * done integrating R'n'D graphics engine into file "SnikSnaks.c"
+       * done integrating R'n'D graphics engine into file "Electrons.c"
+       * done integrating R'n'D graphics engine into file "Zonk.c"
+
+2010-02-14
+       * done integrating R'n'D graphics engine into file "Murphy.c"
+       * done integrating R'n'D graphics engine into file "BugsTerminals.c"
+
+2010-02-07
+       * started integrating R'n'D graphics engine into Supaplex game engine
+
+2010-02-02
+       * added small kludge that allows transparent pushing animation over
+         non-black background (by using "game.use_masked_pushing: true")
+       * added editor flag to Sokoban field/object elements to automatically
+         finish solved Sokoban style levels (even if they contain non-Sokoban
+         elements, which prevents auto-enabling this feature for such levels)
+
+2010-01-10
+       * added new element "from_level_template" which is replaced by element
+         from level template at same playfield position when loaded (currently
+         not accessible from level editor, but only used for special Sokoban
+         level conversion when using "special_flags: load_xsb_to_ces")
+       * added special behaviour for "special_flags: load_xsb_to_ces": global
+         settings of individual level files are overwritten by template level
+         (except playfield size, level name, level author and template flag)
+
+2010-01-07
+       * added handling of gravity ports when converting Supaplex style R'n'D
+         levels to native Supaplex levels for playing with Supaplex engine
+
+2010-01-06
+       * fixed bug in Supaplex engine regarding initial screen scroll position
+
+2009-12-17
+       * fixed EMC style pushing animations in the R'n'D graphics engine (when
+         using ".2nd_movement_tile" for animations having start and end tile)
+       * for this to work (look) properly for two-tile pushing animations with
+         non-black (i.e. opaque) background, the pushing graphics drawing order
+         was changed to first draw the pushed element, then the player (maybe
+         this should be controlled by an ".anim_mode" flag yet to be added)
+       * two-tile animations for moving or pushing should have 7 frames for
+         normal speed, 15 frames for half speed etc. to display correct frames
+       * two-tile animations are also displayed correctly with different speed
+         settings for the player (for pushing animations) or moving elements
+
+2009-12-16
+       * added searching for template level (file "template.level") not only
+         inside the level set directory, but also in above level directories;
+         this makes is possible to use the same single template level file
+         (placed in a level group directory) for many level sub-directories
+
+2009-12-10
+       * fixed bug with steel exit being destructible during opening phase
+       * added token "special_flags" to "levelinfo.conf" (currently with the
+         only recognized value "load_xsb_to_ces", doing the same as the flag
+         "-Dload_xsb_to_ces" on the command line, but as a permanent flag for
+         converting all elements in native (XSB) Sokoban level files to CEs)
+
+2009-12-08
+       * fixed some problems with Supaplex engine when compiling for Windows
+
+2009-12-05
+       * added special mode to convert elements of Sokoban XSB levels to CEs
+         by adding "-Dload_xsb_to_ces" to the command line starting the game
+         (also adding a dependency to a template level file "template.level")
+
+2009-12-01
+       * added reading native Sokoban levels and level packages (XSB files)
+
+2009-11-25
+       * fixed bugs in (auto)scrolling behaviour when passing ports or when
+         wrapping around the playfield through "holes" in the playfield border
+
+2009-11-24
+       * changed internal playfield bitmap handling from playfield sized bitmap
+         to screen sized bitmap (visible scrolling area), therefore speeding up
+         graphics operations (by eliminating bitmap updates in invisible areas)
+         and removing playfield size limitations due to increasing bitmap size
+         for larger playfield sizes (while the new implementation always uses
+         a fixed playfield bitmap size for arbitrary internal playfield sizes)
+
+2009-11-12
+       * fixed bug with single step mode (there were some cases where the game
+         did not automatically return to pause mode, e.g. when trying to push
+         things that cannot be pushed or when trying to run against a wall)
+
+2009-11-01
+       * added support for loading Supaplex levels in MPX level file format
+
+2009-10-31
+       * fixed SP engine to set "game over" not before lead out counter done
+
+2009-10-30
+       * fixed (potential) compile error when using GCC option "-std=gnu99"
+         (thanks to Tom "spot" Callaway)
+
+2009-10-28
+       * fixed array allocation in native Supaplex engine to correctly handle
+         preceding scratch buffers (needed because of missing border checking)
+       * fixed playfield initialization to correctly add raw header bytes as
+         subsequent scratch buffer (needed because of missing border checking)
+
+2009-10-24
+       * most important parts of native Supaplex engine integration working:
+         - native Supaplex levels can be played in native Supaplex engine
+         - native Supaplex level/demo files ("*.sp" files) can be re-played
+         - all 111 classic original Supaplex levels automatically solvable
+         - native Supaplex engine can be selected and used from level editor
+         - logic of re-playing Supaplex demos migrated to R'n'D tape logic
+
+2009-09-25
+       * fixed another translation problem from VisualBasic to C (where "int"
+         should be "short") causing unsolvable demos with bugs and terminals
+         ("bugs" being related to the Supaplex "buggy base" element here ;-) )
+
+2009-09-23
+       * fixed bug when reading Supaplex single level files (preventing loader
+         from seeking to level position like in Supaplex level package files)
+
+2009-08-01
+       * first classic Supaplex level running and solved by solution/demo tape
+
+2009-06-20
+       * started with integration of native Supaplex engine, using source code
+         of Megaplex from Frank Schindler, based on original Supaplex engine
+
+2009-06-16
+       * version number set to 3.2.6.2
+
 2009-06-15
        * version 3.2.6.1 released
 
diff --git a/HARDWARE b/HARDWARE
deleted file mode 100644 (file)
index 49de985..0000000
--- a/HARDWARE
+++ /dev/null
@@ -1,92 +0,0 @@
-
-[Very outdated -- should be rewritten...]
-
-
-Some recommendations for more fun playing Rocks'n'Diamonds:
-===========================================================
-
-About sound
------------
-It is highly recommended to have a decent sound interface for playing
-this game (although it only comes with bad-quality 8000-Hz-samples to
-save memory and to be compatible with /dev/audio).
-
-The best sound platform is an actual Linux system with (at least) kernel
-1.2.x, because it offers some nice real-time sound features which are
-needed to have background music loops in the game.
-
-On all other systems you don't have music loops, but you still have all
-the other sounds.
-
-
-About game speed
-----------------
-You should have a relatively fast hardware.
-
-The game was developed on a i486/33 (which is three years old now),
-and you should probably better not try to run it on a slower system.
-
-You should have an accelerated graphic card; I have found out that it
-starts being playable on my 486/33 with an old ISA cirrus logic 5426
-graphic card, which has a blitter that is supported by XFree86[tm],
-but that it was nearly unplayable on a 486/66 with old, unaccelerated
-ET4000.
-
-If all works fine, you should have something around 30 frames per second.
-
-If you think that the game is to slow to play, you should try out the
-following things:
-
-- Set "Buffered Gfx" to "off" in the setup menu. Normally (on a fast
-  enough system) you should use buffered graphics, which means that
-  all graphics is drawn into an invisible Pixmap and is then copied
-  to the X11 window to avoid flickering. If you disable this double
-  buffering, the graphic is directly drawn into the window. This can
-  cause some slight flickering, but makes graphic operations roughly
-  twice as fast compared to double buffering.
-
-- Set "Game Music" to "off" in the setup menu (and maybe "sound loops"
-  too). Where disabling buffered graphics may be required with slow
-  graphics hardware, disabling sound is especially recommended on slow
-  CPU systems (486/33 and slower), because the sound server eats up a
-  significant amount of CPU time when playing long sounds.
-
-You might also notice that bigger levels tend to be slower on slow
-systems.
-
-About the option "Fading" in the setup menu: It gives a nice looking
-fading when switching to a new screen, but you should really only try
-this out if you think that you have a very fast graphics hardware.
-
-
-About music
------------
-The background music loops are ripped out from several nice music albums.
-Just have a look at the info screen to find out from which album each
-sound loop came from -- they are all very well done pieces of music, but
-unfortunately they don't sound better after converting them to 8 kHz
-samples (to conform to standard SUN /dev/audio). Maybe I change this to
-a better quality in the future, but at the moment, where the sounds
-directory has a size of nearly a megabyte, I'll stay with 8 kHz samples.
-
-So, if you have a non-Linux system (which cannot play sound loops) or
-don't like the "telephone quality" of the music loops, just get some of
-these CDs and play them while your playing the game! ;-)
-
-
-About game-play
----------------
-It is *strongly recommended* to play this game with a high-quality joystick.
-That means, throw your $10 joystick out of the window and buy a decent
-Competition-Pro Digital PC joystick or a high-quality CH Products Analog
-joystick. Believe me, it doubles the fun of playing the game.
-
-If you only have a normal Unix system (and no fine Linux system), you
-are forced to play with the keyboard. It works, but is not only less fun,
-but also more difficult with some levels, because you cannot move in
-diagonal directions with keyboard control at the moment. Another bad thing
-is that you will have some problems when pressing many keys at the same
-time. This might change in the future, when I implement a better keyboard
-handling which not only solves these problems but allows diagonal directions,
-too.
-
index 65ea127afc122305d32049d1b72a8af35326133c..75fde6be5e40b15ae56b27ec64ba6fce4e88df0d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -22,10 +22,14 @@ X11_PATH = /usr/X11R6
 # directory for read-only game data (like graphics, sounds, levels)
 # default is '.' to be able to run program without installation
 # RO_GAME_DIR = /usr/games
+# use the following setting for Debian / Ubuntu installations:
+# RO_GAME_DIR = /usr/share/games/rocksndiamonds
 
 # directory for writable game data (like highscore files)
 # default is '.' to be able to run program without installation
 # RW_GAME_DIR = /var/games
+# use the following setting for Debian / Ubuntu installations:
+# RW_GAME_DIR = /var/games/rocksndiamonds
 
 # uncomment if system has no joystick include file
 # JOYSTICK = -DNO_JOYSTICK
@@ -134,13 +138,12 @@ levelsketch_images: all
        ./Scripts/make_levelsketch_images.sh
 
 backup:
-       ./Scripts/make_backup.sh src 1
+       ./Scripts/make_backup.sh src tar
 
-backup2:
-       ./Scripts/make_backup.sh src 2
+backup-net-copy:
+       ./Scripts/make_backup.sh src scp
 
-backup3:
-       ./Scripts/make_backup.sh src 3
+backup-net: backup backup-net-copy
 
 backup_lev:
        ./Scripts/make_backup.sh lev
@@ -151,6 +154,12 @@ backup_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
 
index bd5538eae7cb19bdd3894e5c8fdf911a1d3f589e..4bbbcca9c1c8fbb29fb4f4c0905fecf82db2c5e2 100644 (file)
@@ -228,7 +228,10 @@ LIBGAME = $(LIBGAME_DIR)/libgame.a
 GAME_EM_DIR = game_em
 GAME_EM = $(GAME_EM_DIR)/game_em.a
 
-RNDLIBS = $(LIBGAME) $(GAME_EM)
+GAME_SP_DIR = game_sp
+GAME_SP = $(GAME_SP_DIR)/game_sp.a
+
+RNDLIBS = $(LIBGAME) $(GAME_EM) $(GAME_SP)
 
 ICONBASE = windows_icon
 ifeq ($(PLATFORM),cross-win32)
@@ -246,7 +249,7 @@ endif
 # build targets
 # -----------------------------------------------------------------------------
 
-all: libgame_dir game_em_dir $(PROGNAME)
+all: libgame_dir game_em_dir game_sp_dir $(PROGNAME)
 
 $(PROGNAME): $(RNDLIBS) $(TIMESTAMP_FILE) $(OBJS) $(ICON)
        $(CC) $(PROFILING) $(OBJS) $(ICON) $(RNDLIBS) $(LDFLAGS) -o $(PROGNAME)
@@ -261,6 +264,11 @@ game_em_dir:
 $(GAME_EM):
        @$(MAKE) -C $(GAME_EM_DIR)
 
+game_sp_dir:
+       @$(MAKE) -C $(GAME_SP_DIR)
+$(GAME_SP):
+       @$(MAKE) -C $(GAME_SP_DIR)
+
 auto-conf:
        @for i in $(CNFS); do                   \
                echo "$(CNFS_CMD) $$i > $$i";   \
@@ -276,7 +284,7 @@ conf_snd.h: conf_snd.c
 conf_mus.h: conf_mus.c
        @$(MAKE) auto-conf
 
-$(TIMESTAMP_FILE): $(SRCS) $(LIBGAME) $(GAME_EM)
+$(TIMESTAMP_FILE): $(SRCS) $(LIBGAME) $(GAME_EM) $(GAME_SP)
        @date '+"%Y-%m-%d %H:%M"' \
        | sed -e 's/^/#define COMPILE_DATE_STRING /' \
        > $(TIMESTAMP_FILE)
@@ -291,9 +299,11 @@ $(ICON):
 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)
 
 clean-ico:
        $(RM) $(ICONBASE).ico
@@ -327,11 +337,12 @@ valgrind: all
 dist-clean: clean-obj
 
 tags:
-       $(ETAGS) *.[ch] $(LIBGAME_DIR)/*.[ch] $(GAME_EM_DIR)/*.[ch]
+       $(ETAGS) *.[ch] $(LIBGAME_DIR)/*.[ch] $(GAME_EM_DIR)/*.[ch] $(GAME_SP_DIR)/*.[ch]
 
 depend:
        $(MAKE) -C $(LIBGAME_DIR) depend
        $(MAKE) -C $(GAME_EM_DIR) depend
+       $(MAKE) -C $(GAME_SP_DIR) depend
        for i in $(SRCS); do $(CPP) $(CFLAGS) -M $$i; done > .depend
 
 ifeq (.depend,$(wildcard .depend))
index 70d6d3d54ac6a8731eff3a45fd86483fa438b517..8ca4bdd5efde9c2e81ffbf96bc1796d1a2adcf17 100644 (file)
@@ -23,15 +23,18 @@ static struct ToonInfo toons[MAX_NUM_TOONS];
 
 static void PrepareBackbuffer()
 {
-  if (game_status == GAME_MODE_PLAYING &&
-      level.game_engine_type == GAME_ENGINE_TYPE_EM)
+  if (game_status != GAME_MODE_PLAYING)
+    return;
+
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
   {
     BlitScreenToBitmap_EM(backbuffer);
-
-    return;
   }
-
-  if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
+  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;
 
index 2d49c0e2ae26c80a9015d0c408375684fd0ea22e..6b154196102455c232bf2d91feb2e09644de6b1b 100644 (file)
@@ -281,6 +281,14 @@ element_to_graphic[] =
     EL_SP_MURPHY,                      ACTION_SLEEPING, MV_BIT_RIGHT, FALSE,
     IMG_SP_MURPHY_SLEEPING_RIGHT
   },
+  {
+    EL_SP_MURPHY,                      ACTION_DROPPING, -1, FALSE,
+    IMG_SP_MURPHY_DROPPING
+  },
+  {
+    EL_SP_MURPHY,                      ACTION_SHRINKING, -1, FALSE,
+    IMG_SP_MURPHY_SHRINKING
+  },
   {
     EL_SP_MURPHY_CLONE,                        -1, -1, FALSE,
     IMG_SP_MURPHY_CLONE
@@ -289,6 +297,14 @@ element_to_graphic[] =
     EL_SP_INFOTRON,                    -1, -1, FALSE,
     IMG_SP_INFOTRON
   },
+  {
+    EL_SP_INFOTRON,                    ACTION_MOVING, MV_BIT_LEFT, FALSE,
+    IMG_SP_INFOTRON_MOVING_LEFT
+  },
+  {
+    EL_SP_INFOTRON,                    ACTION_MOVING, MV_BIT_RIGHT, FALSE,
+    IMG_SP_INFOTRON_MOVING_RIGHT
+  },
   {
     EL_SP_INFOTRON,                    ACTION_COLLECTING, -1, FALSE,
     IMG_SP_INFOTRON_COLLECTING
index 49dca0a7271981c746a4e9f41e97ab43fca69cc8..f8a5ae3f1d4016deedc83088910823bf608bef89 100644 (file)
@@ -67,6 +67,8 @@ struct ConfigTypeInfo image_config_suffix[] =
   { ".align",                          ARG_UNDEFINED,  TYPE_INTEGER    },
   { ".valign",                         ARG_UNDEFINED,  TYPE_INTEGER    },
   { ".sort_priority",                  ARG_UNDEFINED,  TYPE_INTEGER    },
+  { ".class",                          ARG_UNDEFINED,  TYPE_STRING     },
+  { ".style",                          ARG_UNDEFINED,  TYPE_STRING     },
 
   { NULL,                              NULL,           0               }
 };
@@ -281,7 +283,7 @@ struct ConfigInfo image_config[] =
   { "[sp_default].exploding.xpos",             "8"                     },
   { "[sp_default].exploding.ypos",             "3"                     },
   { "[sp_default].exploding.frames",           "8"                     },
-  { "[sp_default].exploding.delay",            "3"                     },
+  { "[sp_default].exploding.delay",            "4"                     },
   { "[sp_default].exploding.anim_mode",                "linear"                },
 
   { "sp_zonk",                                 "RocksSP.pcx"           },
@@ -292,26 +294,26 @@ struct ConfigInfo image_config[] =
   { "sp_zonk.moving.left.xpos",                        "0"                     },
   { "sp_zonk.moving.left.ypos",                        "6"                     },
   { "sp_zonk.moving.left.frames",              "4"                     },
-  { "sp_zonk.moving.left.delay",               "2"                     },
+  { "sp_zonk.moving.left.delay",               "1"                     },
   { "sp_zonk.moving.left.anim_mode",           "reverse"               },
   { "sp_zonk.moving.right",                    "RocksSP.pcx"           },
   { "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",              "2"                     },
+  { "sp_zonk.moving.right.delay",              "1"                     },
   { "sp_zonk.pushing.left",                    "RocksSP.pcx"           },
   { "sp_zonk.pushing.left.xpos",               "0"                     },
   { "sp_zonk.pushing.left.ypos",               "6"                     },
   { "sp_zonk.pushing.left.frames",             "4"                     },
-  { "sp_zonk.pushing.left.delay",              "2"                     },
+  { "sp_zonk.pushing.left.delay",              "1"                     },
   { "sp_zonk.pushing.left.anim_mode",          "reverse"               },
   { "sp_zonk.pushing.right",                   "RocksSP.pcx"           },
   { "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",             "2"                     },
+  { "sp_zonk.pushing.right.delay",             "1"                     },
 
   { "sp_base",                                 "RocksSP.pcx"           },
   { "sp_base.xpos",                            "2"                     },
@@ -338,36 +340,42 @@ struct ConfigInfo image_config[] =
   { "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.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.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.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.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.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.xpos",             "11"                    },
   { "sp_murphy.pushing.left.ypos",             "1"                     },
@@ -418,6 +426,16 @@ struct ConfigInfo image_config[] =
   { "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.xpos",                 "11"                    },
+  { "sp_murphy.dropping.ypos",                 "12"                    },
+  { "sp_murphy.dropping.frames",               "1"                     },
+  { "sp_murphy.shrinking",                     "RocksSP.pcx"           },
+  { "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.xpos",                    "3"                     },
@@ -431,6 +449,16 @@ struct ConfigInfo image_config[] =
   { "sp_infotron.EDITOR",                      "RocksSP.pcx"           },
   { "sp_infotron.EDITOR.xpos",                 "8"                     },
   { "sp_infotron.EDITOR.ypos",                 "11"                    },
+  { "sp_infotron.moving.left",                 "RocksSP.pcx"           },
+  { "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.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.xpos",             "8"                     },
   { "sp_infotron.collecting.ypos",             "7"                     },
@@ -511,9 +539,9 @@ struct ConfigInfo image_config[] =
   { "sp_disk_red.ypos",                                "2"                     },
   { "sp_disk_red.frames",                      "1"                     },
   { "sp_disk_red.collecting",                  "RocksSP.pcx"           },
-  { "sp_disk_red.collecting.xpos",             "8"                     },
+  { "sp_disk_red.collecting.xpos",             "9"                     },
   { "sp_disk_red.collecting.ypos",             "5"                     },
-  { "sp_disk_red.collecting.frames",           "8"                     },
+  { "sp_disk_red.collecting.frames",           "7"                     },
   { "sp_disk_red.collecting.anim_mode",                "linear"                },
   { "sp_disk_red.active",                      "RocksSP.pcx"           },
   { "sp_disk_red.active.xpos",                 "4"                     },
@@ -553,85 +581,85 @@ struct ConfigInfo image_config[] =
   { "sp_gravity_port_right.ypos",              "1"                     },
   { "sp_gravity_port_right.frames",            "1"                     },
   { "sp_gravity_port_right.EDITOR",            "RocksSP.pcx"           },
-  { "sp_gravity_port_right.EDITOR.xpos",       "5"                     },
-  { "sp_gravity_port_right.EDITOR.ypos",       "1                    },
+  { "sp_gravity_port_right.EDITOR.xpos",       "0"                     },
+  { "sp_gravity_port_right.EDITOR.ypos",       "14"                    },
   { "sp_gravity_port_down",                    "RocksSP.pcx"           },
   { "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.xpos",                "6"                     },
-  { "sp_gravity_port_down.EDITOR.ypos",                "1                    },
+  { "sp_gravity_port_down.EDITOR.xpos",                "1"                     },
+  { "sp_gravity_port_down.EDITOR.ypos",                "14"                    },
   { "sp_gravity_port_left",                    "RocksSP.pcx"           },
   { "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.xpos",                "7"                     },
-  { "sp_gravity_port_left.EDITOR.ypos",                "1                    },
+  { "sp_gravity_port_left.EDITOR.xpos",                "2"                     },
+  { "sp_gravity_port_left.EDITOR.ypos",                "14"                    },
   { "sp_gravity_port_up",                      "RocksSP.pcx"           },
   { "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.xpos",          "0"                     },
-  { "sp_gravity_port_up.EDITOR.ypos",          "2"                     },
+  { "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.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.xpos",    "5"                     },
-  { "sp_gravity_on_port_right.EDITOR.ypos",    "1                    },
+  { "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.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.xpos",     "6"                     },
-  { "sp_gravity_on_port_down.EDITOR.ypos",     "1                    },
+  { "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.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.xpos",     "7"                     },
-  { "sp_gravity_on_port_left.EDITOR.ypos",     "1                    },
+  { "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.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.xpos",       "0"                     },
-  { "sp_gravity_on_port_up.EDITOR.ypos",       "2"                     },
+  { "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.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.xpos",   "5"                     },
-  { "sp_gravity_off_port_right.EDITOR.ypos",   "1                    },
+  { "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.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.xpos",    "6"                     },
-  { "sp_gravity_off_port_down.EDITOR.ypos",    "1                    },
+  { "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.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.xpos",    "7"                     },
-  { "sp_gravity_off_port_left.EDITOR.ypos",    "1                    },
+  { "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.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.xpos",      "0"                     },
-  { "sp_gravity_off_port_up.EDITOR.ypos",      "2"                     },
+  { "sp_gravity_off_port_up.EDITOR.xpos",      "7"                     },
+  { "sp_gravity_off_port_up.EDITOR.ypos",      "13"                    },
 
   { "sp_sniksnak",                             "RocksSP.pcx"           },
   { "sp_sniksnak.xpos",                                "1"                     },
@@ -727,7 +755,7 @@ struct ConfigInfo image_config[] =
   { "sp_electron.exploding.xpos",              "8"                     },
   { "sp_electron.exploding.ypos",              "4"                     },
   { "sp_electron.exploding.frames",            "8"                     },
-  { "sp_electron.exploding.delay",             "3"                     },
+  { "sp_electron.exploding.delay",             "4"                     },
   { "sp_electron.exploding.anim_mode",         "linear"                },
 
   { "sp_terminal",                             "RocksSP.pcx"           },
@@ -759,7 +787,8 @@ struct ConfigInfo image_config[] =
   { "sp_buggy_base.active.xpos",               "8"                     },
   { "sp_buggy_base.active.ypos",               "6"                     },
   { "sp_buggy_base.active.frames",             "4"                     },
-  { "sp_buggy_base.active.anim_mode",          "random"                },
+  { "sp_buggy_base.active.delay",              "4"                     },
+  { "sp_buggy_base.active.anim_mode",          "pingpong"              },
 
   { "sp_hardware_base_1",                      "RocksSP.pcx"           },
   { "sp_hardware_base_1.xpos",                 "4"                     },
@@ -4352,6 +4381,16 @@ struct ConfigInfo image_config[] =
 #endif
 #endif
 
+  { "sp_frame_horizontal",                     "RocksSP.pcx"           },
+  { "sp_frame_horizontal.xpos",                        "7"                     },
+  { "sp_frame_horizontal.ypos",                        "14"                    },
+  { "sp_frame_vertical",                       "RocksSP.pcx"           },
+  { "sp_frame_vertical.xpos",                  "6"                     },
+  { "sp_frame_vertical.ypos",                  "14"                    },
+  { "sp_frame_corner",                         "RocksSP.pcx"           },
+  { "sp_frame_corner.xpos",                    "5"                     },
+  { "sp_frame_corner.ypos",                    "14"                    },
+
   { "toon_1",                                  "RocksToons.pcx"        },
   { "toon_1.x",                                        "2"                     },
   { "toon_1.y",                                        "72"                    },
@@ -5370,10 +5409,16 @@ 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[SHORTCUTS]",      "0"                     },
+  { "menu.draw_yoffset.SETUP[SHORTCUTS]",      "0"                     },
   { "menu.draw_xoffset.SETUP[SHORTCUTS_1]",    "0"                     },
   { "menu.draw_yoffset.SETUP[SHORTCUTS_1]",    "0"                     },
   { "menu.draw_xoffset.SETUP[SHORTCUTS_2]",    "0"                     },
   { "menu.draw_yoffset.SETUP[SHORTCUTS_2]",    "0"                     },
+  { "menu.draw_xoffset.SETUP[SHORTCUTS_3]",    "0"                     },
+  { "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[CHOOSE_ARTWORK]", "0"                     },
   { "menu.draw_yoffset.SETUP[CHOOSE_ARTWORK]", "0"                     },
   { "menu.draw_xoffset.SETUP[CHOOSE_OTHER]",   "0"                     },
@@ -5797,6 +5842,15 @@ struct ConfigInfo image_config[] =
   { "game.panel.time_ss.draw_masked",          "true"                  },
   { "game.panel.time_ss.draw_order",           "0"                     },
 
+  { "game.panel.frame.x",                      "-1"                    },
+  { "game.panel.frame.y",                      "-1"                    },
+  { "game.panel.frame.align",                  "left"                  },
+  { "game.panel.frame.valign",                 "top"                   },
+  { "game.panel.frame.digits",                 "-1"                    },
+  { "game.panel.frame.font",                   "font.text_2"           },
+  { "game.panel.frame.draw_masked",            "true"                  },
+  { "game.panel.frame.draw_order",             "0"                     },
+
   { "game.panel.shield_normal.x",              "-1"                    },
   { "game.panel.shield_normal.y",              "-1"                    },
   { "game.panel.shield_normal.tile_size",      "16"                    },
@@ -6344,11 +6398,52 @@ struct ConfigInfo image_config[] =
 
   { "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"                 },
 
   { "[player].boring_delay_fixed",             "1000"                  },
   { "[player].boring_delay_random",            "1000"                  },
   { "[player].sleeping_delay_fixed",           "2000"                  },
   { "[player].sleeping_delay_random",          "2000"                  },
 
+  { "viewport.window.width",                   "672"                   },
+  { "viewport.window.height",                  "560"                   },
+  { "viewport.playfield.x",                    "6"                     },
+  { "viewport.playfield.y",                    "6"                     },
+  { "viewport.playfield.width",                        "548"                   },
+  { "viewport.playfield.height",               "548"                   },
+  { "viewport.playfield.border_size",          "2"                     },
+  { "viewport.playfield.MAIN.x",               ARG_DEFAULT             },
+  { "viewport.playfield.MAIN.y",               ARG_DEFAULT             },
+  { "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.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.door_1.x",                       "566"                   },
+  { "viewport.door_1.y",                       "60"                    },
+  { "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.EDITOR.x",                        ARG_DEFAULT             },
+  { "viewport.door_1.EDITOR.y",                        ARG_DEFAULT             },
+  { "viewport.door_2.x",                       "566"                   },
+  { "viewport.door_2.y",                       "400"                   },
+  { "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.EDITOR.x",                        "566"                   },
+  { "viewport.door_2.EDITOR.y",                        "356"                   },
+
   { NULL,                                      NULL                    }
 };
index 471937df3b308d25fa2f7ce49d90fd395805ae54..a8557b04028e9849f309259274976d235b7fee91 100644 (file)
 #define IMG_SP_MURPHY_BORING_1                         60
 #define IMG_SP_MURPHY_SLEEPING_LEFT                    61
 #define IMG_SP_MURPHY_SLEEPING_RIGHT                   62
-#define IMG_SP_MURPHY_CLONE                            63
-#define IMG_SP_INFOTRON                                        64
-#define IMG_SP_INFOTRON_EDITOR                         65
-#define IMG_SP_INFOTRON_COLLECTING                     66
-#define IMG_SP_CHIP_SINGLE                             67
-#define IMG_SP_CHIP_LEFT                               68
-#define IMG_SP_CHIP_RIGHT                              69
-#define IMG_SP_CHIP_TOP                                        70
-#define IMG_SP_CHIP_BOTTOM                             71
-#define IMG_SP_HARDWARE_GRAY                           72
-#define IMG_SP_HARDWARE_GREEN                          73
-#define IMG_SP_HARDWARE_BLUE                           74
-#define IMG_SP_HARDWARE_RED                            75
-#define IMG_SP_HARDWARE_YELLOW                         76
-#define IMG_SP_EXIT_CLOSED                             77
-#define IMG_SP_EXIT_OPENING                            78
-#define IMG_SP_EXIT_OPEN                               79
-#define IMG_SP_EXIT_CLOSING                            80
-#define IMG_SP_DISK_ORANGE                             81
-#define IMG_SP_DISK_YELLOW                             82
-#define IMG_SP_DISK_RED                                        83
-#define IMG_SP_DISK_RED_COLLECTING                     84
-#define IMG_SP_DISK_RED_ACTIVE                         85
-#define IMG_SP_PORT_RIGHT                              86
-#define IMG_SP_PORT_DOWN                               87
-#define IMG_SP_PORT_LEFT                               88
-#define IMG_SP_PORT_UP                                 89
-#define IMG_SP_PORT_HORIZONTAL                         90
-#define IMG_SP_PORT_VERTICAL                           91
-#define IMG_SP_PORT_ANY                                        92
-#define IMG_SP_GRAVITY_PORT_RIGHT                      93
-#define IMG_SP_GRAVITY_PORT_RIGHT_EDITOR               94
-#define IMG_SP_GRAVITY_PORT_DOWN                       95
-#define IMG_SP_GRAVITY_PORT_DOWN_EDITOR                        96
-#define IMG_SP_GRAVITY_PORT_LEFT                       97
-#define IMG_SP_GRAVITY_PORT_LEFT_EDITOR                        98
-#define IMG_SP_GRAVITY_PORT_UP                         99
-#define IMG_SP_GRAVITY_PORT_UP_EDITOR                  100
-#define IMG_SP_GRAVITY_ON_PORT_RIGHT                   101
-#define IMG_SP_GRAVITY_ON_PORT_RIGHT_EDITOR            102
-#define IMG_SP_GRAVITY_ON_PORT_DOWN                    103
-#define IMG_SP_GRAVITY_ON_PORT_DOWN_EDITOR             104
-#define IMG_SP_GRAVITY_ON_PORT_LEFT                    105
-#define IMG_SP_GRAVITY_ON_PORT_LEFT_EDITOR             106
-#define IMG_SP_GRAVITY_ON_PORT_UP                      107
-#define IMG_SP_GRAVITY_ON_PORT_UP_EDITOR               108
-#define IMG_SP_GRAVITY_OFF_PORT_RIGHT                  109
-#define IMG_SP_GRAVITY_OFF_PORT_RIGHT_EDITOR           110
-#define IMG_SP_GRAVITY_OFF_PORT_DOWN                   111
-#define IMG_SP_GRAVITY_OFF_PORT_DOWN_EDITOR            112
-#define IMG_SP_GRAVITY_OFF_PORT_LEFT                   113
-#define IMG_SP_GRAVITY_OFF_PORT_LEFT_EDITOR            114
-#define IMG_SP_GRAVITY_OFF_PORT_UP                     115
-#define IMG_SP_GRAVITY_OFF_PORT_UP_EDITOR              116
-#define IMG_SP_SNIKSNAK                                        117
-#define IMG_SP_SNIKSNAK_LEFT                           118
-#define IMG_SP_SNIKSNAK_RIGHT                          119
-#define IMG_SP_SNIKSNAK_UP                             120
-#define IMG_SP_SNIKSNAK_DOWN                           121
-#define IMG_SP_SNIKSNAK_TURNING_FROM_LEFT_UP           122
-#define IMG_SP_SNIKSNAK_TURNING_FROM_LEFT_DOWN         123
-#define IMG_SP_SNIKSNAK_TURNING_FROM_RIGHT_UP          124
-#define IMG_SP_SNIKSNAK_TURNING_FROM_RIGHT_DOWN                125
-#define IMG_SP_SNIKSNAK_TURNING_FROM_UP_LEFT           126
-#define IMG_SP_SNIKSNAK_TURNING_FROM_UP_RIGHT          127
-#define IMG_SP_SNIKSNAK_TURNING_FROM_DOWN_LEFT         128
-#define IMG_SP_SNIKSNAK_TURNING_FROM_DOWN_RIGHT                129
-#define IMG_SP_ELECTRON                                        130
-#define IMG_SP_ELECTRON_EDITOR                         131
-#define IMG_SP_ELECTRON_EXPLODING                      132
-#define IMG_SP_TERMINAL                                        133
-#define IMG_SP_TERMINAL_EDITOR                         134
-#define IMG_SP_TERMINAL_ACTIVE                         135
-#define IMG_SP_BUGGY_BASE                              136
-#define IMG_SP_BUGGY_BASE_EDITOR                       137
-#define IMG_SP_BUGGY_BASE_ACTIVATING                   138
-#define IMG_SP_BUGGY_BASE_ACTIVE                       139
-#define IMG_SP_HARDWARE_BASE_1                         140
-#define IMG_SP_HARDWARE_BASE_2                         141
-#define IMG_SP_HARDWARE_BASE_3                         142
-#define IMG_SP_HARDWARE_BASE_4                         143
-#define IMG_SP_HARDWARE_BASE_5                         144
-#define IMG_SP_HARDWARE_BASE_6                         145
-#define IMG_SOKOBAN_OBJECT                             146
-#define IMG_SOKOBAN_OBJECT_EDITOR                      147
-#define IMG_SOKOBAN_FIELD_EMPTY                                148
-#define IMG_SOKOBAN_FIELD_FULL                         149
-#define IMG_SOKOBAN_FIELD_PLAYER                       150
-#define IMG_SOKOBAN_FIELD_PLAYER_EDITOR                        151
-#define IMG_EMPTY_SPACE                                        152
-#define IMG_SAND                                       153
-#define IMG_SAND_CRUMBLED                              154
-#define IMG_SAND_DIGGING_LEFT                          155
-#define IMG_SAND_DIGGING_RIGHT                         156
-#define IMG_SAND_DIGGING_UP                            157
-#define IMG_SAND_DIGGING_DOWN                          158
-#define IMG_SAND_DIGGING_LEFT_CRUMBLED                 159
-#define IMG_SAND_DIGGING_RIGHT_CRUMBLED                        160
-#define IMG_SAND_DIGGING_UP_CRUMBLED                   161
-#define IMG_SAND_DIGGING_DOWN_CRUMBLED                 162
-#define IMG_WALL                                       163
-#define IMG_WALL_SLIPPERY                              164
-#define IMG_STEELWALL                                  165
-#define IMG_ROCK                                       166
-#define IMG_ROCK_MOVING_LEFT                           167
-#define IMG_ROCK_MOVING_RIGHT                          168
-#define IMG_ROCK_PUSHING_LEFT                          169
-#define IMG_ROCK_PUSHING_RIGHT                         170
-#define IMG_EMERALD                                    171
-#define IMG_EMERALD_MOVING                             172
-#define IMG_EMERALD_FALLING                            173
-#define IMG_EMERALD_COLLECTING                         174
-#define IMG_DIAMOND                                    175
-#define IMG_DIAMOND_MOVING                             176
-#define IMG_DIAMOND_FALLING                            177
-#define IMG_DIAMOND_COLLECTING                         178
-#define IMG_BOMB                                       179
-#define IMG_NUT                                                180
-#define IMG_NUT_BREAKING                               181
-#define IMG_DYNAMITE                                   182
-#define IMG_DYNAMITE_EDITOR                            183
-#define IMG_DYNAMITE_ACTIVE                            184
-#define IMG_DYNAMITE_ACTIVE_EDITOR                     185
-#define IMG_EM_DYNAMITE                                        186
-#define IMG_EM_DYNAMITE_ACTIVE                         187
-#define IMG_EM_DYNAMITE_ACTIVE_EDITOR                  188
-#define IMG_WALL_EMERALD                               189
-#define IMG_WALL_DIAMOND                               190
-#define IMG_BUG                                                191
-#define IMG_BUG_RIGHT                                  192
-#define IMG_BUG_UP                                     193
-#define IMG_BUG_LEFT                                   194
-#define IMG_BUG_DOWN                                   195
-#define IMG_BUG_MOVING_RIGHT                           196
-#define IMG_BUG_MOVING_UP                              197
-#define IMG_BUG_MOVING_LEFT                            198
-#define IMG_BUG_MOVING_DOWN                            199
-#define IMG_BUG_TURNING_FROM_RIGHT_UP                  200
-#define IMG_BUG_TURNING_FROM_UP_LEFT                   201
-#define IMG_BUG_TURNING_FROM_LEFT_DOWN                 202
-#define IMG_BUG_TURNING_FROM_DOWN_RIGHT                        203
-#define IMG_BUG_TURNING_FROM_RIGHT_DOWN                        204
-#define IMG_BUG_TURNING_FROM_UP_RIGHT                  205
-#define IMG_BUG_TURNING_FROM_LEFT_UP                   206
-#define IMG_BUG_TURNING_FROM_DOWN_LEFT                 207
-#define IMG_SPACESHIP                                  208
-#define IMG_SPACESHIP_RIGHT                            209
-#define IMG_SPACESHIP_UP                               210
-#define IMG_SPACESHIP_LEFT                             211
-#define IMG_SPACESHIP_DOWN                             212
-#define IMG_SPACESHIP_MOVING_RIGHT                     213
-#define IMG_SPACESHIP_MOVING_UP                                214
-#define IMG_SPACESHIP_MOVING_LEFT                      215
-#define IMG_SPACESHIP_MOVING_DOWN                      216
-#define IMG_SPACESHIP_TURNING_FROM_RIGHT_UP            217
-#define IMG_SPACESHIP_TURNING_FROM_UP_LEFT             218
-#define IMG_SPACESHIP_TURNING_FROM_LEFT_DOWN           219
-#define IMG_SPACESHIP_TURNING_FROM_DOWN_RIGHT          220
-#define IMG_SPACESHIP_TURNING_FROM_RIGHT_DOWN          221
-#define IMG_SPACESHIP_TURNING_FROM_UP_RIGHT            222
-#define IMG_SPACESHIP_TURNING_FROM_LEFT_UP             223
-#define IMG_SPACESHIP_TURNING_FROM_DOWN_LEFT           224
-#define IMG_YAMYAM                                     225
-#define IMG_YAMYAM_LEFT                                        226
-#define IMG_YAMYAM_LEFT_EDITOR                         227
-#define IMG_YAMYAM_RIGHT                               228
-#define IMG_YAMYAM_RIGHT_EDITOR                                229
-#define IMG_YAMYAM_UP                                  230
-#define IMG_YAMYAM_UP_EDITOR                           231
-#define IMG_YAMYAM_DOWN                                        232
-#define IMG_YAMYAM_DOWN_EDITOR                         233
-#define IMG_YAMYAM_MOVING                              234
-#define IMG_ROBOT                                      235
-#define IMG_ROBOT_MOVING                               236
-#define IMG_ROBOT_WHEEL                                        237
-#define IMG_ROBOT_WHEEL_ACTIVE                         238
-#define IMG_MAGIC_WALL                                 239
-#define IMG_MAGIC_WALL_ACTIVE                          240
-#define IMG_MAGIC_WALL_FILLING                         241
-#define IMG_MAGIC_WALL_FULL                            242
-#define IMG_MAGIC_WALL_EMPTYING                                243
-#define IMG_MAGIC_WALL_DEAD                            244
-#define IMG_DC_MAGIC_WALL                              245
-#define IMG_DC_MAGIC_WALL_ACTIVE                       246
-#define IMG_DC_MAGIC_WALL_FILLING                      247
-#define IMG_DC_MAGIC_WALL_FULL                         248
-#define IMG_DC_MAGIC_WALL_EMPTYING                     249
-#define IMG_DC_MAGIC_WALL_DEAD                         250
-#define IMG_QUICKSAND_EMPTY                            251
-#define IMG_QUICKSAND_FILLING                          252
-#define IMG_QUICKSAND_FULL                             253
-#define IMG_QUICKSAND_FULL_EDITOR                      254
-#define IMG_QUICKSAND_EMPTYING                         255
-#define IMG_QUICKSAND_FAST_EMPTY                       256
-#define IMG_QUICKSAND_FAST_FILLING                     257
-#define IMG_QUICKSAND_FAST_FULL                                258
-#define IMG_QUICKSAND_FAST_FULL_EDITOR                 259
-#define IMG_QUICKSAND_FAST_EMPTYING                    260
-#define IMG_ACID_POOL_TOPLEFT                          261
-#define IMG_ACID_POOL_TOPRIGHT                         262
-#define IMG_ACID_POOL_BOTTOMLEFT                       263
-#define IMG_ACID_POOL_BOTTOM                           264
-#define IMG_ACID_POOL_BOTTOMRIGHT                      265
-#define IMG_ACID                                       266
-#define IMG_ACID_SPLASH_LEFT                           267
-#define IMG_ACID_SPLASH_RIGHT                          268
-#define IMG_AMOEBA_DROP                                        269
-#define IMG_AMOEBA_GROWING                             270
-#define IMG_AMOEBA_SHRINKING                           271
-#define IMG_AMOEBA_WET                                 272
-#define IMG_AMOEBA_WET_EDITOR                          273
-#define IMG_AMOEBA_DROPPING                            274
-#define IMG_AMOEBA_DRY                                 275
-#define IMG_AMOEBA_FULL                                        276
-#define IMG_AMOEBA_FULL_EDITOR                         277
-#define IMG_AMOEBA_DEAD                                        278
-#define IMG_AMOEBA_DEAD_EDITOR                         279
-#define IMG_EM_KEY_1                                   280
-#define IMG_EM_KEY_2                                   281
-#define IMG_EM_KEY_3                                   282
-#define IMG_EM_KEY_4                                   283
-#define IMG_DC_KEY_WHITE                               284
-#define IMG_EM_GATE_1                                  285
-#define IMG_EM_GATE_2                                  286
-#define IMG_EM_GATE_3                                  287
-#define IMG_EM_GATE_4                                  288
-#define IMG_DC_GATE_WHITE                              289
-#define IMG_EM_GATE_1_GRAY                             290
-#define IMG_EM_GATE_1_GRAY_EDITOR                      291
-#define IMG_EM_GATE_1_GRAY_ACTIVE                      292
-#define IMG_EM_GATE_2_GRAY                             293
-#define IMG_EM_GATE_2_GRAY_EDITOR                      294
-#define IMG_EM_GATE_2_GRAY_ACTIVE                      295
-#define IMG_EM_GATE_3_GRAY                             296
-#define IMG_EM_GATE_3_GRAY_EDITOR                      297
-#define IMG_EM_GATE_3_GRAY_ACTIVE                      298
-#define IMG_EM_GATE_4_GRAY                             299
-#define IMG_EM_GATE_4_GRAY_EDITOR                      300
-#define IMG_EM_GATE_4_GRAY_ACTIVE                      301
-#define IMG_DC_GATE_WHITE_GRAY                         302
-#define IMG_DC_GATE_WHITE_GRAY_EDITOR                  303
-#define IMG_DC_GATE_WHITE_GRAY_ACTIVE                  304
-#define IMG_DC_GATE_FAKE_GRAY                          305
-#define IMG_EXIT_CLOSED                                        306
-#define IMG_EXIT_OPENING                               307
-#define IMG_EXIT_OPEN                                  308
-#define IMG_EXIT_CLOSING                               309
-#define IMG_STEEL_EXIT_CLOSED                          310
-#define IMG_STEEL_EXIT_OPENING                         311
-#define IMG_STEEL_EXIT_OPEN                            312
-#define IMG_STEEL_EXIT_CLOSING                         313
-#define IMG_EM_EXIT_CLOSED                             314
-#define IMG_EM_EXIT_OPENING                            315
-#define IMG_EM_EXIT_OPEN                               316
-#define IMG_EM_EXIT_CLOSING                            317
-#define IMG_EM_STEEL_EXIT_CLOSED                       318
-#define IMG_EM_STEEL_EXIT_OPENING                      319
-#define IMG_EM_STEEL_EXIT_OPEN                         320
-#define IMG_EM_STEEL_EXIT_CLOSING                      321
-#define IMG_BALLOON                                    322
-#define IMG_BALLOON_MOVING                             323
-#define IMG_BALLOON_PUSHING                            324
-#define IMG_BALLOON_SWITCH_LEFT                                325
-#define IMG_BALLOON_SWITCH_RIGHT                       326
-#define IMG_BALLOON_SWITCH_UP                          327
-#define IMG_BALLOON_SWITCH_DOWN                                328
-#define IMG_BALLOON_SWITCH_ANY                         329
-#define IMG_BALLOON_SWITCH_NONE                                330
-#define IMG_SPRING                                     331
-#define IMG_EMC_STEELWALL_1                            332
-#define IMG_EMC_STEELWALL_2                            333
-#define IMG_EMC_STEELWALL_3                            334
-#define IMG_EMC_STEELWALL_4                            335
-#define IMG_EMC_WALL_1                                 336
-#define IMG_EMC_WALL_2                                 337
-#define IMG_EMC_WALL_3                                 338
-#define IMG_EMC_WALL_4                                 339
-#define IMG_EMC_WALL_5                                 340
-#define IMG_EMC_WALL_6                                 341
-#define IMG_EMC_WALL_7                                 342
-#define IMG_EMC_WALL_8                                 343
-#define IMG_INVISIBLE_STEELWALL                                344
-#define IMG_INVISIBLE_STEELWALL_EDITOR                 345
-#define IMG_INVISIBLE_STEELWALL_ACTIVE                 346
-#define IMG_INVISIBLE_WALL                             347
-#define IMG_INVISIBLE_WALL_EDITOR                      348
-#define IMG_INVISIBLE_WALL_ACTIVE                      349
-#define IMG_INVISIBLE_SAND                             350
-#define IMG_INVISIBLE_SAND_EDITOR                      351
-#define IMG_INVISIBLE_SAND_ACTIVE                      352
-#define IMG_INVISIBLE_SAND_ACTIVE_CRUMBLED             353
-#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_LEFT         354
-#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_RIGHT                355
-#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_UP           356
-#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_DOWN         357
-#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_LEFT_CRUMBLED        358
-#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_RIGHT_CRUMBLED       359
-#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_UP_CRUMBLED  360
-#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_DOWN_CRUMBLED        361
-#define IMG_CONVEYOR_BELT_1_MIDDLE                     362
-#define IMG_CONVEYOR_BELT_1_MIDDLE_ACTIVE              363
-#define IMG_CONVEYOR_BELT_1_LEFT                       364
-#define IMG_CONVEYOR_BELT_1_LEFT_ACTIVE                        365
-#define IMG_CONVEYOR_BELT_1_RIGHT                      366
-#define IMG_CONVEYOR_BELT_1_RIGHT_ACTIVE               367
-#define IMG_CONVEYOR_BELT_1_SWITCH_LEFT                        368
-#define IMG_CONVEYOR_BELT_1_SWITCH_MIDDLE              369
-#define IMG_CONVEYOR_BELT_1_SWITCH_RIGHT               370
-#define IMG_CONVEYOR_BELT_2_MIDDLE                     371
-#define IMG_CONVEYOR_BELT_2_MIDDLE_ACTIVE              372
-#define IMG_CONVEYOR_BELT_2_LEFT                       373
-#define IMG_CONVEYOR_BELT_2_LEFT_ACTIVE                        374
-#define IMG_CONVEYOR_BELT_2_RIGHT                      375
-#define IMG_CONVEYOR_BELT_2_RIGHT_ACTIVE               376
-#define IMG_CONVEYOR_BELT_2_SWITCH_LEFT                        377
-#define IMG_CONVEYOR_BELT_2_SWITCH_MIDDLE              378
-#define IMG_CONVEYOR_BELT_2_SWITCH_RIGHT               379
-#define IMG_CONVEYOR_BELT_3_MIDDLE                     380
-#define IMG_CONVEYOR_BELT_3_MIDDLE_ACTIVE              381
-#define IMG_CONVEYOR_BELT_3_LEFT                       382
-#define IMG_CONVEYOR_BELT_3_LEFT_ACTIVE                        383
-#define IMG_CONVEYOR_BELT_3_RIGHT                      384
-#define IMG_CONVEYOR_BELT_3_RIGHT_ACTIVE               385
-#define IMG_CONVEYOR_BELT_3_SWITCH_LEFT                        386
-#define IMG_CONVEYOR_BELT_3_SWITCH_MIDDLE              387
-#define IMG_CONVEYOR_BELT_3_SWITCH_RIGHT               388
-#define IMG_CONVEYOR_BELT_4_MIDDLE                     389
-#define IMG_CONVEYOR_BELT_4_MIDDLE_ACTIVE              390
-#define IMG_CONVEYOR_BELT_4_LEFT                       391
-#define IMG_CONVEYOR_BELT_4_LEFT_ACTIVE                        392
-#define IMG_CONVEYOR_BELT_4_RIGHT                      393
-#define IMG_CONVEYOR_BELT_4_RIGHT_ACTIVE               394
-#define IMG_CONVEYOR_BELT_4_SWITCH_LEFT                        395
-#define IMG_CONVEYOR_BELT_4_SWITCH_MIDDLE              396
-#define IMG_CONVEYOR_BELT_4_SWITCH_RIGHT               397
-#define IMG_SWITCHGATE_SWITCH_UP                       398
-#define IMG_SWITCHGATE_SWITCH_DOWN                     399
-#define IMG_DC_SWITCHGATE_SWITCH_UP                    400
-#define IMG_DC_SWITCHGATE_SWITCH_DOWN                  401
-#define IMG_LIGHT_SWITCH                               402
-#define IMG_LIGHT_SWITCH_ACTIVE                                403
-#define IMG_TIMEGATE_SWITCH                            404
-#define IMG_TIMEGATE_SWITCH_ACTIVE                     405
-#define IMG_DC_TIMEGATE_SWITCH                         406
-#define IMG_DC_TIMEGATE_SWITCH_ACTIVE                  407
-#define IMG_ENVELOPE_1                                 408
-#define IMG_ENVELOPE_1_COLLECTING                      409
-#define IMG_ENVELOPE_2                                 410
-#define IMG_ENVELOPE_2_COLLECTING                      411
-#define IMG_ENVELOPE_3                                 412
-#define IMG_ENVELOPE_3_COLLECTING                      413
-#define IMG_ENVELOPE_4                                 414
-#define IMG_ENVELOPE_4_COLLECTING                      415
-#define IMG_SIGN_RADIOACTIVITY                         416
-#define IMG_SIGN_GIVE_WAY                              417
-#define IMG_SIGN_NO_ENTRY                              418
-#define IMG_SIGN_EMERGENCY_EXIT                                419
-#define IMG_SIGN_YIN_YANG                              420
-#define IMG_SIGN_EXCLAMATION                           421
-#define IMG_SIGN_STOP                                  422
-#define IMG_SIGN_PARKING                               423
-#define IMG_SIGN_WHEELCHAIR                            424
-#define IMG_SIGN_ENTRY_FORBIDDEN                       425
-#define IMG_SPERMS                                     426
-#define IMG_BULLET                                     427
-#define IMG_HEART                                      428
-#define IMG_CROSS                                      429
-#define IMG_FRANKIE                                    430
-#define IMG_SIGN_SPERMS                                        431
-#define IMG_SIGN_BULLET                                        432
-#define IMG_SIGN_HEART                                 433
-#define IMG_SIGN_CROSS                                 434
-#define IMG_SIGN_FRANKIE                               435
-#define IMG_LANDMINE                                   436
-#define IMG_DC_LANDMINE                                        437
-#define IMG_STEELWALL_SLIPPERY                         438
-#define IMG_EXTRA_TIME                                 439
-#define IMG_SHIELD_NORMAL                              440
-#define IMG_SHIELD_NORMAL_ACTIVE                       441
-#define IMG_SHIELD_DEADLY                              442
-#define IMG_SHIELD_DEADLY_ACTIVE                       443
-#define IMG_SWITCHGATE_CLOSED                          444
-#define IMG_SWITCHGATE_OPENING                         445
-#define IMG_SWITCHGATE_OPEN                            446
-#define IMG_SWITCHGATE_CLOSING                         447
-#define IMG_TIMEGATE_CLOSED                            448
-#define IMG_TIMEGATE_OPENING                           449
-#define IMG_TIMEGATE_OPEN                              450
-#define IMG_TIMEGATE_CLOSING                           451
-#define IMG_PEARL                                      452
-#define IMG_PEARL_BREAKING                             453
-#define IMG_CRYSTAL                                    454
-#define IMG_WALL_PEARL                                 455
-#define IMG_WALL_CRYSTAL                               456
-#define IMG_DC_STEELWALL_1_LEFT                                457
-#define IMG_DC_STEELWALL_1_RIGHT                       458
-#define IMG_DC_STEELWALL_1_TOP                         459
-#define IMG_DC_STEELWALL_1_BOTTOM                      460
-#define IMG_DC_STEELWALL_1_HORIZONTAL                  461
-#define IMG_DC_STEELWALL_1_VERTICAL                    462
-#define IMG_DC_STEELWALL_1_TOPLEFT                     463
-#define IMG_DC_STEELWALL_1_TOPRIGHT                    464
-#define IMG_DC_STEELWALL_1_BOTTOMLEFT                  465
-#define IMG_DC_STEELWALL_1_BOTTOMRIGHT                 466
-#define IMG_DC_STEELWALL_1_TOPLEFT_2                   467
-#define IMG_DC_STEELWALL_1_TOPRIGHT_2                  468
-#define IMG_DC_STEELWALL_1_BOTTOMLEFT_2                        469
-#define IMG_DC_STEELWALL_1_BOTTOMRIGHT_2               470
-#define IMG_DC_STEELWALL_2_LEFT                                471
-#define IMG_DC_STEELWALL_2_RIGHT                       472
-#define IMG_DC_STEELWALL_2_TOP                         473
-#define IMG_DC_STEELWALL_2_BOTTOM                      474
-#define IMG_DC_STEELWALL_2_HORIZONTAL                  475
-#define IMG_DC_STEELWALL_2_VERTICAL                    476
-#define IMG_DC_STEELWALL_2_MIDDLE                      477
-#define IMG_DC_STEELWALL_2_SINGLE                      478
-#define IMG_TUBE_RIGHT_DOWN                            479
-#define IMG_TUBE_HORIZONTAL_DOWN                       480
-#define IMG_TUBE_LEFT_DOWN                             481
-#define IMG_TUBE_HORIZONTAL                            482
-#define IMG_TUBE_VERTICAL_RIGHT                                483
-#define IMG_TUBE_ANY                                   484
-#define IMG_TUBE_VERTICAL_LEFT                         485
-#define IMG_TUBE_VERTICAL                              486
-#define IMG_TUBE_RIGHT_UP                              487
-#define IMG_TUBE_HORIZONTAL_UP                         488
-#define IMG_TUBE_LEFT_UP                               489
-#define IMG_TRAP                                       490
-#define IMG_TRAP_ACTIVE                                        491
-#define IMG_DX_SUPABOMB                                        492
-#define IMG_KEY_1                                      493
-#define IMG_KEY_1_EDITOR                               494
-#define IMG_KEY_2                                      495
-#define IMG_KEY_2_EDITOR                               496
-#define IMG_KEY_3                                      497
-#define IMG_KEY_3_EDITOR                               498
-#define IMG_KEY_4                                      499
-#define IMG_KEY_4_EDITOR                               500
-#define IMG_GATE_1                                     501
-#define IMG_GATE_2                                     502
-#define IMG_GATE_3                                     503
-#define IMG_GATE_4                                     504
-#define IMG_GATE_1_GRAY                                        505
-#define IMG_GATE_1_GRAY_EDITOR                         506
-#define IMG_GATE_1_GRAY_ACTIVE                         507
-#define IMG_GATE_2_GRAY                                        508
-#define IMG_GATE_2_GRAY_EDITOR                         509
-#define IMG_GATE_2_GRAY_ACTIVE                         510
-#define IMG_GATE_3_GRAY                                        511
-#define IMG_GATE_3_GRAY_EDITOR                         512
-#define IMG_GATE_3_GRAY_ACTIVE                         513
-#define IMG_GATE_4_GRAY                                        514
-#define IMG_GATE_4_GRAY_EDITOR                         515
-#define IMG_GATE_4_GRAY_ACTIVE                         516
-#define IMG_GAME_OF_LIFE                               517
-#define IMG_BIOMAZE                                    518
-#define IMG_PACMAN                                     519
-#define IMG_PACMAN_RIGHT                               520
-#define IMG_PACMAN_UP                                  521
-#define IMG_PACMAN_LEFT                                        522
-#define IMG_PACMAN_DOWN                                        523
-#define IMG_PACMAN_TURNING_FROM_RIGHT                  524
-#define IMG_PACMAN_TURNING_FROM_UP                     525
-#define IMG_PACMAN_TURNING_FROM_LEFT                   526
-#define IMG_PACMAN_TURNING_FROM_DOWN                   527
-#define IMG_LAMP                                       528
-#define IMG_LAMP_EDITOR                                        529
-#define IMG_LAMP_ACTIVE                                        530
-#define IMG_TIME_ORB_FULL                              531
-#define IMG_TIME_ORB_EMPTY                             532
-#define IMG_EMERALD_YELLOW                             533
-#define IMG_EMERALD_YELLOW_MOVING                      534
-#define IMG_EMERALD_YELLOW_FALLING                     535
-#define IMG_EMERALD_RED                                        536
-#define IMG_EMERALD_RED_MOVING                         537
-#define IMG_EMERALD_RED_FALLING                                538
-#define IMG_EMERALD_PURPLE                             539
-#define IMG_EMERALD_PURPLE_MOVING                      540
-#define IMG_EMERALD_PURPLE_FALLING                     541
-#define IMG_WALL_EMERALD_YELLOW                                542
-#define IMG_WALL_EMERALD_RED                           543
-#define IMG_WALL_EMERALD_PURPLE                                544
-#define IMG_WALL_BD_DIAMOND                            545
-#define IMG_EXPANDABLE_WALL                            546
-#define IMG_EXPANDABLE_WALL_HORIZONTAL                 547
-#define IMG_EXPANDABLE_WALL_HORIZONTAL_EDITOR          548
-#define IMG_EXPANDABLE_WALL_VERTICAL                   549
-#define IMG_EXPANDABLE_WALL_VERTICAL_EDITOR            550
-#define IMG_EXPANDABLE_WALL_ANY                                551
-#define IMG_EXPANDABLE_WALL_ANY_EDITOR                 552
-#define IMG_EXPANDABLE_STEELWALL_HORIZONTAL            553
-#define IMG_EXPANDABLE_STEELWALL_HORIZONTAL_EDITOR     554
-#define IMG_EXPANDABLE_STEELWALL_VERTICAL              555
-#define IMG_EXPANDABLE_STEELWALL_VERTICAL_EDITOR       556
-#define IMG_EXPANDABLE_STEELWALL_ANY                   557
-#define IMG_EXPANDABLE_STEELWALL_ANY_EDITOR            558
-#define IMG_BD_EXPANDABLE_WALL                         559
-#define IMG_BD_EXPANDABLE_WALL_EDITOR                  560
-#define IMG_EXPANDABLE_WALL_GROWING_LEFT               561
-#define IMG_EXPANDABLE_WALL_GROWING_RIGHT              562
-#define IMG_EXPANDABLE_WALL_GROWING_UP                 563
-#define IMG_EXPANDABLE_WALL_GROWING_DOWN               564
-#define IMG_EXPANDABLE_STEELWALL_GROWING_LEFT          565
-#define IMG_EXPANDABLE_STEELWALL_GROWING_RIGHT         566
-#define IMG_EXPANDABLE_STEELWALL_GROWING_UP            567
-#define IMG_EXPANDABLE_STEELWALL_GROWING_DOWN          568
-#define IMG_BLACK_ORB                                  569
-#define IMG_SPEED_PILL                                 570
-#define IMG_DARK_YAMYAM                                        571
-#define IMG_DYNABOMB                                   572
-#define IMG_DYNABOMB_ACTIVE                            573
-#define IMG_DYNABOMB_PLAYER_1                          574
-#define IMG_DYNABOMB_PLAYER_1_ACTIVE                   575
-#define IMG_DYNABOMB_PLAYER_2                          576
-#define IMG_DYNABOMB_PLAYER_2_ACTIVE                   577
-#define IMG_DYNABOMB_PLAYER_3                          578
-#define IMG_DYNABOMB_PLAYER_3_ACTIVE                   579
-#define IMG_DYNABOMB_PLAYER_4                          580
-#define IMG_DYNABOMB_PLAYER_4_ACTIVE                   581
-#define IMG_DYNABOMB_INCREASE_NUMBER                   582
-#define IMG_DYNABOMB_INCREASE_SIZE                     583
-#define IMG_DYNABOMB_INCREASE_POWER                    584
-#define IMG_PIG                                                585
-#define IMG_PIG_DOWN                                   586
-#define IMG_PIG_UP                                     587
-#define IMG_PIG_LEFT                                   588
-#define IMG_PIG_RIGHT                                  589
-#define IMG_PIG_MOVING_DOWN                            590
-#define IMG_PIG_MOVING_UP                              591
-#define IMG_PIG_MOVING_LEFT                            592
-#define IMG_PIG_MOVING_RIGHT                           593
-#define IMG_PIG_DIGGING_DOWN                           594
-#define IMG_PIG_DIGGING_UP                             595
-#define IMG_PIG_DIGGING_LEFT                           596
-#define IMG_PIG_DIGGING_RIGHT                          597
-#define IMG_DRAGON                                     598
-#define IMG_DRAGON_DOWN                                        599
-#define IMG_DRAGON_UP                                  600
-#define IMG_DRAGON_LEFT                                        601
-#define IMG_DRAGON_RIGHT                               602
-#define IMG_DRAGON_MOVING_DOWN                         603
-#define IMG_DRAGON_MOVING_UP                           604
-#define IMG_DRAGON_MOVING_LEFT                         605
-#define IMG_DRAGON_MOVING_RIGHT                                606
-#define IMG_DRAGON_ATTACKING_DOWN                      607
-#define IMG_DRAGON_ATTACKING_UP                                608
-#define IMG_DRAGON_ATTACKING_LEFT                      609
-#define IMG_DRAGON_ATTACKING_RIGHT                     610
-#define IMG_MOLE                                       611
-#define IMG_MOLE_DOWN                                  612
-#define IMG_MOLE_UP                                    613
-#define IMG_MOLE_LEFT                                  614
-#define IMG_MOLE_RIGHT                                 615
-#define IMG_MOLE_MOVING_DOWN                           616
-#define IMG_MOLE_MOVING_UP                             617
-#define IMG_MOLE_MOVING_LEFT                           618
-#define IMG_MOLE_MOVING_RIGHT                          619
-#define IMG_MOLE_DIGGING_DOWN                          620
-#define IMG_MOLE_DIGGING_UP                            621
-#define IMG_MOLE_DIGGING_LEFT                          622
-#define IMG_MOLE_DIGGING_RIGHT                         623
-#define IMG_PENGUIN                                    624
-#define IMG_PENGUIN_EDITOR                             625
-#define IMG_PENGUIN_DOWN                               626
-#define IMG_PENGUIN_UP                                 627
-#define IMG_PENGUIN_LEFT                               628
-#define IMG_PENGUIN_RIGHT                              629
-#define IMG_PENGUIN_MOVING_DOWN                                630
-#define IMG_PENGUIN_MOVING_UP                          631
-#define IMG_PENGUIN_MOVING_LEFT                                632
-#define IMG_PENGUIN_MOVING_RIGHT                       633
-#define IMG_SATELLITE                                  634
-#define IMG_FLAMES_1_LEFT                              635
-#define IMG_FLAMES_2_LEFT                              636
-#define IMG_FLAMES_3_LEFT                              637
-#define IMG_FLAMES_1_RIGHT                             638
-#define IMG_FLAMES_2_RIGHT                             639
-#define IMG_FLAMES_3_RIGHT                             640
-#define IMG_FLAMES_1_UP                                        641
-#define IMG_FLAMES_2_UP                                        642
-#define IMG_FLAMES_3_UP                                        643
-#define IMG_FLAMES_1_DOWN                              644
-#define IMG_FLAMES_2_DOWN                              645
-#define IMG_FLAMES_3_DOWN                              646
-#define IMG_STONEBLOCK                                 647
-#define IMG_PLAYER_1                                   648
-#define IMG_PLAYER_1_EDITOR                            649
-#define IMG_PLAYER_1_DOWN                              650
-#define IMG_PLAYER_1_UP                                        651
-#define IMG_PLAYER_1_LEFT                              652
-#define IMG_PLAYER_1_RIGHT                             653
-#define IMG_PLAYER_1_MOVING_DOWN                       654
-#define IMG_PLAYER_1_MOVING_UP                         655
-#define IMG_PLAYER_1_MOVING_LEFT                       656
-#define IMG_PLAYER_1_MOVING_RIGHT                      657
-#define IMG_PLAYER_1_DIGGING_DOWN                      658
-#define IMG_PLAYER_1_DIGGING_UP                                659
-#define IMG_PLAYER_1_DIGGING_LEFT                      660
-#define IMG_PLAYER_1_DIGGING_RIGHT                     661
-#define IMG_PLAYER_1_COLLECTING_DOWN                   662
-#define IMG_PLAYER_1_COLLECTING_UP                     663
-#define IMG_PLAYER_1_COLLECTING_LEFT                   664
-#define IMG_PLAYER_1_COLLECTING_RIGHT                  665
-#define IMG_PLAYER_1_PUSHING_DOWN                      666
-#define IMG_PLAYER_1_PUSHING_UP                                667
-#define IMG_PLAYER_1_PUSHING_LEFT                      668
-#define IMG_PLAYER_1_PUSHING_RIGHT                     669
-#define IMG_PLAYER_1_SNAPPING_DOWN                     670
-#define IMG_PLAYER_1_SNAPPING_UP                       671
-#define IMG_PLAYER_1_SNAPPING_LEFT                     672
-#define IMG_PLAYER_1_SNAPPING_RIGHT                    673
-#define IMG_PLAYER_2                                   674
-#define IMG_PLAYER_2_EDITOR                            675
-#define IMG_PLAYER_2_DOWN                              676
-#define IMG_PLAYER_2_UP                                        677
-#define IMG_PLAYER_2_LEFT                              678
-#define IMG_PLAYER_2_RIGHT                             679
-#define IMG_PLAYER_2_MOVING_DOWN                       680
-#define IMG_PLAYER_2_MOVING_UP                         681
-#define IMG_PLAYER_2_MOVING_LEFT                       682
-#define IMG_PLAYER_2_MOVING_RIGHT                      683
-#define IMG_PLAYER_2_DIGGING_DOWN                      684
-#define IMG_PLAYER_2_DIGGING_UP                                685
-#define IMG_PLAYER_2_DIGGING_LEFT                      686
-#define IMG_PLAYER_2_DIGGING_RIGHT                     687
-#define IMG_PLAYER_2_COLLECTING_DOWN                   688
-#define IMG_PLAYER_2_COLLECTING_UP                     689
-#define IMG_PLAYER_2_COLLECTING_LEFT                   690
-#define IMG_PLAYER_2_COLLECTING_RIGHT                  691
-#define IMG_PLAYER_2_PUSHING_DOWN                      692
-#define IMG_PLAYER_2_PUSHING_UP                                693
-#define IMG_PLAYER_2_PUSHING_LEFT                      694
-#define IMG_PLAYER_2_PUSHING_RIGHT                     695
-#define IMG_PLAYER_2_SNAPPING_DOWN                     696
-#define IMG_PLAYER_2_SNAPPING_UP                       697
-#define IMG_PLAYER_2_SNAPPING_LEFT                     698
-#define IMG_PLAYER_2_SNAPPING_RIGHT                    699
-#define IMG_PLAYER_3                                   700
-#define IMG_PLAYER_3_EDITOR                            701
-#define IMG_PLAYER_3_DOWN                              702
-#define IMG_PLAYER_3_UP                                        703
-#define IMG_PLAYER_3_LEFT                              704
-#define IMG_PLAYER_3_RIGHT                             705
-#define IMG_PLAYER_3_MOVING_DOWN                       706
-#define IMG_PLAYER_3_MOVING_UP                         707
-#define IMG_PLAYER_3_MOVING_LEFT                       708
-#define IMG_PLAYER_3_MOVING_RIGHT                      709
-#define IMG_PLAYER_3_DIGGING_DOWN                      710
-#define IMG_PLAYER_3_DIGGING_UP                                711
-#define IMG_PLAYER_3_DIGGING_LEFT                      712
-#define IMG_PLAYER_3_DIGGING_RIGHT                     713
-#define IMG_PLAYER_3_COLLECTING_DOWN                   714
-#define IMG_PLAYER_3_COLLECTING_UP                     715
-#define IMG_PLAYER_3_COLLECTING_LEFT                   716
-#define IMG_PLAYER_3_COLLECTING_RIGHT                  717
-#define IMG_PLAYER_3_PUSHING_DOWN                      718
-#define IMG_PLAYER_3_PUSHING_UP                                719
-#define IMG_PLAYER_3_PUSHING_LEFT                      720
-#define IMG_PLAYER_3_PUSHING_RIGHT                     721
-#define IMG_PLAYER_3_SNAPPING_DOWN                     722
-#define IMG_PLAYER_3_SNAPPING_UP                       723
-#define IMG_PLAYER_3_SNAPPING_LEFT                     724
-#define IMG_PLAYER_3_SNAPPING_RIGHT                    725
-#define IMG_PLAYER_4                                   726
-#define IMG_PLAYER_4_EDITOR                            727
-#define IMG_PLAYER_4_DOWN                              728
-#define IMG_PLAYER_4_UP                                        729
-#define IMG_PLAYER_4_LEFT                              730
-#define IMG_PLAYER_4_RIGHT                             731
-#define IMG_PLAYER_4_MOVING_DOWN                       732
-#define IMG_PLAYER_4_MOVING_UP                         733
-#define IMG_PLAYER_4_MOVING_LEFT                       734
-#define IMG_PLAYER_4_MOVING_RIGHT                      735
-#define IMG_PLAYER_4_DIGGING_DOWN                      736
-#define IMG_PLAYER_4_DIGGING_UP                                737
-#define IMG_PLAYER_4_DIGGING_LEFT                      738
-#define IMG_PLAYER_4_DIGGING_RIGHT                     739
-#define IMG_PLAYER_4_COLLECTING_DOWN                   740
-#define IMG_PLAYER_4_COLLECTING_UP                     741
-#define IMG_PLAYER_4_COLLECTING_LEFT                   742
-#define IMG_PLAYER_4_COLLECTING_RIGHT                  743
-#define IMG_PLAYER_4_PUSHING_DOWN                      744
-#define IMG_PLAYER_4_PUSHING_UP                                745
-#define IMG_PLAYER_4_PUSHING_LEFT                      746
-#define IMG_PLAYER_4_PUSHING_RIGHT                     747
-#define IMG_PLAYER_4_SNAPPING_DOWN                     748
-#define IMG_PLAYER_4_SNAPPING_UP                       749
-#define IMG_PLAYER_4_SNAPPING_LEFT                     750
-#define IMG_PLAYER_4_SNAPPING_RIGHT                    751
-#define IMG_DEFAULT_EXPLODING                          752
-#define IMG_TWINKLE_BLUE                               753
-#define IMG_TWINKLE_WHITE                              754
-#define IMG_STEELWALL_TOPLEFT                          755
-#define IMG_STEELWALL_TOPRIGHT                         756
-#define IMG_STEELWALL_BOTTOMLEFT                       757
-#define IMG_STEELWALL_BOTTOMRIGHT                      758
-#define IMG_STEELWALL_HORIZONTAL                       759
-#define IMG_STEELWALL_VERTICAL                         760
-#define IMG_STEELWALL_TOPLEFT_EDITOR                   761
-#define IMG_STEELWALL_TOPRIGHT_EDITOR                  762
-#define IMG_STEELWALL_BOTTOMLEFT_EDITOR                        763
-#define IMG_STEELWALL_BOTTOMRIGHT_EDITOR               764
-#define IMG_STEELWALL_HORIZONTAL_EDITOR                        765
-#define IMG_STEELWALL_VERTICAL_EDITOR                  766
-#define IMG_INVISIBLE_STEELWALL_TOPLEFT                        767
-#define IMG_INVISIBLE_STEELWALL_TOPRIGHT               768
-#define IMG_INVISIBLE_STEELWALL_BOTTOMLEFT             769
-#define IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT            770
-#define IMG_INVISIBLE_STEELWALL_HORIZONTAL             771
-#define IMG_INVISIBLE_STEELWALL_VERTICAL               772
-#define IMG_INVISIBLE_STEELWALL_TOPLEFT_EDITOR         773
-#define IMG_INVISIBLE_STEELWALL_TOPRIGHT_EDITOR                774
-#define IMG_INVISIBLE_STEELWALL_BOTTOMLEFT_EDITOR      775
-#define IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT_EDITOR     776
-#define IMG_INVISIBLE_STEELWALL_HORIZONTAL_EDITOR      777
-#define IMG_INVISIBLE_STEELWALL_VERTICAL_EDITOR                778
-#define IMG_ARROW_LEFT                                 779
-#define IMG_ARROW_RIGHT                                        780
-#define IMG_ARROW_UP                                   781
-#define IMG_ARROW_DOWN                                 782
-#define IMG_UNKNOWN                                    783
-#define IMG_TRIGGER_ELEMENT                            784
-#define IMG_TRIGGER_PLAYER                             785
-#define IMG_TRIGGER_CE_VALUE                           786
-#define IMG_TRIGGER_CE_SCORE                           787
-#define IMG_CURRENT_CE_VALUE                           788
-#define IMG_CURRENT_CE_SCORE                           789
-#define IMG_PREV_CE_1                                  790
-#define IMG_PREV_CE_2                                  791
-#define IMG_PREV_CE_3                                  792
-#define IMG_PREV_CE_4                                  793
-#define IMG_PREV_CE_5                                  794
-#define IMG_PREV_CE_6                                  795
-#define IMG_PREV_CE_7                                  796
-#define IMG_PREV_CE_8                                  797
-#define IMG_NEXT_CE_1                                  798
-#define IMG_NEXT_CE_2                                  799
-#define IMG_NEXT_CE_3                                  800
-#define IMG_NEXT_CE_4                                  801
-#define IMG_NEXT_CE_5                                  802
-#define IMG_NEXT_CE_6                                  803
-#define IMG_NEXT_CE_7                                  804
-#define IMG_NEXT_CE_8                                  805
-#define IMG_SELF                                       806
-#define IMG_ANY_ELEMENT                                        807
-#define IMG_EMC_KEY_5                                  808
-#define IMG_EMC_KEY_6                                  809
-#define IMG_EMC_KEY_7                                  810
-#define IMG_EMC_KEY_8                                  811
-#define IMG_EMC_GATE_5                                 812
-#define IMG_EMC_GATE_6                                 813
-#define IMG_EMC_GATE_7                                 814
-#define IMG_EMC_GATE_8                                 815
-#define IMG_EMC_GATE_5_GRAY                            816
-#define IMG_EMC_GATE_5_GRAY_EDITOR                     817
-#define IMG_EMC_GATE_5_GRAY_ACTIVE                     818
-#define IMG_EMC_GATE_6_GRAY                            819
-#define IMG_EMC_GATE_6_GRAY_EDITOR                     820
-#define IMG_EMC_GATE_6_GRAY_ACTIVE                     821
-#define IMG_EMC_GATE_7_GRAY                            822
-#define IMG_EMC_GATE_7_GRAY_EDITOR                     823
-#define IMG_EMC_GATE_7_GRAY_ACTIVE                     824
-#define IMG_EMC_GATE_8_GRAY                            825
-#define IMG_EMC_GATE_8_GRAY_EDITOR                     826
-#define IMG_EMC_GATE_8_GRAY_ACTIVE                     827
-#define IMG_EMC_ANDROID                                        828
-#define IMG_EMC_ANDROID_SHRINKING_UPLEFT               829
-#define IMG_EMC_ANDROID_GROWING_DOWNRIGHT              830
-#define IMG_EMC_ANDROID_SHRINKING_DOWNLEFT             831
-#define IMG_EMC_ANDROID_GROWING_UPRIGHT                        832
-#define IMG_EMC_ANDROID_SHRINKING_UPRIGHT              833
-#define IMG_EMC_ANDROID_GROWING_DOWNLEFT               834
-#define IMG_EMC_ANDROID_SHRINKING_DOWNRIGHT            835
-#define IMG_EMC_ANDROID_GROWING_UPLEFT                 836
-#define IMG_EMC_GRASS                                  837
-#define IMG_EMC_GRASS_CRUMBLED                         838
-#define IMG_EMC_GRASS_DIGGING_LEFT                     839
-#define IMG_EMC_GRASS_DIGGING_RIGHT                    840
-#define IMG_EMC_GRASS_DIGGING_UP                       841
-#define IMG_EMC_GRASS_DIGGING_DOWN                     842
-#define IMG_EMC_GRASS_DIGGING_LEFT_CRUMBLED            843
-#define IMG_EMC_GRASS_DIGGING_RIGHT_CRUMBLED           844
-#define IMG_EMC_GRASS_DIGGING_UP_CRUMBLED              845
-#define IMG_EMC_GRASS_DIGGING_DOWN_CRUMBLED            846
-#define IMG_EMC_MAGIC_BALL                             847
-#define IMG_EMC_MAGIC_BALL_ACTIVE                      848
-#define IMG_EMC_MAGIC_BALL_DROPPING                    849
-#define IMG_EMC_MAGIC_BALL_SWITCH                      850
-#define IMG_EMC_MAGIC_BALL_SWITCH_ACTIVE               851
-#define IMG_EMC_SPRING_BUMPER                          852
-#define IMG_EMC_SPRING_BUMPER_ACTIVE                   853
-#define IMG_EMC_PLANT                                  854
-#define IMG_EMC_PLANT_CRUMBLED                         855
-#define IMG_EMC_LENSES                                 856
-#define IMG_EMC_MAGNIFIER                              857
-#define IMG_EMC_WALL_9                                 858
-#define IMG_EMC_WALL_10                                        859
-#define IMG_EMC_WALL_11                                        860
-#define IMG_EMC_WALL_12                                        861
-#define IMG_EMC_WALL_13                                        862
-#define IMG_EMC_WALL_14                                        863
-#define IMG_EMC_WALL_15                                        864
-#define IMG_EMC_WALL_16                                        865
-#define IMG_EMC_WALL_SLIPPERY_1                                866
-#define IMG_EMC_WALL_SLIPPERY_2                                867
-#define IMG_EMC_WALL_SLIPPERY_3                                868
-#define IMG_EMC_WALL_SLIPPERY_4                                869
-#define IMG_EMC_FAKE_GRASS                             870
-#define IMG_EMC_FAKE_GRASS_CRUMBLED                    871
-#define IMG_EMC_FAKE_GRASS_ACTIVE                      872
-#define IMG_EMC_FAKE_GRASS_ACTIVE_CRUMBLED             873
-#define IMG_EMC_FAKE_GRASS_EDITOR                      874
-#define IMG_EMC_FAKE_ACID                              875
-#define IMG_EMC_DRIPPER                                        876
-#define IMG_EMC_DRIPPER_EDITOR                         877
-#define IMG_EMC_DRIPPER_ACTIVE                         878
-#define IMG_GRAPHIC_1                                  879
-#define IMG_GRAPHIC_2                                  880
-#define IMG_GRAPHIC_3                                  881
-#define IMG_GRAPHIC_4                                  882
-#define IMG_GRAPHIC_5                                  883
-#define IMG_GRAPHIC_6                                  884
-#define IMG_GRAPHIC_7                                  885
-#define IMG_GRAPHIC_8                                  886
-#define IMG_CHAR_SPACE                                 887
-#define IMG_CHAR_SPACE_EDITOR                          888
-#define IMG_CHAR_EXCLAM                                        889
-#define IMG_CHAR_QUOTEDBL                              890
-#define IMG_CHAR_NUMBERSIGN                            891
-#define IMG_CHAR_DOLLAR                                        892
-#define IMG_CHAR_PERCENT                               893
-#define IMG_CHAR_AMPERSAND                             894
-#define IMG_CHAR_APOSTROPHE                            895
-#define IMG_CHAR_PARENLEFT                             896
-#define IMG_CHAR_PARENRIGHT                            897
-#define IMG_CHAR_ASTERISK                              898
-#define IMG_CHAR_PLUS                                  899
-#define IMG_CHAR_COMMA                                 900
-#define IMG_CHAR_MINUS                                 901
-#define IMG_CHAR_PERIOD                                        902
-#define IMG_CHAR_SLASH                                 903
-#define IMG_CHAR_0                                     904
-#define IMG_CHAR_1                                     905
-#define IMG_CHAR_2                                     906
-#define IMG_CHAR_3                                     907
-#define IMG_CHAR_4                                     908
-#define IMG_CHAR_5                                     909
-#define IMG_CHAR_6                                     910
-#define IMG_CHAR_7                                     911
-#define IMG_CHAR_8                                     912
-#define IMG_CHAR_9                                     913
-#define IMG_CHAR_COLON                                 914
-#define IMG_CHAR_SEMICOLON                             915
-#define IMG_CHAR_LESS                                  916
-#define IMG_CHAR_EQUAL                                 917
-#define IMG_CHAR_GREATER                               918
-#define IMG_CHAR_QUESTION                              919
-#define IMG_CHAR_AT                                    920
-#define IMG_CHAR_A                                     921
-#define IMG_CHAR_B                                     922
-#define IMG_CHAR_C                                     923
-#define IMG_CHAR_D                                     924
-#define IMG_CHAR_E                                     925
-#define IMG_CHAR_F                                     926
-#define IMG_CHAR_G                                     927
-#define IMG_CHAR_H                                     928
-#define IMG_CHAR_I                                     929
-#define IMG_CHAR_J                                     930
-#define IMG_CHAR_K                                     931
-#define IMG_CHAR_L                                     932
-#define IMG_CHAR_M                                     933
-#define IMG_CHAR_N                                     934
-#define IMG_CHAR_O                                     935
-#define IMG_CHAR_P                                     936
-#define IMG_CHAR_Q                                     937
-#define IMG_CHAR_R                                     938
-#define IMG_CHAR_S                                     939
-#define IMG_CHAR_T                                     940
-#define IMG_CHAR_U                                     941
-#define IMG_CHAR_V                                     942
-#define IMG_CHAR_W                                     943
-#define IMG_CHAR_X                                     944
-#define IMG_CHAR_Y                                     945
-#define IMG_CHAR_Z                                     946
-#define IMG_CHAR_BRACKETLEFT                           947
-#define IMG_CHAR_BACKSLASH                             948
-#define IMG_CHAR_BRACKETRIGHT                          949
-#define IMG_CHAR_ASCIICIRCUM                           950
-#define IMG_CHAR_UNDERSCORE                            951
-#define IMG_CHAR_COPYRIGHT                             952
-#define IMG_CHAR_AUMLAUT                               953
-#define IMG_CHAR_OUMLAUT                               954
-#define IMG_CHAR_UUMLAUT                               955
-#define IMG_CHAR_DEGREE                                        956
-#define IMG_CHAR_TRADEMARK                             957
-#define IMG_CHAR_CURSOR                                        958
-#define IMG_CHAR_BUTTON                                        959
-#define IMG_CHAR_UP                                    960
-#define IMG_CHAR_DOWN                                  961
-#define IMG_STEEL_CHAR_SPACE                           962
-#define IMG_STEEL_CHAR_SPACE_EDITOR                    963
-#define IMG_STEEL_CHAR_EXCLAM                          964
-#define IMG_STEEL_CHAR_QUOTEDBL                                965
-#define IMG_STEEL_CHAR_NUMBERSIGN                      966
-#define IMG_STEEL_CHAR_DOLLAR                          967
-#define IMG_STEEL_CHAR_PERCENT                         968
-#define IMG_STEEL_CHAR_AMPERSAND                       969
-#define IMG_STEEL_CHAR_APOSTROPHE                      970
-#define IMG_STEEL_CHAR_PARENLEFT                       971
-#define IMG_STEEL_CHAR_PARENRIGHT                      972
-#define IMG_STEEL_CHAR_ASTERISK                                973
-#define IMG_STEEL_CHAR_PLUS                            974
-#define IMG_STEEL_CHAR_COMMA                           975
-#define IMG_STEEL_CHAR_MINUS                           976
-#define IMG_STEEL_CHAR_PERIOD                          977
-#define IMG_STEEL_CHAR_SLASH                           978
-#define IMG_STEEL_CHAR_0                               979
-#define IMG_STEEL_CHAR_1                               980
-#define IMG_STEEL_CHAR_2                               981
-#define IMG_STEEL_CHAR_3                               982
-#define IMG_STEEL_CHAR_4                               983
-#define IMG_STEEL_CHAR_5                               984
-#define IMG_STEEL_CHAR_6                               985
-#define IMG_STEEL_CHAR_7                               986
-#define IMG_STEEL_CHAR_8                               987
-#define IMG_STEEL_CHAR_9                               988
-#define IMG_STEEL_CHAR_COLON                           989
-#define IMG_STEEL_CHAR_SEMICOLON                       990
-#define IMG_STEEL_CHAR_LESS                            991
-#define IMG_STEEL_CHAR_EQUAL                           992
-#define IMG_STEEL_CHAR_GREATER                         993
-#define IMG_STEEL_CHAR_QUESTION                                994
-#define IMG_STEEL_CHAR_AT                              995
-#define IMG_STEEL_CHAR_A                               996
-#define IMG_STEEL_CHAR_B                               997
-#define IMG_STEEL_CHAR_C                               998
-#define IMG_STEEL_CHAR_D                               999
-#define IMG_STEEL_CHAR_E                               1000
-#define IMG_STEEL_CHAR_F                               1001
-#define IMG_STEEL_CHAR_G                               1002
-#define IMG_STEEL_CHAR_H                               1003
-#define IMG_STEEL_CHAR_I                               1004
-#define IMG_STEEL_CHAR_J                               1005
-#define IMG_STEEL_CHAR_K                               1006
-#define IMG_STEEL_CHAR_L                               1007
-#define IMG_STEEL_CHAR_M                               1008
-#define IMG_STEEL_CHAR_N                               1009
-#define IMG_STEEL_CHAR_O                               1010
-#define IMG_STEEL_CHAR_P                               1011
-#define IMG_STEEL_CHAR_Q                               1012
-#define IMG_STEEL_CHAR_R                               1013
-#define IMG_STEEL_CHAR_S                               1014
-#define IMG_STEEL_CHAR_T                               1015
-#define IMG_STEEL_CHAR_U                               1016
-#define IMG_STEEL_CHAR_V                               1017
-#define IMG_STEEL_CHAR_W                               1018
-#define IMG_STEEL_CHAR_X                               1019
-#define IMG_STEEL_CHAR_Y                               1020
-#define IMG_STEEL_CHAR_Z                               1021
-#define IMG_STEEL_CHAR_BRACKETLEFT                     1022
-#define IMG_STEEL_CHAR_BACKSLASH                       1023
-#define IMG_STEEL_CHAR_BRACKETRIGHT                    1024
-#define IMG_STEEL_CHAR_ASCIICIRCUM                     1025
-#define IMG_STEEL_CHAR_UNDERSCORE                      1026
-#define IMG_STEEL_CHAR_COPYRIGHT                       1027
-#define IMG_STEEL_CHAR_AUMLAUT                         1028
-#define IMG_STEEL_CHAR_OUMLAUT                         1029
-#define IMG_STEEL_CHAR_UUMLAUT                         1030
-#define IMG_STEEL_CHAR_DEGREE                          1031
-#define IMG_STEEL_CHAR_TRADEMARK                       1032
-#define IMG_STEEL_CHAR_CURSOR                          1033
-#define IMG_STEEL_CHAR_BUTTON                          1034
-#define IMG_STEEL_CHAR_UP                              1035
-#define IMG_STEEL_CHAR_DOWN                            1036
-#define IMG_CUSTOM_1                                   1037
-#define IMG_CUSTOM_1_EDITOR                            1038
-#define IMG_CUSTOM_2                                   1039
-#define IMG_CUSTOM_2_EDITOR                            1040
-#define IMG_CUSTOM_3                                   1041
-#define IMG_CUSTOM_3_EDITOR                            1042
-#define IMG_CUSTOM_4                                   1043
-#define IMG_CUSTOM_4_EDITOR                            1044
-#define IMG_CUSTOM_5                                   1045
-#define IMG_CUSTOM_5_EDITOR                            1046
-#define IMG_CUSTOM_6                                   1047
-#define IMG_CUSTOM_6_EDITOR                            1048
-#define IMG_CUSTOM_7                                   1049
-#define IMG_CUSTOM_7_EDITOR                            1050
-#define IMG_CUSTOM_8                                   1051
-#define IMG_CUSTOM_8_EDITOR                            1052
-#define IMG_CUSTOM_9                                   1053
-#define IMG_CUSTOM_9_EDITOR                            1054
-#define IMG_CUSTOM_10                                  1055
-#define IMG_CUSTOM_10_EDITOR                           1056
-#define IMG_CUSTOM_11                                  1057
-#define IMG_CUSTOM_11_EDITOR                           1058
-#define IMG_CUSTOM_12                                  1059
-#define IMG_CUSTOM_12_EDITOR                           1060
-#define IMG_CUSTOM_13                                  1061
-#define IMG_CUSTOM_13_EDITOR                           1062
-#define IMG_CUSTOM_14                                  1063
-#define IMG_CUSTOM_14_EDITOR                           1064
-#define IMG_CUSTOM_15                                  1065
-#define IMG_CUSTOM_15_EDITOR                           1066
-#define IMG_CUSTOM_16                                  1067
-#define IMG_CUSTOM_16_EDITOR                           1068
-#define IMG_CUSTOM_17                                  1069
-#define IMG_CUSTOM_17_EDITOR                           1070
-#define IMG_CUSTOM_18                                  1071
-#define IMG_CUSTOM_18_EDITOR                           1072
-#define IMG_CUSTOM_19                                  1073
-#define IMG_CUSTOM_19_EDITOR                           1074
-#define IMG_CUSTOM_20                                  1075
-#define IMG_CUSTOM_20_EDITOR                           1076
-#define IMG_CUSTOM_21                                  1077
-#define IMG_CUSTOM_21_EDITOR                           1078
-#define IMG_CUSTOM_22                                  1079
-#define IMG_CUSTOM_22_EDITOR                           1080
-#define IMG_CUSTOM_23                                  1081
-#define IMG_CUSTOM_23_EDITOR                           1082
-#define IMG_CUSTOM_24                                  1083
-#define IMG_CUSTOM_24_EDITOR                           1084
-#define IMG_CUSTOM_25                                  1085
-#define IMG_CUSTOM_25_EDITOR                           1086
-#define IMG_CUSTOM_26                                  1087
-#define IMG_CUSTOM_26_EDITOR                           1088
-#define IMG_CUSTOM_27                                  1089
-#define IMG_CUSTOM_27_EDITOR                           1090
-#define IMG_CUSTOM_28                                  1091
-#define IMG_CUSTOM_28_EDITOR                           1092
-#define IMG_CUSTOM_29                                  1093
-#define IMG_CUSTOM_29_EDITOR                           1094
-#define IMG_CUSTOM_30                                  1095
-#define IMG_CUSTOM_30_EDITOR                           1096
-#define IMG_CUSTOM_31                                  1097
-#define IMG_CUSTOM_31_EDITOR                           1098
-#define IMG_CUSTOM_32                                  1099
-#define IMG_CUSTOM_32_EDITOR                           1100
-#define IMG_CUSTOM_33                                  1101
-#define IMG_CUSTOM_33_EDITOR                           1102
-#define IMG_CUSTOM_34                                  1103
-#define IMG_CUSTOM_34_EDITOR                           1104
-#define IMG_CUSTOM_35                                  1105
-#define IMG_CUSTOM_35_EDITOR                           1106
-#define IMG_CUSTOM_36                                  1107
-#define IMG_CUSTOM_36_EDITOR                           1108
-#define IMG_CUSTOM_37                                  1109
-#define IMG_CUSTOM_37_EDITOR                           1110
-#define IMG_CUSTOM_38                                  1111
-#define IMG_CUSTOM_38_EDITOR                           1112
-#define IMG_CUSTOM_39                                  1113
-#define IMG_CUSTOM_39_EDITOR                           1114
-#define IMG_CUSTOM_40                                  1115
-#define IMG_CUSTOM_40_EDITOR                           1116
-#define IMG_CUSTOM_41                                  1117
-#define IMG_CUSTOM_41_EDITOR                           1118
-#define IMG_CUSTOM_42                                  1119
-#define IMG_CUSTOM_42_EDITOR                           1120
-#define IMG_CUSTOM_43                                  1121
-#define IMG_CUSTOM_43_EDITOR                           1122
-#define IMG_CUSTOM_44                                  1123
-#define IMG_CUSTOM_44_EDITOR                           1124
-#define IMG_CUSTOM_45                                  1125
-#define IMG_CUSTOM_45_EDITOR                           1126
-#define IMG_CUSTOM_46                                  1127
-#define IMG_CUSTOM_46_EDITOR                           1128
-#define IMG_CUSTOM_47                                  1129
-#define IMG_CUSTOM_47_EDITOR                           1130
-#define IMG_CUSTOM_48                                  1131
-#define IMG_CUSTOM_48_EDITOR                           1132
-#define IMG_CUSTOM_49                                  1133
-#define IMG_CUSTOM_49_EDITOR                           1134
-#define IMG_CUSTOM_50                                  1135
-#define IMG_CUSTOM_50_EDITOR                           1136
-#define IMG_CUSTOM_51                                  1137
-#define IMG_CUSTOM_51_EDITOR                           1138
-#define IMG_CUSTOM_52                                  1139
-#define IMG_CUSTOM_52_EDITOR                           1140
-#define IMG_CUSTOM_53                                  1141
-#define IMG_CUSTOM_53_EDITOR                           1142
-#define IMG_CUSTOM_54                                  1143
-#define IMG_CUSTOM_54_EDITOR                           1144
-#define IMG_CUSTOM_55                                  1145
-#define IMG_CUSTOM_55_EDITOR                           1146
-#define IMG_CUSTOM_56                                  1147
-#define IMG_CUSTOM_56_EDITOR                           1148
-#define IMG_CUSTOM_57                                  1149
-#define IMG_CUSTOM_57_EDITOR                           1150
-#define IMG_CUSTOM_58                                  1151
-#define IMG_CUSTOM_58_EDITOR                           1152
-#define IMG_CUSTOM_59                                  1153
-#define IMG_CUSTOM_59_EDITOR                           1154
-#define IMG_CUSTOM_60                                  1155
-#define IMG_CUSTOM_60_EDITOR                           1156
-#define IMG_CUSTOM_61                                  1157
-#define IMG_CUSTOM_61_EDITOR                           1158
-#define IMG_CUSTOM_62                                  1159
-#define IMG_CUSTOM_62_EDITOR                           1160
-#define IMG_CUSTOM_63                                  1161
-#define IMG_CUSTOM_63_EDITOR                           1162
-#define IMG_CUSTOM_64                                  1163
-#define IMG_CUSTOM_64_EDITOR                           1164
-#define IMG_CUSTOM_65                                  1165
-#define IMG_CUSTOM_65_EDITOR                           1166
-#define IMG_CUSTOM_66                                  1167
-#define IMG_CUSTOM_66_EDITOR                           1168
-#define IMG_CUSTOM_67                                  1169
-#define IMG_CUSTOM_67_EDITOR                           1170
-#define IMG_CUSTOM_68                                  1171
-#define IMG_CUSTOM_68_EDITOR                           1172
-#define IMG_CUSTOM_69                                  1173
-#define IMG_CUSTOM_69_EDITOR                           1174
-#define IMG_CUSTOM_70                                  1175
-#define IMG_CUSTOM_70_EDITOR                           1176
-#define IMG_CUSTOM_71                                  1177
-#define IMG_CUSTOM_71_EDITOR                           1178
-#define IMG_CUSTOM_72                                  1179
-#define IMG_CUSTOM_72_EDITOR                           1180
-#define IMG_CUSTOM_73                                  1181
-#define IMG_CUSTOM_73_EDITOR                           1182
-#define IMG_CUSTOM_74                                  1183
-#define IMG_CUSTOM_74_EDITOR                           1184
-#define IMG_CUSTOM_75                                  1185
-#define IMG_CUSTOM_75_EDITOR                           1186
-#define IMG_CUSTOM_76                                  1187
-#define IMG_CUSTOM_76_EDITOR                           1188
-#define IMG_CUSTOM_77                                  1189
-#define IMG_CUSTOM_77_EDITOR                           1190
-#define IMG_CUSTOM_78                                  1191
-#define IMG_CUSTOM_78_EDITOR                           1192
-#define IMG_CUSTOM_79                                  1193
-#define IMG_CUSTOM_79_EDITOR                           1194
-#define IMG_CUSTOM_80                                  1195
-#define IMG_CUSTOM_80_EDITOR                           1196
-#define IMG_CUSTOM_81                                  1197
-#define IMG_CUSTOM_81_EDITOR                           1198
-#define IMG_CUSTOM_82                                  1199
-#define IMG_CUSTOM_82_EDITOR                           1200
-#define IMG_CUSTOM_83                                  1201
-#define IMG_CUSTOM_83_EDITOR                           1202
-#define IMG_CUSTOM_84                                  1203
-#define IMG_CUSTOM_84_EDITOR                           1204
-#define IMG_CUSTOM_85                                  1205
-#define IMG_CUSTOM_85_EDITOR                           1206
-#define IMG_CUSTOM_86                                  1207
-#define IMG_CUSTOM_86_EDITOR                           1208
-#define IMG_CUSTOM_87                                  1209
-#define IMG_CUSTOM_87_EDITOR                           1210
-#define IMG_CUSTOM_88                                  1211
-#define IMG_CUSTOM_88_EDITOR                           1212
-#define IMG_CUSTOM_89                                  1213
-#define IMG_CUSTOM_89_EDITOR                           1214
-#define IMG_CUSTOM_90                                  1215
-#define IMG_CUSTOM_90_EDITOR                           1216
-#define IMG_CUSTOM_91                                  1217
-#define IMG_CUSTOM_91_EDITOR                           1218
-#define IMG_CUSTOM_92                                  1219
-#define IMG_CUSTOM_92_EDITOR                           1220
-#define IMG_CUSTOM_93                                  1221
-#define IMG_CUSTOM_93_EDITOR                           1222
-#define IMG_CUSTOM_94                                  1223
-#define IMG_CUSTOM_94_EDITOR                           1224
-#define IMG_CUSTOM_95                                  1225
-#define IMG_CUSTOM_95_EDITOR                           1226
-#define IMG_CUSTOM_96                                  1227
-#define IMG_CUSTOM_96_EDITOR                           1228
-#define IMG_CUSTOM_97                                  1229
-#define IMG_CUSTOM_97_EDITOR                           1230
-#define IMG_CUSTOM_98                                  1231
-#define IMG_CUSTOM_98_EDITOR                           1232
-#define IMG_CUSTOM_99                                  1233
-#define IMG_CUSTOM_99_EDITOR                           1234
-#define IMG_CUSTOM_100                                 1235
-#define IMG_CUSTOM_100_EDITOR                          1236
-#define IMG_CUSTOM_101                                 1237
-#define IMG_CUSTOM_101_EDITOR                          1238
-#define IMG_CUSTOM_102                                 1239
-#define IMG_CUSTOM_102_EDITOR                          1240
-#define IMG_CUSTOM_103                                 1241
-#define IMG_CUSTOM_103_EDITOR                          1242
-#define IMG_CUSTOM_104                                 1243
-#define IMG_CUSTOM_104_EDITOR                          1244
-#define IMG_CUSTOM_105                                 1245
-#define IMG_CUSTOM_105_EDITOR                          1246
-#define IMG_CUSTOM_106                                 1247
-#define IMG_CUSTOM_106_EDITOR                          1248
-#define IMG_CUSTOM_107                                 1249
-#define IMG_CUSTOM_107_EDITOR                          1250
-#define IMG_CUSTOM_108                                 1251
-#define IMG_CUSTOM_108_EDITOR                          1252
-#define IMG_CUSTOM_109                                 1253
-#define IMG_CUSTOM_109_EDITOR                          1254
-#define IMG_CUSTOM_110                                 1255
-#define IMG_CUSTOM_110_EDITOR                          1256
-#define IMG_CUSTOM_111                                 1257
-#define IMG_CUSTOM_111_EDITOR                          1258
-#define IMG_CUSTOM_112                                 1259
-#define IMG_CUSTOM_112_EDITOR                          1260
-#define IMG_CUSTOM_113                                 1261
-#define IMG_CUSTOM_113_EDITOR                          1262
-#define IMG_CUSTOM_114                                 1263
-#define IMG_CUSTOM_114_EDITOR                          1264
-#define IMG_CUSTOM_115                                 1265
-#define IMG_CUSTOM_115_EDITOR                          1266
-#define IMG_CUSTOM_116                                 1267
-#define IMG_CUSTOM_116_EDITOR                          1268
-#define IMG_CUSTOM_117                                 1269
-#define IMG_CUSTOM_117_EDITOR                          1270
-#define IMG_CUSTOM_118                                 1271
-#define IMG_CUSTOM_118_EDITOR                          1272
-#define IMG_CUSTOM_119                                 1273
-#define IMG_CUSTOM_119_EDITOR                          1274
-#define IMG_CUSTOM_120                                 1275
-#define IMG_CUSTOM_120_EDITOR                          1276
-#define IMG_CUSTOM_121                                 1277
-#define IMG_CUSTOM_121_EDITOR                          1278
-#define IMG_CUSTOM_122                                 1279
-#define IMG_CUSTOM_122_EDITOR                          1280
-#define IMG_CUSTOM_123                                 1281
-#define IMG_CUSTOM_123_EDITOR                          1282
-#define IMG_CUSTOM_124                                 1283
-#define IMG_CUSTOM_124_EDITOR                          1284
-#define IMG_CUSTOM_125                                 1285
-#define IMG_CUSTOM_125_EDITOR                          1286
-#define IMG_CUSTOM_126                                 1287
-#define IMG_CUSTOM_126_EDITOR                          1288
-#define IMG_CUSTOM_127                                 1289
-#define IMG_CUSTOM_127_EDITOR                          1290
-#define IMG_CUSTOM_128                                 1291
-#define IMG_CUSTOM_128_EDITOR                          1292
-#define IMG_CUSTOM_129                                 1293
-#define IMG_CUSTOM_129_EDITOR                          1294
-#define IMG_CUSTOM_130                                 1295
-#define IMG_CUSTOM_130_EDITOR                          1296
-#define IMG_CUSTOM_131                                 1297
-#define IMG_CUSTOM_131_EDITOR                          1298
-#define IMG_CUSTOM_132                                 1299
-#define IMG_CUSTOM_132_EDITOR                          1300
-#define IMG_CUSTOM_133                                 1301
-#define IMG_CUSTOM_133_EDITOR                          1302
-#define IMG_CUSTOM_134                                 1303
-#define IMG_CUSTOM_134_EDITOR                          1304
-#define IMG_CUSTOM_135                                 1305
-#define IMG_CUSTOM_135_EDITOR                          1306
-#define IMG_CUSTOM_136                                 1307
-#define IMG_CUSTOM_136_EDITOR                          1308
-#define IMG_CUSTOM_137                                 1309
-#define IMG_CUSTOM_137_EDITOR                          1310
-#define IMG_CUSTOM_138                                 1311
-#define IMG_CUSTOM_138_EDITOR                          1312
-#define IMG_CUSTOM_139                                 1313
-#define IMG_CUSTOM_139_EDITOR                          1314
-#define IMG_CUSTOM_140                                 1315
-#define IMG_CUSTOM_140_EDITOR                          1316
-#define IMG_CUSTOM_141                                 1317
-#define IMG_CUSTOM_141_EDITOR                          1318
-#define IMG_CUSTOM_142                                 1319
-#define IMG_CUSTOM_142_EDITOR                          1320
-#define IMG_CUSTOM_143                                 1321
-#define IMG_CUSTOM_143_EDITOR                          1322
-#define IMG_CUSTOM_144                                 1323
-#define IMG_CUSTOM_144_EDITOR                          1324
-#define IMG_CUSTOM_145                                 1325
-#define IMG_CUSTOM_145_EDITOR                          1326
-#define IMG_CUSTOM_146                                 1327
-#define IMG_CUSTOM_146_EDITOR                          1328
-#define IMG_CUSTOM_147                                 1329
-#define IMG_CUSTOM_147_EDITOR                          1330
-#define IMG_CUSTOM_148                                 1331
-#define IMG_CUSTOM_148_EDITOR                          1332
-#define IMG_CUSTOM_149                                 1333
-#define IMG_CUSTOM_149_EDITOR                          1334
-#define IMG_CUSTOM_150                                 1335
-#define IMG_CUSTOM_150_EDITOR                          1336
-#define IMG_CUSTOM_151                                 1337
-#define IMG_CUSTOM_151_EDITOR                          1338
-#define IMG_CUSTOM_152                                 1339
-#define IMG_CUSTOM_152_EDITOR                          1340
-#define IMG_CUSTOM_153                                 1341
-#define IMG_CUSTOM_153_EDITOR                          1342
-#define IMG_CUSTOM_154                                 1343
-#define IMG_CUSTOM_154_EDITOR                          1344
-#define IMG_CUSTOM_155                                 1345
-#define IMG_CUSTOM_155_EDITOR                          1346
-#define IMG_CUSTOM_156                                 1347
-#define IMG_CUSTOM_156_EDITOR                          1348
-#define IMG_CUSTOM_157                                 1349
-#define IMG_CUSTOM_157_EDITOR                          1350
-#define IMG_CUSTOM_158                                 1351
-#define IMG_CUSTOM_158_EDITOR                          1352
-#define IMG_CUSTOM_159                                 1353
-#define IMG_CUSTOM_159_EDITOR                          1354
-#define IMG_CUSTOM_160                                 1355
-#define IMG_CUSTOM_160_EDITOR                          1356
-#define IMG_CUSTOM_161                                 1357
-#define IMG_CUSTOM_161_EDITOR                          1358
-#define IMG_CUSTOM_162                                 1359
-#define IMG_CUSTOM_162_EDITOR                          1360
-#define IMG_CUSTOM_163                                 1361
-#define IMG_CUSTOM_163_EDITOR                          1362
-#define IMG_CUSTOM_164                                 1363
-#define IMG_CUSTOM_164_EDITOR                          1364
-#define IMG_CUSTOM_165                                 1365
-#define IMG_CUSTOM_165_EDITOR                          1366
-#define IMG_CUSTOM_166                                 1367
-#define IMG_CUSTOM_166_EDITOR                          1368
-#define IMG_CUSTOM_167                                 1369
-#define IMG_CUSTOM_167_EDITOR                          1370
-#define IMG_CUSTOM_168                                 1371
-#define IMG_CUSTOM_168_EDITOR                          1372
-#define IMG_CUSTOM_169                                 1373
-#define IMG_CUSTOM_169_EDITOR                          1374
-#define IMG_CUSTOM_170                                 1375
-#define IMG_CUSTOM_170_EDITOR                          1376
-#define IMG_CUSTOM_171                                 1377
-#define IMG_CUSTOM_171_EDITOR                          1378
-#define IMG_CUSTOM_172                                 1379
-#define IMG_CUSTOM_172_EDITOR                          1380
-#define IMG_CUSTOM_173                                 1381
-#define IMG_CUSTOM_173_EDITOR                          1382
-#define IMG_CUSTOM_174                                 1383
-#define IMG_CUSTOM_174_EDITOR                          1384
-#define IMG_CUSTOM_175                                 1385
-#define IMG_CUSTOM_175_EDITOR                          1386
-#define IMG_CUSTOM_176                                 1387
-#define IMG_CUSTOM_176_EDITOR                          1388
-#define IMG_CUSTOM_177                                 1389
-#define IMG_CUSTOM_177_EDITOR                          1390
-#define IMG_CUSTOM_178                                 1391
-#define IMG_CUSTOM_178_EDITOR                          1392
-#define IMG_CUSTOM_179                                 1393
-#define IMG_CUSTOM_179_EDITOR                          1394
-#define IMG_CUSTOM_180                                 1395
-#define IMG_CUSTOM_180_EDITOR                          1396
-#define IMG_CUSTOM_181                                 1397
-#define IMG_CUSTOM_181_EDITOR                          1398
-#define IMG_CUSTOM_182                                 1399
-#define IMG_CUSTOM_182_EDITOR                          1400
-#define IMG_CUSTOM_183                                 1401
-#define IMG_CUSTOM_183_EDITOR                          1402
-#define IMG_CUSTOM_184                                 1403
-#define IMG_CUSTOM_184_EDITOR                          1404
-#define IMG_CUSTOM_185                                 1405
-#define IMG_CUSTOM_185_EDITOR                          1406
-#define IMG_CUSTOM_186                                 1407
-#define IMG_CUSTOM_186_EDITOR                          1408
-#define IMG_CUSTOM_187                                 1409
-#define IMG_CUSTOM_187_EDITOR                          1410
-#define IMG_CUSTOM_188                                 1411
-#define IMG_CUSTOM_188_EDITOR                          1412
-#define IMG_CUSTOM_189                                 1413
-#define IMG_CUSTOM_189_EDITOR                          1414
-#define IMG_CUSTOM_190                                 1415
-#define IMG_CUSTOM_190_EDITOR                          1416
-#define IMG_CUSTOM_191                                 1417
-#define IMG_CUSTOM_191_EDITOR                          1418
-#define IMG_CUSTOM_192                                 1419
-#define IMG_CUSTOM_192_EDITOR                          1420
-#define IMG_CUSTOM_193                                 1421
-#define IMG_CUSTOM_193_EDITOR                          1422
-#define IMG_CUSTOM_194                                 1423
-#define IMG_CUSTOM_194_EDITOR                          1424
-#define IMG_CUSTOM_195                                 1425
-#define IMG_CUSTOM_195_EDITOR                          1426
-#define IMG_CUSTOM_196                                 1427
-#define IMG_CUSTOM_196_EDITOR                          1428
-#define IMG_CUSTOM_197                                 1429
-#define IMG_CUSTOM_197_EDITOR                          1430
-#define IMG_CUSTOM_198                                 1431
-#define IMG_CUSTOM_198_EDITOR                          1432
-#define IMG_CUSTOM_199                                 1433
-#define IMG_CUSTOM_199_EDITOR                          1434
-#define IMG_CUSTOM_200                                 1435
-#define IMG_CUSTOM_200_EDITOR                          1436
-#define IMG_CUSTOM_201                                 1437
-#define IMG_CUSTOM_201_EDITOR                          1438
-#define IMG_CUSTOM_202                                 1439
-#define IMG_CUSTOM_202_EDITOR                          1440
-#define IMG_CUSTOM_203                                 1441
-#define IMG_CUSTOM_203_EDITOR                          1442
-#define IMG_CUSTOM_204                                 1443
-#define IMG_CUSTOM_204_EDITOR                          1444
-#define IMG_CUSTOM_205                                 1445
-#define IMG_CUSTOM_205_EDITOR                          1446
-#define IMG_CUSTOM_206                                 1447
-#define IMG_CUSTOM_206_EDITOR                          1448
-#define IMG_CUSTOM_207                                 1449
-#define IMG_CUSTOM_207_EDITOR                          1450
-#define IMG_CUSTOM_208                                 1451
-#define IMG_CUSTOM_208_EDITOR                          1452
-#define IMG_CUSTOM_209                                 1453
-#define IMG_CUSTOM_209_EDITOR                          1454
-#define IMG_CUSTOM_210                                 1455
-#define IMG_CUSTOM_210_EDITOR                          1456
-#define IMG_CUSTOM_211                                 1457
-#define IMG_CUSTOM_211_EDITOR                          1458
-#define IMG_CUSTOM_212                                 1459
-#define IMG_CUSTOM_212_EDITOR                          1460
-#define IMG_CUSTOM_213                                 1461
-#define IMG_CUSTOM_213_EDITOR                          1462
-#define IMG_CUSTOM_214                                 1463
-#define IMG_CUSTOM_214_EDITOR                          1464
-#define IMG_CUSTOM_215                                 1465
-#define IMG_CUSTOM_215_EDITOR                          1466
-#define IMG_CUSTOM_216                                 1467
-#define IMG_CUSTOM_216_EDITOR                          1468
-#define IMG_CUSTOM_217                                 1469
-#define IMG_CUSTOM_217_EDITOR                          1470
-#define IMG_CUSTOM_218                                 1471
-#define IMG_CUSTOM_218_EDITOR                          1472
-#define IMG_CUSTOM_219                                 1473
-#define IMG_CUSTOM_219_EDITOR                          1474
-#define IMG_CUSTOM_220                                 1475
-#define IMG_CUSTOM_220_EDITOR                          1476
-#define IMG_CUSTOM_221                                 1477
-#define IMG_CUSTOM_221_EDITOR                          1478
-#define IMG_CUSTOM_222                                 1479
-#define IMG_CUSTOM_222_EDITOR                          1480
-#define IMG_CUSTOM_223                                 1481
-#define IMG_CUSTOM_223_EDITOR                          1482
-#define IMG_CUSTOM_224                                 1483
-#define IMG_CUSTOM_224_EDITOR                          1484
-#define IMG_CUSTOM_225                                 1485
-#define IMG_CUSTOM_225_EDITOR                          1486
-#define IMG_CUSTOM_226                                 1487
-#define IMG_CUSTOM_226_EDITOR                          1488
-#define IMG_CUSTOM_227                                 1489
-#define IMG_CUSTOM_227_EDITOR                          1490
-#define IMG_CUSTOM_228                                 1491
-#define IMG_CUSTOM_228_EDITOR                          1492
-#define IMG_CUSTOM_229                                 1493
-#define IMG_CUSTOM_229_EDITOR                          1494
-#define IMG_CUSTOM_230                                 1495
-#define IMG_CUSTOM_230_EDITOR                          1496
-#define IMG_CUSTOM_231                                 1497
-#define IMG_CUSTOM_231_EDITOR                          1498
-#define IMG_CUSTOM_232                                 1499
-#define IMG_CUSTOM_232_EDITOR                          1500
-#define IMG_CUSTOM_233                                 1501
-#define IMG_CUSTOM_233_EDITOR                          1502
-#define IMG_CUSTOM_234                                 1503
-#define IMG_CUSTOM_234_EDITOR                          1504
-#define IMG_CUSTOM_235                                 1505
-#define IMG_CUSTOM_235_EDITOR                          1506
-#define IMG_CUSTOM_236                                 1507
-#define IMG_CUSTOM_236_EDITOR                          1508
-#define IMG_CUSTOM_237                                 1509
-#define IMG_CUSTOM_237_EDITOR                          1510
-#define IMG_CUSTOM_238                                 1511
-#define IMG_CUSTOM_238_EDITOR                          1512
-#define IMG_CUSTOM_239                                 1513
-#define IMG_CUSTOM_239_EDITOR                          1514
-#define IMG_CUSTOM_240                                 1515
-#define IMG_CUSTOM_240_EDITOR                          1516
-#define IMG_CUSTOM_241                                 1517
-#define IMG_CUSTOM_241_EDITOR                          1518
-#define IMG_CUSTOM_242                                 1519
-#define IMG_CUSTOM_242_EDITOR                          1520
-#define IMG_CUSTOM_243                                 1521
-#define IMG_CUSTOM_243_EDITOR                          1522
-#define IMG_CUSTOM_244                                 1523
-#define IMG_CUSTOM_244_EDITOR                          1524
-#define IMG_CUSTOM_245                                 1525
-#define IMG_CUSTOM_245_EDITOR                          1526
-#define IMG_CUSTOM_246                                 1527
-#define IMG_CUSTOM_246_EDITOR                          1528
-#define IMG_CUSTOM_247                                 1529
-#define IMG_CUSTOM_247_EDITOR                          1530
-#define IMG_CUSTOM_248                                 1531
-#define IMG_CUSTOM_248_EDITOR                          1532
-#define IMG_CUSTOM_249                                 1533
-#define IMG_CUSTOM_249_EDITOR                          1534
-#define IMG_CUSTOM_250                                 1535
-#define IMG_CUSTOM_250_EDITOR                          1536
-#define IMG_CUSTOM_251                                 1537
-#define IMG_CUSTOM_251_EDITOR                          1538
-#define IMG_CUSTOM_252                                 1539
-#define IMG_CUSTOM_252_EDITOR                          1540
-#define IMG_CUSTOM_253                                 1541
-#define IMG_CUSTOM_253_EDITOR                          1542
-#define IMG_CUSTOM_254                                 1543
-#define IMG_CUSTOM_254_EDITOR                          1544
-#define IMG_CUSTOM_255                                 1545
-#define IMG_CUSTOM_255_EDITOR                          1546
-#define IMG_CUSTOM_256                                 1547
-#define IMG_CUSTOM_256_EDITOR                          1548
-#define IMG_GROUP_1                                    1549
-#define IMG_GROUP_1_EDITOR                             1550
-#define IMG_GROUP_2                                    1551
-#define IMG_GROUP_2_EDITOR                             1552
-#define IMG_GROUP_3                                    1553
-#define IMG_GROUP_3_EDITOR                             1554
-#define IMG_GROUP_4                                    1555
-#define IMG_GROUP_4_EDITOR                             1556
-#define IMG_GROUP_5                                    1557
-#define IMG_GROUP_5_EDITOR                             1558
-#define IMG_GROUP_6                                    1559
-#define IMG_GROUP_6_EDITOR                             1560
-#define IMG_GROUP_7                                    1561
-#define IMG_GROUP_7_EDITOR                             1562
-#define IMG_GROUP_8                                    1563
-#define IMG_GROUP_8_EDITOR                             1564
-#define IMG_GROUP_9                                    1565
-#define IMG_GROUP_9_EDITOR                             1566
-#define IMG_GROUP_10                                   1567
-#define IMG_GROUP_10_EDITOR                            1568
-#define IMG_GROUP_11                                   1569
-#define IMG_GROUP_11_EDITOR                            1570
-#define IMG_GROUP_12                                   1571
-#define IMG_GROUP_12_EDITOR                            1572
-#define IMG_GROUP_13                                   1573
-#define IMG_GROUP_13_EDITOR                            1574
-#define IMG_GROUP_14                                   1575
-#define IMG_GROUP_14_EDITOR                            1576
-#define IMG_GROUP_15                                   1577
-#define IMG_GROUP_15_EDITOR                            1578
-#define IMG_GROUP_16                                   1579
-#define IMG_GROUP_16_EDITOR                            1580
-#define IMG_GROUP_17                                   1581
-#define IMG_GROUP_17_EDITOR                            1582
-#define IMG_GROUP_18                                   1583
-#define IMG_GROUP_18_EDITOR                            1584
-#define IMG_GROUP_19                                   1585
-#define IMG_GROUP_19_EDITOR                            1586
-#define IMG_GROUP_20                                   1587
-#define IMG_GROUP_20_EDITOR                            1588
-#define IMG_GROUP_21                                   1589
-#define IMG_GROUP_21_EDITOR                            1590
-#define IMG_GROUP_22                                   1591
-#define IMG_GROUP_22_EDITOR                            1592
-#define IMG_GROUP_23                                   1593
-#define IMG_GROUP_23_EDITOR                            1594
-#define IMG_GROUP_24                                   1595
-#define IMG_GROUP_24_EDITOR                            1596
-#define IMG_GROUP_25                                   1597
-#define IMG_GROUP_25_EDITOR                            1598
-#define IMG_GROUP_26                                   1599
-#define IMG_GROUP_26_EDITOR                            1600
-#define IMG_GROUP_27                                   1601
-#define IMG_GROUP_27_EDITOR                            1602
-#define IMG_GROUP_28                                   1603
-#define IMG_GROUP_28_EDITOR                            1604
-#define IMG_GROUP_29                                   1605
-#define IMG_GROUP_29_EDITOR                            1606
-#define IMG_GROUP_30                                   1607
-#define IMG_GROUP_30_EDITOR                            1608
-#define IMG_GROUP_31                                   1609
-#define IMG_GROUP_31_EDITOR                            1610
-#define IMG_GROUP_32                                   1611
-#define IMG_GROUP_32_EDITOR                            1612
-#define IMG_EMC_OBJECT                                 1613
-#define IMG_EMC_SPRITE                                 1614
-#define IMG_TOON_1                                     1615
-#define IMG_TOON_2                                     1616
-#define IMG_TOON_3                                     1617
-#define IMG_TOON_4                                     1618
-#define IMG_TOON_5                                     1619
-#define IMG_TOON_6                                     1620
-#define IMG_TOON_7                                     1621
-#define IMG_TOON_8                                     1622
-#define IMG_TOON_9                                     1623
-#define IMG_TOON_10                                    1624
-#define IMG_TOON_11                                    1625
-#define IMG_TOON_12                                    1626
-#define IMG_TOON_13                                    1627
-#define IMG_TOON_14                                    1628
-#define IMG_TOON_15                                    1629
-#define IMG_TOON_16                                    1630
-#define IMG_TOON_17                                    1631
-#define IMG_TOON_18                                    1632
-#define IMG_TOON_19                                    1633
-#define IMG_TOON_20                                    1634
-#define IMG_MENU_CALIBRATE_RED                         1635
-#define IMG_MENU_CALIBRATE_BLUE                                1636
-#define IMG_MENU_CALIBRATE_YELLOW                      1637
-#define IMG_MENU_BUTTON                                        1638
-#define IMG_MENU_BUTTON_ACTIVE                         1639
-#define IMG_MENU_BUTTON_LEFT                           1640
-#define IMG_MENU_BUTTON_LEFT_ACTIVE                    1641
-#define IMG_MENU_BUTTON_RIGHT                          1642
-#define IMG_MENU_BUTTON_RIGHT_ACTIVE                   1643
-#define IMG_MENU_BUTTON_UP                             1644
-#define IMG_MENU_BUTTON_UP_ACTIVE                      1645
-#define IMG_MENU_BUTTON_DOWN                           1646
-#define IMG_MENU_BUTTON_DOWN_ACTIVE                    1647
-#define IMG_MENU_BUTTON_ENTER_MENU                     1648
-#define IMG_MENU_BUTTON_ENTER_MENU_ACTIVE              1649
-#define IMG_MENU_BUTTON_LEAVE_MENU                     1650
-#define IMG_MENU_BUTTON_LEAVE_MENU_ACTIVE              1651
-#define IMG_MENU_BUTTON_NEXT_LEVEL                     1652
-#define IMG_MENU_BUTTON_NEXT_LEVEL_ACTIVE              1653
-#define IMG_MENU_BUTTON_PREV_LEVEL                     1654
-#define IMG_MENU_BUTTON_PREV_LEVEL_ACTIVE              1655
-#define IMG_MENU_BUTTON_NAME                           1656
-#define IMG_MENU_BUTTON_NAME_ACTIVE                    1657
-#define IMG_MENU_BUTTON_LEVELS                         1658
-#define IMG_MENU_BUTTON_LEVELS_ACTIVE                  1659
-#define IMG_MENU_BUTTON_SCORES                         1660
-#define IMG_MENU_BUTTON_SCORES_ACTIVE                  1661
-#define IMG_MENU_BUTTON_EDITOR                         1662
-#define IMG_MENU_BUTTON_EDITOR_ACTIVE                  1663
-#define IMG_MENU_BUTTON_INFO                           1664
-#define IMG_MENU_BUTTON_INFO_ACTIVE                    1665
-#define IMG_MENU_BUTTON_GAME                           1666
-#define IMG_MENU_BUTTON_GAME_ACTIVE                    1667
-#define IMG_MENU_BUTTON_SETUP                          1668
-#define IMG_MENU_BUTTON_SETUP_ACTIVE                   1669
-#define IMG_MENU_BUTTON_QUIT                           1670
-#define IMG_MENU_BUTTON_QUIT_ACTIVE                    1671
-#define IMG_MENU_SCROLLBAR                             1672
-#define IMG_MENU_SCROLLBAR_ACTIVE                      1673
-#define IMG_FONT_INITIAL_1                             1674
-#define IMG_FONT_INITIAL_2                             1675
-#define IMG_FONT_INITIAL_3                             1676
-#define IMG_FONT_INITIAL_4                             1677
-#define IMG_FONT_TITLE_1                               1678
-#define IMG_FONT_TITLE_2                               1679
-#define IMG_FONT_TITLE_2_SETUP                         1680
-#define IMG_FONT_MENU_1                                        1681
-#define IMG_FONT_MENU_1_ACTIVE                         1682
-#define IMG_FONT_MENU_2                                        1683
-#define IMG_FONT_MENU_2_ACTIVE                         1684
-#define IMG_FONT_TEXT_1                                        1685
-#define IMG_FONT_TEXT_1_MAIN                           1686
-#define IMG_FONT_TEXT_1_LEVELS                         1687
-#define IMG_FONT_TEXT_1_SETUP                          1688
-#define IMG_FONT_TEXT_1_PREVIEW                                1689
-#define IMG_FONT_TEXT_1_SCORES                         1690
-#define IMG_FONT_TEXT_1_ACTIVE_SCORES                  1691
-#define IMG_FONT_TEXT_1_PANEL                          1692
-#define IMG_FONT_TEXT_1_DOOR                           1693
-#define IMG_FONT_TEXT_2                                        1694
-#define IMG_FONT_TEXT_2_MAIN                           1695
-#define IMG_FONT_TEXT_2_LEVELS                         1696
-#define IMG_FONT_TEXT_2_SETUP                          1697
-#define IMG_FONT_TEXT_2_PREVIEW                                1698
-#define IMG_FONT_TEXT_2_SCORES                         1699
-#define IMG_FONT_TEXT_2_ACTIVE_SCORES                  1700
-#define IMG_FONT_TEXT_3                                        1701
-#define IMG_FONT_TEXT_3_LEVELS                         1702
-#define IMG_FONT_TEXT_3_SETUP                          1703
-#define IMG_FONT_TEXT_3_PREVIEW                                1704
-#define IMG_FONT_TEXT_3_SCORES                         1705
-#define IMG_FONT_TEXT_3_ACTIVE_SCORES                  1706
-#define IMG_FONT_TEXT_4                                        1707
-#define IMG_FONT_TEXT_4_MAIN                           1708
-#define IMG_FONT_TEXT_4_LEVELS                         1709
-#define IMG_FONT_TEXT_4_SETUP                          1710
-#define IMG_FONT_TEXT_4_SCORES                         1711
-#define IMG_FONT_TEXT_4_ACTIVE_SCORES                  1712
-#define IMG_FONT_ENVELOPE_1                            1713
-#define IMG_FONT_ENVELOPE_2                            1714
-#define IMG_FONT_ENVELOPE_3                            1715
-#define IMG_FONT_ENVELOPE_4                            1716
-#define IMG_FONT_INPUT_1                               1717
-#define IMG_FONT_INPUT_1_MAIN                          1718
-#define IMG_FONT_INPUT_1_ACTIVE                                1719
-#define IMG_FONT_INPUT_1_ACTIVE_MAIN                   1720
-#define IMG_FONT_INPUT_1_ACTIVE_SETUP                  1721
-#define IMG_FONT_INPUT_2                               1722
-#define IMG_FONT_INPUT_2_ACTIVE                                1723
-#define IMG_FONT_OPTION_OFF                            1724
-#define IMG_FONT_OPTION_ON                             1725
-#define IMG_FONT_VALUE_1                               1726
-#define IMG_FONT_VALUE_2                               1727
-#define IMG_FONT_VALUE_OLD                             1728
-#define IMG_FONT_LEVEL_NUMBER                          1729
-#define IMG_FONT_LEVEL_NUMBER_ACTIVE                   1730
-#define IMG_FONT_TAPE_RECORDER                         1731
-#define IMG_FONT_GAME_INFO                             1732
-#define IMG_FONT_INFO_ELEMENTS                         1733
-#define IMG_FONT_INFO_LEVELSET                         1734
-#define IMG_GLOBAL_BORDER                              1735
-#define IMG_GLOBAL_DOOR                                        1736
-#define IMG_GLOBAL_BUSY                                        1737
-#define IMG_EDITOR_ELEMENT_BORDER                      1738
-#define IMG_EDITOR_ELEMENT_BORDER_INPUT                        1739
-#define IMG_EDITOR_CASCADE_LIST                                1740
-#define IMG_EDITOR_CASCADE_LIST_ACTIVE                 1741
-#define IMG_BACKGROUND                                 1742
-#define IMG_BACKGROUND_TITLE_INITIAL                   1743
-#define IMG_BACKGROUND_TITLE                           1744
-#define IMG_BACKGROUND_MAIN                            1745
-#define IMG_BACKGROUND_LEVELS                          1746
-#define IMG_BACKGROUND_SCORES                          1747
-#define IMG_BACKGROUND_EDITOR                          1748
-#define IMG_BACKGROUND_INFO                            1749
-#define IMG_BACKGROUND_INFO_ELEMENTS                   1750
-#define IMG_BACKGROUND_INFO_MUSIC                      1751
-#define IMG_BACKGROUND_INFO_CREDITS                    1752
-#define IMG_BACKGROUND_INFO_PROGRAM                    1753
-#define IMG_BACKGROUND_INFO_VERSION                    1754
-#define IMG_BACKGROUND_INFO_LEVELSET                   1755
-#define IMG_BACKGROUND_SETUP                           1756
-#define IMG_BACKGROUND_PLAYING                         1757
-#define IMG_BACKGROUND_DOOR                            1758
-#define IMG_BACKGROUND_TITLESCREEN_INITIAL_1           1759
-#define IMG_BACKGROUND_TITLESCREEN_INITIAL_2           1760
-#define IMG_BACKGROUND_TITLESCREEN_INITIAL_3           1761
-#define IMG_BACKGROUND_TITLESCREEN_INITIAL_4           1762
-#define IMG_BACKGROUND_TITLESCREEN_INITIAL_5           1763
-#define IMG_BACKGROUND_TITLESCREEN_1                   1764
-#define IMG_BACKGROUND_TITLESCREEN_2                   1765
-#define IMG_BACKGROUND_TITLESCREEN_3                   1766
-#define IMG_BACKGROUND_TITLESCREEN_4                   1767
-#define IMG_BACKGROUND_TITLESCREEN_5                   1768
-#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_1          1769
-#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_2          1770
-#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_3          1771
-#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_4          1772
-#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_5          1773
-#define IMG_BACKGROUND_TITLEMESSAGE_1                  1774
-#define IMG_BACKGROUND_TITLEMESSAGE_2                  1775
-#define IMG_BACKGROUND_TITLEMESSAGE_3                  1776
-#define IMG_BACKGROUND_TITLEMESSAGE_4                  1777
-#define IMG_BACKGROUND_TITLEMESSAGE_5                  1778
-#define IMG_BACKGROUND_ENVELOPE_1                      1779
-#define IMG_BACKGROUND_ENVELOPE_2                      1780
-#define IMG_BACKGROUND_ENVELOPE_3                      1781
-#define IMG_BACKGROUND_ENVELOPE_4                      1782
-#define IMG_TITLESCREEN_INITIAL_1                      1783
-#define IMG_TITLESCREEN_INITIAL_2                      1784
-#define IMG_TITLESCREEN_INITIAL_3                      1785
-#define IMG_TITLESCREEN_INITIAL_4                      1786
-#define IMG_TITLESCREEN_INITIAL_5                      1787
-#define IMG_TITLESCREEN_1                              1788
-#define IMG_TITLESCREEN_2                              1789
-#define IMG_TITLESCREEN_3                              1790
-#define IMG_TITLESCREEN_4                              1791
-#define IMG_TITLESCREEN_5                              1792
+#define IMG_SP_MURPHY_DROPPING                         63
+#define IMG_SP_MURPHY_SHRINKING                                64
+#define IMG_SP_MURPHY_CLONE                            65
+#define IMG_SP_INFOTRON                                        66
+#define IMG_SP_INFOTRON_EDITOR                         67
+#define IMG_SP_INFOTRON_MOVING_LEFT                    68
+#define IMG_SP_INFOTRON_MOVING_RIGHT                   69
+#define IMG_SP_INFOTRON_COLLECTING                     70
+#define IMG_SP_CHIP_SINGLE                             71
+#define IMG_SP_CHIP_LEFT                               72
+#define IMG_SP_CHIP_RIGHT                              73
+#define IMG_SP_CHIP_TOP                                        74
+#define IMG_SP_CHIP_BOTTOM                             75
+#define IMG_SP_HARDWARE_GRAY                           76
+#define IMG_SP_HARDWARE_GREEN                          77
+#define IMG_SP_HARDWARE_BLUE                           78
+#define IMG_SP_HARDWARE_RED                            79
+#define IMG_SP_HARDWARE_YELLOW                         80
+#define IMG_SP_EXIT_CLOSED                             81
+#define IMG_SP_EXIT_OPENING                            82
+#define IMG_SP_EXIT_OPEN                               83
+#define IMG_SP_EXIT_CLOSING                            84
+#define IMG_SP_DISK_ORANGE                             85
+#define IMG_SP_DISK_YELLOW                             86
+#define IMG_SP_DISK_RED                                        87
+#define IMG_SP_DISK_RED_COLLECTING                     88
+#define IMG_SP_DISK_RED_ACTIVE                         89
+#define IMG_SP_PORT_RIGHT                              90
+#define IMG_SP_PORT_DOWN                               91
+#define IMG_SP_PORT_LEFT                               92
+#define IMG_SP_PORT_UP                                 93
+#define IMG_SP_PORT_HORIZONTAL                         94
+#define IMG_SP_PORT_VERTICAL                           95
+#define IMG_SP_PORT_ANY                                        96
+#define IMG_SP_GRAVITY_PORT_RIGHT                      97
+#define IMG_SP_GRAVITY_PORT_RIGHT_EDITOR               98
+#define IMG_SP_GRAVITY_PORT_DOWN                       99
+#define IMG_SP_GRAVITY_PORT_DOWN_EDITOR                        100
+#define IMG_SP_GRAVITY_PORT_LEFT                       101
+#define IMG_SP_GRAVITY_PORT_LEFT_EDITOR                        102
+#define IMG_SP_GRAVITY_PORT_UP                         103
+#define IMG_SP_GRAVITY_PORT_UP_EDITOR                  104
+#define IMG_SP_GRAVITY_ON_PORT_RIGHT                   105
+#define IMG_SP_GRAVITY_ON_PORT_RIGHT_EDITOR            106
+#define IMG_SP_GRAVITY_ON_PORT_DOWN                    107
+#define IMG_SP_GRAVITY_ON_PORT_DOWN_EDITOR             108
+#define IMG_SP_GRAVITY_ON_PORT_LEFT                    109
+#define IMG_SP_GRAVITY_ON_PORT_LEFT_EDITOR             110
+#define IMG_SP_GRAVITY_ON_PORT_UP                      111
+#define IMG_SP_GRAVITY_ON_PORT_UP_EDITOR               112
+#define IMG_SP_GRAVITY_OFF_PORT_RIGHT                  113
+#define IMG_SP_GRAVITY_OFF_PORT_RIGHT_EDITOR           114
+#define IMG_SP_GRAVITY_OFF_PORT_DOWN                   115
+#define IMG_SP_GRAVITY_OFF_PORT_DOWN_EDITOR            116
+#define IMG_SP_GRAVITY_OFF_PORT_LEFT                   117
+#define IMG_SP_GRAVITY_OFF_PORT_LEFT_EDITOR            118
+#define IMG_SP_GRAVITY_OFF_PORT_UP                     119
+#define IMG_SP_GRAVITY_OFF_PORT_UP_EDITOR              120
+#define IMG_SP_SNIKSNAK                                        121
+#define IMG_SP_SNIKSNAK_LEFT                           122
+#define IMG_SP_SNIKSNAK_RIGHT                          123
+#define IMG_SP_SNIKSNAK_UP                             124
+#define IMG_SP_SNIKSNAK_DOWN                           125
+#define IMG_SP_SNIKSNAK_TURNING_FROM_LEFT_UP           126
+#define IMG_SP_SNIKSNAK_TURNING_FROM_LEFT_DOWN         127
+#define IMG_SP_SNIKSNAK_TURNING_FROM_RIGHT_UP          128
+#define IMG_SP_SNIKSNAK_TURNING_FROM_RIGHT_DOWN                129
+#define IMG_SP_SNIKSNAK_TURNING_FROM_UP_LEFT           130
+#define IMG_SP_SNIKSNAK_TURNING_FROM_UP_RIGHT          131
+#define IMG_SP_SNIKSNAK_TURNING_FROM_DOWN_LEFT         132
+#define IMG_SP_SNIKSNAK_TURNING_FROM_DOWN_RIGHT                133
+#define IMG_SP_ELECTRON                                        134
+#define IMG_SP_ELECTRON_EDITOR                         135
+#define IMG_SP_ELECTRON_EXPLODING                      136
+#define IMG_SP_TERMINAL                                        137
+#define IMG_SP_TERMINAL_EDITOR                         138
+#define IMG_SP_TERMINAL_ACTIVE                         139
+#define IMG_SP_BUGGY_BASE                              140
+#define IMG_SP_BUGGY_BASE_EDITOR                       141
+#define IMG_SP_BUGGY_BASE_ACTIVATING                   142
+#define IMG_SP_BUGGY_BASE_ACTIVE                       143
+#define IMG_SP_HARDWARE_BASE_1                         144
+#define IMG_SP_HARDWARE_BASE_2                         145
+#define IMG_SP_HARDWARE_BASE_3                         146
+#define IMG_SP_HARDWARE_BASE_4                         147
+#define IMG_SP_HARDWARE_BASE_5                         148
+#define IMG_SP_HARDWARE_BASE_6                         149
+#define IMG_SOKOBAN_OBJECT                             150
+#define IMG_SOKOBAN_OBJECT_EDITOR                      151
+#define IMG_SOKOBAN_FIELD_EMPTY                                152
+#define IMG_SOKOBAN_FIELD_FULL                         153
+#define IMG_SOKOBAN_FIELD_PLAYER                       154
+#define IMG_SOKOBAN_FIELD_PLAYER_EDITOR                        155
+#define IMG_EMPTY_SPACE                                        156
+#define IMG_SAND                                       157
+#define IMG_SAND_CRUMBLED                              158
+#define IMG_SAND_DIGGING_LEFT                          159
+#define IMG_SAND_DIGGING_RIGHT                         160
+#define IMG_SAND_DIGGING_UP                            161
+#define IMG_SAND_DIGGING_DOWN                          162
+#define IMG_SAND_DIGGING_LEFT_CRUMBLED                 163
+#define IMG_SAND_DIGGING_RIGHT_CRUMBLED                        164
+#define IMG_SAND_DIGGING_UP_CRUMBLED                   165
+#define IMG_SAND_DIGGING_DOWN_CRUMBLED                 166
+#define IMG_WALL                                       167
+#define IMG_WALL_SLIPPERY                              168
+#define IMG_STEELWALL                                  169
+#define IMG_ROCK                                       170
+#define IMG_ROCK_MOVING_LEFT                           171
+#define IMG_ROCK_MOVING_RIGHT                          172
+#define IMG_ROCK_PUSHING_LEFT                          173
+#define IMG_ROCK_PUSHING_RIGHT                         174
+#define IMG_EMERALD                                    175
+#define IMG_EMERALD_MOVING                             176
+#define IMG_EMERALD_FALLING                            177
+#define IMG_EMERALD_COLLECTING                         178
+#define IMG_DIAMOND                                    179
+#define IMG_DIAMOND_MOVING                             180
+#define IMG_DIAMOND_FALLING                            181
+#define IMG_DIAMOND_COLLECTING                         182
+#define IMG_BOMB                                       183
+#define IMG_NUT                                                184
+#define IMG_NUT_BREAKING                               185
+#define IMG_DYNAMITE                                   186
+#define IMG_DYNAMITE_EDITOR                            187
+#define IMG_DYNAMITE_ACTIVE                            188
+#define IMG_DYNAMITE_ACTIVE_EDITOR                     189
+#define IMG_EM_DYNAMITE                                        190
+#define IMG_EM_DYNAMITE_ACTIVE                         191
+#define IMG_EM_DYNAMITE_ACTIVE_EDITOR                  192
+#define IMG_WALL_EMERALD                               193
+#define IMG_WALL_DIAMOND                               194
+#define IMG_BUG                                                195
+#define IMG_BUG_RIGHT                                  196
+#define IMG_BUG_UP                                     197
+#define IMG_BUG_LEFT                                   198
+#define IMG_BUG_DOWN                                   199
+#define IMG_BUG_MOVING_RIGHT                           200
+#define IMG_BUG_MOVING_UP                              201
+#define IMG_BUG_MOVING_LEFT                            202
+#define IMG_BUG_MOVING_DOWN                            203
+#define IMG_BUG_TURNING_FROM_RIGHT_UP                  204
+#define IMG_BUG_TURNING_FROM_UP_LEFT                   205
+#define IMG_BUG_TURNING_FROM_LEFT_DOWN                 206
+#define IMG_BUG_TURNING_FROM_DOWN_RIGHT                        207
+#define IMG_BUG_TURNING_FROM_RIGHT_DOWN                        208
+#define IMG_BUG_TURNING_FROM_UP_RIGHT                  209
+#define IMG_BUG_TURNING_FROM_LEFT_UP                   210
+#define IMG_BUG_TURNING_FROM_DOWN_LEFT                 211
+#define IMG_SPACESHIP                                  212
+#define IMG_SPACESHIP_RIGHT                            213
+#define IMG_SPACESHIP_UP                               214
+#define IMG_SPACESHIP_LEFT                             215
+#define IMG_SPACESHIP_DOWN                             216
+#define IMG_SPACESHIP_MOVING_RIGHT                     217
+#define IMG_SPACESHIP_MOVING_UP                                218
+#define IMG_SPACESHIP_MOVING_LEFT                      219
+#define IMG_SPACESHIP_MOVING_DOWN                      220
+#define IMG_SPACESHIP_TURNING_FROM_RIGHT_UP            221
+#define IMG_SPACESHIP_TURNING_FROM_UP_LEFT             222
+#define IMG_SPACESHIP_TURNING_FROM_LEFT_DOWN           223
+#define IMG_SPACESHIP_TURNING_FROM_DOWN_RIGHT          224
+#define IMG_SPACESHIP_TURNING_FROM_RIGHT_DOWN          225
+#define IMG_SPACESHIP_TURNING_FROM_UP_RIGHT            226
+#define IMG_SPACESHIP_TURNING_FROM_LEFT_UP             227
+#define IMG_SPACESHIP_TURNING_FROM_DOWN_LEFT           228
+#define IMG_YAMYAM                                     229
+#define IMG_YAMYAM_LEFT                                        230
+#define IMG_YAMYAM_LEFT_EDITOR                         231
+#define IMG_YAMYAM_RIGHT                               232
+#define IMG_YAMYAM_RIGHT_EDITOR                                233
+#define IMG_YAMYAM_UP                                  234
+#define IMG_YAMYAM_UP_EDITOR                           235
+#define IMG_YAMYAM_DOWN                                        236
+#define IMG_YAMYAM_DOWN_EDITOR                         237
+#define IMG_YAMYAM_MOVING                              238
+#define IMG_ROBOT                                      239
+#define IMG_ROBOT_MOVING                               240
+#define IMG_ROBOT_WHEEL                                        241
+#define IMG_ROBOT_WHEEL_ACTIVE                         242
+#define IMG_MAGIC_WALL                                 243
+#define IMG_MAGIC_WALL_ACTIVE                          244
+#define IMG_MAGIC_WALL_FILLING                         245
+#define IMG_MAGIC_WALL_FULL                            246
+#define IMG_MAGIC_WALL_EMPTYING                                247
+#define IMG_MAGIC_WALL_DEAD                            248
+#define IMG_DC_MAGIC_WALL                              249
+#define IMG_DC_MAGIC_WALL_ACTIVE                       250
+#define IMG_DC_MAGIC_WALL_FILLING                      251
+#define IMG_DC_MAGIC_WALL_FULL                         252
+#define IMG_DC_MAGIC_WALL_EMPTYING                     253
+#define IMG_DC_MAGIC_WALL_DEAD                         254
+#define IMG_QUICKSAND_EMPTY                            255
+#define IMG_QUICKSAND_FILLING                          256
+#define IMG_QUICKSAND_FULL                             257
+#define IMG_QUICKSAND_FULL_EDITOR                      258
+#define IMG_QUICKSAND_EMPTYING                         259
+#define IMG_QUICKSAND_FAST_EMPTY                       260
+#define IMG_QUICKSAND_FAST_FILLING                     261
+#define IMG_QUICKSAND_FAST_FULL                                262
+#define IMG_QUICKSAND_FAST_FULL_EDITOR                 263
+#define IMG_QUICKSAND_FAST_EMPTYING                    264
+#define IMG_ACID_POOL_TOPLEFT                          265
+#define IMG_ACID_POOL_TOPRIGHT                         266
+#define IMG_ACID_POOL_BOTTOMLEFT                       267
+#define IMG_ACID_POOL_BOTTOM                           268
+#define IMG_ACID_POOL_BOTTOMRIGHT                      269
+#define IMG_ACID                                       270
+#define IMG_ACID_SPLASH_LEFT                           271
+#define IMG_ACID_SPLASH_RIGHT                          272
+#define IMG_AMOEBA_DROP                                        273
+#define IMG_AMOEBA_GROWING                             274
+#define IMG_AMOEBA_SHRINKING                           275
+#define IMG_AMOEBA_WET                                 276
+#define IMG_AMOEBA_WET_EDITOR                          277
+#define IMG_AMOEBA_DROPPING                            278
+#define IMG_AMOEBA_DRY                                 279
+#define IMG_AMOEBA_FULL                                        280
+#define IMG_AMOEBA_FULL_EDITOR                         281
+#define IMG_AMOEBA_DEAD                                        282
+#define IMG_AMOEBA_DEAD_EDITOR                         283
+#define IMG_EM_KEY_1                                   284
+#define IMG_EM_KEY_2                                   285
+#define IMG_EM_KEY_3                                   286
+#define IMG_EM_KEY_4                                   287
+#define IMG_DC_KEY_WHITE                               288
+#define IMG_EM_GATE_1                                  289
+#define IMG_EM_GATE_2                                  290
+#define IMG_EM_GATE_3                                  291
+#define IMG_EM_GATE_4                                  292
+#define IMG_DC_GATE_WHITE                              293
+#define IMG_EM_GATE_1_GRAY                             294
+#define IMG_EM_GATE_1_GRAY_EDITOR                      295
+#define IMG_EM_GATE_1_GRAY_ACTIVE                      296
+#define IMG_EM_GATE_2_GRAY                             297
+#define IMG_EM_GATE_2_GRAY_EDITOR                      298
+#define IMG_EM_GATE_2_GRAY_ACTIVE                      299
+#define IMG_EM_GATE_3_GRAY                             300
+#define IMG_EM_GATE_3_GRAY_EDITOR                      301
+#define IMG_EM_GATE_3_GRAY_ACTIVE                      302
+#define IMG_EM_GATE_4_GRAY                             303
+#define IMG_EM_GATE_4_GRAY_EDITOR                      304
+#define IMG_EM_GATE_4_GRAY_ACTIVE                      305
+#define IMG_DC_GATE_WHITE_GRAY                         306
+#define IMG_DC_GATE_WHITE_GRAY_EDITOR                  307
+#define IMG_DC_GATE_WHITE_GRAY_ACTIVE                  308
+#define IMG_DC_GATE_FAKE_GRAY                          309
+#define IMG_EXIT_CLOSED                                        310
+#define IMG_EXIT_OPENING                               311
+#define IMG_EXIT_OPEN                                  312
+#define IMG_EXIT_CLOSING                               313
+#define IMG_STEEL_EXIT_CLOSED                          314
+#define IMG_STEEL_EXIT_OPENING                         315
+#define IMG_STEEL_EXIT_OPEN                            316
+#define IMG_STEEL_EXIT_CLOSING                         317
+#define IMG_EM_EXIT_CLOSED                             318
+#define IMG_EM_EXIT_OPENING                            319
+#define IMG_EM_EXIT_OPEN                               320
+#define IMG_EM_EXIT_CLOSING                            321
+#define IMG_EM_STEEL_EXIT_CLOSED                       322
+#define IMG_EM_STEEL_EXIT_OPENING                      323
+#define IMG_EM_STEEL_EXIT_OPEN                         324
+#define IMG_EM_STEEL_EXIT_CLOSING                      325
+#define IMG_BALLOON                                    326
+#define IMG_BALLOON_MOVING                             327
+#define IMG_BALLOON_PUSHING                            328
+#define IMG_BALLOON_SWITCH_LEFT                                329
+#define IMG_BALLOON_SWITCH_RIGHT                       330
+#define IMG_BALLOON_SWITCH_UP                          331
+#define IMG_BALLOON_SWITCH_DOWN                                332
+#define IMG_BALLOON_SWITCH_ANY                         333
+#define IMG_BALLOON_SWITCH_NONE                                334
+#define IMG_SPRING                                     335
+#define IMG_EMC_STEELWALL_1                            336
+#define IMG_EMC_STEELWALL_2                            337
+#define IMG_EMC_STEELWALL_3                            338
+#define IMG_EMC_STEELWALL_4                            339
+#define IMG_EMC_WALL_1                                 340
+#define IMG_EMC_WALL_2                                 341
+#define IMG_EMC_WALL_3                                 342
+#define IMG_EMC_WALL_4                                 343
+#define IMG_EMC_WALL_5                                 344
+#define IMG_EMC_WALL_6                                 345
+#define IMG_EMC_WALL_7                                 346
+#define IMG_EMC_WALL_8                                 347
+#define IMG_INVISIBLE_STEELWALL                                348
+#define IMG_INVISIBLE_STEELWALL_EDITOR                 349
+#define IMG_INVISIBLE_STEELWALL_ACTIVE                 350
+#define IMG_INVISIBLE_WALL                             351
+#define IMG_INVISIBLE_WALL_EDITOR                      352
+#define IMG_INVISIBLE_WALL_ACTIVE                      353
+#define IMG_INVISIBLE_SAND                             354
+#define IMG_INVISIBLE_SAND_EDITOR                      355
+#define IMG_INVISIBLE_SAND_ACTIVE                      356
+#define IMG_INVISIBLE_SAND_ACTIVE_CRUMBLED             357
+#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_LEFT         358
+#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_RIGHT                359
+#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_UP           360
+#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_DOWN         361
+#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_LEFT_CRUMBLED        362
+#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_RIGHT_CRUMBLED       363
+#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_UP_CRUMBLED  364
+#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_DOWN_CRUMBLED        365
+#define IMG_CONVEYOR_BELT_1_MIDDLE                     366
+#define IMG_CONVEYOR_BELT_1_MIDDLE_ACTIVE              367
+#define IMG_CONVEYOR_BELT_1_LEFT                       368
+#define IMG_CONVEYOR_BELT_1_LEFT_ACTIVE                        369
+#define IMG_CONVEYOR_BELT_1_RIGHT                      370
+#define IMG_CONVEYOR_BELT_1_RIGHT_ACTIVE               371
+#define IMG_CONVEYOR_BELT_1_SWITCH_LEFT                        372
+#define IMG_CONVEYOR_BELT_1_SWITCH_MIDDLE              373
+#define IMG_CONVEYOR_BELT_1_SWITCH_RIGHT               374
+#define IMG_CONVEYOR_BELT_2_MIDDLE                     375
+#define IMG_CONVEYOR_BELT_2_MIDDLE_ACTIVE              376
+#define IMG_CONVEYOR_BELT_2_LEFT                       377
+#define IMG_CONVEYOR_BELT_2_LEFT_ACTIVE                        378
+#define IMG_CONVEYOR_BELT_2_RIGHT                      379
+#define IMG_CONVEYOR_BELT_2_RIGHT_ACTIVE               380
+#define IMG_CONVEYOR_BELT_2_SWITCH_LEFT                        381
+#define IMG_CONVEYOR_BELT_2_SWITCH_MIDDLE              382
+#define IMG_CONVEYOR_BELT_2_SWITCH_RIGHT               383
+#define IMG_CONVEYOR_BELT_3_MIDDLE                     384
+#define IMG_CONVEYOR_BELT_3_MIDDLE_ACTIVE              385
+#define IMG_CONVEYOR_BELT_3_LEFT                       386
+#define IMG_CONVEYOR_BELT_3_LEFT_ACTIVE                        387
+#define IMG_CONVEYOR_BELT_3_RIGHT                      388
+#define IMG_CONVEYOR_BELT_3_RIGHT_ACTIVE               389
+#define IMG_CONVEYOR_BELT_3_SWITCH_LEFT                        390
+#define IMG_CONVEYOR_BELT_3_SWITCH_MIDDLE              391
+#define IMG_CONVEYOR_BELT_3_SWITCH_RIGHT               392
+#define IMG_CONVEYOR_BELT_4_MIDDLE                     393
+#define IMG_CONVEYOR_BELT_4_MIDDLE_ACTIVE              394
+#define IMG_CONVEYOR_BELT_4_LEFT                       395
+#define IMG_CONVEYOR_BELT_4_LEFT_ACTIVE                        396
+#define IMG_CONVEYOR_BELT_4_RIGHT                      397
+#define IMG_CONVEYOR_BELT_4_RIGHT_ACTIVE               398
+#define IMG_CONVEYOR_BELT_4_SWITCH_LEFT                        399
+#define IMG_CONVEYOR_BELT_4_SWITCH_MIDDLE              400
+#define IMG_CONVEYOR_BELT_4_SWITCH_RIGHT               401
+#define IMG_SWITCHGATE_SWITCH_UP                       402
+#define IMG_SWITCHGATE_SWITCH_DOWN                     403
+#define IMG_DC_SWITCHGATE_SWITCH_UP                    404
+#define IMG_DC_SWITCHGATE_SWITCH_DOWN                  405
+#define IMG_LIGHT_SWITCH                               406
+#define IMG_LIGHT_SWITCH_ACTIVE                                407
+#define IMG_TIMEGATE_SWITCH                            408
+#define IMG_TIMEGATE_SWITCH_ACTIVE                     409
+#define IMG_DC_TIMEGATE_SWITCH                         410
+#define IMG_DC_TIMEGATE_SWITCH_ACTIVE                  411
+#define IMG_ENVELOPE_1                                 412
+#define IMG_ENVELOPE_1_COLLECTING                      413
+#define IMG_ENVELOPE_2                                 414
+#define IMG_ENVELOPE_2_COLLECTING                      415
+#define IMG_ENVELOPE_3                                 416
+#define IMG_ENVELOPE_3_COLLECTING                      417
+#define IMG_ENVELOPE_4                                 418
+#define IMG_ENVELOPE_4_COLLECTING                      419
+#define IMG_SIGN_RADIOACTIVITY                         420
+#define IMG_SIGN_GIVE_WAY                              421
+#define IMG_SIGN_NO_ENTRY                              422
+#define IMG_SIGN_EMERGENCY_EXIT                                423
+#define IMG_SIGN_YIN_YANG                              424
+#define IMG_SIGN_EXCLAMATION                           425
+#define IMG_SIGN_STOP                                  426
+#define IMG_SIGN_PARKING                               427
+#define IMG_SIGN_WHEELCHAIR                            428
+#define IMG_SIGN_ENTRY_FORBIDDEN                       429
+#define IMG_SPERMS                                     430
+#define IMG_BULLET                                     431
+#define IMG_HEART                                      432
+#define IMG_CROSS                                      433
+#define IMG_FRANKIE                                    434
+#define IMG_SIGN_SPERMS                                        435
+#define IMG_SIGN_BULLET                                        436
+#define IMG_SIGN_HEART                                 437
+#define IMG_SIGN_CROSS                                 438
+#define IMG_SIGN_FRANKIE                               439
+#define IMG_LANDMINE                                   440
+#define IMG_DC_LANDMINE                                        441
+#define IMG_STEELWALL_SLIPPERY                         442
+#define IMG_EXTRA_TIME                                 443
+#define IMG_SHIELD_NORMAL                              444
+#define IMG_SHIELD_NORMAL_ACTIVE                       445
+#define IMG_SHIELD_DEADLY                              446
+#define IMG_SHIELD_DEADLY_ACTIVE                       447
+#define IMG_SWITCHGATE_CLOSED                          448
+#define IMG_SWITCHGATE_OPENING                         449
+#define IMG_SWITCHGATE_OPEN                            450
+#define IMG_SWITCHGATE_CLOSING                         451
+#define IMG_TIMEGATE_CLOSED                            452
+#define IMG_TIMEGATE_OPENING                           453
+#define IMG_TIMEGATE_OPEN                              454
+#define IMG_TIMEGATE_CLOSING                           455
+#define IMG_PEARL                                      456
+#define IMG_PEARL_BREAKING                             457
+#define IMG_CRYSTAL                                    458
+#define IMG_WALL_PEARL                                 459
+#define IMG_WALL_CRYSTAL                               460
+#define IMG_DC_STEELWALL_1_LEFT                                461
+#define IMG_DC_STEELWALL_1_RIGHT                       462
+#define IMG_DC_STEELWALL_1_TOP                         463
+#define IMG_DC_STEELWALL_1_BOTTOM                      464
+#define IMG_DC_STEELWALL_1_HORIZONTAL                  465
+#define IMG_DC_STEELWALL_1_VERTICAL                    466
+#define IMG_DC_STEELWALL_1_TOPLEFT                     467
+#define IMG_DC_STEELWALL_1_TOPRIGHT                    468
+#define IMG_DC_STEELWALL_1_BOTTOMLEFT                  469
+#define IMG_DC_STEELWALL_1_BOTTOMRIGHT                 470
+#define IMG_DC_STEELWALL_1_TOPLEFT_2                   471
+#define IMG_DC_STEELWALL_1_TOPRIGHT_2                  472
+#define IMG_DC_STEELWALL_1_BOTTOMLEFT_2                        473
+#define IMG_DC_STEELWALL_1_BOTTOMRIGHT_2               474
+#define IMG_DC_STEELWALL_2_LEFT                                475
+#define IMG_DC_STEELWALL_2_RIGHT                       476
+#define IMG_DC_STEELWALL_2_TOP                         477
+#define IMG_DC_STEELWALL_2_BOTTOM                      478
+#define IMG_DC_STEELWALL_2_HORIZONTAL                  479
+#define IMG_DC_STEELWALL_2_VERTICAL                    480
+#define IMG_DC_STEELWALL_2_MIDDLE                      481
+#define IMG_DC_STEELWALL_2_SINGLE                      482
+#define IMG_TUBE_RIGHT_DOWN                            483
+#define IMG_TUBE_HORIZONTAL_DOWN                       484
+#define IMG_TUBE_LEFT_DOWN                             485
+#define IMG_TUBE_HORIZONTAL                            486
+#define IMG_TUBE_VERTICAL_RIGHT                                487
+#define IMG_TUBE_ANY                                   488
+#define IMG_TUBE_VERTICAL_LEFT                         489
+#define IMG_TUBE_VERTICAL                              490
+#define IMG_TUBE_RIGHT_UP                              491
+#define IMG_TUBE_HORIZONTAL_UP                         492
+#define IMG_TUBE_LEFT_UP                               493
+#define IMG_TRAP                                       494
+#define IMG_TRAP_ACTIVE                                        495
+#define IMG_DX_SUPABOMB                                        496
+#define IMG_KEY_1                                      497
+#define IMG_KEY_1_EDITOR                               498
+#define IMG_KEY_2                                      499
+#define IMG_KEY_2_EDITOR                               500
+#define IMG_KEY_3                                      501
+#define IMG_KEY_3_EDITOR                               502
+#define IMG_KEY_4                                      503
+#define IMG_KEY_4_EDITOR                               504
+#define IMG_GATE_1                                     505
+#define IMG_GATE_2                                     506
+#define IMG_GATE_3                                     507
+#define IMG_GATE_4                                     508
+#define IMG_GATE_1_GRAY                                        509
+#define IMG_GATE_1_GRAY_EDITOR                         510
+#define IMG_GATE_1_GRAY_ACTIVE                         511
+#define IMG_GATE_2_GRAY                                        512
+#define IMG_GATE_2_GRAY_EDITOR                         513
+#define IMG_GATE_2_GRAY_ACTIVE                         514
+#define IMG_GATE_3_GRAY                                        515
+#define IMG_GATE_3_GRAY_EDITOR                         516
+#define IMG_GATE_3_GRAY_ACTIVE                         517
+#define IMG_GATE_4_GRAY                                        518
+#define IMG_GATE_4_GRAY_EDITOR                         519
+#define IMG_GATE_4_GRAY_ACTIVE                         520
+#define IMG_GAME_OF_LIFE                               521
+#define IMG_BIOMAZE                                    522
+#define IMG_PACMAN                                     523
+#define IMG_PACMAN_RIGHT                               524
+#define IMG_PACMAN_UP                                  525
+#define IMG_PACMAN_LEFT                                        526
+#define IMG_PACMAN_DOWN                                        527
+#define IMG_PACMAN_TURNING_FROM_RIGHT                  528
+#define IMG_PACMAN_TURNING_FROM_UP                     529
+#define IMG_PACMAN_TURNING_FROM_LEFT                   530
+#define IMG_PACMAN_TURNING_FROM_DOWN                   531
+#define IMG_LAMP                                       532
+#define IMG_LAMP_EDITOR                                        533
+#define IMG_LAMP_ACTIVE                                        534
+#define IMG_TIME_ORB_FULL                              535
+#define IMG_TIME_ORB_EMPTY                             536
+#define IMG_EMERALD_YELLOW                             537
+#define IMG_EMERALD_YELLOW_MOVING                      538
+#define IMG_EMERALD_YELLOW_FALLING                     539
+#define IMG_EMERALD_RED                                        540
+#define IMG_EMERALD_RED_MOVING                         541
+#define IMG_EMERALD_RED_FALLING                                542
+#define IMG_EMERALD_PURPLE                             543
+#define IMG_EMERALD_PURPLE_MOVING                      544
+#define IMG_EMERALD_PURPLE_FALLING                     545
+#define IMG_WALL_EMERALD_YELLOW                                546
+#define IMG_WALL_EMERALD_RED                           547
+#define IMG_WALL_EMERALD_PURPLE                                548
+#define IMG_WALL_BD_DIAMOND                            549
+#define IMG_EXPANDABLE_WALL                            550
+#define IMG_EXPANDABLE_WALL_HORIZONTAL                 551
+#define IMG_EXPANDABLE_WALL_HORIZONTAL_EDITOR          552
+#define IMG_EXPANDABLE_WALL_VERTICAL                   553
+#define IMG_EXPANDABLE_WALL_VERTICAL_EDITOR            554
+#define IMG_EXPANDABLE_WALL_ANY                                555
+#define IMG_EXPANDABLE_WALL_ANY_EDITOR                 556
+#define IMG_EXPANDABLE_STEELWALL_HORIZONTAL            557
+#define IMG_EXPANDABLE_STEELWALL_HORIZONTAL_EDITOR     558
+#define IMG_EXPANDABLE_STEELWALL_VERTICAL              559
+#define IMG_EXPANDABLE_STEELWALL_VERTICAL_EDITOR       560
+#define IMG_EXPANDABLE_STEELWALL_ANY                   561
+#define IMG_EXPANDABLE_STEELWALL_ANY_EDITOR            562
+#define IMG_BD_EXPANDABLE_WALL                         563
+#define IMG_BD_EXPANDABLE_WALL_EDITOR                  564
+#define IMG_EXPANDABLE_WALL_GROWING_LEFT               565
+#define IMG_EXPANDABLE_WALL_GROWING_RIGHT              566
+#define IMG_EXPANDABLE_WALL_GROWING_UP                 567
+#define IMG_EXPANDABLE_WALL_GROWING_DOWN               568
+#define IMG_EXPANDABLE_STEELWALL_GROWING_LEFT          569
+#define IMG_EXPANDABLE_STEELWALL_GROWING_RIGHT         570
+#define IMG_EXPANDABLE_STEELWALL_GROWING_UP            571
+#define IMG_EXPANDABLE_STEELWALL_GROWING_DOWN          572
+#define IMG_BLACK_ORB                                  573
+#define IMG_SPEED_PILL                                 574
+#define IMG_DARK_YAMYAM                                        575
+#define IMG_DYNABOMB                                   576
+#define IMG_DYNABOMB_ACTIVE                            577
+#define IMG_DYNABOMB_PLAYER_1                          578
+#define IMG_DYNABOMB_PLAYER_1_ACTIVE                   579
+#define IMG_DYNABOMB_PLAYER_2                          580
+#define IMG_DYNABOMB_PLAYER_2_ACTIVE                   581
+#define IMG_DYNABOMB_PLAYER_3                          582
+#define IMG_DYNABOMB_PLAYER_3_ACTIVE                   583
+#define IMG_DYNABOMB_PLAYER_4                          584
+#define IMG_DYNABOMB_PLAYER_4_ACTIVE                   585
+#define IMG_DYNABOMB_INCREASE_NUMBER                   586
+#define IMG_DYNABOMB_INCREASE_SIZE                     587
+#define IMG_DYNABOMB_INCREASE_POWER                    588
+#define IMG_PIG                                                589
+#define IMG_PIG_DOWN                                   590
+#define IMG_PIG_UP                                     591
+#define IMG_PIG_LEFT                                   592
+#define IMG_PIG_RIGHT                                  593
+#define IMG_PIG_MOVING_DOWN                            594
+#define IMG_PIG_MOVING_UP                              595
+#define IMG_PIG_MOVING_LEFT                            596
+#define IMG_PIG_MOVING_RIGHT                           597
+#define IMG_PIG_DIGGING_DOWN                           598
+#define IMG_PIG_DIGGING_UP                             599
+#define IMG_PIG_DIGGING_LEFT                           600
+#define IMG_PIG_DIGGING_RIGHT                          601
+#define IMG_DRAGON                                     602
+#define IMG_DRAGON_DOWN                                        603
+#define IMG_DRAGON_UP                                  604
+#define IMG_DRAGON_LEFT                                        605
+#define IMG_DRAGON_RIGHT                               606
+#define IMG_DRAGON_MOVING_DOWN                         607
+#define IMG_DRAGON_MOVING_UP                           608
+#define IMG_DRAGON_MOVING_LEFT                         609
+#define IMG_DRAGON_MOVING_RIGHT                                610
+#define IMG_DRAGON_ATTACKING_DOWN                      611
+#define IMG_DRAGON_ATTACKING_UP                                612
+#define IMG_DRAGON_ATTACKING_LEFT                      613
+#define IMG_DRAGON_ATTACKING_RIGHT                     614
+#define IMG_MOLE                                       615
+#define IMG_MOLE_DOWN                                  616
+#define IMG_MOLE_UP                                    617
+#define IMG_MOLE_LEFT                                  618
+#define IMG_MOLE_RIGHT                                 619
+#define IMG_MOLE_MOVING_DOWN                           620
+#define IMG_MOLE_MOVING_UP                             621
+#define IMG_MOLE_MOVING_LEFT                           622
+#define IMG_MOLE_MOVING_RIGHT                          623
+#define IMG_MOLE_DIGGING_DOWN                          624
+#define IMG_MOLE_DIGGING_UP                            625
+#define IMG_MOLE_DIGGING_LEFT                          626
+#define IMG_MOLE_DIGGING_RIGHT                         627
+#define IMG_PENGUIN                                    628
+#define IMG_PENGUIN_EDITOR                             629
+#define IMG_PENGUIN_DOWN                               630
+#define IMG_PENGUIN_UP                                 631
+#define IMG_PENGUIN_LEFT                               632
+#define IMG_PENGUIN_RIGHT                              633
+#define IMG_PENGUIN_MOVING_DOWN                                634
+#define IMG_PENGUIN_MOVING_UP                          635
+#define IMG_PENGUIN_MOVING_LEFT                                636
+#define IMG_PENGUIN_MOVING_RIGHT                       637
+#define IMG_SATELLITE                                  638
+#define IMG_FLAMES_1_LEFT                              639
+#define IMG_FLAMES_2_LEFT                              640
+#define IMG_FLAMES_3_LEFT                              641
+#define IMG_FLAMES_1_RIGHT                             642
+#define IMG_FLAMES_2_RIGHT                             643
+#define IMG_FLAMES_3_RIGHT                             644
+#define IMG_FLAMES_1_UP                                        645
+#define IMG_FLAMES_2_UP                                        646
+#define IMG_FLAMES_3_UP                                        647
+#define IMG_FLAMES_1_DOWN                              648
+#define IMG_FLAMES_2_DOWN                              649
+#define IMG_FLAMES_3_DOWN                              650
+#define IMG_STONEBLOCK                                 651
+#define IMG_PLAYER_1                                   652
+#define IMG_PLAYER_1_EDITOR                            653
+#define IMG_PLAYER_1_DOWN                              654
+#define IMG_PLAYER_1_UP                                        655
+#define IMG_PLAYER_1_LEFT                              656
+#define IMG_PLAYER_1_RIGHT                             657
+#define IMG_PLAYER_1_MOVING_DOWN                       658
+#define IMG_PLAYER_1_MOVING_UP                         659
+#define IMG_PLAYER_1_MOVING_LEFT                       660
+#define IMG_PLAYER_1_MOVING_RIGHT                      661
+#define IMG_PLAYER_1_DIGGING_DOWN                      662
+#define IMG_PLAYER_1_DIGGING_UP                                663
+#define IMG_PLAYER_1_DIGGING_LEFT                      664
+#define IMG_PLAYER_1_DIGGING_RIGHT                     665
+#define IMG_PLAYER_1_COLLECTING_DOWN                   666
+#define IMG_PLAYER_1_COLLECTING_UP                     667
+#define IMG_PLAYER_1_COLLECTING_LEFT                   668
+#define IMG_PLAYER_1_COLLECTING_RIGHT                  669
+#define IMG_PLAYER_1_PUSHING_DOWN                      670
+#define IMG_PLAYER_1_PUSHING_UP                                671
+#define IMG_PLAYER_1_PUSHING_LEFT                      672
+#define IMG_PLAYER_1_PUSHING_RIGHT                     673
+#define IMG_PLAYER_1_SNAPPING_DOWN                     674
+#define IMG_PLAYER_1_SNAPPING_UP                       675
+#define IMG_PLAYER_1_SNAPPING_LEFT                     676
+#define IMG_PLAYER_1_SNAPPING_RIGHT                    677
+#define IMG_PLAYER_2                                   678
+#define IMG_PLAYER_2_EDITOR                            679
+#define IMG_PLAYER_2_DOWN                              680
+#define IMG_PLAYER_2_UP                                        681
+#define IMG_PLAYER_2_LEFT                              682
+#define IMG_PLAYER_2_RIGHT                             683
+#define IMG_PLAYER_2_MOVING_DOWN                       684
+#define IMG_PLAYER_2_MOVING_UP                         685
+#define IMG_PLAYER_2_MOVING_LEFT                       686
+#define IMG_PLAYER_2_MOVING_RIGHT                      687
+#define IMG_PLAYER_2_DIGGING_DOWN                      688
+#define IMG_PLAYER_2_DIGGING_UP                                689
+#define IMG_PLAYER_2_DIGGING_LEFT                      690
+#define IMG_PLAYER_2_DIGGING_RIGHT                     691
+#define IMG_PLAYER_2_COLLECTING_DOWN                   692
+#define IMG_PLAYER_2_COLLECTING_UP                     693
+#define IMG_PLAYER_2_COLLECTING_LEFT                   694
+#define IMG_PLAYER_2_COLLECTING_RIGHT                  695
+#define IMG_PLAYER_2_PUSHING_DOWN                      696
+#define IMG_PLAYER_2_PUSHING_UP                                697
+#define IMG_PLAYER_2_PUSHING_LEFT                      698
+#define IMG_PLAYER_2_PUSHING_RIGHT                     699
+#define IMG_PLAYER_2_SNAPPING_DOWN                     700
+#define IMG_PLAYER_2_SNAPPING_UP                       701
+#define IMG_PLAYER_2_SNAPPING_LEFT                     702
+#define IMG_PLAYER_2_SNAPPING_RIGHT                    703
+#define IMG_PLAYER_3                                   704
+#define IMG_PLAYER_3_EDITOR                            705
+#define IMG_PLAYER_3_DOWN                              706
+#define IMG_PLAYER_3_UP                                        707
+#define IMG_PLAYER_3_LEFT                              708
+#define IMG_PLAYER_3_RIGHT                             709
+#define IMG_PLAYER_3_MOVING_DOWN                       710
+#define IMG_PLAYER_3_MOVING_UP                         711
+#define IMG_PLAYER_3_MOVING_LEFT                       712
+#define IMG_PLAYER_3_MOVING_RIGHT                      713
+#define IMG_PLAYER_3_DIGGING_DOWN                      714
+#define IMG_PLAYER_3_DIGGING_UP                                715
+#define IMG_PLAYER_3_DIGGING_LEFT                      716
+#define IMG_PLAYER_3_DIGGING_RIGHT                     717
+#define IMG_PLAYER_3_COLLECTING_DOWN                   718
+#define IMG_PLAYER_3_COLLECTING_UP                     719
+#define IMG_PLAYER_3_COLLECTING_LEFT                   720
+#define IMG_PLAYER_3_COLLECTING_RIGHT                  721
+#define IMG_PLAYER_3_PUSHING_DOWN                      722
+#define IMG_PLAYER_3_PUSHING_UP                                723
+#define IMG_PLAYER_3_PUSHING_LEFT                      724
+#define IMG_PLAYER_3_PUSHING_RIGHT                     725
+#define IMG_PLAYER_3_SNAPPING_DOWN                     726
+#define IMG_PLAYER_3_SNAPPING_UP                       727
+#define IMG_PLAYER_3_SNAPPING_LEFT                     728
+#define IMG_PLAYER_3_SNAPPING_RIGHT                    729
+#define IMG_PLAYER_4                                   730
+#define IMG_PLAYER_4_EDITOR                            731
+#define IMG_PLAYER_4_DOWN                              732
+#define IMG_PLAYER_4_UP                                        733
+#define IMG_PLAYER_4_LEFT                              734
+#define IMG_PLAYER_4_RIGHT                             735
+#define IMG_PLAYER_4_MOVING_DOWN                       736
+#define IMG_PLAYER_4_MOVING_UP                         737
+#define IMG_PLAYER_4_MOVING_LEFT                       738
+#define IMG_PLAYER_4_MOVING_RIGHT                      739
+#define IMG_PLAYER_4_DIGGING_DOWN                      740
+#define IMG_PLAYER_4_DIGGING_UP                                741
+#define IMG_PLAYER_4_DIGGING_LEFT                      742
+#define IMG_PLAYER_4_DIGGING_RIGHT                     743
+#define IMG_PLAYER_4_COLLECTING_DOWN                   744
+#define IMG_PLAYER_4_COLLECTING_UP                     745
+#define IMG_PLAYER_4_COLLECTING_LEFT                   746
+#define IMG_PLAYER_4_COLLECTING_RIGHT                  747
+#define IMG_PLAYER_4_PUSHING_DOWN                      748
+#define IMG_PLAYER_4_PUSHING_UP                                749
+#define IMG_PLAYER_4_PUSHING_LEFT                      750
+#define IMG_PLAYER_4_PUSHING_RIGHT                     751
+#define IMG_PLAYER_4_SNAPPING_DOWN                     752
+#define IMG_PLAYER_4_SNAPPING_UP                       753
+#define IMG_PLAYER_4_SNAPPING_LEFT                     754
+#define IMG_PLAYER_4_SNAPPING_RIGHT                    755
+#define IMG_DEFAULT_EXPLODING                          756
+#define IMG_TWINKLE_BLUE                               757
+#define IMG_TWINKLE_WHITE                              758
+#define IMG_STEELWALL_TOPLEFT                          759
+#define IMG_STEELWALL_TOPRIGHT                         760
+#define IMG_STEELWALL_BOTTOMLEFT                       761
+#define IMG_STEELWALL_BOTTOMRIGHT                      762
+#define IMG_STEELWALL_HORIZONTAL                       763
+#define IMG_STEELWALL_VERTICAL                         764
+#define IMG_STEELWALL_TOPLEFT_EDITOR                   765
+#define IMG_STEELWALL_TOPRIGHT_EDITOR                  766
+#define IMG_STEELWALL_BOTTOMLEFT_EDITOR                        767
+#define IMG_STEELWALL_BOTTOMRIGHT_EDITOR               768
+#define IMG_STEELWALL_HORIZONTAL_EDITOR                        769
+#define IMG_STEELWALL_VERTICAL_EDITOR                  770
+#define IMG_INVISIBLE_STEELWALL_TOPLEFT                        771
+#define IMG_INVISIBLE_STEELWALL_TOPRIGHT               772
+#define IMG_INVISIBLE_STEELWALL_BOTTOMLEFT             773
+#define IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT            774
+#define IMG_INVISIBLE_STEELWALL_HORIZONTAL             775
+#define IMG_INVISIBLE_STEELWALL_VERTICAL               776
+#define IMG_INVISIBLE_STEELWALL_TOPLEFT_EDITOR         777
+#define IMG_INVISIBLE_STEELWALL_TOPRIGHT_EDITOR                778
+#define IMG_INVISIBLE_STEELWALL_BOTTOMLEFT_EDITOR      779
+#define IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT_EDITOR     780
+#define IMG_INVISIBLE_STEELWALL_HORIZONTAL_EDITOR      781
+#define IMG_INVISIBLE_STEELWALL_VERTICAL_EDITOR                782
+#define IMG_ARROW_LEFT                                 783
+#define IMG_ARROW_RIGHT                                        784
+#define IMG_ARROW_UP                                   785
+#define IMG_ARROW_DOWN                                 786
+#define IMG_UNKNOWN                                    787
+#define IMG_TRIGGER_ELEMENT                            788
+#define IMG_TRIGGER_PLAYER                             789
+#define IMG_TRIGGER_CE_VALUE                           790
+#define IMG_TRIGGER_CE_SCORE                           791
+#define IMG_CURRENT_CE_VALUE                           792
+#define IMG_CURRENT_CE_SCORE                           793
+#define IMG_PREV_CE_1                                  794
+#define IMG_PREV_CE_2                                  795
+#define IMG_PREV_CE_3                                  796
+#define IMG_PREV_CE_4                                  797
+#define IMG_PREV_CE_5                                  798
+#define IMG_PREV_CE_6                                  799
+#define IMG_PREV_CE_7                                  800
+#define IMG_PREV_CE_8                                  801
+#define IMG_NEXT_CE_1                                  802
+#define IMG_NEXT_CE_2                                  803
+#define IMG_NEXT_CE_3                                  804
+#define IMG_NEXT_CE_4                                  805
+#define IMG_NEXT_CE_5                                  806
+#define IMG_NEXT_CE_6                                  807
+#define IMG_NEXT_CE_7                                  808
+#define IMG_NEXT_CE_8                                  809
+#define IMG_SELF                                       810
+#define IMG_ANY_ELEMENT                                        811
+#define IMG_EMC_KEY_5                                  812
+#define IMG_EMC_KEY_6                                  813
+#define IMG_EMC_KEY_7                                  814
+#define IMG_EMC_KEY_8                                  815
+#define IMG_EMC_GATE_5                                 816
+#define IMG_EMC_GATE_6                                 817
+#define IMG_EMC_GATE_7                                 818
+#define IMG_EMC_GATE_8                                 819
+#define IMG_EMC_GATE_5_GRAY                            820
+#define IMG_EMC_GATE_5_GRAY_EDITOR                     821
+#define IMG_EMC_GATE_5_GRAY_ACTIVE                     822
+#define IMG_EMC_GATE_6_GRAY                            823
+#define IMG_EMC_GATE_6_GRAY_EDITOR                     824
+#define IMG_EMC_GATE_6_GRAY_ACTIVE                     825
+#define IMG_EMC_GATE_7_GRAY                            826
+#define IMG_EMC_GATE_7_GRAY_EDITOR                     827
+#define IMG_EMC_GATE_7_GRAY_ACTIVE                     828
+#define IMG_EMC_GATE_8_GRAY                            829
+#define IMG_EMC_GATE_8_GRAY_EDITOR                     830
+#define IMG_EMC_GATE_8_GRAY_ACTIVE                     831
+#define IMG_EMC_ANDROID                                        832
+#define IMG_EMC_ANDROID_SHRINKING_UPLEFT               833
+#define IMG_EMC_ANDROID_GROWING_DOWNRIGHT              834
+#define IMG_EMC_ANDROID_SHRINKING_DOWNLEFT             835
+#define IMG_EMC_ANDROID_GROWING_UPRIGHT                        836
+#define IMG_EMC_ANDROID_SHRINKING_UPRIGHT              837
+#define IMG_EMC_ANDROID_GROWING_DOWNLEFT               838
+#define IMG_EMC_ANDROID_SHRINKING_DOWNRIGHT            839
+#define IMG_EMC_ANDROID_GROWING_UPLEFT                 840
+#define IMG_EMC_GRASS                                  841
+#define IMG_EMC_GRASS_CRUMBLED                         842
+#define IMG_EMC_GRASS_DIGGING_LEFT                     843
+#define IMG_EMC_GRASS_DIGGING_RIGHT                    844
+#define IMG_EMC_GRASS_DIGGING_UP                       845
+#define IMG_EMC_GRASS_DIGGING_DOWN                     846
+#define IMG_EMC_GRASS_DIGGING_LEFT_CRUMBLED            847
+#define IMG_EMC_GRASS_DIGGING_RIGHT_CRUMBLED           848
+#define IMG_EMC_GRASS_DIGGING_UP_CRUMBLED              849
+#define IMG_EMC_GRASS_DIGGING_DOWN_CRUMBLED            850
+#define IMG_EMC_MAGIC_BALL                             851
+#define IMG_EMC_MAGIC_BALL_ACTIVE                      852
+#define IMG_EMC_MAGIC_BALL_DROPPING                    853
+#define IMG_EMC_MAGIC_BALL_SWITCH                      854
+#define IMG_EMC_MAGIC_BALL_SWITCH_ACTIVE               855
+#define IMG_EMC_SPRING_BUMPER                          856
+#define IMG_EMC_SPRING_BUMPER_ACTIVE                   857
+#define IMG_EMC_PLANT                                  858
+#define IMG_EMC_PLANT_CRUMBLED                         859
+#define IMG_EMC_LENSES                                 860
+#define IMG_EMC_MAGNIFIER                              861
+#define IMG_EMC_WALL_9                                 862
+#define IMG_EMC_WALL_10                                        863
+#define IMG_EMC_WALL_11                                        864
+#define IMG_EMC_WALL_12                                        865
+#define IMG_EMC_WALL_13                                        866
+#define IMG_EMC_WALL_14                                        867
+#define IMG_EMC_WALL_15                                        868
+#define IMG_EMC_WALL_16                                        869
+#define IMG_EMC_WALL_SLIPPERY_1                                870
+#define IMG_EMC_WALL_SLIPPERY_2                                871
+#define IMG_EMC_WALL_SLIPPERY_3                                872
+#define IMG_EMC_WALL_SLIPPERY_4                                873
+#define IMG_EMC_FAKE_GRASS                             874
+#define IMG_EMC_FAKE_GRASS_CRUMBLED                    875
+#define IMG_EMC_FAKE_GRASS_ACTIVE                      876
+#define IMG_EMC_FAKE_GRASS_ACTIVE_CRUMBLED             877
+#define IMG_EMC_FAKE_GRASS_EDITOR                      878
+#define IMG_EMC_FAKE_ACID                              879
+#define IMG_EMC_DRIPPER                                        880
+#define IMG_EMC_DRIPPER_EDITOR                         881
+#define IMG_EMC_DRIPPER_ACTIVE                         882
+#define IMG_GRAPHIC_1                                  883
+#define IMG_GRAPHIC_2                                  884
+#define IMG_GRAPHIC_3                                  885
+#define IMG_GRAPHIC_4                                  886
+#define IMG_GRAPHIC_5                                  887
+#define IMG_GRAPHIC_6                                  888
+#define IMG_GRAPHIC_7                                  889
+#define IMG_GRAPHIC_8                                  890
+#define IMG_CHAR_SPACE                                 891
+#define IMG_CHAR_SPACE_EDITOR                          892
+#define IMG_CHAR_EXCLAM                                        893
+#define IMG_CHAR_QUOTEDBL                              894
+#define IMG_CHAR_NUMBERSIGN                            895
+#define IMG_CHAR_DOLLAR                                        896
+#define IMG_CHAR_PERCENT                               897
+#define IMG_CHAR_AMPERSAND                             898
+#define IMG_CHAR_APOSTROPHE                            899
+#define IMG_CHAR_PARENLEFT                             900
+#define IMG_CHAR_PARENRIGHT                            901
+#define IMG_CHAR_ASTERISK                              902
+#define IMG_CHAR_PLUS                                  903
+#define IMG_CHAR_COMMA                                 904
+#define IMG_CHAR_MINUS                                 905
+#define IMG_CHAR_PERIOD                                        906
+#define IMG_CHAR_SLASH                                 907
+#define IMG_CHAR_0                                     908
+#define IMG_CHAR_1                                     909
+#define IMG_CHAR_2                                     910
+#define IMG_CHAR_3                                     911
+#define IMG_CHAR_4                                     912
+#define IMG_CHAR_5                                     913
+#define IMG_CHAR_6                                     914
+#define IMG_CHAR_7                                     915
+#define IMG_CHAR_8                                     916
+#define IMG_CHAR_9                                     917
+#define IMG_CHAR_COLON                                 918
+#define IMG_CHAR_SEMICOLON                             919
+#define IMG_CHAR_LESS                                  920
+#define IMG_CHAR_EQUAL                                 921
+#define IMG_CHAR_GREATER                               922
+#define IMG_CHAR_QUESTION                              923
+#define IMG_CHAR_AT                                    924
+#define IMG_CHAR_A                                     925
+#define IMG_CHAR_B                                     926
+#define IMG_CHAR_C                                     927
+#define IMG_CHAR_D                                     928
+#define IMG_CHAR_E                                     929
+#define IMG_CHAR_F                                     930
+#define IMG_CHAR_G                                     931
+#define IMG_CHAR_H                                     932
+#define IMG_CHAR_I                                     933
+#define IMG_CHAR_J                                     934
+#define IMG_CHAR_K                                     935
+#define IMG_CHAR_L                                     936
+#define IMG_CHAR_M                                     937
+#define IMG_CHAR_N                                     938
+#define IMG_CHAR_O                                     939
+#define IMG_CHAR_P                                     940
+#define IMG_CHAR_Q                                     941
+#define IMG_CHAR_R                                     942
+#define IMG_CHAR_S                                     943
+#define IMG_CHAR_T                                     944
+#define IMG_CHAR_U                                     945
+#define IMG_CHAR_V                                     946
+#define IMG_CHAR_W                                     947
+#define IMG_CHAR_X                                     948
+#define IMG_CHAR_Y                                     949
+#define IMG_CHAR_Z                                     950
+#define IMG_CHAR_BRACKETLEFT                           951
+#define IMG_CHAR_BACKSLASH                             952
+#define IMG_CHAR_BRACKETRIGHT                          953
+#define IMG_CHAR_ASCIICIRCUM                           954
+#define IMG_CHAR_UNDERSCORE                            955
+#define IMG_CHAR_COPYRIGHT                             956
+#define IMG_CHAR_AUMLAUT                               957
+#define IMG_CHAR_OUMLAUT                               958
+#define IMG_CHAR_UUMLAUT                               959
+#define IMG_CHAR_DEGREE                                        960
+#define IMG_CHAR_TRADEMARK                             961
+#define IMG_CHAR_CURSOR                                        962
+#define IMG_CHAR_BUTTON                                        963
+#define IMG_CHAR_UP                                    964
+#define IMG_CHAR_DOWN                                  965
+#define IMG_STEEL_CHAR_SPACE                           966
+#define IMG_STEEL_CHAR_SPACE_EDITOR                    967
+#define IMG_STEEL_CHAR_EXCLAM                          968
+#define IMG_STEEL_CHAR_QUOTEDBL                                969
+#define IMG_STEEL_CHAR_NUMBERSIGN                      970
+#define IMG_STEEL_CHAR_DOLLAR                          971
+#define IMG_STEEL_CHAR_PERCENT                         972
+#define IMG_STEEL_CHAR_AMPERSAND                       973
+#define IMG_STEEL_CHAR_APOSTROPHE                      974
+#define IMG_STEEL_CHAR_PARENLEFT                       975
+#define IMG_STEEL_CHAR_PARENRIGHT                      976
+#define IMG_STEEL_CHAR_ASTERISK                                977
+#define IMG_STEEL_CHAR_PLUS                            978
+#define IMG_STEEL_CHAR_COMMA                           979
+#define IMG_STEEL_CHAR_MINUS                           980
+#define IMG_STEEL_CHAR_PERIOD                          981
+#define IMG_STEEL_CHAR_SLASH                           982
+#define IMG_STEEL_CHAR_0                               983
+#define IMG_STEEL_CHAR_1                               984
+#define IMG_STEEL_CHAR_2                               985
+#define IMG_STEEL_CHAR_3                               986
+#define IMG_STEEL_CHAR_4                               987
+#define IMG_STEEL_CHAR_5                               988
+#define IMG_STEEL_CHAR_6                               989
+#define IMG_STEEL_CHAR_7                               990
+#define IMG_STEEL_CHAR_8                               991
+#define IMG_STEEL_CHAR_9                               992
+#define IMG_STEEL_CHAR_COLON                           993
+#define IMG_STEEL_CHAR_SEMICOLON                       994
+#define IMG_STEEL_CHAR_LESS                            995
+#define IMG_STEEL_CHAR_EQUAL                           996
+#define IMG_STEEL_CHAR_GREATER                         997
+#define IMG_STEEL_CHAR_QUESTION                                998
+#define IMG_STEEL_CHAR_AT                              999
+#define IMG_STEEL_CHAR_A                               1000
+#define IMG_STEEL_CHAR_B                               1001
+#define IMG_STEEL_CHAR_C                               1002
+#define IMG_STEEL_CHAR_D                               1003
+#define IMG_STEEL_CHAR_E                               1004
+#define IMG_STEEL_CHAR_F                               1005
+#define IMG_STEEL_CHAR_G                               1006
+#define IMG_STEEL_CHAR_H                               1007
+#define IMG_STEEL_CHAR_I                               1008
+#define IMG_STEEL_CHAR_J                               1009
+#define IMG_STEEL_CHAR_K                               1010
+#define IMG_STEEL_CHAR_L                               1011
+#define IMG_STEEL_CHAR_M                               1012
+#define IMG_STEEL_CHAR_N                               1013
+#define IMG_STEEL_CHAR_O                               1014
+#define IMG_STEEL_CHAR_P                               1015
+#define IMG_STEEL_CHAR_Q                               1016
+#define IMG_STEEL_CHAR_R                               1017
+#define IMG_STEEL_CHAR_S                               1018
+#define IMG_STEEL_CHAR_T                               1019
+#define IMG_STEEL_CHAR_U                               1020
+#define IMG_STEEL_CHAR_V                               1021
+#define IMG_STEEL_CHAR_W                               1022
+#define IMG_STEEL_CHAR_X                               1023
+#define IMG_STEEL_CHAR_Y                               1024
+#define IMG_STEEL_CHAR_Z                               1025
+#define IMG_STEEL_CHAR_BRACKETLEFT                     1026
+#define IMG_STEEL_CHAR_BACKSLASH                       1027
+#define IMG_STEEL_CHAR_BRACKETRIGHT                    1028
+#define IMG_STEEL_CHAR_ASCIICIRCUM                     1029
+#define IMG_STEEL_CHAR_UNDERSCORE                      1030
+#define IMG_STEEL_CHAR_COPYRIGHT                       1031
+#define IMG_STEEL_CHAR_AUMLAUT                         1032
+#define IMG_STEEL_CHAR_OUMLAUT                         1033
+#define IMG_STEEL_CHAR_UUMLAUT                         1034
+#define IMG_STEEL_CHAR_DEGREE                          1035
+#define IMG_STEEL_CHAR_TRADEMARK                       1036
+#define IMG_STEEL_CHAR_CURSOR                          1037
+#define IMG_STEEL_CHAR_BUTTON                          1038
+#define IMG_STEEL_CHAR_UP                              1039
+#define IMG_STEEL_CHAR_DOWN                            1040
+#define IMG_CUSTOM_1                                   1041
+#define IMG_CUSTOM_1_EDITOR                            1042
+#define IMG_CUSTOM_2                                   1043
+#define IMG_CUSTOM_2_EDITOR                            1044
+#define IMG_CUSTOM_3                                   1045
+#define IMG_CUSTOM_3_EDITOR                            1046
+#define IMG_CUSTOM_4                                   1047
+#define IMG_CUSTOM_4_EDITOR                            1048
+#define IMG_CUSTOM_5                                   1049
+#define IMG_CUSTOM_5_EDITOR                            1050
+#define IMG_CUSTOM_6                                   1051
+#define IMG_CUSTOM_6_EDITOR                            1052
+#define IMG_CUSTOM_7                                   1053
+#define IMG_CUSTOM_7_EDITOR                            1054
+#define IMG_CUSTOM_8                                   1055
+#define IMG_CUSTOM_8_EDITOR                            1056
+#define IMG_CUSTOM_9                                   1057
+#define IMG_CUSTOM_9_EDITOR                            1058
+#define IMG_CUSTOM_10                                  1059
+#define IMG_CUSTOM_10_EDITOR                           1060
+#define IMG_CUSTOM_11                                  1061
+#define IMG_CUSTOM_11_EDITOR                           1062
+#define IMG_CUSTOM_12                                  1063
+#define IMG_CUSTOM_12_EDITOR                           1064
+#define IMG_CUSTOM_13                                  1065
+#define IMG_CUSTOM_13_EDITOR                           1066
+#define IMG_CUSTOM_14                                  1067
+#define IMG_CUSTOM_14_EDITOR                           1068
+#define IMG_CUSTOM_15                                  1069
+#define IMG_CUSTOM_15_EDITOR                           1070
+#define IMG_CUSTOM_16                                  1071
+#define IMG_CUSTOM_16_EDITOR                           1072
+#define IMG_CUSTOM_17                                  1073
+#define IMG_CUSTOM_17_EDITOR                           1074
+#define IMG_CUSTOM_18                                  1075
+#define IMG_CUSTOM_18_EDITOR                           1076
+#define IMG_CUSTOM_19                                  1077
+#define IMG_CUSTOM_19_EDITOR                           1078
+#define IMG_CUSTOM_20                                  1079
+#define IMG_CUSTOM_20_EDITOR                           1080
+#define IMG_CUSTOM_21                                  1081
+#define IMG_CUSTOM_21_EDITOR                           1082
+#define IMG_CUSTOM_22                                  1083
+#define IMG_CUSTOM_22_EDITOR                           1084
+#define IMG_CUSTOM_23                                  1085
+#define IMG_CUSTOM_23_EDITOR                           1086
+#define IMG_CUSTOM_24                                  1087
+#define IMG_CUSTOM_24_EDITOR                           1088
+#define IMG_CUSTOM_25                                  1089
+#define IMG_CUSTOM_25_EDITOR                           1090
+#define IMG_CUSTOM_26                                  1091
+#define IMG_CUSTOM_26_EDITOR                           1092
+#define IMG_CUSTOM_27                                  1093
+#define IMG_CUSTOM_27_EDITOR                           1094
+#define IMG_CUSTOM_28                                  1095
+#define IMG_CUSTOM_28_EDITOR                           1096
+#define IMG_CUSTOM_29                                  1097
+#define IMG_CUSTOM_29_EDITOR                           1098
+#define IMG_CUSTOM_30                                  1099
+#define IMG_CUSTOM_30_EDITOR                           1100
+#define IMG_CUSTOM_31                                  1101
+#define IMG_CUSTOM_31_EDITOR                           1102
+#define IMG_CUSTOM_32                                  1103
+#define IMG_CUSTOM_32_EDITOR                           1104
+#define IMG_CUSTOM_33                                  1105
+#define IMG_CUSTOM_33_EDITOR                           1106
+#define IMG_CUSTOM_34                                  1107
+#define IMG_CUSTOM_34_EDITOR                           1108
+#define IMG_CUSTOM_35                                  1109
+#define IMG_CUSTOM_35_EDITOR                           1110
+#define IMG_CUSTOM_36                                  1111
+#define IMG_CUSTOM_36_EDITOR                           1112
+#define IMG_CUSTOM_37                                  1113
+#define IMG_CUSTOM_37_EDITOR                           1114
+#define IMG_CUSTOM_38                                  1115
+#define IMG_CUSTOM_38_EDITOR                           1116
+#define IMG_CUSTOM_39                                  1117
+#define IMG_CUSTOM_39_EDITOR                           1118
+#define IMG_CUSTOM_40                                  1119
+#define IMG_CUSTOM_40_EDITOR                           1120
+#define IMG_CUSTOM_41                                  1121
+#define IMG_CUSTOM_41_EDITOR                           1122
+#define IMG_CUSTOM_42                                  1123
+#define IMG_CUSTOM_42_EDITOR                           1124
+#define IMG_CUSTOM_43                                  1125
+#define IMG_CUSTOM_43_EDITOR                           1126
+#define IMG_CUSTOM_44                                  1127
+#define IMG_CUSTOM_44_EDITOR                           1128
+#define IMG_CUSTOM_45                                  1129
+#define IMG_CUSTOM_45_EDITOR                           1130
+#define IMG_CUSTOM_46                                  1131
+#define IMG_CUSTOM_46_EDITOR                           1132
+#define IMG_CUSTOM_47                                  1133
+#define IMG_CUSTOM_47_EDITOR                           1134
+#define IMG_CUSTOM_48                                  1135
+#define IMG_CUSTOM_48_EDITOR                           1136
+#define IMG_CUSTOM_49                                  1137
+#define IMG_CUSTOM_49_EDITOR                           1138
+#define IMG_CUSTOM_50                                  1139
+#define IMG_CUSTOM_50_EDITOR                           1140
+#define IMG_CUSTOM_51                                  1141
+#define IMG_CUSTOM_51_EDITOR                           1142
+#define IMG_CUSTOM_52                                  1143
+#define IMG_CUSTOM_52_EDITOR                           1144
+#define IMG_CUSTOM_53                                  1145
+#define IMG_CUSTOM_53_EDITOR                           1146
+#define IMG_CUSTOM_54                                  1147
+#define IMG_CUSTOM_54_EDITOR                           1148
+#define IMG_CUSTOM_55                                  1149
+#define IMG_CUSTOM_55_EDITOR                           1150
+#define IMG_CUSTOM_56                                  1151
+#define IMG_CUSTOM_56_EDITOR                           1152
+#define IMG_CUSTOM_57                                  1153
+#define IMG_CUSTOM_57_EDITOR                           1154
+#define IMG_CUSTOM_58                                  1155
+#define IMG_CUSTOM_58_EDITOR                           1156
+#define IMG_CUSTOM_59                                  1157
+#define IMG_CUSTOM_59_EDITOR                           1158
+#define IMG_CUSTOM_60                                  1159
+#define IMG_CUSTOM_60_EDITOR                           1160
+#define IMG_CUSTOM_61                                  1161
+#define IMG_CUSTOM_61_EDITOR                           1162
+#define IMG_CUSTOM_62                                  1163
+#define IMG_CUSTOM_62_EDITOR                           1164
+#define IMG_CUSTOM_63                                  1165
+#define IMG_CUSTOM_63_EDITOR                           1166
+#define IMG_CUSTOM_64                                  1167
+#define IMG_CUSTOM_64_EDITOR                           1168
+#define IMG_CUSTOM_65                                  1169
+#define IMG_CUSTOM_65_EDITOR                           1170
+#define IMG_CUSTOM_66                                  1171
+#define IMG_CUSTOM_66_EDITOR                           1172
+#define IMG_CUSTOM_67                                  1173
+#define IMG_CUSTOM_67_EDITOR                           1174
+#define IMG_CUSTOM_68                                  1175
+#define IMG_CUSTOM_68_EDITOR                           1176
+#define IMG_CUSTOM_69                                  1177
+#define IMG_CUSTOM_69_EDITOR                           1178
+#define IMG_CUSTOM_70                                  1179
+#define IMG_CUSTOM_70_EDITOR                           1180
+#define IMG_CUSTOM_71                                  1181
+#define IMG_CUSTOM_71_EDITOR                           1182
+#define IMG_CUSTOM_72                                  1183
+#define IMG_CUSTOM_72_EDITOR                           1184
+#define IMG_CUSTOM_73                                  1185
+#define IMG_CUSTOM_73_EDITOR                           1186
+#define IMG_CUSTOM_74                                  1187
+#define IMG_CUSTOM_74_EDITOR                           1188
+#define IMG_CUSTOM_75                                  1189
+#define IMG_CUSTOM_75_EDITOR                           1190
+#define IMG_CUSTOM_76                                  1191
+#define IMG_CUSTOM_76_EDITOR                           1192
+#define IMG_CUSTOM_77                                  1193
+#define IMG_CUSTOM_77_EDITOR                           1194
+#define IMG_CUSTOM_78                                  1195
+#define IMG_CUSTOM_78_EDITOR                           1196
+#define IMG_CUSTOM_79                                  1197
+#define IMG_CUSTOM_79_EDITOR                           1198
+#define IMG_CUSTOM_80                                  1199
+#define IMG_CUSTOM_80_EDITOR                           1200
+#define IMG_CUSTOM_81                                  1201
+#define IMG_CUSTOM_81_EDITOR                           1202
+#define IMG_CUSTOM_82                                  1203
+#define IMG_CUSTOM_82_EDITOR                           1204
+#define IMG_CUSTOM_83                                  1205
+#define IMG_CUSTOM_83_EDITOR                           1206
+#define IMG_CUSTOM_84                                  1207
+#define IMG_CUSTOM_84_EDITOR                           1208
+#define IMG_CUSTOM_85                                  1209
+#define IMG_CUSTOM_85_EDITOR                           1210
+#define IMG_CUSTOM_86                                  1211
+#define IMG_CUSTOM_86_EDITOR                           1212
+#define IMG_CUSTOM_87                                  1213
+#define IMG_CUSTOM_87_EDITOR                           1214
+#define IMG_CUSTOM_88                                  1215
+#define IMG_CUSTOM_88_EDITOR                           1216
+#define IMG_CUSTOM_89                                  1217
+#define IMG_CUSTOM_89_EDITOR                           1218
+#define IMG_CUSTOM_90                                  1219
+#define IMG_CUSTOM_90_EDITOR                           1220
+#define IMG_CUSTOM_91                                  1221
+#define IMG_CUSTOM_91_EDITOR                           1222
+#define IMG_CUSTOM_92                                  1223
+#define IMG_CUSTOM_92_EDITOR                           1224
+#define IMG_CUSTOM_93                                  1225
+#define IMG_CUSTOM_93_EDITOR                           1226
+#define IMG_CUSTOM_94                                  1227
+#define IMG_CUSTOM_94_EDITOR                           1228
+#define IMG_CUSTOM_95                                  1229
+#define IMG_CUSTOM_95_EDITOR                           1230
+#define IMG_CUSTOM_96                                  1231
+#define IMG_CUSTOM_96_EDITOR                           1232
+#define IMG_CUSTOM_97                                  1233
+#define IMG_CUSTOM_97_EDITOR                           1234
+#define IMG_CUSTOM_98                                  1235
+#define IMG_CUSTOM_98_EDITOR                           1236
+#define IMG_CUSTOM_99                                  1237
+#define IMG_CUSTOM_99_EDITOR                           1238
+#define IMG_CUSTOM_100                                 1239
+#define IMG_CUSTOM_100_EDITOR                          1240
+#define IMG_CUSTOM_101                                 1241
+#define IMG_CUSTOM_101_EDITOR                          1242
+#define IMG_CUSTOM_102                                 1243
+#define IMG_CUSTOM_102_EDITOR                          1244
+#define IMG_CUSTOM_103                                 1245
+#define IMG_CUSTOM_103_EDITOR                          1246
+#define IMG_CUSTOM_104                                 1247
+#define IMG_CUSTOM_104_EDITOR                          1248
+#define IMG_CUSTOM_105                                 1249
+#define IMG_CUSTOM_105_EDITOR                          1250
+#define IMG_CUSTOM_106                                 1251
+#define IMG_CUSTOM_106_EDITOR                          1252
+#define IMG_CUSTOM_107                                 1253
+#define IMG_CUSTOM_107_EDITOR                          1254
+#define IMG_CUSTOM_108                                 1255
+#define IMG_CUSTOM_108_EDITOR                          1256
+#define IMG_CUSTOM_109                                 1257
+#define IMG_CUSTOM_109_EDITOR                          1258
+#define IMG_CUSTOM_110                                 1259
+#define IMG_CUSTOM_110_EDITOR                          1260
+#define IMG_CUSTOM_111                                 1261
+#define IMG_CUSTOM_111_EDITOR                          1262
+#define IMG_CUSTOM_112                                 1263
+#define IMG_CUSTOM_112_EDITOR                          1264
+#define IMG_CUSTOM_113                                 1265
+#define IMG_CUSTOM_113_EDITOR                          1266
+#define IMG_CUSTOM_114                                 1267
+#define IMG_CUSTOM_114_EDITOR                          1268
+#define IMG_CUSTOM_115                                 1269
+#define IMG_CUSTOM_115_EDITOR                          1270
+#define IMG_CUSTOM_116                                 1271
+#define IMG_CUSTOM_116_EDITOR                          1272
+#define IMG_CUSTOM_117                                 1273
+#define IMG_CUSTOM_117_EDITOR                          1274
+#define IMG_CUSTOM_118                                 1275
+#define IMG_CUSTOM_118_EDITOR                          1276
+#define IMG_CUSTOM_119                                 1277
+#define IMG_CUSTOM_119_EDITOR                          1278
+#define IMG_CUSTOM_120                                 1279
+#define IMG_CUSTOM_120_EDITOR                          1280
+#define IMG_CUSTOM_121                                 1281
+#define IMG_CUSTOM_121_EDITOR                          1282
+#define IMG_CUSTOM_122                                 1283
+#define IMG_CUSTOM_122_EDITOR                          1284
+#define IMG_CUSTOM_123                                 1285
+#define IMG_CUSTOM_123_EDITOR                          1286
+#define IMG_CUSTOM_124                                 1287
+#define IMG_CUSTOM_124_EDITOR                          1288
+#define IMG_CUSTOM_125                                 1289
+#define IMG_CUSTOM_125_EDITOR                          1290
+#define IMG_CUSTOM_126                                 1291
+#define IMG_CUSTOM_126_EDITOR                          1292
+#define IMG_CUSTOM_127                                 1293
+#define IMG_CUSTOM_127_EDITOR                          1294
+#define IMG_CUSTOM_128                                 1295
+#define IMG_CUSTOM_128_EDITOR                          1296
+#define IMG_CUSTOM_129                                 1297
+#define IMG_CUSTOM_129_EDITOR                          1298
+#define IMG_CUSTOM_130                                 1299
+#define IMG_CUSTOM_130_EDITOR                          1300
+#define IMG_CUSTOM_131                                 1301
+#define IMG_CUSTOM_131_EDITOR                          1302
+#define IMG_CUSTOM_132                                 1303
+#define IMG_CUSTOM_132_EDITOR                          1304
+#define IMG_CUSTOM_133                                 1305
+#define IMG_CUSTOM_133_EDITOR                          1306
+#define IMG_CUSTOM_134                                 1307
+#define IMG_CUSTOM_134_EDITOR                          1308
+#define IMG_CUSTOM_135                                 1309
+#define IMG_CUSTOM_135_EDITOR                          1310
+#define IMG_CUSTOM_136                                 1311
+#define IMG_CUSTOM_136_EDITOR                          1312
+#define IMG_CUSTOM_137                                 1313
+#define IMG_CUSTOM_137_EDITOR                          1314
+#define IMG_CUSTOM_138                                 1315
+#define IMG_CUSTOM_138_EDITOR                          1316
+#define IMG_CUSTOM_139                                 1317
+#define IMG_CUSTOM_139_EDITOR                          1318
+#define IMG_CUSTOM_140                                 1319
+#define IMG_CUSTOM_140_EDITOR                          1320
+#define IMG_CUSTOM_141                                 1321
+#define IMG_CUSTOM_141_EDITOR                          1322
+#define IMG_CUSTOM_142                                 1323
+#define IMG_CUSTOM_142_EDITOR                          1324
+#define IMG_CUSTOM_143                                 1325
+#define IMG_CUSTOM_143_EDITOR                          1326
+#define IMG_CUSTOM_144                                 1327
+#define IMG_CUSTOM_144_EDITOR                          1328
+#define IMG_CUSTOM_145                                 1329
+#define IMG_CUSTOM_145_EDITOR                          1330
+#define IMG_CUSTOM_146                                 1331
+#define IMG_CUSTOM_146_EDITOR                          1332
+#define IMG_CUSTOM_147                                 1333
+#define IMG_CUSTOM_147_EDITOR                          1334
+#define IMG_CUSTOM_148                                 1335
+#define IMG_CUSTOM_148_EDITOR                          1336
+#define IMG_CUSTOM_149                                 1337
+#define IMG_CUSTOM_149_EDITOR                          1338
+#define IMG_CUSTOM_150                                 1339
+#define IMG_CUSTOM_150_EDITOR                          1340
+#define IMG_CUSTOM_151                                 1341
+#define IMG_CUSTOM_151_EDITOR                          1342
+#define IMG_CUSTOM_152                                 1343
+#define IMG_CUSTOM_152_EDITOR                          1344
+#define IMG_CUSTOM_153                                 1345
+#define IMG_CUSTOM_153_EDITOR                          1346
+#define IMG_CUSTOM_154                                 1347
+#define IMG_CUSTOM_154_EDITOR                          1348
+#define IMG_CUSTOM_155                                 1349
+#define IMG_CUSTOM_155_EDITOR                          1350
+#define IMG_CUSTOM_156                                 1351
+#define IMG_CUSTOM_156_EDITOR                          1352
+#define IMG_CUSTOM_157                                 1353
+#define IMG_CUSTOM_157_EDITOR                          1354
+#define IMG_CUSTOM_158                                 1355
+#define IMG_CUSTOM_158_EDITOR                          1356
+#define IMG_CUSTOM_159                                 1357
+#define IMG_CUSTOM_159_EDITOR                          1358
+#define IMG_CUSTOM_160                                 1359
+#define IMG_CUSTOM_160_EDITOR                          1360
+#define IMG_CUSTOM_161                                 1361
+#define IMG_CUSTOM_161_EDITOR                          1362
+#define IMG_CUSTOM_162                                 1363
+#define IMG_CUSTOM_162_EDITOR                          1364
+#define IMG_CUSTOM_163                                 1365
+#define IMG_CUSTOM_163_EDITOR                          1366
+#define IMG_CUSTOM_164                                 1367
+#define IMG_CUSTOM_164_EDITOR                          1368
+#define IMG_CUSTOM_165                                 1369
+#define IMG_CUSTOM_165_EDITOR                          1370
+#define IMG_CUSTOM_166                                 1371
+#define IMG_CUSTOM_166_EDITOR                          1372
+#define IMG_CUSTOM_167                                 1373
+#define IMG_CUSTOM_167_EDITOR                          1374
+#define IMG_CUSTOM_168                                 1375
+#define IMG_CUSTOM_168_EDITOR                          1376
+#define IMG_CUSTOM_169                                 1377
+#define IMG_CUSTOM_169_EDITOR                          1378
+#define IMG_CUSTOM_170                                 1379
+#define IMG_CUSTOM_170_EDITOR                          1380
+#define IMG_CUSTOM_171                                 1381
+#define IMG_CUSTOM_171_EDITOR                          1382
+#define IMG_CUSTOM_172                                 1383
+#define IMG_CUSTOM_172_EDITOR                          1384
+#define IMG_CUSTOM_173                                 1385
+#define IMG_CUSTOM_173_EDITOR                          1386
+#define IMG_CUSTOM_174                                 1387
+#define IMG_CUSTOM_174_EDITOR                          1388
+#define IMG_CUSTOM_175                                 1389
+#define IMG_CUSTOM_175_EDITOR                          1390
+#define IMG_CUSTOM_176                                 1391
+#define IMG_CUSTOM_176_EDITOR                          1392
+#define IMG_CUSTOM_177                                 1393
+#define IMG_CUSTOM_177_EDITOR                          1394
+#define IMG_CUSTOM_178                                 1395
+#define IMG_CUSTOM_178_EDITOR                          1396
+#define IMG_CUSTOM_179                                 1397
+#define IMG_CUSTOM_179_EDITOR                          1398
+#define IMG_CUSTOM_180                                 1399
+#define IMG_CUSTOM_180_EDITOR                          1400
+#define IMG_CUSTOM_181                                 1401
+#define IMG_CUSTOM_181_EDITOR                          1402
+#define IMG_CUSTOM_182                                 1403
+#define IMG_CUSTOM_182_EDITOR                          1404
+#define IMG_CUSTOM_183                                 1405
+#define IMG_CUSTOM_183_EDITOR                          1406
+#define IMG_CUSTOM_184                                 1407
+#define IMG_CUSTOM_184_EDITOR                          1408
+#define IMG_CUSTOM_185                                 1409
+#define IMG_CUSTOM_185_EDITOR                          1410
+#define IMG_CUSTOM_186                                 1411
+#define IMG_CUSTOM_186_EDITOR                          1412
+#define IMG_CUSTOM_187                                 1413
+#define IMG_CUSTOM_187_EDITOR                          1414
+#define IMG_CUSTOM_188                                 1415
+#define IMG_CUSTOM_188_EDITOR                          1416
+#define IMG_CUSTOM_189                                 1417
+#define IMG_CUSTOM_189_EDITOR                          1418
+#define IMG_CUSTOM_190                                 1419
+#define IMG_CUSTOM_190_EDITOR                          1420
+#define IMG_CUSTOM_191                                 1421
+#define IMG_CUSTOM_191_EDITOR                          1422
+#define IMG_CUSTOM_192                                 1423
+#define IMG_CUSTOM_192_EDITOR                          1424
+#define IMG_CUSTOM_193                                 1425
+#define IMG_CUSTOM_193_EDITOR                          1426
+#define IMG_CUSTOM_194                                 1427
+#define IMG_CUSTOM_194_EDITOR                          1428
+#define IMG_CUSTOM_195                                 1429
+#define IMG_CUSTOM_195_EDITOR                          1430
+#define IMG_CUSTOM_196                                 1431
+#define IMG_CUSTOM_196_EDITOR                          1432
+#define IMG_CUSTOM_197                                 1433
+#define IMG_CUSTOM_197_EDITOR                          1434
+#define IMG_CUSTOM_198                                 1435
+#define IMG_CUSTOM_198_EDITOR                          1436
+#define IMG_CUSTOM_199                                 1437
+#define IMG_CUSTOM_199_EDITOR                          1438
+#define IMG_CUSTOM_200                                 1439
+#define IMG_CUSTOM_200_EDITOR                          1440
+#define IMG_CUSTOM_201                                 1441
+#define IMG_CUSTOM_201_EDITOR                          1442
+#define IMG_CUSTOM_202                                 1443
+#define IMG_CUSTOM_202_EDITOR                          1444
+#define IMG_CUSTOM_203                                 1445
+#define IMG_CUSTOM_203_EDITOR                          1446
+#define IMG_CUSTOM_204                                 1447
+#define IMG_CUSTOM_204_EDITOR                          1448
+#define IMG_CUSTOM_205                                 1449
+#define IMG_CUSTOM_205_EDITOR                          1450
+#define IMG_CUSTOM_206                                 1451
+#define IMG_CUSTOM_206_EDITOR                          1452
+#define IMG_CUSTOM_207                                 1453
+#define IMG_CUSTOM_207_EDITOR                          1454
+#define IMG_CUSTOM_208                                 1455
+#define IMG_CUSTOM_208_EDITOR                          1456
+#define IMG_CUSTOM_209                                 1457
+#define IMG_CUSTOM_209_EDITOR                          1458
+#define IMG_CUSTOM_210                                 1459
+#define IMG_CUSTOM_210_EDITOR                          1460
+#define IMG_CUSTOM_211                                 1461
+#define IMG_CUSTOM_211_EDITOR                          1462
+#define IMG_CUSTOM_212                                 1463
+#define IMG_CUSTOM_212_EDITOR                          1464
+#define IMG_CUSTOM_213                                 1465
+#define IMG_CUSTOM_213_EDITOR                          1466
+#define IMG_CUSTOM_214                                 1467
+#define IMG_CUSTOM_214_EDITOR                          1468
+#define IMG_CUSTOM_215                                 1469
+#define IMG_CUSTOM_215_EDITOR                          1470
+#define IMG_CUSTOM_216                                 1471
+#define IMG_CUSTOM_216_EDITOR                          1472
+#define IMG_CUSTOM_217                                 1473
+#define IMG_CUSTOM_217_EDITOR                          1474
+#define IMG_CUSTOM_218                                 1475
+#define IMG_CUSTOM_218_EDITOR                          1476
+#define IMG_CUSTOM_219                                 1477
+#define IMG_CUSTOM_219_EDITOR                          1478
+#define IMG_CUSTOM_220                                 1479
+#define IMG_CUSTOM_220_EDITOR                          1480
+#define IMG_CUSTOM_221                                 1481
+#define IMG_CUSTOM_221_EDITOR                          1482
+#define IMG_CUSTOM_222                                 1483
+#define IMG_CUSTOM_222_EDITOR                          1484
+#define IMG_CUSTOM_223                                 1485
+#define IMG_CUSTOM_223_EDITOR                          1486
+#define IMG_CUSTOM_224                                 1487
+#define IMG_CUSTOM_224_EDITOR                          1488
+#define IMG_CUSTOM_225                                 1489
+#define IMG_CUSTOM_225_EDITOR                          1490
+#define IMG_CUSTOM_226                                 1491
+#define IMG_CUSTOM_226_EDITOR                          1492
+#define IMG_CUSTOM_227                                 1493
+#define IMG_CUSTOM_227_EDITOR                          1494
+#define IMG_CUSTOM_228                                 1495
+#define IMG_CUSTOM_228_EDITOR                          1496
+#define IMG_CUSTOM_229                                 1497
+#define IMG_CUSTOM_229_EDITOR                          1498
+#define IMG_CUSTOM_230                                 1499
+#define IMG_CUSTOM_230_EDITOR                          1500
+#define IMG_CUSTOM_231                                 1501
+#define IMG_CUSTOM_231_EDITOR                          1502
+#define IMG_CUSTOM_232                                 1503
+#define IMG_CUSTOM_232_EDITOR                          1504
+#define IMG_CUSTOM_233                                 1505
+#define IMG_CUSTOM_233_EDITOR                          1506
+#define IMG_CUSTOM_234                                 1507
+#define IMG_CUSTOM_234_EDITOR                          1508
+#define IMG_CUSTOM_235                                 1509
+#define IMG_CUSTOM_235_EDITOR                          1510
+#define IMG_CUSTOM_236                                 1511
+#define IMG_CUSTOM_236_EDITOR                          1512
+#define IMG_CUSTOM_237                                 1513
+#define IMG_CUSTOM_237_EDITOR                          1514
+#define IMG_CUSTOM_238                                 1515
+#define IMG_CUSTOM_238_EDITOR                          1516
+#define IMG_CUSTOM_239                                 1517
+#define IMG_CUSTOM_239_EDITOR                          1518
+#define IMG_CUSTOM_240                                 1519
+#define IMG_CUSTOM_240_EDITOR                          1520
+#define IMG_CUSTOM_241                                 1521
+#define IMG_CUSTOM_241_EDITOR                          1522
+#define IMG_CUSTOM_242                                 1523
+#define IMG_CUSTOM_242_EDITOR                          1524
+#define IMG_CUSTOM_243                                 1525
+#define IMG_CUSTOM_243_EDITOR                          1526
+#define IMG_CUSTOM_244                                 1527
+#define IMG_CUSTOM_244_EDITOR                          1528
+#define IMG_CUSTOM_245                                 1529
+#define IMG_CUSTOM_245_EDITOR                          1530
+#define IMG_CUSTOM_246                                 1531
+#define IMG_CUSTOM_246_EDITOR                          1532
+#define IMG_CUSTOM_247                                 1533
+#define IMG_CUSTOM_247_EDITOR                          1534
+#define IMG_CUSTOM_248                                 1535
+#define IMG_CUSTOM_248_EDITOR                          1536
+#define IMG_CUSTOM_249                                 1537
+#define IMG_CUSTOM_249_EDITOR                          1538
+#define IMG_CUSTOM_250                                 1539
+#define IMG_CUSTOM_250_EDITOR                          1540
+#define IMG_CUSTOM_251                                 1541
+#define IMG_CUSTOM_251_EDITOR                          1542
+#define IMG_CUSTOM_252                                 1543
+#define IMG_CUSTOM_252_EDITOR                          1544
+#define IMG_CUSTOM_253                                 1545
+#define IMG_CUSTOM_253_EDITOR                          1546
+#define IMG_CUSTOM_254                                 1547
+#define IMG_CUSTOM_254_EDITOR                          1548
+#define IMG_CUSTOM_255                                 1549
+#define IMG_CUSTOM_255_EDITOR                          1550
+#define IMG_CUSTOM_256                                 1551
+#define IMG_CUSTOM_256_EDITOR                          1552
+#define IMG_GROUP_1                                    1553
+#define IMG_GROUP_1_EDITOR                             1554
+#define IMG_GROUP_2                                    1555
+#define IMG_GROUP_2_EDITOR                             1556
+#define IMG_GROUP_3                                    1557
+#define IMG_GROUP_3_EDITOR                             1558
+#define IMG_GROUP_4                                    1559
+#define IMG_GROUP_4_EDITOR                             1560
+#define IMG_GROUP_5                                    1561
+#define IMG_GROUP_5_EDITOR                             1562
+#define IMG_GROUP_6                                    1563
+#define IMG_GROUP_6_EDITOR                             1564
+#define IMG_GROUP_7                                    1565
+#define IMG_GROUP_7_EDITOR                             1566
+#define IMG_GROUP_8                                    1567
+#define IMG_GROUP_8_EDITOR                             1568
+#define IMG_GROUP_9                                    1569
+#define IMG_GROUP_9_EDITOR                             1570
+#define IMG_GROUP_10                                   1571
+#define IMG_GROUP_10_EDITOR                            1572
+#define IMG_GROUP_11                                   1573
+#define IMG_GROUP_11_EDITOR                            1574
+#define IMG_GROUP_12                                   1575
+#define IMG_GROUP_12_EDITOR                            1576
+#define IMG_GROUP_13                                   1577
+#define IMG_GROUP_13_EDITOR                            1578
+#define IMG_GROUP_14                                   1579
+#define IMG_GROUP_14_EDITOR                            1580
+#define IMG_GROUP_15                                   1581
+#define IMG_GROUP_15_EDITOR                            1582
+#define IMG_GROUP_16                                   1583
+#define IMG_GROUP_16_EDITOR                            1584
+#define IMG_GROUP_17                                   1585
+#define IMG_GROUP_17_EDITOR                            1586
+#define IMG_GROUP_18                                   1587
+#define IMG_GROUP_18_EDITOR                            1588
+#define IMG_GROUP_19                                   1589
+#define IMG_GROUP_19_EDITOR                            1590
+#define IMG_GROUP_20                                   1591
+#define IMG_GROUP_20_EDITOR                            1592
+#define IMG_GROUP_21                                   1593
+#define IMG_GROUP_21_EDITOR                            1594
+#define IMG_GROUP_22                                   1595
+#define IMG_GROUP_22_EDITOR                            1596
+#define IMG_GROUP_23                                   1597
+#define IMG_GROUP_23_EDITOR                            1598
+#define IMG_GROUP_24                                   1599
+#define IMG_GROUP_24_EDITOR                            1600
+#define IMG_GROUP_25                                   1601
+#define IMG_GROUP_25_EDITOR                            1602
+#define IMG_GROUP_26                                   1603
+#define IMG_GROUP_26_EDITOR                            1604
+#define IMG_GROUP_27                                   1605
+#define IMG_GROUP_27_EDITOR                            1606
+#define IMG_GROUP_28                                   1607
+#define IMG_GROUP_28_EDITOR                            1608
+#define IMG_GROUP_29                                   1609
+#define IMG_GROUP_29_EDITOR                            1610
+#define IMG_GROUP_30                                   1611
+#define IMG_GROUP_30_EDITOR                            1612
+#define IMG_GROUP_31                                   1613
+#define IMG_GROUP_31_EDITOR                            1614
+#define IMG_GROUP_32                                   1615
+#define IMG_GROUP_32_EDITOR                            1616
+#define IMG_EMC_OBJECT                                 1617
+#define IMG_EMC_SPRITE                                 1618
+#define IMG_SP_FRAME_HORIZONTAL                                1619
+#define IMG_SP_FRAME_VERTICAL                          1620
+#define IMG_SP_FRAME_CORNER                            1621
+#define IMG_TOON_1                                     1622
+#define IMG_TOON_2                                     1623
+#define IMG_TOON_3                                     1624
+#define IMG_TOON_4                                     1625
+#define IMG_TOON_5                                     1626
+#define IMG_TOON_6                                     1627
+#define IMG_TOON_7                                     1628
+#define IMG_TOON_8                                     1629
+#define IMG_TOON_9                                     1630
+#define IMG_TOON_10                                    1631
+#define IMG_TOON_11                                    1632
+#define IMG_TOON_12                                    1633
+#define IMG_TOON_13                                    1634
+#define IMG_TOON_14                                    1635
+#define IMG_TOON_15                                    1636
+#define IMG_TOON_16                                    1637
+#define IMG_TOON_17                                    1638
+#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 NUM_IMAGE_FILES                                        1793
+#define NUM_IMAGE_FILES                                        1800
 
 #endif /* CONF_GFX_H */
index f0993e6e4832d8c337af80dcc8b067dcb2f36ffe..e12f0015938b77fd769bb1a0c30248caab987ee6 100644 (file)
@@ -1288,6 +1288,14 @@ struct TokenIntPtrInfo image_config_vars[] =
     "menu.draw_yoffset.SETUP[INPUT]",
     &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_INPUT]
   },
+  {
+    "menu.draw_xoffset.SETUP[SHORTCUTS]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS]
+  },
+  {
+    "menu.draw_yoffset.SETUP[SHORTCUTS]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS]
+  },
   {
     "menu.draw_xoffset.SETUP[SHORTCUTS_1]",
     &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_1]
@@ -1304,6 +1312,22 @@ struct TokenIntPtrInfo image_config_vars[] =
     "menu.draw_yoffset.SETUP[SHORTCUTS_2]",
     &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_2]
   },
+  {
+    "menu.draw_xoffset.SETUP[SHORTCUTS_3]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_3]
+  },
+  {
+    "menu.draw_yoffset.SETUP[SHORTCUTS_3]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_3]
+  },
+  {
+    "menu.draw_xoffset.SETUP[SHORTCUTS_4]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_4]
+  },
+  {
+    "menu.draw_yoffset.SETUP[SHORTCUTS_4]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_4]
+  },
   {
     "menu.draw_xoffset.SETUP[CHOOSE_ARTWORK]",
     &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_CHOOSE_ARTWORK]
@@ -2912,6 +2936,38 @@ struct TokenIntPtrInfo image_config_vars[] =
     "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
@@ -5012,6 +5068,14 @@ struct TokenIntPtrInfo image_config_vars[] =
     "game.use_native_emc_graphics_engine",
     &game.use_native_emc_graphics_engine
   },
+  {
+    "game.use_native_sp_graphics_engine",
+    &game.use_native_sp_graphics_engine
+  },
+  {
+    "game.use_masked_pushing",
+    &game.use_masked_pushing
+  },
   {
     "[player].boring_delay_fixed",
     &game.player_boring_delay_fixed
@@ -5028,6 +5092,158 @@ struct TokenIntPtrInfo image_config_vars[] =
     "[player].sleeping_delay_random",
     &game.player_sleeping_delay_random
   },
+  {
+    "viewport.window.width",
+    &viewport.window.width
+  },
+  {
+    "viewport.window.height",
+    &viewport.window.height
+  },
+  {
+    "viewport.playfield.x",
+    &viewport.playfield[GFX_SPECIAL_ARG_DEFAULT].x
+  },
+  {
+    "viewport.playfield.y",
+    &viewport.playfield[GFX_SPECIAL_ARG_DEFAULT].y
+  },
+  {
+    "viewport.playfield.width",
+    &viewport.playfield[GFX_SPECIAL_ARG_DEFAULT].width
+  },
+  {
+    "viewport.playfield.height",
+    &viewport.playfield[GFX_SPECIAL_ARG_DEFAULT].height
+  },
+  {
+    "viewport.playfield.border_size",
+    &viewport.playfield[GFX_SPECIAL_ARG_DEFAULT].border_size
+  },
+  {
+    "viewport.playfield.MAIN.x",
+    &viewport.playfield[GFX_SPECIAL_ARG_MAIN].x
+  },
+  {
+    "viewport.playfield.MAIN.y",
+    &viewport.playfield[GFX_SPECIAL_ARG_MAIN].y
+  },
+  {
+    "viewport.playfield.MAIN.width",
+    &viewport.playfield[GFX_SPECIAL_ARG_MAIN].width
+  },
+  {
+    "viewport.playfield.MAIN.height",
+    &viewport.playfield[GFX_SPECIAL_ARG_MAIN].height
+  },
+  {
+    "viewport.playfield.MAIN.border_size",
+    &viewport.playfield[GFX_SPECIAL_ARG_MAIN].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.playfield.EDITOR.x",
+    &viewport.playfield[GFX_SPECIAL_ARG_EDITOR].x
+  },
+  {
+    "viewport.playfield.EDITOR.y",
+    &viewport.playfield[GFX_SPECIAL_ARG_EDITOR].y
+  },
+  {
+    "viewport.playfield.EDITOR.width",
+    &viewport.playfield[GFX_SPECIAL_ARG_EDITOR].width
+  },
+  {
+    "viewport.playfield.EDITOR.height",
+    &viewport.playfield[GFX_SPECIAL_ARG_EDITOR].height
+  },
+  {
+    "viewport.playfield.EDITOR.border_size",
+    &viewport.playfield[GFX_SPECIAL_ARG_EDITOR].border_size
+  },
+  {
+    "viewport.door_1.x",
+    &viewport.door_1[GFX_SPECIAL_ARG_DEFAULT].x
+  },
+  {
+    "viewport.door_1.y",
+    &viewport.door_1[GFX_SPECIAL_ARG_DEFAULT].y
+  },
+  {
+    "viewport.door_1.MAIN.x",
+    &viewport.door_1[GFX_SPECIAL_ARG_MAIN].x
+  },
+  {
+    "viewport.door_1.MAIN.y",
+    &viewport.door_1[GFX_SPECIAL_ARG_MAIN].y
+  },
+  {
+    "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.EDITOR.x",
+    &viewport.door_1[GFX_SPECIAL_ARG_EDITOR].x
+  },
+  {
+    "viewport.door_1.EDITOR.y",
+    &viewport.door_1[GFX_SPECIAL_ARG_EDITOR].y
+  },
+  {
+    "viewport.door_2.x",
+    &viewport.door_2[GFX_SPECIAL_ARG_DEFAULT].x
+  },
+  {
+    "viewport.door_2.y",
+    &viewport.door_2[GFX_SPECIAL_ARG_DEFAULT].y
+  },
+  {
+    "viewport.door_2.MAIN.x",
+    &viewport.door_2[GFX_SPECIAL_ARG_MAIN].x
+  },
+  {
+    "viewport.door_2.MAIN.y",
+    &viewport.door_2[GFX_SPECIAL_ARG_MAIN].y
+  },
+  {
+    "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.EDITOR.x",
+    &viewport.door_2[GFX_SPECIAL_ARG_EDITOR].x
+  },
+  {
+    "viewport.door_2.EDITOR.y",
+    &viewport.door_2[GFX_SPECIAL_ARG_EDITOR].y
+  },
   {
     NULL,
     NULL
index e3b6bfc91f60b860a302f5b0a28817ac1e4121da..9be483641a98f8003cf4eeb794120cf35957acae 100644 (file)
@@ -1 +1 @@
-#define COMPILE_DATE_STRING "2009-06-15 22:46"
+#define COMPILE_DATE_STRING "2010-05-25 22:42"
index 5fb4dd93b4444f26017086e13c78fbcd145dee6c..5752d7420e34397251e9c344aea87e536efd70a8 100644 (file)
 #define GADGET_ID_RANDOM_BALL_CONTENT  (GADGET_ID_CHECKBUTTON_FIRST + 8)
 #define GADGET_ID_INITIAL_BALL_STATE   (GADGET_ID_CHECKBUTTON_FIRST + 9)
 #define GADGET_ID_GROW_INTO_DIGGABLE   (GADGET_ID_CHECKBUTTON_FIRST + 10)
-#define GADGET_ID_CONTINUOUS_SNAPPING  (GADGET_ID_CHECKBUTTON_FIRST + 11)
-#define GADGET_ID_BLOCK_SNAP_FIELD     (GADGET_ID_CHECKBUTTON_FIRST + 12)
-#define GADGET_ID_BLOCK_LAST_FIELD     (GADGET_ID_CHECKBUTTON_FIRST + 13)
-#define GADGET_ID_SP_BLOCK_LAST_FIELD  (GADGET_ID_CHECKBUTTON_FIRST + 14)
-#define GADGET_ID_INSTANT_RELOCATION   (GADGET_ID_CHECKBUTTON_FIRST + 15)
-#define GADGET_ID_SHIFTED_RELOCATION   (GADGET_ID_CHECKBUTTON_FIRST + 16)
-#define GADGET_ID_USE_START_ELEMENT    (GADGET_ID_CHECKBUTTON_FIRST + 17)
-#define GADGET_ID_USE_ARTWORK_ELEMENT  (GADGET_ID_CHECKBUTTON_FIRST + 18)
-#define GADGET_ID_USE_EXPLOSION_ELEMENT        (GADGET_ID_CHECKBUTTON_FIRST + 19)
-#define GADGET_ID_INITIAL_GRAVITY      (GADGET_ID_CHECKBUTTON_FIRST + 20)
-#define GADGET_ID_USE_INITIAL_INVENTORY        (GADGET_ID_CHECKBUTTON_FIRST + 21)
-#define GADGET_ID_CAN_PASS_TO_WALKABLE (GADGET_ID_CHECKBUTTON_FIRST + 22)
-#define GADGET_ID_CAN_FALL_INTO_ACID   (GADGET_ID_CHECKBUTTON_FIRST + 23)
-#define GADGET_ID_CAN_MOVE_INTO_ACID   (GADGET_ID_CHECKBUTTON_FIRST + 24)
-#define GADGET_ID_DONT_COLLIDE_WITH    (GADGET_ID_CHECKBUTTON_FIRST + 25)
-#define GADGET_ID_ENVELOPE_AUTOWRAP    (GADGET_ID_CHECKBUTTON_FIRST + 26)
-#define GADGET_ID_ENVELOPE_CENTERED    (GADGET_ID_CHECKBUTTON_FIRST + 27)
-#define GADGET_ID_CUSTOM_INDESTRUCTIBLE        (GADGET_ID_CHECKBUTTON_FIRST + 28)
-#define GADGET_ID_CUSTOM_CAN_EXPLODE   (GADGET_ID_CHECKBUTTON_FIRST + 29)
-#define GADGET_ID_CUSTOM_EXPLODE_FIRE  (GADGET_ID_CHECKBUTTON_FIRST + 30)
-#define GADGET_ID_CUSTOM_EXPLODE_SMASH (GADGET_ID_CHECKBUTTON_FIRST + 31)
-#define GADGET_ID_CUSTOM_EXPLODE_IMPACT        (GADGET_ID_CHECKBUTTON_FIRST + 32)
-#define GADGET_ID_CUSTOM_WALK_TO_OBJECT        (GADGET_ID_CHECKBUTTON_FIRST + 33)
-#define GADGET_ID_CUSTOM_DEADLY                (GADGET_ID_CHECKBUTTON_FIRST + 34)
-#define GADGET_ID_CUSTOM_CAN_MOVE      (GADGET_ID_CHECKBUTTON_FIRST + 35)
-#define GADGET_ID_CUSTOM_CAN_FALL      (GADGET_ID_CHECKBUTTON_FIRST + 36)
-#define GADGET_ID_CUSTOM_CAN_SMASH     (GADGET_ID_CHECKBUTTON_FIRST + 37)
-#define GADGET_ID_CUSTOM_SLIPPERY      (GADGET_ID_CHECKBUTTON_FIRST + 38)
-#define GADGET_ID_CUSTOM_ACCESSIBLE    (GADGET_ID_CHECKBUTTON_FIRST + 39)
-#define GADGET_ID_CUSTOM_GRAV_REACHABLE        (GADGET_ID_CHECKBUTTON_FIRST + 40)
-#define GADGET_ID_CUSTOM_USE_LAST_VALUE        (GADGET_ID_CHECKBUTTON_FIRST + 41)
-#define GADGET_ID_CUSTOM_USE_GRAPHIC   (GADGET_ID_CHECKBUTTON_FIRST + 42)
-#define GADGET_ID_CUSTOM_USE_TEMPLATE  (GADGET_ID_CHECKBUTTON_FIRST + 43)
-#define GADGET_ID_CUSTOM_CAN_CHANGE    (GADGET_ID_CHECKBUTTON_FIRST + 44)
-#define GADGET_ID_CHANGE_USE_CONTENT   (GADGET_ID_CHECKBUTTON_FIRST + 45)
-#define GADGET_ID_CHANGE_USE_EXPLOSION (GADGET_ID_CHECKBUTTON_FIRST + 46)
-#define GADGET_ID_CHANGE_ONLY_COMPLETE (GADGET_ID_CHECKBUTTON_FIRST + 47)
-#define GADGET_ID_CHANGE_USE_RANDOM    (GADGET_ID_CHECKBUTTON_FIRST + 48)
-#define GADGET_ID_CHANGE_HAS_ACTION    (GADGET_ID_CHECKBUTTON_FIRST + 49)
-#define GADGET_ID_CHANGE_DELAY         (GADGET_ID_CHECKBUTTON_FIRST + 50)
-#define GADGET_ID_CHANGE_BY_DIRECT_ACT (GADGET_ID_CHECKBUTTON_FIRST + 51)
-#define GADGET_ID_CHANGE_BY_OTHER_ACT  (GADGET_ID_CHECKBUTTON_FIRST + 52)
+#define GADGET_ID_AUTO_EXIT_SOKOBAN    (GADGET_ID_CHECKBUTTON_FIRST + 11)
+#define GADGET_ID_CONTINUOUS_SNAPPING  (GADGET_ID_CHECKBUTTON_FIRST + 12)
+#define GADGET_ID_BLOCK_SNAP_FIELD     (GADGET_ID_CHECKBUTTON_FIRST + 13)
+#define GADGET_ID_BLOCK_LAST_FIELD     (GADGET_ID_CHECKBUTTON_FIRST + 14)
+#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)
 
 /* gadgets for buttons in element list */
-#define GADGET_ID_ELEMENTLIST_FIRST    (GADGET_ID_CHECKBUTTON_FIRST + 53)
+#define GADGET_ID_ELEMENTLIST_FIRST    (GADGET_ID_CHECKBUTTON_FIRST + 54)
 #define GADGET_ID_ELEMENTLIST_LAST     (GADGET_ID_ELEMENTLIST_FIRST +  \
                                        ED_NUM_ELEMENTLIST_BUTTONS - 1)
 
 #define ED_CHECKBUTTON_ID_RANDOM_BALL_CONTENT  6
 #define ED_CHECKBUTTON_ID_INITIAL_BALL_STATE   7
 #define ED_CHECKBUTTON_ID_GROW_INTO_DIGGABLE   8
-#define ED_CHECKBUTTON_ID_CONTINUOUS_SNAPPING  9
-#define ED_CHECKBUTTON_ID_BLOCK_SNAP_FIELD     10
-#define ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD     11
-#define ED_CHECKBUTTON_ID_SP_BLOCK_LAST_FIELD  12
-#define ED_CHECKBUTTON_ID_INSTANT_RELOCATION   13
-#define ED_CHECKBUTTON_ID_SHIFTED_RELOCATION   14
-#define ED_CHECKBUTTON_ID_USE_START_ELEMENT    15
-#define ED_CHECKBUTTON_ID_USE_ARTWORK_ELEMENT  16
-#define ED_CHECKBUTTON_ID_USE_EXPLOSION_ELEMENT        17
-#define ED_CHECKBUTTON_ID_INITIAL_GRAVITY      18
-#define ED_CHECKBUTTON_ID_USE_INITIAL_INVENTORY        19
-#define ED_CHECKBUTTON_ID_CAN_PASS_TO_WALKABLE 20
-#define ED_CHECKBUTTON_ID_CAN_FALL_INTO_ACID   21
-#define ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID   22
-#define ED_CHECKBUTTON_ID_DONT_COLLIDE_WITH    23
-#define ED_CHECKBUTTON_ID_ENVELOPE_AUTOWRAP    24
-#define ED_CHECKBUTTON_ID_ENVELOPE_CENTERED    25
-#define ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC   26
-#define ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE  27
-#define ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE    28
-#define ED_CHECKBUTTON_ID_CUSTOM_GRAV_REACHABLE        29
-#define ED_CHECKBUTTON_ID_CUSTOM_USE_LAST_VALUE        30
-#define ED_CHECKBUTTON_ID_CUSTOM_WALK_TO_OBJECT        31
-#define ED_CHECKBUTTON_ID_CUSTOM_INDESTRUCTIBLE        32
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_MOVE      33
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_FALL      34
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_SMASH     35
-#define ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY      36
-#define ED_CHECKBUTTON_ID_CUSTOM_DEADLY                37
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_EXPLODE   38
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_FIRE  39
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_SMASH 40
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT        41
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE    42
-#define ED_CHECKBUTTON_ID_CHANGE_DELAY         43
-#define ED_CHECKBUTTON_ID_CHANGE_BY_DIRECT_ACT 44
-#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER_ACT  45
-#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION 46
-#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT   47
-#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE 48
-#define ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM    49
-#define ED_CHECKBUTTON_ID_CHANGE_HAS_ACTION    50
-
-#define ED_NUM_CHECKBUTTONS                    51
+#define ED_CHECKBUTTON_ID_AUTO_EXIT_SOKOBAN    9
+#define ED_CHECKBUTTON_ID_CONTINUOUS_SNAPPING  10
+#define ED_CHECKBUTTON_ID_BLOCK_SNAP_FIELD     11
+#define ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD     12
+#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_EDITOR_FIRST ED_CHECKBUTTON_ID_RANDOM_RESTRICTED
 #define ED_CHECKBUTTON_ID_EDITOR_LAST  ED_CHECKBUTTON_ID_RANDOM_RESTRICTED
@@ -1045,7 +1047,11 @@ 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,
@@ -1398,6 +1404,7 @@ static struct ValueTextInfo options_game_engine_type[] =
 {
   { GAME_ENGINE_TYPE_RND,      "Rocks'n'Diamonds"              },
   { GAME_ENGINE_TYPE_EM,       "Emerald Mine"                  },
+  { GAME_ENGINE_TYPE_SP,       "Supaplex"                      },
 
   { -1,                                NULL                            }
 };
@@ -2471,25 +2478,41 @@ static struct
 {
   {
     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
     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
     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
     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
     GADGET_ID_SCROLL_RIGHT,
     "scroll level editing area right"
   },
@@ -2521,14 +2544,16 @@ static struct
 {
   {
     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,
-#if 1
     SX,                                        SY,
     SXSIZE,                            SYSIZE,
-#else
-    0,                                 0,
-    SX + SXSIZE + SX,                  WIN_YSIZE,
 #endif
     GD_TYPE_SCROLLBAR_HORIZONTAL,
     GADGET_ID_SCROLL_HORIZONTAL,
@@ -2536,14 +2561,16 @@ static struct
   },
   {
     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,
-#if 1
     SX,                                        SY,
     SXSIZE,                            SYSIZE,
-#else
-    0,                                 0,
-    SX + SXSIZE + SX,                  WIN_YSIZE,
 #endif
     GD_TYPE_SCROLLBAR_VERTICAL,
     GADGET_ID_SCROLL_VERTICAL,
@@ -2551,15 +2578,16 @@ static struct
   },
   {
     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,
-#if 1
     DX,                                        DY,
-    DXSIZE,                            DYSIZE,
-#else
-    SX + SXSIZE + SX,                  0,
-    WIN_XSIZE - (SX + SXSIZE + SX),    WIN_YSIZE,
 #endif
+    DXSIZE,                            DYSIZE,
     GD_TYPE_SCROLLBAR_VERTICAL,
     GADGET_ID_SCROLL_LIST_VERTICAL,
     "scroll element list vertically"
@@ -2670,6 +2698,13 @@ static struct
     NULL,
     "can grow into anything diggable", "grow into more than just sand"
   },
+  {
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(0),
+    GADGET_ID_AUTO_EXIT_SOKOBAN,       GADGET_ID_NONE,
+    &level.auto_exit_sokoban,
+    NULL,
+    "exit level if all fields solved", "automatically finish Sokoban levels"
+  },
   {
     ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(8),
     GADGET_ID_CONTINUOUS_SNAPPING,     GADGET_ID_NONE,
@@ -2997,7 +3032,12 @@ static struct
   {
     0,                                 0,
     GADGET_ID_DRAWING_LEVEL,           GADGET_ID_NONE,
-    NULL,                              MAX_ED_FIELDX, MAX_ED_FIELDY,
+    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
   },
 
@@ -3259,7 +3299,11 @@ static struct
 */
 
 /* 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;
@@ -3704,6 +3748,16 @@ static int editor_el_supaplex[] =
   EL_SP_GRAVITY_PORT_UP,
   EL_SP_GRAVITY_PORT_DOWN,
 
+  EL_SP_GRAVITY_ON_PORT_LEFT,
+  EL_SP_GRAVITY_ON_PORT_RIGHT,
+  EL_SP_GRAVITY_ON_PORT_UP,
+  EL_SP_GRAVITY_ON_PORT_DOWN,
+
+  EL_SP_GRAVITY_OFF_PORT_LEFT,
+  EL_SP_GRAVITY_OFF_PORT_RIGHT,
+  EL_SP_GRAVITY_OFF_PORT_UP,
+  EL_SP_GRAVITY_OFF_PORT_DOWN,
+
   EL_SP_HARDWARE_GRAY,
   EL_SP_HARDWARE_GREEN,
   EL_SP_HARDWARE_BLUE,
@@ -5138,38 +5192,10 @@ static void DrawDrawingArea(int id)
 
 static void ScrollMiniLevel(int from_x, int from_y, int scroll)
 {
-#if 0
-  /* (directly solved in BlitBitmap() now) */
-  static Bitmap *tmp_backbuffer = NULL;
-#endif
   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);
 
-#if 0
-  /* (directly solved in BlitBitmap() now) */
-  if (tmp_backbuffer == NULL)
-    tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, 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, tmp_backbuffer,
-            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));
-  BlitBitmap(tmp_backbuffer, 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));
-
-#else
-
   BlitBitmap(drawto, drawto,
             SX + (dx == -1 ? MINI_TILEX : 0),
             SY + (dy == -1 ? MINI_TILEY : 0),
@@ -5177,7 +5203,6 @@ static void ScrollMiniLevel(int from_x, int from_y, int scroll)
             (ed_fieldy * MINI_TILEY) - (dy != 0 ? MINI_TILEY : 0),
             SX + (dx == +1 ? MINI_TILEX : 0),
             SY + (dy == +1 ? MINI_TILEY : 0));
-#endif
 
   if (dx)
   {
@@ -5335,6 +5360,16 @@ static void CreateControlButtons()
     level_editor_gadget[id] = gi;
   }
 
+  /* 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;
+
   /* create buttons for scrolling of drawing area and element list */
   for (i = 0; i < ED_NUM_SCROLLBUTTONS; i++)
   {
@@ -5450,6 +5485,10 @@ 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;
@@ -5604,6 +5643,10 @@ static void CreateDrawingAreas()
 {
   int i;
 
+  /* these values are not constant, but can change at runtime */
+  drawingarea_info[ED_DRAWING_ID_DRAWING_LEVEL].area_xsize = MAX_ED_FIELDX;
+  drawingarea_info[ED_DRAWING_ID_DRAWING_LEVEL].area_ysize = MAX_ED_FIELDY;
+
   for (i = 0; i < ED_NUM_DRAWING_AREAS; i++)
   {
     struct GadgetInfo *gi;
@@ -5971,6 +6014,40 @@ static void CreateScrollbarGadgets()
 {
   int i;
 
+  /* these values are not constant, but can change at runtime */
+  scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].x =
+    SX + ED_SCROLL_HORIZONTAL_XPOS;
+  scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].y =
+    SY + ED_SCROLL_HORIZONTAL_YPOS;
+  scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].width =
+    ED_SCROLL_HORIZONTAL_XSIZE;
+  scrollbar_info[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_info[ED_SCROLLBAR_ID_AREA_VERTICAL].x =
+    SX + ED_SCROLL_VERTICAL_XPOS;
+  scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].y =
+    SY + ED_SCROLL_VERTICAL_YPOS;
+  scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].width =
+    ED_SCROLL_VERTICAL_XSIZE;
+  scrollbar_info[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;
+
   for (i = 0; i < ED_NUM_SCROLLBARS; i++)
   {
     int id = scrollbar_info[i].gadget_id;
@@ -6173,6 +6250,10 @@ void CreateLevelEditorGadgets()
   /* setting 'game_status' is needed to get the right fonts for the editor */
   game_status = 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;
+
   ReinitializeElementList();
 
   CreateControlButtons();
@@ -6610,8 +6691,12 @@ 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++)
@@ -6621,21 +6706,151 @@ static boolean LevelChanged()
   return (level.changed || field_changed);
 }
 
-static boolean LevelContainsPlayer()
+static boolean PrepareSavingIntoPersonalLevelSet()
 {
-  boolean player_found = FALSE;
-  int x, y;
+  static LevelDirTree *last_copied_leveldir = NULL;
+  static LevelDirTree *last_written_leveldir = NULL;
+  static int last_copied_level_nr = -1;
+  static int last_written_level_nr = -1;
+  LevelDirTree *leveldir_former = leveldir_current;
+  int level_nr_former = level_nr;
+  int new_level_nr;
 
-  return TRUE;         /* !!! CURRENTLY DEACTIVATED !!! */
+  // remember last mod/save so that for current session, we write
+  // back to the same personal copy, asking only about overwrite.
+  if (leveldir_current == last_copied_leveldir &&
+      level_nr == last_copied_level_nr)
+  {
+    // "cd" to personal level set dir (as used when writing last copy)
+    leveldir_current = last_written_leveldir;
+    level_nr = last_written_level_nr;
+
+    return TRUE;
+  }
+
+  if (!Request("This level is read only ! "
+              "Save into personal level set ?", REQ_ASK))
+    return FALSE;
 
-  for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
+  // "cd" to personal level set dir (for writing copy the first time)
+  leveldir_current =
+    getTreeInfoFromIdentifier(leveldir_first, getLoginName());
+
+  // find unused level number
+  for (new_level_nr = leveldir_current->first_level; ; new_level_nr++)
   {
-    if (Feld[x][y] == EL_PLAYER_1 ||
-       Feld[x][y] == EL_SP_MURPHY) 
-      player_found = TRUE;
+    static char *level_filename = NULL;
+
+    setString(&level_filename, getDefaultLevelFilename(new_level_nr));
+
+    if (!fileExists(level_filename))
+      break;
   }
 
-  return player_found;
+  last_copied_leveldir = leveldir_former;
+  last_copied_level_nr = level_nr_former;
+
+  last_written_leveldir = leveldir_current;
+  last_written_level_nr = level_nr = new_level_nr;
+
+  return TRUE;
+}
+
+static void ModifyLevelInfoForSavingIntoPersonalLevelSet(char *former_name)
+{
+  static char *filename_levelinfo = NULL, *mod_name = NULL;
+  FILE *file;
+
+  // annotate this copy-and-mod in personal levelinfo.conf
+  setString(&filename_levelinfo,
+           getPath2(getCurrentLevelDir(), LEVELINFO_FILENAME));
+
+  if ((file = fopen(filename_levelinfo, MODE_APPEND)))
+  {
+    fprintf(file, "\n");
+    fprintf(file, "# level %d was modified from:\n", level_nr);
+    fprintf(file, "# - previous level set name:    %s\n",
+           former_name);
+    fprintf(file, "# - level within previous set:  %d \"%s\"\n",
+           level.file_info.nr, level.name);
+    fprintf(file, "# - previous author:            %s\n",
+           level.author);
+    fprintf(file, "# - previous save date:         ");
+
+    if (level.creation_date.src == DATE_SRC_LEVELFILE)
+    {
+      fprintf(file, "%04d-%02d-%02d\n",
+             level.creation_date.year,
+             level.creation_date.month,
+             level.creation_date.day);
+    }
+    else
+    {
+      fprintf(file, "not recorded\n");
+    }
+
+    fclose(file);
+  }
+
+  if (level_nr > leveldir_current->last_level)
+  {
+    static char *temp_levelinfo = NULL;
+    FILE *temp_file = NULL;
+    char line[MAX_LINE_LEN];
+
+    setString(&temp_levelinfo,
+             getPath2(getCurrentLevelDir(),
+                      getStringCat2(LEVELINFO_FILENAME, ".new")));
+
+    if ((file = fopen(filename_levelinfo, MODE_READ)) &&
+       (temp_file = fopen(temp_levelinfo, MODE_WRITE)))
+    {
+      while (fgets(line, MAX_LINE_LEN, file))
+      {
+       if (!strPrefix(line, "levels:"))
+         fputs(line, temp_file);
+       else
+         fprintf(temp_file, "%-32s%d\n", "levels:", level_nr + 9);
+      }
+    }
+
+    if (temp_file)
+      fclose(temp_file);
+
+    if (file)
+      fclose(file);
+
+    // needs error handling; also, ok on dos/win?
+    unlink(filename_levelinfo);
+    rename(temp_levelinfo, filename_levelinfo);
+  }
+
+  // else: allow the save even if annotation failed
+
+  // now... spray graffiti on the old level vital statistics
+  // user can change these; just trying to set a good baseline
+
+  // don't truncate names for fear of making offensive or silly:
+  // long-named original author only recorded in levelinfo.conf.
+  // try to fit "Joe after Bob", "Joe (ed.)", then just "Joe"
+  if (!strEqual(level.author, leveldir_current->author))
+  {
+    setString(&mod_name, getStringCat3(leveldir_current->author,
+                                      " after ", level.author));
+
+    if (strlen(mod_name) > MAX_LEVEL_AUTHOR_LEN)
+      setString(&mod_name,
+               getStringCat2(leveldir_current->author, " (ed.)"));
+
+    if (strlen(mod_name) > MAX_LEVEL_AUTHOR_LEN)
+      setString(&mod_name, leveldir_current->author);
+
+    strncpy(level.author, mod_name, MAX_LEVEL_AUTHOR_LEN);
+
+    // less worried about truncation here
+    setString(&mod_name, getStringCat2("Mod: ", level.name));
+    strncpy(level.name, mod_name, MAX_LEVEL_NAME_LEN);
+  }
 }
 
 static void CopyPlayfield(short src[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
@@ -7194,6 +7409,11 @@ void DrawLevelEd()
   FadeOut(REDRAW_FIELD);
 #endif
 
+#if 1
+  /* needed if different viewport properties defined for editor */
+  ChangeViewportPropertiesIfNeeded();
+#endif
+
   OpenDoor(DOOR_OPEN_2 | DOOR_NO_DELAY);
 
 #if DEBUG
@@ -7223,6 +7443,10 @@ void DrawLevelEd()
   BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
             DOOR_GFX_PAGEX6, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY);
 
+#if 0
+  printf("::: %d, %d  /  %d, %d\n", VX, VY, EX, EY);
+#endif
+
   /* draw bigger door */
   DrawSpecialEditorDoor();
 
@@ -7232,6 +7456,11 @@ void DrawLevelEd()
 
   redraw_mask |= REDRAW_ALL;
 
+#if 1
+  FreeLevelEditorGadgets();
+  CreateLevelEditorGadgets();
+#endif
+
   ReinitializeElementList();           /* update dynamic level element list */
   ReinitializeElementListButtons();    /* custom element may look different */
 
@@ -7944,7 +8173,7 @@ static int PrintElementDescriptionFromFile(char *filename, int start_line)
   int max_lines_per_screen = (SYSIZE - pad_y) / font_height - 1;
 
   return DrawTextFile(sx, sy, filename, font_nr, max_chars_per_line, -1,
-                     max_lines_per_screen, -1, TRUE, FALSE, FALSE);
+                     max_lines_per_screen, 0, -1, TRUE, FALSE, FALSE);
 }
 
 static void DrawPropertiesInfo()
@@ -8212,7 +8441,10 @@ static boolean checkPropertiesConfig(int element)
       HAS_EDITOR_CONTENT(element) ||
       CAN_GROW(element) ||
       COULD_MOVE_INTO_ACID(element) ||
-      MAYBE_DONT_COLLIDE_WITH(element))
+      MAYBE_DONT_COLLIDE_WITH(element) ||
+      element == EL_SOKOBAN_OBJECT ||
+      element == EL_SOKOBAN_FIELD_EMPTY ||
+      element == EL_SOKOBAN_FIELD_FULL)
     return TRUE;
   else
     for (i = 0; elements_with_counter[i].element != -1; i++)
@@ -8406,6 +8638,11 @@ static void DrawPropertiesConfig()
     MapCheckbuttonGadget(ED_CHECKBUTTON_ID_GROW_INTO_DIGGABLE);
   }
 
+  if (properties_element == EL_SOKOBAN_OBJECT ||
+      properties_element == EL_SOKOBAN_FIELD_EMPTY ||
+      properties_element == EL_SOKOBAN_FIELD_FULL)
+    MapCheckbuttonGadget(ED_CHECKBUTTON_ID_AUTO_EXIT_SOKOBAN);
+
   if (IS_ENVELOPE(properties_element))
   {
     int counter1_id = ED_COUNTER_ID_ENVELOPE_XSIZE;
@@ -9592,20 +9829,6 @@ static void SetElementIntelliDraw(int x, int y, int new_element,
        EL_SP_GRAVITY_PORT_LEFT
       },
 
-      {
-       EL_MOLE_UP,
-       EL_MOLE_RIGHT,
-       EL_MOLE_DOWN,
-       EL_MOLE_LEFT
-      },
-
-      {
-       EL_BALLOON_SWITCH_UP,
-       EL_BALLOON_SWITCH_RIGHT,
-       EL_BALLOON_SWITCH_DOWN,
-       EL_BALLOON_SWITCH_LEFT
-      },
-
       {
        EL_SP_GRAVITY_ON_PORT_UP,
        EL_SP_GRAVITY_ON_PORT_RIGHT,
@@ -9620,6 +9843,20 @@ static void SetElementIntelliDraw(int x, int y, int new_element,
        EL_SP_GRAVITY_OFF_PORT_LEFT
       },
 
+      {
+       EL_MOLE_UP,
+       EL_MOLE_RIGHT,
+       EL_MOLE_DOWN,
+       EL_MOLE_LEFT
+      },
+
+      {
+       EL_BALLOON_SWITCH_UP,
+       EL_BALLOON_SWITCH_RIGHT,
+       EL_BALLOON_SWITCH_DOWN,
+       EL_BALLOON_SWITCH_LEFT
+      },
+
       {
        -1,
        -1,
@@ -9887,7 +10124,11 @@ 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;
@@ -10791,12 +11032,21 @@ static void HandleTextbuttonGadgets(struct GadgetInfo *gi)
     char *template_filename = getDefaultLevelFilename(-1);
     boolean new_template = !fileExists(template_filename);
 
+    /* backup original "level.field" (needed to track playfield changes) */
+    CopyPlayfield(level.field, FieldBackup);
+
+    /* "SaveLevelTemplate()" uses "level.field", so copy editor playfield */
+    CopyPlayfield(Feld, level.field);
+
     if (new_template ||
        Request("Save this template and kill the old ?", REQ_ASK))
       SaveLevelTemplate();
 
     if (new_template)
       Request("Template saved !", REQ_CONFIRM);
+
+    /* restore original "level.field" (needed to track playfield changes) */
+    CopyPlayfield(FieldBackup, level.field);
   }
   else if (type_id == ED_TEXTBUTTON_ID_ADD_CHANGE_PAGE &&
           custom_element.num_change_pages < MAX_CHANGE_PAGES)
@@ -11200,60 +11450,78 @@ static void HandleControlButtons(struct GadgetInfo *gi)
       break;
 
     case GADGET_ID_SAVE:
-      if (leveldir_current->readonly)
-      {
-       Request("This level is read only !", REQ_CONFIRM);
+    {
+      /* saving read-only levels into personal level set modifies global vars
+        "leveldir_current" and "level_nr"; restore them after saving level */
+      LevelDirTree *leveldir_former = leveldir_current;
+      int level_nr_former = level_nr;
+      char *level_filename;
+      boolean new_level;
+
+      if (leveldir_current->readonly &&
+         !PrepareSavingIntoPersonalLevelSet())
        break;
-      }
 
-      if (!LevelContainsPlayer())
-       Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
-      else
+      level_filename = getDefaultLevelFilename(level_nr);
+      new_level = !fileExists(level_filename);
+
+      if (new_level ||
+         Request("Save this level and kill the old ?", REQ_ASK))
       {
-       char *level_filename = getDefaultLevelFilename(level_nr);
-       boolean new_level = !fileExists(level_filename);
+       if (leveldir_former->readonly)
+         ModifyLevelInfoForSavingIntoPersonalLevelSet(leveldir_former->name);
 
-       if (new_level ||
-           Request("Save this level and kill the old ?", REQ_ASK))
-       {
-         CopyPlayfield(Feld, level.field);
+       CopyPlayfield(Feld, level.field);
+       SaveLevel(level_nr);
 
-         SaveLevel(level_nr);
-       }
+       level.changed = FALSE;
 
        if (new_level)
-         Request("Level saved !", REQ_CONFIRM);
+       {
+         char level_saved_msg[64];
 
-       level.changed = FALSE;
+         if (leveldir_former->readonly)
+           sprintf(level_saved_msg,
+                   "Level saved as level %d into personal level set !",
+                   level_nr);
+         else
+           strcpy(level_saved_msg, "Level saved !");
+
+         Request(level_saved_msg, REQ_CONFIRM);
+       }
       }
+
+      /* "cd" back to copied-from levelset (in case of saved read-only level) */
+      leveldir_current = leveldir_former;
+      level_nr = level_nr_former;
+
       break;
+    }
 
     case GADGET_ID_TEST:
-      if (!LevelContainsPlayer())
-       Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
-      else
-      {
-       if (LevelChanged())
-         level.game_version = GAME_VERSION_ACTUAL;
+      if (LevelChanged())
+       level.game_version = GAME_VERSION_ACTUAL;
 
-       CopyPlayfield(level.field, FieldBackup);
-       CopyPlayfield(Feld, level.field);
+      CopyPlayfield(level.field, FieldBackup);
+      CopyPlayfield(Feld, level.field);
+
+      CopyNativeLevel_RND_to_Native(&level);
 
-       CopyNativeLevel_RND_to_Native(&level);
+      UnmapLevelEditorGadgets();
+      UndrawSpecialEditorDoor();
 
-       UnmapLevelEditorGadgets();
-       UndrawSpecialEditorDoor();
+      CloseDoor(DOOR_CLOSE_ALL);
 
-       CloseDoor(DOOR_CLOSE_ALL);
+      BackToFront();           /* force redraw of undrawn special door */
 
-       BackToFront();          /* force redraw of undrawn special door */
+#if 0
+      DrawCompleteVideoDisplay();
+#endif
 
-       DrawCompleteVideoDisplay();
+      level_editor_test_game = TRUE;
 
-       level_editor_test_game = TRUE;
+      StartGameActions(FALSE, setup.autorecord, level.random_seed);
 
-       StartGameActions(FALSE, setup.autorecord, level.random_seed);
-      }
       break;
 
     case GADGET_ID_EXIT:
@@ -11462,7 +11730,9 @@ void HandleLevelEditorKeyInput(Key key)
       ClickOnGadget(level_editor_gadget[id], button);
     else if (letter == '.')
       ClickOnGadget(level_editor_gadget[GADGET_ID_SINGLE_ITEMS], button);
-    else if (key == KSYM_Return || key == setup.shortcut.toggle_pause)
+    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++)
index 156a639882e4b9dbe7e38cd65ae548d33f05c654..8bd49cb837457269404701adf9571abc721f13b8 100644 (file)
 
 #include "libgame/libgame.h"
 #include "game_em/export.h"
+#include "game_sp/export.h"
+
+#include "game.h"
 
 
 /* ========================================================================= */
 /* functions and definitions exported from main program to game_em           */
 /* ========================================================================= */
 
-#include "game.h"
-
 extern void SetBitmaps_EM(Bitmap **);
 extern void UpdateEngineValues(int, int);
 extern void DrawAllGameValues(int, int, int, int, int);
@@ -33,9 +34,26 @@ 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);
 
 void SetGfxAnimation_EM(struct GraphicInfo_EM *, int, int, int, int);
 void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *, int, int, int, int);
 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 getGraphicSource_SP(struct GraphicInfo_SP *, int, int, int, int);
+int getGraphicInfo_Delay(int);
+boolean isNextAnimationFrame_SP(int, int);
+
+
 #endif /* ENGINES_H */
index 278704e6763f9924142f2a6cc4c74c00f055773a..9a42eb47c16e74f5b7c6edfa7140c2f9712e5091 100644 (file)
@@ -577,6 +577,11 @@ static void HandleKeysSpecial(Key key)
     {
       DumpTape(&tape);
     }
+    else if (is_string_suffix(cheat_input, ":save-native-level") ||
+            is_string_suffix(cheat_input, ":snl"))
+    {
+      SaveNativeLevel(&level);
+    }
   }
   else if (game_status == GAME_MODE_PLAYING)
   {
@@ -757,6 +762,9 @@ void HandleKey(Key key, int key_status)
       TapeQuickLoad();
     else if (key == setup.shortcut.toggle_pause)
       TapeTogglePause(TAPE_TOGGLE_MANUAL);
+
+    HandleTapeButtonKeys(key);
+    HandleSoundButtonKeys(key);
   }
 
   if (game_status == GAME_MODE_PLAYING && !network_playing)
@@ -863,6 +871,12 @@ void HandleKey(Key key, int key_status)
        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:
index bfa498816b667306e86dcf59f9ce43a6b07f0b18..d7837486d401d930248e8bfafe7836753027f1fe 100644 (file)
@@ -236,6 +236,12 @@ static struct LevelFileConfigInfo chunk_config_INFO[] =
     &li.score[SC_TIME_BONUS],          1
   },
 
+  {
+    -1,                                        -1,
+    TYPE_BOOLEAN,                      CONF_VALUE_8_BIT(9),
+    &li.auto_exit_sokoban,             FALSE
+  },
+
   {
     -1,                                        -1,
     -1,                                        -1,
@@ -1314,6 +1320,22 @@ filetype_id_list[] =
 /* level file functions                                                      */
 /* ========================================================================= */
 
+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;
+
+  return FALSE;
+}
+
 static struct DateInfo getCurrentDate()
 {
   time_t epoch_seconds = time(NULL);
@@ -1324,6 +1346,8 @@ static struct DateInfo getCurrentDate()
   date.month = now->tm_mon  + 1;
   date.day   = now->tm_mday;
 
+  date.src   = DATE_SRC_CLOCK;
+
   return date;
 }
 
@@ -1587,8 +1611,10 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
   *level = li;         /* copy temporary buffer back to level data */
 
   setLevelInfoToDefaults_EM();
+  setLevelInfoToDefaults_SP();
 
   level->native_em_level = &native_em_level;
+  level->native_sp_level = &native_sp_level;
 
   level->file_version = FILE_VERSION_ACTUAL;
   level->game_version = GAME_VERSION_ACTUAL;
@@ -1750,9 +1776,44 @@ static void setFileInfoToDefaults(struct LevelFileInfo *level_file_info)
 
 static void ActivateLevelTemplate()
 {
+  int x, y;
+
   /* 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. */
+
+  /* Exception: 'from_level_template' elements in the original level playfield
+     are overwritten with the corresponding elements at the same position in
+     playfield from the level template. */
+
+  for (x = 0; x < level.fieldx; x++)
+    for (y = 0; y < level.fieldy; y++)
+      if (level.field[x][y] == EL_FROM_LEVEL_TEMPLATE)
+       level.field[x][y] = level_template.field[x][y];
+
+  if (check_special_flags("load_xsb_to_ces"))
+  {
+    struct LevelInfo level_backup = level;
+
+    /* overwrite all individual level settings from template level settings */
+    level = level_template;
+
+    /* restore playfield size */
+    level.fieldx = level_backup.fieldx;
+    level.fieldy = level_backup.fieldy;
+
+    /* restore playfield content */
+    for (x = 0; x < level.fieldx; x++)
+      for (y = 0; y < level.fieldy; y++)
+       level.field[x][y] = level_backup.field[x][y];
+
+    /* restore name and author from individual level */
+    strcpy(level.name,   level_backup.name);
+    strcpy(level.author, level_backup.author);
+
+    /* restore flag "use_custom_template" */
+    level.use_custom_template = level_backup.use_custom_template;
+  }
 }
 
 static char *getLevelFilenameFromBasename(char *basename)
@@ -1768,21 +1829,33 @@ static char *getLevelFilenameFromBasename(char *basename)
 
 static int getFileTypeFromBasename(char *basename)
 {
+  /* !!! ALSO SEE COMMENT IN checkForPackageFromBasename() !!! */
+
   static char *filename = NULL;
   struct stat file_status;
 
   /* ---------- 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 (strSuffix(basename, ".dc") ||
-      strSuffix(basename, ".dc2"))
+  if (strSuffixLower(basename, ".dc") ||
+      strSuffixLower(basename, ".dc2"))
     return LEVEL_FILE_TYPE_DC;
 
+  /* check for typical filename of a Sokoban level package file */
+  if (strSuffixLower(basename, ".xsb") &&
+      strchr(basename, '%') == NULL)
+    return LEVEL_FILE_TYPE_SB;
+
   /* ---------- try to determine file type from filesize ---------- */
 
   checked_free(filename);
@@ -1798,18 +1871,31 @@ static int getFileTypeFromBasename(char *basename)
   return LEVEL_FILE_TYPE_UNKNOWN;
 }
 
-static char *getSingleLevelBasename(int nr)
+static boolean checkForPackageFromBasename(char *basename)
+{
+  /* !!! WON'T WORK ANYMORE IF getFileTypeFromBasename() ALSO DETECTS !!!
+     !!! SINGLE LEVELS (CURRENTLY ONLY DETECTS LEVEL PACKAGES         !!! */
+
+  return (getFileTypeFromBasename(basename) != LEVEL_FILE_TYPE_UNKNOWN);
+}
+
+static char *getSingleLevelBasenameExt(int nr, char *extension)
 {
   static char basename[MAX_FILENAME_LEN];
 
   if (nr < 0)
-    sprintf(basename, "template.%s", LEVELFILE_EXTENSION);
+    sprintf(basename, "template.%s", extension);
   else
-    sprintf(basename, "%03d.%s", nr, LEVELFILE_EXTENSION);
+    sprintf(basename, "%03d.%s", nr, extension);
 
   return basename;
 }
 
+static char *getSingleLevelBasename(int nr)
+{
+  return getSingleLevelBasenameExt(nr, LEVELFILE_EXTENSION);
+}
+
 static char *getPackedLevelBasename(int type)
 {
   static char basename[MAX_FILENAME_LEN];
@@ -1937,9 +2023,33 @@ 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;
+
+    /* check for template level in path from current to topmost tree node */
+
+    while (leveldir_current != NULL)
+    {
+      setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_RND,
+                                          "template.%s", LEVELFILE_EXTENSION);
+
+      if (fileExists(lfi->filename))
+       break;
+
+      leveldir_current = leveldir_current->node_parent;
+    }
+
+    /* 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;
   }
@@ -1951,6 +2061,9 @@ static void determineLevelFileInfo_Filename(struct LevelFileInfo *lfi)
 
     setLevelFileInfo_FormatLevelFilename(lfi, filetype,
                                         leveldir_current->level_filename, nr);
+
+    lfi->packed = checkForPackageFromBasename(leveldir_current->level_filename);
+
     if (fileExists(lfi->filename))
       return;
   }
@@ -2114,6 +2227,8 @@ static int LoadLevel_DATE(FILE *file, int chunk_size, struct LevelInfo *level)
   level->creation_date.month = getFile8Bit(file);
   level->creation_date.day   = getFile8Bit(file);
 
+  level->creation_date.src   = DATE_SRC_LEVELFILE;
+
   return chunk_size;
 }
 
@@ -3017,8 +3132,12 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level,
   {
     level->no_valid_file = TRUE;
 
+#if 1
+    Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
+#else
     if (level != &level_template)
       Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
+#endif
 
     return;
   }
@@ -3799,30 +3918,13 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level)
   }
 }
 
-static void LoadLevelFromFileInfo_EM(struct LevelInfo *level,
-                                    struct LevelFileInfo *level_file_info)
-{
-  if (!LoadNativeLevel_EM(level_file_info->filename))
-    level->no_valid_file = TRUE;
-}
-
-void CopyNativeLevel_RND_to_Native(struct LevelInfo *level)
-{
-  if (level->game_engine_type == GAME_ENGINE_TYPE_EM)
-    CopyNativeLevel_RND_to_EM(level);
-}
-
-void CopyNativeLevel_Native_to_RND(struct LevelInfo *level)
-{
-  if (level->game_engine_type == GAME_ENGINE_TYPE_EM)
-    CopyNativeLevel_EM_to_RND(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
@@ -4013,7 +4115,8 @@ static void LoadLevelFromFileInfo_SP(struct LevelInfo *level,
   }
 
   /* position file stream to the requested level inside the level package */
-  if (fseek(file, nr * SP_LEVEL_SIZE, SEEK_SET) != 0)
+  if (level_file_info->packed &&
+      fseek(file, nr * SP_LEVEL_SIZE, SEEK_SET) != 0)
   {
     level->no_valid_file = TRUE;
 
@@ -4167,6 +4270,261 @@ static void LoadLevelFromFileInfo_SP(struct LevelInfo *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;
+    }
+    else if (element >= EL_SP_GRAVITY_OFF_PORT_RIGHT &&
+            element <= EL_SP_GRAVITY_OFF_PORT_UP)
+    {
+      gravity_port_found = TRUE;
+      gravity_port_valid = TRUE;
+      gravity_port_flag = 0;
+      gravity_port_base_element = EL_SP_GRAVITY_OFF_PORT_RIGHT;
+    }
+    else if (element >= EL_SP_GRAVITY_PORT_RIGHT &&
+            element <= EL_SP_GRAVITY_PORT_UP)
+    {
+      /* change R'n'D style gravity inverting special port to normal port
+        (there are no gravity inverting ports in native Supaplex engine) */
+
+      gravity_port_found = TRUE;
+      gravity_port_valid = FALSE;
+      gravity_port_base_element = EL_SP_GRAVITY_PORT_RIGHT;
+    }
+
+    if (gravity_port_found)
+    {
+      if (gravity_port_valid &&
+         header->SpecialPortCount < SP_MAX_SPECIAL_PORTS)
+      {
+       SpecialPortType *port = &header->SpecialPort[header->SpecialPortCount];
+
+       port->PortLocation = (y * level->fieldx + x) * 2;
+       port->Gravity = gravity_port_flag;
+
+       element += EL_SP_GRAVITY_PORT_RIGHT - gravity_port_base_element;
+
+       header->SpecialPortCount++;
+      }
+      else
+      {
+       /* change special gravity port to normal port */
+
+       element += EL_SP_PORT_RIGHT - gravity_port_base_element;
+      }
+
+      level_sp->playfield[x][y] = element - EL_SP_START;
+    }
+  }
+}
+
+void CopyNativeLevel_SP_to_RND(struct LevelInfo *level)
+{
+  struct LevelInfo_SP *level_sp = level->native_sp_level;
+  LevelInfoType *header = &level_sp->header;
+  int i, x, y;
+
+  level->fieldx = level_sp->width;
+  level->fieldy = level_sp->height;
+
+  for (x = 0; x < level->fieldx; x++)
+  {
+    for (y = 0; y < level->fieldy; y++)
+    {
+      int element_old = level_sp->playfield[x][y];
+      int element_new = getMappedElement(map_element_SP_to_RND(element_old));
+
+      if (element_new == EL_UNKNOWN)
+       Error(ERR_WARN, "invalid element %d at position %d, %d",
+             element_old, x, y);
+
+      level->field[x][y] = element_new;
+    }
+  }
+
+  for (i = 0; i < MAX_PLAYERS; i++)
+    level->initial_player_gravity[i] =
+      (header->InitialGravity == 1 ? TRUE : FALSE);
+
+  for (i = 0; i < SP_LEVEL_NAME_LEN; i++)
+    level->name[i] = header->LevelTitle[i];
+  level->name[SP_LEVEL_NAME_LEN] = '\0';
+
+  level->gems_needed = header->InfotronsNeeded;
+
+  for (i = 0; i < header->SpecialPortCount; i++)
+  {
+    SpecialPortType *port = &header->SpecialPort[i];
+    int port_location = port->PortLocation;
+    int gravity = port->Gravity;
+    int port_x, port_y, port_element;
+
+    port_x = (port_location / 2) % level->fieldx;
+    port_y = (port_location / 2) / level->fieldx;
+
+    if (port_x < 0 || port_x >= level->fieldx ||
+       port_y < 0 || port_y >= level->fieldy)
+    {
+      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;
+  }
+
+  /* change special gravity ports without database entries to normal ports */
+  for (x = 0; x < level->fieldx; x++)
+    for (y = 0; y < level->fieldy; y++)
+      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;
+
+  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 (x = 0; x < 3; x++)
+      for (y = 0; y < 3; y++)
+       level->yamyam_content[i].e[x][y] = EL_EMPTY;
+}
+
+static void CopyNativeTape_RND_to_SP(struct LevelInfo *level)
+{
+  struct LevelInfo_SP *level_sp = level->native_sp_level;
+  struct DemoInfo_SP *demo = &level_sp->demo;
+  int i, j;
+
+  /* always start with reliable default values */
+  demo->is_available = FALSE;
+  demo->length = 0;
+
+  if (TAPE_IS_EMPTY(tape))
+    return;
+
+  demo->level_nr = tape.level_nr;      /* (currently not used) */
+
+  level_sp->header.DemoRandomSeed = tape.random_seed;
+
+  demo->length = 0;
+  for (i = 0; i < tape.length; i++)
+  {
+    int demo_action = map_key_RND_to_SP(tape.pos[i].action[0]);
+    int demo_repeat = tape.pos[i].delay;
+
+    for (j = 0; j < demo_repeat / 16; j++)
+      demo->data[demo->length++] = 0xf0 | demo_action;
+
+    if (demo_repeat % 16)
+      demo->data[demo->length++] = ((demo_repeat % 16 - 1) << 4) | demo_action;
+  }
+
+  demo->data[demo->length++] = 0xff;
+
+  demo->is_available = TRUE;
+}
+
+static void setTapeInfoToDefaults();
+
+static void CopyNativeTape_SP_to_RND(struct LevelInfo *level)
+{
+  struct LevelInfo_SP *level_sp = level->native_sp_level;
+  struct DemoInfo_SP *demo = &level_sp->demo;
+  char *filename = level->file_info.filename;
+  int i;
+
+  /* always start with reliable default values */
+  setTapeInfoToDefaults();
+
+  if (!demo->is_available)
+    return;
+
+  tape.level_nr = demo->level_nr;      /* (currently not used) */
+  tape.length = demo->length - 1;      /* without "end of demo" byte */
+  tape.random_seed = level_sp->header.DemoRandomSeed;
+
+  TapeSetDateFromEpochSeconds(getFileTimestampEpochSeconds(filename));
+
+  for (i = 0; i < demo->length - 1; i++)
+  {
+    int demo_action = demo->data[i] & 0x0f;
+    int demo_repeat = (demo->data[i] & 0xf0) >> 4;
+
+    tape.pos[i].action[0] = map_key_SP_to_RND(demo_action);
+    tape.pos[i].delay = demo_repeat + 1;
+  }
+
+  tape.length_seconds = GetTapeLength();
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* functions for loading DC level                                            */
+/* ------------------------------------------------------------------------- */
 
 #define DC_LEVEL_HEADER_SIZE           344
 
@@ -6138,32 +6496,434 @@ static void LoadLevelFromFileInfo_DC(struct LevelInfo *level,
 
 
 /* ------------------------------------------------------------------------- */
-/* functions for loading generic level                                       */
+/* functions for loading SB level                                            */
 /* ------------------------------------------------------------------------- */
 
-void LoadLevelFromFileInfo(struct LevelInfo *level,
-                          struct LevelFileInfo *level_file_info)
+int getMappedElement_SB(int element_ascii, boolean use_ces)
 {
-  /* always start with reliable default values */
-  setLevelInfoToDefaults(level);
-
-  switch (level_file_info->type)
+  static struct
   {
-    case LEVEL_FILE_TYPE_RND:
-      LoadLevelFromFileInfo_RND(level, level_file_info);
-      break;
+    int ascii;
+    int sb;
+    int ce;
+  }
+  sb_element_mapping[] =
+  {
+    { ' ', EL_EMPTY,                EL_CUSTOM_1 },  /* floor (space) */
+    { '#', EL_STEELWALL,            EL_CUSTOM_2 },  /* wall */
+    { '@', EL_PLAYER_1,             EL_CUSTOM_3 },  /* player */
+    { '$', EL_SOKOBAN_OBJECT,       EL_CUSTOM_4 },  /* box */
+    { '.', 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
 
-    case LEVEL_FILE_TYPE_EM:
-      LoadLevelFromFileInfo_EM(level, level_file_info);
-      level->game_engine_type = GAME_ENGINE_TYPE_EM;
-      break;
+    { 0,   -1,                      -1          },
+  };
 
-    case LEVEL_FILE_TYPE_SP:
-      LoadLevelFromFileInfo_SP(level, level_file_info);
-      break;
+  int i;
 
-    case LEVEL_FILE_TYPE_DC:
-      LoadLevelFromFileInfo_DC(level, level_file_info);
+  for (i = 0; sb_element_mapping[i].ascii != 0; i++)
+    if (element_ascii == sb_element_mapping[i].ascii)
+      return (use_ces ? sb_element_mapping[i].ce : sb_element_mapping[i].sb);
+
+  return EL_UNDEFINED;
+}
+
+static void LoadLevelFromFileInfo_SB(struct LevelInfo *level,
+                                    struct LevelFileInfo *level_file_info)
+{
+  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;
+  int num_levels_to_skip = level_file_info->nr - leveldir_current->first_level;
+  boolean read_continued_line = FALSE;
+  boolean reading_playfield = FALSE;
+  boolean got_valid_playfield_line = FALSE;
+  boolean invalid_playfield_char = FALSE;
+  boolean load_xsb_to_ces = check_special_flags("load_xsb_to_ces");
+  int file_level_nr = 0;
+  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)))
+  {
+    level->no_valid_file = TRUE;
+
+    Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
+
+    return;
+  }
+
+  while (!feof(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;
+
+      if (file_level_nr >= num_levels_to_skip)
+       break;
+
+      file_level_nr++;
+
+      last_comment[0] = '\0';
+      level_name[0] = '\0';
+
+      reading_playfield = FALSE;
+    }
+
+    got_valid_playfield_line = FALSE;
+
+    /* 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)
+    {
+      /* 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;
+    }
+
+    /* skip empty lines */
+    if (line[0] == '\0')
+      continue;
+
+    /* extract comment text from comment line */
+    if (line[0] == ';')
+    {
+      for (line_ptr = line; *line_ptr; line_ptr++)
+        if (*line_ptr != ' ' && *line_ptr != '\t' && *line_ptr != ';')
+          break;
+
+      strcpy(last_comment, line_ptr);
+
+#if 0
+      printf("::: found comment '%s' in line %d\n", last_comment, line_nr);
+#endif
+
+      continue;
+    }
+
+    /* extract level title text from line containing level title */
+    if (line[0] == '\'')
+    {
+      strcpy(level_name, &line[1]);
+
+      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;
+    }
+
+    /* skip lines containing only spaces (or empty lines) */
+    for (line_ptr = line; *line_ptr; line_ptr++)
+      if (*line_ptr != ' ')
+       break;
+    if (*line_ptr == '\0')
+      continue;
+
+    /* 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)
+    {
+      reading_playfield = TRUE;
+      invalid_playfield_char = FALSE;
+
+      for (x = 0; x < MAX_LEV_FIELDX; x++)
+       for (y = 0; y < MAX_LEV_FIELDY; y++)
+         level->field[x][y] = getMappedElement_SB(' ', load_xsb_to_ces);
+
+      level->fieldx = 0;
+      level->fieldy = 0;
+
+      /* start with topmost tile row */
+      y = 0;
+    }
+
+    /* skip playfield line if larger row than allowed */
+    if (y >= MAX_LEV_FIELDY)
+      continue;
+
+    /* start with leftmost tile column */
+    x = 0;
+
+    /* read playfield elements from line */
+    for (line_ptr = line; *line_ptr; line_ptr++)
+    {
+      int mapped_sb_element = getMappedElement_SB(*line_ptr, load_xsb_to_ces);
+
+      /* stop parsing playfield line if larger column than allowed */
+      if (x >= MAX_LEV_FIELDX)
+       break;
+
+      if (mapped_sb_element == EL_UNDEFINED)
+      {
+       invalid_playfield_char = TRUE;
+
+       break;
+      }
+
+      level->field[x][y] = mapped_sb_element;
+
+      /* continue with next tile column */
+      x++;
+
+      level->fieldx = MAX(x, level->fieldx);
+    }
+
+    if (invalid_playfield_char)
+    {
+      /* if first playfield line, treat invalid lines as comment lines */
+      if (y == 0)
+       reading_playfield = FALSE;
+
+      continue;
+    }
+
+    /* continue with next tile row */
+    y++;
+  }
+
+  fclose(file);
+
+  level->fieldy = y;
+
+  level->fieldx = MIN(MAX(MIN_LEV_FIELDX, level->fieldx), MAX_LEV_FIELDX);
+  level->fieldy = MIN(MAX(MIN_LEV_FIELDY, level->fieldy), MAX_LEV_FIELDY);
+
+  if (!reading_playfield)
+  {
+    level->no_valid_file = TRUE;
+
+    Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
+
+    return;
+  }
+
+  if (*level_name != '\0')
+  {
+    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
+  {
+    sprintf(level->name, "--> Level %d <--", level_file_info->nr);
+  }
+
+  /* set all empty fields beyond the border walls to invisible steel wall */
+  for (y = 0; y < level->fieldy; y++) for (x = 0; x < level->fieldx; x++)
+  {
+    if ((x == 0 || x == level->fieldx - 1 ||
+        y == 0 || y == level->fieldy - 1) &&
+       level->field[x][y] == getMappedElement_SB(' ', load_xsb_to_ces))
+      FloodFillLevel(x, y, getMappedElement_SB('_', load_xsb_to_ces),
+                    level->field, level->fieldx, level->fieldy);
+  }
+
+  /* set special level settings for Sokoban levels */
+
+  level->time = 0;
+  level->use_step_counter = TRUE;
+
+  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;
+    }
+
+    level->use_custom_template = TRUE;
+  }
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* functions for handling native levels                                      */
+/* ------------------------------------------------------------------------- */
+
+static void LoadLevelFromFileInfo_EM(struct LevelInfo *level,
+                                    struct LevelFileInfo *level_file_info)
+{
+  if (!LoadNativeLevel_EM(level_file_info->filename))
+    level->no_valid_file = TRUE;
+}
+
+static void LoadLevelFromFileInfo_SP(struct LevelInfo *level,
+                                    struct LevelFileInfo *level_file_info)
+{
+  int pos = 0;
+
+  /* determine position of requested level inside level package */
+  if (level_file_info->packed)
+    pos = level_file_info->nr - leveldir_current->first_level;
+
+  if (!LoadNativeLevel_SP(level_file_info->filename, pos))
+    level->no_valid_file = TRUE;
+}
+
+void CopyNativeLevel_RND_to_Native(struct LevelInfo *level)
+{
+  if (level->game_engine_type == GAME_ENGINE_TYPE_EM)
+    CopyNativeLevel_RND_to_EM(level);
+  else if (level->game_engine_type == GAME_ENGINE_TYPE_SP)
+    CopyNativeLevel_RND_to_SP(level);
+}
+
+void CopyNativeLevel_Native_to_RND(struct LevelInfo *level)
+{
+  if (level->game_engine_type == GAME_ENGINE_TYPE_EM)
+    CopyNativeLevel_EM_to_RND(level);
+  else if (level->game_engine_type == GAME_ENGINE_TYPE_SP)
+    CopyNativeLevel_SP_to_RND(level);
+}
+
+void SaveNativeLevel(struct LevelInfo *level)
+{
+  if (level->game_engine_type == GAME_ENGINE_TYPE_SP)
+  {
+    char *basename = getSingleLevelBasenameExt(level->file_info.nr, "sp");
+    char *filename = getLevelFilenameFromBasename(basename);
+
+    CopyNativeLevel_RND_to_SP(level);
+    CopyNativeTape_RND_to_SP(level);
+
+    SaveNativeLevel_SP(filename);
+  }
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* functions for loading generic level                                       */
+/* ------------------------------------------------------------------------- */
+
+void LoadLevelFromFileInfo(struct LevelInfo *level,
+                          struct LevelFileInfo *level_file_info)
+{
+  /* always start with reliable default values */
+  setLevelInfoToDefaults(level);
+
+  switch (level_file_info->type)
+  {
+    case LEVEL_FILE_TYPE_RND:
+      LoadLevelFromFileInfo_RND(level, level_file_info);
+      break;
+
+    case LEVEL_FILE_TYPE_EM:
+      LoadLevelFromFileInfo_EM(level, level_file_info);
+      level->game_engine_type = GAME_ENGINE_TYPE_EM;
+      break;
+
+    case LEVEL_FILE_TYPE_SP:
+      LoadLevelFromFileInfo_SP(level, level_file_info);
+      level->game_engine_type = GAME_ENGINE_TYPE_SP;
+      break;
+
+    case LEVEL_FILE_TYPE_DC:
+      LoadLevelFromFileInfo_DC(level, level_file_info);
+      break;
+
+    case LEVEL_FILE_TYPE_SB:
+      LoadLevelFromFileInfo_SB(level, level_file_info);
       break;
 
     default:
@@ -7692,6 +8452,79 @@ static int LoadTape_BODY(FILE *file, int chunk_size, struct TapeInfo *tape)
   return chunk_size;
 }
 
+void LoadTape_SokobanSolution(char *filename)
+{
+  FILE *file;
+  int move_delay = TILESIZE / level.initial_player_stepsize[0];
+
+  if (!(file = fopen(filename, MODE_READ)))
+  {
+    tape.no_valid_file = TRUE;
+
+    return;
+  }
+
+  while (!feof(file))
+  {
+    unsigned char c = fgetc(file);
+
+    if (feof(file))
+      break;
+
+    switch (c)
+    {
+      case 'u':
+      case 'U':
+       tape.pos[tape.length].action[0] = MV_UP;
+       tape.pos[tape.length].delay = move_delay + (c < 'a' ? 2 : 0);
+       tape.length++;
+       break;
+
+      case 'd':
+      case 'D':
+       tape.pos[tape.length].action[0] = MV_DOWN;
+       tape.pos[tape.length].delay = move_delay + (c < 'a' ? 2 : 0);
+       tape.length++;
+       break;
+
+      case 'l':
+      case 'L':
+       tape.pos[tape.length].action[0] = MV_LEFT;
+       tape.pos[tape.length].delay = move_delay + (c < 'a' ? 2 : 0);
+       tape.length++;
+       break;
+
+      case 'r':
+      case 'R':
+       tape.pos[tape.length].action[0] = MV_RIGHT;
+       tape.pos[tape.length].delay = move_delay + (c < 'a' ? 2 : 0);
+       tape.length++;
+       break;
+
+      case '\n':
+      case '\r':
+      case '\t':
+      case ' ':
+       /* ignore white-space characters */
+       break;
+
+      default:
+       tape.no_valid_file = TRUE;
+
+       Error(ERR_WARN, "unsupported Sokoban solution file '%s' ['%d']", filename, c);
+
+       break;
+    }
+  }
+
+  fclose(file);
+
+  if (tape.no_valid_file)
+    return;
+
+  tape.length_seconds = GetTapeLength();
+}
+
 void LoadTapeFromFilename(char *filename)
 {
   char cookie[MAX_LINE_LEN];
@@ -7702,6 +8535,13 @@ void LoadTapeFromFilename(char *filename)
   /* always start with reliable default values */
   setTapeInfoToDefaults();
 
+  if (strSuffix(filename, ".sln"))
+  {
+    LoadTape_SokobanSolution(filename);
+
+    return;
+  }
+
   if (!(file = fopen(filename, MODE_READ)))
   {
     tape.no_valid_file = TRUE;
@@ -7746,6 +8586,7 @@ void LoadTapeFromFilename(char *filename)
 
       Error(ERR_WARN, "unsupported version of tape file '%s'", filename);
       fclose(file);
+
       return;
     }
 
@@ -7838,6 +8679,13 @@ void LoadSolutionTape(int nr)
   char *filename = getSolutionTapeFilename(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)
@@ -8152,14 +9000,15 @@ void SaveScore(int nr)
 #define SETUP_TOKEN_INPUT_ON_FOCUS             22
 #define SETUP_TOKEN_PREFER_AGA_GRAPHICS                23
 #define SETUP_TOKEN_GAME_FRAME_DELAY           24
-#define SETUP_TOKEN_GRAPHICS_SET               25
-#define SETUP_TOKEN_SOUNDS_SET                 26
-#define SETUP_TOKEN_MUSIC_SET                  27
-#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS    28
-#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS      29
-#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC       30
+#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                        31
+#define NUM_GLOBAL_SETUP_TOKENS                        32
 
 /* editor setup */
 #define SETUP_TOKEN_EDITOR_EL_BOULDERDASH      0
@@ -8210,8 +9059,16 @@ void SaveScore(int nr)
 #define SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_3    5
 #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 NUM_SHORTCUT_SETUP_TOKENS              8
+#define NUM_SHORTCUT_SETUP_TOKENS              16
 
 /* player setup */
 #define SETUP_TOKEN_PLAYER_USE_JOYSTICK                0
@@ -8256,34 +9113,35 @@ static struct OptionInfo soi;
 
 static struct TokenInfo global_setup_tokens[] =
 {
-  { TYPE_STRING, &si.player_name,      "player_name"                   },
-  { TYPE_SWITCH, &si.sound,            "sound"                         },
-  { TYPE_SWITCH, &si.sound_loops,      "repeating_sound_loops"         },
-  { TYPE_SWITCH, &si.sound_music,      "background_music"              },
-  { TYPE_SWITCH, &si.sound_simple,     "simple_sound_effects"          },
-  { 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_SWITCH, &si.fade_screens,     "fade_screens"                  },
-  { TYPE_SWITCH, &si.autorecord,       "automatic_tape_recording"      },
-  { TYPE_SWITCH, &si.show_titlescreen, "show_titlescreen"              },
-  { TYPE_SWITCH, &si.quick_doors,      "quick_doors"                   },
-  { TYPE_SWITCH, &si.team_mode,                "team_mode"                     },
-  { TYPE_SWITCH, &si.handicap,         "handicap"                      },
-  { 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_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"           },
-  { TYPE_SWITCH, &si.input_on_focus,   "input_on_focus"                },
-  { TYPE_SWITCH, &si.prefer_aga_graphics, "prefer_aga_graphics"                },
-  { TYPE_INTEGER,&si.game_frame_delay, "game_frame_delay"              },
-  { TYPE_STRING, &si.graphics_set,     "graphics_set"                  },
-  { TYPE_STRING, &si.sounds_set,       "sounds_set"                    },
-  { TYPE_STRING, &si.music_set,                "music_set"                     },
+  { TYPE_STRING, &si.player_name,             "player_name"            },
+  { TYPE_SWITCH, &si.sound,                   "sound"                  },
+  { TYPE_SWITCH, &si.sound_loops,             "repeating_sound_loops"  },
+  { TYPE_SWITCH, &si.sound_music,             "background_music"       },
+  { TYPE_SWITCH, &si.sound_simple,            "simple_sound_effects"   },
+  { 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_SWITCH, &si.fade_screens,            "fade_screens"           },
+  { TYPE_SWITCH, &si.autorecord,              "automatic_tape_recording"},
+  { TYPE_SWITCH, &si.show_titlescreen,        "show_titlescreen"       },
+  { TYPE_SWITCH, &si.quick_doors,             "quick_doors"            },
+  { TYPE_SWITCH, &si.team_mode,               "team_mode"              },
+  { TYPE_SWITCH, &si.handicap,                "handicap"               },
+  { 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_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"    },
+  { TYPE_SWITCH, &si.input_on_focus,          "input_on_focus"         },
+  { 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_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"   },
@@ -8355,6 +9213,14 @@ static struct TokenInfo shortcut_setup_tokens[] =
   { TYPE_KEY_X11, &ssi.focus_player[2],        "shortcut.focus_player_3"       },
   { 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_stop,      "shortcut.tape_stop"            },
+  { TYPE_KEY_X11, &ssi.tape_pause,     "shortcut.tape_pause"           },
+  { TYPE_KEY_X11, &ssi.tape_record,    "shortcut.tape_record"          },
+  { TYPE_KEY_X11, &ssi.tape_play,      "shortcut.tape_play"            },
+  { TYPE_KEY_X11, &ssi.sound_simple,   "shortcut.sound_simple"         },
+  { TYPE_KEY_X11, &ssi.sound_loops,    "shortcut.sound_loops"          },
+  { TYPE_KEY_X11, &ssi.sound_music,    "shortcut.sound_music"          },
 };
 
 static struct TokenInfo player_setup_tokens[] =
@@ -8434,6 +9300,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->input_on_focus = FALSE;
   si->prefer_aga_graphics = TRUE;
   si->game_frame_delay = GAME_FRAME_DELAY;
+  si->sp_show_border_elements = FALSE;
 
   si->graphics_set = getStringCopy(GFX_DEFAULT_SUBDIR);
   si->sounds_set = getStringCopy(SND_DEFAULT_SUBDIR);
@@ -8470,6 +9337,16 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->shortcut.focus_player[3] = DEFAULT_KEY_FOCUS_PLAYER_4;
   si->shortcut.focus_player_all        = DEFAULT_KEY_FOCUS_PLAYER_ALL;
 
+  si->shortcut.tape_eject      = DEFAULT_KEY_TAPE_EJECT;
+  si->shortcut.tape_stop       = DEFAULT_KEY_TAPE_STOP;
+  si->shortcut.tape_pause      = DEFAULT_KEY_TAPE_PAUSE;
+  si->shortcut.tape_record     = DEFAULT_KEY_TAPE_RECORD;
+  si->shortcut.tape_play       = DEFAULT_KEY_TAPE_PLAY;
+
+  si->shortcut.sound_simple    = DEFAULT_KEY_SOUND_SIMPLE;
+  si->shortcut.sound_loops     = DEFAULT_KEY_SOUND_LOOPS;
+  si->shortcut.sound_music     = DEFAULT_KEY_SOUND_MUSIC;
+
   for (i = 0; i < MAX_PLAYERS; i++)
   {
     si->input[i].use_joystick = FALSE;
@@ -8497,6 +9374,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->options.verbose = FALSE;
 
 #if defined(CREATE_SPECIAL_EDITION_RND_JUE)
+  si->toons = FALSE;
   si->handicap = FALSE;
   si->fullscreen = TRUE;
   si->override_level_graphics = AUTO;
@@ -8930,6 +9808,16 @@ static void InitMenuDesignSettings_SpecialPreProcessing()
     menu.enter_screen[i] = menu.enter_screen[GFX_SPECIAL_ARG_DEFAULT];
     menu.leave_screen[i] = menu.leave_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.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];
+  }
 }
 
 static void InitMenuDesignSettings_SpecialPostProcessing()
@@ -9067,6 +9955,50 @@ static void LoadMenuDesignSettingsFromFilename(char *filename)
                                                                  value_6);
   }
 
+  /* 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);
+
+    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 "titlemessage_1.fade_mode" from "[titlemessage].fade_mode") */
   for (i = 0; titlemessage_arrays[i].array != NULL; i++)
@@ -9403,6 +10335,10 @@ void LoadMusicInfo()
     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;
     }
@@ -9448,6 +10384,10 @@ void LoadMusicInfo()
     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;
     }
index 75dc34601e02e72b237e06b1f872f102aa1bb0ed..9edda3222fd68a5002d1768e6b637f3a70a39671 100644 (file)
@@ -38,6 +38,7 @@ void LoadLevel(int);
 void LoadLevelTemplate(int);
 void SaveLevel(int);
 void SaveLevelTemplate();
+void SaveNativeLevel(struct LevelInfo *);
 void DumpLevel(struct LevelInfo *);
 boolean SaveLevelChecked(int);
 
index d4e4cf3f28c69bc7331151108bc03d011410b082..aeb40a51fcc369b0e06378145c6891669790cc84 100644 (file)
 #if USE_DELAYED_GFX_REDRAW
 #define TEST_DrawLevelField(x, y)                              \
        GfxRedraw[x][y] |= GFX_REDRAW_TILE
-#define TEST_DrawLevelFieldCrumbledSand(x, y)                  \
+#define TEST_DrawLevelFieldCrumbled(x, y)                      \
        GfxRedraw[x][y] |= GFX_REDRAW_TILE_CRUMBLED
-#define TEST_DrawLevelFieldCrumbledSandNeighbours(x, y)                \
+#define TEST_DrawLevelFieldCrumbledNeighbours(x, y)            \
        GfxRedraw[x][y] |= GFX_REDRAW_TILE_CRUMBLED_NEIGHBOURS
 #define TEST_DrawTwinkleOnField(x, y)                          \
        GfxRedraw[x][y] |= GFX_REDRAW_TILE_TWINKLED
 #else
 #define TEST_DrawLevelField(x, y)                              \
             DrawLevelField(x, y)
-#define TEST_DrawLevelFieldCrumbledSand(x, y)                  \
-            DrawLevelFieldCrumbledSand(x, y)
-#define TEST_DrawLevelFieldCrumbledSandNeighbours(x, y)                \
-            DrawLevelFieldCrumbledSandNeighbours(x, y)
+#define TEST_DrawLevelFieldCrumbled(x, y)                      \
+            DrawLevelFieldCrumbled(x, y)
+#define TEST_DrawLevelFieldCrumbledNeighbours(x, y)            \
+            DrawLevelFieldCrumbledNeighbours(x, y)
 #define TEST_DrawTwinkleOnField(x, y)                          \
             DrawTwinkleOnField(x, y)
 #endif
 #define GAME_PANEL_TIME_HH                     32
 #define GAME_PANEL_TIME_MM                     33
 #define GAME_PANEL_TIME_SS                     34
-#define GAME_PANEL_SHIELD_NORMAL               35
-#define GAME_PANEL_SHIELD_NORMAL_TIME          36
-#define GAME_PANEL_SHIELD_DEADLY               37
-#define GAME_PANEL_SHIELD_DEADLY_TIME          38
-#define GAME_PANEL_EXIT                                39
-#define GAME_PANEL_EMC_MAGIC_BALL              40
-#define GAME_PANEL_EMC_MAGIC_BALL_SWITCH       41
-#define GAME_PANEL_LIGHT_SWITCH                        42
-#define GAME_PANEL_LIGHT_SWITCH_TIME           43
-#define GAME_PANEL_TIMEGATE_SWITCH             44
-#define GAME_PANEL_TIMEGATE_SWITCH_TIME                45
-#define GAME_PANEL_SWITCHGATE_SWITCH           46
-#define GAME_PANEL_EMC_LENSES                  47
-#define GAME_PANEL_EMC_LENSES_TIME             48
-#define GAME_PANEL_EMC_MAGNIFIER               49
-#define GAME_PANEL_EMC_MAGNIFIER_TIME          50
-#define GAME_PANEL_BALLOON_SWITCH              51
-#define GAME_PANEL_DYNABOMB_NUMBER             52
-#define GAME_PANEL_DYNABOMB_SIZE               53
-#define GAME_PANEL_DYNABOMB_POWER              54
-#define GAME_PANEL_PENGUINS                    55
-#define GAME_PANEL_SOKOBAN_OBJECTS             56
-#define GAME_PANEL_SOKOBAN_FIELDS              57
-#define GAME_PANEL_ROBOT_WHEEL                 58
-#define GAME_PANEL_CONVEYOR_BELT_1             59
-#define GAME_PANEL_CONVEYOR_BELT_2             60
-#define GAME_PANEL_CONVEYOR_BELT_3             61
-#define GAME_PANEL_CONVEYOR_BELT_4             62
-#define GAME_PANEL_CONVEYOR_BELT_1_SWITCH      63
-#define GAME_PANEL_CONVEYOR_BELT_2_SWITCH      64
-#define GAME_PANEL_CONVEYOR_BELT_3_SWITCH      65
-#define GAME_PANEL_CONVEYOR_BELT_4_SWITCH      66
-#define GAME_PANEL_MAGIC_WALL                  67
-#define GAME_PANEL_MAGIC_WALL_TIME             68
-#define GAME_PANEL_GRAVITY_STATE               69
-#define GAME_PANEL_GRAPHIC_1                   70
-#define GAME_PANEL_GRAPHIC_2                   71
-#define GAME_PANEL_GRAPHIC_3                   72
-#define GAME_PANEL_GRAPHIC_4                   73
-#define GAME_PANEL_GRAPHIC_5                   74
-#define GAME_PANEL_GRAPHIC_6                   75
-#define GAME_PANEL_GRAPHIC_7                   76
-#define GAME_PANEL_GRAPHIC_8                   77
-#define GAME_PANEL_ELEMENT_1                   78
-#define GAME_PANEL_ELEMENT_2                   79
-#define GAME_PANEL_ELEMENT_3                   80
-#define GAME_PANEL_ELEMENT_4                   81
-#define GAME_PANEL_ELEMENT_5                   82
-#define GAME_PANEL_ELEMENT_6                   83
-#define GAME_PANEL_ELEMENT_7                   84
-#define GAME_PANEL_ELEMENT_8                   85
-#define GAME_PANEL_ELEMENT_COUNT_1             86
-#define GAME_PANEL_ELEMENT_COUNT_2             87
-#define GAME_PANEL_ELEMENT_COUNT_3             88
-#define GAME_PANEL_ELEMENT_COUNT_4             89
-#define GAME_PANEL_ELEMENT_COUNT_5             90
-#define GAME_PANEL_ELEMENT_COUNT_6             91
-#define GAME_PANEL_ELEMENT_COUNT_7             92
-#define GAME_PANEL_ELEMENT_COUNT_8             93
-#define GAME_PANEL_CE_SCORE_1                  94
-#define GAME_PANEL_CE_SCORE_2                  95
-#define GAME_PANEL_CE_SCORE_3                  96
-#define GAME_PANEL_CE_SCORE_4                  97
-#define GAME_PANEL_CE_SCORE_5                  98
-#define GAME_PANEL_CE_SCORE_6                  99
-#define GAME_PANEL_CE_SCORE_7                  100
-#define GAME_PANEL_CE_SCORE_8                  101
-#define GAME_PANEL_CE_SCORE_1_ELEMENT          102
-#define GAME_PANEL_CE_SCORE_2_ELEMENT          103
-#define GAME_PANEL_CE_SCORE_3_ELEMENT          104
-#define GAME_PANEL_CE_SCORE_4_ELEMENT          105
-#define GAME_PANEL_CE_SCORE_5_ELEMENT          106
-#define GAME_PANEL_CE_SCORE_6_ELEMENT          107
-#define GAME_PANEL_CE_SCORE_7_ELEMENT          108
-#define GAME_PANEL_CE_SCORE_8_ELEMENT          109
-#define GAME_PANEL_PLAYER_NAME                 110
-#define GAME_PANEL_LEVEL_NAME                  111
-#define GAME_PANEL_LEVEL_AUTHOR                        112
-
-#define NUM_GAME_PANEL_CONTROLS                        113
+#define GAME_PANEL_FRAME                       35
+#define GAME_PANEL_SHIELD_NORMAL               36
+#define GAME_PANEL_SHIELD_NORMAL_TIME          37
+#define GAME_PANEL_SHIELD_DEADLY               38
+#define GAME_PANEL_SHIELD_DEADLY_TIME          39
+#define GAME_PANEL_EXIT                                40
+#define GAME_PANEL_EMC_MAGIC_BALL              41
+#define GAME_PANEL_EMC_MAGIC_BALL_SWITCH       42
+#define GAME_PANEL_LIGHT_SWITCH                        43
+#define GAME_PANEL_LIGHT_SWITCH_TIME           44
+#define GAME_PANEL_TIMEGATE_SWITCH             45
+#define GAME_PANEL_TIMEGATE_SWITCH_TIME                46
+#define GAME_PANEL_SWITCHGATE_SWITCH           47
+#define GAME_PANEL_EMC_LENSES                  48
+#define GAME_PANEL_EMC_LENSES_TIME             49
+#define GAME_PANEL_EMC_MAGNIFIER               50
+#define GAME_PANEL_EMC_MAGNIFIER_TIME          51
+#define GAME_PANEL_BALLOON_SWITCH              52
+#define GAME_PANEL_DYNABOMB_NUMBER             53
+#define GAME_PANEL_DYNABOMB_SIZE               54
+#define GAME_PANEL_DYNABOMB_POWER              55
+#define GAME_PANEL_PENGUINS                    56
+#define GAME_PANEL_SOKOBAN_OBJECTS             57
+#define GAME_PANEL_SOKOBAN_FIELDS              58
+#define GAME_PANEL_ROBOT_WHEEL                 59
+#define GAME_PANEL_CONVEYOR_BELT_1             60
+#define GAME_PANEL_CONVEYOR_BELT_2             61
+#define GAME_PANEL_CONVEYOR_BELT_3             62
+#define GAME_PANEL_CONVEYOR_BELT_4             63
+#define GAME_PANEL_CONVEYOR_BELT_1_SWITCH      64
+#define GAME_PANEL_CONVEYOR_BELT_2_SWITCH      65
+#define GAME_PANEL_CONVEYOR_BELT_3_SWITCH      66
+#define GAME_PANEL_CONVEYOR_BELT_4_SWITCH      67
+#define GAME_PANEL_MAGIC_WALL                  68
+#define GAME_PANEL_MAGIC_WALL_TIME             69
+#define GAME_PANEL_GRAVITY_STATE               70
+#define GAME_PANEL_GRAPHIC_1                   71
+#define GAME_PANEL_GRAPHIC_2                   72
+#define GAME_PANEL_GRAPHIC_3                   73
+#define GAME_PANEL_GRAPHIC_4                   74
+#define GAME_PANEL_GRAPHIC_5                   75
+#define GAME_PANEL_GRAPHIC_6                   76
+#define GAME_PANEL_GRAPHIC_7                   77
+#define GAME_PANEL_GRAPHIC_8                   78
+#define GAME_PANEL_ELEMENT_1                   79
+#define GAME_PANEL_ELEMENT_2                   80
+#define GAME_PANEL_ELEMENT_3                   81
+#define GAME_PANEL_ELEMENT_4                   82
+#define GAME_PANEL_ELEMENT_5                   83
+#define GAME_PANEL_ELEMENT_6                   84
+#define GAME_PANEL_ELEMENT_7                   85
+#define GAME_PANEL_ELEMENT_8                   86
+#define GAME_PANEL_ELEMENT_COUNT_1             87
+#define GAME_PANEL_ELEMENT_COUNT_2             88
+#define GAME_PANEL_ELEMENT_COUNT_3             89
+#define GAME_PANEL_ELEMENT_COUNT_4             90
+#define GAME_PANEL_ELEMENT_COUNT_5             91
+#define GAME_PANEL_ELEMENT_COUNT_6             92
+#define GAME_PANEL_ELEMENT_COUNT_7             93
+#define GAME_PANEL_ELEMENT_COUNT_8             94
+#define GAME_PANEL_CE_SCORE_1                  95
+#define GAME_PANEL_CE_SCORE_2                  96
+#define GAME_PANEL_CE_SCORE_3                  97
+#define GAME_PANEL_CE_SCORE_4                  98
+#define GAME_PANEL_CE_SCORE_5                  99
+#define GAME_PANEL_CE_SCORE_6                  100
+#define GAME_PANEL_CE_SCORE_7                  101
+#define GAME_PANEL_CE_SCORE_8                  102
+#define GAME_PANEL_CE_SCORE_1_ELEMENT          103
+#define GAME_PANEL_CE_SCORE_2_ELEMENT          104
+#define GAME_PANEL_CE_SCORE_3_ELEMENT          105
+#define GAME_PANEL_CE_SCORE_4_ELEMENT          106
+#define GAME_PANEL_CE_SCORE_5_ELEMENT          107
+#define GAME_PANEL_CE_SCORE_6_ELEMENT          108
+#define GAME_PANEL_CE_SCORE_7_ELEMENT          109
+#define GAME_PANEL_CE_SCORE_8_ELEMENT          110
+#define GAME_PANEL_PLAYER_NAME                 111
+#define GAME_PANEL_LEVEL_NAME                  112
+#define GAME_PANEL_LEVEL_AUTHOR                        113
+
+#define NUM_GAME_PANEL_CONTROLS                        114
 
 struct GamePanelOrderInfo
 {
@@ -473,6 +474,11 @@ static struct GamePanelControlInfo game_panel_controls[] =
     &game.panel.time_ss,
     TYPE_INTEGER,
   },
+  {
+    GAME_PANEL_FRAME,
+    &game.panel.frame,
+    TYPE_INTEGER,
+  },
   {
     GAME_PANEL_SHIELD_NORMAL,
     &game.panel.shield_normal,
@@ -2221,17 +2227,25 @@ void UpdateGameControlValues()
              local_player->LevelSolved_CountingTime :
              level.game_engine_type == GAME_ENGINE_TYPE_EM ?
              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);
   int score = (local_player->LevelSolved ?
               local_player->LevelSolved_CountingScore :
               level.game_engine_type == GAME_ENGINE_TYPE_EM ?
               level.native_em_level->lev->score :
+              level.game_engine_type == GAME_ENGINE_TYPE_SP ?
+              level.native_sp_level->game_sp->score :
               local_player->score);
   int gems = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
              level.native_em_level->lev->required :
+             level.game_engine_type == GAME_ENGINE_TYPE_SP ?
+             level.native_sp_level->game_sp->infotrons_still_needed :
              local_player->gems_still_needed);
   int exit_closed = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
                     level.native_em_level->lev->required > 0 :
+                    level.game_engine_type == GAME_ENGINE_TYPE_SP ?
+                    level.native_sp_level->game_sp->infotrons_still_needed > 0 :
                     local_player->gems_still_needed > 0 ||
                     local_player->sokobanfields_still_needed > 0 ||
                     local_player->lights_still_needed > 0);
@@ -2253,6 +2267,10 @@ void UpdateGameControlValues()
   {
     for (i = 0; i < MAX_PLAYERS; i++)
     {
+      /* only one player in Supaplex game engine */
+      if (level.game_engine_type == GAME_ENGINE_TYPE_SP && i > 0)
+       break;
+
       for (k = 0; k < MAX_NUM_KEYS; k++)
       {
        if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
@@ -2269,6 +2287,9 @@ void UpdateGameControlValues()
       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;
@@ -2301,6 +2322,9 @@ void UpdateGameControlValues()
     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;
@@ -2329,6 +2353,8 @@ void UpdateGameControlValues()
   game_panel_controls[GAME_PANEL_TIME_MM].value = (time / 60) % 60;
   game_panel_controls[GAME_PANEL_TIME_SS].value = time % 60;
 
+  game_panel_controls[GAME_PANEL_FRAME].value = FrameCounter;
+
   game_panel_controls[GAME_PANEL_SHIELD_NORMAL].value =
     (local_player->shield_normal_time_left > 0 ? EL_SHIELD_NORMAL_ACTIVE :
      EL_EMPTY);
@@ -3694,6 +3720,15 @@ void InitGame()
 
   game_status = GAME_MODE_PLAYING;
 
+#if 1
+  /* needed if different viewport properties defined for playing */
+  ChangeViewportPropertiesIfNeeded();
+#endif
+
+#if 1
+  DrawCompleteVideoDisplay();
+#endif
+
   InitGameEngine();
   InitGameControlValues();
 
@@ -4468,6 +4503,13 @@ void InitGame()
     /* 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();
@@ -5765,10 +5807,19 @@ void RelocatePlayer(int jx, int jy, int el_player_raw)
   Feld[jx][jy] = el_player;
   InitPlayerField(jx, jy, el_player, TRUE);
 
+  /* "InitPlayerField()" above sets Feld[jx][jy] to EL_EMPTY, but it may be
+     possible that the relocation target field did not contain a player element,
+     but a walkable element, to which the new player was relocated -- in this
+     case, restore that (already initialized!) element on the player field */
   if (!ELEM_IS_PLAYER(element))        /* player may be set on walkable element */
   {
-    Feld[jx][jy] = 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 */
@@ -6116,7 +6167,7 @@ void Explode(int ex, int ey, int phase, int mode)
     TestIfElementTouchesCustomElement(x, y);
 
     if (GFX_CRUMBLED(element))
-      TEST_DrawLevelFieldCrumbledSandNeighbours(x, y);
+      TEST_DrawLevelFieldCrumbledNeighbours(x, y);
 
     if (IS_PLAYER(x, y) && !PLAYERINFO(x, y)->present)
       StorePlayer[x][y] = 0;
@@ -6130,7 +6181,7 @@ void Explode(int ex, int ey, int phase, int mode)
     int frame = getGraphicAnimationFrame(graphic, GfxFrame[x][y]);
 
     if (phase == delay)
-      TEST_DrawLevelFieldCrumbledSand(x, y);
+      TEST_DrawLevelFieldCrumbled(x, y);
 
     if (IS_WALKABLE_OVER(Back[x][y]) && Back[x][y] != EL_EMPTY)
     {
@@ -6588,7 +6639,7 @@ static void RedrawAllLightSwitchesAndInvisibleElements()
 
       /* uncrumble neighbour fields, if needed */
       if (element == EL_INVISIBLE_SAND)
-       TEST_DrawLevelFieldCrumbledSandNeighbours(x, y);
+       TEST_DrawLevelFieldCrumbledNeighbours(x, y);
     }
     else if (element == EL_INVISIBLE_STEELWALL_ACTIVE ||
             element == EL_INVISIBLE_WALL_ACTIVE ||
@@ -6601,7 +6652,7 @@ static void RedrawAllLightSwitchesAndInvisibleElements()
 
       /* re-crumble neighbour fields, if needed */
       if (element == EL_INVISIBLE_SAND)
-       TEST_DrawLevelFieldCrumbledSandNeighbours(x, y);
+       TEST_DrawLevelFieldCrumbledNeighbours(x, y);
     }
   }
 }
@@ -6637,7 +6688,7 @@ static void RedrawAllInvisibleElementsForLenses()
 
       /* uncrumble neighbour fields, if needed */
       if (element == EL_INVISIBLE_SAND)
-       TEST_DrawLevelFieldCrumbledSandNeighbours(x, y);
+       TEST_DrawLevelFieldCrumbledNeighbours(x, y);
     }
     else if (element == EL_INVISIBLE_STEELWALL_ACTIVE ||
             element == EL_INVISIBLE_WALL_ACTIVE ||
@@ -6650,7 +6701,7 @@ static void RedrawAllInvisibleElementsForLenses()
 
       /* re-crumble neighbour fields, if needed */
       if (element == EL_INVISIBLE_SAND)
-       TEST_DrawLevelFieldCrumbledSandNeighbours(x, y);
+       TEST_DrawLevelFieldCrumbledNeighbours(x, y);
     }
   }
 }
@@ -8467,7 +8518,7 @@ void StartMoving(int x, int y)
 
            if (IN_SCR_FIELD(sx, sy))
            {
-             TEST_DrawLevelFieldCrumbledSand(xx, yy);
+             TEST_DrawLevelFieldCrumbled(xx, yy);
              DrawGraphic(sx, sy, flame_graphic, frame);
            }
          }
@@ -8970,7 +9021,7 @@ void ContinueMoving(int x, int y)
   {
     Feld[x][y] = EL_SAND;
 
-    TEST_DrawLevelFieldCrumbledSandNeighbours(x, y);
+    TEST_DrawLevelFieldCrumbledNeighbours(x, y);
   }
   else if (element == EL_QUICKSAND_FILLING)
   {
@@ -9137,7 +9188,7 @@ void ContinueMoving(int x, int y)
     InitField(x, y, FALSE);
 
     if (GFX_CRUMBLED(Feld[x][y]))
-      TEST_DrawLevelFieldCrumbledSandNeighbours(x, y);
+      TEST_DrawLevelFieldCrumbledNeighbours(x, y);
 
     if (ELEM_IS_PLAYER(move_leave_element))
       RelocatePlayer(x, y, move_leave_element);
@@ -10331,7 +10382,7 @@ static void ChangeActiveTrap(int x, int y)
 
   /* if new animation frame was drawn, correct crumbled sand border */
   if (IS_NEW_FRAME(GfxFrame[x][y], graphic))
-    TEST_DrawLevelFieldCrumbledSand(x, y);
+    TEST_DrawLevelFieldCrumbled(x, y);
 }
 
 static int getSpecialActionElement(int element, int number, int base_element)
@@ -11067,7 +11118,7 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change)
     TEST_DrawLevelField(x, y);
 
     if (GFX_CRUMBLED(new_element))
-      TEST_DrawLevelFieldCrumbledSandNeighbours(x, y);
+      TEST_DrawLevelFieldCrumbledNeighbours(x, y);
   }
 
 #if 1
@@ -11976,7 +12027,16 @@ static byte PlayerActions(struct PlayerInfo *player, byte player_action)
 
     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 */
@@ -12013,6 +12073,7 @@ static void CheckLevelTime()
 {
   int i;
 
+  /* !!! SAME CODE AS IN "GameActions()" -- FIX THIS !!! */
   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
   {
     if (level.native_em_level->lev->home == 0) /* all players at home */
@@ -12030,6 +12091,21 @@ static void CheckLevelTime()
        level.native_em_level->ply[3]->alive == 0)      /* all dead */
       AllPlayersGone = TRUE;
   }
+  else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+  {
+    if (game_sp.LevelSolved &&
+       !game_sp.GameOver)                              /* game won */
+    {
+      PlayerWins(local_player);
+
+      game_sp.GameOver = TRUE;
+
+      AllPlayersGone = TRUE;
+    }
+
+    if (game_sp.GameOver)                              /* game lost */
+      AllPlayersGone = TRUE;
+  }
 
   if (TimeFrames >= FRAMES_PER_SECOND)
   {
@@ -12207,6 +12283,7 @@ void GameActions()
   if (game.restart_level)
     StartGameActions(options.network, setup.autorecord, level.random_seed);
 
+  /* !!! SAME CODE AS IN "CheckLevelTime()" -- FIX THIS !!! */
   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
   {
     if (level.native_em_level->lev->home == 0) /* all players at home */
@@ -12224,6 +12301,21 @@ void GameActions()
        level.native_em_level->ply[3]->alive == 0)      /* all dead */
       AllPlayersGone = TRUE;
   }
+  else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+  {
+    if (game_sp.LevelSolved &&
+       !game_sp.GameOver)                              /* game won */
+    {
+      PlayerWins(local_player);
+
+      game_sp.GameOver = TRUE;
+
+      AllPlayersGone = TRUE;
+    }
+
+    if (game_sp.GameOver)                              /* game lost */
+      AllPlayersGone = TRUE;
+  }
 
   if (local_player->LevelSolved && !local_player->LevelSolved_GameEnd)
     GameWon();
@@ -12341,6 +12433,10 @@ void GameActions()
   {
     GameActions_EM_Main();
   }
+  else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+  {
+    GameActions_SP_Main();
+  }
   else
   {
     GameActions_RND();
@@ -12363,6 +12459,22 @@ void GameActions_EM_Main()
   AdvanceFrameAndPlayerCounters(-1);   /* advance counters for all players */
 }
 
+void GameActions_SP_Main()
+{
+  byte effective_action[MAX_PLAYERS];
+  boolean warp_mode = (tape.playing && tape.warp_forward && !tape.pausing);
+  int i;
+
+  for (i = 0; i < MAX_PLAYERS; i++)
+    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()
 {
   int magic_wall_x = 0, magic_wall_y = 0;
@@ -13075,10 +13187,10 @@ void GameActions_RND()
        DrawLevelField(x, y);
 
       if (GfxRedraw[x][y] & GFX_REDRAW_TILE_CRUMBLED)
-       DrawLevelFieldCrumbledSand(x, y);
+       DrawLevelFieldCrumbled(x, y);
 
       if (GfxRedraw[x][y] & GFX_REDRAW_TILE_CRUMBLED_NEIGHBOURS)
-       DrawLevelFieldCrumbledSandNeighbours(x, y);
+       DrawLevelFieldCrumbledNeighbours(x, y);
 
       if (GfxRedraw[x][y] & GFX_REDRAW_TILE_TWINKLED)
        DrawTwinkleOnField(x, y);
@@ -15321,8 +15433,13 @@ 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);
 
@@ -16108,6 +16225,21 @@ void PlayLevelSound_EM(int xx, int yy, int element_em, int sample)
   }
 }
 
+void PlayLevelSound_SP(int xx, int yy, int element_sp, int action_sp)
+{
+  int element = map_element_SP_to_RND(element_sp);
+  int action = map_action_SP_to_RND(action_sp);
+  int offset = (setup.sp_show_border_elements ? 0 : 1);
+  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)
 {
@@ -16331,8 +16463,6 @@ unsigned int RND(int max)
 /* game engine snapshot handling functions                                   */
 /* ------------------------------------------------------------------------- */
 
-#define ARGS_ADDRESS_AND_SIZEOF(x)             (&(x)), (sizeof(x))
-
 struct EngineSnapshotInfo
 {
   /* runtime values for custom element collect score */
@@ -16342,32 +16472,14 @@ struct EngineSnapshotInfo
   int choice_pos[NUM_GROUP_ELEMENTS];
 
   /* runtime values for belt position animations */
-  int belt_graphic[4 * NUM_BELT_PARTS];
-  int belt_anim_mode[4 * NUM_BELT_PARTS];
-};
-
-struct EngineSnapshotNodeInfo
-{
-  void *buffer_orig;
-  void *buffer_copy;
-  int size;
+  int belt_graphic[4][NUM_BELT_PARTS];
+  int belt_anim_mode[4][NUM_BELT_PARTS];
 };
 
 static struct EngineSnapshotInfo engine_snapshot_rnd;
-static ListNode *engine_snapshot_list = NULL;
 static char *snapshot_level_identifier = NULL;
 static int snapshot_level_nr = -1;
 
-void FreeEngineSnapshot()
-{
-  while (engine_snapshot_list != NULL)
-    deleteNodeFromList(&engine_snapshot_list, engine_snapshot_list->key,
-                      checked_free);
-
-  setString(&snapshot_level_identifier, NULL);
-  snapshot_level_nr = -1;
-}
-
 static void SaveEngineSnapshotValues_RND()
 {
   static int belt_base_active_element[4] =
@@ -16401,8 +16513,8 @@ static void SaveEngineSnapshotValues_RND()
       int graphic = el2img(element);
       int anim_mode = graphic_info[graphic].anim_mode;
 
-      engine_snapshot_rnd.belt_graphic[i * 4 + j] = graphic;
-      engine_snapshot_rnd.belt_anim_mode[i * 4 + j] = anim_mode;
+      engine_snapshot_rnd.belt_graphic[i][j] = graphic;
+      engine_snapshot_rnd.belt_anim_mode[i][j] = anim_mode;
     }
   }
 }
@@ -16430,8 +16542,8 @@ static void LoadEngineSnapshotValues_RND()
   {
     for (j = 0; j < NUM_BELT_PARTS; j++)
     {
-      int graphic = engine_snapshot_rnd.belt_graphic[i * 4 + j];
-      int anim_mode = engine_snapshot_rnd.belt_anim_mode[i * 4 + j];
+      int graphic = engine_snapshot_rnd.belt_graphic[i][j];
+      int anim_mode = engine_snapshot_rnd.belt_anim_mode[i][j];
 
       graphic_info[graphic].anim_mode = anim_mode;
     }
@@ -16453,36 +16565,26 @@ static void LoadEngineSnapshotValues_RND()
   }
 }
 
-static void SaveEngineSnapshotBuffer(void *buffer, int size)
-{
-  struct EngineSnapshotNodeInfo *bi =
-    checked_calloc(sizeof(struct EngineSnapshotNodeInfo));
-
-  bi->buffer_orig = buffer;
-  bi->buffer_copy = checked_malloc(size);
-  bi->size = size;
-
-  memcpy(bi->buffer_copy, buffer, size);
-
-  addNodeToList(&engine_snapshot_list, NULL, bi);
-}
-
 void SaveEngineSnapshot()
 {
-  FreeEngineSnapshot();                /* free previous snapshot, if needed */
-
-  if (level_editor_test_game)  /* do not save snapshots from editor */
+  /* do not save snapshots from editor */
+  if (level_editor_test_game)
     return;
 
+  /* free previous snapshot buffers, if needed */
+  FreeEngineSnapshotBuffers();
+
   /* copy some special values to a structure better suited for the snapshot */
 
   SaveEngineSnapshotValues_RND();
   SaveEngineSnapshotValues_EM();
+  SaveEngineSnapshotValues_SP();
 
   /* 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));
 
   /* save further RND engine values */
 
@@ -16556,7 +16658,7 @@ void SaveEngineSnapshot()
   snapshot_level_nr = level_nr;
 
 #if 0
-  ListNode *node = engine_snapshot_list;
+  ListNode *node = engine_snapshot_list_rnd;
   int num_bytes = 0;
 
   while (node != NULL)
@@ -16570,29 +16672,17 @@ void SaveEngineSnapshot()
 #endif
 }
 
-static void LoadEngineSnapshotBuffer(struct EngineSnapshotNodeInfo *bi)
-{
-  memcpy(bi->buffer_orig, bi->buffer_copy, bi->size);
-}
-
 void LoadEngineSnapshot()
 {
-  ListNode *node = engine_snapshot_list;
-
-  if (engine_snapshot_list == NULL)
-    return;
+  /* restore generically stored snapshot buffers */
 
-  while (node != NULL)
-  {
-    LoadEngineSnapshotBuffer((struct EngineSnapshotNodeInfo *)node->content);
-
-    node = node->next;
-  }
+  LoadEngineSnapshotBuffers();
 
   /* restore special values from snapshot structure */
 
   LoadEngineSnapshotValues_RND();
   LoadEngineSnapshotValues_EM();
+  LoadEngineSnapshotValues_SP();
 }
 
 boolean CheckEngineSnapshot()
@@ -16805,10 +16895,8 @@ void RedrawGameButtons()
     RedrawGadget(game_gadget[i]);
 }
 
-static void HandleGameButtons(struct GadgetInfo *gi)
+static void HandleGameButtonsExt(int id)
 {
-  int id = gi->custom_id;
-
   if (game_status != GAME_MODE_PLAYING)
     return;
 
@@ -16854,6 +16942,7 @@ static void HandleGameButtons(struct GadgetInfo *gi)
       if (setup.sound_music)
       { 
        setup.sound_music = FALSE;
+
        FadeMusic();
       }
       else if (audio.music_available)
@@ -16872,6 +16961,7 @@ static void HandleGameButtons(struct GadgetInfo *gi)
       else if (audio.loops_available)
       {
        setup.sound = setup.sound_loops = TRUE;
+
        SetAudioMode(setup.sound);
       }
       break;
@@ -16882,6 +16972,7 @@ static void HandleGameButtons(struct GadgetInfo *gi)
       else if (audio.sound_available)
       {
        setup.sound = setup.sound_simple = TRUE;
+
        SetAudioMode(setup.sound);
       }
       break;
@@ -16890,3 +16981,27 @@ static void HandleGameButtons(struct GadgetInfo *gi)
       break;
   }
 }
+
+static void HandleGameButtons(struct GadgetInfo *gi)
+{
+  HandleGameButtonsExt(gi->custom_id);
+}
+
+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
+}
index 7a9bf984963fd9b76a8cc276605e23c203f0ac41..c764e1d39163d18cf7dd56f5e54215fc7143906b 100644 (file)
@@ -47,6 +47,7 @@ struct GamePanelInfo
   struct TextPosInfo time_hh;
   struct TextPosInfo time_mm;
   struct TextPosInfo time_ss;
+  struct TextPosInfo frame;
   struct TextPosInfo shield_normal;
   struct TextPosInfo shield_normal_time;
   struct TextPosInfo shield_deadly;
@@ -117,6 +118,8 @@ struct GameInfo
 
   /* values for graphics engine customization */
   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;
 
@@ -331,12 +334,14 @@ void StartGameActions(boolean, boolean, long);
 
 void GameActions(void);
 void GameActions_EM_Main();
+void GameActions_SP_Main();
 void GameActions_RND();
 
 void ScrollLevel(int, int);
 
 void InitPlayLevelSound();
 void PlayLevelSound_EM(int, int, int, int);
+void PlayLevelSound_SP(int, int, int, int);
 
 void RaiseScore(int);
 void RaiseScoreElement(int);
@@ -357,4 +362,6 @@ void FreeGameButtons();
 void UnmapGameButtons();
 void RedrawGameButtons();
 
+void HandleSoundButtonKeys(Key);
+
 #endif
index aec69d091a181b622e9c068441192bc77a5534d9..4fc21cd0f12f70d64b654b99203430597c36e5e0 100644 (file)
@@ -1,7 +1,7 @@
 # =============================================================================
 # Rocks'n'Diamonds Makefile (game_em)
 # -----------------------------------------------------------------------------
-# (c) 1995-2005 Holger Schemel <info@artsoft.org>
+# (c) 1995-2006 Holger Schemel <info@artsoft.org>
 # -----------------------------------------------------------------------------
 # Emerald Mine for X11 © 2000,2001 David Tritscher
 # =============================================================================
index 29d9e15d9d19d5ca3f39c1051c87b0028335045f..5764e9e3390ba056584cc75fb41f0c4301c6e27d 100644 (file)
 
 #define USE_EXTENDED_GRAPHICS_ENGINE           1
 
-int frame;                     /* current screen frame */
-int screen_x;                  /* current scroll position */
-int screen_y;
+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
@@ -96,12 +102,21 @@ void BlitScreenToBitmap_EM(Bitmap *target_bitmap)
 
 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)
@@ -114,6 +129,50 @@ void BackToFront_EM(void)
   }
   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++)
@@ -127,6 +186,7 @@ void BackToFront_EM(void)
                     SX + x * TILEX, SY + y * TILEY);
       }
     }
+#endif
   }
 
   FlushDisplay();
@@ -136,6 +196,8 @@ void BackToFront_EM(void)
       redraw[x][y] = FALSE;
   redraw_tiles = 0;
 
+  screen_x_last = screen_x;
+  screen_y_last = screen_y;
   scrolling_last = scrolling;
 }
 
@@ -207,7 +269,11 @@ 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 left = screen_x / TILEX;
   int top  = screen_y / TILEY;
   int i;
@@ -220,6 +286,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",
@@ -433,6 +503,10 @@ 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))
   {
index cc703ba96cb4ab622f7bec3c2e7f7e5a1dd1b5f1..7447f4b1901d4ba642bc4841898c1eb3e3865dfa 100644 (file)
@@ -91,6 +91,7 @@ void GameActions_EM(byte action[MAX_PLAYERS], boolean warp_mode)
     printf("::: %05d: %lu, %d\n", FrameCounter, RandomEM, frame);
 #endif
 
+#if 0
   game_animscreen();
 
 #if 1
@@ -99,6 +100,7 @@ void GameActions_EM(byte action[MAX_PLAYERS], boolean warp_mode)
 #endif
 
   blitscreen();
+#endif
 #endif
 
   RandomEM = RandomEM * 129 + 1;
@@ -124,6 +126,20 @@ void GameActions_EM(byte action[MAX_PLAYERS], boolean warp_mode)
     if (!warp_mode)            /* do not redraw values in warp mode */
       DrawGameDoorValues_EM();
   }
+
+  CheckSingleStepMode_EM(action, frame, game_em.any_player_moving);
+
+#if 1
+  game_animscreen();
+
+#if 1
+#if 0
+  SyncDisplay();
+#endif
+
+  blitscreen();
+#endif
+#endif
 }
 
 /* read input device for players */
index 87e9d9527fb147a470eddbf8684cb25adc0ae20d..c5efc415d4aa717d70d0e5cdcea246d1db89f533 100644 (file)
 #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          (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
-#define SY                     8
+#if 1
+extern int                     SX, SY;
+#else
 #define SX                     8
 #define SY                     8
+#endif
 #define SXSIZE                 (SCR_FIELDX * TILEX)
 #define SYSIZE                 (SCR_FIELDY * TILEY)
 
diff --git a/src/game_sp/ASM.c b/src/game_sp/ASM.c
new file mode 100644 (file)
index 0000000..ae2de3e
--- /dev/null
@@ -0,0 +1,36 @@
+// ----------------------------------------------------------------------------
+// ASM.c
+// ----------------------------------------------------------------------------
+
+#include "ASM.h"
+
+
+void MovLowByte(int *p, int i)
+{
+  *p = (*p & 0xff00) | (i & 0xff);
+}
+
+void MovHighByte(int *p, int i)
+{
+  *p = (*p & 0xff) | ((i << 8) & 0xff00);
+}
+
+int LowByte(int i)
+{
+  return (i & 0xff);
+}
+
+int HighByte(int i)
+{
+  return ((i >> 8) & 0xff);
+}
+
+int SgnHighByte(int i)
+{
+  return (signed char)HighByte(i);
+}
+
+int ByteToInt(byte b)
+{
+  return (signed char)b;
+}
diff --git a/src/game_sp/ASM.h b/src/game_sp/ASM.h
new file mode 100644 (file)
index 0000000..a149c80
--- /dev/null
@@ -0,0 +1,18 @@
+// ----------------------------------------------------------------------------
+// ASM.h
+// ----------------------------------------------------------------------------
+
+#ifndef ASM_H
+#define ASM_H
+
+#include "global.h"
+
+
+extern void MovLowByte(int *, int);
+extern void MovHighByte(int *, int);
+extern int LowByte(int);
+extern int HighByte(int);
+extern int SgnHighByte(int);
+extern int ByteToInt(byte);
+
+#endif /* ASM_H */
diff --git a/src/game_sp/BugsTerminals.c b/src/game_sp/BugsTerminals.c
new file mode 100644 (file)
index 0000000..9485027
--- /dev/null
@@ -0,0 +1,153 @@
+// ----------------------------------------------------------------------------
+// BugsTerminals.c
+// ----------------------------------------------------------------------------
+
+#include "BugsTerminals.h"
+
+
+#if 1
+byte TerminalState[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE];
+#else
+byte *TerminalState;
+#endif
+
+int TerminalMaxCycles;
+
+
+// ==========================================================================
+//                              SUBROUTINE
+// Animate bugs
+// ==========================================================================
+
+void subAnimateBugs(int si)
+{
+  int bl;
+
+  if (fiBug != LowByte(PlayField16[si]))
+    return;
+
+  bl = SgnHighByte(PlayField16[si]);   // get and increment sequence number
+
+  if ((TimerVar & 3) == 0)
+  {
+    bl = bl + 1;
+    if (bl >= 14)                      // bugs animation has 14 frames
+    {
+      bl = subGetRandomNumber();       // generate new random number
+      bl = -((bl & 0x3F) + 0x20);
+    }
+
+    MovHighByte(&PlayField16[si], bl); // save sequence number
+  }
+
+  if (bl < 0)                          // bug sleeps / is inactive
+    return;
+
+  // now the bug is active! Beware Murphy!
+  if ((TimerVar & 3) == 0 &&
+      (LowByte(PlayField16[si - FieldWidth - 1]) == fiMurphy ||
+       LowByte(PlayField16[si - FieldWidth])     == fiMurphy ||
+       LowByte(PlayField16[si - FieldWidth + 1]) == fiMurphy ||
+       LowByte(PlayField16[si - 1])              == fiMurphy ||
+       LowByte(PlayField16[si + 1])              == fiMurphy ||
+       LowByte(PlayField16[si + FieldWidth - 1]) == fiMurphy ||
+       LowByte(PlayField16[si + FieldWidth])     == fiMurphy ||
+       LowByte(PlayField16[si + FieldWidth + 1]) == fiMurphy))
+    subSoundFX(si, fiBug, actActive);          // play dangerous sound
+
+  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  GfxGraphic[GetX(si)][GetY(si)] = (bl == 0  ? aniBugActivating :
+                                   bl == 12 ? aniBugDeactivating :
+                                   bl == 13 ? aniBug : aniBugActive);
+  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+}
+
+
+// ==========================================================================
+//                              SUBROUTINE
+// Animate terminals
+// ==========================================================================
+
+void subAnimateTerminals(int si)
+{
+  int bl;
+
+  int lx = GetX(si);
+  int ly = GetY(si);
+  int graphic;
+
+  if (LowByte(PlayField16[si]) != fiTerminal)
+    return;
+
+  /* use native frame handling (undo frame incrementation in main loop) */
+  if (game.use_native_sp_graphics_engine)
+    GfxFrame[lx][ly]--;
+
+  /* get last random animation delay */
+  bl = SgnHighByte(PlayField16[si]);
+
+  bl = bl + 1;
+  if (bl <= 0)         /* return if random animation delay not yet reached */
+  {
+    MovHighByte(&PlayField16[si], bl);
+
+    return;
+  }
+
+  /* calculate new random animation delay */
+  bl = -(subGetRandomNumber() & TerminalMaxCycles); // generate new random number
+  MovHighByte(&PlayField16[si], bl); // save new sequence number
+
+  /* check terminal state (active or inactive) */
+  bl = TerminalState[si] + 1;
+  if (bl == 8)
+    bl = 0;
+  else if (15 < bl)
+    bl = 8;
+
+  TerminalState[si] = bl;
+
+  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+  graphic = (bl < 8 ? aniTerminal : aniTerminalActive);
+
+  if (game.use_native_sp_graphics_engine)
+    GfxFrame[lx][ly] += getGraphicInfo_Delay(graphic);
+
+  GfxGraphic[lx][ly] = (bl < 8 ? aniTerminal : aniTerminalActive);
+
+  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+}
+
+
+// ==========================================================================
+//                              SUBROUTINE
+// Randomize random number generator
+// ==========================================================================
+
+void subRandomize()
+{
+  long Tick = MyGetTickCount();
+
+  RandomSeed = (Tick ^ (Tick >> 16)) & 0xFFFF;
+}
+
+
+// ==========================================================================
+//                              SUBROUTINE
+// Generate new random number, first method (see also sub_g_8580)
+// ==========================================================================
+
+int subGetRandomNumber()
+{
+  RandomSeed = (RandomSeed * 0x5E5 + 0x31) & 0xFFFF;
+
+  return (RandomSeed >> 1);
+
+  //  Mov ax, randomseed
+  //  Mov bx, &H5E5
+  //  mul bx                          ' dx:ax = reg * ax
+  //  Add ax, &H31
+  //  Mov randomseed, ax
+  //  shr ax,1
+}
diff --git a/src/game_sp/BugsTerminals.h b/src/game_sp/BugsTerminals.h
new file mode 100644 (file)
index 0000000..6145852
--- /dev/null
@@ -0,0 +1,23 @@
+// ----------------------------------------------------------------------------
+// BugsTerminals.h
+// ----------------------------------------------------------------------------
+
+#ifndef BUGSTERMINALS_H
+#define BUGSTERMINALS_H
+
+#include "global.h"
+
+#if 1
+extern byte TerminalState[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE];
+#else
+extern byte *TerminalState;
+#endif
+
+extern int TerminalMaxCycles;
+
+extern void subAnimateBugs(int si);
+extern void subAnimateTerminals(int si);
+extern void subRandomize();
+extern int subGetRandomNumber();
+
+#endif /* BUGSTERMINALS_H */
diff --git a/src/game_sp/DDScrollBuffer.c b/src/game_sp/DDScrollBuffer.c
new file mode 100644 (file)
index 0000000..e8bd2fb
--- /dev/null
@@ -0,0 +1,386 @@
+// ----------------------------------------------------------------------------
+// DDScrollBuffer.c
+// ----------------------------------------------------------------------------
+
+#include "DDScrollBuffer.h"
+
+#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
+
+
+void RestorePlayfield()
+{
+  int x1 = mScrollX / TILEX - 2;
+  int y1 = mScrollY / TILEY - 2;
+  int x2 = mScrollX / TILEX + (SCR_FIELDX - 1) + 2;
+  int y2 = mScrollY / TILEY + (SCR_FIELDY - 1) + 2;
+  int x, y;
+
+  DrawFrameIfNeeded();
+
+  for (y = DisplayMinY; y <= DisplayMaxY; y++)
+  {
+    for (x = DisplayMinX; x <= DisplayMaxX; x++)
+    {
+      if (x >= x1 && x <= x2 && y >= y1 && y <= y2)
+      {
+       DrawFieldNoAnimated(x, y);
+       DrawFieldAnimated(x, y);
+      }
+    }
+  }
+}
+
+static void ScrollPlayfield(int dx, int dy)
+{
+  int x1 = mScrollX_last / TILEX - 2;
+  int y1 = mScrollY_last / TILEY - 2;
+  int x2 = mScrollX_last / TILEX + (SCR_FIELDX - 1) + 2;
+  int y2 = mScrollY_last / TILEY + (SCR_FIELDY - 1) + 2;
+  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;
+
+  DrawFrameIfNeeded();
+
+  for (y = DisplayMinY; y <= DisplayMaxY; y++)
+  {
+    for (x = DisplayMinX; x <= DisplayMaxX; x++)
+    {
+      if (x >= x1 && x <= x2 && y >= y1 && y <= y2)
+      {
+       int sx = x - x1;
+       int sy = y - y1;
+       int tsi = GetSI(x, y);
+       long id = ((PlayField16[tsi]) |
+                  (PlayField8[tsi] << 16) |
+                  (DisPlayField[tsi] << 24));
+
+       if ((dx == -1 && x == x2) ||
+           (dx == +1 && x == x1) ||
+           (dy == -1 && y == y2) ||
+           (dy == +1 && y == y1))
+       {
+         DrawFieldNoAnimated(x, y);
+         DrawFieldAnimated(x, y);
+       }
+
+       ScreenBuffer[sx][sy] = id;
+      }
+    }
+  }
+}
+
+static void ScrollPlayfieldIfNeededExt(boolean reset)
+{
+  if (reset)
+  {
+    mScrollX_last = -1;
+    mScrollY_last = -1;
+
+    return;
+  }
+
+  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;
+  }
+
+  /* check if scrolling the playfield requires redrawing the viewport bitmap */
+  if ((mScrollX != mScrollX_last ||
+       mScrollY != mScrollY_last) &&
+      (ABS(mScrollX - mScrollX_last) >= TILEX ||
+       ABS(mScrollY - mScrollY_last) >= TILEY))
+  {
+    int dx = (ABS(mScrollX - mScrollX_last) < TILEX ? 0 :
+             mScrollX < mScrollX_last ? 1 : mScrollX > mScrollX_last ? -1 : 0);
+    int dy = (ABS(mScrollY - mScrollY_last) < TILEY ? 0 :
+             mScrollY < mScrollY_last ? 1 : mScrollY > mScrollY_last ? -1 : 0);
+
+    mScrollX_last -= dx * TILEX;
+    mScrollY_last -= dy * TILEY;
+
+    ScrollPlayfield(dx, dy);
+  }
+}
+
+static void ScrollPlayfieldIfNeeded()
+{
+  ScrollPlayfieldIfNeededExt(FALSE);
+}
+
+void InitScrollPlayfield()
+{
+  ScrollPlayfieldIfNeededExt(TRUE);
+}
+
+void UpdatePlayfield(boolean force_redraw)
+{
+  int x, y;
+#if 1
+  int num_redrawn = 0;
+#endif
+
+  for (y = DisplayMinY; y <= DisplayMaxY; y++)
+  {
+    for (x = DisplayMinX; x <= DisplayMaxX; x++)
+    {
+      int element = LowByte(PlayField16[GetSI(x, y)]);
+      int graphic = GfxGraphic[x][y];
+      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];
+
+       continue;
+      }
+
+      if (element != GfxElementLast[x][y] &&
+         graphic == GfxGraphicLast[x][y])
+      {
+       /* element changed, but not graphic => disable updating graphic */
+
+       GfxElementLast[x][y] = element;
+       GfxGraphicLast[x][y] = GfxGraphic[x][y] = -1;
+
+       continue;
+      }
+
+      if (graphic != GfxGraphicLast[x][y])                     // new graphic
+      {
+       redraw = TRUE;
+
+       GfxElementLast[x][y] = element;
+       GfxGraphicLast[x][y] = GfxGraphic[x][y];
+       sync_frame = GfxFrame[x][y] = 0;
+      }
+      else if (isNextAnimationFrame_SP(graphic, sync_frame))   // new frame
+      {
+       redraw = TRUE;
+      }
+
+      if (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
+       num_redrawn++;
+#endif
+      }
+    }
+  }
+
+#if 0
+  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
+
+  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
+
+  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)
+    return;
+
+  ScrollX = mScrollX = X;
+  ScrollY = mScrollY = Y;
+
+  ScrollPlayfieldIfNeeded();
+}
+
+void DDScrollBuffer_ScrollTowards(int X, int Y, double Step)
+{
+  double dx, dY, r;
+
+  if (NoDisplayFlag)
+    return;
+
+  dx = X - mScrollX;
+  dY = Y - mScrollY;
+
+  r = Sqr(dx * dx + dY * dY);
+  if (r == 0)  // we are there already
+    return;
+
+  if (Step < r)
+    r = Step / r;
+  else
+    r = 1;
+
+  ScrollX = mScrollX = mScrollX + dx * r;
+  ScrollY = mScrollY = mScrollY + dY * r;
+
+  ScrollPlayfieldIfNeeded();
+}
+
+void DDScrollBuffer_SoftScrollTo(int X, int Y, long TimeMS, int FPS)
+{
+  double dx, dY;
+  long dT, StepCount;
+  double T, tStep;
+  long oldX, oldY, maxD;
+  static boolean AlreadyRunning = False;
+
+  if (NoDisplayFlag)
+    return;
+
+  if (AlreadyRunning)
+    return;
+
+  AlreadyRunning = True;
+
+  dx = X - mScrollX;
+  dY = Y - mScrollY;
+  maxD = (Abs(dx) < Abs(dY) ? Abs(dY) : Abs(dx));
+
+  StepCount = FPS * (TimeMS / (double)1000);
+  if (StepCount > maxD)
+    StepCount = maxD;
+
+  if (StepCount == 0)
+    StepCount = 1;
+
+  dT = 1000 / FPS;
+  tStep = (double)1 / StepCount;
+  oldX = mScrollX;
+  oldY = mScrollY;
+
+  for (T = (double)tStep; T <= (double)1; T += tStep)
+  {
+    ScrollX = mScrollX = oldX + T * dx;
+    ScrollY = mScrollY = oldY + T * dY;
+  }
+
+  ScrollX = mScrollX = X;
+  ScrollY = mScrollY = Y;
+
+  AlreadyRunning = False;
+
+  ScrollPlayfieldIfNeeded();
+}
diff --git a/src/game_sp/DDScrollBuffer.h b/src/game_sp/DDScrollBuffer.h
new file mode 100644 (file)
index 0000000..e34ef21
--- /dev/null
@@ -0,0 +1,31 @@
+// ----------------------------------------------------------------------------
+// DDScrollBuffer.h
+// ----------------------------------------------------------------------------
+
+#ifndef DDSCROLLBUFFER_H
+#define DDSCROLLBUFFER_H
+
+#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 void InitScrollPlayfield();
+extern void UpdatePlayfield();
+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);
+
+#endif /* DDSCROLLBUFFER_H */
diff --git a/src/game_sp/DDSpriteBuffer.c b/src/game_sp/DDSpriteBuffer.c
new file mode 100644 (file)
index 0000000..4683d31
--- /dev/null
@@ -0,0 +1,41 @@
+// ----------------------------------------------------------------------------
+// DDSpriteBuffer.c
+// ----------------------------------------------------------------------------
+
+#include "DDSpriteBuffer.h"
+
+
+static void Blt(int pX, int pY, Bitmap *bitmap, int SpriteX, int SpriteY)
+{
+  int scx = (mScrollX_last < 0 ? 0 : mScrollX_last);
+  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 sx = pX - sx1;
+  int sy = pY - sy1;
+
+  if (NoDisplayFlag)
+    return;
+
+  /* do not draw fields that are outside the visible screen area */
+  if (pX < sx1 || pX > sx2 || pY < sy1 || pY > sy2)
+    return;
+
+  BlitBitmap(bitmap, bitmap_db_field_sp, SpriteX, SpriteY,
+            TILEX, TILEY, sx, sy);
+}
+
+void DDSpriteBuffer_BltImg(int pX, int pY, int graphic, int sync_frame)
+{
+  struct GraphicInfo_SP g;
+
+  if (NoDisplayFlag)
+    return;
+
+  getGraphicSource_SP(&g, graphic, sync_frame, -1, -1);
+
+  Blt(pX, pY, g.bitmap, g.src_x, g.src_y);
+}
diff --git a/src/game_sp/DDSpriteBuffer.h b/src/game_sp/DDSpriteBuffer.h
new file mode 100644 (file)
index 0000000..9872f57
--- /dev/null
@@ -0,0 +1,13 @@
+// ----------------------------------------------------------------------------
+// DDSpriteBuffer.h
+// ----------------------------------------------------------------------------
+
+#ifndef DDSPRITEBUFFER_H
+#define DDSPRITEBUFFER_H
+
+#include "global.h"
+
+
+extern void DDSpriteBuffer_BltImg(int pX, int pY, int graphic, int sync_frame);
+
+#endif /* DDSPRITEBUFFER_H */
diff --git a/src/game_sp/Display.c b/src/game_sp/Display.c
new file mode 100644 (file)
index 0000000..d3bf853
--- /dev/null
@@ -0,0 +1,68 @@
+// ----------------------------------------------------------------------------
+// Display.c
+// ----------------------------------------------------------------------------
+
+#include "Display.h"
+
+
+int ScreenScrollXPos, ScreenScrollYPos;
+
+int ExplosionShake, ExplosionShakeMurphy;
+boolean NoDisplayFlag;
+
+long DisplayMinX, DisplayMaxX;
+long DisplayMinY, DisplayMaxY;
+
+
+void subDisplayLevel()
+{
+  if (NoDisplayFlag || ! LevelLoaded)
+    return;
+
+  DisplayLevel();
+}
+
+void ScrollTo(int X, int Y)
+{
+  if (NoDisplayFlag)
+    return;
+
+  X = ScrollDelta * (X / ScrollDelta);
+  X = Max(X, ScrollMinX);
+  X = Min(X, ScrollMaxX);
+  Y = ScrollDelta * (Y / ScrollDelta);
+  Y = Max(Y, ScrollMinY);
+  Y = Min(Y, ScrollMaxY);
+
+  DDScrollBuffer_ScrollTo(X, Y);
+}
+
+void ScrollTowards(int X, int Y)
+{
+  if (NoDisplayFlag)
+    return;
+
+  X = ScrollDelta * (X / ScrollDelta);
+  X = Max(X, ScrollMinX);
+  X = Min(X, ScrollMaxX);
+  Y = ScrollDelta * (Y / ScrollDelta);
+  Y = Max(Y, ScrollMinY);
+  Y = Min(Y, ScrollMaxY);
+
+  DDScrollBuffer_ScrollTowards(X, Y, 2 * ZoomFactor);
+}
+
+void SoftScrollTo(int X, int Y, long TimeMS, int FPS)
+{
+  if (NoDisplayFlag)
+    return;
+
+  X = ScrollDelta * (X / ScrollDelta);
+  X = Max(X, ScrollMinX);
+  X = Min(X, ScrollMaxX);
+  Y = ScrollDelta * (Y / ScrollDelta);
+  Y = Max(Y, ScrollMinY);
+  Y = Min(Y, ScrollMaxY);
+
+  DDScrollBuffer_SoftScrollTo(X, Y, TimeMS, FPS);
+}
diff --git a/src/game_sp/Display.h b/src/game_sp/Display.h
new file mode 100644 (file)
index 0000000..bc0934f
--- /dev/null
@@ -0,0 +1,24 @@
+// ----------------------------------------------------------------------------
+// Display.h
+// ----------------------------------------------------------------------------
+
+#ifndef DISPLAY_H
+#define DISPLAY_H
+
+#include "global.h"
+
+
+extern int ScreenScrollXPos, ScreenScrollYPos;
+
+extern int ExplosionShake, ExplosionShakeMurphy;
+extern boolean NoDisplayFlag;
+
+extern long DisplayMinX, DisplayMaxX;
+extern long DisplayMinY, DisplayMaxY;
+
+extern void subDisplayLevel();
+extern void ScrollTo(int, int);
+extern void ScrollTowards(int, int);
+extern void SoftScrollTo(int, int, long, int);
+
+#endif /* DISPLAY_H */
diff --git a/src/game_sp/DoGameStuff.c b/src/game_sp/DoGameStuff.c
new file mode 100644 (file)
index 0000000..5575d11
--- /dev/null
@@ -0,0 +1,162 @@
+// ----------------------------------------------------------------------------
+// DoGameStuff.c
+// ----------------------------------------------------------------------------
+
+#include "DoGameStuff.h"
+
+
+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
+
+
+// ==========================================================================
+//                              SUBROUTINE
+// Do game stuff
+// ==========================================================================
+
+void subDoGameStuff()
+{
+  int si, cx, dx, bl;
+
+  subAnimateMurphy(&MurphyPosIndex);       // move Murphy in any direction
+
+  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  // Build a database of locations and subs-to-call of animatable fields only:
+  // Make a snapshot from the field before the animation cycle starts.
+  // first and last line are not animated.
+  si = FieldWidth + 1;
+  cx = LevelMax - 2 * FieldWidth - 1;
+  dx = 0;
+  do // locloop_g_2282:
+  {
+    bl = LowByte(PlayField16[si]);
+    if (((bl & 0xD) != 0) && (bl < 0x20)) // all animatables have 1's in &H0D' above &H1F? (&H1F=explosion!)
+    {
+      if (IsToBeAnimated(bl))
+      {
+        AnimationPosTable[dx] = si;
+        AnimationSubTable[dx] = bl;
+        dx = dx + 1; // count database entries
+      }
+    }
+
+    si = si + 1; // next field
+    cx = cx - 1;
+  }
+  while (0 < cx); // locloop_g_2282' until all lines scanned(not top- and bottom edge)
+
+  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  // Now use the database to animate all animatables the fastest way.
+  // All the other fields are not checked anymore: those have no database entry.
+  // The field from before animation is frozen in the database in order not to
+  // do follow-up animations in the same loop.
+  if (dx != 0) // any database entries?
+  {
+    dx = dx - 1;
+    for (cx = 0; cx <= dx; cx++)
+    {
+      CallAnimation(AnimationPosTable[cx], AnimationSubTable[cx]);
+    } // loop    locloop_g_22B8          ' until all animatables done
+  }
+
+  // All animations are done now
+  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  if (KillMurphyFlag == 1 || MurphyMoveCounter == 0)
+  {
+    if (LeadOutCounter == 0 &&
+       !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:
+}
+
+static boolean IsToBeAnimated(int bl)
+{
+  static boolean IsToBeAnimated;
+
+  switch (bl)
+  {
+    case fiZonk:
+    case fiInfotron:
+    case fiOrangeDisk:
+    case fiSnikSnak:
+    case fiTerminal:
+    case fiElectron:
+    case fiBug:
+    case fiExplosion:
+      IsToBeAnimated = True;
+      break;
+
+    default:
+      IsToBeAnimated = False;
+      break;
+  }
+
+  return IsToBeAnimated;
+}
+
+static void CallAnimation(int si, byte bl)
+{
+  switch (bl)
+  {
+    case fiZonk:
+      subAnimateZonks(si);
+      break;
+
+    case fiInfotron:
+      subAnimateInfotrons(si);
+      break;
+
+    case fiOrangeDisk:
+      subAnimateOrangeDisks(si);
+      break;
+
+    case fiSnikSnak:
+      subAnimateSnikSnaks(si);
+      break;
+
+    case fiTerminal:
+      subAnimateTerminals(si);
+      break;
+
+    case fiElectron:
+      subAnimateElectrons(si);
+      break;
+
+    case fiBug:
+      subAnimateBugs(si);
+      break;
+
+    case fiExplosion:
+      subAnimateExplosion(si);
+      break;
+
+    default:
+      // Debug.Assert(False);
+      break;
+  }
+}
+
diff --git a/src/game_sp/DoGameStuff.h b/src/game_sp/DoGameStuff.h
new file mode 100644 (file)
index 0000000..4cf9818
--- /dev/null
@@ -0,0 +1,20 @@
+// ----------------------------------------------------------------------------
+// DoGameStuff.h
+// ----------------------------------------------------------------------------
+
+#ifndef DOGAMESTUFF_H
+#define DOGAMESTUFF_H
+
+#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();
+
+#endif /* DOGAMESTUFF_H */
diff --git a/src/game_sp/Electrons.c b/src/game_sp/Electrons.c
new file mode 100644 (file)
index 0000000..496e350
--- /dev/null
@@ -0,0 +1,620 @@
+// ----------------------------------------------------------------------------
+// Electrons.c
+// ----------------------------------------------------------------------------
+
+#include "Electrons.h"
+
+
+// ==========================================================================
+//                              SUBROUTINE
+// Animate/move Electrons
+// ==========================================================================
+
+void subAnimateElectrons(int si)
+{
+  int bx, Tmp;
+
+  if (SnikSnaksElectronsFrozen == 1)
+    return;
+
+  if (LowByte(PlayField16[si]) != fiElectron)
+    return;
+
+  bx = HighByte(PlayField16[si]);
+
+  Tmp = bx / 8;
+  switch (Tmp)
+  {
+    case 0:
+      subElectronTurnLeft(si, bx); // turning, bx=0 -> point N, bx = 1 -> point NW etc.
+      break;
+
+    case 1:
+      subElectronTurnRight(si, bx); // turn right
+      break;
+
+    case 2:
+      subElectronFromBelow(si, bx); // access si from below
+      break;
+
+    case 3:
+      subElectronFromRight(si, bx); // access si from right
+      break;
+
+    case 4:
+      subElectronFromAbove(si, bx); // access si from above
+      break;
+
+    case 5:
+      subElectronFromLeft(si, bx); // access si from left
+      break;
+  }
+}
+
+void subDrawAnimatedElectrons(int si)
+{
+  int bx, Tmp;
+
+  // If SnikSnaksElectronsFrozen = 1 Then Exit Function
+  if (LowByte(PlayField16[si]) != fiElectron)
+    return;
+
+  bx = HighByte(PlayField16[si]);
+
+  Tmp = bx / 8;
+  switch (Tmp)
+  {
+    case 0:
+      subDrawElectronTurnLeft(si, bx); // turning, bx=0 -> point N, bx = 1 -> point NW etc.
+      break;
+
+    case 1:
+      subDrawElectronTurnRight(si, bx); // turn right
+      break;
+
+    case 2:
+      subDrawElectronFromBelow(si, bx); // access si from below
+      break;
+
+    case 3:
+      subDrawElectronFromRight(si, bx); // access si from right
+      break;
+
+    case 4:
+      subDrawElectronFromAbove(si, bx); // access si from above
+      break;
+
+    case 5:
+      subDrawElectronFromLeft(si, bx); // access si from left
+      break;
+  }
+}
+
+void subElectronTurnLeft(int si, int bx)
+{
+  int ax, bl;
+
+  ax = (TimerVar & 3);
+  if (ax != 0)
+  {
+    if (ax == 3)
+      goto loc_g_7ACD;
+
+    return;
+  } // loc_g_7A9F:
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  subDrawElectronTurnLeft(si, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+  bx = (bx + 1) & 0x7;
+  MovHighByte(&PlayField16[si], bx);
+
+  return;
+
+loc_g_7ACD:
+  bl = HighByte(PlayField16[si]);
+  if (bl == 0)
+    goto loc_g_7AE6;
+
+  if (bl == 2)
+    goto loc_g_7B05;
+
+  if (bl == 4)
+    goto loc_g_7B24;
+
+  if (bl == 6)
+    goto loc_g_7B43;
+
+  return;
+
+loc_g_7AE6: // pointing up
+  ax = PlayField16[si - FieldWidth];
+  if (ax == 0) // above is empty -> go up
+    goto loc_g_7AF5;
+
+  if (LowByte(ax) == fiMurphy) // above is murphy -> explode
+    ExplodeFieldSP(si);
+
+  return;
+
+loc_g_7AF5: // above is empty -> go up
+  PlayField16[si] = 0x1BB;
+  si = si - FieldWidth; // 1 field up
+  PlayField16[si] = 0x1018;
+
+  return;
+
+loc_g_7B05: // pointing left
+  ax = PlayField16[si - 1];
+  if (ax == 0) // left is empty -> go there
+    goto loc_g_7B14;
+
+  if (LowByte(ax) == fiMurphy) // left is murphy -> explode
+    ExplodeFieldSP(si);
+
+  return;
+
+loc_g_7B14: // left is empty -> go there
+  PlayField16[si] = 0x2BB;
+  si = si - 1; // 1 field left
+  PlayField16[si] = 0x1818;
+
+  return;
+
+loc_g_7B24: // pointing down
+  ax = PlayField16[si + FieldWidth];
+  if (ax == 0) // below is empty -> go down
+    goto loc_g_7B33;
+
+  if (LowByte(ax) == fiMurphy) // below is murphy -> explode
+    ExplodeFieldSP(si);
+
+  return;
+
+loc_g_7B33: // below is empty -> go down
+  PlayField16[si] = 0x3BB;
+  si = si + FieldWidth; // 1 field down
+  PlayField16[si] = 0x2018;
+
+  return;
+
+loc_g_7B43: // pointing Right
+  ax = PlayField16[si + 1];
+  if (ax == 0) // right is empty -> go there
+    goto loc_g_7B55;
+
+  if (LowByte(ax) == fiMurphy) // right is murphy -> explode
+    ExplodeFieldSP(si);
+
+  return;
+
+loc_g_7B55: // right is empty -> go there
+  PlayField16[si] = 0x4BB;
+  si = si + 1; // 1 field right
+  PlayField16[si] = 0x2818;
+}
+
+void subElectronTurnRight(int si, int bx)
+{
+  int ax, bl;
+
+  ax = (TimerVar & 3);
+  if (ax != 0)
+  {
+    if (ax == 3)
+      goto loc_g_7BA3;
+
+    return;
+  } // loc_g_7B73:
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  subDrawElectronTurnRight(si, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+  bx = ((bx + 1) & 0x7) | 8;
+  MovHighByte(&PlayField16[si], bx);
+
+  return;
+
+loc_g_7BA3:
+  bl = HighByte(PlayField16[si]);
+  if (bl == 0x8)
+    goto loc_g_7BBC;
+
+  if (bl == 0xA)
+    goto loc_g_7C19;
+
+  if (bl == 0xC)
+    goto loc_g_7BFA;
+
+  if (bl == 0xE)
+    goto loc_g_7BDB;
+
+  return;
+
+loc_g_7BBC: // pointing up
+  ax = PlayField16[si - FieldWidth];
+  if (ax == 0) // above is empty -> go up
+    goto loc_g_7BCB;
+
+  if (LowByte(ax) == fiMurphy) // above is murphy -> explode
+    ExplodeFieldSP(si);
+
+  return;
+
+loc_g_7BCB: // above is empty -> go up
+  PlayField16[si] = 0x1BB;
+  si = si - FieldWidth; // 1 field up
+  PlayField16[si] = 0x1018;
+
+  return;
+
+loc_g_7BDB: // pointing left
+  ax = PlayField16[si - 1];
+  if (ax == 0) // left is empty -> go there
+    goto loc_g_7BEA;
+
+  if (LowByte(ax) == fiMurphy) // left is murphy -> explode
+    ExplodeFieldSP(si);
+
+  return;
+
+loc_g_7BEA: // left is empty -> go there
+  PlayField16[si] = 0x2BB;
+  si = si - 1; // 1 field left
+  PlayField16[si] = 0x1818;
+
+  return;
+
+loc_g_7BFA: // pointing down
+  ax = PlayField16[si + FieldWidth];
+  if (ax == 0) // below is empty -> go down
+    goto loc_g_7C09;
+
+  if (LowByte(ax) == fiMurphy) // below is murphy -> explode
+    ExplodeFieldSP(si);
+
+  return;
+
+loc_g_7C09: // below is empty -> go down
+  PlayField16[si] = 0x3BB;
+  si = si + FieldWidth; // 1 field down
+  PlayField16[si] = 0x2018;
+
+  return;
+
+loc_g_7C19: // pointing Right
+  ax = PlayField16[si + 1];
+  if (ax == 0) // right is empty -> go there
+    goto loc_g_7C2B;
+
+  if (LowByte(ax) == fiMurphy) // right is murphy -> explode
+    ExplodeFieldSP(si);
+
+  return;
+
+loc_g_7C2B: // right is empty -> go there
+  PlayField16[si] = 0x4BB;
+  si = si + 1; // 1 field right
+  PlayField16[si] = 0x2818;
+}
+
+void subElectronFromBelow(int si, int bx)
+{
+  int ax, bl;
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  subDrawElectronFromBelow(si, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  bx = bx - 0xF;  // get and increment sequence#
+
+  bl = LowByte(bx);
+  if (bl == 7 && LowByte(PlayField16[si + FieldWidth]) != fiExplosion)
+  {
+    PlayField16[si + FieldWidth] = 0; // electron left that field
+  }
+
+  if (bl < 8) // electron still goes up
+  {
+    bl = bl + 0x10;
+    MovHighByte(&PlayField16[si], bl);
+
+    return;
+  } // loc_g_7C84
+
+  PlayField16[si] = 0x18; // sequence#=8 -> arrived at the new field
+  ax = PlayField16[si - 1]; // check left field
+  if (ax == 0 || LowByte(ax) == fiMurphy) // check for empty or murphy
+  {
+    MovHighByte(&PlayField16[si], 1); // start to turn left
+
+    return;
+  } // loc_g_7CA4:
+
+  ax = PlayField16[si - FieldWidth]; // cannot turn left -> check above
+  if (ax == 0) // check if empty
+  {
+    PlayField16[si] = 0x1BB; // mark as "electron leaving"
+    si = si - FieldWidth; // go up!
+    PlayField16[si] = 0x1018;
+
+    return;
+  }
+
+  if (LowByte(ax) == fiMurphy) // check for murphy above
+  {
+    ExplodeFieldSP(si); // Explode
+
+    return;
+  } // loc_g_7CC6:
+
+  ax = PlayField16[si + 1]; // check right field
+  if (ax == 0 || LowByte(ax) == fiMurphy) // check for empty or murphy
+  {
+    MovHighByte(&PlayField16[si], 9); // start to turn right
+
+    return;
+  } // loc_g_7CE0:
+
+  // else: no way to go, start turning around
+  MovHighByte(&PlayField16[si], 1);
+}
+
+void subElectronFromRight(int si, int bx)
+{
+  int ax, bl;
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  subDrawElectronFromRight(si, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  bx = bx - 0x17;  // get and increment sequence#
+
+  bl = LowByte(bx);
+  if (bl == 7 && LowByte(PlayField16[si + 1]) != fiExplosion)
+  {
+    PlayField16[si + 1] = 0; // electron left that field
+  } // loc_g_7D1D:
+
+  if (bl < 8) // sniksnak still goes left
+  {
+    bl = bl + 0x18;
+    MovHighByte(&PlayField16[si], bl);
+
+    return;
+  } // loc_g_7D2A:
+
+  PlayField16[si] = 0x18; // sequence#=8 -> arrived at the new field
+  ax = PlayField16[si + FieldWidth]; // check below
+  if (ax == 0 || LowByte(ax) == fiMurphy) // empty or murphy?
+  {
+    MovHighByte(&PlayField16[si], 3); // yes -> turn left down
+
+    return;
+  } // loc_g_7D4A:
+
+  ax = PlayField16[si - 1]; // check left, etc ... see the comments on subElectronFromBelow()
+  if (ax == 0)
+  {
+    PlayField16[si] = 0x2BB;
+    si = si - 1;                // 1 field left
+    PlayField16[si] = 0x1818;
+
+    return;
+  } // loc_g_7D61:
+
+  if (LowByte(ax) == fiMurphy)
+  {
+    ExplodeFieldSP(si);      // Explode
+
+    return;
+  } // loc_g_7D6C:
+
+  ax = PlayField16[si - FieldWidth]; // check above
+  if (ax == 0 || LowByte(ax) == fiMurphy)
+  {
+    MovHighByte(&PlayField16[si], 0xF);
+
+    return;
+  } // loc_g_7D86:
+
+  MovHighByte(&PlayField16[si], 3);
+}
+
+void subElectronFromAbove(int si, int bx)
+{
+  int ax, bl;
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  subDrawElectronFromAbove(si, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  bx = bx - 0x1F;  // get and increment sequence#
+
+  bl = LowByte(bx);
+  if (bl == 7 && LowByte(PlayField16[si - FieldWidth]) != fiExplosion)
+  {
+    PlayField16[si - FieldWidth] = 0; // electron left that field
+  }
+
+  if (bl < 8) // electron still goes down
+  {
+    bl = bl + 0x20;
+    MovHighByte(&PlayField16[si], bl);
+
+    return;
+  } // loc_g_7DD7
+
+  PlayField16[si] = 0x18; // sequence#=8 -> arrived at the new field
+  ax = PlayField16[si + 1]; // check right
+  if (ax == 0 || LowByte(ax) == fiMurphy)
+  {
+    MovHighByte(&PlayField16[si], 5);
+
+    return;
+  } // loc_g_7DF7:
+
+  ax = PlayField16[si + FieldWidth]; // check below
+  if (ax == 0)
+  {
+    PlayField16[si] = 0x3BB;
+    si = si + FieldWidth;                 // 1 field down
+    PlayField16[si] = 0x2018;
+
+    return;
+  } // loc_g_7E0E:
+
+  if (LowByte(ax) == fiMurphy)
+  {
+    ExplodeFieldSP(si);        // Explode
+
+    return;
+  } // loc_g_7E19:
+
+  ax = PlayField16[si - 1]; // check left
+  if (ax == 0 || LowByte(ax) == fiMurphy)
+  {
+    MovHighByte(&PlayField16[si], 0xD);
+
+    return;
+  } // loc_g_7E33:
+
+  MovHighByte(&PlayField16[si], 5);
+}
+
+void subElectronFromLeft(int si, int bx)
+{
+  int ax, bl;
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  subDrawElectronFromLeft(si, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  bx = bx - 0x27;  // get and increment sequence#
+
+  bl = LowByte(bx);
+  if (bl == 7 && LowByte(PlayField16[si - 1]) != fiExplosion)
+  {
+    PlayField16[si - 1] = 0; // electron left that field
+  }
+
+  if (bl < 8) // electron still goes right
+  {
+    bl = bl + 0x28;
+    MovHighByte(&PlayField16[si], bl);
+
+    return;
+  } // loc_g_7E7E:
+
+  PlayField16[si] = 0x18; // sequence#=8 -> arrived at the new field
+  ax = PlayField16[si - FieldWidth]; // check above
+  if (ax == 0 || LowByte(ax) == fiMurphy)
+  {
+    MovHighByte(&PlayField16[si], 7);
+
+    return;
+  } // loc_g_7E9E:
+
+  ax = PlayField16[si + 1]; // check right(straight on)
+  if (ax == 0)
+  {
+    PlayField16[si] = 0x4BB;
+    si = si + 1;                   // 1 field right
+    PlayField16[si] = 0x2818;
+
+    return;
+  } // loc_g_7EB5:
+
+  if (LowByte(ax) == fiMurphy)
+  {
+    ExplodeFieldSP(si);    // Explode
+
+    return;
+  } // loc_g_7EC0:
+
+  ax = PlayField16[si + FieldWidth]; // check below
+  if (ax == 0 || LowByte(ax) == fiMurphy)
+  {
+    MovHighByte(&PlayField16[si], 0xB);
+
+    return;
+  } // loc_g_7A69:
+
+  MovHighByte(&PlayField16[si], 7);
+}
+
+void subDrawElectronTurnLeft(int si, int bx)
+{
+  int X, Y;
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si);
+  Y = GetStretchY(si);
+  DDSpriteBuffer_BltImg(X, Y, aniElectron, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+}
+
+void subDrawElectronTurnRight(int si, int bx)
+{
+  int X, Y;
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si);
+  Y = GetStretchY(si);
+  DDSpriteBuffer_BltImg(X, Y, aniElectron, 0x10 - bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+}
+
+void subDrawElectronFromBelow(int si, int bx)
+{
+  int X, Y;
+
+  bx = bx - 0xF;  // get and increment sequence#
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si);
+  Y = GetStretchY(si + FieldWidth);
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X, Y - bx * TwoPixels, aniElectron, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+}
+
+void subDrawElectronFromRight(int si, int bx)
+{
+  int X, Y;
+
+  bx = bx - 0x17;  // get and increment sequence#
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si + 1);
+  Y = GetStretchY(si);
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X - bx * TwoPixels, Y, aniElectron, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+}
+
+void subDrawElectronFromAbove(int si, int bx)
+{
+  int X, Y;
+
+  bx = bx - 0x1F;  // get and increment sequence#
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si);
+  Y = GetStretchY(si - FieldWidth);
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X, Y + bx * TwoPixels, aniElectron, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+}
+
+void subDrawElectronFromLeft(int si, int bx)
+{
+  int X, Y;
+
+  bx = bx - 0x27;  // get and increment sequence#
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si - 1);
+  Y = GetStretchY(si);
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X + bx * TwoPixels, Y, aniElectron, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+}
diff --git a/src/game_sp/Electrons.h b/src/game_sp/Electrons.h
new file mode 100644 (file)
index 0000000..2e12dd3
--- /dev/null
@@ -0,0 +1,26 @@
+// ----------------------------------------------------------------------------
+// Electrons.h
+// ----------------------------------------------------------------------------
+
+#ifndef ELECTRONS_H
+#define ELECTRONS_H
+
+#include "global.h"
+
+
+extern void subAnimateElectrons(int);
+extern void subDrawAnimatedElectrons(int);
+extern void subDrawElectronFromAbove(int, int);
+extern void subDrawElectronFromBelow(int, int);
+extern void subDrawElectronFromLeft(int, int);
+extern void subDrawElectronFromRight(int, int);
+extern void subDrawElectronTurnLeft(int, int);
+extern void subDrawElectronTurnRight(int, int);
+extern void subElectronFromAbove(int, int);
+extern void subElectronFromBelow(int, int);
+extern void subElectronFromLeft(int, int);
+extern void subElectronFromRight(int, int);
+extern void subElectronTurnLeft(int, int);
+extern void subElectronTurnRight(int, int);
+
+#endif /* ELECTRONS_H */
diff --git a/src/game_sp/Explosions.c b/src/game_sp/Explosions.c
new file mode 100644 (file)
index 0000000..4eded7b
--- /dev/null
@@ -0,0 +1,353 @@
+// ----------------------------------------------------------------------------
+// Explosions.c
+// ----------------------------------------------------------------------------
+
+#include "Explosions.h"
+
+
+static void LetExplodeFieldSP(int tsi, int cx, int dh);
+static void subExplodeInfotron(int tsi, int cx);
+static void subExplodeZonk(int tsi, int cx);
+
+
+// ==========================================================================
+//                              SUBROUTINE
+// Animate explosion
+// ==========================================================================
+
+void subAnimateExplosion(int si)
+{
+  int ax, bl, X, Y;
+
+  if (LowByte(PlayField16[si]) != fiExplosion)
+    return;
+
+  ax = (TimerVar & 3);
+  if (ax != 0)
+    return;
+
+  bl = HighByte(PlayField16[si]);
+
+  if ((bl & 0x80) != 0) // infotron explosion!
+    goto loc_g_28D0;
+
+  bl = bl + 1;
+  MovHighByte(&PlayField16[si], bl);
+
+  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si);
+  Y = GetStretchY(si);
+  GfxGraphic[GetX(si)][GetY(si)] = aniDefaultExplosion;
+  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+  if (bl == 8)
+  {
+    PlayField16[si] = 0;
+    ExplosionShake = 0;                // nothing explodes
+    // ExplosionShakeMurphy = 0;       // nothing explodes
+
+    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+    GfxGraphic[GetX(si)][GetY(si)] = aniSpace;
+    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  } // loc_ret_g_28CF:
+
+  return;
+
+loc_g_28D0: // explosion produces infotron
+  bl = bl + 1;
+  if (bl == 0x89)
+  {
+    PlayField16[si] = fiInfotron;
+    MovLowByte(&ExplosionShake, 0);            // nothing explodes
+    // MovLowByte(&ExplosionShakeMurphy, 0);   // nothing explodes
+
+    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+    GfxGraphic[GetX(si)][GetY(si)] = aniInfotron;
+    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+    return;
+  } // loc_g_28E3:
+
+  MovHighByte(&PlayField16[si], bl);
+
+  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si);
+  Y = GetStretchY(si);
+  GfxGraphic[GetX(si)][GetY(si)] = aniElectronExplosion;
+  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+}
+
+// ==========================================================================
+//                              SUBROUTINE
+// Explode
+// ==========================================================================
+
+void ExplodeFieldSP(int si)
+{
+  int ax, cx, dl;
+
+  ax = LowByte(PlayField16[si]);
+  if (ax == fiHardWare)
+    return;
+
+  ExplosionShake = 1;          // something explodes
+
+  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)
+  {
+    cx = 0x801F; // produce infotrons
+    dl = 0xF3;
+  }
+  else // loc_g_2977:
+  {
+    cx = 0x1F; // normal explosion
+    dl = 0xD;
+  } // loc_g_297C:
+
+  LetExplodeFieldSP(si - FieldWidth - 1, cx, dl);
+  LetExplodeFieldSP(si - FieldWidth, cx, dl);
+  LetExplodeFieldSP(si - FieldWidth + 1, cx, dl);
+  LetExplodeFieldSP(si - 1, cx, dl);
+  PlayField16[si] = cx;
+  LetExplodeFieldSP(si + 1, cx, dl);
+  LetExplodeFieldSP(si + FieldWidth - 1, cx, dl);
+  LetExplodeFieldSP(si + FieldWidth, cx, dl);
+  LetExplodeFieldSP(si + FieldWidth + 1, cx, dl);
+
+  GfxGraphic[GetX(si)][GetY(si)] = -1;         // restart for chain-explosions
+
+  // loc_g_2C3B:
+  subSoundFX(si, ax, actExploding);
+}
+
+static void LetExplodeFieldSP(int tsi, int cx, int dh)
+{
+  int al;
+
+  if (tsi < (-FieldWidth))
+    return;
+
+  al = LowByte(PlayField16[tsi]);
+  switch (al)
+  {
+    case fiHardWare:
+      return;
+
+      break;
+
+    case fiOrangeDisk:
+    case fiYellowDisk:
+    case fiSnikSnak:
+      PlayField8[tsi] = dh;
+      PlayField16[tsi] = cx;
+      break;
+
+    case fiZonk:
+      subExplodeZonk(tsi, cx);
+      break;
+
+    case fiInfotron:
+      subExplodeInfotron(tsi, cx);
+      break;
+
+    case fiElectron:
+      PlayField8[tsi] = (-dh) & 0xFF;
+      PlayField16[tsi] = 0x801F;
+      break;
+
+    case fiMurphy:
+#if 0
+      printf("::: Explosions.c: LetExplodeFieldSP(): killing murphy [%d]\n",
+            tsi);
+#endif
+
+      KillMurphyFlag = 1;
+      PlayField8[tsi] = dh;
+      PlayField16[tsi] = cx;
+      break;
+
+    default:
+      PlayField16[tsi] = cx;
+      break;
+  }
+
+  GfxGraphic[GetX(tsi)][GetY(tsi)] = -1;       // restart for chain-explosions
+}
+
+static void subExplodeZonk(int tsi, int cx)
+{
+  int ah;
+
+  ah = HighByte(PlayField16[tsi]) & 0xF0;
+  PlayField16[tsi] = cx;
+  switch (ah)
+  {
+    case 0x10:
+    case 0x70:
+      subClearFieldDueToExplosion(tsi - FieldWidth);
+      tsi = tsi + FieldWidth;
+      if (PlayField16[tsi] == 0x9999)
+        subClearFieldDueToExplosion(tsi);
+
+      break;
+
+    case 0x20:
+      subClearFieldDueToExplosion(tsi + 1);
+      subClearFieldDueToExplosion(tsi + FieldWidth);
+      break;
+
+    case 0x30:
+      subClearFieldDueToExplosion(tsi - 1);
+      subClearFieldDueToExplosion(tsi + FieldWidth);
+      break;
+
+    case 0x50:
+      subClearFieldDueToExplosion(tsi - 1);
+      break;
+
+    case 0x60:
+      subClearFieldDueToExplosion(tsi + 1);
+      break;
+
+    case 0xFF000070: // !!! 0x70; this will never be reached! ...??
+      subClearFieldDueToExplosion(tsi + FieldWidth);
+      break;
+  }
+}
+
+static void subExplodeInfotron(int tsi, int cx)
+{
+  int ah;
+
+  ah = HighByte(PlayField16[tsi]) & 0xF0;
+  PlayField16[tsi] = cx;
+  switch (ah)
+  {
+    case 0x10:
+    case 0x70:
+      subClearFieldDueToExplosion(tsi - FieldWidth);
+      tsi = tsi + FieldWidth;
+      if (PlayField16[tsi] == 0x9999)
+        subClearFieldDueToExplosion(tsi);
+
+      break;
+
+    case 0x20:
+      subClearFieldDueToExplosion(tsi + 1);
+      tsi = tsi + FieldWidth; // differnt from zonk version
+      if (PlayField16[tsi] == 0x9999)
+        subClearFieldDueToExplosion(tsi);
+
+      break;
+
+    case 0x30:
+      subClearFieldDueToExplosion(tsi - 1);
+      tsi = tsi + FieldWidth; // differnt from zonk version
+      if (PlayField16[tsi] == 0x9999)
+        subClearFieldDueToExplosion(tsi);
+
+      break;
+
+    case 0x50:
+      subClearFieldDueToExplosion(tsi - 1);
+      break;
+
+    case 0x60:
+      subClearFieldDueToExplosion(tsi + 1);
+      break;
+
+    case 0xFF000070: // !!! 0x70; this will never be reached! ...??
+      subClearFieldDueToExplosion(tsi + FieldWidth);
+      break;
+  }
+}
+
+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;
+  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+}
+
+void subRedDiskReleaseExplosion()
+{
+  int al, X, Y, si;
+
+  al = RedDiskReleasePhase;            // Red disk release phase
+  if (al <= 1)
+    return;
+
+  si = RedDiskReleaseMurphyPos;
+  if (PlayField16[si] == 0) // Release red disk
+    PlayField16[si] = fiRedDisk;
+
+  // +++++++++++++++++++++++++++++++++++++++++
+  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;
+  if (RedDiskReleasePhase >= 0x28)
+  {
+    // si = RedDiskReleaseMurphyPos           ' Red disk was released here
+    ExplodeFieldSP(si);                 // Explode
+    RedDiskReleasePhase = 0;
+  }
+}
+
+void subFollowUpExplosions()
+{
+  int ax, si;
+
+  // locloop_g_2919:
+  for (si = 0; si <= LevelMax; si++)
+  {
+    ax = ByteToInt(PlayField8[si]);
+    if (ax != 0)
+    {
+      if (ax < 0)
+      {
+        ax = ax + 1;
+        PlayField8[si] = ax & 0xFF;
+        if (ax == 0)
+        {
+          PlayField16[si] = 0xFF18;
+          ExplodeFieldSP(si);                 // Explode
+        }
+      }
+      else
+      {
+        ax = ax - 1;
+        PlayField8[si] = ax;
+        if (ax == 0)
+          ExplodeFieldSP(si);
+      }
+    }
+  }
+}
diff --git a/src/game_sp/Explosions.h b/src/game_sp/Explosions.h
new file mode 100644 (file)
index 0000000..b62ea8b
--- /dev/null
@@ -0,0 +1,17 @@
+// ----------------------------------------------------------------------------
+// Explosions.h
+// ----------------------------------------------------------------------------
+
+#ifndef EXPLOSIONS_H
+#define EXPLOSIONS_H
+
+#include "global.h"
+
+
+extern void ExplodeFieldSP(int);
+extern void subAnimateExplosion(int);
+extern void subClearFieldDueToExplosion(int);
+extern void subFollowUpExplosions();
+extern void subRedDiskReleaseExplosion();
+
+#endif /* EXPLOSIONS_H */
diff --git a/src/game_sp/Globals.c b/src/game_sp/Globals.c
new file mode 100644 (file)
index 0000000..e34d196
--- /dev/null
@@ -0,0 +1,247 @@
+// ----------------------------------------------------------------------------
+// Globals.c
+// ----------------------------------------------------------------------------
+
+#include "Globals.h"
+
+
+boolean LevelLoaded;
+
+boolean DemoAvailable;
+boolean menBorder;
+
+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
+
+int TimerVar;
+#if 1
+short RandomSeed;
+#else
+int RandomSeed;
+#endif
+
+int FreezeZonks;
+
+LevelInfoType LInfo;
+
+int ScrollMinX, ScrollMaxX, ScrollMinY, ScrollMaxY;
+int ScrollX, ScrollY;
+
+int MurphyPosIndex, MurphyXPos, MurphyYPos;
+int MurphyScreenXPos, MurphyScreenYPos;
+int MurphyExplodePos, SplitMoveFlag, RedDiskReleaseMurphyPos;
+int KillMurphyFlag, MurphyMoveCounter;
+long YawnSleepCounter;
+int MurphyVarFaceLeft;
+int ScratchGravity, GravityFlag;
+int RedDiskReleaseFlag, MovingPictureSequencePhase;
+
+int YellowDisksExploded;
+int AllowRedDiskCheat, AllowEatRightRedDiskBug;
+
+int GameBusyFlag;
+int InfotronsNeeded, TotalInfotronsNeeded;
+int RedDiskCount;
+int SnikSnaksElectronsFrozen;
+
+int DemoKeyCode;
+
+int RedDiskReleasePhase;
+
+int fiGraphic[] =
+{
+  aniSpace,
+  aniZonk,
+  aniBase,
+  aniMurphy,
+  aniInfotron,
+  aniRAM,
+  aniHardWare,
+  aniExit,
+  aniOrangeDisk,
+  aniPortRight,
+  aniPortDown,
+  aniPortLeft,
+  aniPortUp,
+  aniSpPortRight,
+  aniSpPortDown,
+  aniSpPortLeft,
+  aniSpPortUp,
+  aniSnikSnak,
+  aniYellowDisk,
+  aniTerminal,
+  aniRedDisk,
+  aniPortUpAndDown,
+  aniPortLeftAndRight,
+  aniPortAllDirections,
+  aniElectron,
+  aniBug,
+  aniRAMLeft,
+  aniRAMRight,
+  aniHW0,
+  aniHW1,
+  aniHW2,
+  aniHW3,
+  aniHW4,
+  aniHW5,
+  aniHW6,
+  aniHW7,
+  aniHW8,
+  aniHW9,
+  aniRAMTop,
+  aniRAMBottom,
+  aniWallSpace
+};
+
+int aniSnikSnakTurningLeft[] =
+{
+  aniSnikSnakTurnUpToLeft,
+  aniSnikSnakTurnLeftToDown,
+  aniSnikSnakTurnDownToRight,
+  aniSnikSnakTurnRightToUp
+};
+
+int aniSnikSnakTurningRight[] =
+{
+  aniSnikSnakTurnUpToRight,
+  aniSnikSnakTurnRightToDown,
+  aniSnikSnakTurnDownToLeft,
+  aniSnikSnakTurnLeftToUp
+};
+
+
+int getSequenceLength(int sequence)
+{
+  switch (sequence)
+  {
+    case aniBug:
+      return 14;
+
+    case aniElectron:
+    case aniExplosion:
+      return 9;
+
+    case aniTouchInfotron:
+      return 7;
+
+    case aniMurphyExit:
+      return 40;
+
+    case aniRedDisk:
+      return 1;
+
+    default:
+      return 8;
+  }
+}
+
+boolean isSnappingSequence(int sequence)
+{
+  switch (sequence)
+  {
+    case aniTouchBase:
+    case aniTouchInfotron:
+    case aniTouchRedDisk:
+      return TRUE;
+
+    default:
+      return FALSE;
+  }
+}
+
+void InitGlobals()
+{
+  AutoScrollFlag = True;
+  FreezeZonks = 0;
+  LevelLoaded = False;
+  FieldWidth = 60;
+  FieldHeight = 24;
+  HeaderSize = 96;
+  FieldMax = (FieldWidth * FieldHeight) + HeaderSize - 1;
+  LevelMax = (FieldWidth * FieldHeight) - 1;
+  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
+}
+
+int GetSI(int X, int Y)
+{
+  return Y * FieldWidth + X;
+}
+
+int GetX(int si)
+{
+  return si % FieldWidth;
+}
+
+int GetY(int si)
+{
+  return si / FieldWidth;
+}
+
+int GetStretchX(int si)
+{
+  return StretchWidth * (si % FieldWidth);
+}
+
+int GetStretchY(int si)
+{
+  return StretchWidth * (si / FieldWidth);
+}
+
+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);
+}
+
+int Max(int A, int B)
+{
+  return (A < B ? B : A);
+}
diff --git a/src/game_sp/Globals.h b/src/game_sp/Globals.h
new file mode 100644 (file)
index 0000000..05d4cd7
--- /dev/null
@@ -0,0 +1,339 @@
+// ----------------------------------------------------------------------------
+// Globals.h
+// ----------------------------------------------------------------------------
+
+#ifndef GLOBALS_H
+#define GLOBALS_H
+
+#include "global.h"
+
+
+#ifndef False
+#define False                          0
+#define True                           (!False)
+#endif
+
+#define ScrollDelta                    ((long)1)
+
+#define ZoomFactor                     (2)
+
+#define StretchWidth                   (ZoomFactor * 16)
+#define TwoPixels                      (ZoomFactor * 2)
+
+
+// ----------------------------------------------------------------------------
+// elements (stored in file and playfield)
+// ----------------------------------------------------------------------------
+
+#define fiSpace                                (0)
+#define fiZonk                         (1)
+#define fiBase                         (2)
+#define fiMurphy                       (3)
+#define fiInfotron                     (4)
+#define fiRAM                          (5)
+#define fiHardWare                     (6)
+#define fiExit                         (7)
+#define fiOrangeDisk                   (8)
+#define fiPortRight                    (9)
+#define fiPortDown                     (10)
+#define fiPortLeft                     (11)
+#define fiPortUp                       (12)
+#define fiSpPortRight                  (13)
+#define fiSpPortDown                   (14)
+#define fiSpPortLeft                   (15)
+#define fiSpPortUp                     (16)
+#define fiSnikSnak                     (17)
+#define fiYellowDisk                   (18)
+#define fiTerminal                     (19)
+#define fiRedDisk                      (20)
+#define fiPortUpAndDown                        (21)
+#define fiPortLeftAndRight             (22)
+#define fiPortAllDirections            (23)
+#define fiElectron                     (24)
+#define fiBug                          (25)
+#define fiRAMLeft                      (26)
+#define fiRAMRight                     (27)
+#define fiHWFirst                      (28)
+#define fiHW0                          (fiHWFirst + 0)         // fiHWFirst
+#define fiHW1                          (fiHWFirst + 1)
+#define fiHW2                          (fiHWFirst + 2)
+#define fiHW3                          (fiHWFirst + 3)
+#define fiHW4                          (fiHWFirst + 4)
+#define fiHW5                          (fiHWFirst + 5)
+#define fiHW6                          (fiHWFirst + 6)
+#define fiHW7                          (fiHWFirst + 7)
+#define fiHW8                          (fiHWFirst + 8)
+#define fiHW9                          (fiHWFirst + 9)         // fiHWLast
+#define fiHWLast                       (37)
+#define fiRAMTop                       (38)
+#define fiRAMBottom                    (39)
+#define fiWallSpace                    (40)
+
+#define fiExplosion                    (0x1F)
+
+#define fiFirst                                (0)
+#define fiLast                         (40)
+
+
+// ----------------------------------------------------------------------------
+// graphics and animations (used at runtime to display the elements)
+// ----------------------------------------------------------------------------
+
+// graphics and animations directly related to file elements
+
+#define aniSpace                       IMG_EMPTY_SPACE
+#define aniZonk                                IMG_SP_ZONK
+#define aniBase                                IMG_SP_BASE
+#define aniMurphy                      IMG_SP_MURPHY
+#define aniInfotron                    IMG_SP_INFOTRON
+#define aniRAM                         IMG_SP_CHIP_SINGLE
+#define aniHardWare                    IMG_SP_HARDWARE_GRAY
+#define aniExit                                IMG_SP_EXIT_CLOSED
+#define aniOrangeDisk                  IMG_SP_DISK_ORANGE
+#define aniPortRight                   IMG_SP_PORT_RIGHT
+#define aniPortDown                    IMG_SP_PORT_DOWN
+#define aniPortLeft                    IMG_SP_PORT_LEFT
+#define aniPortUp                      IMG_SP_PORT_UP
+#define aniSpPortRight                 IMG_SP_GRAVITY_PORT_RIGHT
+#define aniSpPortDown                  IMG_SP_GRAVITY_PORT_DOWN
+#define aniSpPortLeft                  IMG_SP_GRAVITY_PORT_LEFT
+#define aniSpPortUp                    IMG_SP_GRAVITY_PORT_UP
+#define aniSnikSnak                    IMG_SP_SNIKSNAK
+#define aniYellowDisk                  IMG_SP_DISK_YELLOW
+#define aniTerminal                    IMG_SP_TERMINAL
+#define aniRedDisk                     IMG_SP_DISK_RED
+#define aniPortUpAndDown               IMG_SP_PORT_VERTICAL
+#define aniPortLeftAndRight            IMG_SP_PORT_HORIZONTAL
+#define aniPortAllDirections           IMG_SP_PORT_ANY
+#define aniElectron                    IMG_SP_ELECTRON
+#define aniBug                         IMG_SP_BUGGY_BASE
+#define aniRAMLeft                     IMG_SP_CHIP_LEFT
+#define aniRAMRight                    IMG_SP_CHIP_RIGHT
+#define aniHWFirst                     IMG_SP_HARDWARE_BASE_1
+#define aniHW0                         IMG_SP_HARDWARE_BASE_1
+#define aniHW1                         IMG_SP_HARDWARE_GREEN
+#define aniHW2                         IMG_SP_HARDWARE_BLUE
+#define aniHW3                         IMG_SP_HARDWARE_RED
+#define aniHW4                         IMG_SP_HARDWARE_YELLOW
+#define aniHW5                         IMG_SP_HARDWARE_BASE_2
+#define aniHW6                         IMG_SP_HARDWARE_BASE_3
+#define aniHW7                         IMG_SP_HARDWARE_BASE_4
+#define aniHW8                         IMG_SP_HARDWARE_BASE_5
+#define aniHW9                         IMG_SP_HARDWARE_BASE_6
+#define aniHWLast                      IMG_SP_HARDWARE_BASE_6
+#define aniRAMTop                      IMG_SP_CHIP_TOP
+#define aniRAMBottom                   IMG_SP_CHIP_BOTTOM
+#define aniWallSpace                   IMG_INVISIBLE_WALL
+#define aniHWTrash1                    
+#define aniHWTrash2                    
+#define aniHWMurphy                    
+
+
+// graphics and animations related to in-game animations for element actions
+
+#define aniMurphyDropping              IMG_SP_MURPHY_DROPPING
+
+#define aniMurphySleepLeft             IMG_SP_MURPHY_SLEEPING_LEFT
+#define aniMurphySleepRight            IMG_SP_MURPHY_SLEEPING_RIGHT
+#define aniMurphyTouchLeft             IMG_SP_MURPHY_SNAPPING_LEFT
+#define aniMurphyTouchRight            IMG_SP_MURPHY_SNAPPING_RIGHT
+#define aniMurphyTouchUp               IMG_SP_MURPHY_SNAPPING_UP
+#define aniMurphyTouchDown             IMG_SP_MURPHY_SNAPPING_DOWN
+#define aniMurphyYawn                  IMG_SP_MURPHY_BORING_1
+#define aniPushLeft                    IMG_SP_MURPHY_PUSHING_LEFT
+#define aniPushRight                   IMG_SP_MURPHY_PUSHING_RIGHT
+
+#define aniBugActivating               IMG_SP_BUGGY_BASE_ACTIVATING
+#define aniBugDeactivating             IMG_SP_BUGGY_BASE_ACTIVATING
+#define aniBugActive                   IMG_SP_BUGGY_BASE_ACTIVE
+#define aniZonkRollLeft                        IMG_SP_ZONK_MOVING_LEFT
+#define aniZonkRollRight               IMG_SP_ZONK_MOVING_RIGHT
+#define aniEatInfotronLeft             IMG_SP_MURPHY_COLLECTING_LEFT
+#define aniEatInfotronRight            IMG_SP_MURPHY_COLLECTING_RIGHT
+#define aniInfotronRollLeft            IMG_SP_INFOTRON_MOVING_LEFT
+#define aniInfotronRollRight           IMG_SP_INFOTRON_MOVING_RIGHT
+#define aniMurphyMoveLeft              IMG_SP_MURPHY_MOVING_LEFT
+#define aniMurphyMoveRight             IMG_SP_MURPHY_MOVING_RIGHT
+#define aniMurphyMoveUpLeft            IMG_SP_MURPHY_MOVING_LEFT
+#define aniMurphyMoveUpRight           IMG_SP_MURPHY_MOVING_RIGHT
+#define aniMurphyDigLeft               IMG_SP_MURPHY_DIGGING_LEFT
+#define aniMurphyDigRight              IMG_SP_MURPHY_DIGGING_RIGHT
+#define aniMurphyDigUpLeft             IMG_SP_MURPHY_DIGGING_LEFT
+#define aniMurphyDigUpRight            IMG_SP_MURPHY_DIGGING_RIGHT
+#define aniMurphyEatLeft               IMG_SP_MURPHY_COLLECTING_LEFT
+#define aniMurphyEatRight              IMG_SP_MURPHY_COLLECTING_RIGHT
+#define aniMurphyEatUpLeft             IMG_SP_MURPHY_COLLECTING_LEFT
+#define aniMurphyEatUpRight            IMG_SP_MURPHY_COLLECTING_RIGHT
+#define aniSplitUpDown                 IMG_SP_MURPHY
+#define aniMurphyExit                  IMG_SP_MURPHY_SHRINKING
+#define aniElectron                    IMG_SP_ELECTRON
+#define aniExplosion                   IMG_SP_DEFAULT_EXPLODING
+#define aniTouchBase                   IMG_SP_BASE_SNAPPING
+#define aniTouchInfotron               IMG_SP_INFOTRON_COLLECTING
+#define aniTouchRedDisk                        IMG_SP_DISK_RED_COLLECTING
+#define aniYellowDisk                  IMG_SP_DISK_YELLOW
+#define aniOrangeDisk                  IMG_SP_DISK_ORANGE
+#define aniRedDisk                     IMG_SP_DISK_RED
+
+#define aniSnikSnakDown                        IMG_SP_SNIKSNAK_DOWN
+#define aniSnikSnakLeft                        IMG_SP_SNIKSNAK_LEFT
+#define aniSnikSnakRight               IMG_SP_SNIKSNAK_RIGHT
+#define aniSnikSnakUp                  IMG_SP_SNIKSNAK_UP
+
+#define aniSnikSnakTurnLeftToUp                IMG_SP_SNIKSNAK_TURNING_FROM_LEFT_UP
+#define aniSnikSnakTurnLeftToDown      IMG_SP_SNIKSNAK_TURNING_FROM_LEFT_DOWN
+#define aniSnikSnakTurnRightToUp       IMG_SP_SNIKSNAK_TURNING_FROM_RIGHT_UP
+#define aniSnikSnakTurnRightToDown     IMG_SP_SNIKSNAK_TURNING_FROM_RIGHT_DOWN
+#define aniSnikSnakTurnUpToLeft                IMG_SP_SNIKSNAK_TURNING_FROM_UP_LEFT
+#define aniSnikSnakTurnUpToRight       IMG_SP_SNIKSNAK_TURNING_FROM_UP_RIGHT
+#define aniSnikSnakTurnDownToLeft      IMG_SP_SNIKSNAK_TURNING_FROM_DOWN_LEFT
+#define aniSnikSnakTurnDownToRight     IMG_SP_SNIKSNAK_TURNING_FROM_DOWN_RIGHT
+
+#define aniTerminalActive              IMG_SP_TERMINAL_ACTIVE
+
+#define aniDefaultExplosion            IMG_SP_DEFAULT_EXPLODING
+#define aniElectronExplosion           IMG_SP_ELECTRON_EXPLODING
+
+#define imgFrameCorner                 IMG_SP_FRAME_CORNER
+#define imgFrameHorizontal             IMG_SP_FRAME_HORIZONTAL
+#define imgFrameVertical               IMG_SP_FRAME_VERTICAL
+
+
+// ----------------------------------------------------------------------------
+// input keys
+// ----------------------------------------------------------------------------
+
+#define keyNone                                (0)
+#define keyUp                          (1)
+#define keyLeft                                (2)
+#define keyDown                                (3)
+#define keyRight                       (4)
+#define keySpaceUp                     (5)
+#define keySpaceLeft                   (6)
+#define keySpaceDown                   (7)
+#define keySpaceRight                  (8)
+#define keySpace                       (9)
+
+
+// ----------------------------------------------------------------------------
+// data structures
+// ----------------------------------------------------------------------------
+
+#ifndef HAS_LevelDescriptor
+typedef struct
+{
+  int Width;
+  int Height;
+  long OffSet;
+  long Size;
+} LevelDescriptor;
+#define HAS_LevelDescriptor
+#endif
+
+#ifndef HAS_SpecialPortType
+typedef struct
+{
+  short PortLocation; // = 2*(x+(y*60))
+  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
+  byte UnUsed;
+} SpecialPortType;
+#define HAS_SpecialPortType
+#endif
+
+#ifndef HAS_LevelInfoType
+typedef struct
+{
+  byte UnUsed[4];
+  byte InitialGravity; // 1=on, anything else (0) = off
+  byte Version; // SpeedFixVersion XOR &H20
+  char LevelTitle[23];
+  byte InitialFreezeZonks; // 2=on, anything else (0) = off.  (1=off too!)
+  byte InfotronsNeeded;
+
+  // 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 then result in 0-to-eat, etc.!)
+  byte SpecialPortCount; // Maximum 10 allowed!
+  SpecialPortType SpecialPort[10];
+  byte SpeedByte; // = Speed XOR Highbyte(RandomSeed)
+  byte CheckSumByte; // = CheckSum XOR SpeedByte
+  short DemoRandomSeed;
+} LevelInfoType;
+#define HAS_LevelInfoType
+#endif
+
+
+extern int GetSI(int X, int Y);
+extern int GetStretchX(int si);
+extern int GetStretchY(int si);
+extern int GetX(int si);
+extern int GetY(int si);
+extern void InitGlobals();
+
+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);
+
+extern int fiGraphic[];
+extern int aniSnikSnakTurningLeft[];
+extern int aniSnikSnakTurningRight[];
+
+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 int FieldHeight;
+extern int FieldMax, LevelMax;
+extern int FieldWidth;
+extern int FreezeZonks;
+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;
+
+extern int AllowRedDiskCheat, AllowEatRightRedDiskBug;
+extern int Data_SubRest, Data_SubRstFlg;
+extern int DemoKeyCode;
+extern int GameBusyFlag;
+extern int InfotronsNeeded, TotalInfotronsNeeded;
+extern int KillMurphyFlag, MurphyMoveCounter;
+extern int MurphyExplodePos, SplitMoveFlag, RedDiskReleaseMurphyPos;
+extern int MurphyPosIndex, MurphyXPos, MurphyYPos;
+extern int MurphyScreenXPos, MurphyScreenYPos;
+extern int MurphyVarFaceLeft;
+extern int RedDiskCount;
+extern int RedDiskReleaseFlag, MovingPictureSequencePhase;
+extern int RedDiskReleasePhase;
+extern int ScratchGravity, GravityFlag;
+extern int SnikSnaksElectronsFrozen;
+extern int YellowDisksExploded;
+extern long YawnSleepCounter;
+
+#endif /* GLOBALS_H */
diff --git a/src/game_sp/Infotrons.c b/src/game_sp/Infotrons.c
new file mode 100644 (file)
index 0000000..c671c60
--- /dev/null
@@ -0,0 +1,454 @@
+// ----------------------------------------------------------------------------
+// Infotrons.c
+// ----------------------------------------------------------------------------
+
+#include "Infotrons.h"
+
+
+// ==========================================================================
+//                              SUBROUTINE
+// Animate Infotrons (falling)
+// ==========================================================================
+
+void subAnimateInfotrons(int si)
+{
+  int tFld;
+
+  int ax, bx, dx, X, Y;
+  int al, bl;
+
+  tFld = PlayField16[si];
+  if ((tFld & 0xFF) != fiInfotron)
+    return;
+
+  if (tFld == fiInfotron)
+  {
+    ax = PlayField16[si + FieldWidth]; // select case playfield16(si+60)
+    if (ax == 0)
+      goto loc_g_11D5;
+
+    if (ax == fiZonk)
+      goto loc_g_11A6;
+
+    if (ax == fiInfotron)
+      goto loc_g_11A6;
+
+    if (ax == fiRAM)
+      goto loc_g_11A6;
+
+    return;
+
+loc_g_11A6: //        Case fiZonk, fiInfotron, fiRAM
+    ax = PlayField16[si + FieldWidth - 1];
+    if (ax == 0 || ax == 0x8888 || ax == 0xAAAA)
+      goto loc_g_11DC;
+
+loc_g_11BD:
+    ax = PlayField16[si + FieldWidth + 1];
+    if (ax == 0 || ax == 0x8888 || ax == 0xAAAA)
+      goto loc_g_11F2;
+
+    return;
+
+loc_g_11D5: //       Case fiSpace
+    MovHighByte(&PlayField16[si], 0x40);
+    goto loc_g_1207;
+
+loc_g_11DC: // roll left?
+    if (PlayField16[si - 1] == 0)
+      goto loc_g_11E5;
+
+    goto loc_g_11BD;
+
+loc_g_11E5:
+    MovHighByte(&PlayField16[si], 0x50);
+    PlayField16[si - 1] = 0x8888;
+    goto loc_g_1207;
+
+loc_g_11F2: // roll right?
+    if (PlayField16[si + 1] == 0)
+      goto loc_g_11FA;
+
+    return;
+
+loc_g_11FA:
+    MovHighByte(&PlayField16[si], 0x60);
+    PlayField16[si + 1] = 0x8888;
+  } // tFld = fiInfotron
+
+loc_g_1207:
+  // from now on the infotron is definitely moving,
+  // maybe the sequence is in an advanced frame
+  // or just beeing initialized due to the code above
+  bl = HighByte(PlayField16[si]);
+  bx = 0;
+  MovLowByte(&bx, bl);
+
+  al = bl & 0xF0;
+  if (al == 0x10) // infotron comes falling from above
+    goto loc_g_1242;
+
+  if (al == 0x20) // infotron comes rolling from right to left
+    goto loc_g_138D;
+
+  if (al == 0x30) // infotron comes rolling from left to right
+    goto loc_g_13E9;
+
+  if (al == 0x40) // infotron falls straight down
+    goto loc_g_1444;
+
+  if (al == 0x50) // infotron rolls left
+    goto loc_g_1472;
+
+  if (al == 0x60) // infotron rolls right
+    goto loc_g_14E0;
+
+  if (al == 0x70) // intermediate state
+    goto loc_g_154E;
+
+  return;
+
+loc_g_1242: // infotron comes falling from above
+  //      To Do: draw infotron falling from above
+  //      according to position in (bl And &H07)
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si);
+  Y = GetStretchY(si - FieldWidth);
+  dx = bl & 0x7;
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X, Y + TwoPixels * (dx + 1), aniInfotron, dx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+  bl = HighByte(PlayField16[si]) + 1;
+  if (bl == 0x16)
+  {
+    MovHighByte(&PlayField16[si], bl);
+    subCleanUpForInfotronsAbove(si - FieldWidth);
+
+    return;
+  } // loc_g_1285:
+
+  if (bl < 0x18)
+  {
+    MovHighByte(&PlayField16[si], bl);
+
+    return;
+  } // loc_g_128F:
+
+  MovHighByte(&PlayField16[si], 0); // infotron arrived at the field
+
+  // now check if the zonk may go on falling somehow
+  ax = PlayField16[si + FieldWidth];
+  if (ax == 0) // below is empty!-> go on falling
+    goto loc_g_132D;
+
+  if (ax == 0x9999) // below is only temporarily used
+    goto loc_g_132D;
+
+  if ((ax & 0xFF) == fiMurphy) // Murphy dies
+    goto loc_g_1364;
+
+  if (ax == fiRedDisk) // red disk hit
+    goto loc_g_1386;
+
+  if ((ax & 0xFF) == fiSnikSnak) // SnikSnak dies
+    goto loc_g_1386;
+
+
+  if ((ax & 0xFF) == fiElectron) // Electron cracked!
+    goto loc_g_1386;
+
+  if (ax == fiYellowDisk) // yellow disk hit
+    goto loc_g_1386;
+
+  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;
+
+  // infotron rolls somewhere
+  ax = PlayField16[si + FieldWidth - 1];
+  if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) // may roll left
+    goto loc_g_133A;
+
+  ax = PlayField16[si + FieldWidth + 1];
+  if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) // may roll right
+    goto loc_g_1350;
+
+  return;
+
+loc_g_132D:     // go on falling down?
+  PlayField16[si] = 0x7004; // go into intermediate waitstate
+  PlayField16[si + FieldWidth] = 0x9999; // mark as "zonk waiting to access"
+
+  return;
+
+loc_g_133A:     // test if infotron may roll left
+  // This if(if true) jumps up far above
+  // to the according rountine for fixed infotrons!
+  if (PlayField16[si - 1] != 0) // Remarkable!!! ' loc_g_0EF4:
+    goto loc_g_11BD;
+
+  MovHighByte(&PlayField16[si], 0x50); // infotron rolls left
+  PlayField16[si - 1] = 0x8888;
+
+  return;
+
+loc_g_1350:     // test if infotron may roll right
+  if (PlayField16[si + 1] != 0)
+    return;
+
+  MovHighByte(&PlayField16[si], 0x60); // infotron rolls right
+  PlayField16[si + 1] = 0x8888;
+
+  return;
+
+loc_g_1364:     // Murphy dies, but not in any case
+  bl = HighByte(PlayField16[si + FieldWidth]);
+  if (bl == 0xE || bl == 0xF || bl == 0x28)
+    return;
+
+  if (bl == 0x29 || bl == 0x25 || bl == 0x26)
+    return;
+
+loc_g_1386:     // someone dies/explodes immediately
+  si = si + FieldWidth;                 // 1 field down
+  ExplodeFieldSP(si);               // Explode
+
+  return;
+
+loc_g_138D: // infotron comes rolling from right to left
+  //  To Do: draw infotron rolling from right
+  //  according to position in (bl And &H07)
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si + 1);
+  Y = GetStretchY(si);
+  dx = (bl & 0x7) + 1;
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X - (TwoPixels * dx), Y, aniInfotronRollLeft, dx - 1);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+  bl = HighByte(PlayField16[si]) + 1; // get and increment sequence#
+  if (bl == 0x24)
+    PlayField16[si + 1] = 0xAAAA;
+
+  if (bl == 0x26)
+  {
+    MovHighByte(&PlayField16[si], bl);
+    subCleanUpForInfotronsAbove(si + 1);
+  }
+  else if (bl < 0x28)
+  {
+    MovHighByte(&PlayField16[si], bl);
+  }
+  else
+  {
+    PlayField16[si] = 0x7004; // go into intermediate state
+  }
+
+  return;
+
+loc_g_13E9: // infotron comes rolling from left to right
+  //  To Do: draw infotron rolling from left
+  //  according to position in (bl And &H07)
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si - 1);
+  Y = GetStretchY(si);
+  dx = (bl & 0x7) + 1;
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X + (TwoPixels * dx), Y, aniInfotronRollRight, dx - 1);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+  bl = HighByte(PlayField16[si]) + 1;
+  if (bl == 0x34)
+    PlayField16[si - 1] = 0xAAAA;
+
+  if (bl == 0x36)
+  {
+    MovHighByte(&PlayField16[si], bl);
+    subCleanUpForInfotronsAbove(si - 1);
+  }
+  else if (bl < 0x38)
+  {
+    MovHighByte(&PlayField16[si], bl);
+  }
+  else
+  {
+    PlayField16[si] = 0x7004; // go into intermediate state
+  }
+
+  return;
+
+loc_g_1444: // infotron falls straight down
+  bl = bl + 1;
+  if (bl < 0x42)
+  {
+    MovHighByte(&PlayField16[si], bl);
+  }
+  else if (PlayField16[si + FieldWidth] != 0)
+  {
+    bl = bl - 1; // stay waiting
+    MovHighByte(&PlayField16[si], bl);
+  }
+  else
+  {
+    PlayField16[si] = 0xFFFF;
+    si = si + FieldWidth;                 // 1 field down
+    PlayField16[si] = 0x1004; // go falling
+  }
+
+  return;
+
+loc_g_1472: // infotron rolls left
+  //  To Do: draw infotron rolling to left
+  //  according to position in (bl And &H0F)
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si);
+  Y = GetStretchY(si);
+  dx = (bl & 0xF) + 1;
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X - (TwoPixels * dx), Y, aniInfotronRollLeft, dx - 1);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+  bl = HighByte(PlayField16[si]) + 1; // retrieve and increment sequence#
+  if (bl < 0x52)
+  {
+    MovHighByte(&PlayField16[si], bl);
+
+    return;
+  }
+
+  if (PlayField16[si + FieldWidth - 1] != 0)
+    goto loc_g_14D9;
+
+  if (PlayField16[si - 1] != 0)
+  {
+    if (PlayField16[si - 1] != 0x8888)
+      goto loc_g_14D9;
+  }
+
+  PlayField16[si] = 0xFFFF;
+  si = si - 1;                   // 1 field left
+  PlayField16[si] = 0x2204;
+  PlayField16[si + FieldWidth] = 0x9999;
+
+  return;
+
+loc_g_14D9: // stay waiting
+  bl = bl - 1;
+  MovHighByte(&PlayField16[si], bl);
+
+  return;
+
+loc_g_14E0: // infotron rolls right
+  //  To Do: draw infotron rolling to right
+  //  according to position in (bl And &H07)
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si);
+  Y = GetStretchY(si);
+  dx = (bl & 0x7) + 1;
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X + (TwoPixels * dx), Y, aniInfotronRollRight, dx - 1);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+  bl = HighByte(PlayField16[si]) + 1;
+  if (bl < 0x62)
+  {
+    MovHighByte(&PlayField16[si], bl);
+
+    return;
+  }
+
+  if (PlayField16[si + FieldWidth + 1] != 0)
+    goto loc_g_1547;
+
+  if (PlayField16[si + 1] != 0)
+  {
+    if (PlayField16[si + 1] != 0x8888)
+      goto loc_g_1547;
+  }
+
+  PlayField16[si] = 0xFFFF;
+  si = si + 1;
+  PlayField16[si] = 0x3204;
+  PlayField16[si + FieldWidth] = 0x9999;
+
+  return;
+
+loc_g_1547: // stay waiting
+  bl = bl - 1;
+  MovHighByte(&PlayField16[si], bl);
+
+  return;
+
+loc_g_154E: // intermediate state
+  ax = PlayField16[si + FieldWidth];
+  if (ax == 0 || ax == 0x9999)
+  {
+    PlayField16[si] = 0xFFFF;
+    si = si + FieldWidth;                 // 1 field down
+    PlayField16[si] = 0x1004; // start falling down
+    goto loc_g_1242;
+  }
+}
+
+void subCleanUpForInfotronsAbove(int si)
+{
+  int ax;
+
+  if (LowByte(PlayField16[si]) != fiExplosion)
+    PlayField16[si] = 0;
+
+  if (PlayField16[si - FieldWidth] != 0)
+  {
+    if (PlayField16[si - FieldWidth] != 0x9999)
+      return;
+
+    if (LowByte(PlayField16[si - 2 * FieldWidth]) != fiZonk)
+      return;
+  }
+
+  if (PlayField16[si - FieldWidth - 1] == fiInfotron)
+    goto loc_g_16FE;
+
+loc_g_16F6:
+  if (PlayField16[si - FieldWidth + 1] == fiInfotron)
+    goto loc_g_1722;
+
+  return;
+
+loc_g_16FE:
+  ax = PlayField16[si - 1];
+  if (ax == fiZonk || ax == fiInfotron || ax == fiRAM)
+  {
+    PlayField16[si - FieldWidth - 1] = 0x6004;
+    PlayField16[si - FieldWidth] = 0x8888;
+
+    return;
+  }
+
+  goto loc_g_16F6;
+
+loc_g_1722:
+  ax = PlayField16[si + 1];
+  if (ax == fiZonk || ax == fiInfotron || ax == fiRAM)
+  {
+    PlayField16[si - FieldWidth + 1] = 0x5004;
+    PlayField16[si - FieldWidth] = 0x8888;
+  }
+}
diff --git a/src/game_sp/Infotrons.h b/src/game_sp/Infotrons.h
new file mode 100644 (file)
index 0000000..a18fedd
--- /dev/null
@@ -0,0 +1,14 @@
+// ----------------------------------------------------------------------------
+// Infotrons.h
+// ----------------------------------------------------------------------------
+
+#ifndef INFOTRONS_H
+#define INFOTRONS_H
+
+#include "global.h"
+
+
+extern void subAnimateInfotrons(int);
+extern void subCleanUpForInfotronsAbove(int);
+
+#endif /* INFOTRONS_H */
diff --git a/src/game_sp/InitGameConditions.c b/src/game_sp/InitGameConditions.c
new file mode 100644 (file)
index 0000000..1313c49
--- /dev/null
@@ -0,0 +1,259 @@
+// ----------------------------------------------------------------------------
+// InitGameConditions.c
+// ----------------------------------------------------------------------------
+
+#include "InitGameConditions.h"
+
+
+// ==========================================================================
+//                              SUBROUTINE
+// Init game conditions (variables)
+// ==========================================================================
+
+void subInitGameConditions()
+{
+  MurphyVarFaceLeft = 0;
+  KillMurphyFlag = 0;                  // no "kill Murphy"
+  ExitToMenuFlag = 0;
+  LeadOutCounter = 0;                  // quit flag: lead-out counter
+  RedDiskCount = 0;                    // Red disk counter
+
+  YawnSleepCounter = 0;                        // Wake up sleeping Murphy
+
+  ExplosionShake = 0;                  // Force explosion flag off
+  ExplosionShakeMurphy = 0;            // Force explosion flag off
+
+  TerminalMaxCycles = 0x7F;
+  YellowDisksExploded = 0;
+
+  TimerVar = 0;
+
+  SnikSnaksElectronsFrozen = 0;                // Snik-Snaks and Electrons move!
+
+  SplitMoveFlag = 0;                   // Reset Split-through-ports
+  RedDiskReleasePhase = 0;             // (re-)enable red disk release
+  RedDiskReleaseMurphyPos = 0;         // Red disk was released here
+}
+
+
+// ==========================================================================
+//                              SUBROUTINE
+// Locate Murphy and init location.
+// ==========================================================================
+
+void InitMurphyPos()
+{
+  int si;
+
+  for (si = 0; si < LevelMax; si++)
+    if (PlayField16[si] == fiMurphy)
+      break;
+
+  InitMurphyPosB(si);
+
+  MurphyPosIndex = si;
+}
+
+void InitMurphyPosB(int si)
+{
+  MurphyScreenXPos = MurphyXPos = GetStretchX(si); // Murphy's screen x-position
+  MurphyScreenYPos = MurphyYPos = GetStretchY(si); // Murphy's screen y-position
+
+  // To Do: draw Murphy in location ax
+  DDSpriteBuffer_BltImg(MurphyScreenXPos, MurphyScreenYPos, aniMurphy, 0);
+
+  subCalculateScreenScrollPos();           // calculate screen start addrs
+
+  if (AutoScrollFlag)
+  {
+    if (bPlaying)
+      SoftScrollTo(ScreenScrollXPos, ScreenScrollYPos, 1000, 25);
+    else
+      ScrollTo(ScreenScrollXPos, ScreenScrollYPos);
+  }
+}
+
+
+// ==========================================================================
+//                              SUBROUTINE
+// Convert to easy symbols and reset Infotron count If not ThenVer62
+// ==========================================================================
+
+int subConvertToEasySymbols()
+{
+  int ax, bx, cx, dx, i;
+  int al;
+
+  bx = 0;
+  dx = 0;
+  cx = LevelMax + 1;
+  i = 0;
+
+loc_g_26C9:
+  ax = PlayField16[i];
+  al = LowByte(ax);
+  if (al == 0xF1) // converted explosion?
+  {
+    MovLowByte(&PlayField16[i], 0x1F);      // restore explosions
+    goto loc_g_2778;
+  }
+
+  if (LowByte(GameBusyFlag) != 1) // free screen write?
+  {
+    if (ax == fiInfotron) // Infotron? -> yes--count!
+      goto loc_g_2704;
+
+    if (ax == fiSnikSnak) // Snik Snak? -> yes--rearrange
+      goto loc_g_2713;
+
+    if (ax == fiElectron) // Electron? -> yes--rearrange
+      goto loc_g_2741;
+  }
+
+  // test for fancy RAM Chips:
+  if (ax == fiRAMLeft || ax == fiRAMRight)
+    goto loc_g_2707;
+
+  if (ax == fiRAMTop || ax == fiRAMBottom)
+    goto loc_g_2707;
+
+  if (ax < fiHWFirst) // All but deco hardware?
+    goto loc_g_26F8;
+
+  if (ax < fiRAMTop) // Decorative hardware?
+    goto loc_g_270D;
+
+loc_g_26F8:
+  if (ax < fiSpPortRight) // Gravity change ports only?
+    goto loc_g_2778;
+
+  if (ax < fiSnikSnak) // Gravity change port! 'loc_g_2702:
+    goto loc_g_276F;
+
+  goto loc_g_2778;
+
+loc_g_2704:                                     // INFOTRON
+  dx = dx + 1;                      // Count Infotrons
+  goto loc_g_2778;
+
+loc_g_2707:                                     // DECO RAM CHIPS
+  PlayField16[i] = fiRAM; // Convert to standard RAM chip
+  goto loc_g_2778;
+
+loc_g_270D:                                     // DECO HARDWARE
+  PlayField16[i] = fiHardWare; // Convert to standard hardware
+  goto loc_g_2778;
+
+loc_g_2713:                                     // SNIK-SNAK
+  if (PlayField16[i - 1] != 0) // 1 field left empty? -> no--try up
+    goto loc_g_271F;
+
+  MovHighByte(&PlayField16[i], 1); // turn left, step = NorthWest
+  goto loc_g_2778;
+
+loc_g_271F:
+  if (PlayField16[i - FieldWidth] != 0) // 1 field up empty? -> no--try right
+    goto loc_g_2730;
+
+  PlayField16[i - FieldWidth] = 0x1011; // SnikSnak accessing from below, step = 0
+  PlayField16[i] = 0xFFFF;
+  goto loc_g_2778;
+
+loc_g_2730:
+  if (PlayField16[i + 1] != 0) // 1 field right empty? -> point up
+    goto loc_g_2778;
+
+  PlayField16[i + 1] = 0x2811; // SnikSnak accessing from left, step = 0
+  PlayField16[i] = 0xFFFF;
+  goto loc_g_2778;
+
+loc_g_2741:                                     // ELECTRON
+  if (PlayField16[i - 1] != 0) // 1 field left empty? -> no--try up
+    goto loc_g_274D;
+
+  MovHighByte(&PlayField16[i], 1);
+  goto loc_g_2778;
+
+loc_g_274D:
+  if (PlayField16[i - FieldWidth] != 0) // 1 field up empty? -> no--try right
+    goto loc_g_275E;
+
+  PlayField16[i - FieldWidth] = 0x1018; // 1 field up
+  PlayField16[i] = 0xFFFF;
+  goto loc_g_2778;
+
+loc_g_275E:
+  if (PlayField16[i + 1] != 0) // 1 field right empty? -> no--point down
+    goto loc_g_2778;
+
+  PlayField16[i + 1] = 0x2818;
+  PlayField16[i] = 0xFFFF;
+  goto loc_g_2778;
+
+loc_g_276F:                                     // GRAVITY CHANGING PORTS
+  PlayField16[i] = (ax - 4) | 0x100;    // Convert to standard ports
+  goto loc_g_2778;
+
+loc_g_2778:
+  i = i + 1;                   // Next field
+  bx = bx + 1;
+  cx = cx - 1;
+  if (0 < cx) // Until all done 'loc_g_2782:
+    goto loc_g_26C9;
+
+  return dx;   // return InfotronCount
+}
+
+
+// ==========================================================================
+//                              SUBROUTINE
+// Reset Infotron count.  Call immediately after subConvertToEasySymbols
+// ==========================================================================
+
+void ResetInfotronsNeeded(int dx)
+{
+  if (LInfo.InfotronsNeeded != 0)              // Jump If equal (autodetect)
+    dx = LInfo.InfotronsNeeded;
+
+  InfotronsNeeded = LowByte(dx);               // Remaining Infotrons needed
+  TotalInfotronsNeeded = InfotronsNeeded;      // Number of Infotrons needed
+}
+
+
+// ==========================================================================
+//                              SUBROUTINE
+// Fetch and initialize a level
+// ==========================================================================
+
+void subFetchAndInitLevelB()
+{
+  subFetchAndInitLevelA();
+}
+
+void subFetchAndInitLevelA()
+{
+  GameBusyFlag = 0;                            // restore scissors too
+  subFetchAndInitLevel();                      // fetch and initialize a level
+  GameBusyFlag = 1;                            // no free screen write
+
+  DemoKeyCode = 0;                             // delete last demo key!
+}
+
+void subFetchAndInitLevel()
+{
+  int InfoCountInLevel;
+
+  PrepareLevel();                              // initialize level data
+
+  GameBusyFlag = -GameBusyFlag;                        // make != 1
+  InfoCountInLevel = subConvertToEasySymbols();        // convert to easy symbols
+  GameBusyFlag = -GameBusyFlag;                        // restore
+
+  subDisplayLevel();                           // paint (init) game field
+
+  ResetInfotronsNeeded(InfoCountInLevel);      // and reset Infotron count
+
+  subInitGameConditions();                     // init game conditions (vars)
+
+  InitMurphyPos();                             // locate Murphy + screen pos
+}
diff --git a/src/game_sp/InitGameConditions.h b/src/game_sp/InitGameConditions.h
new file mode 100644 (file)
index 0000000..eb4249f
--- /dev/null
@@ -0,0 +1,21 @@
+// ----------------------------------------------------------------------------
+// InitGameConditions.h
+// ----------------------------------------------------------------------------
+
+#ifndef INITGAMECONDITIONS_H
+#define INITGAMECONDITIONS_H
+
+#include "global.h"
+
+
+extern int subConvertToEasySymbols();
+
+extern void InitMurphyPos();
+extern void InitMurphyPosB(int);
+extern void ResetInfotronsNeeded(int);
+extern void subFetchAndInitLevel();
+extern void subFetchAndInitLevelA();
+extern void subFetchAndInitLevelB();
+extern void subInitGameConditions();
+
+#endif /* INITGAMECONDITIONS_H */
diff --git a/src/game_sp/Input.c b/src/game_sp/Input.c
new file mode 100644 (file)
index 0000000..5a46957
--- /dev/null
@@ -0,0 +1,42 @@
+// ----------------------------------------------------------------------------
+// Input.c
+// ----------------------------------------------------------------------------
+
+#include "Input.h"
+
+
+int map_key_RND_to_SP(int key)
+{
+  if (key & KEY_BUTTON)
+  {
+    return (key & MV_UP                ? keySpaceUp    :
+           key & MV_LEFT       ? keySpaceLeft  :
+           key & MV_DOWN       ? keySpaceDown  :
+           key & MV_RIGHT      ? keySpaceRight : keySpace);
+  }
+  else
+  {
+    return (key & MV_UP                ? keyUp         :
+           key & MV_LEFT       ? keyLeft       :
+           key & MV_DOWN       ? keyDown       :
+           key & MV_RIGHT      ? keyRight      : keyNone);
+  }
+}
+
+int map_key_SP_to_RND(int key)
+{
+  return (key == keyUp         ? MV_UP                 :
+         key == keyLeft        ? MV_LEFT               :
+         key == keyDown        ? MV_DOWN               :
+         key == keyRight       ? MV_RIGHT              :
+         key == keySpaceUp     ? KEY_BUTTON | MV_UP    :
+         key == keySpaceLeft   ? KEY_BUTTON | MV_LEFT  :
+         key == keySpaceDown   ? KEY_BUTTON | MV_DOWN  :
+         key == keySpaceRight  ? KEY_BUTTON | MV_RIGHT :
+         key == keySpace       ? KEY_BUTTON            : MV_NONE);
+}
+
+void subProcessKeyboardInput(byte action)
+{
+  DemoKeyCode = map_key_RND_to_SP(action);
+}
diff --git a/src/game_sp/Input.h b/src/game_sp/Input.h
new file mode 100644 (file)
index 0000000..55f6aaf
--- /dev/null
@@ -0,0 +1,13 @@
+// ----------------------------------------------------------------------------
+// Input.h
+// ----------------------------------------------------------------------------
+
+#ifndef INPUT_H
+#define INPUT_H
+
+#include "global.h"
+
+
+extern void subProcessKeyboardInput(byte);
+
+#endif /* INPUT_H */
diff --git a/src/game_sp/MainForm.c b/src/game_sp/MainForm.c
new file mode 100644 (file)
index 0000000..c54bf63
--- /dev/null
@@ -0,0 +1,302 @@
+// ----------------------------------------------------------------------------
+// MainForm.c
+// ----------------------------------------------------------------------------
+
+#include "MainForm.h"
+
+
+static void DrawFrame(int Delta);
+static void ReStretch();
+
+void DrawField(int X, int Y);
+void DrawFieldAnimated(int X, int Y);
+void DrawFieldNoAnimated(int X, int Y);
+
+void DrawFrameIfNeeded()
+{
+  DrawFrame(0);
+
+  /* !!! CHECK THIS !!! */
+#if 1
+  if (! menBorder)
+    DrawFrame(1);
+#endif
+}
+
+void DisplayLevel()
+{
+  int X, Y;
+
+  if (! LevelLoaded)
+    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();
+
+  if (bPlaying)
+  {
+    for (Y = DisplayMinY; Y <= DisplayMaxY; Y++)
+      for (X = DisplayMinX; X <= DisplayMaxX; X++)
+        DrawFieldNoAnimated(X, Y);
+
+    for (Y = DisplayMinY; Y <= DisplayMaxY; Y++)
+      for (X = DisplayMinX; X <= DisplayMaxX; X++)
+        DrawFieldAnimated(X, Y);
+  }
+  else
+  {
+    for (Y = DisplayMinY; Y <= DisplayMaxY; Y++)
+      for (X = DisplayMinX; X <= DisplayMaxX; X++)
+        DrawField(X, Y);
+  }
+}
+
+void Form_Load()
+{
+  InitGlobals();
+
+  ReStretch();
+}
+
+static void DrawFrame(int Delta)
+{
+  int i, LX, tY, RX, BY;
+
+  LX = -1 + Delta;
+  tY = -1 + Delta;
+  RX = FieldWidth - Delta;
+  BY = FieldHeight - Delta;
+
+  DrawImage(LX, tY, (Delta > 0 ? imgFrameCorner : aniSpace));
+  DrawImage(LX, BY, (Delta > 0 ? imgFrameCorner : aniSpace));
+  DrawImage(RX, tY, (Delta > 0 ? imgFrameCorner : aniSpace));
+  DrawImage(RX, BY, (Delta > 0 ? imgFrameCorner : aniSpace));
+
+  for (i = LX + 1; i <= RX - 1; i++)
+  {
+    DrawImage(i, tY, (Delta > 0 ? imgFrameHorizontal : aniSpace));
+    DrawImage(i, BY, (Delta > 0 ? imgFrameHorizontal : aniSpace));
+  }
+
+  for (i = tY + 1; i <= BY - 1; i++)
+  {
+    DrawImage(LX, i, (Delta > 0 ? imgFrameVertical : aniSpace));
+    DrawImage(RX, i, (Delta > 0 ? imgFrameVertical : aniSpace));
+  }
+
+  if (Delta > 0)
+  {
+    // ...
+    // ClearRectangle(bitmap_db_field_sp, 
+  }
+}
+
+static void RestoreFrame()
+{
+  int i, LX, tY, RX, BY;
+
+  LX = 0;
+  tY = 0;
+  RX = FieldWidth - 1;
+  BY = FieldHeight - 1;
+
+  for (i = LX; i <= RX; i++)
+  {
+    DrawField(i, tY);
+    DrawField(i, BY);
+  }
+
+  for (i = tY + 1; i <= BY - 1; i++)
+  {
+    DrawField(LX, i);
+    DrawField(RX, i);
+  }
+}
+
+void SetDisplayRegion()
+{
+  if (! menBorder)
+  {
+    DisplayMinX = 1;
+    DisplayMinY = 1;
+    DisplayMaxX = FieldWidth - 2;
+    DisplayMaxY = FieldHeight - 2;
+
+    if (LevelLoaded)
+      DrawFrame(1);
+  }
+  else
+  {
+    DisplayMinX = 0;
+    DisplayMinY = 0;
+    DisplayMaxX = FieldWidth - 1;
+    DisplayMaxY = FieldHeight - 1;
+
+    if (LevelLoaded)
+      RestoreFrame();
+  }
+}
+
+void menPlay_Click()
+{
+  bPlaying = True;
+
+  subFetchAndInitLevelB();
+
+  ReStretch();
+
+  subMainGameLoop_Init();
+
+#if 1
+  return;
+#endif
+
+  bPlaying = False;
+
+  subFetchAndInitLevel();
+}
+
+static void ReStretch()
+{
+  if (LevelLoaded)
+  {
+    SetDisplayRegion();
+
+    SetScrollEdges();
+
+    ScrollTo(ScrollX, ScrollY);
+
+    DisplayLevel();
+  }
+
+  subCalculateScreenScrollPos();
+
+  ScrollTo(ScreenScrollXPos, ScreenScrollYPos);
+}
+
+void SetScrollEdges()
+{
+  int border1_offset = (menBorder ? 1 : 2);
+  int border2_offset = (menBorder ? 0 : TILESIZE / 2);
+
+  /* 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;
+
+  /* scroll correction for border element (half tile on left and right side) */
+  ScrollMinX += border2_offset;
+  ScrollMinY += border2_offset;
+  ScrollMaxX -= border2_offset;
+  ScrollMaxY -= border2_offset;
+
+  /* scroll correction for even number of visible tiles (half tile shifted) */
+  ScrollMinX -= game_sp.scroll_xoffset;
+  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)
+{
+  int tsi = GetSI(X, Y);
+  int Tmp = LowByte(PlayField16[tsi]);
+
+  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];
+}
+
+void DrawFieldAnimated(int X, int Y)
+{
+  int tsi = GetSI(X, Y);
+  int Tmp = LowByte(PlayField16[tsi]);
+
+  switch (Tmp)
+  {
+    case fiSnikSnak:
+      subDrawAnimatedSnikSnaks(tsi);
+      break;
+
+    case fiElectron:
+      subDrawAnimatedElectrons(tsi);
+      break;
+
+    default:
+      break;
+  }
+}
+
+void DrawFieldNoAnimated(int X, int Y)
+{
+  int tsi = GetSI(X, Y);
+  int Tmp = LowByte(PlayField16[tsi]);
+
+  switch (Tmp)
+  {
+    case fiSnikSnak:
+      subCopyImageToScreen(tsi, aniSpace);
+      break;
+
+    case fiElectron:
+      subCopyImageToScreen(tsi, aniSpace);
+      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;
+  }
+}
+
+void DrawImage(int X, int Y, int graphic)
+{
+  DDSpriteBuffer_BltImg(StretchWidth * X, StretchWidth * Y, graphic, 0);
+}
diff --git a/src/game_sp/MainForm.h b/src/game_sp/MainForm.h
new file mode 100644 (file)
index 0000000..24cbd46
--- /dev/null
@@ -0,0 +1,27 @@
+// ----------------------------------------------------------------------------
+// MainForm.h
+// ----------------------------------------------------------------------------
+
+#ifndef MAINFORM_H
+#define MAINFORM_H
+
+#include "global.h"
+
+
+extern void DrawFrameIfNeeded();
+
+extern void DisplayLevel();
+extern void DrawField(int X, int Y);
+extern void DrawFieldAnimated(int X, int Y);
+extern void DrawFieldNoAnimated(int X, int Y);
+extern void DrawSprite(int X, int Y, int SpritePos);
+extern void DrawImage(int X, int Y, int graphic);
+
+extern void SetDisplayRegion();
+extern void SetScrollEdges();
+
+extern void menPlay_Click();
+
+extern void Form_Load();
+
+#endif /* MAINFORM_H */
diff --git a/src/game_sp/MainGameLoop.c b/src/game_sp/MainGameLoop.c
new file mode 100644 (file)
index 0000000..48a1ac4
--- /dev/null
@@ -0,0 +1,131 @@
+// ----------------------------------------------------------------------------
+// MainGameLoop.c
+// ----------------------------------------------------------------------------
+
+#include "MainGameLoop.h"
+
+
+boolean bPlaying;
+int LeadOutCounter;
+int ExitToMenuFlag;
+boolean AutoScrollFlag;
+
+
+// ==========================================================================
+//                              SUBROUTINE
+// Play a game/demo
+// ==========================================================================
+
+void subMainGameLoop_Init()
+{
+  // This was a bug in the original Supaplex: sometimes red disks could not
+  // be released.  This happened if Murphy was killed DURING a red disk release
+  // and the next try started.
+
+  RedDiskReleasePhase = 0; // (re-)enable red disk release
+}
+
+void subMainGameLoop_Main(byte action, boolean warp_mode)
+{
+  // ---------------------------------------------------------------------------
+  // --------------------- START OF GAME-BUSY LOOP -----------------------------
+  // ---------------------------------------------------------------------------
+
+  subProcessKeyboardInput(action);     // check keyboard, act on keys
+
+  // ---------------------------------------------------------------------------
+  //
+
+  subDoGameStuff();                    // do all game stuff
+
+  //
+  // ---------------------------------------------------------------------------
+
+  subRedDiskReleaseExplosion();                // Red Disk release and explode
+  subFollowUpExplosions();             // every explosion may cause up to 8 following explosions
+
+  subCalculateScreenScrollPos();       // calculate screen start addrs
+
+  if (AutoScrollFlag)
+    ScrollTowards(ScreenScrollXPos, ScreenScrollYPos);
+
+  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;
+
+  // ---------------------------------------------------------------------------
+  // ---------------------- END OF GAME-BUSY LOOP ------------------------------
+  // ---------------------------------------------------------------------------
+
+  LeadOutCounter = LeadOutCounter - 1;         // do more lead-out after quit
+
+  if (LeadOutCounter != 0)                     // lead-out not ready: more
+    return;
+
+  // 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 */
+  if (MurphyScreenXPos < -jump_pos)
+  {
+    MurphyScreenXPos = FieldWidth * TILEX + MurphyScreenXPos;
+    MurphyScreenYPos -= TILEY;
+  }
+  else if (MurphyScreenXPos >= FieldWidth * TILEX - jump_pos)
+  {
+    MurphyScreenXPos = MurphyScreenXPos - FieldWidth * TILEX;
+    MurphyScreenYPos += TILEY;
+  }
+#endif
+
+  if (ExplosionShake != 0)
+  {
+    subGetRandomNumber();
+
+    // printf("::: ExplosionShake [%d]\n", FrameCounter);
+  }
+
+  ScreenScrollXPos = MurphyScreenXPos - (SCR_FIELDX / 2) * TILESIZE;
+  ScreenScrollYPos = MurphyScreenYPos - (SCR_FIELDY / 2) * TILESIZE;
+}
diff --git a/src/game_sp/MainGameLoop.h b/src/game_sp/MainGameLoop.h
new file mode 100644 (file)
index 0000000..3ce85d2
--- /dev/null
@@ -0,0 +1,20 @@
+// ----------------------------------------------------------------------------
+// MainGameLoop.h
+// ----------------------------------------------------------------------------
+
+#ifndef MAINGAMELOOP_H
+#define MAINGAMELOOP_H
+
+#include "global.h"
+
+
+extern boolean AutoScrollFlag;
+extern boolean bPlaying;
+extern int ExitToMenuFlag;
+extern int LeadOutCounter;
+
+extern void subMainGameLoop_Init();
+extern void subMainGameLoop_Main(byte, boolean);
+extern void subCalculateScreenScrollPos();
+
+#endif /* MAINGAMELOOP_H */
diff --git a/src/game_sp/Makefile b/src/game_sp/Makefile
new file mode 100644 (file)
index 0000000..d1d9ffc
--- /dev/null
@@ -0,0 +1,95 @@
+# =============================================================================
+# Makefile for native Supaplex engine for Rocks'n'Diamonds (game_sp)
+# -----------------------------------------------------------------------------
+# (c) 1995-2009 Holger Schemel <info@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
+# =============================================================================
+
+# -----------------------------------------------------------------------------
+# configuration
+# -----------------------------------------------------------------------------
+
+SRCS = init.c                  \
+       file.c                  \
+       main.c                  \
+       vb_lib.c                \
+                               \
+       ASM.c                   \
+       BugsTerminals.c         \
+       DDScrollBuffer.c        \
+       DDSpriteBuffer.c        \
+       Display.c               \
+       DoGameStuff.c           \
+       Electrons.c             \
+       Explosions.c            \
+       Globals.c               \
+       Infotrons.c             \
+       InitGameConditions.c    \
+       Input.c                 \
+       MainForm.c              \
+       MainGameLoop.c          \
+       Murphy.c                \
+       OrangeDisk.c            \
+       SnikSnaks.c             \
+       Sound.c                 \
+       Zonk.c
+
+OBJS = init.o                  \
+       file.o                  \
+       main.o                  \
+       vb_lib.o                \
+                               \
+       ASM.o                   \
+       BugsTerminals.o         \
+       DDScrollBuffer.o        \
+       DDSpriteBuffer.o        \
+       Display.o               \
+       DoGameStuff.o           \
+       Electrons.o             \
+       Explosions.o            \
+       Globals.o               \
+       Infotrons.o             \
+       InitGameConditions.o    \
+       Input.o                 \
+       MainForm.o              \
+       MainGameLoop.o          \
+       Murphy.o                \
+       OrangeDisk.o            \
+       SnikSnaks.o             \
+       Sound.o                 \
+       Zonk.o
+
+GAME_SP = game_sp.a
+
+
+# -----------------------------------------------------------------------------
+# build targets
+# -----------------------------------------------------------------------------
+
+all: $(GAME_SP)
+
+$(GAME_SP): $(OBJS)
+       $(AR) cru $(GAME_SP) $(OBJS)
+       $(RANLIB) $(GAME_SP)
+
+.c.o:
+       $(CC) $(PROFILING) $(CFLAGS) -c $*.c
+
+clean:
+       $(RM) $(OBJS)
+       $(RM) $(GAME_SP)
+
+
+# -----------------------------------------------------------------------------
+# development only
+# -----------------------------------------------------------------------------
+
+depend:
+       for i in $(SRCS); do $(CPP) $(CFLAGS) -M $$i; done > .depend
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
diff --git a/src/game_sp/Murphy.c b/src/game_sp/Murphy.c
new file mode 100644 (file)
index 0000000..06cd9f7
--- /dev/null
@@ -0,0 +1,2591 @@
+// ----------------------------------------------------------------------------
+// Murphy.c
+// ----------------------------------------------------------------------------
+
+#include "Murphy.h"
+
+
+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
+// ==========================================================================
+
+void subAnimateMurphy(int *si)
+{
+  int ax, al, bl, i, X, Y;
+  int time1, time2;
+  int tDeltaX, tDeltaY, tPos, Tmp;
+
+  // Variables that hold information about the animation sequence
+  static int dx1 = 0; // image/animation token
+  static int dx2 = 0; // an additional image position of a second sprite, for instance: yellow disk if pushed
+  static int MurphyDX = 0, MurphyDY = 0; // murphys move steps
+  static int SeqPos = 0; // index into dx()
+  static int ClearPos = 0; // Position to clear before blitting sprites, none=-1
+  static int dxPos = 0; // field-position  to draw dx(SeqPos)
+  static int dx2Step = 0; // position of dx2 relative to dx-position
+  static int dx1SequenceLength = 0;
+
+  ax = PlayField16[*si];
+  al = LowByte(ax);
+
+  if (al != fiMurphy)
+  {
+    MurphyMoveCounter = 0;             // We have no Murphy! Exit!
+
+    return;
+  }
+
+  MurphyMoveCounter = 1;             // We have a Murphy!
+  MurphyExplodePos = *si;
+
+  // (check if high byte of PlayField16 has stored movement information)
+  if (ax != fiMurphy) // yes--go proceed moving murphy?
+    goto locProceedMovingMurphy;
+
+  // FS: reset moving sequence variables
+  MurphyDX = 0;
+  MurphyDY = 0;
+  ClearPos = *si;
+  dxPos = *si;
+  dx1 = -1;
+  dx2 = -1;
+  SeqPos = 0;
+  // end of FS
+
+  ScratchGravity = 0; // scratch gravity off
+  if (GravityFlag != 0) // Gravity? (1=gravity on)
+  {
+    bl = LowByte(PlayField16[*si - FieldWidth]); // check above
+    if (! (bl == fiPortUp ||
+          bl == fiPortUpAndDown ||
+          bl == fiPortAllDirections))
+    {
+      if (PlayField16[*si + FieldWidth] == 0) // gravity on and space below!
+        ScratchGravity = 1;
+    }
+  } // loc_g_5E8B:
+
+  bl = DemoKeyCode;
+  if (bl != 0) // a key was pressed!
+    goto locKeyPressed5FCF;
+
+  RedDiskReleaseFlag = 1;
+  if (ScratchGravity != 0) // gravity pulls & space below?'-> force Space up to down
+  {
+    MurphyDY = 2;
+    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:
+
+  YawnSleepCounter = YawnSleepCounter + 1;
+
+  if (YawnSleepCounter < 16)
+    return;
+
+  if (YawnSleepCounter < 2000)
+  {
+    // normal grin
+    // (default: single graphic, no animation)
+    subCopyAnimToScreen(*si, aniMurphy, YawnSleepCounter - 16);
+
+    return;
+  }
+
+  if (YawnSleepCounter < 4000)
+  {
+    // yawn! and look depressed afterwards...
+    // (default: 12 animation frames with delay of 8)
+    subCopyAnimToScreen(*si, aniMurphyYawn, YawnSleepCounter - 2000);
+
+    return;
+  }
+
+  if (YawnSleepCounter < 6400)
+  {
+    // yawn again!
+    // (default: 12 animation frames with delay of 8)
+    subCopyAnimToScreen(*si, aniMurphyYawn, YawnSleepCounter - 4000);
+
+    return;
+  }
+
+  // time1 = 6400 + 12 * 8;    // (default: 6496 == 6400 + 12 * 8)
+  time1 = 6400 + 12 * 10;
+
+  if (YawnSleepCounter < time1)
+  {
+    // yawn again! - third time
+    // (default: 12 animation frames with delay of 8)
+    subCopyAnimToScreen(*si, aniMurphyYawn, YawnSleepCounter - 6400);
+
+    return;
+  }
+
+  // time2 = 6496 + 3 * 64;    // (default: 6688 == 6496 + 3 * 64)
+  time2 = 6496 + 3 * 100;
+
+  if (YawnSleepCounter > time2)                // Murphy already went to sleep
+    return;
+
+  if (PlayField16[*si - 1] == 0)
+  {
+    if (PlayField16[*si + 1] == 0)
+    {
+      // no sleep -- go back to "wait and start yawning" phase
+      YawnSleepCounter = 144;
+
+      return;
+    }
+    else
+    {
+      // go to sleep (right side)
+      // (default: 3 animation frames with delay of 64)
+      subCopyAnimToScreen(*si, aniMurphySleepRight, YawnSleepCounter - time1);
+
+      return;
+    }
+  }
+
+  // go to sleep (left side)
+  // (default: 3 animation frames with delay of 64)
+  subCopyAnimToScreen(*si, aniMurphySleepLeft, YawnSleepCounter - time1);
+
+  return;
+
+  // 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
+  // ==========================================================================
+
+locKeyPressed5FCF:
+  if (ScratchGravity == 0)
+    goto loc_g_6003;
+
+  if (PlayField16[*si + FieldWidth] != 0)
+    goto loc_g_6003;
+
+  if (bl == keyUp)
+  {
+    if (PlayField16[*si - FieldWidth] == fiBase)
+      goto loc_g_6003;
+
+  }
+  else if (bl == keyLeft)
+  {
+    if (PlayField16[*si - 1] == fiBase)
+      goto loc_g_6003;
+
+  }
+  else if (bl == keyRight)
+  {
+    if (PlayField16[*si + 1] == fiBase)
+      goto loc_g_6003;
+  } // loc_g_6001:
+
+  bl = keyDown;                      // force moving down!
+loc_g_6003:
+  switch (bl)
+  {
+    case keyUp: // 1
+      RedDiskReleaseFlag = 0; // moving down to up ...
+      goto loc_g_6078;
+
+      break;
+
+    case keyLeft: // 2
+      RedDiskReleaseFlag = 0; // moving right to left ...
+      goto loc_g_60DA;
+
+      break;
+
+    case keyDown: // 3
+      RedDiskReleaseFlag = 0; // moving up to down ...
+      goto loc_g_6154;
+
+      break;
+
+    case keyRight: // 4
+      RedDiskReleaseFlag = 0; // moving left to right ...
+      goto loc_g_61B6;
+
+      break;
+
+    case keySpaceUp: // 5
+      RedDiskReleaseFlag = 0; // touching down to up ...
+      goto loc_g_622E;
+
+      break;
+
+    case keySpaceLeft: // 6
+      RedDiskReleaseFlag = 0; // touching right to left ...
+      goto loc_g_6258;
+
+      break;
+
+    case keySpaceDown: // 7
+      RedDiskReleaseFlag = 0; // touching up to down ...
+      goto loc_g_6288;
+
+      break;
+
+    case keySpaceRight: // 8
+      RedDiskReleaseFlag = 0; // touching left to right ...
+      goto loc_g_62B2;
+
+      break;
+
+    case keySpace: // 9
+      goto loc_g_62E2;                         // no move ...
+
+      break;
+
+    default:
+      RedDiskReleaseFlag = 0;
+      return;
+      break;
+  }
+
+  // ==========================================================================
+  // moving down to up ...
+  // ==========================================================================
+
+loc_g_6078:
+  // FS:
+  MurphyDY = -2;
+  // end of FS
+  ax = PlayField16[*si - FieldWidth];
+  al = LowByte(ax);
+  if (ax == fiSpace)
+    goto loc_g_6312;
+
+  if (ax == fiBase)
+    goto loc_g_63D3;
+
+  if (al == fiBug)
+    goto loc_g_63C2;
+
+  if (ax == fiInfotron)
+    goto loc_g_65C6;
+
+  if (ax == fiExit)
+    goto loc_g_6756;
+
+  if (al == fiTerminal)
+    goto loc_g_6817;
+
+  if (al == fiPortUp || al == fiPortUpAndDown || al == fiPortAllDirections)
+    goto loc_g_6916;
+
+  if (al == fiRedDisk)
+    goto loc_g_69A6;
+
+  if (al == fiYellowDisk)
+    goto loc_g_6AB8;
+
+  if (! subMoveKillsMurphy(*si - FieldWidth, ax, bl))
+    goto loc_g_6078;
+
+  return;
+
+  // ==========================================================================
+  // moving right to left ...
+  // ==========================================================================
+
+loc_g_60DA:
+  // FS:
+  MurphyDX = -2;
+  // end of FS
+  MurphyVarFaceLeft = 1;
+  ax = PlayField16[*si - 1];
+  al = LowByte(ax);
+  if (ax == fiSpace)
+    goto loc_g_6341;
+
+  if (ax == fiBase)
+    goto loc_g_641C;
+
+  if (al == fiBug)
+    goto loc_g_640B;
+
+  if (ax == fiInfotron)
+    goto loc_g_65FE;
+
+  if (ax == fiExit)
+    goto loc_g_6756;
+
+  if (ax == fiZonk)
+    goto loc_g_679B;
+
+  if (al == fiTerminal)
+    goto loc_g_684E;
+
+  if (al == fiPortLeft || al == fiPortLeftAndRight || al == fiPortAllDirections)
+    goto loc_g_693A;
+
+  if (ax == fiRedDisk)
+    goto loc_g_69CE;
+
+  if (ax == fiYellowDisk)
+    goto loc_g_6AF1;
+
+  if (ax == fiOrangeDisk)
+    goto loc_g_6B9B;
+
+  if (! subMoveKillsMurphy(*si - 1, ax, bl))
+    goto loc_g_60DA;
+
+  return;
+
+  // ==========================================================================
+  // moving up to down ...
+  // ==========================================================================
+
+loc_g_6154:
+  // FS:
+  MurphyDY = 2;
+  // end of FS
+  ax = PlayField16[*si + FieldWidth];
+  al = LowByte(ax);
+  if (ax == fiSpace)
+    goto loc_g_6364;
+
+  if (ax == fiBase)
+    goto loc_g_6459;
+
+  if (al == fiBug)
+    goto loc_g_6448;
+
+  if (ax == fiInfotron)
+    goto loc_g_662A;
+
+  if (ax == fiExit)
+    goto loc_g_6756;
+
+  if (al == fiTerminal)
+    goto loc_g_6884;
+
+  if (al == fiPortDown || al == fiPortUpAndDown || al == fiPortAllDirections)
+    goto loc_g_695E;
+
+  if (al == fiRedDisk)
+    goto loc_g_69F7;
+
+  if (al == fiYellowDisk)
+    goto loc_g_6B2A;
+
+  if (! subMoveKillsMurphy(*si + FieldWidth, ax, bl))
+    goto loc_g_6154;
+
+  return;
+
+  // ==========================================================================
+  // moving left to right ...
+  // ==========================================================================
+
+loc_g_61B6:
+  // FS:
+  MurphyDX = 2;
+  // end of FS
+  MurphyVarFaceLeft = 0;
+  ax = PlayField16[*si + 1];
+  al = LowByte(ax);
+  if (ax == fiSpace)
+    goto loc_g_6399;
+
+  if (ax == fiBase)
+    goto loc_g_64A2;
+
+  if (al == fiBug)
+    goto loc_g_6491;
+
+  if (ax == fiInfotron)
+    goto loc_g_6662;
+
+  if (ax == fiExit)
+    goto loc_g_6756;
+
+  if (ax == fiZonk)
+    goto loc_g_67D4;
+
+  if (al == fiTerminal)
+    goto loc_g_68BA;
+
+  if (al == fiPortRight || al == fiPortLeftAndRight || al == fiPortAllDirections)
+    goto loc_g_6982;
+
+  if (al == fiRedDisk)
+    goto loc_g_6A1F;
+
+  if (al == fiYellowDisk)
+    goto loc_g_6B63;
+
+  if (ax == fiOrangeDisk)
+    goto loc_g_6BD3;
+
+  if (! subMoveKillsMurphy(*si + 1, ax, bl))
+    goto loc_g_61B6;
+
+  return;
+
+  // ==========================================================================
+  // touching down to up ...
+  // ==========================================================================
+
+loc_g_622E:
+  // FS:
+  ClearPos = -1;
+  dxPos = *si - FieldWidth;
+  // end of FS
+  ax = PlayField16[*si - FieldWidth];
+  al = LowByte(ax);
+  al = LowByte(ax);
+  if (ax == fiBase)
+    goto loc_g_64DF;
+
+  if (al == fiBug)
+    goto loc_g_64CE;
+
+  if (ax == fiInfotron)
+    goto loc_g_668E;
+
+  if (al == fiTerminal)
+    goto loc_g_6817;
+
+  if (al == fiRedDisk)
+    goto loc_g_6A48;
+
+  return;
+
+  // ==========================================================================
+  // touching right to left ...
+  // ==========================================================================
+
+loc_g_6258:
+  // FS:
+  ClearPos = -1;
+  dxPos = *si - 1;
+  // end of FS
+  MurphyVarFaceLeft = 1;
+  ax = PlayField16[*si - 1];
+  al = LowByte(ax);
+  if (ax == fiBase)
+    goto loc_g_651D;
+
+  if (al == fiBug)
+    goto loc_g_650C;
+
+  if (ax == fiInfotron)
+    goto loc_g_66C0;
+
+  if (al == fiTerminal)
+    goto loc_g_684E;
+
+  if (al == fiRedDisk)
+    goto loc_g_6A64;
+
+  return;
+
+  // ==========================================================================
+  // touching up to down ...
+  // ==========================================================================
+
+loc_g_6288:
+  // FS:
+  ClearPos = -1;
+  dxPos = *si + FieldWidth;
+  // end of FS
+  ax = PlayField16[*si + FieldWidth];
+  al = LowByte(ax);
+  if (ax == fiBase)
+    goto loc_g_655B;
+
+  if (al == fiBug)
+    goto loc_g_654A;
+
+  if (ax == fiInfotron)
+    goto loc_g_66F2;
+
+  if (al == fiTerminal)
+    goto loc_g_6884;
+
+  if (al == fiRedDisk)
+    goto loc_g_6A80;
+
+  return;
+
+  // ==========================================================================
+  // touching left to right ...
+  // ==========================================================================
+
+loc_g_62B2:
+  // FS:
+  ClearPos = -1;
+  dxPos = *si + 1;
+  // end of FS
+  MurphyVarFaceLeft = 0;
+  ax = PlayField16[*si + 1];
+  al = LowByte(ax);
+  if (ax == fiBase)
+    goto loc_g_6599;
+
+  if (al == fiBug)
+    goto loc_g_6588;
+
+  if (ax == fiInfotron)
+    goto loc_g_6724;
+
+  if (al == fiTerminal)
+    goto loc_g_68BA;
+
+  if (al == fiRedDisk)
+    goto loc_g_6A9C;
+
+  return;
+
+  // ==========================================================================
+  // Release Red disk: no move ...
+  // ==========================================================================
+
+loc_g_62E2:
+  // FS:
+  ClearPos = -1;
+  // end of FS
+  if (LowByte(RedDiskCount) == 0)
+    return;
+
+  if (LowByte(RedDiskReleasePhase) != 0)
+    return;
+
+  if (LowByte(RedDiskReleaseFlag) != 1)
+    return;
+
+  MovHighByte(&PlayField16[*si], 0x2A);
+  MovingPictureSequencePhase = 0x40; // init picture move sequence
+  dx1 = aniRedDisk;
+  MovLowByte(&RedDiskReleasePhase, 1);
+  RedDiskReleaseMurphyPos = *si;             // remember Murphy's location
+  goto loc_Split;
+
+  // ==========================================================================
+  // SPACE moving down to up
+  // ==========================================================================
+
+loc_g_6312:
+  dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyMoveUpRight : aniMurphyMoveUpLeft);
+  PlayField16[*si - FieldWidth] = 0x103;
+  PlayField16[*si] = 0x300;
+  *si = *si - FieldWidth;
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // SPACE moving right to left
+  // ==========================================================================
+
+loc_g_6341:
+  dx1 = aniMurphyMoveLeft;
+  PlayField16[*si - 1] = 0x203;
+  PlayField16[*si] = 0x300;
+  *si = *si - 1;
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // SPACE moving up to down, and when gravity is pulling!
+  // ==========================================================================
+
+loc_g_6364:
+  dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyMoveUpRight : aniMurphyMoveUpLeft);
+  PlayField16[*si + FieldWidth] = 0x303;
+  PlayField16[*si] = 0x300;
+  *si = *si + FieldWidth;
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // SPACE moving left to right
+  // ==========================================================================
+
+loc_g_6399:
+  dx1 = aniMurphyMoveRight;
+  PlayField16[*si + 1] = 0x403;
+  PlayField16[*si] = 0x300;
+  *si = *si + 1;
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // BUG moving down to up
+  // ==========================================================================
+
+loc_g_63C2:
+  if (SgnHighByte(PlayField16[*si - FieldWidth]) >= 0)
+  {
+    ExplodeFieldSP(*si);                 // Explode
+
+    return;
+  }
+
+  PlayField16[*si - FieldWidth] = fiBase;
+  // ==========================================================================
+  // BASE moving down to up
+  // ==========================================================================
+
+loc_g_63D3:
+  subSoundFX(*si, fiBase, actDigging);
+
+  dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyDigUpRight : aniMurphyDigUpLeft);
+  PlayField16[*si - FieldWidth] = 0x503;
+  PlayField16[*si] = 0x300;
+  *si = *si - FieldWidth;
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // BUG moving right to left
+  // ==========================================================================
+
+loc_g_640B:
+  if (SgnHighByte(PlayField16[*si - 1]) >= 0)
+  {
+    ExplodeFieldSP(*si);                 // Explode
+
+    return;
+  }
+
+  PlayField16[*si - 1] = fiBase;
+  // ==========================================================================
+  // BASE moving right to left
+  // ==========================================================================
+
+loc_g_641C:
+  subSoundFX(*si, fiBase, actDigging);
+
+  dx1 = aniMurphyDigLeft;
+  PlayField16[*si - 1] = 0x203;
+  PlayField16[*si] = 0x300;
+  *si = *si - 1;
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // BUG moving up to down
+  // ==========================================================================
+
+loc_g_6448:
+  if (SgnHighByte(PlayField16[*si + FieldWidth]) >= 0)
+  {
+    ExplodeFieldSP(*si);                 // Explode
+
+    return;
+  }
+
+  PlayField16[*si + FieldWidth] = fiBase;
+  // ==========================================================================
+  // BASE moving up to down
+  // ==========================================================================
+
+loc_g_6459:
+  subSoundFX(*si, fiBase, actDigging);
+
+  dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyDigUpRight : aniMurphyDigUpLeft);
+  PlayField16[*si + FieldWidth] = 0x703;
+  PlayField16[*si] = 0x300;
+  *si = *si + FieldWidth;
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // BUG moving left to right
+  // ==========================================================================
+
+loc_g_6491:
+  if (SgnHighByte(PlayField16[*si + 1]) >= 0)
+  {
+    ExplodeFieldSP(*si);                 // Explode
+
+    return;
+  }
+
+  PlayField16[*si + 1] = fiBase;
+  // ==========================================================================
+  // BASE moving left to right
+  // ==========================================================================
+
+loc_g_64A2:
+  subSoundFX(*si, fiBase, actDigging);
+
+  dx1 = aniMurphyDigRight;
+  PlayField16[*si + 1] = 0x803;
+  PlayField16[*si] = 0x300;
+  *si = *si + 1;
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // BUG touching down to up
+  // ==========================================================================
+
+loc_g_64CE:
+  if (SgnHighByte(PlayField16[*si - FieldWidth]) >= 0)
+  {
+    ExplodeFieldSP(*si);                 // Explode
+
+    return;
+  }
+
+  PlayField16[*si - FieldWidth] = fiBase;
+  // ==========================================================================
+  // BASE touching down to up
+  // ==========================================================================
+
+loc_g_64DF:
+  subCopyImageToScreen(*si, aniMurphyTouchUp);
+  subSoundFX(*si, fiBase, actDigging);
+
+  dx1 = aniTouchBase;
+  dxPos = *si - FieldWidth;
+  MovHighByte(&PlayField16[*si], 0x10);
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // BUG touching right to left
+  // ==========================================================================
+
+loc_g_650C:
+  if (SgnHighByte(PlayField16[*si - 1]) >= 0)
+  {
+    ExplodeFieldSP(*si);                 // Explode
+
+    return;
+  }
+
+  PlayField16[*si - 1] = fiBase;
+  // ==========================================================================
+  // BASE touching right to left
+  // ==========================================================================
+
+loc_g_651D:
+  subCopyImageToScreen(*si, aniMurphyTouchLeft);
+  subSoundFX(*si, fiBase, actDigging);
+
+  dx1 = aniTouchBase;
+  dxPos = *si - 1;
+  MovHighByte(&PlayField16[*si], 0x11);
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // BUG touching up to down
+  // ==========================================================================
+
+loc_g_654A:
+  if (SgnHighByte(PlayField16[*si + FieldWidth]) >= 0)
+  {
+    ExplodeFieldSP(*si);                 // Explode
+
+    return;
+  }
+
+  PlayField16[*si + FieldWidth] = fiBase;
+  // ==========================================================================
+  // BASE touching up to down
+  // ==========================================================================
+
+loc_g_655B:
+  subCopyImageToScreen(*si, aniMurphyTouchDown);
+  subSoundFX(*si, fiBase, actDigging);
+
+  dx1 = aniTouchBase;
+  dxPos = *si + FieldWidth;
+  MovHighByte(&PlayField16[*si], 0x12);
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // BUG touching left to right
+  // ==========================================================================
+
+loc_g_6588:
+  if (SgnHighByte(PlayField16[*si + 1]) >= 0)
+  {
+    ExplodeFieldSP(*si);                 // Explode
+
+    return;
+  }
+
+  PlayField16[*si + 1] = fiBase;
+  // ==========================================================================
+  // BASE touching left to right
+  // ==========================================================================
+
+loc_g_6599:
+  subCopyImageToScreen(*si, aniMurphyTouchRight);
+  subSoundFX(*si, fiBase, actDigging);
+
+  dx1 = aniTouchBase;
+  dxPos = *si + 1;
+  MovHighByte(&PlayField16[*si], 0x13);
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // INFOTRON moving down to up
+  // ==========================================================================
+
+loc_g_65C6:
+  subSoundFX(*si, fiInfotron, actCollecting);
+
+  dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
+  PlayField16[*si - FieldWidth] = 0x903;
+  PlayField16[*si] = 0x300;
+  *si = *si - FieldWidth;
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // INFOTRON moving right to left
+  // ==========================================================================
+
+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;
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // INFOTRON moving up to down
+  // ==========================================================================
+
+loc_g_662A:
+  subSoundFX(*si, fiInfotron, actCollecting);
+
+  dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
+  PlayField16[*si + FieldWidth] = 0xB03;
+  PlayField16[*si] = 0x300;
+  *si = *si + FieldWidth;
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // INFOTRON moving left to right
+  // ==========================================================================
+
+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;
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // INFOTRON touching down to up
+  // ==========================================================================
+
+loc_g_668E:
+  subCopyImageToScreen(*si, aniMurphyTouchUp);
+  subSoundFX(*si, fiInfotron, actCollecting);
+
+  dx1 = aniTouchInfotron;
+  MovHighByte(&PlayField16[*si], 0x14);
+  MovHighByte(&PlayField16[*si - FieldWidth], 0xFF);
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // INFOTRON touching right to left
+  // ==========================================================================
+
+loc_g_66C0:
+  subCopyImageToScreen(*si, aniMurphyTouchLeft);
+  subSoundFX(*si, fiInfotron, actCollecting);
+
+  dx1 = aniTouchInfotron;
+  MovHighByte(&PlayField16[*si], 0x15);
+  MovHighByte(&PlayField16[*si - 1], 0xFF);
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // INFOTRON touching up to down
+  // ==========================================================================
+
+loc_g_66F2:
+  subCopyImageToScreen(*si, aniMurphyTouchDown);
+  subSoundFX(*si, fiInfotron, actCollecting);
+
+  dx1 = aniTouchInfotron;
+  MovHighByte(&PlayField16[*si], 0x16);
+  MovHighByte(&PlayField16[*si + FieldWidth], 0xFF);
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // INFOTRON touching left to right
+  // ==========================================================================
+
+loc_g_6724:
+  subCopyImageToScreen(*si, aniMurphyTouchRight);
+  subSoundFX(*si, fiInfotron, actCollecting);
+
+  dx1 = aniTouchInfotron;
+  MovHighByte(&PlayField16[*si], 0x17);
+  MovHighByte(&PlayField16[*si + 1], 0xFF);
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // EXIT pressed from any direction
+  // ==========================================================================
+
+loc_g_6756:
+  // FS
+  ClearPos = -1;
+  MurphyDX = 0;
+  MurphyDY = 0;
+  // end of FS
+  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);
+
+  LeadOutCounter = 0x40;          // quit: start lead-out
+  dx1 = aniMurphyExit;
+  MovHighByte(&PlayField16[*si], 0xD);
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // ZONK moving right to left
+  // ==========================================================================
+
+loc_g_679B:
+  ax = PlayField16[*si - 2];
+  if (ax != 0)
+    return;
+
+  MovHighByte(&PlayField16[*si - 2], 1);
+  subCopyImageToScreen(*si, aniPushLeft); // draw pushing murphy
+  dx1 = aniZonkRollLeft;
+  dxPos = *si - 1;
+  dx2 = aniPushLeft;
+  dx2Step = 1;
+  MovHighByte(&PlayField16[*si], 0xE);
+  goto loc_MoveNoSplit;
+
+  // ==========================================================================
+  // ZONK moving left to right
+  // ==========================================================================
+
+loc_g_67D4:
+  ax = PlayField16[*si + 2];
+  if (ax != 0)
+    return;
+
+  ax = PlayField16[*si + FieldWidth + 1];
+  if (ax == 0) // zonk falls
+    return;
+
+  MovHighByte(&PlayField16[*si + 2], 1);
+  subCopyImageToScreen(*si, aniPushRight); // draw pushing murphy
+  dx1 = aniZonkRollRight;
+  dxPos = *si + 1;
+  dx2 = aniPushRight;
+  dx2Step = -1;
+  MovHighByte(&PlayField16[*si], 0xF);
+  goto loc_MoveNoSplit;
+
+  // ==========================================================================
+  // TERMINAL moving/touching down to up
+  // ==========================================================================
+
+loc_g_6817:
+  subCopyImageToScreen(*si, aniMurphyTouchUp);
+  if (YellowDisksExploded != 0)
+  {
+    YawnSleepCounter = 40; // stay hypnotized
+
+    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;
+
+  // ==========================================================================
+  // TERMINAL moving/touching right to left
+  // ==========================================================================
+
+loc_g_684E:
+  subCopyImageToScreen(*si, aniMurphyTouchLeft);
+  if (YellowDisksExploded != 0)
+  {
+    YawnSleepCounter = 40; // stay hypnotized
+
+    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;
+
+  // ==========================================================================
+  // TERMINAL moving/touching up to down
+  // ==========================================================================
+
+loc_g_6884:
+  subCopyImageToScreen(*si, aniMurphyTouchDown);
+  if (YellowDisksExploded != 0)
+  {
+    YawnSleepCounter = 40; // stay hypnotized
+
+    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;
+
+  // ==========================================================================
+  // TERMINAL moving/touching left to right
+  // ==========================================================================
+
+loc_g_68BA:
+  subCopyImageToScreen(*si, aniMurphyTouchRight);
+  if (YellowDisksExploded != 0)
+  {
+    YawnSleepCounter = 40; // stay hypnotized
+
+    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
+  // ==========================================================================
+
+loc_g_68F0:
+  TerminalMaxCycles = 7;
+  YellowDisksExploded = 1;
+  for (i = 0; i <= LevelMax; i++)
+  {
+    if (PlayField16[i] == fiYellowDisk)
+      ExplodeFieldSP (i);
+  }
+
+  return;
+
+  // ==========================================================================
+  // PORT down to up, VERTICAL PORT, CROSS PORT all moving down to up
+  // ==========================================================================
+
+loc_g_6916:
+  if (PlayField16[*si - 2 * FieldWidth] != 0)
+    return;
+
+  dx1 = aniSplitUpDown;
+  dx2Step = -FieldWidth;
+  PlayField16[*si] = 0x1803;
+  PlayField16[*si - 2 * FieldWidth] = 0x300;
+  goto loc_StopSplit;
+
+  // ==========================================================================
+  // PORT right to left, HORIZONTAL PORT, CROSS PORT all moving right to left
+  // ==========================================================================
+
+loc_g_693A:
+  if (PlayField16[*si - 2] != 0)
+    return;
+
+  dx1 = aniMurphyMoveLeft;
+  dx2Step = -1;
+  PlayField16[*si] = 0x1903;
+  PlayField16[*si - 2] = 0x300;
+  goto loc_StopSplit;
+
+  // ==========================================================================
+  // PORT up to down, VERTICAL PORT, CROSS PORT all moving up to down
+  // ==========================================================================
+
+loc_g_695E:
+  if (PlayField16[*si + 2 * FieldWidth] != 0)
+    return;
+
+  dx1 = aniSplitUpDown;
+  dx2Step = FieldWidth;
+  PlayField16[*si] = 0x1A03;
+  PlayField16[*si + 2 * FieldWidth] = 0x300;
+  goto loc_StopSplit;
+
+  // ==========================================================================
+  // PORT left to right, HORIZONTAL PORT, CROSS PORT all moving left to right
+  // ==========================================================================
+
+loc_g_6982:
+  if (PlayField16[*si + 2] != 0)
+    return;
+
+  dx1 = aniMurphyMoveRight;
+  dx2Step = 1;
+  PlayField16[*si] = 0x1B03;
+  PlayField16[*si + 2] = 0x300;
+
+loc_StopSplit:
+  MovingPictureSequencePhase = 0; // stop picture move sequence
+  SplitMoveFlag = 1; // port: split movement
+  goto loc_Split;
+
+  // ==========================================================================
+  // RED DISK moving down to up
+  // ==========================================================================
+
+loc_g_69A6:
+  dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
+  PlayField16[*si] = 0x1C03;
+  PlayField16[*si - FieldWidth] = 0x300;
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // RED DISK moving right to left
+  // ==========================================================================
+
+loc_g_69CE:
+  dx1 = aniMurphyEatLeft;
+  PlayField16[*si] = 0x300; // !!!!!! this time we move murphy at sequence-start!
+  PlayField16[*si - 1] = 0x1D03;
+  *si = *si - 1;
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // RED DISK moving up to down
+  // ==========================================================================
+
+loc_g_69F7:
+  dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
+  PlayField16[*si] = 0x1E03;
+  PlayField16[*si + FieldWidth] = 0x300;
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // RED DISK moving left to right
+  // ==========================================================================
+
+loc_g_6A1F:
+  //  dx = aniMurphyEatRightRedDisk 'this sequence is 9 steps long!
+  dx1 = aniMurphyEatRight;
+  // --------------------------------------------------------------------------
+  // BugFix
+  // Table data_h_145A, pointed to by table data_h_105E, has a severe bug:
+  // The Red Disk sequence is 8 pictures long, but 9 are displayed, because it
+  // has 1 extra entry, which causes Murphy to end slightly shifted to the left!
+  // We may not fix the table, because then the timing of the game changes
+  // and several existing demo's do not run properly anymore.
+  // We only correct Murphies x-location here, when the sequence starts.
+  // Remember that this is not the real bug-fix, but we must live with
+  // this existing bug and correct for the consequences of it.
+
+  if (AllowEatRightRedDiskBug == 0) // Murphy's screen x-position
+    MurphyScreenXPos = MurphyScreenXPos - 2 * MurphyZoomFactor;
+
+  SeqPos = -1;
+  // FS: for me this means to blit the first animation frame twice
+  // end of BugFix
+  // --------------------------------------------------------------------------
+  PlayField16[*si] = 0x300; // !!!!!! this time we move murphy at sequence-start!
+  PlayField16[*si + 1] = 0x1F03;
+  *si = *si + 1;
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // RED DISK touching down to up
+  // ==========================================================================
+
+loc_g_6A48:
+  dx1 = aniTouchRedDisk;
+  MovHighByte(&PlayField16[*si], 0x20);
+  MovHighByte(&PlayField16[*si - FieldWidth], 3);
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // RED DISK touching right to left
+  // ==========================================================================
+
+loc_g_6A64:
+  dx1 = aniTouchRedDisk;
+  MovHighByte(&PlayField16[*si], 0x21);
+  MovHighByte(&PlayField16[*si - 1], 3);
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // RED DISK touching up to down
+  // ==========================================================================
+
+loc_g_6A80:
+  dx1 = aniTouchRedDisk;
+  MovHighByte(&PlayField16[*si], 0x22);
+  MovHighByte(&PlayField16[*si + FieldWidth], 3);
+  goto loc_StopNoSplit;
+
+  // ==========================================================================
+  // RED DISK touching left to right
+  // ==========================================================================
+
+loc_g_6A9C:
+  dx1 = aniTouchRedDisk;
+  MovHighByte(&PlayField16[*si], 0x23);
+  MovHighByte(&PlayField16[*si + 1], 3);
+
+loc_StopNoSplit:
+  MovingPictureSequencePhase = 0; // stop picture move sequence
+  goto loc_NoSplit;
+
+  // ==========================================================================
+  // YELLOW DISK moving down to up
+  // ==========================================================================
+
+loc_g_6AB8:
+  if (PlayField16[*si - 2 * FieldWidth] != 0)
+    return;
+
+  PlayField16[*si - 2 * FieldWidth] = 0x1200;
+  dx1 = aniYellowDisk;
+  dxPos = *si - FieldWidth;
+  dx2 = (MurphyVarFaceLeft == 0 ? aniPushRight : aniPushLeft);
+  dx2Step = FieldWidth;
+  PlayField16[*si] = 0x2403;
+  subCopyImageToScreen(*si, dx2);
+  goto loc_MoveNoSplit;
+
+  // ==========================================================================
+  // YELLOW DISK moving right to left
+  // ==========================================================================
+
+loc_g_6AF1:
+  if (PlayField16[*si - 2] != 0)
+    return;
+
+  PlayField16[*si - 2] = 0x1200;
+  subCopyImageToScreen(*si, aniPushLeft);
+  dx1 = aniYellowDisk;
+  dxPos = *si - 1;
+  dx2 = aniPushLeft;
+  dx2Step = 1;
+  PlayField16[*si] = 0x2503;
+  goto loc_MoveNoSplit;
+
+  // ==========================================================================
+  // YELLOW DISK moving up to down
+  // ==========================================================================
+
+loc_g_6B2A:
+  if (PlayField16[*si + 2 * FieldWidth] != 0)
+    return;
+
+  PlayField16[*si + 2 * FieldWidth] = 0x1200;
+  dx1 = aniYellowDisk;
+  dxPos = *si + FieldWidth;
+  dx2 = (MurphyVarFaceLeft == 0 ? aniPushRight : aniPushLeft);
+  dx2Step = -FieldWidth;
+  PlayField16[*si] = 0x2703;
+  subCopyImageToScreen(*si, dx2);
+  goto loc_MoveNoSplit;
+
+  // ==========================================================================
+  // YELLOW DISK moving left to right
+  // ==========================================================================
+
+loc_g_6B63:
+  if (PlayField16[*si + 2] != 0)
+    return;
+
+  PlayField16[*si + 2] = 0x1200;
+  subCopyImageToScreen(*si, aniPushRight);
+  dx1 = aniYellowDisk;
+  dxPos = *si + 1;
+  dx2 = aniPushRight;
+  dx2Step = -1;
+  PlayField16[*si] = 0x2603;
+  goto loc_MoveNoSplit;
+
+  // ==========================================================================
+  // ORANGE DISK moving right to left
+  // ==========================================================================
+
+loc_g_6B9B:
+  if (PlayField16[*si - 2] != 0)
+    return;
+
+  PlayField16[*si - 2] = 0x800;
+  subCopyImageToScreen(*si, aniPushLeft);
+  dx1 = aniOrangeDisk;
+  dxPos = *si - 1;
+  dx2 = aniPushLeft;
+  dx2Step = 1;
+  PlayField16[*si] = 0x2803;
+  goto loc_MoveNoSplit;
+
+  // ==========================================================================
+  // ORANGE DISK moving left to right
+  // ==========================================================================
+
+loc_g_6BD3:
+  if (PlayField16[*si + 2] != 0)
+    return;
+
+  if (PlayField16[*si + FieldWidth + 1] == 0) // falling goes before pushing
+    return;
+
+  PlayField16[*si + 2] = 0x100;
+  subCopyImageToScreen(*si, aniPushRight);
+  dx1 = aniOrangeDisk;
+  dxPos = *si + 1;
+  dx2 = aniPushRight;
+  dx2Step = -1;
+  PlayField16[*si] = 0x2903;
+  // ==========================================================================
+  // Copy screen animation action table to action work space
+  // (To paint sequence: Push Zonk/Disk / release red disk / Port passing)
+  // ==========================================================================
+
+loc_MoveNoSplit:
+  MovingPictureSequencePhase = 8; // init picture move sequence
+
+loc_NoSplit:
+  SplitMoveFlag = 0; // no port: no split movement
+
+loc_Split:
+  //  copy/store global move sequence info????????????????????????????????????
+  //  ... dont think so ...(FS)
+  // ==========================================================================
+  // Proceed with all movements
+  // ==========================================================================
+
+locProceedMovingMurphy: // proceed moving murphy
+  YawnSleepCounter = 0; // Wake up sleeping Murphy
+  ax = MovingPictureSequencePhase;            // sequence busy?
+  if (ax == 0)             // no -- start sequence!
+    goto loc_g_6C8F;
+
+  ax = ax - 1;   // next picture of sequence
+  MovingPictureSequencePhase = ax;            // store for later
+
+  if (ax == 0) // Sound effects
+  {
+    switch (HighByte(PlayField16[*si]))
+    {
+      case 0xE:
+      case 0xF:
+       subSoundFX(*si, fiZonk, actPushing);
+       break;
+
+      case 0x28:
+      case 0x29:
+       subSoundFX(*si, fiOrangeDisk, actPushing);
+       break;
+
+      case 0x24:
+      case 0x25:
+      case 0x26:
+      case 0x27:
+       subSoundFX(*si, fiYellowDisk, actPushing);
+       break;
+
+      default:
+       break;
+    }
+  }
+
+  bl = HighByte(PlayField16[*si]);
+  if (bl == 0xE)        // Push Zonk to left
+    goto loc_g_6F7E;
+
+  if (bl == 0xF)        // Push Zonk to right
+    goto loc_g_6FBC;
+
+  if (bl == 0x28)       // Push orange disk to left
+    goto loc_g_6FFA;
+
+  if (bl == 0x29)       // Push orange disk to right
+    goto loc_g_7038;
+
+  if (bl == 0x24)       // Push yellow disk up
+    goto loc_g_7076;
+
+  if (bl == 0x25)       // Push yellow disk to left
+    goto loc_g_70B4;
+
+  if (bl == 0x27)       // Push yellow disk down
+    goto loc_g_70F2;
+
+  if (bl == 0x26)       // Push yellow disk to right
+    goto loc_g_7130;
+
+  if (bl == 0x2A)       // Red disk release timer
+    goto loc_g_716E;
+
+  return;
+
+  // ==========================================================================
+  // Paint frame of MOVING.DAT sequence
+  // ==========================================================================
+
+loc_g_6C8F:
+
+#if 1
+  if (SeqPos <= 0)
+    dx1SequenceLength = getSequenceLength(dx1);
+#endif
+
+  if (SplitMoveFlag == 0)
+  {
+    // ++++++++++++++++++++++++++
+    // Begin of normal movement
+    MurphyScreenXPos = MurphyScreenXPos + MurphyDX * MurphyZoomFactor;
+    MurphyScreenYPos = MurphyScreenYPos + MurphyDY * MurphyZoomFactor;
+
+    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);
+    }
+
+    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);
+      }
+    }
+
+    // End of normal movement
+    // ------------------------
+  }
+  else
+  {
+    // ++++++++++++++++++++++++++++++++
+    // Begin of split movement (port)
+    MurphyScreenXPos = MurphyScreenXPos + 2 * MurphyDX * MurphyZoomFactor;
+    MurphyScreenYPos = MurphyScreenYPos + 2 * MurphyDY * MurphyZoomFactor;
+    subCopyImageToScreen(ClearPos, aniSpace); // clear the field that murphy leaves
+    tDeltaX = MurphyDX * LocalStretch * (SeqPos + 1);
+    tDeltaY = MurphyDY * LocalStretch * (SeqPos + 1);
+    X = GetStretchX(dxPos) + tDeltaX;
+    Y = GetStretchY(dxPos) + tDeltaY;
+    DDSpriteBuffer_BltImg(X, Y, dx1, SeqPos); // plot first murphy
+
+    tPos = dxPos + dx2Step;
+    X = GetStretchX(tPos);
+    Y = GetStretchY(tPos);
+    DDSpriteBuffer_BltImg(X + tDeltaX, Y + tDeltaY, dx1, SeqPos); // plot second murphy
+    DDSpriteBuffer_BltImg(X, Y, fiGraphic[LowByte(PlayField16[tPos])], 0); // replot the port on top
+    // End of split movement (port)
+    // ------------------------------
+  } // 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;
+  MurphyYPos = MurphyYPos + MurphyDY;
+  bl = HighByte(PlayField16[*si]);  // animation phase
+  MovHighByte(&PlayField16[*si], 0);
+
+  if (bl == 0x1)    // space, moving up
+    goto loc_g_6EC8;
+
+  if (bl == 0x2)    // space, moving left
+    goto loc_g_6EE6;
+
+  if (bl == 0x3)    // space, moving down
+    goto loc_g_6F04;
+
+  if (bl == 0x4)    // space, moving right
+    goto loc_g_71C4;
+
+  if (bl == 0x5)    // base , moving up
+    goto loc_g_6EC8;
+
+  if (bl == 0x6)    // base , moving left -> 6 is not used, value is set to 2 instead of 6!
+    goto loc_g_6EE6;
+
+  if (bl == 0x7)    // base , moving down
+    goto loc_g_6F04;
+
+  if (bl == 0x8)    // base , moving right
+    goto loc_g_71C4;
+
+  if (bl == 0x9)    // infotron, moving up
+    goto loc_g_6EBA;
+
+  if (bl == 0xA)      // infotron, moving left
+    goto loc_g_6ED8;
+
+  if (bl == 0xB)    // infotron, moving down
+    goto loc_g_6EF6;
+
+  if (bl == 0xC)      // infotron, moving right
+    goto loc_g_71B6;
+
+  if (bl == 0xD)      // exit
+    goto loc_g_6F77;
+
+  if (bl == 0xE)      // zonk, pushing left
+    goto loc_g_6F18;
+
+  if (bl == 0xF)      // zonk, pushing right
+    goto loc_g_6F3B;
+
+  if (bl == 0x10)   // base , touching up
+    goto loc_g_71E2;
+
+  if (bl == 0x11)   // base , touching left
+    goto loc_g_71FE;
+
+  if (bl == 0x12)   // base , touching down
+    goto loc_g_721A;
+
+  if (bl == 0x13)   // base , touching right
+    goto loc_g_7236;
+
+  if (bl == 0x14)   // infotron touching up
+    goto loc_g_71D4;
+
+  if (bl == 0x15)   // infotron touching left
+    goto loc_g_71F0;
+
+  if (bl == 0x16)   // infotron touching down
+    goto loc_g_720C;
+
+  if (bl == 0x17)   // infotron touching right
+    goto loc_g_7228;
+
+  if (bl == 0x18)     // port up
+    goto loc_g_7244;
+
+  if (bl == 0x19)     // port left
+    goto loc_g_7272;
+
+  if (bl == 0x1A)     // port down
+    goto loc_g_729F;
+
+  if (bl == 0x1B)     // port right
+    goto loc_g_72CD;
+
+  if (bl == 0x1C)   // red disk, moving up
+    goto loc_g_72FA;
+
+  if (bl == 0x1D)   // red disk, moving left
+    goto loc_g_7318;
+
+  if (bl == 0x1E)   // red disk, moving down
+    goto loc_g_7333;
+
+  if (bl == 0x1F)   // red disk, moving right -> 9-Step-Bug!
+    goto loc_g_7351;
+
+  if (bl == 0x20)   // red disk, touching up
+    goto loc_g_736C;
+
+  if (bl == 0x21)   // red disk, touching left
+    goto loc_g_7381;
+
+  if (bl == 0x22)   // red disk, touching down
+    goto loc_g_7396;
+
+  if (bl == 0x23)   // red disk, touching right
+    goto loc_g_73AB;
+
+  if (bl == 0x24)     // yellow disk, pushing up
+    goto loc_g_73C0;
+
+  if (bl == 0x25)     // yellow disk, pushing left
+    goto loc_g_73DD;
+
+  if (bl == 0x26)     // yellow disk, pushing right -> order of "down" exchanged with "right"!
+    goto loc_g_7417;
+
+  if (bl == 0x27)     // yellow disk, pushing down  -> order of "down" exchanged with "right"!
+    goto loc_g_73FA;
+
+  if (bl == 0x28)     // orange disk, pushing left
+    goto loc_g_7434;
+
+  if (bl == 0x29)     // orange disk, pushing right
+    goto loc_g_7451;
+
+  if (bl == 0x2A)   // red disk, release
+    goto loc_g_747F;
+
+  ExitToMenuFlag = 1;
+
+  return;
+
+  // ==========================================================================
+  //                       infotron, moving up
+  // ==========================================================================
+
+loc_g_6EBA:
+  if (0 < LowByte(InfotronsNeeded))
+    InfotronsNeeded = InfotronsNeeded - 1;
+
+loc_g_6EC8: // space, base
+  PlayField16[*si] = fiMurphy;
+  subAdjustZonksInfotronsAboveMurphy(*si + FieldWidth);
+
+  return;
+
+  // ==========================================================================
+  //                       infotron, moving left
+  // ==========================================================================
+
+loc_g_6ED8:
+  if (0 < LowByte(InfotronsNeeded))
+    InfotronsNeeded = InfotronsNeeded - 1;
+
+loc_g_6EE6: // space, base
+  PlayField16[*si] = fiMurphy;
+  subAdjustZonksInfotronsAboveMurphy(*si + 1);
+
+  return;
+
+  // ==========================================================================
+  //                       infotron, moving down
+  // ==========================================================================
+
+loc_g_6EF6:
+  if (0 < LowByte(InfotronsNeeded))
+    InfotronsNeeded = InfotronsNeeded - 1;
+
+loc_g_6F04: // space, base
+  if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion)
+    PlayField16[*si - FieldWidth] = 0;
+
+  PlayField16[*si] = fiMurphy;
+
+  return;
+
+  // ==========================================================================
+  //                       infotron, moving right
+  // ==========================================================================
+
+loc_g_71B6:
+  if (0 < LowByte(InfotronsNeeded))
+    InfotronsNeeded = InfotronsNeeded - 1;
+
+loc_g_71C4: // space, base
+  subAdjustZonksInfotronsAboveMurphy(*si - 1);
+  PlayField16[*si] = fiMurphy;
+
+  return;
+
+  // ==========================================================================
+  //                       infotron, touching up
+  // ==========================================================================
+
+loc_g_71D4:
+  if (0 < LowByte(InfotronsNeeded))
+    InfotronsNeeded = InfotronsNeeded - 1;
+
+loc_g_71E2: // base
+  if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion)
+    PlayField16[*si - FieldWidth] = 0;
+
+  return;
+
+  // ==========================================================================
+  //                       infotron, touching left
+  // ==========================================================================
+
+loc_g_71F0:
+  if (0 < LowByte(InfotronsNeeded))
+    InfotronsNeeded = InfotronsNeeded - 1;
+
+loc_g_71FE: // base
+  if (LowByte(PlayField16[*si - 1]) != fiExplosion)
+    PlayField16[*si - 1] = 0;
+
+  return;
+
+  // ==========================================================================
+  //                       infotron, touching down
+  // ==========================================================================
+
+loc_g_720C:
+  if (0 < LowByte(InfotronsNeeded))
+    InfotronsNeeded = InfotronsNeeded - 1;
+
+loc_g_721A: // base
+  if (LowByte(PlayField16[*si + FieldWidth]) != fiExplosion)
+    PlayField16[*si + FieldWidth] = 0;
+
+  return;
+
+  // ==========================================================================
+  //                       infotron, touching right
+  // ==========================================================================
+
+loc_g_7228:
+  if (0 < LowByte(InfotronsNeeded))
+    InfotronsNeeded = InfotronsNeeded - 1;
+
+loc_g_7236: // base
+  if (LowByte(PlayField16[*si + 1]) != fiExplosion)
+    PlayField16[*si + 1] = 0;
+
+  return;
+
+  // ==========================================================================
+  //                       zonk, pushing left
+  // ==========================================================================
+
+loc_g_6F18:
+  if (LowByte(PlayField16[*si]) != fiExplosion)
+    PlayField16[*si] = 0;
+
+  PlayField16[*si - 1] = fiMurphy;
+  PlayField16[*si - 2] = fiZonk;
+  subExplodeSnikSnaksBelow(*si - 2);
+  *si = *si - 1;
+
+  return;
+
+  // ==========================================================================
+  //                       zonk, pushing right
+  // ==========================================================================
+
+loc_g_6F3B:
+  if (LowByte(PlayField16[*si]) != fiExplosion)
+    PlayField16[*si] = 0;
+
+  PlayField16[*si + 1] = fiMurphy;
+  PlayField16[*si + 2] = fiZonk;
+  subExplodeSnikSnaksBelow(*si + 2);
+  *si = *si + 1;
+
+  return;
+
+  // ==========================================================================
+  //                       exit
+  // ==========================================================================
+
+loc_g_6F77:
+  ExitToMenuFlag = 1;
+
+#if 1
+  PlayField16[*si] = fiSpace;  // remove Murphy from playfield after exiting
+#endif
+
+  return;
+
+  // ==========================================================================
+  //               Push Zonk from right to left
+  // ==========================================================================
+
+loc_g_6F7E:
+  if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiZonk)
+    return;
+
+  PlayField16[*si] = fiMurphy; // else restore - no more zonk pushing!
+  PlayField16[*si - 1] = fiZonk;
+  if (LowByte(PlayField16[*si - 2]) != fiExplosion)
+    PlayField16[*si - 2] = 0;
+
+  subCopyImageToScreen(*si, aniMurphy);
+
+  return;
+
+  // ==========================================================================
+  //                       Push Zonk from left to right
+  // ==========================================================================
+
+loc_g_6FBC:
+  if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiZonk)
+    return;
+
+  PlayField16[*si] = fiMurphy; // else restore - no more zonk pushing!
+  PlayField16[*si + 1] = fiZonk;
+  if (LowByte(PlayField16[*si + 2]) != fiExplosion)
+    PlayField16[*si + 2] = 0;
+
+  subCopyImageToScreen(*si, aniMurphy);
+
+  return;
+
+  // ==========================================================================
+  //               Push orange disk from right to left
+  // ==========================================================================
+
+loc_g_6FFA:
+  if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiOrangeDisk)
+    return;
+
+  PlayField16[*si] = fiMurphy; // else restore - no more pushing!
+  PlayField16[*si - 1] = fiOrangeDisk;
+  if (LowByte(PlayField16[*si - 2]) != fiExplosion)
+    PlayField16[*si - 2] = 0;
+
+  subCopyImageToScreen(*si, aniMurphy);
+
+  return;
+
+  // ==========================================================================
+  //               Push orange disk from left to right
+  // ==========================================================================
+
+loc_g_7038:
+  if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiOrangeDisk)
+    return;
+
+  PlayField16[*si] = fiMurphy; // else restore - no more pushing!
+  PlayField16[*si + 1] = fiOrangeDisk;
+  if (LowByte(PlayField16[*si + 2]) != fiExplosion)
+    PlayField16[*si + 2] = 0;
+
+  subCopyImageToScreen(*si, aniMurphy);
+
+  return;
+
+  // ==========================================================================
+  //               Push yellow disk from down to up
+  // ==========================================================================
+
+loc_g_7076:
+  if (DemoKeyCode == keyUp && PlayField16[*si - FieldWidth] == fiYellowDisk)
+    return;
+
+  PlayField16[*si] = fiMurphy; // else restore - no more pushing!
+  PlayField16[*si - FieldWidth] = fiYellowDisk;
+  if (LowByte(PlayField16[*si - 2 * FieldWidth]) != fiExplosion)
+    PlayField16[*si - 2 * FieldWidth] = 0;
+
+  subCopyImageToScreen(*si, aniMurphy);
+
+  return;
+
+  // ==========================================================================
+  //               Push yellow disk from right to left
+  // ==========================================================================
+
+loc_g_70B4:
+  if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiYellowDisk)
+    return;
+
+  PlayField16[*si] = fiMurphy; // else restore - no more pushing!
+  PlayField16[*si - 1] = fiYellowDisk;
+  if (LowByte(PlayField16[*si - 2]) != fiExplosion)
+    PlayField16[*si - 2] = 0;
+
+  subCopyImageToScreen(*si, aniMurphy);
+
+  return;
+
+  // ==========================================================================
+  //               Push yellow disk from up to down
+  // ==========================================================================
+
+loc_g_70F2:
+  if (DemoKeyCode == keyDown && PlayField16[*si + FieldWidth] == fiYellowDisk)
+    return;
+
+  PlayField16[*si] = fiMurphy; // else restore - no more pushing!
+  PlayField16[*si + FieldWidth] = fiYellowDisk;
+  if (LowByte(PlayField16[*si + 2 * FieldWidth]) != fiExplosion)
+    PlayField16[*si + 2 * FieldWidth] = 0;
+
+  subCopyImageToScreen(*si, aniMurphy);
+
+  return;
+
+  // ==========================================================================
+  //               Push yellow disk from left to right
+  // ==========================================================================
+
+loc_g_7130:
+  if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiYellowDisk)
+    return;
+
+  PlayField16[*si] = fiMurphy; // else restore - no more pushing!
+  PlayField16[*si + 1] = fiYellowDisk;
+  if (LowByte(PlayField16[*si + 2]) != fiExplosion)
+    PlayField16[*si + 2] = 0;
+
+  subCopyImageToScreen(*si, aniMurphy);
+
+  return;
+
+  // ==========================================================================
+  //               time red disk release (space)
+  // ==========================================================================
+
+loc_g_716E:
+  if (DemoKeyCode != keySpace)
+  {
+    PlayField16[*si] = fiMurphy;
+    subCopyImageToScreen(*si, aniMurphy);
+    RedDiskReleasePhase = 0;
+  }
+  else if (MovingPictureSequencePhase == 0x20)
+  {
+    // anxious murphy, dropping red disk
+    subCopyImageToScreen(*si, aniMurphyDropping);
+    RedDiskReleasePhase = 1;
+  }
+
+  return;
+
+  // ==========================================================================
+  // Special port down to up
+  // ==========================================================================
+
+loc_g_7244:
+  if (LowByte(PlayField16[*si]) != fiExplosion)
+    PlayField16[*si] = 0;
+
+  PlayField16[*si - 2 * FieldWidth] = fiMurphy;
+  SplitMoveFlag = 0;
+  *si = *si - FieldWidth;
+  if (HighByte(PlayField16[*si]) == 1)
+    subSpPortTest(*si);
+
+  *si = *si - FieldWidth;
+
+  return;
+
+  // ==========================================================================
+  // Special port right to left
+  // ==========================================================================
+
+loc_g_7272:
+  if (LowByte(PlayField16[*si]) != fiExplosion)
+    PlayField16[*si] = 0;
+
+  PlayField16[*si - 2] = fiMurphy;
+  SplitMoveFlag = 0;
+  *si = *si - 1;
+  if (HighByte(PlayField16[*si]) == 1)
+    subSpPortTest(*si);
+
+  *si = *si - 1;
+
+  return;
+
+  // ==========================================================================
+  // Special port up to down
+  // ==========================================================================
+
+loc_g_729F:
+  if (LowByte(PlayField16[*si]) != fiExplosion)
+    PlayField16[*si] = 0;
+
+  PlayField16[*si + 2 * FieldWidth] = fiMurphy;
+  SplitMoveFlag = 0;
+  *si = *si + FieldWidth;
+  if (HighByte(PlayField16[*si]) == 1)
+    subSpPortTest(*si);
+
+  *si = *si + FieldWidth;
+
+  return;
+
+  // ==========================================================================
+  // Special port left to right
+  // ==========================================================================
+
+loc_g_72CD:
+  if (LowByte(PlayField16[*si]) != fiExplosion)
+    PlayField16[*si] = 0;
+
+  PlayField16[*si + 2] = fiMurphy;
+  SplitMoveFlag = 0;
+  *si = *si + 1;
+  if (HighByte(PlayField16[*si]) == 1)
+    subSpPortTest(*si);
+
+  *si = *si + 1;
+
+  return;
+
+  // ==========================================================================
+  // Move Red Disk up
+  // ==========================================================================
+
+loc_g_72FA:
+  if (LowByte(PlayField16[*si]) != fiExplosion)
+    PlayField16[*si] = 0;
+
+  *si = *si - FieldWidth;
+  PlayField16[*si] = fiMurphy;
+  subEatRedDisk(*si); // inc+show Murphy's red disks
+
+  return;
+
+  // ==========================================================================
+  // Move Red Disk left
+  // ==========================================================================
+
+loc_g_7318:
+  if (LowByte(PlayField16[*si + 1]) != fiExplosion)
+    PlayField16[*si + 1] = 0;
+
+  PlayField16[*si] = fiMurphy;
+  subEatRedDisk(*si); // inc+show Murphy's red disks
+
+  return;
+
+  // ==========================================================================
+  // Move Red Disk down
+  // ==========================================================================
+
+loc_g_7333:
+  if (LowByte(PlayField16[*si]) != fiExplosion)
+    PlayField16[*si] = 0;
+
+  *si = *si + FieldWidth;
+  PlayField16[*si] = fiMurphy;
+  subEatRedDisk(*si); // inc+show Murphy's red disks
+
+  return;
+
+  // ==========================================================================
+  // Move Red Disk right
+  // ==========================================================================
+
+loc_g_7351:
+  if (LowByte(PlayField16[*si - 1]) != fiExplosion)
+    PlayField16[*si - 1] = 0;
+
+  PlayField16[*si] = fiMurphy;
+  subEatRedDisk(*si); // inc+show Murphy's red disks
+
+  return;
+
+  // ==========================================================================
+  // Eat Red Disk up
+  // ==========================================================================
+
+loc_g_736C:
+  if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion)
+    PlayField16[*si - FieldWidth] = 0;
+
+  subEatRedDisk(*si - FieldWidth); // inc+show Murphy's red disks
+
+  return;
+
+  // ==========================================================================
+  // Eat Red Disk left
+  // ==========================================================================
+
+loc_g_7381:
+  if (LowByte(PlayField16[*si - 1]) != fiExplosion)
+    PlayField16[*si - 1] = 0;
+
+  subEatRedDisk(*si - 1); // inc+show Murphy's red disks
+
+  return;
+
+  // ==========================================================================
+  // Eat Red Disk down
+  // ==========================================================================
+
+loc_g_7396:
+  if (LowByte(PlayField16[*si + FieldWidth]) != fiExplosion)
+    PlayField16[*si + FieldWidth] = 0;
+
+  subEatRedDisk(*si + FieldWidth); // inc+show Murphy's red disks
+
+  return;
+
+  // ==========================================================================
+  // Eat Red Disk right
+  // ==========================================================================
+
+loc_g_73AB:
+  if (LowByte(PlayField16[*si + 1]) != fiExplosion)
+    PlayField16[*si + 1] = 0;
+
+  subEatRedDisk(*si + 1); // inc+show Murphy's red disks
+
+  return;
+
+  // ==========================================================================
+  //                       yellow disk, pushing up
+  // ==========================================================================
+
+loc_g_73C0:
+  if (LowByte(PlayField16[*si]) != fiExplosion)
+    PlayField16[*si] = 0;
+
+  *si = *si - FieldWidth;
+  PlayField16[*si] = fiMurphy;
+  PlayField16[*si - FieldWidth] = fiYellowDisk;
+
+  return;
+
+  // ==========================================================================
+  //                       yellow disk, pushing left
+  // ==========================================================================
+
+loc_g_73DD:
+  if (LowByte(PlayField16[*si]) != fiExplosion)
+    PlayField16[*si] = 0;
+
+  *si = *si - 1;
+  PlayField16[*si] = fiMurphy;
+  PlayField16[*si - 1] = fiYellowDisk;
+
+  return;
+
+  // ==========================================================================
+  //                       yellow disk, pushing down
+  // ==========================================================================
+
+loc_g_73FA:
+  if (LowByte(PlayField16[*si]) != fiExplosion)
+    PlayField16[*si] = 0;
+
+  *si = *si + FieldWidth;
+  PlayField16[*si] = fiMurphy;
+  PlayField16[*si + FieldWidth] = fiYellowDisk;
+
+  return;
+
+  // ==========================================================================
+  //                       yellow disk pushing right
+  // ==========================================================================
+
+loc_g_7417:
+  if (LowByte(PlayField16[*si]) != fiExplosion)
+    PlayField16[*si] = 0;
+
+  *si = *si + 1;
+  PlayField16[*si] = fiMurphy;
+  PlayField16[*si + 1] = fiYellowDisk;
+
+  return;
+
+  // ==========================================================================
+  //                       orange disk, pushing left
+  // ==========================================================================
+
+loc_g_7434:
+  if (LowByte(PlayField16[*si]) != fiExplosion)
+    PlayField16[*si] = 0;
+
+  *si = *si - 1;
+  PlayField16[*si] = fiMurphy;
+  PlayField16[*si - 1] = fiOrangeDisk;
+
+  return;
+
+  // ==========================================================================
+  //                       orange disk, pushing right
+  // ==========================================================================
+
+loc_g_7451:
+  if (LowByte(PlayField16[*si]) != fiExplosion)
+    PlayField16[*si] = 0;
+
+  *si = *si + 1;
+  PlayField16[*si] = fiMurphy;
+  PlayField16[*si + 1] = fiOrangeDisk;
+  if (PlayField16[*si + FieldWidth + 1] == 0) // make it fall down if below is empty
+  {
+    MovHighByte(&PlayField16[*si + 1], 0x20);
+    MovHighByte(&PlayField16[*si + FieldWidth + 1], fiOrangeDisk);
+  }
+
+  return;
+
+  // ==========================================================================
+  //                     Release a red disk
+  // ==========================================================================
+
+loc_g_747F:
+  PlayField16[*si] = fiMurphy;
+  RedDiskReleasePhase = 2;
+  RedDiskCount = RedDiskCount - 1;
+
+  subSoundFX(*si, fiRedDisk, actDropping);
+} // subAnimateMurphy
+
+// ==========================================================================
+//                              SUBROUTINE
+// ==========================================================================
+void subExplodeSnikSnaksBelow(int si)
+{
+  int ax;
+
+  ax = LowByte(PlayField16[si + FieldWidth]);
+  if (ax == 0x11 || ax == 0xBB)
+    ExplodeFieldSP(si + FieldWidth);
+} // subExplodeSnikSnaksBelow
+
+// ==========================================================================
+//                              SUBROUTINE
+// Does pushing against an object kill Murphy?
+// ==========================================================================
+static boolean subMoveKillsMurphy(int si, int ax, int bl)
+{
+  static boolean subMoveKillsMurphy;
+
+  int al, ah;
+
+  al = LowByte(ax);
+  ah = HighByte(ax);
+  if (ax == 0xFFFF || ax == 0xAAAA || ah == 0)
+    goto loc_g_752E;
+
+  if (al == fiZonk)
+    goto loc_g_74E7;
+
+  if (al == fiExplosion)
+    goto loc_g_7530;
+
+  if (fiOrangeDisk <= al && al <= fiPortUp)
+    goto loc_g_752E;
+
+  ExplodeFieldSP(si);                 // Explode
+  subMoveKillsMurphy = True;
+  return subMoveKillsMurphy;
+
+loc_g_74E7: // zonk
+  if (bl == keyLeft)
+    goto loc_g_74F6;
+
+  if (bl == keyRight)
+    goto loc_g_7512;
+
+  ExplodeFieldSP(si);                 // Explode
+  subMoveKillsMurphy = True;
+  return subMoveKillsMurphy;
+
+loc_g_74F6: // zonk left
+  ah = ah & 0xF0;
+  if (! (ah == 0x20 || ah == 0x40 || ah == 0x50 || ah == 0x70))
+    ExplodeFieldSP(si);
+
+  subMoveKillsMurphy = True;                           // Set carry flag
+  return subMoveKillsMurphy;
+
+loc_g_7512: // zonk right
+  ah = ah & 0xF0;
+  if (! (ah == 0x30 || ah == 0x40 || ah == 0x60 || ah == 0x70))
+    ExplodeFieldSP(si);
+
+loc_g_752E: // Marked fields and Ports
+  subMoveKillsMurphy = True;                           // Set carry flag
+  return subMoveKillsMurphy;
+
+loc_g_7530: // explosion
+  if ((ah & 0x80) != 0)
+    goto loc_g_753A;
+
+  if (ah >= 4)
+    goto loc_g_753F;
+
+loc_g_753A:
+  ExplodeFieldSP(si);                 // Explode
+  subMoveKillsMurphy = True;                           // Set carry flag
+  return subMoveKillsMurphy;
+
+loc_g_753F:
+  PlayField16[si] = 0;
+  subMoveKillsMurphy = False;
+
+  return subMoveKillsMurphy;
+} // subMoveKillsMurphy
+
+// ==========================================================================
+//                              SUBROUTINE
+// Test If si 's a special (grav) port and If so Then fetch new values (see below)
+// change conditions to port specs
+// The 10-port data base is at data_h_0D28, 10 entries of 6 bytes each:
+// (hi),(lo),(gravity),(freeze zonks),(freeze enemies),(unused)
+// ==========================================================================
+
+void subSpPortTest(int si)
+{
+  int i;
+
+  for (i = 0; i < LInfo.SpecialPortCount; i++)
+  {
+    if (LInfo.SpecialPort[i].PortLocation / 2 == si)
+    {
+      GravityFlag              = LInfo.SpecialPort[i].Gravity;
+      FreezeZonks              = LInfo.SpecialPort[i].FreezeZonks;
+      SnikSnaksElectronsFrozen = LInfo.SpecialPort[i].FreezeEnemies;
+
+      break;
+    }
+  }
+}
+
+void subCopyAnimToScreen(int si, int graphic, int sync_frame)
+{
+  int X, Y;
+
+  // +++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si);
+  Y = GetStretchY(si);
+  DDSpriteBuffer_BltImg(X, Y, graphic, sync_frame);
+  // +++++++++++++++++++++++++++++++++++++++++
+}
+
+void subCopyImageToScreen(int si, int graphic)
+{
+  subCopyAnimToScreen(si, graphic, 0);
+}
+
+static void subEatRedDisk(int si)
+{
+  if (AllowRedDiskCheat == 0)
+  {
+    if (RedDiskReleasePhase != 0)
+    {
+      if (RedDiskReleaseMurphyPos == si)
+        return;
+    }
+  }
+
+  RedDiskCount = (RedDiskCount + 1) % 256;
+}
+
+void subAdjustZonksInfotronsAboveMurphy(int si)
+{
+  int ax;
+
+  if (LowByte(PlayField16[si]) != fiExplosion)
+    PlayField16[si] = 0;
+
+  ax = PlayField16[si - FieldWidth];
+  if (ax == 0 || ax == 0x9999)
+    goto loc_g_15A8;
+
+  if (ax == fiZonk || ax == fiInfotron)
+  {
+    MovHighByte(&PlayField16[si - FieldWidth], 0x40); // make falling straigt down
+  }
+
+  return;
+
+loc_g_15A8: // empty above
+  ax = PlayField16[si - FieldWidth - 1];
+  if (ax == fiZonk || ax == fiInfotron)
+    goto loc_g_15C5;
+
+loc_g_15B6:
+  ax = PlayField16[si - FieldWidth + 1];
+  if (ax == fiZonk || ax == fiInfotron)
+    goto loc_g_15E8;
+
+  return;
+
+loc_g_15C5: // zonk/infotron above left
+  ax = PlayField16[si - 1];
+  if (! (ax == fiZonk || ax == fiInfotron || ax == fiRAM)) // continue testing right above
+    goto loc_g_15B6;
+
+  MovHighByte(&PlayField16[si - FieldWidth - 1], 0x60); // make roll right
+  PlayField16[si - FieldWidth] = 0x8888;
+
+  return;
+
+loc_g_15E8: // zonk/infotron above right
+  ax = PlayField16[si + 1];
+  if (ax == fiZonk || ax == fiInfotron || ax == fiRAM)
+  {
+    MovHighByte(&PlayField16[si - FieldWidth + 1], 0x50); // make roll left
+    PlayField16[si - FieldWidth] = 0x8888;
+  }
+}
diff --git a/src/game_sp/Murphy.h b/src/game_sp/Murphy.h
new file mode 100644 (file)
index 0000000..e0d51a3
--- /dev/null
@@ -0,0 +1,18 @@
+// ----------------------------------------------------------------------------
+// Murphy.h
+// ----------------------------------------------------------------------------
+
+#ifndef MURPHY_H
+#define MURPHY_H
+
+#include "global.h"
+
+extern void subAdjustZonksInfotronsAboveMurphy(int);
+extern void subAnimateMurphy(int *);
+extern void subCopyFieldToScreen(int, int);
+extern void subCopyImageToScreen(int, int);
+extern void subCopyAnimToScreen(int, int, int);
+extern void subExplodeSnikSnaksBelow(int);
+extern void subSpPortTest(int);
+
+#endif /* MURPHY_H */
diff --git a/src/game_sp/OrangeDisk.c b/src/game_sp/OrangeDisk.c
new file mode 100644 (file)
index 0000000..dc83e9e
--- /dev/null
@@ -0,0 +1,86 @@
+// ----------------------------------------------------------------------------
+// OrangeDisk.c
+// ----------------------------------------------------------------------------
+
+#include "OrangeDisk.h"
+
+
+// ==========================================================================
+//                              SUBROUTINE
+// Animate/move orange disks (falling)
+// ==========================================================================
+
+void subAnimateOrangeDisks(int si)
+{
+  int ax, bl, dx, X, Y;
+
+  ax = PlayField16[si];
+  if (LowByte(ax) != fiOrangeDisk)
+    return;
+
+  if (ax >= 0x3008) // disk is falling
+    goto loc_g_2804;
+
+  if (ax >= 0x2008) // disk is in wait state before falling
+    goto loc_g_27DA;
+
+  if (PlayField16[si + FieldWidth] == 0)
+    goto loc_g_27CF;
+
+  return;
+
+loc_g_27CF: // below is empty -> disk may start to fall
+  MovHighByte(&PlayField16[si], 0x20);
+  MovHighByte(&PlayField16[si + FieldWidth], fiOrangeDisk);
+
+  return;
+
+loc_g_27DA:
+  if (PlayField16[si + FieldWidth] == 0)
+  {
+    PlayField16[si] = fiOrangeDisk;
+
+    return;
+  } // loc_g_27E8:
+
+  bl = HighByte(PlayField16[si]) + 1;
+  if (bl == 0x22) // wait phase is finished
+    bl = 0x30;
+
+  MovHighByte(&PlayField16[si], bl);
+
+  return;
+
+loc_g_2804: // disk is falling
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  dx = HighByte(PlayField16[si]) & 0x7;
+  X = GetStretchX(si);
+  Y = GetStretchY(si);
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X, Y + TwoPixels * (dx + 1), aniOrangeDisk, dx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+  bl = HighByte(PlayField16[si]) + 1;
+  if ((bl & 0x7) != 0)
+  {
+    MovHighByte(&PlayField16[si], bl);
+
+    return;
+  }
+
+  PlayField16[si] = 0;
+  PlayField16[si + FieldWidth] = fiOrangeDisk;
+  si = si + FieldWidth;
+  if (PlayField16[si + FieldWidth] == 0)
+  {
+    MovHighByte(&PlayField16[si], 0x30); // go on falling down
+    MovHighByte(&PlayField16[si + FieldWidth], fiOrangeDisk);
+
+    return;
+  } // loc_g_2867:
+
+  if (LowByte(PlayField16[si + FieldWidth]) == fiExplosion)
+    return;
+
+  ExplodeFieldSP(si);                 // Explode
+}
diff --git a/src/game_sp/OrangeDisk.h b/src/game_sp/OrangeDisk.h
new file mode 100644 (file)
index 0000000..410aab4
--- /dev/null
@@ -0,0 +1,13 @@
+// ----------------------------------------------------------------------------
+// OrangeDisk.h
+// ----------------------------------------------------------------------------
+
+#ifndef ORANGEDISK_H
+#define ORANGEDISK_H
+
+#include "global.h"
+
+
+extern void subAnimateOrangeDisks(int);
+
+#endif /* ORANGEDISK_H */
diff --git a/src/game_sp/SnikSnaks.c b/src/game_sp/SnikSnaks.c
new file mode 100644 (file)
index 0000000..e23dc90
--- /dev/null
@@ -0,0 +1,677 @@
+// ----------------------------------------------------------------------------
+// SnikSnaks.c
+// ----------------------------------------------------------------------------
+
+#include "SnikSnaks.h"
+
+
+static void subDrawSnikSnakFromAbove(int, int);
+static void subDrawSnikSnakFromBelow(int, int);
+static void subDrawSnikSnakFromLeft(int, int);
+static void subDrawSnikSnakFromRight(int, int);
+static void subDrawSnikSnakTurnLeft(int, int);
+static void subDrawSnikSnakTurnRight(int, int);
+static void subSnikSnakFromAbove(int, int);
+static void subSnikSnakFromBelow(int, int);
+static void subSnikSnakFromLeft(int, int);
+static void subSnikSnakFromRight(int, int);
+static void subSnikSnakTurnLeft(int, int);
+static void subSnikSnakTurnRight(int, int);
+
+// static char *VB_Name = "modSnikSnak";
+
+// --- Option Explicit
+// ==========================================================================
+//                              SUBROUTINE
+// Animate/move Snik-Snaks
+// ==========================================================================
+
+void subAnimateSnikSnaks(int si)
+{
+  int bx, Tmp;
+
+  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);
+
+  bx = HighByte(PlayField16[si]);
+  Tmp = bx / 8;
+  switch (Tmp)
+  {
+    case 0:
+      subSnikSnakTurnLeft(si, bx); // turning, bx=0 -> point N, bx = 1 -> point NW etc.
+      break;
+
+    case 1:
+      subSnikSnakTurnRight(si, bx); // turn right
+      break;
+
+    case 2:
+      subSnikSnakFromBelow(si, bx); // access si from below
+      break;
+
+    case 3:
+      subSnikSnakFromRight(si, bx); // access si from right
+      break;
+
+    case 4:
+      subSnikSnakFromAbove(si, bx); // access si from above
+      break;
+
+    case 5:
+      subSnikSnakFromLeft(si, bx); // access si from left
+      break;
+
+    default:
+      // Debug.Assert(False);
+      break;
+  }
+}
+
+void subDrawAnimatedSnikSnaks(int si)
+{
+  int bx, Tmp;
+
+  // If SnikSnaksElectronsFrozen = 1 Then Exit Function
+
+  if (LowByte(PlayField16[si]) != fiSnikSnak)
+    return;
+
+  bx = HighByte(PlayField16[si]);
+  Tmp = bx / 8;
+  switch (Tmp)
+  {
+    case 0:
+      subDrawSnikSnakTurnLeft(si, bx); // turning, bx=0 -> point N, bx = 1 -> point NW etc.
+      break;
+
+    case 1:
+      subDrawSnikSnakTurnRight(si, bx); // turn right
+      break;
+
+    case 2:
+      subDrawSnikSnakFromBelow(si, bx); // access si from below
+      break;
+
+    case 3:
+      subDrawSnikSnakFromRight(si, bx); // access si from right
+      break;
+
+    case 4:
+      subDrawSnikSnakFromAbove(si, bx); // access si from above
+      break;
+
+    case 5:
+      subDrawSnikSnakFromLeft(si, bx); // access si from left
+      break;
+  }
+}
+
+static void subSnikSnakTurnLeft(int si, int bx)
+{
+  int ax, ah, bl;
+
+  ax = (TimerVar & 3);
+  if (ax != 0)
+  {
+    if (ax == 3)
+      goto loc_g_7622;
+
+    return;
+  } // loc_g_75E0:
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  subDrawSnikSnakTurnLeft(si, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+  bx = (bx + 1) & 0x7;
+  MovHighByte(&PlayField16[si], bx);
+
+  return;
+
+locMayExplode760A:
+  ah = HighByte(ax);
+  if (ah == 0x1B)
+    return;
+
+  if (ah == 0x19)
+    return;
+
+  if (ah == 0x18)
+    return;
+
+  if (ah == 0x1A)
+    return;
+
+  ExplodeFieldSP(si); // Explode
+
+  return;
+
+loc_g_7622:
+  bl = HighByte(PlayField16[si]);
+  if (bl == 0)
+    goto loc_g_763B;
+
+  if (bl == 2)
+    goto loc_g_765E;
+
+  if (bl == 4)
+    goto loc_g_7681;
+
+  if (bl == 6)
+    goto loc_g_76A7;
+
+  return;
+
+loc_g_763B: // pointing up
+  ax = PlayField16[si - FieldWidth];
+  if (ax == 0) // above is empty -> go up
+    goto loc_g_764E;
+
+  if (LowByte(ax) == fiMurphy) // above is murphy -> explode
+    goto locMayExplode760A;
+
+  return;
+
+loc_g_764E: // above is empty -> go up
+  PlayField16[si] = 0x1BB;
+  si = si - FieldWidth;
+  PlayField16[si] = 0x1011;
+
+  return;
+
+loc_g_765E: // pointing left
+  ax = PlayField16[si - 1];
+  if (ax == 0) // left is empty -> go there
+    goto loc_g_7671;
+
+  if (LowByte(ax) == fiMurphy) // left is murphy -> explode
+    goto locMayExplode760A;
+
+  return;
+
+loc_g_7671: // left is empty -> go there
+  PlayField16[si] = 0x2BB;
+  si = si - 1;
+  PlayField16[si] = 0x1811;
+
+  return;
+
+loc_g_7681: // pointing down
+  ax = PlayField16[si + FieldWidth];
+  if (ax == 0) // below is empty -> go down
+    goto loc_g_7697;
+
+  if (LowByte(ax) == fiMurphy) // below is murphy -> explode
+    goto locMayExplode760A;
+
+  return;
+
+loc_g_7697: // below is empty -> go down
+  PlayField16[si] = 0x3BB;
+  si = si + FieldWidth;
+  PlayField16[si] = 0x2011;
+
+  return;
+
+loc_g_76A7: // pointing Right
+  ax = PlayField16[si + 1];
+  if (ax == 0) // right is empty -> go there
+    goto loc_g_76BD;
+
+  if (LowByte(ax) == fiMurphy) // right is murphy -> explode
+    goto locMayExplode760A;
+
+  return;
+
+loc_g_76BD: // right is empty -> go there
+  PlayField16[si] = 0x4BB;
+  si = si + 1;
+  PlayField16[si] = 0x2811;
+}
+
+static void subSnikSnakTurnRight(int si, int bx)
+{
+  int ax, ah, bl;
+
+  ax = (TimerVar & 3);
+  if (ax != 0)
+  {
+    if (ax == 3)
+      goto loc_g_771F;
+
+    return;
+  } // loc_g_76DB:
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  subDrawSnikSnakTurnRight(si, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+  bx = ((bx + 1) & 0x7) | 8;
+  MovHighByte(&PlayField16[si], bx);
+
+  return;
+
+locMayExplode7707:
+  ah = HighByte(ax);
+  if (ah == 0x1B)
+    return;
+
+  if (ah == 0x19)
+    return;
+
+  if (ah == 0x18)
+    return;
+
+  if (ah == 0x1A)
+    return;
+
+  ExplodeFieldSP(si); // Explode
+
+  return;
+
+loc_g_771F:
+  bl = HighByte(PlayField16[si]);
+  if (bl == 0x8)
+    goto loc_g_7738;
+
+  if (bl == 0xA)
+    goto loc_g_77A4;
+
+  if (bl == 0xC)
+    goto loc_g_777E;
+
+  if (bl == 0xE)
+    goto loc_g_775B;
+
+  return;
+
+loc_g_7738: // pointing up
+  ax = PlayField16[si - FieldWidth];
+  if (ax == 0) // above is empty -> go up
+    goto loc_g_774B;
+
+  if (LowByte(ax) == fiMurphy) // above is murphy -> explode
+    goto locMayExplode7707;
+
+  return;
+
+loc_g_774B: // above is empty -> go up
+  PlayField16[si] = 0x1BB;
+  si = si - FieldWidth;
+  PlayField16[si] = 0x1011;
+
+  return;
+
+loc_g_775B: // pointing left
+  ax = PlayField16[si - 1];
+  if (ax == 0) // left is empty -> go there
+    goto loc_g_776E;
+
+  if (LowByte(ax) == fiMurphy) // left is murphy -> explode
+    goto locMayExplode7707;
+
+  return;
+
+loc_g_776E: // left is empty -> go there
+  PlayField16[si] = 0x2BB;
+  si = si - 1;
+  PlayField16[si] = 0x1811;
+
+  return;
+
+loc_g_777E: // pointing down
+  ax = PlayField16[si + FieldWidth];
+  if (ax == 0) // below is empty -> go down
+    goto loc_g_7794;
+
+  if (LowByte(ax) == fiMurphy) // below is murphy -> explode
+    goto locMayExplode7707;
+
+  return;
+
+loc_g_7794: // below is empty -> go down
+  PlayField16[si] = 0x3BB;
+  si = si + FieldWidth;
+  PlayField16[si] = 0x2011;
+
+  return;
+
+loc_g_77A4: // pointing Right
+  ax = PlayField16[si + 1];
+  if (ax == 0) // right is empty -> go there
+    goto loc_g_77BA;
+
+  if (LowByte(ax) == fiMurphy) // right is murphy -> explode
+    goto locMayExplode7707;
+
+  return;
+
+loc_g_77BA: // right is empty -> go there
+  PlayField16[si] = 0x4BB;
+  si = si + 1;
+  PlayField16[si] = 0x2811;
+}
+
+static void subSnikSnakFromBelow(int si, int bx)
+{
+  int ax, bl;
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  subDrawSnikSnakFromBelow(si, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  bx = bx - 0xF;  // get and increment sequence#
+
+  bl = LowByte(bx);
+  if (bl == 7 && LowByte(PlayField16[si + FieldWidth]) != fiExplosion)
+  {
+    PlayField16[si + FieldWidth] = 0; // sniknak left that field
+  }
+
+  if (bl < 8) // sniksnak still goes up
+  {
+    bl = bl + 0x10;
+    MovHighByte(&PlayField16[si], bl);
+
+    return;
+  } // loc_g_7813
+
+  PlayField16[si] = 0x11; // sequence#=8 -> arrived at the new field
+  ax = PlayField16[si - 1]; // check left field
+  if (ax == 0 || LowByte(ax) == fiMurphy) // check for empty or murphy
+  {
+    MovHighByte(&PlayField16[si], 1); // start to turn left
+
+    return;
+  } // loc_g_7826: and 'loc_g_7833:
+
+  ax = PlayField16[si - FieldWidth]; // cannot turn left -> check above
+  if (ax == 0) // check if empty
+  {
+    PlayField16[si] = 0x1BB; // mark as "sniksnak leaving"
+    si = si - FieldWidth; // go up!
+    PlayField16[si] = 0x1011;
+
+    return;
+  } // loc_g_784A:
+
+  if (LowByte(ax) == fiMurphy) // check for murphy above
+  {
+    ExplodeFieldSP(si); // Explode
+
+    return;
+  } // loc_g_7855:
+
+  ax = PlayField16[si + 1]; // check right field
+  if (ax == 0 || LowByte(ax) == fiMurphy) // check for empty or murphy
+  {
+    MovHighByte(&PlayField16[si], 9); // start to turn right
+
+    return;
+  } // loc_g_7862: and 'loc_g_786F:
+
+  // else: no way to go, start turning around
+  MovHighByte(&PlayField16[si], 1);
+}
+
+static void subSnikSnakFromRight(int si, int bx)
+{
+  int ax, bl;
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  subDrawSnikSnakFromRight(si, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  bx = bx - 0x17;  // get and increment sequence#
+
+  bl = LowByte(bx);
+  if (bl == 7 && LowByte(PlayField16[si + 1]) != fiExplosion)
+  {
+    PlayField16[si + 1] = 0; // sniknak left that field
+  } // loc_g_78AC:
+
+  if (bl < 8) // sniksnak still goes left
+  {
+    bl = bl + 0x18;
+    MovHighByte(&PlayField16[si], bl);
+
+    return;
+  } // loc_g_78B9:
+
+  PlayField16[si] = 0x11; // sequence#=8 -> arrived at the new field
+  ax = PlayField16[si + FieldWidth]; // check below
+  if (ax == 0 || LowByte(ax) == fiMurphy) // empty or murphy?
+  {
+    MovHighByte(&PlayField16[si], 3); // yes -> turn left down
+
+    return;
+  } // loc_g_78CC: and 'loc_g_78D9:
+
+  ax = PlayField16[si - 1]; // check left, etc ... see the comments on subSnikSnakFromBelow()
+  if (ax == 0)
+  {
+    PlayField16[si] = 0x2BB;
+    si = si - 1;                // 1 field left
+    PlayField16[si] = 0x1811;
+
+    return;
+  } // loc_g_78F0:
+
+  if (LowByte(ax) == fiMurphy)
+  {
+    ExplodeFieldSP(si);      // Explode
+
+    return;
+  } // loc_g_78FB:
+
+  ax = PlayField16[si - FieldWidth]; // check above
+  if (ax == 0 || LowByte(ax) == fiMurphy)
+  {
+    MovHighByte(&PlayField16[si], 0xF);
+
+    return;
+  } // loc_g_7908:loc_g_7915:
+
+  MovHighByte(&PlayField16[si], 3);
+}
+
+static void subSnikSnakFromAbove(int si, int bx)
+{
+  int ax, bl;
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  subDrawSnikSnakFromAbove(si, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  bx = bx - 0x1F;  // get and increment sequence#
+
+  bl = LowByte(bx);
+  if (bl == 7 && LowByte(PlayField16[si - FieldWidth]) != fiExplosion)
+  {
+    PlayField16[si - FieldWidth] = 0; // sniknak left that field
+  }
+
+  if (bl < 8) // sniksnak still goes down
+  {
+    bl = bl + 0x20;
+    MovHighByte(&PlayField16[si], bl);
+
+    return;
+  } // loc_g_7813
+
+  PlayField16[si] = 0x11; // sequence#=8 -> arrived at the new field
+  ax = PlayField16[si + 1]; // check right
+  if (ax == 0 || LowByte(ax) == fiMurphy)
+  {
+    MovHighByte(&PlayField16[si], 5);
+
+    return;
+  } // loc_g_7986:
+
+  ax = PlayField16[si + FieldWidth]; // check below
+  if (ax == 0)
+  {
+    PlayField16[si] = 0x3BB;
+    si = si + FieldWidth;                 // 1 field down
+    PlayField16[si] = 0x2011;
+
+    return;
+  } // loc_g_799D:
+
+  if (LowByte(ax) == fiMurphy)
+  {
+    ExplodeFieldSP(si);        // Explode
+
+    return;
+  } // loc_g_79A8:
+
+  ax = PlayField16[si - 1]; // check left
+  if (ax == 0 || LowByte(ax) == fiMurphy)
+  {
+    MovHighByte(&PlayField16[si], 0xD);
+
+    return;
+  } // loc_g_79C2:
+
+  MovHighByte(&PlayField16[si], 5);
+}
+
+static void subSnikSnakFromLeft(int si, int bx)
+{
+  int ax, bl;
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  subDrawSnikSnakFromLeft(si, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  bx = bx - 0x27;  // get and increment sequence#
+
+  bl = LowByte(bx);
+  if (bl == 7 && LowByte(PlayField16[si - 1]) != fiExplosion)
+  {
+    PlayField16[si - 1] = 0; // sniknak left that field
+  }
+
+  if (bl < 8) // sniksnak still goes right
+  {
+    bl = bl + 0x28;
+    MovHighByte(&PlayField16[si], bl);
+
+    return;
+  } // loc_g_78B9:
+
+  PlayField16[si] = 0x11; // sequence#=8 -> arrived at the new field
+  ax = PlayField16[si - FieldWidth]; // check above
+  if (ax == 0 || LowByte(ax) == fiMurphy)
+  {
+    MovHighByte(&PlayField16[si], 7);
+
+    return;
+  } // loc_g_7A2D:
+
+  ax = PlayField16[si + 1]; // check right(straight on)
+  if (ax == 0)
+  {
+    PlayField16[si] = 0x4BB;
+    si = si + 1;                   // 1 field right
+    PlayField16[si] = 0x2811;
+
+    return;
+  } // loc_g_7A44:
+
+  if (LowByte(ax) == fiMurphy)
+  {
+    ExplodeFieldSP(si);    // Explode
+
+    return;
+  } // loc_g_7A4F:
+
+  ax = PlayField16[si + FieldWidth]; // check below
+  if (ax == 0 || LowByte(ax) == fiMurphy)
+  {
+    MovHighByte(&PlayField16[si], 0xB);
+
+    return;
+  } // loc_g_7A69:
+
+  MovHighByte(&PlayField16[si], 7);
+}
+
+static void subDrawSnikSnakTurnLeft(int si, int bx)
+{
+  int pos = ((bx + 7) % 8) / 2;
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  GfxGraphic[GetX(si)][GetY(si)] = aniSnikSnakTurningLeft[pos];
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+}
+
+static void subDrawSnikSnakTurnRight(int si, int bx)
+{
+  int pos = ((bx - 1) % 8) / 2;
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  GfxGraphic[GetX(si)][GetY(si)] = aniSnikSnakTurningRight[pos];
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+}
+
+static void subDrawSnikSnakFromBelow(int si, int bx)
+{
+  int X, Y;
+
+  bx = bx - 0xF; // get and anti-increment sequence#
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si);
+  Y = GetStretchY(si + FieldWidth);
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X, Y - bx * TwoPixels, aniSnikSnakUp, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+}
+
+static void subDrawSnikSnakFromRight(int si, int bx)
+{
+  int X, Y;
+
+  bx = bx - 0x17; // get and increment sequence#
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si + 1);
+  Y = GetStretchY(si);
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X - bx * TwoPixels, Y, aniSnikSnakLeft, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+}
+
+static void subDrawSnikSnakFromAbove(int si, int bx)
+{
+  int X, Y;
+
+  bx = bx - 0x1F; // get and increment sequence#
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si);
+  Y = GetStretchY(si - FieldWidth);
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X, Y + bx * TwoPixels, aniSnikSnakDown, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+}
+
+static void subDrawSnikSnakFromLeft(int si, int bx)
+{
+  int X, Y;
+
+  bx = bx - 0x27; // get and increment sequence#
+
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si - 1);
+  Y = GetStretchY(si);
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X + bx * TwoPixels, Y, aniSnikSnakRight, bx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+}
diff --git a/src/game_sp/SnikSnaks.h b/src/game_sp/SnikSnaks.h
new file mode 100644 (file)
index 0000000..fd5f9ff
--- /dev/null
@@ -0,0 +1,14 @@
+// ----------------------------------------------------------------------------
+// SnikSnaks.h
+// ----------------------------------------------------------------------------
+
+#ifndef SNIKSNAKS_H
+#define SNIKSNAKS_H
+
+#include "global.h"
+
+
+extern void subAnimateSnikSnaks(int);
+extern void subDrawAnimatedSnikSnaks(int);
+
+#endif /* SNIKSNAKS_H */
diff --git a/src/game_sp/Sound.c b/src/game_sp/Sound.c
new file mode 100644 (file)
index 0000000..4a79925
--- /dev/null
@@ -0,0 +1,14 @@
+// ----------------------------------------------------------------------------
+// Sound.c
+// ----------------------------------------------------------------------------
+
+#include "Sound.h"
+
+
+void subSoundFX(int si, int element, int action)
+{
+  int x = GetX(si);
+  int y = GetY(si);
+
+  PlayLevelSound_SP(x, y, element, action);
+}
diff --git a/src/game_sp/Sound.h b/src/game_sp/Sound.h
new file mode 100644 (file)
index 0000000..f4ca0f4
--- /dev/null
@@ -0,0 +1,13 @@
+// ----------------------------------------------------------------------------
+// Sound.h
+// ----------------------------------------------------------------------------
+
+#ifndef GAME_SP_SOUND_H
+#define GAME_SP_SOUND_H
+
+#include "global.h"
+
+
+extern void subSoundFX(int, int, int);
+
+#endif /* GAME_SP_SOUND_H */
diff --git a/src/game_sp/Zonk.c b/src/game_sp/Zonk.c
new file mode 100644 (file)
index 0000000..d828534
--- /dev/null
@@ -0,0 +1,485 @@
+// ----------------------------------------------------------------------------
+// Zonk.c
+// ----------------------------------------------------------------------------
+
+#include "Zonk.h"
+
+
+void subCleanUpForZonksAbove(int si);
+
+
+// static char *VB_Name = "modZonk";
+// --- Option Explicit
+
+// ==========================================================================
+//                              SUBROUTINE
+// Animate Zonks (falling)
+// ==========================================================================
+
+void subAnimateZonks(int si)
+{
+  int tFld;
+
+  // PseudoRegisters:
+  // int ax, bx, cx, dx, di, X, Y;
+  int ax, bx, dx, X, Y;
+  // int ah, bh, ch, dh, al, bl, cl, dl;
+  int al, bl;
+
+  tFld = PlayField16[si];
+  if ((tFld & 0xFF) != fiZonk)
+    return;
+
+  if (tFld == fiZonk)
+  {
+    if (FreezeZonks == 2) // Do Zonks fall? (debug)
+      return;
+
+    ax = PlayField16[si + FieldWidth]; // select case playfield16(si+60)
+    if (ax == 0)
+      goto loc_g_0D64;
+
+    if (ax == fiZonk)
+      goto loc_g_0D35;
+
+    if (ax == fiInfotron)
+      goto loc_g_0D35;
+
+    if (ax == fiRAM)
+      goto loc_g_0D35;
+
+    return;
+
+loc_g_0D35: //        Case fiZonk, fiInfotron, fiRAM
+    ax = PlayField16[si + FieldWidth - 1];
+    if (ax == 0 || ax == 0x8888 || ax == 0xAAAA)
+      goto loc_g_0D6B;
+
+loc_g_0D4C:
+    ax = PlayField16[si + FieldWidth + 1];
+    if (ax == 0 || ax == 0x8888 || ax == 0xAAAA)
+      goto loc_g_0D81;
+
+    return;
+
+loc_g_0D64: //       Case fiSpace
+    MovHighByte(&PlayField16[si], 0x40);
+    goto loc_g_0DA5;
+
+loc_g_0D6B: // roll left?
+    if (PlayField16[si - 1] == 0)
+      goto loc_g_0D74;
+
+    goto loc_g_0D4C;
+
+loc_g_0D74:
+    MovHighByte(&PlayField16[si], 0x50);
+    PlayField16[si - 1] = 0x8888;
+    goto loc_g_0DA5;
+
+loc_g_0D81: // roll right?
+    if (PlayField16[si + 1] == 0)
+      goto loc_g_0D98;
+
+    if (PlayField16[si + 1] != 0x9999) // wow right is different from left!
+      return;
+
+    if (LowByte(PlayField16[si - FieldWidth + 1]) != 1)
+      return;
+
+loc_g_0D98:
+    MovHighByte(&PlayField16[si], 0x60);
+    PlayField16[si + 1] = 0x8888;
+  } // tFld = fiZonk
+
+loc_g_0DA5:
+  // from now on the zonk is definitely moving,
+  // maybe the sequence is in an advanced frame
+  // or just beeing initialized due to the code above
+  bl = HighByte(PlayField16[si]);
+  bx = 0;
+  MovLowByte(&bx, bl);
+  al = bl & 0xF0;
+  if (al == 0x10) // zonk comes falling from above
+    goto loc_g_0DE8;
+
+  if (al == 0x20) // zonk comes rolling from right to left
+    goto loc_g_0F83;
+
+  if (al == 0x30) // zonk comes rolling from left to right
+    goto loc_g_0FE8;
+
+  if (FreezeZonks == 2)
+    return;
+
+  if (al == 0x40) // zonk falls straight down
+    goto loc_g_104D;
+
+  if (al == 0x50) // zonk rolls left
+    goto loc_g_107B;
+
+  if (al == 0x60) // zonk rolls right
+    goto loc_g_10E9;
+
+  if (al == 0x70) // intermediate state
+    goto loc_g_1157;
+
+  return;
+
+loc_g_0DE8: // zonk comes falling from above
+  //      To Do: draw zonk falling from above
+  //      according to position in (bl And &H07)
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si);
+  Y = GetStretchY(si - FieldWidth);
+  dx = bl & 0x7;
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X, Y + TwoPixels * (dx + 1), aniZonk, dx);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+  bl = HighByte(PlayField16[si]) + 1;
+  if (bl == 0x16)
+  {
+    MovHighByte(&PlayField16[si], bl);
+    subCleanUpForZonksAbove(si - FieldWidth);
+    return;
+  } // loc_g_0E2B:
+
+  if (bl < 0x18)
+  {
+    MovHighByte(&PlayField16[si], bl);
+    return;
+  } // loc_g_0E35:
+
+  MovHighByte(&PlayField16[si], 0); // zonk arrived at the field
+  if ((FreezeZonks & 0xFF) == 2)
+    return;
+
+  // loc_g_0E42:     // now check if the zonk may go on falling somehow
+  ax = PlayField16[si + FieldWidth];
+  if (ax == 0) // below is empty!-> go on falling 'loc_g_0E4C:
+    goto loc_g_0EDD;
+
+  if (ax == 0x9999) // below is only temporarily used ' loc_g_0E57:
+    goto loc_g_0EDD;
+
+  if ((ax & 0xFF) == fiMurphy) // Murphy dies 'loc_g_0E61:
+    goto loc_g_0F14;
+
+  if ((ax & 0xFF) == fiSnikSnak) // SnikSnak dies 'loc_g_0E6B:
+    goto loc_g_0F6E;
+
+  if (ax == 0x2BB) // loc_g_0E76:
+    goto loc_g_0F36;
+
+  if (ax == 0x4BB) // loc_g_0E81:
+    goto loc_g_0F52;
+
+  if ((ax & 0xFF) == fiElectron) // Electron cracked! 'loc_g_0E8B:
+    goto loc_g_0F6E;
+
+  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;
+
+  // loc_g_0EAE: ' Zonk rolls somewhere
+  ax = PlayField16[si + FieldWidth - 1];
+  if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) // may roll left
+    goto loc_g_0EEA;
+
+  ax = PlayField16[si + FieldWidth + 1];
+  if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) // may roll right
+    goto loc_g_0F00;
+
+  return;
+
+loc_g_0EDD:     // go on falling down?
+  PlayField16[si] = 0x7001; // go into intermediate waitstate
+  PlayField16[si + FieldWidth] = 0x9999; // mark as "zonk waiting to access"
+  return;
+
+loc_g_0EEA:     // test if zonk may roll left
+  // This if(if true) jumps up far above
+  // to the according rountine for fixed zonks!
+  if (PlayField16[si - 1] != 0) // Remarkable!!! ' loc_g_0EF4:
+    goto loc_g_0D4C;
+
+  MovHighByte(&PlayField16[si], 0x50); // zonk rolls left
+  PlayField16[si - 1] = 0x8888; // mark as zonk accessing?
+  return;
+
+loc_g_0F00:     // test if zonk may roll right
+  if (PlayField16[si + 1] != 0) // loc_g_0F08:
+    return;
+
+  MovHighByte(&PlayField16[si], 0x60); // zonk rolls right
+  PlayField16[si + 1] = 0x8888; // mark as zonk accessing?
+  return;
+
+loc_g_0F14:     // Murphy dies, but not in any case
+  bl = HighByte(PlayField16[si + FieldWidth]);
+  if (bl == 0xE || bl == 0xF || bl == 0x28)
+    return;
+
+  if (bl == 0x29 || bl == 0x25 || bl == 0x26)
+    return;
+
+loc_g_0F36:     // ??
+  ax = LowByte(PlayField16[si + FieldWidth - 1]);
+  if (ax == fiElectron) // loc_g_0F43:
+    PlayField16[si + FieldWidth] = fiElectron;
+
+  if (ax != 0x1F)
+    PlayField16[si + FieldWidth - 1] = 0;
+
+  goto loc_g_0F6E;
+
+loc_g_0F52:     // ??
+  ax = LowByte(PlayField16[si + FieldWidth + 1]);
+  if (ax == fiElectron) // loc_g_0F5F:
+    PlayField16[si + FieldWidth] = fiElectron;
+
+  if (ax != 0x1F)
+    PlayField16[si + FieldWidth + 1] = 0;
+
+  goto loc_g_0F6E;
+
+loc_g_0F6E:     // someone dies/explodes
+  si = si + FieldWidth;                 // 1 field down
+  ExplodeFieldSP(si);               // Explode
+  return;
+
+loc_g_0F75:     // OrangeDisk explodes next cycle
+  si = si + FieldWidth;                 // 1 field down
+  PlayField8[si] = fiHardWare;
+  return;
+
+loc_g_0F83: // zonk comes rolling from right to left
+  //  To Do: draw zonk rolling from right
+  //  according to position in (bl And &H07)
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si + 1);
+  Y = GetStretchY(si);
+  dx = (bl & 0x7) + 1;
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X - (TwoPixels * dx), Y, aniZonkRollLeft, dx - 1);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+  bl = HighByte(PlayField16[si]) + 1; // get and increment sequence#
+  if (bl == 0x24)
+    PlayField16[si + 1] = 0xAAAA;
+
+  if (bl == 0x26)
+  {
+    MovHighByte(&PlayField16[si], bl);
+    subCleanUpForZonksAbove(si + 1);
+  }
+  else if (bl < 0x28)
+  {
+    MovHighByte(&PlayField16[si], bl);
+  }
+  else
+  {
+    PlayField16[si] = 0xFFFF;
+    si = si + FieldWidth;                 // 1 field down
+    PlayField16[si] = 0x1001; // convert rolling zonk to a falling zonk
+  }
+
+  return;
+
+loc_g_0FE8: // zonk comes rolling from left to right
+  //  To Do: draw zonk rolling from left
+  //  according to position in (bl And &H07)
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si - 1);
+  Y = GetStretchY(si);
+  dx = (bl & 0x7) + 1;
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X + (TwoPixels * dx), Y, aniZonkRollRight, dx - 1);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+  bl = HighByte(PlayField16[si]) + 1;
+  if (bl == 0x34)
+    PlayField16[si - 1] = 0xAAAA;
+
+  if (bl == 0x36)
+  {
+    MovHighByte(&PlayField16[si], bl);
+    subCleanUpForZonksAbove(si - 1);
+  }
+  else if (bl < 0x38)
+  {
+    MovHighByte(&PlayField16[si], bl);
+  }
+  else
+  {
+    PlayField16[si] = 0xFFFF;
+    si = si + FieldWidth;                   // 1 field down
+    PlayField16[si] = 0x1001; // convert rolling zonk to a falling zonk
+  }
+
+  return;
+
+loc_g_104D: // zonk falls straight down
+  bl = bl + 1;
+  if (bl < 0x42)
+  {
+    MovHighByte(&PlayField16[si], bl);
+  }
+  else if (PlayField16[si + FieldWidth] != 0)
+  {
+    bl = bl - 1; // stay waiting
+    MovHighByte(&PlayField16[si], bl);
+  }
+  else
+  {
+    PlayField16[si] = 0xFFFF; // mark as "zonk leaving"
+    si = si + FieldWidth;                 // 1 field down
+    PlayField16[si] = 0x1001; // go falling
+  }
+
+  return;
+
+loc_g_107B: // zonk rolls left
+  //  To Do: draw zonk rolling to left
+  //  according to position in (bl And &H0F)
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si);
+  Y = GetStretchY(si);
+  dx = (bl & 0xF) + 1;
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X - (TwoPixels * dx), Y, aniZonkRollLeft, dx - 1);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+  bl = HighByte(PlayField16[si]) + 1; // retrieve and increment sequence#
+  if (bl < 0x52)
+  {
+    MovHighByte(&PlayField16[si], bl);
+    return;
+  }
+
+  if (PlayField16[si + FieldWidth - 1] != 0)
+    goto loc_g_10E2;
+
+  if (PlayField16[si - 1] != 0)
+  {
+    if (PlayField16[si - 1] != 0x8888)
+      goto loc_g_10E2;
+  } // loc_g_10C8:
+
+  PlayField16[si] = 0xFFFF;
+  si = si - 1;                   // 1 field left
+  PlayField16[si] = 0x2201;
+  PlayField16[si + FieldWidth] = 0xFFFF;
+  return;
+
+loc_g_10E2: // stay waiting
+  bl = bl - 1;
+  MovHighByte(&PlayField16[si], bl);
+  return;
+
+loc_g_10E9: // zonk rolls right
+  //  To Do: draw zonk rolling to right
+  //  according to position in (bl And &H07)
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+  X = GetStretchX(si);
+  Y = GetStretchY(si);
+  dx = (bl & 0x7) + 1;
+  DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
+  DDSpriteBuffer_BltImg(X + (TwoPixels * dx), Y, aniZonkRollRight, dx - 1);
+  // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+  bl = HighByte(PlayField16[si]) + 1;
+  if (bl < 0x62)
+  {
+    MovHighByte(&PlayField16[si], bl);
+    return;
+  }
+
+  if (PlayField16[si + FieldWidth + 1] != 0)
+    goto loc_g_1150;
+
+  if (PlayField16[si + 1] != 0)
+  {
+    if (PlayField16[si + 1] != 0x8888)
+      goto loc_g_1150;
+  }
+
+  PlayField16[si] = 0xFFFF;
+  si = si + 1;
+  PlayField16[si] = 0x3201;
+  PlayField16[si + FieldWidth] = 0xFFFF;
+  return;
+
+loc_g_1150: // stay waiting
+  bl = bl - 1;
+  MovHighByte(&PlayField16[si], bl);
+  return;
+
+loc_g_1157: // intermediate state
+  ax = PlayField16[si + FieldWidth];
+  if (ax == 0 || ax == 0x9999)
+  {
+    PlayField16[si] = 0xFFFF;
+    si = si + FieldWidth;                 // 1 field down
+    PlayField16[si] = 0x1001; // start falling down
+    goto loc_g_0DE8;
+  }
+
+  return;
+} // subAnimateZonks endp
+
+void subCleanUpForZonksAbove(int si)
+{
+  int ax;
+
+  if (LowByte(PlayField16[si]) != fiExplosion)
+    PlayField16[si] = 0;
+
+  if (PlayField16[si - FieldWidth] != 0)
+  {
+    if (PlayField16[si - FieldWidth] != 0x9999)
+      return;
+
+    if (LowByte(PlayField16[si - 2 * FieldWidth]) != fiInfotron)
+      return;
+  } // loc_g_1674:
+
+  if (PlayField16[si - FieldWidth - 1] != fiZonk)
+  {
+    if (PlayField16[si - FieldWidth + 1] != fiZonk)
+      return;
+
+    goto loc_g_16A7;
+  }
+
+  ax = PlayField16[si - 1];
+  if (ax == fiZonk || ax == fiInfotron || ax == fiRAM)
+  {
+    PlayField16[si - FieldWidth - 1] = 0x6001;
+    PlayField16[si - FieldWidth] = 0x8888;
+    return;
+  }
+
+  if (PlayField16[si - FieldWidth + 1] != fiZonk)
+    return;
+
+loc_g_16A7:
+  ax = PlayField16[si + 1];
+  if (ax == fiZonk || ax == fiInfotron || ax == fiRAM)
+  {
+    PlayField16[si - FieldWidth + 1] = 0x5001;
+    PlayField16[si - FieldWidth] = 0x8888;
+  }
+
+  return;
+} // subCleanUpForZonksAbove
diff --git a/src/game_sp/Zonk.h b/src/game_sp/Zonk.h
new file mode 100644 (file)
index 0000000..e99ab01
--- /dev/null
@@ -0,0 +1,12 @@
+// ----------------------------------------------------------------------------
+// Zonk.h
+// ----------------------------------------------------------------------------
+
+#ifndef ZONK_H
+#define ZONK_H
+
+#include "global.h"
+
+extern void subAnimateZonks(int si);
+
+#endif /* ZONK_H */
diff --git a/src/game_sp/export.h b/src/game_sp/export.h
new file mode 100644 (file)
index 0000000..fe5995f
--- /dev/null
@@ -0,0 +1,212 @@
+#ifndef GAME_SP_EXPORT_H
+#define GAME_SP_EXPORT_H
+
+/* ========================================================================= */
+/* functions and definitions exported from game_sp to main program           */
+/* ========================================================================= */
+
+/* ------------------------------------------------------------------------- */
+/* constant definitions                                                      */
+/* ------------------------------------------------------------------------- */
+
+#define SP_MAX_PLAYFIELD_WIDTH         MAX_PLAYFIELD_WIDTH
+#define SP_MAX_PLAYFIELD_HEIGHT                MAX_PLAYFIELD_HEIGHT
+
+#define SP_NUM_LEVELS_PER_PACKAGE      111
+
+#define SP_STD_PLAYFIELD_WIDTH         60
+#define SP_STD_PLAYFIELD_HEIGHT                24
+#define SP_LEVEL_NAME_LEN              23
+#define SP_MAX_SPECIAL_PORTS           10
+
+#define SP_HEADER_SIZE                 96
+#define SP_STD_PLAYFIELD_SIZE          (SP_STD_PLAYFIELD_WIDTH *       \
+                                        SP_STD_PLAYFIELD_HEIGHT)
+#define SP_MAX_PLAYFIELD_SIZE          (SP_MAX_PLAYFIELD_WIDTH *       \
+                                        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") */
+
+
+/* sound actions */
+
+#define actActive                      0
+#define actImpact                      1
+#define actExploding                   2
+#define actDigging                     3
+#define actSnapping                    4
+#define actCollecting                  5
+#define actPassing                     6
+#define actPushing                     7
+#define actDropping                    8
+
+
+/* ------------------------------------------------------------------------- */
+/* data structure definitions                                                */
+/* ------------------------------------------------------------------------- */
+
+#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
+  byte UnUsed;
+} SpecialPortType;
+#define HAS_SpecialPortType
+#endif
+
+#ifndef HAS_LevelInfoType
+typedef struct
+{
+  byte UnUsed[4];
+  byte InitialGravity; // 1=on, anything else (0) = off
+  byte Version; // SpeedFixVersion XOR &H20
+  char LevelTitle[23];
+  byte InitialFreezeZonks; // 2=on, anything else (0) = off.  (1=off too!)
+  byte InfotronsNeeded;
+
+  // 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 then result in 0-to-eat, etc.!)
+  byte SpecialPortCount; // Maximum 10 allowed!
+  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
+
+struct GlobalInfo_SP
+{
+};
+
+struct GameInfo_SP
+{
+  boolean LevelSolved;
+  boolean GameOver;
+
+  /* needed for updating panel */
+  int time_played;
+  int infotrons_still_needed;
+  int red_disk_count;
+  int score;
+
+  /* needed for engine snapshots */
+  int preceding_buffer_size;
+
+  int scroll_xoffset, scroll_yoffset;
+};
+
+struct DemoInfo_SP
+{
+  boolean is_available;                /* structure contains valid demo */
+
+  int level_nr;                        /* number of corresponding level */
+
+  int length;                  /* number of demo entries */
+  byte data[SP_MAX_TAPE_LEN];  /* array of demo entries */
+};
+
+struct LevelInfo_SP
+{
+  LevelInfoType header;
+  byte header_raw_bytes[SP_HEADER_SIZE];
+
+  int width, height;
+
+  byte playfield[SP_MAX_PLAYFIELD_WIDTH][SP_MAX_PLAYFIELD_HEIGHT];
+
+  struct DemoInfo_SP demo;
+
+  /* used for runtime values */
+  struct GameInfo_SP *game_sp;
+};
+
+struct GraphicInfo_SP
+{
+  Bitmap *bitmap;
+  int src_x, src_y;
+  int src_offset_x, src_offset_y;
+  int dst_offset_x, dst_offset_y;
+  int width, height;
+
+  Bitmap *crumbled_bitmap;
+  int crumbled_src_x, crumbled_src_y;
+  int crumbled_border_size;
+
+  boolean has_crumbled_graphics;
+  boolean preserve_background;
+
+  int unique_identifier;       /* used to identify needed screen updates */
+};
+
+struct EngineSnapshotInfo_SP
+{
+  struct GameInfo_SP game_sp;
+
+  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];
+
+  int AnimationPosTable[SP_MAX_PLAYFIELD_SIZE];
+  byte AnimationSubTable[SP_MAX_PLAYFIELD_SIZE];
+  byte TerminalState[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE];
+};
+
+
+/* ------------------------------------------------------------------------- */
+/* exported functions                                                        */
+/* ------------------------------------------------------------------------- */
+
+extern struct GlobalInfo_SP global_sp_info;
+extern struct GameInfo_SP game_sp;
+extern struct LevelInfo_SP native_sp_level;
+extern struct GraphicInfo_SP graphic_info_sp_object[TILE_MAX][8];
+extern struct GraphicInfo_SP graphic_info_sp_player[MAX_PLAYERS][SPR_MAX][8];
+extern struct EngineSnapshotInfo_SP engine_snapshot_sp;
+
+extern void sp_open_all();
+extern void sp_close_all();
+
+extern void InitGfxBuffers_SP();
+
+extern void InitGameEngine_SP();
+extern void GameActions_SP(byte *, boolean);
+
+extern unsigned int InitEngineRandom_SP(long);
+
+extern void setLevelInfoToDefaults_SP();
+extern void copyInternalEngineVars_SP();
+extern boolean LoadNativeLevel_SP(char *, int);
+extern void SaveNativeLevel_SP(char *);
+
+extern void BackToFront_SP(void);
+extern void BlitScreenToBitmap_SP(Bitmap *);
+extern void RedrawPlayfield_SP(boolean);
+extern void DrawGameDoorValues_SP();
+
+extern void LoadEngineSnapshotValues_SP();
+extern void SaveEngineSnapshotValues_SP();
+
+extern int map_key_RND_to_SP(int);
+extern int map_key_SP_to_RND(int);
+
+#endif /* GAME_SP_EXPORT_H */
diff --git a/src/game_sp/file.c b/src/game_sp/file.c
new file mode 100644 (file)
index 0000000..f841cf2
--- /dev/null
@@ -0,0 +1,660 @@
+
+#include "main_sp.h"
+#include "global.h"
+
+
+/* ------------------------------------------------------------------------- */
+/* functions for loading Supaplex level                                      */
+/* ------------------------------------------------------------------------- */
+
+void setTapeInfoToDefaults_SP()
+{
+  native_sp_level.demo.is_available = FALSE;
+  native_sp_level.demo.length = 0;
+}
+
+void setLevelInfoToDefaults_SP()
+{
+  LevelInfoType *header = &native_sp_level.header;
+  char *empty_title = "-------- EMPTY --------";
+  int i, x, y;
+
+  native_sp_level.game_sp = &game_sp;
+
+  native_sp_level.width  = SP_STD_PLAYFIELD_WIDTH;
+  native_sp_level.height = SP_STD_PLAYFIELD_HEIGHT;
+
+  for (x = 0; x < native_sp_level.width; x++)
+    for (y = 0; y < native_sp_level.height; y++)
+      native_sp_level.playfield[x][y] = fiSpace;
+
+  /* copy string (without terminating '\0' character!) */
+  for (i = 0; i < SP_LEVEL_NAME_LEN; i++)
+    header->LevelTitle[i] = empty_title[i];
+
+  header->InitialGravity = 0;
+  header->Version = 0;
+  header->InitialFreezeZonks = 0;
+  header->InfotronsNeeded = 0;
+  header->SpecialPortCount = 0;
+  header->SpeedByte = 0;
+  header->CheckSumByte = 0;
+  header->DemoRandomSeed = 0;
+
+  for (i = 0; i < SP_MAX_SPECIAL_PORTS; i++)
+  {
+    SpecialPortType *port = &header->SpecialPort[i];
+
+    port->PortLocation = 0;
+    port->Gravity = 0;
+    port->FreezeZonks = 0;
+    port->FreezeEnemies = 0;
+  }
+
+  /* set raw header bytes (used for subsequent buffer zone) to "hardware" */
+  for (i = 0; i < SP_HEADER_SIZE; i++)
+    native_sp_level.header_raw_bytes[i] = 0x20;
+
+  setTapeInfoToDefaults_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;
+  FieldHeight = native_sp_level.height;
+  HeaderSize = 96;
+
+  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;
+
+#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
+
+  count = 0;
+  for (i = 0; preceding_playfield_memory[i] != NULL; i++)
+  {
+    char *s = preceding_playfield_memory[i];
+    boolean hi_byte = FALSE;   /* little endian data => start with low byte */
+
+    while (s[0] != '\0' && s[1] != '\0')
+    {
+      int hi_nibble = s[0] - (s[0] > '9' ? 'a' - 10 : '0');
+      int lo_nibble = s[1] - (s[1] > '9' ? 'a' - 10 : '0');
+      int byte = (hi_nibble << 4) | lo_nibble;
+
+      if (hi_byte)
+       byte <<= 8;
+
+      PlayField16[-preceding_buffer_size + count] |= byte;
+
+      if (hi_byte)
+       count++;
+
+      hi_byte = !hi_byte;
+
+      s += 2;
+
+      while (*s == ' ')
+       s++;
+    }
+  }
+
+  count = 0;
+  for (y = 0; y < native_sp_level.height; y++)
+    for (x = 0; x < native_sp_level.width; x++)
+      PlayField8[count++] = native_sp_level.playfield[x][y];
+
+  /* add raw header bytes to subsequent playfield buffer zone */
+  for (i = 0; i < SP_HEADER_SIZE; i++)
+    PlayField8[count++] = native_sp_level.header_raw_bytes[i];
+
+  for (i = 0; i < count; i++)
+  {
+    PlayField16[i] = PlayField8[i];
+    DisPlayField[i] = PlayField8[i];
+    PlayField8[i] = 0;
+  }
+
+  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;
+}
+
+static void LoadNativeLevelFromFileStream_SP(FILE *file, int width, int height,
+                                            boolean demo_available)
+{
+  LevelInfoType *header = &native_sp_level.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 */
+
+  native_sp_level.width  = MIN(width,  SP_MAX_PLAYFIELD_WIDTH);
+  native_sp_level.height = MIN(height, SP_MAX_PLAYFIELD_HEIGHT);
+
+  /* read level playfield (width * height == 60 * 24 tiles == 1440 bytes) */
+  /* (MPX levels may have non-standard playfield size -- check max. size) */
+  for (y = 0; y < height; y++)
+  {
+    for (x = 0; x < width; x++)
+    {
+      byte element = getFile8Bit(file);
+
+      if (x < SP_MAX_PLAYFIELD_WIDTH &&
+         y < SP_MAX_PLAYFIELD_HEIGHT)
+       native_sp_level.playfield[x][y] = element;
+    }
+  }
+
+  /* read level header (96 bytes) */
+
+  ReadUnusedBytesFromFile(file, 4);    /* (not used by Supaplex engine) */
+
+  /* initial gravity: 1 == "on", anything else (0) == "off" */
+  header->InitialGravity = getFile8Bit(file);
+
+  /* SpeedFixVersion XOR 0x20 */
+  header->Version = getFile8Bit(file);
+
+  /* level title in uppercase letters, padded with dashes ("-") (23 bytes) */
+  for (i = 0; i < SP_LEVEL_NAME_LEN; i++)
+    header->LevelTitle[i] = getFile8Bit(file);
+
+  /* initial "freeze zonks": 2 == "on", anything else (0, 1) == "off" */
+  header->InitialFreezeZonks = getFile8Bit(file);
+
+  /* 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"!) */
+  header->InfotronsNeeded = getFile8Bit(file);
+
+  /* number of special ("gravity") port entries below (maximum 10 allowed) */
+  header->SpecialPortCount = getFile8Bit(file);
+
+  /* database of properties of up to 10 special ports (6 bytes per port) */
+  for (i = 0; i < SP_MAX_SPECIAL_PORTS; i++)
+  {
+    SpecialPortType *port = &header->SpecialPort[i];
+
+    /* 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->PortLocation = getFile16BitBE(file);         /* yes, big endian */
+
+    /* change gravity: 1 == "turn on", anything else (0) == "turn off" */
+    port->Gravity = getFile8Bit(file);
+
+    /* "freeze zonks": 2 == "turn on", anything else (0, 1) == "turn off" */
+    port->FreezeZonks = getFile8Bit(file);
+
+    /* "freeze enemies": 1 == "turn on", anything else (0) == "turn off" */
+    port->FreezeEnemies = getFile8Bit(file);
+
+    ReadUnusedBytesFromFile(file, 1);  /* (not used by Supaplex engine) */
+  }
+
+  /* SpeedByte XOR Highbyte(RandomSeed) */
+  header->SpeedByte = getFile8Bit(file);
+
+  /* CheckSum XOR SpeedByte */
+  header->CheckSumByte = getFile8Bit(file);
+
+  /* random seed used for recorded demos */
+  header->DemoRandomSeed = getFile16BitLE(file);       /* yes, little endian */
+
+  /* auto-determine number of infotrons if it was stored as "0" -- see above */
+  if (header->InfotronsNeeded == 0)
+  {
+    for (x = 0; x < native_sp_level.width; x++)
+      for (y = 0; y < native_sp_level.height; y++)
+       if (native_sp_level.playfield[x][y] == fiInfotron)
+         header->InfotronsNeeded++;
+
+    header->InfotronsNeeded &= 0xff;   /* only use low byte -- see above */
+  }
+
+  /* read raw level header bytes (96 bytes) */
+
+  fseek(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);
+
+  /* also load demo tape, if available (only in single level files) */
+
+  if (demo_available)
+  {
+    int level_nr = getFile8Bit(file);
+
+    level_nr &= 0x7f;                  /* clear highest bit */
+    level_nr = (level_nr < 1   ? 1   :
+               level_nr > 111 ? 111 : level_nr);
+
+    native_sp_level.demo.level_nr = level_nr;
+
+    for (i = 0; i < SP_MAX_TAPE_LEN && !feof(file); i++)
+    {
+      native_sp_level.demo.data[i] = getFile8Bit(file);
+
+      if (native_sp_level.demo.data[i] == 0xff)        /* "end of demo" byte */
+      {
+       i++;
+
+       break;
+      }
+    }
+
+    native_sp_level.demo.length = i;
+    native_sp_level.demo.is_available = (native_sp_level.demo.length > 0);
+  }
+}
+
+boolean LoadNativeLevel_SP(char *filename, int level_pos)
+{
+  FILE *file;
+  int i, l, x, y;
+  char name_first, name_last;
+  struct LevelInfo_SP 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;
+  LevelInfoType *header = &native_sp_level.header;
+  boolean is_single_level_file = (strSuffixLower(filename, ".sp") ||
+                                 strSuffixLower(filename, ".mpx"));
+  boolean demo_available = is_single_level_file;
+  boolean is_mpx_file = strSuffixLower(filename, ".mpx");
+  int file_seek_pos = level_pos * SP_STD_LEVEL_SIZE;
+  int level_width  = SP_STD_PLAYFIELD_WIDTH;
+  int level_height = SP_STD_PLAYFIELD_HEIGHT;
+
+  /* always start with reliable default values */
+  setLevelInfoToDefaults_SP();
+  copyInternalEngineVars_SP();
+
+  if (!(file = fopen(filename, MODE_READ)))
+  {
+    Error(ERR_WARN, "cannot open file '%s' -- using empty level", filename);
+
+    return FALSE;
+  }
+
+  if (is_mpx_file)
+  {
+    char mpx_chunk_name[4 + 1];
+    int mpx_version;
+    int mpx_level_count;
+    LevelDescriptor *mpx_level_desc;
+
+    getFileChunkBE(file, mpx_chunk_name, NULL);
+
+    if (!strEqual(mpx_chunk_name, "MPX "))
+    {
+      Error(ERR_WARN, "cannot find MPX ID in file '%s' -- using empty level",
+           filename);
+
+      return FALSE;
+    }
+
+    mpx_version = getFile16BitLE(file);
+
+    if (mpx_version != 1)
+    {
+      Error(ERR_WARN, "unknown MPX version in file '%s' -- using empty level",
+           filename);
+
+      return FALSE;
+    }
+
+    mpx_level_count = getFile16BitLE(file);
+
+    if (mpx_level_count < 1)
+    {
+      Error(ERR_WARN, "no MPX levels found in file '%s' -- using empty level",
+           filename);
+
+      return FALSE;
+    }
+
+    if (level_pos >= mpx_level_count)
+    {
+      Error(ERR_WARN, "MPX level not found in file '%s' -- using empty level",
+           filename);
+
+      return FALSE;
+    }
+
+    mpx_level_desc = checked_calloc(mpx_level_count * sizeof(LevelDescriptor));
+
+    for (i = 0; i < mpx_level_count; i++)
+    {
+      LevelDescriptor *ldesc = &mpx_level_desc[i];
+
+      ldesc->Width  = getFile16BitLE(file);
+      ldesc->Height = getFile16BitLE(file);
+      ldesc->OffSet = getFile32BitLE(file);    /* starts with 1, not with 0 */
+      ldesc->Size   = getFile32BitLE(file);
+    }
+
+    level_width  = mpx_level_desc[level_pos].Width;
+    level_height = mpx_level_desc[level_pos].Height;
+
+    file_seek_pos = mpx_level_desc[level_pos].OffSet - 1;
+  }
+
+  /* position file stream to the requested level (in case of level package) */
+  if (fseek(file, file_seek_pos, SEEK_SET) != 0)
+  {
+    Error(ERR_WARN, "cannot fseek in file '%s' -- using empty level", filename);
+
+    return FALSE;
+  }
+
+  /* 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 = level_pos; l < SP_NUM_LEVELS_PER_PACKAGE; l++)
+  {
+    LoadNativeLevelFromFileStream_SP(file, level_width, level_height,
+                                    demo_available);
+
+    /* check if this level is a part of a bigger multi-part level */
+
+    if (is_single_level_file)
+      break;
+
+    name_first = header->LevelTitle[0];
+    name_last  = header->LevelTitle[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'));
+
+    if (is_multipart_level)
+    {
+      /* correct leading multipart level meta information in level name */
+      for (i = 0;
+          i < SP_LEVEL_NAME_LEN && header->LevelTitle[i] == name_first;
+          i++)
+       header->LevelTitle[i] = '-';
+
+      /* correct trailing multipart level meta information in level name */
+      for (i = SP_LEVEL_NAME_LEN - 1;
+          i >= 0 && header->LevelTitle[i] == name_last;
+          i--)
+       header->LevelTitle[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 ||
+        !strEqualN(header->LevelTitle, multipart_level.header.LevelTitle,
+                   SP_LEVEL_NAME_LEN)))
+    {
+      /* 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 = native_sp_level;
+
+      /* clear playfield of new multi-part level */
+      for (x = 0; x < SP_MAX_PLAYFIELD_WIDTH; x++)
+       for (y = 0; y < SP_MAX_PLAYFIELD_HEIGHT; y++)
+         multipart_level.playfield[x][y] = fiSpace;
+    }
+
+    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.header.LevelTitle);
+#endif
+
+    if (multipart_xpos * SP_STD_PLAYFIELD_WIDTH  > SP_MAX_PLAYFIELD_WIDTH ||
+       multipart_ypos * SP_STD_PLAYFIELD_HEIGHT > SP_MAX_PLAYFIELD_HEIGHT)
+    {
+      Error(ERR_WARN, "multi-part level is too big -- ignoring part of it");
+
+      break;
+    }
+
+    multipart_level.width  = MAX(multipart_level.width,
+                                multipart_xpos * SP_STD_PLAYFIELD_WIDTH);
+    multipart_level.height = MAX(multipart_level.height,
+                                multipart_ypos * SP_STD_PLAYFIELD_HEIGHT);
+
+    /* copy level part at the right position of multi-part level */
+    for (x = 0; x < SP_STD_PLAYFIELD_WIDTH; x++)
+    {
+      for (y = 0; y < SP_STD_PLAYFIELD_HEIGHT; y++)
+      {
+       int start_x = (multipart_xpos - 1) * SP_STD_PLAYFIELD_WIDTH;
+       int start_y = (multipart_ypos - 1) * SP_STD_PLAYFIELD_HEIGHT;
+
+       multipart_level.playfield[start_x + x][start_y + y] =
+         native_sp_level.playfield[x][y];
+      }
+    }
+  }
+
+  fclose(file);
+
+  if (use_empty_level)
+  {
+    setLevelInfoToDefaults_SP();
+
+    Error(ERR_WARN, "single part of multi-part level -- using empty level");
+  }
+
+  if (reading_multipart_level)
+    native_sp_level = multipart_level;
+
+  copyInternalEngineVars_SP();
+
+  return TRUE;
+}
+
+void SaveNativeLevel_SP(char *filename)
+{
+  LevelInfoType *header = &native_sp_level.header;
+  FILE *file;
+  int i, x, y;
+
+  if (!(file = fopen(filename, MODE_WRITE)))
+  {
+    Error(ERR_WARN, "cannot save native level file '%s'", filename);
+
+    return;
+  }
+
+  /* write level playfield (width * height == 60 * 24 tiles == 1440 bytes) */
+  for (y = 0; y < native_sp_level.height; y++)
+    for (x = 0; x < native_sp_level.width; x++)
+      putFile8Bit(file, native_sp_level.playfield[x][y]);
+
+  /* write level header (96 bytes) */
+
+  WriteUnusedBytesToFile(file, 4);
+
+  putFile8Bit(file, header->InitialGravity);
+  putFile8Bit(file, header->Version);
+
+  for (i = 0; i < SP_LEVEL_NAME_LEN; i++)
+    putFile8Bit(file, header->LevelTitle[i]);
+
+  putFile8Bit(file, header->InitialFreezeZonks);
+  putFile8Bit(file, header->InfotronsNeeded);
+  putFile8Bit(file, header->SpecialPortCount);
+
+  for (i = 0; i < SP_MAX_SPECIAL_PORTS; i++)
+  {
+    SpecialPortType *port = &header->SpecialPort[i];
+
+    putFile16BitBE(file, port->PortLocation);
+    putFile8Bit(file, port->Gravity);
+    putFile8Bit(file, port->FreezeZonks);
+    putFile8Bit(file, port->FreezeEnemies);
+
+    WriteUnusedBytesToFile(file, 1);
+  }
+
+  putFile8Bit(file, header->SpeedByte);
+  putFile8Bit(file, header->CheckSumByte);
+  putFile16BitLE(file, header->DemoRandomSeed);
+
+  /* also save demo tape, if available */
+
+  if (native_sp_level.demo.is_available)
+  {
+    putFile8Bit(file, native_sp_level.demo.level_nr);
+
+    for (i = 0; i < native_sp_level.demo.length; i++)
+      putFile8Bit(file, native_sp_level.demo.data[i]);
+  }
+
+  fclose(file);
+}
diff --git a/src/game_sp/game_sp.h b/src/game_sp/game_sp.h
new file mode 100644 (file)
index 0000000..9551e84
--- /dev/null
@@ -0,0 +1,21 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2006 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* game_sp.h                                                *
+***********************************************************/
+
+#ifndef GAME_SP_H
+#define GAME_SP_H
+
+#define GAME_SP_VERSION_1_0_0
+
+#include "export.h"
+
+#endif /* GAME_SP_H */
diff --git a/src/game_sp/global.h b/src/game_sp/global.h
new file mode 100644 (file)
index 0000000..91847c2
--- /dev/null
@@ -0,0 +1,32 @@
+// ----------------------------------------------------------------------------
+// global.h
+// ----------------------------------------------------------------------------
+
+#ifndef GAME_SP_GLOBAL_H
+#define GAME_SP_GLOBAL_H
+
+#include "main_sp.h"
+
+#include "vb_lib.h"
+
+#include "ASM.h"
+#include "BugsTerminals.h"
+#include "DDScrollBuffer.h"
+#include "DDSpriteBuffer.h"
+#include "Display.h"
+#include "DoGameStuff.h"
+#include "Electrons.h"
+#include "Explosions.h"
+#include "Globals.h"
+#include "Infotrons.h"
+#include "InitGameConditions.h"
+#include "Input.h"
+#include "MainForm.h"
+#include "MainGameLoop.h"
+#include "Murphy.h"
+#include "OrangeDisk.h"
+#include "SnikSnaks.h"
+#include "Sound.h"
+#include "Zonk.h"
+
+#endif /* GAME_SP_GLOBAL_H */
diff --git a/src/game_sp/init.c b/src/game_sp/init.c
new file mode 100644 (file)
index 0000000..d8e4597
--- /dev/null
@@ -0,0 +1,155 @@
+
+#include "main_sp.h"
+#include "global.h"
+
+
+Bitmap *bitmap_db_field_sp;
+
+struct EngineSnapshotInfo_SP engine_snapshot_sp;
+
+void sp_open_all()
+{
+  Form_Load();
+}
+
+void sp_close_all()
+{
+}
+
+void InitGfxBuffers_SP()
+{
+  ReCreateBitmap(&bitmap_db_field_sp, FXSIZE, FYSIZE, DEFAULT_DEPTH);
+}
+
+unsigned int InitEngineRandom_SP(long seed)
+{
+  if (seed == NEW_RANDOMIZE)
+  {
+    subRandomize();
+
+    seed = (long)RandomSeed;
+  }
+
+  RandomSeed = (short)seed;
+
+  return (unsigned int) seed;
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* Supaplex game engine snapshot handling functions                          */
+/* ------------------------------------------------------------------------- */
+
+void SaveEngineSnapshotValues_SP()
+{
+  int i;
+
+  engine_snapshot_sp.game_sp = game_sp;
+
+  /* these arrays have playfield-size dependent variable size */
+
+  for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++)
+    engine_snapshot_sp.PlayField16[i] = PlayField16[i];
+  for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++)
+    engine_snapshot_sp.PlayField8[i] = PlayField8[i];
+  for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++)
+    engine_snapshot_sp.DisPlayField[i] = DisPlayField[i];
+
+  for (i = 0; i < FieldWidth * (FieldHeight - 2); i++)
+    engine_snapshot_sp.AnimationPosTable[i] = AnimationPosTable[i];
+  for (i = 0; i < FieldWidth * (FieldHeight - 2); i++)
+    engine_snapshot_sp.AnimationSubTable[i] = AnimationSubTable[i];
+  for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++)
+    engine_snapshot_sp.TerminalState[i] = TerminalState[i];
+
+  /* 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));
+}
+
+void LoadEngineSnapshotValues_SP()
+{
+  int i;
+
+  /* stored engine snapshot buffers already restored at this point */
+
+  game_sp = engine_snapshot_sp.game_sp;
+
+  /* these arrays have playfield-size dependent variable size */
+
+  for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++)
+    PlayField16[i] = engine_snapshot_sp.PlayField16[i];
+  for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++)
+    PlayField8[i] = engine_snapshot_sp.PlayField8[i];
+  for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++)
+    DisPlayField[i] = engine_snapshot_sp.DisPlayField[i];
+
+  for (i = 0; i < FieldWidth * (FieldHeight - 2); i++)
+    AnimationPosTable[i] = engine_snapshot_sp.AnimationPosTable[i];
+  for (i = 0; i < FieldWidth * (FieldHeight - 2); i++)
+    AnimationSubTable[i] = engine_snapshot_sp.AnimationSubTable[i];
+  for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++)
+    TerminalState[i] = engine_snapshot_sp.TerminalState[i];
+
+  RedrawPlayfield_SP(TRUE);
+}
diff --git a/src/game_sp/main.c b/src/game_sp/main.c
new file mode 100644 (file)
index 0000000..1308353
--- /dev/null
@@ -0,0 +1,94 @@
+
+#include "main_sp.h"
+#include "global.h"
+
+
+struct GameInfo_SP game_sp;
+struct LevelInfo_SP native_sp_level;
+
+int GfxElementLast[SP_MAX_PLAYFIELD_WIDTH][SP_MAX_PLAYFIELD_HEIGHT];
+int GfxGraphicLast[SP_MAX_PLAYFIELD_WIDTH][SP_MAX_PLAYFIELD_HEIGHT];
+int GfxGraphic[SP_MAX_PLAYFIELD_WIDTH][SP_MAX_PLAYFIELD_HEIGHT];
+int GfxFrame[SP_MAX_PLAYFIELD_WIDTH][SP_MAX_PLAYFIELD_HEIGHT];
+
+
+void InitGameEngine_SP()
+{
+  int x, y;
+
+  gfx.anim_random_frame = -1;  // (use simple, ad-hoc random numbers)
+
+  game_sp.LevelSolved = FALSE;
+  game_sp.GameOver = FALSE;
+
+  game_sp.time_played = 0;
+  game_sp.infotrons_still_needed = native_sp_level.header.InfotronsNeeded;
+  game_sp.red_disk_count = 0;
+  game_sp.score = 0;
+
+  menBorder = setup.sp_show_border_elements;
+
+  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++)
+  {
+    for (y = 0; y < SP_MAX_PLAYFIELD_HEIGHT; y++)
+    {
+      GfxElementLast[x][y] = -1;
+      GfxGraphicLast[x][y] = -1;
+      GfxGraphic[x][y] = -1;
+      GfxFrame[x][y] = 0;
+    }
+  }
+
+  InitScrollPlayfield();
+
+  menPlay_Click();
+}
+
+void RedrawPlayfield_SP(boolean force_redraw)
+{
+  if (force_redraw)
+    RestorePlayfield();
+
+  UpdatePlayfield(force_redraw);
+
+  BackToFront_SP();
+}
+
+void DrawGameDoorValues_SP()
+{
+  game_sp.time_played = TimerVar / setup.game_frame_delay;
+  game_sp.infotrons_still_needed = InfotronsNeeded;
+  game_sp.red_disk_count = RedDiskCount;
+  game_sp.score = 0;           // (currently no score in Supaplex engine)
+}
+
+void GameActions_SP(byte action[MAX_PLAYERS], boolean warp_mode)
+{
+  byte single_player_action = action[0];
+  int x, y;
+
+  UpdateEngineValues(mScrollX / TILEX, mScrollY / TILEY);
+
+  subMainGameLoop_Main(single_player_action, warp_mode);
+
+  RedrawPlayfield_SP(FALSE);
+
+  if (!warp_mode)              /* do not redraw values in warp mode */
+    DrawGameDoorValues_SP();
+
+  CheckSingleStepMode_SP(PlayField16[MurphyPosIndex] != fiMurphy);
+
+  for (x = DisplayMinX; x <= DisplayMaxX; x++)
+    for (y = DisplayMinY; y <= DisplayMaxY; y++)
+      GfxFrame[x][y]++;
+}
diff --git a/src/game_sp/main_sp.h b/src/game_sp/main_sp.h
new file mode 100644 (file)
index 0000000..6e61508
--- /dev/null
@@ -0,0 +1,95 @@
+#ifndef MAIN_SP_H
+#define MAIN_SP_H
+
+/* ========================================================================= */
+/* external functions and definitions imported from main program to game_sp  */
+/* ========================================================================= */
+
+#include "../engines.h"
+#include "../conf_gfx.h"
+
+
+/* ========================================================================= */
+/* functions and definitions that are exported from game_sp to main program  */
+/* ========================================================================= */
+
+#include "export.h"
+
+
+/* ========================================================================= */
+/* internal functions and definitions that are not exported to main program  */
+/* ========================================================================= */
+
+
+/* ------------------------------------------------------------------------- */
+/* constant definitions                                                      */
+/* ------------------------------------------------------------------------- */
+
+/* screen sizes and positions for SP engine */
+
+#define ORIG_TILESIZE          16
+
+#define ZOOM_FACTOR            2
+
+#define TILESIZE               (ORIG_TILESIZE * ZOOM_FACTOR)
+#define TILEX                  TILESIZE
+#define TILEY                  TILESIZE
+
+#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
+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)
+
+
+/* ------------------------------------------------------------------------- */
+/* data structure definitions                                                */
+/* ------------------------------------------------------------------------- */
+
+/* ------------------------------------------------------------------------- */
+/* exported variables                                                        */
+/* ------------------------------------------------------------------------- */
+
+extern struct LevelInfo_SP native_sp_level;
+
+extern Bitmap *bitmap_db_field_sp;
+
+extern int GfxElementLast[SP_MAX_PLAYFIELD_WIDTH][SP_MAX_PLAYFIELD_HEIGHT];
+extern int GfxGraphicLast[SP_MAX_PLAYFIELD_WIDTH][SP_MAX_PLAYFIELD_HEIGHT];
+extern int GfxGraphic[SP_MAX_PLAYFIELD_WIDTH][SP_MAX_PLAYFIELD_HEIGHT];
+extern int GfxFrame[SP_MAX_PLAYFIELD_WIDTH][SP_MAX_PLAYFIELD_HEIGHT];
+
+
+/* ------------------------------------------------------------------------- */
+/* exported functions                                                        */
+/* ------------------------------------------------------------------------- */
+
+#endif /* MAIN_SP_H */
diff --git a/src/game_sp/vb_lib.c b/src/game_sp/vb_lib.c
new file mode 100644 (file)
index 0000000..f71693c
--- /dev/null
@@ -0,0 +1,29 @@
+// ----------------------------------------------------------------------------
+// vb_lib.c
+// ----------------------------------------------------------------------------
+
+#include "main_sp.h"
+
+#include "vb_lib.h"
+
+
+/* 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()
+{
+  return random_linux_libc(RANDOM_SIMPLE);
+}
diff --git a/src/game_sp/vb_lib.h b/src/game_sp/vb_lib.h
new file mode 100644 (file)
index 0000000..cf8e346
--- /dev/null
@@ -0,0 +1,20 @@
+// ----------------------------------------------------------------------------
+// vb_lib.h
+// ----------------------------------------------------------------------------
+
+#ifndef VB_LIB_H
+#define VB_LIB_H
+
+#define Abs(x) ABS(x)
+#define Sqr(x) sqrt(x)
+
+
+/* helper functions for constructs not supported by C */
+
+#if 0
+extern void *REDIM_1D(int, int, int);
+#endif
+
+extern long MyGetTickCount();
+
+#endif /* VB_LIB_H */
index ea5ec18de985d667f2fccda3b504cdbc3f7c1fc5..5e5301c728941fee464336c504e25ce77a8b0ec6 100644 (file)
@@ -186,20 +186,8 @@ void DrawInitAnim()
   }
 #endif
 
-#if 0
-  anim_initial.anim_mode = ANIM_LOOP;
-  anim_initial.anim_start_frame = 0;
-  anim_initial.offset_x = anim_initial.width;
-  anim_initial.offset_y = 0;
-#endif
-
-#if 1
-  x = ALIGNED_TEXT_XPOS(&init.busy);
-  y = ALIGNED_TEXT_YPOS(&init.busy);
-#else
-  x = WIN_XSIZE / 2 - TILESIZE / 2;
-  y = WIN_YSIZE / 2 - TILESIZE / 2;
-#endif
+  x = ALIGNED_TEXT_XPOS(&init_last.busy);
+  y = ALIGNED_TEXT_YPOS(&init_last.busy);
 
   graphic_info = &anim_initial;                /* graphic == 0 => anim_initial */
 
@@ -329,6 +317,14 @@ void SetBitmaps_EM(Bitmap **em_bitmap)
 }
 #endif
 
+#if 0
+/* !!! FIX THIS (CHANGE TO USING NORMAL ELEMENT GRAPHIC DEFINITIONS) !!! */
+void SetBitmaps_SP(Bitmap **sp_bitmap)
+{
+  *sp_bitmap = graphic_info[IMG_SP_OBJECTS].bitmap;
+}
+#endif
+
 static int getFontBitmapID(int font_nr)
 {
   int special = -1;
@@ -1298,6 +1294,8 @@ static void set_graphic_parameters_ext(int graphic, int *parameter,
   g->align = ALIGN_CENTER;             /* default for title screens */
   g->valign = VALIGN_MIDDLE;           /* default for title screens */
   g->sort_priority = 0;                        /* default for title screens */
+  g->class = 0;
+  g->style = STYLE_DEFAULT;
 
   g->bitmap = src_bitmap;
 
@@ -1498,6 +1496,11 @@ static void set_graphic_parameters_ext(int graphic, int *parameter,
     g->valign = parameter[GFX_ARG_VALIGN];
   if (parameter[GFX_ARG_SORT_PRIORITY] != ARG_UNDEFINED_VALUE)
     g->sort_priority = parameter[GFX_ARG_SORT_PRIORITY];
+
+  if (parameter[GFX_ARG_CLASS] != ARG_UNDEFINED_VALUE)
+    g->class = parameter[GFX_ARG_CLASS];
+  if (parameter[GFX_ARG_STYLE] != ARG_UNDEFINED_VALUE)
+    g->style = parameter[GFX_ARG_STYLE];
 }
 
 static void set_graphic_parameters(int graphic)
@@ -2829,8 +2832,12 @@ void InitElementPropertiesStatic()
     EL_SIGN_FRANKIE,
     EL_STEEL_EXIT_CLOSED,
     EL_STEEL_EXIT_OPEN,
+    EL_STEEL_EXIT_OPENING,
+    EL_STEEL_EXIT_CLOSING,
     EL_EM_STEEL_EXIT_CLOSED,
     EL_EM_STEEL_EXIT_OPEN,
+    EL_EM_STEEL_EXIT_OPENING,
+    EL_EM_STEEL_EXIT_CLOSING,
     EL_DC_STEELWALL_1_LEFT,
     EL_DC_STEELWALL_1_RIGHT,
     EL_DC_STEELWALL_1_TOP,
@@ -4174,6 +4181,7 @@ void InitElementPropertiesStatic()
     EL_PLAYER_2,
     EL_PLAYER_3,
     EL_PLAYER_4,
+    EL_SOKOBAN_FIELD_PLAYER,
     EL_SP_MURPHY,
     EL_YAMYAM,
     EL_YAMYAM_LEFT,
@@ -5124,7 +5132,7 @@ void Execute_Command(char *command)
 
     exit(0);
   }
-  else if (strncmp(command, "dump level ", 11) == 0)
+  else if (strPrefix(command, "dump level "))
   {
     char *filename = &command[11];
 
@@ -5136,7 +5144,7 @@ void Execute_Command(char *command)
 
     exit(0);
   }
-  else if (strncmp(command, "dump tape ", 10) == 0)
+  else if (strPrefix(command, "dump tape "))
   {
     char *filename = &command[10];
 
@@ -5148,7 +5156,7 @@ void Execute_Command(char *command)
 
     exit(0);
   }
-  else if (strncmp(command, "autoplay ", 9) == 0)
+  else if (strPrefix(command, "autoplay "))
   {
     char *str_ptr = getStringCopy(&command[9]);        /* read command parameters */
 
@@ -5184,9 +5192,9 @@ void Execute_Command(char *command)
        str_ptr++;
     }
   }
-  else if (strncmp(command, "convert ", 8) == 0)
+  else if (strPrefix(command, "convert "))
   {
-    char *str_copy = getStringCopy(&command[8]);
+    char *str_copy = getStringCopy(strchr(command, ' ') + 1);
     char *str_ptr = strchr(str_copy, ' ');
 
     global.convert_leveldir = str_copy;
@@ -5198,7 +5206,7 @@ void Execute_Command(char *command)
       global.convert_level_nr = atoi(str_ptr); /* get level_nr value */
     }
   }
-  else if (strncmp(command, "create images ", 14) == 0)
+  else if (strPrefix(command, "create images "))
   {
 #if defined(TARGET_SDL)
     global.create_images_dir = getStringCopy(&command[14]);
@@ -5441,6 +5449,28 @@ static void InitMixer()
   StartMixer();
 }
 
+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);
+
+  /* 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);
+  InitGfxClipRegion(FALSE, -1, -1, -1, -1);
+
+  InitGfxBuffers_SP();
+}
+
 void InitGfx()
 {
   struct GraphicInfo *graphic_info_last = graphic_info;
@@ -5487,7 +5517,11 @@ 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);
@@ -5502,6 +5536,8 @@ void InitGfx()
   InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
   InitGfxWindowInfo(WIN_XSIZE, WIN_YSIZE);
   InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
+#endif
+
   InitGfxCustomArtworkInfo();
 
   bitmap_font_initial = LoadCustomImage(filename_font_initial);
@@ -5615,6 +5651,9 @@ void InitGfx()
 
   InitMenuDesignSettings_Static();
   InitGfxDrawBusyAnimFunction(DrawInitAnim);
+
+  /* use copy of busy animation to prevent change while reloading artwork */
+  init_last = init;
 #endif
 }
 
@@ -6094,6 +6133,8 @@ void ReloadCustomArtwork(int force_reload)
 
   game_status = last_game_status;      /* restore current game status */
 
+  init_last = init;                    /* switch to new busy animation */
+
 #if 0
   printf("::: ----------------DELAY 1 ...\n");
   Delay(3000);
@@ -6151,8 +6192,14 @@ void OpenAll()
 
   game_status = GAME_MODE_LOADING;
 
+#if 1
+  InitCounter();
+#endif
+
   InitGlobal();                        /* initialize some global variables */
 
+  print_timestamp_time("[init global stuff]");
+
   if (options.execute_command)
     Execute_Command(options.execute_command);
 
@@ -6175,25 +6222,29 @@ void OpenAll()
   InitArtworkConfig();         /* needed before forking sound child process */
   InitMixer();
 
+#if 0
   InitCounter();
+#endif
 
   InitRND(NEW_RANDOMIZE);
   InitSimpleRandom(NEW_RANDOMIZE);
 
   InitJoysticks();
 
-  print_timestamp_time("[pre-video]");
+  print_timestamp_time("[init setup/config stuff]");
 
   InitVideoDisplay();
   InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
 
   InitEventFilter(FilterMouseMotionEvents);
 
+  print_timestamp_time("[init video stuff]");
+
   InitElementPropertiesStatic();
   InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
   InitElementPropertiesGfxElement();
 
-  print_timestamp_time("[post-video]");
+  print_timestamp_time("[init element properties stuff]");
 
   InitGfx();
 
@@ -6223,6 +6274,10 @@ void OpenAll()
   em_open_all();
 #endif
 
+#if 1
+  sp_open_all();
+#endif
+
   if (global.autoplay_leveldir)
   {
     AutoPlayTape();
@@ -6270,6 +6325,10 @@ void CloseAllAndExit(int exit_value)
   em_close_all();
 #endif
 
+#if 1
+  sp_close_all();
+#endif
+
   FreeAllImages();
 
 #if defined(TARGET_SDL)
index 4226241afc7bfe467ead6e61854c153e1c7a48a2..42bc9f740525d79035a0abfdd5c8bbb1d6297b1a 100644 (file)
@@ -43,6 +43,9 @@ void RedrawBackground();
 
 void KeyboardAutoRepeatOffUnlessAutoplay();
 
+void InitGfxBuffers();
+void InitGadgets();
+
 void OpenAll(void);
 void CloseAllAndExit(int);
 
index 6148a9850eea68621ed487abca8a02bc2927eecb..140e9fd9a5bb6aebd65b494ce3363042b361ecc4 100644 (file)
@@ -13,6 +13,7 @@ SRCS =        system.c        \
        text.c          \
        sound.c         \
        joystick.c      \
+       snapshot.c      \
        toons.c         \
        pcx.c           \
        image.c         \
@@ -28,6 +29,7 @@ OBJS =        system.o        \
        gadgets.o       \
        text.o          \
        sound.o         \
+       snapshot.o      \
        joystick.o      \
        toons.o         \
        pcx.o           \
index 3d593a9b1f12ba6ee05346c898bcb6775ddf29ee..4ac2a294202b249eb88fc6831dc7b0c623fd6d6b 100644 (file)
@@ -383,7 +383,7 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
        /* gadget text value */
 #if 1
        DrawTextBuffer(gi->x + border_x, gi->y + border_y, gi->textarea.value,
-                      font_nr, gi->textarea.xsize, -1, gi->textarea.ysize,
+                      font_nr, gi->textarea.xsize, 0, -1, gi->textarea.ysize,
                       BLIT_ON_BACKGROUND, FALSE, FALSE, FALSE);
 #else
        DrawTextToTextArea(gi->x + border_x, gi->y + border_y,
index 0d20f2c42283475d7e4b7362343799c9102c1d8a..17e511e97fc1c28ceba78e819d632927cc467646 100644 (file)
@@ -251,23 +251,16 @@ struct hashtable_itr *
 hashtable_iterator(struct hashtable *h);
 
 /*****************************************************************************/
-/* hashtable_iterator_key
- * - return the value of the (key,value) pair at the current position */
+/* key - return the key of the (key,value) pair at the current position */
 
-extern inline void *
-hashtable_iterator_key(struct hashtable_itr *i)
-{
-  return i->e->k;
-}
+void *
+hashtable_iterator_key(struct hashtable_itr *i);
 
 /*****************************************************************************/
 /* value - return the value of the (key,value) pair at the current position */
 
-extern inline void *
-hashtable_iterator_value(struct hashtable_itr *i)
-{
-  return i->e->v;
-}
+void *
+hashtable_iterator_value(struct hashtable_itr *i);
 
 /*****************************************************************************/
 /* advance - advance the iterator to the next element
index 6f4c20c29e248d3f77eea1c9ec1fc04436c32926..d1f05c82fe561e07c112e9c4aaf0c97dc5608546 100644 (file)
@@ -23,6 +23,7 @@
 #include "gadgets.h"
 #include "text.h"
 #include "sound.h"
+#include "snapshot.h"
 #include "joystick.h"
 #include "toons.h"
 #include "image.h"
index 5e4b9310bc4701f9921603fa1b353a94398462d9..b8f2fe5c4d502d6e3896dedc7103613be5fcb52c 100644 (file)
@@ -14,6 +14,7 @@
 #include <time.h>
 #include <sys/time.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <stdarg.h>
 #include <ctype.h>
 #include <string.h>
@@ -181,6 +182,46 @@ END_OF_FUNCTION(increment_counter);
 /* maximal allowed length of a command line option */
 #define MAX_OPTION_LEN         256
 
+#if 1
+
+#ifdef TARGET_SDL
+static unsigned long getCurrentMS()
+{
+  return SDL_GetTicks();
+}
+
+#else /* !TARGET_SDL */
+
+#if defined(PLATFORM_UNIX)
+static unsigned long getCurrentMS()
+{
+  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;
+
+  /* get current system milliseconds */
+  current_ms = getCurrentMS();
+
+  /* reset base timestamp in case of counter reset or wrap-around */
+  if (mode == INIT_COUNTER || current_ms < base_ms)
+    base_ms = current_ms;
+
+  /* return milliseconds since last counter reset */
+  return current_ms - base_ms;
+}
+
+#else
+
 #ifdef TARGET_SDL
 static unsigned long mainCounter(int mode)
 {
@@ -222,6 +263,8 @@ static unsigned long mainCounter(int mode)
 #endif /* PLATFORM_UNIX */
 #endif /* !TARGET_SDL */
 
+#endif
+
 void InitCounter()             /* set counter back to zero */
 {
 #if !defined(PLATFORM_MSDOS)
@@ -468,6 +511,16 @@ char *getRealName()
   return real_name;
 }
 
+time_t getFileTimestampEpochSeconds(char *filename)
+{
+  struct stat file_status;
+
+  if (stat(filename, &file_status) != 0)       /* cannot stat file */
+    return 0;
+
+  return file_status.st_mtime;
+}
+
 
 /* ------------------------------------------------------------------------- */
 /* path manipulation functions                                               */
@@ -637,6 +690,26 @@ boolean strSuffix(char *s, char *suffix)
          strncmp(&s[strlen(s) - strlen(suffix)], suffix, strlen(suffix)) == 0);
 }
 
+boolean strPrefixLower(char *s, char *prefix)
+{
+  char *s_lower = getStringToLower(s);
+  boolean match = strPrefix(s_lower, prefix);
+
+  free(s_lower);
+
+  return match;
+}
+
+boolean strSuffixLower(char *s, char *suffix)
+{
+  char *s_lower = getStringToLower(s);
+  boolean match = strSuffix(s_lower, suffix);
+
+  free(s_lower);
+
+  return match;
+}
+
 
 /* ------------------------------------------------------------------------- */
 /* command line option handling functions                                    */
@@ -665,6 +738,7 @@ void GetOptions(char *argv[], void (*print_usage_function)(void))
   options.display_name = NULL;
   options.server_host = NULL;
   options.server_port = 0;
+
   options.ro_base_directory = ro_base_path;
   options.rw_base_directory = rw_base_path;
   options.level_directory    = getPath2(ro_base_path, LEVELS_DIRECTORY);
@@ -672,7 +746,10 @@ void GetOptions(char *argv[], void (*print_usage_function)(void))
   options.sounds_directory   = getPath2(ro_base_path, SOUNDS_DIRECTORY);
   options.music_directory    = getPath2(ro_base_path, MUSIC_DIRECTORY);
   options.docs_directory     = getPath2(ro_base_path, DOCS_DIRECTORY);
+
   options.execute_command = NULL;
+  options.special_flags = NULL;
+
   options.serveronly = FALSE;
   options.network = FALSE;
   options.verbose = FALSE;
@@ -701,7 +778,7 @@ void GetOptions(char *argv[], void (*print_usage_function)(void))
     if (strEqual(option, "--"))                        /* stop scanning arguments */
       break;
 
-    if (strncmp(option, "--", 2) == 0)         /* treat '--' like '-' */
+    if (strPrefix(option, "--"))               /* treat '--' like '-' */
       option++;
 
     option_arg = strchr(option, '=');
@@ -807,6 +884,25 @@ void GetOptions(char *argv[], void (*print_usage_function)(void))
     {
       options.debug_x11_sync = TRUE;
     }
+    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)
     {
       if (option_arg == NULL)
@@ -1409,7 +1505,7 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
     Key key = KSYM_UNDEFINED;
     char *name_ptr = *x11name;
 
-    if (strncmp(name_ptr, "XK_", 3) == 0 && strlen(name_ptr) == 4)
+    if (strPrefix(name_ptr, "XK_") && strlen(name_ptr) == 4)
     {
       char c = name_ptr[3];
 
@@ -1420,14 +1516,14 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
       else if (c >= '0' && c <= '9')
        key = KSYM_0 + (Key)(c - '0');
     }
-    else if (strncmp(name_ptr, "XK_KP_", 6) == 0 && strlen(name_ptr) == 7)
+    else if (strPrefix(name_ptr, "XK_KP_") && strlen(name_ptr) == 7)
     {
       char c = name_ptr[6];
 
       if (c >= '0' && c <= '9')
        key = KSYM_KP_0 + (Key)(c - '0');
     }
-    else if (strncmp(name_ptr, "XK_F", 4) == 0 && strlen(name_ptr) <= 6)
+    else if (strPrefix(name_ptr, "XK_F") && strlen(name_ptr) <= 6)
     {
       char c1 = name_ptr[4];
       char c2 = name_ptr[5];
@@ -1440,7 +1536,7 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
       if (d >= 1 && d <= KSYM_NUM_FKEYS)
        key = KSYM_F1 + (Key)(d - 1);
     }
-    else if (strncmp(name_ptr, "XK_", 3) == 0)
+    else if (strPrefix(name_ptr, "XK_"))
     {
       i = 0;
 
@@ -1454,7 +1550,7 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
       }
       while (translate_key[++i].x11name);
     }
-    else if (strncmp(name_ptr, "0x", 2) == 0)
+    else if (strPrefix(name_ptr, "0x"))
     {
       unsigned long value = 0;
 
@@ -1777,7 +1873,7 @@ boolean FileIsMusic(char *filename)
     return TRUE;
 
 #if defined(TARGET_SDL)
-  if (fileHasPrefix(basename, "mod") ||
+  if ((fileHasPrefix(basename, "mod") && !fileHasSuffix(basename, "txt")) ||
       fileHasSuffix(basename, "mod") ||
       fileHasSuffix(basename, "s3m") ||
       fileHasSuffix(basename, "it") ||
@@ -1915,6 +2011,20 @@ int get_parameter_value(char *value_raw, char *suffix, int type)
     if (string_has_parameter(value, "static_panel"))
       result |= ANIM_STATIC_PANEL;
   }
+  else if (strEqual(suffix, ".class"))
+  {
+    result = get_hash_from_key(value);
+  }
+  else if (strEqual(suffix, ".style"))
+  {
+    result = STYLE_DEFAULT;
+
+    if (string_has_parameter(value, "accurate_borders"))
+      result |= STYLE_ACCURATE_BORDERS;
+
+    if (string_has_parameter(value, "inner_corners"))
+      result |= STYLE_INNER_CORNERS;
+  }
   else if (strEqual(suffix, ".fade_mode"))
   {
     result = (string_has_parameter(value, "none")      ? FADE_MODE_NONE :
index 56467dc1220255a11c51d9870a660b2dad4c6a75..34499610e2633ea978a4b11553a32cceb9a34105 100644 (file)
@@ -92,6 +92,8 @@ unsigned int get_random_number(int, int);
 char *getLoginName(void);
 char *getRealName(void);
 
+time_t getFileTimestampEpochSeconds(char *);
+
 char *getBasePath(char *);
 char *getBaseName(char *);
 char *getBaseNamePtr(char *);
@@ -110,6 +112,8 @@ boolean strEqual(char *, char *);
 boolean strEqualN(char *, char *, int);
 boolean strPrefix(char *, char *);
 boolean strSuffix(char *, char *);
+boolean strPrefixLower(char *, char *);
+boolean strSuffixLower(char *, char *);
 
 void GetOptions(char **, void (*print_usage_function)(void));
 
index f751fe85be2a5e568b94c6929f3ea79fc5f3d0ee..4c484243934102774e2670d626f967495d87ef53 100644 (file)
@@ -140,6 +140,13 @@ void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
   fullscreen_xoffset = (fullscreen_width  - video.width)  / 2;
   fullscreen_yoffset = (fullscreen_height - video.height) / 2;
 
+#if 1
+  checked_free(video.fullscreen_modes);
+
+  video.fullscreen_modes = NULL;
+  video.fullscreen_mode_current = NULL;
+#endif
+
   /* get available hardware supported fullscreen modes */
   modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
 
@@ -228,7 +235,11 @@ void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
      should never be drawn to directly, it would do no harm nevertheless. */
 
   /* create additional (symbolic) buffer for double-buffering */
+#if 1
+  ReCreateBitmap(window, video.width, video.height, video.depth);
+#else
   *window = CreateBitmap(video.width, video.height, video.depth);
+#endif
 }
 
 boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
@@ -241,6 +252,10 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
   if (*backbuffer == NULL)
     *backbuffer = CreateBitmapStruct();
 
+  /* (real bitmap might be larger in fullscreen mode with video offsets) */
+  (*backbuffer)->width  = video.width;
+  (*backbuffer)->height = video.height;
+
   if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
   {
     setFullscreenParameters(setup.fullscreen_mode);
@@ -292,11 +307,11 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
       (*backbuffer)->surface = new_surface;
 
       video.fullscreen_enabled = FALSE;
+
       success = TRUE;
     }
   }
 
-
 #if 1
   SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
 
@@ -423,6 +438,17 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
   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);
+
+    initialization_needed = TRUE;
+  }
+
   src_rect.x = src_x;
   src_rect.y = src_y;
   src_rect.w = width;
index 3e5392498dbdb63474df4b3e75b19c22488452d5..b7e34adf1b3d2ab8267102e7cb48731f9d9be03d 100644 (file)
@@ -412,6 +412,19 @@ char *getSolutionTapeFilename(int nr)
   sprintf(basename, "%03d.%s", nr, TAPEFILE_EXTENSION);
   filename = getPath2(getSolutionTapeDir(), basename);
 
+  if (!fileExists(filename))
+  {
+    static char *filename_sln = NULL;
+
+    checked_free(filename_sln);
+
+    sprintf(basename, "%03d.sln", nr);
+    filename_sln = getPath2(getSolutionTapeDir(), basename);
+
+    if (fileExists(filename_sln))
+      return filename_sln;
+  }
+
   return filename;
 }
 
@@ -1410,21 +1423,41 @@ static int posix_mkdir(const char *pathname, mode_t mode)
 #endif
 }
 
+static boolean posix_process_running_setgid()
+{
+#if defined(PLATFORM_UNIX)
+  return (getgid() != getegid());
+#else
+  return FALSE;
+#endif
+}
+
 void createDirectory(char *dir, char *text, int permission_class)
 {
   /* 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 ?
                     DIR_PERMS_PRIVATE : DIR_PERMS_PUBLIC);
-  mode_t normal_umask = posix_umask(0);
+  mode_t last_umask = posix_umask(0);
   mode_t group_umask = ~(dir_mode & S_IRWXG);
-  posix_umask(normal_umask & group_umask);
+  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 (running_setgid)
+    posix_umask(last_umask & group_umask);
+  else
+    dir_mode |= MODE_W_ALL;
 
   if (!fileExists(dir))
     if (posix_mkdir(dir, dir_mode) != 0)
       Error(ERR_WARN, "cannot create %s directory '%s'", text, dir);
 
-  posix_umask(normal_umask);           /* reset normal umask */
+  if (permission_class == PERMS_PUBLIC && !running_setgid)
+    chmod(dir, dir_mode);
+
+  posix_umask(last_umask);             /* restore previous umask */
 }
 
 void InitUserDataDirectory()
@@ -1434,8 +1467,14 @@ void InitUserDataDirectory()
 
 void SetFilePermissions(char *filename, int permission_class)
 {
-  chmod(filename, (permission_class == PERMS_PRIVATE ?
-                  FILE_PERMS_PRIVATE : FILE_PERMS_PUBLIC));
+  int running_setgid = posix_process_running_setgid();
+  int perms = (permission_class == PERMS_PRIVATE ?
+              FILE_PERMS_PRIVATE : FILE_PERMS_PUBLIC);
+
+  if (permission_class == PERMS_PUBLIC && !running_setgid)
+    perms |= MODE_W_ALL;
+
+  chmod(filename, perms);
 }
 
 char *getCookie(char *file_type)
@@ -1616,7 +1655,7 @@ DEFINE_HASHTABLE_REMOVE(remove_hash_entry, char, char);
 #define remove_hash_entry hashtable_remove
 #endif
 
-static unsigned int get_hash_from_key(void *key)
+unsigned int get_hash_from_key(void *key)
 {
   /*
     djb2
@@ -2375,10 +2414,11 @@ void checkSetupFileHashIdentifier(SetupFileHash *setup_file_hash,
 #define LEVELINFO_TOKEN_MUSIC_SET              18
 #define LEVELINFO_TOKEN_FILENAME               19
 #define LEVELINFO_TOKEN_FILETYPE               20
-#define LEVELINFO_TOKEN_HANDICAP               21
-#define LEVELINFO_TOKEN_SKIP_LEVELS            22
+#define LEVELINFO_TOKEN_SPECIAL_FLAGS          21
+#define LEVELINFO_TOKEN_HANDICAP               22
+#define LEVELINFO_TOKEN_SKIP_LEVELS            23
 
-#define NUM_LEVELINFO_TOKENS                   23
+#define NUM_LEVELINFO_TOKENS                   24
 
 static LevelDirTree ldi;
 
@@ -2406,6 +2446,7 @@ static struct TokenInfo levelinfo_tokens[] =
   { TYPE_STRING,       &ldi.music_set,         "music_set"             },
   { TYPE_STRING,       &ldi.level_filename,    "filename"              },
   { TYPE_STRING,       &ldi.level_filetype,    "filetype"              },
+  { TYPE_STRING,       &ldi.special_flags,     "special_flags"         },
   { TYPE_BOOLEAN,      &ldi.handicap,          "handicap"              },
   { TYPE_BOOLEAN,      &ldi.skip_levels,       "skip_levels"           }
 };
@@ -2482,6 +2523,8 @@ static void setTreeInfoToDefaults(TreeInfo *ti, int type)
     ti->level_filename = NULL;
     ti->level_filetype = NULL;
 
+    ti->special_flags = NULL;
+
     ti->levels = 0;
     ti->first_level = 0;
     ti->last_level = 0;
@@ -2553,12 +2596,18 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ti, TreeInfo *parent)
     ti->level_filename = NULL;
     ti->level_filetype = NULL;
 
+    ti->special_flags = getStringCopy(parent->special_flags);
+
     ti->levels = 0;
     ti->first_level = 0;
     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;
   }
@@ -2604,6 +2653,8 @@ static TreeInfo *getTreeInfoCopy(TreeInfo *ti)
   ti_copy->level_filename      = getStringCopy(ti->level_filename);
   ti_copy->level_filetype      = getStringCopy(ti->level_filetype);
 
+  ti_copy->special_flags       = getStringCopy(ti->special_flags);
+
   ti_copy->levels              = ti->levels;
   ti_copy->first_level         = ti->first_level;
   ti_copy->last_level          = ti->last_level;
@@ -2665,6 +2716,8 @@ static void freeTreeInfo(TreeInfo *ti)
 
     checked_free(ti->level_filename);
     checked_free(ti->level_filetype);
+
+    checked_free(ti->special_flags);
   }
 
   checked_free(ti);
@@ -2840,14 +2893,18 @@ static char *getCacheToken(char *prefix, char *suffix)
   return token;
 }
 
-static char *getFileTimestamp(char *filename)
+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)
@@ -2964,8 +3021,8 @@ static void setArtworkInfoCacheEntry(TreeInfo *artwork_info,
                                        LEVELINFO_FILENAME);
     char *filename_artworkinfo = getPath2(getSetupArtworkDir(artwork_info),
                                          ARTWORKINFO_FILENAME(type));
-    char *timestamp_levelinfo = getFileTimestamp(filename_levelinfo);
-    char *timestamp_artworkinfo = getFileTimestamp(filename_artworkinfo);
+    char *timestamp_levelinfo = getFileTimestampString(filename_levelinfo);
+    char *timestamp_artworkinfo = getFileTimestampString(filename_artworkinfo);
 
     token_main = getCacheToken(token_prefix, "TIMESTAMP_LEVELINFO");
     setHashEntry(artworkinfo_cache_new, token_main, timestamp_levelinfo);
@@ -3084,6 +3141,12 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
   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 &&
index 414cf74e7ad2db66db009756387c0d644f68bbce..b0b6a8d2dfbc998fda2d1f85082a7caed3d0f412 100644 (file)
@@ -306,6 +306,8 @@ void setSetupInfo(struct TokenInfo *, int, char *);
 char *getSetupValue(int, void *);
 char *getSetupLine(struct TokenInfo *, char *, int);
 
+unsigned int get_hash_from_key(void *);
+
 boolean AdjustGraphicsForEMC();
 
 void LoadLevelInfo(void);
diff --git a/src/libgame/snapshot.c b/src/libgame/snapshot.c
new file mode 100644 (file)
index 0000000..d28ae34
--- /dev/null
@@ -0,0 +1,55 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1995-2006 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* snapshot.c                                               *
+***********************************************************/
+
+#include "snapshot.h"
+
+
+static ListNode *engine_snapshot_list = NULL;
+
+void SaveEngineSnapshotBuffer(void *buffer, int size)
+{
+  struct EngineSnapshotNodeInfo *bi =
+    checked_calloc(sizeof(struct EngineSnapshotNodeInfo));
+
+  bi->buffer_orig = buffer;
+  bi->buffer_copy = checked_malloc(size);
+  bi->size = size;
+
+  memcpy(bi->buffer_copy, buffer, size);
+
+  addNodeToList(&engine_snapshot_list, NULL, bi);
+}
+
+static void LoadEngineSnapshotBuffer(struct EngineSnapshotNodeInfo *bi)
+{
+  memcpy(bi->buffer_orig, bi->buffer_copy, bi->size);
+}
+
+void LoadEngineSnapshotBuffers()
+{
+  ListNode *node = engine_snapshot_list;
+
+  while (node != NULL)
+  {
+    LoadEngineSnapshotBuffer((struct EngineSnapshotNodeInfo *)node->content);
+
+    node = node->next;
+  }
+}
+
+void FreeEngineSnapshotBuffers()
+{
+  while (engine_snapshot_list != NULL)
+    deleteNodeFromList(&engine_snapshot_list, engine_snapshot_list->key,
+                      checked_free);
+}
diff --git a/src/libgame/snapshot.h b/src/libgame/snapshot.h
new file mode 100644 (file)
index 0000000..706fc05
--- /dev/null
@@ -0,0 +1,36 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1995-2006 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* snapshot.h                                               *
+***********************************************************/
+
+#ifndef SNAPSHOT_H
+#define SNAPSHOT_H
+
+#include "system.h"
+#include "misc.h"
+
+
+/* needed for comfortably saving engine snapshot buffers */
+#define ARGS_ADDRESS_AND_SIZEOF(x)             (&(x)), (sizeof(x))
+
+struct EngineSnapshotNodeInfo
+{
+  void *buffer_orig;
+  void *buffer_copy;
+  int size;
+};
+
+
+void SaveEngineSnapshotBuffer(void *buffer, int size);
+void LoadEngineSnapshotBuffers();
+void FreeEngineSnapshotBuffers();
+
+#endif /* SNAPSHOT_H */
index d4b7f9a92b7b5147f38f93eca7ad7e028bb6b7f8..4b7a3cad7a238069e30d6f60bf345ce23e59e41e 100644 (file)
@@ -166,8 +166,10 @@ 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 */
@@ -193,6 +195,12 @@ void InitGfxWindowInfo(int win_xsize, int 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)
@@ -203,6 +211,15 @@ void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height)
   gfx.scrollbuffer_height = scrollbuffer_height;
 }
 
+void InitGfxClipRegion(boolean enabled, int x, int y, int width, int height)
+{
+  gfx.clipping_enabled = enabled;
+  gfx.clip_x = x;
+  gfx.clip_y = y;
+  gfx.clip_width = width;
+  gfx.clip_height = height;
+}
+
 void InitGfxDrawBusyAnimFunction(void (*draw_busy_anim_function)(void))
 {
   gfx.draw_busy_anim_function = draw_busy_anim_function;
@@ -259,9 +276,11 @@ 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;
@@ -367,8 +386,10 @@ void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
 
   video.fullscreen_available = FULLSCREEN_STATUS;
   video.fullscreen_enabled = FALSE;
-  video.fullscreen_modes = NULL;
+#if 0
   video.fullscreen_mode_current = NULL;
+  video.fullscreen_modes = NULL;
+#endif
 
 #if defined(TARGET_SDL)
   SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
@@ -379,34 +400,6 @@ void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
   drawto = backbuffer;
 }
 
-Bitmap *CreateBitmapStruct(void)
-{
-#if defined(TARGET_SDL)
-  return checked_calloc(sizeof(struct SDLSurfaceInfo));
-#else
-  return checked_calloc(sizeof(struct X11DrawableInfo));
-#endif
-}
-
-Bitmap *CreateBitmap(int width, int height, int depth)
-{
-  Bitmap *new_bitmap = CreateBitmapStruct();
-  int real_width  = MAX(1, width);     /* prevent zero bitmap width */
-  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;
-
-  return new_bitmap;
-}
-
 inline static void FreeBitmapPointers(Bitmap *bitmap)
 {
   if (bitmap == NULL)
@@ -443,16 +436,53 @@ void FreeBitmap(Bitmap *bitmap)
   free(bitmap);
 }
 
-void CloseWindow(DrawWindow *window)
+Bitmap *CreateBitmapStruct(void)
 {
-#if defined(TARGET_X11)
-  if (window->drawable)
+#if defined(TARGET_SDL)
+  return checked_calloc(sizeof(struct SDLSurfaceInfo));
+#else
+  return checked_calloc(sizeof(struct X11DrawableInfo));
+#endif
+}
+
+Bitmap *CreateBitmap(int width, int height, int depth)
+{
+  Bitmap *new_bitmap = CreateBitmapStruct();
+  int real_width  = MAX(1, width);     /* prevent zero bitmap width */
+  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;
+
+  return new_bitmap;
+}
+
+void ReCreateBitmap(Bitmap **bitmap, int width, int height, int depth)
+{
+  Bitmap *new_bitmap = CreateBitmap(width, height, depth);
+
+  if (*bitmap == NULL)
   {
-    XUnmapWindow(display, window->drawable);
-    XDestroyWindow(display, window->drawable);
+    *bitmap = new_bitmap;
   }
-  if (window->gc)
-    XFreeGC(display, window->gc);
+  else
+  {
+    TransferBitmapPointers(new_bitmap, *bitmap);
+    free(new_bitmap);
+  }
+}
+
+void CloseWindow(DrawWindow *window)
+{
+#if defined(TARGET_X11)
+  X11CloseWindow(window);
 #endif
 }
 
@@ -491,13 +521,133 @@ boolean DrawingOnBackground(int x, int y)
          CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
 }
 
+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 */
+  {
+    clip_x = MIN(MAX(0, gfx.clip_x), bitmap->width);
+    clip_y = MIN(MAX(0, gfx.clip_y), bitmap->height);
+    clip_width = MIN(MAX(0, gfx.clip_width), bitmap->width - clip_x);
+    clip_height = MIN(MAX(0, gfx.clip_height), bitmap->height - clip_y);
+  }
+  else
+  {
+    clip_x = 0;
+    clip_y = 0;
+    clip_width = bitmap->width;
+    clip_height = bitmap->height;
+  }
+
+  /* skip if rectangle completely outside bitmap */
+
+  if (*x + *width  <= clip_x ||
+      *y + *height <= clip_y ||
+      *x >= clip_x + clip_width ||
+      *y >= clip_y + clip_height)
+    return FALSE;
+
+  /* clip if rectangle overlaps bitmap */
+
+  if (*x < clip_x)
+  {
+    *width -= clip_x - *x;
+    *x = clip_x;
+  }
+  else if (*x + *width > clip_x + clip_width)
+  {
+    *width = clip_x + clip_width - *x;
+  }
+
+  if (*y < clip_y)
+  {
+    *height -= clip_y - *y;
+    *y = clip_y;
+  }
+  else if (*y + *height > clip_y + clip_height)
+  {
+    *height = clip_y + clip_height - *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,
                int src_x, int src_y, int width, int height,
                int dst_x, int dst_y)
 {
+  int dst_x_unclipped = dst_x;
+  int dst_y_unclipped = dst_y;
+
   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;
+
+  /* source x/y might need adjustment if destination x/y was clipped top/left */
+  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
   /* !!! 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,
@@ -559,6 +709,12 @@ void FadeRectangle(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))
 {
+#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);
@@ -574,6 +730,22 @@ 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);
 }
 
index aa1057fd956f6b7066acc3c893333ae2b35fed60..cbcf5c86ae4d24abcdbb66d561b17d22fd1f9ed5 100644 (file)
 #define DEFAULT_KEY_FOCUS_PLAYER_3     KSYM_F7
 #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_STOP          KSYM_UNDEFINED
+#define DEFAULT_KEY_TAPE_PAUSE         KSYM_UNDEFINED
+#define DEFAULT_KEY_TAPE_RECORD                KSYM_UNDEFINED
+#define DEFAULT_KEY_TAPE_PLAY          KSYM_UNDEFINED
+#define DEFAULT_KEY_SOUND_SIMPLE       KSYM_UNDEFINED
+#define DEFAULT_KEY_SOUND_LOOPS                KSYM_UNDEFINED
+#define DEFAULT_KEY_SOUND_MUSIC                KSYM_UNDEFINED
 
 /* values for key_status */
 #define KEY_NOT_PRESSED                        FALSE
 
 #define ANIM_DEFAULT           ANIM_LOOP
 
+/* values for special drawing styles (currently only for crumbled graphics) */
+#define STYLE_NONE             0
+#define STYLE_ACCURATE_BORDERS (1 << 0)
+#define STYLE_INNER_CORNERS    (1 << 1)
+
+#define STYLE_DEFAULT          STYLE_NONE
+
 /* values for fade mode */
 #define FADE_TYPE_NONE         0
 #define FADE_TYPE_FADE_IN      (1 << 0)
@@ -650,8 +665,11 @@ struct OptionInfo
   char *sounds_directory;
   char *music_directory;
   char *docs_directory;
+
   char *execute_command;
 
+  char *special_flags;
+
   boolean serveronly;
   boolean network;
   boolean verbose;
@@ -736,6 +754,10 @@ struct GfxInfo
   Bitmap *background_bitmap;
   int background_bitmap_mask;
 
+  boolean clipping_enabled;
+  int clip_x, clip_y;
+  int clip_width, clip_height;
+
   boolean override_level_graphics;
   boolean override_level_sounds;
   boolean override_level_music;
@@ -831,6 +853,16 @@ struct SetupShortcutInfo
 
   Key focus_player[MAX_PLAYERS];
   Key focus_player_all;
+
+  Key tape_eject;
+  Key tape_stop;
+  Key tape_pause;
+  Key tape_record;
+  Key tape_play;
+
+  Key sound_simple;
+  Key sound_loops;
+  Key sound_music;
 };
 
 struct SetupSystemInfo
@@ -868,6 +900,7 @@ struct SetupInfo
   boolean input_on_focus;
   boolean prefer_aga_graphics;
   int game_frame_delay;
+  boolean sp_show_border_elements;
 
   char *graphics_set;
   char *sounds_set;
@@ -922,6 +955,8 @@ struct TreeInfo
   char *level_filename;        /* filename of level file (for packed level file) */
   char *level_filetype;        /* type of levels in level directory or level file */
 
+  char *special_flags; /* flags for special actions performed on level file */
+
   int levels;          /* number of levels in level series */
   int first_level;     /* first level number (to allow start with 0 or 1) */
   int last_level;      /* last level number (automatically calculated) */
@@ -1077,6 +1112,13 @@ struct Rect
   int width, height;
 };
 
+struct RectWithBorder
+{
+  int x, y;
+  int width, height;
+  int border_size;
+};
+
 struct MenuPosInfo
 {
   int x, y;
@@ -1148,6 +1190,7 @@ void InitGfxDoor1Info(int, int, int, int);
 void InitGfxDoor2Info(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 InitGfxCustomArtworkInfo();
 void SetDrawDeactivationMask(int);
@@ -1161,6 +1204,7 @@ void CloseVideoDisplay(void);
 void InitVideoBuffer(int, int, int, boolean);
 Bitmap *CreateBitmapStruct(void);
 Bitmap *CreateBitmap(int, int, int);
+void ReCreateBitmap(Bitmap **, int, 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,
index f0cdb01adaecedd75fb3325b440ba40dd840b1dd..23de7cac548849a90e4c395a35391e9b0b1fb640 100644 (file)
@@ -188,6 +188,22 @@ void getFontCharSource(int font_nr, char c, Bitmap **bitmap, int *x, int *y)
 }
 
 
+/* ========================================================================= */
+/* text string helper functions                                              */
+/* ========================================================================= */
+
+int maxWordLengthInString(char *text)
+{
+  char *text_ptr;
+  int max_word_len = 0;
+
+  for (text_ptr = text; *text_ptr; text_ptr++)
+    max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
+
+  return max_word_len;
+}
+
+
 /* ========================================================================= */
 /* simple text drawing functions                                             */
 /* ========================================================================= */
@@ -728,7 +744,8 @@ static boolean getCheckedTokenValueFromString(char *string, char **token,
 }
 
 static void DrawTextBuffer_Flush(int x, int y, char *buffer, int font_nr,
-                                int line_length, int cut_length, int mask_mode,
+                                int line_length, int cut_length,
+                                int line_spacing, int mask_mode,
                                 boolean centered, int current_line)
 {
   int buffer_len = strlen(buffer);
@@ -739,7 +756,7 @@ static void DrawTextBuffer_Flush(int x, int y, char *buffer, int font_nr,
     (centered ? font_width * (line_length - buffer_len) / 2 : 0);
   int final_cut_length = MAX(0, cut_length - offset_chars);
   int xx = x + offset_xsize;
-  int yy = y + current_line * font_height;
+  int yy = y + current_line * (font_height + line_spacing);
 
   buffer[final_cut_length] = '\0';
 
@@ -751,8 +768,8 @@ static void DrawTextBuffer_Flush(int x, int y, char *buffer, int font_nr,
 
 int DrawTextBuffer(int x, int y, char *text_buffer, int font_nr,
                   int line_length, int cut_length, int max_lines,
-                  int mask_mode, boolean autowrap, boolean centered,
-                  boolean parse_comments)
+                  int line_spacing, int mask_mode, boolean autowrap,
+                  boolean centered, boolean parse_comments)
 {
 #if 0
   int font_width = getFontWidth(font_nr);
@@ -808,7 +825,7 @@ int DrawTextBuffer(int x, int y, char *text_buffer, int font_nr,
        if (buffer_len > 0 && current_line < max_lines)
        {
          DrawTextBuffer_Flush(x, y, buffer, font_nr, line_length, cut_length,
-                              mask_mode, centered, current_line);
+                              line_spacing, mask_mode, centered, current_line);
 
          current_line++;
 
@@ -876,7 +893,7 @@ int DrawTextBuffer(int x, int y, char *text_buffer, int font_nr,
       {
 #if 1
        DrawTextBuffer_Flush(x, y, buffer, font_nr, line_length, cut_length,
-                            mask_mode, centered, current_line);
+                            line_spacing, mask_mode, centered, current_line);
 #else
        int offset_chars = (centered ? (line_length - buffer_len) / 2 : 0);
        int offset_xsize =
@@ -907,7 +924,7 @@ int DrawTextBuffer(int x, int y, char *text_buffer, int font_nr,
   {
 #if 1
     DrawTextBuffer_Flush(x, y, buffer, font_nr, line_length, cut_length,
-                        mask_mode, centered, current_line);
+                        line_spacing, mask_mode, centered, current_line);
 #else
     int offset_chars = (centered ? (line_length - buffer_len) / 2 : 0);
        int offset_xsize =
@@ -932,14 +949,14 @@ int DrawTextBuffer(int x, int y, char *text_buffer, int font_nr,
 
 int DrawTextFile(int x, int y, char *filename, int font_nr,
                 int line_length, int cut_length, int max_lines,
-                int mask_mode, boolean autowrap, boolean centered,
-                boolean parse_comments)
+                int line_spacing, int mask_mode, boolean autowrap,
+                boolean centered, boolean parse_comments)
 {
   char *text_buffer = GetTextBufferFromFile(filename, MAX_LINES_FROM_FILE);
   int num_lines_printed = DrawTextBuffer(x, y, text_buffer, font_nr,
                                         line_length, cut_length, max_lines,
-                                        mask_mode, autowrap, centered,
-                                        parse_comments);
+                                        line_spacing, mask_mode, autowrap,
+                                        centered, parse_comments);
   checked_free(text_buffer);
 
   return num_lines_printed;
index 146648a311febdce38fcad7249dc607ce96c74ce..1d54a716d22d64b47eae590f88b9ed39a35cafea 100644 (file)
@@ -73,6 +73,8 @@ int getTextWidth(char *, int);
 
 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);
@@ -87,9 +89,9 @@ void DrawText(int, int, char *, int);
 void DrawTextExt(DrawBuffer *, int, int, char *, int, int);
 
 char *GetTextBufferFromFile(char *, int);
-int DrawTextBuffer(int, int, char *, int, int, int, int, int, boolean, boolean,
-                  boolean);
-int DrawTextFile(int, int, char *, int, int, int, int, int, boolean, boolean,
-                boolean);
+int DrawTextBuffer(int, int, char *, int, int, int, int, int, int,
+                  boolean, boolean, boolean);
+int DrawTextFile(int, int, char *, int, int, int, int, int, int,
+                boolean, boolean, boolean);
 
 #endif /* TEXT_H */
index d6f49bdd68026c47a6557575f8eb15ad2e8c1d86..6e55364cb9ddd40945865a5eda9cbd262324c8ac 100644 (file)
@@ -58,6 +58,14 @@ typedef unsigned char byte;
 #define SIGN(a)                ((a) < 0 ? -1 : ((a) > 0 ? 1 : 0))
 #endif
 
+#ifndef ODD
+#define ODD(a)         (((a) & 1) == 1)
+#endif
+
+#ifndef EVEN
+#define EVEN(a)                (((a) & 1) == 0)
+#endif
+
 #define SIZEOF_ARRAY(array, type)      (sizeof(array) / sizeof(type))
 #define SIZEOF_ARRAY_INT(array)                SIZEOF_ARRAY(array, int)
 
index fe022c5bf3f8ddb1f50d9d8c7b776c4f7694894b..f95c3da99e479ff9ce400a5b9fad1725d18c3dc7 100644 (file)
@@ -40,13 +40,21 @@ void X11InitVideoDisplay(void)
 
 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()
@@ -129,6 +137,9 @@ static DrawWindow *X11InitWindow()
   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,
@@ -227,6 +238,20 @@ static DrawWindow *X11InitWindow()
   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)
index 2ebaf86ca00d883c0e8bda78c77ce98d049b0070..9f2efee8b44470fe7a03fc8c5c23a869a5372ac2 100644 (file)
@@ -333,6 +333,8 @@ struct MouseCursorInfo
 void X11InitVideoDisplay(void);
 void X11InitVideoBuffer(DrawBuffer **, DrawWindow **);
 
+void X11CloseWindow(DrawWindow *);
+
 void X11ZoomBitmap(Bitmap *, Bitmap *);
 Bitmap *X11LoadImage(char *);
 
index f1ea104e361ad855d33dc45b9977f49fb2bac73f..d5dbe91c9d35f12f3f20d6b745c11bf60785d86c 100644 (file)
@@ -20,6 +20,7 @@
 #include "events.h"
 #include "config.h"
 
+Bitmap                *bitmap_db_store;
 Bitmap                *bitmap_db_cross;
 Bitmap                *bitmap_db_field;
 Bitmap                *bitmap_db_panel;
@@ -39,7 +40,11 @@ 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];
@@ -84,15 +89,33 @@ 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                    REAL_SX = 6, REAL_SY = 6;
+int                    DX = 566, DY = 60;
+int                    VX = 566, VY = 400;
+int                    EX = 566, EY = 356;
+int                    dDX, dDY;
+
+#if 1
+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                    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;
@@ -112,6 +135,7 @@ struct SetupInfo    setup;
 struct GameInfo                game;
 struct GlobalInfo      global;
 struct BorderInfo      border;
+struct ViewportInfo    viewport;
 struct TitleFadingInfo fading;
 struct TitleFadingInfo title_initial_default;
 struct TitleFadingInfo title_default;
@@ -120,7 +144,7 @@ struct TitleMessageInfo     titlemessage_initial[MAX_NUM_TITLE_MESSAGES];
 struct TitleMessageInfo        titlemessage_default;
 struct TitleMessageInfo        titlemessage[MAX_NUM_TITLE_MESSAGES];
 struct TitleMessageInfo        readme;
-struct InitInfo                init;
+struct InitInfo                init, init_last;
 struct MenuInfo                menu;
 struct DoorInfo                door_1, door_2;
 struct PreviewInfo     preview;
@@ -1262,23 +1286,23 @@ struct ElementNameInfo element_name_info[MAX_NUM_ELEMENTS + 1] =
   },
   {
     "sp_gravity_port_right",
-    "sp_port",
-    "gravity port (leading right)"
+    "sp_gravity_port",
+    "gravity-on/off port (leading right)"
   },
   {
     "sp_gravity_port_down",
-    "sp_port",
-    "gravity port (leading down)"
+    "sp_gravity_port",
+    "gravity-on/off port (leading down)"
   },
   {
     "sp_gravity_port_left",
-    "sp_port",
-    "gravity port (leading left)"
+    "sp_gravity_port",
+    "gravity-on/off port (leading left)"
   },
   {
     "sp_gravity_port_up",
-    "sp_port",
-    "gravity port (leading up)"
+    "sp_gravity_port",
+    "gravity-on/off port (leading up)"
   },
   {
     "sp_sniksnak",
@@ -3442,43 +3466,43 @@ struct ElementNameInfo element_name_info[MAX_NUM_ELEMENTS + 1] =
   },
   {
     "sp_gravity_on_port_right",
-    "sp_port",
-    "gravity on port (leading right)"
+    "sp_gravity_on_port",
+    "gravity-on port (leading right)"
   },
   {
     "sp_gravity_on_port_down",
-    "sp_port",
-    "gravity on port (leading down)"
+    "sp_gravity_on_port",
+    "gravity-on port (leading down)"
   },
   {
     "sp_gravity_on_port_left",
-    "sp_port",
-    "gravity on port (leading left)"
+    "sp_gravity_on_port",
+    "gravity-on port (leading left)"
   },
   {
     "sp_gravity_on_port_up",
-    "sp_port",
-    "gravity on port (leading up)"
+    "sp_gravity_on_port",
+    "gravity-on port (leading up)"
   },
   {
     "sp_gravity_off_port_right",
-    "sp_port",
-    "gravity off port (leading right)"
+    "sp_gravity_off_port",
+    "gravity-off port (leading right)"
   },
   {
     "sp_gravity_off_port_down",
-    "sp_port",
-    "gravity off port (leading down)"
+    "sp_gravity_off_port",
+    "gravity-off port (leading down)"
   },
   {
     "sp_gravity_off_port_left",
-    "sp_port",
-    "gravity off port (leading left)"
+    "sp_gravity_off_port",
+    "gravity-off port (leading left)"
   },
   {
     "sp_gravity_off_port_up",
-    "sp_port",
-    "gravity off port (leading up)"
+    "sp_gravity_off_port",
+    "gravity-off port (leading up)"
   },
   {
     "balloon_switch_none",
@@ -4460,6 +4484,11 @@ struct ElementNameInfo element_name_info[MAX_NUM_ELEMENTS + 1] =
     "quicksand",
     "fast quicksand (with rock)"
   },
+  {
+    "from_level_template",
+    "from_level_template",
+    "element taken from level template"
+  },
 
   /* ----------------------------------------------------------------------- */
   /* "real" (and therefore drawable) runtime elements                        */
index 68f1eed082c22ec8b93d9b9e902c93f65ca9849d..0933b06470633fc74a3e888c0a12ab90540d7b2a 100644 (file)
 
 #include "libgame/libgame.h"
 #include "game_em/game_em.h"
+#include "game_sp/game_sp.h"
 
 #include "conf_gfx.h"  /* include auto-generated data structure definitions */
 #include "conf_snd.h"  /* include auto-generated data structure definitions */
 #include "conf_mus.h"  /* include auto-generated data structure definitions */
 
+
 #define IMG_UNDEFINED                  (-1)
 #define IMG_EMPTY                      IMG_EMPTY_SPACE
-#define IMG_SP_EMPTY                   IMG_SP_EMPTY_SPACE
+#define IMG_SP_EMPTY                   IMG_EMPTY_SPACE
+#define IMG_SP_EMPTY_SPACE             IMG_EMPTY_SPACE
 #define IMG_EXPLOSION                  IMG_DEFAULT_EXPLODING
 #define IMG_CHAR_START                 IMG_CHAR_SPACE
 #define IMG_STEEL_CHAR_START           IMG_STEEL_CHAR_SPACE
 #define SND_UNDEFINED                  (-1)
 #define MUS_UNDEFINED                  (-1)
 
+#if 0
 #define WIN_XSIZE                      672
 #define WIN_YSIZE                      560
+#endif
 
 #define DEFAULT_FULLSCREEN_MODE                "800x600"
 
+#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
 #define MAX_INITIAL_INVENTORY_SIZE     8
 
 /* often used screen positions */
+#if 0
 #define SX                     8
 #define SY                     8
 #define REAL_SX                        (SX - 2)
 #define VY                     400
 #define EX                     DX
 #define EY                     (VY - 44)
+#endif
 #define TILESIZE               32
 #define TILEX                  TILESIZE
 #define TILEY                  TILESIZE
 #define EL_QUICKSAND_FAST_EMPTY                861
 #define EL_QUICKSAND_FAST_FULL         862
 
-#define NUM_FILE_ELEMENTS              863
+#define EL_FROM_LEVEL_TEMPLATE         863
+
+#define NUM_FILE_ELEMENTS              864
 
 
 /* "real" (and therefore drawable) runtime elements */
 #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_1      7
-#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_2      8
-#define GFX_SPECIAL_ARG_SETUP_CHOOSE_ARTWORK   9
-#define GFX_SPECIAL_ARG_SETUP_CHOOSE_OTHER     10
+#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 NUM_SPECIAL_GFX_SETUP_ARGS             11
+#define NUM_SPECIAL_GFX_SETUP_ARGS             14
 
 
 /* values for image configuration suffixes */
 #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                   46
+#define NUM_GFX_ARGS                   48
 
 
 /* values for sound configuration suffixes */
 
 /* program information and versioning definitions */
 #define PROGRAM_VERSION_MAJOR          3
-#define PROGRAM_VERSION_MINOR          2
-#define PROGRAM_VERSION_PATCH          6
-#define PROGRAM_VERSION_BUILD          1
+#define PROGRAM_VERSION_MINOR          3
+#define PROGRAM_VERSION_PATCH          0
+#define PROGRAM_VERSION_BUILD          0
 
 #define PROGRAM_TITLE_STRING           "Rocks'n'Diamonds"
 #define PROGRAM_AUTHOR_STRING          "Holger Schemel"
-#define PROGRAM_COPYRIGHT_STRING       "Copyright ©1995-2008 by Holger Schemel"
+#define PROGRAM_COPYRIGHT_STRING       "Copyright ©1995-2010 by Holger Schemel"
 #define PROGRAM_EMAIL_STRING           "info@artsoft.org"
 #define PROGRAM_WEBSITE_STRING         "http://www.artsoft.org/"
 #define PROGRAM_GAME_BY_STRING         "A Game by Artsoft Entertainment"
 #define GAME_ENGINE_TYPE_UNKNOWN       LEVEL_FILE_TYPE_UNKNOWN
 #define GAME_ENGINE_TYPE_RND           LEVEL_FILE_TYPE_RND
 #define GAME_ENGINE_TYPE_EM            LEVEL_FILE_TYPE_EM
+#define GAME_ENGINE_TYPE_SP            LEVEL_FILE_TYPE_SP
 
-#define NUM_ENGINE_TYPES               3
+#define NUM_ENGINE_TYPES               4
 
 
 struct BorderInfo
@@ -2240,6 +2257,14 @@ struct PreviewInfo
   int anim_mode;
 };
 
+struct ViewportInfo
+{
+  struct RectWithBorder window;
+  struct RectWithBorder playfield[NUM_SPECIAL_GFX_ARGS];
+  struct RectWithBorder door_1[NUM_SPECIAL_GFX_ARGS];
+  struct RectWithBorder door_2[NUM_SPECIAL_GFX_ARGS];
+};
+
 struct HiScore
 {
   char Name[MAX_PLAYER_NAME_LEN + 1];
@@ -2281,6 +2306,12 @@ struct DateInfo
   int year;
   int month;
   int day;
+
+  enum
+  {
+    DATE_SRC_CLOCK,
+    DATE_SRC_LEVELFILE
+  } src;
 };
 
 struct LevelInfo
@@ -2291,6 +2322,7 @@ struct LevelInfo
 
   /* level stored in native format for the alternative native game engines */
   struct LevelInfo_EM *native_em_level;
+  struct LevelInfo_SP *native_sp_level;
 
   int file_version;    /* file format version the level is stored with    */
   int game_version;    /* game release version the level was created with */
@@ -2383,6 +2415,7 @@ struct LevelInfo
   boolean shifted_relocation;  /* no level centering when relocating player */
   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 */
 
   boolean continuous_snapping; /* repeated snapping without releasing key */
   boolean block_snap_field;    /* snapping blocks field to show animation */
@@ -2680,6 +2713,9 @@ struct GraphicInfo
   int align, valign;           /* optional setting for drawing title screens */
   int sort_priority;           /* optional setting for drawing title screens */
 
+  int class;
+  int style;
+
   boolean use_image_size;      /* use image size as default width and height */
 
 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
@@ -2756,6 +2792,7 @@ struct HelpAnimInfo
 };
 
 
+extern Bitmap                 *bitmap_db_store;
 extern Bitmap                 *bitmap_db_cross;
 extern Bitmap                 *bitmap_db_field;
 extern Bitmap                 *bitmap_db_panel;
@@ -2776,7 +2813,11 @@ 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];
@@ -2821,6 +2862,15 @@ extern int                       ActiveFont[NUM_FONTS];
 extern int                     lev_fieldx, lev_fieldy;
 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                     DX, DY;
+extern int                     VX, VY;
+extern int                     EX, EY;
+extern int                     dDX, dDY;
+
 extern int                     FX, FY;
 extern int                     ScrollStepSize;
 extern int                     ScreenMovDir, ScreenMovPos, ScreenGfxPos;
@@ -2847,6 +2897,7 @@ extern struct HiScore             highscore[];
 extern struct TapeInfo         tape;
 extern struct GlobalInfo       global;
 extern struct BorderInfo       border;
+extern struct ViewportInfo     viewport;
 extern struct TitleFadingInfo  fading;
 extern struct TitleFadingInfo  fading_none;
 extern struct TitleFadingInfo  title_initial_default;
@@ -2856,7 +2907,7 @@ extern struct TitleMessageInfo    titlemessage_initial[];
 extern struct TitleMessageInfo titlemessage_default;
 extern struct TitleMessageInfo titlemessage[];
 extern struct TitleMessageInfo readme;
-extern struct InitInfo         init;
+extern struct InitInfo         init, init_last;
 extern struct MenuInfo         menu;
 extern struct DoorInfo         door_1, door_2;
 extern struct PreviewInfo      preview;
index 60bba4561f390f7af8f3bc768ca9bcf12b8d9ef8..db347cdaa88e55ca0c28a2ce531b74fb2e7ef08c 100644 (file)
 #define SETUP_MODE_SOUND               4
 #define SETUP_MODE_ARTWORK             5
 #define SETUP_MODE_INPUT               6
-#define SETUP_MODE_SHORTCUTS_1         7
-#define SETUP_MODE_SHORTCUTS_2         8
+#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
 
 /* sub-screens on the setup screen (generic) */
-#define SETUP_MODE_CHOOSE_ARTWORK      9
-#define SETUP_MODE_CHOOSE_OTHER                10
+#define SETUP_MODE_CHOOSE_ARTWORK      12
+#define SETUP_MODE_CHOOSE_OTHER                13
 
 /* sub-screens on the setup screen (specific) */
-#define SETUP_MODE_CHOOSE_GAME_SPEED   11
-#define SETUP_MODE_CHOOSE_SCREEN_MODE  12
-#define SETUP_MODE_CHOOSE_SCROLL_DELAY 13
-#define SETUP_MODE_CHOOSE_GRAPHICS     14
-#define SETUP_MODE_CHOOSE_SOUNDS       15
-#define SETUP_MODE_CHOOSE_MUSIC                16
+#define SETUP_MODE_CHOOSE_GAME_SPEED   14
+#define SETUP_MODE_CHOOSE_SCREEN_MODE  15
+#define SETUP_MODE_CHOOSE_SCROLL_DELAY 16
+#define SETUP_MODE_CHOOSE_GRAPHICS     17
+#define SETUP_MODE_CHOOSE_SOUNDS       18
+#define SETUP_MODE_CHOOSE_MUSIC                19
 
-#define MAX_SETUP_MODES                        17
+#define MAX_SETUP_MODES                        20
 
 /* for input setup functions */
 #define SETUPINPUT_SCREEN_POS_START    0
@@ -232,7 +235,7 @@ static struct
                                 INFO_MODE_MAIN)
 
 #define DRAW_MODE_SETUP(i)     ((i) >= SETUP_MODE_MAIN &&              \
-                                (i) <= SETUP_MODE_SHORTCUTS_2 ? (i) :  \
+                                (i) <= SETUP_MODE_SHORTCUTS_4 ? (i) :  \
                                 (i) >= SETUP_MODE_CHOOSE_GRAPHICS &&   \
                                 (i) <= SETUP_MODE_CHOOSE_MUSIC ?       \
                                 SETUP_MODE_CHOOSE_ARTWORK :            \
@@ -757,10 +760,12 @@ 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);
 
   /* sort title screens according to sort_priority and title number */
@@ -1020,7 +1025,11 @@ static boolean insideTextPosRect(struct TextPosInfo *rect, int x, int y)
 
 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);
 
@@ -1181,7 +1190,7 @@ void DrawTitleScreenMessage(int nr, boolean initial)
   ClearRectangleOnBackground(drawto, 0, 0, WIN_XSIZE, WIN_YSIZE);
 
   DrawTextFile(ALIGNED_TEXT_XPOS(tmi), ALIGNED_TEXT_YPOS(tmi),
-              filename, tmi->font, tmi->chars, -1, tmi->lines, -1,
+              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 */
@@ -1261,6 +1270,8 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading)
   /* store valid level series information */
   leveldir_last_valid = leveldir_current;
 
+  init_last = init;                    /* switch to new busy animation */
+
   /* needed if last screen (level choice) changed graphics, sounds or music */
   ReloadCustomArtwork(0);
 
@@ -1278,6 +1289,11 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading)
 #endif
 #endif
 
+#if 1
+  /* needed if different viewport properties defined for menues */
+  ChangeViewportPropertiesIfNeeded();
+#endif
+
 #if defined(TARGET_SDL)
   SetDrawtoField(DRAW_BACKBUFFER);
 #endif
@@ -1375,7 +1391,7 @@ void DrawMainMenu()
   DrawMainMenuExt(REDRAW_ALL, FALSE);
 }
 
-#if 0
+#if defined(CREATE_SPECIAL_EDITION_RND_JUE)
 static void gotoTopLevelDir()
 {
   /* move upwards to top level directory */
@@ -1742,7 +1758,7 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
          SaveLevelSetup_LastSeries();
          SaveLevelSetup_SeriesInfo();
 
-#if 0
+#if defined(CREATE_SPECIAL_EDITION_RND_JUE)
          gotoTopLevelDir();
 #endif
 
@@ -1765,6 +1781,11 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
 
        FadeSetEnterScreen();
 
+#if 0
+       /* needed if different viewport properties defined for editor */
+       ChangeViewportPropertiesIfNeeded();
+#endif
+
        DrawLevelEd();
       }
       else if (pos == MAIN_CONTROL_INFO)
@@ -2235,7 +2256,7 @@ void DrawInfoScreen_HelpText(int element, int action, int direction, int ypos)
     sy += getFontHeight(font_nr) / 2;
 
   DrawTextBuffer(sx, sy + ypos * ystep, text, font_nr,
-                max_chars_per_line, -1, max_lines_per_text, -1,
+                max_chars_per_line, -1, max_lines_per_text, 0, -1,
                 TRUE, FALSE, FALSE);
 }
 
@@ -2637,8 +2658,15 @@ static void DrawInfoScreen_CreditsScreen(int screen_nr)
                      "Thanks to");
     DrawTextSCentered(ystart2 + 1 * ystep, FONT_TEXT_3,
                      "David Tritscher");
+#if 1
+    DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_2,
+                     "for the code base used for the");
+    DrawTextSCentered(ystart2 + 3 * ystep, FONT_TEXT_2,
+                     "native Emerald Mine engine");
+#else
     DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_2,
                      "for the new Emerald Mine engine");
+#endif
   }
   else if (screen_nr == 7)
   {
@@ -3032,7 +3060,7 @@ void DrawInfoScreen_LevelSet()
 
   if (filename != NULL)
     DrawTextFile(mSX + ALIGNED_TEXT_XPOS(tmi), mSY + ALIGNED_TEXT_YPOS(tmi),
-                filename, tmi->font, tmi->chars, -1, tmi->lines, -1,
+                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,
@@ -4072,6 +4100,13 @@ static void execSetupInput()
   DrawSetupScreen();
 }
 
+static void execSetupShortcuts()
+{
+  setup_mode = SETUP_MODE_SHORTCUTS;
+
+  DrawSetupScreen();
+}
+
 static void execSetupShortcuts1()
 {
   setup_mode = SETUP_MODE_SHORTCUTS_1;
@@ -4086,6 +4121,20 @@ static void execSetupShortcuts2()
   DrawSetupScreen();
 }
 
+static void execSetupShortcuts3()
+{
+  setup_mode = SETUP_MODE_SHORTCUTS_3;
+
+  DrawSetupScreen();
+}
+
+static void execSetupShortcuts4()
+{
+  setup_mode = SETUP_MODE_SHORTCUTS_4;
+
+  DrawSetupScreen();
+}
+
 static void execExitSetup()
 {
   game_status = GAME_MODE_MAIN;
@@ -4107,8 +4156,7 @@ static struct TokenInfo setup_info_main[] =
   { TYPE_ENTER_MENU,   execSetupSound,         "Sound & Music"         },
   { TYPE_ENTER_MENU,   execSetupArtwork,       "Custom Artwork"        },
   { TYPE_ENTER_MENU,   execSetupInput,         "Input Devices"         },
-  { TYPE_ENTER_MENU,   execSetupShortcuts1,    "Key Shortcuts 1"       },
-  { TYPE_ENTER_MENU,   execSetupShortcuts2,    "Key Shortcuts 2"       },
+  { TYPE_ENTER_MENU,   execSetupShortcuts,     "Key Shortcuts"         },
   { TYPE_EMPTY,                NULL,                   ""                      },
   { TYPE_LEAVE_MENU,   execExitSetup,          "Exit"                  },
   { TYPE_LEAVE_MENU,   execSaveAndExitSetup,   "Save and Exit"         },
@@ -4184,6 +4232,7 @@ static struct TokenInfo setup_info_graphics[] =
   { TYPE_SWITCH,       &setup.show_titlescreen,"Show Title Screens:"   },
   { TYPE_SWITCH,       &setup.toons,           "Show Toons:"           },
   { TYPE_ECS_AGA,      &setup.prefer_aga_graphics,"EMC graphics preference:" },
+  { TYPE_SWITCH, &setup.sp_show_border_elements,"Supaplex Border Elements:" },
   { TYPE_EMPTY,                NULL,                   ""                      },
   { TYPE_LEAVE_MENU,   execSetupMain,          "Back"                  },
 
@@ -4253,6 +4302,18 @@ static struct TokenInfo setup_info_input[] =
   { 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_EMPTY,                NULL,                   ""                      },
+  { TYPE_LEAVE_MENU,   execSetupMain,          "Back"                  },
+
+  { 0,                 NULL,                   NULL                    }
+};
+
 static struct TokenInfo setup_info_shortcuts_1[] =
 {
   { TYPE_KEYTEXT,      NULL,           "Quick Save Game to Tape:",     },
@@ -4265,7 +4326,7 @@ static struct TokenInfo setup_info_shortcuts_1[] =
   { TYPE_YES_NO,       &setup.ask_on_escape,   "Ask on 'Esc' Key:"     },
   { TYPE_YES_NO, &setup.ask_on_escape_editor,  "Ask on 'Esc' Key (Editor):" },
   { TYPE_EMPTY,                NULL,                   ""                      },
-  { TYPE_LEAVE_MENU,   execSetupMain,          "Back"                  },
+  { TYPE_LEAVE_MENU,   execSetupShortcuts,     "Back"                  },
 
   { 0,                 NULL,                   NULL                    }
 };
@@ -4283,7 +4344,39 @@ static struct TokenInfo setup_info_shortcuts_2[] =
   { TYPE_KEYTEXT,      NULL,           "Set Focus to All Players:",    },
   { TYPE_KEY,          &setup.shortcut.focus_player_all, ""            },
   { TYPE_EMPTY,                NULL,                   ""                      },
-  { TYPE_LEAVE_MENU,   execSetupMain,          "Back"                  },
+  { TYPE_LEAVE_MENU,   execSetupShortcuts,     "Back"                  },
+
+  { 0,                 NULL,                   NULL                    }
+};
+
+static struct TokenInfo setup_info_shortcuts_3[] =
+{
+  { TYPE_KEYTEXT,      NULL,                   "Tape Eject:",          },
+  { TYPE_KEY,          &setup.shortcut.tape_eject, ""                  },
+  { TYPE_KEYTEXT,      NULL,                   "Tape Stop:",           },
+  { TYPE_KEY,          &setup.shortcut.tape_stop, ""                   },
+  { TYPE_KEYTEXT,      NULL,                   "Tape Pause:",          },
+  { TYPE_KEY,          &setup.shortcut.tape_pause, ""                  },
+  { TYPE_KEYTEXT,      NULL,                   "Tape Record:",         },
+  { TYPE_KEY,          &setup.shortcut.tape_record, ""                 },
+  { TYPE_KEYTEXT,      NULL,                   "Tape Play:",           },
+  { TYPE_KEY,          &setup.shortcut.tape_play, ""                   },
+  { TYPE_EMPTY,                NULL,                   ""                      },
+  { TYPE_LEAVE_MENU,   execSetupShortcuts,     "Back"                  },
+
+  { 0,                 NULL,                   NULL                    }
+};
+
+static struct TokenInfo setup_info_shortcuts_4[] =
+{
+  { TYPE_KEYTEXT,      NULL,           "Sound Effects (Normal):",      },
+  { TYPE_KEY,          &setup.shortcut.sound_simple, ""                },
+  { TYPE_KEYTEXT,      NULL,           "Sound Effects (Looping):",     },
+  { TYPE_KEY,          &setup.shortcut.sound_loops, ""                 },
+  { TYPE_KEYTEXT,      NULL,           "Music:",                       },
+  { TYPE_KEY,          &setup.shortcut.sound_music, ""                 },
+  { TYPE_EMPTY,                NULL,                   ""                      },
+  { TYPE_LEAVE_MENU,   execSetupShortcuts,     "Back"                  },
 
   { 0,                 NULL,                   NULL                    }
 };
@@ -4566,6 +4659,11 @@ static void DrawSetupScreen_Generic()
     setup_info = setup_info_artwork;
     title_string = "Custom Artwork";
   }
+  else if (setup_mode == SETUP_MODE_SHORTCUTS)
+  {
+    setup_info = setup_info_shortcuts;
+    title_string = "Setup Shortcuts";
+  }
   else if (setup_mode == SETUP_MODE_SHORTCUTS_1)
   {
     setup_info = setup_info_shortcuts_1;
@@ -4576,6 +4674,16 @@ static void DrawSetupScreen_Generic()
     setup_info = setup_info_shortcuts_2;
     title_string = "Setup Shortcuts";
   }
+  else if (setup_mode == SETUP_MODE_SHORTCUTS_3)
+  {
+    setup_info = setup_info_shortcuts_3;
+    title_string = "Setup Shortcuts";
+  }
+  else if (setup_mode == SETUP_MODE_SHORTCUTS_4)
+  {
+    setup_info = setup_info_shortcuts_4;
+    title_string = "Setup Shortcuts";
+  }
 
   DrawTextSCentered(mSY - SY + 16, FONT_TITLE_1, title_string);
 
@@ -5574,13 +5682,21 @@ 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"
   }
@@ -5606,8 +5722,13 @@ static struct
 #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"
@@ -5673,6 +5794,12 @@ static void CreateScreenScrollbuttons()
   unsigned long event_mask;
   int i;
 
+  /* these values are not constant, but can change at runtime */
+  scrollbutton_info[0].x = SC_SCROLL_UP_XPOS;
+  scrollbutton_info[0].y = SC_SCROLL_UP_YPOS;
+  scrollbutton_info[1].x = SC_SCROLL_DOWN_XPOS;
+  scrollbutton_info[1].y = SC_SCROLL_DOWN_YPOS;
+
   for (i = 0; i < NUM_SCREEN_SCROLLBUTTONS; i++)
   {
     Bitmap *gd_bitmap_unpressed, *gd_bitmap_pressed;
@@ -5728,6 +5855,12 @@ static void CreateScreenScrollbars()
 {
   int i;
 
+  /* these values are not constant, but can change at runtime */
+  scrollbar_info[0].x = SC_SCROLL_VERTICAL_XPOS;
+  scrollbar_info[0].y = SC_SCROLL_VERTICAL_YPOS;
+  scrollbar_info[0].width  = SC_SCROLL_VERTICAL_XSIZE;
+  scrollbar_info[0].height = SC_SCROLL_VERTICAL_YSIZE;
+
   for (i = 0; i < NUM_SCREEN_SCROLLBARS; i++)
   {
     Bitmap *gd_bitmap_unpressed, *gd_bitmap_pressed;
index 49f06aa32272c5f77c13e0de6584d78411a23561..5c90cb416d074b931f45df93e919b24fdf1b268d 100644 (file)
@@ -410,6 +410,12 @@ void DrawVideoDisplay(unsigned long state, unsigned long value)
 
 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
+
   BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
             DOOR_GFX_PAGEX3, DOOR_GFX_PAGEY2,
             gfx.vxsize, gfx.vysize, gfx.vx, gfx.vy);
@@ -420,11 +426,38 @@ void DrawCompleteVideoDisplay()
             gfx.vx + VIDEO_CONTROL_XPOS, gfx.vy + VIDEO_CONTROL_YPOS);
 
   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);
+
+    if (tape.pausing)
+      DrawVideoDisplay(VIDEO_STATE_PAUSE_ON, 0);
+  }
+  else if (tape.playing)
+  {
+    DrawVideoDisplay(VIDEO_STATE_PLAY_ON, 0);
+    DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
+    DrawVideoDisplay(VIDEO_STATE_TIME_ON, 0);
+
+    if (tape.pausing)
+      DrawVideoDisplay(VIDEO_STATE_PAUSE_ON, 0);
+  }
+  else if (tape.date && tape.length)
+  {
+    DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
+    DrawVideoDisplay(VIDEO_STATE_TIME_ON, tape.length_seconds);
+  }
+#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);
@@ -453,20 +486,25 @@ void TapeDeactivateDisplayOff(boolean redraw_display)
 /* tape control functions                                                    */
 /* ========================================================================= */
 
-static void TapeSetDate()
+void TapeSetDateFromEpochSeconds(time_t epoch_seconds)
 {
-  time_t epoch_seconds = time(NULL);
-  struct tm *now = localtime(&epoch_seconds);
+  struct tm *lt = localtime(&epoch_seconds);
 
-  tape.date = 10000 * (now->tm_year % 100) + 100 * now->tm_mon + now->tm_mday;
+  tape.date = 10000 * (lt->tm_year % 100) + 100 * lt->tm_mon + lt->tm_mday;
+}
+
+void TapeSetDateFromNow()
+{
+  TapeSetDateFromEpochSeconds(time(NULL));
 }
 
 void TapeErase()
 {
   int i;
 
-  tape.length = 0;
   tape.counter = 0;
+  tape.length = 0;
+  tape.length_seconds = 0;
 
   if (leveldir_current)
     setString(&tape.level_identifier, leveldir_current->identifier);
@@ -481,7 +519,7 @@ void TapeErase()
   tape.game_version = GAME_VERSION_ACTUAL;
   tape.engine_version = level.game_version;
 
-  TapeSetDate();
+  TapeSetDateFromNow();
 
   for (i = 0; i < MAX_PLAYERS; i++)
     tape.player_participates[i] = FALSE;
@@ -530,6 +568,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);
+
   MapTapeWarpButton();
 
   SetDrawDeactivationMask(REDRAW_NONE);
@@ -562,7 +601,7 @@ static void TapeAppendRecording()
   tape.recording = TRUE;
   tape.changed = TRUE;
 
-  TapeSetDate();
+  TapeSetDateFromNow();
 
   DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
   DrawVideoDisplay(VIDEO_STATE_PLAY_OFF | VIDEO_STATE_REC_ON, 0);
@@ -703,6 +742,7 @@ void TapeStartPlaying()
   DrawVideoDisplay(VIDEO_STATE_PLAY_ON, 0);
   DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
   DrawVideoDisplay(VIDEO_STATE_TIME_ON, 0);
+
   MapTapeWarpButton();
 
   SetDrawDeactivationMask(REDRAW_NONE);
@@ -1295,10 +1335,8 @@ void UnmapTapeButtons()
     UnmapGadget(tape_gadget[i]);
 }
 
-static void HandleTapeButtons(struct GadgetInfo *gi)
+static void HandleTapeButtonsExt(int id)
 {
-  int id = gi->custom_id;
-
   if (game_status != GAME_MODE_MAIN && game_status != GAME_MODE_PLAYING)
     return;
 
@@ -1403,3 +1441,24 @@ static void HandleTapeButtons(struct GadgetInfo *gi)
       break;
   }
 }
+
+static void HandleTapeButtons(struct GadgetInfo *gi)
+{
+  HandleTapeButtonsExt(gi->custom_id);
+}
+
+void HandleTapeButtonKeys(Key key)
+{
+  boolean use_extra = (tape.recording || tape.playing);
+
+  if (key == setup.shortcut.tape_eject)
+    HandleTapeButtonsExt(use_extra ? TAPE_CTRL_ID_EXTRA : TAPE_CTRL_ID_EJECT);
+  else if (key == setup.shortcut.tape_stop)
+    HandleTapeButtonsExt(TAPE_CTRL_ID_STOP);
+  else if (key == setup.shortcut.tape_pause)
+    HandleTapeButtonsExt(TAPE_CTRL_ID_PAUSE);
+  else if (key == setup.shortcut.tape_record)
+    HandleTapeButtonsExt(TAPE_CTRL_ID_RECORD);
+  else if (key == setup.shortcut.tape_play)
+    HandleTapeButtonsExt(TAPE_CTRL_ID_PLAY);
+}
index fe636495df8b07380d58bb0fe4ce6c775ddb3023..cafa235d41170fc46ad4191df5a0509510b17172 100644 (file)
@@ -138,6 +138,9 @@ void DrawCompleteVideoDisplay(void);
 void TapeDeactivateDisplayOn();
 void TapeDeactivateDisplayOff(boolean);
 
+void TapeSetDateFromEpochSeconds(time_t);
+void TapeSetDateFromNow();
+
 void TapeStartRecording(long);
 void TapeHaltRecording(void);
 void TapeStopRecording(void);
@@ -162,4 +165,6 @@ void MapTapeWarpButton();
 void MapTapeButtons();
 void UnmapTapeButtons();
 
+void HandleTapeButtonKeys(Key);
+
 #endif
index e80cd9967eb6c6acfd8e603e3c3fe0e87bf7c6f2..c26996b6720fef0ee85581256e04de8eb3322ad7 100644 (file)
@@ -14,6 +14,7 @@
 #include "libgame/libgame.h"
 
 #include "tools.h"
+#include "init.h"
 #include "game.h"
 #include "events.h"
 #include "cartoons.h"
@@ -144,7 +145,17 @@ void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
     /* blit playfield from scroll buffer to normal back buffer for fading in */
     BlitScreenToBitmap_EM(backbuffer);
   }
-  else if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
+  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)
     {
@@ -338,6 +349,10 @@ void BackToFront()
 
   if (redraw_mask & REDRAW_FIELD)
   {
+#if 0
+    printf("::: REDRAW_FIELD\n");
+#endif
+
     if (game_status != GAME_MODE_PLAYING ||
        redraw_mask & REDRAW_FROM_BACKBUFFER)
     {
@@ -420,6 +435,10 @@ void BackToFront()
 
   if (redraw_mask & REDRAW_TILES)
   {
+#if 0
+    printf("::: REDRAW_TILES\n");
+#endif
+
     for (x = 0; x < SCR_FIELDX; x++)
       for (y = 0 ; y < SCR_FIELDY; y++)
        if (redraw[redraw_x1 + x][redraw_y1 + y])
@@ -1232,14 +1251,43 @@ inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
   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;
-  int sync_frame = (dx ? ABS(dx) : ABS(dy)) * anim_frames / TILESIZE;
+#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))
   {
@@ -1403,14 +1451,205 @@ void DrawLevelFieldThruMask(int x, int y)
                             (e) == EL_QUICKSAND_EMPTYING ||            \
                             (e) == EL_QUICKSAND_FAST_EMPTYING))
 
-static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
+static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy,
+                                              int graphic)
 {
   Bitmap *src_bitmap;
   int src_x, src_y;
+  int width, height, cx, cy;
   int sx = SCREENX(x), sy = SCREENY(y);
-  int element;
-  int width, height, cx, cy, i;
   int crumbled_border_size = graphic_info[graphic].border_size;
+  int i;
+
+  getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
+
+  for (i = 1; i < 4; i++)
+  {
+    int dxx = (i & 1 ? dx : 0);
+    int dyy = (i & 2 ? dy : 0);
+    int xx = x + dxx;
+    int yy = y + dyy;
+    int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
+                  BorderElement);
+
+    /* check if neighbour field is of same crumble type */
+    boolean same = (IS_CRUMBLED_TILE(xx, yy, element) &&
+                   graphic_info[graphic].class ==
+                   graphic_info[el_act2crm(element, ACTION_DEFAULT)].class);
+
+    /* return if check prevents inner corner */
+    if (same == (dxx == dx && dyy == dy))
+      return;
+  }
+
+  /* if we reach this point, we have an inner corner */
+
+  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);
+
+  BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+            width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
+}
+
+static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
+                                         int dir)
+{
+  Bitmap *src_bitmap;
+  int src_x, src_y;
+  int width, height, bx, by, cx, cy;
+  int sx = SCREENX(x), sy = SCREENY(y);
+  int crumbled_border_size = graphic_info[graphic].border_size;
+  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
+
+  BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+            width, height, FX + sx * TILEX + cx, FY + sy * TILEY + 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)
+    return;
+
+  /* correct corners of crumbled border, if needed */
+
+#if 1
+  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);
+    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 */
+
+      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);
+
+      width  = crumbled_border_size;
+      height = crumbled_border_size;
+
+      if (dir == 1 || dir == 2)
+      {
+       cx = c1;
+       cy = c2;
+       bx = cx;
+       by = b1;
+      }
+      else
+      {
+       cx = c2;
+       cy = c1;
+       bx = b1;
+       by = cy;
+      }
+
+      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);
+      }
+    }
+  }
+#endif
+}
+
+static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
+{
+  int sx = SCREENX(x), sy = SCREENY(y);
+  int element;
+  int i;
   static int xy[4][2] =
   {
     { 0, -1 },
@@ -1425,17 +1664,11 @@ static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
   element = TILE_GFX_ELEMENT(x, y);
 
   /* crumble field itself */
-#if 1
   if (IS_CRUMBLED_TILE(x, y, element))
-#else
-  if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
-#endif
   {
     if (!IN_SCR_FIELD(sx, sy))
       return;
 
-    getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
-
     for (i = 0; i < 4; i++)
     {
       int xx = x + xy[i][0];
@@ -1444,37 +1677,35 @@ static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
       element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
                 BorderElement);
 
-      /* check if neighbour field is of same type */
+      /* check if neighbour field is of same crumble type */
 #if 1
-      if (IS_CRUMBLED_TILE(xx, yy, element))
+      if (IS_CRUMBLED_TILE(xx, yy, element) &&
+         graphic_info[graphic].class ==
+         graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
        continue;
 #else
-      if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
+      if (IS_CRUMBLED_TILE(xx, yy, element))
        continue;
 #endif
 
-      if (i == 1 || i == 2)
-      {
-       width = crumbled_border_size;
-       height = TILEY;
-       cx = (i == 2 ? TILEX - crumbled_border_size : 0);
-       cy = 0;
-      }
-      else
+      DrawLevelFieldCrumbledBorders(x, y, graphic, frame, i);
+    }
+
+    if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
+       graphic_info[graphic].anim_frames == 2)
+    {
+      for (i = 0; i < 4; i++)
       {
-       width = TILEX;
-       height = crumbled_border_size;
-       cx = 0;
-       cy = (i == 3 ? TILEY - crumbled_border_size : 0);
-      }
+       int dx = (i & 1 ? +1 : -1);
+       int dy = (i & 2 ? +1 : -1);
 
-      BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
-                width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
+       DrawLevelFieldCrumbledInnerCorners(x, y, dx, dy, graphic);
+      }
     }
 
     MarkTileDirty(sx, sy);
   }
-  else         /* crumble neighbour fields */
+  else         /* center field not crumbled -- crumble neighbour fields */
   {
     for (i = 0; i < 4; i++)
     {
@@ -1483,59 +1714,28 @@ static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
       int sxx = sx + xy[i][0];
       int syy = sy + xy[i][1];
 
-#if 1
       if (!IN_LEV_FIELD(xx, yy) ||
          !IN_SCR_FIELD(sxx, syy))
        continue;
-#else
-      if (!IN_LEV_FIELD(xx, yy) ||
-         !IN_SCR_FIELD(sxx, syy) ||
-         IS_MOVING(xx, yy))
-       continue;
-#endif
 
       if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
        continue;
 
       element = TILE_GFX_ELEMENT(xx, yy);
 
-#if 1
       if (!IS_CRUMBLED_TILE(xx, yy, element))
        continue;
-#else
-      if (!GFX_CRUMBLED(element))
-       continue;
-#endif
 
       graphic = el_act2crm(element, ACTION_DEFAULT);
-      crumbled_border_size = graphic_info[graphic].border_size;
 
-      getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
-
-      if (i == 1 || i == 2)
-      {
-       width = crumbled_border_size;
-       height = TILEY;
-       cx = (i == 1 ? TILEX - crumbled_border_size : 0);
-       cy = 0;
-      }
-      else
-      {
-       width = TILEX;
-       height = crumbled_border_size;
-       cx = 0;
-       cy = (i == 0 ? TILEY - crumbled_border_size : 0);
-      }
-
-      BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
-                width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
+      DrawLevelFieldCrumbledBorders(xx, yy, graphic, 0, 3 - i);
 
       MarkTileDirty(sxx, syy);
     }
   }
 }
 
-void DrawLevelFieldCrumbledSand(int x, int y)
+void DrawLevelFieldCrumbled(int x, int y)
 {
   int graphic;
 
@@ -1554,7 +1754,7 @@ void DrawLevelFieldCrumbledSand(int x, int y)
       GfxElement[x][y] != EL_UNDEFINED &&
       GFX_CRUMBLED(GfxElement[x][y]))
   {
-    DrawLevelFieldCrumbledSandDigging(x, y, GfxDir[x][y], GfxFrame[x][y]);
+    DrawLevelFieldCrumbledDigging(x, y, GfxDir[x][y], GfxFrame[x][y]);
 
     return;
   }
@@ -1566,11 +1766,11 @@ void DrawLevelFieldCrumbledSand(int x, int y)
   graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
 #endif
 
-  DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
+  DrawLevelFieldCrumbledExt(x, y, graphic, 0);
 }
 
-void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
-                                      int step_frame)
+void DrawLevelFieldCrumbledDigging(int x, int y, int direction,
+                                  int step_frame)
 {
   int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
   int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
@@ -1579,10 +1779,10 @@ void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
   int sx = SCREENX(x), sy = SCREENY(y);
 
   DrawGraphic(sx, sy, graphic1, frame1);
-  DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
+  DrawLevelFieldCrumbledExt(x, y, graphic2, frame2);
 }
 
-void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
+void DrawLevelFieldCrumbledNeighbours(int x, int y)
 {
   int sx = SCREENX(x), sy = SCREENY(y);
   static int xy[4][2] =
@@ -1637,7 +1837,7 @@ static int getBorderElement(int x, int y)
 void DrawScreenElement(int x, int y, int element)
 {
   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
-  DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
+  DrawLevelFieldCrumbled(LEVELX(x), LEVELY(y));
 }
 
 void DrawLevelElement(int x, int y, int element)
@@ -1899,7 +2099,7 @@ void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
 #if 1
     DrawTextBuffer(SX + sx + font_width, SY + sy + font_height,
                   level.envelope[envelope_nr].text, font_nr, max_xsize,
-                  xsize - 2, ysize - 2, mask_mode,
+                  xsize - 2, ysize - 2, 0, mask_mode,
                   level.envelope[envelope_nr].autowrap,
                   level.envelope[envelope_nr].centered, FALSE);
 #else
@@ -1915,6 +2115,182 @@ void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
   }
 }
 
+void AnimateEnvelopeDoor(char *text, int anim_mode, int action)
+{
+#if 1
+  int envelope_nr = 0;
+#endif
+  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);
+  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;
+
+#if 1
+  char *text_ptr;
+  char *text_copy = getStringCopy(text);
+#else
+#if 1
+  font_nr = FONT_TEXT_2;
+
+  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);
+
+  font_nr = FONT_TEXT_2;
+
+  for (text_ptr = text; *text_ptr; text_ptr++)
+  {
+    max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
+
+    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;
+
+      break;
+    }
+  }
+#endif
+#endif
+
+#if 1
+  for (text_ptr = text_copy; *text_ptr; text_ptr++)
+    if (*text_ptr == ' ')
+      *text_ptr = '\n';
+#endif
+
+#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
+
+  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;
+
+#if 1
+    BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+#else
+    SetDrawtoField(DRAW_BUFFERED);
+
+    BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
+
+    SetDrawtoField(DRAW_BACKBUFFER);
+#endif
+
+    for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
+      DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
+
+#if 1
+
+#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
+
+#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
+
+    /* 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 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 1
+    DoAnimation();
+    BackToFront();
+#else
+    BackToFront();
+#endif
+
+    WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
+  }
+
+#if 1
+  free(text_copy);
+#endif
+}
+
 void ShowEnvelope(int envelope_nr)
 {
   int element = EL_ENVELOPE_1 + envelope_nr;
@@ -1931,32 +2307,150 @@ void ShowEnvelope(int envelope_nr)
 
   game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
 
-  PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
+  PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
+
+  if (anim_mode == ANIM_DEFAULT)
+    AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
+
+  AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
+
+  if (tape.playing)
+    Delay(wait_delay_value);
+  else
+    WaitForEventToContinue();
+
+  PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
+
+  if (anim_mode != ANIM_NONE)
+    AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
+
+  if (anim_mode == ANIM_DEFAULT)
+    AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
+
+  game.envelope_active = FALSE;
+
+  SetDrawtoField(DRAW_BUFFERED);
+
+  redraw_mask |= REDRAW_FIELD;
+  BackToFront();
+}
+
+void ShowEnvelopeDoor(char *text, 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
+  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);
+
+#if 1
+  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);
+    else
+    {
+      BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
+    }
+  }
+
+  SetDrawtoField(DRAW_BACKBUFFER);
+
+  // SetDrawBackgroundMask(REDRAW_NONE);
+
+  if (action == ACTION_OPENING)
+  {
+    BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+
+    if (game_status != GAME_MODE_MAIN)
+      InitAnimation();
+  }
+
+  /* force DOOR font inside door area */
+  game_status = GAME_MODE_PSEUDO_DOOR;
+#endif
+
+  game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
+
+  if (action == ACTION_OPENING)
+  {
+    PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
 
-  if (anim_mode == ANIM_DEFAULT)
-    AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
+    if (anim_mode == ANIM_DEFAULT)
+      AnimateEnvelopeDoor(text, ANIM_DEFAULT, ACTION_OPENING);
 
-  AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
+    AnimateEnvelopeDoor(text, main_anim_mode, ACTION_OPENING);
 
-  if (tape.playing)
-    Delay(wait_delay_value);
+#if 0
+    if (tape.playing)
+      Delay(wait_delay_value);
+    else
+      WaitForEventToContinue();
+#endif
+  }
   else
-    WaitForEventToContinue();
-
-  PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
+  {
+    PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
 
-  if (anim_mode != ANIM_NONE)
-    AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
+    if (anim_mode != ANIM_NONE)
+      AnimateEnvelopeDoor(text, main_anim_mode, ACTION_CLOSING);
 
-  if (anim_mode == ANIM_DEFAULT)
-    AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
+    if (anim_mode == ANIM_DEFAULT)
+      AnimateEnvelopeDoor(text, 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
 
+  // 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 &&
+      level.game_engine_type == GAME_ENGINE_TYPE_RND)
+    SetDrawtoField(DRAW_BUFFERED);
+#else
   BackToFront();
+#endif
 }
 
 void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
@@ -2371,10 +2865,10 @@ inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
 
 #if 1
   if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
-    DrawLevelFieldCrumbledSand(x, y);
+    DrawLevelFieldCrumbled(x, y);
 #else
   if (GFX_CRUMBLED(Feld[x][y]))
-    DrawLevelFieldCrumbledSand(x, y);
+    DrawLevelFieldCrumbled(x, y);
 #endif
 }
 
@@ -2394,7 +2888,7 @@ void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
   DrawGraphicAnimation(sx, sy, graphic);
 
   if (GFX_CRUMBLED(element))
-    DrawLevelFieldCrumbledSand(x, y);
+    DrawLevelFieldCrumbled(x, y);
 }
 
 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
@@ -2451,6 +2945,8 @@ void DrawPlayerField(int x, int y)
   DrawPlayer(PLAYERINFO(x, y));
 }
 
+#define DRAW_PLAYER_OVER_PUSHED_ELEMENT        1
+
 void DrawPlayer(struct PlayerInfo *player)
 {
   int jx = player->jx;
@@ -2564,7 +3060,7 @@ void DrawPlayer(struct PlayerInfo *player)
       int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
 
       if (GFX_CRUMBLED(old_element))
-       DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
+       DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
       else
        DrawGraphic(sx, sy, old_graphic, frame);
 
@@ -2590,6 +3086,7 @@ void DrawPlayer(struct PlayerInfo *player)
     }
   }
 
+#if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
   /* ----------------------------------------------------------------------- */
   /* draw player himself                                                     */
   /* ----------------------------------------------------------------------- */
@@ -2627,6 +3124,17 @@ void DrawPlayer(struct PlayerInfo *player)
 
     DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
   }
+#endif
+
+#if DRAW_PLAYER_OVER_PUSHED_ELEMENT
+  if (player->GfxPos)
+  {
+    if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
+      sxx = player->GfxPos;
+    else
+      syy = player->GfxPos;
+  }
+#endif
 
   /* ----------------------------------------------------------------------- */
   /* draw things the player is pushing, if needed                            */
@@ -2666,11 +3174,90 @@ void DrawPlayer(struct PlayerInfo *player)
 #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 */
+
+      if (Back[jx][jy])
+       DrawLevelElement(jx, jy, Back[jx][jy]);
+      else
+       DrawLevelElement(jx, jy, EL_EMPTY);
+
+      if (Back[next_jx][next_jy])
+       DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
+      else
+       DrawLevelElement(next_jx, next_jy, EL_EMPTY);
+    }
+    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 */
+    /* (two-tile animations usually do not contain start and end frame) */
+    if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
+      DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
+    else
+      DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
+#else
     /* masked drawing is needed for EMC style (double) movement graphics */
+    /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */
     DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
+#endif
+  }
+#endif
+
+#if DRAW_PLAYER_OVER_PUSHED_ELEMENT
+  /* ----------------------------------------------------------------------- */
+  /* draw player himself                                                     */
+  /* ----------------------------------------------------------------------- */
+
+  graphic = getPlayerGraphic(player, move_dir);
+
+  /* in the case of changed player action or direction, prevent the current
+     animation frame from being restarted for identical animations */
+  if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
+    player->Frame = last_player_frame;
+
+  frame = getGraphicAnimationFrame(graphic, player->Frame);
+
+  if (player->GfxPos)
+  {
+    if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
+      sxx = player->GfxPos;
+    else
+      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
+    DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
+
+  if (SHIELD_ON(player))
+  {
+    int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
+                  IMG_SHIELD_NORMAL_ACTIVE);
+    int frame = getGraphicAnimationFrame(graphic, -1);
+
+    DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
   }
 #endif
 
@@ -2791,9 +3378,20 @@ boolean Request(char *text, unsigned int req_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;
 
+#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);
@@ -2810,10 +3408,15 @@ boolean Request(char *text, unsigned int req_state)
       break;
     }
   }
+#endif
 
-  if (game_status == GAME_MODE_PLAYING &&
-      level.game_engine_type == GAME_ENGINE_TYPE_EM)
-    BlitScreenToBitmap_EM(backbuffer);
+  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);
+  }
 
   /* disable deactivated drawing when quick-loading level tape recording */
   if (tape.playing && tape.deactivate_display)
@@ -2837,7 +3440,11 @@ boolean Request(char *text, unsigned int req_state)
 
   UnmapAllGadgets();
 
+#if 1
+  if (old_door_state & DOOR_OPEN_1 && !use_envelope_request)
+#else
   if (old_door_state & DOOR_OPEN_1)
+#endif
   {
     CloseDoor(DOOR_CLOSE_1);
 
@@ -2860,40 +3467,49 @@ boolean Request(char *text, unsigned int req_state)
   game_status = GAME_MODE_PSEUDO_DOOR;
 
   /* write text for request */
-  for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
+  for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
   {
     char text_line[max_request_line_len + 1];
     int tx, tl, tc = 0;
 
-    if (!*text)
+    if (!*text_ptr)
       break;
 
     for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
     {
-      tc = *(text + tx);
+      tc = *(text_ptr + tx);
       if (!tc || tc == ' ')
        break;
     }
 
     if (!tl)
     { 
-      text++; 
+      text_ptr++; 
       ty--; 
       continue; 
     }
 
-    strncpy(text_line, text, tl);
+    strncpy(text_line, text_ptr, tl);
     text_line[tl] = 0;
 
     DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
             DY + 8 + ty * (getFontHeight(font_nr) + 2),
             text_line, font_nr);
 
-    text += tl + (tc == ' ' ? 1 : 0);
+    text_ptr += tl + (tc == ' ' ? 1 : 0);
   }
 
   game_status = last_game_status;      /* restore current game status */
 
+#if 1
+  if (use_envelope_request)
+  {
+    /* !!! TMP !!! */
+    FreeToolButtons();
+    CreateToolButtons();
+  }
+#endif
+
   if (req_state & REQ_ASK)
   {
     MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
@@ -2916,7 +3532,36 @@ boolean Request(char *text, unsigned int req_state)
             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;
+
+       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))
   {
@@ -2933,8 +3578,13 @@ 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;
 
@@ -3093,7 +3743,16 @@ boolean Request(char *text, unsigned int req_state)
 
   UnmapToolButtons();
 
+#if 1
+  if (use_envelope_request)
+    ShowEnvelopeDoor(text, ACTION_CLOSING);
+#endif
+
+#if 1
+  if (!(req_state & REQ_STAY_OPEN) && !use_envelope_request)
+#else
   if (!(req_state & REQ_STAY_OPEN))
+#endif
   {
     CloseDoor(DOOR_CLOSE_1);
 
@@ -5764,6 +6423,52 @@ int map_direction_EM_to_RND(int direction)
          MV_NONE);
 }
 
+int map_element_RND_to_SP(int element_rnd)
+{
+  int element_sp = 0x20;       /* map unknown elements to yellow "hardware" */
+
+  if (element_rnd >= EL_SP_START &&
+      element_rnd <= EL_SP_END)
+    element_sp = element_rnd - EL_SP_START;
+  else if (element_rnd == EL_EMPTY_SPACE)
+    element_sp = 0x00;
+  else if (element_rnd == EL_INVISIBLE_WALL)
+    element_sp = 0x28;
+
+  return element_sp;
+}
+
+int map_element_SP_to_RND(int element_sp)
+{
+  int element_rnd = EL_UNKNOWN;
+
+  if (element_sp >= 0x00 &&
+      element_sp <= 0x27)
+    element_rnd = EL_SP_START + element_sp;
+  else if (element_sp == 0x28)
+    element_rnd = EL_INVISIBLE_WALL;
+
+  return element_rnd;
+}
+
+int map_action_SP_to_RND(int action_sp)
+{
+  switch (action_sp)
+  {
+    case actActive:            return ACTION_ACTIVE;
+    case actImpact:            return ACTION_IMPACT;
+    case actExploding:         return ACTION_EXPLODING;
+    case actDigging:           return ACTION_DIGGING;
+    case actSnapping:          return ACTION_SNAPPING;
+    case actCollecting:                return ACTION_COLLECTING;
+    case actPassing:           return ACTION_PASSING;
+    case actPushing:           return ACTION_PUSHING;
+    case actDropping:          return ACTION_DROPPING;
+
+    default:                   return ACTION_DEFAULT;
+  }
+}
+
 int get_next_element(int element)
 {
   switch (element)
@@ -6044,6 +6749,8 @@ unsigned int InitRND(long seed)
 {
   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
     return InitEngineRandom_EM(seed);
+  else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+    return InitEngineRandom_SP(seed);
   else
     return InitEngineRandom_RND(seed);
 }
@@ -6070,6 +6777,12 @@ 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;
     }
@@ -6147,6 +6860,11 @@ 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;
   }
 
@@ -6755,6 +7473,23 @@ void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
 #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
@@ -7597,6 +8332,51 @@ void InitGraphicInfo_EM(void)
 #endif
 }
 
+void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
+                           boolean any_player_moving)
+{
+  int i;
+
+  if (tape.single_step && tape.recording && !tape.pausing)
+  {
+    boolean active_players = FALSE;
+
+    for (i = 0; i < MAX_PLAYERS; i++)
+      if (action[i] != JOY_NO_ACTION)
+       active_players = TRUE;
+
+    if (frame == 0)
+      TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
+  }
+}
+
+void CheckSingleStepMode_SP(boolean murphy_is_moving)
+{
+  if (tape.single_step && tape.recording && !tape.pausing)
+  {
+    if (!murphy_is_moving)
+      TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
+  }
+}
+
+void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
+                        int graphic, int sync_frame, int x, int y)
+{
+  int frame = getGraphicAnimationFrame(graphic, sync_frame);
+
+  getGraphicSource(graphic, frame, &g_sp->bitmap, &g_sp->src_x, &g_sp->src_y);
+}
+
+boolean isNextAnimationFrame_SP(int graphic, int sync_frame)
+{
+  return (IS_NEXT_FRAME(sync_frame, graphic));
+}
+
+int getGraphicInfo_Delay(int graphic)
+{
+  return graphic_info[graphic].anim_delay;
+}
+
 void PlayMenuSoundExt(int sound)
 {
   if (sound == SND_UNDEFINED)
@@ -7691,30 +8471,16 @@ void ToggleFullscreenIfNeeded()
   if (!video.fullscreen_available)
     return;
 
-#if 1
   if (change_fullscreen || change_fullscreen_mode)
-#else
-  if (setup.fullscreen != video.fullscreen_enabled ||
-      setup.fullscreen_mode != video.fullscreen_mode_current)
-#endif
   {
     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 1
     if (change_fullscreen_mode)
-#else
-    if (setup.fullscreen && video.fullscreen_enabled)
-#endif
     {
       /* keep fullscreen, but change fullscreen mode (screen resolution) */
-#if 1
-      /* (this is now set in sdl.c) */
-#else
-      video.fullscreen_mode_current = setup.fullscreen_mode;
-#endif
       video.fullscreen_enabled = FALSE;                /* force new fullscreen mode */
     }
 
@@ -7736,3 +8502,81 @@ void ToggleFullscreenIfNeeded()
 #endif
   }
 }
+
+void ChangeViewportPropertiesIfNeeded()
+{
+  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;
+
+#if 0
+  /* !!! TEST ONLY !!! */
+  // InitGfxBuffers();
+  return;
+#endif
+
+  if (viewport.window.width  != WIN_XSIZE ||
+      viewport.window.height != WIN_YSIZE)
+  {
+    WIN_XSIZE = viewport.window.width;
+    WIN_YSIZE = viewport.window.height;
+
+    InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
+    InitGfxBuffers();
+
+#if 1
+    SetDrawDeactivationMask(REDRAW_NONE);
+    SetDrawBackgroundMask(REDRAW_FIELD);
+
+    // RedrawBackground();
+#endif
+  }
+
+  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)
+  {
+    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;
+
+    InitGfxBuffers();
+
+    if (gfx_game_mode == GAME_MODE_MAIN)
+    {
+      InitGadgets();
+      InitToons();
+    }
+  }
+
+#if 0
+  printf("::: %d, %d  /  %d, %d [%d]\n", VX, VY, EX, EY, game_status);
+#endif
+}
index 136a305cf948777f8c1fc0277e51175eb3176092..510524af77f4ac381be3bffb62fa56c583594786 100644 (file)
@@ -135,9 +135,9 @@ void DrawLevelElementShifted(int, int, int, int, int, int);
 void DrawScreenElementThruMask(int, int, int);
 void DrawLevelElementThruMask(int, int, int);
 void DrawLevelFieldThruMask(int, int);
-void DrawLevelFieldCrumbledSand(int, int);
-void DrawLevelFieldCrumbledSandDigging(int, int, int, int);
-void DrawLevelFieldCrumbledSandNeighbours(int, int);
+void DrawLevelFieldCrumbled(int, int);
+void DrawLevelFieldCrumbledDigging(int, int, int, int);
+void DrawLevelFieldCrumbledNeighbours(int, int);
 void DrawScreenElement(int, int, int);
 void DrawLevelElement(int, int, int);
 void DrawScreenField(int, int);
@@ -146,7 +146,8 @@ void DrawLevelField(int, int);
 void DrawMiniElement(int, int, int);
 void DrawMiniElementOrWall(int, int, int, int);
 
-void ShowEnvelope();
+void ShowEnvelope(int);
+void ShowEnvelopeDoor(char *text, int);
 
 void DrawLevel(void);
 void DrawMiniLevel(int, int, int, int);
@@ -174,6 +175,10 @@ int map_direction_EM_to_RND(int);
 void map_android_clone_elements_RND_to_EM(struct LevelInfo *);
 void map_android_clone_elements_EM_to_RND(struct LevelInfo *);
 
+int map_element_RND_to_SP(int);
+int map_element_SP_to_RND(int);
+int map_action_SP_to_RND(int);
+
 int get_next_element(int);
 int el_act_dir2img(int, int, int);
 int el_act2img(int, int);
@@ -211,5 +216,6 @@ void PlaySoundActivating();
 void PlaySoundSelecting();
 
 void ToggleFullscreenIfNeeded();
+void ChangeViewportPropertiesIfNeeded();
 
 #endif /* TOOLS_H */