From: Holger Schemel Date: Sat, 30 Aug 2014 08:59:16 +0000 (+0200) Subject: Merge branch 'master' into releases X-Git-Tag: 3.3.0.0^0 X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=commitdiff_plain;h=fc5c46ee4587fb1bbc60a1b6bfc0221d83be3d81;hp=21d98987523453cd39ea3de441b0a69546f89dfc Merge branch 'master' into releases --- diff --git a/CHANGES b/CHANGES deleted file mode 100644 index e7218e42..00000000 --- a/CHANGES +++ /dev/null @@ -1,437 +0,0 @@ -Release Version 3.1.1 [16 AUG 2005] ------------------------------------ - - added tutorial level set created by Aaron Davidson - - added editor element descriptions written by Aaron Davidson - - added native game engine for Emerald Mine (Club) levels - - added level skipping functionality to main menu - - added support for dumping small-sized level sketches from editor - - added use of "editorsetup.conf" for different level sets - - lots of bugfixes and internal engine changes (see ChangeLog) - -Release Version 3.1.0 [07 JUN 2004] ------------------------------------ - - fixed obvious bug with wrong "Murphy" graphics (when digging etc.) - - fixed a lot of Emerald Mine and Supaplex game engine emulation bugs - - re-converted Emerald Mine and Supaplex levels to apply engine fixes - - changed default snap/drop keys from left/right Shift to Control keys - - added level loader for loading native Emerald Mine levels - - added level loader for loading native Supaplex packed levels - - added group elements for multiple matches and random element creation - - added elements that can be digged or left behind by custom elements - - added element "Sokoban field with player" missing for Sokoban levels - - added custom element features to allow building of teleporters - - added option to use step limit instead of time limit for level - - added pressing "space" key as valid action to select menu options - - added clipboard (cut and paste buttons) for custom and group elements - - added shortcut to dump brush (type ":DB" in editor) for use in forum - - added network multiplayer code for Windows (still only command line) - - replaced old tutorial level set with far better one by Niko Böhm - - "contributions" levels now separate package to make base set smaller - - too many bugfixes and changes to list them all here (see ChangeLog) - -Release Version 3.0.8 [14 DEC 2003] ------------------------------------ - - added "musicinfo.conf" for menu and level music configuration - - added "editorsetup.conf" for editor element list configuration - - added "copy" and "exchange" functions for custom elements to editor - - added configurable "bored" and "sleeping" animations for the player - - added "awakening" sound for player when waking up after sleeping - - added configurable element animations for info screen - - added configurable music credits for info screen - - added configurable level set information for info screen - - added warnings for undefined token values in artwork config files - - menu entries now also selectable by clicking on entry text - - better sniksnak turning movement (two steps instead of only one) - - fixed turning movement of butterflies and fireflies (no frame reset) - - fixed bug with wrong default impact sound for colored emeralds - - fixed bug with double nut cracking sound - - fixed a very nasty bug in dragon turning code in TurnRoundExt() - - finally fixed tape recording when player is created from CE change - - added new contributed levels from the following players: - + Audrius Saikunas (4 levels) - + Efraim Yawitz (20 levels) - + Krystian Abramowicz (100 levels) - + Paul E Collins (formerly known as Equinox Tetrachloride; 64 levels) - + Sebastian Simon (12 levels) - - amazing new level set: - + "BD2K3" from Alan Bond - + 43 levels full of BD nostalgia, action and fantastic effects - + overwhelming use of custom elements - + complete artwork set with graphics, sounds and music - + available as a separate download from www.artsoft.org - - another great level set was updated: - + "jue2" from Jürgen Bonhagen - + 15 new mind-boggling levels full of new challenges for your brain - + complete artwork set with graphics and sounds - + available for downloading from "http://www.jb-line.de/rnd.html" - -Release Version 3.0.7 [10 NOV 2003] ------------------------------------ - - fixed incorrectly displayed animation for attacking dragon - - fixed bug with not setting initial gravity for each new game - - fixed bug with teleportation of player by custom element change - - fixed bug with player not getting smashed by rock sometimes - - fixed serious bug in code for delayed element pushing - - fixed little bug in animation frame selection for pushed elements - - fixed bug when pushing element that can move away to the side - - fixed tape recording when player is created from CE element change - - fixed player animation frame reset for identical animations - - unavailable setup options now marked as "n/a" instead of "off" - - prevent "extended" changed elements from delay change in same frame - - speed-up of reading config file for verbose output - - added configuration option for opening and closing Supaplex exit - - added configuration option for moving up/down animation for Murphy - - added animation for "turning" action (for elements with move delay) - - added turning animations for bug, spaceship and sniksnak - -Release Version 3.0.6 [06 OCT 2003] ------------------------------------ - - fixed bug when initializing font graphic structure - - fixed bug with animation mode "pingpong" when using only 1 frame - - fixed bug with extended change target introduced in 3.0.5 - - fixed bug where passing over moving element doubles player speed - - fixed bug with elements continuing to move into push direction - - fixed bug with duplicated player when dropping bomb with shield on - - fixed switching bug (resetting flag when not switching but not idle) - - fixed element tokens for certain file elements with ".active" etc. - - added "switching" event for custom elements ("pressing" only once) - - added support for MP3 music for SDL version through SMPEG library - -Release Version 3.0.5 [29 SEP 2003] ------------------------------------ - - fixed bug in multiple config pages loader code that caused crashes - - enhanced (remaining low-resolution) Supaplex graphics - - active/inactive sides configurable for custom element changes - - new movement type "move when pushed" available for custom elements - - now four envelope elements available - - font, background, animation and sound for envelope now configurable - - main menu doors opening/closing animation type now configurable - -Release Version 3.0.4 [13 SEP 2003] ------------------------------------ - - fixed bug in multiple config pages code that caused crashes - - fixed bug in custom definition of crumbled element graphics - -Release Version 3.0.3 [08 SEP 2003] ------------------------------------ - - fixed bug (missing array boundary check) which could crash the game - - fixed problem with setting mouse cursor in SDL version in fullscreen - - fixed problem with flickering when drawing toon animations - - fixed problem with player animation when snapping and moving - - fixed several nasty bugs that may have caused crashes on some systems - - added envelope content which gets displayed when collecting envelope - - added multiple change event pages for custom elements - - added support for loading various music formats through SDL_mixer - - added music to Supaplex classic level set - -Release Version 3.0.2 [22 AUG 2003] ------------------------------------ - - fixed bug with messing up custom element properties in 3.0.0 levels - - fixed bug with choosing wrong engine version when playing tapes - - fixed bug with creating inaccessible elements at player position - - fixed bug with not finding current level artwork directory - -Release Version 3.0.1 [18 AUG 2003] ------------------------------------ - - fixed bug that caused a crash at startup under Solaris - - fixed bug that caused the DOS version not finding its files - - fixed bug with missing graphic for active red disk bomb - - added custom element property for dropping collected elements - - added another 128 custom elements for those who can't get enough - - fixed PCX files in the DOS version ("classic" graphics only) - -Release Version 3.0.0 [05 AUG 2003] ------------------------------------ - - final version bumped to 3.0.0 due to the massive changes - - graphics and sounds now completely and dynamically customizable - - custom elements now have lots of configurable properties - - advanced custom element settings for powerful, self-created elements - - fixed Supaplex gravity tubes - - fixed very nasty bug in SDL_image (and X11) PCX loading routine - - fixed some very nasty bugs in bitmap zoom routine - - fixed very nasty bug in level/artwork loading routine - - added new contributed levels and artwork from the following players: - * in the section "Contributions - 2002": - + Abby King (14 levels) - + Alan Bond (30 levels, all solvable, BD style artwork set) - + David Hutchinson (25 levels, artwork set) - + Equinox Tetrachloride (50 levels + 100 levels, all solvable) - + Sylvan Hancock (39 levels) - * in the section "Contributions - 2003": - + Andreas Buschbeck (85 levels, all solvable, complete artwork set) - + Edward Leuf (10 levels, all solvable, artwork set) - + Emanuel Schmieg (22 levels, all solvable, complete artwork set) - + Gavin Davidson (47 levels) - + Jorge Jordan (17 levels) - + Rafael Gatti (17 levels) - + Randy Johannessen (17 levels) - + Richard Valvona (3 levels) - + Sam Bateman (35 levels) - - great new levels with full artwork are now available from: - + Juergen Bonhagen (with complete artwork set) - * download these levels from "http://www.jb-line.de/" - + Andreas Buschbeck (with complete artwork set) - * download these levels from "http://home.vr-web.de/~abuschbeck/" - -Pre-Release Version 2.2.0rc7 [17 JUL 2003] ------------------------------------------- - - fixed bug when picking element in the editor - - added more custom elements properties - - fixed bugs when smashing penguin - -Pre-Release Version 2.2.0rc6 [22 APR 2003] ------------------------------------------- - - fixed small font configuration directive bug - - tape recorder font slightly enhanced (now complete character set) - - added missing font configuration source file - - added updated CHANGES file ;-) - -Pre-Release Version 2.2.0rc5 [20 APR 2003] ------------------------------------------- - - added generic selectbox gadget - - added special mouse cursor for playfield while playing - - font handling now more flexible (support for ISO-Latin-1 fonts) - - font graphics adjusted accordingly - -Pre-Release Version 2.2.0rc4 [30 MAR 2003] ------------------------------------------- - - changes for menu configuration - - not officially announced pre-release version - - Emerald Mine text font now much better quality - -Pre-Release Version 2.2.0rc3 [11 FEB 2003] ------------------------------------------- - - first custom element properties - - animation configuration for dynamically defined element actions - - automatically downscaled graphics (small graphics not needed anymore) - - ".EDITOR" and ".PREVIEW" suffixes for special editor/preview graphics - - toon animations (and number of toons) now fully configurable - -Pre-Release Version 2.2.0rc2 [13 JAN 2003] ------------------------------------------- - - added support for stereo WAV sound files - - moving objects can now have arbitrary animation length - - new batch command for dumping level information - - added support for background images for all menu screens - - added 128 custom elements that can be decorated with own graphics - - added some example levels showing how to create custom artwork - - added new contributed levels from the following players: - + Emanuel Schmieg: "Into The Ice Caves" (22 levels + artwork) - -Pre-Release Version 2.2.0rc1 [31 DEC 2002] ------------------------------------------- - - level series artwork now configurable via level series config file - - single graphics and animations can now be replaced with different - ones (independantly from default image files which may be larger) - by defining and using additional image files - - element animation length, speed and mode now freely configurable - - automatic tape playing function for game engine and level testing - - missing steel wall graphic added (thanks to Equinox Tetrachloride) - - added new contributed levels from the following players: - + Abby King (14 levels) - + Andreas Buschbeck (80 levels with complete artwork set) - + David Hutchinson (25 levels with graphics set) - + Equinox Tetrachloride (150 levels guaranteed to be solvable) - + Sylvan Hancock (39 levels) - -Release Version 2.1.1 [13 AUG 2002] ------------------------------------ - - sound bug (causing crashes) fixed (reported by Keith Peterston) - - support for /dev/sound/dsp (devfs) added (thanks to Christoph Bauer) - - small NetBSD compilation bug fixed (thanks to Adam Ciarcinski) - - default keys for "snap field" and "place bomb" fixed for Mac OS X - - added new contributed levels from the following players: - + Alan Bond - + Gerrit Holl and Timen van den Berg - -Release Version 2.1.0 [05 AUG 2002] ------------------------------------ - - native Mac OS X port (finally!) - - graphics, sounds and music now fully configurable - - added support for TrueColor PCX graphics files - - added support for 16 bit WAV sound files - - enhanced sound system (especially regarding stereo and loop sounds) - - new structured setup menu (with sub-menues for graphics and sounds) - - added "quick save" and "quick load" functions with shortcut key - - added single-step playing mode (automatic pause after each step) - - behaviour of "Escape" key in level editor now more intuitive - - changed default slipping behaviour of gems back to 2.0.0 style; - this is now an element property for gems in the level editor, - although existing converted levels use the new EM gems behaviour - - bug fixed that prevented walking through tubes when gravity on - - added Boulder Dash style "snap-pushing" (thanks to Achim Härtel) - - fixed memory leak in image loading code - - fixed some "solid" elements that were accidentally destructible - - fixed some tape stuff - - added new contributed levels from the following players: - + Conor Mancone - + Gavin Davidson - + Jerome Kunegis - + Rüdiger Schäfer - + Flyboy: level group "Cops and Robbers", with own graphics set - - added custom graphics set "Animal Kingdom" by Flyboy - -Release Version 2.0.1 [19 MAR 2002] ------------------------------------ - - bug in explosion code fixed that broke level 24 of "Baby Ghost Mine" - - several Supaplex emulation bugs fixed (thanks to Mihail Milushev): - + orange disk does not fall off from slippery elements - + infotrons kill electrons and snik snaks and trigger orange disks - + explosion chain reactions are now a bit slower than murphy - - behaviour of robots adjusted to make them less aggressive - (needed for quite some Emerald Mine Club levels) - - emeralds and diamonds now fall off normal, steel and growing walls, - as this is the correct behaviour in Emerald Mine; existing private - and contributed levels will still behave as before, unless saved - again (with or without modifications) from the level editor of the - current version of the game - - icon for Windows executable added - - bug when selecting default level series fixed - - new IFF style file format for level and tape files - - bug in storing amoeba content fixed - - nasty tape bugs fixed (completely reworked tape stuff) - - fullscreen mode now works with Windows (workaround for bug in SDL) - - /dev/dsp support for NetBSD added (thanks to Krister Walfridsson) - - file permissions when saving files and creating directories changed - - some small sound bugs fixed - - added new contributed levels from the following players: - + Arno Luppold - + Barak Shacked - + Ben Braithwaite - + Dominik Seichter - + Emilio Hemken - + Glenn Alexander - + Helge Hafting - + Paul Sutton - -Release Version 2.0.0 [01 JAN 2001] ------------------------------------ - - major code redesign to maintain generic game functions in a separate - library and make it easier to port the game to new targets like SDL - - can be compiled with SDL library to build native Windows version - - DOS and Windows versions can be compiled with gcc cross-compiler - - trying to open already busy audio device does not block the game - - bug in network playing code fixed (patch from web site) - - SDL version can load and play music modules - - bug in level editor fixed for EM doors and keys element description - - sound sample frequency raised from 8 kHz to 22 kHz - -Release Version 1.4.0 [27 OCT 1999] ------------------------------------ - - new Boulder Dash elements for better game emulation - - new cool medium-sized crystal font - - new elements and graphics for Diamond Caves II levels - - new elements and graphics for Emerald Mine Club levels - - brushed-up (higher resolution) graphics for Supaplex elements - - special oversized Supaplex levels included - - new elements for more authentic Emerald Mine elements (doors) - - more level editor enhancements: - element list scrollbar and level number selection within editor - - lots of new levels converted from Emerald Mine Club disks, - DX-Boulderdash and Supaplex - - new levels created and contributed by players - - now over 160 level series with over 14.000 levels - - high score list now scrollable to see all 100 entries - - new 16-bit elements level format to allow more than 256 elements - - re-introduced level handicap for more challange (levels must be - solved to be able to play the next one; can be disabled in setup) - - new setup option to disable time limit for relaxed playing :-) - - GAME_DIR path split into RO_GAME_DIR and RW_GAME_DIR to allow - distributors to separate read-only (levels, graphics, sounds) - from writable (hich scores) game data - - new personal level setup files to store level handicap and - last played level for each level series - - removed some 32-bit dependent code; should be 64-bit clean now - - some little bugs fixed - -Release Version 1.3.0 [5 FEB 1999] ----------------------------------- - - strongly enhanced level editor - - new elements, graphics and levels for Supaplex style games - - completely rewritten platform independent gadget code - (buttons, scrollbars, text and number input gadgets) - - nasty sound bug fixed (showed up with Linux kernel 2.2.x) - -Release Version 1.2.0 [5 DEC 1998] ----------------------------------- - - DOS/Windows version - - new WAV sound loader (to replace the old Amiga 8SVX files) - - new PCX graphics loader (to avoid GIF license problems) - - network multiplayer games with upto four players - - no separate network server needed; each client can - fork a network server at startup if there's no server - running at this moment - - possibility to invoke the game to act as a standalone - network server (on a separate machine, for example) - - local multiplayer games with upto four players - - support for upto four joysticks - - completely free customizable keyboard and joystick - for all four players individually - - new joystick calibration screen which can be left - (with Escape key) if no joystick is connected... ;-) - - new (working) GIF graphics loader (but still support - for the old XPM method) - - supports private colormap with extremely less flashing - on 8-bit (256 colors) displays - - soft-scrolling with 50 frames per second (which raises - the system requirements and makes it completely - unplayable on my "old reference" 486/33 (where 0.9b runs - smoothly) and running at 90% speed on my K6-200. - - completely new file format for personal setup data - in ASCII format which is human readable and easily - customizable even with a texteditor; stored in the - user's home directory and no longer somewhere in the - game's installation directory - - high score lists changed: now one file per level and - no longer one file per level series; now using readable - ASCII format - - useful command line options to specify the X11 display, - the game's base (installation) directory, an alternate - level directory, standalone server execution and verbose - execution - -Version 1.1 [???] [NOT RELEASED] --------------------------------- - - new (but broken) GIF graphics loader to be independent - from the XPM library and to replace all graphics by GIF files - -Version 1.0 [9 APR 1997] [NOT RELEASED] ---------------------------------------- - - the game now contains many really playable levels, - not only a few levels for testing - - the game is now even better playable by keyboard - (now you have the same gameplay functionality - compared to playing with a joystick. Especially - there are diagonal directions with keyboard playing - and the fire buttons are mapped to the shift keys) - - a lot of new elements for better emulation of levels - from the games "Boulder Dash", "Emerald Mine" and - "Sokoban". New elements to build "Dynablaster" style - levels. - - enhanced functionality of the level tape recorder - to make it possible to go on with a game at any tape - position - -Version 0.9b2 [21 NOV 1995] [NOT RELEASED] ------------------------------------------- - - new game elements - -Pre-Release Version 0.9b [4 NOV 1995] -------------------------------------- - - the game is now completely Freeware - - the game is now better playable by keyboard - (in the last version, the player was making more than - one step for one keystroke in some cases -- thanks to - Warwick Allison for the hint with "XSync()"!) - - new amoeba type with configurable content (like in the - original C64 version, when aboeba cannot grow anymore - and explodes to diamonds or some other elements) - - compile error with ONE_PER_NAME in high score function - removed (thanks to Dmitry Kohmanyuk) - - little code cleanup (to get some new bugs ;) - - FreeBSD sound and joystick support (thanks to Jean-Marc - Zucconi) - -Pre-Release Version 0.9 [23 OCT 1995] -------------------------------------- - - first (pre)release version diff --git a/CREDITS b/CREDITS index bb187417..601a4370 100644 --- a/CREDITS +++ b/CREDITS @@ -1,3 +1,55 @@ -[Credits file yet to be written.] +Rocks'n'Diamonds contains a lot of inspiration, ideas, code and contributions +by many people and projects, which are listed here in no particular order. If +somebody should be added to this list of credits, please let me know! +------------------------------------------------------------------------------- + +Special thanks to Peter Liepa for creating "Boulder Dash" that started it all! + +Special thanks to Klaus Heinz and Volker Wertich for creating "Emerald Mine", +which took this kind of game to a new level! + +Special thanks to Michael Stopp and Philip Jespersen for creating "Supaplex"! + +Special thanks to Hiroyuki Imabayashi for creating "Sokoban"! + +Special thanks to Alan Bond and Jürgen Bonhagen for the continuous creation +of outstanding level sets! + +Thanks to Peter Elzner for ideas and inspiration by Diamond Caves. + +Thanks to Steffest for ideas and inspiration by DX-Boulderdash. + +Thanks to Guido Schulz for the initial MS-DOS port of the game. + +The native Emerald mine engine was derived from Emerald Mine for X11 +which was developed by David Tritscher as a very compatible Emerald Mine clone. +Thanks a lot for this contribution! + +The native Supaplex engine is based on MegaPlex by Frank Schindler, which is +based on the Supaplex Speed Fix by Herman Perk, which is based on the original +Supaplex game by Michael Stopp and Philip Jespersen. Thanks a lot for this +contribution! + +Thanks to Karl Hörnell for some additional toon graphics taken from "Iceblox": +The penguin, the mole, the pig and the dragon. + +Thanks to the composers of the included music modules: "mod.apoplexy" by +bee hunter/jazz, "mod.chiptune" by 4-mat/anarchy and "mod.cream_of_the_earth" +by romeoknight. + +Thanks to Christopher Clark for the hash functions. + +The random number generator was taken from the GNU C library. + +The networking code was derived from xtris. Thanks! + +Thanks to Francesco Carta for the comprehensive Rocks'n'Diamonds manual. + +Thanks to Niko Böhm for the Rocks'n'Diamonds documentation wiki. + +Thanks to Simon Forsberg for being the moderator of the R'n'D forum. + +And not to forget: Many thanks to all those who contributed levels to this game +since 1995! diff --git a/ChangeLog b/ChangeLog index 41f88faf..94518588 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,240 @@ +2010-05-22 + * fixed missing memory allocation in SP engine when saving engine data + for non-SP game engine snapshots (which also stores SP engine part) + +2010-05-21 + * fixed problem with scrolling in native EM engine in multi-user mode + (this bug was just introduced with the experimental viewport stuff) + * fixed animation of splashing acid in EM engine with classic artwork + * fixed animation of cracking nut in EM engine with classic artwork + * fixed (implemented) single step mode in native EM and SP engines + * fixed "latest_engine" flag in classic levels (moved to single sets) + * updated SDL library DLLs for Windows to the latest release versions + (this fixed some mysterious crashes of the game on Windows systems) + * replaced EM and SP set in classic level set with native level files + * finally added a newly written "CREDITS" file to the game package + * removed sampled music loops from classic music set + +2010-04-20 + * changed native Emerald Mine engine to support different viewport sizes + +2010-04-19 + * changed native Supaplex engine to support different viewport sizes + +2010-04-07 + * added initial, experimental support for different viewport properties + (with "viewports" being menu/playfield area and doors; currently the + size of the menu/playfield area and door positions can be redefined) + +2010-04-02 + * added initial, experimental support for different window sizes + +2010-03-27 + * added support for native Sokoban solution files in pure 'udlrUDLR' + format with extension ".sln" instead of ".tape" for solution tapes + +2010-03-26 + * added image config suffix ".class" to be able to define classes of + crumbled elements which are then separated against each others when + drawing crumbled borders (class names can freely be defined) + (Example: "sand.CRUMBLED.class: sand" and "emc_grass.CRUMBLED.class: + emc_grass" results in sand and emc_grass being crumbled separately, + even if directly adjacent on the playfield.) + * added image config suffix ".style" to use two new features for + crumbled graphics: + - "accurate_borders": try to draw correctly crumbled corners (which + means that a row of crumbled elements does not have two crumbled + corners for each element in the row, but only at the "real" corners + at the start and the end of the row of elements) + - "inner_corners": also draw inner corners in concave constructions + of several crumbled elements -- this is currently a big kludge: the + number of frames for crumbled graphic must be "2", with the first + frame as usual (crumbled graphic), while the second frame contains + the graphic with inner (crumbled) corners for the crumbled graphic + (These two features are mainly intended for bevelled walls, not for + diggable elements like sand; "inner_corners" only works reliably for + static walls, not for in-game dynamically changing walls using CEs.) + +2010-03-16 + * finished code cleanup of native Supaplex game engine + +2010-03-14 + * started code cleanup of native Supaplex game engine + +2010-03-13 + * integrated playing sound effects into native Supaplex game engine + +2010-03-10 + * added configurable key shortcuts for the tape recorder buttons + +2010-03-09 + * added (hidden) function to save native Supaplex levels with tape as + native *.sp file containing level with demo (saved with a file name + similar to native R'n'D levels, but with ".sp" extension instead of + ".level"); to use this functionality, enter ":save-native-level" or + ":snl" from the main menu with the native Supaplex level loaded and + the appropriate tape loaded to the tape recorder + * fixed potential crash bug caused by illegal array access in engine + snapshot loading and saving code + * changed setting permissions of score files to be world-writable if + the program is not installed and running setgid to allow the program + to modify existing score files when run as a different user (which + allows cheating, of course, as the score files are not protected + against modification in this case) + * added (commented out) suggestions for RO_GAME_DIR and RW_GAME_DIR to + the top level Makefile for Debian / Ubuntu installations + * added saving read-only levels from editor into personal level set + (thanks to Bela Lubkin for the above four patches) + +2010-03-03 + * added updating of game values on the panel to Supaplex game engine + +2010-02-23 + * finished integrating R'n'D graphics engine into Supaplex game engine + (although some animations do not support full customizability yet) + +2010-02-22 + * done integrating R'n'D graphics engine into file "Infotron.c" + * done integrating R'n'D graphics engine into file "OrangeDisk.c" + +2010-02-19 + * integrated engine snapshot functionality into Supaplex game engine + +2010-02-16 + * fixed bug in native Supaplex engine that broke several demo solutions + * fixed bug with re-initializing already existing elements in function + RelocatePlayer() in src/game.c (causing problems with Sokoban fields + counted a second time, making the currently playing level unsolvable) + * done integrating R'n'D graphics engine into file "SnikSnaks.c" + * done integrating R'n'D graphics engine into file "Electrons.c" + * done integrating R'n'D graphics engine into file "Zonk.c" + +2010-02-14 + * done integrating R'n'D graphics engine into file "Murphy.c" + * done integrating R'n'D graphics engine into file "BugsTerminals.c" + +2010-02-07 + * started integrating R'n'D graphics engine into Supaplex game engine + +2010-02-02 + * added small kludge that allows transparent pushing animation over + non-black background (by using "game.use_masked_pushing: true") + * added editor flag to Sokoban field/object elements to automatically + finish solved Sokoban style levels (even if they contain non-Sokoban + elements, which prevents auto-enabling this feature for such levels) + +2010-01-10 + * added new element "from_level_template" which is replaced by element + from level template at same playfield position when loaded (currently + not accessible from level editor, but only used for special Sokoban + level conversion when using "special_flags: load_xsb_to_ces") + * added special behaviour for "special_flags: load_xsb_to_ces": global + settings of individual level files are overwritten by template level + (except playfield size, level name, level author and template flag) + +2010-01-07 + * added handling of gravity ports when converting Supaplex style R'n'D + levels to native Supaplex levels for playing with Supaplex engine + +2010-01-06 + * fixed bug in Supaplex engine regarding initial screen scroll position + +2009-12-17 + * fixed EMC style pushing animations in the R'n'D graphics engine (when + using ".2nd_movement_tile" for animations having start and end tile) + * for this to work (look) properly for two-tile pushing animations with + non-black (i.e. opaque) background, the pushing graphics drawing order + was changed to first draw the pushed element, then the player (maybe + this should be controlled by an ".anim_mode" flag yet to be added) + * two-tile animations for moving or pushing should have 7 frames for + normal speed, 15 frames for half speed etc. to display correct frames + * two-tile animations are also displayed correctly with different speed + settings for the player (for pushing animations) or moving elements + +2009-12-16 + * added searching for template level (file "template.level") not only + inside the level set directory, but also in above level directories; + this makes is possible to use the same single template level file + (placed in a level group directory) for many level sub-directories + +2009-12-10 + * fixed bug with steel exit being destructible during opening phase + * added token "special_flags" to "levelinfo.conf" (currently with the + only recognized value "load_xsb_to_ces", doing the same as the flag + "-Dload_xsb_to_ces" on the command line, but as a permanent flag for + converting all elements in native (XSB) Sokoban level files to CEs) + +2009-12-08 + * fixed some problems with Supaplex engine when compiling for Windows + +2009-12-05 + * added special mode to convert elements of Sokoban XSB levels to CEs + by adding "-Dload_xsb_to_ces" to the command line starting the game + (also adding a dependency to a template level file "template.level") + +2009-12-01 + * added reading native Sokoban levels and level packages (XSB files) + +2009-11-25 + * fixed bugs in (auto)scrolling behaviour when passing ports or when + wrapping around the playfield through "holes" in the playfield border + +2009-11-24 + * changed internal playfield bitmap handling from playfield sized bitmap + to screen sized bitmap (visible scrolling area), therefore speeding up + graphics operations (by eliminating bitmap updates in invisible areas) + and removing playfield size limitations due to increasing bitmap size + for larger playfield sizes (while the new implementation always uses + a fixed playfield bitmap size for arbitrary internal playfield sizes) + +2009-11-12 + * fixed bug with single step mode (there were some cases where the game + did not automatically return to pause mode, e.g. when trying to push + things that cannot be pushed or when trying to run against a wall) + +2009-11-01 + * added support for loading Supaplex levels in MPX level file format + +2009-10-31 + * fixed SP engine to set "game over" not before lead out counter done + +2009-10-30 + * fixed (potential) compile error when using GCC option "-std=gnu99" + (thanks to Tom "spot" Callaway) + +2009-10-28 + * fixed array allocation in native Supaplex engine to correctly handle + preceding scratch buffers (needed because of missing border checking) + * fixed playfield initialization to correctly add raw header bytes as + subsequent scratch buffer (needed because of missing border checking) + +2009-10-24 + * most important parts of native Supaplex engine integration working: + - native Supaplex levels can be played in native Supaplex engine + - native Supaplex level/demo files ("*.sp" files) can be re-played + - all 111 classic original Supaplex levels automatically solvable + - native Supaplex engine can be selected and used from level editor + - logic of re-playing Supaplex demos migrated to R'n'D tape logic + +2009-09-25 + * fixed another translation problem from VisualBasic to C (where "int" + should be "short") causing unsolvable demos with bugs and terminals + ("bugs" being related to the Supaplex "buggy base" element here ;-) ) + +2009-09-23 + * fixed bug when reading Supaplex single level files (preventing loader + from seeking to level position like in Supaplex level package files) + +2009-08-01 + * first classic Supaplex level running and solved by solution/demo tape + +2009-06-20 + * started with integration of native Supaplex engine, using source code + of Megaplex from Frank Schindler, based on original Supaplex engine + +2009-06-16 + * version number set to 3.2.6.2 + 2009-06-15 * version 3.2.6.1 released diff --git a/HARDWARE b/HARDWARE deleted file mode 100644 index 49de985a..00000000 --- a/HARDWARE +++ /dev/null @@ -1,92 +0,0 @@ - -[Very outdated -- should be rewritten...] - - -Some recommendations for more fun playing Rocks'n'Diamonds: -=========================================================== - -About sound ------------ -It is highly recommended to have a decent sound interface for playing -this game (although it only comes with bad-quality 8000-Hz-samples to -save memory and to be compatible with /dev/audio). - -The best sound platform is an actual Linux system with (at least) kernel -1.2.x, because it offers some nice real-time sound features which are -needed to have background music loops in the game. - -On all other systems you don't have music loops, but you still have all -the other sounds. - - -About game speed ----------------- -You should have a relatively fast hardware. - -The game was developed on a i486/33 (which is three years old now), -and you should probably better not try to run it on a slower system. - -You should have an accelerated graphic card; I have found out that it -starts being playable on my 486/33 with an old ISA cirrus logic 5426 -graphic card, which has a blitter that is supported by XFree86[tm], -but that it was nearly unplayable on a 486/66 with old, unaccelerated -ET4000. - -If all works fine, you should have something around 30 frames per second. - -If you think that the game is to slow to play, you should try out the -following things: - -- Set "Buffered Gfx" to "off" in the setup menu. Normally (on a fast - enough system) you should use buffered graphics, which means that - all graphics is drawn into an invisible Pixmap and is then copied - to the X11 window to avoid flickering. If you disable this double - buffering, the graphic is directly drawn into the window. This can - cause some slight flickering, but makes graphic operations roughly - twice as fast compared to double buffering. - -- Set "Game Music" to "off" in the setup menu (and maybe "sound loops" - too). Where disabling buffered graphics may be required with slow - graphics hardware, disabling sound is especially recommended on slow - CPU systems (486/33 and slower), because the sound server eats up a - significant amount of CPU time when playing long sounds. - -You might also notice that bigger levels tend to be slower on slow -systems. - -About the option "Fading" in the setup menu: It gives a nice looking -fading when switching to a new screen, but you should really only try -this out if you think that you have a very fast graphics hardware. - - -About music ------------ -The background music loops are ripped out from several nice music albums. -Just have a look at the info screen to find out from which album each -sound loop came from -- they are all very well done pieces of music, but -unfortunately they don't sound better after converting them to 8 kHz -samples (to conform to standard SUN /dev/audio). Maybe I change this to -a better quality in the future, but at the moment, where the sounds -directory has a size of nearly a megabyte, I'll stay with 8 kHz samples. - -So, if you have a non-Linux system (which cannot play sound loops) or -don't like the "telephone quality" of the music loops, just get some of -these CDs and play them while your playing the game! ;-) - - -About game-play ---------------- -It is *strongly recommended* to play this game with a high-quality joystick. -That means, throw your $10 joystick out of the window and buy a decent -Competition-Pro Digital PC joystick or a high-quality CH Products Analog -joystick. Believe me, it doubles the fun of playing the game. - -If you only have a normal Unix system (and no fine Linux system), you -are forced to play with the keyboard. It works, but is not only less fun, -but also more difficult with some levels, because you cannot move in -diagonal directions with keyboard control at the moment. Another bad thing -is that you will have some problems when pressing many keys at the same -time. This might change in the future, when I implement a better keyboard -handling which not only solves these problems but allows diagonal directions, -too. - diff --git a/Makefile b/Makefile index 65ea127a..75fde6be 100644 --- a/Makefile +++ b/Makefile @@ -22,10 +22,14 @@ X11_PATH = /usr/X11R6 # directory for read-only game data (like graphics, sounds, levels) # default is '.' to be able to run program without installation # RO_GAME_DIR = /usr/games +# use the following setting for Debian / Ubuntu installations: +# RO_GAME_DIR = /usr/share/games/rocksndiamonds # directory for writable game data (like highscore files) # default is '.' to be able to run program without installation # RW_GAME_DIR = /var/games +# use the following setting for Debian / Ubuntu installations: +# RW_GAME_DIR = /var/games/rocksndiamonds # uncomment if system has no joystick include file # JOYSTICK = -DNO_JOYSTICK @@ -134,13 +138,12 @@ levelsketch_images: all ./Scripts/make_levelsketch_images.sh backup: - ./Scripts/make_backup.sh src 1 + ./Scripts/make_backup.sh src tar -backup2: - ./Scripts/make_backup.sh src 2 +backup-net-copy: + ./Scripts/make_backup.sh src scp -backup3: - ./Scripts/make_backup.sh src 3 +backup-net: backup backup-net-copy backup_lev: ./Scripts/make_backup.sh lev @@ -151,6 +154,12 @@ backup_gfx: # prerelease: # ./Scripts/make_prerelease.sh +jue: + @$(MAKE) SPECIAL_EDITION=rnd_jue all + +jue-win: + @$(MAKE) SPECIAL_EDITION=rnd_jue cross-win32 + dist-clean: @$(MAKE_CMD) dist-clean diff --git a/src/Makefile b/src/Makefile index bd5538ea..4bbbcca9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -228,7 +228,10 @@ LIBGAME = $(LIBGAME_DIR)/libgame.a GAME_EM_DIR = game_em GAME_EM = $(GAME_EM_DIR)/game_em.a -RNDLIBS = $(LIBGAME) $(GAME_EM) +GAME_SP_DIR = game_sp +GAME_SP = $(GAME_SP_DIR)/game_sp.a + +RNDLIBS = $(LIBGAME) $(GAME_EM) $(GAME_SP) ICONBASE = windows_icon ifeq ($(PLATFORM),cross-win32) @@ -246,7 +249,7 @@ endif # build targets # ----------------------------------------------------------------------------- -all: libgame_dir game_em_dir $(PROGNAME) +all: libgame_dir game_em_dir game_sp_dir $(PROGNAME) $(PROGNAME): $(RNDLIBS) $(TIMESTAMP_FILE) $(OBJS) $(ICON) $(CC) $(PROFILING) $(OBJS) $(ICON) $(RNDLIBS) $(LDFLAGS) -o $(PROGNAME) @@ -261,6 +264,11 @@ game_em_dir: $(GAME_EM): @$(MAKE) -C $(GAME_EM_DIR) +game_sp_dir: + @$(MAKE) -C $(GAME_SP_DIR) +$(GAME_SP): + @$(MAKE) -C $(GAME_SP_DIR) + auto-conf: @for i in $(CNFS); do \ echo "$(CNFS_CMD) $$i > $$i"; \ @@ -276,7 +284,7 @@ conf_snd.h: conf_snd.c conf_mus.h: conf_mus.c @$(MAKE) auto-conf -$(TIMESTAMP_FILE): $(SRCS) $(LIBGAME) $(GAME_EM) +$(TIMESTAMP_FILE): $(SRCS) $(LIBGAME) $(GAME_EM) $(GAME_SP) @date '+"%Y-%m-%d %H:%M"' \ | sed -e 's/^/#define COMPILE_DATE_STRING /' \ > $(TIMESTAMP_FILE) @@ -291,9 +299,11 @@ $(ICON): clean-obj: $(MAKE) -C $(LIBGAME_DIR) clean $(MAKE) -C $(GAME_EM_DIR) clean + $(MAKE) -C $(GAME_SP_DIR) clean $(RM) $(OBJS) $(RM) $(LIBGAME) $(RM) $(GAME_EM) + $(RM) $(GAME_SP) clean-ico: $(RM) $(ICONBASE).ico @@ -327,11 +337,12 @@ valgrind: all dist-clean: clean-obj tags: - $(ETAGS) *.[ch] $(LIBGAME_DIR)/*.[ch] $(GAME_EM_DIR)/*.[ch] + $(ETAGS) *.[ch] $(LIBGAME_DIR)/*.[ch] $(GAME_EM_DIR)/*.[ch] $(GAME_SP_DIR)/*.[ch] depend: $(MAKE) -C $(LIBGAME_DIR) depend $(MAKE) -C $(GAME_EM_DIR) depend + $(MAKE) -C $(GAME_SP_DIR) depend for i in $(SRCS); do $(CPP) $(CFLAGS) -M $$i; done > .depend ifeq (.depend,$(wildcard .depend)) diff --git a/src/cartoons.c b/src/cartoons.c index 70d6d3d5..8ca4bdd5 100644 --- a/src/cartoons.c +++ b/src/cartoons.c @@ -23,15 +23,18 @@ static struct ToonInfo toons[MAX_NUM_TOONS]; static void PrepareBackbuffer() { - if (game_status == GAME_MODE_PLAYING && - level.game_engine_type == GAME_ENGINE_TYPE_EM) + if (game_status != GAME_MODE_PLAYING) + return; + + if (level.game_engine_type == GAME_ENGINE_TYPE_EM) { BlitScreenToBitmap_EM(backbuffer); - - return; } - - if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING) + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + { + BlitScreenToBitmap_SP(backbuffer); + } + else if (setup.soft_scrolling) /* GAME_ENGINE_TYPE_RND */ { int fx = FX, fy = FY; diff --git a/src/conf_e2g.c b/src/conf_e2g.c index 2d49c0e2..6b154196 100644 --- a/src/conf_e2g.c +++ b/src/conf_e2g.c @@ -281,6 +281,14 @@ element_to_graphic[] = EL_SP_MURPHY, ACTION_SLEEPING, MV_BIT_RIGHT, FALSE, IMG_SP_MURPHY_SLEEPING_RIGHT }, + { + EL_SP_MURPHY, ACTION_DROPPING, -1, FALSE, + IMG_SP_MURPHY_DROPPING + }, + { + EL_SP_MURPHY, ACTION_SHRINKING, -1, FALSE, + IMG_SP_MURPHY_SHRINKING + }, { EL_SP_MURPHY_CLONE, -1, -1, FALSE, IMG_SP_MURPHY_CLONE @@ -289,6 +297,14 @@ element_to_graphic[] = EL_SP_INFOTRON, -1, -1, FALSE, IMG_SP_INFOTRON }, + { + EL_SP_INFOTRON, ACTION_MOVING, MV_BIT_LEFT, FALSE, + IMG_SP_INFOTRON_MOVING_LEFT + }, + { + EL_SP_INFOTRON, ACTION_MOVING, MV_BIT_RIGHT, FALSE, + IMG_SP_INFOTRON_MOVING_RIGHT + }, { EL_SP_INFOTRON, ACTION_COLLECTING, -1, FALSE, IMG_SP_INFOTRON_COLLECTING diff --git a/src/conf_gfx.c b/src/conf_gfx.c index 49dca0a7..f8a5ae3f 100644 --- a/src/conf_gfx.c +++ b/src/conf_gfx.c @@ -67,6 +67,8 @@ struct ConfigTypeInfo image_config_suffix[] = { ".align", ARG_UNDEFINED, TYPE_INTEGER }, { ".valign", ARG_UNDEFINED, TYPE_INTEGER }, { ".sort_priority", ARG_UNDEFINED, TYPE_INTEGER }, + { ".class", ARG_UNDEFINED, TYPE_STRING }, + { ".style", ARG_UNDEFINED, TYPE_STRING }, { NULL, NULL, 0 } }; @@ -281,7 +283,7 @@ struct ConfigInfo image_config[] = { "[sp_default].exploding.xpos", "8" }, { "[sp_default].exploding.ypos", "3" }, { "[sp_default].exploding.frames", "8" }, - { "[sp_default].exploding.delay", "3" }, + { "[sp_default].exploding.delay", "4" }, { "[sp_default].exploding.anim_mode", "linear" }, { "sp_zonk", "RocksSP.pcx" }, @@ -292,26 +294,26 @@ struct ConfigInfo image_config[] = { "sp_zonk.moving.left.xpos", "0" }, { "sp_zonk.moving.left.ypos", "6" }, { "sp_zonk.moving.left.frames", "4" }, - { "sp_zonk.moving.left.delay", "2" }, + { "sp_zonk.moving.left.delay", "1" }, { "sp_zonk.moving.left.anim_mode", "reverse" }, { "sp_zonk.moving.right", "RocksSP.pcx" }, { "sp_zonk.moving.right.xpos", "0" }, { "sp_zonk.moving.right.ypos", "6" }, { "sp_zonk.moving.right.frames", "4" }, { "sp_zonk.moving.right.start_frame", "1" }, - { "sp_zonk.moving.right.delay", "2" }, + { "sp_zonk.moving.right.delay", "1" }, { "sp_zonk.pushing.left", "RocksSP.pcx" }, { "sp_zonk.pushing.left.xpos", "0" }, { "sp_zonk.pushing.left.ypos", "6" }, { "sp_zonk.pushing.left.frames", "4" }, - { "sp_zonk.pushing.left.delay", "2" }, + { "sp_zonk.pushing.left.delay", "1" }, { "sp_zonk.pushing.left.anim_mode", "reverse" }, { "sp_zonk.pushing.right", "RocksSP.pcx" }, { "sp_zonk.pushing.right.xpos", "0" }, { "sp_zonk.pushing.right.ypos", "6" }, { "sp_zonk.pushing.right.frames", "4" }, { "sp_zonk.pushing.right.start_frame", "1" }, - { "sp_zonk.pushing.right.delay", "2" }, + { "sp_zonk.pushing.right.delay", "1" }, { "sp_base", "RocksSP.pcx" }, { "sp_base.xpos", "2" }, @@ -338,36 +340,42 @@ struct ConfigInfo image_config[] = { "sp_murphy.moving.left.frames", "3" }, { "sp_murphy.moving.left.anim_mode", "pingpong" }, { "sp_murphy.moving.left.delay", "2" }, + { "sp_murphy.moving.left.start_frame", "1" }, { "sp_murphy.moving.right", "RocksSP.pcx" }, { "sp_murphy.moving.right.xpos", "11" }, { "sp_murphy.moving.right.ypos", "0" }, { "sp_murphy.moving.right.frames", "3" }, { "sp_murphy.moving.right.anim_mode", "pingpong" }, { "sp_murphy.moving.right.delay", "2" }, + { "sp_murphy.moving.right.start_frame", "1" }, { "sp_murphy.digging.left", "RocksSP.pcx" }, { "sp_murphy.digging.left.xpos", "8" }, { "sp_murphy.digging.left.ypos", "0" }, { "sp_murphy.digging.left.frames", "3" }, { "sp_murphy.digging.left.anim_mode", "pingpong" }, { "sp_murphy.digging.left.delay", "2" }, + { "sp_murphy.digging.left.start_frame", "1" }, { "sp_murphy.digging.right", "RocksSP.pcx" }, { "sp_murphy.digging.right.xpos", "11" }, { "sp_murphy.digging.right.ypos", "0" }, { "sp_murphy.digging.right.frames", "3" }, { "sp_murphy.digging.right.anim_mode", "pingpong" }, { "sp_murphy.digging.right.delay", "2" }, + { "sp_murphy.digging.right.start_frame", "1" }, { "sp_murphy.collecting.left", "RocksSP.pcx" }, { "sp_murphy.collecting.left.xpos", "8" }, { "sp_murphy.collecting.left.ypos", "0" }, { "sp_murphy.collecting.left.frames", "3" }, { "sp_murphy.collecting.left.anim_mode", "pingpong" }, { "sp_murphy.collecting.left.delay", "2" }, + { "sp_murphy.collecting.left.start_frame", "1" }, { "sp_murphy.collecting.right", "RocksSP.pcx" }, { "sp_murphy.collecting.right.xpos", "11" }, { "sp_murphy.collecting.right.ypos", "0" }, { "sp_murphy.collecting.right.frames", "3" }, { "sp_murphy.collecting.right.anim_mode", "pingpong" }, { "sp_murphy.collecting.right.delay", "2" }, + { "sp_murphy.collecting.right.start_frame", "1" }, { "sp_murphy.pushing.left", "RocksSP.pcx" }, { "sp_murphy.pushing.left.xpos", "11" }, { "sp_murphy.pushing.left.ypos", "1" }, @@ -418,6 +426,16 @@ struct ConfigInfo image_config[] = { "sp_murphy.sleeping.right.frames", "3" }, { "sp_murphy.sleeping.right.delay", "100" }, { "sp_murphy.sleeping.right.anim_mode", "linear" }, + { "sp_murphy.dropping", "RocksSP.pcx" }, + { "sp_murphy.dropping.xpos", "11" }, + { "sp_murphy.dropping.ypos", "12" }, + { "sp_murphy.dropping.frames", "1" }, + { "sp_murphy.shrinking", "RocksSP.pcx" }, + { "sp_murphy.shrinking.xpos", "8" }, + { "sp_murphy.shrinking.ypos", "14" }, + { "sp_murphy.shrinking.frames", "8" }, + { "sp_murphy.shrinking.delay", "4" }, + { "sp_murphy.shrinking.anim_mode", "linear" }, { "sp_murphy_clone", "RocksSP.pcx" }, { "sp_murphy_clone.xpos", "3" }, @@ -431,6 +449,16 @@ struct ConfigInfo image_config[] = { "sp_infotron.EDITOR", "RocksSP.pcx" }, { "sp_infotron.EDITOR.xpos", "8" }, { "sp_infotron.EDITOR.ypos", "11" }, + { "sp_infotron.moving.left", "RocksSP.pcx" }, + { "sp_infotron.moving.left.xpos", "8" }, + { "sp_infotron.moving.left.ypos", "13" }, + { "sp_infotron.moving.left.frames", "8" }, + { "sp_infotron.moving.right", "RocksSP.pcx" }, + { "sp_infotron.moving.right.xpos", "8" }, + { "sp_infotron.moving.right.ypos", "13" }, + { "sp_infotron.moving.right.frames", "8" }, + { "sp_infotron.moving.right.start_frame", "6" }, + { "sp_infotron.moving.right.anim_mode", "reverse" }, { "sp_infotron.collecting", "RocksSP.pcx" }, { "sp_infotron.collecting.xpos", "8" }, { "sp_infotron.collecting.ypos", "7" }, @@ -511,9 +539,9 @@ struct ConfigInfo image_config[] = { "sp_disk_red.ypos", "2" }, { "sp_disk_red.frames", "1" }, { "sp_disk_red.collecting", "RocksSP.pcx" }, - { "sp_disk_red.collecting.xpos", "8" }, + { "sp_disk_red.collecting.xpos", "9" }, { "sp_disk_red.collecting.ypos", "5" }, - { "sp_disk_red.collecting.frames", "8" }, + { "sp_disk_red.collecting.frames", "7" }, { "sp_disk_red.collecting.anim_mode", "linear" }, { "sp_disk_red.active", "RocksSP.pcx" }, { "sp_disk_red.active.xpos", "4" }, @@ -553,85 +581,85 @@ struct ConfigInfo image_config[] = { "sp_gravity_port_right.ypos", "1" }, { "sp_gravity_port_right.frames", "1" }, { "sp_gravity_port_right.EDITOR", "RocksSP.pcx" }, - { "sp_gravity_port_right.EDITOR.xpos", "5" }, - { "sp_gravity_port_right.EDITOR.ypos", "1" }, + { "sp_gravity_port_right.EDITOR.xpos", "0" }, + { "sp_gravity_port_right.EDITOR.ypos", "14" }, { "sp_gravity_port_down", "RocksSP.pcx" }, { "sp_gravity_port_down.xpos", "2" }, { "sp_gravity_port_down.ypos", "1" }, { "sp_gravity_port_down.frames", "1" }, { "sp_gravity_port_down.EDITOR", "RocksSP.pcx" }, - { "sp_gravity_port_down.EDITOR.xpos", "6" }, - { "sp_gravity_port_down.EDITOR.ypos", "1" }, + { "sp_gravity_port_down.EDITOR.xpos", "1" }, + { "sp_gravity_port_down.EDITOR.ypos", "14" }, { "sp_gravity_port_left", "RocksSP.pcx" }, { "sp_gravity_port_left.xpos", "3" }, { "sp_gravity_port_left.ypos", "1" }, { "sp_gravity_port_left.frames", "1" }, { "sp_gravity_port_left.EDITOR", "RocksSP.pcx" }, - { "sp_gravity_port_left.EDITOR.xpos", "7" }, - { "sp_gravity_port_left.EDITOR.ypos", "1" }, + { "sp_gravity_port_left.EDITOR.xpos", "2" }, + { "sp_gravity_port_left.EDITOR.ypos", "14" }, { "sp_gravity_port_up", "RocksSP.pcx" }, { "sp_gravity_port_up.xpos", "4" }, { "sp_gravity_port_up.ypos", "1" }, { "sp_gravity_port_up.frames", "1" }, { "sp_gravity_port_up.EDITOR", "RocksSP.pcx" }, - { "sp_gravity_port_up.EDITOR.xpos", "0" }, - { "sp_gravity_port_up.EDITOR.ypos", "2" }, + { "sp_gravity_port_up.EDITOR.xpos", "3" }, + { "sp_gravity_port_up.EDITOR.ypos", "14" }, { "sp_gravity_on_port_right", "RocksSP.pcx" }, { "sp_gravity_on_port_right.xpos", "1" }, { "sp_gravity_on_port_right.ypos", "1" }, { "sp_gravity_on_port_right.frames", "1" }, { "sp_gravity_on_port_right.EDITOR", "RocksSP.pcx" }, - { "sp_gravity_on_port_right.EDITOR.xpos", "5" }, - { "sp_gravity_on_port_right.EDITOR.ypos", "1" }, + { "sp_gravity_on_port_right.EDITOR.xpos", "0" }, + { "sp_gravity_on_port_right.EDITOR.ypos", "13" }, { "sp_gravity_on_port_down", "RocksSP.pcx" }, { "sp_gravity_on_port_down.xpos", "2" }, { "sp_gravity_on_port_down.ypos", "1" }, { "sp_gravity_on_port_down.frames", "1" }, { "sp_gravity_on_port_down.EDITOR", "RocksSP.pcx" }, - { "sp_gravity_on_port_down.EDITOR.xpos", "6" }, - { "sp_gravity_on_port_down.EDITOR.ypos", "1" }, + { "sp_gravity_on_port_down.EDITOR.xpos", "1" }, + { "sp_gravity_on_port_down.EDITOR.ypos", "13" }, { "sp_gravity_on_port_left", "RocksSP.pcx" }, { "sp_gravity_on_port_left.xpos", "3" }, { "sp_gravity_on_port_left.ypos", "1" }, { "sp_gravity_on_port_left.frames", "1" }, { "sp_gravity_on_port_left.EDITOR", "RocksSP.pcx" }, - { "sp_gravity_on_port_left.EDITOR.xpos", "7" }, - { "sp_gravity_on_port_left.EDITOR.ypos", "1" }, + { "sp_gravity_on_port_left.EDITOR.xpos", "2" }, + { "sp_gravity_on_port_left.EDITOR.ypos", "13" }, { "sp_gravity_on_port_up", "RocksSP.pcx" }, { "sp_gravity_on_port_up.xpos", "4" }, { "sp_gravity_on_port_up.ypos", "1" }, { "sp_gravity_on_port_up.frames", "1" }, { "sp_gravity_on_port_up.EDITOR", "RocksSP.pcx" }, - { "sp_gravity_on_port_up.EDITOR.xpos", "0" }, - { "sp_gravity_on_port_up.EDITOR.ypos", "2" }, + { "sp_gravity_on_port_up.EDITOR.xpos", "3" }, + { "sp_gravity_on_port_up.EDITOR.ypos", "13" }, { "sp_gravity_off_port_right", "RocksSP.pcx" }, { "sp_gravity_off_port_right.xpos", "1" }, { "sp_gravity_off_port_right.ypos", "1" }, { "sp_gravity_off_port_right.frames", "1" }, { "sp_gravity_off_port_right.EDITOR", "RocksSP.pcx" }, - { "sp_gravity_off_port_right.EDITOR.xpos", "5" }, - { "sp_gravity_off_port_right.EDITOR.ypos", "1" }, + { "sp_gravity_off_port_right.EDITOR.xpos", "4" }, + { "sp_gravity_off_port_right.EDITOR.ypos", "13" }, { "sp_gravity_off_port_down", "RocksSP.pcx" }, { "sp_gravity_off_port_down.xpos", "2" }, { "sp_gravity_off_port_down.ypos", "1" }, { "sp_gravity_off_port_down.frames", "1" }, { "sp_gravity_off_port_down.EDITOR", "RocksSP.pcx" }, - { "sp_gravity_off_port_down.EDITOR.xpos", "6" }, - { "sp_gravity_off_port_down.EDITOR.ypos", "1" }, + { "sp_gravity_off_port_down.EDITOR.xpos", "5" }, + { "sp_gravity_off_port_down.EDITOR.ypos", "13" }, { "sp_gravity_off_port_left", "RocksSP.pcx" }, { "sp_gravity_off_port_left.xpos", "3" }, { "sp_gravity_off_port_left.ypos", "1" }, { "sp_gravity_off_port_left.frames", "1" }, { "sp_gravity_off_port_left.EDITOR", "RocksSP.pcx" }, - { "sp_gravity_off_port_left.EDITOR.xpos", "7" }, - { "sp_gravity_off_port_left.EDITOR.ypos", "1" }, + { "sp_gravity_off_port_left.EDITOR.xpos", "6" }, + { "sp_gravity_off_port_left.EDITOR.ypos", "13" }, { "sp_gravity_off_port_up", "RocksSP.pcx" }, { "sp_gravity_off_port_up.xpos", "4" }, { "sp_gravity_off_port_up.ypos", "1" }, { "sp_gravity_off_port_up.frames", "1" }, { "sp_gravity_off_port_up.EDITOR", "RocksSP.pcx" }, - { "sp_gravity_off_port_up.EDITOR.xpos", "0" }, - { "sp_gravity_off_port_up.EDITOR.ypos", "2" }, + { "sp_gravity_off_port_up.EDITOR.xpos", "7" }, + { "sp_gravity_off_port_up.EDITOR.ypos", "13" }, { "sp_sniksnak", "RocksSP.pcx" }, { "sp_sniksnak.xpos", "1" }, @@ -727,7 +755,7 @@ struct ConfigInfo image_config[] = { "sp_electron.exploding.xpos", "8" }, { "sp_electron.exploding.ypos", "4" }, { "sp_electron.exploding.frames", "8" }, - { "sp_electron.exploding.delay", "3" }, + { "sp_electron.exploding.delay", "4" }, { "sp_electron.exploding.anim_mode", "linear" }, { "sp_terminal", "RocksSP.pcx" }, @@ -759,7 +787,8 @@ struct ConfigInfo image_config[] = { "sp_buggy_base.active.xpos", "8" }, { "sp_buggy_base.active.ypos", "6" }, { "sp_buggy_base.active.frames", "4" }, - { "sp_buggy_base.active.anim_mode", "random" }, + { "sp_buggy_base.active.delay", "4" }, + { "sp_buggy_base.active.anim_mode", "pingpong" }, { "sp_hardware_base_1", "RocksSP.pcx" }, { "sp_hardware_base_1.xpos", "4" }, @@ -4352,6 +4381,16 @@ struct ConfigInfo image_config[] = #endif #endif + { "sp_frame_horizontal", "RocksSP.pcx" }, + { "sp_frame_horizontal.xpos", "7" }, + { "sp_frame_horizontal.ypos", "14" }, + { "sp_frame_vertical", "RocksSP.pcx" }, + { "sp_frame_vertical.xpos", "6" }, + { "sp_frame_vertical.ypos", "14" }, + { "sp_frame_corner", "RocksSP.pcx" }, + { "sp_frame_corner.xpos", "5" }, + { "sp_frame_corner.ypos", "14" }, + { "toon_1", "RocksToons.pcx" }, { "toon_1.x", "2" }, { "toon_1.y", "72" }, @@ -5370,10 +5409,16 @@ struct ConfigInfo image_config[] = { "menu.draw_yoffset.SETUP[ARTWORK]", "0" }, { "menu.draw_xoffset.SETUP[INPUT]", "0" }, { "menu.draw_yoffset.SETUP[INPUT]", "0" }, + { "menu.draw_xoffset.SETUP[SHORTCUTS]", "0" }, + { "menu.draw_yoffset.SETUP[SHORTCUTS]", "0" }, { "menu.draw_xoffset.SETUP[SHORTCUTS_1]", "0" }, { "menu.draw_yoffset.SETUP[SHORTCUTS_1]", "0" }, { "menu.draw_xoffset.SETUP[SHORTCUTS_2]", "0" }, { "menu.draw_yoffset.SETUP[SHORTCUTS_2]", "0" }, + { "menu.draw_xoffset.SETUP[SHORTCUTS_3]", "0" }, + { "menu.draw_yoffset.SETUP[SHORTCUTS_3]", "0" }, + { "menu.draw_xoffset.SETUP[SHORTCUTS_4]", "0" }, + { "menu.draw_yoffset.SETUP[SHORTCUTS_4]", "0" }, { "menu.draw_xoffset.SETUP[CHOOSE_ARTWORK]", "0" }, { "menu.draw_yoffset.SETUP[CHOOSE_ARTWORK]", "0" }, { "menu.draw_xoffset.SETUP[CHOOSE_OTHER]", "0" }, @@ -5797,6 +5842,15 @@ struct ConfigInfo image_config[] = { "game.panel.time_ss.draw_masked", "true" }, { "game.panel.time_ss.draw_order", "0" }, + { "game.panel.frame.x", "-1" }, + { "game.panel.frame.y", "-1" }, + { "game.panel.frame.align", "left" }, + { "game.panel.frame.valign", "top" }, + { "game.panel.frame.digits", "-1" }, + { "game.panel.frame.font", "font.text_2" }, + { "game.panel.frame.draw_masked", "true" }, + { "game.panel.frame.draw_order", "0" }, + { "game.panel.shield_normal.x", "-1" }, { "game.panel.shield_normal.y", "-1" }, { "game.panel.shield_normal.tile_size", "16" }, @@ -6344,11 +6398,52 @@ struct ConfigInfo image_config[] = { "game.forced_scroll_delay_value", "-1" }, { "game.use_native_emc_graphics_engine", "false" }, + { "game.use_native_sp_graphics_engine", "true" }, + { "game.use_masked_pushing", "false" }, { "[player].boring_delay_fixed", "1000" }, { "[player].boring_delay_random", "1000" }, { "[player].sleeping_delay_fixed", "2000" }, { "[player].sleeping_delay_random", "2000" }, + { "viewport.window.width", "672" }, + { "viewport.window.height", "560" }, + { "viewport.playfield.x", "6" }, + { "viewport.playfield.y", "6" }, + { "viewport.playfield.width", "548" }, + { "viewport.playfield.height", "548" }, + { "viewport.playfield.border_size", "2" }, + { "viewport.playfield.MAIN.x", ARG_DEFAULT }, + { "viewport.playfield.MAIN.y", ARG_DEFAULT }, + { "viewport.playfield.MAIN.width", ARG_DEFAULT }, + { "viewport.playfield.MAIN.height", ARG_DEFAULT }, + { "viewport.playfield.MAIN.border_size", ARG_DEFAULT }, + { "viewport.playfield.PLAYING.x", ARG_DEFAULT }, + { "viewport.playfield.PLAYING.y", ARG_DEFAULT }, + { "viewport.playfield.PLAYING.width", ARG_DEFAULT }, + { "viewport.playfield.PLAYING.height", ARG_DEFAULT }, + { "viewport.playfield.PLAYING.border_size", ARG_DEFAULT }, + { "viewport.playfield.EDITOR.x", ARG_DEFAULT }, + { "viewport.playfield.EDITOR.y", ARG_DEFAULT }, + { "viewport.playfield.EDITOR.width", ARG_DEFAULT }, + { "viewport.playfield.EDITOR.height", ARG_DEFAULT }, + { "viewport.playfield.EDITOR.border_size", ARG_DEFAULT }, + { "viewport.door_1.x", "566" }, + { "viewport.door_1.y", "60" }, + { "viewport.door_1.MAIN.x", ARG_DEFAULT }, + { "viewport.door_1.MAIN.y", ARG_DEFAULT }, + { "viewport.door_1.PLAYING.x", ARG_DEFAULT }, + { "viewport.door_1.PLAYING.y", ARG_DEFAULT }, + { "viewport.door_1.EDITOR.x", ARG_DEFAULT }, + { "viewport.door_1.EDITOR.y", ARG_DEFAULT }, + { "viewport.door_2.x", "566" }, + { "viewport.door_2.y", "400" }, + { "viewport.door_2.MAIN.x", ARG_DEFAULT }, + { "viewport.door_2.MAIN.y", ARG_DEFAULT }, + { "viewport.door_2.PLAYING.x", ARG_DEFAULT }, + { "viewport.door_2.PLAYING.y", ARG_DEFAULT }, + { "viewport.door_2.EDITOR.x", "566" }, + { "viewport.door_2.EDITOR.y", "356" }, + { NULL, NULL } }; diff --git a/src/conf_gfx.h b/src/conf_gfx.h index 471937df..a8557b04 100644 --- a/src/conf_gfx.h +++ b/src/conf_gfx.h @@ -81,1737 +81,1744 @@ #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 */ diff --git a/src/conf_var.c b/src/conf_var.c index f0993e6e..e12f0015 100644 --- a/src/conf_var.c +++ b/src/conf_var.c @@ -1288,6 +1288,14 @@ struct TokenIntPtrInfo image_config_vars[] = "menu.draw_yoffset.SETUP[INPUT]", &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_INPUT] }, + { + "menu.draw_xoffset.SETUP[SHORTCUTS]", + &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS] + }, + { + "menu.draw_yoffset.SETUP[SHORTCUTS]", + &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS] + }, { "menu.draw_xoffset.SETUP[SHORTCUTS_1]", &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_1] @@ -1304,6 +1312,22 @@ struct TokenIntPtrInfo image_config_vars[] = "menu.draw_yoffset.SETUP[SHORTCUTS_2]", &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_2] }, + { + "menu.draw_xoffset.SETUP[SHORTCUTS_3]", + &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_3] + }, + { + "menu.draw_yoffset.SETUP[SHORTCUTS_3]", + &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_3] + }, + { + "menu.draw_xoffset.SETUP[SHORTCUTS_4]", + &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_4] + }, + { + "menu.draw_yoffset.SETUP[SHORTCUTS_4]", + &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS_4] + }, { "menu.draw_xoffset.SETUP[CHOOSE_ARTWORK]", &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_CHOOSE_ARTWORK] @@ -2912,6 +2936,38 @@ struct TokenIntPtrInfo image_config_vars[] = "game.panel.time_ss.draw_order", &game.panel.time_ss.sort_priority }, + { + "game.panel.frame.x", + &game.panel.frame.x + }, + { + "game.panel.frame.y", + &game.panel.frame.y + }, + { + "game.panel.frame.align", + &game.panel.frame.align + }, + { + "game.panel.frame.valign", + &game.panel.frame.valign + }, + { + "game.panel.frame.digits", + &game.panel.frame.size + }, + { + "game.panel.frame.font", + &game.panel.frame.font + }, + { + "game.panel.frame.draw_masked", + &game.panel.frame.draw_masked + }, + { + "game.panel.frame.draw_order", + &game.panel.frame.sort_priority + }, { "game.panel.shield_normal.x", &game.panel.shield_normal.x @@ -5012,6 +5068,14 @@ struct TokenIntPtrInfo image_config_vars[] = "game.use_native_emc_graphics_engine", &game.use_native_emc_graphics_engine }, + { + "game.use_native_sp_graphics_engine", + &game.use_native_sp_graphics_engine + }, + { + "game.use_masked_pushing", + &game.use_masked_pushing + }, { "[player].boring_delay_fixed", &game.player_boring_delay_fixed @@ -5028,6 +5092,158 @@ struct TokenIntPtrInfo image_config_vars[] = "[player].sleeping_delay_random", &game.player_sleeping_delay_random }, + { + "viewport.window.width", + &viewport.window.width + }, + { + "viewport.window.height", + &viewport.window.height + }, + { + "viewport.playfield.x", + &viewport.playfield[GFX_SPECIAL_ARG_DEFAULT].x + }, + { + "viewport.playfield.y", + &viewport.playfield[GFX_SPECIAL_ARG_DEFAULT].y + }, + { + "viewport.playfield.width", + &viewport.playfield[GFX_SPECIAL_ARG_DEFAULT].width + }, + { + "viewport.playfield.height", + &viewport.playfield[GFX_SPECIAL_ARG_DEFAULT].height + }, + { + "viewport.playfield.border_size", + &viewport.playfield[GFX_SPECIAL_ARG_DEFAULT].border_size + }, + { + "viewport.playfield.MAIN.x", + &viewport.playfield[GFX_SPECIAL_ARG_MAIN].x + }, + { + "viewport.playfield.MAIN.y", + &viewport.playfield[GFX_SPECIAL_ARG_MAIN].y + }, + { + "viewport.playfield.MAIN.width", + &viewport.playfield[GFX_SPECIAL_ARG_MAIN].width + }, + { + "viewport.playfield.MAIN.height", + &viewport.playfield[GFX_SPECIAL_ARG_MAIN].height + }, + { + "viewport.playfield.MAIN.border_size", + &viewport.playfield[GFX_SPECIAL_ARG_MAIN].border_size + }, + { + "viewport.playfield.PLAYING.x", + &viewport.playfield[GFX_SPECIAL_ARG_PLAYING].x + }, + { + "viewport.playfield.PLAYING.y", + &viewport.playfield[GFX_SPECIAL_ARG_PLAYING].y + }, + { + "viewport.playfield.PLAYING.width", + &viewport.playfield[GFX_SPECIAL_ARG_PLAYING].width + }, + { + "viewport.playfield.PLAYING.height", + &viewport.playfield[GFX_SPECIAL_ARG_PLAYING].height + }, + { + "viewport.playfield.PLAYING.border_size", + &viewport.playfield[GFX_SPECIAL_ARG_PLAYING].border_size + }, + { + "viewport.playfield.EDITOR.x", + &viewport.playfield[GFX_SPECIAL_ARG_EDITOR].x + }, + { + "viewport.playfield.EDITOR.y", + &viewport.playfield[GFX_SPECIAL_ARG_EDITOR].y + }, + { + "viewport.playfield.EDITOR.width", + &viewport.playfield[GFX_SPECIAL_ARG_EDITOR].width + }, + { + "viewport.playfield.EDITOR.height", + &viewport.playfield[GFX_SPECIAL_ARG_EDITOR].height + }, + { + "viewport.playfield.EDITOR.border_size", + &viewport.playfield[GFX_SPECIAL_ARG_EDITOR].border_size + }, + { + "viewport.door_1.x", + &viewport.door_1[GFX_SPECIAL_ARG_DEFAULT].x + }, + { + "viewport.door_1.y", + &viewport.door_1[GFX_SPECIAL_ARG_DEFAULT].y + }, + { + "viewport.door_1.MAIN.x", + &viewport.door_1[GFX_SPECIAL_ARG_MAIN].x + }, + { + "viewport.door_1.MAIN.y", + &viewport.door_1[GFX_SPECIAL_ARG_MAIN].y + }, + { + "viewport.door_1.PLAYING.x", + &viewport.door_1[GFX_SPECIAL_ARG_PLAYING].x + }, + { + "viewport.door_1.PLAYING.y", + &viewport.door_1[GFX_SPECIAL_ARG_PLAYING].y + }, + { + "viewport.door_1.EDITOR.x", + &viewport.door_1[GFX_SPECIAL_ARG_EDITOR].x + }, + { + "viewport.door_1.EDITOR.y", + &viewport.door_1[GFX_SPECIAL_ARG_EDITOR].y + }, + { + "viewport.door_2.x", + &viewport.door_2[GFX_SPECIAL_ARG_DEFAULT].x + }, + { + "viewport.door_2.y", + &viewport.door_2[GFX_SPECIAL_ARG_DEFAULT].y + }, + { + "viewport.door_2.MAIN.x", + &viewport.door_2[GFX_SPECIAL_ARG_MAIN].x + }, + { + "viewport.door_2.MAIN.y", + &viewport.door_2[GFX_SPECIAL_ARG_MAIN].y + }, + { + "viewport.door_2.PLAYING.x", + &viewport.door_2[GFX_SPECIAL_ARG_PLAYING].x + }, + { + "viewport.door_2.PLAYING.y", + &viewport.door_2[GFX_SPECIAL_ARG_PLAYING].y + }, + { + "viewport.door_2.EDITOR.x", + &viewport.door_2[GFX_SPECIAL_ARG_EDITOR].x + }, + { + "viewport.door_2.EDITOR.y", + &viewport.door_2[GFX_SPECIAL_ARG_EDITOR].y + }, { NULL, NULL diff --git a/src/conftime.h b/src/conftime.h index e3b6bfc9..9be48364 100644 --- a/src/conftime.h +++ b/src/conftime.h @@ -1 +1 @@ -#define COMPILE_DATE_STRING "2009-06-15 22:46" +#define COMPILE_DATE_STRING "2010-05-25 22:42" diff --git a/src/editor.c b/src/editor.c index 5fb4dd93..5752d742 100644 --- a/src/editor.c +++ b/src/editor.c @@ -576,51 +576,52 @@ #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) @@ -815,50 +816,51 @@ #define ED_CHECKBUTTON_ID_RANDOM_BALL_CONTENT 6 #define ED_CHECKBUTTON_ID_INITIAL_BALL_STATE 7 #define ED_CHECKBUTTON_ID_GROW_INTO_DIGGABLE 8 -#define ED_CHECKBUTTON_ID_CONTINUOUS_SNAPPING 9 -#define ED_CHECKBUTTON_ID_BLOCK_SNAP_FIELD 10 -#define ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD 11 -#define ED_CHECKBUTTON_ID_SP_BLOCK_LAST_FIELD 12 -#define ED_CHECKBUTTON_ID_INSTANT_RELOCATION 13 -#define ED_CHECKBUTTON_ID_SHIFTED_RELOCATION 14 -#define ED_CHECKBUTTON_ID_USE_START_ELEMENT 15 -#define ED_CHECKBUTTON_ID_USE_ARTWORK_ELEMENT 16 -#define ED_CHECKBUTTON_ID_USE_EXPLOSION_ELEMENT 17 -#define ED_CHECKBUTTON_ID_INITIAL_GRAVITY 18 -#define ED_CHECKBUTTON_ID_USE_INITIAL_INVENTORY 19 -#define ED_CHECKBUTTON_ID_CAN_PASS_TO_WALKABLE 20 -#define ED_CHECKBUTTON_ID_CAN_FALL_INTO_ACID 21 -#define ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID 22 -#define ED_CHECKBUTTON_ID_DONT_COLLIDE_WITH 23 -#define ED_CHECKBUTTON_ID_ENVELOPE_AUTOWRAP 24 -#define ED_CHECKBUTTON_ID_ENVELOPE_CENTERED 25 -#define ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC 26 -#define ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE 27 -#define ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE 28 -#define ED_CHECKBUTTON_ID_CUSTOM_GRAV_REACHABLE 29 -#define ED_CHECKBUTTON_ID_CUSTOM_USE_LAST_VALUE 30 -#define ED_CHECKBUTTON_ID_CUSTOM_WALK_TO_OBJECT 31 -#define ED_CHECKBUTTON_ID_CUSTOM_INDESTRUCTIBLE 32 -#define ED_CHECKBUTTON_ID_CUSTOM_CAN_MOVE 33 -#define ED_CHECKBUTTON_ID_CUSTOM_CAN_FALL 34 -#define ED_CHECKBUTTON_ID_CUSTOM_CAN_SMASH 35 -#define ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY 36 -#define ED_CHECKBUTTON_ID_CUSTOM_DEADLY 37 -#define ED_CHECKBUTTON_ID_CUSTOM_CAN_EXPLODE 38 -#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_FIRE 39 -#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_SMASH 40 -#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT 41 -#define ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE 42 -#define ED_CHECKBUTTON_ID_CHANGE_DELAY 43 -#define ED_CHECKBUTTON_ID_CHANGE_BY_DIRECT_ACT 44 -#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER_ACT 45 -#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION 46 -#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT 47 -#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE 48 -#define ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM 49 -#define ED_CHECKBUTTON_ID_CHANGE_HAS_ACTION 50 - -#define ED_NUM_CHECKBUTTONS 51 +#define ED_CHECKBUTTON_ID_AUTO_EXIT_SOKOBAN 9 +#define ED_CHECKBUTTON_ID_CONTINUOUS_SNAPPING 10 +#define ED_CHECKBUTTON_ID_BLOCK_SNAP_FIELD 11 +#define ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD 12 +#define ED_CHECKBUTTON_ID_SP_BLOCK_LAST_FIELD 13 +#define ED_CHECKBUTTON_ID_INSTANT_RELOCATION 14 +#define ED_CHECKBUTTON_ID_SHIFTED_RELOCATION 15 +#define ED_CHECKBUTTON_ID_USE_START_ELEMENT 16 +#define ED_CHECKBUTTON_ID_USE_ARTWORK_ELEMENT 17 +#define ED_CHECKBUTTON_ID_USE_EXPLOSION_ELEMENT 18 +#define ED_CHECKBUTTON_ID_INITIAL_GRAVITY 19 +#define ED_CHECKBUTTON_ID_USE_INITIAL_INVENTORY 20 +#define ED_CHECKBUTTON_ID_CAN_PASS_TO_WALKABLE 21 +#define ED_CHECKBUTTON_ID_CAN_FALL_INTO_ACID 22 +#define ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID 23 +#define ED_CHECKBUTTON_ID_DONT_COLLIDE_WITH 24 +#define ED_CHECKBUTTON_ID_ENVELOPE_AUTOWRAP 25 +#define ED_CHECKBUTTON_ID_ENVELOPE_CENTERED 26 +#define ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC 27 +#define ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE 28 +#define ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE 29 +#define ED_CHECKBUTTON_ID_CUSTOM_GRAV_REACHABLE 30 +#define ED_CHECKBUTTON_ID_CUSTOM_USE_LAST_VALUE 31 +#define ED_CHECKBUTTON_ID_CUSTOM_WALK_TO_OBJECT 32 +#define ED_CHECKBUTTON_ID_CUSTOM_INDESTRUCTIBLE 33 +#define ED_CHECKBUTTON_ID_CUSTOM_CAN_MOVE 34 +#define ED_CHECKBUTTON_ID_CUSTOM_CAN_FALL 35 +#define ED_CHECKBUTTON_ID_CUSTOM_CAN_SMASH 36 +#define ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY 37 +#define ED_CHECKBUTTON_ID_CUSTOM_DEADLY 38 +#define ED_CHECKBUTTON_ID_CUSTOM_CAN_EXPLODE 39 +#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_FIRE 40 +#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_SMASH 41 +#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT 42 +#define ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE 43 +#define ED_CHECKBUTTON_ID_CHANGE_DELAY 44 +#define ED_CHECKBUTTON_ID_CHANGE_BY_DIRECT_ACT 45 +#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER_ACT 46 +#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION 47 +#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT 48 +#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE 49 +#define ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM 50 +#define ED_CHECKBUTTON_ID_CHANGE_HAS_ACTION 51 + +#define ED_NUM_CHECKBUTTONS 52 #define ED_CHECKBUTTON_ID_EDITOR_FIRST ED_CHECKBUTTON_ID_RANDOM_RESTRICTED #define ED_CHECKBUTTON_ID_EDITOR_LAST ED_CHECKBUTTON_ID_RANDOM_RESTRICTED @@ -1045,7 +1047,11 @@ static struct /* ---------- current level number --------------------------------------- */ { +#if 1 + -1, -1, /* these values are not constant, but can change at runtime */ +#else DX + 5 - SX, DY + 3 - SY, +#endif 1, 100, GADGET_ID_SELECT_LEVEL_DOWN, GADGET_ID_SELECT_LEVEL_UP, GADGET_ID_SELECT_LEVEL_TEXT, GADGET_ID_NONE, @@ -1398,6 +1404,7 @@ static struct ValueTextInfo options_game_engine_type[] = { { GAME_ENGINE_TYPE_RND, "Rocks'n'Diamonds" }, { GAME_ENGINE_TYPE_EM, "Emerald Mine" }, + { GAME_ENGINE_TYPE_SP, "Supaplex" }, { -1, NULL } }; @@ -2471,25 +2478,41 @@ static struct { { ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 0 * ED_SCROLLBUTTON_YSIZE, +#if 1 + -1, -1, /* these values are not constant, but can change at runtime */ +#else ED_SCROLL_UP_XPOS, ED_SCROLL_UP_YPOS, +#endif GADGET_ID_SCROLL_UP, "scroll level editing area up" }, { ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 1 * ED_SCROLLBUTTON_YSIZE, +#if 1 + -1, -1, /* these values are not constant, but can change at runtime */ +#else ED_SCROLL_DOWN_XPOS, ED_SCROLL_DOWN_YPOS, +#endif GADGET_ID_SCROLL_DOWN, "scroll level editing area down" }, { ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 2 * ED_SCROLLBUTTON_YSIZE, +#if 1 + -1, -1, /* these values are not constant, but can change at runtime */ +#else ED_SCROLL_LEFT_XPOS, ED_SCROLL_LEFT_YPOS, +#endif GADGET_ID_SCROLL_LEFT, "scroll level editing area left" }, { ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 3 * ED_SCROLLBUTTON_YSIZE, +#if 1 + -1, -1, /* these values are not constant, but can change at runtime */ +#else ED_SCROLL_RIGHT_XPOS, ED_SCROLL_RIGHT_YPOS, +#endif GADGET_ID_SCROLL_RIGHT, "scroll level editing area right" }, @@ -2521,14 +2544,16 @@ static struct { { ED_SCROLLBAR_XPOS, ED_SCROLLBAR_YPOS, +#if 1 + -1, -1, /* these values are not constant, but can change at runtime */ + -1, -1, /* these values are not constant, but can change at runtime */ + -1, -1, /* these values are not constant, but can change at runtime */ + -1, -1, /* these values are not constant, but can change at runtime */ +#else SX + ED_SCROLL_HORIZONTAL_XPOS, SY + ED_SCROLL_HORIZONTAL_YPOS, ED_SCROLL_HORIZONTAL_XSIZE, ED_SCROLL_HORIZONTAL_YSIZE, -#if 1 SX, SY, SXSIZE, SYSIZE, -#else - 0, 0, - SX + SXSIZE + SX, WIN_YSIZE, #endif GD_TYPE_SCROLLBAR_HORIZONTAL, GADGET_ID_SCROLL_HORIZONTAL, @@ -2536,14 +2561,16 @@ static struct }, { ED_SCROLLBAR_XPOS, ED_SCROLLBAR_YPOS, +#if 1 + -1, -1, /* these values are not constant, but can change at runtime */ + -1, -1, /* these values are not constant, but can change at runtime */ + -1, -1, /* these values are not constant, but can change at runtime */ + -1, -1, /* these values are not constant, but can change at runtime */ +#else SX + ED_SCROLL_VERTICAL_XPOS, SY + ED_SCROLL_VERTICAL_YPOS, ED_SCROLL_VERTICAL_XSIZE, ED_SCROLL_VERTICAL_YSIZE, -#if 1 SX, SY, SXSIZE, SYSIZE, -#else - 0, 0, - SX + SXSIZE + SX, WIN_YSIZE, #endif GD_TYPE_SCROLLBAR_VERTICAL, GADGET_ID_SCROLL_VERTICAL, @@ -2551,15 +2578,16 @@ static struct }, { ED_SCROLLBAR2_XPOS, ED_SCROLLBAR2_YPOS, +#if 1 + -1, -1, /* these values are not constant, but can change at runtime */ + ED_SCROLL2_VERTICAL_XSIZE, ED_SCROLL2_VERTICAL_YSIZE, + -1, -1, /* these values are not constant, but can change at runtime */ +#else DX + ED_SCROLL2_VERTICAL_XPOS, DY + ED_SCROLL2_VERTICAL_YPOS, ED_SCROLL2_VERTICAL_XSIZE, ED_SCROLL2_VERTICAL_YSIZE, -#if 1 DX, DY, - DXSIZE, DYSIZE, -#else - SX + SXSIZE + SX, 0, - WIN_XSIZE - (SX + SXSIZE + SX), WIN_YSIZE, #endif + DXSIZE, DYSIZE, GD_TYPE_SCROLLBAR_VERTICAL, GADGET_ID_SCROLL_LIST_VERTICAL, "scroll element list vertically" @@ -2670,6 +2698,13 @@ static struct NULL, "can grow into anything diggable", "grow into more than just sand" }, + { + ED_ELEMENT_SETTINGS_XPOS(0), ED_ELEMENT_SETTINGS_YPOS(0), + GADGET_ID_AUTO_EXIT_SOKOBAN, GADGET_ID_NONE, + &level.auto_exit_sokoban, + NULL, + "exit level if all fields solved", "automatically finish Sokoban levels" + }, { ED_ELEMENT_SETTINGS_XPOS(0), ED_ELEMENT_SETTINGS_YPOS(8), GADGET_ID_CONTINUOUS_SNAPPING, GADGET_ID_NONE, @@ -2997,7 +3032,12 @@ static struct { 0, 0, GADGET_ID_DRAWING_LEVEL, GADGET_ID_NONE, - NULL, MAX_ED_FIELDX, MAX_ED_FIELDY, + NULL, +#if 1 + -1, -1, /* these values are not constant, but can change at runtime */ +#else + MAX_ED_FIELDX, MAX_ED_FIELDY, +#endif NULL, NULL, NULL, NULL }, @@ -3259,7 +3299,11 @@ static struct */ /* actual size of level editor drawing area */ +#if 1 +static int ed_fieldx, ed_fieldy; +#else static int ed_fieldx = MAX_ED_FIELDX - 1, ed_fieldy = MAX_ED_FIELDY - 1; +#endif /* actual position of level editor drawing area in level playfield */ static int level_xpos = -1, level_ypos = -1; @@ -3704,6 +3748,16 @@ static int editor_el_supaplex[] = EL_SP_GRAVITY_PORT_UP, EL_SP_GRAVITY_PORT_DOWN, + EL_SP_GRAVITY_ON_PORT_LEFT, + EL_SP_GRAVITY_ON_PORT_RIGHT, + EL_SP_GRAVITY_ON_PORT_UP, + EL_SP_GRAVITY_ON_PORT_DOWN, + + EL_SP_GRAVITY_OFF_PORT_LEFT, + EL_SP_GRAVITY_OFF_PORT_RIGHT, + EL_SP_GRAVITY_OFF_PORT_UP, + EL_SP_GRAVITY_OFF_PORT_DOWN, + EL_SP_HARDWARE_GRAY, EL_SP_HARDWARE_GREEN, EL_SP_HARDWARE_BLUE, @@ -5138,38 +5192,10 @@ static void DrawDrawingArea(int id) static void ScrollMiniLevel(int from_x, int from_y, int scroll) { -#if 0 - /* (directly solved in BlitBitmap() now) */ - static Bitmap *tmp_backbuffer = NULL; -#endif int x, y; int dx = (scroll == ED_SCROLL_LEFT ? -1 : scroll == ED_SCROLL_RIGHT ? 1 : 0); int dy = (scroll == ED_SCROLL_UP ? -1 : scroll == ED_SCROLL_DOWN ? 1 : 0); -#if 0 - /* (directly solved in BlitBitmap() now) */ - if (tmp_backbuffer == NULL) - tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH); - - /* needed when blitting directly to same bitmap -- should not be needed with - recent SDL libraries, but apparently does not work in 1.2.11 directly */ - BlitBitmap(drawto, tmp_backbuffer, - SX + (dx == -1 ? MINI_TILEX : 0), - SY + (dy == -1 ? MINI_TILEY : 0), - (ed_fieldx * MINI_TILEX) - (dx != 0 ? MINI_TILEX : 0), - (ed_fieldy * MINI_TILEY) - (dy != 0 ? MINI_TILEY : 0), - SX + (dx == +1 ? MINI_TILEX : 0), - SY + (dy == +1 ? MINI_TILEY : 0)); - BlitBitmap(tmp_backbuffer, drawto, - SX + (dx == +1 ? MINI_TILEX : 0), - SY + (dy == +1 ? MINI_TILEY : 0), - (ed_fieldx * MINI_TILEX) - (dx != 0 ? MINI_TILEX : 0), - (ed_fieldy * MINI_TILEY) - (dy != 0 ? MINI_TILEY : 0), - SX + (dx == +1 ? MINI_TILEX : 0), - SY + (dy == +1 ? MINI_TILEY : 0)); - -#else - BlitBitmap(drawto, drawto, SX + (dx == -1 ? MINI_TILEX : 0), SY + (dy == -1 ? MINI_TILEY : 0), @@ -5177,7 +5203,6 @@ static void ScrollMiniLevel(int from_x, int from_y, int scroll) (ed_fieldy * MINI_TILEY) - (dy != 0 ? MINI_TILEY : 0), SX + (dx == +1 ? MINI_TILEX : 0), SY + (dy == +1 ? MINI_TILEY : 0)); -#endif if (dx) { @@ -5335,6 +5360,16 @@ static void CreateControlButtons() level_editor_gadget[id] = gi; } + /* these values are not constant, but can change at runtime */ + scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_UP].x = ED_SCROLL_UP_XPOS; + scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_UP].y = ED_SCROLL_UP_YPOS; + scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_DOWN].x = ED_SCROLL_DOWN_XPOS; + scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_DOWN].y = ED_SCROLL_DOWN_YPOS; + scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_LEFT].x = ED_SCROLL_LEFT_XPOS; + scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_LEFT].y = ED_SCROLL_LEFT_YPOS; + scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_RIGHT].x = ED_SCROLL_RIGHT_XPOS; + scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_RIGHT].y = ED_SCROLL_RIGHT_YPOS; + /* create buttons for scrolling of drawing area and element list */ for (i = 0; i < ED_NUM_SCROLLBUTTONS; i++) { @@ -5450,6 +5485,10 @@ static void CreateCounterButtons() int max_infotext_len = getMaxInfoTextLength(); int i; + /* these values are not constant, but can change at runtime */ + counterbutton_info[ED_COUNTER_ID_SELECT_LEVEL].x = DX + 5 - SX; + counterbutton_info[ED_COUNTER_ID_SELECT_LEVEL].y = DY + 3 - SY; + for (i = 0; i < ED_NUM_COUNTERBUTTONS; i++) { int j; @@ -5604,6 +5643,10 @@ static void CreateDrawingAreas() { int i; + /* these values are not constant, but can change at runtime */ + drawingarea_info[ED_DRAWING_ID_DRAWING_LEVEL].area_xsize = MAX_ED_FIELDX; + drawingarea_info[ED_DRAWING_ID_DRAWING_LEVEL].area_ysize = MAX_ED_FIELDY; + for (i = 0; i < ED_NUM_DRAWING_AREAS; i++) { struct GadgetInfo *gi; @@ -5971,6 +6014,40 @@ static void CreateScrollbarGadgets() { int i; + /* these values are not constant, but can change at runtime */ + scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].x = + SX + ED_SCROLL_HORIZONTAL_XPOS; + scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].y = + SY + ED_SCROLL_HORIZONTAL_YPOS; + scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].width = + ED_SCROLL_HORIZONTAL_XSIZE; + scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].height = + ED_SCROLL_HORIZONTAL_YSIZE; + scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].wheel_x = SX; + scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].wheel_y = SY; + scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].wheel_width = SXSIZE; + scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].wheel_height = SYSIZE; + + scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].x = + SX + ED_SCROLL_VERTICAL_XPOS; + scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].y = + SY + ED_SCROLL_VERTICAL_YPOS; + scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].width = + ED_SCROLL_VERTICAL_XSIZE; + scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].height = + ED_SCROLL_VERTICAL_YSIZE; + scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].wheel_x = SX; + scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].wheel_y = SY; + scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].wheel_width = SXSIZE; + scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].wheel_height = SYSIZE; + + scrollbar_info[ED_SCROLLBAR_ID_LIST_VERTICAL].x = + DX + ED_SCROLL2_VERTICAL_XPOS; + scrollbar_info[ED_SCROLLBAR_ID_LIST_VERTICAL].y = + DY + ED_SCROLL2_VERTICAL_YPOS; + scrollbar_info[ED_SCROLLBAR_ID_LIST_VERTICAL].wheel_x = DX; + scrollbar_info[ED_SCROLLBAR_ID_LIST_VERTICAL].wheel_y = DY; + for (i = 0; i < ED_NUM_SCROLLBARS; i++) { int id = scrollbar_info[i].gadget_id; @@ -6173,6 +6250,10 @@ void CreateLevelEditorGadgets() /* setting 'game_status' is needed to get the right fonts for the editor */ game_status = GAME_MODE_EDITOR; + /* these values are not constant, but can change at runtime */ + ed_fieldx = MAX_ED_FIELDX - 1; + ed_fieldy = MAX_ED_FIELDY - 1; + ReinitializeElementList(); CreateControlButtons(); @@ -6610,8 +6691,12 @@ static boolean LevelChanged() boolean field_changed = FALSE; int x, y; +#if 1 + /* changed read-only levels can now be saved in personal level set */ +#else if (leveldir_current->readonly) return FALSE; +#endif for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++) @@ -6621,21 +6706,151 @@ static boolean LevelChanged() return (level.changed || field_changed); } -static boolean LevelContainsPlayer() +static boolean PrepareSavingIntoPersonalLevelSet() { - boolean player_found = FALSE; - int x, y; + static LevelDirTree *last_copied_leveldir = NULL; + static LevelDirTree *last_written_leveldir = NULL; + static int last_copied_level_nr = -1; + static int last_written_level_nr = -1; + LevelDirTree *leveldir_former = leveldir_current; + int level_nr_former = level_nr; + int new_level_nr; - return TRUE; /* !!! CURRENTLY DEACTIVATED !!! */ + // remember last mod/save so that for current session, we write + // back to the same personal copy, asking only about overwrite. + if (leveldir_current == last_copied_leveldir && + level_nr == last_copied_level_nr) + { + // "cd" to personal level set dir (as used when writing last copy) + leveldir_current = last_written_leveldir; + level_nr = last_written_level_nr; + + return TRUE; + } + + if (!Request("This level is read only ! " + "Save into personal level set ?", REQ_ASK)) + return FALSE; - for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++) + // "cd" to personal level set dir (for writing copy the first time) + leveldir_current = + getTreeInfoFromIdentifier(leveldir_first, getLoginName()); + + // find unused level number + for (new_level_nr = leveldir_current->first_level; ; new_level_nr++) { - if (Feld[x][y] == EL_PLAYER_1 || - Feld[x][y] == EL_SP_MURPHY) - player_found = TRUE; + static char *level_filename = NULL; + + setString(&level_filename, getDefaultLevelFilename(new_level_nr)); + + if (!fileExists(level_filename)) + break; } - return player_found; + last_copied_leveldir = leveldir_former; + last_copied_level_nr = level_nr_former; + + last_written_leveldir = leveldir_current; + last_written_level_nr = level_nr = new_level_nr; + + return TRUE; +} + +static void ModifyLevelInfoForSavingIntoPersonalLevelSet(char *former_name) +{ + static char *filename_levelinfo = NULL, *mod_name = NULL; + FILE *file; + + // annotate this copy-and-mod in personal levelinfo.conf + setString(&filename_levelinfo, + getPath2(getCurrentLevelDir(), LEVELINFO_FILENAME)); + + if ((file = fopen(filename_levelinfo, MODE_APPEND))) + { + fprintf(file, "\n"); + fprintf(file, "# level %d was modified from:\n", level_nr); + fprintf(file, "# - previous level set name: %s\n", + former_name); + fprintf(file, "# - level within previous set: %d \"%s\"\n", + level.file_info.nr, level.name); + fprintf(file, "# - previous author: %s\n", + level.author); + fprintf(file, "# - previous save date: "); + + if (level.creation_date.src == DATE_SRC_LEVELFILE) + { + fprintf(file, "%04d-%02d-%02d\n", + level.creation_date.year, + level.creation_date.month, + level.creation_date.day); + } + else + { + fprintf(file, "not recorded\n"); + } + + fclose(file); + } + + if (level_nr > leveldir_current->last_level) + { + static char *temp_levelinfo = NULL; + FILE *temp_file = NULL; + char line[MAX_LINE_LEN]; + + setString(&temp_levelinfo, + getPath2(getCurrentLevelDir(), + getStringCat2(LEVELINFO_FILENAME, ".new"))); + + if ((file = fopen(filename_levelinfo, MODE_READ)) && + (temp_file = fopen(temp_levelinfo, MODE_WRITE))) + { + while (fgets(line, MAX_LINE_LEN, file)) + { + if (!strPrefix(line, "levels:")) + fputs(line, temp_file); + else + fprintf(temp_file, "%-32s%d\n", "levels:", level_nr + 9); + } + } + + if (temp_file) + fclose(temp_file); + + if (file) + fclose(file); + + // needs error handling; also, ok on dos/win? + unlink(filename_levelinfo); + rename(temp_levelinfo, filename_levelinfo); + } + + // else: allow the save even if annotation failed + + // now... spray graffiti on the old level vital statistics + // user can change these; just trying to set a good baseline + + // don't truncate names for fear of making offensive or silly: + // long-named original author only recorded in levelinfo.conf. + // try to fit "Joe after Bob", "Joe (ed.)", then just "Joe" + if (!strEqual(level.author, leveldir_current->author)) + { + setString(&mod_name, getStringCat3(leveldir_current->author, + " after ", level.author)); + + if (strlen(mod_name) > MAX_LEVEL_AUTHOR_LEN) + setString(&mod_name, + getStringCat2(leveldir_current->author, " (ed.)")); + + if (strlen(mod_name) > MAX_LEVEL_AUTHOR_LEN) + setString(&mod_name, leveldir_current->author); + + strncpy(level.author, mod_name, MAX_LEVEL_AUTHOR_LEN); + + // less worried about truncation here + setString(&mod_name, getStringCat2("Mod: ", level.name)); + strncpy(level.name, mod_name, MAX_LEVEL_NAME_LEN); + } } static void CopyPlayfield(short src[MAX_LEV_FIELDX][MAX_LEV_FIELDY], @@ -7194,6 +7409,11 @@ void DrawLevelEd() FadeOut(REDRAW_FIELD); #endif +#if 1 + /* needed if different viewport properties defined for editor */ + ChangeViewportPropertiesIfNeeded(); +#endif + OpenDoor(DOOR_OPEN_2 | DOOR_NO_DELAY); #if DEBUG @@ -7223,6 +7443,10 @@ void DrawLevelEd() BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, DOOR_GFX_PAGEX6, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY); +#if 0 + printf("::: %d, %d / %d, %d\n", VX, VY, EX, EY); +#endif + /* draw bigger door */ DrawSpecialEditorDoor(); @@ -7232,6 +7456,11 @@ void DrawLevelEd() redraw_mask |= REDRAW_ALL; +#if 1 + FreeLevelEditorGadgets(); + CreateLevelEditorGadgets(); +#endif + ReinitializeElementList(); /* update dynamic level element list */ ReinitializeElementListButtons(); /* custom element may look different */ @@ -7944,7 +8173,7 @@ static int PrintElementDescriptionFromFile(char *filename, int start_line) int max_lines_per_screen = (SYSIZE - pad_y) / font_height - 1; return DrawTextFile(sx, sy, filename, font_nr, max_chars_per_line, -1, - max_lines_per_screen, -1, TRUE, FALSE, FALSE); + max_lines_per_screen, 0, -1, TRUE, FALSE, FALSE); } static void DrawPropertiesInfo() @@ -8212,7 +8441,10 @@ static boolean checkPropertiesConfig(int element) HAS_EDITOR_CONTENT(element) || CAN_GROW(element) || COULD_MOVE_INTO_ACID(element) || - MAYBE_DONT_COLLIDE_WITH(element)) + MAYBE_DONT_COLLIDE_WITH(element) || + element == EL_SOKOBAN_OBJECT || + element == EL_SOKOBAN_FIELD_EMPTY || + element == EL_SOKOBAN_FIELD_FULL) return TRUE; else for (i = 0; elements_with_counter[i].element != -1; i++) @@ -8406,6 +8638,11 @@ static void DrawPropertiesConfig() MapCheckbuttonGadget(ED_CHECKBUTTON_ID_GROW_INTO_DIGGABLE); } + if (properties_element == EL_SOKOBAN_OBJECT || + properties_element == EL_SOKOBAN_FIELD_EMPTY || + properties_element == EL_SOKOBAN_FIELD_FULL) + MapCheckbuttonGadget(ED_CHECKBUTTON_ID_AUTO_EXIT_SOKOBAN); + if (IS_ENVELOPE(properties_element)) { int counter1_id = ED_COUNTER_ID_ENVELOPE_XSIZE; @@ -9592,20 +9829,6 @@ static void SetElementIntelliDraw(int x, int y, int new_element, EL_SP_GRAVITY_PORT_LEFT }, - { - EL_MOLE_UP, - EL_MOLE_RIGHT, - EL_MOLE_DOWN, - EL_MOLE_LEFT - }, - - { - EL_BALLOON_SWITCH_UP, - EL_BALLOON_SWITCH_RIGHT, - EL_BALLOON_SWITCH_DOWN, - EL_BALLOON_SWITCH_LEFT - }, - { EL_SP_GRAVITY_ON_PORT_UP, EL_SP_GRAVITY_ON_PORT_RIGHT, @@ -9620,6 +9843,20 @@ static void SetElementIntelliDraw(int x, int y, int new_element, EL_SP_GRAVITY_OFF_PORT_LEFT }, + { + EL_MOLE_UP, + EL_MOLE_RIGHT, + EL_MOLE_DOWN, + EL_MOLE_LEFT + }, + + { + EL_BALLOON_SWITCH_UP, + EL_BALLOON_SWITCH_RIGHT, + EL_BALLOON_SWITCH_DOWN, + EL_BALLOON_SWITCH_LEFT + }, + { -1, -1, @@ -9887,7 +10124,11 @@ static void SelectArea(int from_x, int from_y, int to_x, int to_y, static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, int button, int mode) { +#if 1 + static short brush_buffer[MAX_LEV_FIELDX][MAX_LEV_FIELDY]; +#else static short brush_buffer[MAX_ED_FIELDX][MAX_ED_FIELDY]; +#endif static int brush_width, brush_height; static int last_cursor_x = -1, last_cursor_y = -1; static boolean delete_old_brush; @@ -10791,12 +11032,21 @@ static void HandleTextbuttonGadgets(struct GadgetInfo *gi) char *template_filename = getDefaultLevelFilename(-1); boolean new_template = !fileExists(template_filename); + /* backup original "level.field" (needed to track playfield changes) */ + CopyPlayfield(level.field, FieldBackup); + + /* "SaveLevelTemplate()" uses "level.field", so copy editor playfield */ + CopyPlayfield(Feld, level.field); + if (new_template || Request("Save this template and kill the old ?", REQ_ASK)) SaveLevelTemplate(); if (new_template) Request("Template saved !", REQ_CONFIRM); + + /* restore original "level.field" (needed to track playfield changes) */ + CopyPlayfield(FieldBackup, level.field); } else if (type_id == ED_TEXTBUTTON_ID_ADD_CHANGE_PAGE && custom_element.num_change_pages < MAX_CHANGE_PAGES) @@ -11200,60 +11450,78 @@ static void HandleControlButtons(struct GadgetInfo *gi) break; case GADGET_ID_SAVE: - if (leveldir_current->readonly) - { - Request("This level is read only !", REQ_CONFIRM); + { + /* saving read-only levels into personal level set modifies global vars + "leveldir_current" and "level_nr"; restore them after saving level */ + LevelDirTree *leveldir_former = leveldir_current; + int level_nr_former = level_nr; + char *level_filename; + boolean new_level; + + if (leveldir_current->readonly && + !PrepareSavingIntoPersonalLevelSet()) break; - } - if (!LevelContainsPlayer()) - Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM); - else + level_filename = getDefaultLevelFilename(level_nr); + new_level = !fileExists(level_filename); + + if (new_level || + Request("Save this level and kill the old ?", REQ_ASK)) { - char *level_filename = getDefaultLevelFilename(level_nr); - boolean new_level = !fileExists(level_filename); + if (leveldir_former->readonly) + ModifyLevelInfoForSavingIntoPersonalLevelSet(leveldir_former->name); - if (new_level || - Request("Save this level and kill the old ?", REQ_ASK)) - { - CopyPlayfield(Feld, level.field); + CopyPlayfield(Feld, level.field); + SaveLevel(level_nr); - SaveLevel(level_nr); - } + level.changed = FALSE; if (new_level) - Request("Level saved !", REQ_CONFIRM); + { + char level_saved_msg[64]; - level.changed = FALSE; + if (leveldir_former->readonly) + sprintf(level_saved_msg, + "Level saved as level %d into personal level set !", + level_nr); + else + strcpy(level_saved_msg, "Level saved !"); + + Request(level_saved_msg, REQ_CONFIRM); + } } + + /* "cd" back to copied-from levelset (in case of saved read-only level) */ + leveldir_current = leveldir_former; + level_nr = level_nr_former; + break; + } case GADGET_ID_TEST: - if (!LevelContainsPlayer()) - Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM); - else - { - if (LevelChanged()) - level.game_version = GAME_VERSION_ACTUAL; + if (LevelChanged()) + level.game_version = GAME_VERSION_ACTUAL; - CopyPlayfield(level.field, FieldBackup); - CopyPlayfield(Feld, level.field); + CopyPlayfield(level.field, FieldBackup); + CopyPlayfield(Feld, level.field); + + CopyNativeLevel_RND_to_Native(&level); - CopyNativeLevel_RND_to_Native(&level); + UnmapLevelEditorGadgets(); + UndrawSpecialEditorDoor(); - UnmapLevelEditorGadgets(); - UndrawSpecialEditorDoor(); + CloseDoor(DOOR_CLOSE_ALL); - CloseDoor(DOOR_CLOSE_ALL); + BackToFront(); /* force redraw of undrawn special door */ - BackToFront(); /* force redraw of undrawn special door */ +#if 0 + DrawCompleteVideoDisplay(); +#endif - DrawCompleteVideoDisplay(); + level_editor_test_game = TRUE; - level_editor_test_game = TRUE; + StartGameActions(FALSE, setup.autorecord, level.random_seed); - StartGameActions(FALSE, setup.autorecord, level.random_seed); - } break; case GADGET_ID_EXIT: @@ -11462,7 +11730,9 @@ void HandleLevelEditorKeyInput(Key key) ClickOnGadget(level_editor_gadget[id], button); else if (letter == '.') ClickOnGadget(level_editor_gadget[GADGET_ID_SINGLE_ITEMS], button); - else if (key == KSYM_Return || key == setup.shortcut.toggle_pause) + else if (key == KSYM_Return || + key == KSYM_space || + key == setup.shortcut.toggle_pause) ClickOnGadget(level_editor_gadget[GADGET_ID_TEST], button); else for (i = 0; i < ED_NUM_CTRL_BUTTONS; i++) diff --git a/src/engines.h b/src/engines.h index 156a6398..8bd49cb8 100644 --- a/src/engines.h +++ b/src/engines.h @@ -16,14 +16,15 @@ #include "libgame/libgame.h" #include "game_em/export.h" +#include "game_sp/export.h" + +#include "game.h" /* ========================================================================= */ /* functions and definitions exported from main program to game_em */ /* ========================================================================= */ -#include "game.h" - extern void SetBitmaps_EM(Bitmap **); extern void UpdateEngineValues(int, int); extern void DrawAllGameValues(int, int, int, int, int); @@ -33,9 +34,26 @@ extern int getGameFrameDelay_EM(int); extern void PlayLevelSound_EM(int, int, int, int); extern void InitGraphicInfo_EM(void); +extern void CheckSingleStepMode_EM(byte action[], int, boolean); void SetGfxAnimation_EM(struct GraphicInfo_EM *, int, int, int, int); void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *, int, int, int, int); void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *, int, int, int); + +/* ========================================================================= */ +/* functions and definitions exported from main program to game_sp */ +/* ========================================================================= */ + +#if 0 +extern void SetBitmaps_SP(Bitmap **); +#endif + +void CheckSingleStepMode_SP(boolean); + +void getGraphicSource_SP(struct GraphicInfo_SP *, int, int, int, int); +int getGraphicInfo_Delay(int); +boolean isNextAnimationFrame_SP(int, int); + + #endif /* ENGINES_H */ diff --git a/src/events.c b/src/events.c index 278704e6..9a42eb47 100644 --- a/src/events.c +++ b/src/events.c @@ -577,6 +577,11 @@ static void HandleKeysSpecial(Key key) { DumpTape(&tape); } + else if (is_string_suffix(cheat_input, ":save-native-level") || + is_string_suffix(cheat_input, ":snl")) + { + SaveNativeLevel(&level); + } } else if (game_status == GAME_MODE_PLAYING) { @@ -757,6 +762,9 @@ void HandleKey(Key key, int key_status) TapeQuickLoad(); else if (key == setup.shortcut.toggle_pause) TapeTogglePause(TAPE_TOGGLE_MANUAL); + + HandleTapeButtonKeys(key); + HandleSoundButtonKeys(key); } if (game_status == GAME_MODE_PLAYING && !network_playing) @@ -863,6 +871,12 @@ void HandleKey(Key key, int key_status) case KSYM_0: GameFrameDelay = (GameFrameDelay == 500 ? GAME_FRAME_DELAY : 500); break; + + case KSYM_b: + setup.sp_show_border_elements = !setup.sp_show_border_elements; + printf("Supaplex border elements %s\n", + setup.sp_show_border_elements ? "enabled" : "disabled"); + break; #endif default: diff --git a/src/files.c b/src/files.c index bfa49881..d7837486 100644 --- a/src/files.c +++ b/src/files.c @@ -236,6 +236,12 @@ static struct LevelFileConfigInfo chunk_config_INFO[] = &li.score[SC_TIME_BONUS], 1 }, + { + -1, -1, + TYPE_BOOLEAN, CONF_VALUE_8_BIT(9), + &li.auto_exit_sokoban, FALSE + }, + { -1, -1, -1, -1, @@ -1314,6 +1320,22 @@ filetype_id_list[] = /* level file functions */ /* ========================================================================= */ +static boolean check_special_flags(char *flag) +{ +#if 0 + printf("::: '%s', '%s', '%s'\n", + flag, + options.special_flags, + leveldir_current->special_flags); +#endif + + if (strEqual(options.special_flags, flag) || + strEqual(leveldir_current->special_flags, flag)) + return TRUE; + + return FALSE; +} + static struct DateInfo getCurrentDate() { time_t epoch_seconds = time(NULL); @@ -1324,6 +1346,8 @@ static struct DateInfo getCurrentDate() date.month = now->tm_mon + 1; date.day = now->tm_mday; + date.src = DATE_SRC_CLOCK; + return date; } @@ -1587,8 +1611,10 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) *level = li; /* copy temporary buffer back to level data */ setLevelInfoToDefaults_EM(); + setLevelInfoToDefaults_SP(); level->native_em_level = &native_em_level; + level->native_sp_level = &native_sp_level; level->file_version = FILE_VERSION_ACTUAL; level->game_version = GAME_VERSION_ACTUAL; @@ -1750,9 +1776,44 @@ static void setFileInfoToDefaults(struct LevelFileInfo *level_file_info) static void ActivateLevelTemplate() { + int x, y; + /* Currently there is no special action needed to activate the template data, because 'element_info' property settings overwrite the original level data, while all other variables do not change. */ + + /* Exception: 'from_level_template' elements in the original level playfield + are overwritten with the corresponding elements at the same position in + playfield from the level template. */ + + for (x = 0; x < level.fieldx; x++) + for (y = 0; y < level.fieldy; y++) + if (level.field[x][y] == EL_FROM_LEVEL_TEMPLATE) + level.field[x][y] = level_template.field[x][y]; + + if (check_special_flags("load_xsb_to_ces")) + { + struct LevelInfo level_backup = level; + + /* overwrite all individual level settings from template level settings */ + level = level_template; + + /* restore playfield size */ + level.fieldx = level_backup.fieldx; + level.fieldy = level_backup.fieldy; + + /* restore playfield content */ + for (x = 0; x < level.fieldx; x++) + for (y = 0; y < level.fieldy; y++) + level.field[x][y] = level_backup.field[x][y]; + + /* restore name and author from individual level */ + strcpy(level.name, level_backup.name); + strcpy(level.author, level_backup.author); + + /* restore flag "use_custom_template" */ + level.use_custom_template = level_backup.use_custom_template; + } } static char *getLevelFilenameFromBasename(char *basename) @@ -1768,21 +1829,33 @@ static char *getLevelFilenameFromBasename(char *basename) static int getFileTypeFromBasename(char *basename) { + /* !!! ALSO SEE COMMENT IN checkForPackageFromBasename() !!! */ + static char *filename = NULL; struct stat file_status; /* ---------- try to determine file type from filename ---------- */ /* check for typical filename of a Supaplex level package file */ +#if 1 + if (strlen(basename) == 10 && strPrefixLower(basename, "levels.d")) + return LEVEL_FILE_TYPE_SP; +#else if (strlen(basename) == 10 && (strncmp(basename, "levels.d", 8) == 0 || strncmp(basename, "LEVELS.D", 8) == 0)) return LEVEL_FILE_TYPE_SP; +#endif /* check for typical filename of a Diamond Caves II level package file */ - if (strSuffix(basename, ".dc") || - strSuffix(basename, ".dc2")) + if (strSuffixLower(basename, ".dc") || + strSuffixLower(basename, ".dc2")) return LEVEL_FILE_TYPE_DC; + /* check for typical filename of a Sokoban level package file */ + if (strSuffixLower(basename, ".xsb") && + strchr(basename, '%') == NULL) + return LEVEL_FILE_TYPE_SB; + /* ---------- try to determine file type from filesize ---------- */ checked_free(filename); @@ -1798,18 +1871,31 @@ static int getFileTypeFromBasename(char *basename) return LEVEL_FILE_TYPE_UNKNOWN; } -static char *getSingleLevelBasename(int nr) +static boolean checkForPackageFromBasename(char *basename) +{ + /* !!! WON'T WORK ANYMORE IF getFileTypeFromBasename() ALSO DETECTS !!! + !!! SINGLE LEVELS (CURRENTLY ONLY DETECTS LEVEL PACKAGES !!! */ + + return (getFileTypeFromBasename(basename) != LEVEL_FILE_TYPE_UNKNOWN); +} + +static char *getSingleLevelBasenameExt(int nr, char *extension) { static char basename[MAX_FILENAME_LEN]; if (nr < 0) - sprintf(basename, "template.%s", LEVELFILE_EXTENSION); + sprintf(basename, "template.%s", extension); else - sprintf(basename, "%03d.%s", nr, LEVELFILE_EXTENSION); + sprintf(basename, "%03d.%s", nr, extension); return basename; } +static char *getSingleLevelBasename(int nr) +{ + return getSingleLevelBasenameExt(nr, LEVELFILE_EXTENSION); +} + static char *getPackedLevelBasename(int type) { static char basename[MAX_FILENAME_LEN]; @@ -1937,9 +2023,33 @@ static void determineLevelFileInfo_Filename(struct LevelFileInfo *lfi) /* special case: level number is negative => check for level template file */ if (nr < 0) { +#if 1 + /* global variable "leveldir_current" must be modified in the loop below */ + LevelDirTree *leveldir_current_last = leveldir_current; + + /* check for template level in path from current to topmost tree node */ + + while (leveldir_current != NULL) + { + setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_RND, + "template.%s", LEVELFILE_EXTENSION); + + if (fileExists(lfi->filename)) + break; + + leveldir_current = leveldir_current->node_parent; + } + + /* restore global variable "leveldir_current" modified in above loop */ + leveldir_current = leveldir_current_last; + +#else + setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_RND, "template.%s", LEVELFILE_EXTENSION); +#endif + /* no fallback if template file not existing */ return; } @@ -1951,6 +2061,9 @@ static void determineLevelFileInfo_Filename(struct LevelFileInfo *lfi) setLevelFileInfo_FormatLevelFilename(lfi, filetype, leveldir_current->level_filename, nr); + + lfi->packed = checkForPackageFromBasename(leveldir_current->level_filename); + if (fileExists(lfi->filename)) return; } @@ -2114,6 +2227,8 @@ static int LoadLevel_DATE(FILE *file, int chunk_size, struct LevelInfo *level) level->creation_date.month = getFile8Bit(file); level->creation_date.day = getFile8Bit(file); + level->creation_date.src = DATE_SRC_LEVELFILE; + return chunk_size; } @@ -3017,8 +3132,12 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level, { level->no_valid_file = TRUE; +#if 1 + Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename); +#else if (level != &level_template) Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename); +#endif return; } @@ -3799,30 +3918,13 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level) } } -static void LoadLevelFromFileInfo_EM(struct LevelInfo *level, - struct LevelFileInfo *level_file_info) -{ - if (!LoadNativeLevel_EM(level_file_info->filename)) - level->no_valid_file = TRUE; -} - -void CopyNativeLevel_RND_to_Native(struct LevelInfo *level) -{ - if (level->game_engine_type == GAME_ENGINE_TYPE_EM) - CopyNativeLevel_RND_to_EM(level); -} - -void CopyNativeLevel_Native_to_RND(struct LevelInfo *level) -{ - if (level->game_engine_type == GAME_ENGINE_TYPE_EM) - CopyNativeLevel_EM_to_RND(level); -} - /* ------------------------------------------------------------------------- */ /* functions for loading SP level */ /* ------------------------------------------------------------------------- */ +#if 0 + #define NUM_SUPAPLEX_LEVELS_PER_PACKAGE 111 #define SP_LEVEL_SIZE 1536 #define SP_LEVEL_XSIZE 60 @@ -4013,7 +4115,8 @@ static void LoadLevelFromFileInfo_SP(struct LevelInfo *level, } /* position file stream to the requested level inside the level package */ - if (fseek(file, nr * SP_LEVEL_SIZE, SEEK_SET) != 0) + if (level_file_info->packed && + fseek(file, nr * SP_LEVEL_SIZE, SEEK_SET) != 0) { level->no_valid_file = TRUE; @@ -4167,6 +4270,261 @@ static void LoadLevelFromFileInfo_SP(struct LevelInfo *level, *level = multipart_level; } +#endif + +void CopyNativeLevel_RND_to_SP(struct LevelInfo *level) +{ + struct LevelInfo_SP *level_sp = level->native_sp_level; + LevelInfoType *header = &level_sp->header; + int i, x, y; + + level_sp->width = level->fieldx; + level_sp->height = level->fieldy; + + for (x = 0; x < level->fieldx; x++) + for (y = 0; y < level->fieldy; y++) + level_sp->playfield[x][y] = map_element_RND_to_SP(level->field[x][y]); + + header->InitialGravity = (level->initial_player_gravity[0] ? 1 : 0); + + for (i = 0; i < SP_LEVEL_NAME_LEN; i++) + header->LevelTitle[i] = level->name[i]; + /* !!! NO STRING TERMINATION IN SUPAPLEX VB CODE YET -- FIX THIS !!! */ + + header->InfotronsNeeded = level->gems_needed; + + header->SpecialPortCount = 0; + + for (x = 0; x < level->fieldx; x++) for (y = 0; y < level->fieldy; y++) + { + boolean gravity_port_found = FALSE; + boolean gravity_port_valid = FALSE; + int gravity_port_flag; + int gravity_port_base_element; + int element = level->field[x][y]; + + if (element >= EL_SP_GRAVITY_ON_PORT_RIGHT && + element <= EL_SP_GRAVITY_ON_PORT_UP) + { + gravity_port_found = TRUE; + gravity_port_valid = TRUE; + gravity_port_flag = 1; + gravity_port_base_element = EL_SP_GRAVITY_ON_PORT_RIGHT; + } + else if (element >= EL_SP_GRAVITY_OFF_PORT_RIGHT && + element <= EL_SP_GRAVITY_OFF_PORT_UP) + { + gravity_port_found = TRUE; + gravity_port_valid = TRUE; + gravity_port_flag = 0; + gravity_port_base_element = EL_SP_GRAVITY_OFF_PORT_RIGHT; + } + else if (element >= EL_SP_GRAVITY_PORT_RIGHT && + element <= EL_SP_GRAVITY_PORT_UP) + { + /* change R'n'D style gravity inverting special port to normal port + (there are no gravity inverting ports in native Supaplex engine) */ + + gravity_port_found = TRUE; + gravity_port_valid = FALSE; + gravity_port_base_element = EL_SP_GRAVITY_PORT_RIGHT; + } + + if (gravity_port_found) + { + if (gravity_port_valid && + header->SpecialPortCount < SP_MAX_SPECIAL_PORTS) + { + SpecialPortType *port = &header->SpecialPort[header->SpecialPortCount]; + + port->PortLocation = (y * level->fieldx + x) * 2; + port->Gravity = gravity_port_flag; + + element += EL_SP_GRAVITY_PORT_RIGHT - gravity_port_base_element; + + header->SpecialPortCount++; + } + else + { + /* change special gravity port to normal port */ + + element += EL_SP_PORT_RIGHT - gravity_port_base_element; + } + + level_sp->playfield[x][y] = element - EL_SP_START; + } + } +} + +void CopyNativeLevel_SP_to_RND(struct LevelInfo *level) +{ + struct LevelInfo_SP *level_sp = level->native_sp_level; + LevelInfoType *header = &level_sp->header; + int i, x, y; + + level->fieldx = level_sp->width; + level->fieldy = level_sp->height; + + for (x = 0; x < level->fieldx; x++) + { + for (y = 0; y < level->fieldy; y++) + { + int element_old = level_sp->playfield[x][y]; + int element_new = getMappedElement(map_element_SP_to_RND(element_old)); + + if (element_new == EL_UNKNOWN) + Error(ERR_WARN, "invalid element %d at position %d, %d", + element_old, x, y); + + level->field[x][y] = element_new; + } + } + + for (i = 0; i < MAX_PLAYERS; i++) + level->initial_player_gravity[i] = + (header->InitialGravity == 1 ? TRUE : FALSE); + + for (i = 0; i < SP_LEVEL_NAME_LEN; i++) + level->name[i] = header->LevelTitle[i]; + level->name[SP_LEVEL_NAME_LEN] = '\0'; + + level->gems_needed = header->InfotronsNeeded; + + for (i = 0; i < header->SpecialPortCount; i++) + { + SpecialPortType *port = &header->SpecialPort[i]; + int port_location = port->PortLocation; + int gravity = port->Gravity; + int port_x, port_y, port_element; + + port_x = (port_location / 2) % level->fieldx; + port_y = (port_location / 2) / level->fieldx; + + if (port_x < 0 || port_x >= level->fieldx || + port_y < 0 || port_y >= level->fieldy) + { + Error(ERR_WARN, "special port position (%d, %d) out of bounds", + port_x, port_y); + + continue; + } + + port_element = level->field[port_x][port_y]; + + if (port_element < EL_SP_GRAVITY_PORT_RIGHT || + port_element > EL_SP_GRAVITY_PORT_UP) + { + Error(ERR_WARN, "no special port at position (%d, %d)", port_x, port_y); + + continue; + } + + /* change previous (wrong) gravity inverting special port to either + gravity enabling special port or gravity disabling special port */ + level->field[port_x][port_y] += + (gravity == 1 ? EL_SP_GRAVITY_ON_PORT_RIGHT : + EL_SP_GRAVITY_OFF_PORT_RIGHT) - EL_SP_GRAVITY_PORT_RIGHT; + } + + /* change special gravity ports without database entries to normal ports */ + for (x = 0; x < level->fieldx; x++) + for (y = 0; y < level->fieldy; y++) + if (level->field[x][y] >= EL_SP_GRAVITY_PORT_RIGHT && + level->field[x][y] <= EL_SP_GRAVITY_PORT_UP) + level->field[x][y] += EL_SP_PORT_RIGHT - EL_SP_GRAVITY_PORT_RIGHT; + + level->time = 0; /* no time limit */ + level->amoeba_speed = 0; + level->time_magic_wall = 0; + level->time_wheel = 0; + level->amoeba_content = EL_EMPTY; + +#if 1 + /* original Supaplex does not use score values -- use default values */ +#else + for (i = 0; i < LEVEL_SCORE_ELEMENTS; i++) + level->score[i] = 0; +#endif + + /* there are no yamyams in supaplex levels */ + for (i = 0; i < level->num_yamyam_contents; i++) + for (x = 0; x < 3; x++) + for (y = 0; y < 3; y++) + level->yamyam_content[i].e[x][y] = EL_EMPTY; +} + +static void CopyNativeTape_RND_to_SP(struct LevelInfo *level) +{ + struct LevelInfo_SP *level_sp = level->native_sp_level; + struct DemoInfo_SP *demo = &level_sp->demo; + int i, j; + + /* always start with reliable default values */ + demo->is_available = FALSE; + demo->length = 0; + + if (TAPE_IS_EMPTY(tape)) + return; + + demo->level_nr = tape.level_nr; /* (currently not used) */ + + level_sp->header.DemoRandomSeed = tape.random_seed; + + demo->length = 0; + for (i = 0; i < tape.length; i++) + { + int demo_action = map_key_RND_to_SP(tape.pos[i].action[0]); + int demo_repeat = tape.pos[i].delay; + + for (j = 0; j < demo_repeat / 16; j++) + demo->data[demo->length++] = 0xf0 | demo_action; + + if (demo_repeat % 16) + demo->data[demo->length++] = ((demo_repeat % 16 - 1) << 4) | demo_action; + } + + demo->data[demo->length++] = 0xff; + + demo->is_available = TRUE; +} + +static void setTapeInfoToDefaults(); + +static void CopyNativeTape_SP_to_RND(struct LevelInfo *level) +{ + struct LevelInfo_SP *level_sp = level->native_sp_level; + struct DemoInfo_SP *demo = &level_sp->demo; + char *filename = level->file_info.filename; + int i; + + /* always start with reliable default values */ + setTapeInfoToDefaults(); + + if (!demo->is_available) + return; + + tape.level_nr = demo->level_nr; /* (currently not used) */ + tape.length = demo->length - 1; /* without "end of demo" byte */ + tape.random_seed = level_sp->header.DemoRandomSeed; + + TapeSetDateFromEpochSeconds(getFileTimestampEpochSeconds(filename)); + + for (i = 0; i < demo->length - 1; i++) + { + int demo_action = demo->data[i] & 0x0f; + int demo_repeat = (demo->data[i] & 0xf0) >> 4; + + tape.pos[i].action[0] = map_key_SP_to_RND(demo_action); + tape.pos[i].delay = demo_repeat + 1; + } + + tape.length_seconds = GetTapeLength(); +} + + +/* ------------------------------------------------------------------------- */ +/* functions for loading DC level */ +/* ------------------------------------------------------------------------- */ #define DC_LEVEL_HEADER_SIZE 344 @@ -6138,32 +6496,434 @@ static void LoadLevelFromFileInfo_DC(struct LevelInfo *level, /* ------------------------------------------------------------------------- */ -/* functions for loading generic level */ +/* functions for loading SB level */ /* ------------------------------------------------------------------------- */ -void LoadLevelFromFileInfo(struct LevelInfo *level, - struct LevelFileInfo *level_file_info) +int getMappedElement_SB(int element_ascii, boolean use_ces) { - /* always start with reliable default values */ - setLevelInfoToDefaults(level); - - switch (level_file_info->type) + static struct { - case LEVEL_FILE_TYPE_RND: - LoadLevelFromFileInfo_RND(level, level_file_info); - break; + int ascii; + int sb; + int ce; + } + sb_element_mapping[] = + { + { ' ', EL_EMPTY, EL_CUSTOM_1 }, /* floor (space) */ + { '#', EL_STEELWALL, EL_CUSTOM_2 }, /* wall */ + { '@', EL_PLAYER_1, EL_CUSTOM_3 }, /* player */ + { '$', EL_SOKOBAN_OBJECT, EL_CUSTOM_4 }, /* box */ + { '.', EL_SOKOBAN_FIELD_EMPTY, EL_CUSTOM_5 }, /* goal square */ + { '*', EL_SOKOBAN_FIELD_FULL, EL_CUSTOM_6 }, /* box on goal square */ + { '+', EL_SOKOBAN_FIELD_PLAYER, EL_CUSTOM_7 }, /* player on goal square */ +#if 0 + { '_', EL_INVISIBLE_STEELWALL, EL_CUSTOM_8 }, /* floor beyond border */ +#else + { '_', EL_INVISIBLE_STEELWALL, EL_FROM_LEVEL_TEMPLATE }, /* floor beyond border */ +#endif - case LEVEL_FILE_TYPE_EM: - LoadLevelFromFileInfo_EM(level, level_file_info); - level->game_engine_type = GAME_ENGINE_TYPE_EM; - break; + { 0, -1, -1 }, + }; - case LEVEL_FILE_TYPE_SP: - LoadLevelFromFileInfo_SP(level, level_file_info); - break; + int i; - case LEVEL_FILE_TYPE_DC: - LoadLevelFromFileInfo_DC(level, level_file_info); + for (i = 0; sb_element_mapping[i].ascii != 0; i++) + if (element_ascii == sb_element_mapping[i].ascii) + return (use_ces ? sb_element_mapping[i].ce : sb_element_mapping[i].sb); + + return EL_UNDEFINED; +} + +static void LoadLevelFromFileInfo_SB(struct LevelInfo *level, + struct LevelFileInfo *level_file_info) +{ + char *filename = level_file_info->filename; + char line[MAX_LINE_LEN], line_raw[MAX_LINE_LEN], previous_line[MAX_LINE_LEN]; + char last_comment[MAX_LINE_LEN]; + char level_name[MAX_LINE_LEN]; + char *line_ptr; + FILE *file; + int num_levels_to_skip = level_file_info->nr - leveldir_current->first_level; + boolean read_continued_line = FALSE; + boolean reading_playfield = FALSE; + boolean got_valid_playfield_line = FALSE; + boolean invalid_playfield_char = FALSE; + boolean load_xsb_to_ces = check_special_flags("load_xsb_to_ces"); + int file_level_nr = 0; + int line_nr = 0; + int x = 0, y = 0; /* initialized to make compilers happy */ + +#if 0 + printf("::: looking for level number %d [%d]\n", + level_file_info->nr, num_levels_to_skip); +#endif + + last_comment[0] = '\0'; + level_name[0] = '\0'; + + if (!(file = fopen(filename, MODE_READ))) + { + level->no_valid_file = TRUE; + + Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename); + + return; + } + + while (!feof(file)) + { + /* level successfully read, but next level may follow here */ + if (!got_valid_playfield_line && reading_playfield) + { +#if 0 + printf("::: read complete playfield\n"); +#endif + + /* read playfield from single level file -- skip remaining file */ + if (!level_file_info->packed) + break; + + if (file_level_nr >= num_levels_to_skip) + break; + + file_level_nr++; + + last_comment[0] = '\0'; + level_name[0] = '\0'; + + reading_playfield = FALSE; + } + + got_valid_playfield_line = FALSE; + + /* read next line of input file */ + if (!fgets(line, MAX_LINE_LEN, file)) + break; + + /* check if line was completely read and is terminated by line break */ + if (strlen(line) > 0 && line[strlen(line) - 1] == '\n') + line_nr++; + + /* cut trailing line break (this can be newline and/or carriage return) */ + for (line_ptr = &line[strlen(line)]; line_ptr >= line; line_ptr--) + if ((*line_ptr == '\n' || *line_ptr == '\r') && *(line_ptr + 1) == '\0') + *line_ptr = '\0'; + + /* copy raw input line for later use (mainly debugging output) */ + strcpy(line_raw, line); + + if (read_continued_line) + { + /* append new line to existing line, if there is enough space */ + if (strlen(previous_line) + strlen(line_ptr) < MAX_LINE_LEN) + strcat(previous_line, line_ptr); + + strcpy(line, previous_line); /* copy storage buffer to line */ + + read_continued_line = FALSE; + } + + /* if the last character is '\', continue at next line */ + if (strlen(line) > 0 && line[strlen(line) - 1] == '\\') + { + line[strlen(line) - 1] = '\0'; /* cut off trailing backslash */ + strcpy(previous_line, line); /* copy line to storage buffer */ + + read_continued_line = TRUE; + + continue; + } + + /* skip empty lines */ + if (line[0] == '\0') + continue; + + /* extract comment text from comment line */ + if (line[0] == ';') + { + for (line_ptr = line; *line_ptr; line_ptr++) + if (*line_ptr != ' ' && *line_ptr != '\t' && *line_ptr != ';') + break; + + strcpy(last_comment, line_ptr); + +#if 0 + printf("::: found comment '%s' in line %d\n", last_comment, line_nr); +#endif + + continue; + } + + /* extract level title text from line containing level title */ + if (line[0] == '\'') + { + strcpy(level_name, &line[1]); + + if (strlen(level_name) > 0 && level_name[strlen(level_name) - 1] == '\'') + level_name[strlen(level_name) - 1] = '\0'; + +#if 0 + printf("::: found level name '%s' in line %d\n", level_name, line_nr); +#endif + + continue; + } + + /* skip lines containing only spaces (or empty lines) */ + for (line_ptr = line; *line_ptr; line_ptr++) + if (*line_ptr != ' ') + break; + if (*line_ptr == '\0') + continue; + + /* at this point, we have found a line containing part of a playfield */ + +#if 0 + printf("::: found playfield row in line %d\n", line_nr); +#endif + + got_valid_playfield_line = TRUE; + + if (!reading_playfield) + { + reading_playfield = TRUE; + invalid_playfield_char = FALSE; + + for (x = 0; x < MAX_LEV_FIELDX; x++) + for (y = 0; y < MAX_LEV_FIELDY; y++) + level->field[x][y] = getMappedElement_SB(' ', load_xsb_to_ces); + + level->fieldx = 0; + level->fieldy = 0; + + /* start with topmost tile row */ + y = 0; + } + + /* skip playfield line if larger row than allowed */ + if (y >= MAX_LEV_FIELDY) + continue; + + /* start with leftmost tile column */ + x = 0; + + /* read playfield elements from line */ + for (line_ptr = line; *line_ptr; line_ptr++) + { + int mapped_sb_element = getMappedElement_SB(*line_ptr, load_xsb_to_ces); + + /* stop parsing playfield line if larger column than allowed */ + if (x >= MAX_LEV_FIELDX) + break; + + if (mapped_sb_element == EL_UNDEFINED) + { + invalid_playfield_char = TRUE; + + break; + } + + level->field[x][y] = mapped_sb_element; + + /* continue with next tile column */ + x++; + + level->fieldx = MAX(x, level->fieldx); + } + + if (invalid_playfield_char) + { + /* if first playfield line, treat invalid lines as comment lines */ + if (y == 0) + reading_playfield = FALSE; + + continue; + } + + /* continue with next tile row */ + y++; + } + + fclose(file); + + level->fieldy = y; + + level->fieldx = MIN(MAX(MIN_LEV_FIELDX, level->fieldx), MAX_LEV_FIELDX); + level->fieldy = MIN(MAX(MIN_LEV_FIELDY, level->fieldy), MAX_LEV_FIELDY); + + if (!reading_playfield) + { + level->no_valid_file = TRUE; + + Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename); + + return; + } + + if (*level_name != '\0') + { + strncpy(level->name, level_name, MAX_LEVEL_NAME_LEN); + level->name[MAX_LEVEL_NAME_LEN] = '\0'; + +#if 0 + printf(":1: level name: '%s'\n", level->name); +#endif + } + else if (*last_comment != '\0') + { + strncpy(level->name, last_comment, MAX_LEVEL_NAME_LEN); + level->name[MAX_LEVEL_NAME_LEN] = '\0'; + +#if 0 + printf(":2: level name: '%s'\n", level->name); +#endif + } + else + { + sprintf(level->name, "--> Level %d <--", level_file_info->nr); + } + + /* set all empty fields beyond the border walls to invisible steel wall */ + for (y = 0; y < level->fieldy; y++) for (x = 0; x < level->fieldx; x++) + { + if ((x == 0 || x == level->fieldx - 1 || + y == 0 || y == level->fieldy - 1) && + level->field[x][y] == getMappedElement_SB(' ', load_xsb_to_ces)) + FloodFillLevel(x, y, getMappedElement_SB('_', load_xsb_to_ces), + level->field, level->fieldx, level->fieldy); + } + + /* set special level settings for Sokoban levels */ + + level->time = 0; + level->use_step_counter = TRUE; + + if (load_xsb_to_ces) + { +#if 1 + /* !!! special global settings can now be set in level template !!! */ +#else + level->initial_player_stepsize[0] = STEPSIZE_SLOW; +#endif + + /* fill smaller playfields with padding "beyond border wall" elements */ + if (level->fieldx < SCR_FIELDX || + level->fieldy < SCR_FIELDY) + { + short field[level->fieldx][level->fieldy]; + int new_fieldx = MAX(level->fieldx, SCR_FIELDX); + int new_fieldy = MAX(level->fieldy, SCR_FIELDY); + int pos_fieldx = (new_fieldx - level->fieldx) / 2; + int pos_fieldy = (new_fieldy - level->fieldy) / 2; + + /* copy old playfield (which is smaller than the visible area) */ + for (y = 0; y < level->fieldy; y++) for (x = 0; x < level->fieldx; x++) + field[x][y] = level->field[x][y]; + + /* fill new, larger playfield with "beyond border wall" elements */ + for (y = 0; y < new_fieldy; y++) for (x = 0; x < new_fieldx; x++) + level->field[x][y] = getMappedElement_SB('_', load_xsb_to_ces); + + /* copy the old playfield to the middle of the new playfield */ + for (y = 0; y < level->fieldy; y++) for (x = 0; x < level->fieldx; x++) + level->field[pos_fieldx + x][pos_fieldy + y] = field[x][y]; + + level->fieldx = new_fieldx; + level->fieldy = new_fieldy; + } + + level->use_custom_template = TRUE; + } +} + + +/* ------------------------------------------------------------------------- */ +/* functions for handling native levels */ +/* ------------------------------------------------------------------------- */ + +static void LoadLevelFromFileInfo_EM(struct LevelInfo *level, + struct LevelFileInfo *level_file_info) +{ + if (!LoadNativeLevel_EM(level_file_info->filename)) + level->no_valid_file = TRUE; +} + +static void LoadLevelFromFileInfo_SP(struct LevelInfo *level, + struct LevelFileInfo *level_file_info) +{ + int pos = 0; + + /* determine position of requested level inside level package */ + if (level_file_info->packed) + pos = level_file_info->nr - leveldir_current->first_level; + + if (!LoadNativeLevel_SP(level_file_info->filename, pos)) + level->no_valid_file = TRUE; +} + +void CopyNativeLevel_RND_to_Native(struct LevelInfo *level) +{ + if (level->game_engine_type == GAME_ENGINE_TYPE_EM) + CopyNativeLevel_RND_to_EM(level); + else if (level->game_engine_type == GAME_ENGINE_TYPE_SP) + CopyNativeLevel_RND_to_SP(level); +} + +void CopyNativeLevel_Native_to_RND(struct LevelInfo *level) +{ + if (level->game_engine_type == GAME_ENGINE_TYPE_EM) + CopyNativeLevel_EM_to_RND(level); + else if (level->game_engine_type == GAME_ENGINE_TYPE_SP) + CopyNativeLevel_SP_to_RND(level); +} + +void SaveNativeLevel(struct LevelInfo *level) +{ + if (level->game_engine_type == GAME_ENGINE_TYPE_SP) + { + char *basename = getSingleLevelBasenameExt(level->file_info.nr, "sp"); + char *filename = getLevelFilenameFromBasename(basename); + + CopyNativeLevel_RND_to_SP(level); + CopyNativeTape_RND_to_SP(level); + + SaveNativeLevel_SP(filename); + } +} + + +/* ------------------------------------------------------------------------- */ +/* functions for loading generic level */ +/* ------------------------------------------------------------------------- */ + +void LoadLevelFromFileInfo(struct LevelInfo *level, + struct LevelFileInfo *level_file_info) +{ + /* always start with reliable default values */ + setLevelInfoToDefaults(level); + + switch (level_file_info->type) + { + case LEVEL_FILE_TYPE_RND: + LoadLevelFromFileInfo_RND(level, level_file_info); + break; + + case LEVEL_FILE_TYPE_EM: + LoadLevelFromFileInfo_EM(level, level_file_info); + level->game_engine_type = GAME_ENGINE_TYPE_EM; + break; + + case LEVEL_FILE_TYPE_SP: + LoadLevelFromFileInfo_SP(level, level_file_info); + level->game_engine_type = GAME_ENGINE_TYPE_SP; + break; + + case LEVEL_FILE_TYPE_DC: + LoadLevelFromFileInfo_DC(level, level_file_info); + break; + + case LEVEL_FILE_TYPE_SB: + LoadLevelFromFileInfo_SB(level, level_file_info); break; default: @@ -7692,6 +8452,79 @@ static int LoadTape_BODY(FILE *file, int chunk_size, struct TapeInfo *tape) return chunk_size; } +void LoadTape_SokobanSolution(char *filename) +{ + FILE *file; + int move_delay = TILESIZE / level.initial_player_stepsize[0]; + + if (!(file = fopen(filename, MODE_READ))) + { + tape.no_valid_file = TRUE; + + return; + } + + while (!feof(file)) + { + unsigned char c = fgetc(file); + + if (feof(file)) + break; + + switch (c) + { + case 'u': + case 'U': + tape.pos[tape.length].action[0] = MV_UP; + tape.pos[tape.length].delay = move_delay + (c < 'a' ? 2 : 0); + tape.length++; + break; + + case 'd': + case 'D': + tape.pos[tape.length].action[0] = MV_DOWN; + tape.pos[tape.length].delay = move_delay + (c < 'a' ? 2 : 0); + tape.length++; + break; + + case 'l': + case 'L': + tape.pos[tape.length].action[0] = MV_LEFT; + tape.pos[tape.length].delay = move_delay + (c < 'a' ? 2 : 0); + tape.length++; + break; + + case 'r': + case 'R': + tape.pos[tape.length].action[0] = MV_RIGHT; + tape.pos[tape.length].delay = move_delay + (c < 'a' ? 2 : 0); + tape.length++; + break; + + case '\n': + case '\r': + case '\t': + case ' ': + /* ignore white-space characters */ + break; + + default: + tape.no_valid_file = TRUE; + + Error(ERR_WARN, "unsupported Sokoban solution file '%s' ['%d']", filename, c); + + break; + } + } + + fclose(file); + + if (tape.no_valid_file) + return; + + tape.length_seconds = GetTapeLength(); +} + void LoadTapeFromFilename(char *filename) { char cookie[MAX_LINE_LEN]; @@ -7702,6 +8535,13 @@ void LoadTapeFromFilename(char *filename) /* always start with reliable default values */ setTapeInfoToDefaults(); + if (strSuffix(filename, ".sln")) + { + LoadTape_SokobanSolution(filename); + + return; + } + if (!(file = fopen(filename, MODE_READ))) { tape.no_valid_file = TRUE; @@ -7746,6 +8586,7 @@ void LoadTapeFromFilename(char *filename) Error(ERR_WARN, "unsupported version of tape file '%s'", filename); fclose(file); + return; } @@ -7838,6 +8679,13 @@ void LoadSolutionTape(int nr) char *filename = getSolutionTapeFilename(nr); LoadTapeFromFilename(filename); + +#if 1 + if (TAPE_IS_EMPTY(tape) && + level.game_engine_type == GAME_ENGINE_TYPE_SP && + level.native_sp_level->demo.is_available) + CopyNativeTape_SP_to_RND(&level); +#endif } static void SaveTape_VERS(FILE *file, struct TapeInfo *tape) @@ -8152,14 +9000,15 @@ void SaveScore(int nr) #define SETUP_TOKEN_INPUT_ON_FOCUS 22 #define SETUP_TOKEN_PREFER_AGA_GRAPHICS 23 #define SETUP_TOKEN_GAME_FRAME_DELAY 24 -#define SETUP_TOKEN_GRAPHICS_SET 25 -#define SETUP_TOKEN_SOUNDS_SET 26 -#define SETUP_TOKEN_MUSIC_SET 27 -#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS 28 -#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS 29 -#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC 30 +#define SETUP_TOKEN_SP_SHOW_BORDER_ELEMENTS 25 +#define SETUP_TOKEN_GRAPHICS_SET 26 +#define SETUP_TOKEN_SOUNDS_SET 27 +#define SETUP_TOKEN_MUSIC_SET 28 +#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS 29 +#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS 30 +#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC 31 -#define NUM_GLOBAL_SETUP_TOKENS 31 +#define NUM_GLOBAL_SETUP_TOKENS 32 /* editor setup */ #define SETUP_TOKEN_EDITOR_EL_BOULDERDASH 0 @@ -8210,8 +9059,16 @@ void SaveScore(int nr) #define SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_3 5 #define SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_4 6 #define SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_ALL 7 +#define SETUP_TOKEN_SHORTCUT_TAPE_EJECT 8 +#define SETUP_TOKEN_SHORTCUT_TAPE_STOP 9 +#define SETUP_TOKEN_SHORTCUT_TAPE_PAUSE 10 +#define SETUP_TOKEN_SHORTCUT_TAPE_RECORD 11 +#define SETUP_TOKEN_SHORTCUT_TAPE_PLAY 12 +#define SETUP_TOKEN_SHORTCUT_SOUND_SIMPLE 13 +#define SETUP_TOKEN_SHORTCUT_SOUND_LOOPS 14 +#define SETUP_TOKEN_SHORTCUT_SOUND_MUSIC 15 -#define NUM_SHORTCUT_SETUP_TOKENS 8 +#define NUM_SHORTCUT_SETUP_TOKENS 16 /* player setup */ #define SETUP_TOKEN_PLAYER_USE_JOYSTICK 0 @@ -8256,34 +9113,35 @@ static struct OptionInfo soi; static struct TokenInfo global_setup_tokens[] = { - { TYPE_STRING, &si.player_name, "player_name" }, - { TYPE_SWITCH, &si.sound, "sound" }, - { TYPE_SWITCH, &si.sound_loops, "repeating_sound_loops" }, - { TYPE_SWITCH, &si.sound_music, "background_music" }, - { TYPE_SWITCH, &si.sound_simple, "simple_sound_effects" }, - { TYPE_SWITCH, &si.toons, "toons" }, - { TYPE_SWITCH, &si.scroll_delay, "scroll_delay" }, - { TYPE_INTEGER,&si.scroll_delay_value,"scroll_delay_value" }, - { TYPE_SWITCH, &si.soft_scrolling, "soft_scrolling" }, - { TYPE_SWITCH, &si.fade_screens, "fade_screens" }, - { TYPE_SWITCH, &si.autorecord, "automatic_tape_recording" }, - { TYPE_SWITCH, &si.show_titlescreen, "show_titlescreen" }, - { TYPE_SWITCH, &si.quick_doors, "quick_doors" }, - { TYPE_SWITCH, &si.team_mode, "team_mode" }, - { TYPE_SWITCH, &si.handicap, "handicap" }, - { TYPE_SWITCH, &si.skip_levels, "skip_levels" }, - { TYPE_SWITCH, &si.time_limit, "time_limit" }, - { TYPE_SWITCH, &si.fullscreen, "fullscreen" }, - { TYPE_STRING, &si.fullscreen_mode, "fullscreen_mode" }, - { TYPE_SWITCH, &si.ask_on_escape, "ask_on_escape" }, - { TYPE_SWITCH, &si.ask_on_escape_editor, "ask_on_escape_editor" }, - { TYPE_SWITCH, &si.quick_switch, "quick_player_switch" }, - { TYPE_SWITCH, &si.input_on_focus, "input_on_focus" }, - { TYPE_SWITCH, &si.prefer_aga_graphics, "prefer_aga_graphics" }, - { TYPE_INTEGER,&si.game_frame_delay, "game_frame_delay" }, - { TYPE_STRING, &si.graphics_set, "graphics_set" }, - { TYPE_STRING, &si.sounds_set, "sounds_set" }, - { TYPE_STRING, &si.music_set, "music_set" }, + { TYPE_STRING, &si.player_name, "player_name" }, + { TYPE_SWITCH, &si.sound, "sound" }, + { TYPE_SWITCH, &si.sound_loops, "repeating_sound_loops" }, + { TYPE_SWITCH, &si.sound_music, "background_music" }, + { TYPE_SWITCH, &si.sound_simple, "simple_sound_effects" }, + { TYPE_SWITCH, &si.toons, "toons" }, + { TYPE_SWITCH, &si.scroll_delay, "scroll_delay" }, + { TYPE_INTEGER,&si.scroll_delay_value, "scroll_delay_value" }, + { TYPE_SWITCH, &si.soft_scrolling, "soft_scrolling" }, + { TYPE_SWITCH, &si.fade_screens, "fade_screens" }, + { TYPE_SWITCH, &si.autorecord, "automatic_tape_recording"}, + { TYPE_SWITCH, &si.show_titlescreen, "show_titlescreen" }, + { TYPE_SWITCH, &si.quick_doors, "quick_doors" }, + { TYPE_SWITCH, &si.team_mode, "team_mode" }, + { TYPE_SWITCH, &si.handicap, "handicap" }, + { TYPE_SWITCH, &si.skip_levels, "skip_levels" }, + { TYPE_SWITCH, &si.time_limit, "time_limit" }, + { TYPE_SWITCH, &si.fullscreen, "fullscreen" }, + { TYPE_STRING, &si.fullscreen_mode, "fullscreen_mode" }, + { TYPE_SWITCH, &si.ask_on_escape, "ask_on_escape" }, + { TYPE_SWITCH, &si.ask_on_escape_editor, "ask_on_escape_editor" }, + { TYPE_SWITCH, &si.quick_switch, "quick_player_switch" }, + { TYPE_SWITCH, &si.input_on_focus, "input_on_focus" }, + { TYPE_SWITCH, &si.prefer_aga_graphics, "prefer_aga_graphics" }, + { TYPE_INTEGER,&si.game_frame_delay, "game_frame_delay" }, + { TYPE_SWITCH, &si.sp_show_border_elements, "sp_show_border_elements" }, + { TYPE_STRING, &si.graphics_set, "graphics_set" }, + { TYPE_STRING, &si.sounds_set, "sounds_set" }, + { TYPE_STRING, &si.music_set, "music_set" }, { TYPE_SWITCH3,&si.override_level_graphics, "override_level_graphics" }, { TYPE_SWITCH3,&si.override_level_sounds, "override_level_sounds" }, { TYPE_SWITCH3,&si.override_level_music, "override_level_music" }, @@ -8355,6 +9213,14 @@ static struct TokenInfo shortcut_setup_tokens[] = { TYPE_KEY_X11, &ssi.focus_player[2], "shortcut.focus_player_3" }, { TYPE_KEY_X11, &ssi.focus_player[3], "shortcut.focus_player_4" }, { TYPE_KEY_X11, &ssi.focus_player_all,"shortcut.focus_player_all" }, + { TYPE_KEY_X11, &ssi.tape_eject, "shortcut.tape_eject" }, + { TYPE_KEY_X11, &ssi.tape_stop, "shortcut.tape_stop" }, + { TYPE_KEY_X11, &ssi.tape_pause, "shortcut.tape_pause" }, + { TYPE_KEY_X11, &ssi.tape_record, "shortcut.tape_record" }, + { TYPE_KEY_X11, &ssi.tape_play, "shortcut.tape_play" }, + { TYPE_KEY_X11, &ssi.sound_simple, "shortcut.sound_simple" }, + { TYPE_KEY_X11, &ssi.sound_loops, "shortcut.sound_loops" }, + { TYPE_KEY_X11, &ssi.sound_music, "shortcut.sound_music" }, }; static struct TokenInfo player_setup_tokens[] = @@ -8434,6 +9300,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->input_on_focus = FALSE; si->prefer_aga_graphics = TRUE; si->game_frame_delay = GAME_FRAME_DELAY; + si->sp_show_border_elements = FALSE; si->graphics_set = getStringCopy(GFX_DEFAULT_SUBDIR); si->sounds_set = getStringCopy(SND_DEFAULT_SUBDIR); @@ -8470,6 +9337,16 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->shortcut.focus_player[3] = DEFAULT_KEY_FOCUS_PLAYER_4; si->shortcut.focus_player_all = DEFAULT_KEY_FOCUS_PLAYER_ALL; + si->shortcut.tape_eject = DEFAULT_KEY_TAPE_EJECT; + si->shortcut.tape_stop = DEFAULT_KEY_TAPE_STOP; + si->shortcut.tape_pause = DEFAULT_KEY_TAPE_PAUSE; + si->shortcut.tape_record = DEFAULT_KEY_TAPE_RECORD; + si->shortcut.tape_play = DEFAULT_KEY_TAPE_PLAY; + + si->shortcut.sound_simple = DEFAULT_KEY_SOUND_SIMPLE; + si->shortcut.sound_loops = DEFAULT_KEY_SOUND_LOOPS; + si->shortcut.sound_music = DEFAULT_KEY_SOUND_MUSIC; + for (i = 0; i < MAX_PLAYERS; i++) { si->input[i].use_joystick = FALSE; @@ -8497,6 +9374,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->options.verbose = FALSE; #if defined(CREATE_SPECIAL_EDITION_RND_JUE) + si->toons = FALSE; si->handicap = FALSE; si->fullscreen = TRUE; si->override_level_graphics = AUTO; @@ -8930,6 +9808,16 @@ static void InitMenuDesignSettings_SpecialPreProcessing() menu.enter_screen[i] = menu.enter_screen[GFX_SPECIAL_ARG_DEFAULT]; menu.leave_screen[i] = menu.leave_screen[GFX_SPECIAL_ARG_DEFAULT]; } + + /* special case: initialize "ARG_DEFAULT" values in static default config */ + /* (eg, init "viewport.door_1.MAIN.xyz" from "viewport.door_1.xyz") */ + for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++) + { + viewport.playfield[i] = viewport.playfield[GFX_SPECIAL_ARG_DEFAULT]; + viewport.door_1[i] = viewport.door_1[GFX_SPECIAL_ARG_DEFAULT]; + if (i != GFX_SPECIAL_ARG_EDITOR) /* editor value already initialized */ + viewport.door_2[i] = viewport.door_2[GFX_SPECIAL_ARG_DEFAULT]; + } } static void InitMenuDesignSettings_SpecialPostProcessing() @@ -9067,6 +9955,50 @@ static void LoadMenuDesignSettingsFromFilename(char *filename) value_6); } + /* special case: initialize with default values that may be overwritten */ + /* (eg, init "viewport.door_1.MAIN.xyz" from "viewport.door_1.xyz") */ + for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++) + { + char *token_1 = "viewport.playfield.x"; + char *token_2 = "viewport.playfield.y"; + char *token_3 = "viewport.playfield.width"; + char *token_4 = "viewport.playfield.height"; + char *token_5 = "viewport.playfield.border_size"; + char *token_6 = "viewport.door_1.x"; + char *token_7 = "viewport.door_1.y"; + char *token_8 = "viewport.door_2.x"; + char *token_9 = "viewport.door_2.y"; + char *value_1 = getHashEntry(setup_file_hash, token_1); + char *value_2 = getHashEntry(setup_file_hash, token_2); + char *value_3 = getHashEntry(setup_file_hash, token_3); + char *value_4 = getHashEntry(setup_file_hash, token_4); + char *value_5 = getHashEntry(setup_file_hash, token_5); + char *value_6 = getHashEntry(setup_file_hash, token_6); + char *value_7 = getHashEntry(setup_file_hash, token_7); + char *value_8 = getHashEntry(setup_file_hash, token_8); + char *value_9 = getHashEntry(setup_file_hash, token_9); + + if (value_1 != NULL) + viewport.playfield[i].x = get_token_parameter_value(token_1, value_1); + if (value_2 != NULL) + viewport.playfield[i].y = get_token_parameter_value(token_2, value_2); + if (value_3 != NULL) + viewport.playfield[i].width = get_token_parameter_value(token_3, value_3); + if (value_4 != NULL) + viewport.playfield[i].height = get_token_parameter_value(token_4,value_4); + if (value_5 != NULL) + viewport.playfield[i].border_size = get_token_parameter_value(token_5, + value_5); + if (value_6 != NULL) + viewport.door_1[i].x = get_token_parameter_value(token_6, value_6); + if (value_7 != NULL) + viewport.door_1[i].y = get_token_parameter_value(token_7, value_7); + if (value_8 != NULL) + viewport.door_2[i].x = get_token_parameter_value(token_8, value_8); + if (value_9 != NULL) + viewport.door_2[i].y = get_token_parameter_value(token_9, value_9); + } + /* special case: initialize with default values that may be overwritten */ /* (e.g., init "titlemessage_1.fade_mode" from "[titlemessage].fade_mode") */ for (i = 0; titlemessage_arrays[i].array != NULL; i++) @@ -9403,6 +10335,10 @@ void LoadMusicInfo() if (!music_info_listed(music_file_info, music->filename)) { *new = get_music_file_info(music->filename, i); +#if 0 + if (*new != NULL) + printf(":1: adding '%s' ['%s'] ...\n", (*new)->title, music->filename); +#endif if (*new != NULL) new = &(*new)->next; } @@ -9448,6 +10384,10 @@ void LoadMusicInfo() if (!music_info_listed(music_file_info, basename)) { *new = get_music_file_info(basename, MAP_NOCONF_MUSIC(num_music_noconf)); +#if 0 + if (*new != NULL) + printf(":2: adding '%s' ['%s'] ...\n", (*new)->title, basename); +#endif if (*new != NULL) new = &(*new)->next; } diff --git a/src/files.h b/src/files.h index 75dc3460..9edda322 100644 --- a/src/files.h +++ b/src/files.h @@ -38,6 +38,7 @@ void LoadLevel(int); void LoadLevelTemplate(int); void SaveLevel(int); void SaveLevelTemplate(); +void SaveNativeLevel(struct LevelInfo *); void DumpLevel(struct LevelInfo *); boolean SaveLevelChecked(int); diff --git a/src/game.c b/src/game.c index d4e4cf3f..aeb40a51 100644 --- a/src/game.c +++ b/src/game.c @@ -72,19 +72,19 @@ #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 @@ -194,86 +194,87 @@ #define GAME_PANEL_TIME_HH 32 #define GAME_PANEL_TIME_MM 33 #define GAME_PANEL_TIME_SS 34 -#define GAME_PANEL_SHIELD_NORMAL 35 -#define GAME_PANEL_SHIELD_NORMAL_TIME 36 -#define GAME_PANEL_SHIELD_DEADLY 37 -#define GAME_PANEL_SHIELD_DEADLY_TIME 38 -#define GAME_PANEL_EXIT 39 -#define GAME_PANEL_EMC_MAGIC_BALL 40 -#define GAME_PANEL_EMC_MAGIC_BALL_SWITCH 41 -#define GAME_PANEL_LIGHT_SWITCH 42 -#define GAME_PANEL_LIGHT_SWITCH_TIME 43 -#define GAME_PANEL_TIMEGATE_SWITCH 44 -#define GAME_PANEL_TIMEGATE_SWITCH_TIME 45 -#define GAME_PANEL_SWITCHGATE_SWITCH 46 -#define GAME_PANEL_EMC_LENSES 47 -#define GAME_PANEL_EMC_LENSES_TIME 48 -#define GAME_PANEL_EMC_MAGNIFIER 49 -#define GAME_PANEL_EMC_MAGNIFIER_TIME 50 -#define GAME_PANEL_BALLOON_SWITCH 51 -#define GAME_PANEL_DYNABOMB_NUMBER 52 -#define GAME_PANEL_DYNABOMB_SIZE 53 -#define GAME_PANEL_DYNABOMB_POWER 54 -#define GAME_PANEL_PENGUINS 55 -#define GAME_PANEL_SOKOBAN_OBJECTS 56 -#define GAME_PANEL_SOKOBAN_FIELDS 57 -#define GAME_PANEL_ROBOT_WHEEL 58 -#define GAME_PANEL_CONVEYOR_BELT_1 59 -#define GAME_PANEL_CONVEYOR_BELT_2 60 -#define GAME_PANEL_CONVEYOR_BELT_3 61 -#define GAME_PANEL_CONVEYOR_BELT_4 62 -#define GAME_PANEL_CONVEYOR_BELT_1_SWITCH 63 -#define GAME_PANEL_CONVEYOR_BELT_2_SWITCH 64 -#define GAME_PANEL_CONVEYOR_BELT_3_SWITCH 65 -#define GAME_PANEL_CONVEYOR_BELT_4_SWITCH 66 -#define GAME_PANEL_MAGIC_WALL 67 -#define GAME_PANEL_MAGIC_WALL_TIME 68 -#define GAME_PANEL_GRAVITY_STATE 69 -#define GAME_PANEL_GRAPHIC_1 70 -#define GAME_PANEL_GRAPHIC_2 71 -#define GAME_PANEL_GRAPHIC_3 72 -#define GAME_PANEL_GRAPHIC_4 73 -#define GAME_PANEL_GRAPHIC_5 74 -#define GAME_PANEL_GRAPHIC_6 75 -#define GAME_PANEL_GRAPHIC_7 76 -#define GAME_PANEL_GRAPHIC_8 77 -#define GAME_PANEL_ELEMENT_1 78 -#define GAME_PANEL_ELEMENT_2 79 -#define GAME_PANEL_ELEMENT_3 80 -#define GAME_PANEL_ELEMENT_4 81 -#define GAME_PANEL_ELEMENT_5 82 -#define GAME_PANEL_ELEMENT_6 83 -#define GAME_PANEL_ELEMENT_7 84 -#define GAME_PANEL_ELEMENT_8 85 -#define GAME_PANEL_ELEMENT_COUNT_1 86 -#define GAME_PANEL_ELEMENT_COUNT_2 87 -#define GAME_PANEL_ELEMENT_COUNT_3 88 -#define GAME_PANEL_ELEMENT_COUNT_4 89 -#define GAME_PANEL_ELEMENT_COUNT_5 90 -#define GAME_PANEL_ELEMENT_COUNT_6 91 -#define GAME_PANEL_ELEMENT_COUNT_7 92 -#define GAME_PANEL_ELEMENT_COUNT_8 93 -#define GAME_PANEL_CE_SCORE_1 94 -#define GAME_PANEL_CE_SCORE_2 95 -#define GAME_PANEL_CE_SCORE_3 96 -#define GAME_PANEL_CE_SCORE_4 97 -#define GAME_PANEL_CE_SCORE_5 98 -#define GAME_PANEL_CE_SCORE_6 99 -#define GAME_PANEL_CE_SCORE_7 100 -#define GAME_PANEL_CE_SCORE_8 101 -#define GAME_PANEL_CE_SCORE_1_ELEMENT 102 -#define GAME_PANEL_CE_SCORE_2_ELEMENT 103 -#define GAME_PANEL_CE_SCORE_3_ELEMENT 104 -#define GAME_PANEL_CE_SCORE_4_ELEMENT 105 -#define GAME_PANEL_CE_SCORE_5_ELEMENT 106 -#define GAME_PANEL_CE_SCORE_6_ELEMENT 107 -#define GAME_PANEL_CE_SCORE_7_ELEMENT 108 -#define GAME_PANEL_CE_SCORE_8_ELEMENT 109 -#define GAME_PANEL_PLAYER_NAME 110 -#define GAME_PANEL_LEVEL_NAME 111 -#define GAME_PANEL_LEVEL_AUTHOR 112 - -#define NUM_GAME_PANEL_CONTROLS 113 +#define GAME_PANEL_FRAME 35 +#define GAME_PANEL_SHIELD_NORMAL 36 +#define GAME_PANEL_SHIELD_NORMAL_TIME 37 +#define GAME_PANEL_SHIELD_DEADLY 38 +#define GAME_PANEL_SHIELD_DEADLY_TIME 39 +#define GAME_PANEL_EXIT 40 +#define GAME_PANEL_EMC_MAGIC_BALL 41 +#define GAME_PANEL_EMC_MAGIC_BALL_SWITCH 42 +#define GAME_PANEL_LIGHT_SWITCH 43 +#define GAME_PANEL_LIGHT_SWITCH_TIME 44 +#define GAME_PANEL_TIMEGATE_SWITCH 45 +#define GAME_PANEL_TIMEGATE_SWITCH_TIME 46 +#define GAME_PANEL_SWITCHGATE_SWITCH 47 +#define GAME_PANEL_EMC_LENSES 48 +#define GAME_PANEL_EMC_LENSES_TIME 49 +#define GAME_PANEL_EMC_MAGNIFIER 50 +#define GAME_PANEL_EMC_MAGNIFIER_TIME 51 +#define GAME_PANEL_BALLOON_SWITCH 52 +#define GAME_PANEL_DYNABOMB_NUMBER 53 +#define GAME_PANEL_DYNABOMB_SIZE 54 +#define GAME_PANEL_DYNABOMB_POWER 55 +#define GAME_PANEL_PENGUINS 56 +#define GAME_PANEL_SOKOBAN_OBJECTS 57 +#define GAME_PANEL_SOKOBAN_FIELDS 58 +#define GAME_PANEL_ROBOT_WHEEL 59 +#define GAME_PANEL_CONVEYOR_BELT_1 60 +#define GAME_PANEL_CONVEYOR_BELT_2 61 +#define GAME_PANEL_CONVEYOR_BELT_3 62 +#define GAME_PANEL_CONVEYOR_BELT_4 63 +#define GAME_PANEL_CONVEYOR_BELT_1_SWITCH 64 +#define GAME_PANEL_CONVEYOR_BELT_2_SWITCH 65 +#define GAME_PANEL_CONVEYOR_BELT_3_SWITCH 66 +#define GAME_PANEL_CONVEYOR_BELT_4_SWITCH 67 +#define GAME_PANEL_MAGIC_WALL 68 +#define GAME_PANEL_MAGIC_WALL_TIME 69 +#define GAME_PANEL_GRAVITY_STATE 70 +#define GAME_PANEL_GRAPHIC_1 71 +#define GAME_PANEL_GRAPHIC_2 72 +#define GAME_PANEL_GRAPHIC_3 73 +#define GAME_PANEL_GRAPHIC_4 74 +#define GAME_PANEL_GRAPHIC_5 75 +#define GAME_PANEL_GRAPHIC_6 76 +#define GAME_PANEL_GRAPHIC_7 77 +#define GAME_PANEL_GRAPHIC_8 78 +#define GAME_PANEL_ELEMENT_1 79 +#define GAME_PANEL_ELEMENT_2 80 +#define GAME_PANEL_ELEMENT_3 81 +#define GAME_PANEL_ELEMENT_4 82 +#define GAME_PANEL_ELEMENT_5 83 +#define GAME_PANEL_ELEMENT_6 84 +#define GAME_PANEL_ELEMENT_7 85 +#define GAME_PANEL_ELEMENT_8 86 +#define GAME_PANEL_ELEMENT_COUNT_1 87 +#define GAME_PANEL_ELEMENT_COUNT_2 88 +#define GAME_PANEL_ELEMENT_COUNT_3 89 +#define GAME_PANEL_ELEMENT_COUNT_4 90 +#define GAME_PANEL_ELEMENT_COUNT_5 91 +#define GAME_PANEL_ELEMENT_COUNT_6 92 +#define GAME_PANEL_ELEMENT_COUNT_7 93 +#define GAME_PANEL_ELEMENT_COUNT_8 94 +#define GAME_PANEL_CE_SCORE_1 95 +#define GAME_PANEL_CE_SCORE_2 96 +#define GAME_PANEL_CE_SCORE_3 97 +#define GAME_PANEL_CE_SCORE_4 98 +#define GAME_PANEL_CE_SCORE_5 99 +#define GAME_PANEL_CE_SCORE_6 100 +#define GAME_PANEL_CE_SCORE_7 101 +#define GAME_PANEL_CE_SCORE_8 102 +#define GAME_PANEL_CE_SCORE_1_ELEMENT 103 +#define GAME_PANEL_CE_SCORE_2_ELEMENT 104 +#define GAME_PANEL_CE_SCORE_3_ELEMENT 105 +#define GAME_PANEL_CE_SCORE_4_ELEMENT 106 +#define GAME_PANEL_CE_SCORE_5_ELEMENT 107 +#define GAME_PANEL_CE_SCORE_6_ELEMENT 108 +#define GAME_PANEL_CE_SCORE_7_ELEMENT 109 +#define GAME_PANEL_CE_SCORE_8_ELEMENT 110 +#define GAME_PANEL_PLAYER_NAME 111 +#define GAME_PANEL_LEVEL_NAME 112 +#define GAME_PANEL_LEVEL_AUTHOR 113 + +#define NUM_GAME_PANEL_CONTROLS 114 struct GamePanelOrderInfo { @@ -473,6 +474,11 @@ static struct GamePanelControlInfo game_panel_controls[] = &game.panel.time_ss, TYPE_INTEGER, }, + { + GAME_PANEL_FRAME, + &game.panel.frame, + TYPE_INTEGER, + }, { GAME_PANEL_SHIELD_NORMAL, &game.panel.shield_normal, @@ -2221,17 +2227,25 @@ void UpdateGameControlValues() local_player->LevelSolved_CountingTime : level.game_engine_type == GAME_ENGINE_TYPE_EM ? level.native_em_level->lev->time : + level.game_engine_type == GAME_ENGINE_TYPE_SP ? + level.native_sp_level->game_sp->time_played : level.time == 0 ? TimePlayed : TimeLeft); int score = (local_player->LevelSolved ? local_player->LevelSolved_CountingScore : level.game_engine_type == GAME_ENGINE_TYPE_EM ? level.native_em_level->lev->score : + level.game_engine_type == GAME_ENGINE_TYPE_SP ? + level.native_sp_level->game_sp->score : local_player->score); int gems = (level.game_engine_type == GAME_ENGINE_TYPE_EM ? level.native_em_level->lev->required : + level.game_engine_type == GAME_ENGINE_TYPE_SP ? + level.native_sp_level->game_sp->infotrons_still_needed : local_player->gems_still_needed); int exit_closed = (level.game_engine_type == GAME_ENGINE_TYPE_EM ? level.native_em_level->lev->required > 0 : + level.game_engine_type == GAME_ENGINE_TYPE_SP ? + level.native_sp_level->game_sp->infotrons_still_needed > 0 : local_player->gems_still_needed > 0 || local_player->sokobanfields_still_needed > 0 || local_player->lights_still_needed > 0); @@ -2253,6 +2267,10 @@ void UpdateGameControlValues() { for (i = 0; i < MAX_PLAYERS; i++) { + /* only one player in Supaplex game engine */ + if (level.game_engine_type == GAME_ENGINE_TYPE_SP && i > 0) + break; + for (k = 0; k < MAX_NUM_KEYS; k++) { if (level.game_engine_type == GAME_ENGINE_TYPE_EM) @@ -2269,6 +2287,9 @@ void UpdateGameControlValues() if (level.game_engine_type == GAME_ENGINE_TYPE_EM) game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value += level.native_em_level->ply[i]->dynamite; + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value += + level.native_sp_level->game_sp->red_disk_count; else game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value += stored_player[i].inventory_size; @@ -2301,6 +2322,9 @@ void UpdateGameControlValues() if (level.game_engine_type == GAME_ENGINE_TYPE_EM) game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value += level.native_em_level->ply[player_nr]->dynamite; + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value += + level.native_sp_level->game_sp->red_disk_count; else game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value += stored_player[player_nr].inventory_size; @@ -2329,6 +2353,8 @@ void UpdateGameControlValues() game_panel_controls[GAME_PANEL_TIME_MM].value = (time / 60) % 60; game_panel_controls[GAME_PANEL_TIME_SS].value = time % 60; + game_panel_controls[GAME_PANEL_FRAME].value = FrameCounter; + game_panel_controls[GAME_PANEL_SHIELD_NORMAL].value = (local_player->shield_normal_time_left > 0 ? EL_SHIELD_NORMAL_ACTIVE : EL_EMPTY); @@ -3694,6 +3720,15 @@ void InitGame() game_status = GAME_MODE_PLAYING; +#if 1 + /* needed if different viewport properties defined for playing */ + ChangeViewportPropertiesIfNeeded(); +#endif + +#if 1 + DrawCompleteVideoDisplay(); +#endif + InitGameEngine(); InitGameControlValues(); @@ -4468,6 +4503,13 @@ void InitGame() /* blit playfield from scroll buffer to normal back buffer for fading in */ BlitScreenToBitmap_EM(backbuffer); } + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + { + InitGameEngine_SP(); + + /* blit playfield from scroll buffer to normal back buffer for fading in */ + BlitScreenToBitmap_SP(backbuffer); + } else { DrawLevel(); @@ -5765,10 +5807,19 @@ void RelocatePlayer(int jx, int jy, int el_player_raw) Feld[jx][jy] = el_player; InitPlayerField(jx, jy, el_player, TRUE); + /* "InitPlayerField()" above sets Feld[jx][jy] to EL_EMPTY, but it may be + possible that the relocation target field did not contain a player element, + but a walkable element, to which the new player was relocated -- in this + case, restore that (already initialized!) element on the player field */ if (!ELEM_IS_PLAYER(element)) /* player may be set on walkable element */ { - Feld[jx][jy] = element; + Feld[jx][jy] = element; /* restore previously existing element */ +#if 0 + /* !!! do not initialize already initialized element a second time !!! */ + /* (this causes at least problems with "element creation" CE trigger for + already existing elements, and existing Sokoban fields counted twice) */ InitField(jx, jy, FALSE); +#endif } /* only visually relocate centered player */ @@ -6116,7 +6167,7 @@ void Explode(int ex, int ey, int phase, int mode) TestIfElementTouchesCustomElement(x, y); if (GFX_CRUMBLED(element)) - TEST_DrawLevelFieldCrumbledSandNeighbours(x, y); + TEST_DrawLevelFieldCrumbledNeighbours(x, y); if (IS_PLAYER(x, y) && !PLAYERINFO(x, y)->present) StorePlayer[x][y] = 0; @@ -6130,7 +6181,7 @@ void Explode(int ex, int ey, int phase, int mode) int frame = getGraphicAnimationFrame(graphic, GfxFrame[x][y]); if (phase == delay) - TEST_DrawLevelFieldCrumbledSand(x, y); + TEST_DrawLevelFieldCrumbled(x, y); if (IS_WALKABLE_OVER(Back[x][y]) && Back[x][y] != EL_EMPTY) { @@ -6588,7 +6639,7 @@ static void RedrawAllLightSwitchesAndInvisibleElements() /* uncrumble neighbour fields, if needed */ if (element == EL_INVISIBLE_SAND) - TEST_DrawLevelFieldCrumbledSandNeighbours(x, y); + TEST_DrawLevelFieldCrumbledNeighbours(x, y); } else if (element == EL_INVISIBLE_STEELWALL_ACTIVE || element == EL_INVISIBLE_WALL_ACTIVE || @@ -6601,7 +6652,7 @@ static void RedrawAllLightSwitchesAndInvisibleElements() /* re-crumble neighbour fields, if needed */ if (element == EL_INVISIBLE_SAND) - TEST_DrawLevelFieldCrumbledSandNeighbours(x, y); + TEST_DrawLevelFieldCrumbledNeighbours(x, y); } } } @@ -6637,7 +6688,7 @@ static void RedrawAllInvisibleElementsForLenses() /* uncrumble neighbour fields, if needed */ if (element == EL_INVISIBLE_SAND) - TEST_DrawLevelFieldCrumbledSandNeighbours(x, y); + TEST_DrawLevelFieldCrumbledNeighbours(x, y); } else if (element == EL_INVISIBLE_STEELWALL_ACTIVE || element == EL_INVISIBLE_WALL_ACTIVE || @@ -6650,7 +6701,7 @@ static void RedrawAllInvisibleElementsForLenses() /* re-crumble neighbour fields, if needed */ if (element == EL_INVISIBLE_SAND) - TEST_DrawLevelFieldCrumbledSandNeighbours(x, y); + TEST_DrawLevelFieldCrumbledNeighbours(x, y); } } } @@ -8467,7 +8518,7 @@ void StartMoving(int x, int y) if (IN_SCR_FIELD(sx, sy)) { - TEST_DrawLevelFieldCrumbledSand(xx, yy); + TEST_DrawLevelFieldCrumbled(xx, yy); DrawGraphic(sx, sy, flame_graphic, frame); } } @@ -8970,7 +9021,7 @@ void ContinueMoving(int x, int y) { Feld[x][y] = EL_SAND; - TEST_DrawLevelFieldCrumbledSandNeighbours(x, y); + TEST_DrawLevelFieldCrumbledNeighbours(x, y); } else if (element == EL_QUICKSAND_FILLING) { @@ -9137,7 +9188,7 @@ void ContinueMoving(int x, int y) InitField(x, y, FALSE); if (GFX_CRUMBLED(Feld[x][y])) - TEST_DrawLevelFieldCrumbledSandNeighbours(x, y); + TEST_DrawLevelFieldCrumbledNeighbours(x, y); if (ELEM_IS_PLAYER(move_leave_element)) RelocatePlayer(x, y, move_leave_element); @@ -10331,7 +10382,7 @@ static void ChangeActiveTrap(int x, int y) /* if new animation frame was drawn, correct crumbled sand border */ if (IS_NEW_FRAME(GfxFrame[x][y], graphic)) - TEST_DrawLevelFieldCrumbledSand(x, y); + TEST_DrawLevelFieldCrumbled(x, y); } static int getSpecialActionElement(int element, int number, int base_element) @@ -11067,7 +11118,7 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change) TEST_DrawLevelField(x, y); if (GFX_CRUMBLED(new_element)) - TEST_DrawLevelFieldCrumbledSandNeighbours(x, y); + TEST_DrawLevelFieldCrumbledNeighbours(x, y); } #if 1 @@ -11976,7 +12027,16 @@ static byte PlayerActions(struct PlayerInfo *player, byte player_action) if (tape.single_step && tape.recording && !tape.pausing) { +#if 1 + /* as it is called "single step mode", just return to pause mode when the + player stopped moving after one tile (or never starts moving at all) */ + if (!player->is_moving) +#else + /* this is buggy: there are quite some cases where the single step mode + does not return to pause mode (like pushing things that don't move + or simply by trying to run against a wall) */ if (button1 || (dropped && !moved)) +#endif { TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); SnapField(player, 0, 0); /* stop snapping */ @@ -12013,6 +12073,7 @@ static void CheckLevelTime() { int i; + /* !!! SAME CODE AS IN "GameActions()" -- FIX THIS !!! */ if (level.game_engine_type == GAME_ENGINE_TYPE_EM) { if (level.native_em_level->lev->home == 0) /* all players at home */ @@ -12030,6 +12091,21 @@ static void CheckLevelTime() level.native_em_level->ply[3]->alive == 0) /* all dead */ AllPlayersGone = TRUE; } + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + { + if (game_sp.LevelSolved && + !game_sp.GameOver) /* game won */ + { + PlayerWins(local_player); + + game_sp.GameOver = TRUE; + + AllPlayersGone = TRUE; + } + + if (game_sp.GameOver) /* game lost */ + AllPlayersGone = TRUE; + } if (TimeFrames >= FRAMES_PER_SECOND) { @@ -12207,6 +12283,7 @@ void GameActions() if (game.restart_level) StartGameActions(options.network, setup.autorecord, level.random_seed); + /* !!! SAME CODE AS IN "CheckLevelTime()" -- FIX THIS !!! */ if (level.game_engine_type == GAME_ENGINE_TYPE_EM) { if (level.native_em_level->lev->home == 0) /* all players at home */ @@ -12224,6 +12301,21 @@ void GameActions() level.native_em_level->ply[3]->alive == 0) /* all dead */ AllPlayersGone = TRUE; } + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + { + if (game_sp.LevelSolved && + !game_sp.GameOver) /* game won */ + { + PlayerWins(local_player); + + game_sp.GameOver = TRUE; + + AllPlayersGone = TRUE; + } + + if (game_sp.GameOver) /* game lost */ + AllPlayersGone = TRUE; + } if (local_player->LevelSolved && !local_player->LevelSolved_GameEnd) GameWon(); @@ -12341,6 +12433,10 @@ void GameActions() { GameActions_EM_Main(); } + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + { + GameActions_SP_Main(); + } else { GameActions_RND(); @@ -12363,6 +12459,22 @@ void GameActions_EM_Main() AdvanceFrameAndPlayerCounters(-1); /* advance counters for all players */ } +void GameActions_SP_Main() +{ + byte effective_action[MAX_PLAYERS]; + boolean warp_mode = (tape.playing && tape.warp_forward && !tape.pausing); + int i; + + for (i = 0; i < MAX_PLAYERS; i++) + effective_action[i] = stored_player[i].effective_action; + + GameActions_SP(effective_action, warp_mode); + + CheckLevelTime(); + + AdvanceFrameAndPlayerCounters(-1); /* advance counters for all players */ +} + void GameActions_RND() { int magic_wall_x = 0, magic_wall_y = 0; @@ -13075,10 +13187,10 @@ void GameActions_RND() DrawLevelField(x, y); if (GfxRedraw[x][y] & GFX_REDRAW_TILE_CRUMBLED) - DrawLevelFieldCrumbledSand(x, y); + DrawLevelFieldCrumbled(x, y); if (GfxRedraw[x][y] & GFX_REDRAW_TILE_CRUMBLED_NEIGHBOURS) - DrawLevelFieldCrumbledSandNeighbours(x, y); + DrawLevelFieldCrumbledNeighbours(x, y); if (GfxRedraw[x][y] & GFX_REDRAW_TILE_TWINKLED) DrawTwinkleOnField(x, y); @@ -15321,8 +15433,13 @@ static int DigField(struct PlayerInfo *player, PlayLevelSoundElementAction(nextx, nexty, EL_SOKOBAN_FIELD_EMPTY, ACTION_FILLING); +#if 1 + if (local_player->sokobanfields_still_needed == 0 && + (game.emulation == EMU_SOKOBAN || level.auto_exit_sokoban)) +#else if (local_player->sokobanfields_still_needed == 0 && game.emulation == EMU_SOKOBAN) +#endif { PlayerWins(player); @@ -16108,6 +16225,21 @@ void PlayLevelSound_EM(int xx, int yy, int element_em, int sample) } } +void PlayLevelSound_SP(int xx, int yy, int element_sp, int action_sp) +{ + int element = map_element_SP_to_RND(element_sp); + int action = map_action_SP_to_RND(action_sp); + int offset = (setup.sp_show_border_elements ? 0 : 1); + int x = xx - offset; + int y = yy - offset; + +#if 0 + printf("::: %d -> %d\n", element_sp, action_sp); +#endif + + PlayLevelSoundElementAction(x, y, element, action); +} + #if 0 void ChangeTime(int value) { @@ -16331,8 +16463,6 @@ unsigned int RND(int max) /* game engine snapshot handling functions */ /* ------------------------------------------------------------------------- */ -#define ARGS_ADDRESS_AND_SIZEOF(x) (&(x)), (sizeof(x)) - struct EngineSnapshotInfo { /* runtime values for custom element collect score */ @@ -16342,32 +16472,14 @@ struct EngineSnapshotInfo int choice_pos[NUM_GROUP_ELEMENTS]; /* runtime values for belt position animations */ - int belt_graphic[4 * NUM_BELT_PARTS]; - int belt_anim_mode[4 * NUM_BELT_PARTS]; -}; - -struct EngineSnapshotNodeInfo -{ - void *buffer_orig; - void *buffer_copy; - int size; + int belt_graphic[4][NUM_BELT_PARTS]; + int belt_anim_mode[4][NUM_BELT_PARTS]; }; static struct EngineSnapshotInfo engine_snapshot_rnd; -static ListNode *engine_snapshot_list = NULL; static char *snapshot_level_identifier = NULL; static int snapshot_level_nr = -1; -void FreeEngineSnapshot() -{ - while (engine_snapshot_list != NULL) - deleteNodeFromList(&engine_snapshot_list, engine_snapshot_list->key, - checked_free); - - setString(&snapshot_level_identifier, NULL); - snapshot_level_nr = -1; -} - static void SaveEngineSnapshotValues_RND() { static int belt_base_active_element[4] = @@ -16401,8 +16513,8 @@ static void SaveEngineSnapshotValues_RND() int graphic = el2img(element); int anim_mode = graphic_info[graphic].anim_mode; - engine_snapshot_rnd.belt_graphic[i * 4 + j] = graphic; - engine_snapshot_rnd.belt_anim_mode[i * 4 + j] = anim_mode; + engine_snapshot_rnd.belt_graphic[i][j] = graphic; + engine_snapshot_rnd.belt_anim_mode[i][j] = anim_mode; } } } @@ -16430,8 +16542,8 @@ static void LoadEngineSnapshotValues_RND() { for (j = 0; j < NUM_BELT_PARTS; j++) { - int graphic = engine_snapshot_rnd.belt_graphic[i * 4 + j]; - int anim_mode = engine_snapshot_rnd.belt_anim_mode[i * 4 + j]; + int graphic = engine_snapshot_rnd.belt_graphic[i][j]; + int anim_mode = engine_snapshot_rnd.belt_anim_mode[i][j]; graphic_info[graphic].anim_mode = anim_mode; } @@ -16453,36 +16565,26 @@ static void LoadEngineSnapshotValues_RND() } } -static void SaveEngineSnapshotBuffer(void *buffer, int size) -{ - struct EngineSnapshotNodeInfo *bi = - checked_calloc(sizeof(struct EngineSnapshotNodeInfo)); - - bi->buffer_orig = buffer; - bi->buffer_copy = checked_malloc(size); - bi->size = size; - - memcpy(bi->buffer_copy, buffer, size); - - addNodeToList(&engine_snapshot_list, NULL, bi); -} - void SaveEngineSnapshot() { - FreeEngineSnapshot(); /* free previous snapshot, if needed */ - - if (level_editor_test_game) /* do not save snapshots from editor */ + /* do not save snapshots from editor */ + if (level_editor_test_game) return; + /* free previous snapshot buffers, if needed */ + FreeEngineSnapshotBuffers(); + /* copy some special values to a structure better suited for the snapshot */ SaveEngineSnapshotValues_RND(); SaveEngineSnapshotValues_EM(); + SaveEngineSnapshotValues_SP(); /* save values stored in special snapshot structure */ SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_rnd)); SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_em)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_sp)); /* save further RND engine values */ @@ -16556,7 +16658,7 @@ void SaveEngineSnapshot() snapshot_level_nr = level_nr; #if 0 - ListNode *node = engine_snapshot_list; + ListNode *node = engine_snapshot_list_rnd; int num_bytes = 0; while (node != NULL) @@ -16570,29 +16672,17 @@ void SaveEngineSnapshot() #endif } -static void LoadEngineSnapshotBuffer(struct EngineSnapshotNodeInfo *bi) -{ - memcpy(bi->buffer_orig, bi->buffer_copy, bi->size); -} - void LoadEngineSnapshot() { - ListNode *node = engine_snapshot_list; - - if (engine_snapshot_list == NULL) - return; + /* restore generically stored snapshot buffers */ - while (node != NULL) - { - LoadEngineSnapshotBuffer((struct EngineSnapshotNodeInfo *)node->content); - - node = node->next; - } + LoadEngineSnapshotBuffers(); /* restore special values from snapshot structure */ LoadEngineSnapshotValues_RND(); LoadEngineSnapshotValues_EM(); + LoadEngineSnapshotValues_SP(); } boolean CheckEngineSnapshot() @@ -16805,10 +16895,8 @@ void RedrawGameButtons() RedrawGadget(game_gadget[i]); } -static void HandleGameButtons(struct GadgetInfo *gi) +static void HandleGameButtonsExt(int id) { - int id = gi->custom_id; - if (game_status != GAME_MODE_PLAYING) return; @@ -16854,6 +16942,7 @@ static void HandleGameButtons(struct GadgetInfo *gi) if (setup.sound_music) { setup.sound_music = FALSE; + FadeMusic(); } else if (audio.music_available) @@ -16872,6 +16961,7 @@ static void HandleGameButtons(struct GadgetInfo *gi) else if (audio.loops_available) { setup.sound = setup.sound_loops = TRUE; + SetAudioMode(setup.sound); } break; @@ -16882,6 +16972,7 @@ static void HandleGameButtons(struct GadgetInfo *gi) else if (audio.sound_available) { setup.sound = setup.sound_simple = TRUE; + SetAudioMode(setup.sound); } break; @@ -16890,3 +16981,27 @@ static void HandleGameButtons(struct GadgetInfo *gi) break; } } + +static void HandleGameButtons(struct GadgetInfo *gi) +{ + HandleGameButtonsExt(gi->custom_id); +} + +void HandleSoundButtonKeys(Key key) +{ +#if 1 + if (key == setup.shortcut.sound_simple) + ClickOnGadget(game_gadget[SOUND_CTRL_ID_SIMPLE], MB_LEFTBUTTON); + else if (key == setup.shortcut.sound_loops) + ClickOnGadget(game_gadget[SOUND_CTRL_ID_LOOPS], MB_LEFTBUTTON); + else if (key == setup.shortcut.sound_music) + ClickOnGadget(game_gadget[SOUND_CTRL_ID_MUSIC], MB_LEFTBUTTON); +#else + if (key == setup.shortcut.sound_simple) + HandleGameButtonsExt(SOUND_CTRL_ID_SIMPLE); + else if (key == setup.shortcut.sound_loops) + HandleGameButtonsExt(SOUND_CTRL_ID_LOOPS); + else if (key == setup.shortcut.sound_music) + HandleGameButtonsExt(SOUND_CTRL_ID_MUSIC); +#endif +} diff --git a/src/game.h b/src/game.h index 7a9bf984..c764e1d3 100644 --- a/src/game.h +++ b/src/game.h @@ -47,6 +47,7 @@ struct GamePanelInfo struct TextPosInfo time_hh; struct TextPosInfo time_mm; struct TextPosInfo time_ss; + struct TextPosInfo frame; struct TextPosInfo shield_normal; struct TextPosInfo shield_normal_time; struct TextPosInfo shield_deadly; @@ -117,6 +118,8 @@ struct GameInfo /* values for graphics engine customization */ boolean use_native_emc_graphics_engine; + boolean use_native_sp_graphics_engine; + boolean use_masked_pushing; int forced_scroll_delay_value; int scroll_delay_value; @@ -331,12 +334,14 @@ void StartGameActions(boolean, boolean, long); void GameActions(void); void GameActions_EM_Main(); +void GameActions_SP_Main(); void GameActions_RND(); void ScrollLevel(int, int); void InitPlayLevelSound(); void PlayLevelSound_EM(int, int, int, int); +void PlayLevelSound_SP(int, int, int, int); void RaiseScore(int); void RaiseScoreElement(int); @@ -357,4 +362,6 @@ void FreeGameButtons(); void UnmapGameButtons(); void RedrawGameButtons(); +void HandleSoundButtonKeys(Key); + #endif diff --git a/src/game_em/Makefile b/src/game_em/Makefile index aec69d09..4fc21cd0 100644 --- a/src/game_em/Makefile +++ b/src/game_em/Makefile @@ -1,7 +1,7 @@ # ============================================================================= # Rocks'n'Diamonds Makefile (game_em) # ----------------------------------------------------------------------------- -# (c) 1995-2005 Holger Schemel +# (c) 1995-2006 Holger Schemel # ----------------------------------------------------------------------------- # Emerald Mine for X11 © 2000,2001 David Tritscher # ============================================================================= diff --git a/src/game_em/graphics.c b/src/game_em/graphics.c index 29d9e15d..5764e9e3 100644 --- a/src/game_em/graphics.c +++ b/src/game_em/graphics.c @@ -29,15 +29,21 @@ #define USE_EXTENDED_GRAPHICS_ENGINE 1 -int frame; /* current screen frame */ -int screen_x; /* current scroll position */ -int screen_y; +int frame; /* current screen frame */ +int screen_x, screen_y; /* current scroll position */ /* tiles currently on screen */ +#if 1 +static int screentiles[MAX_PLAYFIELD_HEIGHT + 2][MAX_PLAYFIELD_WIDTH + 2]; +static int crumbled_state[MAX_PLAYFIELD_HEIGHT + 2][MAX_PLAYFIELD_WIDTH + 2]; + +static boolean redraw[MAX_PLAYFIELD_WIDTH + 2][MAX_PLAYFIELD_HEIGHT + 2]; +#else static int screentiles[MAX_BUF_YSIZE][MAX_BUF_XSIZE]; static int crumbled_state[MAX_BUF_YSIZE][MAX_BUF_XSIZE]; static boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE]; +#endif #if 0 #if 1 @@ -96,12 +102,21 @@ void BlitScreenToBitmap_EM(Bitmap *target_bitmap) void BackToFront_EM(void) { + static int screen_x_last = -1, screen_y_last = -1; static boolean scrolling_last = FALSE; int left = screen_x / TILEX; int top = screen_y / TILEY; +#if 1 + boolean scrolling = (screen_x != screen_x_last || screen_y != screen_y_last); +#else boolean scrolling = (screen_x % TILEX != 0 || screen_y % TILEY != 0); +#endif int x, y; +#if 0 + printf("::: %d, %d\n", screen_x, screen_y); +#endif + SyncDisplay(); if (redraw_tiles > REDRAWTILES_THRESHOLD || scrolling || scrolling_last) @@ -114,6 +129,50 @@ void BackToFront_EM(void) } else { +#if 1 +#if 1 + boolean half_shifted_x = (screen_x % TILEX != 0); + boolean half_shifted_y = (screen_y % TILEY != 0); +#else + boolean half_shifted_x = (EVEN(SCR_FIELDX) && screen_x % TILEX != 0); + boolean half_shifted_y = (EVEN(SCR_FIELDY) && screen_y % TILEY != 0); +#endif + +#if 0 +#if 1 + printf("::: %d, %d\n", EVEN(SCR_FIELDX), screen_x); +#else + half_shifted_x = TRUE; + half_shifted_y = FALSE; +#endif +#endif + + int x1 = 0, x2 = SCR_FIELDX - (half_shifted_x ? 0 : 1); + int y1 = 0, y2 = SCR_FIELDY - (half_shifted_y ? 0 : 1); + int scroll_xoffset = (half_shifted_x ? TILEX / 2 : 0); + int scroll_yoffset = (half_shifted_y ? TILEY / 2 : 0); + + InitGfxClipRegion(TRUE, SX, SY, SXSIZE, SYSIZE); + + for (x = x1; x <= x2; x++) + { + for (y = y1; y <= y2; y++) + { + int xx = (left + x) % MAX_BUF_XSIZE; + int yy = (top + y) % MAX_BUF_YSIZE; + + if (redraw[xx][yy]) + BlitBitmap(screenBitmap, window, + xx * TILEX, yy * TILEY, TILEX, TILEY, + SX + x * TILEX - scroll_xoffset, + SY + y * TILEY - scroll_yoffset); + } + } + + InitGfxClipRegion(FALSE, -1, -1, -1, -1); + +#else + for (x = 0; x < SCR_FIELDX; x++) { for (y = 0; y < SCR_FIELDY; y++) @@ -127,6 +186,7 @@ void BackToFront_EM(void) SX + x * TILEX, SY + y * TILEY); } } +#endif } FlushDisplay(); @@ -136,6 +196,8 @@ void BackToFront_EM(void) redraw[x][y] = FALSE; redraw_tiles = 0; + screen_x_last = screen_x; + screen_y_last = screen_y; scrolling_last = scrolling; } @@ -207,7 +269,11 @@ static void DrawLevelField_EM(int x, int y, int sx, int sy, static void DrawLevelFieldCrumbled_EM(int x, int y, int sx, int sy, int crm, boolean draw_masked) { +#if 1 + struct GraphicInfo_EM *g; +#else struct GraphicInfo_EM *g = getObjectGraphic(x, y); +#endif int left = screen_x / TILEX; int top = screen_y / TILEY; int i; @@ -220,6 +286,10 @@ static void DrawLevelFieldCrumbled_EM(int x, int y, int sx, int sy, if (crm == 0) /* no crumbled edges for this tile */ return; +#if 1 + g = getObjectGraphic(x, y); +#endif + #if 0 if (x == 3 && y == 3 && frame == 0) printf("::: %d, %d\n", @@ -433,6 +503,10 @@ static void blitplayer(struct PLAYER *ply) x2 = x1 + TILEX - 1; y2 = y1 + TILEY - 1; +#if 0 + printf("::: %d, %d\n", x1, y1); +#endif + if ((int)(x2 - screen_x) < ((MAX_BUF_XSIZE - 1) * TILEX - 1) && (int)(y2 - screen_y) < ((MAX_BUF_YSIZE - 1) * TILEY - 1)) { diff --git a/src/game_em/input.c b/src/game_em/input.c index cc703ba9..7447f4b1 100644 --- a/src/game_em/input.c +++ b/src/game_em/input.c @@ -91,6 +91,7 @@ void GameActions_EM(byte action[MAX_PLAYERS], boolean warp_mode) printf("::: %05d: %lu, %d\n", FrameCounter, RandomEM, frame); #endif +#if 0 game_animscreen(); #if 1 @@ -99,6 +100,7 @@ void GameActions_EM(byte action[MAX_PLAYERS], boolean warp_mode) #endif blitscreen(); +#endif #endif RandomEM = RandomEM * 129 + 1; @@ -124,6 +126,20 @@ void GameActions_EM(byte action[MAX_PLAYERS], boolean warp_mode) if (!warp_mode) /* do not redraw values in warp mode */ DrawGameDoorValues_EM(); } + + CheckSingleStepMode_EM(action, frame, game_em.any_player_moving); + +#if 1 + game_animscreen(); + +#if 1 +#if 0 + SyncDisplay(); +#endif + + blitscreen(); +#endif +#endif } /* read input device for players */ diff --git a/src/game_em/main_em.h b/src/game_em/main_em.h index 87e9d952..c5efc415 100644 --- a/src/game_em/main_em.h +++ b/src/game_em/main_em.h @@ -69,17 +69,24 @@ #define ORIG_SCR_MENUY 12 #define SCR_MENUX 17 #define SCR_MENUY 12 +#if 1 +extern int SCR_FIELDX, SCR_FIELDY; +#else #define SCR_FIELDX 17 #define SCR_FIELDY 17 +#endif #define MAX_BUF_XSIZE (SCR_FIELDX + 2) #define MAX_BUF_YSIZE (SCR_FIELDY + 2) /* often used screen positions */ #define ORIG_MENU_SX ((ORIG_SCR_MENUX - SCR_MENUX) * TILEX / 2) #define ORIG_MENU_SY 0 -#define SY 8 +#if 1 +extern int SX, SY; +#else #define SX 8 #define SY 8 +#endif #define SXSIZE (SCR_FIELDX * TILEX) #define SYSIZE (SCR_FIELDY * TILEY) diff --git a/src/game_sp/ASM.c b/src/game_sp/ASM.c new file mode 100644 index 00000000..ae2de3ee --- /dev/null +++ b/src/game_sp/ASM.c @@ -0,0 +1,36 @@ +// ---------------------------------------------------------------------------- +// ASM.c +// ---------------------------------------------------------------------------- + +#include "ASM.h" + + +void MovLowByte(int *p, int i) +{ + *p = (*p & 0xff00) | (i & 0xff); +} + +void MovHighByte(int *p, int i) +{ + *p = (*p & 0xff) | ((i << 8) & 0xff00); +} + +int LowByte(int i) +{ + return (i & 0xff); +} + +int HighByte(int i) +{ + return ((i >> 8) & 0xff); +} + +int SgnHighByte(int i) +{ + return (signed char)HighByte(i); +} + +int ByteToInt(byte b) +{ + return (signed char)b; +} diff --git a/src/game_sp/ASM.h b/src/game_sp/ASM.h new file mode 100644 index 00000000..a149c808 --- /dev/null +++ b/src/game_sp/ASM.h @@ -0,0 +1,18 @@ +// ---------------------------------------------------------------------------- +// ASM.h +// ---------------------------------------------------------------------------- + +#ifndef ASM_H +#define ASM_H + +#include "global.h" + + +extern void MovLowByte(int *, int); +extern void MovHighByte(int *, int); +extern int LowByte(int); +extern int HighByte(int); +extern int SgnHighByte(int); +extern int ByteToInt(byte); + +#endif /* ASM_H */ diff --git a/src/game_sp/BugsTerminals.c b/src/game_sp/BugsTerminals.c new file mode 100644 index 00000000..94850270 --- /dev/null +++ b/src/game_sp/BugsTerminals.c @@ -0,0 +1,153 @@ +// ---------------------------------------------------------------------------- +// BugsTerminals.c +// ---------------------------------------------------------------------------- + +#include "BugsTerminals.h" + + +#if 1 +byte TerminalState[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE]; +#else +byte *TerminalState; +#endif + +int TerminalMaxCycles; + + +// ========================================================================== +// SUBROUTINE +// Animate bugs +// ========================================================================== + +void subAnimateBugs(int si) +{ + int bl; + + if (fiBug != LowByte(PlayField16[si])) + return; + + bl = SgnHighByte(PlayField16[si]); // get and increment sequence number + + if ((TimerVar & 3) == 0) + { + bl = bl + 1; + if (bl >= 14) // bugs animation has 14 frames + { + bl = subGetRandomNumber(); // generate new random number + bl = -((bl & 0x3F) + 0x20); + } + + MovHighByte(&PlayField16[si], bl); // save sequence number + } + + if (bl < 0) // bug sleeps / is inactive + return; + + // now the bug is active! Beware Murphy! + if ((TimerVar & 3) == 0 && + (LowByte(PlayField16[si - FieldWidth - 1]) == fiMurphy || + LowByte(PlayField16[si - FieldWidth]) == fiMurphy || + LowByte(PlayField16[si - FieldWidth + 1]) == fiMurphy || + LowByte(PlayField16[si - 1]) == fiMurphy || + LowByte(PlayField16[si + 1]) == fiMurphy || + LowByte(PlayField16[si + FieldWidth - 1]) == fiMurphy || + LowByte(PlayField16[si + FieldWidth]) == fiMurphy || + LowByte(PlayField16[si + FieldWidth + 1]) == fiMurphy)) + subSoundFX(si, fiBug, actActive); // play dangerous sound + + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + GfxGraphic[GetX(si)][GetY(si)] = (bl == 0 ? aniBugActivating : + bl == 12 ? aniBugDeactivating : + bl == 13 ? aniBug : aniBugActive); + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +} + + +// ========================================================================== +// SUBROUTINE +// Animate terminals +// ========================================================================== + +void subAnimateTerminals(int si) +{ + int bl; + + int lx = GetX(si); + int ly = GetY(si); + int graphic; + + if (LowByte(PlayField16[si]) != fiTerminal) + return; + + /* use native frame handling (undo frame incrementation in main loop) */ + if (game.use_native_sp_graphics_engine) + GfxFrame[lx][ly]--; + + /* get last random animation delay */ + bl = SgnHighByte(PlayField16[si]); + + bl = bl + 1; + if (bl <= 0) /* return if random animation delay not yet reached */ + { + MovHighByte(&PlayField16[si], bl); + + return; + } + + /* calculate new random animation delay */ + bl = -(subGetRandomNumber() & TerminalMaxCycles); // generate new random number + MovHighByte(&PlayField16[si], bl); // save new sequence number + + /* check terminal state (active or inactive) */ + bl = TerminalState[si] + 1; + if (bl == 8) + bl = 0; + else if (15 < bl) + bl = 8; + + TerminalState[si] = bl; + + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + graphic = (bl < 8 ? aniTerminal : aniTerminalActive); + + if (game.use_native_sp_graphics_engine) + GfxFrame[lx][ly] += getGraphicInfo_Delay(graphic); + + GfxGraphic[lx][ly] = (bl < 8 ? aniTerminal : aniTerminalActive); + + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +} + + +// ========================================================================== +// SUBROUTINE +// Randomize random number generator +// ========================================================================== + +void subRandomize() +{ + long Tick = MyGetTickCount(); + + RandomSeed = (Tick ^ (Tick >> 16)) & 0xFFFF; +} + + +// ========================================================================== +// SUBROUTINE +// Generate new random number, first method (see also sub_g_8580) +// ========================================================================== + +int subGetRandomNumber() +{ + RandomSeed = (RandomSeed * 0x5E5 + 0x31) & 0xFFFF; + + return (RandomSeed >> 1); + + // Mov ax, randomseed + // Mov bx, &H5E5 + // mul bx ' dx:ax = reg * ax + // Add ax, &H31 + // Mov randomseed, ax + // shr ax,1 +} diff --git a/src/game_sp/BugsTerminals.h b/src/game_sp/BugsTerminals.h new file mode 100644 index 00000000..61458526 --- /dev/null +++ b/src/game_sp/BugsTerminals.h @@ -0,0 +1,23 @@ +// ---------------------------------------------------------------------------- +// BugsTerminals.h +// ---------------------------------------------------------------------------- + +#ifndef BUGSTERMINALS_H +#define BUGSTERMINALS_H + +#include "global.h" + +#if 1 +extern byte TerminalState[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE]; +#else +extern byte *TerminalState; +#endif + +extern int TerminalMaxCycles; + +extern void subAnimateBugs(int si); +extern void subAnimateTerminals(int si); +extern void subRandomize(); +extern int subGetRandomNumber(); + +#endif /* BUGSTERMINALS_H */ diff --git a/src/game_sp/DDScrollBuffer.c b/src/game_sp/DDScrollBuffer.c new file mode 100644 index 00000000..e8bd2fbc --- /dev/null +++ b/src/game_sp/DDScrollBuffer.c @@ -0,0 +1,386 @@ +// ---------------------------------------------------------------------------- +// DDScrollBuffer.c +// ---------------------------------------------------------------------------- + +#include "DDScrollBuffer.h" + +#include + + +long mScrollX, mScrollY; +long mScrollX_last, mScrollY_last; + +#if 1 +long ScreenBuffer[2 + MAX_PLAYFIELD_WIDTH + 2][2 + MAX_PLAYFIELD_HEIGHT + 2]; +boolean redraw[2 + MAX_PLAYFIELD_WIDTH + 2][2 + MAX_PLAYFIELD_HEIGHT + 2]; +#else +long ScreenBuffer[MAX_BUF_XSIZE][MAX_BUF_YSIZE]; +boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE]; +#endif + + +void RestorePlayfield() +{ + int x1 = mScrollX / TILEX - 2; + int y1 = mScrollY / TILEY - 2; + int x2 = mScrollX / TILEX + (SCR_FIELDX - 1) + 2; + int y2 = mScrollY / TILEY + (SCR_FIELDY - 1) + 2; + int x, y; + + DrawFrameIfNeeded(); + + for (y = DisplayMinY; y <= DisplayMaxY; y++) + { + for (x = DisplayMinX; x <= DisplayMaxX; x++) + { + if (x >= x1 && x <= x2 && y >= y1 && y <= y2) + { + DrawFieldNoAnimated(x, y); + DrawFieldAnimated(x, y); + } + } + } +} + +static void ScrollPlayfield(int dx, int dy) +{ + int x1 = mScrollX_last / TILEX - 2; + int y1 = mScrollY_last / TILEY - 2; + int x2 = mScrollX_last / TILEX + (SCR_FIELDX - 1) + 2; + int y2 = mScrollY_last / TILEY + (SCR_FIELDY - 1) + 2; + int x, y; + + BlitBitmap(bitmap_db_field_sp, bitmap_db_field_sp, + TILEX * (dx == -1), + TILEY * (dy == -1), + (MAX_BUF_XSIZE * TILEX) - TILEX * (dx != 0), + (MAX_BUF_YSIZE * TILEY) - TILEY * (dy != 0), + TILEX * (dx == 1), + TILEY * (dy == 1)); + + /* when scrolling the whole playfield, do not redraw single tiles */ + for (x = 0; x < MAX_BUF_XSIZE; x++) + for (y = 0; y < MAX_BUF_YSIZE; y++) + redraw[x][y] = FALSE; + redraw_tiles = 0; + + DrawFrameIfNeeded(); + + for (y = DisplayMinY; y <= DisplayMaxY; y++) + { + for (x = DisplayMinX; x <= DisplayMaxX; x++) + { + if (x >= x1 && x <= x2 && y >= y1 && y <= y2) + { + int sx = x - x1; + int sy = y - y1; + int tsi = GetSI(x, y); + long id = ((PlayField16[tsi]) | + (PlayField8[tsi] << 16) | + (DisPlayField[tsi] << 24)); + + if ((dx == -1 && x == x2) || + (dx == +1 && x == x1) || + (dy == -1 && y == y2) || + (dy == +1 && y == y1)) + { + DrawFieldNoAnimated(x, y); + DrawFieldAnimated(x, y); + } + + ScreenBuffer[sx][sy] = id; + } + } + } +} + +static void ScrollPlayfieldIfNeededExt(boolean reset) +{ + if (reset) + { + mScrollX_last = -1; + mScrollY_last = -1; + + return; + } + + if (mScrollX_last == -1 || mScrollY_last == -1) + { +#if 1 + mScrollX_last = (mScrollX / TILESIZE) * TILESIZE; + mScrollY_last = (mScrollY / TILESIZE) * TILESIZE; +#else + mScrollX_last = mScrollX; + mScrollY_last = mScrollY; +#endif + + return; + } + + /* check if scrolling the playfield requires redrawing the viewport bitmap */ + if ((mScrollX != mScrollX_last || + mScrollY != mScrollY_last) && + (ABS(mScrollX - mScrollX_last) >= TILEX || + ABS(mScrollY - mScrollY_last) >= TILEY)) + { + int dx = (ABS(mScrollX - mScrollX_last) < TILEX ? 0 : + mScrollX < mScrollX_last ? 1 : mScrollX > mScrollX_last ? -1 : 0); + int dy = (ABS(mScrollY - mScrollY_last) < TILEY ? 0 : + mScrollY < mScrollY_last ? 1 : mScrollY > mScrollY_last ? -1 : 0); + + mScrollX_last -= dx * TILEX; + mScrollY_last -= dy * TILEY; + + ScrollPlayfield(dx, dy); + } +} + +static void ScrollPlayfieldIfNeeded() +{ + ScrollPlayfieldIfNeededExt(FALSE); +} + +void InitScrollPlayfield() +{ + ScrollPlayfieldIfNeededExt(TRUE); +} + +void UpdatePlayfield(boolean force_redraw) +{ + int x, y; +#if 1 + int num_redrawn = 0; +#endif + + for (y = DisplayMinY; y <= DisplayMaxY; y++) + { + for (x = DisplayMinX; x <= DisplayMaxX; x++) + { + int element = LowByte(PlayField16[GetSI(x, y)]); + int graphic = GfxGraphic[x][y]; + int sync_frame = GfxFrame[x][y]; + boolean redraw = force_redraw; + +#if 0 + redraw = TRUE; // !!! TEST ONLY -- ALWAYS REDRAW !!! +#endif + + if (graphic < 0) + { + GfxGraphicLast[x][y] = GfxGraphic[x][y]; + + continue; + } + + if (element != GfxElementLast[x][y] && + graphic == GfxGraphicLast[x][y]) + { + /* element changed, but not graphic => disable updating graphic */ + + GfxElementLast[x][y] = element; + GfxGraphicLast[x][y] = GfxGraphic[x][y] = -1; + + continue; + } + + if (graphic != GfxGraphicLast[x][y]) // new graphic + { + redraw = TRUE; + + GfxElementLast[x][y] = element; + GfxGraphicLast[x][y] = GfxGraphic[x][y]; + sync_frame = GfxFrame[x][y] = 0; + } + else if (isNextAnimationFrame_SP(graphic, sync_frame)) // new frame + { + redraw = TRUE; + } + + if (redraw) + { + int sx = x * StretchWidth; + int sy = y * StretchWidth; + +#if 0 + printf("::: REDRAW (%d, %d): %d, %d\n", x, y, graphic, sync_frame); +#endif + + DDSpriteBuffer_BltImg(sx, sy, graphic, sync_frame); + +#if 1 + num_redrawn++; +#endif + } + } + } + +#if 0 + printf("::: FRAME %d: %d redrawn\n", FrameCounter, num_redrawn); +#endif +} + +/* copy the entire screen to the window at the scroll position */ + +void BlitScreenToBitmap_SP(Bitmap *target_bitmap) +{ + int px = 2 * TILEX + (mScrollX - mScrollX_last) % TILEX; + int py = 2 * TILEY + (mScrollY - mScrollY_last) % TILEY; + int sx, sy, sxsize, sysize; + +#if 0 + printf("::: %d, %d / %d, %d / %ld, %ld (%ld, %ld) / %d, %d\n", + MurphyScreenXPos, MurphyScreenYPos, + ScreenScrollXPos, ScreenScrollYPos, + mScrollX, mScrollY, + mScrollX_last, mScrollY_last, + px, py); +#endif + + int xsize = SXSIZE; + int ysize = SYSIZE; + int full_xsize = (FieldWidth - (menBorder ? 0 : 1)) * TILEX; + int full_ysize = (FieldHeight - (menBorder ? 0 : 1)) * TILEY; + + sxsize = (full_xsize < xsize ? full_xsize : xsize); + sysize = (full_ysize < ysize ? full_ysize : ysize); + sx = SX + (full_xsize < xsize ? (xsize - full_xsize) / 2 : 0); + sy = SY + (full_ysize < ysize ? (ysize - full_ysize) / 2 : 0); + + /* scroll correction for even number of visible tiles (half tile shifted) */ + px += game_sp.scroll_xoffset; + py += game_sp.scroll_yoffset; + +#if 1 + if (ExplosionShakeMurphy != 0) + { + px += TILEX / 2 - GetSimpleRandom(TILEX + 1); + py += TILEY / 2 - GetSimpleRandom(TILEX + 1); + } +#endif + + BlitBitmap(bitmap_db_field_sp, target_bitmap, px, py, sxsize, sysize, sx, sy); +} + +void BackToFront_SP(void) +{ + static boolean scrolling_last = FALSE; + int left = mScrollX / TILEX; + int top = mScrollY / TILEY; + boolean scrolling = (mScrollX % TILEX != 0 || mScrollY % TILEY != 0); + int x, y; + + SyncDisplay(); + + if (1 || + redraw_tiles > REDRAWTILES_THRESHOLD || scrolling || scrolling_last) + { + BlitScreenToBitmap_SP(window); + } + else + { + for (x = 0; x < SCR_FIELDX; x++) + { + for (y = 0; y < SCR_FIELDY; y++) + { + int xx = (left + x) % MAX_BUF_XSIZE; + int yy = (top + y) % MAX_BUF_YSIZE; + + if (redraw[xx][yy]) + BlitBitmap(bitmap_db_field_sp, window, + xx * TILEX, yy * TILEY, TILEX, TILEY, + SX + x * TILEX, SY + y * TILEY); + } + } + } + + FlushDisplay(); + + for (x = 0; x < MAX_BUF_XSIZE; x++) + for (y = 0; y < MAX_BUF_YSIZE; y++) + redraw[x][y] = FALSE; + redraw_tiles = 0; + + scrolling_last = scrolling; +} + +void DDScrollBuffer_ScrollTo(int X, int Y) +{ + if (NoDisplayFlag) + return; + + ScrollX = mScrollX = X; + ScrollY = mScrollY = Y; + + ScrollPlayfieldIfNeeded(); +} + +void DDScrollBuffer_ScrollTowards(int X, int Y, double Step) +{ + double dx, dY, r; + + if (NoDisplayFlag) + return; + + dx = X - mScrollX; + dY = Y - mScrollY; + + r = Sqr(dx * dx + dY * dY); + if (r == 0) // we are there already + return; + + if (Step < r) + r = Step / r; + else + r = 1; + + ScrollX = mScrollX = mScrollX + dx * r; + ScrollY = mScrollY = mScrollY + dY * r; + + ScrollPlayfieldIfNeeded(); +} + +void DDScrollBuffer_SoftScrollTo(int X, int Y, long TimeMS, int FPS) +{ + double dx, dY; + long dT, StepCount; + double T, tStep; + long oldX, oldY, maxD; + static boolean AlreadyRunning = False; + + if (NoDisplayFlag) + return; + + if (AlreadyRunning) + return; + + AlreadyRunning = True; + + dx = X - mScrollX; + dY = Y - mScrollY; + maxD = (Abs(dx) < Abs(dY) ? Abs(dY) : Abs(dx)); + + StepCount = FPS * (TimeMS / (double)1000); + if (StepCount > maxD) + StepCount = maxD; + + if (StepCount == 0) + StepCount = 1; + + dT = 1000 / FPS; + tStep = (double)1 / StepCount; + oldX = mScrollX; + oldY = mScrollY; + + for (T = (double)tStep; T <= (double)1; T += tStep) + { + ScrollX = mScrollX = oldX + T * dx; + ScrollY = mScrollY = oldY + T * dY; + } + + ScrollX = mScrollX = X; + ScrollY = mScrollY = Y; + + AlreadyRunning = False; + + ScrollPlayfieldIfNeeded(); +} diff --git a/src/game_sp/DDScrollBuffer.h b/src/game_sp/DDScrollBuffer.h new file mode 100644 index 00000000..e34ef219 --- /dev/null +++ b/src/game_sp/DDScrollBuffer.h @@ -0,0 +1,31 @@ +// ---------------------------------------------------------------------------- +// DDScrollBuffer.h +// ---------------------------------------------------------------------------- + +#ifndef DDSCROLLBUFFER_H +#define DDSCROLLBUFFER_H + +#include "global.h" + + +extern long mScrollX, mScrollY; +extern long mScrollX_last, mScrollY_last; + +#if 1 +extern boolean redraw[2 + MAX_PLAYFIELD_WIDTH + 2][2 + MAX_PLAYFIELD_HEIGHT + 2]; +#else +extern boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE]; +#endif + +extern int TEST_flag; + + +extern void InitScrollPlayfield(); +extern void UpdatePlayfield(); +extern void RestorePlayfield(); + +extern void DDScrollBuffer_ScrollTo(int X, int Y); +extern void DDScrollBuffer_ScrollTowards(int X, int Y, double Step); +extern void DDScrollBuffer_SoftScrollTo(int X, int Y, long TimeMS, int FPS); + +#endif /* DDSCROLLBUFFER_H */ diff --git a/src/game_sp/DDSpriteBuffer.c b/src/game_sp/DDSpriteBuffer.c new file mode 100644 index 00000000..4683d319 --- /dev/null +++ b/src/game_sp/DDSpriteBuffer.c @@ -0,0 +1,41 @@ +// ---------------------------------------------------------------------------- +// DDSpriteBuffer.c +// ---------------------------------------------------------------------------- + +#include "DDSpriteBuffer.h" + + +static void Blt(int pX, int pY, Bitmap *bitmap, int SpriteX, int SpriteY) +{ + int scx = (mScrollX_last < 0 ? 0 : mScrollX_last); + int scy = (mScrollY_last < 0 ? 0 : mScrollY_last); + int sx1 = scx - 2 * TILEX; + int sy1 = scy - 2 * TILEY; + int sx2 = scx + SXSIZE + 1 * TILEX; + int sy2 = scy + SYSIZE + 1 * TILEY; + + int sx = pX - sx1; + int sy = pY - sy1; + + if (NoDisplayFlag) + return; + + /* do not draw fields that are outside the visible screen area */ + if (pX < sx1 || pX > sx2 || pY < sy1 || pY > sy2) + return; + + BlitBitmap(bitmap, bitmap_db_field_sp, SpriteX, SpriteY, + TILEX, TILEY, sx, sy); +} + +void DDSpriteBuffer_BltImg(int pX, int pY, int graphic, int sync_frame) +{ + struct GraphicInfo_SP g; + + if (NoDisplayFlag) + return; + + getGraphicSource_SP(&g, graphic, sync_frame, -1, -1); + + Blt(pX, pY, g.bitmap, g.src_x, g.src_y); +} diff --git a/src/game_sp/DDSpriteBuffer.h b/src/game_sp/DDSpriteBuffer.h new file mode 100644 index 00000000..9872f576 --- /dev/null +++ b/src/game_sp/DDSpriteBuffer.h @@ -0,0 +1,13 @@ +// ---------------------------------------------------------------------------- +// DDSpriteBuffer.h +// ---------------------------------------------------------------------------- + +#ifndef DDSPRITEBUFFER_H +#define DDSPRITEBUFFER_H + +#include "global.h" + + +extern void DDSpriteBuffer_BltImg(int pX, int pY, int graphic, int sync_frame); + +#endif /* DDSPRITEBUFFER_H */ diff --git a/src/game_sp/Display.c b/src/game_sp/Display.c new file mode 100644 index 00000000..d3bf853e --- /dev/null +++ b/src/game_sp/Display.c @@ -0,0 +1,68 @@ +// ---------------------------------------------------------------------------- +// Display.c +// ---------------------------------------------------------------------------- + +#include "Display.h" + + +int ScreenScrollXPos, ScreenScrollYPos; + +int ExplosionShake, ExplosionShakeMurphy; +boolean NoDisplayFlag; + +long DisplayMinX, DisplayMaxX; +long DisplayMinY, DisplayMaxY; + + +void subDisplayLevel() +{ + if (NoDisplayFlag || ! LevelLoaded) + return; + + DisplayLevel(); +} + +void ScrollTo(int X, int Y) +{ + if (NoDisplayFlag) + return; + + X = ScrollDelta * (X / ScrollDelta); + X = Max(X, ScrollMinX); + X = Min(X, ScrollMaxX); + Y = ScrollDelta * (Y / ScrollDelta); + Y = Max(Y, ScrollMinY); + Y = Min(Y, ScrollMaxY); + + DDScrollBuffer_ScrollTo(X, Y); +} + +void ScrollTowards(int X, int Y) +{ + if (NoDisplayFlag) + return; + + X = ScrollDelta * (X / ScrollDelta); + X = Max(X, ScrollMinX); + X = Min(X, ScrollMaxX); + Y = ScrollDelta * (Y / ScrollDelta); + Y = Max(Y, ScrollMinY); + Y = Min(Y, ScrollMaxY); + + DDScrollBuffer_ScrollTowards(X, Y, 2 * ZoomFactor); +} + +void SoftScrollTo(int X, int Y, long TimeMS, int FPS) +{ + if (NoDisplayFlag) + return; + + X = ScrollDelta * (X / ScrollDelta); + X = Max(X, ScrollMinX); + X = Min(X, ScrollMaxX); + Y = ScrollDelta * (Y / ScrollDelta); + Y = Max(Y, ScrollMinY); + Y = Min(Y, ScrollMaxY); + + DDScrollBuffer_SoftScrollTo(X, Y, TimeMS, FPS); +} diff --git a/src/game_sp/Display.h b/src/game_sp/Display.h new file mode 100644 index 00000000..bc0934f4 --- /dev/null +++ b/src/game_sp/Display.h @@ -0,0 +1,24 @@ +// ---------------------------------------------------------------------------- +// Display.h +// ---------------------------------------------------------------------------- + +#ifndef DISPLAY_H +#define DISPLAY_H + +#include "global.h" + + +extern int ScreenScrollXPos, ScreenScrollYPos; + +extern int ExplosionShake, ExplosionShakeMurphy; +extern boolean NoDisplayFlag; + +extern long DisplayMinX, DisplayMaxX; +extern long DisplayMinY, DisplayMaxY; + +extern void subDisplayLevel(); +extern void ScrollTo(int, int); +extern void ScrollTowards(int, int); +extern void SoftScrollTo(int, int, long, int); + +#endif /* DISPLAY_H */ diff --git a/src/game_sp/DoGameStuff.c b/src/game_sp/DoGameStuff.c new file mode 100644 index 00000000..5575d11a --- /dev/null +++ b/src/game_sp/DoGameStuff.c @@ -0,0 +1,162 @@ +// ---------------------------------------------------------------------------- +// DoGameStuff.c +// ---------------------------------------------------------------------------- + +#include "DoGameStuff.h" + + +static void CallAnimation(int si, byte bl); +static boolean IsToBeAnimated(int bl); + +#if 1 +int AnimationPosTable[SP_MAX_PLAYFIELD_SIZE]; +byte AnimationSubTable[SP_MAX_PLAYFIELD_SIZE]; +#else +int *AnimationPosTable; +byte *AnimationSubTable; +#endif + + +// ========================================================================== +// SUBROUTINE +// Do game stuff +// ========================================================================== + +void subDoGameStuff() +{ + int si, cx, dx, bl; + + subAnimateMurphy(&MurphyPosIndex); // move Murphy in any direction + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Build a database of locations and subs-to-call of animatable fields only: + // Make a snapshot from the field before the animation cycle starts. + // first and last line are not animated. + si = FieldWidth + 1; + cx = LevelMax - 2 * FieldWidth - 1; + dx = 0; + do // locloop_g_2282: + { + bl = LowByte(PlayField16[si]); + if (((bl & 0xD) != 0) && (bl < 0x20)) // all animatables have 1's in &H0D' above &H1F? (&H1F=explosion!) + { + if (IsToBeAnimated(bl)) + { + AnimationPosTable[dx] = si; + AnimationSubTable[dx] = bl; + dx = dx + 1; // count database entries + } + } + + si = si + 1; // next field + cx = cx - 1; + } + while (0 < cx); // locloop_g_2282' until all lines scanned(not top- and bottom edge) + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Now use the database to animate all animatables the fastest way. + // All the other fields are not checked anymore: those have no database entry. + // The field from before animation is frozen in the database in order not to + // do follow-up animations in the same loop. + if (dx != 0) // any database entries? + { + dx = dx - 1; + for (cx = 0; cx <= dx; cx++) + { + CallAnimation(AnimationPosTable[cx], AnimationSubTable[cx]); + } // loop locloop_g_22B8 ' until all animatables done + } + + // All animations are done now + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + if (KillMurphyFlag == 1 || MurphyMoveCounter == 0) + { + if (LeadOutCounter == 0 && + !game_sp.LevelSolved && + !game_sp.GameOver) + { +#if 0 + printf("::: DoGameStuff.c: killing murphy [%d] ...\n", KillMurphyFlag); +#endif + + KillMurphyFlag = 0; // no more "kill Murphy" + ExplodeFieldSP(MurphyExplodePos); // Explode + LeadOutCounter = 0x40; // quit: start lead-out + +#if 0 + printf("::: DoGameStuff.c: !!!!!!!!!! GAME OVER !!!!!!!!!!\n"); + printf("::: [KillMurphyFlag == %d]\n", KillMurphyFlag); +#endif + + /* give Murphy some more time (LeadOutCounter) to reach the exit */ + } + } // loc_g_22FB: +} + +static boolean IsToBeAnimated(int bl) +{ + static boolean IsToBeAnimated; + + switch (bl) + { + case fiZonk: + case fiInfotron: + case fiOrangeDisk: + case fiSnikSnak: + case fiTerminal: + case fiElectron: + case fiBug: + case fiExplosion: + IsToBeAnimated = True; + break; + + default: + IsToBeAnimated = False; + break; + } + + return IsToBeAnimated; +} + +static void CallAnimation(int si, byte bl) +{ + switch (bl) + { + case fiZonk: + subAnimateZonks(si); + break; + + case fiInfotron: + subAnimateInfotrons(si); + break; + + case fiOrangeDisk: + subAnimateOrangeDisks(si); + break; + + case fiSnikSnak: + subAnimateSnikSnaks(si); + break; + + case fiTerminal: + subAnimateTerminals(si); + break; + + case fiElectron: + subAnimateElectrons(si); + break; + + case fiBug: + subAnimateBugs(si); + break; + + case fiExplosion: + subAnimateExplosion(si); + break; + + default: + // Debug.Assert(False); + break; + } +} + diff --git a/src/game_sp/DoGameStuff.h b/src/game_sp/DoGameStuff.h new file mode 100644 index 00000000..4cf98184 --- /dev/null +++ b/src/game_sp/DoGameStuff.h @@ -0,0 +1,20 @@ +// ---------------------------------------------------------------------------- +// DoGameStuff.h +// ---------------------------------------------------------------------------- + +#ifndef DOGAMESTUFF_H +#define DOGAMESTUFF_H + +#include "global.h" + +#if 1 +extern int AnimationPosTable[SP_MAX_PLAYFIELD_SIZE]; +extern byte AnimationSubTable[SP_MAX_PLAYFIELD_SIZE]; +#else +extern byte *AnimationSubTable; +extern int *AnimationPosTable; +#endif + +extern void subDoGameStuff(); + +#endif /* DOGAMESTUFF_H */ diff --git a/src/game_sp/Electrons.c b/src/game_sp/Electrons.c new file mode 100644 index 00000000..496e3507 --- /dev/null +++ b/src/game_sp/Electrons.c @@ -0,0 +1,620 @@ +// ---------------------------------------------------------------------------- +// Electrons.c +// ---------------------------------------------------------------------------- + +#include "Electrons.h" + + +// ========================================================================== +// SUBROUTINE +// Animate/move Electrons +// ========================================================================== + +void subAnimateElectrons(int si) +{ + int bx, Tmp; + + if (SnikSnaksElectronsFrozen == 1) + return; + + if (LowByte(PlayField16[si]) != fiElectron) + return; + + bx = HighByte(PlayField16[si]); + + Tmp = bx / 8; + switch (Tmp) + { + case 0: + subElectronTurnLeft(si, bx); // turning, bx=0 -> point N, bx = 1 -> point NW etc. + break; + + case 1: + subElectronTurnRight(si, bx); // turn right + break; + + case 2: + subElectronFromBelow(si, bx); // access si from below + break; + + case 3: + subElectronFromRight(si, bx); // access si from right + break; + + case 4: + subElectronFromAbove(si, bx); // access si from above + break; + + case 5: + subElectronFromLeft(si, bx); // access si from left + break; + } +} + +void subDrawAnimatedElectrons(int si) +{ + int bx, Tmp; + + // If SnikSnaksElectronsFrozen = 1 Then Exit Function + if (LowByte(PlayField16[si]) != fiElectron) + return; + + bx = HighByte(PlayField16[si]); + + Tmp = bx / 8; + switch (Tmp) + { + case 0: + subDrawElectronTurnLeft(si, bx); // turning, bx=0 -> point N, bx = 1 -> point NW etc. + break; + + case 1: + subDrawElectronTurnRight(si, bx); // turn right + break; + + case 2: + subDrawElectronFromBelow(si, bx); // access si from below + break; + + case 3: + subDrawElectronFromRight(si, bx); // access si from right + break; + + case 4: + subDrawElectronFromAbove(si, bx); // access si from above + break; + + case 5: + subDrawElectronFromLeft(si, bx); // access si from left + break; + } +} + +void subElectronTurnLeft(int si, int bx) +{ + int ax, bl; + + ax = (TimerVar & 3); + if (ax != 0) + { + if (ax == 3) + goto loc_g_7ACD; + + return; + } // loc_g_7A9F: + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + subDrawElectronTurnLeft(si, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + bx = (bx + 1) & 0x7; + MovHighByte(&PlayField16[si], bx); + + return; + +loc_g_7ACD: + bl = HighByte(PlayField16[si]); + if (bl == 0) + goto loc_g_7AE6; + + if (bl == 2) + goto loc_g_7B05; + + if (bl == 4) + goto loc_g_7B24; + + if (bl == 6) + goto loc_g_7B43; + + return; + +loc_g_7AE6: // pointing up + ax = PlayField16[si - FieldWidth]; + if (ax == 0) // above is empty -> go up + goto loc_g_7AF5; + + if (LowByte(ax) == fiMurphy) // above is murphy -> explode + ExplodeFieldSP(si); + + return; + +loc_g_7AF5: // above is empty -> go up + PlayField16[si] = 0x1BB; + si = si - FieldWidth; // 1 field up + PlayField16[si] = 0x1018; + + return; + +loc_g_7B05: // pointing left + ax = PlayField16[si - 1]; + if (ax == 0) // left is empty -> go there + goto loc_g_7B14; + + if (LowByte(ax) == fiMurphy) // left is murphy -> explode + ExplodeFieldSP(si); + + return; + +loc_g_7B14: // left is empty -> go there + PlayField16[si] = 0x2BB; + si = si - 1; // 1 field left + PlayField16[si] = 0x1818; + + return; + +loc_g_7B24: // pointing down + ax = PlayField16[si + FieldWidth]; + if (ax == 0) // below is empty -> go down + goto loc_g_7B33; + + if (LowByte(ax) == fiMurphy) // below is murphy -> explode + ExplodeFieldSP(si); + + return; + +loc_g_7B33: // below is empty -> go down + PlayField16[si] = 0x3BB; + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x2018; + + return; + +loc_g_7B43: // pointing Right + ax = PlayField16[si + 1]; + if (ax == 0) // right is empty -> go there + goto loc_g_7B55; + + if (LowByte(ax) == fiMurphy) // right is murphy -> explode + ExplodeFieldSP(si); + + return; + +loc_g_7B55: // right is empty -> go there + PlayField16[si] = 0x4BB; + si = si + 1; // 1 field right + PlayField16[si] = 0x2818; +} + +void subElectronTurnRight(int si, int bx) +{ + int ax, bl; + + ax = (TimerVar & 3); + if (ax != 0) + { + if (ax == 3) + goto loc_g_7BA3; + + return; + } // loc_g_7B73: + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + subDrawElectronTurnRight(si, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + bx = ((bx + 1) & 0x7) | 8; + MovHighByte(&PlayField16[si], bx); + + return; + +loc_g_7BA3: + bl = HighByte(PlayField16[si]); + if (bl == 0x8) + goto loc_g_7BBC; + + if (bl == 0xA) + goto loc_g_7C19; + + if (bl == 0xC) + goto loc_g_7BFA; + + if (bl == 0xE) + goto loc_g_7BDB; + + return; + +loc_g_7BBC: // pointing up + ax = PlayField16[si - FieldWidth]; + if (ax == 0) // above is empty -> go up + goto loc_g_7BCB; + + if (LowByte(ax) == fiMurphy) // above is murphy -> explode + ExplodeFieldSP(si); + + return; + +loc_g_7BCB: // above is empty -> go up + PlayField16[si] = 0x1BB; + si = si - FieldWidth; // 1 field up + PlayField16[si] = 0x1018; + + return; + +loc_g_7BDB: // pointing left + ax = PlayField16[si - 1]; + if (ax == 0) // left is empty -> go there + goto loc_g_7BEA; + + if (LowByte(ax) == fiMurphy) // left is murphy -> explode + ExplodeFieldSP(si); + + return; + +loc_g_7BEA: // left is empty -> go there + PlayField16[si] = 0x2BB; + si = si - 1; // 1 field left + PlayField16[si] = 0x1818; + + return; + +loc_g_7BFA: // pointing down + ax = PlayField16[si + FieldWidth]; + if (ax == 0) // below is empty -> go down + goto loc_g_7C09; + + if (LowByte(ax) == fiMurphy) // below is murphy -> explode + ExplodeFieldSP(si); + + return; + +loc_g_7C09: // below is empty -> go down + PlayField16[si] = 0x3BB; + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x2018; + + return; + +loc_g_7C19: // pointing Right + ax = PlayField16[si + 1]; + if (ax == 0) // right is empty -> go there + goto loc_g_7C2B; + + if (LowByte(ax) == fiMurphy) // right is murphy -> explode + ExplodeFieldSP(si); + + return; + +loc_g_7C2B: // right is empty -> go there + PlayField16[si] = 0x4BB; + si = si + 1; // 1 field right + PlayField16[si] = 0x2818; +} + +void subElectronFromBelow(int si, int bx) +{ + int ax, bl; + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + subDrawElectronFromBelow(si, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bx = bx - 0xF; // get and increment sequence# + + bl = LowByte(bx); + if (bl == 7 && LowByte(PlayField16[si + FieldWidth]) != fiExplosion) + { + PlayField16[si + FieldWidth] = 0; // electron left that field + } + + if (bl < 8) // electron still goes up + { + bl = bl + 0x10; + MovHighByte(&PlayField16[si], bl); + + return; + } // loc_g_7C84 + + PlayField16[si] = 0x18; // sequence#=8 -> arrived at the new field + ax = PlayField16[si - 1]; // check left field + if (ax == 0 || LowByte(ax) == fiMurphy) // check for empty or murphy + { + MovHighByte(&PlayField16[si], 1); // start to turn left + + return; + } // loc_g_7CA4: + + ax = PlayField16[si - FieldWidth]; // cannot turn left -> check above + if (ax == 0) // check if empty + { + PlayField16[si] = 0x1BB; // mark as "electron leaving" + si = si - FieldWidth; // go up! + PlayField16[si] = 0x1018; + + return; + } + + if (LowByte(ax) == fiMurphy) // check for murphy above + { + ExplodeFieldSP(si); // Explode + + return; + } // loc_g_7CC6: + + ax = PlayField16[si + 1]; // check right field + if (ax == 0 || LowByte(ax) == fiMurphy) // check for empty or murphy + { + MovHighByte(&PlayField16[si], 9); // start to turn right + + return; + } // loc_g_7CE0: + + // else: no way to go, start turning around + MovHighByte(&PlayField16[si], 1); +} + +void subElectronFromRight(int si, int bx) +{ + int ax, bl; + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + subDrawElectronFromRight(si, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bx = bx - 0x17; // get and increment sequence# + + bl = LowByte(bx); + if (bl == 7 && LowByte(PlayField16[si + 1]) != fiExplosion) + { + PlayField16[si + 1] = 0; // electron left that field + } // loc_g_7D1D: + + if (bl < 8) // sniksnak still goes left + { + bl = bl + 0x18; + MovHighByte(&PlayField16[si], bl); + + return; + } // loc_g_7D2A: + + PlayField16[si] = 0x18; // sequence#=8 -> arrived at the new field + ax = PlayField16[si + FieldWidth]; // check below + if (ax == 0 || LowByte(ax) == fiMurphy) // empty or murphy? + { + MovHighByte(&PlayField16[si], 3); // yes -> turn left down + + return; + } // loc_g_7D4A: + + ax = PlayField16[si - 1]; // check left, etc ... see the comments on subElectronFromBelow() + if (ax == 0) + { + PlayField16[si] = 0x2BB; + si = si - 1; // 1 field left + PlayField16[si] = 0x1818; + + return; + } // loc_g_7D61: + + if (LowByte(ax) == fiMurphy) + { + ExplodeFieldSP(si); // Explode + + return; + } // loc_g_7D6C: + + ax = PlayField16[si - FieldWidth]; // check above + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 0xF); + + return; + } // loc_g_7D86: + + MovHighByte(&PlayField16[si], 3); +} + +void subElectronFromAbove(int si, int bx) +{ + int ax, bl; + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + subDrawElectronFromAbove(si, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bx = bx - 0x1F; // get and increment sequence# + + bl = LowByte(bx); + if (bl == 7 && LowByte(PlayField16[si - FieldWidth]) != fiExplosion) + { + PlayField16[si - FieldWidth] = 0; // electron left that field + } + + if (bl < 8) // electron still goes down + { + bl = bl + 0x20; + MovHighByte(&PlayField16[si], bl); + + return; + } // loc_g_7DD7 + + PlayField16[si] = 0x18; // sequence#=8 -> arrived at the new field + ax = PlayField16[si + 1]; // check right + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 5); + + return; + } // loc_g_7DF7: + + ax = PlayField16[si + FieldWidth]; // check below + if (ax == 0) + { + PlayField16[si] = 0x3BB; + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x2018; + + return; + } // loc_g_7E0E: + + if (LowByte(ax) == fiMurphy) + { + ExplodeFieldSP(si); // Explode + + return; + } // loc_g_7E19: + + ax = PlayField16[si - 1]; // check left + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 0xD); + + return; + } // loc_g_7E33: + + MovHighByte(&PlayField16[si], 5); +} + +void subElectronFromLeft(int si, int bx) +{ + int ax, bl; + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + subDrawElectronFromLeft(si, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bx = bx - 0x27; // get and increment sequence# + + bl = LowByte(bx); + if (bl == 7 && LowByte(PlayField16[si - 1]) != fiExplosion) + { + PlayField16[si - 1] = 0; // electron left that field + } + + if (bl < 8) // electron still goes right + { + bl = bl + 0x28; + MovHighByte(&PlayField16[si], bl); + + return; + } // loc_g_7E7E: + + PlayField16[si] = 0x18; // sequence#=8 -> arrived at the new field + ax = PlayField16[si - FieldWidth]; // check above + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 7); + + return; + } // loc_g_7E9E: + + ax = PlayField16[si + 1]; // check right(straight on) + if (ax == 0) + { + PlayField16[si] = 0x4BB; + si = si + 1; // 1 field right + PlayField16[si] = 0x2818; + + return; + } // loc_g_7EB5: + + if (LowByte(ax) == fiMurphy) + { + ExplodeFieldSP(si); // Explode + + return; + } // loc_g_7EC0: + + ax = PlayField16[si + FieldWidth]; // check below + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 0xB); + + return; + } // loc_g_7A69: + + MovHighByte(&PlayField16[si], 7); +} + +void subDrawElectronTurnLeft(int si, int bx) +{ + int X, Y; + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + DDSpriteBuffer_BltImg(X, Y, aniElectron, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ +} + +void subDrawElectronTurnRight(int si, int bx) +{ + int X, Y; + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + DDSpriteBuffer_BltImg(X, Y, aniElectron, 0x10 - bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ +} + +void subDrawElectronFromBelow(int si, int bx) +{ + int X, Y; + + bx = bx - 0xF; // get and increment sequence# + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si + FieldWidth); + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X, Y - bx * TwoPixels, aniElectron, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ +} + +void subDrawElectronFromRight(int si, int bx) +{ + int X, Y; + + bx = bx - 0x17; // get and increment sequence# + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si + 1); + Y = GetStretchY(si); + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X - bx * TwoPixels, Y, aniElectron, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ +} + +void subDrawElectronFromAbove(int si, int bx) +{ + int X, Y; + + bx = bx - 0x1F; // get and increment sequence# + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si - FieldWidth); + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X, Y + bx * TwoPixels, aniElectron, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ +} + +void subDrawElectronFromLeft(int si, int bx) +{ + int X, Y; + + bx = bx - 0x27; // get and increment sequence# + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si - 1); + Y = GetStretchY(si); + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X + bx * TwoPixels, Y, aniElectron, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ +} diff --git a/src/game_sp/Electrons.h b/src/game_sp/Electrons.h new file mode 100644 index 00000000..2e12dd37 --- /dev/null +++ b/src/game_sp/Electrons.h @@ -0,0 +1,26 @@ +// ---------------------------------------------------------------------------- +// Electrons.h +// ---------------------------------------------------------------------------- + +#ifndef ELECTRONS_H +#define ELECTRONS_H + +#include "global.h" + + +extern void subAnimateElectrons(int); +extern void subDrawAnimatedElectrons(int); +extern void subDrawElectronFromAbove(int, int); +extern void subDrawElectronFromBelow(int, int); +extern void subDrawElectronFromLeft(int, int); +extern void subDrawElectronFromRight(int, int); +extern void subDrawElectronTurnLeft(int, int); +extern void subDrawElectronTurnRight(int, int); +extern void subElectronFromAbove(int, int); +extern void subElectronFromBelow(int, int); +extern void subElectronFromLeft(int, int); +extern void subElectronFromRight(int, int); +extern void subElectronTurnLeft(int, int); +extern void subElectronTurnRight(int, int); + +#endif /* ELECTRONS_H */ diff --git a/src/game_sp/Explosions.c b/src/game_sp/Explosions.c new file mode 100644 index 00000000..4eded7b3 --- /dev/null +++ b/src/game_sp/Explosions.c @@ -0,0 +1,353 @@ +// ---------------------------------------------------------------------------- +// Explosions.c +// ---------------------------------------------------------------------------- + +#include "Explosions.h" + + +static void LetExplodeFieldSP(int tsi, int cx, int dh); +static void subExplodeInfotron(int tsi, int cx); +static void subExplodeZonk(int tsi, int cx); + + +// ========================================================================== +// SUBROUTINE +// Animate explosion +// ========================================================================== + +void subAnimateExplosion(int si) +{ + int ax, bl, X, Y; + + if (LowByte(PlayField16[si]) != fiExplosion) + return; + + ax = (TimerVar & 3); + if (ax != 0) + return; + + bl = HighByte(PlayField16[si]); + + if ((bl & 0x80) != 0) // infotron explosion! + goto loc_g_28D0; + + bl = bl + 1; + MovHighByte(&PlayField16[si], bl); + + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + GfxGraphic[GetX(si)][GetY(si)] = aniDefaultExplosion; + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + if (bl == 8) + { + PlayField16[si] = 0; + ExplosionShake = 0; // nothing explodes + // ExplosionShakeMurphy = 0; // nothing explodes + + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + GfxGraphic[GetX(si)][GetY(si)] = aniSpace; + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + } // loc_ret_g_28CF: + + return; + +loc_g_28D0: // explosion produces infotron + bl = bl + 1; + if (bl == 0x89) + { + PlayField16[si] = fiInfotron; + MovLowByte(&ExplosionShake, 0); // nothing explodes + // MovLowByte(&ExplosionShakeMurphy, 0); // nothing explodes + + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + GfxGraphic[GetX(si)][GetY(si)] = aniInfotron; + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + return; + } // loc_g_28E3: + + MovHighByte(&PlayField16[si], bl); + + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + GfxGraphic[GetX(si)][GetY(si)] = aniElectronExplosion; + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +} + +// ========================================================================== +// SUBROUTINE +// Explode +// ========================================================================== + +void ExplodeFieldSP(int si) +{ + int ax, cx, dl; + + ax = LowByte(PlayField16[si]); + if (ax == fiHardWare) + return; + + ExplosionShake = 1; // something explodes + + if (ax == fiMurphy) + { +#if 0 + printf("::: Explosions.c: ExplodeFieldSP(): killing murphy\n"); +#endif + + KillMurphyFlag = 1; + +#if 1 + ExplosionShakeMurphy = 30; // Murphy explodes +#endif + } + + if (ax == fiElectron) + { + cx = 0x801F; // produce infotrons + dl = 0xF3; + } + else // loc_g_2977: + { + cx = 0x1F; // normal explosion + dl = 0xD; + } // loc_g_297C: + + LetExplodeFieldSP(si - FieldWidth - 1, cx, dl); + LetExplodeFieldSP(si - FieldWidth, cx, dl); + LetExplodeFieldSP(si - FieldWidth + 1, cx, dl); + LetExplodeFieldSP(si - 1, cx, dl); + PlayField16[si] = cx; + LetExplodeFieldSP(si + 1, cx, dl); + LetExplodeFieldSP(si + FieldWidth - 1, cx, dl); + LetExplodeFieldSP(si + FieldWidth, cx, dl); + LetExplodeFieldSP(si + FieldWidth + 1, cx, dl); + + GfxGraphic[GetX(si)][GetY(si)] = -1; // restart for chain-explosions + + // loc_g_2C3B: + subSoundFX(si, ax, actExploding); +} + +static void LetExplodeFieldSP(int tsi, int cx, int dh) +{ + int al; + + if (tsi < (-FieldWidth)) + return; + + al = LowByte(PlayField16[tsi]); + switch (al) + { + case fiHardWare: + return; + + break; + + case fiOrangeDisk: + case fiYellowDisk: + case fiSnikSnak: + PlayField8[tsi] = dh; + PlayField16[tsi] = cx; + break; + + case fiZonk: + subExplodeZonk(tsi, cx); + break; + + case fiInfotron: + subExplodeInfotron(tsi, cx); + break; + + case fiElectron: + PlayField8[tsi] = (-dh) & 0xFF; + PlayField16[tsi] = 0x801F; + break; + + case fiMurphy: +#if 0 + printf("::: Explosions.c: LetExplodeFieldSP(): killing murphy [%d]\n", + tsi); +#endif + + KillMurphyFlag = 1; + PlayField8[tsi] = dh; + PlayField16[tsi] = cx; + break; + + default: + PlayField16[tsi] = cx; + break; + } + + GfxGraphic[GetX(tsi)][GetY(tsi)] = -1; // restart for chain-explosions +} + +static void subExplodeZonk(int tsi, int cx) +{ + int ah; + + ah = HighByte(PlayField16[tsi]) & 0xF0; + PlayField16[tsi] = cx; + switch (ah) + { + case 0x10: + case 0x70: + subClearFieldDueToExplosion(tsi - FieldWidth); + tsi = tsi + FieldWidth; + if (PlayField16[tsi] == 0x9999) + subClearFieldDueToExplosion(tsi); + + break; + + case 0x20: + subClearFieldDueToExplosion(tsi + 1); + subClearFieldDueToExplosion(tsi + FieldWidth); + break; + + case 0x30: + subClearFieldDueToExplosion(tsi - 1); + subClearFieldDueToExplosion(tsi + FieldWidth); + break; + + case 0x50: + subClearFieldDueToExplosion(tsi - 1); + break; + + case 0x60: + subClearFieldDueToExplosion(tsi + 1); + break; + + case 0xFF000070: // !!! 0x70; this will never be reached! ...?? + subClearFieldDueToExplosion(tsi + FieldWidth); + break; + } +} + +static void subExplodeInfotron(int tsi, int cx) +{ + int ah; + + ah = HighByte(PlayField16[tsi]) & 0xF0; + PlayField16[tsi] = cx; + switch (ah) + { + case 0x10: + case 0x70: + subClearFieldDueToExplosion(tsi - FieldWidth); + tsi = tsi + FieldWidth; + if (PlayField16[tsi] == 0x9999) + subClearFieldDueToExplosion(tsi); + + break; + + case 0x20: + subClearFieldDueToExplosion(tsi + 1); + tsi = tsi + FieldWidth; // differnt from zonk version + if (PlayField16[tsi] == 0x9999) + subClearFieldDueToExplosion(tsi); + + break; + + case 0x30: + subClearFieldDueToExplosion(tsi - 1); + tsi = tsi + FieldWidth; // differnt from zonk version + if (PlayField16[tsi] == 0x9999) + subClearFieldDueToExplosion(tsi); + + break; + + case 0x50: + subClearFieldDueToExplosion(tsi - 1); + break; + + case 0x60: + subClearFieldDueToExplosion(tsi + 1); + break; + + case 0xFF000070: // !!! 0x70; this will never be reached! ...?? + subClearFieldDueToExplosion(tsi + FieldWidth); + break; + } +} + +void subClearFieldDueToExplosion(int si) +{ + int X, Y; + + if (LowByte(PlayField16[si]) == fiExplosion) + return; + + PlayField16[si] = 0; + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + GfxGraphic[GetX(si)][GetY(si)] = aniSpace; + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +} + +void subRedDiskReleaseExplosion() +{ + int al, X, Y, si; + + al = RedDiskReleasePhase; // Red disk release phase + if (al <= 1) + return; + + si = RedDiskReleaseMurphyPos; + if (PlayField16[si] == 0) // Release red disk + PlayField16[si] = fiRedDisk; + + // +++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); +#if 0 + // !!! causes flicker -- fix in Murphy.c !!! + GfxGraphic[GetX(si)][GetY(si)] = aniRedDisk; +#else + DDSpriteBuffer_BltImg(X, Y, aniRedDisk, 0); +#endif + // +++++++++++++++++++++++++++++++++++++++++ + + RedDiskReleasePhase = RedDiskReleasePhase + 1; + if (RedDiskReleasePhase >= 0x28) + { + // si = RedDiskReleaseMurphyPos ' Red disk was released here + ExplodeFieldSP(si); // Explode + RedDiskReleasePhase = 0; + } +} + +void subFollowUpExplosions() +{ + int ax, si; + + // locloop_g_2919: + for (si = 0; si <= LevelMax; si++) + { + ax = ByteToInt(PlayField8[si]); + if (ax != 0) + { + if (ax < 0) + { + ax = ax + 1; + PlayField8[si] = ax & 0xFF; + if (ax == 0) + { + PlayField16[si] = 0xFF18; + ExplodeFieldSP(si); // Explode + } + } + else + { + ax = ax - 1; + PlayField8[si] = ax; + if (ax == 0) + ExplodeFieldSP(si); + } + } + } +} diff --git a/src/game_sp/Explosions.h b/src/game_sp/Explosions.h new file mode 100644 index 00000000..b62ea8b3 --- /dev/null +++ b/src/game_sp/Explosions.h @@ -0,0 +1,17 @@ +// ---------------------------------------------------------------------------- +// Explosions.h +// ---------------------------------------------------------------------------- + +#ifndef EXPLOSIONS_H +#define EXPLOSIONS_H + +#include "global.h" + + +extern void ExplodeFieldSP(int); +extern void subAnimateExplosion(int); +extern void subClearFieldDueToExplosion(int); +extern void subFollowUpExplosions(); +extern void subRedDiskReleaseExplosion(); + +#endif /* EXPLOSIONS_H */ diff --git a/src/game_sp/Globals.c b/src/game_sp/Globals.c new file mode 100644 index 00000000..e34d1962 --- /dev/null +++ b/src/game_sp/Globals.c @@ -0,0 +1,247 @@ +// ---------------------------------------------------------------------------- +// Globals.c +// ---------------------------------------------------------------------------- + +#include "Globals.h" + + +boolean LevelLoaded; + +boolean DemoAvailable; +boolean menBorder; + +int FieldWidth; // standard size = 60 +int FieldHeight; // standard size = 24 +int HeaderSize; // standard size = 96 +int FieldMax, LevelMax; +long FileMax; + +#if 1 +int PlayField16[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE]; +byte PlayField8[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE]; +byte DisPlayField[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE]; +#else +int *PlayField16; +byte *PlayField8; +byte *DisPlayField; +#endif + +int TimerVar; +#if 1 +short RandomSeed; +#else +int RandomSeed; +#endif + +int FreezeZonks; + +LevelInfoType LInfo; + +int ScrollMinX, ScrollMaxX, ScrollMinY, ScrollMaxY; +int ScrollX, ScrollY; + +int MurphyPosIndex, MurphyXPos, MurphyYPos; +int MurphyScreenXPos, MurphyScreenYPos; +int MurphyExplodePos, SplitMoveFlag, RedDiskReleaseMurphyPos; +int KillMurphyFlag, MurphyMoveCounter; +long YawnSleepCounter; +int MurphyVarFaceLeft; +int ScratchGravity, GravityFlag; +int RedDiskReleaseFlag, MovingPictureSequencePhase; + +int YellowDisksExploded; +int AllowRedDiskCheat, AllowEatRightRedDiskBug; + +int GameBusyFlag; +int InfotronsNeeded, TotalInfotronsNeeded; +int RedDiskCount; +int SnikSnaksElectronsFrozen; + +int DemoKeyCode; + +int RedDiskReleasePhase; + +int fiGraphic[] = +{ + aniSpace, + aniZonk, + aniBase, + aniMurphy, + aniInfotron, + aniRAM, + aniHardWare, + aniExit, + aniOrangeDisk, + aniPortRight, + aniPortDown, + aniPortLeft, + aniPortUp, + aniSpPortRight, + aniSpPortDown, + aniSpPortLeft, + aniSpPortUp, + aniSnikSnak, + aniYellowDisk, + aniTerminal, + aniRedDisk, + aniPortUpAndDown, + aniPortLeftAndRight, + aniPortAllDirections, + aniElectron, + aniBug, + aniRAMLeft, + aniRAMRight, + aniHW0, + aniHW1, + aniHW2, + aniHW3, + aniHW4, + aniHW5, + aniHW6, + aniHW7, + aniHW8, + aniHW9, + aniRAMTop, + aniRAMBottom, + aniWallSpace +}; + +int aniSnikSnakTurningLeft[] = +{ + aniSnikSnakTurnUpToLeft, + aniSnikSnakTurnLeftToDown, + aniSnikSnakTurnDownToRight, + aniSnikSnakTurnRightToUp +}; + +int aniSnikSnakTurningRight[] = +{ + aniSnikSnakTurnUpToRight, + aniSnikSnakTurnRightToDown, + aniSnikSnakTurnDownToLeft, + aniSnikSnakTurnLeftToUp +}; + + +int getSequenceLength(int sequence) +{ + switch (sequence) + { + case aniBug: + return 14; + + case aniElectron: + case aniExplosion: + return 9; + + case aniTouchInfotron: + return 7; + + case aniMurphyExit: + return 40; + + case aniRedDisk: + return 1; + + default: + return 8; + } +} + +boolean isSnappingSequence(int sequence) +{ + switch (sequence) + { + case aniTouchBase: + case aniTouchInfotron: + case aniTouchRedDisk: + return TRUE; + + default: + return FALSE; + } +} + +void InitGlobals() +{ + AutoScrollFlag = True; + FreezeZonks = 0; + LevelLoaded = False; + FieldWidth = 60; + FieldHeight = 24; + HeaderSize = 96; + FieldMax = (FieldWidth * FieldHeight) + HeaderSize - 1; + LevelMax = (FieldWidth * FieldHeight) - 1; + bPlaying = False; + menBorder = False; + +#if 0 + /* these defaults will be changed after reading a Supaplex level file */ + PlayField8 = REDIM_1D(sizeof(byte), 0, FieldMax); + DisPlayField = REDIM_1D(sizeof(byte), 0, FieldMax); + PlayField16 = REDIM_1D(sizeof(int), 0, FieldMax); + + AnimationPosTable = REDIM_1D(sizeof(int), 0, LevelMax); + AnimationSubTable = REDIM_1D(sizeof(byte), 0, LevelMax); + TerminalState = REDIM_1D(sizeof(byte), 0, FieldMax); +#endif +} + +int GetSI(int X, int Y) +{ + return Y * FieldWidth + X; +} + +int GetX(int si) +{ + return si % FieldWidth; +} + +int GetY(int si) +{ + return si / FieldWidth; +} + +int GetStretchX(int si) +{ + return StretchWidth * (si % FieldWidth); +} + +int GetStretchY(int si) +{ + return StretchWidth * (si / FieldWidth); +} + +void PrepareLevel() +{ + copyInternalEngineVars_SP(); + +#if 1 + SetDisplayRegion(); + SetScrollEdges(); +#endif + + LevelLoaded = True; +} + +#if 0 +void Trace(char *Source, char *Message) +{ + printf("::: Trace: Source == '%s', Message == '%s'\n", Source, Message); +} + +void ReportError(char *Source, char *Message) +{ + printf("::: ReportError: Source == '%s', Message == '%s'\n", Source, Message); +} +#endif + +int Min(int A, int B) +{ + return (A < B ? A : B); +} + +int Max(int A, int B) +{ + return (A < B ? B : A); +} diff --git a/src/game_sp/Globals.h b/src/game_sp/Globals.h new file mode 100644 index 00000000..05d4cd7c --- /dev/null +++ b/src/game_sp/Globals.h @@ -0,0 +1,339 @@ +// ---------------------------------------------------------------------------- +// Globals.h +// ---------------------------------------------------------------------------- + +#ifndef GLOBALS_H +#define GLOBALS_H + +#include "global.h" + + +#ifndef False +#define False 0 +#define True (!False) +#endif + +#define ScrollDelta ((long)1) + +#define ZoomFactor (2) + +#define StretchWidth (ZoomFactor * 16) +#define TwoPixels (ZoomFactor * 2) + + +// ---------------------------------------------------------------------------- +// elements (stored in file and playfield) +// ---------------------------------------------------------------------------- + +#define fiSpace (0) +#define fiZonk (1) +#define fiBase (2) +#define fiMurphy (3) +#define fiInfotron (4) +#define fiRAM (5) +#define fiHardWare (6) +#define fiExit (7) +#define fiOrangeDisk (8) +#define fiPortRight (9) +#define fiPortDown (10) +#define fiPortLeft (11) +#define fiPortUp (12) +#define fiSpPortRight (13) +#define fiSpPortDown (14) +#define fiSpPortLeft (15) +#define fiSpPortUp (16) +#define fiSnikSnak (17) +#define fiYellowDisk (18) +#define fiTerminal (19) +#define fiRedDisk (20) +#define fiPortUpAndDown (21) +#define fiPortLeftAndRight (22) +#define fiPortAllDirections (23) +#define fiElectron (24) +#define fiBug (25) +#define fiRAMLeft (26) +#define fiRAMRight (27) +#define fiHWFirst (28) +#define fiHW0 (fiHWFirst + 0) // fiHWFirst +#define fiHW1 (fiHWFirst + 1) +#define fiHW2 (fiHWFirst + 2) +#define fiHW3 (fiHWFirst + 3) +#define fiHW4 (fiHWFirst + 4) +#define fiHW5 (fiHWFirst + 5) +#define fiHW6 (fiHWFirst + 6) +#define fiHW7 (fiHWFirst + 7) +#define fiHW8 (fiHWFirst + 8) +#define fiHW9 (fiHWFirst + 9) // fiHWLast +#define fiHWLast (37) +#define fiRAMTop (38) +#define fiRAMBottom (39) +#define fiWallSpace (40) + +#define fiExplosion (0x1F) + +#define fiFirst (0) +#define fiLast (40) + + +// ---------------------------------------------------------------------------- +// graphics and animations (used at runtime to display the elements) +// ---------------------------------------------------------------------------- + +// graphics and animations directly related to file elements + +#define aniSpace IMG_EMPTY_SPACE +#define aniZonk IMG_SP_ZONK +#define aniBase IMG_SP_BASE +#define aniMurphy IMG_SP_MURPHY +#define aniInfotron IMG_SP_INFOTRON +#define aniRAM IMG_SP_CHIP_SINGLE +#define aniHardWare IMG_SP_HARDWARE_GRAY +#define aniExit IMG_SP_EXIT_CLOSED +#define aniOrangeDisk IMG_SP_DISK_ORANGE +#define aniPortRight IMG_SP_PORT_RIGHT +#define aniPortDown IMG_SP_PORT_DOWN +#define aniPortLeft IMG_SP_PORT_LEFT +#define aniPortUp IMG_SP_PORT_UP +#define aniSpPortRight IMG_SP_GRAVITY_PORT_RIGHT +#define aniSpPortDown IMG_SP_GRAVITY_PORT_DOWN +#define aniSpPortLeft IMG_SP_GRAVITY_PORT_LEFT +#define aniSpPortUp IMG_SP_GRAVITY_PORT_UP +#define aniSnikSnak IMG_SP_SNIKSNAK +#define aniYellowDisk IMG_SP_DISK_YELLOW +#define aniTerminal IMG_SP_TERMINAL +#define aniRedDisk IMG_SP_DISK_RED +#define aniPortUpAndDown IMG_SP_PORT_VERTICAL +#define aniPortLeftAndRight IMG_SP_PORT_HORIZONTAL +#define aniPortAllDirections IMG_SP_PORT_ANY +#define aniElectron IMG_SP_ELECTRON +#define aniBug IMG_SP_BUGGY_BASE +#define aniRAMLeft IMG_SP_CHIP_LEFT +#define aniRAMRight IMG_SP_CHIP_RIGHT +#define aniHWFirst IMG_SP_HARDWARE_BASE_1 +#define aniHW0 IMG_SP_HARDWARE_BASE_1 +#define aniHW1 IMG_SP_HARDWARE_GREEN +#define aniHW2 IMG_SP_HARDWARE_BLUE +#define aniHW3 IMG_SP_HARDWARE_RED +#define aniHW4 IMG_SP_HARDWARE_YELLOW +#define aniHW5 IMG_SP_HARDWARE_BASE_2 +#define aniHW6 IMG_SP_HARDWARE_BASE_3 +#define aniHW7 IMG_SP_HARDWARE_BASE_4 +#define aniHW8 IMG_SP_HARDWARE_BASE_5 +#define aniHW9 IMG_SP_HARDWARE_BASE_6 +#define aniHWLast IMG_SP_HARDWARE_BASE_6 +#define aniRAMTop IMG_SP_CHIP_TOP +#define aniRAMBottom IMG_SP_CHIP_BOTTOM +#define aniWallSpace IMG_INVISIBLE_WALL +#define aniHWTrash1 +#define aniHWTrash2 +#define aniHWMurphy + + +// graphics and animations related to in-game animations for element actions + +#define aniMurphyDropping IMG_SP_MURPHY_DROPPING + +#define aniMurphySleepLeft IMG_SP_MURPHY_SLEEPING_LEFT +#define aniMurphySleepRight IMG_SP_MURPHY_SLEEPING_RIGHT +#define aniMurphyTouchLeft IMG_SP_MURPHY_SNAPPING_LEFT +#define aniMurphyTouchRight IMG_SP_MURPHY_SNAPPING_RIGHT +#define aniMurphyTouchUp IMG_SP_MURPHY_SNAPPING_UP +#define aniMurphyTouchDown IMG_SP_MURPHY_SNAPPING_DOWN +#define aniMurphyYawn IMG_SP_MURPHY_BORING_1 +#define aniPushLeft IMG_SP_MURPHY_PUSHING_LEFT +#define aniPushRight IMG_SP_MURPHY_PUSHING_RIGHT + +#define aniBugActivating IMG_SP_BUGGY_BASE_ACTIVATING +#define aniBugDeactivating IMG_SP_BUGGY_BASE_ACTIVATING +#define aniBugActive IMG_SP_BUGGY_BASE_ACTIVE +#define aniZonkRollLeft IMG_SP_ZONK_MOVING_LEFT +#define aniZonkRollRight IMG_SP_ZONK_MOVING_RIGHT +#define aniEatInfotronLeft IMG_SP_MURPHY_COLLECTING_LEFT +#define aniEatInfotronRight IMG_SP_MURPHY_COLLECTING_RIGHT +#define aniInfotronRollLeft IMG_SP_INFOTRON_MOVING_LEFT +#define aniInfotronRollRight IMG_SP_INFOTRON_MOVING_RIGHT +#define aniMurphyMoveLeft IMG_SP_MURPHY_MOVING_LEFT +#define aniMurphyMoveRight IMG_SP_MURPHY_MOVING_RIGHT +#define aniMurphyMoveUpLeft IMG_SP_MURPHY_MOVING_LEFT +#define aniMurphyMoveUpRight IMG_SP_MURPHY_MOVING_RIGHT +#define aniMurphyDigLeft IMG_SP_MURPHY_DIGGING_LEFT +#define aniMurphyDigRight IMG_SP_MURPHY_DIGGING_RIGHT +#define aniMurphyDigUpLeft IMG_SP_MURPHY_DIGGING_LEFT +#define aniMurphyDigUpRight IMG_SP_MURPHY_DIGGING_RIGHT +#define aniMurphyEatLeft IMG_SP_MURPHY_COLLECTING_LEFT +#define aniMurphyEatRight IMG_SP_MURPHY_COLLECTING_RIGHT +#define aniMurphyEatUpLeft IMG_SP_MURPHY_COLLECTING_LEFT +#define aniMurphyEatUpRight IMG_SP_MURPHY_COLLECTING_RIGHT +#define aniSplitUpDown IMG_SP_MURPHY +#define aniMurphyExit IMG_SP_MURPHY_SHRINKING +#define aniElectron IMG_SP_ELECTRON +#define aniExplosion IMG_SP_DEFAULT_EXPLODING +#define aniTouchBase IMG_SP_BASE_SNAPPING +#define aniTouchInfotron IMG_SP_INFOTRON_COLLECTING +#define aniTouchRedDisk IMG_SP_DISK_RED_COLLECTING +#define aniYellowDisk IMG_SP_DISK_YELLOW +#define aniOrangeDisk IMG_SP_DISK_ORANGE +#define aniRedDisk IMG_SP_DISK_RED + +#define aniSnikSnakDown IMG_SP_SNIKSNAK_DOWN +#define aniSnikSnakLeft IMG_SP_SNIKSNAK_LEFT +#define aniSnikSnakRight IMG_SP_SNIKSNAK_RIGHT +#define aniSnikSnakUp IMG_SP_SNIKSNAK_UP + +#define aniSnikSnakTurnLeftToUp IMG_SP_SNIKSNAK_TURNING_FROM_LEFT_UP +#define aniSnikSnakTurnLeftToDown IMG_SP_SNIKSNAK_TURNING_FROM_LEFT_DOWN +#define aniSnikSnakTurnRightToUp IMG_SP_SNIKSNAK_TURNING_FROM_RIGHT_UP +#define aniSnikSnakTurnRightToDown IMG_SP_SNIKSNAK_TURNING_FROM_RIGHT_DOWN +#define aniSnikSnakTurnUpToLeft IMG_SP_SNIKSNAK_TURNING_FROM_UP_LEFT +#define aniSnikSnakTurnUpToRight IMG_SP_SNIKSNAK_TURNING_FROM_UP_RIGHT +#define aniSnikSnakTurnDownToLeft IMG_SP_SNIKSNAK_TURNING_FROM_DOWN_LEFT +#define aniSnikSnakTurnDownToRight IMG_SP_SNIKSNAK_TURNING_FROM_DOWN_RIGHT + +#define aniTerminalActive IMG_SP_TERMINAL_ACTIVE + +#define aniDefaultExplosion IMG_SP_DEFAULT_EXPLODING +#define aniElectronExplosion IMG_SP_ELECTRON_EXPLODING + +#define imgFrameCorner IMG_SP_FRAME_CORNER +#define imgFrameHorizontal IMG_SP_FRAME_HORIZONTAL +#define imgFrameVertical IMG_SP_FRAME_VERTICAL + + +// ---------------------------------------------------------------------------- +// input keys +// ---------------------------------------------------------------------------- + +#define keyNone (0) +#define keyUp (1) +#define keyLeft (2) +#define keyDown (3) +#define keyRight (4) +#define keySpaceUp (5) +#define keySpaceLeft (6) +#define keySpaceDown (7) +#define keySpaceRight (8) +#define keySpace (9) + + +// ---------------------------------------------------------------------------- +// data structures +// ---------------------------------------------------------------------------- + +#ifndef HAS_LevelDescriptor +typedef struct +{ + int Width; + int Height; + long OffSet; + long Size; +} LevelDescriptor; +#define HAS_LevelDescriptor +#endif + +#ifndef HAS_SpecialPortType +typedef struct +{ + short PortLocation; // = 2*(x+(y*60)) + byte Gravity; // 1 = turn on, anything else (0) = turn off + byte FreezeZonks; // 2 = turn on, anything else (0) = turn off (1=off!) + byte FreezeEnemies; // 1 = turn on, anything else (0) = turn off + byte UnUsed; +} SpecialPortType; +#define HAS_SpecialPortType +#endif + +#ifndef HAS_LevelInfoType +typedef struct +{ + byte UnUsed[4]; + byte InitialGravity; // 1=on, anything else (0) = off + byte Version; // SpeedFixVersion XOR &H20 + char LevelTitle[23]; + byte InitialFreezeZonks; // 2=on, anything else (0) = off. (1=off too!) + byte InfotronsNeeded; + + // Number of Infotrons needed. 0 means that Supaplex will count the total + // amount of Infotrons in the level, and use the low byte of that number. + // (A multiple of 256 Infotrons will then result in 0-to-eat, etc.!) + byte SpecialPortCount; // Maximum 10 allowed! + SpecialPortType SpecialPort[10]; + byte SpeedByte; // = Speed XOR Highbyte(RandomSeed) + byte CheckSumByte; // = CheckSum XOR SpeedByte + short DemoRandomSeed; +} LevelInfoType; +#define HAS_LevelInfoType +#endif + + +extern int GetSI(int X, int Y); +extern int GetStretchX(int si); +extern int GetStretchY(int si); +extern int GetX(int si); +extern int GetY(int si); +extern void InitGlobals(); + +extern void PrepareLevel(); + +extern int getSequenceLength(int sequence); +extern boolean isSnappingSequence(int sequence); + +#if 0 +extern void Trace(char *Source, char *Message); +extern void ReportError(char *Source, char *Message); +#endif + +extern int Min(int A, int B); +extern int Max(int A, int B); + +extern int fiGraphic[]; +extern int aniSnikSnakTurningLeft[]; +extern int aniSnikSnakTurningRight[]; + +extern boolean LevelLoaded; + +extern boolean DemoAvailable; +extern boolean menBorder; + +#if 1 +extern int PlayField16[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE]; +extern byte PlayField8[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE]; +extern byte DisPlayField[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE]; +#else +extern int *PlayField16; +extern byte *PlayField8; +extern byte *DisPlayField; +#endif + +extern int FieldHeight; +extern int FieldMax, LevelMax; +extern int FieldWidth; +extern int FreezeZonks; +extern int HeaderSize; +extern int TimerVar; +extern short RandomSeed; + +extern long FileMax; + +extern LevelInfoType LInfo; +extern int ScrollMinX, ScrollMaxX, ScrollMinY, ScrollMaxY; +extern int ScrollX, ScrollY; + +extern int AllowRedDiskCheat, AllowEatRightRedDiskBug; +extern int Data_SubRest, Data_SubRstFlg; +extern int DemoKeyCode; +extern int GameBusyFlag; +extern int InfotronsNeeded, TotalInfotronsNeeded; +extern int KillMurphyFlag, MurphyMoveCounter; +extern int MurphyExplodePos, SplitMoveFlag, RedDiskReleaseMurphyPos; +extern int MurphyPosIndex, MurphyXPos, MurphyYPos; +extern int MurphyScreenXPos, MurphyScreenYPos; +extern int MurphyVarFaceLeft; +extern int RedDiskCount; +extern int RedDiskReleaseFlag, MovingPictureSequencePhase; +extern int RedDiskReleasePhase; +extern int ScratchGravity, GravityFlag; +extern int SnikSnaksElectronsFrozen; +extern int YellowDisksExploded; +extern long YawnSleepCounter; + +#endif /* GLOBALS_H */ diff --git a/src/game_sp/Infotrons.c b/src/game_sp/Infotrons.c new file mode 100644 index 00000000..c671c606 --- /dev/null +++ b/src/game_sp/Infotrons.c @@ -0,0 +1,454 @@ +// ---------------------------------------------------------------------------- +// Infotrons.c +// ---------------------------------------------------------------------------- + +#include "Infotrons.h" + + +// ========================================================================== +// SUBROUTINE +// Animate Infotrons (falling) +// ========================================================================== + +void subAnimateInfotrons(int si) +{ + int tFld; + + int ax, bx, dx, X, Y; + int al, bl; + + tFld = PlayField16[si]; + if ((tFld & 0xFF) != fiInfotron) + return; + + if (tFld == fiInfotron) + { + ax = PlayField16[si + FieldWidth]; // select case playfield16(si+60) + if (ax == 0) + goto loc_g_11D5; + + if (ax == fiZonk) + goto loc_g_11A6; + + if (ax == fiInfotron) + goto loc_g_11A6; + + if (ax == fiRAM) + goto loc_g_11A6; + + return; + +loc_g_11A6: // Case fiZonk, fiInfotron, fiRAM + ax = PlayField16[si + FieldWidth - 1]; + if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) + goto loc_g_11DC; + +loc_g_11BD: + ax = PlayField16[si + FieldWidth + 1]; + if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) + goto loc_g_11F2; + + return; + +loc_g_11D5: // Case fiSpace + MovHighByte(&PlayField16[si], 0x40); + goto loc_g_1207; + +loc_g_11DC: // roll left? + if (PlayField16[si - 1] == 0) + goto loc_g_11E5; + + goto loc_g_11BD; + +loc_g_11E5: + MovHighByte(&PlayField16[si], 0x50); + PlayField16[si - 1] = 0x8888; + goto loc_g_1207; + +loc_g_11F2: // roll right? + if (PlayField16[si + 1] == 0) + goto loc_g_11FA; + + return; + +loc_g_11FA: + MovHighByte(&PlayField16[si], 0x60); + PlayField16[si + 1] = 0x8888; + } // tFld = fiInfotron + +loc_g_1207: + // from now on the infotron is definitely moving, + // maybe the sequence is in an advanced frame + // or just beeing initialized due to the code above + bl = HighByte(PlayField16[si]); + bx = 0; + MovLowByte(&bx, bl); + + al = bl & 0xF0; + if (al == 0x10) // infotron comes falling from above + goto loc_g_1242; + + if (al == 0x20) // infotron comes rolling from right to left + goto loc_g_138D; + + if (al == 0x30) // infotron comes rolling from left to right + goto loc_g_13E9; + + if (al == 0x40) // infotron falls straight down + goto loc_g_1444; + + if (al == 0x50) // infotron rolls left + goto loc_g_1472; + + if (al == 0x60) // infotron rolls right + goto loc_g_14E0; + + if (al == 0x70) // intermediate state + goto loc_g_154E; + + return; + +loc_g_1242: // infotron comes falling from above + // To Do: draw infotron falling from above + // according to position in (bl And &H07) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si - FieldWidth); + dx = bl & 0x7; + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X, Y + TwoPixels * (dx + 1), aniInfotron, dx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + bl = HighByte(PlayField16[si]) + 1; + if (bl == 0x16) + { + MovHighByte(&PlayField16[si], bl); + subCleanUpForInfotronsAbove(si - FieldWidth); + + return; + } // loc_g_1285: + + if (bl < 0x18) + { + MovHighByte(&PlayField16[si], bl); + + return; + } // loc_g_128F: + + MovHighByte(&PlayField16[si], 0); // infotron arrived at the field + + // now check if the zonk may go on falling somehow + ax = PlayField16[si + FieldWidth]; + if (ax == 0) // below is empty!-> go on falling + goto loc_g_132D; + + if (ax == 0x9999) // below is only temporarily used + goto loc_g_132D; + + if ((ax & 0xFF) == fiMurphy) // Murphy dies + goto loc_g_1364; + + if (ax == fiRedDisk) // red disk hit + goto loc_g_1386; + + if ((ax & 0xFF) == fiSnikSnak) // SnikSnak dies + goto loc_g_1386; + + + if ((ax & 0xFF) == fiElectron) // Electron cracked! + goto loc_g_1386; + + if (ax == fiYellowDisk) // yellow disk hit + goto loc_g_1386; + + if (ax == fiOrangeDisk) // orange disk hit + goto loc_g_1386; + +#if 1 + +#if 1 + // play the infotron sound, 'cause infotron hits something "hard" + subSoundFX(si, fiInfotron, actImpact); +#else + // play the zonk sound, 'cause zonk hits something "hard" + subSoundFX(si, fiZonk, actImpact); +#endif + +#else + subSoundFXZonk(); // play the zonk sound,'cause zonk hits something "hard" +#endif + + if (! (ax == fiZonk || ax == fiInfotron || ax == fiRAM)) + return; + + // infotron rolls somewhere + ax = PlayField16[si + FieldWidth - 1]; + if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) // may roll left + goto loc_g_133A; + + ax = PlayField16[si + FieldWidth + 1]; + if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) // may roll right + goto loc_g_1350; + + return; + +loc_g_132D: // go on falling down? + PlayField16[si] = 0x7004; // go into intermediate waitstate + PlayField16[si + FieldWidth] = 0x9999; // mark as "zonk waiting to access" + + return; + +loc_g_133A: // test if infotron may roll left + // This if(if true) jumps up far above + // to the according rountine for fixed infotrons! + if (PlayField16[si - 1] != 0) // Remarkable!!! ' loc_g_0EF4: + goto loc_g_11BD; + + MovHighByte(&PlayField16[si], 0x50); // infotron rolls left + PlayField16[si - 1] = 0x8888; + + return; + +loc_g_1350: // test if infotron may roll right + if (PlayField16[si + 1] != 0) + return; + + MovHighByte(&PlayField16[si], 0x60); // infotron rolls right + PlayField16[si + 1] = 0x8888; + + return; + +loc_g_1364: // Murphy dies, but not in any case + bl = HighByte(PlayField16[si + FieldWidth]); + if (bl == 0xE || bl == 0xF || bl == 0x28) + return; + + if (bl == 0x29 || bl == 0x25 || bl == 0x26) + return; + +loc_g_1386: // someone dies/explodes immediately + si = si + FieldWidth; // 1 field down + ExplodeFieldSP(si); // Explode + + return; + +loc_g_138D: // infotron comes rolling from right to left + // To Do: draw infotron rolling from right + // according to position in (bl And &H07) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si + 1); + Y = GetStretchY(si); + dx = (bl & 0x7) + 1; + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X - (TwoPixels * dx), Y, aniInfotronRollLeft, dx - 1); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + bl = HighByte(PlayField16[si]) + 1; // get and increment sequence# + if (bl == 0x24) + PlayField16[si + 1] = 0xAAAA; + + if (bl == 0x26) + { + MovHighByte(&PlayField16[si], bl); + subCleanUpForInfotronsAbove(si + 1); + } + else if (bl < 0x28) + { + MovHighByte(&PlayField16[si], bl); + } + else + { + PlayField16[si] = 0x7004; // go into intermediate state + } + + return; + +loc_g_13E9: // infotron comes rolling from left to right + // To Do: draw infotron rolling from left + // according to position in (bl And &H07) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si - 1); + Y = GetStretchY(si); + dx = (bl & 0x7) + 1; + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X + (TwoPixels * dx), Y, aniInfotronRollRight, dx - 1); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + bl = HighByte(PlayField16[si]) + 1; + if (bl == 0x34) + PlayField16[si - 1] = 0xAAAA; + + if (bl == 0x36) + { + MovHighByte(&PlayField16[si], bl); + subCleanUpForInfotronsAbove(si - 1); + } + else if (bl < 0x38) + { + MovHighByte(&PlayField16[si], bl); + } + else + { + PlayField16[si] = 0x7004; // go into intermediate state + } + + return; + +loc_g_1444: // infotron falls straight down + bl = bl + 1; + if (bl < 0x42) + { + MovHighByte(&PlayField16[si], bl); + } + else if (PlayField16[si + FieldWidth] != 0) + { + bl = bl - 1; // stay waiting + MovHighByte(&PlayField16[si], bl); + } + else + { + PlayField16[si] = 0xFFFF; + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x1004; // go falling + } + + return; + +loc_g_1472: // infotron rolls left + // To Do: draw infotron rolling to left + // according to position in (bl And &H0F) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + dx = (bl & 0xF) + 1; + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X - (TwoPixels * dx), Y, aniInfotronRollLeft, dx - 1); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + bl = HighByte(PlayField16[si]) + 1; // retrieve and increment sequence# + if (bl < 0x52) + { + MovHighByte(&PlayField16[si], bl); + + return; + } + + if (PlayField16[si + FieldWidth - 1] != 0) + goto loc_g_14D9; + + if (PlayField16[si - 1] != 0) + { + if (PlayField16[si - 1] != 0x8888) + goto loc_g_14D9; + } + + PlayField16[si] = 0xFFFF; + si = si - 1; // 1 field left + PlayField16[si] = 0x2204; + PlayField16[si + FieldWidth] = 0x9999; + + return; + +loc_g_14D9: // stay waiting + bl = bl - 1; + MovHighByte(&PlayField16[si], bl); + + return; + +loc_g_14E0: // infotron rolls right + // To Do: draw infotron rolling to right + // according to position in (bl And &H07) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + dx = (bl & 0x7) + 1; + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X + (TwoPixels * dx), Y, aniInfotronRollRight, dx - 1); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + bl = HighByte(PlayField16[si]) + 1; + if (bl < 0x62) + { + MovHighByte(&PlayField16[si], bl); + + return; + } + + if (PlayField16[si + FieldWidth + 1] != 0) + goto loc_g_1547; + + if (PlayField16[si + 1] != 0) + { + if (PlayField16[si + 1] != 0x8888) + goto loc_g_1547; + } + + PlayField16[si] = 0xFFFF; + si = si + 1; + PlayField16[si] = 0x3204; + PlayField16[si + FieldWidth] = 0x9999; + + return; + +loc_g_1547: // stay waiting + bl = bl - 1; + MovHighByte(&PlayField16[si], bl); + + return; + +loc_g_154E: // intermediate state + ax = PlayField16[si + FieldWidth]; + if (ax == 0 || ax == 0x9999) + { + PlayField16[si] = 0xFFFF; + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x1004; // start falling down + goto loc_g_1242; + } +} + +void subCleanUpForInfotronsAbove(int si) +{ + int ax; + + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + if (PlayField16[si - FieldWidth] != 0) + { + if (PlayField16[si - FieldWidth] != 0x9999) + return; + + if (LowByte(PlayField16[si - 2 * FieldWidth]) != fiZonk) + return; + } + + if (PlayField16[si - FieldWidth - 1] == fiInfotron) + goto loc_g_16FE; + +loc_g_16F6: + if (PlayField16[si - FieldWidth + 1] == fiInfotron) + goto loc_g_1722; + + return; + +loc_g_16FE: + ax = PlayField16[si - 1]; + if (ax == fiZonk || ax == fiInfotron || ax == fiRAM) + { + PlayField16[si - FieldWidth - 1] = 0x6004; + PlayField16[si - FieldWidth] = 0x8888; + + return; + } + + goto loc_g_16F6; + +loc_g_1722: + ax = PlayField16[si + 1]; + if (ax == fiZonk || ax == fiInfotron || ax == fiRAM) + { + PlayField16[si - FieldWidth + 1] = 0x5004; + PlayField16[si - FieldWidth] = 0x8888; + } +} diff --git a/src/game_sp/Infotrons.h b/src/game_sp/Infotrons.h new file mode 100644 index 00000000..a18fedd0 --- /dev/null +++ b/src/game_sp/Infotrons.h @@ -0,0 +1,14 @@ +// ---------------------------------------------------------------------------- +// Infotrons.h +// ---------------------------------------------------------------------------- + +#ifndef INFOTRONS_H +#define INFOTRONS_H + +#include "global.h" + + +extern void subAnimateInfotrons(int); +extern void subCleanUpForInfotronsAbove(int); + +#endif /* INFOTRONS_H */ diff --git a/src/game_sp/InitGameConditions.c b/src/game_sp/InitGameConditions.c new file mode 100644 index 00000000..1313c49d --- /dev/null +++ b/src/game_sp/InitGameConditions.c @@ -0,0 +1,259 @@ +// ---------------------------------------------------------------------------- +// InitGameConditions.c +// ---------------------------------------------------------------------------- + +#include "InitGameConditions.h" + + +// ========================================================================== +// SUBROUTINE +// Init game conditions (variables) +// ========================================================================== + +void subInitGameConditions() +{ + MurphyVarFaceLeft = 0; + KillMurphyFlag = 0; // no "kill Murphy" + ExitToMenuFlag = 0; + LeadOutCounter = 0; // quit flag: lead-out counter + RedDiskCount = 0; // Red disk counter + + YawnSleepCounter = 0; // Wake up sleeping Murphy + + ExplosionShake = 0; // Force explosion flag off + ExplosionShakeMurphy = 0; // Force explosion flag off + + TerminalMaxCycles = 0x7F; + YellowDisksExploded = 0; + + TimerVar = 0; + + SnikSnaksElectronsFrozen = 0; // Snik-Snaks and Electrons move! + + SplitMoveFlag = 0; // Reset Split-through-ports + RedDiskReleasePhase = 0; // (re-)enable red disk release + RedDiskReleaseMurphyPos = 0; // Red disk was released here +} + + +// ========================================================================== +// SUBROUTINE +// Locate Murphy and init location. +// ========================================================================== + +void InitMurphyPos() +{ + int si; + + for (si = 0; si < LevelMax; si++) + if (PlayField16[si] == fiMurphy) + break; + + InitMurphyPosB(si); + + MurphyPosIndex = si; +} + +void InitMurphyPosB(int si) +{ + MurphyScreenXPos = MurphyXPos = GetStretchX(si); // Murphy's screen x-position + MurphyScreenYPos = MurphyYPos = GetStretchY(si); // Murphy's screen y-position + + // To Do: draw Murphy in location ax + DDSpriteBuffer_BltImg(MurphyScreenXPos, MurphyScreenYPos, aniMurphy, 0); + + subCalculateScreenScrollPos(); // calculate screen start addrs + + if (AutoScrollFlag) + { + if (bPlaying) + SoftScrollTo(ScreenScrollXPos, ScreenScrollYPos, 1000, 25); + else + ScrollTo(ScreenScrollXPos, ScreenScrollYPos); + } +} + + +// ========================================================================== +// SUBROUTINE +// Convert to easy symbols and reset Infotron count If not ThenVer62 +// ========================================================================== + +int subConvertToEasySymbols() +{ + int ax, bx, cx, dx, i; + int al; + + bx = 0; + dx = 0; + cx = LevelMax + 1; + i = 0; + +loc_g_26C9: + ax = PlayField16[i]; + al = LowByte(ax); + if (al == 0xF1) // converted explosion? + { + MovLowByte(&PlayField16[i], 0x1F); // restore explosions + goto loc_g_2778; + } + + if (LowByte(GameBusyFlag) != 1) // free screen write? + { + if (ax == fiInfotron) // Infotron? -> yes--count! + goto loc_g_2704; + + if (ax == fiSnikSnak) // Snik Snak? -> yes--rearrange + goto loc_g_2713; + + if (ax == fiElectron) // Electron? -> yes--rearrange + goto loc_g_2741; + } + + // test for fancy RAM Chips: + if (ax == fiRAMLeft || ax == fiRAMRight) + goto loc_g_2707; + + if (ax == fiRAMTop || ax == fiRAMBottom) + goto loc_g_2707; + + if (ax < fiHWFirst) // All but deco hardware? + goto loc_g_26F8; + + if (ax < fiRAMTop) // Decorative hardware? + goto loc_g_270D; + +loc_g_26F8: + if (ax < fiSpPortRight) // Gravity change ports only? + goto loc_g_2778; + + if (ax < fiSnikSnak) // Gravity change port! 'loc_g_2702: + goto loc_g_276F; + + goto loc_g_2778; + +loc_g_2704: // INFOTRON + dx = dx + 1; // Count Infotrons + goto loc_g_2778; + +loc_g_2707: // DECO RAM CHIPS + PlayField16[i] = fiRAM; // Convert to standard RAM chip + goto loc_g_2778; + +loc_g_270D: // DECO HARDWARE + PlayField16[i] = fiHardWare; // Convert to standard hardware + goto loc_g_2778; + +loc_g_2713: // SNIK-SNAK + if (PlayField16[i - 1] != 0) // 1 field left empty? -> no--try up + goto loc_g_271F; + + MovHighByte(&PlayField16[i], 1); // turn left, step = NorthWest + goto loc_g_2778; + +loc_g_271F: + if (PlayField16[i - FieldWidth] != 0) // 1 field up empty? -> no--try right + goto loc_g_2730; + + PlayField16[i - FieldWidth] = 0x1011; // SnikSnak accessing from below, step = 0 + PlayField16[i] = 0xFFFF; + goto loc_g_2778; + +loc_g_2730: + if (PlayField16[i + 1] != 0) // 1 field right empty? -> point up + goto loc_g_2778; + + PlayField16[i + 1] = 0x2811; // SnikSnak accessing from left, step = 0 + PlayField16[i] = 0xFFFF; + goto loc_g_2778; + +loc_g_2741: // ELECTRON + if (PlayField16[i - 1] != 0) // 1 field left empty? -> no--try up + goto loc_g_274D; + + MovHighByte(&PlayField16[i], 1); + goto loc_g_2778; + +loc_g_274D: + if (PlayField16[i - FieldWidth] != 0) // 1 field up empty? -> no--try right + goto loc_g_275E; + + PlayField16[i - FieldWidth] = 0x1018; // 1 field up + PlayField16[i] = 0xFFFF; + goto loc_g_2778; + +loc_g_275E: + if (PlayField16[i + 1] != 0) // 1 field right empty? -> no--point down + goto loc_g_2778; + + PlayField16[i + 1] = 0x2818; + PlayField16[i] = 0xFFFF; + goto loc_g_2778; + +loc_g_276F: // GRAVITY CHANGING PORTS + PlayField16[i] = (ax - 4) | 0x100; // Convert to standard ports + goto loc_g_2778; + +loc_g_2778: + i = i + 1; // Next field + bx = bx + 1; + cx = cx - 1; + if (0 < cx) // Until all done 'loc_g_2782: + goto loc_g_26C9; + + return dx; // return InfotronCount +} + + +// ========================================================================== +// SUBROUTINE +// Reset Infotron count. Call immediately after subConvertToEasySymbols +// ========================================================================== + +void ResetInfotronsNeeded(int dx) +{ + if (LInfo.InfotronsNeeded != 0) // Jump If equal (autodetect) + dx = LInfo.InfotronsNeeded; + + InfotronsNeeded = LowByte(dx); // Remaining Infotrons needed + TotalInfotronsNeeded = InfotronsNeeded; // Number of Infotrons needed +} + + +// ========================================================================== +// SUBROUTINE +// Fetch and initialize a level +// ========================================================================== + +void subFetchAndInitLevelB() +{ + subFetchAndInitLevelA(); +} + +void subFetchAndInitLevelA() +{ + GameBusyFlag = 0; // restore scissors too + subFetchAndInitLevel(); // fetch and initialize a level + GameBusyFlag = 1; // no free screen write + + DemoKeyCode = 0; // delete last demo key! +} + +void subFetchAndInitLevel() +{ + int InfoCountInLevel; + + PrepareLevel(); // initialize level data + + GameBusyFlag = -GameBusyFlag; // make != 1 + InfoCountInLevel = subConvertToEasySymbols(); // convert to easy symbols + GameBusyFlag = -GameBusyFlag; // restore + + subDisplayLevel(); // paint (init) game field + + ResetInfotronsNeeded(InfoCountInLevel); // and reset Infotron count + + subInitGameConditions(); // init game conditions (vars) + + InitMurphyPos(); // locate Murphy + screen pos +} diff --git a/src/game_sp/InitGameConditions.h b/src/game_sp/InitGameConditions.h new file mode 100644 index 00000000..eb4249ff --- /dev/null +++ b/src/game_sp/InitGameConditions.h @@ -0,0 +1,21 @@ +// ---------------------------------------------------------------------------- +// InitGameConditions.h +// ---------------------------------------------------------------------------- + +#ifndef INITGAMECONDITIONS_H +#define INITGAMECONDITIONS_H + +#include "global.h" + + +extern int subConvertToEasySymbols(); + +extern void InitMurphyPos(); +extern void InitMurphyPosB(int); +extern void ResetInfotronsNeeded(int); +extern void subFetchAndInitLevel(); +extern void subFetchAndInitLevelA(); +extern void subFetchAndInitLevelB(); +extern void subInitGameConditions(); + +#endif /* INITGAMECONDITIONS_H */ diff --git a/src/game_sp/Input.c b/src/game_sp/Input.c new file mode 100644 index 00000000..5a469575 --- /dev/null +++ b/src/game_sp/Input.c @@ -0,0 +1,42 @@ +// ---------------------------------------------------------------------------- +// Input.c +// ---------------------------------------------------------------------------- + +#include "Input.h" + + +int map_key_RND_to_SP(int key) +{ + if (key & KEY_BUTTON) + { + return (key & MV_UP ? keySpaceUp : + key & MV_LEFT ? keySpaceLeft : + key & MV_DOWN ? keySpaceDown : + key & MV_RIGHT ? keySpaceRight : keySpace); + } + else + { + return (key & MV_UP ? keyUp : + key & MV_LEFT ? keyLeft : + key & MV_DOWN ? keyDown : + key & MV_RIGHT ? keyRight : keyNone); + } +} + +int map_key_SP_to_RND(int key) +{ + return (key == keyUp ? MV_UP : + key == keyLeft ? MV_LEFT : + key == keyDown ? MV_DOWN : + key == keyRight ? MV_RIGHT : + key == keySpaceUp ? KEY_BUTTON | MV_UP : + key == keySpaceLeft ? KEY_BUTTON | MV_LEFT : + key == keySpaceDown ? KEY_BUTTON | MV_DOWN : + key == keySpaceRight ? KEY_BUTTON | MV_RIGHT : + key == keySpace ? KEY_BUTTON : MV_NONE); +} + +void subProcessKeyboardInput(byte action) +{ + DemoKeyCode = map_key_RND_to_SP(action); +} diff --git a/src/game_sp/Input.h b/src/game_sp/Input.h new file mode 100644 index 00000000..55f6aaf9 --- /dev/null +++ b/src/game_sp/Input.h @@ -0,0 +1,13 @@ +// ---------------------------------------------------------------------------- +// Input.h +// ---------------------------------------------------------------------------- + +#ifndef INPUT_H +#define INPUT_H + +#include "global.h" + + +extern void subProcessKeyboardInput(byte); + +#endif /* INPUT_H */ diff --git a/src/game_sp/MainForm.c b/src/game_sp/MainForm.c new file mode 100644 index 00000000..c54bf63d --- /dev/null +++ b/src/game_sp/MainForm.c @@ -0,0 +1,302 @@ +// ---------------------------------------------------------------------------- +// MainForm.c +// ---------------------------------------------------------------------------- + +#include "MainForm.h" + + +static void DrawFrame(int Delta); +static void ReStretch(); + +void DrawField(int X, int Y); +void DrawFieldAnimated(int X, int Y); +void DrawFieldNoAnimated(int X, int Y); + +void DrawFrameIfNeeded() +{ + DrawFrame(0); + + /* !!! CHECK THIS !!! */ +#if 1 + if (! menBorder) + DrawFrame(1); +#endif +} + +void DisplayLevel() +{ + int X, Y; + + if (! LevelLoaded) + return; + + ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE); +#if 1 + ClearRectangle(bitmap_db_field_sp, 0, 0, FXSIZE, FYSIZE); +#else + ClearRectangle(bitmap_db_field_sp, 0, 0, + MAX_BUF_XSIZE * TILEX, MAX_BUF_YSIZE * TILEY); +#endif + +#if 1 + SetDisplayRegion(); +#endif + + DrawFrameIfNeeded(); + + if (bPlaying) + { + for (Y = DisplayMinY; Y <= DisplayMaxY; Y++) + for (X = DisplayMinX; X <= DisplayMaxX; X++) + DrawFieldNoAnimated(X, Y); + + for (Y = DisplayMinY; Y <= DisplayMaxY; Y++) + for (X = DisplayMinX; X <= DisplayMaxX; X++) + DrawFieldAnimated(X, Y); + } + else + { + for (Y = DisplayMinY; Y <= DisplayMaxY; Y++) + for (X = DisplayMinX; X <= DisplayMaxX; X++) + DrawField(X, Y); + } +} + +void Form_Load() +{ + InitGlobals(); + + ReStretch(); +} + +static void DrawFrame(int Delta) +{ + int i, LX, tY, RX, BY; + + LX = -1 + Delta; + tY = -1 + Delta; + RX = FieldWidth - Delta; + BY = FieldHeight - Delta; + + DrawImage(LX, tY, (Delta > 0 ? imgFrameCorner : aniSpace)); + DrawImage(LX, BY, (Delta > 0 ? imgFrameCorner : aniSpace)); + DrawImage(RX, tY, (Delta > 0 ? imgFrameCorner : aniSpace)); + DrawImage(RX, BY, (Delta > 0 ? imgFrameCorner : aniSpace)); + + for (i = LX + 1; i <= RX - 1; i++) + { + DrawImage(i, tY, (Delta > 0 ? imgFrameHorizontal : aniSpace)); + DrawImage(i, BY, (Delta > 0 ? imgFrameHorizontal : aniSpace)); + } + + for (i = tY + 1; i <= BY - 1; i++) + { + DrawImage(LX, i, (Delta > 0 ? imgFrameVertical : aniSpace)); + DrawImage(RX, i, (Delta > 0 ? imgFrameVertical : aniSpace)); + } + + if (Delta > 0) + { + // ... + // ClearRectangle(bitmap_db_field_sp, + } +} + +static void RestoreFrame() +{ + int i, LX, tY, RX, BY; + + LX = 0; + tY = 0; + RX = FieldWidth - 1; + BY = FieldHeight - 1; + + for (i = LX; i <= RX; i++) + { + DrawField(i, tY); + DrawField(i, BY); + } + + for (i = tY + 1; i <= BY - 1; i++) + { + DrawField(LX, i); + DrawField(RX, i); + } +} + +void SetDisplayRegion() +{ + if (! menBorder) + { + DisplayMinX = 1; + DisplayMinY = 1; + DisplayMaxX = FieldWidth - 2; + DisplayMaxY = FieldHeight - 2; + + if (LevelLoaded) + DrawFrame(1); + } + else + { + DisplayMinX = 0; + DisplayMinY = 0; + DisplayMaxX = FieldWidth - 1; + DisplayMaxY = FieldHeight - 1; + + if (LevelLoaded) + RestoreFrame(); + } +} + +void menPlay_Click() +{ + bPlaying = True; + + subFetchAndInitLevelB(); + + ReStretch(); + + subMainGameLoop_Init(); + +#if 1 + return; +#endif + + bPlaying = False; + + subFetchAndInitLevel(); +} + +static void ReStretch() +{ + if (LevelLoaded) + { + SetDisplayRegion(); + + SetScrollEdges(); + + ScrollTo(ScrollX, ScrollY); + + DisplayLevel(); + } + + subCalculateScreenScrollPos(); + + ScrollTo(ScreenScrollXPos, ScreenScrollYPos); +} + +void SetScrollEdges() +{ + int border1_offset = (menBorder ? 1 : 2); + int border2_offset = (menBorder ? 0 : TILESIZE / 2); + + /* scroll correction for border frame (1 tile) or border element (2 tiles) */ + ScrollMinX = 0; + ScrollMinY = 0; + ScrollMaxX = (DisplayMaxX + border1_offset) * TILEX - SXSIZE; + ScrollMaxY = (DisplayMaxY + border1_offset) * TILEY - SYSIZE; + + /* scroll correction for border element (half tile on left and right side) */ + ScrollMinX += border2_offset; + ScrollMinY += border2_offset; + ScrollMaxX -= border2_offset; + ScrollMaxY -= border2_offset; + + /* scroll correction for even number of visible tiles (half tile shifted) */ + ScrollMinX -= game_sp.scroll_xoffset; + ScrollMaxX -= game_sp.scroll_xoffset; + ScrollMinY -= game_sp.scroll_yoffset; + ScrollMaxY -= game_sp.scroll_yoffset; + +#if 0 + printf("::: (%ld, %ld), (%ld, %ld) -> (%d, %d), (%d, %d)\n", + DisplayMinX, DisplayMinY, DisplayMaxX, DisplayMaxY, + ScrollMinX, ScrollMinY, ScrollMaxX, ScrollMaxY); +#endif +} + +void DrawField(int X, int Y) +{ + int tsi = GetSI(X, Y); + int Tmp = LowByte(PlayField16[tsi]); + + if (Tmp < fiFirst || Tmp > fiLast) + Tmp = fiSpace; + + if (Tmp == fiRAM || + Tmp == fiHardWare || + Tmp == fiBug || + Tmp == fiWallSpace) + Tmp = DisPlayField[tsi]; + + subCopyImageToScreen(tsi, fiGraphic[Tmp]); + + if (Tmp != fiSpace && + Tmp != fiSnikSnak && + Tmp != fiElectron) + GfxGraphic[X][Y] = fiGraphic[Tmp]; +} + +void DrawFieldAnimated(int X, int Y) +{ + int tsi = GetSI(X, Y); + int Tmp = LowByte(PlayField16[tsi]); + + switch (Tmp) + { + case fiSnikSnak: + subDrawAnimatedSnikSnaks(tsi); + break; + + case fiElectron: + subDrawAnimatedElectrons(tsi); + break; + + default: + break; + } +} + +void DrawFieldNoAnimated(int X, int Y) +{ + int tsi = GetSI(X, Y); + int Tmp = LowByte(PlayField16[tsi]); + + switch (Tmp) + { + case fiSnikSnak: + subCopyImageToScreen(tsi, aniSpace); + break; + + case fiElectron: + subCopyImageToScreen(tsi, aniSpace); + break; + + default: +#if 1 + DrawField(X, Y); +#else + if (Tmp < fiFirst || Tmp > fiLast) + Tmp = fiSpace; + + if (Tmp == fiRAM || + Tmp == fiHardWare || + Tmp == fiBug || + Tmp == fiWallSpace) + Tmp = DisPlayField[tsi]; + + subCopyImageToScreen(tsi, fiGraphic[Tmp]); + + if (Tmp != fiSpace && + Tmp != fiSnikSnak && + Tmp != fiElectron) + GfxGraphic[X][Y] = fiGraphic[Tmp]; +#endif + break; + } +} + +void DrawImage(int X, int Y, int graphic) +{ + DDSpriteBuffer_BltImg(StretchWidth * X, StretchWidth * Y, graphic, 0); +} diff --git a/src/game_sp/MainForm.h b/src/game_sp/MainForm.h new file mode 100644 index 00000000..24cbd46e --- /dev/null +++ b/src/game_sp/MainForm.h @@ -0,0 +1,27 @@ +// ---------------------------------------------------------------------------- +// MainForm.h +// ---------------------------------------------------------------------------- + +#ifndef MAINFORM_H +#define MAINFORM_H + +#include "global.h" + + +extern void DrawFrameIfNeeded(); + +extern void DisplayLevel(); +extern void DrawField(int X, int Y); +extern void DrawFieldAnimated(int X, int Y); +extern void DrawFieldNoAnimated(int X, int Y); +extern void DrawSprite(int X, int Y, int SpritePos); +extern void DrawImage(int X, int Y, int graphic); + +extern void SetDisplayRegion(); +extern void SetScrollEdges(); + +extern void menPlay_Click(); + +extern void Form_Load(); + +#endif /* MAINFORM_H */ diff --git a/src/game_sp/MainGameLoop.c b/src/game_sp/MainGameLoop.c new file mode 100644 index 00000000..48a1ac48 --- /dev/null +++ b/src/game_sp/MainGameLoop.c @@ -0,0 +1,131 @@ +// ---------------------------------------------------------------------------- +// MainGameLoop.c +// ---------------------------------------------------------------------------- + +#include "MainGameLoop.h" + + +boolean bPlaying; +int LeadOutCounter; +int ExitToMenuFlag; +boolean AutoScrollFlag; + + +// ========================================================================== +// SUBROUTINE +// Play a game/demo +// ========================================================================== + +void subMainGameLoop_Init() +{ + // This was a bug in the original Supaplex: sometimes red disks could not + // be released. This happened if Murphy was killed DURING a red disk release + // and the next try started. + + RedDiskReleasePhase = 0; // (re-)enable red disk release +} + +void subMainGameLoop_Main(byte action, boolean warp_mode) +{ + // --------------------------------------------------------------------------- + // --------------------- START OF GAME-BUSY LOOP ----------------------------- + // --------------------------------------------------------------------------- + + subProcessKeyboardInput(action); // check keyboard, act on keys + + // --------------------------------------------------------------------------- + // + + subDoGameStuff(); // do all game stuff + + // + // --------------------------------------------------------------------------- + + subRedDiskReleaseExplosion(); // Red Disk release and explode + subFollowUpExplosions(); // every explosion may cause up to 8 following explosions + + subCalculateScreenScrollPos(); // calculate screen start addrs + + if (AutoScrollFlag) + ScrollTowards(ScreenScrollXPos, ScreenScrollYPos); + + TimerVar = TimerVar + 1; + +#if 1 + if (ExplosionShakeMurphy > 0) + ExplosionShakeMurphy--; +#endif + +#if 1 + if (ExitToMenuFlag == 1) + { + // happens when demo ends or when Murphy enters exit (to be checked) + +#if 0 + goto locExitMainGameLoop; +#endif + } +#else + if (ExitToMenuFlag == 1) + goto locExitMainGameLoop; +#endif + + if (LeadOutCounter == 0) // no lead-out: game busy + return; + + // --------------------------------------------------------------------------- + // ---------------------- END OF GAME-BUSY LOOP ------------------------------ + // --------------------------------------------------------------------------- + + LeadOutCounter = LeadOutCounter - 1; // do more lead-out after quit + + if (LeadOutCounter != 0) // lead-out not ready: more + return; + + // lead-out done: exit now + // ---------------------- END OF GAME-BUSY LOOP (including lead-out) --------- + +#if 0 +locExitMainGameLoop: +#endif + +#if 0 + printf("::: locExitMainGameLoop reached [%d]\n", LeadOutCounter); + printf("::: [KillMurphyFlag == %d]\n", KillMurphyFlag); +#endif + +#if 1 + /* if the game is not won when reaching this point, then it is lost */ + if (!game_sp.LevelSolved) + game_sp.GameOver = TRUE; +#endif +} + +void subCalculateScreenScrollPos() +{ +#if 1 + int jump_pos = TILEX / 2; + + /* handle wrap-around */ + if (MurphyScreenXPos < -jump_pos) + { + MurphyScreenXPos = FieldWidth * TILEX + MurphyScreenXPos; + MurphyScreenYPos -= TILEY; + } + else if (MurphyScreenXPos >= FieldWidth * TILEX - jump_pos) + { + MurphyScreenXPos = MurphyScreenXPos - FieldWidth * TILEX; + MurphyScreenYPos += TILEY; + } +#endif + + if (ExplosionShake != 0) + { + subGetRandomNumber(); + + // printf("::: ExplosionShake [%d]\n", FrameCounter); + } + + ScreenScrollXPos = MurphyScreenXPos - (SCR_FIELDX / 2) * TILESIZE; + ScreenScrollYPos = MurphyScreenYPos - (SCR_FIELDY / 2) * TILESIZE; +} diff --git a/src/game_sp/MainGameLoop.h b/src/game_sp/MainGameLoop.h new file mode 100644 index 00000000..3ce85d27 --- /dev/null +++ b/src/game_sp/MainGameLoop.h @@ -0,0 +1,20 @@ +// ---------------------------------------------------------------------------- +// MainGameLoop.h +// ---------------------------------------------------------------------------- + +#ifndef MAINGAMELOOP_H +#define MAINGAMELOOP_H + +#include "global.h" + + +extern boolean AutoScrollFlag; +extern boolean bPlaying; +extern int ExitToMenuFlag; +extern int LeadOutCounter; + +extern void subMainGameLoop_Init(); +extern void subMainGameLoop_Main(byte, boolean); +extern void subCalculateScreenScrollPos(); + +#endif /* MAINGAMELOOP_H */ diff --git a/src/game_sp/Makefile b/src/game_sp/Makefile new file mode 100644 index 00000000..d1d9ffc3 --- /dev/null +++ b/src/game_sp/Makefile @@ -0,0 +1,95 @@ +# ============================================================================= +# Makefile for native Supaplex engine for Rocks'n'Diamonds (game_sp) +# ----------------------------------------------------------------------------- +# (c) 1995-2009 Holger Schemel +# ----------------------------------------------------------------------------- +# based on MegaPlex version 0.5 beta release xmas 2001 by Frank Schindler, +# based on the Speed Fix 6.3+ by Herman Perk, +# based on original Supaplex by Michael Stopp & Philip Jespersen +# ============================================================================= + +# ----------------------------------------------------------------------------- +# configuration +# ----------------------------------------------------------------------------- + +SRCS = init.c \ + file.c \ + main.c \ + vb_lib.c \ + \ + ASM.c \ + BugsTerminals.c \ + DDScrollBuffer.c \ + DDSpriteBuffer.c \ + Display.c \ + DoGameStuff.c \ + Electrons.c \ + Explosions.c \ + Globals.c \ + Infotrons.c \ + InitGameConditions.c \ + Input.c \ + MainForm.c \ + MainGameLoop.c \ + Murphy.c \ + OrangeDisk.c \ + SnikSnaks.c \ + Sound.c \ + Zonk.c + +OBJS = init.o \ + file.o \ + main.o \ + vb_lib.o \ + \ + ASM.o \ + BugsTerminals.o \ + DDScrollBuffer.o \ + DDSpriteBuffer.o \ + Display.o \ + DoGameStuff.o \ + Electrons.o \ + Explosions.o \ + Globals.o \ + Infotrons.o \ + InitGameConditions.o \ + Input.o \ + MainForm.o \ + MainGameLoop.o \ + Murphy.o \ + OrangeDisk.o \ + SnikSnaks.o \ + Sound.o \ + Zonk.o + +GAME_SP = game_sp.a + + +# ----------------------------------------------------------------------------- +# build targets +# ----------------------------------------------------------------------------- + +all: $(GAME_SP) + +$(GAME_SP): $(OBJS) + $(AR) cru $(GAME_SP) $(OBJS) + $(RANLIB) $(GAME_SP) + +.c.o: + $(CC) $(PROFILING) $(CFLAGS) -c $*.c + +clean: + $(RM) $(OBJS) + $(RM) $(GAME_SP) + + +# ----------------------------------------------------------------------------- +# development only +# ----------------------------------------------------------------------------- + +depend: + for i in $(SRCS); do $(CPP) $(CFLAGS) -M $$i; done > .depend + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/src/game_sp/Murphy.c b/src/game_sp/Murphy.c new file mode 100644 index 00000000..06cd9f7d --- /dev/null +++ b/src/game_sp/Murphy.c @@ -0,0 +1,2591 @@ +// ---------------------------------------------------------------------------- +// Murphy.c +// ---------------------------------------------------------------------------- + +#include "Murphy.h" + + +static void subEatRedDisk(int si); +static boolean subMoveKillsMurphy(int si, int ax, int bl); + +#if 1 + +#define LocalStretch (2) +#define MurphyZoomFactor (ZoomFactor) + +#else + +#define LocalStretch (1) +#define MurphyZoomFactor (1) + +#endif + +// ========================================================================== +// SUBROUTINE +// Move Murphy in any direction +// ========================================================================== + +void subAnimateMurphy(int *si) +{ + int ax, al, bl, i, X, Y; + int time1, time2; + int tDeltaX, tDeltaY, tPos, Tmp; + + // Variables that hold information about the animation sequence + static int dx1 = 0; // image/animation token + static int dx2 = 0; // an additional image position of a second sprite, for instance: yellow disk if pushed + static int MurphyDX = 0, MurphyDY = 0; // murphys move steps + static int SeqPos = 0; // index into dx() + static int ClearPos = 0; // Position to clear before blitting sprites, none=-1 + static int dxPos = 0; // field-position to draw dx(SeqPos) + static int dx2Step = 0; // position of dx2 relative to dx-position + static int dx1SequenceLength = 0; + + ax = PlayField16[*si]; + al = LowByte(ax); + + if (al != fiMurphy) + { + MurphyMoveCounter = 0; // We have no Murphy! Exit! + + return; + } + + MurphyMoveCounter = 1; // We have a Murphy! + MurphyExplodePos = *si; + + // (check if high byte of PlayField16 has stored movement information) + if (ax != fiMurphy) // yes--go proceed moving murphy? + goto locProceedMovingMurphy; + + // FS: reset moving sequence variables + MurphyDX = 0; + MurphyDY = 0; + ClearPos = *si; + dxPos = *si; + dx1 = -1; + dx2 = -1; + SeqPos = 0; + // end of FS + + ScratchGravity = 0; // scratch gravity off + if (GravityFlag != 0) // Gravity? (1=gravity on) + { + bl = LowByte(PlayField16[*si - FieldWidth]); // check above + if (! (bl == fiPortUp || + bl == fiPortUpAndDown || + bl == fiPortAllDirections)) + { + if (PlayField16[*si + FieldWidth] == 0) // gravity on and space below! + ScratchGravity = 1; + } + } // loc_g_5E8B: + + bl = DemoKeyCode; + if (bl != 0) // a key was pressed! + goto locKeyPressed5FCF; + + RedDiskReleaseFlag = 1; + if (ScratchGravity != 0) // gravity pulls & space below?'-> force Space up to down + { + MurphyDY = 2; + goto loc_g_6364; + } + +#if 1 + +#if 0 + ax = (TimerVar & 3); + if (ax != 0) + return; +#endif + + // ------------------------------------------------------------------ + // Murphy's YAWN & SLEEP sequence, counted down by YawnSleepCounter: + + YawnSleepCounter = YawnSleepCounter + 1; + + if (YawnSleepCounter < 16) + return; + + if (YawnSleepCounter < 2000) + { + // normal grin + // (default: single graphic, no animation) + subCopyAnimToScreen(*si, aniMurphy, YawnSleepCounter - 16); + + return; + } + + if (YawnSleepCounter < 4000) + { + // yawn! and look depressed afterwards... + // (default: 12 animation frames with delay of 8) + subCopyAnimToScreen(*si, aniMurphyYawn, YawnSleepCounter - 2000); + + return; + } + + if (YawnSleepCounter < 6400) + { + // yawn again! + // (default: 12 animation frames with delay of 8) + subCopyAnimToScreen(*si, aniMurphyYawn, YawnSleepCounter - 4000); + + return; + } + + // time1 = 6400 + 12 * 8; // (default: 6496 == 6400 + 12 * 8) + time1 = 6400 + 12 * 10; + + if (YawnSleepCounter < time1) + { + // yawn again! - third time + // (default: 12 animation frames with delay of 8) + subCopyAnimToScreen(*si, aniMurphyYawn, YawnSleepCounter - 6400); + + return; + } + + // time2 = 6496 + 3 * 64; // (default: 6688 == 6496 + 3 * 64) + time2 = 6496 + 3 * 100; + + if (YawnSleepCounter > time2) // Murphy already went to sleep + return; + + if (PlayField16[*si - 1] == 0) + { + if (PlayField16[*si + 1] == 0) + { + // no sleep -- go back to "wait and start yawning" phase + YawnSleepCounter = 144; + + return; + } + else + { + // go to sleep (right side) + // (default: 3 animation frames with delay of 64) + subCopyAnimToScreen(*si, aniMurphySleepRight, YawnSleepCounter - time1); + + return; + } + } + + // go to sleep (left side) + // (default: 3 animation frames with delay of 64) + subCopyAnimToScreen(*si, aniMurphySleepLeft, YawnSleepCounter - time1); + + return; + + // end of YAWN-SLEEP-Sequence + +#else + + ax = (TimerVar & 3); + if (ax != 0) + return; + + // ------------------------------------------------------------------ + // Murphy's YAWN & SLEEP sequence, counted down by YawnSleepCounter: + YawnSleepCounter = YawnSleepCounter + 1; + if (YawnSleepCounter == 4) + { + subCopyFieldToScreen(*si, fiMurphy); // normal grin + return; + } // loc_g_5ECE: + + if (YawnSleepCounter <= 500) // loc_g_5ED7: + return; + + if (YawnSleepCounter <= 522) + { + bx = (YawnSleepCounter - 500) / 2; + subCopyFieldToScreen(*si, aniMurphyYawn + bx); // yawn! and look depressed afterwards... + return; + } // loc_g_5F00: + + if (YawnSleepCounter <= 1000) + return; + + if (YawnSleepCounter <= 1022) + { + bx = (YawnSleepCounter - 1000) / 2; + subCopyFieldToScreen(*si, aniMurphyYawn + bx); // yawn again! + return; + } // loc_g_5F32: + + if (YawnSleepCounter <= 1600) // loc_g_5F3B: + return; + + if (YawnSleepCounter <= 1622) + { + bx = (YawnSleepCounter - 1600) / 2; + subCopyFieldToScreen(*si, aniMurphyYawn + bx); // yawn again! - third time + return; + } // loc_g_5F64: + + if (YawnSleepCounter > 1654) + return; + + if (PlayField16[*si - 1] == 0) + { + if (PlayField16[*si + 1] == 0) + { + YawnSleepCounter = 36; + return; + + } + else + { + bx = (YawnSleepCounter - 1622) / 16; + subCopyFieldToScreen(*si, aniMurphySleepRight + bx); // go to sleep + return; + } + } // loc_g_5F81: + + bx = (YawnSleepCounter - 1622) / 16; + subCopyFieldToScreen(*si, aniMurphySleepLeft + bx); // go to sleep + + return; + + // end of YAWN-SLEEP-Sequence + +#endif + + // ------------------------------------------------------------------ + // ========================================================================== + // (Direct Jump) a key was pressed + // ========================================================================== + +locKeyPressed5FCF: + if (ScratchGravity == 0) + goto loc_g_6003; + + if (PlayField16[*si + FieldWidth] != 0) + goto loc_g_6003; + + if (bl == keyUp) + { + if (PlayField16[*si - FieldWidth] == fiBase) + goto loc_g_6003; + + } + else if (bl == keyLeft) + { + if (PlayField16[*si - 1] == fiBase) + goto loc_g_6003; + + } + else if (bl == keyRight) + { + if (PlayField16[*si + 1] == fiBase) + goto loc_g_6003; + } // loc_g_6001: + + bl = keyDown; // force moving down! +loc_g_6003: + switch (bl) + { + case keyUp: // 1 + RedDiskReleaseFlag = 0; // moving down to up ... + goto loc_g_6078; + + break; + + case keyLeft: // 2 + RedDiskReleaseFlag = 0; // moving right to left ... + goto loc_g_60DA; + + break; + + case keyDown: // 3 + RedDiskReleaseFlag = 0; // moving up to down ... + goto loc_g_6154; + + break; + + case keyRight: // 4 + RedDiskReleaseFlag = 0; // moving left to right ... + goto loc_g_61B6; + + break; + + case keySpaceUp: // 5 + RedDiskReleaseFlag = 0; // touching down to up ... + goto loc_g_622E; + + break; + + case keySpaceLeft: // 6 + RedDiskReleaseFlag = 0; // touching right to left ... + goto loc_g_6258; + + break; + + case keySpaceDown: // 7 + RedDiskReleaseFlag = 0; // touching up to down ... + goto loc_g_6288; + + break; + + case keySpaceRight: // 8 + RedDiskReleaseFlag = 0; // touching left to right ... + goto loc_g_62B2; + + break; + + case keySpace: // 9 + goto loc_g_62E2; // no move ... + + break; + + default: + RedDiskReleaseFlag = 0; + return; + break; + } + + // ========================================================================== + // moving down to up ... + // ========================================================================== + +loc_g_6078: + // FS: + MurphyDY = -2; + // end of FS + ax = PlayField16[*si - FieldWidth]; + al = LowByte(ax); + if (ax == fiSpace) + goto loc_g_6312; + + if (ax == fiBase) + goto loc_g_63D3; + + if (al == fiBug) + goto loc_g_63C2; + + if (ax == fiInfotron) + goto loc_g_65C6; + + if (ax == fiExit) + goto loc_g_6756; + + if (al == fiTerminal) + goto loc_g_6817; + + if (al == fiPortUp || al == fiPortUpAndDown || al == fiPortAllDirections) + goto loc_g_6916; + + if (al == fiRedDisk) + goto loc_g_69A6; + + if (al == fiYellowDisk) + goto loc_g_6AB8; + + if (! subMoveKillsMurphy(*si - FieldWidth, ax, bl)) + goto loc_g_6078; + + return; + + // ========================================================================== + // moving right to left ... + // ========================================================================== + +loc_g_60DA: + // FS: + MurphyDX = -2; + // end of FS + MurphyVarFaceLeft = 1; + ax = PlayField16[*si - 1]; + al = LowByte(ax); + if (ax == fiSpace) + goto loc_g_6341; + + if (ax == fiBase) + goto loc_g_641C; + + if (al == fiBug) + goto loc_g_640B; + + if (ax == fiInfotron) + goto loc_g_65FE; + + if (ax == fiExit) + goto loc_g_6756; + + if (ax == fiZonk) + goto loc_g_679B; + + if (al == fiTerminal) + goto loc_g_684E; + + if (al == fiPortLeft || al == fiPortLeftAndRight || al == fiPortAllDirections) + goto loc_g_693A; + + if (ax == fiRedDisk) + goto loc_g_69CE; + + if (ax == fiYellowDisk) + goto loc_g_6AF1; + + if (ax == fiOrangeDisk) + goto loc_g_6B9B; + + if (! subMoveKillsMurphy(*si - 1, ax, bl)) + goto loc_g_60DA; + + return; + + // ========================================================================== + // moving up to down ... + // ========================================================================== + +loc_g_6154: + // FS: + MurphyDY = 2; + // end of FS + ax = PlayField16[*si + FieldWidth]; + al = LowByte(ax); + if (ax == fiSpace) + goto loc_g_6364; + + if (ax == fiBase) + goto loc_g_6459; + + if (al == fiBug) + goto loc_g_6448; + + if (ax == fiInfotron) + goto loc_g_662A; + + if (ax == fiExit) + goto loc_g_6756; + + if (al == fiTerminal) + goto loc_g_6884; + + if (al == fiPortDown || al == fiPortUpAndDown || al == fiPortAllDirections) + goto loc_g_695E; + + if (al == fiRedDisk) + goto loc_g_69F7; + + if (al == fiYellowDisk) + goto loc_g_6B2A; + + if (! subMoveKillsMurphy(*si + FieldWidth, ax, bl)) + goto loc_g_6154; + + return; + + // ========================================================================== + // moving left to right ... + // ========================================================================== + +loc_g_61B6: + // FS: + MurphyDX = 2; + // end of FS + MurphyVarFaceLeft = 0; + ax = PlayField16[*si + 1]; + al = LowByte(ax); + if (ax == fiSpace) + goto loc_g_6399; + + if (ax == fiBase) + goto loc_g_64A2; + + if (al == fiBug) + goto loc_g_6491; + + if (ax == fiInfotron) + goto loc_g_6662; + + if (ax == fiExit) + goto loc_g_6756; + + if (ax == fiZonk) + goto loc_g_67D4; + + if (al == fiTerminal) + goto loc_g_68BA; + + if (al == fiPortRight || al == fiPortLeftAndRight || al == fiPortAllDirections) + goto loc_g_6982; + + if (al == fiRedDisk) + goto loc_g_6A1F; + + if (al == fiYellowDisk) + goto loc_g_6B63; + + if (ax == fiOrangeDisk) + goto loc_g_6BD3; + + if (! subMoveKillsMurphy(*si + 1, ax, bl)) + goto loc_g_61B6; + + return; + + // ========================================================================== + // touching down to up ... + // ========================================================================== + +loc_g_622E: + // FS: + ClearPos = -1; + dxPos = *si - FieldWidth; + // end of FS + ax = PlayField16[*si - FieldWidth]; + al = LowByte(ax); + al = LowByte(ax); + if (ax == fiBase) + goto loc_g_64DF; + + if (al == fiBug) + goto loc_g_64CE; + + if (ax == fiInfotron) + goto loc_g_668E; + + if (al == fiTerminal) + goto loc_g_6817; + + if (al == fiRedDisk) + goto loc_g_6A48; + + return; + + // ========================================================================== + // touching right to left ... + // ========================================================================== + +loc_g_6258: + // FS: + ClearPos = -1; + dxPos = *si - 1; + // end of FS + MurphyVarFaceLeft = 1; + ax = PlayField16[*si - 1]; + al = LowByte(ax); + if (ax == fiBase) + goto loc_g_651D; + + if (al == fiBug) + goto loc_g_650C; + + if (ax == fiInfotron) + goto loc_g_66C0; + + if (al == fiTerminal) + goto loc_g_684E; + + if (al == fiRedDisk) + goto loc_g_6A64; + + return; + + // ========================================================================== + // touching up to down ... + // ========================================================================== + +loc_g_6288: + // FS: + ClearPos = -1; + dxPos = *si + FieldWidth; + // end of FS + ax = PlayField16[*si + FieldWidth]; + al = LowByte(ax); + if (ax == fiBase) + goto loc_g_655B; + + if (al == fiBug) + goto loc_g_654A; + + if (ax == fiInfotron) + goto loc_g_66F2; + + if (al == fiTerminal) + goto loc_g_6884; + + if (al == fiRedDisk) + goto loc_g_6A80; + + return; + + // ========================================================================== + // touching left to right ... + // ========================================================================== + +loc_g_62B2: + // FS: + ClearPos = -1; + dxPos = *si + 1; + // end of FS + MurphyVarFaceLeft = 0; + ax = PlayField16[*si + 1]; + al = LowByte(ax); + if (ax == fiBase) + goto loc_g_6599; + + if (al == fiBug) + goto loc_g_6588; + + if (ax == fiInfotron) + goto loc_g_6724; + + if (al == fiTerminal) + goto loc_g_68BA; + + if (al == fiRedDisk) + goto loc_g_6A9C; + + return; + + // ========================================================================== + // Release Red disk: no move ... + // ========================================================================== + +loc_g_62E2: + // FS: + ClearPos = -1; + // end of FS + if (LowByte(RedDiskCount) == 0) + return; + + if (LowByte(RedDiskReleasePhase) != 0) + return; + + if (LowByte(RedDiskReleaseFlag) != 1) + return; + + MovHighByte(&PlayField16[*si], 0x2A); + MovingPictureSequencePhase = 0x40; // init picture move sequence + dx1 = aniRedDisk; + MovLowByte(&RedDiskReleasePhase, 1); + RedDiskReleaseMurphyPos = *si; // remember Murphy's location + goto loc_Split; + + // ========================================================================== + // SPACE moving down to up + // ========================================================================== + +loc_g_6312: + dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyMoveUpRight : aniMurphyMoveUpLeft); + PlayField16[*si - FieldWidth] = 0x103; + PlayField16[*si] = 0x300; + *si = *si - FieldWidth; + goto loc_StopNoSplit; + + // ========================================================================== + // SPACE moving right to left + // ========================================================================== + +loc_g_6341: + dx1 = aniMurphyMoveLeft; + PlayField16[*si - 1] = 0x203; + PlayField16[*si] = 0x300; + *si = *si - 1; + goto loc_StopNoSplit; + + // ========================================================================== + // SPACE moving up to down, and when gravity is pulling! + // ========================================================================== + +loc_g_6364: + dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyMoveUpRight : aniMurphyMoveUpLeft); + PlayField16[*si + FieldWidth] = 0x303; + PlayField16[*si] = 0x300; + *si = *si + FieldWidth; + goto loc_StopNoSplit; + + // ========================================================================== + // SPACE moving left to right + // ========================================================================== + +loc_g_6399: + dx1 = aniMurphyMoveRight; + PlayField16[*si + 1] = 0x403; + PlayField16[*si] = 0x300; + *si = *si + 1; + goto loc_StopNoSplit; + + // ========================================================================== + // BUG moving down to up + // ========================================================================== + +loc_g_63C2: + if (SgnHighByte(PlayField16[*si - FieldWidth]) >= 0) + { + ExplodeFieldSP(*si); // Explode + + return; + } + + PlayField16[*si - FieldWidth] = fiBase; + // ========================================================================== + // BASE moving down to up + // ========================================================================== + +loc_g_63D3: + subSoundFX(*si, fiBase, actDigging); + + dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyDigUpRight : aniMurphyDigUpLeft); + PlayField16[*si - FieldWidth] = 0x503; + PlayField16[*si] = 0x300; + *si = *si - FieldWidth; + goto loc_StopNoSplit; + + // ========================================================================== + // BUG moving right to left + // ========================================================================== + +loc_g_640B: + if (SgnHighByte(PlayField16[*si - 1]) >= 0) + { + ExplodeFieldSP(*si); // Explode + + return; + } + + PlayField16[*si - 1] = fiBase; + // ========================================================================== + // BASE moving right to left + // ========================================================================== + +loc_g_641C: + subSoundFX(*si, fiBase, actDigging); + + dx1 = aniMurphyDigLeft; + PlayField16[*si - 1] = 0x203; + PlayField16[*si] = 0x300; + *si = *si - 1; + goto loc_StopNoSplit; + + // ========================================================================== + // BUG moving up to down + // ========================================================================== + +loc_g_6448: + if (SgnHighByte(PlayField16[*si + FieldWidth]) >= 0) + { + ExplodeFieldSP(*si); // Explode + + return; + } + + PlayField16[*si + FieldWidth] = fiBase; + // ========================================================================== + // BASE moving up to down + // ========================================================================== + +loc_g_6459: + subSoundFX(*si, fiBase, actDigging); + + dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyDigUpRight : aniMurphyDigUpLeft); + PlayField16[*si + FieldWidth] = 0x703; + PlayField16[*si] = 0x300; + *si = *si + FieldWidth; + goto loc_StopNoSplit; + + // ========================================================================== + // BUG moving left to right + // ========================================================================== + +loc_g_6491: + if (SgnHighByte(PlayField16[*si + 1]) >= 0) + { + ExplodeFieldSP(*si); // Explode + + return; + } + + PlayField16[*si + 1] = fiBase; + // ========================================================================== + // BASE moving left to right + // ========================================================================== + +loc_g_64A2: + subSoundFX(*si, fiBase, actDigging); + + dx1 = aniMurphyDigRight; + PlayField16[*si + 1] = 0x803; + PlayField16[*si] = 0x300; + *si = *si + 1; + goto loc_StopNoSplit; + + // ========================================================================== + // BUG touching down to up + // ========================================================================== + +loc_g_64CE: + if (SgnHighByte(PlayField16[*si - FieldWidth]) >= 0) + { + ExplodeFieldSP(*si); // Explode + + return; + } + + PlayField16[*si - FieldWidth] = fiBase; + // ========================================================================== + // BASE touching down to up + // ========================================================================== + +loc_g_64DF: + subCopyImageToScreen(*si, aniMurphyTouchUp); + subSoundFX(*si, fiBase, actDigging); + + dx1 = aniTouchBase; + dxPos = *si - FieldWidth; + MovHighByte(&PlayField16[*si], 0x10); + goto loc_StopNoSplit; + + // ========================================================================== + // BUG touching right to left + // ========================================================================== + +loc_g_650C: + if (SgnHighByte(PlayField16[*si - 1]) >= 0) + { + ExplodeFieldSP(*si); // Explode + + return; + } + + PlayField16[*si - 1] = fiBase; + // ========================================================================== + // BASE touching right to left + // ========================================================================== + +loc_g_651D: + subCopyImageToScreen(*si, aniMurphyTouchLeft); + subSoundFX(*si, fiBase, actDigging); + + dx1 = aniTouchBase; + dxPos = *si - 1; + MovHighByte(&PlayField16[*si], 0x11); + goto loc_StopNoSplit; + + // ========================================================================== + // BUG touching up to down + // ========================================================================== + +loc_g_654A: + if (SgnHighByte(PlayField16[*si + FieldWidth]) >= 0) + { + ExplodeFieldSP(*si); // Explode + + return; + } + + PlayField16[*si + FieldWidth] = fiBase; + // ========================================================================== + // BASE touching up to down + // ========================================================================== + +loc_g_655B: + subCopyImageToScreen(*si, aniMurphyTouchDown); + subSoundFX(*si, fiBase, actDigging); + + dx1 = aniTouchBase; + dxPos = *si + FieldWidth; + MovHighByte(&PlayField16[*si], 0x12); + goto loc_StopNoSplit; + + // ========================================================================== + // BUG touching left to right + // ========================================================================== + +loc_g_6588: + if (SgnHighByte(PlayField16[*si + 1]) >= 0) + { + ExplodeFieldSP(*si); // Explode + + return; + } + + PlayField16[*si + 1] = fiBase; + // ========================================================================== + // BASE touching left to right + // ========================================================================== + +loc_g_6599: + subCopyImageToScreen(*si, aniMurphyTouchRight); + subSoundFX(*si, fiBase, actDigging); + + dx1 = aniTouchBase; + dxPos = *si + 1; + MovHighByte(&PlayField16[*si], 0x13); + goto loc_StopNoSplit; + + // ========================================================================== + // INFOTRON moving down to up + // ========================================================================== + +loc_g_65C6: + subSoundFX(*si, fiInfotron, actCollecting); + + dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft); + PlayField16[*si - FieldWidth] = 0x903; + PlayField16[*si] = 0x300; + *si = *si - FieldWidth; + goto loc_StopNoSplit; + + // ========================================================================== + // INFOTRON moving right to left + // ========================================================================== + +loc_g_65FE: + subSoundFX(*si, fiInfotron, actCollecting); + + dx1 = aniEatInfotronLeft; +#if 0 + dx2 = fiInfotron; + dx2Step = -1; + ClearPos = -1; +#endif + PlayField16[*si - 1] = 0xA03; + PlayField16[*si] = 0x300; + *si = *si - 1; + goto loc_StopNoSplit; + + // ========================================================================== + // INFOTRON moving up to down + // ========================================================================== + +loc_g_662A: + subSoundFX(*si, fiInfotron, actCollecting); + + dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft); + PlayField16[*si + FieldWidth] = 0xB03; + PlayField16[*si] = 0x300; + *si = *si + FieldWidth; + goto loc_StopNoSplit; + + // ========================================================================== + // INFOTRON moving left to right + // ========================================================================== + +loc_g_6662: + subSoundFX(*si, fiInfotron, actCollecting); + + dx1 = aniEatInfotronRight; +#if 0 + dx2 = fiInfotron; + dx2Step = 1; + ClearPos = -1; +#endif + PlayField16[*si + 1] = 0xC03; + PlayField16[*si] = 0x300; + *si = *si + 1; + goto loc_StopNoSplit; + + // ========================================================================== + // INFOTRON touching down to up + // ========================================================================== + +loc_g_668E: + subCopyImageToScreen(*si, aniMurphyTouchUp); + subSoundFX(*si, fiInfotron, actCollecting); + + dx1 = aniTouchInfotron; + MovHighByte(&PlayField16[*si], 0x14); + MovHighByte(&PlayField16[*si - FieldWidth], 0xFF); + goto loc_StopNoSplit; + + // ========================================================================== + // INFOTRON touching right to left + // ========================================================================== + +loc_g_66C0: + subCopyImageToScreen(*si, aniMurphyTouchLeft); + subSoundFX(*si, fiInfotron, actCollecting); + + dx1 = aniTouchInfotron; + MovHighByte(&PlayField16[*si], 0x15); + MovHighByte(&PlayField16[*si - 1], 0xFF); + goto loc_StopNoSplit; + + // ========================================================================== + // INFOTRON touching up to down + // ========================================================================== + +loc_g_66F2: + subCopyImageToScreen(*si, aniMurphyTouchDown); + subSoundFX(*si, fiInfotron, actCollecting); + + dx1 = aniTouchInfotron; + MovHighByte(&PlayField16[*si], 0x16); + MovHighByte(&PlayField16[*si + FieldWidth], 0xFF); + goto loc_StopNoSplit; + + // ========================================================================== + // INFOTRON touching left to right + // ========================================================================== + +loc_g_6724: + subCopyImageToScreen(*si, aniMurphyTouchRight); + subSoundFX(*si, fiInfotron, actCollecting); + + dx1 = aniTouchInfotron; + MovHighByte(&PlayField16[*si], 0x17); + MovHighByte(&PlayField16[*si + 1], 0xFF); + goto loc_StopNoSplit; + + // ========================================================================== + // EXIT pressed from any direction + // ========================================================================== + +loc_g_6756: + // FS + ClearPos = -1; + MurphyDX = 0; + MurphyDY = 0; + // end of FS + if (LowByte(InfotronsNeeded) != 0) + return; + +#if 0 + if (!game_sp.LevelSolved) + printf("::: Murphy.c: !!!!!!!!!! LEVEL %d SOLVED !!!!!!!!!!\n", level_nr); +#endif + +#if 1 + game_sp.LevelSolved = TRUE; +#endif + + subSoundFX(*si, fiExit, actPassing); + + LeadOutCounter = 0x40; // quit: start lead-out + dx1 = aniMurphyExit; + MovHighByte(&PlayField16[*si], 0xD); + goto loc_StopNoSplit; + + // ========================================================================== + // ZONK moving right to left + // ========================================================================== + +loc_g_679B: + ax = PlayField16[*si - 2]; + if (ax != 0) + return; + + MovHighByte(&PlayField16[*si - 2], 1); + subCopyImageToScreen(*si, aniPushLeft); // draw pushing murphy + dx1 = aniZonkRollLeft; + dxPos = *si - 1; + dx2 = aniPushLeft; + dx2Step = 1; + MovHighByte(&PlayField16[*si], 0xE); + goto loc_MoveNoSplit; + + // ========================================================================== + // ZONK moving left to right + // ========================================================================== + +loc_g_67D4: + ax = PlayField16[*si + 2]; + if (ax != 0) + return; + + ax = PlayField16[*si + FieldWidth + 1]; + if (ax == 0) // zonk falls + return; + + MovHighByte(&PlayField16[*si + 2], 1); + subCopyImageToScreen(*si, aniPushRight); // draw pushing murphy + dx1 = aniZonkRollRight; + dxPos = *si + 1; + dx2 = aniPushRight; + dx2Step = -1; + MovHighByte(&PlayField16[*si], 0xF); + goto loc_MoveNoSplit; + + // ========================================================================== + // TERMINAL moving/touching down to up + // ========================================================================== + +loc_g_6817: + subCopyImageToScreen(*si, aniMurphyTouchUp); + if (YellowDisksExploded != 0) + { + YawnSleepCounter = 40; // stay hypnotized + + return; + } // loc_g_6838: + +#if 1 + // draw new terminal type +#if 1 + GfxGraphic[GetX(*si - FieldWidth)][GetY(*si - FieldWidth)] = aniTerminalActive; +#else + subCopyImageToScreen(*si - FieldWidth, aniTerminalActive); +#endif +#else + subCopyFieldToScreen(*si - FieldWidth, 0x88); // draw new terminal type +#endif + TerminalState[*si - FieldWidth] = 8; + goto loc_g_68F0; + + // ========================================================================== + // TERMINAL moving/touching right to left + // ========================================================================== + +loc_g_684E: + subCopyImageToScreen(*si, aniMurphyTouchLeft); + if (YellowDisksExploded != 0) + { + YawnSleepCounter = 40; // stay hypnotized + + return; + } // loc_g_6838: + +#if 1 + // draw new terminal type +#if 1 + GfxGraphic[GetX(*si - 1)][GetY(*si - 1)] = aniTerminalActive; +#else + subCopyImageToScreen(*si - 1, aniTerminalActive); +#endif +#else + subCopyFieldToScreen(*si - 1, 0x88); // draw new terminal type +#endif + TerminalState[*si - 1] = 8; + goto loc_g_68F0; + + // ========================================================================== + // TERMINAL moving/touching up to down + // ========================================================================== + +loc_g_6884: + subCopyImageToScreen(*si, aniMurphyTouchDown); + if (YellowDisksExploded != 0) + { + YawnSleepCounter = 40; // stay hypnotized + + return; + } // loc_g_6838: + +#if 1 + // draw new terminal type +#if 1 + GfxGraphic[GetX(*si + FieldWidth)][GetY(*si + FieldWidth)] = aniTerminalActive; +#else + subCopyImageToScreen(*si + FieldWidth, aniTerminalActive); +#endif +#else + subCopyFieldToScreen(*si + FieldWidth, 0x88); // draw new terminal type +#endif + TerminalState[*si + FieldWidth] = 8; + goto loc_g_68F0; + + // ========================================================================== + // TERMINAL moving/touching left to right + // ========================================================================== + +loc_g_68BA: + subCopyImageToScreen(*si, aniMurphyTouchRight); + if (YellowDisksExploded != 0) + { + YawnSleepCounter = 40; // stay hypnotized + + return; + } // loc_g_6838: + +#if 1 + // draw new terminal type +#if 1 + GfxGraphic[GetX(*si + 1)][GetY(*si + 1)] = aniTerminalActive; +#else + subCopyImageToScreen(*si + 1, aniTerminalActive); +#endif +#else + subCopyFieldToScreen(*si + 1, 0x88); // draw new terminal type +#endif + TerminalState[*si + 1] = 8; + // ========================================================================== + // common TERMINAL stuff moving/touching from all directions + // ========================================================================== + +loc_g_68F0: + TerminalMaxCycles = 7; + YellowDisksExploded = 1; + for (i = 0; i <= LevelMax; i++) + { + if (PlayField16[i] == fiYellowDisk) + ExplodeFieldSP (i); + } + + return; + + // ========================================================================== + // PORT down to up, VERTICAL PORT, CROSS PORT all moving down to up + // ========================================================================== + +loc_g_6916: + if (PlayField16[*si - 2 * FieldWidth] != 0) + return; + + dx1 = aniSplitUpDown; + dx2Step = -FieldWidth; + PlayField16[*si] = 0x1803; + PlayField16[*si - 2 * FieldWidth] = 0x300; + goto loc_StopSplit; + + // ========================================================================== + // PORT right to left, HORIZONTAL PORT, CROSS PORT all moving right to left + // ========================================================================== + +loc_g_693A: + if (PlayField16[*si - 2] != 0) + return; + + dx1 = aniMurphyMoveLeft; + dx2Step = -1; + PlayField16[*si] = 0x1903; + PlayField16[*si - 2] = 0x300; + goto loc_StopSplit; + + // ========================================================================== + // PORT up to down, VERTICAL PORT, CROSS PORT all moving up to down + // ========================================================================== + +loc_g_695E: + if (PlayField16[*si + 2 * FieldWidth] != 0) + return; + + dx1 = aniSplitUpDown; + dx2Step = FieldWidth; + PlayField16[*si] = 0x1A03; + PlayField16[*si + 2 * FieldWidth] = 0x300; + goto loc_StopSplit; + + // ========================================================================== + // PORT left to right, HORIZONTAL PORT, CROSS PORT all moving left to right + // ========================================================================== + +loc_g_6982: + if (PlayField16[*si + 2] != 0) + return; + + dx1 = aniMurphyMoveRight; + dx2Step = 1; + PlayField16[*si] = 0x1B03; + PlayField16[*si + 2] = 0x300; + +loc_StopSplit: + MovingPictureSequencePhase = 0; // stop picture move sequence + SplitMoveFlag = 1; // port: split movement + goto loc_Split; + + // ========================================================================== + // RED DISK moving down to up + // ========================================================================== + +loc_g_69A6: + dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft); + PlayField16[*si] = 0x1C03; + PlayField16[*si - FieldWidth] = 0x300; + goto loc_StopNoSplit; + + // ========================================================================== + // RED DISK moving right to left + // ========================================================================== + +loc_g_69CE: + dx1 = aniMurphyEatLeft; + PlayField16[*si] = 0x300; // !!!!!! this time we move murphy at sequence-start! + PlayField16[*si - 1] = 0x1D03; + *si = *si - 1; + goto loc_StopNoSplit; + + // ========================================================================== + // RED DISK moving up to down + // ========================================================================== + +loc_g_69F7: + dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft); + PlayField16[*si] = 0x1E03; + PlayField16[*si + FieldWidth] = 0x300; + goto loc_StopNoSplit; + + // ========================================================================== + // RED DISK moving left to right + // ========================================================================== + +loc_g_6A1F: + // dx = aniMurphyEatRightRedDisk 'this sequence is 9 steps long! + dx1 = aniMurphyEatRight; + // -------------------------------------------------------------------------- + // BugFix + // Table data_h_145A, pointed to by table data_h_105E, has a severe bug: + // The Red Disk sequence is 8 pictures long, but 9 are displayed, because it + // has 1 extra entry, which causes Murphy to end slightly shifted to the left! + // We may not fix the table, because then the timing of the game changes + // and several existing demo's do not run properly anymore. + // We only correct Murphies x-location here, when the sequence starts. + // Remember that this is not the real bug-fix, but we must live with + // this existing bug and correct for the consequences of it. + + if (AllowEatRightRedDiskBug == 0) // Murphy's screen x-position + MurphyScreenXPos = MurphyScreenXPos - 2 * MurphyZoomFactor; + + SeqPos = -1; + // FS: for me this means to blit the first animation frame twice + // end of BugFix + // -------------------------------------------------------------------------- + PlayField16[*si] = 0x300; // !!!!!! this time we move murphy at sequence-start! + PlayField16[*si + 1] = 0x1F03; + *si = *si + 1; + goto loc_StopNoSplit; + + // ========================================================================== + // RED DISK touching down to up + // ========================================================================== + +loc_g_6A48: + dx1 = aniTouchRedDisk; + MovHighByte(&PlayField16[*si], 0x20); + MovHighByte(&PlayField16[*si - FieldWidth], 3); + goto loc_StopNoSplit; + + // ========================================================================== + // RED DISK touching right to left + // ========================================================================== + +loc_g_6A64: + dx1 = aniTouchRedDisk; + MovHighByte(&PlayField16[*si], 0x21); + MovHighByte(&PlayField16[*si - 1], 3); + goto loc_StopNoSplit; + + // ========================================================================== + // RED DISK touching up to down + // ========================================================================== + +loc_g_6A80: + dx1 = aniTouchRedDisk; + MovHighByte(&PlayField16[*si], 0x22); + MovHighByte(&PlayField16[*si + FieldWidth], 3); + goto loc_StopNoSplit; + + // ========================================================================== + // RED DISK touching left to right + // ========================================================================== + +loc_g_6A9C: + dx1 = aniTouchRedDisk; + MovHighByte(&PlayField16[*si], 0x23); + MovHighByte(&PlayField16[*si + 1], 3); + +loc_StopNoSplit: + MovingPictureSequencePhase = 0; // stop picture move sequence + goto loc_NoSplit; + + // ========================================================================== + // YELLOW DISK moving down to up + // ========================================================================== + +loc_g_6AB8: + if (PlayField16[*si - 2 * FieldWidth] != 0) + return; + + PlayField16[*si - 2 * FieldWidth] = 0x1200; + dx1 = aniYellowDisk; + dxPos = *si - FieldWidth; + dx2 = (MurphyVarFaceLeft == 0 ? aniPushRight : aniPushLeft); + dx2Step = FieldWidth; + PlayField16[*si] = 0x2403; + subCopyImageToScreen(*si, dx2); + goto loc_MoveNoSplit; + + // ========================================================================== + // YELLOW DISK moving right to left + // ========================================================================== + +loc_g_6AF1: + if (PlayField16[*si - 2] != 0) + return; + + PlayField16[*si - 2] = 0x1200; + subCopyImageToScreen(*si, aniPushLeft); + dx1 = aniYellowDisk; + dxPos = *si - 1; + dx2 = aniPushLeft; + dx2Step = 1; + PlayField16[*si] = 0x2503; + goto loc_MoveNoSplit; + + // ========================================================================== + // YELLOW DISK moving up to down + // ========================================================================== + +loc_g_6B2A: + if (PlayField16[*si + 2 * FieldWidth] != 0) + return; + + PlayField16[*si + 2 * FieldWidth] = 0x1200; + dx1 = aniYellowDisk; + dxPos = *si + FieldWidth; + dx2 = (MurphyVarFaceLeft == 0 ? aniPushRight : aniPushLeft); + dx2Step = -FieldWidth; + PlayField16[*si] = 0x2703; + subCopyImageToScreen(*si, dx2); + goto loc_MoveNoSplit; + + // ========================================================================== + // YELLOW DISK moving left to right + // ========================================================================== + +loc_g_6B63: + if (PlayField16[*si + 2] != 0) + return; + + PlayField16[*si + 2] = 0x1200; + subCopyImageToScreen(*si, aniPushRight); + dx1 = aniYellowDisk; + dxPos = *si + 1; + dx2 = aniPushRight; + dx2Step = -1; + PlayField16[*si] = 0x2603; + goto loc_MoveNoSplit; + + // ========================================================================== + // ORANGE DISK moving right to left + // ========================================================================== + +loc_g_6B9B: + if (PlayField16[*si - 2] != 0) + return; + + PlayField16[*si - 2] = 0x800; + subCopyImageToScreen(*si, aniPushLeft); + dx1 = aniOrangeDisk; + dxPos = *si - 1; + dx2 = aniPushLeft; + dx2Step = 1; + PlayField16[*si] = 0x2803; + goto loc_MoveNoSplit; + + // ========================================================================== + // ORANGE DISK moving left to right + // ========================================================================== + +loc_g_6BD3: + if (PlayField16[*si + 2] != 0) + return; + + if (PlayField16[*si + FieldWidth + 1] == 0) // falling goes before pushing + return; + + PlayField16[*si + 2] = 0x100; + subCopyImageToScreen(*si, aniPushRight); + dx1 = aniOrangeDisk; + dxPos = *si + 1; + dx2 = aniPushRight; + dx2Step = -1; + PlayField16[*si] = 0x2903; + // ========================================================================== + // Copy screen animation action table to action work space + // (To paint sequence: Push Zonk/Disk / release red disk / Port passing) + // ========================================================================== + +loc_MoveNoSplit: + MovingPictureSequencePhase = 8; // init picture move sequence + +loc_NoSplit: + SplitMoveFlag = 0; // no port: no split movement + +loc_Split: + // copy/store global move sequence info???????????????????????????????????? + // ... dont think so ...(FS) + // ========================================================================== + // Proceed with all movements + // ========================================================================== + +locProceedMovingMurphy: // proceed moving murphy + YawnSleepCounter = 0; // Wake up sleeping Murphy + ax = MovingPictureSequencePhase; // sequence busy? + if (ax == 0) // no -- start sequence! + goto loc_g_6C8F; + + ax = ax - 1; // next picture of sequence + MovingPictureSequencePhase = ax; // store for later + + if (ax == 0) // Sound effects + { + switch (HighByte(PlayField16[*si])) + { + case 0xE: + case 0xF: + subSoundFX(*si, fiZonk, actPushing); + break; + + case 0x28: + case 0x29: + subSoundFX(*si, fiOrangeDisk, actPushing); + break; + + case 0x24: + case 0x25: + case 0x26: + case 0x27: + subSoundFX(*si, fiYellowDisk, actPushing); + break; + + default: + break; + } + } + + bl = HighByte(PlayField16[*si]); + if (bl == 0xE) // Push Zonk to left + goto loc_g_6F7E; + + if (bl == 0xF) // Push Zonk to right + goto loc_g_6FBC; + + if (bl == 0x28) // Push orange disk to left + goto loc_g_6FFA; + + if (bl == 0x29) // Push orange disk to right + goto loc_g_7038; + + if (bl == 0x24) // Push yellow disk up + goto loc_g_7076; + + if (bl == 0x25) // Push yellow disk to left + goto loc_g_70B4; + + if (bl == 0x27) // Push yellow disk down + goto loc_g_70F2; + + if (bl == 0x26) // Push yellow disk to right + goto loc_g_7130; + + if (bl == 0x2A) // Red disk release timer + goto loc_g_716E; + + return; + + // ========================================================================== + // Paint frame of MOVING.DAT sequence + // ========================================================================== + +loc_g_6C8F: + +#if 1 + if (SeqPos <= 0) + dx1SequenceLength = getSequenceLength(dx1); +#endif + + if (SplitMoveFlag == 0) + { + // ++++++++++++++++++++++++++ + // Begin of normal movement + MurphyScreenXPos = MurphyScreenXPos + MurphyDX * MurphyZoomFactor; + MurphyScreenYPos = MurphyScreenYPos + MurphyDY * MurphyZoomFactor; + + if (!(ClearPos < 0)) // clear field that murphy is leaving + subCopyImageToScreen(ClearPos, aniSpace); + +#if 0 + // !!! special two-tile animation currently not used !!! + if (dx2 == fiInfotron) // special case of infotron moving left or right + { + tDeltaX = 0; + tDeltaY = 0; + } + else +#endif + { + tDeltaX = MurphyDX * LocalStretch * (SeqPos + 1); + tDeltaY = MurphyDY * LocalStretch * (SeqPos + 1); + } + + X = GetStretchX(dxPos) + tDeltaX; + Y = GetStretchY(dxPos) + tDeltaY; + Tmp = (SeqPos < 0 ? 0 : SeqPos); // 9StepBugFix!(red disk move right) + +#if 1 + if (isSnappingSequence(dx1) && SeqPos == dx1SequenceLength - 1) + dx1 = aniSpace; +#endif + +#if 1 + DDSpriteBuffer_BltImg(X, Y, dx1, Tmp); + GfxGraphic[GetX(*si)][GetY(*si)] = -1; // (Murphy's position) + GfxGraphic[GetX(dxPos)][GetY(dxPos)] = -1; // (snapping position) + // printf("::: Tmp: %d\n", Tmp); +#else + StretchedSprites.BltEx(X, Y, dx[Tmp]); +#endif + + if (!(dx2 < 0)) + { + tPos = dxPos + dx2Step; + X = GetStretchX(tPos); + Y = GetStretchY(tPos); +#if 0 + // !!! special two-tile animation currently not used !!! + if (dx2 == fiInfotron) // special case of infotron moving left or right + { + StretchedSprites.BltEx(X, Y, dx[SeqPos] + dx2Step); + } + else // pushing something +#endif + { + // (SeqPos iterates from 0 to 7 while pushing) + DDSpriteBuffer_BltImg(X + tDeltaX, Y + tDeltaY, dx2, SeqPos); + } + } + + // End of normal movement + // ------------------------ + } + else + { + // ++++++++++++++++++++++++++++++++ + // Begin of split movement (port) + MurphyScreenXPos = MurphyScreenXPos + 2 * MurphyDX * MurphyZoomFactor; + MurphyScreenYPos = MurphyScreenYPos + 2 * MurphyDY * MurphyZoomFactor; + subCopyImageToScreen(ClearPos, aniSpace); // clear the field that murphy leaves + tDeltaX = MurphyDX * LocalStretch * (SeqPos + 1); + tDeltaY = MurphyDY * LocalStretch * (SeqPos + 1); + X = GetStretchX(dxPos) + tDeltaX; + Y = GetStretchY(dxPos) + tDeltaY; + DDSpriteBuffer_BltImg(X, Y, dx1, SeqPos); // plot first murphy + + tPos = dxPos + dx2Step; + X = GetStretchX(tPos); + Y = GetStretchY(tPos); + DDSpriteBuffer_BltImg(X + tDeltaX, Y + tDeltaY, dx1, SeqPos); // plot second murphy + DDSpriteBuffer_BltImg(X, Y, fiGraphic[LowByte(PlayField16[tPos])], 0); // replot the port on top + // End of split movement (port) + // ------------------------------ + } // loc_g_6D1E:'loc_g_6D28: + + SeqPos = SeqPos + 1; +#if 1 + if (SeqPos < dx1SequenceLength) + return; +#else + if (dx[SeqPos] > -1) + return; +#endif + + // Follow-up after movement completed 'loc_g_6D35: + MurphyXPos = MurphyXPos + MurphyDX; + MurphyYPos = MurphyYPos + MurphyDY; + bl = HighByte(PlayField16[*si]); // animation phase + MovHighByte(&PlayField16[*si], 0); + + if (bl == 0x1) // space, moving up + goto loc_g_6EC8; + + if (bl == 0x2) // space, moving left + goto loc_g_6EE6; + + if (bl == 0x3) // space, moving down + goto loc_g_6F04; + + if (bl == 0x4) // space, moving right + goto loc_g_71C4; + + if (bl == 0x5) // base , moving up + goto loc_g_6EC8; + + if (bl == 0x6) // base , moving left -> 6 is not used, value is set to 2 instead of 6! + goto loc_g_6EE6; + + if (bl == 0x7) // base , moving down + goto loc_g_6F04; + + if (bl == 0x8) // base , moving right + goto loc_g_71C4; + + if (bl == 0x9) // infotron, moving up + goto loc_g_6EBA; + + if (bl == 0xA) // infotron, moving left + goto loc_g_6ED8; + + if (bl == 0xB) // infotron, moving down + goto loc_g_6EF6; + + if (bl == 0xC) // infotron, moving right + goto loc_g_71B6; + + if (bl == 0xD) // exit + goto loc_g_6F77; + + if (bl == 0xE) // zonk, pushing left + goto loc_g_6F18; + + if (bl == 0xF) // zonk, pushing right + goto loc_g_6F3B; + + if (bl == 0x10) // base , touching up + goto loc_g_71E2; + + if (bl == 0x11) // base , touching left + goto loc_g_71FE; + + if (bl == 0x12) // base , touching down + goto loc_g_721A; + + if (bl == 0x13) // base , touching right + goto loc_g_7236; + + if (bl == 0x14) // infotron touching up + goto loc_g_71D4; + + if (bl == 0x15) // infotron touching left + goto loc_g_71F0; + + if (bl == 0x16) // infotron touching down + goto loc_g_720C; + + if (bl == 0x17) // infotron touching right + goto loc_g_7228; + + if (bl == 0x18) // port up + goto loc_g_7244; + + if (bl == 0x19) // port left + goto loc_g_7272; + + if (bl == 0x1A) // port down + goto loc_g_729F; + + if (bl == 0x1B) // port right + goto loc_g_72CD; + + if (bl == 0x1C) // red disk, moving up + goto loc_g_72FA; + + if (bl == 0x1D) // red disk, moving left + goto loc_g_7318; + + if (bl == 0x1E) // red disk, moving down + goto loc_g_7333; + + if (bl == 0x1F) // red disk, moving right -> 9-Step-Bug! + goto loc_g_7351; + + if (bl == 0x20) // red disk, touching up + goto loc_g_736C; + + if (bl == 0x21) // red disk, touching left + goto loc_g_7381; + + if (bl == 0x22) // red disk, touching down + goto loc_g_7396; + + if (bl == 0x23) // red disk, touching right + goto loc_g_73AB; + + if (bl == 0x24) // yellow disk, pushing up + goto loc_g_73C0; + + if (bl == 0x25) // yellow disk, pushing left + goto loc_g_73DD; + + if (bl == 0x26) // yellow disk, pushing right -> order of "down" exchanged with "right"! + goto loc_g_7417; + + if (bl == 0x27) // yellow disk, pushing down -> order of "down" exchanged with "right"! + goto loc_g_73FA; + + if (bl == 0x28) // orange disk, pushing left + goto loc_g_7434; + + if (bl == 0x29) // orange disk, pushing right + goto loc_g_7451; + + if (bl == 0x2A) // red disk, release + goto loc_g_747F; + + ExitToMenuFlag = 1; + + return; + + // ========================================================================== + // infotron, moving up + // ========================================================================== + +loc_g_6EBA: + if (0 < LowByte(InfotronsNeeded)) + InfotronsNeeded = InfotronsNeeded - 1; + +loc_g_6EC8: // space, base + PlayField16[*si] = fiMurphy; + subAdjustZonksInfotronsAboveMurphy(*si + FieldWidth); + + return; + + // ========================================================================== + // infotron, moving left + // ========================================================================== + +loc_g_6ED8: + if (0 < LowByte(InfotronsNeeded)) + InfotronsNeeded = InfotronsNeeded - 1; + +loc_g_6EE6: // space, base + PlayField16[*si] = fiMurphy; + subAdjustZonksInfotronsAboveMurphy(*si + 1); + + return; + + // ========================================================================== + // infotron, moving down + // ========================================================================== + +loc_g_6EF6: + if (0 < LowByte(InfotronsNeeded)) + InfotronsNeeded = InfotronsNeeded - 1; + +loc_g_6F04: // space, base + if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion) + PlayField16[*si - FieldWidth] = 0; + + PlayField16[*si] = fiMurphy; + + return; + + // ========================================================================== + // infotron, moving right + // ========================================================================== + +loc_g_71B6: + if (0 < LowByte(InfotronsNeeded)) + InfotronsNeeded = InfotronsNeeded - 1; + +loc_g_71C4: // space, base + subAdjustZonksInfotronsAboveMurphy(*si - 1); + PlayField16[*si] = fiMurphy; + + return; + + // ========================================================================== + // infotron, touching up + // ========================================================================== + +loc_g_71D4: + if (0 < LowByte(InfotronsNeeded)) + InfotronsNeeded = InfotronsNeeded - 1; + +loc_g_71E2: // base + if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion) + PlayField16[*si - FieldWidth] = 0; + + return; + + // ========================================================================== + // infotron, touching left + // ========================================================================== + +loc_g_71F0: + if (0 < LowByte(InfotronsNeeded)) + InfotronsNeeded = InfotronsNeeded - 1; + +loc_g_71FE: // base + if (LowByte(PlayField16[*si - 1]) != fiExplosion) + PlayField16[*si - 1] = 0; + + return; + + // ========================================================================== + // infotron, touching down + // ========================================================================== + +loc_g_720C: + if (0 < LowByte(InfotronsNeeded)) + InfotronsNeeded = InfotronsNeeded - 1; + +loc_g_721A: // base + if (LowByte(PlayField16[*si + FieldWidth]) != fiExplosion) + PlayField16[*si + FieldWidth] = 0; + + return; + + // ========================================================================== + // infotron, touching right + // ========================================================================== + +loc_g_7228: + if (0 < LowByte(InfotronsNeeded)) + InfotronsNeeded = InfotronsNeeded - 1; + +loc_g_7236: // base + if (LowByte(PlayField16[*si + 1]) != fiExplosion) + PlayField16[*si + 1] = 0; + + return; + + // ========================================================================== + // zonk, pushing left + // ========================================================================== + +loc_g_6F18: + if (LowByte(PlayField16[*si]) != fiExplosion) + PlayField16[*si] = 0; + + PlayField16[*si - 1] = fiMurphy; + PlayField16[*si - 2] = fiZonk; + subExplodeSnikSnaksBelow(*si - 2); + *si = *si - 1; + + return; + + // ========================================================================== + // zonk, pushing right + // ========================================================================== + +loc_g_6F3B: + if (LowByte(PlayField16[*si]) != fiExplosion) + PlayField16[*si] = 0; + + PlayField16[*si + 1] = fiMurphy; + PlayField16[*si + 2] = fiZonk; + subExplodeSnikSnaksBelow(*si + 2); + *si = *si + 1; + + return; + + // ========================================================================== + // exit + // ========================================================================== + +loc_g_6F77: + ExitToMenuFlag = 1; + +#if 1 + PlayField16[*si] = fiSpace; // remove Murphy from playfield after exiting +#endif + + return; + + // ========================================================================== + // Push Zonk from right to left + // ========================================================================== + +loc_g_6F7E: + if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiZonk) + return; + + PlayField16[*si] = fiMurphy; // else restore - no more zonk pushing! + PlayField16[*si - 1] = fiZonk; + if (LowByte(PlayField16[*si - 2]) != fiExplosion) + PlayField16[*si - 2] = 0; + + subCopyImageToScreen(*si, aniMurphy); + + return; + + // ========================================================================== + // Push Zonk from left to right + // ========================================================================== + +loc_g_6FBC: + if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiZonk) + return; + + PlayField16[*si] = fiMurphy; // else restore - no more zonk pushing! + PlayField16[*si + 1] = fiZonk; + if (LowByte(PlayField16[*si + 2]) != fiExplosion) + PlayField16[*si + 2] = 0; + + subCopyImageToScreen(*si, aniMurphy); + + return; + + // ========================================================================== + // Push orange disk from right to left + // ========================================================================== + +loc_g_6FFA: + if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiOrangeDisk) + return; + + PlayField16[*si] = fiMurphy; // else restore - no more pushing! + PlayField16[*si - 1] = fiOrangeDisk; + if (LowByte(PlayField16[*si - 2]) != fiExplosion) + PlayField16[*si - 2] = 0; + + subCopyImageToScreen(*si, aniMurphy); + + return; + + // ========================================================================== + // Push orange disk from left to right + // ========================================================================== + +loc_g_7038: + if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiOrangeDisk) + return; + + PlayField16[*si] = fiMurphy; // else restore - no more pushing! + PlayField16[*si + 1] = fiOrangeDisk; + if (LowByte(PlayField16[*si + 2]) != fiExplosion) + PlayField16[*si + 2] = 0; + + subCopyImageToScreen(*si, aniMurphy); + + return; + + // ========================================================================== + // Push yellow disk from down to up + // ========================================================================== + +loc_g_7076: + if (DemoKeyCode == keyUp && PlayField16[*si - FieldWidth] == fiYellowDisk) + return; + + PlayField16[*si] = fiMurphy; // else restore - no more pushing! + PlayField16[*si - FieldWidth] = fiYellowDisk; + if (LowByte(PlayField16[*si - 2 * FieldWidth]) != fiExplosion) + PlayField16[*si - 2 * FieldWidth] = 0; + + subCopyImageToScreen(*si, aniMurphy); + + return; + + // ========================================================================== + // Push yellow disk from right to left + // ========================================================================== + +loc_g_70B4: + if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiYellowDisk) + return; + + PlayField16[*si] = fiMurphy; // else restore - no more pushing! + PlayField16[*si - 1] = fiYellowDisk; + if (LowByte(PlayField16[*si - 2]) != fiExplosion) + PlayField16[*si - 2] = 0; + + subCopyImageToScreen(*si, aniMurphy); + + return; + + // ========================================================================== + // Push yellow disk from up to down + // ========================================================================== + +loc_g_70F2: + if (DemoKeyCode == keyDown && PlayField16[*si + FieldWidth] == fiYellowDisk) + return; + + PlayField16[*si] = fiMurphy; // else restore - no more pushing! + PlayField16[*si + FieldWidth] = fiYellowDisk; + if (LowByte(PlayField16[*si + 2 * FieldWidth]) != fiExplosion) + PlayField16[*si + 2 * FieldWidth] = 0; + + subCopyImageToScreen(*si, aniMurphy); + + return; + + // ========================================================================== + // Push yellow disk from left to right + // ========================================================================== + +loc_g_7130: + if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiYellowDisk) + return; + + PlayField16[*si] = fiMurphy; // else restore - no more pushing! + PlayField16[*si + 1] = fiYellowDisk; + if (LowByte(PlayField16[*si + 2]) != fiExplosion) + PlayField16[*si + 2] = 0; + + subCopyImageToScreen(*si, aniMurphy); + + return; + + // ========================================================================== + // time red disk release (space) + // ========================================================================== + +loc_g_716E: + if (DemoKeyCode != keySpace) + { + PlayField16[*si] = fiMurphy; + subCopyImageToScreen(*si, aniMurphy); + RedDiskReleasePhase = 0; + } + else if (MovingPictureSequencePhase == 0x20) + { + // anxious murphy, dropping red disk + subCopyImageToScreen(*si, aniMurphyDropping); + RedDiskReleasePhase = 1; + } + + return; + + // ========================================================================== + // Special port down to up + // ========================================================================== + +loc_g_7244: + if (LowByte(PlayField16[*si]) != fiExplosion) + PlayField16[*si] = 0; + + PlayField16[*si - 2 * FieldWidth] = fiMurphy; + SplitMoveFlag = 0; + *si = *si - FieldWidth; + if (HighByte(PlayField16[*si]) == 1) + subSpPortTest(*si); + + *si = *si - FieldWidth; + + return; + + // ========================================================================== + // Special port right to left + // ========================================================================== + +loc_g_7272: + if (LowByte(PlayField16[*si]) != fiExplosion) + PlayField16[*si] = 0; + + PlayField16[*si - 2] = fiMurphy; + SplitMoveFlag = 0; + *si = *si - 1; + if (HighByte(PlayField16[*si]) == 1) + subSpPortTest(*si); + + *si = *si - 1; + + return; + + // ========================================================================== + // Special port up to down + // ========================================================================== + +loc_g_729F: + if (LowByte(PlayField16[*si]) != fiExplosion) + PlayField16[*si] = 0; + + PlayField16[*si + 2 * FieldWidth] = fiMurphy; + SplitMoveFlag = 0; + *si = *si + FieldWidth; + if (HighByte(PlayField16[*si]) == 1) + subSpPortTest(*si); + + *si = *si + FieldWidth; + + return; + + // ========================================================================== + // Special port left to right + // ========================================================================== + +loc_g_72CD: + if (LowByte(PlayField16[*si]) != fiExplosion) + PlayField16[*si] = 0; + + PlayField16[*si + 2] = fiMurphy; + SplitMoveFlag = 0; + *si = *si + 1; + if (HighByte(PlayField16[*si]) == 1) + subSpPortTest(*si); + + *si = *si + 1; + + return; + + // ========================================================================== + // Move Red Disk up + // ========================================================================== + +loc_g_72FA: + if (LowByte(PlayField16[*si]) != fiExplosion) + PlayField16[*si] = 0; + + *si = *si - FieldWidth; + PlayField16[*si] = fiMurphy; + subEatRedDisk(*si); // inc+show Murphy's red disks + + return; + + // ========================================================================== + // Move Red Disk left + // ========================================================================== + +loc_g_7318: + if (LowByte(PlayField16[*si + 1]) != fiExplosion) + PlayField16[*si + 1] = 0; + + PlayField16[*si] = fiMurphy; + subEatRedDisk(*si); // inc+show Murphy's red disks + + return; + + // ========================================================================== + // Move Red Disk down + // ========================================================================== + +loc_g_7333: + if (LowByte(PlayField16[*si]) != fiExplosion) + PlayField16[*si] = 0; + + *si = *si + FieldWidth; + PlayField16[*si] = fiMurphy; + subEatRedDisk(*si); // inc+show Murphy's red disks + + return; + + // ========================================================================== + // Move Red Disk right + // ========================================================================== + +loc_g_7351: + if (LowByte(PlayField16[*si - 1]) != fiExplosion) + PlayField16[*si - 1] = 0; + + PlayField16[*si] = fiMurphy; + subEatRedDisk(*si); // inc+show Murphy's red disks + + return; + + // ========================================================================== + // Eat Red Disk up + // ========================================================================== + +loc_g_736C: + if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion) + PlayField16[*si - FieldWidth] = 0; + + subEatRedDisk(*si - FieldWidth); // inc+show Murphy's red disks + + return; + + // ========================================================================== + // Eat Red Disk left + // ========================================================================== + +loc_g_7381: + if (LowByte(PlayField16[*si - 1]) != fiExplosion) + PlayField16[*si - 1] = 0; + + subEatRedDisk(*si - 1); // inc+show Murphy's red disks + + return; + + // ========================================================================== + // Eat Red Disk down + // ========================================================================== + +loc_g_7396: + if (LowByte(PlayField16[*si + FieldWidth]) != fiExplosion) + PlayField16[*si + FieldWidth] = 0; + + subEatRedDisk(*si + FieldWidth); // inc+show Murphy's red disks + + return; + + // ========================================================================== + // Eat Red Disk right + // ========================================================================== + +loc_g_73AB: + if (LowByte(PlayField16[*si + 1]) != fiExplosion) + PlayField16[*si + 1] = 0; + + subEatRedDisk(*si + 1); // inc+show Murphy's red disks + + return; + + // ========================================================================== + // yellow disk, pushing up + // ========================================================================== + +loc_g_73C0: + if (LowByte(PlayField16[*si]) != fiExplosion) + PlayField16[*si] = 0; + + *si = *si - FieldWidth; + PlayField16[*si] = fiMurphy; + PlayField16[*si - FieldWidth] = fiYellowDisk; + + return; + + // ========================================================================== + // yellow disk, pushing left + // ========================================================================== + +loc_g_73DD: + if (LowByte(PlayField16[*si]) != fiExplosion) + PlayField16[*si] = 0; + + *si = *si - 1; + PlayField16[*si] = fiMurphy; + PlayField16[*si - 1] = fiYellowDisk; + + return; + + // ========================================================================== + // yellow disk, pushing down + // ========================================================================== + +loc_g_73FA: + if (LowByte(PlayField16[*si]) != fiExplosion) + PlayField16[*si] = 0; + + *si = *si + FieldWidth; + PlayField16[*si] = fiMurphy; + PlayField16[*si + FieldWidth] = fiYellowDisk; + + return; + + // ========================================================================== + // yellow disk pushing right + // ========================================================================== + +loc_g_7417: + if (LowByte(PlayField16[*si]) != fiExplosion) + PlayField16[*si] = 0; + + *si = *si + 1; + PlayField16[*si] = fiMurphy; + PlayField16[*si + 1] = fiYellowDisk; + + return; + + // ========================================================================== + // orange disk, pushing left + // ========================================================================== + +loc_g_7434: + if (LowByte(PlayField16[*si]) != fiExplosion) + PlayField16[*si] = 0; + + *si = *si - 1; + PlayField16[*si] = fiMurphy; + PlayField16[*si - 1] = fiOrangeDisk; + + return; + + // ========================================================================== + // orange disk, pushing right + // ========================================================================== + +loc_g_7451: + if (LowByte(PlayField16[*si]) != fiExplosion) + PlayField16[*si] = 0; + + *si = *si + 1; + PlayField16[*si] = fiMurphy; + PlayField16[*si + 1] = fiOrangeDisk; + if (PlayField16[*si + FieldWidth + 1] == 0) // make it fall down if below is empty + { + MovHighByte(&PlayField16[*si + 1], 0x20); + MovHighByte(&PlayField16[*si + FieldWidth + 1], fiOrangeDisk); + } + + return; + + // ========================================================================== + // Release a red disk + // ========================================================================== + +loc_g_747F: + PlayField16[*si] = fiMurphy; + RedDiskReleasePhase = 2; + RedDiskCount = RedDiskCount - 1; + + subSoundFX(*si, fiRedDisk, actDropping); +} // subAnimateMurphy + +// ========================================================================== +// SUBROUTINE +// ========================================================================== +void subExplodeSnikSnaksBelow(int si) +{ + int ax; + + ax = LowByte(PlayField16[si + FieldWidth]); + if (ax == 0x11 || ax == 0xBB) + ExplodeFieldSP(si + FieldWidth); +} // subExplodeSnikSnaksBelow + +// ========================================================================== +// SUBROUTINE +// Does pushing against an object kill Murphy? +// ========================================================================== +static boolean subMoveKillsMurphy(int si, int ax, int bl) +{ + static boolean subMoveKillsMurphy; + + int al, ah; + + al = LowByte(ax); + ah = HighByte(ax); + if (ax == 0xFFFF || ax == 0xAAAA || ah == 0) + goto loc_g_752E; + + if (al == fiZonk) + goto loc_g_74E7; + + if (al == fiExplosion) + goto loc_g_7530; + + if (fiOrangeDisk <= al && al <= fiPortUp) + goto loc_g_752E; + + ExplodeFieldSP(si); // Explode + subMoveKillsMurphy = True; + return subMoveKillsMurphy; + +loc_g_74E7: // zonk + if (bl == keyLeft) + goto loc_g_74F6; + + if (bl == keyRight) + goto loc_g_7512; + + ExplodeFieldSP(si); // Explode + subMoveKillsMurphy = True; + return subMoveKillsMurphy; + +loc_g_74F6: // zonk left + ah = ah & 0xF0; + if (! (ah == 0x20 || ah == 0x40 || ah == 0x50 || ah == 0x70)) + ExplodeFieldSP(si); + + subMoveKillsMurphy = True; // Set carry flag + return subMoveKillsMurphy; + +loc_g_7512: // zonk right + ah = ah & 0xF0; + if (! (ah == 0x30 || ah == 0x40 || ah == 0x60 || ah == 0x70)) + ExplodeFieldSP(si); + +loc_g_752E: // Marked fields and Ports + subMoveKillsMurphy = True; // Set carry flag + return subMoveKillsMurphy; + +loc_g_7530: // explosion + if ((ah & 0x80) != 0) + goto loc_g_753A; + + if (ah >= 4) + goto loc_g_753F; + +loc_g_753A: + ExplodeFieldSP(si); // Explode + subMoveKillsMurphy = True; // Set carry flag + return subMoveKillsMurphy; + +loc_g_753F: + PlayField16[si] = 0; + subMoveKillsMurphy = False; + + return subMoveKillsMurphy; +} // subMoveKillsMurphy + +// ========================================================================== +// SUBROUTINE +// Test If si 's a special (grav) port and If so Then fetch new values (see below) +// change conditions to port specs +// The 10-port data base is at data_h_0D28, 10 entries of 6 bytes each: +// (hi),(lo),(gravity),(freeze zonks),(freeze enemies),(unused) +// ========================================================================== + +void subSpPortTest(int si) +{ + int i; + + for (i = 0; i < LInfo.SpecialPortCount; i++) + { + if (LInfo.SpecialPort[i].PortLocation / 2 == si) + { + GravityFlag = LInfo.SpecialPort[i].Gravity; + FreezeZonks = LInfo.SpecialPort[i].FreezeZonks; + SnikSnaksElectronsFrozen = LInfo.SpecialPort[i].FreezeEnemies; + + break; + } + } +} + +void subCopyAnimToScreen(int si, int graphic, int sync_frame) +{ + int X, Y; + + // +++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + DDSpriteBuffer_BltImg(X, Y, graphic, sync_frame); + // +++++++++++++++++++++++++++++++++++++++++ +} + +void subCopyImageToScreen(int si, int graphic) +{ + subCopyAnimToScreen(si, graphic, 0); +} + +static void subEatRedDisk(int si) +{ + if (AllowRedDiskCheat == 0) + { + if (RedDiskReleasePhase != 0) + { + if (RedDiskReleaseMurphyPos == si) + return; + } + } + + RedDiskCount = (RedDiskCount + 1) % 256; +} + +void subAdjustZonksInfotronsAboveMurphy(int si) +{ + int ax; + + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + ax = PlayField16[si - FieldWidth]; + if (ax == 0 || ax == 0x9999) + goto loc_g_15A8; + + if (ax == fiZonk || ax == fiInfotron) + { + MovHighByte(&PlayField16[si - FieldWidth], 0x40); // make falling straigt down + } + + return; + +loc_g_15A8: // empty above + ax = PlayField16[si - FieldWidth - 1]; + if (ax == fiZonk || ax == fiInfotron) + goto loc_g_15C5; + +loc_g_15B6: + ax = PlayField16[si - FieldWidth + 1]; + if (ax == fiZonk || ax == fiInfotron) + goto loc_g_15E8; + + return; + +loc_g_15C5: // zonk/infotron above left + ax = PlayField16[si - 1]; + if (! (ax == fiZonk || ax == fiInfotron || ax == fiRAM)) // continue testing right above + goto loc_g_15B6; + + MovHighByte(&PlayField16[si - FieldWidth - 1], 0x60); // make roll right + PlayField16[si - FieldWidth] = 0x8888; + + return; + +loc_g_15E8: // zonk/infotron above right + ax = PlayField16[si + 1]; + if (ax == fiZonk || ax == fiInfotron || ax == fiRAM) + { + MovHighByte(&PlayField16[si - FieldWidth + 1], 0x50); // make roll left + PlayField16[si - FieldWidth] = 0x8888; + } +} diff --git a/src/game_sp/Murphy.h b/src/game_sp/Murphy.h new file mode 100644 index 00000000..e0d51a35 --- /dev/null +++ b/src/game_sp/Murphy.h @@ -0,0 +1,18 @@ +// ---------------------------------------------------------------------------- +// Murphy.h +// ---------------------------------------------------------------------------- + +#ifndef MURPHY_H +#define MURPHY_H + +#include "global.h" + +extern void subAdjustZonksInfotronsAboveMurphy(int); +extern void subAnimateMurphy(int *); +extern void subCopyFieldToScreen(int, int); +extern void subCopyImageToScreen(int, int); +extern void subCopyAnimToScreen(int, int, int); +extern void subExplodeSnikSnaksBelow(int); +extern void subSpPortTest(int); + +#endif /* MURPHY_H */ diff --git a/src/game_sp/OrangeDisk.c b/src/game_sp/OrangeDisk.c new file mode 100644 index 00000000..dc83e9ea --- /dev/null +++ b/src/game_sp/OrangeDisk.c @@ -0,0 +1,86 @@ +// ---------------------------------------------------------------------------- +// OrangeDisk.c +// ---------------------------------------------------------------------------- + +#include "OrangeDisk.h" + + +// ========================================================================== +// SUBROUTINE +// Animate/move orange disks (falling) +// ========================================================================== + +void subAnimateOrangeDisks(int si) +{ + int ax, bl, dx, X, Y; + + ax = PlayField16[si]; + if (LowByte(ax) != fiOrangeDisk) + return; + + if (ax >= 0x3008) // disk is falling + goto loc_g_2804; + + if (ax >= 0x2008) // disk is in wait state before falling + goto loc_g_27DA; + + if (PlayField16[si + FieldWidth] == 0) + goto loc_g_27CF; + + return; + +loc_g_27CF: // below is empty -> disk may start to fall + MovHighByte(&PlayField16[si], 0x20); + MovHighByte(&PlayField16[si + FieldWidth], fiOrangeDisk); + + return; + +loc_g_27DA: + if (PlayField16[si + FieldWidth] == 0) + { + PlayField16[si] = fiOrangeDisk; + + return; + } // loc_g_27E8: + + bl = HighByte(PlayField16[si]) + 1; + if (bl == 0x22) // wait phase is finished + bl = 0x30; + + MovHighByte(&PlayField16[si], bl); + + return; + +loc_g_2804: // disk is falling + // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + dx = HighByte(PlayField16[si]) & 0x7; + X = GetStretchX(si); + Y = GetStretchY(si); + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X, Y + TwoPixels * (dx + 1), aniOrangeDisk, dx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + bl = HighByte(PlayField16[si]) + 1; + if ((bl & 0x7) != 0) + { + MovHighByte(&PlayField16[si], bl); + + return; + } + + PlayField16[si] = 0; + PlayField16[si + FieldWidth] = fiOrangeDisk; + si = si + FieldWidth; + if (PlayField16[si + FieldWidth] == 0) + { + MovHighByte(&PlayField16[si], 0x30); // go on falling down + MovHighByte(&PlayField16[si + FieldWidth], fiOrangeDisk); + + return; + } // loc_g_2867: + + if (LowByte(PlayField16[si + FieldWidth]) == fiExplosion) + return; + + ExplodeFieldSP(si); // Explode +} diff --git a/src/game_sp/OrangeDisk.h b/src/game_sp/OrangeDisk.h new file mode 100644 index 00000000..410aab4d --- /dev/null +++ b/src/game_sp/OrangeDisk.h @@ -0,0 +1,13 @@ +// ---------------------------------------------------------------------------- +// OrangeDisk.h +// ---------------------------------------------------------------------------- + +#ifndef ORANGEDISK_H +#define ORANGEDISK_H + +#include "global.h" + + +extern void subAnimateOrangeDisks(int); + +#endif /* ORANGEDISK_H */ diff --git a/src/game_sp/SnikSnaks.c b/src/game_sp/SnikSnaks.c new file mode 100644 index 00000000..e23dc902 --- /dev/null +++ b/src/game_sp/SnikSnaks.c @@ -0,0 +1,677 @@ +// ---------------------------------------------------------------------------- +// SnikSnaks.c +// ---------------------------------------------------------------------------- + +#include "SnikSnaks.h" + + +static void subDrawSnikSnakFromAbove(int, int); +static void subDrawSnikSnakFromBelow(int, int); +static void subDrawSnikSnakFromLeft(int, int); +static void subDrawSnikSnakFromRight(int, int); +static void subDrawSnikSnakTurnLeft(int, int); +static void subDrawSnikSnakTurnRight(int, int); +static void subSnikSnakFromAbove(int, int); +static void subSnikSnakFromBelow(int, int); +static void subSnikSnakFromLeft(int, int); +static void subSnikSnakFromRight(int, int); +static void subSnikSnakTurnLeft(int, int); +static void subSnikSnakTurnRight(int, int); + +// static char *VB_Name = "modSnikSnak"; + +// --- Option Explicit +// ========================================================================== +// SUBROUTINE +// Animate/move Snik-Snaks +// ========================================================================== + +void subAnimateSnikSnaks(int si) +{ + int bx, Tmp; + + if (SnikSnaksElectronsFrozen == 1) + return; + +#if 1 + /* (not sure why this was removed -- this broke several level solutions) */ + if (LowByte(PlayField16[si]) != fiSnikSnak) + return; +#endif + + // If LowByte(PlayField16(si)) <> fiSnikSnak Then Exit Function + // Debug.Assert (LowByte(PlayField16[si]) == fiSnikSnak); + + bx = HighByte(PlayField16[si]); + Tmp = bx / 8; + switch (Tmp) + { + case 0: + subSnikSnakTurnLeft(si, bx); // turning, bx=0 -> point N, bx = 1 -> point NW etc. + break; + + case 1: + subSnikSnakTurnRight(si, bx); // turn right + break; + + case 2: + subSnikSnakFromBelow(si, bx); // access si from below + break; + + case 3: + subSnikSnakFromRight(si, bx); // access si from right + break; + + case 4: + subSnikSnakFromAbove(si, bx); // access si from above + break; + + case 5: + subSnikSnakFromLeft(si, bx); // access si from left + break; + + default: + // Debug.Assert(False); + break; + } +} + +void subDrawAnimatedSnikSnaks(int si) +{ + int bx, Tmp; + + // If SnikSnaksElectronsFrozen = 1 Then Exit Function + + if (LowByte(PlayField16[si]) != fiSnikSnak) + return; + + bx = HighByte(PlayField16[si]); + Tmp = bx / 8; + switch (Tmp) + { + case 0: + subDrawSnikSnakTurnLeft(si, bx); // turning, bx=0 -> point N, bx = 1 -> point NW etc. + break; + + case 1: + subDrawSnikSnakTurnRight(si, bx); // turn right + break; + + case 2: + subDrawSnikSnakFromBelow(si, bx); // access si from below + break; + + case 3: + subDrawSnikSnakFromRight(si, bx); // access si from right + break; + + case 4: + subDrawSnikSnakFromAbove(si, bx); // access si from above + break; + + case 5: + subDrawSnikSnakFromLeft(si, bx); // access si from left + break; + } +} + +static void subSnikSnakTurnLeft(int si, int bx) +{ + int ax, ah, bl; + + ax = (TimerVar & 3); + if (ax != 0) + { + if (ax == 3) + goto loc_g_7622; + + return; + } // loc_g_75E0: + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + subDrawSnikSnakTurnLeft(si, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + bx = (bx + 1) & 0x7; + MovHighByte(&PlayField16[si], bx); + + return; + +locMayExplode760A: + ah = HighByte(ax); + if (ah == 0x1B) + return; + + if (ah == 0x19) + return; + + if (ah == 0x18) + return; + + if (ah == 0x1A) + return; + + ExplodeFieldSP(si); // Explode + + return; + +loc_g_7622: + bl = HighByte(PlayField16[si]); + if (bl == 0) + goto loc_g_763B; + + if (bl == 2) + goto loc_g_765E; + + if (bl == 4) + goto loc_g_7681; + + if (bl == 6) + goto loc_g_76A7; + + return; + +loc_g_763B: // pointing up + ax = PlayField16[si - FieldWidth]; + if (ax == 0) // above is empty -> go up + goto loc_g_764E; + + if (LowByte(ax) == fiMurphy) // above is murphy -> explode + goto locMayExplode760A; + + return; + +loc_g_764E: // above is empty -> go up + PlayField16[si] = 0x1BB; + si = si - FieldWidth; + PlayField16[si] = 0x1011; + + return; + +loc_g_765E: // pointing left + ax = PlayField16[si - 1]; + if (ax == 0) // left is empty -> go there + goto loc_g_7671; + + if (LowByte(ax) == fiMurphy) // left is murphy -> explode + goto locMayExplode760A; + + return; + +loc_g_7671: // left is empty -> go there + PlayField16[si] = 0x2BB; + si = si - 1; + PlayField16[si] = 0x1811; + + return; + +loc_g_7681: // pointing down + ax = PlayField16[si + FieldWidth]; + if (ax == 0) // below is empty -> go down + goto loc_g_7697; + + if (LowByte(ax) == fiMurphy) // below is murphy -> explode + goto locMayExplode760A; + + return; + +loc_g_7697: // below is empty -> go down + PlayField16[si] = 0x3BB; + si = si + FieldWidth; + PlayField16[si] = 0x2011; + + return; + +loc_g_76A7: // pointing Right + ax = PlayField16[si + 1]; + if (ax == 0) // right is empty -> go there + goto loc_g_76BD; + + if (LowByte(ax) == fiMurphy) // right is murphy -> explode + goto locMayExplode760A; + + return; + +loc_g_76BD: // right is empty -> go there + PlayField16[si] = 0x4BB; + si = si + 1; + PlayField16[si] = 0x2811; +} + +static void subSnikSnakTurnRight(int si, int bx) +{ + int ax, ah, bl; + + ax = (TimerVar & 3); + if (ax != 0) + { + if (ax == 3) + goto loc_g_771F; + + return; + } // loc_g_76DB: + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + subDrawSnikSnakTurnRight(si, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + bx = ((bx + 1) & 0x7) | 8; + MovHighByte(&PlayField16[si], bx); + + return; + +locMayExplode7707: + ah = HighByte(ax); + if (ah == 0x1B) + return; + + if (ah == 0x19) + return; + + if (ah == 0x18) + return; + + if (ah == 0x1A) + return; + + ExplodeFieldSP(si); // Explode + + return; + +loc_g_771F: + bl = HighByte(PlayField16[si]); + if (bl == 0x8) + goto loc_g_7738; + + if (bl == 0xA) + goto loc_g_77A4; + + if (bl == 0xC) + goto loc_g_777E; + + if (bl == 0xE) + goto loc_g_775B; + + return; + +loc_g_7738: // pointing up + ax = PlayField16[si - FieldWidth]; + if (ax == 0) // above is empty -> go up + goto loc_g_774B; + + if (LowByte(ax) == fiMurphy) // above is murphy -> explode + goto locMayExplode7707; + + return; + +loc_g_774B: // above is empty -> go up + PlayField16[si] = 0x1BB; + si = si - FieldWidth; + PlayField16[si] = 0x1011; + + return; + +loc_g_775B: // pointing left + ax = PlayField16[si - 1]; + if (ax == 0) // left is empty -> go there + goto loc_g_776E; + + if (LowByte(ax) == fiMurphy) // left is murphy -> explode + goto locMayExplode7707; + + return; + +loc_g_776E: // left is empty -> go there + PlayField16[si] = 0x2BB; + si = si - 1; + PlayField16[si] = 0x1811; + + return; + +loc_g_777E: // pointing down + ax = PlayField16[si + FieldWidth]; + if (ax == 0) // below is empty -> go down + goto loc_g_7794; + + if (LowByte(ax) == fiMurphy) // below is murphy -> explode + goto locMayExplode7707; + + return; + +loc_g_7794: // below is empty -> go down + PlayField16[si] = 0x3BB; + si = si + FieldWidth; + PlayField16[si] = 0x2011; + + return; + +loc_g_77A4: // pointing Right + ax = PlayField16[si + 1]; + if (ax == 0) // right is empty -> go there + goto loc_g_77BA; + + if (LowByte(ax) == fiMurphy) // right is murphy -> explode + goto locMayExplode7707; + + return; + +loc_g_77BA: // right is empty -> go there + PlayField16[si] = 0x4BB; + si = si + 1; + PlayField16[si] = 0x2811; +} + +static void subSnikSnakFromBelow(int si, int bx) +{ + int ax, bl; + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + subDrawSnikSnakFromBelow(si, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bx = bx - 0xF; // get and increment sequence# + + bl = LowByte(bx); + if (bl == 7 && LowByte(PlayField16[si + FieldWidth]) != fiExplosion) + { + PlayField16[si + FieldWidth] = 0; // sniknak left that field + } + + if (bl < 8) // sniksnak still goes up + { + bl = bl + 0x10; + MovHighByte(&PlayField16[si], bl); + + return; + } // loc_g_7813 + + PlayField16[si] = 0x11; // sequence#=8 -> arrived at the new field + ax = PlayField16[si - 1]; // check left field + if (ax == 0 || LowByte(ax) == fiMurphy) // check for empty or murphy + { + MovHighByte(&PlayField16[si], 1); // start to turn left + + return; + } // loc_g_7826: and 'loc_g_7833: + + ax = PlayField16[si - FieldWidth]; // cannot turn left -> check above + if (ax == 0) // check if empty + { + PlayField16[si] = 0x1BB; // mark as "sniksnak leaving" + si = si - FieldWidth; // go up! + PlayField16[si] = 0x1011; + + return; + } // loc_g_784A: + + if (LowByte(ax) == fiMurphy) // check for murphy above + { + ExplodeFieldSP(si); // Explode + + return; + } // loc_g_7855: + + ax = PlayField16[si + 1]; // check right field + if (ax == 0 || LowByte(ax) == fiMurphy) // check for empty or murphy + { + MovHighByte(&PlayField16[si], 9); // start to turn right + + return; + } // loc_g_7862: and 'loc_g_786F: + + // else: no way to go, start turning around + MovHighByte(&PlayField16[si], 1); +} + +static void subSnikSnakFromRight(int si, int bx) +{ + int ax, bl; + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + subDrawSnikSnakFromRight(si, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bx = bx - 0x17; // get and increment sequence# + + bl = LowByte(bx); + if (bl == 7 && LowByte(PlayField16[si + 1]) != fiExplosion) + { + PlayField16[si + 1] = 0; // sniknak left that field + } // loc_g_78AC: + + if (bl < 8) // sniksnak still goes left + { + bl = bl + 0x18; + MovHighByte(&PlayField16[si], bl); + + return; + } // loc_g_78B9: + + PlayField16[si] = 0x11; // sequence#=8 -> arrived at the new field + ax = PlayField16[si + FieldWidth]; // check below + if (ax == 0 || LowByte(ax) == fiMurphy) // empty or murphy? + { + MovHighByte(&PlayField16[si], 3); // yes -> turn left down + + return; + } // loc_g_78CC: and 'loc_g_78D9: + + ax = PlayField16[si - 1]; // check left, etc ... see the comments on subSnikSnakFromBelow() + if (ax == 0) + { + PlayField16[si] = 0x2BB; + si = si - 1; // 1 field left + PlayField16[si] = 0x1811; + + return; + } // loc_g_78F0: + + if (LowByte(ax) == fiMurphy) + { + ExplodeFieldSP(si); // Explode + + return; + } // loc_g_78FB: + + ax = PlayField16[si - FieldWidth]; // check above + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 0xF); + + return; + } // loc_g_7908:loc_g_7915: + + MovHighByte(&PlayField16[si], 3); +} + +static void subSnikSnakFromAbove(int si, int bx) +{ + int ax, bl; + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + subDrawSnikSnakFromAbove(si, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bx = bx - 0x1F; // get and increment sequence# + + bl = LowByte(bx); + if (bl == 7 && LowByte(PlayField16[si - FieldWidth]) != fiExplosion) + { + PlayField16[si - FieldWidth] = 0; // sniknak left that field + } + + if (bl < 8) // sniksnak still goes down + { + bl = bl + 0x20; + MovHighByte(&PlayField16[si], bl); + + return; + } // loc_g_7813 + + PlayField16[si] = 0x11; // sequence#=8 -> arrived at the new field + ax = PlayField16[si + 1]; // check right + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 5); + + return; + } // loc_g_7986: + + ax = PlayField16[si + FieldWidth]; // check below + if (ax == 0) + { + PlayField16[si] = 0x3BB; + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x2011; + + return; + } // loc_g_799D: + + if (LowByte(ax) == fiMurphy) + { + ExplodeFieldSP(si); // Explode + + return; + } // loc_g_79A8: + + ax = PlayField16[si - 1]; // check left + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 0xD); + + return; + } // loc_g_79C2: + + MovHighByte(&PlayField16[si], 5); +} + +static void subSnikSnakFromLeft(int si, int bx) +{ + int ax, bl; + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + subDrawSnikSnakFromLeft(si, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bx = bx - 0x27; // get and increment sequence# + + bl = LowByte(bx); + if (bl == 7 && LowByte(PlayField16[si - 1]) != fiExplosion) + { + PlayField16[si - 1] = 0; // sniknak left that field + } + + if (bl < 8) // sniksnak still goes right + { + bl = bl + 0x28; + MovHighByte(&PlayField16[si], bl); + + return; + } // loc_g_78B9: + + PlayField16[si] = 0x11; // sequence#=8 -> arrived at the new field + ax = PlayField16[si - FieldWidth]; // check above + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 7); + + return; + } // loc_g_7A2D: + + ax = PlayField16[si + 1]; // check right(straight on) + if (ax == 0) + { + PlayField16[si] = 0x4BB; + si = si + 1; // 1 field right + PlayField16[si] = 0x2811; + + return; + } // loc_g_7A44: + + if (LowByte(ax) == fiMurphy) + { + ExplodeFieldSP(si); // Explode + + return; + } // loc_g_7A4F: + + ax = PlayField16[si + FieldWidth]; // check below + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 0xB); + + return; + } // loc_g_7A69: + + MovHighByte(&PlayField16[si], 7); +} + +static void subDrawSnikSnakTurnLeft(int si, int bx) +{ + int pos = ((bx + 7) % 8) / 2; + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + GfxGraphic[GetX(si)][GetY(si)] = aniSnikSnakTurningLeft[pos]; + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ +} + +static void subDrawSnikSnakTurnRight(int si, int bx) +{ + int pos = ((bx - 1) % 8) / 2; + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + GfxGraphic[GetX(si)][GetY(si)] = aniSnikSnakTurningRight[pos]; + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ +} + +static void subDrawSnikSnakFromBelow(int si, int bx) +{ + int X, Y; + + bx = bx - 0xF; // get and anti-increment sequence# + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si + FieldWidth); + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X, Y - bx * TwoPixels, aniSnikSnakUp, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ +} + +static void subDrawSnikSnakFromRight(int si, int bx) +{ + int X, Y; + + bx = bx - 0x17; // get and increment sequence# + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si + 1); + Y = GetStretchY(si); + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X - bx * TwoPixels, Y, aniSnikSnakLeft, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ +} + +static void subDrawSnikSnakFromAbove(int si, int bx) +{ + int X, Y; + + bx = bx - 0x1F; // get and increment sequence# + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si - FieldWidth); + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X, Y + bx * TwoPixels, aniSnikSnakDown, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ +} + +static void subDrawSnikSnakFromLeft(int si, int bx) +{ + int X, Y; + + bx = bx - 0x27; // get and increment sequence# + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si - 1); + Y = GetStretchY(si); + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X + bx * TwoPixels, Y, aniSnikSnakRight, bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ +} diff --git a/src/game_sp/SnikSnaks.h b/src/game_sp/SnikSnaks.h new file mode 100644 index 00000000..fd5f9ffe --- /dev/null +++ b/src/game_sp/SnikSnaks.h @@ -0,0 +1,14 @@ +// ---------------------------------------------------------------------------- +// SnikSnaks.h +// ---------------------------------------------------------------------------- + +#ifndef SNIKSNAKS_H +#define SNIKSNAKS_H + +#include "global.h" + + +extern void subAnimateSnikSnaks(int); +extern void subDrawAnimatedSnikSnaks(int); + +#endif /* SNIKSNAKS_H */ diff --git a/src/game_sp/Sound.c b/src/game_sp/Sound.c new file mode 100644 index 00000000..4a79925e --- /dev/null +++ b/src/game_sp/Sound.c @@ -0,0 +1,14 @@ +// ---------------------------------------------------------------------------- +// Sound.c +// ---------------------------------------------------------------------------- + +#include "Sound.h" + + +void subSoundFX(int si, int element, int action) +{ + int x = GetX(si); + int y = GetY(si); + + PlayLevelSound_SP(x, y, element, action); +} diff --git a/src/game_sp/Sound.h b/src/game_sp/Sound.h new file mode 100644 index 00000000..f4ca0f4b --- /dev/null +++ b/src/game_sp/Sound.h @@ -0,0 +1,13 @@ +// ---------------------------------------------------------------------------- +// Sound.h +// ---------------------------------------------------------------------------- + +#ifndef GAME_SP_SOUND_H +#define GAME_SP_SOUND_H + +#include "global.h" + + +extern void subSoundFX(int, int, int); + +#endif /* GAME_SP_SOUND_H */ diff --git a/src/game_sp/Zonk.c b/src/game_sp/Zonk.c new file mode 100644 index 00000000..d8285345 --- /dev/null +++ b/src/game_sp/Zonk.c @@ -0,0 +1,485 @@ +// ---------------------------------------------------------------------------- +// Zonk.c +// ---------------------------------------------------------------------------- + +#include "Zonk.h" + + +void subCleanUpForZonksAbove(int si); + + +// static char *VB_Name = "modZonk"; +// --- Option Explicit + +// ========================================================================== +// SUBROUTINE +// Animate Zonks (falling) +// ========================================================================== + +void subAnimateZonks(int si) +{ + int tFld; + + // PseudoRegisters: + // int ax, bx, cx, dx, di, X, Y; + int ax, bx, dx, X, Y; + // int ah, bh, ch, dh, al, bl, cl, dl; + int al, bl; + + tFld = PlayField16[si]; + if ((tFld & 0xFF) != fiZonk) + return; + + if (tFld == fiZonk) + { + if (FreezeZonks == 2) // Do Zonks fall? (debug) + return; + + ax = PlayField16[si + FieldWidth]; // select case playfield16(si+60) + if (ax == 0) + goto loc_g_0D64; + + if (ax == fiZonk) + goto loc_g_0D35; + + if (ax == fiInfotron) + goto loc_g_0D35; + + if (ax == fiRAM) + goto loc_g_0D35; + + return; + +loc_g_0D35: // Case fiZonk, fiInfotron, fiRAM + ax = PlayField16[si + FieldWidth - 1]; + if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) + goto loc_g_0D6B; + +loc_g_0D4C: + ax = PlayField16[si + FieldWidth + 1]; + if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) + goto loc_g_0D81; + + return; + +loc_g_0D64: // Case fiSpace + MovHighByte(&PlayField16[si], 0x40); + goto loc_g_0DA5; + +loc_g_0D6B: // roll left? + if (PlayField16[si - 1] == 0) + goto loc_g_0D74; + + goto loc_g_0D4C; + +loc_g_0D74: + MovHighByte(&PlayField16[si], 0x50); + PlayField16[si - 1] = 0x8888; + goto loc_g_0DA5; + +loc_g_0D81: // roll right? + if (PlayField16[si + 1] == 0) + goto loc_g_0D98; + + if (PlayField16[si + 1] != 0x9999) // wow right is different from left! + return; + + if (LowByte(PlayField16[si - FieldWidth + 1]) != 1) + return; + +loc_g_0D98: + MovHighByte(&PlayField16[si], 0x60); + PlayField16[si + 1] = 0x8888; + } // tFld = fiZonk + +loc_g_0DA5: + // from now on the zonk is definitely moving, + // maybe the sequence is in an advanced frame + // or just beeing initialized due to the code above + bl = HighByte(PlayField16[si]); + bx = 0; + MovLowByte(&bx, bl); + al = bl & 0xF0; + if (al == 0x10) // zonk comes falling from above + goto loc_g_0DE8; + + if (al == 0x20) // zonk comes rolling from right to left + goto loc_g_0F83; + + if (al == 0x30) // zonk comes rolling from left to right + goto loc_g_0FE8; + + if (FreezeZonks == 2) + return; + + if (al == 0x40) // zonk falls straight down + goto loc_g_104D; + + if (al == 0x50) // zonk rolls left + goto loc_g_107B; + + if (al == 0x60) // zonk rolls right + goto loc_g_10E9; + + if (al == 0x70) // intermediate state + goto loc_g_1157; + + return; + +loc_g_0DE8: // zonk comes falling from above + // To Do: draw zonk falling from above + // according to position in (bl And &H07) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si - FieldWidth); + dx = bl & 0x7; + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X, Y + TwoPixels * (dx + 1), aniZonk, dx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + bl = HighByte(PlayField16[si]) + 1; + if (bl == 0x16) + { + MovHighByte(&PlayField16[si], bl); + subCleanUpForZonksAbove(si - FieldWidth); + return; + } // loc_g_0E2B: + + if (bl < 0x18) + { + MovHighByte(&PlayField16[si], bl); + return; + } // loc_g_0E35: + + MovHighByte(&PlayField16[si], 0); // zonk arrived at the field + if ((FreezeZonks & 0xFF) == 2) + return; + + // loc_g_0E42: // now check if the zonk may go on falling somehow + ax = PlayField16[si + FieldWidth]; + if (ax == 0) // below is empty!-> go on falling 'loc_g_0E4C: + goto loc_g_0EDD; + + if (ax == 0x9999) // below is only temporarily used ' loc_g_0E57: + goto loc_g_0EDD; + + if ((ax & 0xFF) == fiMurphy) // Murphy dies 'loc_g_0E61: + goto loc_g_0F14; + + if ((ax & 0xFF) == fiSnikSnak) // SnikSnak dies 'loc_g_0E6B: + goto loc_g_0F6E; + + if (ax == 0x2BB) // loc_g_0E76: + goto loc_g_0F36; + + if (ax == 0x4BB) // loc_g_0E81: + goto loc_g_0F52; + + if ((ax & 0xFF) == fiElectron) // Electron cracked! 'loc_g_0E8B: + goto loc_g_0F6E; + + if (ax == fiOrangeDisk) // OrangeDisk explodes 'loc_g_0E95: + goto loc_g_0F75; + +#if 1 + // play the zonk sound, 'cause zonk hits something "hard" + subSoundFX(si, fiZonk, actImpact); +#else + subSoundFXZonk(); // play the zonk sound,'cause zonk hits something "hard" +#endif + + if (! (ax == fiZonk || ax == fiInfotron || ax == fiRAM)) + return; + + // loc_g_0EAE: ' Zonk rolls somewhere + ax = PlayField16[si + FieldWidth - 1]; + if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) // may roll left + goto loc_g_0EEA; + + ax = PlayField16[si + FieldWidth + 1]; + if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) // may roll right + goto loc_g_0F00; + + return; + +loc_g_0EDD: // go on falling down? + PlayField16[si] = 0x7001; // go into intermediate waitstate + PlayField16[si + FieldWidth] = 0x9999; // mark as "zonk waiting to access" + return; + +loc_g_0EEA: // test if zonk may roll left + // This if(if true) jumps up far above + // to the according rountine for fixed zonks! + if (PlayField16[si - 1] != 0) // Remarkable!!! ' loc_g_0EF4: + goto loc_g_0D4C; + + MovHighByte(&PlayField16[si], 0x50); // zonk rolls left + PlayField16[si - 1] = 0x8888; // mark as zonk accessing? + return; + +loc_g_0F00: // test if zonk may roll right + if (PlayField16[si + 1] != 0) // loc_g_0F08: + return; + + MovHighByte(&PlayField16[si], 0x60); // zonk rolls right + PlayField16[si + 1] = 0x8888; // mark as zonk accessing? + return; + +loc_g_0F14: // Murphy dies, but not in any case + bl = HighByte(PlayField16[si + FieldWidth]); + if (bl == 0xE || bl == 0xF || bl == 0x28) + return; + + if (bl == 0x29 || bl == 0x25 || bl == 0x26) + return; + +loc_g_0F36: // ?? + ax = LowByte(PlayField16[si + FieldWidth - 1]); + if (ax == fiElectron) // loc_g_0F43: + PlayField16[si + FieldWidth] = fiElectron; + + if (ax != 0x1F) + PlayField16[si + FieldWidth - 1] = 0; + + goto loc_g_0F6E; + +loc_g_0F52: // ?? + ax = LowByte(PlayField16[si + FieldWidth + 1]); + if (ax == fiElectron) // loc_g_0F5F: + PlayField16[si + FieldWidth] = fiElectron; + + if (ax != 0x1F) + PlayField16[si + FieldWidth + 1] = 0; + + goto loc_g_0F6E; + +loc_g_0F6E: // someone dies/explodes + si = si + FieldWidth; // 1 field down + ExplodeFieldSP(si); // Explode + return; + +loc_g_0F75: // OrangeDisk explodes next cycle + si = si + FieldWidth; // 1 field down + PlayField8[si] = fiHardWare; + return; + +loc_g_0F83: // zonk comes rolling from right to left + // To Do: draw zonk rolling from right + // according to position in (bl And &H07) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si + 1); + Y = GetStretchY(si); + dx = (bl & 0x7) + 1; + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X - (TwoPixels * dx), Y, aniZonkRollLeft, dx - 1); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + bl = HighByte(PlayField16[si]) + 1; // get and increment sequence# + if (bl == 0x24) + PlayField16[si + 1] = 0xAAAA; + + if (bl == 0x26) + { + MovHighByte(&PlayField16[si], bl); + subCleanUpForZonksAbove(si + 1); + } + else if (bl < 0x28) + { + MovHighByte(&PlayField16[si], bl); + } + else + { + PlayField16[si] = 0xFFFF; + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x1001; // convert rolling zonk to a falling zonk + } + + return; + +loc_g_0FE8: // zonk comes rolling from left to right + // To Do: draw zonk rolling from left + // according to position in (bl And &H07) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si - 1); + Y = GetStretchY(si); + dx = (bl & 0x7) + 1; + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X + (TwoPixels * dx), Y, aniZonkRollRight, dx - 1); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + bl = HighByte(PlayField16[si]) + 1; + if (bl == 0x34) + PlayField16[si - 1] = 0xAAAA; + + if (bl == 0x36) + { + MovHighByte(&PlayField16[si], bl); + subCleanUpForZonksAbove(si - 1); + } + else if (bl < 0x38) + { + MovHighByte(&PlayField16[si], bl); + } + else + { + PlayField16[si] = 0xFFFF; + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x1001; // convert rolling zonk to a falling zonk + } + + return; + +loc_g_104D: // zonk falls straight down + bl = bl + 1; + if (bl < 0x42) + { + MovHighByte(&PlayField16[si], bl); + } + else if (PlayField16[si + FieldWidth] != 0) + { + bl = bl - 1; // stay waiting + MovHighByte(&PlayField16[si], bl); + } + else + { + PlayField16[si] = 0xFFFF; // mark as "zonk leaving" + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x1001; // go falling + } + + return; + +loc_g_107B: // zonk rolls left + // To Do: draw zonk rolling to left + // according to position in (bl And &H0F) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + dx = (bl & 0xF) + 1; + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X - (TwoPixels * dx), Y, aniZonkRollLeft, dx - 1); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + bl = HighByte(PlayField16[si]) + 1; // retrieve and increment sequence# + if (bl < 0x52) + { + MovHighByte(&PlayField16[si], bl); + return; + } + + if (PlayField16[si + FieldWidth - 1] != 0) + goto loc_g_10E2; + + if (PlayField16[si - 1] != 0) + { + if (PlayField16[si - 1] != 0x8888) + goto loc_g_10E2; + } // loc_g_10C8: + + PlayField16[si] = 0xFFFF; + si = si - 1; // 1 field left + PlayField16[si] = 0x2201; + PlayField16[si + FieldWidth] = 0xFFFF; + return; + +loc_g_10E2: // stay waiting + bl = bl - 1; + MovHighByte(&PlayField16[si], bl); + return; + +loc_g_10E9: // zonk rolls right + // To Do: draw zonk rolling to right + // according to position in (bl And &H07) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + dx = (bl & 0x7) + 1; + DDSpriteBuffer_BltImg(X, Y, aniSpace, 0); + DDSpriteBuffer_BltImg(X + (TwoPixels * dx), Y, aniZonkRollRight, dx - 1); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + bl = HighByte(PlayField16[si]) + 1; + if (bl < 0x62) + { + MovHighByte(&PlayField16[si], bl); + return; + } + + if (PlayField16[si + FieldWidth + 1] != 0) + goto loc_g_1150; + + if (PlayField16[si + 1] != 0) + { + if (PlayField16[si + 1] != 0x8888) + goto loc_g_1150; + } + + PlayField16[si] = 0xFFFF; + si = si + 1; + PlayField16[si] = 0x3201; + PlayField16[si + FieldWidth] = 0xFFFF; + return; + +loc_g_1150: // stay waiting + bl = bl - 1; + MovHighByte(&PlayField16[si], bl); + return; + +loc_g_1157: // intermediate state + ax = PlayField16[si + FieldWidth]; + if (ax == 0 || ax == 0x9999) + { + PlayField16[si] = 0xFFFF; + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x1001; // start falling down + goto loc_g_0DE8; + } + + return; +} // subAnimateZonks endp + +void subCleanUpForZonksAbove(int si) +{ + int ax; + + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + if (PlayField16[si - FieldWidth] != 0) + { + if (PlayField16[si - FieldWidth] != 0x9999) + return; + + if (LowByte(PlayField16[si - 2 * FieldWidth]) != fiInfotron) + return; + } // loc_g_1674: + + if (PlayField16[si - FieldWidth - 1] != fiZonk) + { + if (PlayField16[si - FieldWidth + 1] != fiZonk) + return; + + goto loc_g_16A7; + } + + ax = PlayField16[si - 1]; + if (ax == fiZonk || ax == fiInfotron || ax == fiRAM) + { + PlayField16[si - FieldWidth - 1] = 0x6001; + PlayField16[si - FieldWidth] = 0x8888; + return; + } + + if (PlayField16[si - FieldWidth + 1] != fiZonk) + return; + +loc_g_16A7: + ax = PlayField16[si + 1]; + if (ax == fiZonk || ax == fiInfotron || ax == fiRAM) + { + PlayField16[si - FieldWidth + 1] = 0x5001; + PlayField16[si - FieldWidth] = 0x8888; + } + + return; +} // subCleanUpForZonksAbove diff --git a/src/game_sp/Zonk.h b/src/game_sp/Zonk.h new file mode 100644 index 00000000..e99ab018 --- /dev/null +++ b/src/game_sp/Zonk.h @@ -0,0 +1,12 @@ +// ---------------------------------------------------------------------------- +// Zonk.h +// ---------------------------------------------------------------------------- + +#ifndef ZONK_H +#define ZONK_H + +#include "global.h" + +extern void subAnimateZonks(int si); + +#endif /* ZONK_H */ diff --git a/src/game_sp/export.h b/src/game_sp/export.h new file mode 100644 index 00000000..fe5995fd --- /dev/null +++ b/src/game_sp/export.h @@ -0,0 +1,212 @@ +#ifndef GAME_SP_EXPORT_H +#define GAME_SP_EXPORT_H + +/* ========================================================================= */ +/* functions and definitions exported from game_sp to main program */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* constant definitions */ +/* ------------------------------------------------------------------------- */ + +#define SP_MAX_PLAYFIELD_WIDTH MAX_PLAYFIELD_WIDTH +#define SP_MAX_PLAYFIELD_HEIGHT MAX_PLAYFIELD_HEIGHT + +#define SP_NUM_LEVELS_PER_PACKAGE 111 + +#define SP_STD_PLAYFIELD_WIDTH 60 +#define SP_STD_PLAYFIELD_HEIGHT 24 +#define SP_LEVEL_NAME_LEN 23 +#define SP_MAX_SPECIAL_PORTS 10 + +#define SP_HEADER_SIZE 96 +#define SP_STD_PLAYFIELD_SIZE (SP_STD_PLAYFIELD_WIDTH * \ + SP_STD_PLAYFIELD_HEIGHT) +#define SP_MAX_PLAYFIELD_SIZE (SP_MAX_PLAYFIELD_WIDTH * \ + SP_MAX_PLAYFIELD_HEIGHT) +#define SP_STD_LEVEL_SIZE (SP_HEADER_SIZE + SP_STD_PLAYFIELD_SIZE) + +#if 0 +#define SP_SCREEN_BUFFER_XSIZE (SCR_FIELDX + 2) +#define SP_SCREEN_BUFFER_YSIZE (SCR_FIELDY + 2) +#endif + +#define SP_FRAMES_PER_SECOND 35 +#define SP_MAX_TAPE_LEN 64010 /* (see "spfix63.doc") */ + + +/* sound actions */ + +#define actActive 0 +#define actImpact 1 +#define actExploding 2 +#define actDigging 3 +#define actSnapping 4 +#define actCollecting 5 +#define actPassing 6 +#define actPushing 7 +#define actDropping 8 + + +/* ------------------------------------------------------------------------- */ +/* data structure definitions */ +/* ------------------------------------------------------------------------- */ + +#ifndef HAS_SpecialPortType +typedef struct +{ +#if 1 + short PortLocation; // = 2*(x+(y*60)) /* big endian format */ +#else + int PortLocation; // = 2*(x+(y*60)) +#endif + byte Gravity; // 1 = turn on, anything else (0) = turn off + byte FreezeZonks; // 2 = turn on, anything else (0) = turn off (1=off!) + byte FreezeEnemies; // 1 = turn on, anything else (0) = turn off + byte UnUsed; +} SpecialPortType; +#define HAS_SpecialPortType +#endif + +#ifndef HAS_LevelInfoType +typedef struct +{ + byte UnUsed[4]; + byte InitialGravity; // 1=on, anything else (0) = off + byte Version; // SpeedFixVersion XOR &H20 + char LevelTitle[23]; + byte InitialFreezeZonks; // 2=on, anything else (0) = off. (1=off too!) + byte InfotronsNeeded; + + // Number of Infotrons needed. 0 means that Supaplex will count the total + // amount of Infotrons in the level, and use the low byte of that number. + // (A multiple of 256 Infotrons will then result in 0-to-eat, etc.!) + byte SpecialPortCount; // Maximum 10 allowed! + SpecialPortType SpecialPort[10]; + byte SpeedByte; // = Speed XOR Highbyte(RandomSeed) + byte CheckSumByte; // = CheckSum XOR SpeedByte +#if 1 + short DemoRandomSeed; /* little endian format */ +#else + int DemoRandomSeed; +#endif +} LevelInfoType; +#define HAS_LevelInfoType +#endif + +struct GlobalInfo_SP +{ +}; + +struct GameInfo_SP +{ + boolean LevelSolved; + boolean GameOver; + + /* needed for updating panel */ + int time_played; + int infotrons_still_needed; + int red_disk_count; + int score; + + /* needed for engine snapshots */ + int preceding_buffer_size; + + int scroll_xoffset, scroll_yoffset; +}; + +struct DemoInfo_SP +{ + boolean is_available; /* structure contains valid demo */ + + int level_nr; /* number of corresponding level */ + + int length; /* number of demo entries */ + byte data[SP_MAX_TAPE_LEN]; /* array of demo entries */ +}; + +struct LevelInfo_SP +{ + LevelInfoType header; + byte header_raw_bytes[SP_HEADER_SIZE]; + + int width, height; + + byte playfield[SP_MAX_PLAYFIELD_WIDTH][SP_MAX_PLAYFIELD_HEIGHT]; + + struct DemoInfo_SP demo; + + /* used for runtime values */ + struct GameInfo_SP *game_sp; +}; + +struct GraphicInfo_SP +{ + Bitmap *bitmap; + int src_x, src_y; + int src_offset_x, src_offset_y; + int dst_offset_x, dst_offset_y; + int width, height; + + Bitmap *crumbled_bitmap; + int crumbled_src_x, crumbled_src_y; + int crumbled_border_size; + + boolean has_crumbled_graphics; + boolean preserve_background; + + int unique_identifier; /* used to identify needed screen updates */ +}; + +struct EngineSnapshotInfo_SP +{ + struct GameInfo_SP game_sp; + + int PlayField16[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE]; + byte PlayField8[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE]; + byte DisPlayField[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE]; + + int AnimationPosTable[SP_MAX_PLAYFIELD_SIZE]; + byte AnimationSubTable[SP_MAX_PLAYFIELD_SIZE]; + byte TerminalState[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE]; +}; + + +/* ------------------------------------------------------------------------- */ +/* exported functions */ +/* ------------------------------------------------------------------------- */ + +extern struct GlobalInfo_SP global_sp_info; +extern struct GameInfo_SP game_sp; +extern struct LevelInfo_SP native_sp_level; +extern struct GraphicInfo_SP graphic_info_sp_object[TILE_MAX][8]; +extern struct GraphicInfo_SP graphic_info_sp_player[MAX_PLAYERS][SPR_MAX][8]; +extern struct EngineSnapshotInfo_SP engine_snapshot_sp; + +extern void sp_open_all(); +extern void sp_close_all(); + +extern void InitGfxBuffers_SP(); + +extern void InitGameEngine_SP(); +extern void GameActions_SP(byte *, boolean); + +extern unsigned int InitEngineRandom_SP(long); + +extern void setLevelInfoToDefaults_SP(); +extern void copyInternalEngineVars_SP(); +extern boolean LoadNativeLevel_SP(char *, int); +extern void SaveNativeLevel_SP(char *); + +extern void BackToFront_SP(void); +extern void BlitScreenToBitmap_SP(Bitmap *); +extern void RedrawPlayfield_SP(boolean); +extern void DrawGameDoorValues_SP(); + +extern void LoadEngineSnapshotValues_SP(); +extern void SaveEngineSnapshotValues_SP(); + +extern int map_key_RND_to_SP(int); +extern int map_key_SP_to_RND(int); + +#endif /* GAME_SP_EXPORT_H */ diff --git a/src/game_sp/file.c b/src/game_sp/file.c new file mode 100644 index 00000000..f841cf20 --- /dev/null +++ b/src/game_sp/file.c @@ -0,0 +1,660 @@ + +#include "main_sp.h" +#include "global.h" + + +/* ------------------------------------------------------------------------- */ +/* functions for loading Supaplex level */ +/* ------------------------------------------------------------------------- */ + +void setTapeInfoToDefaults_SP() +{ + native_sp_level.demo.is_available = FALSE; + native_sp_level.demo.length = 0; +} + +void setLevelInfoToDefaults_SP() +{ + LevelInfoType *header = &native_sp_level.header; + char *empty_title = "-------- EMPTY --------"; + int i, x, y; + + native_sp_level.game_sp = &game_sp; + + native_sp_level.width = SP_STD_PLAYFIELD_WIDTH; + native_sp_level.height = SP_STD_PLAYFIELD_HEIGHT; + + for (x = 0; x < native_sp_level.width; x++) + for (y = 0; y < native_sp_level.height; y++) + native_sp_level.playfield[x][y] = fiSpace; + + /* copy string (without terminating '\0' character!) */ + for (i = 0; i < SP_LEVEL_NAME_LEN; i++) + header->LevelTitle[i] = empty_title[i]; + + header->InitialGravity = 0; + header->Version = 0; + header->InitialFreezeZonks = 0; + header->InfotronsNeeded = 0; + header->SpecialPortCount = 0; + header->SpeedByte = 0; + header->CheckSumByte = 0; + header->DemoRandomSeed = 0; + + for (i = 0; i < SP_MAX_SPECIAL_PORTS; i++) + { + SpecialPortType *port = &header->SpecialPort[i]; + + port->PortLocation = 0; + port->Gravity = 0; + port->FreezeZonks = 0; + port->FreezeEnemies = 0; + } + + /* set raw header bytes (used for subsequent buffer zone) to "hardware" */ + for (i = 0; i < SP_HEADER_SIZE; i++) + native_sp_level.header_raw_bytes[i] = 0x20; + + setTapeInfoToDefaults_SP(); +} + +void copyInternalEngineVars_SP() +{ + char *preceding_playfield_memory[] = + { + "95 89 95 89 95 89 3b 8a 3b 8a 3b 8a 3b 8a 3b 8a", // |......;.;.;.;.;.| + "3b 8a 3b 8a 3b 8a e8 8a e8 8a e8 8a e8 8a e8 8a", // |;.;.;.è.è.è.è.è.| + "e8 8a e8 8a e8 8a b1 8b b1 8b b1 8b b1 8b b1 8b", // |è.è.è.±.±.±.±.±.| + "b1 8b b1 8b b1 8b 85 8c 85 8c 85 8c 85 8c 85 8c", // |±.±.±...........| + "85 8c 85 8c 85 8c 5b 8d 5b 8d 5b 8d 5b 8d 5b 8d", // |......[.[.[.[.[.| + "5b 8d 5b 8d 5b 8d 06 8e 06 8e 06 8e 06 8e 06 8e", // |[.[.[...........| + "06 8e 06 8e 06 8e ac 8e ac 8e ac 8e ac 8e ac 8e", // |......¬.¬.¬.¬.¬.| + "ac 8e ac 8e ac 8e 59 8f 59 8f 59 8f 59 8f 59 8f", // |¬.¬.¬.Y.Y.Y.Y.Y.| + "59 8f 59 8f 59 8f 00 00 70 13 00 00 00 00 e8 17", // |Y.Y.Y...p.....è.| + "00 00 00 00 00 00 69 38 00 00 00 00 00 00 00 00", // |......i8........| + "00 00 00 00 00 00 00 00 d0 86 00 00 b2 34 00 00", // |........Ð...²4..| + "00 00 00 00 00 00 8f 8b 1d 34 00 00 00 00 00 00", // |.........4......| + "00 00 00 00 23 39 09 09 00 0c 00 08 00 58 00 00", // |....#9.......X..| + "00 00 00 25 77 06 7f 00 00 00 01 00 00 00 00 00", // |...%w...........| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 ec 06 26 05 00 00 00", // |.........ì.&....| + "00 00 00 01 00 00 00 00 31 32 33 34 35 36 37 38", // |........12345678| + "39 30 2d 00 08 00 51 57 45 52 54 59 55 49 4f 50", // |90-...QWERTYUIOP| + "00 00 0a 00 41 53 44 46 47 48 4a 4b 4c 00 00 00", // |....ASDFGHJKL...| + "00 00 5a 58 43 56 42 4e 4d 00 00 00 00 00 00 20", // |..ZXCVBNM...... | + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 2e 00 1e 00 31 00 14 00 39 00", // |..........1...9.| + "1f 00 14 00 18 00 ff ff 01 00 01 4c 45 56 45 4c", // |......ÿÿ...LEVEL| + "53 2e 44 41 54 00 00 00 00 00 00 00 00 00 00 00", // |S.DAT...........| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", // |................| + + NULL + }; + int preceding_buffer_size = 0; + int count; + int i, x, y; + + for (i = 0; preceding_playfield_memory[i] != NULL; i++) + preceding_buffer_size += 8; /* eight 16-bit integer values */ + + /* needed for engine snapshots */ + game_sp.preceding_buffer_size = preceding_buffer_size; + + LInfo = native_sp_level.header; + + FieldWidth = native_sp_level.width; + FieldHeight = native_sp_level.height; + HeaderSize = 96; + + FieldMax = (FieldWidth * FieldHeight) + HeaderSize - 1; + LevelMax = (FieldWidth * FieldHeight) - 1; + + /* (add one byte for the level number stored as first byte of demo data) */ + FileMax = FieldMax + native_sp_level.demo.length + 1; + +#if 0 + PlayField8 = REDIM_1D(sizeof(byte), 0, FileMax); + DisPlayField = REDIM_1D(sizeof(byte), 0, FieldMax); + PlayField16 = REDIM_1D(sizeof(int), -preceding_buffer_size, FieldMax); +#endif + + count = 0; + for (i = 0; preceding_playfield_memory[i] != NULL; i++) + { + char *s = preceding_playfield_memory[i]; + boolean hi_byte = FALSE; /* little endian data => start with low byte */ + + while (s[0] != '\0' && s[1] != '\0') + { + int hi_nibble = s[0] - (s[0] > '9' ? 'a' - 10 : '0'); + int lo_nibble = s[1] - (s[1] > '9' ? 'a' - 10 : '0'); + int byte = (hi_nibble << 4) | lo_nibble; + + if (hi_byte) + byte <<= 8; + + PlayField16[-preceding_buffer_size + count] |= byte; + + if (hi_byte) + count++; + + hi_byte = !hi_byte; + + s += 2; + + while (*s == ' ') + s++; + } + } + + count = 0; + for (y = 0; y < native_sp_level.height; y++) + for (x = 0; x < native_sp_level.width; x++) + PlayField8[count++] = native_sp_level.playfield[x][y]; + + /* add raw header bytes to subsequent playfield buffer zone */ + for (i = 0; i < SP_HEADER_SIZE; i++) + PlayField8[count++] = native_sp_level.header_raw_bytes[i]; + + for (i = 0; i < count; i++) + { + PlayField16[i] = PlayField8[i]; + DisPlayField[i] = PlayField8[i]; + PlayField8[i] = 0; + } + + if (native_sp_level.demo.is_available) + { + DemoAvailable = True; + +#if 0 + /* !!! NEVER USED !!! */ + PlayField8[FieldMax + 1] = native_sp_level.demo.level_nr; + + /* !!! NEVER USED !!! */ + for (i = 0; i < native_sp_level.demo.length; i++) + PlayField8[FieldMax + 2 + i] = native_sp_level.demo.data[i]; +#endif + } + +#if 0 + AnimationPosTable = REDIM_1D(sizeof(int), 0, LevelMax - 2 * FieldWidth); + AnimationSubTable = REDIM_1D(sizeof(byte), 0, LevelMax - 2 * FieldWidth); + TerminalState = REDIM_1D(sizeof(byte), 0, FieldMax); +#endif + + GravityFlag = LInfo.InitialGravity; + FreezeZonks = LInfo.InitialFreezeZonks; + +#if 1 + /* this is set by main game tape code to native random generator directly */ +#else + RandomSeed = LInfo.DemoRandomSeed; +#endif + + LevelLoaded = True; +} + +static void LoadNativeLevelFromFileStream_SP(FILE *file, int width, int height, + boolean demo_available) +{ + LevelInfoType *header = &native_sp_level.header; + int i, x, y; + + /* for details of the Supaplex level format, see Herman Perk's Supaplex + documentation file "SPFIX63.DOC" from his Supaplex "SpeedFix" package */ + + native_sp_level.width = MIN(width, SP_MAX_PLAYFIELD_WIDTH); + native_sp_level.height = MIN(height, SP_MAX_PLAYFIELD_HEIGHT); + + /* read level playfield (width * height == 60 * 24 tiles == 1440 bytes) */ + /* (MPX levels may have non-standard playfield size -- check max. size) */ + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + byte element = getFile8Bit(file); + + if (x < SP_MAX_PLAYFIELD_WIDTH && + y < SP_MAX_PLAYFIELD_HEIGHT) + native_sp_level.playfield[x][y] = element; + } + } + + /* read level header (96 bytes) */ + + ReadUnusedBytesFromFile(file, 4); /* (not used by Supaplex engine) */ + + /* initial gravity: 1 == "on", anything else (0) == "off" */ + header->InitialGravity = getFile8Bit(file); + + /* SpeedFixVersion XOR 0x20 */ + header->Version = getFile8Bit(file); + + /* level title in uppercase letters, padded with dashes ("-") (23 bytes) */ + for (i = 0; i < SP_LEVEL_NAME_LEN; i++) + header->LevelTitle[i] = getFile8Bit(file); + + /* initial "freeze zonks": 2 == "on", anything else (0, 1) == "off" */ + header->InitialFreezeZonks = getFile8Bit(file); + + /* number of infotrons needed; 0 means that Supaplex will count the total + amount of infotrons in the level and use the low byte of that number + (a multiple of 256 infotrons will result in "0 infotrons needed"!) */ + header->InfotronsNeeded = getFile8Bit(file); + + /* number of special ("gravity") port entries below (maximum 10 allowed) */ + header->SpecialPortCount = getFile8Bit(file); + + /* database of properties of up to 10 special ports (6 bytes per port) */ + for (i = 0; i < SP_MAX_SPECIAL_PORTS; i++) + { + SpecialPortType *port = &header->SpecialPort[i]; + + /* high and low byte of the location of a special port; if (x, y) are the + coordinates of a port in the field and (0, 0) is the top-left corner, + the 16 bit value here calculates as 2 * (x + (y * 60)) (this is twice + of what may be expected: Supaplex works with a game field in memory + which is 2 bytes per tile) */ + port->PortLocation = getFile16BitBE(file); /* yes, big endian */ + + /* change gravity: 1 == "turn on", anything else (0) == "turn off" */ + port->Gravity = getFile8Bit(file); + + /* "freeze zonks": 2 == "turn on", anything else (0, 1) == "turn off" */ + port->FreezeZonks = getFile8Bit(file); + + /* "freeze enemies": 1 == "turn on", anything else (0) == "turn off" */ + port->FreezeEnemies = getFile8Bit(file); + + ReadUnusedBytesFromFile(file, 1); /* (not used by Supaplex engine) */ + } + + /* SpeedByte XOR Highbyte(RandomSeed) */ + header->SpeedByte = getFile8Bit(file); + + /* CheckSum XOR SpeedByte */ + header->CheckSumByte = getFile8Bit(file); + + /* random seed used for recorded demos */ + header->DemoRandomSeed = getFile16BitLE(file); /* yes, little endian */ + + /* auto-determine number of infotrons if it was stored as "0" -- see above */ + if (header->InfotronsNeeded == 0) + { + for (x = 0; x < native_sp_level.width; x++) + for (y = 0; y < native_sp_level.height; y++) + if (native_sp_level.playfield[x][y] == fiInfotron) + header->InfotronsNeeded++; + + header->InfotronsNeeded &= 0xff; /* only use low byte -- see above */ + } + + /* read raw level header bytes (96 bytes) */ + + fseek(file, -(SP_HEADER_SIZE), SEEK_CUR); /* rewind file */ + for (i = 0; i < SP_HEADER_SIZE; i++) + native_sp_level.header_raw_bytes[i] = fgetc(file); + + /* also load demo tape, if available (only in single level files) */ + + if (demo_available) + { + int level_nr = getFile8Bit(file); + + level_nr &= 0x7f; /* clear highest bit */ + level_nr = (level_nr < 1 ? 1 : + level_nr > 111 ? 111 : level_nr); + + native_sp_level.demo.level_nr = level_nr; + + for (i = 0; i < SP_MAX_TAPE_LEN && !feof(file); i++) + { + native_sp_level.demo.data[i] = getFile8Bit(file); + + if (native_sp_level.demo.data[i] == 0xff) /* "end of demo" byte */ + { + i++; + + break; + } + } + + native_sp_level.demo.length = i; + native_sp_level.demo.is_available = (native_sp_level.demo.length > 0); + } +} + +boolean LoadNativeLevel_SP(char *filename, int level_pos) +{ + FILE *file; + int i, l, x, y; + char name_first, name_last; + struct LevelInfo_SP multipart_level; + int multipart_xpos, multipart_ypos; + boolean is_multipart_level; + boolean is_first_part; + boolean reading_multipart_level = FALSE; + boolean use_empty_level = FALSE; + LevelInfoType *header = &native_sp_level.header; + boolean is_single_level_file = (strSuffixLower(filename, ".sp") || + strSuffixLower(filename, ".mpx")); + boolean demo_available = is_single_level_file; + boolean is_mpx_file = strSuffixLower(filename, ".mpx"); + int file_seek_pos = level_pos * SP_STD_LEVEL_SIZE; + int level_width = SP_STD_PLAYFIELD_WIDTH; + int level_height = SP_STD_PLAYFIELD_HEIGHT; + + /* always start with reliable default values */ + setLevelInfoToDefaults_SP(); + copyInternalEngineVars_SP(); + + if (!(file = fopen(filename, MODE_READ))) + { + Error(ERR_WARN, "cannot open file '%s' -- using empty level", filename); + + return FALSE; + } + + if (is_mpx_file) + { + char mpx_chunk_name[4 + 1]; + int mpx_version; + int mpx_level_count; + LevelDescriptor *mpx_level_desc; + + getFileChunkBE(file, mpx_chunk_name, NULL); + + if (!strEqual(mpx_chunk_name, "MPX ")) + { + Error(ERR_WARN, "cannot find MPX ID in file '%s' -- using empty level", + filename); + + return FALSE; + } + + mpx_version = getFile16BitLE(file); + + if (mpx_version != 1) + { + Error(ERR_WARN, "unknown MPX version in file '%s' -- using empty level", + filename); + + return FALSE; + } + + mpx_level_count = getFile16BitLE(file); + + if (mpx_level_count < 1) + { + Error(ERR_WARN, "no MPX levels found in file '%s' -- using empty level", + filename); + + return FALSE; + } + + if (level_pos >= mpx_level_count) + { + Error(ERR_WARN, "MPX level not found in file '%s' -- using empty level", + filename); + + return FALSE; + } + + mpx_level_desc = checked_calloc(mpx_level_count * sizeof(LevelDescriptor)); + + for (i = 0; i < mpx_level_count; i++) + { + LevelDescriptor *ldesc = &mpx_level_desc[i]; + + ldesc->Width = getFile16BitLE(file); + ldesc->Height = getFile16BitLE(file); + ldesc->OffSet = getFile32BitLE(file); /* starts with 1, not with 0 */ + ldesc->Size = getFile32BitLE(file); + } + + level_width = mpx_level_desc[level_pos].Width; + level_height = mpx_level_desc[level_pos].Height; + + file_seek_pos = mpx_level_desc[level_pos].OffSet - 1; + } + + /* position file stream to the requested level (in case of level package) */ + if (fseek(file, file_seek_pos, SEEK_SET) != 0) + { + Error(ERR_WARN, "cannot fseek in file '%s' -- using empty level", filename); + + return FALSE; + } + + /* there exist Supaplex level package files with multi-part levels which + can be detected as follows: instead of leading and trailing dashes ('-') + to pad the level name, they have leading and trailing numbers which are + the x and y coordinations of the current part of the multi-part level; + if there are '?' characters instead of numbers on the left or right side + of the level name, the multi-part level consists of only horizontal or + vertical parts */ + + for (l = level_pos; l < SP_NUM_LEVELS_PER_PACKAGE; l++) + { + LoadNativeLevelFromFileStream_SP(file, level_width, level_height, + demo_available); + + /* check if this level is a part of a bigger multi-part level */ + + if (is_single_level_file) + break; + + name_first = header->LevelTitle[0]; + name_last = header->LevelTitle[SP_LEVEL_NAME_LEN - 1]; + + is_multipart_level = + ((name_first == '?' || (name_first >= '0' && name_first <= '9')) && + (name_last == '?' || (name_last >= '0' && name_last <= '9'))); + + is_first_part = + ((name_first == '?' || name_first == '1') && + (name_last == '?' || name_last == '1')); + + if (is_multipart_level) + { + /* correct leading multipart level meta information in level name */ + for (i = 0; + i < SP_LEVEL_NAME_LEN && header->LevelTitle[i] == name_first; + i++) + header->LevelTitle[i] = '-'; + + /* correct trailing multipart level meta information in level name */ + for (i = SP_LEVEL_NAME_LEN - 1; + i >= 0 && header->LevelTitle[i] == name_last; + i--) + header->LevelTitle[i] = '-'; + } + + /* ---------- check for normal single level ---------- */ + + if (!reading_multipart_level && !is_multipart_level) + { + /* the current level is simply a normal single-part level, and we are + not reading a multi-part level yet, so return the level as it is */ + + break; + } + + /* ---------- check for empty level (unused multi-part) ---------- */ + + if (!reading_multipart_level && is_multipart_level && !is_first_part) + { + /* this is a part of a multi-part level, but not the first part + (and we are not already reading parts of a multi-part level); + in this case, use an empty level instead of the single part */ + + use_empty_level = TRUE; + + break; + } + + /* ---------- check for finished multi-part level ---------- */ + + if (reading_multipart_level && + (!is_multipart_level || + !strEqualN(header->LevelTitle, multipart_level.header.LevelTitle, + SP_LEVEL_NAME_LEN))) + { + /* we are already reading parts of a multi-part level, but this level is + either not a multi-part level, or a part of a different multi-part + level; in both cases, the multi-part level seems to be complete */ + + break; + } + + /* ---------- here we have one part of a multi-part level ---------- */ + + reading_multipart_level = TRUE; + + if (is_first_part) /* start with first part of new multi-part level */ + { + /* copy level info structure from first part */ + multipart_level = native_sp_level; + + /* clear playfield of new multi-part level */ + for (x = 0; x < SP_MAX_PLAYFIELD_WIDTH; x++) + for (y = 0; y < SP_MAX_PLAYFIELD_HEIGHT; y++) + multipart_level.playfield[x][y] = fiSpace; + } + + if (name_first == '?') + name_first = '1'; + if (name_last == '?') + name_last = '1'; + + multipart_xpos = (int)(name_first - '0'); + multipart_ypos = (int)(name_last - '0'); + +#if 0 + printf("----------> part (%d/%d) of multi-part level '%s'\n", + multipart_xpos, multipart_ypos, multipart_level.header.LevelTitle); +#endif + + if (multipart_xpos * SP_STD_PLAYFIELD_WIDTH > SP_MAX_PLAYFIELD_WIDTH || + multipart_ypos * SP_STD_PLAYFIELD_HEIGHT > SP_MAX_PLAYFIELD_HEIGHT) + { + Error(ERR_WARN, "multi-part level is too big -- ignoring part of it"); + + break; + } + + multipart_level.width = MAX(multipart_level.width, + multipart_xpos * SP_STD_PLAYFIELD_WIDTH); + multipart_level.height = MAX(multipart_level.height, + multipart_ypos * SP_STD_PLAYFIELD_HEIGHT); + + /* copy level part at the right position of multi-part level */ + for (x = 0; x < SP_STD_PLAYFIELD_WIDTH; x++) + { + for (y = 0; y < SP_STD_PLAYFIELD_HEIGHT; y++) + { + int start_x = (multipart_xpos - 1) * SP_STD_PLAYFIELD_WIDTH; + int start_y = (multipart_ypos - 1) * SP_STD_PLAYFIELD_HEIGHT; + + multipart_level.playfield[start_x + x][start_y + y] = + native_sp_level.playfield[x][y]; + } + } + } + + fclose(file); + + if (use_empty_level) + { + setLevelInfoToDefaults_SP(); + + Error(ERR_WARN, "single part of multi-part level -- using empty level"); + } + + if (reading_multipart_level) + native_sp_level = multipart_level; + + copyInternalEngineVars_SP(); + + return TRUE; +} + +void SaveNativeLevel_SP(char *filename) +{ + LevelInfoType *header = &native_sp_level.header; + FILE *file; + int i, x, y; + + if (!(file = fopen(filename, MODE_WRITE))) + { + Error(ERR_WARN, "cannot save native level file '%s'", filename); + + return; + } + + /* write level playfield (width * height == 60 * 24 tiles == 1440 bytes) */ + for (y = 0; y < native_sp_level.height; y++) + for (x = 0; x < native_sp_level.width; x++) + putFile8Bit(file, native_sp_level.playfield[x][y]); + + /* write level header (96 bytes) */ + + WriteUnusedBytesToFile(file, 4); + + putFile8Bit(file, header->InitialGravity); + putFile8Bit(file, header->Version); + + for (i = 0; i < SP_LEVEL_NAME_LEN; i++) + putFile8Bit(file, header->LevelTitle[i]); + + putFile8Bit(file, header->InitialFreezeZonks); + putFile8Bit(file, header->InfotronsNeeded); + putFile8Bit(file, header->SpecialPortCount); + + for (i = 0; i < SP_MAX_SPECIAL_PORTS; i++) + { + SpecialPortType *port = &header->SpecialPort[i]; + + putFile16BitBE(file, port->PortLocation); + putFile8Bit(file, port->Gravity); + putFile8Bit(file, port->FreezeZonks); + putFile8Bit(file, port->FreezeEnemies); + + WriteUnusedBytesToFile(file, 1); + } + + putFile8Bit(file, header->SpeedByte); + putFile8Bit(file, header->CheckSumByte); + putFile16BitLE(file, header->DemoRandomSeed); + + /* also save demo tape, if available */ + + if (native_sp_level.demo.is_available) + { + putFile8Bit(file, native_sp_level.demo.level_nr); + + for (i = 0; i < native_sp_level.demo.length; i++) + putFile8Bit(file, native_sp_level.demo.data[i]); + } + + fclose(file); +} diff --git a/src/game_sp/game_sp.h b/src/game_sp/game_sp.h new file mode 100644 index 00000000..9551e84e --- /dev/null +++ b/src/game_sp/game_sp.h @@ -0,0 +1,21 @@ +/*********************************************************** +* Artsoft Retro-Game Library * +*----------------------------------------------------------* +* (c) 1994-2006 Artsoft Entertainment * +* Holger Schemel * +* Detmolder Strasse 189 * +* 33604 Bielefeld * +* Germany * +* e-mail: info@artsoft.org * +*----------------------------------------------------------* +* game_sp.h * +***********************************************************/ + +#ifndef GAME_SP_H +#define GAME_SP_H + +#define GAME_SP_VERSION_1_0_0 + +#include "export.h" + +#endif /* GAME_SP_H */ diff --git a/src/game_sp/global.h b/src/game_sp/global.h new file mode 100644 index 00000000..91847c2c --- /dev/null +++ b/src/game_sp/global.h @@ -0,0 +1,32 @@ +// ---------------------------------------------------------------------------- +// global.h +// ---------------------------------------------------------------------------- + +#ifndef GAME_SP_GLOBAL_H +#define GAME_SP_GLOBAL_H + +#include "main_sp.h" + +#include "vb_lib.h" + +#include "ASM.h" +#include "BugsTerminals.h" +#include "DDScrollBuffer.h" +#include "DDSpriteBuffer.h" +#include "Display.h" +#include "DoGameStuff.h" +#include "Electrons.h" +#include "Explosions.h" +#include "Globals.h" +#include "Infotrons.h" +#include "InitGameConditions.h" +#include "Input.h" +#include "MainForm.h" +#include "MainGameLoop.h" +#include "Murphy.h" +#include "OrangeDisk.h" +#include "SnikSnaks.h" +#include "Sound.h" +#include "Zonk.h" + +#endif /* GAME_SP_GLOBAL_H */ diff --git a/src/game_sp/init.c b/src/game_sp/init.c new file mode 100644 index 00000000..d8e4597d --- /dev/null +++ b/src/game_sp/init.c @@ -0,0 +1,155 @@ + +#include "main_sp.h" +#include "global.h" + + +Bitmap *bitmap_db_field_sp; + +struct EngineSnapshotInfo_SP engine_snapshot_sp; + +void sp_open_all() +{ + Form_Load(); +} + +void sp_close_all() +{ +} + +void InitGfxBuffers_SP() +{ + ReCreateBitmap(&bitmap_db_field_sp, FXSIZE, FYSIZE, DEFAULT_DEPTH); +} + +unsigned int InitEngineRandom_SP(long seed) +{ + if (seed == NEW_RANDOMIZE) + { + subRandomize(); + + seed = (long)RandomSeed; + } + + RandomSeed = (short)seed; + + return (unsigned int) seed; +} + + +/* ------------------------------------------------------------------------- */ +/* Supaplex game engine snapshot handling functions */ +/* ------------------------------------------------------------------------- */ + +void SaveEngineSnapshotValues_SP() +{ + int i; + + engine_snapshot_sp.game_sp = game_sp; + + /* these arrays have playfield-size dependent variable size */ + + for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++) + engine_snapshot_sp.PlayField16[i] = PlayField16[i]; + for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++) + engine_snapshot_sp.PlayField8[i] = PlayField8[i]; + for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++) + engine_snapshot_sp.DisPlayField[i] = DisPlayField[i]; + + for (i = 0; i < FieldWidth * (FieldHeight - 2); i++) + engine_snapshot_sp.AnimationPosTable[i] = AnimationPosTable[i]; + for (i = 0; i < FieldWidth * (FieldHeight - 2); i++) + engine_snapshot_sp.AnimationSubTable[i] = AnimationSubTable[i]; + for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++) + engine_snapshot_sp.TerminalState[i] = TerminalState[i]; + + /* store special data into engine snapshot buffers */ + + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(FieldWidth)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(FieldHeight)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(FieldMax)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(LevelMax)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(FileMax)); + + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TimerVar)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RandomSeed)); + + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TerminalMaxCycles)); + + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(mScrollX)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(mScrollY)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(mScrollX_last)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(mScrollY_last)); + + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScreenScrollXPos)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScreenScrollYPos)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(DisplayMinX)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(DisplayMinY)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(DisplayMaxX)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(DisplayMaxY)); + + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(InfotronsNeeded)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(KillMurphyFlag)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyMoveCounter)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyExplodePos)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(SplitMoveFlag)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RedDiskReleaseMurphyPos)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyPosIndex)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyXPos)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyYPos)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyScreenXPos)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyScreenYPos)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyVarFaceLeft)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RedDiskCount)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RedDiskReleaseFlag)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MovingPictureSequencePhase)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RedDiskReleasePhase)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScratchGravity)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GravityFlag)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(SnikSnaksElectronsFrozen)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(YellowDisksExploded)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(YawnSleepCounter)); + + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(LeadOutCounter)); + + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxElementLast)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxGraphicLast)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxGraphic)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxFrame)); + + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollMinX)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollMinY)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollMaxX)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollMaxY)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollX)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollY)); + + SaveEngineSnapshotBuffer(&PlayField16[-game_sp.preceding_buffer_size], + game_sp.preceding_buffer_size * sizeof(int)); +} + +void LoadEngineSnapshotValues_SP() +{ + int i; + + /* stored engine snapshot buffers already restored at this point */ + + game_sp = engine_snapshot_sp.game_sp; + + /* these arrays have playfield-size dependent variable size */ + + for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++) + PlayField16[i] = engine_snapshot_sp.PlayField16[i]; + for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++) + PlayField8[i] = engine_snapshot_sp.PlayField8[i]; + for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++) + DisPlayField[i] = engine_snapshot_sp.DisPlayField[i]; + + for (i = 0; i < FieldWidth * (FieldHeight - 2); i++) + AnimationPosTable[i] = engine_snapshot_sp.AnimationPosTable[i]; + for (i = 0; i < FieldWidth * (FieldHeight - 2); i++) + AnimationSubTable[i] = engine_snapshot_sp.AnimationSubTable[i]; + for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++) + TerminalState[i] = engine_snapshot_sp.TerminalState[i]; + + RedrawPlayfield_SP(TRUE); +} diff --git a/src/game_sp/main.c b/src/game_sp/main.c new file mode 100644 index 00000000..1308353d --- /dev/null +++ b/src/game_sp/main.c @@ -0,0 +1,94 @@ + +#include "main_sp.h" +#include "global.h" + + +struct GameInfo_SP game_sp; +struct LevelInfo_SP native_sp_level; + +int GfxElementLast[SP_MAX_PLAYFIELD_WIDTH][SP_MAX_PLAYFIELD_HEIGHT]; +int GfxGraphicLast[SP_MAX_PLAYFIELD_WIDTH][SP_MAX_PLAYFIELD_HEIGHT]; +int GfxGraphic[SP_MAX_PLAYFIELD_WIDTH][SP_MAX_PLAYFIELD_HEIGHT]; +int GfxFrame[SP_MAX_PLAYFIELD_WIDTH][SP_MAX_PLAYFIELD_HEIGHT]; + + +void InitGameEngine_SP() +{ + int x, y; + + gfx.anim_random_frame = -1; // (use simple, ad-hoc random numbers) + + game_sp.LevelSolved = FALSE; + game_sp.GameOver = FALSE; + + game_sp.time_played = 0; + game_sp.infotrons_still_needed = native_sp_level.header.InfotronsNeeded; + game_sp.red_disk_count = 0; + game_sp.score = 0; + + menBorder = setup.sp_show_border_elements; + + game_sp.scroll_xoffset = (EVEN(SCR_FIELDX) ? TILEX / 2 : 0); + game_sp.scroll_yoffset = (EVEN(SCR_FIELDY) ? TILEY / 2 : 0); + +#if 1 + if (native_sp_level.width <= SCR_FIELDX) + game_sp.scroll_xoffset = TILEX / 2; + if (native_sp_level.height <= SCR_FIELDY) + game_sp.scroll_yoffset = TILEY / 2; +#endif + + for (x = 0; x < SP_MAX_PLAYFIELD_WIDTH; x++) + { + for (y = 0; y < SP_MAX_PLAYFIELD_HEIGHT; y++) + { + GfxElementLast[x][y] = -1; + GfxGraphicLast[x][y] = -1; + GfxGraphic[x][y] = -1; + GfxFrame[x][y] = 0; + } + } + + InitScrollPlayfield(); + + menPlay_Click(); +} + +void RedrawPlayfield_SP(boolean force_redraw) +{ + if (force_redraw) + RestorePlayfield(); + + UpdatePlayfield(force_redraw); + + BackToFront_SP(); +} + +void DrawGameDoorValues_SP() +{ + game_sp.time_played = TimerVar / setup.game_frame_delay; + game_sp.infotrons_still_needed = InfotronsNeeded; + game_sp.red_disk_count = RedDiskCount; + game_sp.score = 0; // (currently no score in Supaplex engine) +} + +void GameActions_SP(byte action[MAX_PLAYERS], boolean warp_mode) +{ + byte single_player_action = action[0]; + int x, y; + + UpdateEngineValues(mScrollX / TILEX, mScrollY / TILEY); + + subMainGameLoop_Main(single_player_action, warp_mode); + + RedrawPlayfield_SP(FALSE); + + if (!warp_mode) /* do not redraw values in warp mode */ + DrawGameDoorValues_SP(); + + CheckSingleStepMode_SP(PlayField16[MurphyPosIndex] != fiMurphy); + + for (x = DisplayMinX; x <= DisplayMaxX; x++) + for (y = DisplayMinY; y <= DisplayMaxY; y++) + GfxFrame[x][y]++; +} diff --git a/src/game_sp/main_sp.h b/src/game_sp/main_sp.h new file mode 100644 index 00000000..6e61508b --- /dev/null +++ b/src/game_sp/main_sp.h @@ -0,0 +1,95 @@ +#ifndef MAIN_SP_H +#define MAIN_SP_H + +/* ========================================================================= */ +/* external functions and definitions imported from main program to game_sp */ +/* ========================================================================= */ + +#include "../engines.h" +#include "../conf_gfx.h" + + +/* ========================================================================= */ +/* functions and definitions that are exported from game_sp to main program */ +/* ========================================================================= */ + +#include "export.h" + + +/* ========================================================================= */ +/* internal functions and definitions that are not exported to main program */ +/* ========================================================================= */ + + +/* ------------------------------------------------------------------------- */ +/* constant definitions */ +/* ------------------------------------------------------------------------- */ + +/* screen sizes and positions for SP engine */ + +#define ORIG_TILESIZE 16 + +#define ZOOM_FACTOR 2 + +#define TILESIZE (ORIG_TILESIZE * ZOOM_FACTOR) +#define TILEX TILESIZE +#define TILEY TILESIZE + +#define ORIG_SCR_MENUX 20 +#define ORIG_SCR_MENUY 12 +#define SCR_MENUX 17 +#define SCR_MENUY 12 +#if 1 +extern int SCR_FIELDX, SCR_FIELDY; +#else +#define SCR_FIELDX 17 +#define SCR_FIELDY 17 +#endif +#define MAX_BUF_XSIZE (2 + SCR_FIELDX + 2) +#define MAX_BUF_YSIZE (2 + SCR_FIELDY + 2) + +/* often used screen positions */ +#if 1 +extern int SX, SY; +#else +#define SX 8 +#define SY 8 +#endif +#define SXSIZE (SCR_FIELDX * TILEX) +#define SYSIZE (SCR_FIELDY * TILEY) +#define FXSIZE (MAX_BUF_XSIZE * TILEX) +#define FYSIZE (MAX_BUF_YSIZE * TILEY) + +#if 1 +extern int REAL_SX, REAL_SY; +#else +#define REAL_SX (SX - 2) +#define REAL_SY (SY - 2) +#endif +#define FULL_SXSIZE (2 + SXSIZE + 2) +#define FULL_SYSIZE (2 + SYSIZE + 2) + + +/* ------------------------------------------------------------------------- */ +/* data structure definitions */ +/* ------------------------------------------------------------------------- */ + +/* ------------------------------------------------------------------------- */ +/* exported variables */ +/* ------------------------------------------------------------------------- */ + +extern struct LevelInfo_SP native_sp_level; + +extern Bitmap *bitmap_db_field_sp; + +extern int GfxElementLast[SP_MAX_PLAYFIELD_WIDTH][SP_MAX_PLAYFIELD_HEIGHT]; +extern int GfxGraphicLast[SP_MAX_PLAYFIELD_WIDTH][SP_MAX_PLAYFIELD_HEIGHT]; +extern int GfxGraphic[SP_MAX_PLAYFIELD_WIDTH][SP_MAX_PLAYFIELD_HEIGHT]; +extern int GfxFrame[SP_MAX_PLAYFIELD_WIDTH][SP_MAX_PLAYFIELD_HEIGHT]; + + +/* ------------------------------------------------------------------------- */ +/* exported functions */ +/* ------------------------------------------------------------------------- */ + +#endif /* MAIN_SP_H */ diff --git a/src/game_sp/vb_lib.c b/src/game_sp/vb_lib.c new file mode 100644 index 00000000..f71693c0 --- /dev/null +++ b/src/game_sp/vb_lib.c @@ -0,0 +1,29 @@ +// ---------------------------------------------------------------------------- +// vb_lib.c +// ---------------------------------------------------------------------------- + +#include "main_sp.h" + +#include "vb_lib.h" + + +/* helper functions for constructs not supported by C */ + +#if 0 +void *REDIM_1D(int data_size, int first_data_pos, int last_data_pos) +{ + /* for a buffer of n elements, first_data_pos is 0 and last_data_pos is n-1 */ + /* a negative value for "first_data_pos" indicates a preceding buffer zone */ + + int data_count = last_data_pos - first_data_pos + 1; + int buffer_size = data_size * data_count; + int buffer_start = data_size * first_data_pos; + + return (checked_calloc(buffer_size) - buffer_start); +} +#endif + +long MyGetTickCount() +{ + return random_linux_libc(RANDOM_SIMPLE); +} diff --git a/src/game_sp/vb_lib.h b/src/game_sp/vb_lib.h new file mode 100644 index 00000000..cf8e3462 --- /dev/null +++ b/src/game_sp/vb_lib.h @@ -0,0 +1,20 @@ +// ---------------------------------------------------------------------------- +// vb_lib.h +// ---------------------------------------------------------------------------- + +#ifndef VB_LIB_H +#define VB_LIB_H + +#define Abs(x) ABS(x) +#define Sqr(x) sqrt(x) + + +/* helper functions for constructs not supported by C */ + +#if 0 +extern void *REDIM_1D(int, int, int); +#endif + +extern long MyGetTickCount(); + +#endif /* VB_LIB_H */ diff --git a/src/init.c b/src/init.c index ea5ec18d..5e5301c7 100644 --- a/src/init.c +++ b/src/init.c @@ -186,20 +186,8 @@ void DrawInitAnim() } #endif -#if 0 - anim_initial.anim_mode = ANIM_LOOP; - anim_initial.anim_start_frame = 0; - anim_initial.offset_x = anim_initial.width; - anim_initial.offset_y = 0; -#endif - -#if 1 - x = ALIGNED_TEXT_XPOS(&init.busy); - y = ALIGNED_TEXT_YPOS(&init.busy); -#else - x = WIN_XSIZE / 2 - TILESIZE / 2; - y = WIN_YSIZE / 2 - TILESIZE / 2; -#endif + x = ALIGNED_TEXT_XPOS(&init_last.busy); + y = ALIGNED_TEXT_YPOS(&init_last.busy); graphic_info = &anim_initial; /* graphic == 0 => anim_initial */ @@ -329,6 +317,14 @@ void SetBitmaps_EM(Bitmap **em_bitmap) } #endif +#if 0 +/* !!! FIX THIS (CHANGE TO USING NORMAL ELEMENT GRAPHIC DEFINITIONS) !!! */ +void SetBitmaps_SP(Bitmap **sp_bitmap) +{ + *sp_bitmap = graphic_info[IMG_SP_OBJECTS].bitmap; +} +#endif + static int getFontBitmapID(int font_nr) { int special = -1; @@ -1298,6 +1294,8 @@ static void set_graphic_parameters_ext(int graphic, int *parameter, g->align = ALIGN_CENTER; /* default for title screens */ g->valign = VALIGN_MIDDLE; /* default for title screens */ g->sort_priority = 0; /* default for title screens */ + g->class = 0; + g->style = STYLE_DEFAULT; g->bitmap = src_bitmap; @@ -1498,6 +1496,11 @@ static void set_graphic_parameters_ext(int graphic, int *parameter, g->valign = parameter[GFX_ARG_VALIGN]; if (parameter[GFX_ARG_SORT_PRIORITY] != ARG_UNDEFINED_VALUE) g->sort_priority = parameter[GFX_ARG_SORT_PRIORITY]; + + if (parameter[GFX_ARG_CLASS] != ARG_UNDEFINED_VALUE) + g->class = parameter[GFX_ARG_CLASS]; + if (parameter[GFX_ARG_STYLE] != ARG_UNDEFINED_VALUE) + g->style = parameter[GFX_ARG_STYLE]; } static void set_graphic_parameters(int graphic) @@ -2829,8 +2832,12 @@ void InitElementPropertiesStatic() EL_SIGN_FRANKIE, EL_STEEL_EXIT_CLOSED, EL_STEEL_EXIT_OPEN, + EL_STEEL_EXIT_OPENING, + EL_STEEL_EXIT_CLOSING, EL_EM_STEEL_EXIT_CLOSED, EL_EM_STEEL_EXIT_OPEN, + EL_EM_STEEL_EXIT_OPENING, + EL_EM_STEEL_EXIT_CLOSING, EL_DC_STEELWALL_1_LEFT, EL_DC_STEELWALL_1_RIGHT, EL_DC_STEELWALL_1_TOP, @@ -4174,6 +4181,7 @@ void InitElementPropertiesStatic() EL_PLAYER_2, EL_PLAYER_3, EL_PLAYER_4, + EL_SOKOBAN_FIELD_PLAYER, EL_SP_MURPHY, EL_YAMYAM, EL_YAMYAM_LEFT, @@ -5124,7 +5132,7 @@ void Execute_Command(char *command) exit(0); } - else if (strncmp(command, "dump level ", 11) == 0) + else if (strPrefix(command, "dump level ")) { char *filename = &command[11]; @@ -5136,7 +5144,7 @@ void Execute_Command(char *command) exit(0); } - else if (strncmp(command, "dump tape ", 10) == 0) + else if (strPrefix(command, "dump tape ")) { char *filename = &command[10]; @@ -5148,7 +5156,7 @@ void Execute_Command(char *command) exit(0); } - else if (strncmp(command, "autoplay ", 9) == 0) + else if (strPrefix(command, "autoplay ")) { char *str_ptr = getStringCopy(&command[9]); /* read command parameters */ @@ -5184,9 +5192,9 @@ void Execute_Command(char *command) str_ptr++; } } - else if (strncmp(command, "convert ", 8) == 0) + else if (strPrefix(command, "convert ")) { - char *str_copy = getStringCopy(&command[8]); + char *str_copy = getStringCopy(strchr(command, ' ') + 1); char *str_ptr = strchr(str_copy, ' '); global.convert_leveldir = str_copy; @@ -5198,7 +5206,7 @@ void Execute_Command(char *command) global.convert_level_nr = atoi(str_ptr); /* get level_nr value */ } } - else if (strncmp(command, "create images ", 14) == 0) + else if (strPrefix(command, "create images ")) { #if defined(TARGET_SDL) global.create_images_dir = getStringCopy(&command[14]); @@ -5441,6 +5449,28 @@ static void InitMixer() StartMixer(); } +void InitGfxBuffers() +{ + ReCreateBitmap(&bitmap_db_store, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH); + ReCreateBitmap(&bitmap_db_cross, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH); + ReCreateBitmap(&bitmap_db_field, FXSIZE, FYSIZE, DEFAULT_DEPTH); + ReCreateBitmap(&bitmap_db_panel, DXSIZE, DYSIZE, DEFAULT_DEPTH); + ReCreateBitmap(&bitmap_db_door, 3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH); + ReCreateBitmap(&bitmap_db_toons, FULL_SXSIZE, FULL_SYSIZE, DEFAULT_DEPTH); + + /* initialize screen properties */ + InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE, + REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, + bitmap_db_field); + InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE); + InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE); + InitGfxWindowInfo(WIN_XSIZE, WIN_YSIZE); + InitGfxScrollbufferInfo(FXSIZE, FYSIZE); + InitGfxClipRegion(FALSE, -1, -1, -1, -1); + + InitGfxBuffers_SP(); +} + void InitGfx() { struct GraphicInfo *graphic_info_last = graphic_info; @@ -5487,7 +5517,11 @@ void InitGfx() if (filename_font_initial == NULL) /* should not happen */ Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL); +#if 1 + InitGfxBuffers(); +#else /* create additional image buffers for double-buffering and cross-fading */ + bitmap_db_store = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH); bitmap_db_cross = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH); bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH); bitmap_db_panel = CreateBitmap(DXSIZE, DYSIZE, DEFAULT_DEPTH); @@ -5502,6 +5536,8 @@ void InitGfx() InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE); InitGfxWindowInfo(WIN_XSIZE, WIN_YSIZE); InitGfxScrollbufferInfo(FXSIZE, FYSIZE); +#endif + InitGfxCustomArtworkInfo(); bitmap_font_initial = LoadCustomImage(filename_font_initial); @@ -5615,6 +5651,9 @@ void InitGfx() InitMenuDesignSettings_Static(); InitGfxDrawBusyAnimFunction(DrawInitAnim); + + /* use copy of busy animation to prevent change while reloading artwork */ + init_last = init; #endif } @@ -6094,6 +6133,8 @@ void ReloadCustomArtwork(int force_reload) game_status = last_game_status; /* restore current game status */ + init_last = init; /* switch to new busy animation */ + #if 0 printf("::: ----------------DELAY 1 ...\n"); Delay(3000); @@ -6151,8 +6192,14 @@ void OpenAll() game_status = GAME_MODE_LOADING; +#if 1 + InitCounter(); +#endif + InitGlobal(); /* initialize some global variables */ + print_timestamp_time("[init global stuff]"); + if (options.execute_command) Execute_Command(options.execute_command); @@ -6175,25 +6222,29 @@ void OpenAll() InitArtworkConfig(); /* needed before forking sound child process */ InitMixer(); +#if 0 InitCounter(); +#endif InitRND(NEW_RANDOMIZE); InitSimpleRandom(NEW_RANDOMIZE); InitJoysticks(); - print_timestamp_time("[pre-video]"); + print_timestamp_time("[init setup/config stuff]"); InitVideoDisplay(); InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen); InitEventFilter(FilterMouseMotionEvents); + print_timestamp_time("[init video stuff]"); + InitElementPropertiesStatic(); InitElementPropertiesEngine(GAME_VERSION_ACTUAL); InitElementPropertiesGfxElement(); - print_timestamp_time("[post-video]"); + print_timestamp_time("[init element properties stuff]"); InitGfx(); @@ -6223,6 +6274,10 @@ void OpenAll() em_open_all(); #endif +#if 1 + sp_open_all(); +#endif + if (global.autoplay_leveldir) { AutoPlayTape(); @@ -6270,6 +6325,10 @@ void CloseAllAndExit(int exit_value) em_close_all(); #endif +#if 1 + sp_close_all(); +#endif + FreeAllImages(); #if defined(TARGET_SDL) diff --git a/src/init.h b/src/init.h index 4226241a..42bc9f74 100644 --- a/src/init.h +++ b/src/init.h @@ -43,6 +43,9 @@ void RedrawBackground(); void KeyboardAutoRepeatOffUnlessAutoplay(); +void InitGfxBuffers(); +void InitGadgets(); + void OpenAll(void); void CloseAllAndExit(int); diff --git a/src/libgame/Makefile b/src/libgame/Makefile index 6148a985..140e9fd9 100644 --- a/src/libgame/Makefile +++ b/src/libgame/Makefile @@ -13,6 +13,7 @@ SRCS = system.c \ text.c \ sound.c \ joystick.c \ + snapshot.c \ toons.c \ pcx.c \ image.c \ @@ -28,6 +29,7 @@ OBJS = system.o \ gadgets.o \ text.o \ sound.o \ + snapshot.o \ joystick.o \ toons.o \ pcx.o \ diff --git a/src/libgame/gadgets.c b/src/libgame/gadgets.c index 3d593a9b..4ac2a294 100644 --- a/src/libgame/gadgets.c +++ b/src/libgame/gadgets.c @@ -383,7 +383,7 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct) /* gadget text value */ #if 1 DrawTextBuffer(gi->x + border_x, gi->y + border_y, gi->textarea.value, - font_nr, gi->textarea.xsize, -1, gi->textarea.ysize, + font_nr, gi->textarea.xsize, 0, -1, gi->textarea.ysize, BLIT_ON_BACKGROUND, FALSE, FALSE, FALSE); #else DrawTextToTextArea(gi->x + border_x, gi->y + border_y, diff --git a/src/libgame/hash.h b/src/libgame/hash.h index 0d20f2c4..17e511e9 100644 --- a/src/libgame/hash.h +++ b/src/libgame/hash.h @@ -251,23 +251,16 @@ struct hashtable_itr * hashtable_iterator(struct hashtable *h); /*****************************************************************************/ -/* hashtable_iterator_key - * - return the value of the (key,value) pair at the current position */ +/* key - return the key of the (key,value) pair at the current position */ -extern inline void * -hashtable_iterator_key(struct hashtable_itr *i) -{ - return i->e->k; -} +void * +hashtable_iterator_key(struct hashtable_itr *i); /*****************************************************************************/ /* value - return the value of the (key,value) pair at the current position */ -extern inline void * -hashtable_iterator_value(struct hashtable_itr *i) -{ - return i->e->v; -} +void * +hashtable_iterator_value(struct hashtable_itr *i); /*****************************************************************************/ /* advance - advance the iterator to the next element diff --git a/src/libgame/libgame.h b/src/libgame/libgame.h index 6f4c20c2..d1f05c82 100644 --- a/src/libgame/libgame.h +++ b/src/libgame/libgame.h @@ -23,6 +23,7 @@ #include "gadgets.h" #include "text.h" #include "sound.h" +#include "snapshot.h" #include "joystick.h" #include "toons.h" #include "image.h" diff --git a/src/libgame/misc.c b/src/libgame/misc.c index 5e4b9310..b8f2fe5c 100644 --- a/src/libgame/misc.c +++ b/src/libgame/misc.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -181,6 +182,46 @@ END_OF_FUNCTION(increment_counter); /* maximal allowed length of a command line option */ #define MAX_OPTION_LEN 256 +#if 1 + +#ifdef TARGET_SDL +static unsigned long getCurrentMS() +{ + return SDL_GetTicks(); +} + +#else /* !TARGET_SDL */ + +#if defined(PLATFORM_UNIX) +static unsigned long getCurrentMS() +{ + struct timeval current_time; + + gettimeofday(¤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) { @@ -222,6 +263,8 @@ static unsigned long mainCounter(int mode) #endif /* PLATFORM_UNIX */ #endif /* !TARGET_SDL */ +#endif + void InitCounter() /* set counter back to zero */ { #if !defined(PLATFORM_MSDOS) @@ -468,6 +511,16 @@ char *getRealName() return real_name; } +time_t getFileTimestampEpochSeconds(char *filename) +{ + struct stat file_status; + + if (stat(filename, &file_status) != 0) /* cannot stat file */ + return 0; + + return file_status.st_mtime; +} + /* ------------------------------------------------------------------------- */ /* path manipulation functions */ @@ -637,6 +690,26 @@ boolean strSuffix(char *s, char *suffix) strncmp(&s[strlen(s) - strlen(suffix)], suffix, strlen(suffix)) == 0); } +boolean strPrefixLower(char *s, char *prefix) +{ + char *s_lower = getStringToLower(s); + boolean match = strPrefix(s_lower, prefix); + + free(s_lower); + + return match; +} + +boolean strSuffixLower(char *s, char *suffix) +{ + char *s_lower = getStringToLower(s); + boolean match = strSuffix(s_lower, suffix); + + free(s_lower); + + return match; +} + /* ------------------------------------------------------------------------- */ /* command line option handling functions */ @@ -665,6 +738,7 @@ void GetOptions(char *argv[], void (*print_usage_function)(void)) options.display_name = NULL; options.server_host = NULL; options.server_port = 0; + options.ro_base_directory = ro_base_path; options.rw_base_directory = rw_base_path; options.level_directory = getPath2(ro_base_path, LEVELS_DIRECTORY); @@ -672,7 +746,10 @@ void GetOptions(char *argv[], void (*print_usage_function)(void)) options.sounds_directory = getPath2(ro_base_path, SOUNDS_DIRECTORY); options.music_directory = getPath2(ro_base_path, MUSIC_DIRECTORY); options.docs_directory = getPath2(ro_base_path, DOCS_DIRECTORY); + options.execute_command = NULL; + options.special_flags = NULL; + options.serveronly = FALSE; options.network = FALSE; options.verbose = FALSE; @@ -701,7 +778,7 @@ void GetOptions(char *argv[], void (*print_usage_function)(void)) if (strEqual(option, "--")) /* stop scanning arguments */ break; - if (strncmp(option, "--", 2) == 0) /* treat '--' like '-' */ + if (strPrefix(option, "--")) /* treat '--' like '-' */ option++; option_arg = strchr(option, '='); @@ -807,6 +884,25 @@ void GetOptions(char *argv[], void (*print_usage_function)(void)) { options.debug_x11_sync = TRUE; } + else if (strPrefix(option, "-D")) + { +#if 1 + options.special_flags = getStringCopy(&option[2]); +#else + char *flags_string = &option[2]; + unsigned long flags_value; + + if (*flags_string == '\0') + Error(ERR_EXIT_HELP, "empty flag ignored"); + + flags_value = get_special_flags_function(flags_string); + + if (flags_value == 0) + Error(ERR_EXIT_HELP, "unknown flag '%s'", flags_string); + + options.special_flags |= flags_value; +#endif + } else if (strncmp(option, "-execute", option_len) == 0) { if (option_arg == NULL) @@ -1409,7 +1505,7 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode) Key key = KSYM_UNDEFINED; char *name_ptr = *x11name; - if (strncmp(name_ptr, "XK_", 3) == 0 && strlen(name_ptr) == 4) + if (strPrefix(name_ptr, "XK_") && strlen(name_ptr) == 4) { char c = name_ptr[3]; @@ -1420,14 +1516,14 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode) else if (c >= '0' && c <= '9') key = KSYM_0 + (Key)(c - '0'); } - else if (strncmp(name_ptr, "XK_KP_", 6) == 0 && strlen(name_ptr) == 7) + else if (strPrefix(name_ptr, "XK_KP_") && strlen(name_ptr) == 7) { char c = name_ptr[6]; if (c >= '0' && c <= '9') key = KSYM_KP_0 + (Key)(c - '0'); } - else if (strncmp(name_ptr, "XK_F", 4) == 0 && strlen(name_ptr) <= 6) + else if (strPrefix(name_ptr, "XK_F") && strlen(name_ptr) <= 6) { char c1 = name_ptr[4]; char c2 = name_ptr[5]; @@ -1440,7 +1536,7 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode) if (d >= 1 && d <= KSYM_NUM_FKEYS) key = KSYM_F1 + (Key)(d - 1); } - else if (strncmp(name_ptr, "XK_", 3) == 0) + else if (strPrefix(name_ptr, "XK_")) { i = 0; @@ -1454,7 +1550,7 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode) } while (translate_key[++i].x11name); } - else if (strncmp(name_ptr, "0x", 2) == 0) + else if (strPrefix(name_ptr, "0x")) { unsigned long value = 0; @@ -1777,7 +1873,7 @@ boolean FileIsMusic(char *filename) return TRUE; #if defined(TARGET_SDL) - if (fileHasPrefix(basename, "mod") || + if ((fileHasPrefix(basename, "mod") && !fileHasSuffix(basename, "txt")) || fileHasSuffix(basename, "mod") || fileHasSuffix(basename, "s3m") || fileHasSuffix(basename, "it") || @@ -1915,6 +2011,20 @@ int get_parameter_value(char *value_raw, char *suffix, int type) if (string_has_parameter(value, "static_panel")) result |= ANIM_STATIC_PANEL; } + else if (strEqual(suffix, ".class")) + { + result = get_hash_from_key(value); + } + else if (strEqual(suffix, ".style")) + { + result = STYLE_DEFAULT; + + if (string_has_parameter(value, "accurate_borders")) + result |= STYLE_ACCURATE_BORDERS; + + if (string_has_parameter(value, "inner_corners")) + result |= STYLE_INNER_CORNERS; + } else if (strEqual(suffix, ".fade_mode")) { result = (string_has_parameter(value, "none") ? FADE_MODE_NONE : diff --git a/src/libgame/misc.h b/src/libgame/misc.h index 56467dc1..34499610 100644 --- a/src/libgame/misc.h +++ b/src/libgame/misc.h @@ -92,6 +92,8 @@ unsigned int get_random_number(int, int); char *getLoginName(void); char *getRealName(void); +time_t getFileTimestampEpochSeconds(char *); + char *getBasePath(char *); char *getBaseName(char *); char *getBaseNamePtr(char *); @@ -110,6 +112,8 @@ boolean strEqual(char *, char *); boolean strEqualN(char *, char *, int); boolean strPrefix(char *, char *); boolean strSuffix(char *, char *); +boolean strPrefixLower(char *, char *); +boolean strSuffixLower(char *, char *); void GetOptions(char **, void (*print_usage_function)(void)); diff --git a/src/libgame/sdl.c b/src/libgame/sdl.c index f751fe85..4c484243 100644 --- a/src/libgame/sdl.c +++ b/src/libgame/sdl.c @@ -140,6 +140,13 @@ void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window, fullscreen_xoffset = (fullscreen_width - video.width) / 2; fullscreen_yoffset = (fullscreen_height - video.height) / 2; +#if 1 + checked_free(video.fullscreen_modes); + + video.fullscreen_modes = NULL; + video.fullscreen_mode_current = NULL; +#endif + /* get available hardware supported fullscreen modes */ modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE); @@ -228,7 +235,11 @@ void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window, should never be drawn to directly, it would do no harm nevertheless. */ /* create additional (symbolic) buffer for double-buffering */ +#if 1 + ReCreateBitmap(window, video.width, video.height, video.depth); +#else *window = CreateBitmap(video.width, video.height, video.depth); +#endif } boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen) @@ -241,6 +252,10 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen) if (*backbuffer == NULL) *backbuffer = CreateBitmapStruct(); + /* (real bitmap might be larger in fullscreen mode with video offsets) */ + (*backbuffer)->width = video.width; + (*backbuffer)->height = video.height; + if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available) { setFullscreenParameters(setup.fullscreen_mode); @@ -292,11 +307,11 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen) (*backbuffer)->surface = new_surface; video.fullscreen_enabled = FALSE; + success = TRUE; } } - #if 1 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); @@ -423,6 +438,17 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height, int dst_x = x, dst_y = y; unsigned int time_last, time_current; + /* check if screen size has changed */ + if (surface_source != NULL && (video.width != surface_source->w || + video.height != surface_source->h)) + { + SDL_FreeSurface(surface_source); + SDL_FreeSurface(surface_target); + SDL_FreeSurface(surface_black); + + initialization_needed = TRUE; + } + src_rect.x = src_x; src_rect.y = src_y; src_rect.w = width; diff --git a/src/libgame/setup.c b/src/libgame/setup.c index 3e539249..b7e34adf 100644 --- a/src/libgame/setup.c +++ b/src/libgame/setup.c @@ -412,6 +412,19 @@ char *getSolutionTapeFilename(int nr) sprintf(basename, "%03d.%s", nr, TAPEFILE_EXTENSION); filename = getPath2(getSolutionTapeDir(), basename); + if (!fileExists(filename)) + { + static char *filename_sln = NULL; + + checked_free(filename_sln); + + sprintf(basename, "%03d.sln", nr); + filename_sln = getPath2(getSolutionTapeDir(), basename); + + if (fileExists(filename_sln)) + return filename_sln; + } + return filename; } @@ -1410,21 +1423,41 @@ static int posix_mkdir(const char *pathname, mode_t mode) #endif } +static boolean posix_process_running_setgid() +{ +#if defined(PLATFORM_UNIX) + return (getgid() != getegid()); +#else + return FALSE; +#endif +} + void createDirectory(char *dir, char *text, int permission_class) { /* leave "other" permissions in umask untouched, but ensure group parts of USERDATA_DIR_MODE are not masked */ mode_t dir_mode = (permission_class == PERMS_PRIVATE ? DIR_PERMS_PRIVATE : DIR_PERMS_PUBLIC); - mode_t normal_umask = posix_umask(0); + mode_t last_umask = posix_umask(0); mode_t group_umask = ~(dir_mode & S_IRWXG); - posix_umask(normal_umask & group_umask); + int running_setgid = posix_process_running_setgid(); + + /* if we're setgid, protect files against "other" */ + /* else keep umask(0) to make the dir world-writable */ + + if (running_setgid) + posix_umask(last_umask & group_umask); + else + dir_mode |= MODE_W_ALL; if (!fileExists(dir)) if (posix_mkdir(dir, dir_mode) != 0) Error(ERR_WARN, "cannot create %s directory '%s'", text, dir); - posix_umask(normal_umask); /* reset normal umask */ + if (permission_class == PERMS_PUBLIC && !running_setgid) + chmod(dir, dir_mode); + + posix_umask(last_umask); /* restore previous umask */ } void InitUserDataDirectory() @@ -1434,8 +1467,14 @@ void InitUserDataDirectory() void SetFilePermissions(char *filename, int permission_class) { - chmod(filename, (permission_class == PERMS_PRIVATE ? - FILE_PERMS_PRIVATE : FILE_PERMS_PUBLIC)); + int running_setgid = posix_process_running_setgid(); + int perms = (permission_class == PERMS_PRIVATE ? + FILE_PERMS_PRIVATE : FILE_PERMS_PUBLIC); + + if (permission_class == PERMS_PUBLIC && !running_setgid) + perms |= MODE_W_ALL; + + chmod(filename, perms); } char *getCookie(char *file_type) @@ -1616,7 +1655,7 @@ DEFINE_HASHTABLE_REMOVE(remove_hash_entry, char, char); #define remove_hash_entry hashtable_remove #endif -static unsigned int get_hash_from_key(void *key) +unsigned int get_hash_from_key(void *key) { /* djb2 @@ -2375,10 +2414,11 @@ void checkSetupFileHashIdentifier(SetupFileHash *setup_file_hash, #define LEVELINFO_TOKEN_MUSIC_SET 18 #define LEVELINFO_TOKEN_FILENAME 19 #define LEVELINFO_TOKEN_FILETYPE 20 -#define LEVELINFO_TOKEN_HANDICAP 21 -#define LEVELINFO_TOKEN_SKIP_LEVELS 22 +#define LEVELINFO_TOKEN_SPECIAL_FLAGS 21 +#define LEVELINFO_TOKEN_HANDICAP 22 +#define LEVELINFO_TOKEN_SKIP_LEVELS 23 -#define NUM_LEVELINFO_TOKENS 23 +#define NUM_LEVELINFO_TOKENS 24 static LevelDirTree ldi; @@ -2406,6 +2446,7 @@ static struct TokenInfo levelinfo_tokens[] = { TYPE_STRING, &ldi.music_set, "music_set" }, { TYPE_STRING, &ldi.level_filename, "filename" }, { TYPE_STRING, &ldi.level_filetype, "filetype" }, + { TYPE_STRING, &ldi.special_flags, "special_flags" }, { TYPE_BOOLEAN, &ldi.handicap, "handicap" }, { TYPE_BOOLEAN, &ldi.skip_levels, "skip_levels" } }; @@ -2482,6 +2523,8 @@ static void setTreeInfoToDefaults(TreeInfo *ti, int type) ti->level_filename = NULL; ti->level_filetype = NULL; + ti->special_flags = NULL; + ti->levels = 0; ti->first_level = 0; ti->last_level = 0; @@ -2553,12 +2596,18 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ti, TreeInfo *parent) ti->level_filename = NULL; ti->level_filetype = NULL; + ti->special_flags = getStringCopy(parent->special_flags); + ti->levels = 0; ti->first_level = 0; ti->last_level = 0; ti->level_group = FALSE; ti->handicap_level = 0; +#if 1 + ti->readonly = parent->readonly; +#else ti->readonly = TRUE; +#endif ti->handicap = TRUE; ti->skip_levels = FALSE; } @@ -2604,6 +2653,8 @@ static TreeInfo *getTreeInfoCopy(TreeInfo *ti) ti_copy->level_filename = getStringCopy(ti->level_filename); ti_copy->level_filetype = getStringCopy(ti->level_filetype); + ti_copy->special_flags = getStringCopy(ti->special_flags); + ti_copy->levels = ti->levels; ti_copy->first_level = ti->first_level; ti_copy->last_level = ti->last_level; @@ -2665,6 +2716,8 @@ static void freeTreeInfo(TreeInfo *ti) checked_free(ti->level_filename); checked_free(ti->level_filetype); + + checked_free(ti->special_flags); } checked_free(ti); @@ -2840,14 +2893,18 @@ static char *getCacheToken(char *prefix, char *suffix) return token; } -static char *getFileTimestamp(char *filename) +static char *getFileTimestampString(char *filename) { +#if 1 + return getStringCopy(i_to_a(getFileTimestampEpochSeconds(filename))); +#else struct stat file_status; if (stat(filename, &file_status) != 0) /* cannot stat file */ return getStringCopy(i_to_a(0)); return getStringCopy(i_to_a(file_status.st_mtime)); +#endif } static boolean modifiedFileTimestamp(char *filename, char *timestamp_string) @@ -2964,8 +3021,8 @@ static void setArtworkInfoCacheEntry(TreeInfo *artwork_info, LEVELINFO_FILENAME); char *filename_artworkinfo = getPath2(getSetupArtworkDir(artwork_info), ARTWORKINFO_FILENAME(type)); - char *timestamp_levelinfo = getFileTimestamp(filename_levelinfo); - char *timestamp_artworkinfo = getFileTimestamp(filename_artworkinfo); + char *timestamp_levelinfo = getFileTimestampString(filename_levelinfo); + char *timestamp_artworkinfo = getFileTimestampString(filename_artworkinfo); token_main = getCacheToken(token_prefix, "TIMESTAMP_LEVELINFO"); setHashEntry(artworkinfo_cache_new, token_main, timestamp_levelinfo); @@ -3084,6 +3141,12 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first, leveldir_new->in_user_dir = (!strEqual(leveldir_new->basepath, options.level_directory)); +#if 0 + printf("::: '%s' -> %d\n", + leveldir_new->identifier, + leveldir_new->in_user_dir); +#endif + /* adjust some settings if user's private level directory was detected */ if (leveldir_new->sort_priority == LEVELCLASS_UNDEFINED && leveldir_new->in_user_dir && diff --git a/src/libgame/setup.h b/src/libgame/setup.h index 414cf74e..b0b6a8d2 100644 --- a/src/libgame/setup.h +++ b/src/libgame/setup.h @@ -306,6 +306,8 @@ void setSetupInfo(struct TokenInfo *, int, char *); char *getSetupValue(int, void *); char *getSetupLine(struct TokenInfo *, char *, int); +unsigned int get_hash_from_key(void *); + boolean AdjustGraphicsForEMC(); void LoadLevelInfo(void); diff --git a/src/libgame/snapshot.c b/src/libgame/snapshot.c new file mode 100644 index 00000000..d28ae349 --- /dev/null +++ b/src/libgame/snapshot.c @@ -0,0 +1,55 @@ +/*********************************************************** +* Artsoft Retro-Game Library * +*----------------------------------------------------------* +* (c) 1995-2006 Artsoft Entertainment * +* Holger Schemel * +* Detmolder Strasse 189 * +* 33604 Bielefeld * +* Germany * +* e-mail: info@artsoft.org * +*----------------------------------------------------------* +* snapshot.c * +***********************************************************/ + +#include "snapshot.h" + + +static ListNode *engine_snapshot_list = NULL; + +void SaveEngineSnapshotBuffer(void *buffer, int size) +{ + struct EngineSnapshotNodeInfo *bi = + checked_calloc(sizeof(struct EngineSnapshotNodeInfo)); + + bi->buffer_orig = buffer; + bi->buffer_copy = checked_malloc(size); + bi->size = size; + + memcpy(bi->buffer_copy, buffer, size); + + addNodeToList(&engine_snapshot_list, NULL, bi); +} + +static void LoadEngineSnapshotBuffer(struct EngineSnapshotNodeInfo *bi) +{ + memcpy(bi->buffer_orig, bi->buffer_copy, bi->size); +} + +void LoadEngineSnapshotBuffers() +{ + ListNode *node = engine_snapshot_list; + + while (node != NULL) + { + LoadEngineSnapshotBuffer((struct EngineSnapshotNodeInfo *)node->content); + + node = node->next; + } +} + +void FreeEngineSnapshotBuffers() +{ + while (engine_snapshot_list != NULL) + deleteNodeFromList(&engine_snapshot_list, engine_snapshot_list->key, + checked_free); +} diff --git a/src/libgame/snapshot.h b/src/libgame/snapshot.h new file mode 100644 index 00000000..706fc054 --- /dev/null +++ b/src/libgame/snapshot.h @@ -0,0 +1,36 @@ +/*********************************************************** +* Artsoft Retro-Game Library * +*----------------------------------------------------------* +* (c) 1995-2006 Artsoft Entertainment * +* Holger Schemel * +* Detmolder Strasse 189 * +* 33604 Bielefeld * +* Germany * +* e-mail: info@artsoft.org * +*----------------------------------------------------------* +* snapshot.h * +***********************************************************/ + +#ifndef SNAPSHOT_H +#define SNAPSHOT_H + +#include "system.h" +#include "misc.h" + + +/* needed for comfortably saving engine snapshot buffers */ +#define ARGS_ADDRESS_AND_SIZEOF(x) (&(x)), (sizeof(x)) + +struct EngineSnapshotNodeInfo +{ + void *buffer_orig; + void *buffer_copy; + int size; +}; + + +void SaveEngineSnapshotBuffer(void *buffer, int size); +void LoadEngineSnapshotBuffers(); +void FreeEngineSnapshotBuffers(); + +#endif /* SNAPSHOT_H */ diff --git a/src/libgame/system.c b/src/libgame/system.c index d4b7f9a9..4b7a3cad 100644 --- a/src/libgame/system.c +++ b/src/libgame/system.c @@ -166,8 +166,10 @@ void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize, gfx.field_save_buffer = field_save_buffer; +#if 0 gfx.background_bitmap = NULL; gfx.background_bitmap_mask = REDRAW_NONE; +#endif SetDrawDeactivationMask(REDRAW_NONE); /* do not deactivate drawing */ SetDrawBackgroundMask(REDRAW_NONE); /* deactivate masked drawing */ @@ -193,6 +195,12 @@ void InitGfxWindowInfo(int win_xsize, int win_ysize) { gfx.win_xsize = win_xsize; gfx.win_ysize = win_ysize; + +#if 1 + gfx.background_bitmap_mask = REDRAW_NONE; + + ReCreateBitmap(&gfx.background_bitmap, win_xsize, win_ysize, DEFAULT_DEPTH); +#endif } void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height) @@ -203,6 +211,15 @@ void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height) gfx.scrollbuffer_height = scrollbuffer_height; } +void InitGfxClipRegion(boolean enabled, int x, int y, int width, int height) +{ + gfx.clipping_enabled = enabled; + gfx.clip_x = x; + gfx.clip_y = y; + gfx.clip_width = width; + gfx.clip_height = height; +} + void InitGfxDrawBusyAnimFunction(void (*draw_busy_anim_function)(void)) { gfx.draw_busy_anim_function = draw_busy_anim_function; @@ -259,9 +276,11 @@ void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask) else gfx.background_bitmap_mask &= ~mask; +#if 0 if (gfx.background_bitmap == NULL) gfx.background_bitmap = CreateBitmap(video.width, video.height, DEFAULT_DEPTH); +#endif if (background_bitmap_tile == NULL) /* empty background requested */ return; @@ -367,8 +386,10 @@ void InitVideoBuffer(int width, int height, int depth, boolean fullscreen) video.fullscreen_available = FULLSCREEN_STATUS; video.fullscreen_enabled = FALSE; - video.fullscreen_modes = NULL; +#if 0 video.fullscreen_mode_current = NULL; + video.fullscreen_modes = NULL; +#endif #if defined(TARGET_SDL) SDLInitVideoBuffer(&backbuffer, &window, fullscreen); @@ -379,34 +400,6 @@ void InitVideoBuffer(int width, int height, int depth, boolean fullscreen) drawto = backbuffer; } -Bitmap *CreateBitmapStruct(void) -{ -#if defined(TARGET_SDL) - return checked_calloc(sizeof(struct SDLSurfaceInfo)); -#else - return checked_calloc(sizeof(struct X11DrawableInfo)); -#endif -} - -Bitmap *CreateBitmap(int width, int height, int depth) -{ - Bitmap *new_bitmap = CreateBitmapStruct(); - int real_width = MAX(1, width); /* prevent zero bitmap width */ - int real_height = MAX(1, height); /* prevent zero bitmap height */ - int real_depth = GetRealDepth(depth); - -#if defined(TARGET_SDL) - SDLCreateBitmapContent(new_bitmap, real_width, real_height, real_depth); -#else - X11CreateBitmapContent(new_bitmap, real_width, real_height, real_depth); -#endif - - new_bitmap->width = real_width; - new_bitmap->height = real_height; - - return new_bitmap; -} - inline static void FreeBitmapPointers(Bitmap *bitmap) { if (bitmap == NULL) @@ -443,16 +436,53 @@ void FreeBitmap(Bitmap *bitmap) free(bitmap); } -void CloseWindow(DrawWindow *window) +Bitmap *CreateBitmapStruct(void) { -#if defined(TARGET_X11) - if (window->drawable) +#if defined(TARGET_SDL) + return checked_calloc(sizeof(struct SDLSurfaceInfo)); +#else + return checked_calloc(sizeof(struct X11DrawableInfo)); +#endif +} + +Bitmap *CreateBitmap(int width, int height, int depth) +{ + Bitmap *new_bitmap = CreateBitmapStruct(); + int real_width = MAX(1, width); /* prevent zero bitmap width */ + int real_height = MAX(1, height); /* prevent zero bitmap height */ + int real_depth = GetRealDepth(depth); + +#if defined(TARGET_SDL) + SDLCreateBitmapContent(new_bitmap, real_width, real_height, real_depth); +#else + X11CreateBitmapContent(new_bitmap, real_width, real_height, real_depth); +#endif + + new_bitmap->width = real_width; + new_bitmap->height = real_height; + + return new_bitmap; +} + +void ReCreateBitmap(Bitmap **bitmap, int width, int height, int depth) +{ + Bitmap *new_bitmap = CreateBitmap(width, height, depth); + + if (*bitmap == NULL) { - XUnmapWindow(display, window->drawable); - XDestroyWindow(display, window->drawable); + *bitmap = new_bitmap; } - if (window->gc) - XFreeGC(display, window->gc); + else + { + TransferBitmapPointers(new_bitmap, *bitmap); + free(new_bitmap); + } +} + +void CloseWindow(DrawWindow *window) +{ +#if defined(TARGET_X11) + X11CloseWindow(window); #endif } @@ -491,13 +521,133 @@ boolean DrawingOnBackground(int x, int y) CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask)); } +static boolean InClippedRectangle(Bitmap *bitmap, int *x, int *y, + int *width, int *height, boolean is_dest) +{ +#if 1 + int clip_x, clip_y, clip_width, clip_height; + + if (gfx.clipping_enabled && is_dest) /* only clip destination bitmap */ + { + clip_x = MIN(MAX(0, gfx.clip_x), bitmap->width); + clip_y = MIN(MAX(0, gfx.clip_y), bitmap->height); + clip_width = MIN(MAX(0, gfx.clip_width), bitmap->width - clip_x); + clip_height = MIN(MAX(0, gfx.clip_height), bitmap->height - clip_y); + } + else + { + clip_x = 0; + clip_y = 0; + clip_width = bitmap->width; + clip_height = bitmap->height; + } + + /* skip if rectangle completely outside bitmap */ + + if (*x + *width <= clip_x || + *y + *height <= clip_y || + *x >= clip_x + clip_width || + *y >= clip_y + clip_height) + return FALSE; + + /* clip if rectangle overlaps bitmap */ + + if (*x < clip_x) + { + *width -= clip_x - *x; + *x = clip_x; + } + else if (*x + *width > clip_x + clip_width) + { + *width = clip_x + clip_width - *x; + } + + if (*y < clip_y) + { + *height -= clip_y - *y; + *y = clip_y; + } + else if (*y + *height > clip_y + clip_height) + { + *height = clip_y + clip_height - *y; + } + + return TRUE; + +#else + + /* skip if rectangle completely outside bitmap */ + + if (*x + *width <= 0 || + *y + *height <= 0 || + *x >= bitmap->width || + *y >= bitmap->height) + return FALSE; + + /* clip if rectangle overlaps bitmap */ + + if (*x < 0) + { + *width += *x; + *x = 0; + } + else if (*x + *width > bitmap->width) + { + *width = bitmap->width - *x; + } + + if (*y < 0) + { + *height += *y; + *y = 0; + } + else if (*y + *height > bitmap->height) + { + *height = bitmap->height - *y; + } + + return TRUE; +#endif +} + void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap, int src_x, int src_y, int width, int height, int dst_x, int dst_y) { + int dst_x_unclipped = dst_x; + int dst_y_unclipped = dst_y; + if (DrawingDeactivated(dst_x, dst_y, width, height)) return; +#if 1 + if (!InClippedRectangle(src_bitmap, &src_x, &src_y, &width, &height, FALSE) || + !InClippedRectangle(dst_bitmap, &dst_x, &dst_y, &width, &height, TRUE)) + return; + + /* source x/y might need adjustment if destination x/y was clipped top/left */ + src_x += dst_x - dst_x_unclipped; + src_y += dst_y - dst_y_unclipped; + +#else + /* skip if rectangle starts outside bitmap */ + if (src_x >= src_bitmap->width || + src_y >= src_bitmap->height || + dst_x >= dst_bitmap->width || + dst_y >= dst_bitmap->height) + return; + + /* clip if rectangle overlaps bitmap */ + if (src_x + width > src_bitmap->width) + width = src_bitmap->width - src_x; + if (src_y + height > src_bitmap->height) + height = src_bitmap->height - src_y; + if (dst_x + width > dst_bitmap->width) + width = dst_bitmap->width - dst_x; + if (dst_y + height > dst_bitmap->height) + height = dst_bitmap->height - dst_y; +#endif + #if 0 /* !!! 2009-03-30: Fixed by using self-compiled, patched SDL.dll !!! */ /* (This bug still exists in the actual (as of 2009-06-15) version 1.2.13, @@ -559,6 +709,12 @@ void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height, int fade_mode, int fade_delay, int post_delay, void (*draw_border_function)(void)) { +#if 1 + /* (use destination bitmap "backbuffer" -- "bitmap_cross" may be undefined) */ + if (!InClippedRectangle(backbuffer, &x, &y, &width, &height, TRUE)) + return; +#endif + #if defined(TARGET_SDL) SDLFadeRectangle(bitmap_cross, x, y, width, height, fade_mode, fade_delay, post_delay, draw_border_function); @@ -574,6 +730,22 @@ void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height, if (DrawingDeactivated(x, y, width, height)) return; +#if 1 + if (!InClippedRectangle(bitmap, &x, &y, &width, &height, TRUE)) + return; +#else + /* skip if rectangle starts outside bitmap */ + if (x >= bitmap->width || + y >= bitmap->height) + return; + + /* clip if rectangle overlaps bitmap */ + if (x + width > bitmap->width) + width = bitmap->width - x; + if (y + height > bitmap->height) + height = bitmap->height - y; +#endif + sysFillRectangle(bitmap, x, y, width, height, color); } diff --git a/src/libgame/system.h b/src/libgame/system.h index aa1057fd..cbcf5c86 100644 --- a/src/libgame/system.h +++ b/src/libgame/system.h @@ -72,6 +72,14 @@ #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 @@ -199,6 +207,13 @@ #define ANIM_DEFAULT ANIM_LOOP +/* values for special drawing styles (currently only for crumbled graphics) */ +#define STYLE_NONE 0 +#define STYLE_ACCURATE_BORDERS (1 << 0) +#define STYLE_INNER_CORNERS (1 << 1) + +#define STYLE_DEFAULT STYLE_NONE + /* values for fade mode */ #define FADE_TYPE_NONE 0 #define FADE_TYPE_FADE_IN (1 << 0) @@ -650,8 +665,11 @@ struct OptionInfo char *sounds_directory; char *music_directory; char *docs_directory; + char *execute_command; + char *special_flags; + boolean serveronly; boolean network; boolean verbose; @@ -736,6 +754,10 @@ struct GfxInfo Bitmap *background_bitmap; int background_bitmap_mask; + boolean clipping_enabled; + int clip_x, clip_y; + int clip_width, clip_height; + boolean override_level_graphics; boolean override_level_sounds; boolean override_level_music; @@ -831,6 +853,16 @@ struct SetupShortcutInfo Key focus_player[MAX_PLAYERS]; Key focus_player_all; + + Key tape_eject; + Key tape_stop; + Key tape_pause; + Key tape_record; + Key tape_play; + + Key sound_simple; + Key sound_loops; + Key sound_music; }; struct SetupSystemInfo @@ -868,6 +900,7 @@ struct SetupInfo boolean input_on_focus; boolean prefer_aga_graphics; int game_frame_delay; + boolean sp_show_border_elements; char *graphics_set; char *sounds_set; @@ -922,6 +955,8 @@ struct TreeInfo char *level_filename; /* filename of level file (for packed level file) */ char *level_filetype; /* type of levels in level directory or level file */ + char *special_flags; /* flags for special actions performed on level file */ + int levels; /* number of levels in level series */ int first_level; /* first level number (to allow start with 0 or 1) */ int last_level; /* last level number (automatically calculated) */ @@ -1077,6 +1112,13 @@ struct Rect int width, height; }; +struct RectWithBorder +{ + int x, y; + int width, height; + int border_size; +}; + struct MenuPosInfo { int x, y; @@ -1148,6 +1190,7 @@ void InitGfxDoor1Info(int, int, int, int); void InitGfxDoor2Info(int, int, int, int); void InitGfxWindowInfo(int, int); void InitGfxScrollbufferInfo(int, int); +void InitGfxClipRegion(boolean, int, int, int, int); void InitGfxDrawBusyAnimFunction(void (*draw_busy_anim_function)(void)); void InitGfxCustomArtworkInfo(); void SetDrawDeactivationMask(int); @@ -1161,6 +1204,7 @@ void CloseVideoDisplay(void); void InitVideoBuffer(int, int, int, boolean); Bitmap *CreateBitmapStruct(void); Bitmap *CreateBitmap(int, int, int); +void ReCreateBitmap(Bitmap **, int, int, int); void FreeBitmap(Bitmap *); void BlitBitmap(Bitmap *, Bitmap *, int, int, int, int, int, int); void FadeRectangle(Bitmap *bitmap, int, int, int, int, int, int, int, diff --git a/src/libgame/text.c b/src/libgame/text.c index f0cdb01a..23de7cac 100644 --- a/src/libgame/text.c +++ b/src/libgame/text.c @@ -188,6 +188,22 @@ void getFontCharSource(int font_nr, char c, Bitmap **bitmap, int *x, int *y) } +/* ========================================================================= */ +/* text string helper functions */ +/* ========================================================================= */ + +int maxWordLengthInString(char *text) +{ + char *text_ptr; + int max_word_len = 0; + + for (text_ptr = text; *text_ptr; text_ptr++) + max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0); + + return max_word_len; +} + + /* ========================================================================= */ /* simple text drawing functions */ /* ========================================================================= */ @@ -728,7 +744,8 @@ static boolean getCheckedTokenValueFromString(char *string, char **token, } static void DrawTextBuffer_Flush(int x, int y, char *buffer, int font_nr, - int line_length, int cut_length, int mask_mode, + int line_length, int cut_length, + int line_spacing, int mask_mode, boolean centered, int current_line) { int buffer_len = strlen(buffer); @@ -739,7 +756,7 @@ static void DrawTextBuffer_Flush(int x, int y, char *buffer, int font_nr, (centered ? font_width * (line_length - buffer_len) / 2 : 0); int final_cut_length = MAX(0, cut_length - offset_chars); int xx = x + offset_xsize; - int yy = y + current_line * font_height; + int yy = y + current_line * (font_height + line_spacing); buffer[final_cut_length] = '\0'; @@ -751,8 +768,8 @@ static void DrawTextBuffer_Flush(int x, int y, char *buffer, int font_nr, int DrawTextBuffer(int x, int y, char *text_buffer, int font_nr, int line_length, int cut_length, int max_lines, - int mask_mode, boolean autowrap, boolean centered, - boolean parse_comments) + int line_spacing, int mask_mode, boolean autowrap, + boolean centered, boolean parse_comments) { #if 0 int font_width = getFontWidth(font_nr); @@ -808,7 +825,7 @@ int DrawTextBuffer(int x, int y, char *text_buffer, int font_nr, if (buffer_len > 0 && current_line < max_lines) { DrawTextBuffer_Flush(x, y, buffer, font_nr, line_length, cut_length, - mask_mode, centered, current_line); + line_spacing, mask_mode, centered, current_line); current_line++; @@ -876,7 +893,7 @@ int DrawTextBuffer(int x, int y, char *text_buffer, int font_nr, { #if 1 DrawTextBuffer_Flush(x, y, buffer, font_nr, line_length, cut_length, - mask_mode, centered, current_line); + line_spacing, mask_mode, centered, current_line); #else int offset_chars = (centered ? (line_length - buffer_len) / 2 : 0); int offset_xsize = @@ -907,7 +924,7 @@ int DrawTextBuffer(int x, int y, char *text_buffer, int font_nr, { #if 1 DrawTextBuffer_Flush(x, y, buffer, font_nr, line_length, cut_length, - mask_mode, centered, current_line); + line_spacing, mask_mode, centered, current_line); #else int offset_chars = (centered ? (line_length - buffer_len) / 2 : 0); int offset_xsize = @@ -932,14 +949,14 @@ int DrawTextBuffer(int x, int y, char *text_buffer, int font_nr, int DrawTextFile(int x, int y, char *filename, int font_nr, int line_length, int cut_length, int max_lines, - int mask_mode, boolean autowrap, boolean centered, - boolean parse_comments) + int line_spacing, int mask_mode, boolean autowrap, + boolean centered, boolean parse_comments) { char *text_buffer = GetTextBufferFromFile(filename, MAX_LINES_FROM_FILE); int num_lines_printed = DrawTextBuffer(x, y, text_buffer, font_nr, line_length, cut_length, max_lines, - mask_mode, autowrap, centered, - parse_comments); + line_spacing, mask_mode, autowrap, + centered, parse_comments); checked_free(text_buffer); return num_lines_printed; diff --git a/src/libgame/text.h b/src/libgame/text.h index 146648a3..1d54a716 100644 --- a/src/libgame/text.h +++ b/src/libgame/text.h @@ -73,6 +73,8 @@ int getTextWidth(char *, int); void getFontCharSource(int, char, Bitmap **, int *, int *); +int maxWordLengthInString(char *); + void DrawInitText(char *, int, int); void DrawInitTextIfNeeded(char *, int, int); void DrawInitTextExt(char *, int, int, boolean); @@ -87,9 +89,9 @@ void DrawText(int, int, char *, int); void DrawTextExt(DrawBuffer *, int, int, char *, int, int); char *GetTextBufferFromFile(char *, int); -int DrawTextBuffer(int, int, char *, int, int, int, int, int, boolean, boolean, - boolean); -int DrawTextFile(int, int, char *, int, int, int, int, int, boolean, boolean, - boolean); +int DrawTextBuffer(int, int, char *, int, int, int, int, int, int, + boolean, boolean, boolean); +int DrawTextFile(int, int, char *, int, int, int, int, int, int, + boolean, boolean, boolean); #endif /* TEXT_H */ diff --git a/src/libgame/types.h b/src/libgame/types.h index d6f49bdd..6e55364c 100644 --- a/src/libgame/types.h +++ b/src/libgame/types.h @@ -58,6 +58,14 @@ typedef unsigned char byte; #define SIGN(a) ((a) < 0 ? -1 : ((a) > 0 ? 1 : 0)) #endif +#ifndef ODD +#define ODD(a) (((a) & 1) == 1) +#endif + +#ifndef EVEN +#define EVEN(a) (((a) & 1) == 0) +#endif + #define SIZEOF_ARRAY(array, type) (sizeof(array) / sizeof(type)) #define SIZEOF_ARRAY_INT(array) SIZEOF_ARRAY(array, int) diff --git a/src/libgame/x11.c b/src/libgame/x11.c index fe022c5b..f95c3da9 100644 --- a/src/libgame/x11.c +++ b/src/libgame/x11.c @@ -40,13 +40,21 @@ void X11InitVideoDisplay(void) void X11InitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window) { + if (*window != NULL) + X11CloseWindow(*window); + *window = X11InitWindow(); XMapWindow(display, (*window)->drawable); + FlushDisplay(); /* create additional (off-screen) buffer for double-buffering */ +#if 1 + ReCreateBitmap(backbuffer, video.width, video.height, video.depth); +#else *backbuffer = CreateBitmap(video.width, video.height, video.depth); +#endif } static void X11InitDisplay() @@ -129,6 +137,9 @@ static DrawWindow *X11InitWindow() win_xpos = (screen_width - width) / 2; win_ypos = (screen_height - height) / 2; + new_window->width = width; + new_window->height = height; + new_window->drawable = XCreateSimpleWindow(display, RootWindow(display, screen), win_xpos, win_ypos, @@ -227,6 +238,20 @@ static DrawWindow *X11InitWindow() return new_window; } +void X11CloseWindow(DrawWindow *window) +{ + if (window->drawable) + { + XUnmapWindow(display, window->drawable); + XDestroyWindow(display, window->drawable); + } + + if (window->gc) + XFreeGC(display, window->gc); + + free(window); +} + void X11ZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap) { #if defined(TARGET_ALLEGRO) diff --git a/src/libgame/x11.h b/src/libgame/x11.h index 2ebaf86c..9f2efee8 100644 --- a/src/libgame/x11.h +++ b/src/libgame/x11.h @@ -333,6 +333,8 @@ struct MouseCursorInfo void X11InitVideoDisplay(void); void X11InitVideoBuffer(DrawBuffer **, DrawWindow **); +void X11CloseWindow(DrawWindow *); + void X11ZoomBitmap(Bitmap *, Bitmap *); Bitmap *X11LoadImage(char *); diff --git a/src/main.c b/src/main.c index f1ea104e..d5dbe91c 100644 --- a/src/main.c +++ b/src/main.c @@ -20,6 +20,7 @@ #include "events.h" #include "config.h" +Bitmap *bitmap_db_store; Bitmap *bitmap_db_cross; Bitmap *bitmap_db_field; Bitmap *bitmap_db_panel; @@ -39,7 +40,11 @@ SDL_Thread *server_thread; int key_joystick_mapping = 0; +#if 1 +boolean redraw[MAX_LEV_FIELDX + 2][MAX_LEV_FIELDY + 2]; +#else boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE]; +#endif int redraw_x1 = 0, redraw_y1 = 0; short Feld[MAX_LEV_FIELDX][MAX_LEV_FIELDY]; @@ -84,15 +89,33 @@ int ActiveFont[NUM_FONTS]; int lev_fieldx, lev_fieldy; int scroll_x, scroll_y; +int WIN_XSIZE = 672, WIN_YSIZE = 560; +int SCR_FIELDX = 17, SCR_FIELDY = 17; +int SX = 8, SY = 8; +int REAL_SX = 6, REAL_SY = 6; +int DX = 566, DY = 60; +int VX = 566, VY = 400; +int EX = 566, EY = 356; +int dDX, dDY; + +#if 1 +int FX, FY; +#else int FX = SX, FY = SY; +#endif int ScrollStepSize; int ScreenMovDir = MV_NONE, ScreenMovPos = 0; int ScreenGfxPos = 0; int BorderElement = EL_STEELWALL; int GameFrameDelay = GAME_FRAME_DELAY; int FfwdFrameDelay = FFWD_FRAME_DELAY; +#if 1 +int BX1, BY1; +int BX2, BY2; +#else int BX1 = 0, BY1 = 0; int BX2 = SCR_FIELDX - 1, BY2 = SCR_FIELDY - 1; +#endif int SBX_Left, SBX_Right; int SBY_Upper, SBY_Lower; int ZX, ZY; @@ -112,6 +135,7 @@ struct SetupInfo setup; struct GameInfo game; struct GlobalInfo global; struct BorderInfo border; +struct ViewportInfo viewport; struct TitleFadingInfo fading; struct TitleFadingInfo title_initial_default; struct TitleFadingInfo title_default; @@ -120,7 +144,7 @@ struct TitleMessageInfo titlemessage_initial[MAX_NUM_TITLE_MESSAGES]; struct TitleMessageInfo titlemessage_default; struct TitleMessageInfo titlemessage[MAX_NUM_TITLE_MESSAGES]; struct TitleMessageInfo readme; -struct InitInfo init; +struct InitInfo init, init_last; struct MenuInfo menu; struct DoorInfo door_1, door_2; struct PreviewInfo preview; @@ -1262,23 +1286,23 @@ struct ElementNameInfo element_name_info[MAX_NUM_ELEMENTS + 1] = }, { "sp_gravity_port_right", - "sp_port", - "gravity port (leading right)" + "sp_gravity_port", + "gravity-on/off port (leading right)" }, { "sp_gravity_port_down", - "sp_port", - "gravity port (leading down)" + "sp_gravity_port", + "gravity-on/off port (leading down)" }, { "sp_gravity_port_left", - "sp_port", - "gravity port (leading left)" + "sp_gravity_port", + "gravity-on/off port (leading left)" }, { "sp_gravity_port_up", - "sp_port", - "gravity port (leading up)" + "sp_gravity_port", + "gravity-on/off port (leading up)" }, { "sp_sniksnak", @@ -3442,43 +3466,43 @@ struct ElementNameInfo element_name_info[MAX_NUM_ELEMENTS + 1] = }, { "sp_gravity_on_port_right", - "sp_port", - "gravity on port (leading right)" + "sp_gravity_on_port", + "gravity-on port (leading right)" }, { "sp_gravity_on_port_down", - "sp_port", - "gravity on port (leading down)" + "sp_gravity_on_port", + "gravity-on port (leading down)" }, { "sp_gravity_on_port_left", - "sp_port", - "gravity on port (leading left)" + "sp_gravity_on_port", + "gravity-on port (leading left)" }, { "sp_gravity_on_port_up", - "sp_port", - "gravity on port (leading up)" + "sp_gravity_on_port", + "gravity-on port (leading up)" }, { "sp_gravity_off_port_right", - "sp_port", - "gravity off port (leading right)" + "sp_gravity_off_port", + "gravity-off port (leading right)" }, { "sp_gravity_off_port_down", - "sp_port", - "gravity off port (leading down)" + "sp_gravity_off_port", + "gravity-off port (leading down)" }, { "sp_gravity_off_port_left", - "sp_port", - "gravity off port (leading left)" + "sp_gravity_off_port", + "gravity-off port (leading left)" }, { "sp_gravity_off_port_up", - "sp_port", - "gravity off port (leading up)" + "sp_gravity_off_port", + "gravity-off port (leading up)" }, { "balloon_switch_none", @@ -4460,6 +4484,11 @@ struct ElementNameInfo element_name_info[MAX_NUM_ELEMENTS + 1] = "quicksand", "fast quicksand (with rock)" }, + { + "from_level_template", + "from_level_template", + "element taken from level template" + }, /* ----------------------------------------------------------------------- */ /* "real" (and therefore drawable) runtime elements */ diff --git a/src/main.h b/src/main.h index 68f1eed0..0933b064 100644 --- a/src/main.h +++ b/src/main.h @@ -24,14 +24,17 @@ #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 @@ -40,13 +43,17 @@ #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 @@ -940,6 +947,7 @@ #define MAX_INITIAL_INVENTORY_SIZE 8 /* often used screen positions */ +#if 0 #define SX 8 #define SY 8 #define REAL_SX (SX - 2) @@ -950,6 +958,7 @@ #define VY 400 #define EX DX #define EY (VY - 44) +#endif #define TILESIZE 32 #define TILEX TILESIZE #define TILEY TILESIZE @@ -1516,7 +1525,9 @@ #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 */ @@ -1843,12 +1854,15 @@ #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 */ @@ -1898,8 +1912,10 @@ #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 */ @@ -2005,13 +2021,13 @@ /* 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" @@ -2099,8 +2115,9 @@ #define GAME_ENGINE_TYPE_UNKNOWN LEVEL_FILE_TYPE_UNKNOWN #define GAME_ENGINE_TYPE_RND LEVEL_FILE_TYPE_RND #define GAME_ENGINE_TYPE_EM LEVEL_FILE_TYPE_EM +#define GAME_ENGINE_TYPE_SP LEVEL_FILE_TYPE_SP -#define NUM_ENGINE_TYPES 3 +#define NUM_ENGINE_TYPES 4 struct BorderInfo @@ -2240,6 +2257,14 @@ struct PreviewInfo int anim_mode; }; +struct ViewportInfo +{ + struct RectWithBorder window; + struct RectWithBorder playfield[NUM_SPECIAL_GFX_ARGS]; + struct RectWithBorder door_1[NUM_SPECIAL_GFX_ARGS]; + struct RectWithBorder door_2[NUM_SPECIAL_GFX_ARGS]; +}; + struct HiScore { char Name[MAX_PLAYER_NAME_LEN + 1]; @@ -2281,6 +2306,12 @@ struct DateInfo int year; int month; int day; + + enum + { + DATE_SRC_CLOCK, + DATE_SRC_LEVELFILE + } src; }; struct LevelInfo @@ -2291,6 +2322,7 @@ struct LevelInfo /* level stored in native format for the alternative native game engines */ struct LevelInfo_EM *native_em_level; + struct LevelInfo_SP *native_sp_level; int file_version; /* file format version the level is stored with */ int game_version; /* game release version the level was created with */ @@ -2383,6 +2415,7 @@ struct LevelInfo boolean shifted_relocation; /* no level centering when relocating player */ boolean can_pass_to_walkable; /* player can pass to empty or walkable tile */ boolean grow_into_diggable; /* amoeba can grow into anything diggable */ + boolean auto_exit_sokoban; /* automatically finish solved Sokoban levels */ boolean continuous_snapping; /* repeated snapping without releasing key */ boolean block_snap_field; /* snapping blocks field to show animation */ @@ -2680,6 +2713,9 @@ struct GraphicInfo int align, valign; /* optional setting for drawing title screens */ int sort_priority; /* optional setting for drawing title screens */ + int class; + int style; + boolean use_image_size; /* use image size as default width and height */ #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND) @@ -2756,6 +2792,7 @@ struct HelpAnimInfo }; +extern Bitmap *bitmap_db_store; extern Bitmap *bitmap_db_cross; extern Bitmap *bitmap_db_field; extern Bitmap *bitmap_db_panel; @@ -2776,7 +2813,11 @@ extern SDL_Thread *server_thread; extern int key_joystick_mapping; +#if 1 +extern boolean redraw[MAX_LEV_FIELDX + 2][MAX_LEV_FIELDY + 2]; +#else extern boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE]; +#endif extern int redraw_x1, redraw_y1; extern short Feld[MAX_LEV_FIELDX][MAX_LEV_FIELDY]; @@ -2821,6 +2862,15 @@ extern int ActiveFont[NUM_FONTS]; extern int lev_fieldx, lev_fieldy; extern int scroll_x, scroll_y; +extern int WIN_XSIZE, WIN_YSIZE; +extern int SCR_FIELDX, SCR_FIELDY; +extern int SX, SY; +extern int REAL_SX, REAL_SY; +extern int DX, DY; +extern int VX, VY; +extern int EX, EY; +extern int dDX, dDY; + extern int FX, FY; extern int ScrollStepSize; extern int ScreenMovDir, ScreenMovPos, ScreenGfxPos; @@ -2847,6 +2897,7 @@ extern struct HiScore highscore[]; extern struct TapeInfo tape; extern struct GlobalInfo global; extern struct BorderInfo border; +extern struct ViewportInfo viewport; extern struct TitleFadingInfo fading; extern struct TitleFadingInfo fading_none; extern struct TitleFadingInfo title_initial_default; @@ -2856,7 +2907,7 @@ extern struct TitleMessageInfo titlemessage_initial[]; extern struct TitleMessageInfo titlemessage_default; extern struct TitleMessageInfo titlemessage[]; extern struct TitleMessageInfo readme; -extern struct InitInfo init; +extern struct InitInfo init, init_last; extern struct MenuInfo menu; extern struct DoorInfo door_1, door_2; extern struct PreviewInfo preview; diff --git a/src/screens.c b/src/screens.c index 60bba456..db347cda 100644 --- a/src/screens.c +++ b/src/screens.c @@ -45,22 +45,25 @@ #define SETUP_MODE_SOUND 4 #define SETUP_MODE_ARTWORK 5 #define SETUP_MODE_INPUT 6 -#define SETUP_MODE_SHORTCUTS_1 7 -#define SETUP_MODE_SHORTCUTS_2 8 +#define SETUP_MODE_SHORTCUTS 7 +#define SETUP_MODE_SHORTCUTS_1 8 +#define SETUP_MODE_SHORTCUTS_2 9 +#define SETUP_MODE_SHORTCUTS_3 10 +#define SETUP_MODE_SHORTCUTS_4 11 /* sub-screens on the setup screen (generic) */ -#define SETUP_MODE_CHOOSE_ARTWORK 9 -#define SETUP_MODE_CHOOSE_OTHER 10 +#define SETUP_MODE_CHOOSE_ARTWORK 12 +#define SETUP_MODE_CHOOSE_OTHER 13 /* sub-screens on the setup screen (specific) */ -#define SETUP_MODE_CHOOSE_GAME_SPEED 11 -#define SETUP_MODE_CHOOSE_SCREEN_MODE 12 -#define SETUP_MODE_CHOOSE_SCROLL_DELAY 13 -#define SETUP_MODE_CHOOSE_GRAPHICS 14 -#define SETUP_MODE_CHOOSE_SOUNDS 15 -#define SETUP_MODE_CHOOSE_MUSIC 16 +#define SETUP_MODE_CHOOSE_GAME_SPEED 14 +#define SETUP_MODE_CHOOSE_SCREEN_MODE 15 +#define SETUP_MODE_CHOOSE_SCROLL_DELAY 16 +#define SETUP_MODE_CHOOSE_GRAPHICS 17 +#define SETUP_MODE_CHOOSE_SOUNDS 18 +#define SETUP_MODE_CHOOSE_MUSIC 19 -#define MAX_SETUP_MODES 17 +#define MAX_SETUP_MODES 20 /* for input setup functions */ #define SETUPINPUT_SCREEN_POS_START 0 @@ -232,7 +235,7 @@ static struct INFO_MODE_MAIN) #define DRAW_MODE_SETUP(i) ((i) >= SETUP_MODE_MAIN && \ - (i) <= SETUP_MODE_SHORTCUTS_2 ? (i) : \ + (i) <= SETUP_MODE_SHORTCUTS_4 ? (i) : \ (i) >= SETUP_MODE_CHOOSE_GRAPHICS && \ (i) <= SETUP_MODE_CHOOSE_MUSIC ? \ SETUP_MODE_CHOOSE_ARTWORK : \ @@ -757,10 +760,12 @@ static void InitializeTitleControls(boolean show_title_initial) num_title_screens = 0; #if 1 + /* 1st step: initialize title screens for game start (only when starting) */ if (show_title_initial) InitializeTitleControls_CheckTitleInfo(TRUE); #endif + /* 2nd step: initialize title screens for current level set */ InitializeTitleControls_CheckTitleInfo(FALSE); /* sort title screens according to sort_priority and title number */ @@ -1020,7 +1025,11 @@ static boolean insideTextPosRect(struct TextPosInfo *rect, int x, int y) static void drawCursorExt(int xpos, int ypos, boolean active, int graphic) { +#if 1 + static int cursor_array[MAX_LEV_FIELDY]; +#else static int cursor_array[SCR_FIELDY]; +#endif int x = mSX + TILEX * xpos; int y = mSY + TILEY * (MENU_SCREEN_START_YPOS + ypos); @@ -1181,7 +1190,7 @@ void DrawTitleScreenMessage(int nr, boolean initial) ClearRectangleOnBackground(drawto, 0, 0, WIN_XSIZE, WIN_YSIZE); DrawTextFile(ALIGNED_TEXT_XPOS(tmi), ALIGNED_TEXT_YPOS(tmi), - filename, tmi->font, tmi->chars, -1, tmi->lines, -1, + filename, tmi->font, tmi->chars, -1, tmi->lines, 0, -1, tmi->autowrap, tmi->centered, tmi->parse_comments); game_status = last_game_status; /* restore current game status */ @@ -1261,6 +1270,8 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading) /* store valid level series information */ leveldir_last_valid = leveldir_current; + init_last = init; /* switch to new busy animation */ + /* needed if last screen (level choice) changed graphics, sounds or music */ ReloadCustomArtwork(0); @@ -1278,6 +1289,11 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading) #endif #endif +#if 1 + /* needed if different viewport properties defined for menues */ + ChangeViewportPropertiesIfNeeded(); +#endif + #if defined(TARGET_SDL) SetDrawtoField(DRAW_BACKBUFFER); #endif @@ -1375,7 +1391,7 @@ void DrawMainMenu() DrawMainMenuExt(REDRAW_ALL, FALSE); } -#if 0 +#if defined(CREATE_SPECIAL_EDITION_RND_JUE) static void gotoTopLevelDir() { /* move upwards to top level directory */ @@ -1742,7 +1758,7 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) SaveLevelSetup_LastSeries(); SaveLevelSetup_SeriesInfo(); -#if 0 +#if defined(CREATE_SPECIAL_EDITION_RND_JUE) gotoTopLevelDir(); #endif @@ -1765,6 +1781,11 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) FadeSetEnterScreen(); +#if 0 + /* needed if different viewport properties defined for editor */ + ChangeViewportPropertiesIfNeeded(); +#endif + DrawLevelEd(); } else if (pos == MAIN_CONTROL_INFO) @@ -2235,7 +2256,7 @@ void DrawInfoScreen_HelpText(int element, int action, int direction, int ypos) sy += getFontHeight(font_nr) / 2; DrawTextBuffer(sx, sy + ypos * ystep, text, font_nr, - max_chars_per_line, -1, max_lines_per_text, -1, + max_chars_per_line, -1, max_lines_per_text, 0, -1, TRUE, FALSE, FALSE); } @@ -2637,8 +2658,15 @@ static void DrawInfoScreen_CreditsScreen(int screen_nr) "Thanks to"); DrawTextSCentered(ystart2 + 1 * ystep, FONT_TEXT_3, "David Tritscher"); +#if 1 + DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_2, + "for the code base used for the"); + DrawTextSCentered(ystart2 + 3 * ystep, FONT_TEXT_2, + "native Emerald Mine engine"); +#else DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_2, "for the new Emerald Mine engine"); +#endif } else if (screen_nr == 7) { @@ -3032,7 +3060,7 @@ void DrawInfoScreen_LevelSet() if (filename != NULL) DrawTextFile(mSX + ALIGNED_TEXT_XPOS(tmi), mSY + ALIGNED_TEXT_YPOS(tmi), - filename, tmi->font, tmi->chars, -1, tmi->lines, -1, + filename, tmi->font, tmi->chars, -1, tmi->lines, 0, -1, tmi->autowrap, tmi->centered, tmi->parse_comments); else DrawTextCentered(mSY + ALIGNED_TEXT_YPOS(tmi), FONT_TEXT_2, @@ -4072,6 +4100,13 @@ static void execSetupInput() DrawSetupScreen(); } +static void execSetupShortcuts() +{ + setup_mode = SETUP_MODE_SHORTCUTS; + + DrawSetupScreen(); +} + static void execSetupShortcuts1() { setup_mode = SETUP_MODE_SHORTCUTS_1; @@ -4086,6 +4121,20 @@ static void execSetupShortcuts2() DrawSetupScreen(); } +static void execSetupShortcuts3() +{ + setup_mode = SETUP_MODE_SHORTCUTS_3; + + DrawSetupScreen(); +} + +static void execSetupShortcuts4() +{ + setup_mode = SETUP_MODE_SHORTCUTS_4; + + DrawSetupScreen(); +} + static void execExitSetup() { game_status = GAME_MODE_MAIN; @@ -4107,8 +4156,7 @@ static struct TokenInfo setup_info_main[] = { TYPE_ENTER_MENU, execSetupSound, "Sound & Music" }, { TYPE_ENTER_MENU, execSetupArtwork, "Custom Artwork" }, { TYPE_ENTER_MENU, execSetupInput, "Input Devices" }, - { TYPE_ENTER_MENU, execSetupShortcuts1, "Key Shortcuts 1" }, - { TYPE_ENTER_MENU, execSetupShortcuts2, "Key Shortcuts 2" }, + { TYPE_ENTER_MENU, execSetupShortcuts, "Key Shortcuts" }, { TYPE_EMPTY, NULL, "" }, { TYPE_LEAVE_MENU, execExitSetup, "Exit" }, { TYPE_LEAVE_MENU, execSaveAndExitSetup, "Save and Exit" }, @@ -4184,6 +4232,7 @@ static struct TokenInfo setup_info_graphics[] = { TYPE_SWITCH, &setup.show_titlescreen,"Show Title Screens:" }, { TYPE_SWITCH, &setup.toons, "Show Toons:" }, { TYPE_ECS_AGA, &setup.prefer_aga_graphics,"EMC graphics preference:" }, + { TYPE_SWITCH, &setup.sp_show_border_elements,"Supaplex Border Elements:" }, { TYPE_EMPTY, NULL, "" }, { TYPE_LEAVE_MENU, execSetupMain, "Back" }, @@ -4253,6 +4302,18 @@ static struct TokenInfo setup_info_input[] = { 0, NULL, NULL } }; +static struct TokenInfo setup_info_shortcuts[] = +{ + { TYPE_ENTER_MENU, execSetupShortcuts1, "Various Keys" }, + { TYPE_ENTER_MENU, execSetupShortcuts2, "Player Focus" }, + { TYPE_ENTER_MENU, execSetupShortcuts3, "Tape Buttons" }, + { TYPE_ENTER_MENU, execSetupShortcuts4, "Sound & Music" }, + { TYPE_EMPTY, NULL, "" }, + { TYPE_LEAVE_MENU, execSetupMain, "Back" }, + + { 0, NULL, NULL } +}; + static struct TokenInfo setup_info_shortcuts_1[] = { { TYPE_KEYTEXT, NULL, "Quick Save Game to Tape:", }, @@ -4265,7 +4326,7 @@ static struct TokenInfo setup_info_shortcuts_1[] = { TYPE_YES_NO, &setup.ask_on_escape, "Ask on 'Esc' Key:" }, { TYPE_YES_NO, &setup.ask_on_escape_editor, "Ask on 'Esc' Key (Editor):" }, { TYPE_EMPTY, NULL, "" }, - { TYPE_LEAVE_MENU, execSetupMain, "Back" }, + { TYPE_LEAVE_MENU, execSetupShortcuts, "Back" }, { 0, NULL, NULL } }; @@ -4283,7 +4344,39 @@ static struct TokenInfo setup_info_shortcuts_2[] = { TYPE_KEYTEXT, NULL, "Set Focus to All Players:", }, { TYPE_KEY, &setup.shortcut.focus_player_all, "" }, { TYPE_EMPTY, NULL, "" }, - { TYPE_LEAVE_MENU, execSetupMain, "Back" }, + { TYPE_LEAVE_MENU, execSetupShortcuts, "Back" }, + + { 0, NULL, NULL } +}; + +static struct TokenInfo setup_info_shortcuts_3[] = +{ + { TYPE_KEYTEXT, NULL, "Tape Eject:", }, + { TYPE_KEY, &setup.shortcut.tape_eject, "" }, + { TYPE_KEYTEXT, NULL, "Tape Stop:", }, + { TYPE_KEY, &setup.shortcut.tape_stop, "" }, + { TYPE_KEYTEXT, NULL, "Tape Pause:", }, + { TYPE_KEY, &setup.shortcut.tape_pause, "" }, + { TYPE_KEYTEXT, NULL, "Tape Record:", }, + { TYPE_KEY, &setup.shortcut.tape_record, "" }, + { TYPE_KEYTEXT, NULL, "Tape Play:", }, + { TYPE_KEY, &setup.shortcut.tape_play, "" }, + { TYPE_EMPTY, NULL, "" }, + { TYPE_LEAVE_MENU, execSetupShortcuts, "Back" }, + + { 0, NULL, NULL } +}; + +static struct TokenInfo setup_info_shortcuts_4[] = +{ + { TYPE_KEYTEXT, NULL, "Sound Effects (Normal):", }, + { TYPE_KEY, &setup.shortcut.sound_simple, "" }, + { TYPE_KEYTEXT, NULL, "Sound Effects (Looping):", }, + { TYPE_KEY, &setup.shortcut.sound_loops, "" }, + { TYPE_KEYTEXT, NULL, "Music:", }, + { TYPE_KEY, &setup.shortcut.sound_music, "" }, + { TYPE_EMPTY, NULL, "" }, + { TYPE_LEAVE_MENU, execSetupShortcuts, "Back" }, { 0, NULL, NULL } }; @@ -4566,6 +4659,11 @@ static void DrawSetupScreen_Generic() setup_info = setup_info_artwork; title_string = "Custom Artwork"; } + else if (setup_mode == SETUP_MODE_SHORTCUTS) + { + setup_info = setup_info_shortcuts; + title_string = "Setup Shortcuts"; + } else if (setup_mode == SETUP_MODE_SHORTCUTS_1) { setup_info = setup_info_shortcuts_1; @@ -4576,6 +4674,16 @@ static void DrawSetupScreen_Generic() setup_info = setup_info_shortcuts_2; title_string = "Setup Shortcuts"; } + else if (setup_mode == SETUP_MODE_SHORTCUTS_3) + { + setup_info = setup_info_shortcuts_3; + title_string = "Setup Shortcuts"; + } + else if (setup_mode == SETUP_MODE_SHORTCUTS_4) + { + setup_info = setup_info_shortcuts_4; + title_string = "Setup Shortcuts"; + } DrawTextSCentered(mSY - SY + 16, FONT_TITLE_1, title_string); @@ -5574,13 +5682,21 @@ static struct { { IMG_MENU_BUTTON_UP, IMG_MENU_BUTTON_UP_ACTIVE, +#if 1 + -1, -1, /* these values are not constant, but can change at runtime */ +#else SC_SCROLL_UP_XPOS, SC_SCROLL_UP_YPOS, +#endif SCREEN_CTRL_ID_SCROLL_UP, "scroll up" }, { IMG_MENU_BUTTON_DOWN, IMG_MENU_BUTTON_DOWN_ACTIVE, +#if 1 + -1, -1, /* these values are not constant, but can change at runtime */ +#else SC_SCROLL_DOWN_XPOS, SC_SCROLL_DOWN_YPOS, +#endif SCREEN_CTRL_ID_SCROLL_DOWN, "scroll down" } @@ -5606,8 +5722,13 @@ static struct #else IMG_MENU_SCROLLBAR, IMG_MENU_SCROLLBAR_ACTIVE, #endif +#if 1 + -1, -1, /* these values are not constant, but can change at runtime */ + -1, -1, /* these values are not constant, but can change at runtime */ +#else SC_SCROLL_VERTICAL_XPOS, SC_SCROLL_VERTICAL_YPOS, SC_SCROLL_VERTICAL_XSIZE, SC_SCROLL_VERTICAL_YSIZE, +#endif GD_TYPE_SCROLLBAR_VERTICAL, SCREEN_CTRL_ID_SCROLL_VERTICAL, "scroll level series vertically" @@ -5673,6 +5794,12 @@ static void CreateScreenScrollbuttons() unsigned long event_mask; int i; + /* these values are not constant, but can change at runtime */ + scrollbutton_info[0].x = SC_SCROLL_UP_XPOS; + scrollbutton_info[0].y = SC_SCROLL_UP_YPOS; + scrollbutton_info[1].x = SC_SCROLL_DOWN_XPOS; + scrollbutton_info[1].y = SC_SCROLL_DOWN_YPOS; + for (i = 0; i < NUM_SCREEN_SCROLLBUTTONS; i++) { Bitmap *gd_bitmap_unpressed, *gd_bitmap_pressed; @@ -5728,6 +5855,12 @@ static void CreateScreenScrollbars() { int i; + /* these values are not constant, but can change at runtime */ + scrollbar_info[0].x = SC_SCROLL_VERTICAL_XPOS; + scrollbar_info[0].y = SC_SCROLL_VERTICAL_YPOS; + scrollbar_info[0].width = SC_SCROLL_VERTICAL_XSIZE; + scrollbar_info[0].height = SC_SCROLL_VERTICAL_YSIZE; + for (i = 0; i < NUM_SCREEN_SCROLLBARS; i++) { Bitmap *gd_bitmap_unpressed, *gd_bitmap_pressed; diff --git a/src/tape.c b/src/tape.c index 49f06aa3..5c90cb41 100644 --- a/src/tape.c +++ b/src/tape.c @@ -410,6 +410,12 @@ void DrawVideoDisplay(unsigned long state, unsigned long value) void DrawCompleteVideoDisplay() { +#if 0 + printf("::: %d, %d / %d, %d [%d] [%d, %d] [%d/%d]\n", + VX, VY, EX, EY, game_status, gfx.vx, gfx.vy, + tape.date, tape.length); +#endif + BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, DOOR_GFX_PAGEX3, DOOR_GFX_PAGEY2, gfx.vxsize, gfx.vysize, gfx.vx, gfx.vy); @@ -420,11 +426,38 @@ void DrawCompleteVideoDisplay() gfx.vx + VIDEO_CONTROL_XPOS, gfx.vy + VIDEO_CONTROL_YPOS); DrawVideoDisplay(VIDEO_ALL_OFF, 0); + +#if 1 + if (tape.recording) + { + DrawVideoDisplay(VIDEO_STATE_REC_ON, 0); + DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date); + DrawVideoDisplay(VIDEO_STATE_TIME_ON, tape.length_seconds); + + if (tape.pausing) + DrawVideoDisplay(VIDEO_STATE_PAUSE_ON, 0); + } + else if (tape.playing) + { + DrawVideoDisplay(VIDEO_STATE_PLAY_ON, 0); + DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date); + DrawVideoDisplay(VIDEO_STATE_TIME_ON, 0); + + if (tape.pausing) + DrawVideoDisplay(VIDEO_STATE_PAUSE_ON, 0); + } + else if (tape.date && tape.length) + { + DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date); + DrawVideoDisplay(VIDEO_STATE_TIME_ON, tape.length_seconds); + } +#else if (tape.date && tape.length) { DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date); DrawVideoDisplay(VIDEO_STATE_TIME_ON, tape.length_seconds); } +#endif BlitBitmap(drawto, bitmap_db_door, gfx.vx, gfx.vy, gfx.vxsize, gfx.vysize, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2); @@ -453,20 +486,25 @@ void TapeDeactivateDisplayOff(boolean redraw_display) /* tape control functions */ /* ========================================================================= */ -static void TapeSetDate() +void TapeSetDateFromEpochSeconds(time_t epoch_seconds) { - time_t epoch_seconds = time(NULL); - struct tm *now = localtime(&epoch_seconds); + struct tm *lt = localtime(&epoch_seconds); - tape.date = 10000 * (now->tm_year % 100) + 100 * now->tm_mon + now->tm_mday; + tape.date = 10000 * (lt->tm_year % 100) + 100 * lt->tm_mon + lt->tm_mday; +} + +void TapeSetDateFromNow() +{ + TapeSetDateFromEpochSeconds(time(NULL)); } void TapeErase() { int i; - tape.length = 0; tape.counter = 0; + tape.length = 0; + tape.length_seconds = 0; if (leveldir_current) setString(&tape.level_identifier, leveldir_current->identifier); @@ -481,7 +519,7 @@ void TapeErase() tape.game_version = GAME_VERSION_ACTUAL; tape.engine_version = level.game_version; - TapeSetDate(); + TapeSetDateFromNow(); for (i = 0; i < MAX_PLAYERS; i++) tape.player_participates[i] = FALSE; @@ -530,6 +568,7 @@ void TapeStartRecording(long random_seed) DrawVideoDisplay(VIDEO_STATE_REC_ON, 0); DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date); DrawVideoDisplay(VIDEO_STATE_TIME_ON, 0); + MapTapeWarpButton(); SetDrawDeactivationMask(REDRAW_NONE); @@ -562,7 +601,7 @@ static void TapeAppendRecording() tape.recording = TRUE; tape.changed = TRUE; - TapeSetDate(); + TapeSetDateFromNow(); DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date); DrawVideoDisplay(VIDEO_STATE_PLAY_OFF | VIDEO_STATE_REC_ON, 0); @@ -703,6 +742,7 @@ void TapeStartPlaying() DrawVideoDisplay(VIDEO_STATE_PLAY_ON, 0); DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date); DrawVideoDisplay(VIDEO_STATE_TIME_ON, 0); + MapTapeWarpButton(); SetDrawDeactivationMask(REDRAW_NONE); @@ -1295,10 +1335,8 @@ void UnmapTapeButtons() UnmapGadget(tape_gadget[i]); } -static void HandleTapeButtons(struct GadgetInfo *gi) +static void HandleTapeButtonsExt(int id) { - int id = gi->custom_id; - if (game_status != GAME_MODE_MAIN && game_status != GAME_MODE_PLAYING) return; @@ -1403,3 +1441,24 @@ static void HandleTapeButtons(struct GadgetInfo *gi) break; } } + +static void HandleTapeButtons(struct GadgetInfo *gi) +{ + HandleTapeButtonsExt(gi->custom_id); +} + +void HandleTapeButtonKeys(Key key) +{ + boolean use_extra = (tape.recording || tape.playing); + + if (key == setup.shortcut.tape_eject) + HandleTapeButtonsExt(use_extra ? TAPE_CTRL_ID_EXTRA : TAPE_CTRL_ID_EJECT); + else if (key == setup.shortcut.tape_stop) + HandleTapeButtonsExt(TAPE_CTRL_ID_STOP); + else if (key == setup.shortcut.tape_pause) + HandleTapeButtonsExt(TAPE_CTRL_ID_PAUSE); + else if (key == setup.shortcut.tape_record) + HandleTapeButtonsExt(TAPE_CTRL_ID_RECORD); + else if (key == setup.shortcut.tape_play) + HandleTapeButtonsExt(TAPE_CTRL_ID_PLAY); +} diff --git a/src/tape.h b/src/tape.h index fe636495..cafa235d 100644 --- a/src/tape.h +++ b/src/tape.h @@ -138,6 +138,9 @@ void DrawCompleteVideoDisplay(void); void TapeDeactivateDisplayOn(); void TapeDeactivateDisplayOff(boolean); +void TapeSetDateFromEpochSeconds(time_t); +void TapeSetDateFromNow(); + void TapeStartRecording(long); void TapeHaltRecording(void); void TapeStopRecording(void); @@ -162,4 +165,6 @@ void MapTapeWarpButton(); void MapTapeButtons(); void UnmapTapeButtons(); +void HandleTapeButtonKeys(Key); + #endif diff --git a/src/tools.c b/src/tools.c index e80cd996..c26996b6 100644 --- a/src/tools.c +++ b/src/tools.c @@ -14,6 +14,7 @@ #include "libgame/libgame.h" #include "tools.h" +#include "init.h" #include "game.h" #include "events.h" #include "cartoons.h" @@ -144,7 +145,17 @@ void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height) /* blit playfield from scroll buffer to normal back buffer for fading in */ BlitScreenToBitmap_EM(backbuffer); } - else if (game_status == GAME_MODE_PLAYING && !game.envelope_active) + else if (game_status == GAME_MODE_PLAYING && + level.game_engine_type == GAME_ENGINE_TYPE_SP) + { + /* currently there is no partial redraw -- always redraw whole playfield */ + RedrawPlayfield_SP(TRUE); + + /* blit playfield from scroll buffer to normal back buffer for fading in */ + BlitScreenToBitmap_SP(backbuffer); + } + else if (game_status == GAME_MODE_PLAYING && + !game.envelope_active) { if (force_redraw) { @@ -338,6 +349,10 @@ void BackToFront() if (redraw_mask & REDRAW_FIELD) { +#if 0 + printf("::: REDRAW_FIELD\n"); +#endif + if (game_status != GAME_MODE_PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER) { @@ -420,6 +435,10 @@ void BackToFront() if (redraw_mask & REDRAW_TILES) { +#if 0 + printf("::: REDRAW_TILES\n"); +#endif + for (x = 0; x < SCR_FIELDX; x++) for (y = 0 ; y < SCR_FIELDY; y++) if (redraw[redraw_x1 + x][redraw_y1 + y]) @@ -1232,14 +1251,43 @@ inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy, int y1 = y; int x2 = x + SIGN(dx); int y2 = y + SIGN(dy); +#if 0 + /* !!! DOES NOT WORK FOR SLOW MOVEMENT !!! */ + int sync_frame = GfxFrame[LEVELX(x)][LEVELY(y)]; +#else + /* movement with two-tile animations must be sync'ed with movement position, + not with current GfxFrame (which can be higher when using slow movement) */ + int anim_pos = (dx ? ABS(dx) : ABS(dy)); int anim_frames = graphic_info[graphic].anim_frames; - int sync_frame = (dx ? ABS(dx) : ABS(dy)) * anim_frames / TILESIZE; +#if 1 + /* (we also need anim_delay here for movement animations with less frames) */ + int anim_delay = graphic_info[graphic].anim_delay; + int sync_frame = anim_pos * anim_frames * anim_delay / TILESIZE; +#else + int sync_frame = anim_pos * anim_frames / TILESIZE; +#endif +#endif boolean draw_start_tile = (cut_mode != CUT_ABOVE); /* only for falling! */ boolean draw_end_tile = (cut_mode != CUT_BELOW); /* only for falling! */ /* re-calculate animation frame for two-tile movement animation */ frame = getGraphicAnimationFrame(graphic, sync_frame); +#if 0 +#if 0 + printf("::: %d, %d, %d => %d [%d]\n", + anim_pos, anim_frames, anim_delay, sync_frame, graphic); +#else + printf("::: %d, %d => %d\n", + anim_pos, anim_frames, sync_frame); +#endif +#endif + +#if 0 + printf("::: %d [%d, %d] [%d] [%d]\n", frame, sync_frame, dy, + GfxFrame[LEVELX(x)][LEVELY(y)], mask_mode); +#endif + /* check if movement start graphic inside screen area and should be drawn */ if (draw_start_tile && IN_SCR_FIELD(x1, y1)) { @@ -1403,14 +1451,205 @@ void DrawLevelFieldThruMask(int x, int y) (e) == EL_QUICKSAND_EMPTYING || \ (e) == EL_QUICKSAND_FAST_EMPTYING)) -static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame) +static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy, + int graphic) { Bitmap *src_bitmap; int src_x, src_y; + int width, height, cx, cy; int sx = SCREENX(x), sy = SCREENY(y); - int element; - int width, height, cx, cy, i; int crumbled_border_size = graphic_info[graphic].border_size; + int i; + + getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y); + + for (i = 1; i < 4; i++) + { + int dxx = (i & 1 ? dx : 0); + int dyy = (i & 2 ? dy : 0); + int xx = x + dxx; + int yy = y + dyy; + int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) : + BorderElement); + + /* check if neighbour field is of same crumble type */ + boolean same = (IS_CRUMBLED_TILE(xx, yy, element) && + graphic_info[graphic].class == + graphic_info[el_act2crm(element, ACTION_DEFAULT)].class); + + /* return if check prevents inner corner */ + if (same == (dxx == dx && dyy == dy)) + return; + } + + /* if we reach this point, we have an inner corner */ + + getGraphicSource(graphic, 1, &src_bitmap, &src_x, &src_y); + + width = crumbled_border_size; + height = crumbled_border_size; + cx = (dx > 0 ? TILEX - crumbled_border_size : 0); + cy = (dy > 0 ? TILEY - crumbled_border_size : 0); + + BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy, + width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy); +} + +static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame, + int dir) +{ + Bitmap *src_bitmap; + int src_x, src_y; + int width, height, bx, by, cx, cy; + int sx = SCREENX(x), sy = SCREENY(y); + int crumbled_border_size = graphic_info[graphic].border_size; + int i; + + getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y); + + /* draw simple, sloppy, non-corner-accurate crumbled border */ + +#if 1 + width = (dir == 1 || dir == 2 ? crumbled_border_size : TILEX); + height = (dir == 0 || dir == 3 ? crumbled_border_size : TILEY); + cx = (dir == 2 ? TILEX - crumbled_border_size : 0); + cy = (dir == 3 ? TILEY - crumbled_border_size : 0); +#else + if (dir == 1 || dir == 2) /* left or right crumbled border */ + { + width = crumbled_border_size; + height = TILEY; + cx = (dir == 2 ? TILEX - crumbled_border_size : 0); + cy = 0; + } + else /* top or bottom crumbled border */ + { + width = TILEX; + height = crumbled_border_size; + cx = 0; + cy = (dir == 3 ? TILEY - crumbled_border_size : 0); + } +#endif + + BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy, + width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy); + + /* (remaining middle border part must be at least as big as corner part) */ + if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) || + crumbled_border_size >= TILESIZE / 3) + return; + + /* correct corners of crumbled border, if needed */ + +#if 1 + for (i = -1; i <= 1; i+=2) + { + int xx = x + (dir == 0 || dir == 3 ? i : 0); + int yy = y + (dir == 1 || dir == 2 ? i : 0); + int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) : + BorderElement); + + /* check if neighbour field is of same crumble type */ + if (IS_CRUMBLED_TILE(xx, yy, element) && + graphic_info[graphic].class == + graphic_info[el_act2crm(element, ACTION_DEFAULT)].class) + { + /* no crumbled corner, but continued crumbled border */ + + int c1 = (dir == 2 || dir == 3 ? TILESIZE - crumbled_border_size : 0); + int c2 = (i == 1 ? TILESIZE - crumbled_border_size : 0); + int b1 = (i == 1 ? crumbled_border_size : + TILESIZE - 2 * crumbled_border_size); + + width = crumbled_border_size; + height = crumbled_border_size; + + if (dir == 1 || dir == 2) + { + cx = c1; + cy = c2; + bx = cx; + by = b1; + } + else + { + cx = c2; + cy = c1; + bx = b1; + by = cy; + } + + BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by, + width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy); + } + } +#else + if (dir == 1 || dir == 2) /* left or right crumbled border */ + { + for (i = -1; i <= 1; i+=2) + { + int xx = x; + int yy = y + i; + int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) : + BorderElement); + + /* check if neighbour field is of same crumble type */ + if (IS_CRUMBLED_TILE(xx, yy, element) && + graphic_info[graphic].class == + graphic_info[el_act2crm(element, ACTION_DEFAULT)].class) + { + /* no crumbled corner, but continued crumbled border */ + + width = crumbled_border_size; + height = crumbled_border_size; + cx = (dir == 2 ? TILEX - crumbled_border_size : 0); + cy = (i == 1 ? TILEY - crumbled_border_size : 0); + bx = cx; + by = (i == 1 ? crumbled_border_size : + TILEY - 2 * crumbled_border_size); + + BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by, + width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy); + } + } + } + else /* top or bottom crumbled border */ + { + for (i = -1; i <= 1; i+=2) + { + int xx = x + i; + int yy = y; + int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) : + BorderElement); + + /* check if neighbour field is of same crumble type */ + if (IS_CRUMBLED_TILE(xx, yy, element) && + graphic_info[graphic].class == + graphic_info[el_act2crm(element, ACTION_DEFAULT)].class) + { + /* no crumbled corner, but continued crumbled border */ + + width = crumbled_border_size; + height = crumbled_border_size; + cx = (i == 1 ? TILEX - crumbled_border_size : 0); + cy = (dir == 3 ? TILEY - crumbled_border_size : 0); + bx = (i == 1 ? crumbled_border_size : + TILEX - 2 * crumbled_border_size); + by = cy; + + BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by, + width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy); + } + } + } +#endif +} + +static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame) +{ + int sx = SCREENX(x), sy = SCREENY(y); + int element; + int i; static int xy[4][2] = { { 0, -1 }, @@ -1425,17 +1664,11 @@ static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame) element = TILE_GFX_ELEMENT(x, y); /* crumble field itself */ -#if 1 if (IS_CRUMBLED_TILE(x, y, element)) -#else - if (GFX_CRUMBLED(element) && !IS_MOVING(x, y)) -#endif { if (!IN_SCR_FIELD(sx, sy)) return; - getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y); - for (i = 0; i < 4; i++) { int xx = x + xy[i][0]; @@ -1444,37 +1677,35 @@ static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame) element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) : BorderElement); - /* check if neighbour field is of same type */ + /* check if neighbour field is of same crumble type */ #if 1 - if (IS_CRUMBLED_TILE(xx, yy, element)) + if (IS_CRUMBLED_TILE(xx, yy, element) && + graphic_info[graphic].class == + graphic_info[el_act2crm(element, ACTION_DEFAULT)].class) continue; #else - if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy)) + if (IS_CRUMBLED_TILE(xx, yy, element)) continue; #endif - if (i == 1 || i == 2) - { - width = crumbled_border_size; - height = TILEY; - cx = (i == 2 ? TILEX - crumbled_border_size : 0); - cy = 0; - } - else + DrawLevelFieldCrumbledBorders(x, y, graphic, frame, i); + } + + if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) && + graphic_info[graphic].anim_frames == 2) + { + for (i = 0; i < 4; i++) { - width = TILEX; - height = crumbled_border_size; - cx = 0; - cy = (i == 3 ? TILEY - crumbled_border_size : 0); - } + int dx = (i & 1 ? +1 : -1); + int dy = (i & 2 ? +1 : -1); - BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy, - width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy); + DrawLevelFieldCrumbledInnerCorners(x, y, dx, dy, graphic); + } } MarkTileDirty(sx, sy); } - else /* crumble neighbour fields */ + else /* center field not crumbled -- crumble neighbour fields */ { for (i = 0; i < 4; i++) { @@ -1483,59 +1714,28 @@ static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame) int sxx = sx + xy[i][0]; int syy = sy + xy[i][1]; -#if 1 if (!IN_LEV_FIELD(xx, yy) || !IN_SCR_FIELD(sxx, syy)) continue; -#else - if (!IN_LEV_FIELD(xx, yy) || - !IN_SCR_FIELD(sxx, syy) || - IS_MOVING(xx, yy)) - continue; -#endif if (Feld[xx][yy] == EL_ELEMENT_SNAPPING) continue; element = TILE_GFX_ELEMENT(xx, yy); -#if 1 if (!IS_CRUMBLED_TILE(xx, yy, element)) continue; -#else - if (!GFX_CRUMBLED(element)) - continue; -#endif graphic = el_act2crm(element, ACTION_DEFAULT); - crumbled_border_size = graphic_info[graphic].border_size; - getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y); - - if (i == 1 || i == 2) - { - width = crumbled_border_size; - height = TILEY; - cx = (i == 1 ? TILEX - crumbled_border_size : 0); - cy = 0; - } - else - { - width = TILEX; - height = crumbled_border_size; - cx = 0; - cy = (i == 0 ? TILEY - crumbled_border_size : 0); - } - - BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy, - width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy); + DrawLevelFieldCrumbledBorders(xx, yy, graphic, 0, 3 - i); MarkTileDirty(sxx, syy); } } } -void DrawLevelFieldCrumbledSand(int x, int y) +void DrawLevelFieldCrumbled(int x, int y) { int graphic; @@ -1554,7 +1754,7 @@ void DrawLevelFieldCrumbledSand(int x, int y) GfxElement[x][y] != EL_UNDEFINED && GFX_CRUMBLED(GfxElement[x][y])) { - DrawLevelFieldCrumbledSandDigging(x, y, GfxDir[x][y], GfxFrame[x][y]); + DrawLevelFieldCrumbledDigging(x, y, GfxDir[x][y], GfxFrame[x][y]); return; } @@ -1566,11 +1766,11 @@ void DrawLevelFieldCrumbledSand(int x, int y) graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT); #endif - DrawLevelFieldCrumbledSandExt(x, y, graphic, 0); + DrawLevelFieldCrumbledExt(x, y, graphic, 0); } -void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction, - int step_frame) +void DrawLevelFieldCrumbledDigging(int x, int y, int direction, + int step_frame) { int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction); int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction); @@ -1579,10 +1779,10 @@ void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction, int sx = SCREENX(x), sy = SCREENY(y); DrawGraphic(sx, sy, graphic1, frame1); - DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2); + DrawLevelFieldCrumbledExt(x, y, graphic2, frame2); } -void DrawLevelFieldCrumbledSandNeighbours(int x, int y) +void DrawLevelFieldCrumbledNeighbours(int x, int y) { int sx = SCREENX(x), sy = SCREENY(y); static int xy[4][2] = @@ -1637,7 +1837,7 @@ static int getBorderElement(int x, int y) void DrawScreenElement(int x, int y, int element) { DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING); - DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y)); + DrawLevelFieldCrumbled(LEVELX(x), LEVELY(y)); } void DrawLevelElement(int x, int y, int element) @@ -1899,7 +2099,7 @@ void AnimateEnvelope(int envelope_nr, int anim_mode, int action) #if 1 DrawTextBuffer(SX + sx + font_width, SY + sy + font_height, level.envelope[envelope_nr].text, font_nr, max_xsize, - xsize - 2, ysize - 2, mask_mode, + xsize - 2, ysize - 2, 0, mask_mode, level.envelope[envelope_nr].autowrap, level.envelope[envelope_nr].centered, FALSE); #else @@ -1915,6 +2115,182 @@ void AnimateEnvelope(int envelope_nr, int anim_mode, int action) } } +void AnimateEnvelopeDoor(char *text, int anim_mode, int action) +{ +#if 1 + int envelope_nr = 0; +#endif + int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr; + Bitmap *src_bitmap = graphic_info[graphic].bitmap; + int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND); + boolean ffwd_delay = (tape.playing && tape.fast_forward); + boolean no_delay = (tape.warp_forward); + unsigned long anim_delay = 0; + int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay); + int anim_delay_value = (no_delay ? 0 : frame_delay_value); +#if 1 + int max_word_len = maxWordLengthInString(text); + int font_nr = (max_word_len > 7 ? FONT_TEXT_1 : FONT_TEXT_2); +#else + int font_nr = FONT_ENVELOPE_1 + envelope_nr; +#endif + int font_width = getFontWidth(font_nr); + int font_height = getFontHeight(font_nr); +#if 1 + +#if 1 + int max_xsize = DXSIZE / font_width; + int max_ysize = DYSIZE / font_height; +#else + int max_xsize = 7; /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */ + int max_ysize = 13; /* tools.c: MAX_REQUEST_LINES == 13 */ +#endif + +#else + int max_xsize = level.envelope[envelope_nr].xsize; + int max_ysize = level.envelope[envelope_nr].ysize; +#endif + int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0); + int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0); + int xend = max_xsize; + int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0); + int xstep = (xstart < xend ? 1 : 0); + int ystep = (ystart < yend || xstep == 0 ? 1 : 0); + int x, y; + +#if 1 + char *text_ptr; + char *text_copy = getStringCopy(text); +#else +#if 1 + font_nr = FONT_TEXT_2; + + if (maxWordLengthInString(text) > 7) /* MAX_REQUEST_LINE_FONT1_LEN == 7 */ + { + max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */ + font_nr = FONT_TEXT_1; + } +#else + int max_word_len = 0; + char *text_ptr; + char *text_copy = getStringCopy(text); + + font_nr = FONT_TEXT_2; + + for (text_ptr = text; *text_ptr; text_ptr++) + { + max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0); + + if (max_word_len > 7) /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */ + { + max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */ + font_nr = FONT_TEXT_1; + + break; + } + } +#endif +#endif + +#if 1 + for (text_ptr = text_copy; *text_ptr; text_ptr++) + if (*text_ptr == ' ') + *text_ptr = '\n'; +#endif + +#if 1 + dDX = SX + (SXSIZE - DXSIZE) / 2 - DX; + dDY = SY + (SYSIZE - DYSIZE) / 2 - DY; +#else + dDX = SX + SXSIZE / 2 - max_xsize * font_width / 2 - DX; + dDY = SY + SYSIZE / 2 - max_ysize * font_height / 2 - DY; +#endif + + for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep) + { + int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2; + int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2; + int sx = (SXSIZE - xsize * font_width) / 2; + int sy = (SYSIZE - ysize * font_height) / 2; + int xx, yy; + +#if 1 + BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); +#else + SetDrawtoField(DRAW_BUFFERED); + + BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY); + + SetDrawtoField(DRAW_BACKBUFFER); +#endif + + for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++) + DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr); + +#if 1 + +#if 1 + DrawTextBuffer(SX + sx + font_width, SY + sy + font_height + 8, + text_copy, font_nr, max_xsize, + xsize - 2, ysize - 2, 2, mask_mode, + FALSE, TRUE, FALSE); +#else + DrawTextBuffer(SX + sx + font_width, SY + sy + font_height, + level.envelope[envelope_nr].text, font_nr, max_xsize, + xsize - 2, ysize - 2, 0, mask_mode, + level.envelope[envelope_nr].autowrap, + level.envelope[envelope_nr].centered, FALSE); +#endif + +#else + DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height, + level.envelope[envelope_nr].text, font_nr, max_xsize, + xsize - 2, ysize - 2, mask_mode); +#endif + + /* copy request gadgets to door backbuffer */ +#if 1 + if ((ysize - 2) > 13) + BlitBitmap(bitmap_db_door, drawto, + DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2, + DOOR_GFX_PAGEY1 + 13 * font_height, + (xsize - 2) * font_width, + (ysize - 2 - 13) * font_height, + SX + sx + font_width, + SY + sy + font_height * (1 + 13)); +#else + if ((ysize - 2) > 13) + BlitBitmap(bitmap_db_door, drawto, + DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2, + DOOR_GFX_PAGEY1 + 13 * font_height, + (xsize - 2) * font_width, + (ysize - 2 - 13) * font_height, + SX + sx + font_width, + SY + sy + font_height * (1 + 13)); +#endif + +#if 1 + redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER; + // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER; +#else + redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER; +#endif + +#if 1 + DoAnimation(); + BackToFront(); +#else + BackToFront(); +#endif + + WaitUntilDelayReached(&anim_delay, anim_delay_value / 2); + } + +#if 1 + free(text_copy); +#endif +} + void ShowEnvelope(int envelope_nr) { int element = EL_ENVELOPE_1 + envelope_nr; @@ -1931,32 +2307,150 @@ void ShowEnvelope(int envelope_nr) game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */ - PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE); + PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE); + + if (anim_mode == ANIM_DEFAULT) + AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING); + + AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING); + + if (tape.playing) + Delay(wait_delay_value); + else + WaitForEventToContinue(); + + PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE); + + if (anim_mode != ANIM_NONE) + AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING); + + if (anim_mode == ANIM_DEFAULT) + AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING); + + game.envelope_active = FALSE; + + SetDrawtoField(DRAW_BUFFERED); + + redraw_mask |= REDRAW_FIELD; + BackToFront(); +} + +void ShowEnvelopeDoor(char *text, int action) +{ +#if 1 + int last_game_status = game_status; /* save current game status */ + // int last_draw_background_mask = gfx.draw_background_mask; + int envelope_nr = 0; +#endif + int element = EL_ENVELOPE_1 + envelope_nr; + int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr; + int sound_opening = element_info[element].sound[ACTION_OPENING]; + int sound_closing = element_info[element].sound[ACTION_CLOSING]; +#if 0 + boolean ffwd_delay = (tape.playing && tape.fast_forward); + boolean no_delay = (tape.warp_forward); + int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1); + int wait_delay_value = (no_delay ? 0 : normal_delay_value); +#endif + int anim_mode = graphic_info[graphic].anim_mode; + int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL: + anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode); + +#if 1 + if (game_status == GAME_MODE_PLAYING) + { + if (level.game_engine_type == GAME_ENGINE_TYPE_EM) + BlitScreenToBitmap_EM(backbuffer); + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + BlitScreenToBitmap_SP(backbuffer); + else + { + BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY); + } + } + + SetDrawtoField(DRAW_BACKBUFFER); + + // SetDrawBackgroundMask(REDRAW_NONE); + + if (action == ACTION_OPENING) + { + BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); + + if (game_status != GAME_MODE_MAIN) + InitAnimation(); + } + + /* force DOOR font inside door area */ + game_status = GAME_MODE_PSEUDO_DOOR; +#endif + + game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */ + + if (action == ACTION_OPENING) + { + PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE); - if (anim_mode == ANIM_DEFAULT) - AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING); + if (anim_mode == ANIM_DEFAULT) + AnimateEnvelopeDoor(text, ANIM_DEFAULT, ACTION_OPENING); - AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING); + AnimateEnvelopeDoor(text, main_anim_mode, ACTION_OPENING); - if (tape.playing) - Delay(wait_delay_value); +#if 0 + if (tape.playing) + Delay(wait_delay_value); + else + WaitForEventToContinue(); +#endif + } else - WaitForEventToContinue(); - - PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE); + { + PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE); - if (anim_mode != ANIM_NONE) - AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING); + if (anim_mode != ANIM_NONE) + AnimateEnvelopeDoor(text, main_anim_mode, ACTION_CLOSING); - if (anim_mode == ANIM_DEFAULT) - AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING); + if (anim_mode == ANIM_DEFAULT) + AnimateEnvelopeDoor(text, ANIM_DEFAULT, ACTION_CLOSING); + } game.envelope_active = FALSE; +#if 1 + game_status = last_game_status; /* restore current game status */ + + if (action == ACTION_CLOSING) + { + if (game_status != GAME_MODE_MAIN) + StopAnimation(); + + BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); + } +#else SetDrawtoField(DRAW_BUFFERED); +#endif + // SetDrawBackgroundMask(last_draw_background_mask); + +#if 1 + redraw_mask = REDRAW_FIELD; + // redraw_mask |= REDRAW_ALL; +#else redraw_mask |= REDRAW_FIELD; +#endif + +#if 1 + if (game_status == GAME_MODE_MAIN) + DoAnimation(); + + BackToFront(); + + if (game_status == GAME_MODE_PLAYING && + level.game_engine_type == GAME_ENGINE_TYPE_RND) + SetDrawtoField(DRAW_BUFFERED); +#else BackToFront(); +#endif } void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize) @@ -2371,10 +2865,10 @@ inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic) #if 1 if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y))) - DrawLevelFieldCrumbledSand(x, y); + DrawLevelFieldCrumbled(x, y); #else if (GFX_CRUMBLED(Feld[x][y])) - DrawLevelFieldCrumbledSand(x, y); + DrawLevelFieldCrumbled(x, y); #endif } @@ -2394,7 +2888,7 @@ void DrawLevelElementAnimationIfNeeded(int x, int y, int element) DrawGraphicAnimation(sx, sy, graphic); if (GFX_CRUMBLED(element)) - DrawLevelFieldCrumbledSand(x, y); + DrawLevelFieldCrumbled(x, y); } static int getPlayerGraphic(struct PlayerInfo *player, int move_dir) @@ -2451,6 +2945,8 @@ void DrawPlayerField(int x, int y) DrawPlayer(PLAYERINFO(x, y)); } +#define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1 + void DrawPlayer(struct PlayerInfo *player) { int jx = player->jx; @@ -2564,7 +3060,7 @@ void DrawPlayer(struct PlayerInfo *player) int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame); if (GFX_CRUMBLED(old_element)) - DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame); + DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame); else DrawGraphic(sx, sy, old_graphic, frame); @@ -2590,6 +3086,7 @@ void DrawPlayer(struct PlayerInfo *player) } } +#if !DRAW_PLAYER_OVER_PUSHED_ELEMENT /* ----------------------------------------------------------------------- */ /* draw player himself */ /* ----------------------------------------------------------------------- */ @@ -2627,6 +3124,17 @@ void DrawPlayer(struct PlayerInfo *player) DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING); } +#endif + +#if DRAW_PLAYER_OVER_PUSHED_ELEMENT + if (player->GfxPos) + { + if (move_dir == MV_LEFT || move_dir == MV_RIGHT) + sxx = player->GfxPos; + else + syy = player->GfxPos; + } +#endif /* ----------------------------------------------------------------------- */ /* draw things the player is pushing, if needed */ @@ -2666,11 +3174,90 @@ void DrawPlayer(struct PlayerInfo *player) #endif /* draw background element under pushed element (like the Sokoban field) */ +#if 1 + if (game.use_masked_pushing && IS_MOVING(jx, jy)) + { + /* this allows transparent pushing animation over non-black background */ + + if (Back[jx][jy]) + DrawLevelElement(jx, jy, Back[jx][jy]); + else + DrawLevelElement(jx, jy, EL_EMPTY); + + if (Back[next_jx][next_jy]) + DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]); + else + DrawLevelElement(next_jx, next_jy, EL_EMPTY); + } + else if (Back[next_jx][next_jy]) + DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]); +#else if (Back[next_jx][next_jy]) DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]); +#endif + +#if 0 + printf("::: %d, %d, %d, %d [%d] [%d, %d, %d] [%d] [%d, %d] [%d, %d]\n", + jx, px, player->GfxPos, player->StepFrame, + player->is_pushing, + dx, sxx, pxx, + IS_MOVING(jx, jy), + graphic, frame, + GfxFrame[jx][jy], GfxFrame[next_jx][next_jy]); +#endif +#if 1 + /* do not draw (EM style) pushing animation when pushing is finished */ + /* (two-tile animations usually do not contain start and end frame) */ + if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy)) + DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]); + else + DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING); +#else /* masked drawing is needed for EMC style (double) movement graphics */ + /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */ DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING); +#endif + } +#endif + +#if DRAW_PLAYER_OVER_PUSHED_ELEMENT + /* ----------------------------------------------------------------------- */ + /* draw player himself */ + /* ----------------------------------------------------------------------- */ + + graphic = getPlayerGraphic(player, move_dir); + + /* in the case of changed player action or direction, prevent the current + animation frame from being restarted for identical animations */ + if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic)) + player->Frame = last_player_frame; + + frame = getGraphicAnimationFrame(graphic, player->Frame); + + if (player->GfxPos) + { + if (move_dir == MV_LEFT || move_dir == MV_RIGHT) + sxx = player->GfxPos; + else + syy = player->GfxPos; + } + + if (!setup.soft_scrolling && ScreenMovPos) + sxx = syy = 0; + + if (player_is_opaque) + DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING); + else + DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING); + + if (SHIELD_ON(player)) + { + int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE : + IMG_SHIELD_NORMAL_ACTIVE); + int frame = getGraphicAnimationFrame(graphic, -1); + + DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING); } #endif @@ -2791,9 +3378,20 @@ boolean Request(char *text, unsigned int req_state) int last_game_status = game_status; /* save current game status */ int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN; int font_nr = FONT_TEXT_2; + boolean use_envelope_request = TRUE * 0; +#if 0 int max_word_len = 0; +#endif char *text_ptr; + int i; +#if 1 + if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN) + { + max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN; + font_nr = FONT_TEXT_1; + } +#else for (text_ptr = text; *text_ptr; text_ptr++) { max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0); @@ -2810,10 +3408,15 @@ boolean Request(char *text, unsigned int req_state) break; } } +#endif - if (game_status == GAME_MODE_PLAYING && - level.game_engine_type == GAME_ENGINE_TYPE_EM) - BlitScreenToBitmap_EM(backbuffer); + if (game_status == GAME_MODE_PLAYING) + { + if (level.game_engine_type == GAME_ENGINE_TYPE_EM) + BlitScreenToBitmap_EM(backbuffer); + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + BlitScreenToBitmap_SP(backbuffer); + } /* disable deactivated drawing when quick-loading level tape recording */ if (tape.playing && tape.deactivate_display) @@ -2837,7 +3440,11 @@ boolean Request(char *text, unsigned int req_state) UnmapAllGadgets(); +#if 1 + if (old_door_state & DOOR_OPEN_1 && !use_envelope_request) +#else if (old_door_state & DOOR_OPEN_1) +#endif { CloseDoor(DOOR_CLOSE_1); @@ -2860,40 +3467,49 @@ boolean Request(char *text, unsigned int req_state) game_status = GAME_MODE_PSEUDO_DOOR; /* write text for request */ - for (ty = 0; ty < MAX_REQUEST_LINES; ty++) + for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++) { char text_line[max_request_line_len + 1]; int tx, tl, tc = 0; - if (!*text) + if (!*text_ptr) break; for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++) { - tc = *(text + tx); + tc = *(text_ptr + tx); if (!tc || tc == ' ') break; } if (!tl) { - text++; + text_ptr++; ty--; continue; } - strncpy(text_line, text, tl); + strncpy(text_line, text_ptr, tl); text_line[tl] = 0; DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2, DY + 8 + ty * (getFontHeight(font_nr) + 2), text_line, font_nr); - text += tl + (tc == ' ' ? 1 : 0); + text_ptr += tl + (tc == ' ' ? 1 : 0); } game_status = last_game_status; /* restore current game status */ +#if 1 + if (use_envelope_request) + { + /* !!! TMP !!! */ + FreeToolButtons(); + CreateToolButtons(); + } +#endif + if (req_state & REQ_ASK) { MapGadget(tool_gadget[TOOL_CTRL_ID_YES]); @@ -2916,7 +3532,36 @@ boolean Request(char *text, unsigned int req_state) DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1); +#if 1 + if (use_envelope_request) + { + ShowEnvelopeDoor(text, ACTION_OPENING); + + for (i = 0; i < NUM_TOOL_BUTTONS; i++) + { + if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES || + i == TOOL_CTRL_ID_NO)) || + (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) || + (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 && + i == TOOL_CTRL_ID_PLAYER_2 && + i == TOOL_CTRL_ID_PLAYER_3 && + i == TOOL_CTRL_ID_PLAYER_4))) + { + int x = tool_gadget[i]->x + dDX; + int y = tool_gadget[i]->y + dDY; + + ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END); + } + } + } +#endif + +#if 1 + if (!use_envelope_request) + OpenDoor(DOOR_OPEN_1); +#else OpenDoor(DOOR_OPEN_1); +#endif if (!(req_state & REQUEST_WAIT_FOR_INPUT)) { @@ -2933,8 +3578,13 @@ boolean Request(char *text, unsigned int req_state) return FALSE; } +#if 1 + if (game_status != GAME_MODE_MAIN && !use_envelope_request) + InitAnimation(); +#else if (game_status != GAME_MODE_MAIN) InitAnimation(); +#endif button_status = MB_RELEASED; @@ -3093,7 +3743,16 @@ boolean Request(char *text, unsigned int req_state) UnmapToolButtons(); +#if 1 + if (use_envelope_request) + ShowEnvelopeDoor(text, ACTION_CLOSING); +#endif + +#if 1 + if (!(req_state & REQ_STAY_OPEN) && !use_envelope_request) +#else if (!(req_state & REQ_STAY_OPEN)) +#endif { CloseDoor(DOOR_CLOSE_1); @@ -5764,6 +6423,52 @@ int map_direction_EM_to_RND(int direction) MV_NONE); } +int map_element_RND_to_SP(int element_rnd) +{ + int element_sp = 0x20; /* map unknown elements to yellow "hardware" */ + + if (element_rnd >= EL_SP_START && + element_rnd <= EL_SP_END) + element_sp = element_rnd - EL_SP_START; + else if (element_rnd == EL_EMPTY_SPACE) + element_sp = 0x00; + else if (element_rnd == EL_INVISIBLE_WALL) + element_sp = 0x28; + + return element_sp; +} + +int map_element_SP_to_RND(int element_sp) +{ + int element_rnd = EL_UNKNOWN; + + if (element_sp >= 0x00 && + element_sp <= 0x27) + element_rnd = EL_SP_START + element_sp; + else if (element_sp == 0x28) + element_rnd = EL_INVISIBLE_WALL; + + return element_rnd; +} + +int map_action_SP_to_RND(int action_sp) +{ + switch (action_sp) + { + case actActive: return ACTION_ACTIVE; + case actImpact: return ACTION_IMPACT; + case actExploding: return ACTION_EXPLODING; + case actDigging: return ACTION_DIGGING; + case actSnapping: return ACTION_SNAPPING; + case actCollecting: return ACTION_COLLECTING; + case actPassing: return ACTION_PASSING; + case actPushing: return ACTION_PUSHING; + case actDropping: return ACTION_DROPPING; + + default: return ACTION_DEFAULT; + } +} + int get_next_element(int element) { switch (element) @@ -6044,6 +6749,8 @@ unsigned int InitRND(long seed) { if (level.game_engine_type == GAME_ENGINE_TYPE_EM) return InitEngineRandom_EM(seed); + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + return InitEngineRandom_SP(seed); else return InitEngineRandom_RND(seed); } @@ -6070,6 +6777,12 @@ inline static int get_effective_element_EM(int tile, int frame_em) case Yacid_splash_wB: return (frame_em > 5 ? EL_EMPTY : element); +#if 0 + case Ydiamond_stone: + // if (!game.use_native_emc_graphics_engine) + return EL_ROCK; +#endif + default: return element; } @@ -6147,6 +6860,11 @@ inline static boolean check_linear_animation_EM(int tile) case Ytank_s_e: case Ytank_w_s: case Ytank_n_w: +#if 1 + case Yacid_splash_eB: + case Yacid_splash_wB: + case Yemerald_stone: +#endif return TRUE; } @@ -6755,6 +7473,23 @@ void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em, #endif +#if 0 + if (tile == Ydiamond_stone) + printf("::: stone smashing diamond... %d: %d, %d, %d, %d, %d -> %d [%d, %d, %d, %d, %d, %d] [%d]\n", + frame_em, + g->anim_frames, + g->anim_delay, + g->anim_mode, + g->anim_start_frame, + sync_frame, + frame, + g_em->src_x, g_em->src_y, + g_em->src_offset_x, g_em->src_offset_y, + g_em->dst_offset_x, g_em->dst_offset_y, + graphic); +#endif + + #if 0 return; #endif @@ -7597,6 +8332,51 @@ void InitGraphicInfo_EM(void) #endif } +void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame, + boolean any_player_moving) +{ + int i; + + if (tape.single_step && tape.recording && !tape.pausing) + { + boolean active_players = FALSE; + + for (i = 0; i < MAX_PLAYERS; i++) + if (action[i] != JOY_NO_ACTION) + active_players = TRUE; + + if (frame == 0) + TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); + } +} + +void CheckSingleStepMode_SP(boolean murphy_is_moving) +{ + if (tape.single_step && tape.recording && !tape.pausing) + { + if (!murphy_is_moving) + TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); + } +} + +void getGraphicSource_SP(struct GraphicInfo_SP *g_sp, + int graphic, int sync_frame, int x, int y) +{ + int frame = getGraphicAnimationFrame(graphic, sync_frame); + + getGraphicSource(graphic, frame, &g_sp->bitmap, &g_sp->src_x, &g_sp->src_y); +} + +boolean isNextAnimationFrame_SP(int graphic, int sync_frame) +{ + return (IS_NEXT_FRAME(sync_frame, graphic)); +} + +int getGraphicInfo_Delay(int graphic) +{ + return graphic_info[graphic].anim_delay; +} + void PlayMenuSoundExt(int sound) { if (sound == SND_UNDEFINED) @@ -7691,30 +8471,16 @@ void ToggleFullscreenIfNeeded() if (!video.fullscreen_available) return; -#if 1 if (change_fullscreen || change_fullscreen_mode) -#else - if (setup.fullscreen != video.fullscreen_enabled || - setup.fullscreen_mode != video.fullscreen_mode_current) -#endif { Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH); /* save backbuffer content which gets lost when toggling fullscreen mode */ BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); -#if 1 if (change_fullscreen_mode) -#else - if (setup.fullscreen && video.fullscreen_enabled) -#endif { /* keep fullscreen, but change fullscreen mode (screen resolution) */ -#if 1 - /* (this is now set in sdl.c) */ -#else - video.fullscreen_mode_current = setup.fullscreen_mode; -#endif video.fullscreen_enabled = FALSE; /* force new fullscreen mode */ } @@ -7736,3 +8502,81 @@ void ToggleFullscreenIfNeeded() #endif } } + +void ChangeViewportPropertiesIfNeeded() +{ + int *door_1_x = &DX; + int *door_1_y = &DY; + int *door_2_x = (game_status == GAME_MODE_EDITOR ? &EX : &VX); + int *door_2_y = (game_status == GAME_MODE_EDITOR ? &EY : &VY); + int gfx_game_mode = (game_status == GAME_MODE_PLAYING || + game_status == GAME_MODE_EDITOR ? game_status : + GAME_MODE_MAIN); + struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode]; + struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode]; + struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode]; + int border_size = vp_playfield->border_size; + int new_sx = vp_playfield->x + border_size; + int new_sy = vp_playfield->y + border_size; + int new_scr_fieldx = (vp_playfield->width - 2 * border_size) / TILESIZE; + int new_scr_fieldy = (vp_playfield->height - 2 * border_size) / TILESIZE; + +#if 0 + /* !!! TEST ONLY !!! */ + // InitGfxBuffers(); + return; +#endif + + if (viewport.window.width != WIN_XSIZE || + viewport.window.height != WIN_YSIZE) + { + WIN_XSIZE = viewport.window.width; + WIN_YSIZE = viewport.window.height; + + InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen); + InitGfxBuffers(); + +#if 1 + SetDrawDeactivationMask(REDRAW_NONE); + SetDrawBackgroundMask(REDRAW_FIELD); + + // RedrawBackground(); +#endif + } + + if (new_scr_fieldx != SCR_FIELDX || + new_scr_fieldy != SCR_FIELDY || + new_sx != SX || + new_sy != SY || + vp_playfield->x != REAL_SX || + vp_playfield->y != REAL_SY || + vp_door_1->x != *door_1_x || + vp_door_1->y != *door_1_y || + vp_door_2->x != *door_2_x || + vp_door_2->y != *door_2_y) + { + SCR_FIELDX = new_scr_fieldx; + SCR_FIELDY = new_scr_fieldy; + SX = new_sx; + SY = new_sy; + REAL_SX = vp_playfield->x; + REAL_SY = vp_playfield->y; + + *door_1_x = vp_door_1->x; + *door_1_y = vp_door_1->y; + *door_2_x = vp_door_2->x; + *door_2_y = vp_door_2->y; + + InitGfxBuffers(); + + if (gfx_game_mode == GAME_MODE_MAIN) + { + InitGadgets(); + InitToons(); + } + } + +#if 0 + printf("::: %d, %d / %d, %d [%d]\n", VX, VY, EX, EY, game_status); +#endif +} diff --git a/src/tools.h b/src/tools.h index 136a305c..510524af 100644 --- a/src/tools.h +++ b/src/tools.h @@ -135,9 +135,9 @@ void DrawLevelElementShifted(int, int, int, int, int, int); void DrawScreenElementThruMask(int, int, int); void DrawLevelElementThruMask(int, int, int); void DrawLevelFieldThruMask(int, int); -void DrawLevelFieldCrumbledSand(int, int); -void DrawLevelFieldCrumbledSandDigging(int, int, int, int); -void DrawLevelFieldCrumbledSandNeighbours(int, int); +void DrawLevelFieldCrumbled(int, int); +void DrawLevelFieldCrumbledDigging(int, int, int, int); +void DrawLevelFieldCrumbledNeighbours(int, int); void DrawScreenElement(int, int, int); void DrawLevelElement(int, int, int); void DrawScreenField(int, int); @@ -146,7 +146,8 @@ void DrawLevelField(int, int); void DrawMiniElement(int, int, int); void DrawMiniElementOrWall(int, int, int, int); -void ShowEnvelope(); +void ShowEnvelope(int); +void ShowEnvelopeDoor(char *text, int); void DrawLevel(void); void DrawMiniLevel(int, int, int, int); @@ -174,6 +175,10 @@ int map_direction_EM_to_RND(int); void map_android_clone_elements_RND_to_EM(struct LevelInfo *); void map_android_clone_elements_EM_to_RND(struct LevelInfo *); +int map_element_RND_to_SP(int); +int map_element_SP_to_RND(int); +int map_action_SP_to_RND(int); + int get_next_element(int); int el_act_dir2img(int, int, int); int el_act2img(int, int); @@ -211,5 +216,6 @@ void PlaySoundActivating(); void PlaySoundSelecting(); void ToggleFullscreenIfNeeded(); +void ChangeViewportPropertiesIfNeeded(); #endif /* TOOLS_H */