+++ /dev/null
-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
-[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!
+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
+++ /dev/null
-
-[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.
-
# 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
./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
# 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
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)
# 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)
$(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"; \
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)
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
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))
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;
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
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
{ ".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 }
};
{ "[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" },
{ "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" },
{ "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" },
{ "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" },
{ "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" },
{ "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" },
{ "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" },
{ "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" },
{ "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" },
#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" },
{ "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" },
{ "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" },
{ "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 }
};
#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 */
"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]
"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]
"game.panel.time_ss.draw_order",
&game.panel.time_ss.sort_priority
},
+ {
+ "game.panel.frame.x",
+ &game.panel.frame.x
+ },
+ {
+ "game.panel.frame.y",
+ &game.panel.frame.y
+ },
+ {
+ "game.panel.frame.align",
+ &game.panel.frame.align
+ },
+ {
+ "game.panel.frame.valign",
+ &game.panel.frame.valign
+ },
+ {
+ "game.panel.frame.digits",
+ &game.panel.frame.size
+ },
+ {
+ "game.panel.frame.font",
+ &game.panel.frame.font
+ },
+ {
+ "game.panel.frame.draw_masked",
+ &game.panel.frame.draw_masked
+ },
+ {
+ "game.panel.frame.draw_order",
+ &game.panel.frame.sort_priority
+ },
{
"game.panel.shield_normal.x",
&game.panel.shield_normal.x
"game.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
"[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
-#define COMPILE_DATE_STRING "2009-06-15 22:46"
+#define COMPILE_DATE_STRING "2010-05-25 22:42"
#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
/* ---------- 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,
{
{ GAME_ENGINE_TYPE_RND, "Rocks'n'Diamonds" },
{ GAME_ENGINE_TYPE_EM, "Emerald Mine" },
+ { GAME_ENGINE_TYPE_SP, "Supaplex" },
{ -1, NULL }
};
{
{
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"
},
{
{
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,
},
{
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,
},
{
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"
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,
{
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
},
*/
/* 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;
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,
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),
(ed_fieldy * MINI_TILEY) - (dy != 0 ? MINI_TILEY : 0),
SX + (dx == +1 ? MINI_TILEX : 0),
SY + (dy == +1 ? MINI_TILEY : 0));
-#endif
if (dx)
{
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++)
{
int max_infotext_len = getMaxInfoTextLength();
int i;
+ /* these values are not constant, but can change at runtime */
+ counterbutton_info[ED_COUNTER_ID_SELECT_LEVEL].x = DX + 5 - SX;
+ counterbutton_info[ED_COUNTER_ID_SELECT_LEVEL].y = DY + 3 - SY;
+
for (i = 0; i < ED_NUM_COUNTERBUTTONS; i++)
{
int j;
{
int 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;
{
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;
/* 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();
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++)
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],
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
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();
redraw_mask |= REDRAW_ALL;
+#if 1
+ FreeLevelEditorGadgets();
+ CreateLevelEditorGadgets();
+#endif
+
ReinitializeElementList(); /* update dynamic level element list */
ReinitializeElementListButtons(); /* custom element may look different */
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()
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++)
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;
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,
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,
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;
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)
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:
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++)
#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);
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 */
{
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)
{
TapeQuickLoad();
else if (key == setup.shortcut.toggle_pause)
TapeTogglePause(TAPE_TOGGLE_MANUAL);
+
+ HandleTapeButtonKeys(key);
+ HandleSoundButtonKeys(key);
}
if (game_status == GAME_MODE_PLAYING && !network_playing)
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:
&li.score[SC_TIME_BONUS], 1
},
+ {
+ -1, -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(9),
+ &li.auto_exit_sokoban, FALSE
+ },
+
{
-1, -1,
-1, -1,
/* 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);
date.month = now->tm_mon + 1;
date.day = now->tm_mday;
+ date.src = DATE_SRC_CLOCK;
+
return date;
}
*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;
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)
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);
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];
/* 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;
}
setLevelFileInfo_FormatLevelFilename(lfi, filetype,
leveldir_current->level_filename, nr);
+
+ lfi->packed = checkForPackageFromBasename(leveldir_current->level_filename);
+
if (fileExists(lfi->filename))
return;
}
level->creation_date.month = getFile8Bit(file);
level->creation_date.day = getFile8Bit(file);
+ level->creation_date.src = DATE_SRC_LEVELFILE;
+
return chunk_size;
}
{
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;
}
}
}
-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
}
/* 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;
*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
/* ------------------------------------------------------------------------- */
-/* 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:
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];
/* 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;
Error(ERR_WARN, "unsupported version of tape file '%s'", filename);
fclose(file);
+
return;
}
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)
#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
#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
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" },
{ 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[] =
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);
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;
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;
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()
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++)
if (!music_info_listed(music_file_info, music->filename))
{
*new = get_music_file_info(music->filename, i);
+#if 0
+ if (*new != NULL)
+ printf(":1: adding '%s' ['%s'] ...\n", (*new)->title, music->filename);
+#endif
if (*new != NULL)
new = &(*new)->next;
}
if (!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;
}
void LoadLevelTemplate(int);
void SaveLevel(int);
void SaveLevelTemplate();
+void SaveNativeLevel(struct LevelInfo *);
void DumpLevel(struct LevelInfo *);
boolean SaveLevelChecked(int);
#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
{
&game.panel.time_ss,
TYPE_INTEGER,
},
+ {
+ GAME_PANEL_FRAME,
+ &game.panel.frame,
+ TYPE_INTEGER,
+ },
{
GAME_PANEL_SHIELD_NORMAL,
&game.panel.shield_normal,
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);
{
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)
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;
if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
level.native_em_level->ply[player_nr]->dynamite;
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+ game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
+ level.native_sp_level->game_sp->red_disk_count;
else
game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
stored_player[player_nr].inventory_size;
game_panel_controls[GAME_PANEL_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);
game_status = GAME_MODE_PLAYING;
+#if 1
+ /* needed if different viewport properties defined for playing */
+ ChangeViewportPropertiesIfNeeded();
+#endif
+
+#if 1
+ DrawCompleteVideoDisplay();
+#endif
+
InitGameEngine();
InitGameControlValues();
/* 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();
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 */
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;
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)
{
/* 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 ||
/* re-crumble neighbour fields, if needed */
if (element == EL_INVISIBLE_SAND)
- TEST_DrawLevelFieldCrumbledSandNeighbours(x, y);
+ TEST_DrawLevelFieldCrumbledNeighbours(x, y);
}
}
}
/* 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 ||
/* re-crumble neighbour fields, if needed */
if (element == EL_INVISIBLE_SAND)
- TEST_DrawLevelFieldCrumbledSandNeighbours(x, y);
+ TEST_DrawLevelFieldCrumbledNeighbours(x, y);
}
}
}
if (IN_SCR_FIELD(sx, sy))
{
- TEST_DrawLevelFieldCrumbledSand(xx, yy);
+ TEST_DrawLevelFieldCrumbled(xx, yy);
DrawGraphic(sx, sy, flame_graphic, frame);
}
}
{
Feld[x][y] = EL_SAND;
- TEST_DrawLevelFieldCrumbledSandNeighbours(x, y);
+ TEST_DrawLevelFieldCrumbledNeighbours(x, y);
}
else if (element == EL_QUICKSAND_FILLING)
{
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);
/* 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)
TEST_DrawLevelField(x, y);
if (GFX_CRUMBLED(new_element))
- TEST_DrawLevelFieldCrumbledSandNeighbours(x, y);
+ TEST_DrawLevelFieldCrumbledNeighbours(x, y);
}
#if 1
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 */
{
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 */
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)
{
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 */
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();
{
GameActions_EM_Main();
}
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+ {
+ GameActions_SP_Main();
+ }
else
{
GameActions_RND();
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;
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);
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);
}
}
+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)
{
/* game engine snapshot handling functions */
/* ------------------------------------------------------------------------- */
-#define ARGS_ADDRESS_AND_SIZEOF(x) (&(x)), (sizeof(x))
-
struct EngineSnapshotInfo
{
/* runtime values for custom element collect score */
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] =
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;
}
}
}
{
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;
}
}
}
-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 */
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)
#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()
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;
if (setup.sound_music)
{
setup.sound_music = FALSE;
+
FadeMusic();
}
else if (audio.music_available)
else if (audio.loops_available)
{
setup.sound = setup.sound_loops = TRUE;
+
SetAudioMode(setup.sound);
}
break;
else if (audio.sound_available)
{
setup.sound = setup.sound_simple = TRUE;
+
SetAudioMode(setup.sound);
}
break;
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
+}
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;
/* 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;
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);
void UnmapGameButtons();
void RedrawGameButtons();
+void HandleSoundButtonKeys(Key);
+
#endif
# =============================================================================
# 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
# =============================================================================
#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
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)
}
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++)
SX + x * TILEX, SY + y * TILEY);
}
}
+#endif
}
FlushDisplay();
redraw[x][y] = FALSE;
redraw_tiles = 0;
+ screen_x_last = screen_x;
+ screen_y_last = screen_y;
scrolling_last = scrolling;
}
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;
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",
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))
{
printf("::: %05d: %lu, %d\n", FrameCounter, RandomEM, frame);
#endif
+#if 0
game_animscreen();
#if 1
#endif
blitscreen();
+#endif
#endif
RandomEM = RandomEM * 129 + 1;
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 */
#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)
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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;
+}
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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 */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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
+}
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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 */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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();
+}
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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 */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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);
+}
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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 */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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);
+}
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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 */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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;
+ }
+}
+
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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 */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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);
+ // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+}
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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 */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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);
+ }
+ }
+ }
+}
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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 */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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);
+}
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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 */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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;
+ }
+}
--- /dev/null
+// ----------------------------------------------------------------------------
+// Infotrons.h
+// ----------------------------------------------------------------------------
+
+#ifndef INFOTRONS_H
+#define INFOTRONS_H
+
+#include "global.h"
+
+
+extern void subAnimateInfotrons(int);
+extern void subCleanUpForInfotronsAbove(int);
+
+#endif /* INFOTRONS_H */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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
+}
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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 */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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);
+}
--- /dev/null
+// ----------------------------------------------------------------------------
+// Input.h
+// ----------------------------------------------------------------------------
+
+#ifndef INPUT_H
+#define INPUT_H
+
+#include "global.h"
+
+
+extern void subProcessKeyboardInput(byte);
+
+#endif /* INPUT_H */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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);
+}
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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 */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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;
+}
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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 */
--- /dev/null
+# =============================================================================
+# 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
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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;
+ }
+}
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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 */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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
+}
--- /dev/null
+// ----------------------------------------------------------------------------
+// OrangeDisk.h
+// ----------------------------------------------------------------------------
+
+#ifndef ORANGEDISK_H
+#define ORANGEDISK_H
+
+#include "global.h"
+
+
+extern void subAnimateOrangeDisks(int);
+
+#endif /* ORANGEDISK_H */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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);
+ // +++++++++++++++++++++++++++++++++++++++++++++++++++++
+}
--- /dev/null
+// ----------------------------------------------------------------------------
+// SnikSnaks.h
+// ----------------------------------------------------------------------------
+
+#ifndef SNIKSNAKS_H
+#define SNIKSNAKS_H
+
+#include "global.h"
+
+
+extern void subAnimateSnikSnaks(int);
+extern void subDrawAnimatedSnikSnaks(int);
+
+#endif /* SNIKSNAKS_H */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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);
+}
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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 */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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
--- /dev/null
+// ----------------------------------------------------------------------------
+// Zonk.h
+// ----------------------------------------------------------------------------
+
+#ifndef ZONK_H
+#define ZONK_H
+
+#include "global.h"
+
+extern void subAnimateZonks(int si);
+
+#endif /* ZONK_H */
--- /dev/null
+#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 */
--- /dev/null
+
+#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);
+}
--- /dev/null
+/***********************************************************
+* 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 */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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 */
--- /dev/null
+
+#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);
+}
--- /dev/null
+
+#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]++;
+}
--- /dev/null
+#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 */
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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);
+}
--- /dev/null
+// ----------------------------------------------------------------------------
+// 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 */
}
#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 */
}
#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;
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;
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)
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,
EL_PLAYER_2,
EL_PLAYER_3,
EL_PLAYER_4,
+ EL_SOKOBAN_FIELD_PLAYER,
EL_SP_MURPHY,
EL_YAMYAM,
EL_YAMYAM_LEFT,
exit(0);
}
- else if (strncmp(command, "dump level ", 11) == 0)
+ else if (strPrefix(command, "dump level "))
{
char *filename = &command[11];
exit(0);
}
- else if (strncmp(command, "dump tape ", 10) == 0)
+ else if (strPrefix(command, "dump tape "))
{
char *filename = &command[10];
exit(0);
}
- else if (strncmp(command, "autoplay ", 9) == 0)
+ else if (strPrefix(command, "autoplay "))
{
char *str_ptr = getStringCopy(&command[9]); /* read command parameters */
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;
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]);
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;
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);
InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
InitGfxWindowInfo(WIN_XSIZE, WIN_YSIZE);
InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
+#endif
+
InitGfxCustomArtworkInfo();
bitmap_font_initial = LoadCustomImage(filename_font_initial);
InitMenuDesignSettings_Static();
InitGfxDrawBusyAnimFunction(DrawInitAnim);
+
+ /* use copy of busy animation to prevent change while reloading artwork */
+ init_last = init;
#endif
}
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);
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);
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();
em_open_all();
#endif
+#if 1
+ sp_open_all();
+#endif
+
if (global.autoplay_leveldir)
{
AutoPlayTape();
em_close_all();
#endif
+#if 1
+ sp_close_all();
+#endif
+
FreeAllImages();
#if defined(TARGET_SDL)
void KeyboardAutoRepeatOffUnlessAutoplay();
+void InitGfxBuffers();
+void InitGadgets();
+
void OpenAll(void);
void CloseAllAndExit(int);
text.c \
sound.c \
joystick.c \
+ snapshot.c \
toons.c \
pcx.c \
image.c \
gadgets.o \
text.o \
sound.o \
+ snapshot.o \
joystick.o \
toons.o \
pcx.o \
/* 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,
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
#include "gadgets.h"
#include "text.h"
#include "sound.h"
+#include "snapshot.h"
#include "joystick.h"
#include "toons.h"
#include "image.h"
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
/* 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(¤t_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)
{
#endif /* PLATFORM_UNIX */
#endif /* !TARGET_SDL */
+#endif
+
void InitCounter() /* set counter back to zero */
{
#if !defined(PLATFORM_MSDOS)
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 */
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 */
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);
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;
if (strEqual(option, "--")) /* stop scanning arguments */
break;
- if (strncmp(option, "--", 2) == 0) /* treat '--' like '-' */
+ if (strPrefix(option, "--")) /* treat '--' like '-' */
option++;
option_arg = strchr(option, '=');
{
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)
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];
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];
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;
}
while (translate_key[++i].x11name);
}
- else if (strncmp(name_ptr, "0x", 2) == 0)
+ else if (strPrefix(name_ptr, "0x"))
{
unsigned long value = 0;
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") ||
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 :
char *getLoginName(void);
char *getRealName(void);
+time_t getFileTimestampEpochSeconds(char *);
+
char *getBasePath(char *);
char *getBaseName(char *);
char *getBaseNamePtr(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));
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);
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)
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);
(*backbuffer)->surface = new_surface;
video.fullscreen_enabled = FALSE;
+
success = TRUE;
}
}
-
#if 1
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
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;
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;
}
#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()
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)
#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
#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;
{ 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" }
};
ti->level_filename = NULL;
ti->level_filetype = NULL;
+ ti->special_flags = NULL;
+
ti->levels = 0;
ti->first_level = 0;
ti->last_level = 0;
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;
}
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;
checked_free(ti->level_filename);
checked_free(ti->level_filetype);
+
+ checked_free(ti->special_flags);
}
checked_free(ti);
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)
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);
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 &&
char *getSetupValue(int, void *);
char *getSetupLine(struct TokenInfo *, char *, int);
+unsigned int get_hash_from_key(void *);
+
boolean AdjustGraphicsForEMC();
void LoadLevelInfo(void);
--- /dev/null
+/***********************************************************
+* 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);
+}
--- /dev/null
+/***********************************************************
+* 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 */
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 */
{
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)
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;
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;
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);
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)
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
}
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,
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);
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);
}
#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)
char *sounds_directory;
char *music_directory;
char *docs_directory;
+
char *execute_command;
+ char *special_flags;
+
boolean serveronly;
boolean network;
boolean verbose;
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;
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
boolean input_on_focus;
boolean prefer_aga_graphics;
int game_frame_delay;
+ boolean sp_show_border_elements;
char *graphics_set;
char *sounds_set;
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) */
int width, height;
};
+struct RectWithBorder
+{
+ int x, y;
+ int width, height;
+ int border_size;
+};
+
struct MenuPosInfo
{
int x, y;
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);
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,
}
+/* ========================================================================= */
+/* 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 */
/* ========================================================================= */
}
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);
(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';
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);
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++;
{
#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 =
{
#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 =
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;
void getFontCharSource(int, char, Bitmap **, int *, int *);
+int maxWordLengthInString(char *);
+
void DrawInitText(char *, int, int);
void DrawInitTextIfNeeded(char *, int, int);
void DrawInitTextExt(char *, int, int, boolean);
void 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 */
#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)
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()
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,
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)
void X11InitVideoDisplay(void);
void X11InitVideoBuffer(DrawBuffer **, DrawWindow **);
+void X11CloseWindow(DrawWindow *);
+
void X11ZoomBitmap(Bitmap *, Bitmap *);
Bitmap *X11LoadImage(char *);
#include "events.h"
#include "config.h"
+Bitmap *bitmap_db_store;
Bitmap *bitmap_db_cross;
Bitmap *bitmap_db_field;
Bitmap *bitmap_db_panel;
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];
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;
struct GameInfo game;
struct GlobalInfo global;
struct BorderInfo border;
+struct ViewportInfo viewport;
struct TitleFadingInfo fading;
struct TitleFadingInfo title_initial_default;
struct TitleFadingInfo title_default;
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;
},
{
"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",
},
{
"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",
"quicksand",
"fast quicksand (with rock)"
},
+ {
+ "from_level_template",
+ "from_level_template",
+ "element taken from level template"
+ },
/* ----------------------------------------------------------------------- */
/* "real" (and therefore drawable) runtime elements */
#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
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];
int year;
int month;
int day;
+
+ enum
+ {
+ DATE_SRC_CLOCK,
+ DATE_SRC_LEVELFILE
+ } src;
};
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 */
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 */
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)
};
+extern Bitmap *bitmap_db_store;
extern Bitmap *bitmap_db_cross;
extern Bitmap *bitmap_db_field;
extern Bitmap *bitmap_db_panel;
extern int key_joystick_mapping;
+#if 1
+extern boolean redraw[MAX_LEV_FIELDX + 2][MAX_LEV_FIELDY + 2];
+#else
extern boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
+#endif
extern int redraw_x1, redraw_y1;
extern short Feld[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern 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;
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;
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;
#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
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 : \
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 */
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);
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 */
/* 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);
#endif
#endif
+#if 1
+ /* needed if different viewport properties defined for menues */
+ ChangeViewportPropertiesIfNeeded();
+#endif
+
#if defined(TARGET_SDL)
SetDrawtoField(DRAW_BACKBUFFER);
#endif
DrawMainMenuExt(REDRAW_ALL, FALSE);
}
-#if 0
+#if defined(CREATE_SPECIAL_EDITION_RND_JUE)
static void gotoTopLevelDir()
{
/* move upwards to top level directory */
SaveLevelSetup_LastSeries();
SaveLevelSetup_SeriesInfo();
-#if 0
+#if defined(CREATE_SPECIAL_EDITION_RND_JUE)
gotoTopLevelDir();
#endif
FadeSetEnterScreen();
+#if 0
+ /* needed if different viewport properties defined for editor */
+ ChangeViewportPropertiesIfNeeded();
+#endif
+
DrawLevelEd();
}
else if (pos == MAIN_CONTROL_INFO)
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);
}
"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)
{
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,
DrawSetupScreen();
}
+static void execSetupShortcuts()
+{
+ setup_mode = SETUP_MODE_SHORTCUTS;
+
+ DrawSetupScreen();
+}
+
static void execSetupShortcuts1()
{
setup_mode = SETUP_MODE_SHORTCUTS_1;
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;
{ 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" },
{ 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" },
{ 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:", },
{ 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 }
};
{ 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 }
};
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;
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);
{
{
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"
}
#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"
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;
{
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;
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);
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);
/* 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);
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;
DrawVideoDisplay(VIDEO_STATE_REC_ON, 0);
DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
DrawVideoDisplay(VIDEO_STATE_TIME_ON, 0);
+
MapTapeWarpButton();
SetDrawDeactivationMask(REDRAW_NONE);
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);
DrawVideoDisplay(VIDEO_STATE_PLAY_ON, 0);
DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
DrawVideoDisplay(VIDEO_STATE_TIME_ON, 0);
+
MapTapeWarpButton();
SetDrawDeactivationMask(REDRAW_NONE);
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;
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);
+}
void TapeDeactivateDisplayOn();
void TapeDeactivateDisplayOff(boolean);
+void TapeSetDateFromEpochSeconds(time_t);
+void TapeSetDateFromNow();
+
void TapeStartRecording(long);
void TapeHaltRecording(void);
void TapeStopRecording(void);
void MapTapeButtons();
void UnmapTapeButtons();
+void HandleTapeButtonKeys(Key);
+
#endif
#include "libgame/libgame.h"
#include "tools.h"
+#include "init.h"
#include "game.h"
#include "events.h"
#include "cartoons.h"
/* 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)
{
if (redraw_mask & REDRAW_FIELD)
{
+#if 0
+ printf("::: REDRAW_FIELD\n");
+#endif
+
if (game_status != GAME_MODE_PLAYING ||
redraw_mask & REDRAW_FROM_BACKBUFFER)
{
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])
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))
{
(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 },
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];
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++)
{
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;
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;
}
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);
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] =
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)
#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
}
}
+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;
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)
#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
}
DrawGraphicAnimation(sx, sy, graphic);
if (GFX_CRUMBLED(element))
- DrawLevelFieldCrumbledSand(x, y);
+ DrawLevelFieldCrumbled(x, y);
}
static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
DrawPlayer(PLAYERINFO(x, y));
}
+#define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1
+
void DrawPlayer(struct PlayerInfo *player)
{
int jx = player->jx;
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);
}
}
+#if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
/* ----------------------------------------------------------------------- */
/* draw player himself */
/* ----------------------------------------------------------------------- */
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 */
#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
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);
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)
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);
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]);
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))
{
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;
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);
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)
{
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);
}
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;
}
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;
}
#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
#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)
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 */
}
#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
+}
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);
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);
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);
void PlaySoundSelecting();
void ToggleFullscreenIfNeeded();
+void ChangeViewportPropertiesIfNeeded();
#endif /* TOOLS_H */