Merge branch 'master' into releases 2.0.0
authorHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2014 08:35:44 +0000 (10:35 +0200)
committerHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2014 08:35:44 +0000 (10:35 +0200)
71 files changed:
CHANGES
INSTALL
Makefile
README
src/Makefile
src/buttons.c [deleted file]
src/buttons.h [deleted file]
src/cartoons.c
src/cartoons.h
src/editor.c
src/editor.h
src/events.c
src/events.h
src/files.c
src/files.h
src/game.c
src/game.h
src/image.c [deleted file]
src/image.h [deleted file]
src/init.c
src/init.h
src/joystick.c
src/joystick.h
src/libgame/Makefile [new file with mode: 0644]
src/libgame/gadgets.c [new file with mode: 0644]
src/libgame/gadgets.h [new file with mode: 0644]
src/libgame/image.c [new file with mode: 0644]
src/libgame/image.h [new file with mode: 0644]
src/libgame/libgame.h [new file with mode: 0644]
src/libgame/misc.c [new file with mode: 0644]
src/libgame/misc.h [new file with mode: 0644]
src/libgame/msdos.c [new file with mode: 0644]
src/libgame/msdos.h [new file with mode: 0644]
src/libgame/pcx.c [new file with mode: 0644]
src/libgame/pcx.h [new file with mode: 0644]
src/libgame/platform.h [new file with mode: 0644]
src/libgame/random.c [new file with mode: 0644]
src/libgame/random.h [new file with mode: 0644]
src/libgame/sdl.c [new file with mode: 0644]
src/libgame/sdl.h [new file with mode: 0644]
src/libgame/sound.c [new file with mode: 0644]
src/libgame/sound.h [new file with mode: 0644]
src/libgame/system.c [new file with mode: 0644]
src/libgame/system.h [new file with mode: 0644]
src/libgame/text.c [new file with mode: 0644]
src/libgame/text.h [new file with mode: 0644]
src/libgame/types.h [new file with mode: 0644]
src/libgame/x11.c [new file with mode: 0644]
src/libgame/x11.h [new file with mode: 0644]
src/main.c
src/main.h
src/misc.c [deleted file]
src/misc.h [deleted file]
src/msdos.c [deleted file]
src/msdos.h [deleted file]
src/netserv.c
src/netserv.h
src/network.c
src/network.h
src/pcx.c [deleted file]
src/pcx.h [deleted file]
src/random.c [deleted file]
src/random.h [deleted file]
src/screens.c
src/screens.h
src/sound.c [deleted file]
src/sound.h [deleted file]
src/tape.c
src/tape.h
src/tools.c
src/tools.h

diff --git a/CHANGES b/CHANGES
index bb830209d4660ea6092c5c926e4a9dcfc695e405..304c14eac1bd14023aa4a40234da1836070d1581 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,15 @@
+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
+       - fixed network playing bug (patch from web site)
+       - SDL version can load and play music modules
+       - fixed element description in level editor for EM doors and keys
 
-Release Version 1.3.5 [?? SEP 1999]
+Release Version 1.4.0 [27 OCT 1999]
 -----------------------------------
        - new Boulderdash elements for better game emulation
        - new cool medium-sized crystal font
@@ -73,13 +83,13 @@ Release Version 1.2.0 [5 DEC 1998]
          level directory, standalone server execution and verbose
          execution
 
-Release Version 1.1 [???] [NOT RELEASED]
-----------------------------------------
+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
 
-Release Version 1.0 [9 APR 1997] [NOT RELEASED]
------------------------------------------------
+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
@@ -95,8 +105,8 @@ Release Version 1.0 [9 APR 1997] [NOT RELEASED]
          to make it possible to go on with a game at any tape
          position
 
-Prerelease Version 0.9b2 [21 NOV 1995] [NOT RELEASED]
------------------------------------------------------
+Version 0.9b2 [21 NOV 1995] [NOT RELEASED]
+------------------------------------------
        - new game elements
 
 Prerelease Version 0.9b [4 NOV 1995]
diff --git a/INSTALL b/INSTALL
index 697475a70f88f74f9bb6ff9efa16a8cd5b3d28f2..d014b7a93464e7a2de7ea636161befad45fb306d 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -1,26 +1,31 @@
 
-Installation instructions for Rocks'n'Diamonds 1.2.0
-====================================================
+Installation instructions for Rocks'n'Diamonds
+==============================================
 
 Compilation
 -----------
 
-If your system supports Linux/i386/ELF/libc5 executables (Linux package)
+If your system supports Linux/i386/ELF/glibc executables (Linux package)
 or if you run DOS/Windows (DOS package), you can directly use the included
 precompiled binary.
 
 If you use a different system, just recompile the game:
 
-If you use Linux with gcc or DOS/Windows with djgpp, just try 'make'
+If you use Linux with gcc or DOS or Windows 3.x with djgpp, just try 'make'
 which should work without problems.
 
 If you use SUN/Solaris with gcc and GNU make, try 'make solaris'.
 
+To build the game with SDL support (needed for fullscreen and MOD support),
+type "make sdl". You need at least SDL version 1.1.x and the additional
+SDL libraries SDL_image and SDL_mixer. To get a recent version of the SDL
+library, see http://www.libsdl.org.
+
 If the above doesn't work, edit the Makefile in the top level directory.
 If it doesn't work either, edit the Makefile in the 'src' subdirectory.
 
 If you had to modify any Makefile to compile it, please drop me a note
-about it to 'aeglos@valinor.owl.de'. Thanks!
+about it to 'info@artsoft.org'. Thanks!
 
 
 Customization
@@ -80,6 +85,4 @@ INCL, LIBS    Maybe some more directories for include files and libraries
 
 
 If you have any comments, additions or modifications to the Makefile(s),
-please send me mail: 'aeglos@valinor.owl.de'. Thanks!
-
-05-DEC-1998, Holger Schemel
+please send me mail: 'info@artsoft.org'. Thanks!
index d8c400de583e62e06c42487315345bd092fd5548..78eb6ea087c6d33cf0982fafc7403009c8aeb7bf 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 #=============================================================================#
-# Makefile for Rocks'n'Diamonds 1.4.0                                         #
-# (c) 1995-1999 Holger Schemel, aeglos@valinor.owl.de                         #
+# Makefile for Rocks'n'Diamonds                                               #
+# (c) 1995-2000 Holger Schemel, info@artsoft.org                              #
 #=============================================================================#
 
 #-----------------------------------------------------------------------------#
 # specify your favorite ANSI C compiler
 CC = gcc
 
-# explicitely choose your platform, if defaults doesn't work right
-# needed for SUN/Solaris; Linux and DOS work fine with auto detection
-# PLATFORM = solaris
-# PLATFORM = unix
-# PLATFORM = dos
-
 # specify path to X11 on your system
 # if undefined, use system defaults (works with Linux/gcc/libc5)
 X11_PATH = /usr/X11
@@ -31,9 +25,6 @@ X11_PATH = /usr/X11
 # uncomment this if your system has no joystick include file
 # JOYSTICK = -DNO_JOYSTICK
 
-# uncomment this if your system has no sound
-# SOUNDS = -DNO_SOUNDS
-
 # choose if you want to allow many global score file entries for one player
 # default is 'MANY_PER_NAME'
 # when installing the game in a multi user environment, choose this
@@ -41,6 +32,10 @@ X11_PATH = /usr/X11
 # when installing the game in a single user environment, choose this
 # SCORE_ENTRIES = MANY_PER_NAME
 
+# specify paths for cross-compiling (only needed for MS-DOS and Win32 build)
+CROSS_PATH_MSDOS=/usr/local/cross-msdos/i386-msdosdjgpp
+CROSS_PATH_WIN32=/usr/local/cross-tools/i386-mingw32msvc
+
 #-----------------------------------------------------------------------------#
 # you should not need to change anything below                                #
 #-----------------------------------------------------------------------------#
@@ -50,13 +45,56 @@ X11_PATH = /usr/X11
 MAKE = make
 
 SRC_DIR = src
-MAKE_CMD = @$(MAKE) -C $(SRC_DIR)
+MAKE_CMD = $(MAKE) -C $(SRC_DIR)
 
 all:
-       $(MAKE_CMD)
+       @$(MAKE_CMD) TARGET=x11
+
+x11:
+       @$(MAKE_CMD) TARGET=x11
+
+sdl:
+       @$(MAKE_CMD) TARGET=sdl
 
 solaris:
-       $(MAKE_CMD) PLATFORM=solaris
+       @$(MAKE_CMD) PLATFORM=solaris
+
+msdos:
+       @$(MAKE_CMD) PLATFORM=msdos
+
+cross-msdos:
+       @PATH=$(CROSS_PATH_MSDOS)/bin:${PATH} $(MAKE_CMD) PLATFORM=cross-msdos
+
+cross-win32:
+       @PATH=$(CROSS_PATH_WIN32)/bin:${PATH} $(MAKE_CMD) PLATFORM=cross-win32
 
 clean:
-       $(MAKE_CMD) clean
+       @$(MAKE_CMD) clean
+
+
+#-----------------------------------------------------------------------------#
+# development only stuff                                                      #
+#-----------------------------------------------------------------------------#
+
+backup:
+       ./Scripts/make_backup.sh src
+
+backup_lev:
+       ./Scripts/make_backup.sh lev
+
+backup_gfx:
+       ./Scripts/make_backup.sh gfx
+
+dist-unix:
+       ./Scripts/make_dist.sh unix .
+
+dist-msdos:
+       ./Scripts/make_dist.sh dos .
+
+dist-win32:
+       ./Scripts/make_dist.sh win .
+
+dist: dist-unix dist-msdos dist-win32
+
+depend dep:
+       $(MAKE_CMD) depend
diff --git a/README b/README
index 8843b3b4d457c37e7abd4b24e6ba0b3311624e88..28572bf8cb142c4b4a4a71771e7ac6feaa020fe9 100644 (file)
--- a/README
+++ b/README
@@ -1,17 +1,20 @@
 
 Welcome to
 
-   R O C K S   ' N '   D I A M O N D S   1 . 3 . 0
-   -----------------------------------------------
+   R O C K S   ' N '   D I A M O N D S
+   -----------------------------------
 
-A game for Unix/X11 by Holger Schemel, (c) 1995-99 by Holger Schemel.
-DOS/Windows port by Guido Schulz.
+A game for Unix/X11, DOS and Windows by Holger Schemel.
+DOS port based on code by Guido Schulz.
+(c) 1995-2000 by Holger Schemel.
 
 Introduction
 ============
 This is a nice little game with color graphics and sound for your
-Unix system with color X11. You need an 8-Bit color display or better.
-It will not work on black&white systems, and maybe not on gray scale systems.
+Unix system with color X11, DOS or Windows. You need an 8-bit color
+display or better.
+It will not work on black&white systems, and maybe not on gray scale
+systems.
 
 If you know the game "Boulderdash" (Commodore C64) or "Emerald Mine"
 (Amiga) or "Supaplex" (PC), you know what "ROCKS'N'DIAMONDS" is about.
@@ -19,18 +22,18 @@ If you know the game "Boulderdash" (Commodore C64) or "Emerald Mine"
 
 Getting started
 ===============
-Just 'cd' to the directory 'rocksndiamonds-*' (Unix) or 'rocks-*' (DOS)
-and type 'rocksndiamonds' (Linux) or 'rocks' (DOS/Windows)!
-This works only on Linux and DOS systems, because the included binary was
-compiled for Linux (i386/glibc) (if you have the Unix package) and DOS
-(if you have the DOS/Windows package).
-If you have another Unix system like HPUX, NetBSD or SUN, you first have to
-type 'make' to compile it.
+Just 'cd' to the directory 'rocksndiamonds-*' (Unix, Windows) or 'rocks-*'
+(DOS) and type 'rocksndiamonds' (Linux, Windows) or 'rocks' (DOS)!
+This works only on Linux, DOS and Windows systems, because the included
+binary was compiled for Linux (i386/glibc) (if you have the Unix package)
+and DOS or Windows (if you have the DOS or Windows package).
+If you have another Unix system like HPUX, NetBSD or Solaris, you first have
+to type 'make' to compile it. See the file 'INSTALL' for details.
 This may be needed on Linux systems, too, depending on your kernel version,
-your libc version, your binary format, your processor, ...
+your libc version, your binary format, your processor, your karma, ...
 
-(The included binary was compiled on the following system:
-AMD K6-2, kernel 2.2.1, glibc, gcc 2.7.2.3, ELF format)
+(The included Linux binary was compiled on a glibc 2.x system based on
+a 2.2.x Linux kernel and XFree86 4.0.x libraries.)
 
 
 The Menues
@@ -52,7 +55,7 @@ button and enter a new name.
 This menu will show the text 'team' instead of 'name' if you activated
 the team (local multiplayer) mode in the setup menu. See below.
 
-The menue 'level'
+The menu 'level'
 -----------------
 Choose any level from the current level series you want. The former
 'handicap' limitation in choosing levels has been removed because of
@@ -324,12 +327,12 @@ years like this version... ;-)
 If you have any comments, problems, suggestions, donations, flames,
 send them to
 
-       aeglos@valinor.owl.de
+       info@artsoft.org
 
 or Snail Mail to
 
        Holger Schemel
-       Oststrasse 11a
+       Detmolder Strasse 189
        33604 Bielefeld
        GERMANY
 
index 2be4220a3589872a6d424ee28cd257aeacaf9ca0..eee3bac4f2203a9c2bd7bbff2d5691440608fdee 100644 (file)
@@ -1,11 +1,13 @@
 #=============================================================================#
-# Makefile for Rocks'n'Diamonds 1.4.0                                         #
-# (c) 1995-1999 Holger Schemel, aeglos@valinor.owl.de                         #
+# Makefile for Rocks'n'Diamonds                                               #
+# (c) 1995-2000 Holger Schemel, info@artsoft.org                              #
 #=============================================================================#
 
+.EXPORT_ALL_VARIABLES:
+
 ifndef PLATFORM                        # platform not specified -- try auto detection
 ifdef COMSPEC
-PLATFORM = dos
+PLATFORM = msdos
 else
 PLATFORM = unix
 endif
@@ -18,27 +20,58 @@ X11_INCL = -I$(XINC_PATH)
 X11_LIBS = -L$(XLIB_PATH)
 endif
 
+AR = ar
+RANLIB = ranlib
 
-ifeq ($(PLATFORM),dos)         # DOS / Windows
+ifeq ($(PLATFORM),msdos)       # MS-DOS native compiling
 
 RM = del
 PROGNAME = ../rocks.exe
-LIBS = -s -lm -lalleg
 
-else                           # Unix
+SYS_CFLAGS = -DTARGET_X11
+SYS_LDFLAGS = -s -lalleg
+
+else                           # Unix or cross-compiling for MS-DOS and Win32
 
 RM = rm -f
 PROGNAME = ../rocksndiamonds
 
 ifeq ($(PLATFORM),solaris)
-EXTRA_LIBS = -lnsl -lsocket -R$(XLIB_PATH)
+EXTRA_LDFLAGS = -lnsl -lsocket -R$(XLIB_PATH)
+PLATFORM = unix
+endif
+
+ifeq ($(PLATFORM),unix)
+PROFILING_FLAGS = -pg
+endif
+
+ifeq ($(PLATFORM),cross-msdos)
+PROGNAME = ../rocks.exe
+TARGET = allegro
+endif
+
+ifeq ($(PLATFORM),cross-win32)
+PROGNAME = ../rocksndiamonds.exe
+TARGET = sdl
+endif
+
+ifeq ($(TARGET),x11)
+SYS_CFLAGS  = -DTARGET_X11 $(X11_INCL)
+SYS_LDFLAGS = $(X11_LIBS) -lX11
 endif
 
-INCL = $(X11_INCL)
-LIBS = $(X11_LIBS) -lX11 -lm $(EXTRA_LIBS)
+ifeq ($(TARGET),sdl)
+SYS_CFLAGS  = -DTARGET_SDL $(shell sdl-config --cflags)
+SYS_LDFLAGS = -lSDL_image -lSDL_mixer $(shell sdl-config --libs)
+endif
 
+ifeq ($(TARGET),allegro)
+SYS_CFLAGS = -DTARGET_ALLEGRO -I$(CROSS_PATH_MSDOS)/include
+SYS_LDFLAGS = -lalleg
 endif
 
+endif                          # (PLATFORM != msdos)
+
 
 ifdef RO_GAME_DIR              # path to read-only game data specified
 CONFIG_RO_GAME_DIR = -DRO_GAME_DIR="\"$(RO_GAME_DIR)\""
@@ -55,68 +88,81 @@ endif
 CONFIG_GAME_DIR = $(CONFIG_RO_GAME_DIR) $(CONFIG_RW_GAME_DIR)
 
 
-CONFIG = $(CONFIG_GAME_DIR) $(CONFIG_SCORE_ENTRIES) $(SOUNDS) $(JOYSTICK)
+CONFIG = $(CONFIG_GAME_DIR) $(CONFIG_SCORE_ENTRIES) $(JOYSTICK)
+DEBUG = -DDEBUG -g
+# PROFILING = $(PROFILING_FLAGS)
 
-# OPTIONS = -DDEBUG -g -Wall -ansi -pedantic   # only for debugging purposes
-# OPTIONS = -DDEBUG -g -Wall                   # only for debugging purposes
+# OPTIONS = $(DEBUG) -Wall                     # only for debugging purposes
+# OPTIONS = $(DEBUG) -O3 -Wall                 # only for debugging purposes
+# OPTIONS = $(DEBUG) -Wall -ansi -pedantic     # only for debugging purposes
 # OPTIONS = -O3 -Wall -ansi -pedantic
-# OPTIONS = -O3 -Wall
-OPTIONS = -O3
+OPTIONS = -O3 -Wall
+# OPTIONS = -O3
+# OPTIONS = -DSYSV -Ae                         # may be needed for HP-UX
 
-# SYSTEM = -DSYSV -Ae          # may be needed for HP-UX
+CFLAGS = $(OPTIONS) $(SYS_CFLAGS) $(CONFIG)
+LDFLAGS = $(SYS_LDFLAGS) $(EXTRA_LDFLAGS) -lm
 
-CFLAGS = $(OPTIONS) $(SYSTEM) $(INCL) $(CONFIG)
 
 SRCS = main.c          \
        init.c          \
        events.c        \
        tools.c         \
        screens.c       \
-       misc.c          \
        game.c          \
        editor.c        \
-       buttons.c       \
        files.c         \
        tape.c          \
-       sound.c         \
        joystick.c      \
        cartoons.c      \
-       random.c        \
-       pcx.c           \
-       image.c         \
        network.c       \
-       netserv.c       \
-       msdos.c
+       netserv.c
 
 OBJS = main.o          \
        init.o          \
        events.o        \
        tools.o         \
        screens.o       \
-       misc.o          \
        game.o          \
        editor.o        \
-       buttons.o       \
        files.o         \
        tape.o          \
-       sound.o         \
        joystick.o      \
        cartoons.o      \
-       random.o        \
-       pcx.o           \
-       image.o         \
        network.o       \
-       netserv.o       \
-       msdos.o
+       netserv.o
+
+LIBDIR = libgame
+LIBGAME = $(LIBDIR)/libgame.a
+
+
+all: $(PROGNAME)
 
-all:   $(PROGNAME)
+$(PROGNAME): $(LIBGAME) $(OBJS)
+       $(CC) $(PROFILING) $(OBJS) $(LIBGAME) $(LDFLAGS) -o $(PROGNAME)
 
-$(PROGNAME):   $(OBJS)
-       $(CC) $(CFLAGS) $(OBJS) $(LIBS) -o $(PROGNAME)
+$(LIBGAME):
+       $(MAKE) -C $(LIBDIR)
 
 .c.o:
-       $(CC) $(CFLAGS) -c $*.c
+       $(CC) $(PROFILING) $(CFLAGS) -c $*.c
 
 clean:
-       $(RM) *.o
+       $(MAKE) -C $(LIBDIR) clean
+       $(RM) $(OBJS)
+       $(RM) $(LIBGAME)
        $(RM) $(PROGNAME)
+       $(RM) ../*.exe
+
+
+#-----------------------------------------------------------------------------#
+# development only stuff                                                      #
+#-----------------------------------------------------------------------------#
+
+depend:
+       $(MAKE) -C $(LIBDIR) depend
+       for i in $(SRCS); do $(CPP) $(CFLAGS) -M $$i; done > .depend
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
diff --git a/src/buttons.c b/src/buttons.c
deleted file mode 100644 (file)
index 4844f2f..0000000
+++ /dev/null
@@ -1,1347 +0,0 @@
-/***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
-*----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
-*----------------------------------------------------------*
-*  buttons.c                                               *
-***********************************************************/
-
-#include <stdarg.h>
-
-#include "buttons.h"
-#include "tools.h"
-#include "misc.h"
-#include "editor.h"
-#include "tape.h"
-
-/* some positions in the video tape control window */
-#define VIDEO_DATE_LABEL_XPOS  (VIDEO_DISPLAY1_XPOS)
-#define VIDEO_DATE_LABEL_YPOS  (VIDEO_DISPLAY1_YPOS)
-#define VIDEO_DATE_LABEL_XSIZE (VIDEO_DISPLAY_XSIZE)
-#define VIDEO_DATE_LABEL_YSIZE (VIDEO_DISPLAY_YSIZE)
-#define VIDEO_DATE_XPOS                (VIDEO_DISPLAY1_XPOS + 1)
-#define VIDEO_DATE_YPOS                (VIDEO_DISPLAY1_YPOS + 14)
-#define VIDEO_DATE_XSIZE       (VIDEO_DISPLAY_XSIZE)
-#define VIDEO_DATE_YSIZE       16
-#define VIDEO_REC_LABEL_XPOS   (VIDEO_DISPLAY2_XPOS)
-#define VIDEO_REC_LABEL_YPOS   (VIDEO_DISPLAY2_YPOS)
-#define VIDEO_REC_LABEL_XSIZE  20
-#define VIDEO_REC_LABEL_YSIZE  12
-#define VIDEO_REC_SYMBOL_XPOS  (VIDEO_DISPLAY2_XPOS + 20)
-#define VIDEO_REC_SYMBOL_YPOS  (VIDEO_DISPLAY2_YPOS)
-#define VIDEO_REC_SYMBOL_XSIZE 16
-#define VIDEO_REC_SYMBOL_YSIZE 16
-#define VIDEO_PLAY_LABEL_XPOS  (VIDEO_DISPLAY2_XPOS + 65)
-#define VIDEO_PLAY_LABEL_YPOS  (VIDEO_DISPLAY2_YPOS)
-#define VIDEO_PLAY_LABEL_XSIZE 22
-#define VIDEO_PLAY_LABEL_YSIZE 12
-#define VIDEO_PLAY_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS + 52)
-#define VIDEO_PLAY_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS)
-#define VIDEO_PLAY_SYMBOL_XSIZE        11
-#define VIDEO_PLAY_SYMBOL_YSIZE        13
-#define VIDEO_PAUSE_LABEL_XPOS (VIDEO_DISPLAY2_XPOS)
-#define VIDEO_PAUSE_LABEL_YPOS (VIDEO_DISPLAY2_YPOS + 20)
-#define VIDEO_PAUSE_LABEL_XSIZE        35
-#define VIDEO_PAUSE_LABEL_YSIZE        8
-#define VIDEO_PAUSE_SYMBOL_XPOS        (VIDEO_DISPLAY2_XPOS + 35)
-#define VIDEO_PAUSE_SYMBOL_YPOS        (VIDEO_DISPLAY2_YPOS)
-#define VIDEO_PAUSE_SYMBOL_XSIZE 17
-#define VIDEO_PAUSE_SYMBOL_YSIZE 13
-#define VIDEO_TIME_XPOS                (VIDEO_DISPLAY2_XPOS + 38)
-#define VIDEO_TIME_YPOS                (VIDEO_DISPLAY2_YPOS + 14)
-#define VIDEO_TIME_XSIZE       50
-#define VIDEO_TIME_YSIZE       16
-
-/* special */
-#define VIDEO_PBEND_LABEL_XPOS 6
-#define VIDEO_PBEND_LABEL_YPOS 220
-#define VIDEO_PBEND_LABEL_XSIZE        35
-#define VIDEO_PBEND_LABEL_YSIZE        30
-
-#define VIDEO_STATE_OFF                (VIDEO_STATE_PLAY_OFF   |       \
-                                VIDEO_STATE_REC_OFF    |       \
-                                VIDEO_STATE_PAUSE_OFF  |       \
-                                VIDEO_STATE_FFWD_OFF   |       \
-                                VIDEO_STATE_PBEND_OFF  |       \
-                                VIDEO_STATE_DATE_OFF   |       \
-                                VIDEO_STATE_TIME_OFF)
-#define VIDEO_PRESS_OFF                (VIDEO_PRESS_PLAY_OFF   |       \
-                                VIDEO_PRESS_REC_OFF    |       \
-                                VIDEO_PRESS_PAUSE_OFF  |       \
-                                VIDEO_PRESS_STOP_OFF   |       \
-                                VIDEO_PRESS_EJECT_OFF)
-#define VIDEO_ALL_OFF          (VIDEO_STATE_OFF | VIDEO_PRESS_OFF)
-
-#define VIDEO_STATE_ON         (VIDEO_STATE_PLAY_ON    |       \
-                                VIDEO_STATE_REC_ON     |       \
-                                VIDEO_STATE_PAUSE_ON   |       \
-                                VIDEO_STATE_FFWD_ON    |       \
-                                VIDEO_STATE_PBEND_ON   |       \
-                                VIDEO_STATE_DATE_ON    |       \
-                                VIDEO_STATE_TIME_ON)
-#define VIDEO_PRESS_ON         (VIDEO_PRESS_PLAY_ON    |       \
-                                VIDEO_PRESS_REC_ON     |       \
-                                VIDEO_PRESS_PAUSE_ON   |       \
-                                VIDEO_PRESS_STOP_ON    |       \
-                                VIDEO_PRESS_EJECT_ON)
-#define VIDEO_ALL_ON           (VIDEO_STATE_ON | VIDEO_PRESS_ON)
-
-#define VIDEO_STATE            (VIDEO_STATE_ON | VIDEO_STATE_OFF)
-#define VIDEO_PRESS            (VIDEO_PRESS_ON | VIDEO_PRESS_OFF)
-#define VIDEO_ALL              (VIDEO_ALL_ON | VIDEO_ALL_OFF)
-
-
-void DrawVideoDisplay(unsigned long state, unsigned long value)
-{
-  int i;
-  int part_label = 0, part_symbol = 1;
-  int xpos = 0, ypos = 1, xsize = 2, ysize = 3;
-  static char *monatsname[12] =
-  {
-    "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
-    "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
-  };
-  static int video_pos[5][2][4] =
-  {
-    {{ VIDEO_PLAY_LABEL_XPOS, VIDEO_PLAY_LABEL_YPOS,
-       VIDEO_PLAY_LABEL_XSIZE,VIDEO_PLAY_LABEL_YSIZE },
-     { VIDEO_PLAY_SYMBOL_XPOS, VIDEO_PLAY_SYMBOL_YPOS,
-       VIDEO_PLAY_SYMBOL_XSIZE,VIDEO_PLAY_SYMBOL_YSIZE }},
-
-    {{ VIDEO_REC_LABEL_XPOS, VIDEO_REC_LABEL_YPOS,
-       VIDEO_REC_LABEL_XSIZE,VIDEO_REC_LABEL_YSIZE },
-     { VIDEO_REC_SYMBOL_XPOS, VIDEO_REC_SYMBOL_YPOS,
-       VIDEO_REC_SYMBOL_XSIZE,VIDEO_REC_SYMBOL_YSIZE }},
-
-    {{ VIDEO_PAUSE_LABEL_XPOS, VIDEO_PAUSE_LABEL_YPOS,
-       VIDEO_PAUSE_LABEL_XSIZE,VIDEO_PAUSE_LABEL_YSIZE },
-     { VIDEO_PAUSE_SYMBOL_XPOS, VIDEO_PAUSE_SYMBOL_YPOS,
-       VIDEO_PAUSE_SYMBOL_XSIZE,VIDEO_PAUSE_SYMBOL_YSIZE }},
-
-    {{ VIDEO_DATE_LABEL_XPOS, VIDEO_DATE_LABEL_YPOS,
-       VIDEO_DATE_LABEL_XSIZE,VIDEO_DATE_LABEL_YSIZE },
-     { VIDEO_DATE_XPOS, VIDEO_DATE_YPOS,
-       VIDEO_DATE_XSIZE,VIDEO_DATE_YSIZE }},
-
-    {{ 0,0,
-       0,0 },
-     { VIDEO_TIME_XPOS, VIDEO_TIME_YPOS,
-       VIDEO_TIME_XSIZE,VIDEO_TIME_YSIZE }}
-  };
-
-  if (state & VIDEO_STATE_PBEND_OFF)
-  {
-    int cx = DOOR_GFX_PAGEX3, cy = DOOR_GFX_PAGEY2;
-
-    XCopyArea(display,pix[PIX_DOOR],drawto,gc,
-             cx + VIDEO_REC_LABEL_XPOS,
-             cy + VIDEO_REC_LABEL_YPOS,
-             VIDEO_PBEND_LABEL_XSIZE,
-             VIDEO_PBEND_LABEL_YSIZE,
-             VX + VIDEO_REC_LABEL_XPOS,
-             VY + VIDEO_REC_LABEL_YPOS);
-  }
-
-  for(i=0;i<10;i++)
-  {
-    if (state & (1<<i))
-    {
-      int pos = i/2, cx, cy = DOOR_GFX_PAGEY2;
-
-      if (i%2)                 /* i ungerade => STATE_ON / PRESS_OFF */
-       cx = DOOR_GFX_PAGEX4;
-      else
-       cx = DOOR_GFX_PAGEX3;   /* i gerade => STATE_OFF / PRESS_ON */
-
-      if (video_pos[pos][part_label][0] && value != VIDEO_DISPLAY_SYMBOL_ONLY)
-       XCopyArea(display,pix[PIX_DOOR],drawto,gc,
-                 cx + video_pos[pos][part_label][xpos],
-                 cy + video_pos[pos][part_label][ypos],
-                 video_pos[pos][part_label][xsize],
-                 video_pos[pos][part_label][ysize],
-                 VX + video_pos[pos][part_label][xpos],
-                 VY + video_pos[pos][part_label][ypos]);
-      if (video_pos[pos][part_symbol][0] && value != VIDEO_DISPLAY_LABEL_ONLY)
-       XCopyArea(display,pix[PIX_DOOR],drawto,gc,
-                 cx + video_pos[pos][part_symbol][xpos],
-                 cy + video_pos[pos][part_symbol][ypos],
-                 video_pos[pos][part_symbol][xsize],
-                 video_pos[pos][part_symbol][ysize],
-                 VX + video_pos[pos][part_symbol][xpos],
-                 VY + video_pos[pos][part_symbol][ypos]);
-    }
-  }
-
-  if (state & VIDEO_STATE_FFWD_ON)
-  {
-    int cx = DOOR_GFX_PAGEX4, cy = DOOR_GFX_PAGEY2;
-
-    XCopyArea(display,pix[PIX_DOOR],drawto,gc,
-             cx + VIDEO_PLAY_SYMBOL_XPOS,
-             cy + VIDEO_PLAY_SYMBOL_YPOS,
-             VIDEO_PLAY_SYMBOL_XSIZE - 2,
-             VIDEO_PLAY_SYMBOL_YSIZE,
-             VX + VIDEO_PLAY_SYMBOL_XPOS - 9,
-             VY + VIDEO_PLAY_SYMBOL_YPOS);
-  }
-
-  if (state & VIDEO_STATE_PBEND_ON)
-  {
-    int cx = DOOR_GFX_PAGEX6, cy = DOOR_GFX_PAGEY1;
-
-    XCopyArea(display,pix[PIX_DOOR],drawto,gc,
-             cx + VIDEO_PBEND_LABEL_XPOS,
-             cy + VIDEO_PBEND_LABEL_YPOS,
-             VIDEO_PBEND_LABEL_XSIZE,
-             VIDEO_PBEND_LABEL_YSIZE,
-             VX + VIDEO_REC_LABEL_XPOS,
-             VY + VIDEO_REC_LABEL_YPOS);
-  }
-
-  if (state & VIDEO_STATE_DATE_ON)
-  {
-    int tag = value % 100;
-    int monat = (value/100) % 100;
-    int jahr = (value/10000);
-
-    DrawText(VX+VIDEO_DATE_XPOS,VY+VIDEO_DATE_YPOS,
-            int2str(tag,2),FS_SMALL,FC_SPECIAL1);
-    DrawText(VX+VIDEO_DATE_XPOS+27,VY+VIDEO_DATE_YPOS,
-            monatsname[monat],FS_SMALL,FC_SPECIAL1);
-    DrawText(VX+VIDEO_DATE_XPOS+64,VY+VIDEO_DATE_YPOS,
-            int2str(jahr,2),FS_SMALL,FC_SPECIAL1);
-  }
-
-  if (state & VIDEO_STATE_TIME_ON)
-  {
-    int min = value / 60;
-    int sec = value % 60;
-
-    DrawText(VX+VIDEO_TIME_XPOS,VY+VIDEO_TIME_YPOS,
-            int2str(min,2),FS_SMALL,FC_SPECIAL1);
-    DrawText(VX+VIDEO_TIME_XPOS+27,VY+VIDEO_TIME_YPOS,
-            int2str(sec,2),FS_SMALL,FC_SPECIAL1);
-  }
-
-  if (state & VIDEO_STATE_DATE)
-    redraw_mask |= REDRAW_VIDEO_1;
-  if ((state & ~VIDEO_STATE_DATE) & VIDEO_STATE)
-    redraw_mask |= REDRAW_VIDEO_2;
-  if (state & VIDEO_PRESS)
-    redraw_mask |= REDRAW_VIDEO_3;
-}
-
-void DrawCompleteVideoDisplay()
-{
-  XCopyArea(display,pix[PIX_DOOR],drawto,gc,
-           DOOR_GFX_PAGEX3,DOOR_GFX_PAGEY2, VXSIZE,VYSIZE, VX,VY);
-  XCopyArea(display,pix[PIX_DOOR],drawto,gc,
-           DOOR_GFX_PAGEX4+VIDEO_CONTROL_XPOS,
-           DOOR_GFX_PAGEY2+VIDEO_CONTROL_YPOS,
-           VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
-           VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
-
-  DrawVideoDisplay(VIDEO_ALL_OFF,0);
-  if (tape.date && tape.length)
-  {
-    DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date);
-    DrawVideoDisplay(VIDEO_STATE_TIME_ON,tape.length_seconds);
-  }
-
-  XCopyArea(display,drawto,pix[PIX_DB_DOOR],gc,
-           VX,VY, VXSIZE,VYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
-}
-
-
-/* NEW GADGET STUFF -------------------------------------------------------- */
-
-
-/* values for DrawGadget() */
-#define DG_UNPRESSED           0
-#define DG_PRESSED             1
-#define DG_BUFFERED            0
-#define DG_DIRECT              1
-
-static struct GadgetInfo *gadget_list_first_entry = NULL;
-static struct GadgetInfo *gadget_list_last_entry = NULL;
-static int next_free_gadget_id = 1;
-static boolean gadget_id_wrapped = FALSE;
-
-static struct GadgetInfo *getGadgetInfoFromGadgetID(int id)
-{
-  struct GadgetInfo *gi = gadget_list_first_entry;
-
-  while (gi && gi->id != id)
-    gi = gi->next;
-
-  return gi;
-}
-
-static int getNewGadgetID()
-{
-  int id = next_free_gadget_id++;
-
-  if (next_free_gadget_id <= 0)                /* counter overrun */
-  {
-    gadget_id_wrapped = TRUE;          /* now we must check each ID */
-    next_free_gadget_id = 0;
-  }
-
-  if (gadget_id_wrapped)
-  {
-    next_free_gadget_id++;
-    while (getGadgetInfoFromGadgetID(next_free_gadget_id) != NULL)
-      next_free_gadget_id++;
-  }
-
-  if (next_free_gadget_id <= 0)                /* cannot get new gadget id */
-    Error(ERR_EXIT, "too much gadgets -- this should not happen");
-
-  return id;
-}
-
-static struct GadgetInfo *getGadgetInfoFromMousePosition(int mx, int my)
-{
-  struct GadgetInfo *gi = gadget_list_first_entry;
-
-  while (gi)
-  {
-    if (gi->mapped &&
-       mx >= gi->x && mx < gi->x + gi->width &&
-       my >= gi->y && my < gi->y + gi->height)
-       break;
-
-    gi = gi->next;
-  }
-
-  return gi;
-}
-
-static void default_callback_info(void *ptr)
-{
-  if (game_status == LEVELED)
-    HandleEditorGadgetInfoText(ptr);
-}
-
-static void default_callback_action(void *ptr)
-{
-  return;
-}
-
-static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
-{
-  int state = (pressed ? 1 : 0);
-  struct GadgetDesign *gd = (gi->checked ?
-                            &gi->alt_design[state] :
-                            &gi->design[state]);
-
-  switch (gi->type)
-  {
-    case GD_TYPE_NORMAL_BUTTON:
-    case GD_TYPE_CHECK_BUTTON:
-    case GD_TYPE_RADIO_BUTTON:
-      XCopyArea(display, gd->pixmap, drawto, gc,
-               gd->x, gd->y, gi->width, gi->height, gi->x, gi->y);
-      if (gi->deco.design.pixmap)
-       XCopyArea(display, gi->deco.design.pixmap, drawto, gc,
-                 gi->deco.design.x, gi->deco.design.y,
-                 gi->deco.width, gi->deco.height,
-                 gi->x + gi->deco.x + (pressed ? gi->deco.xshift : 0),
-                 gi->y + gi->deco.y + (pressed ? gi->deco.yshift : 0));
-      break;
-
-    case GD_TYPE_TEXTINPUT_ALPHANUMERIC:
-    case GD_TYPE_TEXTINPUT_NUMERIC:
-      {
-       int i;
-       char cursor_letter;
-       char cursor_string[3];
-       char text[MAX_GADGET_TEXTSIZE + 1];
-       int font_type = gi->text.font_type;
-       int font_width = getFontWidth(FS_SMALL, font_type);
-       int border = gi->border.size;
-       strcpy(text, gi->text.value);
-       strcat(text, " ");
-
-       /* left part of gadget */
-       XCopyArea(display, gd->pixmap, drawto, gc,
-                 gd->x, gd->y, border, gi->height, gi->x, gi->y);
-
-       /* middle part of gadget */
-       for (i=0; i<=gi->text.size; i++)
-         XCopyArea(display, gd->pixmap, drawto, gc,
-                   gd->x + border, gd->y, font_width, gi->height,
-                   gi->x + border + i * font_width, gi->y);
-
-       /* right part of gadget */
-       XCopyArea(display, gd->pixmap, drawto, gc,
-                 gd->x + gi->border.width - border, gd->y,
-                 border, gi->height, gi->x + gi->width - border, gi->y);
-
-       /* gadget text value */
-       DrawText(gi->x + border, gi->y + border, text, FS_SMALL, font_type);
-
-       cursor_letter = gi->text.value[gi->text.cursor_position];
-       cursor_string[0] = '~';
-       cursor_string[1] = (cursor_letter != '\0' ? cursor_letter : ' ');
-       cursor_string[2] = '\0';
-
-       /* draw cursor, if active */
-       if (pressed)
-         DrawText(gi->x + border + gi->text.cursor_position * font_width,
-                  gi->y + border, cursor_string, FS_SMALL, font_type);
-      }
-      break;
-
-    case GD_TYPE_SCROLLBAR_VERTICAL:
-      {
-       int i;
-       int xpos = gi->x;
-       int ypos = gi->y + gi->scrollbar.position;
-       int design_full = gi->width;
-       int design_body = design_full - 2 * gi->border.size;
-       int size_full = gi->scrollbar.size;
-       int size_body = size_full - 2 * gi->border.size;
-       int num_steps = size_body / design_body;
-       int step_size_remain = size_body - num_steps * design_body;
-
-       /* clear scrollbar area */
-       XFillRectangle(display, backbuffer, gc,
-                      gi->x, gi->y, gi->width, gi->height);
-
-       /* upper part of gadget */
-       XCopyArea(display, gd->pixmap, drawto, gc,
-                 gd->x, gd->y,
-                 gi->width, gi->border.size,
-                 xpos, ypos);
-
-       /* middle part of gadget */
-       for (i=0; i<num_steps; i++)
-         XCopyArea(display, gd->pixmap, drawto, gc,
-                   gd->x, gd->y + gi->border.size,
-                   gi->width, design_body,
-                   xpos, ypos + gi->border.size + i * design_body);
-
-       /* remaining middle part of gadget */
-       if (step_size_remain > 0)
-         XCopyArea(display, gd->pixmap, drawto, gc,
-                   gd->x,  gd->y + gi->border.size,
-                   gi->width, step_size_remain,
-                   xpos, ypos + gi->border.size + num_steps * design_body);
-
-       /* lower part of gadget */
-       XCopyArea(display, gd->pixmap, drawto, gc,
-                 gd->x, gd->y + design_full - gi->border.size,
-                 gi->width, gi->border.size,
-                 xpos, ypos + size_full - gi->border.size);
-      }
-      break;
-
-    case GD_TYPE_SCROLLBAR_HORIZONTAL:
-      {
-       int i;
-       int xpos = gi->x + gi->scrollbar.position;
-       int ypos = gi->y;
-       int design_full = gi->height;
-       int design_body = design_full - 2 * gi->border.size;
-       int size_full = gi->scrollbar.size;
-       int size_body = size_full - 2 * gi->border.size;
-       int num_steps = size_body / design_body;
-       int step_size_remain = size_body - num_steps * design_body;
-
-       /* clear scrollbar area */
-       XFillRectangle(display, backbuffer, gc,
-                      gi->x, gi->y, gi->width, gi->height);
-
-       /* left part of gadget */
-       XCopyArea(display, gd->pixmap, drawto, gc,
-                 gd->x, gd->y,
-                 gi->border.size, gi->height,
-                 xpos, ypos);
-
-       /* middle part of gadget */
-       for (i=0; i<num_steps; i++)
-         XCopyArea(display, gd->pixmap, drawto, gc,
-                   gd->x + gi->border.size, gd->y,
-                   design_body, gi->height,
-                   xpos + gi->border.size + i * design_body, ypos);
-
-       /* remaining middle part of gadget */
-       if (step_size_remain > 0)
-         XCopyArea(display, gd->pixmap, drawto, gc,
-                   gd->x + gi->border.size, gd->y,
-                   step_size_remain, gi->height,
-                   xpos + gi->border.size + num_steps * design_body, ypos);
-
-       /* right part of gadget */
-       XCopyArea(display, gd->pixmap, drawto, gc,
-                 gd->x + design_full - gi->border.size, gd->y,
-                 gi->border.size, gi->height,
-                 xpos + size_full - gi->border.size, ypos);
-      }
-      break;
-
-    default:
-      return;
-  }
-
-  if (direct)
-    XCopyArea(display, drawto, window, gc,
-             gi->x, gi->y, gi->width, gi->height, gi->x, gi->y);
-  else
-    redraw_mask |= (gi->x < SX + SXSIZE ? REDRAW_FIELD :
-                   gi->y < DY + DYSIZE ? REDRAW_DOOR_1 :
-                   gi->y > VY ? REDRAW_DOOR_2 : REDRAW_DOOR_3);
-}
-
-static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
-{
-  int tag = first_tag;
-
-  while (tag != GDI_END)
-  {
-    switch(tag)
-    {
-      case GDI_CUSTOM_ID:
-       gi->custom_id = va_arg(ap, int);
-       break;
-
-      case GDI_CUSTOM_TYPE_ID:
-       gi->custom_type_id = va_arg(ap, int);
-       break;
-
-      case GDI_INFO_TEXT:
-       {
-         int max_textsize = MAX_INFO_TEXTSIZE - 1;
-
-         strncpy(gi->info_text, va_arg(ap, char *), max_textsize);
-         gi->info_text[max_textsize] = '\0';
-       }
-       break;
-
-      case GDI_X:
-       gi->x = va_arg(ap, int);
-       break;
-
-      case GDI_Y:
-       gi->y = va_arg(ap, int);
-       break;
-
-      case GDI_WIDTH:
-       gi->width = va_arg(ap, int);
-       break;
-
-      case GDI_HEIGHT:
-       gi->height = va_arg(ap, int);
-       break;
-
-      case GDI_TYPE:
-       gi->type = va_arg(ap, unsigned long);
-       break;
-
-      case GDI_STATE:
-       gi->state = va_arg(ap, unsigned long);
-       break;
-
-      case GDI_CHECKED:
-       gi->checked = va_arg(ap, boolean);
-       break;
-
-      case GDI_RADIO_NR:
-       gi->radio_nr = va_arg(ap, unsigned long);
-       break;
-
-      case GDI_NUMBER_VALUE:
-       gi->text.number_value = va_arg(ap, long);
-       sprintf(gi->text.value, "%d", gi->text.number_value);
-       gi->text.cursor_position = strlen(gi->text.value);
-       break;
-
-      case GDI_NUMBER_MIN:
-       gi->text.number_min = va_arg(ap, long);
-       if (gi->text.number_value < gi->text.number_min)
-       {
-         gi->text.number_value = gi->text.number_min;
-         sprintf(gi->text.value, "%d", gi->text.number_value);
-       }
-       break;
-
-      case GDI_NUMBER_MAX:
-       gi->text.number_max = va_arg(ap, long);
-       if (gi->text.number_value > gi->text.number_max)
-       {
-         gi->text.number_value = gi->text.number_max;
-         sprintf(gi->text.value, "%d", gi->text.number_value);
-       }
-       break;
-
-      case GDI_TEXT_VALUE:
-       {
-         int max_textsize = MAX_GADGET_TEXTSIZE;
-
-         if (gi->text.size)
-           max_textsize = MIN(gi->text.size, MAX_GADGET_TEXTSIZE - 1);
-
-         strncpy(gi->text.value, va_arg(ap, char *), max_textsize);
-         gi->text.value[max_textsize] = '\0';
-         gi->text.cursor_position = strlen(gi->text.value);
-       }
-       break;
-
-      case GDI_TEXT_SIZE:
-       {
-         int tag_value = va_arg(ap, int);
-         int max_textsize = MIN(tag_value, MAX_GADGET_TEXTSIZE - 1);
-
-         gi->text.size = max_textsize;
-         gi->text.value[max_textsize] = '\0';
-       }
-       break;
-
-      case GDI_TEXT_FONT:
-       gi->text.font_type = va_arg(ap, int);
-       break;
-
-      case GDI_DESIGN_UNPRESSED:
-       gi->design[GD_BUTTON_UNPRESSED].pixmap = va_arg(ap, Pixmap);
-       gi->design[GD_BUTTON_UNPRESSED].x = va_arg(ap, int);
-       gi->design[GD_BUTTON_UNPRESSED].y = va_arg(ap, int);
-       break;
-
-      case GDI_DESIGN_PRESSED:
-       gi->design[GD_BUTTON_PRESSED].pixmap = va_arg(ap, Pixmap);
-       gi->design[GD_BUTTON_PRESSED].x = va_arg(ap, int);
-       gi->design[GD_BUTTON_PRESSED].y = va_arg(ap, int);
-       break;
-
-      case GDI_ALT_DESIGN_UNPRESSED:
-       gi->alt_design[GD_BUTTON_UNPRESSED].pixmap= va_arg(ap, Pixmap);
-       gi->alt_design[GD_BUTTON_UNPRESSED].x = va_arg(ap, int);
-       gi->alt_design[GD_BUTTON_UNPRESSED].y = va_arg(ap, int);
-       break;
-
-      case GDI_ALT_DESIGN_PRESSED:
-       gi->alt_design[GD_BUTTON_PRESSED].pixmap = va_arg(ap, Pixmap);
-       gi->alt_design[GD_BUTTON_PRESSED].x = va_arg(ap, int);
-       gi->alt_design[GD_BUTTON_PRESSED].y = va_arg(ap, int);
-       break;
-
-      case GDI_BORDER_SIZE:
-       gi->border.size = va_arg(ap, int);
-       break;
-
-      case GDI_TEXTINPUT_DESIGN_WIDTH:
-       gi->border.width = va_arg(ap, int);
-       break;
-
-      case GDI_DECORATION_DESIGN:
-       gi->deco.design.pixmap = va_arg(ap, Pixmap);
-       gi->deco.design.x = va_arg(ap, int);
-       gi->deco.design.y = va_arg(ap, int);
-       break;
-
-      case GDI_DECORATION_POSITION:
-       gi->deco.x = va_arg(ap, int);
-       gi->deco.y = va_arg(ap, int);
-       break;
-
-      case GDI_DECORATION_SIZE:
-       gi->deco.width = va_arg(ap, int);
-       gi->deco.height = va_arg(ap, int);
-       break;
-
-      case GDI_DECORATION_SHIFTING:
-       gi->deco.xshift = va_arg(ap, int);
-       gi->deco.yshift = va_arg(ap, int);
-       break;
-
-      case GDI_EVENT_MASK:
-       gi->event_mask = va_arg(ap, unsigned long);
-       break;
-
-      case GDI_AREA_SIZE:
-       gi->drawing.area_xsize = va_arg(ap, int);
-       gi->drawing.area_ysize = va_arg(ap, int);
-
-       /* determine dependent values for drawing area gadget, if needed */
-       if (gi->width == 0 && gi->height == 0 &&
-           gi->drawing.item_xsize !=0 && gi->drawing.item_ysize !=0)
-       {
-         gi->width = gi->drawing.area_xsize * gi->drawing.item_xsize;
-         gi->height = gi->drawing.area_ysize * gi->drawing.item_ysize;
-       }
-       else if (gi->drawing.item_xsize == 0 && gi->drawing.item_ysize == 0 &&
-                gi->width != 0 && gi->height != 0)
-       {
-         gi->drawing.item_xsize = gi->width / gi->drawing.area_xsize;
-         gi->drawing.item_ysize = gi->height / gi->drawing.area_ysize;
-       }
-       break;
-
-      case GDI_ITEM_SIZE:
-       gi->drawing.item_xsize = va_arg(ap, int);
-       gi->drawing.item_ysize = va_arg(ap, int);
-
-       /* determine dependent values for drawing area gadget, if needed */
-       if (gi->width == 0 && gi->height == 0 &&
-           gi->drawing.area_xsize !=0 && gi->drawing.area_ysize !=0)
-       {
-         gi->width = gi->drawing.area_xsize * gi->drawing.item_xsize;
-         gi->height = gi->drawing.area_ysize * gi->drawing.item_ysize;
-       }
-       else if (gi->drawing.area_xsize == 0 && gi->drawing.area_ysize == 0 &&
-                gi->width != 0 && gi->height != 0)
-       {
-         gi->drawing.area_xsize = gi->width / gi->drawing.item_xsize;
-         gi->drawing.area_ysize = gi->height / gi->drawing.item_ysize;
-       }
-       break;
-
-      case GDI_SCROLLBAR_ITEMS_MAX:
-       gi->scrollbar.items_max = va_arg(ap, int);
-       break;
-
-      case GDI_SCROLLBAR_ITEMS_VISIBLE:
-       gi->scrollbar.items_visible = va_arg(ap, int);
-       break;
-
-      case GDI_SCROLLBAR_ITEM_POSITION:
-       gi->scrollbar.item_position = va_arg(ap, int);
-       break;
-
-      case GDI_CALLBACK_INFO:
-       gi->callback_info = va_arg(ap, gadget_function);
-       break;
-
-      case GDI_CALLBACK_ACTION:
-       gi->callback_action = va_arg(ap, gadget_function);
-       break;
-
-      default:
-       Error(ERR_EXIT, "HandleGadgetTags(): unknown tag %d", tag);
-    }
-
-    tag = va_arg(ap, int);     /* read next tag */
-  }
-
-  /* check if gadget complete */
-  if (gi->type != GD_TYPE_DRAWING_AREA &&
-      (!gi->design[GD_BUTTON_UNPRESSED].pixmap ||
-       !gi->design[GD_BUTTON_PRESSED].pixmap))
-    Error(ERR_EXIT, "gadget incomplete (missing Pixmap)");
-
-  /* adjust gadget values in relation to other gadget values */
-
-  if (gi->type & GD_TYPE_TEXTINPUT)
-  {
-    int font_width = getFontWidth(FS_SMALL, gi->text.font_type);
-    int font_height = getFontHeight(FS_SMALL, gi->text.font_type);
-
-    gi->width = 2 * gi->border.size + (gi->text.size + 1) * font_width;
-    gi->height = 2 * gi->border.size + font_height;
-  }
-
-  if (gi->type & GD_TYPE_TEXTINPUT_NUMERIC)
-  {
-    struct GadgetTextInput *text = &gi->text;
-    int value = text->number_value;
-
-    text->number_value = (value < text->number_min ? text->number_min :
-                         value > text->number_max ? text->number_max :
-                         value);
-
-    sprintf(text->value, "%d", text->number_value);
-  }
-
-  if (gi->type & GD_TYPE_SCROLLBAR)
-  {
-    struct GadgetScrollbar *gs = &gi->scrollbar;
-
-    if (gi->width == 0 || gi->height == 0 ||
-       gs->items_max == 0 || gs->items_visible == 0)
-      Error(ERR_EXIT, "scrollbar gadget incomplete (missing tags)");
-
-    /* calculate internal scrollbar values */
-    gs->size_max = (gi->type == GD_TYPE_SCROLLBAR_VERTICAL ?
-                   gi->height : gi->width);
-    gs->size = gs->size_max * gs->items_visible / gs->items_max;
-    gs->position = gs->size_max * gs->item_position / gs->items_max;
-    gs->position_max = gs->size_max - gs->size;
-    gs->correction = gs->size_max / gs->items_max / 2;
-
-    /* finetuning for maximal right/bottom position */
-    if (gs->item_position == gs->items_max - gs->items_visible)
-      gs->position = gs->position_max;
-  }
-}
-
-void ModifyGadget(struct GadgetInfo *gi, int first_tag, ...)
-{
-  va_list ap;
-
-  va_start(ap, first_tag);
-  HandleGadgetTags(gi, first_tag, ap);
-  va_end(ap);
-
-  RedrawGadget(gi);
-}
-
-void RedrawGadget(struct GadgetInfo *gi)
-{
-  if (gi->mapped)
-    DrawGadget(gi, gi->state, DG_DIRECT);
-}
-
-struct GadgetInfo *CreateGadget(int first_tag, ...)
-{
-  struct GadgetInfo *new_gadget = checked_malloc(sizeof(struct GadgetInfo));
-  va_list ap;
-
-  /* always start with reliable default values */
-  memset(new_gadget, 0, sizeof(struct GadgetInfo));    /* zero all fields */
-  new_gadget->id = getNewGadgetID();
-  new_gadget->callback_info = default_callback_info;
-  new_gadget->callback_action = default_callback_action;
-
-  va_start(ap, first_tag);
-  HandleGadgetTags(new_gadget, first_tag, ap);
-  va_end(ap);
-
-  /* insert new gadget into global gadget list */
-  if (gadget_list_last_entry)
-  {
-    gadget_list_last_entry->next = new_gadget;
-    gadget_list_last_entry = gadget_list_last_entry->next;
-  }
-  else
-    gadget_list_first_entry = gadget_list_last_entry = new_gadget;
-
-  return new_gadget;
-}
-
-void FreeGadget(struct GadgetInfo *gi)
-{
-  struct GadgetInfo *gi_previous = gadget_list_first_entry;
-
-  while (gi_previous && gi_previous->next != gi)
-    gi_previous = gi_previous->next;
-
-  if (gi == gadget_list_first_entry)
-    gadget_list_first_entry = gi->next;
-
-  if (gi == gadget_list_last_entry)
-    gadget_list_last_entry = gi_previous;
-
-  gi_previous->next = gi->next;
-  free(gi);
-}
-
-static void CheckRangeOfNumericInputGadget(struct GadgetInfo *gi)
-{
-  if (gi->type != GD_TYPE_TEXTINPUT_NUMERIC)
-    return;
-
-  gi->text.number_value = atoi(gi->text.value);
-
-  if (gi->text.number_value < gi->text.number_min)
-    gi->text.number_value = gi->text.number_min;
-  if (gi->text.number_value > gi->text.number_max)
-    gi->text.number_value = gi->text.number_max;
-
-  sprintf(gi->text.value, "%d", gi->text.number_value);
-
-  if (gi->text.cursor_position < 0)
-    gi->text.cursor_position = 0;
-  else if (gi->text.cursor_position > strlen(gi->text.value))
-    gi->text.cursor_position = strlen(gi->text.value);
-}
-
-/* global pointer to gadget actually in use (when mouse button pressed) */
-static struct GadgetInfo *last_gi = NULL;
-
-static void MapGadgetExt(struct GadgetInfo *gi, boolean redraw)
-{
-  if (gi == NULL || gi->mapped)
-    return;
-
-  gi->mapped = TRUE;
-
-  if (redraw)
-    DrawGadget(gi, DG_UNPRESSED, DG_BUFFERED);
-}
-
-void MapGadget(struct GadgetInfo *gi)
-{
-  MapGadgetExt(gi, TRUE);
-}
-
-void UnmapGadget(struct GadgetInfo *gi)
-{
-  if (gi == NULL || !gi->mapped)
-    return;
-
-  gi->mapped = FALSE;
-
-  if (gi == last_gi)
-    last_gi = NULL;
-}
-
-#define MAX_NUM_GADGETS                1024
-#define MULTIMAP_UNMAP         (1 << 0)
-#define MULTIMAP_REMAP         (1 << 1)
-#define MULTIMAP_REDRAW                (1 << 2)
-#define MULTIMAP_PLAYFIELD     (1 << 3)
-#define MULTIMAP_DOOR_1                (1 << 4)
-#define MULTIMAP_DOOR_2                (1 << 5)
-#define MULTIMAP_ALL           (MULTIMAP_PLAYFIELD | \
-                                MULTIMAP_DOOR_1 | \
-                                MULTIMAP_DOOR_2)
-
-static void MultiMapGadgets(int mode)
-{
-  struct GadgetInfo *gi = gadget_list_first_entry;
-  static boolean map_state[MAX_NUM_GADGETS];
-  int map_count = 0;
-
-  while (gi)
-  {
-    if ((mode & MULTIMAP_PLAYFIELD && gi->x < SX + SXSIZE) ||
-       (mode & MULTIMAP_DOOR_1 && gi->x >= DX && gi->y < DY + DYSIZE) ||
-       (mode & MULTIMAP_DOOR_2 && gi->x >= DX && gi->y > DY + DYSIZE) ||
-       (mode & MULTIMAP_ALL) == MULTIMAP_ALL)
-    {
-      if (mode & MULTIMAP_UNMAP)
-      {
-       map_state[map_count++ % MAX_NUM_GADGETS] = gi->mapped;
-       UnmapGadget(gi);
-      }
-      else
-      {
-       if (map_state[map_count++ % MAX_NUM_GADGETS])
-         MapGadgetExt(gi, (mode & MULTIMAP_REDRAW));
-      }
-    }
-
-    gi = gi->next;
-  }
-}
-
-void UnmapAllGadgets()
-{
-  MultiMapGadgets(MULTIMAP_ALL | MULTIMAP_UNMAP);
-}
-
-void RemapAllGadgets()
-{
-  MultiMapGadgets(MULTIMAP_ALL | MULTIMAP_REMAP);
-}
-
-boolean anyTextGadgetActive()
-{
-  return (last_gi && last_gi->type & GD_TYPE_TEXTINPUT && last_gi->mapped);
-}
-
-void ClickOnGadget(struct GadgetInfo *gi, int button)
-{
-  /* simulate releasing mouse button over last gadget, if still pressed */
-  if (button_status)
-    HandleGadgets(-1, -1, 0);
-
-  /* simulate pressing mouse button over specified gadget */
-  HandleGadgets(gi->x, gi->y, button);
-
-  /* simulate releasing mouse button over specified gadget */
-  HandleGadgets(gi->x, gi->y, 0);
-}
-
-void HandleGadgets(int mx, int my, int button)
-{
-  static struct GadgetInfo *last_info_gi = NULL;
-  static unsigned long pressed_delay = 0;
-  static int last_button = 0;
-  static int last_mx = 0, last_my = 0;
-  int scrollbar_mouse_pos = 0;
-  struct GadgetInfo *new_gi, *gi;
-  boolean press_event;
-  boolean release_event;
-  boolean mouse_moving;
-  boolean gadget_pressed;
-  boolean gadget_pressed_repeated;
-  boolean gadget_moving;
-  boolean gadget_moving_inside;
-  boolean gadget_moving_off_borders;
-  boolean gadget_released;
-  boolean gadget_released_inside;
-  boolean gadget_released_off_borders;
-  boolean changed_position = FALSE;
-
-  /* check if there are any gadgets defined */
-  if (gadget_list_first_entry == NULL)
-    return;
-
-  /* check which gadget is under the mouse pointer */
-  new_gi = getGadgetInfoFromMousePosition(mx, my);
-
-  /* check if button state has changed since last invocation */
-  press_event = (button != 0 && last_button == 0);
-  release_event = (button == 0 && last_button != 0);
-  last_button = button;
-
-  /* check if mouse has been moved since last invocation */
-  mouse_moving = ((mx != last_mx || my != last_my) && motion_status);
-  last_mx = mx;
-  last_my = my;
-
-  /* special treatment for text and number input gadgets */
-  if (anyTextGadgetActive() && button != 0 && !motion_status)
-  {
-    struct GadgetInfo *gi = last_gi;
-
-    if (new_gi == last_gi)
-    {
-      /* if mouse button pressed inside activated text gadget, set cursor */
-      gi->text.cursor_position =
-       (mx - gi->x - gi->border.size) /
-       getFontWidth(FS_SMALL, gi->text.font_type);
-
-      if (gi->text.cursor_position < 0)
-       gi->text.cursor_position = 0;
-      else if (gi->text.cursor_position > strlen(gi->text.value))
-       gi->text.cursor_position = strlen(gi->text.value);
-
-      DrawGadget(gi, DG_PRESSED, DG_DIRECT);
-    }
-    else
-    {
-      /* if mouse button pressed outside text input gadget, deactivate it */
-      CheckRangeOfNumericInputGadget(gi);
-      DrawGadget(gi, DG_UNPRESSED, DG_DIRECT);
-
-      gi->event.type = GD_EVENT_TEXT_LEAVING;
-
-      if (gi->event_mask & GD_EVENT_TEXT_LEAVING)
-       gi->callback_action(gi);
-
-      last_gi = NULL;
-    }
-  }
-
-  gadget_pressed =
-    (button != 0 && last_gi == NULL && new_gi != NULL && press_event);
-  gadget_pressed_repeated =
-    (button != 0 && last_gi != NULL && new_gi == last_gi);
-
-  gadget_released =            (release_event && last_gi != NULL);
-  gadget_released_inside =     (gadget_released && new_gi == last_gi);
-  gadget_released_off_borders =        (gadget_released && new_gi != last_gi);
-
-  gadget_moving =            (button != 0 && last_gi != NULL && mouse_moving);
-  gadget_moving_inside =      (gadget_moving && new_gi == last_gi);
-  gadget_moving_off_borders = (gadget_moving && new_gi != last_gi);
-
-  /* if new gadget pressed, store this gadget  */
-  if (gadget_pressed)
-    last_gi = new_gi;
-
-  /* 'gi' is actually handled gadget */
-  gi = last_gi;
-
-  /* if gadget is scrollbar, choose mouse position value */
-  if (gi && gi->type & GD_TYPE_SCROLLBAR)
-    scrollbar_mouse_pos =
-      (gi->type == GD_TYPE_SCROLLBAR_HORIZONTAL ? mx - gi->x : my - gi->y);
-
-  /* if mouse button released, no gadget needs to be handled anymore */
-  if (button == 0 && last_gi && !(last_gi->type & GD_TYPE_TEXTINPUT))
-    last_gi = NULL;
-
-  /* modify event position values even if no gadget is pressed */
-  if (button == 0 && !release_event)
-    gi = new_gi;
-
-  if (gi)
-  {
-    int last_x = gi->event.x;
-    int last_y = gi->event.y;
-
-    gi->event.x = mx - gi->x;
-    gi->event.y = my - gi->y;
-
-    if (gi->type == GD_TYPE_DRAWING_AREA)
-    {
-      gi->event.x /= gi->drawing.item_xsize;
-      gi->event.y /= gi->drawing.item_ysize;
-
-      if (last_x != gi->event.x || last_y != gi->event.y)
-       changed_position = TRUE;
-    }
-  }
-
-  /* handle gadget popup info text */
-  if (last_info_gi != new_gi ||
-      (new_gi && new_gi->type == GD_TYPE_DRAWING_AREA && changed_position))
-  {
-    last_info_gi = new_gi;
-
-    if (new_gi != NULL && (button == 0 || new_gi == last_gi))
-    {
-      new_gi->event.type = 0;
-      new_gi->callback_info(new_gi);
-    }
-    else
-      default_callback_info(NULL);
-  }
-
-  if (gadget_pressed)
-  {
-    if (gi->type == GD_TYPE_CHECK_BUTTON)
-    {
-      gi->checked = !gi->checked;
-    }
-    else if (gi->type == GD_TYPE_RADIO_BUTTON)
-    {
-      struct GadgetInfo *rgi = gadget_list_first_entry;
-
-      while (rgi)
-      {
-       if (rgi->mapped &&
-           rgi->type == GD_TYPE_RADIO_BUTTON &&
-           rgi->radio_nr == gi->radio_nr &&
-           rgi != gi)
-       {
-         rgi->checked = FALSE;
-         DrawGadget(rgi, DG_UNPRESSED, DG_DIRECT);
-       }
-
-       rgi = rgi->next;
-      }
-
-      gi->checked = TRUE;
-    }
-    else if (gi->type & GD_TYPE_SCROLLBAR)
-    {
-      int mpos, gpos;
-
-      if (gi->type == GD_TYPE_SCROLLBAR_HORIZONTAL)
-      {
-       mpos = mx;
-       gpos = gi->x;
-      }
-      else
-      {
-       mpos = my;
-       gpos = gi->y;
-      }
-
-      if (mpos >= gpos + gi->scrollbar.position &&
-         mpos < gpos + gi->scrollbar.position + gi->scrollbar.size)
-      {
-       /* drag scrollbar */
-       gi->scrollbar.drag_position =
-         scrollbar_mouse_pos - gi->scrollbar.position;
-      }
-      else
-      {
-       /* click scrollbar one scrollbar length up/left or down/right */
-
-       struct GadgetScrollbar *gs = &gi->scrollbar;
-       int old_item_position = gs->item_position;
-
-       changed_position = FALSE;
-
-       gs->item_position +=
-         gs->items_visible * (mpos < gpos + gi->scrollbar.position ? -1 : +1);
-
-       if (gs->item_position < 0)
-         gs->item_position = 0;
-       if (gs->item_position > gs->items_max - gs->items_visible)
-         gs->item_position = gs->items_max - gs->items_visible;
-
-       if (old_item_position != gs->item_position)
-       {
-         gi->event.item_position = gs->item_position;
-         changed_position = TRUE;
-       }
-
-       ModifyGadget(gi, GDI_SCROLLBAR_ITEM_POSITION, gs->item_position,
-                    GDI_END);
-
-       gi->state = GD_BUTTON_UNPRESSED;
-       gi->event.type = GD_EVENT_MOVING;
-       gi->event.off_borders = FALSE;
-
-       if (gi->event_mask & GD_EVENT_MOVING && changed_position)
-         gi->callback_action(gi);
-
-       /* don't handle this scrollbar anymore while mouse button pressed */
-       last_gi = NULL;
-
-       return;
-      }
-    }
-
-    DrawGadget(gi, DG_PRESSED, DG_DIRECT);
-
-    gi->state = GD_BUTTON_PRESSED;
-    gi->event.type = GD_EVENT_PRESSED;
-    gi->event.button = button;
-    gi->event.off_borders = FALSE;
-
-    /* initialize delay counter */
-    DelayReached(&pressed_delay, 0);
-
-    if (gi->event_mask & GD_EVENT_PRESSED)
-      gi->callback_action(gi);
-  }
-
-  if (gadget_pressed_repeated)
-  {
-    gi->event.type = GD_EVENT_PRESSED;
-
-    if (gi->event_mask & GD_EVENT_REPEATED &&
-       DelayReached(&pressed_delay, GADGET_FRAME_DELAY))
-      gi->callback_action(gi);
-  }
-
-  if (gadget_moving)
-  {
-    if (gi->type & GD_TYPE_BUTTON)
-    {
-      if (gadget_moving_inside && gi->state == GD_BUTTON_UNPRESSED)
-       DrawGadget(gi, DG_PRESSED, DG_DIRECT);
-      else if (gadget_moving_off_borders && gi->state == GD_BUTTON_PRESSED)
-       DrawGadget(gi, DG_UNPRESSED, DG_DIRECT);
-    }
-
-    if (gi->type & GD_TYPE_SCROLLBAR)
-    {
-      struct GadgetScrollbar *gs = &gi->scrollbar;
-      int old_item_position = gs->item_position;
-
-      gs->position = scrollbar_mouse_pos - gs->drag_position;
-
-      if (gs->position < 0)
-       gs->position = 0;
-      if (gs->position > gs->position_max)
-       gs->position = gs->position_max;
-
-      gs->item_position =
-       gs->items_max * (gs->position + gs->correction) / gs->size_max;
-
-      if (gs->item_position < 0)
-       gs->item_position = 0;
-      if (gs->item_position > gs->items_max - 1)
-       gs->item_position = gs->items_max - 1;
-
-      if (old_item_position != gs->item_position)
-      {
-       gi->event.item_position = gs->item_position;
-       changed_position = TRUE;
-      }
-
-      DrawGadget(gi, DG_PRESSED, DG_DIRECT);
-    }
-
-    gi->state = (gadget_moving_inside || gi->type & GD_TYPE_SCROLLBAR ?
-                GD_BUTTON_PRESSED : GD_BUTTON_UNPRESSED);
-    gi->event.type = GD_EVENT_MOVING;
-    gi->event.off_borders = gadget_moving_off_borders;
-
-    if (gi->event_mask & GD_EVENT_MOVING && changed_position &&
-       (gadget_moving_inside || gi->event_mask & GD_EVENT_OFF_BORDERS))
-      gi->callback_action(gi);
-  }
-
-  if (gadget_released_inside)
-  {
-    if (!(gi->type & GD_TYPE_TEXTINPUT))
-      DrawGadget(gi, DG_UNPRESSED, DG_DIRECT);
-
-    gi->state = GD_BUTTON_UNPRESSED;
-    gi->event.type = GD_EVENT_RELEASED;
-
-    if (gi->event_mask & GD_EVENT_RELEASED)
-      gi->callback_action(gi);
-  }
-
-  if (gadget_released_off_borders)
-  {
-    if (gi->type & GD_TYPE_SCROLLBAR)
-      DrawGadget(gi, DG_UNPRESSED, DG_DIRECT);
-
-    gi->event.type = GD_EVENT_RELEASED;
-
-    if (gi->event_mask & GD_EVENT_RELEASED &&
-       gi->event_mask & GD_EVENT_OFF_BORDERS)
-      gi->callback_action(gi);
-  }
-}
-
-void HandleGadgetsKeyInput(KeySym key)
-{
-  struct GadgetInfo *gi = last_gi;
-  char text[MAX_GADGET_TEXTSIZE];
-  int text_length;
-  int cursor_pos;
-  char letter;
-  boolean legal_letter;
-
-  if (gi == NULL || !(gi->type & GD_TYPE_TEXTINPUT) || !gi->mapped)
-    return;
-
-  text_length = strlen(gi->text.value);
-  cursor_pos = gi->text.cursor_position;
-  letter = getCharFromKeySym(key);
-  legal_letter = (gi->type == GD_TYPE_TEXTINPUT_NUMERIC ?
-                 letter >= '0' && letter <= '9' :
-                 letter != 0);
-
-  if (legal_letter && text_length < gi->text.size)
-  {
-    strcpy(text, gi->text.value);
-    strcpy(&gi->text.value[cursor_pos + 1], &text[cursor_pos]);
-    gi->text.value[cursor_pos] = letter;
-    gi->text.cursor_position++;
-    DrawGadget(gi, DG_PRESSED, DG_DIRECT);
-  }
-  else if (key == XK_Left && cursor_pos > 0)
-  {
-    gi->text.cursor_position--;
-    DrawGadget(gi, DG_PRESSED, DG_DIRECT);
-  }
-  else if (key == XK_Right && cursor_pos < text_length)
-  {
-    gi->text.cursor_position++;
-    DrawGadget(gi, DG_PRESSED, DG_DIRECT);
-  }
-  else if (key == XK_BackSpace && cursor_pos > 0)
-  {
-    strcpy(text, gi->text.value);
-    strcpy(&gi->text.value[cursor_pos - 1], &text[cursor_pos]);
-    gi->text.cursor_position--;
-    DrawGadget(gi, DG_PRESSED, DG_DIRECT);
-  }
-  else if (key == XK_Delete && cursor_pos < text_length)
-  {
-    strcpy(text, gi->text.value);
-    strcpy(&gi->text.value[cursor_pos], &text[cursor_pos + 1]);
-    DrawGadget(gi, DG_PRESSED, DG_DIRECT);
-  }
-  else if (key == XK_Return)
-  {
-    CheckRangeOfNumericInputGadget(gi);
-    DrawGadget(gi, DG_UNPRESSED, DG_DIRECT);
-
-    gi->event.type = GD_EVENT_TEXT_RETURN;
-
-    if (gi->event_mask & GD_EVENT_TEXT_RETURN)
-      gi->callback_action(gi);
-
-    last_gi = NULL;
-  }
-}
diff --git a/src/buttons.h b/src/buttons.h
deleted file mode 100644 (file)
index f3d93c8..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-/***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
-*----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
-*----------------------------------------------------------*
-*  buttons.h                                               *
-***********************************************************/
-
-#ifndef BUTTONS_H
-#define BUTTONS_H
-
-#include "main.h"
-
-/* the following definitions are also used by tools.c */
-
-/* some positions in the video tape control window */
-#define VIDEO_DISPLAY1_XPOS    5
-#define VIDEO_DISPLAY1_YPOS    5
-#define VIDEO_DISPLAY2_XPOS    5
-#define VIDEO_DISPLAY2_YPOS    41
-#define VIDEO_DISPLAY_XSIZE    90
-#define VIDEO_DISPLAY_YSIZE    31
-#define VIDEO_BUTTON_XSIZE     18
-#define VIDEO_BUTTON_YSIZE     18
-#define VIDEO_CONTROL_XPOS     5
-#define VIDEO_CONTROL_YPOS     77
-#define VIDEO_CONTROL_XSIZE    VIDEO_DISPLAY_XSIZE
-#define VIDEO_CONTROL_YSIZE    VIDEO_BUTTON_YSIZE
-
-/* values for video tape control */
-#define VIDEO_STATE_PLAY_OFF   (1L << 0)
-#define VIDEO_STATE_PLAY_ON    (1L << 1)
-#define VIDEO_STATE_PLAY       (VIDEO_STATE_PLAY_OFF   | VIDEO_STATE_PLAY_ON)
-#define VIDEO_STATE_REC_OFF    (1L << 2)
-#define VIDEO_STATE_REC_ON     (1L << 3)
-#define VIDEO_STATE_REC                (VIDEO_STATE_REC_OFF    | VIDEO_STATE_REC_ON)
-#define VIDEO_STATE_PAUSE_OFF  (1L << 4)
-#define VIDEO_STATE_PAUSE_ON   (1L << 5)
-#define VIDEO_STATE_PAUSE      (VIDEO_STATE_PAUSE_OFF  | VIDEO_STATE_PAUSE_ON)
-#define VIDEO_STATE_DATE_OFF   (1L << 6)
-#define VIDEO_STATE_DATE_ON    (1L << 7)
-#define VIDEO_STATE_DATE       (VIDEO_STATE_DATE_OFF   | VIDEO_STATE_DATE_ON)
-#define VIDEO_STATE_TIME_OFF   (1L << 8)
-#define VIDEO_STATE_TIME_ON    (1L << 9)
-#define VIDEO_STATE_TIME       (VIDEO_STATE_TIME_OFF   | VIDEO_STATE_TIME_ON)
-#define VIDEO_PRESS_PLAY_ON    (1L << 10)
-#define VIDEO_PRESS_PLAY_OFF   (1L << 11)
-#define VIDEO_PRESS_PLAY       (VIDEO_PRESS_PLAY_OFF   | VIDEO_PRESS_PLAY_ON)
-#define VIDEO_PRESS_REC_ON     (1L << 12)
-#define VIDEO_PRESS_REC_OFF    (1L << 13)
-#define VIDEO_PRESS_REC                (VIDEO_PRESS_REC_OFF    | VIDEO_PRESS_REC_ON)
-#define VIDEO_PRESS_PAUSE_ON   (1L << 14)
-#define VIDEO_PRESS_PAUSE_OFF  (1L << 15)
-#define VIDEO_PRESS_PAUSE      (VIDEO_PRESS_PAUSE_OFF  | VIDEO_PRESS_PAUSE_ON)
-#define VIDEO_PRESS_STOP_ON    (1L << 16)
-#define VIDEO_PRESS_STOP_OFF   (1L << 17)
-#define VIDEO_PRESS_STOP       (VIDEO_PRESS_STOP_OFF   | VIDEO_PRESS_STOP_ON)
-#define VIDEO_PRESS_EJECT_ON   (1L << 18)
-#define VIDEO_PRESS_EJECT_OFF  (1L << 19)
-#define VIDEO_PRESS_EJECT      (VIDEO_PRESS_EJECT_OFF  | VIDEO_PRESS_EJECT_ON)
-
-/* special */
-#define VIDEO_STATE_FFWD_OFF   ((1L << 20) | VIDEO_STATE_PAUSE_OFF)
-#define VIDEO_STATE_FFWD_ON    (1L << 21)
-#define VIDEO_STATE_FFWD       (VIDEO_STATE_FFWD_OFF   | VIDEO_STATE_FFWD_ON)
-#define VIDEO_STATE_PBEND_OFF  (1L << 22)
-#define VIDEO_STATE_PBEND_ON   (1L << 23)
-#define VIDEO_STATE_PBEND      (VIDEO_STATE_PBEND_OFF  | VIDEO_STATE_PBEND_ON)
-
-/* tags to draw video display labels or symbols only */
-#define VIDEO_DISPLAY_DEFAULT          0
-#define VIDEO_DISPLAY_LABEL_ONLY       1
-#define VIDEO_DISPLAY_SYMBOL_ONLY      2
-
-void DrawVideoDisplay(unsigned long, unsigned long);
-void DrawCompleteVideoDisplay(void);
-
-
-/* NEW GADGET STUFF -------------------------------------------------------- */
-
-/* gadget types */
-#define GD_TYPE_NORMAL_BUTTON          (1 << 0)
-#define GD_TYPE_CHECK_BUTTON           (1 << 1)
-#define GD_TYPE_RADIO_BUTTON           (1 << 2)
-#define GD_TYPE_DRAWING_AREA           (1 << 3)
-#define GD_TYPE_TEXTINPUT_ALPHANUMERIC (1 << 4)
-#define GD_TYPE_TEXTINPUT_NUMERIC      (1 << 5)
-#define GD_TYPE_SCROLLBAR_VERTICAL     (1 << 6)
-#define GD_TYPE_SCROLLBAR_HORIZONTAL   (1 << 7)
-
-#define GD_TYPE_BUTTON                 (GD_TYPE_NORMAL_BUTTON | \
-                                        GD_TYPE_CHECK_BUTTON | \
-                                        GD_TYPE_RADIO_BUTTON)
-#define GD_TYPE_SCROLLBAR              (GD_TYPE_SCROLLBAR_VERTICAL | \
-                                        GD_TYPE_SCROLLBAR_HORIZONTAL)
-#define GD_TYPE_TEXTINPUT              (GD_TYPE_TEXTINPUT_ALPHANUMERIC | \
-                                        GD_TYPE_TEXTINPUT_NUMERIC)
-
-/* gadget events */
-#define GD_EVENT_PRESSED               (1 << 0)
-#define GD_EVENT_RELEASED              (1 << 1)
-#define GD_EVENT_MOVING                        (1 << 2)
-#define GD_EVENT_REPEATED              (1 << 3)
-#define GD_EVENT_OFF_BORDERS           (1 << 4)
-#define GD_EVENT_TEXT_RETURN           (1 << 5)
-#define GD_EVENT_TEXT_LEAVING          (1 << 6)
-
-/* gadget button states */
-#define GD_BUTTON_UNPRESSED            0
-#define GD_BUTTON_PRESSED              1
-
-/* gadget structure constants */
-#define MAX_GADGET_TEXTSIZE            1024
-#define MAX_INFO_TEXTSIZE              1024
-
-/* gadget creation tags */
-#define GDI_END                                0
-#define GDI_CUSTOM_ID                  1
-#define GDI_CUSTOM_TYPE_ID             2
-#define GDI_X                          3
-#define GDI_Y                          4
-#define GDI_WIDTH                      5
-#define GDI_HEIGHT                     6
-#define GDI_TYPE                       7
-#define GDI_STATE                      8
-#define GDI_CHECKED                    9
-#define GDI_RADIO_NR                   10
-#define GDI_NUMBER_VALUE               11
-#define GDI_NUMBER_MIN                 12
-#define GDI_NUMBER_MAX                 13
-#define GDI_TEXT_VALUE                 14
-#define GDI_TEXT_SIZE                  15
-#define GDI_TEXT_FONT                  16
-#define GDI_DESIGN_UNPRESSED           17
-#define GDI_DESIGN_PRESSED             18
-#define GDI_ALT_DESIGN_UNPRESSED       19
-#define GDI_ALT_DESIGN_PRESSED         20
-#define GDI_BORDER_SIZE                        21
-#define GDI_TEXTINPUT_DESIGN_WIDTH     22
-#define GDI_DECORATION_DESIGN          23
-#define GDI_DECORATION_POSITION                24
-#define GDI_DECORATION_SIZE            25
-#define GDI_DECORATION_SHIFTING                26
-#define GDI_EVENT_MASK                 27
-#define GDI_EVENT                      28
-#define GDI_CALLBACK_INFO              29
-#define GDI_CALLBACK_ACTION            30
-#define GDI_AREA_SIZE                  31
-#define GDI_ITEM_SIZE                  32
-#define GDI_SCROLLBAR_ITEMS_MAX                33
-#define GDI_SCROLLBAR_ITEMS_VISIBLE    34
-#define GDI_SCROLLBAR_ITEM_POSITION    35
-#define GDI_INFO_TEXT                  36
-
-typedef void (*gadget_function)(void *);
-
-struct GadgetBorder
-{
-  int size;                            /* size of gadget border */
-  int width;                           /* for text input gadgets */
-};
-
-struct GadgetDesign
-{
-  Pixmap pixmap;                       /* Pixmap with gadget surface */
-  int x, y;                            /* position of rectangle in Pixmap */
-};
-
-struct GadgetDecoration
-{
-  struct GadgetDesign design;          /* decoration design structure */
-  int x, y;                            /* position of deco on the gadget */
-  int width, height;                   /* width and height of decoration */
-  int xshift, yshift;                  /* deco shifting when gadget pressed */
-};
-
-struct GadgetEvent
-{
-  unsigned long type;                  /* event type */
-  int button;                          /* button number for button events */
-  int x, y;                            /* gadget position at event time */
-  boolean off_borders;                 /* mouse pointer outside gadget? */
-  int item_x, item_y, item_position;   /* new item position */
-};
-
-struct GadgetDrawingArea
-{
-  int area_xsize, area_ysize;          /* size of drawing area (in items) */
-  int item_xsize, item_ysize;          /* size of each item in drawing area */
-};
-
-struct GadgetTextInput
-{
-  char value[MAX_GADGET_TEXTSIZE];     /* text string in input field */
-  int number_value;                    /* integer value, if numeric */
-  int number_min;                      /* minimal allowed numeric value */
-  int number_max;                      /* maximal allowed numeric value */
-  int size;                            /* maximal size of input text */
-  int cursor_position;                 /* actual cursor position */
-  int font_type;                       /* font to use for text input */
-};
-
-struct GadgetScrollbar
-{
-  int items_max;                       /* number of items to access */
-  int items_visible;                   /* number of visible items */
-  int item_position;                   /* actual item position */
-  int size_max;                                /* this is either width or height */
-  int size;                            /* scrollbar size on screen */
-  int position;                                /* scrollbar position on screen */
-  int position_max;                    /* bottom/right scrollbar position */
-  int drag_position;                   /* drag position on scrollbar */
-  int correction;                      /* scrollbar position correction */
-};
-
-struct GadgetInfo
-{
-  int id;                              /* internal gadget identifier */
-  int custom_id;                       /* custom gadget identifier */
-  int custom_type_id;                  /* custom gadget type identifier */
-  char info_text[MAX_INFO_TEXTSIZE];   /* short popup info text */
-  int x, y;                            /* gadget position */
-  int width, height;                   /* gadget size */
-  unsigned long type;                  /* type (button, text input, ...) */
-  unsigned long state;                 /* state (pressed, released, ...) */
-  boolean checked;                     /* check/radio button state */
-  int radio_nr;                                /* number of radio button series */
-  boolean mapped;                      /* gadget is active */
-  struct GadgetBorder border;          /* gadget border design */
-  struct GadgetDesign design[2];       /* 0: normal; 1: pressed */
-  struct GadgetDesign alt_design[2];   /* alternative design */
-  struct GadgetDecoration deco;                /* decoration on top of gadget */
-  unsigned long event_mask;            /* possible events for this gadget */
-  struct GadgetEvent event;            /* actual gadget event */
-  gadget_function callback_info;       /* function for pop-up info text */
-  gadget_function callback_action;     /* function for gadget action */
-  struct GadgetDrawingArea drawing;    /* fields for drawing area gadget */
-  struct GadgetTextInput text;         /* fields for text input gadget */
-  struct GadgetScrollbar scrollbar;    /* fields for scrollbar gadget */
-  struct GadgetInfo *next;             /* next list entry */
-};
-
-struct GadgetInfo *CreateGadget(int, ...);
-void FreeGadget(struct GadgetInfo *);
-
-void ModifyGadget(struct GadgetInfo *, int, ...);
-void RedrawGadget(struct GadgetInfo *);
-
-void MapGadget(struct GadgetInfo *);
-void UnmapGadget(struct GadgetInfo *);
-void UnmapAllGadgets();
-void RemapAllGadgets();
-
-boolean anyTextGadgetActive();
-void ClickOnGadget(struct GadgetInfo *, int);
-
-void HandleGadgets(int, int, int);
-void HandleGadgetsKeyInput(KeySym);
-
-#endif
index 07394acdb9538591a3cfb0a7c801b42398b7cd23..2ede557a82c7fba4017843f3f6a5e78cde464994 100644 (file)
@@ -1,24 +1,24 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  cartoons.c                                              *
+* cartoons.c                                               *
 ***********************************************************/
 
 #include "cartoons.h"
 #include "main.h"
-#include "misc.h"
 #include "tools.h"
 
+
 static void HandleAnimation(int);
 static boolean AnimateToon(int, boolean);
-static void DrawAnim(Pixmap, GC, int, int, int, int, int, int, int, int);
+static void DrawAnim(Bitmap *, GC, int, int, int, int, int, int, int, int);
 
 struct AnimInfo
 {
@@ -145,9 +145,7 @@ void HandleAnimation(int mode)
         fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
         fy += (ScreenMovDir & (MV_UP|MV_DOWN)    ? ScreenGfxPos : 0);
 
-       XCopyArea(display,fieldbuffer,backbuffer,gc,
-                 fx,fy, SXSIZE,SYSIZE,
-                 SX,SY);
+       BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
       }
 
       return;
@@ -398,8 +396,9 @@ boolean AnimateToon(int toon_nr, boolean restart)
     },
   };
   struct AnimInfo *anim = &toon[toon_nr];
-  Pixmap anim_pixmap = (toon_nr < 6 ? pix[PIX_TOONS] : pix[PIX_HEROES]);
-  GC anim_clip_gc = (toon_nr < 6 ? clip_gc[PIX_TOONS] : clip_gc[PIX_HEROES]);
+  int anim_bitmap_nr = (toon_nr < 6 ? PIX_TOONS : PIX_HEROES);
+  Bitmap *anim_bitmap = pix[anim_bitmap_nr];
+  GC anim_clip_gc = pix[anim_bitmap_nr]->stored_clip_gc;
 
   if (restart)
   {
@@ -465,7 +464,7 @@ boolean AnimateToon(int toon_nr, boolean restart)
     if ((game_status == HELPSCREEN ||
         (game_status == MAINMENU && redraw_mask & REDRAW_MICROLEVEL))
        && !restart)
-      DrawAnim(anim_pixmap, anim_clip_gc,
+      DrawAnim(anim_bitmap, anim_clip_gc,
               src_x + cut_x, src_y + cut_y, width, height,
               REAL_SX + dest_x, REAL_SY + dest_y, pad_x, pad_y);
 
@@ -509,7 +508,7 @@ boolean AnimateToon(int toon_nr, boolean restart)
   else if (pos_y>FULL_SYSIZE-anim->height)
     height -= (pos_y - (FULL_SYSIZE-anim->height));
 
-  DrawAnim(anim_pixmap,anim_clip_gc,
+  DrawAnim(anim_bitmap,anim_clip_gc,
           src_x+cut_x,src_y+cut_y, width,height,
           REAL_SX+dest_x,REAL_SY+dest_y, pad_x,pad_y);
 
@@ -531,7 +530,7 @@ boolean AnimateToon(int toon_nr, boolean restart)
   return(FALSE);
 }
 
-void DrawAnim(Pixmap toon_pixmap, GC toon_clip_gc,
+void DrawAnim(Bitmap *toon_bitmap, GC toon_clip_gc,
              int src_x, int src_y, int width, int height,
              int dest_x, int dest_y, int pad_x, int pad_y)
 {
@@ -539,27 +538,26 @@ void DrawAnim(Pixmap toon_pixmap, GC toon_clip_gc,
 
 #if 1
   /* special method to avoid flickering interference with BackToFront() */
-  XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,dest_x-pad_x,dest_y-pad_y,
-           width+2*pad_x,height+2*pad_y, buf_x,buf_y);
-  XSetClipOrigin(display,toon_clip_gc,dest_x-src_x,dest_y-src_y);
-  XCopyArea(display,toon_pixmap,backbuffer,toon_clip_gc,
-           src_x,src_y, width,height, dest_x,dest_y);
-  XCopyArea(display,backbuffer,window,gc, dest_x-pad_x,dest_y-pad_y,
-           width+2*pad_x,height+2*pad_y, dest_x-pad_x,dest_y-pad_y);
+  BlitBitmap(backbuffer, pix[PIX_DB_DOOR], dest_x-pad_x, dest_y-pad_y,
+            width+2*pad_x, height+2*pad_y, buf_x, buf_y);
+  SetClipOrigin(toon_bitmap, toon_clip_gc, dest_x-src_x, dest_y-src_y);
+  BlitBitmapMasked(toon_bitmap, backbuffer,
+                  src_x, src_y, width, height, dest_x, dest_y);
+  BlitBitmap(backbuffer, window, dest_x-pad_x, dest_y-pad_y,
+            width+2*pad_x, height+2*pad_y, dest_x-pad_x, dest_y-pad_y);
   BackToFront();
-  XCopyArea(display,pix[PIX_DB_DOOR],backbuffer,gc, buf_x,buf_y,
-           width+2*pad_x,height+2*pad_y, dest_x-pad_x,dest_y-pad_y);
+  BlitBitmap(pix[PIX_DB_DOOR], backbuffer, buf_x, buf_y,
+           width+2*pad_x, height+2*pad_y, dest_x-pad_x, dest_y-pad_y);
 #else
   /* normal method, causing flickering interference with BackToFront() */
-  XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,dest_x-pad_x,dest_y-pad_y,
-           width+2*pad_x,height+2*pad_y, buf_x,buf_y);
-  XSetClipOrigin(display,toon_clip_gc,
-                buf_x-src_x+pad_x,buf_y-src_y+pad_y);
-  XCopyArea(display,toon_pixmap,pix[PIX_DB_DOOR],toon_clip_gc,
-           src_x,src_y, width,height, buf_x+pad_x,buf_y+pad_y);
-  XCopyArea(display,pix[PIX_DB_DOOR],window,gc, buf_x,buf_y,
-           width+2*pad_x,height+2*pad_y, dest_x-pad_x,dest_y-pad_y);
+  BlitBitmap(backbuffer, pix[PIX_DB_DOOR], dest_x-pad_x, dest_y-pad_y,
+            width+2*pad_x, height+2*pad_y, buf_x, buf_y);
+  SetClipOrigin(toon_bitmap,toon_clip_gc, buf_x-src_x+pad_x,buf_y-src_y+pad_y);
+  BlitBitmapMasked(toon_bitmap, pix[PIX_DB_DOOR],
+                  src_x, src_y, width, height, buf_x+pad_x, buf_y+pad_y);
+  BlitBitmap(pix[PIX_DB_DOOR], window, buf_x, buf_y,
+            width+2*pad_x, height+2*pad_y, dest_x-pad_x, dest_y-pad_y);
 #endif
 
-  XFlush(display);
+  FlushDisplay();
 }
index fdde0cbc86789a1070a3d1cd78ab78a113e75fd1..b93c21562323f45602c3c5e97fb59fcc760f765f 100644 (file)
@@ -1,14 +1,14 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  cartoons.h                                              *
+* cartoons.h                                               *
 ***********************************************************/
 
 #ifndef CARTOONS_H
index 91e10699148bb92ef47d048fe84fa2f129c7347a..89e8d438d85b3e7947b1eb3930b46f7fc9865f50 100644 (file)
@@ -1,23 +1,23 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  editor.c                                                *
+* editor.c                                                 *
 ***********************************************************/
 
 #include <math.h>
 
+#include "libgame/libgame.h"
+
 #include "editor.h"
 #include "screens.h"
 #include "tools.h"
-#include "misc.h"
-#include "buttons.h"
 #include "files.h"
 #include "game.h"
 #include "tape.h"
@@ -690,10 +690,10 @@ static int new_element1 = EL_MAUERWERK;
 static int new_element2 = EL_LEERRAUM;
 static int new_element3 = EL_ERDREICH;
 
-#define BUTTON_ELEMENT(button) (button == 1 ? new_element1 : \
-                               button == 2 ? new_element2 : \
-                               button == 3 ? new_element3 : EL_LEERRAUM)
-#define BUTTON_STEPSIZE(button) (button == 1 ? 1 : button == 2 ? 5 : 10)
+#define BUTTON_ELEMENT(button) ((button) == 1 ? new_element1 : \
+                               (button) == 2 ? new_element2 : \
+                               (button) == 3 ? new_element3 : EL_LEERRAUM)
+#define BUTTON_STEPSIZE(button) ((button) == 1 ? 1 : (button) == 2 ? 5 : 10)
 
 /* forward declaration for internal use */
 static void ModifyEditorCounter(int, int);
@@ -1261,19 +1261,31 @@ int editor_element[] =
 };
 int elements_in_list = sizeof(editor_element)/sizeof(int);
 
+static char *getElementInfoText(int element)
+{
+  char *info_text = "unknown";
+
+  if (element < num_element_info)
+    info_text = element_info[element];
+  else
+    Error(ERR_WARN, "no element description for element %d", element);
+
+  return info_text;
+}
+
 static void ScrollMiniLevel(int from_x, int from_y, int scroll)
 {
   int x,y;
   int dx = (scroll == ED_SCROLL_LEFT ? -1 : scroll == ED_SCROLL_RIGHT ? 1 : 0);
   int dy = (scroll == ED_SCROLL_UP   ? -1 : scroll == ED_SCROLL_DOWN  ? 1 : 0);
 
-  XCopyArea(display, drawto, drawto, gc,
-           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(drawto, drawto,
+            SX + (dx == -1 ? MINI_TILEX : 0),
+            SY + (dy == -1 ? MINI_TILEY : 0),
+            (ed_fieldx * MINI_TILEX) - (dx != 0 ? MINI_TILEX : 0),
+            (ed_fieldy * MINI_TILEY) - (dy != 0 ? MINI_TILEY : 0),
+            SX + (dx == +1 ? MINI_TILEX : 0),
+            SY + (dy == +1 ? MINI_TILEY : 0));
   if (dx)
   {
     x = (dx == 1 ? 0 : ed_fieldx - 1);
@@ -1293,7 +1305,7 @@ static void ScrollMiniLevel(int from_x, int from_y, int scroll)
 
 static void CreateControlButtons()
 {
-  Pixmap gd_pixmap = pix[PIX_DOOR];
+  Bitmap *gd_bitmap = pix[PIX_DOOR];
   struct GadgetInfo *gi;
   unsigned long event_mask;
   int i;
@@ -1377,11 +1389,12 @@ static void CreateControlButtons()
                      GDI_STATE, GD_BUTTON_UNPRESSED,
                      GDI_RADIO_NR, radio_button_nr,
                      GDI_CHECKED, checked,
-                     GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
-                     GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y1,
-                     GDI_ALT_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y2,
-                     GDI_ALT_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
+                     GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y1,
+                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y1,
+                     GDI_ALT_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y2,
+                     GDI_ALT_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y2,
                      GDI_EVENT_MASK, event_mask,
+                     GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
                      GDI_CALLBACK_ACTION, HandleControlButtons,
                      GDI_END);
 
@@ -1436,9 +1449,10 @@ static void CreateControlButtons()
                      GDI_HEIGHT, height,
                      GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
                      GDI_STATE, GD_BUTTON_UNPRESSED,
-                     GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
-                     GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
+                     GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y1,
+                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y2,
                      GDI_EVENT_MASK, event_mask,
+                     GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
                      GDI_CALLBACK_ACTION, HandleControlButtons,
                      GDI_END);
 
@@ -1451,7 +1465,7 @@ static void CreateControlButtons()
   /* create buttons for element list */
   for (i=0; i<ED_NUM_ELEMENTLIST_BUTTONS; i++)
   {
-    Pixmap deco_pixmap;
+    Bitmap *deco_bitmap;
     int deco_x, deco_y, deco_xpos, deco_ypos;
     int gd_xoffset, gd_yoffset;
     int gd_x1, gd_x2, gd_y;
@@ -1469,26 +1483,27 @@ static void CreateControlButtons()
     gd_y  = DOOR_GFX_PAGEY1 + ED_ELEMENTLIST_YPOS;
 
     getMiniGraphicSource(el2gfx(editor_element[i]),
-                        &deco_pixmap, &deco_x, &deco_y);
+                        &deco_bitmap, &deco_x, &deco_y);
     deco_xpos = (ED_ELEMENTLIST_XSIZE - MINI_TILEX) / 2;
     deco_ypos = (ED_ELEMENTLIST_YSIZE - MINI_TILEY) / 2;
 
     gi = CreateGadget(GDI_CUSTOM_ID, id,
                      GDI_CUSTOM_TYPE_ID, i,
-                     GDI_INFO_TEXT, element_info[editor_element[i]],
+                     GDI_INFO_TEXT, getElementInfoText(editor_element[i]),
                      GDI_X, DX + gd_xoffset,
                      GDI_Y, DY + gd_yoffset,
                      GDI_WIDTH, ED_ELEMENTLIST_XSIZE,
                      GDI_HEIGHT, ED_ELEMENTLIST_YSIZE,
                      GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
                      GDI_STATE, GD_BUTTON_UNPRESSED,
-                     GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
-                     GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
-                     GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
+                     GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
+                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
+                     GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
                      GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
                      GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
                      GDI_DECORATION_SHIFTING, 1, 1,
                      GDI_EVENT_MASK, event_mask,
+                     GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
                      GDI_CALLBACK_ACTION, HandleControlButtons,
                      GDI_END);
 
@@ -1511,7 +1526,7 @@ static void CreateCounterButtons()
 
     for (j=0; j<2; j++)
     {
-      Pixmap gd_pixmap = pix[PIX_DOOR];
+      Bitmap *gd_bitmap = pix[PIX_DOOR];
       struct GadgetInfo *gi;
       int id = (j == 0 ?
                counterbutton_info[i].gadget_id_down :
@@ -1564,9 +1579,10 @@ static void CreateCounterButtons()
                        GDI_HEIGHT, y_size,
                        GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
                        GDI_STATE, GD_BUTTON_UNPRESSED,
-                       GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
-                       GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
+                       GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
+                       GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
                        GDI_EVENT_MASK, event_mask,
+                       GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
                        GDI_CALLBACK_ACTION, HandleCounterButtons,
                        GDI_END);
 
@@ -1612,11 +1628,12 @@ static void CreateCounterButtons()
                          GDI_NUMBER_MAX, counterbutton_info[i].max_value,
                          GDI_TEXT_SIZE, 3,
                          GDI_TEXT_FONT, font_type,
-                         GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x, gd_y,
-                         GDI_DESIGN_PRESSED, gd_pixmap, gd_x, gd_y,
+                         GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x, gd_y,
+                         GDI_DESIGN_PRESSED, gd_bitmap, gd_x, gd_y,
                          GDI_BORDER_SIZE, ED_BORDER_SIZE,
                          GDI_TEXTINPUT_DESIGN_WIDTH, gd_width,
                          GDI_EVENT_MASK, event_mask,
+                         GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
                          GDI_CALLBACK_ACTION, HandleCounterButtons,
                          GDI_END);
 
@@ -1731,7 +1748,7 @@ static void CreateTextInputGadgets()
 
   for (i=0; i<ED_NUM_TEXTINPUT; i++)
   {
-    Pixmap gd_pixmap = pix[PIX_DOOR];
+    Bitmap *gd_bitmap = pix[PIX_DOOR];
     int gd_x, gd_y;
     struct GadgetInfo *gi;
     unsigned long event_mask;
@@ -1755,11 +1772,12 @@ static void CreateTextInputGadgets()
                      GDI_TEXT_VALUE, textinput_info[i].value,
                      GDI_TEXT_SIZE, textinput_info[i].size,
                      GDI_TEXT_FONT, FC_YELLOW,
-                     GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x, gd_y,
-                     GDI_DESIGN_PRESSED, gd_pixmap, gd_x, gd_y,
+                     GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x, gd_y,
+                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x, gd_y,
                      GDI_BORDER_SIZE, ED_BORDER_SIZE,
                      GDI_TEXTINPUT_DESIGN_WIDTH, ED_WIN_COUNT_XSIZE,
                      GDI_EVENT_MASK, event_mask,
+                     GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
                      GDI_CALLBACK_ACTION, HandleTextInputGadgets,
                      GDI_END);
 
@@ -1777,7 +1795,7 @@ static void CreateScrollbarGadgets()
   for (i=0; i<ED_NUM_SCROLLBARS; i++)
   {
     int id = scrollbar_info[i].gadget_id;
-    Pixmap gd_pixmap = pix[PIX_DOOR];
+    Bitmap *gd_bitmap = pix[PIX_DOOR];
     int gd_x1, gd_x2, gd_y1, gd_y2;
     struct GadgetInfo *gi;
     int items_max, items_visible, item_position;
@@ -1825,10 +1843,11 @@ static void CreateScrollbarGadgets()
                      GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible,
                      GDI_SCROLLBAR_ITEM_POSITION, item_position,
                      GDI_STATE, GD_BUTTON_UNPRESSED,
-                     GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
-                     GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
+                     GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y1,
+                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y2,
                      GDI_BORDER_SIZE, ED_BORDER_SIZE,
                      GDI_EVENT_MASK, event_mask,
+                     GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
                      GDI_CALLBACK_ACTION, HandleControlButtons,
                      GDI_END);
 
@@ -1841,7 +1860,7 @@ static void CreateScrollbarGadgets()
 
 static void CreateCheckbuttonGadgets()
 {
-  Pixmap gd_pixmap = pix[PIX_DOOR];
+  Bitmap *gd_bitmap = pix[PIX_DOOR];
   struct GadgetInfo *gi;
   unsigned long event_mask;
   int gd_x1, gd_x2, gd_x3, gd_x4, gd_y;
@@ -1873,11 +1892,12 @@ static void CreateCheckbuttonGadgets()
                      GDI_TYPE, GD_TYPE_RADIO_BUTTON,
                      GDI_RADIO_NR, radiobutton_info[i].radio_button_nr,
                      GDI_CHECKED, checked,
-                     GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
-                     GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
-                     GDI_ALT_DESIGN_UNPRESSED, gd_pixmap, gd_x3, gd_y,
-                     GDI_ALT_DESIGN_PRESSED, gd_pixmap, gd_x4, gd_y,
+                     GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
+                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
+                     GDI_ALT_DESIGN_UNPRESSED, gd_bitmap, gd_x3, gd_y,
+                     GDI_ALT_DESIGN_PRESSED, gd_bitmap, gd_x4, gd_y,
                      GDI_EVENT_MASK, event_mask,
+                     GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
                      GDI_CALLBACK_ACTION, HandleRadiobuttons,
                      GDI_END);
 
@@ -1905,11 +1925,12 @@ static void CreateCheckbuttonGadgets()
                      GDI_HEIGHT, ED_CHECKBUTTON_YSIZE,
                      GDI_TYPE, GD_TYPE_CHECK_BUTTON,
                      GDI_CHECKED, *checkbutton_info[i].value,
-                     GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
-                     GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
-                     GDI_ALT_DESIGN_UNPRESSED, gd_pixmap, gd_x3, gd_y,
-                     GDI_ALT_DESIGN_PRESSED, gd_pixmap, gd_x4, gd_y,
+                     GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
+                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
+                     GDI_ALT_DESIGN_UNPRESSED, gd_bitmap, gd_x3, gd_y,
+                     GDI_ALT_DESIGN_PRESSED, gd_bitmap, gd_x4, gd_y,
                      GDI_EVENT_MASK, event_mask,
+                     GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
                      GDI_CALLBACK_ACTION, HandleCheckbuttons,
                      GDI_END);
 
@@ -2109,17 +2130,17 @@ void DrawLevelEd()
   }
 
   /* copy default editor door content to main double buffer */
-  XCopyArea(display, pix[PIX_DOOR], drawto, gc,
-           DOOR_GFX_PAGEX6, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY);
+  BlitBitmap(pix[PIX_DOOR], drawto,
+            DOOR_GFX_PAGEX6, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY);
 
   /* draw mouse button brush elements */
-  DrawMiniGraphicExt(drawto, gc,
+  DrawMiniGraphicExt(drawto,
                     DX + ED_WIN_MB_LEFT_XPOS, DY + ED_WIN_MB_LEFT_YPOS,
                     el2gfx(new_element1));
-  DrawMiniGraphicExt(drawto, gc,
+  DrawMiniGraphicExt(drawto,
                     DX + ED_WIN_MB_MIDDLE_XPOS, DY + ED_WIN_MB_MIDDLE_YPOS,
                     el2gfx(new_element2));
-  DrawMiniGraphicExt(drawto, gc,
+  DrawMiniGraphicExt(drawto,
                     DX + ED_WIN_MB_RIGHT_XPOS, DY + ED_WIN_MB_RIGHT_YPOS,
                     el2gfx(new_element3));
 
@@ -2127,18 +2148,16 @@ void DrawLevelEd()
   DrawSpecialEditorDoor();
 
   /* draw new control window */
-  XCopyArea(display, pix[PIX_DOOR], drawto, gc,
-           DOOR_GFX_PAGEX8, 236,
-           EXSIZE, EYSIZE,
-           EX, EY);
+  BlitBitmap(pix[PIX_DOOR], drawto,
+            DOOR_GFX_PAGEX8, 236, EXSIZE, EYSIZE, EX, EY);
 
   redraw_mask |= REDRAW_ALL;
 
   MapControlButtons();
 
   /* copy actual editor door content to door double buffer for OpenDoor() */
-  XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
-           DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+  BlitBitmap(drawto, pix[PIX_DB_DOOR],
+            DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
 
   DrawEditModeWindow();
 
@@ -2294,21 +2313,21 @@ static void PickDrawingElement(int button, int element)
   if (button == 1)
   {
     new_element1 = element;
-    DrawMiniGraphicExt(drawto, gc,
+    DrawMiniGraphicExt(drawto,
                       DX + ED_WIN_MB_LEFT_XPOS, DY + ED_WIN_MB_LEFT_YPOS,
                       el2gfx(new_element1));
   }
   else if (button == 2)
   {
     new_element2 = element;
-    DrawMiniGraphicExt(drawto, gc,
+    DrawMiniGraphicExt(drawto,
                       DX + ED_WIN_MB_MIDDLE_XPOS, DY + ED_WIN_MB_MIDDLE_YPOS,
                       el2gfx(new_element2));
   }
   else
   {
     new_element3 = element;
-    DrawMiniGraphicExt(drawto, gc,
+    DrawMiniGraphicExt(drawto,
                       DX + ED_WIN_MB_RIGHT_XPOS, DY + ED_WIN_MB_RIGHT_YPOS,
                       el2gfx(new_element3));
   }
@@ -2343,14 +2362,14 @@ static void DrawRandomPlacementBackgroundArea()
     for (x=0; x<2; x++)
       DrawMiniElement(area_x + x, area_y + y, EL_ERDREICH);
 
-  XFillRectangle(display, drawto, gc,
+  ClearRectangle(drawto,
                 area_sx + MINI_TILEX/2 - 1, area_sy + MINI_TILEY/2 - 1,
                 MINI_TILEX + 2, MINI_TILEY + 2);
 
   /* copy border to the right location */
-  XCopyArea(display, drawto, drawto, gc,
-           area_sx, area_sy, 3 * MINI_TILEX, 3 * MINI_TILEY,
-           area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
+  BlitBitmap(drawto, drawto,
+            area_sx, area_sy, 3 * MINI_TILEX, 3 * MINI_TILEY,
+            area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
 
   DrawMiniElement(area_x, area_y, ElementContent[0][0][0]);
 
@@ -2465,14 +2484,14 @@ static void DrawAmoebaContentArea()
     for (x=0; x<2; x++)
       DrawMiniElement(area_x + x, area_y + y, EL_ERDREICH);
 
-  XFillRectangle(display, drawto, gc,
+  ClearRectangle(drawto,
                 area_sx + MINI_TILEX/2 - 1, area_sy + MINI_TILEY/2 - 1,
                 MINI_TILEX + 2, MINI_TILEY + 2);
 
   /* copy border to the right location */
-  XCopyArea(display, drawto, drawto, gc,
-           area_sx, area_sy, 3 * MINI_TILEX, 3 * MINI_TILEY,
-           area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
+  BlitBitmap(drawto, drawto,
+            area_sx, area_sy, 3 * MINI_TILEX, 3 * MINI_TILEY,
+            area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
 
   DrawText(area_sx + TILEX, area_sy + 1, "Content of amoeba",
           FS_SMALL, font_color);
@@ -2511,7 +2530,7 @@ static void DrawElementContentAreas()
   MapCounterButtons(counter_id);
 
   /* delete content areas in case of reducing number of them */
-  XFillRectangle(display, backbuffer, gc,
+  ClearRectangle(backbuffer,
                 SX, area_sy - MINI_TILEX,
                 SXSIZE, 12 * MINI_TILEY);
 
@@ -2523,16 +2542,16 @@ static void DrawElementContentAreas()
        DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
                        EL_ERDREICH);
 
-    XFillRectangle(display, drawto, gc,
+    ClearRectangle(drawto,
                   area_sx + 5 * (i % 4) * MINI_TILEX + MINI_TILEX/2 - 1,
                   area_sy + 6 * (i / 4) * MINI_TILEY + MINI_TILEY/2 - 1,
                   3 * MINI_TILEX + 2, 3 * MINI_TILEY + 2);
   }
 
   /* copy border to the right location */
-  XCopyArea(display, drawto, drawto, gc,
-           area_sx, area_sy, (5 * 4 + 1) * MINI_TILEX, 11 * MINI_TILEY,
-           area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
+  BlitBitmap(drawto, drawto,
+            area_sx, area_sy, (5 * 4 + 1) * MINI_TILEX, 11 * MINI_TILEY,
+            area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
 
   DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 0 * MINI_TILEY + 1,
           "Content", FS_SMALL, font_color);
@@ -2642,31 +2661,31 @@ static void DrawPropertiesWindow()
     for (x=0; x<3; x++)
       DrawMiniElement(xstart + x , ystart + y, EL_ERDREICH);
 
-  XFillRectangle(display, drawto, gc,
+  ClearRectangle(drawto,
                 SX + xstart * MINI_TILEX + MINI_TILEX/2 - 1,
                 SY + ystart * MINI_TILEY + MINI_TILEY/2 - 1,
                 TILEX + 2, TILEY + 2);
 
   /* copy border to the right location */
-  XCopyArea(display, drawto, drawto, gc,
-           SX + xstart * MINI_TILEX,
-           SY + ystart * MINI_TILEY,
-           2 * TILEX, 2 * TILEY,
-           SX + xstart * MINI_TILEX - MINI_TILEX/2,
-           SY + ystart * MINI_TILEY - MINI_TILEY/2);
+  BlitBitmap(drawto, drawto,
+            SX + xstart * MINI_TILEX,
+            SY + ystart * MINI_TILEY,
+            2 * TILEX, 2 * TILEY,
+            SX + xstart * MINI_TILEX - MINI_TILEX/2,
+            SY + ystart * MINI_TILEY - MINI_TILEY/2);
 
   DrawGraphic(xstart/2, ystart/2, el2gfx(properties_element));
 
   /* copy the whole stuff to the definitive location */
-  XCopyArea(display, drawto, drawto, gc,
-           SX + xstart * MINI_TILEX - MINI_TILEX/2,
-           SY + ystart * MINI_TILEY - MINI_TILEY,
-           2 * TILEX, 2 * TILEY,
-           SX + xstart * MINI_TILEX - MINI_TILEX/2,
-           SY + ystart * MINI_TILEY - MINI_TILEY/2);
+  BlitBitmap(drawto, drawto,
+            SX + xstart * MINI_TILEX - MINI_TILEX/2,
+            SY + ystart * MINI_TILEY - MINI_TILEY,
+            2 * TILEX, 2 * TILEY,
+            SX + xstart * MINI_TILEX - MINI_TILEX/2,
+            SY + ystart * MINI_TILEY - MINI_TILEY/2);
 
   DrawTextF((xstart + 3) * MINI_TILEX, (ystart + 1) * MINI_TILEY,
-           font_color, element_info[properties_element]);
+           font_color, getElementInfoText(properties_element));
 
   num_elements_in_level = 0;
   for (y=0; y<lev_fieldy; y++) 
@@ -2715,26 +2734,6 @@ static void DrawPropertiesWindow()
   }
 }
 
-static void swap_numbers(int *i1, int *i2)
-{
-  int help = *i1;
-
-  *i1 = *i2;
-  *i2 = help;
-}
-
-static void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
-{
-  int help_x = *x1;
-  int help_y = *y1;
-
-  *x1 = *x2;
-  *x2 = help_x;
-
-  *y1 = *y2;
-  *y2 = help_y;
-}
-
 static void DrawLineElement(int sx, int sy, int element, boolean change_level)
 {
   int lx = sx + level_xpos;
@@ -2914,14 +2913,10 @@ static void DrawAreaBorder(int from_x, int from_y, int to_x, int to_y)
   to_sx = SX + to_x * MINI_TILEX + MINI_TILEX - 1;
   to_sy = SY + to_y * MINI_TILEY + MINI_TILEY - 1;
 
-  XSetForeground(display, gc, WhitePixel(display, screen));
-
-  XDrawLine(display, drawto, gc, from_sx, from_sy, to_sx, from_sy);
-  XDrawLine(display, drawto, gc, to_sx, from_sy, to_sx, to_sy);
-  XDrawLine(display, drawto, gc, to_sx, to_sy, from_sx, to_sy);
-  XDrawLine(display, drawto, gc, from_sx, to_sy, from_sx, from_sy);
-
-  XSetForeground(display, gc, BlackPixel(display, screen));
+  DrawSimpleWhiteLine(drawto, from_sx, from_sy, to_sx, from_sy);
+  DrawSimpleWhiteLine(drawto, to_sx, from_sy, to_sx, to_sy);
+  DrawSimpleWhiteLine(drawto, to_sx, to_sy, from_sx, to_sy);
+  DrawSimpleWhiteLine(drawto, from_sx, to_sy, from_sx, from_sy);
 
   if (from_x == to_x && from_y == to_y)
     MarkTileDirty(from_x/2, from_y/2);
@@ -3456,11 +3451,11 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
       }
       else
       {
-       DrawMiniGraphicExt(drawto, gc,
+       DrawMiniGraphicExt(drawto,
                           gi->x + sx * MINI_TILEX,
                           gi->y + sy * MINI_TILEY,
                           el2gfx(new_element));
-       DrawMiniGraphicExt(window, gc,
+       DrawMiniGraphicExt(window,
                           gi->x + sx * MINI_TILEX,
                           gi->y + sy * MINI_TILEY,
                           el2gfx(new_element));
@@ -3537,7 +3532,8 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
          {
            CopyAreaToBrush(start_sx, start_sy, sx, sy, button);
            CopyBrushToCursor(sx, sy);
-           ClickOnGadget(level_editor_gadget[GADGET_ID_SINGLE_ITEMS],MB_LEFT);
+           ClickOnGadget(level_editor_gadget[GADGET_ID_SINGLE_ITEMS],
+                         MB_LEFTBUTTON);
            draw_with_brush = TRUE;
          }
          else if (drawing_function == GADGET_ID_TEXT)
@@ -3566,7 +3562,8 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
 
     case GADGET_ID_PICK_ELEMENT:
       if (button_release_event)
-       ClickOnGadget(level_editor_gadget[last_drawing_function], MB_LEFT);
+       ClickOnGadget(level_editor_gadget[last_drawing_function],
+                     MB_LEFTBUTTON);
       else
        PickDrawingElement(button, Feld[lx][ly]);
 
@@ -3782,8 +3779,8 @@ static void HandleControlButtons(struct GadgetInfo *gi)
        int element = editor_element[element_shift + i];
 
        UnmapGadget(gi);
-       getMiniGraphicSource(el2gfx(element), &gd->pixmap, &gd->x, &gd->y);
-       ModifyGadget(gi, GDI_INFO_TEXT, element_info[element], GDI_END);
+       getMiniGraphicSource(el2gfx(element), &gd->bitmap, &gd->x, &gd->y);
+       ModifyGadget(gi, GDI_INFO_TEXT, getElementInfoText(element), GDI_END);
        MapGadget(gi);
       }
       break;
@@ -3944,9 +3941,9 @@ static void HandleControlButtons(struct GadgetInfo *gi)
       else
       {
        CloseDoor(DOOR_CLOSE_1);
-       XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
-                 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
-                 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+       BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
+                  DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
+                  DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
        OpenDoor(DOOR_OPEN_1);
       }
       break;
@@ -3969,7 +3966,8 @@ static void HandleControlButtons(struct GadgetInfo *gi)
        }
 
        if (drawing_function == GADGET_ID_PICK_ELEMENT)
-         ClickOnGadget(level_editor_gadget[last_drawing_function], MB_LEFT);
+         ClickOnGadget(level_editor_gadget[last_drawing_function],
+                       MB_LEFTBUTTON);
       }
 #ifdef DEBUG
       else if (gi->event.type == GD_EVENT_PRESSED)
@@ -3985,19 +3983,19 @@ static void HandleControlButtons(struct GadgetInfo *gi)
   }
 }
 
-void HandleLevelEditorKeyInput(KeySym key)
+void HandleLevelEditorKeyInput(Key key)
 {
-  char letter = getCharFromKeySym(key);
-  int button = MB_LEFT;
+  char letter = getCharFromKey(key);
+  int button = MB_LEFTBUTTON;
 
   if (drawing_function == GADGET_ID_TEXT &&
       DrawLevelText(0, 0, 0, TEXT_QUERY_TYPING) == TRUE)
   {
     if (letter)
       DrawLevelText(0, 0, letter, TEXT_WRITECHAR);
-    else if (key == XK_Delete || key == XK_BackSpace)
+    else if (key == KSYM_Delete || key == KSYM_BackSpace)
       DrawLevelText(0, 0, 0, TEXT_BACKSPACE);
-    else if (key == XK_Return)
+    else if (key == KSYM_Return)
       DrawLevelText(0, 0, 0, TEXT_NEWLINE);
   }
   else if (button_status == MB_RELEASED)
@@ -4006,25 +4004,25 @@ void HandleLevelEditorKeyInput(KeySym key)
 
     switch (key)
     {
-      case XK_Left:
+      case KSYM_Left:
        id = GADGET_ID_SCROLL_LEFT;
        break;
-      case XK_Right:
+      case KSYM_Right:
        id = GADGET_ID_SCROLL_RIGHT;
        break;
-      case XK_Up:
+      case KSYM_Up:
        id = GADGET_ID_SCROLL_UP;
        break;
-      case XK_Down:
+      case KSYM_Down:
        id = GADGET_ID_SCROLL_DOWN;
        break;
-      case XK_Page_Up:
+      case KSYM_Page_Up:
        id = GADGET_ID_SCROLL_LIST_UP;
-       button = 3;
+       button = MB_RIGHTBUTTON;
        break;
-      case XK_Page_Down:
+      case KSYM_Page_Down:
        id = GADGET_ID_SCROLL_LIST_DOWN;
-       button = 3;
+       button = MB_RIGHTBUTTON;
        break;
 
       default:
@@ -4036,7 +4034,7 @@ void HandleLevelEditorKeyInput(KeySym key)
       ClickOnGadget(level_editor_gadget[id], button);
     else if (letter == '.')
       ClickOnGadget(level_editor_gadget[GADGET_ID_SINGLE_ITEMS], button);
-    else if (key == XK_space || key == XK_Return)
+    else if (key == KSYM_space || key == KSYM_Return)
       ClickOnGadget(level_editor_gadget[GADGET_ID_TEST], button);
     else
       for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
@@ -4048,7 +4046,7 @@ void HandleLevelEditorKeyInput(KeySym key)
 
 void ClearEditorGadgetInfoText()
 {
-  XFillRectangle(display, drawto, gc,
+  ClearRectangle(drawto,
                 INFOTEXT_XPOS, INFOTEXT_YPOS, INFOTEXT_XSIZE, INFOTEXT_YSIZE);
   redraw_mask |= REDRAW_FIELD;
 }
@@ -4059,6 +4057,9 @@ void HandleEditorGadgetInfoText(void *ptr)
   char infotext[MAX_INFOTEXT_LEN + 1];
   char shortcut[MAX_INFOTEXT_LEN + 1];
 
+  if (game_status != LEVELED)
+    return;
+
   ClearEditorGadgetInfoText();
 
   /* misuse this function to delete brush cursor, if needed */
@@ -4190,7 +4191,7 @@ static void HandleDrawingAreaInfo(struct GadgetInfo *gi)
       }
       else if (drawing_function == GADGET_ID_PICK_ELEMENT)
        DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
-                 "%s", element_info[Feld[lx][ly]]);
+                 "%s", getElementInfoText(Feld[lx][ly]));
       else
        DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
                  "Level position: %d, %d", lx, ly);
index c77fef7ecbb917c68e0badc8b48f9cc5f2d32fcf..60bb32d710ec06cfcd1f97fdbd3b01b2d4e76b72 100644 (file)
@@ -1,14 +1,14 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  editor.h                                                *
+* editor.h                                                 *
 ***********************************************************/
 
 #ifndef EDITOR_H
@@ -27,7 +27,7 @@ extern int elements_in_list;
 void CreateLevelEditorGadgets();
 void UnmapLevelEditorGadgets();
 void DrawLevelEd(void);
-void HandleLevelEditorKeyInput(KeySym);
+void HandleLevelEditorKeyInput(Key);
 void HandleEditorGadgetInfoText(void *ptr);
 
 #endif
index 1866e7ae79d00373ecab208209ad6cd5765c596b..f4e690f82c2ddbe6b6d3f3aba10df575f4bc9025 100644 (file)
@@ -1,26 +1,26 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  events.c                                                *
+* events.c                                                 *
 ***********************************************************/
 
+#include "libgame/libgame.h"
+
 #include "events.h"
 #include "init.h"
 #include "screens.h"
 #include "tools.h"
 #include "game.h"
 #include "editor.h"
-#include "misc.h"
 #include "tape.h"
 #include "joystick.h"
-#include "buttons.h"
 #include "network.h"
 
 /* values for key_status */
 #define KEY_RELEASED           FALSE
 #define KEY_PRESSED            TRUE
 
+
+/* event filter especially needed for SDL event filtering due to
+   delay problems with lots of mouse motion events when mouse
+   button not pressed */
+
+int FilterMouseMotionEvents(const Event *event)
+{
+  if (event->type != EVENT_MOTIONNOTIFY)
+    return 1;
+
+  /* get mouse motion events without pressed button only in level editor */
+  if (button_status == MB_RELEASED && game_status != LEVELED)
+    return 0;
+  else
+    return 1;
+}
+
+/* this is only really needed for non-SDL targets to filter unwanted events;
+   when using SDL with properly installed event filter, this function can be
+   replaced with a simple "NextEvent()" call, but it doesn't hurt either */
+
+static boolean NextValidEvent(Event *event)
+{
+  while (PendingEvent())
+  {
+    NextEvent(event);
+
+    if (FilterMouseMotionEvents(event))
+      return TRUE;
+  }
+
+  return FALSE;
+}
+
 void EventLoop(void)
 {
   while(1)
   {
-    if (XPending(display))     /* got event from X server */
+    if (PendingEvent())                /* got event */
     {
-      XEvent event;
+      Event event;
 
-      XNextEvent(display, &event);
-
-      switch(event.type)
+      if (NextValidEvent(&event))
       {
-       case ButtonPress:
-       case ButtonRelease:
-         HandleButtonEvent((XButtonEvent *) &event);
-         break;
-
-       case MotionNotify:
-         HandleMotionEvent((XMotionEvent *) &event);
-         break;
-
-       case KeyPress:
-       case KeyRelease:
-         HandleKeyEvent((XKeyEvent *) &event);
-         break;
-
-       default:
-         HandleOtherEvents(&event);
-         break;
+       switch(event.type)
+       {
+         case EVENT_BUTTONPRESS:
+         case EVENT_BUTTONRELEASE:
+           HandleButtonEvent((ButtonEvent *) &event);
+           break;
+  
+         case EVENT_MOTIONNOTIFY:
+           HandleMotionEvent((MotionEvent *) &event);
+           break;
+  
+         case EVENT_KEYPRESS:
+         case EVENT_KEYRELEASE:
+           HandleKeyEvent((KeyEvent *) &event);
+           break;
+  
+         default:
+           HandleOtherEvents(&event);
+           break;
+       }
       }
     }
-
-    HandleNoXEvent();
+    else
+      HandleNoEvent();
 
     /* don't use all CPU time when idle; the main loop while playing
        has its own synchronization and is CPU friendly, too */
 
-    if (game_status != PLAYING)
+    if (game_status == PLAYING)
+      HandleGameActions();
+    else
     {
-      XSync(display, FALSE);
-      if (!XPending(display))  /* delay only if no pending events */
+      SyncDisplay();
+      if (!PendingEvent())     /* delay only if no pending events */
        Delay(10);
     }
 
@@ -80,26 +117,34 @@ void EventLoop(void)
   }
 }
 
-void HandleOtherEvents(XEvent *event)
+void HandleOtherEvents(Event *event)
 {
   switch(event->type)
   {
-    case Expose:
-      HandleExposeEvent((XExposeEvent *) event);
+    case EVENT_EXPOSE:
+      HandleExposeEvent((ExposeEvent *) event);
       break;
 
-    case UnmapNotify:
+    case EVENT_UNMAPNOTIFY:
       SleepWhileUnmapped();
       break;
 
-    case FocusIn:
-    case FocusOut:
-      HandleFocusEvent((XFocusChangeEvent *) event);
+    case EVENT_FOCUSIN:
+    case EVENT_FOCUSOUT:
+      HandleFocusEvent((FocusChangeEvent *) event);
+      break;
+
+    case EVENT_CLIENTMESSAGE:
+      HandleClientMessageEvent((ClientMessageEvent *) event);
       break;
 
-    case ClientMessage:
-      HandleClientMessageEvent((XClientMessageEvent *) event);
+#if defined(TARGET_SDL)
+    case SDL_JOYAXISMOTION:
+    case SDL_JOYBUTTONDOWN:
+    case SDL_JOYBUTTONUP:
+      HandleJoystickEvent(event);
       break;
+#endif
 
     default:
       break;
@@ -108,19 +153,19 @@ void HandleOtherEvents(XEvent *event)
 
 void ClearEventQueue()
 {
-  while(XPending(display))
+  while (PendingEvent())
   {
-    XEvent event;
+    Event event;
 
-    XNextEvent(display, &event);
+    NextEvent(&event);
 
     switch(event.type)
     {
-      case ButtonRelease:
+      case EVENT_BUTTONRELEASE:
        button_status = MB_RELEASED;
        break;
 
-      case KeyRelease:
+      case EVENT_KEYRELEASE:
        key_joystick_mapping = 0;
        break;
 
@@ -135,29 +180,29 @@ void SleepWhileUnmapped()
 {
   boolean window_unmapped = TRUE;
 
-  XAutoRepeatOn(display);
+  KeyboardAutoRepeatOn();
 
   while(window_unmapped)
   {
-    XEvent event;
+    Event event;
 
-    XNextEvent(display, &event);
+    NextEvent(&event);
 
     switch(event.type)
     {
-      case ButtonRelease:
+      case EVENT_BUTTONRELEASE:
        button_status = MB_RELEASED;
        break;
 
-      case KeyRelease:
+      case EVENT_KEYRELEASE:
        key_joystick_mapping = 0;
        break;
 
-      case MapNotify:
+      case EVENT_MAPNOTIFY:
        window_unmapped = FALSE;
        break;
 
-      case UnmapNotify:
+      case EVENT_UNMAPNOTIFY:
        /* this is only to surely prevent the 'should not happen' case
         * of recursively looping between 'SleepWhileUnmapped()' and
         * 'HandleOtherEvents()' which usually calls this funtion.
@@ -171,11 +216,12 @@ void SleepWhileUnmapped()
   }
 
   if (game_status == PLAYING)
-    XAutoRepeatOff(display);
+    KeyboardAutoRepeatOff();
 }
 
-void HandleExposeEvent(XExposeEvent *event)
+void HandleExposeEvent(ExposeEvent *event)
 {
+#ifndef TARGET_SDL
   int x = event->x, y = event->y;
   int width = event->width, height = event->height;
 
@@ -203,21 +249,20 @@ void HandleExposeEvent(XExposeEvent *event)
     fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
     fy += (ScreenMovDir & (MV_UP|MV_DOWN)    ? ScreenGfxPos : 0);
 
-    XCopyArea(display,fieldbuffer,backbuffer,gc,
-             fx,fy, SXSIZE,SYSIZE,
-             SX,SY);
+    BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
   }
 
-  XCopyArea(display,drawto,window,gc, x,y, width,height, x,y);
+  BlitBitmap(drawto, window, x,y, width,height, x,y);
 
-  XFlush(display);
+  FlushDisplay();
+#endif
 }
 
-void HandleButtonEvent(XButtonEvent *event)
+void HandleButtonEvent(ButtonEvent *event)
 {
   motion_status = FALSE;
 
-  if (event->type == ButtonPress)
+  if (event->type == EVENT_BUTTONPRESS)
     button_status = event->button;
   else
     button_status = MB_RELEASED;
@@ -225,59 +270,39 @@ void HandleButtonEvent(XButtonEvent *event)
   HandleButton(event->x, event->y, button_status);
 }
 
-void HandleMotionEvent(XMotionEvent *event)
+void HandleMotionEvent(MotionEvent *event)
 {
-  Window root, child;
-  int root_x, root_y;
-  int win_x, win_y;
-  unsigned int mask;
-
-  if (!XQueryPointer(display, window, &root, &child, &root_x, &root_y,
-                    &win_x, &win_y, &mask))
-    return;
+  if (!PointerInWindow(window))
+    return;    /* window and pointer are on different screens */
 
-  if (!button_status && game_status != LEVELED)
+#if 1
+  if (button_status == MB_RELEASED && game_status != LEVELED)
     return;
+#endif
 
   motion_status = TRUE;
 
-  HandleButton(win_x, win_y, button_status);
+  HandleButton(event->x, event->y, button_status);
 }
 
-void HandleKeyEvent(XKeyEvent *event)
+void HandleKeyEvent(KeyEvent *event)
 {
-  int key_status = (event->type == KeyPress ? KEY_PRESSED : KEY_RELEASED);
-  KeySym key;
-
-  if (game_status == PLAYING)
-  {
-    /* use '0' instead of 'event->state' to get the key without modifiers */
-    key = XLookupKeysym(event, 0);
-  }
-  else
-  {
-    /* get the key with all modifiers */
-    char buffer[10];
-    int buffer_size = 10;
-    XComposeStatus compose;
-    int char_count;
-
-    char_count = XLookupString(event, buffer, buffer_size, &key, &compose);
-    buffer[char_count] = '\0';
-  }
+  int key_status = (event->type==EVENT_KEYPRESS ? KEY_PRESSED : KEY_RELEASED);
+  boolean with_modifiers = (game_status == PLAYING ? FALSE : TRUE);
+  Key key = GetEventKey(event, with_modifiers);
 
   HandleKey(key, key_status);
 }
 
-void HandleFocusEvent(XFocusChangeEvent *event)
+void HandleFocusEvent(FocusChangeEvent *event)
 {
   static int old_joystick_status = -1;
 
-  if (event->type == FocusOut)
+  if (event->type == EVENT_FOCUSOUT)
   {
     int i;
 
-    XAutoRepeatOn(display);
+    KeyboardAutoRepeatOn();
     old_joystick_status = joystick_status;
     joystick_status = JOYSTICK_OFF;
 
@@ -286,7 +311,7 @@ void HandleFocusEvent(XFocusChangeEvent *event)
     for (i=0; i<MAX_PLAYERS; i++)
       stored_player[i].action = 0;
   }
-  else if (event->type == FocusIn)
+  else if (event->type == EVENT_FOCUSIN)
   {
     /* When there are two Rocks'n'Diamonds windows which overlap and
        the player moves the pointer from one game window to the other,
@@ -307,20 +332,17 @@ void HandleFocusEvent(XFocusChangeEvent *event)
     if (game_status == PLAYING)
     {
       Delay(100);
-      XAutoRepeatOff(display);
+      KeyboardAutoRepeatOff();
     }
     if (old_joystick_status != -1)
       joystick_status = old_joystick_status;
   }
 }
 
-void HandleClientMessageEvent(XClientMessageEvent *event)
+void HandleClientMessageEvent(ClientMessageEvent *event)
 {
-#ifndef MSDOS
-  if ((event->window == window) &&
-      (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
+  if (CheckCloseWindowEvent(event))
     CloseAllAndExit(0);
-#endif
 }
 
 void HandleButton(int mx, int my, int button)
@@ -348,7 +370,7 @@ void HandleButton(int mx, int my, int button)
       break;
 
     case TYPENAME:
-      HandleTypeName(0, XK_Return);
+      HandleTypeName(0, KSYM_Return);
       break;
 
     case CHOOSELEVEL:
@@ -409,14 +431,15 @@ void HandleButton(int mx, int my, int button)
   }
 }
 
-void HandleKey(KeySym key, int key_status)
+void HandleKey(Key key, int key_status)
 {
   int joy = 0;
+  boolean anyTextGadgetActiveOrJustFinished = anyTextGadgetActive();
   static struct SetupKeyboardInfo custom_key;
   static struct
   {
-    KeySym *keysym_custom;
-    KeySym keysym_default;
+    Key *key_custom;
+    Key key_default;
     byte action;
   } key_info[] =
   {
@@ -443,7 +466,7 @@ void HandleKey(KeySym key, int key_status)
       custom_key = setup.input[pnr].key;
 
       for (i=0; i<6; i++)
-       if (key == *key_info[i].keysym_custom)
+       if (key == *key_info[i].key_custom)
          key_action |= key_info[i].action;
 
       if (key_status == KEY_PRESSED)
@@ -457,7 +480,7 @@ void HandleKey(KeySym key, int key_status)
     int i;
 
     for (i=0; i<6; i++)
-      if (key == key_info[i].keysym_default)
+      if (key == key_info[i].key_default)
        joy |= key_info[i].action;
   }
 
@@ -477,7 +500,7 @@ void HandleKey(KeySym key, int key_status)
   if (key_status == KEY_RELEASED)
     return;
 
-  if ((key == XK_Return || key == XK_space) &&
+  if ((key == KSYM_Return || key == KSYM_space) &&
       game_status == PLAYING && AllPlayersGone)
   {
     CloseDoor(DOOR_CLOSE_1);
@@ -487,7 +510,7 @@ void HandleKey(KeySym key, int key_status)
   }
 
   /* allow quick escape to the main menu with the Escape key */
-  if (key == XK_Escape && game_status != MAINMENU)
+  if (key == KSYM_Escape && game_status != MAINMENU)
   {
     CloseDoor(DOOR_CLOSE_1 | DOOR_OPEN_2 | DOOR_NO_DELAY);
     game_status = MAINMENU;
@@ -520,8 +543,8 @@ void HandleKey(KeySym key, int key_status)
     case SETUPINPUT:
       switch(key)
       {
-       case XK_Return:
-       case XK_space:
+       case KSYM_Return:
+       case KSYM_space:
          if (game_status == MAINMENU)
            HandleMainMenu(0,0, 0,0, MB_MENU_CHOICE);
           else if (game_status == CHOOSELEVEL)
@@ -532,12 +555,12 @@ void HandleKey(KeySym key, int key_status)
            HandleSetupInputScreen(0,0, 0,0, MB_MENU_CHOICE);
          break;
 
-        case XK_Page_Up:
+        case KSYM_Page_Up:
           if (game_status == CHOOSELEVEL)
             HandleChooseLevel(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
          break;
 
-        case XK_Page_Down:
+        case KSYM_Page_Down:
           if (game_status == CHOOSELEVEL)
             HandleChooseLevel(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
          break;
@@ -554,18 +577,18 @@ void HandleKey(KeySym key, int key_status)
     case HALLOFFAME:
       switch(key)
       {
-       case XK_Return:
-       case XK_space:
+       case KSYM_Return:
+       case KSYM_space:
          game_status = MAINMENU;
          DrawMainMenu();
          BackToFront();
          break;
 
-        case XK_Page_Up:
+        case KSYM_Page_Up:
          HandleHallOfFame(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
          break;
 
-        case XK_Page_Down:
+        case KSYM_Page_Down:
          HandleHallOfFame(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
          break;
 
@@ -575,7 +598,8 @@ void HandleKey(KeySym key, int key_status)
       break;
 
     case LEVELED:
-      HandleLevelEditorKeyInput(key);
+      if (!anyTextGadgetActiveOrJustFinished)
+       HandleLevelEditorKeyInput(key);
       break;
 
     case PLAYING:
@@ -584,17 +608,17 @@ void HandleKey(KeySym key, int key_status)
       {
 
 #ifdef DEBUG
-       case XK_0:
-       case XK_1:
-       case XK_2:
-       case XK_3:
-       case XK_4:
-       case XK_5:
-       case XK_6:
-       case XK_7:
-       case XK_8:
-       case XK_9:
-         if (key == XK_0)
+       case KSYM_0:
+       case KSYM_1:
+       case KSYM_2:
+       case KSYM_3:
+       case KSYM_4:
+       case KSYM_5:
+       case KSYM_6:
+       case KSYM_7:
+       case KSYM_8:
+       case KSYM_9:
+         if (key == KSYM_0)
          {
            if (GameFrameDelay == 500)
              GameFrameDelay = GAME_FRAME_DELAY;
@@ -602,14 +626,46 @@ void HandleKey(KeySym key, int key_status)
              GameFrameDelay = 500;
          }
          else
-           GameFrameDelay = (key - XK_0) * 10;
+           GameFrameDelay = (key - KSYM_0) * 10;
          printf("Game speed == %d%% (%d ms delay between two frames)\n",
                 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
          break;
 
+       case KSYM_d:
+         if (options.debug)
+         {
+           options.debug = FALSE;
+           printf("debug mode disabled\n");
+         }
+         else
+         {
+           options.debug = TRUE;
+           printf("debug mode enabled\n");
+         }
+         break;
+
+       case KSYM_s:
+         if (!global.fps_slowdown)
+         {
+           global.fps_slowdown = TRUE;
+           global.fps_slowdown_factor = 2;
+           printf("fps slowdown enabled -- display only every 2nd frame\n");
+         }
+         else if (global.fps_slowdown_factor == 2)
+         {
+           global.fps_slowdown_factor = 4;
+           printf("fps slowdown enabled -- display only every 4th frame\n");
+         }
+         else
+         {
+           global.fps_slowdown = FALSE;
+           global.fps_slowdown_factor = 1;
+           printf("fps slowdown disabled\n");
+         }
+         break;
 
 #if 0
-       case XK_a:
+       case KSYM_a:
          if (ScrollStepSize == TILEX/8)
            ScrollStepSize = TILEX/4;
          else
@@ -619,7 +675,7 @@ void HandleKey(KeySym key, int key_status)
 #endif
 
 #if 0
-       case XK_m:
+       case KSYM_m:
          if (MoveSpeed == 8)
          {
            MoveSpeed = 4;
@@ -634,30 +690,28 @@ void HandleKey(KeySym key, int key_status)
          break;
 #endif
 
-       case XK_f:
+       case KSYM_f:
          ScrollStepSize = TILEX/8;
          printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
          break;
 
-       case XK_g:
+       case KSYM_g:
          ScrollStepSize = TILEX/4;
          printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
          break;
 
-       case XK_h:
+       case KSYM_h:
          ScrollStepSize = TILEX/2;
          printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
          break;
 
-       case XK_l:
+       case KSYM_l:
          ScrollStepSize = TILEX;
          printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
          break;
 
-#ifndef MSDOS
-       case XK_Q:
-#endif
-       case XK_q:
+       case KSYM_Q:
+       case KSYM_q:
          local_player->dynamite = 1000;
          break;
 
@@ -665,7 +719,7 @@ void HandleKey(KeySym key, int key_status)
 
 #if 0
 
-       case XK_z:
+       case KSYM_z:
          {
            int i;
 
@@ -694,7 +748,7 @@ void HandleKey(KeySym key, int key_status)
   }
 }
 
-void HandleNoXEvent()
+void HandleNoEvent()
 {
   if (button_status && game_status != PLAYING)
   {
@@ -702,15 +756,12 @@ void HandleNoXEvent()
     return;
   }
 
-#ifndef MSDOS
+#if defined(PLATFORM_UNIX)
   if (options.network)
     HandleNetworking();
 #endif
 
   HandleJoystick();
-
-  if (game_status == PLAYING)
-    HandleGameActions();
 }
 
 static int HandleJoystickForAllPlayers()
index a7980e5a0912991376cc13efda8fd263642ccd48..b5e522812b2076a5426bc5f8510576682d831d3b 100644 (file)
@@ -1,14 +1,14 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  events.h                                                *
+* events.h                                                 *
 ***********************************************************/
 
 #ifndef EVENTS_H
 
 #include "main.h"
 
+int FilterMouseMotionEvents(const Event *);
 void EventLoop(void);
-void HandleOtherEvents(XEvent *);
+void HandleOtherEvents(Event *);
 void ClearEventQueue(void);
 void SleepWhileUnmapped(void);
 
-void HandleExposeEvent(XExposeEvent *);
-void HandleButtonEvent(XButtonEvent *);
-void HandleMotionEvent(XMotionEvent *);
-void HandleKeyEvent(XKeyEvent *);
-void HandleFocusEvent(XFocusChangeEvent *);
-void HandleClientMessageEvent(XClientMessageEvent *event);
+void HandleExposeEvent(ExposeEvent *);
+void HandleButtonEvent(ButtonEvent *);
+void HandleMotionEvent(MotionEvent *);
+void HandleKeyEvent(KeyEvent *);
+void HandleFocusEvent(FocusChangeEvent *);
+void HandleClientMessageEvent(ClientMessageEvent *event);
 
-void HandleNoXEvent(void);
+void HandleNoEvent(void);
 
 void HandleButton(int, int, int);
-void HandleKey(KeySym, int);
+void HandleKey(Key, int);
 void HandleJoystick();
 
 #endif
index ce0aff38a2769de47d7b22becaa01980225fbb8e..0fa192c31fccf1a95b5cddcdc45ee36c406f81c5 100644 (file)
@@ -1,24 +1,24 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  files.h                                                 *
+* files.c                                                  *
 ***********************************************************/
 
 #include <ctype.h>
 #include <dirent.h>
 #include <sys/stat.h>
-#include <unistd.h>
+
+#include "libgame/libgame.h"
 
 #include "files.h"
 #include "tools.h"
-#include "misc.h"
 #include "tape.h"
 #include "joystick.h"
 
@@ -46,8 +46,7 @@
 #define TAPE_COOKIE_10         "ROCKSNDIAMONDS_LEVELREC_FILE_VERSION_1.0"
 
 /* file names and filename extensions */
-#ifndef MSDOS
-#define USERDATA_DIRECTORY     ".rocksndiamonds"
+#if !defined(PLATFORM_MSDOS)
 #define LEVELSETUP_DIRECTORY   "levelsetup"
 #define SETUP_FILENAME         "setup.conf"
 #define LEVELSETUP_FILENAME    "levelsetup.conf"
@@ -56,7 +55,6 @@
 #define TAPEFILE_EXTENSION     "tape"
 #define SCOREFILE_EXTENSION    "score"
 #else
-#define USERDATA_DIRECTORY     "userdata"
 #define LEVELSETUP_DIRECTORY   "lvlsetup"
 #define SETUP_FILENAME         "setup.cnf"
 #define LEVELSETUP_FILENAME    "lvlsetup.cnf"
 #define LEVELFILE_EXTENSION    "lvl"
 #define TAPEFILE_EXTENSION     "tap"
 #define SCOREFILE_EXTENSION    "sco"
-#define ERROR_FILENAME         "error.out"
 #endif
 
+#if defined(PLATFORM_WIN32)
+#ifndef S_IRGRP
+#define S_IRGRP S_IRUSR
+#endif
+#ifndef S_IROTH
+#define S_IROTH S_IRUSR
+#endif
+#ifndef S_IWGRP
+#define S_IWGRP S_IWUSR
+#endif
+#ifndef S_IWOTH
+#define S_IWOTH S_IWUSR
+#endif
+#ifndef S_IXGRP
+#define S_IXGRP S_IXUSR
+#endif
+#ifndef S_IXOTH
+#define S_IXOTH S_IXUSR
+#endif
+#endif /* PLATFORM_WIN32 */
+
 /* file permissions for newly written files */
 #define MODE_R_ALL             (S_IRUSR | S_IRGRP | S_IROTH)
 #define MODE_W_ALL             (S_IWUSR | S_IWGRP | S_IWOTH)
 #define MODE_X_ALL             (S_IXUSR | S_IXGRP | S_IXOTH)
-#define USERDATA_DIR_MODE      (MODE_R_ALL | MODE_X_ALL | S_IWUSR)
 #define LEVEL_PERMS            (MODE_R_ALL | MODE_W_ALL)
 #define SCORE_PERMS            LEVEL_PERMS
 #define TAPE_PERMS             LEVEL_PERMS
@@ -187,21 +204,6 @@ char *getLevelClassDescription(struct LevelDirInfo *ldi)
 static void SaveUserLevelInfo();               /* for 'InitUserLevelDir()' */
 static char *getSetupLine(char *, int);                /* for 'SaveUserLevelInfo()' */
 
-char *getUserDataDir()
-{
-  static char *userdata_dir = NULL;
-
-  if (!userdata_dir)
-  {
-    char *home_dir = getHomeDir();
-    char *data_dir = USERDATA_DIRECTORY;
-
-    userdata_dir = getPath2(home_dir, data_dir);
-  }
-
-  return userdata_dir;
-}
-
 static char *getSetupDir()
 {
   return getUserDataDir();
@@ -321,18 +323,6 @@ static char *getScoreFilename(int nr)
   return filename;
 }
 
-static void createDirectory(char *dir, char *text)
-{
-  if (access(dir, F_OK) != 0)
-    if (mkdir(dir, USERDATA_DIR_MODE) != 0)
-      Error(ERR_WARN, "cannot create %s directory '%s'", text, dir);
-}
-
-static void InitUserDataDirectory()
-{
-  createDirectory(getUserDataDir(), "user data");
-}
-
 static void InitTapeDirectory(char *level_subdir)
 {
   createDirectory(getUserDataDir(), "user data");
@@ -466,7 +456,7 @@ void LoadLevel(int level_nr)
   /* always start with reliable default values */
   setLevelInfoToDefaults();
 
-  if (!(file = fopen(filename, "r")))
+  if (!(file = fopen(filename, MODE_READ)))
   {
     Error(ERR_WARN, "cannot read level '%s' - creating new level", filename);
     return;
@@ -630,7 +620,7 @@ void SaveLevel(int level_nr)
   char *oldest_possible_cookie;
   FILE *file;
 
-  if (!(file = fopen(filename, "w")))
+  if (!(file = fopen(filename, MODE_WRITE)))
   {
     Error(ERR_WARN, "cannot save level file '%s'", filename);
     return;
@@ -740,7 +730,7 @@ void LoadTape(int level_nr)
   /* at least one (default: the first) player participates in every tape */
   num_participating_players = 1;
 
-  if (!(file = fopen(filename, "r")))
+  if (!(file = fopen(filename, MODE_READ)))
     return;
 
   /* check file identifier */
@@ -902,7 +892,7 @@ void SaveTape(int level_nr)
     }
   }
 
-  if (!(file = fopen(filename, "w")))
+  if (!(file = fopen(filename, MODE_WRITE)))
   {
     Error(ERR_WARN, "cannot save level recording file '%s'", filename);
     return;
@@ -962,7 +952,7 @@ void LoadScore(int level_nr)
     highscore[i].Score = 0;
   }
 
-  if (!(file = fopen(filename, "r")))
+  if (!(file = fopen(filename, MODE_READ)))
     return;
 
   /* check file identifier */
@@ -1007,7 +997,7 @@ void SaveScore(int level_nr)
 
   InitScoreDirectory(leveldir_current->filename);
 
-  if (!(file = fopen(filename, "w")))
+  if (!(file = fopen(filename, MODE_WRITE)))
   {
     Error(ERR_WARN, "cannot save score for level %d", level_nr);
     return;
@@ -1051,39 +1041,40 @@ void SaveScore(int level_nr)
 #define SETUP_TOKEN_TEAM_MODE          10
 #define SETUP_TOKEN_HANDICAP           11
 #define SETUP_TOKEN_TIME_LIMIT         12
+#define SETUP_TOKEN_FULLSCREEN         13
 
 /* player setup */
-#define SETUP_TOKEN_USE_JOYSTICK       13
-#define SETUP_TOKEN_JOY_DEVICE_NAME    14
-#define SETUP_TOKEN_JOY_XLEFT          15
-#define SETUP_TOKEN_JOY_XMIDDLE                16
-#define SETUP_TOKEN_JOY_XRIGHT         17
-#define SETUP_TOKEN_JOY_YUPPER         18
-#define SETUP_TOKEN_JOY_YMIDDLE                19
-#define SETUP_TOKEN_JOY_YLOWER         20
-#define SETUP_TOKEN_JOY_SNAP           21
-#define SETUP_TOKEN_JOY_BOMB           22
-#define SETUP_TOKEN_KEY_LEFT           23
-#define SETUP_TOKEN_KEY_RIGHT          24
-#define SETUP_TOKEN_KEY_UP             25
-#define SETUP_TOKEN_KEY_DOWN           26
-#define SETUP_TOKEN_KEY_SNAP           27
-#define SETUP_TOKEN_KEY_BOMB           28
+#define SETUP_TOKEN_USE_JOYSTICK       14
+#define SETUP_TOKEN_JOY_DEVICE_NAME    15
+#define SETUP_TOKEN_JOY_XLEFT          16
+#define SETUP_TOKEN_JOY_XMIDDLE                17
+#define SETUP_TOKEN_JOY_XRIGHT         18
+#define SETUP_TOKEN_JOY_YUPPER         19
+#define SETUP_TOKEN_JOY_YMIDDLE                20
+#define SETUP_TOKEN_JOY_YLOWER         21
+#define SETUP_TOKEN_JOY_SNAP           22
+#define SETUP_TOKEN_JOY_BOMB           23
+#define SETUP_TOKEN_KEY_LEFT           24
+#define SETUP_TOKEN_KEY_RIGHT          25
+#define SETUP_TOKEN_KEY_UP             26
+#define SETUP_TOKEN_KEY_DOWN           27
+#define SETUP_TOKEN_KEY_SNAP           28
+#define SETUP_TOKEN_KEY_BOMB           29
 
 /* level directory info */
-#define LEVELINFO_TOKEN_NAME           29
-#define LEVELINFO_TOKEN_NAME_SHORT     30
-#define LEVELINFO_TOKEN_NAME_SORTING   31
-#define LEVELINFO_TOKEN_AUTHOR         32
-#define LEVELINFO_TOKEN_IMPORTED_FROM  33
-#define LEVELINFO_TOKEN_LEVELS         34
-#define LEVELINFO_TOKEN_FIRST_LEVEL    35
-#define LEVELINFO_TOKEN_SORT_PRIORITY  36
-#define LEVELINFO_TOKEN_LEVEL_GROUP    37
-#define LEVELINFO_TOKEN_READONLY       38
+#define LEVELINFO_TOKEN_NAME           30
+#define LEVELINFO_TOKEN_NAME_SHORT     31
+#define LEVELINFO_TOKEN_NAME_SORTING   32
+#define LEVELINFO_TOKEN_AUTHOR         33
+#define LEVELINFO_TOKEN_IMPORTED_FROM  34
+#define LEVELINFO_TOKEN_LEVELS         35
+#define LEVELINFO_TOKEN_FIRST_LEVEL    36
+#define LEVELINFO_TOKEN_SORT_PRIORITY  37
+#define LEVELINFO_TOKEN_LEVEL_GROUP    38
+#define LEVELINFO_TOKEN_READONLY       39
 
 #define FIRST_GLOBAL_SETUP_TOKEN       SETUP_TOKEN_PLAYER_NAME
-#define LAST_GLOBAL_SETUP_TOKEN                SETUP_TOKEN_TIME_LIMIT
+#define LAST_GLOBAL_SETUP_TOKEN                SETUP_TOKEN_FULLSCREEN
 
 #define FIRST_PLAYER_SETUP_TOKEN       SETUP_TOKEN_USE_JOYSTICK
 #define LAST_PLAYER_SETUP_TOKEN                SETUP_TOKEN_KEY_BOMB
@@ -1093,7 +1084,7 @@ void SaveScore(int level_nr)
 
 #define TYPE_BOOLEAN                   1
 #define TYPE_SWITCH                    2
-#define TYPE_KEYSYM                    3
+#define TYPE_KEY                       3
 #define TYPE_INTEGER                   4
 #define TYPE_STRING                    5
 
@@ -1127,6 +1118,7 @@ static struct
   { TYPE_SWITCH,  &si.team_mode,       "team_mode"                     },
   { TYPE_SWITCH,  &si.handicap,                "handicap"                      },
   { TYPE_SWITCH,  &si.time_limit,      "time_limit"                    },
+  { TYPE_SWITCH,  &si.fullscreen,      "fullscreen"                    },
 
   /* player setup */
   { TYPE_BOOLEAN, &sii.use_joystick,   ".use_joystick"                 },
@@ -1139,12 +1131,12 @@ static struct
   { TYPE_INTEGER, &sii.joy.ylower,     ".joy.ylower"                   },
   { TYPE_INTEGER, &sii.joy.snap,       ".joy.snap_field"               },
   { TYPE_INTEGER, &sii.joy.bomb,       ".joy.place_bomb"               },
-  { TYPE_KEYSYM,  &sii.key.left,       ".key.move_left"                },
-  { TYPE_KEYSYM,  &sii.key.right,      ".key.move_right"               },
-  { TYPE_KEYSYM,  &sii.key.up,         ".key.move_up"                  },
-  { TYPE_KEYSYM,  &sii.key.down,       ".key.move_down"                },
-  { TYPE_KEYSYM,  &sii.key.snap,       ".key.snap_field"               },
-  { TYPE_KEYSYM,  &sii.key.bomb,       ".key.place_bomb"               },
+  { TYPE_KEY,     &sii.key.left,       ".key.move_left"                },
+  { TYPE_KEY,     &sii.key.right,      ".key.move_right"               },
+  { TYPE_KEY,     &sii.key.up,         ".key.move_up"                  },
+  { TYPE_KEY,     &sii.key.down,       ".key.move_down"                },
+  { TYPE_KEY,     &sii.key.snap,       ".key.snap_field"               },
+  { TYPE_KEY,     &sii.key.bomb,       ".key.place_bomb"               },
 
   /* level directory info */
   { TYPE_STRING,  &ldi.name,           "name"                          },
@@ -1312,7 +1304,7 @@ static struct SetupFileList *loadSetupFileList(char *filename)
 
   FILE *file;
 
-  if (!(file = fopen(filename, "r")))
+  if (!(file = fopen(filename, MODE_READ)))
   {
     Error(ERR_WARN, "cannot open configuration file '%s'", filename);
     return NULL;
@@ -1500,6 +1492,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->team_mode = FALSE;
   si->handicap = TRUE;
   si->time_limit = TRUE;
+  si->fullscreen = FALSE;
 
   for (i=0; i<MAX_PLAYERS; i++)
   {
@@ -1513,12 +1506,12 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
     si->input[i].joy.ylower  = JOYSTICK_YLOWER;
     si->input[i].joy.snap  = (i == 0 ? JOY_BUTTON_1 : 0);
     si->input[i].joy.bomb  = (i == 0 ? JOY_BUTTON_2 : 0);
-    si->input[i].key.left  = (i == 0 ? DEFAULT_KEY_LEFT  : KEY_UNDEFINDED);
-    si->input[i].key.right = (i == 0 ? DEFAULT_KEY_RIGHT : KEY_UNDEFINDED);
-    si->input[i].key.up    = (i == 0 ? DEFAULT_KEY_UP    : KEY_UNDEFINDED);
-    si->input[i].key.down  = (i == 0 ? DEFAULT_KEY_DOWN  : KEY_UNDEFINDED);
-    si->input[i].key.snap  = (i == 0 ? DEFAULT_KEY_SNAP  : KEY_UNDEFINDED);
-    si->input[i].key.bomb  = (i == 0 ? DEFAULT_KEY_BOMB  : KEY_UNDEFINDED);
+    si->input[i].key.left  = (i == 0 ? DEFAULT_KEY_LEFT  : KSYM_UNDEFINED);
+    si->input[i].key.right = (i == 0 ? DEFAULT_KEY_RIGHT : KSYM_UNDEFINED);
+    si->input[i].key.up    = (i == 0 ? DEFAULT_KEY_UP    : KSYM_UNDEFINED);
+    si->input[i].key.down  = (i == 0 ? DEFAULT_KEY_DOWN  : KSYM_UNDEFINED);
+    si->input[i].key.snap  = (i == 0 ? DEFAULT_KEY_SNAP  : KSYM_UNDEFINED);
+    si->input[i].key.bomb  = (i == 0 ? DEFAULT_KEY_BOMB  : KSYM_UNDEFINED);
   }
 }
 
@@ -1538,8 +1531,8 @@ static void setSetupInfo(int token_nr, char *token_value)
       *(boolean *)setup_value = get_string_boolean_value(token_value);
       break;
 
-    case TYPE_KEYSYM:
-      *(KeySym *)setup_value = getKeySymFromX11KeyName(token_value);
+    case TYPE_KEY:
+      *(Key *)setup_value = getKeyFromX11KeyName(token_value);
       break;
 
     case TYPE_INTEGER:
@@ -1789,7 +1782,7 @@ static void SaveUserLevelInfo()
 
   filename = getPath2(getUserLevelDir(getLoginName()), LEVELINFO_FILENAME);
 
-  if (!(file = fopen(filename, "w")))
+  if (!(file = fopen(filename, MODE_WRITE)))
   {
     Error(ERR_WARN, "cannot write level info file '%s'", filename);
     free(filename);
@@ -1884,12 +1877,12 @@ static char *getSetupLine(char *prefix, int token_nr)
       strcat(entry, (*(boolean *)setup_value ? "on" : "off"));
       break;
 
-    case TYPE_KEYSYM:
+    case TYPE_KEY:
       {
-       KeySym keysym = *(KeySym *)setup_value;
-       char *keyname = getKeyNameFromKeySym(keysym);
+       Key key = *(Key *)setup_value;
+       char *keyname = getKeyNameFromKey(key);
 
-       strcat(entry, getX11KeyNameFromKeySym(keysym));
+       strcat(entry, getX11KeyNameFromKey(key));
        for (i=strlen(entry); i<50; i++)
          strcat(entry, " ");
 
@@ -1933,7 +1926,7 @@ void SaveSetup()
 
   filename = getPath2(getSetupDir(), SETUP_FILENAME);
 
-  if (!(file = fopen(filename, "w")))
+  if (!(file = fopen(filename, MODE_WRITE)))
   {
     Error(ERR_WARN, "cannot write setup file '%s'", filename);
     free(filename);
@@ -2021,7 +2014,7 @@ void SaveLevelSetup_LastSeries()
 
   filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME);
 
-  if (!(file = fopen(filename, "w")))
+  if (!(file = fopen(filename, MODE_WRITE)))
   {
     Error(ERR_WARN, "cannot write setup file '%s'", filename);
     free(filename);
@@ -2050,7 +2043,7 @@ static void checkSeriesInfo()
   level_directory = getPath2((leveldir_current->user_defined ?
                              getUserLevelDir("") :
                              options.level_directory),
-                            leveldir_current->filename);
+                            leveldir_current->fullpath);
 
   if ((dir = opendir(level_directory)) == NULL)
   {
@@ -2166,7 +2159,7 @@ void SaveLevelSetup_SeriesInfo()
 
   filename = getPath2(getLevelSetupDir(level_subdir), LEVELSETUP_FILENAME);
 
-  if (!(file = fopen(filename, "w")))
+  if (!(file = fopen(filename, MODE_WRITE)))
   {
     Error(ERR_WARN, "cannot write setup file '%s'", filename);
     free(filename);
@@ -2185,46 +2178,5 @@ void SaveLevelSetup_SeriesInfo()
 
   chmod(filename, SETUP_PERMS);
 }
-
-#ifdef MSDOS
-void initErrorFile()
-{
-  char *filename;
-
-  InitUserDataDirectory();
-
-  filename = getPath2(getUserDataDir(), ERROR_FILENAME);
-  unlink(filename);
-  free(filename);
-}
-
-FILE *openErrorFile()
-{
-  char *filename;
-  FILE *error_file;
-
-  filename = getPath2(getUserDataDir(), ERROR_FILENAME);
-  error_file = fopen(filename, "a");
-  free(filename);
-
-  return error_file;
-}
-
-void dumpErrorFile()
-{
-  char *filename;
-  FILE *error_file;
-
-  filename = getPath2(getUserDataDir(), ERROR_FILENAME);
-  error_file = fopen(filename, "r");
-  free(filename);
-
-  if (error_file != NULL)
-  {
-    while (!feof(error_file))
-      fputc(fgetc(error_file), stderr);
-
-    fclose(error_file);
-  }
-}
-#endif
+/*  LocalWords:  Rocks'n
+ */
index 35fa3f10f7e3672b6043a5c5d019f3b9b6ef3c04..a4aeda095067dfad13fe3b552de09c0c2acd5c02 100644 (file)
@@ -1,14 +1,14 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  files.h                                                 *
+* files.h                                                  *
 ***********************************************************/
 
 #ifndef FILES_H
@@ -33,10 +33,4 @@ void SaveLevelSetup_LastSeries(void);
 void LoadLevelSetup_SeriesInfo(void);
 void SaveLevelSetup_SeriesInfo(void);
 
-#ifdef MSDOS
-void initErrorFile();
-FILE *openErrorFile();
-void dumpErrorFile();
-#endif
-
 #endif /* FILES_H */
index 14e6445da7ccb717999e5b7574d8d85b443f1418..dac4381ee073ba21851cf3459afef4ea6dd01f55 100644 (file)
@@ -1,23 +1,22 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  game.c                                                  *
+* game.c                                                   *
 ***********************************************************/
 
+#include "libgame/libgame.h"
+
 #include "game.h"
-#include "misc.h"
 #include "tools.h"
 #include "screens.h"
-#include "sound.h"
 #include "init.h"
-#include "buttons.h"
 #include "files.h"
 #include "tape.h"
 #include "joystick.h"
@@ -167,17 +166,21 @@ static unsigned int getStateCheckSum(int counter)
 
 void GetPlayerConfig()
 {
-  if (sound_status == SOUND_OFF)
+  if (!audio.sound_available)
     setup.sound = FALSE;
 
-  if (!sound_loops_allowed)
+  if (!audio.loops_available)
   {
     setup.sound_loops = FALSE;
     setup.sound_music = FALSE;
   }
 
+  if (!video.fullscreen_available)
+    setup.fullscreen = FALSE;
+
   setup.sound_simple = setup.sound;
 
+  SetAudioMode(setup.sound);
   InitJoysticks();
 }
 
@@ -502,7 +505,7 @@ void InitGame()
 
   network_player_action_received = FALSE;
 
-#ifndef MSDOS
+#if defined(PLATFORM_UNIX)
   /* initial null action */
   if (network_playing)
     SendToServer_MovePlayer(MV_NO_MOVING);
@@ -510,7 +513,6 @@ void InitGame()
 
   ZX = ZY = -1;
 
-  game.yam_content_nr = 0;
   FrameCounter = 0;
   TimeFrames = 0;
   TimePlayed = 0;
@@ -523,6 +525,8 @@ void InitGame()
   ScrollStepSize = 0;  /* will be correctly initialized by ScrollScreen() */
 
   AllPlayersGone = FALSE;
+
+  game.yam_content_nr = 0;
   game.magic_wall_active = FALSE;
   game.magic_wall_time_left = 0;
   game.light_time_left = 0;
@@ -709,32 +713,30 @@ void InitGame()
   DrawAllPlayers();
   FadeToFront();
 
-  /* after drawing the level, corect some elements */
-
+  /* after drawing the level, correct some elements */
   if (game.timegate_time_left == 0)
     CloseAllOpenTimegates();
 
   if (setup.soft_scrolling)
-    XCopyArea(display, fieldbuffer, backbuffer, gc,
-             FX, FY, SXSIZE, SYSIZE, SX, SY);
+    BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
 
   redraw_mask |= REDRAW_FROM_BACKBUFFER;
 
   /* copy default game door content to main double buffer */
-  XCopyArea(display, pix[PIX_DOOR], drawto, gc,
-           DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY);
+  BlitBitmap(pix[PIX_DOOR], drawto,
+            DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY);
 
   if (level_nr < 100)
     DrawText(DX + XX_LEVEL, DY + YY_LEVEL,
             int2str(level_nr, 2), FS_SMALL, FC_YELLOW);
   else
   {
-    DrawTextExt(drawto, gc, DX + XX_EMERALDS, DY + YY_EMERALDS,
+    DrawTextExt(drawto, DX + XX_EMERALDS, DY + YY_EMERALDS,
                int2str(level_nr, 3), FS_SMALL, FC_SPECIAL3);
-    XCopyArea(display, drawto, drawto, gc,
-             DX + XX_EMERALDS, DY + YY_EMERALDS + 1,
-             FONT5_XSIZE * 3, FONT5_YSIZE - 1,
-             DX + XX_LEVEL - 1, DY + YY_LEVEL + 1);
+    BlitBitmap(drawto, drawto,
+              DX + XX_EMERALDS, DY + YY_EMERALDS + 1,
+              FONT5_XSIZE * 3, FONT5_YSIZE - 1,
+              DX + XX_LEVEL - 1, DY + YY_LEVEL + 1);
   }
 
   DrawText(DX + XX_EMERALDS, DY + YY_EMERALDS,
@@ -754,15 +756,15 @@ void InitGame()
   MapTapeButtons();
 
   /* copy actual game door content to door double buffer for OpenDoor() */
-  XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
-           DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+  BlitBitmap(drawto, pix[PIX_DB_DOOR],
+            DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
 
   OpenDoor(DOOR_OPEN_ALL);
 
-  if (setup.sound_music)
-    PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
+  if (setup.sound_music && num_bg_loops)
+    PlayMusic(level_nr % num_bg_loops);
 
-  XAutoRepeatOff(display);
+  KeyboardAutoRepeatOff();
 
   if (options.verbose)
   {
@@ -958,7 +960,9 @@ void GameWon()
       StopSound(SND_SIRR);
   }
 
+#if 0
   FadeSounds();
+#endif
 
   /* Hero disappears */
   DrawLevelField(ExitX, ExitY);
@@ -979,11 +983,13 @@ void GameWon()
   {
     leveldir_current->handicap_level++;
     SaveLevelSetup_SeriesInfo();
-
-    if (level_nr < leveldir_current->last_level)
-      raise_level = TRUE;
   }
 
+  if (level_editor_test_game)
+    local_player->score = -1;  /* no highscore when playing from editor */
+  else if (level_nr < leveldir_current->last_level)
+    raise_level = TRUE;                /* advance to next level */
+
   if ((hi_pos = NewHiScore()) >= 0) 
   {
     game_status = HALLOFFAME;
@@ -3793,8 +3799,8 @@ void EdelsteinFunkeln(int x, int y)
          dest_x = FX + SCREENX(x)*TILEX;
          dest_y = FY + SCREENY(y)*TILEY;
 
-         XCopyArea(display, drawto_field, window, gc,
-                   dest_x, dest_y, TILEX, TILEY, dest_x, dest_y);
+         BlitBitmap(drawto_field, window,
+                    dest_x, dest_y, TILEX, TILEY, dest_x, dest_y);
          SetDrawtoField(DRAW_DIRECT);
        }
       }
@@ -4241,7 +4247,7 @@ void GameActions()
 #endif
     */
 
-#ifndef MSDOS
+#if defined(PLATFORM_UNIX)
     /* last chance to get network player actions without main loop delay */
     HandleNetworking();
 #endif
@@ -4278,7 +4284,7 @@ void GameActions()
       stored_player[i].effective_action = stored_player[i].action;
   }
 
-#ifndef MSDOS
+#if defined(PLATFORM_UNIX)
   if (network_playing)
     SendToServer_MovePlayer(summarized_player_action);
 #endif
@@ -4561,6 +4567,25 @@ void GameActions()
   }
 
   DrawAllPlayers();
+
+  if (options.debug)                   /* calculate frames per second */
+  {
+    static unsigned long fps_counter = 0;
+    static int fps_frames = 0;
+    unsigned long fps_delay_ms = Counter() - fps_counter;
+
+    fps_frames++;
+
+    if (fps_delay_ms >= 500)   /* calculate fps every 0.5 seconds */
+    {
+      global.frames_per_second = 1000 * (float)fps_frames / fps_delay_ms;
+
+      fps_frames = 0;
+      fps_counter = Counter();
+    }
+
+    redraw_mask |= REDRAW_FPS;
+  }
 }
 
 static boolean AllPlayersInSight(struct PlayerInfo *player, int x, int y)
@@ -4607,13 +4632,13 @@ void ScrollLevel(int dx, int dy)
   int softscroll_offset = (setup.soft_scrolling ? TILEX : 0);
   int x, y;
 
-  XCopyArea(display, drawto_field, drawto_field, gc,
-           FX + TILEX*(dx == -1) - softscroll_offset,
-           FY + TILEY*(dy == -1) - softscroll_offset,
-           SXSIZE - TILEX*(dx!=0) + 2*softscroll_offset,
-           SYSIZE - TILEY*(dy!=0) + 2*softscroll_offset,
-           FX + TILEX*(dx == 1) - softscroll_offset,
-           FY + TILEY*(dy == 1) - softscroll_offset);
+  BlitBitmap(drawto_field, drawto_field,
+            FX + TILEX*(dx == -1) - softscroll_offset,
+            FY + TILEY*(dy == -1) - softscroll_offset,
+            SXSIZE - TILEX*(dx!=0) + 2*softscroll_offset,
+            SYSIZE - TILEY*(dy!=0) + 2*softscroll_offset,
+            FX + TILEX*(dx == 1) - softscroll_offset,
+            FY + TILEY*(dy == 1) - softscroll_offset);
 
   if (dx)
   {
@@ -5382,12 +5407,10 @@ int DigField(struct PlayerInfo *player,
       RemoveField(x, y);
       player->key[key_nr] = TRUE;
       RaiseScoreElement(EL_SCHLUESSEL);
-      DrawMiniGraphicExt(drawto, gc,
-                        DX_KEYS+key_nr*MINI_TILEX, DY_KEYS,
-                        GFX_SCHLUESSEL1+key_nr);
-      DrawMiniGraphicExt(window, gc,
-                        DX_KEYS+key_nr*MINI_TILEX, DY_KEYS,
-                        GFX_SCHLUESSEL1+key_nr);
+      DrawMiniGraphicExt(drawto, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
+                        GFX_SCHLUESSEL1 + key_nr);
+      DrawMiniGraphicExt(window, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
+                        GFX_SCHLUESSEL1 + key_nr);
       PlaySoundLevel(x, y, SND_PONG);
       break;
     }
@@ -5402,12 +5425,10 @@ int DigField(struct PlayerInfo *player,
       RemoveField(x, y);
       player->key[key_nr] = TRUE;
       RaiseScoreElement(EL_SCHLUESSEL);
-      DrawMiniGraphicExt(drawto, gc,
-                        DX_KEYS+key_nr*MINI_TILEX, DY_KEYS,
-                        GFX_SCHLUESSEL1+key_nr);
-      DrawMiniGraphicExt(window, gc,
-                        DX_KEYS+key_nr*MINI_TILEX, DY_KEYS,
-                        GFX_SCHLUESSEL1+key_nr);
+      DrawMiniGraphicExt(drawto, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
+                        GFX_SCHLUESSEL1 + key_nr);
+      DrawMiniGraphicExt(window, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
+                        GFX_SCHLUESSEL1 + key_nr);
       PlaySoundLevel(x, y, SND_PONG);
       break;
     }
@@ -5929,7 +5950,7 @@ void PlaySoundLevel(int x, int y, int sound_nr)
 
   volume = PSND_MAX_VOLUME;
 
-#ifndef MSDOS
+#if !defined(PLATFORM_MSDOS)
   stereo = (sx - SCR_FIELDX/2) * 12;
 #else
   stereo = PSND_MIDDLE + (2 * sx - (SCR_FIELDX - 1)) * 5;
@@ -6065,7 +6086,7 @@ void CreateGameButtons()
 
   for (i=0; i<NUM_GAME_BUTTONS; i++)
   {
-    Pixmap gd_pixmap = pix[PIX_DOOR];
+    Bitmap *gd_bitmap = pix[PIX_DOOR];
     struct GadgetInfo *gi;
     int button_type;
     boolean checked;
@@ -6110,10 +6131,10 @@ void CreateGameButtons()
                      GDI_TYPE, button_type,
                      GDI_STATE, GD_BUTTON_UNPRESSED,
                      GDI_CHECKED, checked,
-                     GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
-                     GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y1,
-                     GDI_ALT_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y2,
-                     GDI_ALT_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
+                     GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y1,
+                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y1,
+                     GDI_ALT_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y2,
+                     GDI_ALT_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y2,
                      GDI_EVENT_MASK, event_mask,
                      GDI_CALLBACK_ACTION, HandleGameButtons,
                      GDI_END);
@@ -6163,7 +6184,7 @@ static void HandleGameButtons(struct GadgetInfo *gi)
          Request("Do you really want to quit the game ?",
                  REQ_ASK | REQ_STAY_CLOSED))
       { 
-#ifndef MSDOS
+#if defined(PLATFORM_UNIX)
        if (options.network)
          SendToServer_StopPlaying();
        else
@@ -6180,7 +6201,7 @@ static void HandleGameButtons(struct GadgetInfo *gi)
     case GAME_CTRL_ID_PAUSE:
       if (options.network)
       {
-#ifndef MSDOS
+#if defined(PLATFORM_UNIX)
        if (tape.pausing)
          SendToServer_ContinuePlaying();
        else
@@ -6194,7 +6215,7 @@ static void HandleGameButtons(struct GadgetInfo *gi)
     case GAME_CTRL_ID_PLAY:
       if (tape.pausing)
       {
-#ifndef MSDOS
+#if defined(PLATFORM_UNIX)
        if (options.network)
          SendToServer_ContinuePlaying();
        else
@@ -6210,26 +6231,27 @@ static void HandleGameButtons(struct GadgetInfo *gi)
       if (setup.sound_music)
       { 
        setup.sound_music = FALSE;
-       FadeSound(background_loop[level_nr % num_bg_loops]);
+       FadeMusic();
       }
-      else if (sound_loops_allowed)
+      else if (audio.loops_available)
       { 
        setup.sound = setup.sound_music = TRUE;
-       PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
+       if (num_bg_loops)
+         PlayMusic(level_nr % num_bg_loops);
       }
       break;
 
     case SOUND_CTRL_ID_LOOPS:
       if (setup.sound_loops)
        setup.sound_loops = FALSE;
-      else if (sound_loops_allowed)
+      else if (audio.loops_available)
        setup.sound = setup.sound_loops = TRUE;
       break;
 
     case SOUND_CTRL_ID_SIMPLE:
       if (setup.sound_simple)
        setup.sound_simple = FALSE;
-      else if (sound_status==SOUND_AVAILABLE)
+      else if (audio.sound_available)
        setup.sound = setup.sound_simple = TRUE;
       break;
 
index 20b8e89af99bd53e7b7ce3072faf0ee0abce8b88..220bc1a76200c12817219a499ad846e3f6b59678 100644 (file)
@@ -1,14 +1,14 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  game.h                                                  *
+* game.h                                                   *
 ***********************************************************/
 
 #ifndef GAME_H
diff --git a/src/image.c b/src/image.c
deleted file mode 100644 (file)
index 83d8216..0000000
+++ /dev/null
@@ -1,554 +0,0 @@
-/***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
-*----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
-*----------------------------------------------------------*
-*  image.c                                                 *
-***********************************************************/
-
-#include "image.h"
-#include "pcx.h"
-#include "misc.h"
-
-/* exclude all except newImage() and freeImage() */
-#ifndef MSDOS
-
-/* extra colors to try allocating in private color maps to minimize flashing */
-#define NOFLASH_COLORS 256
-
-/* architecture independent value-to-memory conversion
-   note: the internal format is big endian */
-
-#define value_to_memory(value, ptr, length) (                          \
-(length) == 1 ? (*( (byte *)(ptr)   ) = ( value     ) ) :              \
-(length) == 2 ? (*( (byte *)(ptr)   ) = (((unsigned long)(value))>> 8),        \
-                *(((byte *)(ptr))+1) = ( value     ) ) :               \
-(length) == 3 ? (*( (byte *)(ptr)   ) = (((unsigned long)(value))>>16),        \
-                *(((byte *)(ptr))+1) = (((unsigned long)(value))>> 8), \
-                *(((byte *)(ptr))+2) = ( value     ) ) :               \
-                (*( (byte *)(ptr)   ) = (((unsigned long)(value))>>24),        \
-                *(((byte *)(ptr))+1) = (((unsigned long)(value))>>16), \
-                *(((byte *)(ptr))+2) = (((unsigned long)(value))>> 8), \
-                *(((byte *)(ptr))+3) = ( value     ) ))
-
-static Pixmap Image_to_Mask(Image *image, Display *display, Window window)
-{
-  byte *src_ptr, *dst_ptr, *dst_ptr2;
-  unsigned int bytes_per_row;
-  unsigned int x, y;
-  byte bitmask;
-  byte *mask_data;
-  Pixmap mask_pixmap;
-
-  bytes_per_row = (image->width + 7) / 8;
-  mask_data = checked_calloc(bytes_per_row * image->height);
-
-  src_ptr = image->data;
-  dst_ptr = mask_data;
-
-  /* create bitmap data which can be used by 'XCreateBitmapFromData()'
-   * directly to create a pixmap of depth 1 for use as a clip mask for
-   * the corresponding image pixmap
-   */
-
-  for (y=0; y<image->height; y++)
-  {
-    bitmask = 0x01;            /* start with leftmost bit in the byte     */
-    dst_ptr2 = dst_ptr;                /* start with leftmost byte in the row     */
-
-    for (x=0; x<image->width; x++)
-    {
-      if (*src_ptr++)          /* source pixel solid? (pixel index != 0)  */
-       *dst_ptr2 |= bitmask;   /* then write a bit into the image mask    */
-
-      if ((bitmask <<= 1) == 0)        /* bit at rightmost byte position reached? */
-      {
-       bitmask = 0x01;         /* start again with leftmost bit position  */
-       dst_ptr2++;             /* continue with next byte in image mask   */
-      }
-    }
-
-    dst_ptr += bytes_per_row;  /* continue with leftmost byte of next row */
-  }
-
-  mask_pixmap = XCreateBitmapFromData(display, window, (char *)mask_data,
-                                     image->width, image->height);
-  free(mask_data);
-
-  return mask_pixmap;
-}
-
-static int bitsPerPixelAtDepth(Display *display, int screen, int depth)
-{
-  XPixmapFormatValues *pixmap_format;
-  int i, num_pixmap_formats, bits_per_pixel = -1;
-
-  /* get Pixmap formats supported by the X server */
-  pixmap_format = XListPixmapFormats(display, &num_pixmap_formats);
-
-  /* find format that matches the given depth */
-  for (i=0; i<num_pixmap_formats; i++)
-    if (pixmap_format[i].depth == depth)
-      bits_per_pixel = pixmap_format[i].bits_per_pixel;
-
-  XFree(pixmap_format);
-
-  if (bits_per_pixel == -1)
-    Error(ERR_EXIT, "cannot find pixmap format for depth %d", depth);
-
-  return bits_per_pixel;
-}
-
-XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual,
-                           Window window, GC gc, int depth, Image *image)
-{
-  static XColor xcolor_private[NOFLASH_COLORS];
-  static int colorcell_used[NOFLASH_COLORS];
-  static Colormap global_cmap = 0;
-  static Pixel *global_cmap_index;
-  static int num_cmap_entries, free_cmap_entries;
-  static boolean private_cmap = FALSE;
-  Pixel *redvalue, *greenvalue, *bluevalue;
-  unsigned int a, c = 0, x, y, bytes_per_pixel, bits_per_pixel;
-  XColor xcolor;
-  XImage *ximage;
-  XImageInfo *ximageinfo;
-  byte *src_ptr, *dst_ptr;
-
-  if (!global_cmap)
-  {
-    if (visual == DefaultVisual(display, screen))
-      global_cmap = DefaultColormap(display, screen);
-    else
-    {
-      global_cmap = XCreateColormap(display, RootWindow(display, screen),
-                                   visual, AllocNone);
-      private_cmap = TRUE;
-    }
-  }
-
-  xcolor.flags = DoRed | DoGreen | DoBlue;
-  redvalue = greenvalue = bluevalue = NULL;
-  ximageinfo = checked_malloc(sizeof(XImageInfo));
-  ximageinfo->display = display;
-  ximageinfo->depth = depth;
-
-  switch (visual->class)
-  {
-    case TrueColor:
-    case DirectColor:
-    {
-      Pixel pixval;
-      unsigned int redcolors, greencolors, bluecolors;
-      unsigned int redstep, greenstep, bluestep;
-      unsigned int redbottom, greenbottom, bluebottom;
-      unsigned int redtop, greentop, bluetop;
-
-      redvalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
-      greenvalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
-      bluevalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
-
-      ximageinfo->cmap = global_cmap;
-
-      retry_direct: /* tag we hit if a DirectColor allocation fails on
-                    * default colormap */
-
-      /* calculate number of distinct colors in each band */
-
-      redcolors = greencolors = bluecolors = 1;
-      for (pixval=1; pixval; pixval <<= 1)
-      {
-       if (pixval & visual->red_mask)
-         redcolors <<= 1;
-       if (pixval & visual->green_mask)
-         greencolors <<= 1;
-       if (pixval & visual->blue_mask)
-         bluecolors <<= 1;
-      }
-      
-      /* consistency check */
-      if (redcolors > visual->map_entries ||
-         greencolors > visual->map_entries ||
-         bluecolors > visual->map_entries)
-       Error(ERR_WARN, "inconsistency in color information");
-
-      redstep = 256 / redcolors;
-      greenstep = 256 / greencolors;
-      bluestep = 256 / bluecolors;
-      redbottom = greenbottom = bluebottom = 0;
-      redtop = greentop = bluetop = 0;
-      for (a=0; a<visual->map_entries; a++)
-      {
-       if (redbottom < 256)
-         redtop = redbottom + redstep;
-       if (greenbottom < 256)
-         greentop = greenbottom + greenstep;
-       if (bluebottom < 256)
-         bluetop = bluebottom + bluestep;
-
-       xcolor.red = (redtop - 1) << 8;
-       xcolor.green = (greentop - 1) << 8;
-       xcolor.blue = (bluetop - 1) << 8;
-       if (!XAllocColor(display, ximageinfo->cmap, &xcolor))
-       {
-         /* if an allocation fails for a DirectColor default visual then
-            we should create a private colormap and try again. */
-
-         if ((visual->class == DirectColor) &&
-             (visual == DefaultVisual(display, screen)))
-         {
-           global_cmap = XCopyColormapAndFree(display, global_cmap);
-           ximageinfo->cmap = global_cmap;
-           private_cmap = TRUE;
-
-           goto retry_direct;
-         }
-
-         /* something completely unexpected happened */
-
-         fprintf(stderr, "imageToXImage: XAllocColor failed on a TrueColor/Directcolor visual\n");
-          free(redvalue);
-          free(greenvalue);
-          free(bluevalue);
-          free(ximageinfo);
-         return NULL;
-       }
-
-       /* fill in pixel values for each band at this intensity */
-
-       while ((redbottom < 256) && (redbottom < redtop))
-         redvalue[redbottom++] = xcolor.pixel & visual->red_mask;
-       while ((greenbottom < 256) && (greenbottom < greentop))
-         greenvalue[greenbottom++] = xcolor.pixel & visual->green_mask;
-       while ((bluebottom < 256) && (bluebottom < bluetop))
-         bluevalue[bluebottom++] = xcolor.pixel & visual->blue_mask;
-      }
-      break;
-    }
-
-    case PseudoColor:
-
-      ximageinfo->cmap = global_cmap;
-
-      for (a=0; a<MAX_COLORS; a++)
-      {
-       XColor xcolor2;
-       unsigned short mask;
-       int color_found;
-       int i;
-
-       if (!image->rgb.color_used[a])
-         continue;
-
-       xcolor.red = *(image->rgb.red + a);
-       xcolor.green = *(image->rgb.green + a);
-       xcolor.blue = *(image->rgb.blue + a);
-  
-       /* look if this color already exists in our colormap */
-       if (!XAllocColor(display, ximageinfo->cmap, &xcolor))
-       {
-         if (!private_cmap)
-         {
-           if (options.verbose)
-             Error(ERR_RETURN, "switching to private colormap");
-
-           /* we just filled up the default colormap -- get a private one
-              which contains all already allocated colors */
-
-           global_cmap = XCopyColormapAndFree(display, global_cmap);
-           ximageinfo->cmap = global_cmap;
-           private_cmap = TRUE;
-
-           /* allocate the rest of the color cells read/write */
-           global_cmap_index =
-             (Pixel *)checked_malloc(sizeof(Pixel) * NOFLASH_COLORS);
-           for (i=0; i<NOFLASH_COLORS; i++)
-             if (!XAllocColorCells(display, global_cmap, FALSE, NULL, 0,
-                                   global_cmap_index + i, 1))
-               break;
-           num_cmap_entries = free_cmap_entries = i;
-
-           /*
-           printf("We've got %d free colormap entries.\n", free_cmap_entries);
-           */
-
-           /* to minimize colormap flashing, copy default colors and try
-              to keep them as near as possible to the old values */
-
-           for(i=0; i<num_cmap_entries; i++)
-           {
-             xcolor2.pixel = *(global_cmap_index + i);
-             XQueryColor(display, DefaultColormap(display, screen), &xcolor2);
-             XStoreColor(display, global_cmap, &xcolor2);
-             xcolor_private[xcolor2.pixel] = xcolor2;
-             colorcell_used[xcolor2.pixel] = FALSE;
-           }
-
-           /* now we have the default colormap private: all colors we
-              successfully allocated so far are read-only, which is okay,
-              because we don't want to change them anymore -- if we need
-              an existing color again, we get it by XAllocColor; all other
-              colors are read/write and we can set them by XStoreColor,
-              but we will try to overwrite those color cells with our new
-              color which are as close as possible to our new color */
-         }
-
-         /* look for an existing default color close the one we want */
-
-         mask = 0xf000;
-         color_found = FALSE;
-
-         while (!color_found)
-         {
-           for (i=num_cmap_entries-1; i>=0; i--)
-           {
-             xcolor2.pixel = *(global_cmap_index + i);
-             xcolor2 = xcolor_private[xcolor2.pixel];
-
-             if (colorcell_used[xcolor2.pixel])
-               continue;
-
-             if ((xcolor.red & mask) == (xcolor2.red & mask) &&
-                 (xcolor.green & mask) == (xcolor2.green & mask) &&
-                 (xcolor.blue & mask) == (xcolor2.blue & mask))
-             {
-               /*
-               printf("replacing color cell %ld with a close color\n",
-                      xcolor2.pixel);
-                      */
-               color_found = TRUE;
-               break;
-             }
-           }
-
-           if (mask == 0x0000)
-             break;
-
-           mask = (mask << 1) & 0xffff;
-         }
-
-         if (!color_found)             /* no more free color cells */
-           Error(ERR_EXIT, "cannot allocate enough color cells");
-
-         xcolor.pixel = xcolor2.pixel;
-         xcolor_private[xcolor.pixel] = xcolor;
-         colorcell_used[xcolor.pixel] = TRUE;
-         XStoreColor(display, ximageinfo->cmap, &xcolor);
-         free_cmap_entries--;
-       }
-
-       *(ximageinfo->index + a) = xcolor.pixel;
-      }
-
-      /*
-      printf("still %d free colormap entries\n", free_cmap_entries);
-      */
-
-      ximageinfo->no = a;      /* number of pixels allocated for this image */
-      break;
-  
-    default:
-      Error(ERR_RETURN, "display class not supported");
-      Error(ERR_EXIT, "DirectColor, TrueColor or PseudoColor display needed");
-      break;
-  }
-
-#if DEBUG_TIMING
-  debug_print_timestamp(2, "   ALLOCATING IMAGE COLORS:   ");
-#endif
-
-  /* create XImage from internal image structure and convert it to Pixmap */
-
-  bits_per_pixel = bitsPerPixelAtDepth(display, screen, depth);
-  bytes_per_pixel = (bits_per_pixel + 7) / 8;
-
-  ximage = XCreateImage(display, visual, depth, ZPixmap, 0,
-                       NULL, image->width, image->height,
-                       8, image->width * bytes_per_pixel);
-  ximage->data =
-    checked_malloc(image->width * image->height * bytes_per_pixel);
-  ximage->byte_order = MSBFirst;
-
-  src_ptr = image->data;
-  dst_ptr = (byte *)ximage->data;
-
-  switch (visual->class)
-  {
-    case DirectColor:
-    case TrueColor:
-    {
-      Pixel pixval;
-
-      for (y=0; y<image->height; y++)          /* general case */
-      {
-       for (x=0; x<image->width; x++)
-       {
-         pixval = *src_ptr++;
-         pixval =
-           redvalue[image->rgb.red[pixval] >> 8] |
-           greenvalue[image->rgb.green[pixval] >> 8] |
-           bluevalue[image->rgb.blue[pixval] >> 8];
-         value_to_memory(pixval, dst_ptr, bytes_per_pixel);
-         dst_ptr += bytes_per_pixel;
-       }
-      }
-      break;
-    }
-
-    case PseudoColor:
-    {
-      if (bytes_per_pixel == 1)                        /* (common) special case */
-      {
-       for (y=0; y<image->height; y++)
-         for (x=0; x<image->width; x++)
-           *dst_ptr++ = ximageinfo->index[c + *src_ptr++];
-      }
-      else                                     /* general case */
-      {
-       for (y=0; y<image->height; y++)
-       {
-         for (x=0; x<image->width; x++)
-         {
-           value_to_memory(ximageinfo->index[c + *src_ptr++],
-                           dst_ptr, bytes_per_pixel);
-           dst_ptr += bytes_per_pixel;
-         }
-       }
-      }
-      break;
-    }
-
-    default:
-      Error(ERR_RETURN, "display class not supported");
-      Error(ERR_EXIT, "DirectColor, TrueColor or PseudoColor display needed");
-      break;
-  }
-
-  if (redvalue)
-  {
-    free((byte *)redvalue);
-    free((byte *)greenvalue);
-    free((byte *)bluevalue);
-  }
-
-#if DEBUG_TIMING
-  debug_print_timestamp(2, "   CONVERTING IMAGE TO XIMAGE:");
-#endif
-
-  ximageinfo->pixmap = XCreatePixmap(display, window,
-                                    ximage->width, ximage->height,
-                                    ximageinfo->depth);
-
-  XPutImage(ximageinfo->display, ximageinfo->pixmap, gc,
-           ximage, 0, 0, 0, 0, ximage->width, ximage->height);
-
-  free(ximage->data);
-  ximage->data = NULL;
-  XDestroyImage(ximage);
-
-  return(ximageinfo);
-}
-
-void freeXImage(Image *image, XImageInfo *ximageinfo)
-{
-  if (ximageinfo->index != NULL && ximageinfo->no > 0)
-    XFreeColors(ximageinfo->display, ximageinfo->cmap, ximageinfo->index,
-               ximageinfo->no, 0);
-  /* this       ^^^^^^^^^^^^^^ is wrong, because the used color cells
-   * are somewhere between 0 and MAX_COLORS; there are indeed 'ximageinfo->no'
-   * used color cells, but they are not at array position 0 - 'ximageinfo->no'
-   */
-
-  free(ximageinfo);
-}
-
-#endif /* !MSDOS */
-
-Image *newImage(unsigned int width, unsigned int height, unsigned int depth)
-{
-  Image *image;
-  const unsigned int bytes_per_pixel = 1;
-  int i;
-
-  if (depth > 8)
-    Error(ERR_EXIT, "images with more than 256 colors are not supported");
-
-  depth = 8;
-  image = checked_malloc(sizeof(Image));
-  image->data = checked_malloc(width * height * bytes_per_pixel);
-  image->width = width;
-  image->height = height;
-  image->depth = depth;
-  image->rgb.used = 0;
-  for (i=0; i<MAX_COLORS; i++)
-    image->rgb.color_used[i] = FALSE;
-
-  return image;
-}
-
-void freeImage(Image *image)
-{
-  free(image->data);
-  free(image);
-}
-
-#ifndef MSDOS
-
-int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename,
-                      Pixmap *pixmap, Pixmap *pixmap_mask)
-{
-  Image *image;
-  XImageInfo *ximageinfo;
-  int screen;
-  Visual *visual;
-  int depth;
-
-#if DEBUG_TIMING
-  debug_print_timestamp(2, NULL);      /* initialize timestamp function */
-#endif
-
-  /* read the graphic file in PCX format to image structure */
-  if ((image = Read_PCX_to_Image(filename)) == NULL)
-    return errno_pcx;
-
-#if DEBUG_TIMING
-  printf("%s:\n", filename);
-  debug_print_timestamp(2, "   READING PCX FILE TO IMAGE: ");
-#endif
-
-  screen = DefaultScreen(display);
-  visual = DefaultVisual(display, screen);
-  depth = DefaultDepth(display, screen);
-
-  /* convert image structure to X11 Pixmap */
-  if (!(ximageinfo = Image_to_Pixmap(display, screen, visual,
-                                    window, gc, depth, image)))
-    Error(ERR_EXIT, "cannot convert Image to Pixmap");
-
-  /* if a private colormap has been created, install it */
-  if (ximageinfo->cmap != DefaultColormap(display, screen))
-    XSetWindowColormap(display, window, ximageinfo->cmap);
-
-#if DEBUG_TIMING
-  debug_print_timestamp(2, "   CONVERTING IMAGE TO PIXMAP:");
-#endif
-
-  /* create clip mask for the image */
-  ximageinfo->pixmap_mask = Image_to_Mask(image, display, window);
-
-#if DEBUG_TIMING
-  debug_print_timestamp(2, "   CONVERTING IMAGE TO MASK:  ");
-#endif
-
-  *pixmap = ximageinfo->pixmap;
-  *pixmap_mask = ximageinfo->pixmap_mask;
-
-  return PCX_Success;
-}
-
-#endif /* !MSDOS */
diff --git a/src/image.h b/src/image.h
deleted file mode 100644 (file)
index 6315340..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
-*----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
-*----------------------------------------------------------*
-*  image.h                                                 *
-***********************************************************/
-
-#ifndef IMAGE_H
-#define IMAGE_H
-
-#include "main.h"
-
-#define MAX_COLORS     256     /* maximal number of colors for each image */
-
-typedef unsigned short Intensity;      /* RGB intensity for X11 */
-
-typedef struct
-{
-  Display  *display;           /* destination display             */
-  int       depth;             /* depth of destination drawable   */
-  Pixel     index[MAX_COLORS]; /* array of pixel values           */
-  int       no;                        /* number of pixels in the array   */
-  Colormap  cmap;              /* colormap used for image         */
-  Pixmap   pixmap;             /* final pixmap                    */
-  Pixmap   pixmap_mask;                /* final pixmap of mask            */
-} XImageInfo;
-
-struct RGBMap
-{
-  unsigned int used;                   /* number of colors used in RGB map */
-  Intensity    red[MAX_COLORS];                /* color values in X style          */
-  Intensity    green[MAX_COLORS];
-  Intensity    blue[MAX_COLORS];
-  boolean      color_used[MAX_COLORS]; /* flag if color cell is used       */
-};
-
-typedef struct
-{
-  struct RGBMap rgb;           /* RGB map of image if IRGB type       */
-  unsigned int  width;         /* width of image in pixels            */
-  unsigned int  height;                /* height of image in pixels           */
-  unsigned int  depth;         /* depth of image in bits if IRGB type */
-  byte         *data;          /* image data                          */
-} Image;
-
-int Read_PCX_to_Pixmap(Display *, Window, GC, char *, Pixmap *, Pixmap *);
-
-Image *newImage(unsigned int, unsigned int, unsigned int);
-void freeImage(Image *);
-void freeXImage(Image *, XImageInfo *);
-
-#endif /* IMAGE_H */
index 78a587f575a78f334642d1b0069cf6a8d21936d2..53b8e965f8cab3105516f71b6cec38759f708aca 100644 (file)
@@ -1,21 +1,20 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  init.c                                                  *
+* init.c                                                   *
 ***********************************************************/
 
-#include <signal.h>
+#include "libgame/libgame.h"
 
 #include "init.h"
-#include "misc.h"
-#include "sound.h"
+#include "events.h"
 #include "screens.h"
 #include "editor.h"
 #include "game.h"
 #include "tools.h"
 #include "files.h"
 #include "joystick.h"
-#include "image.h"
-#include "pcx.h"
 #include "network.h"
 #include "netserv.h"
 
-struct PictureFileInfo
-{
-  char *picture_filename;
-  boolean picture_with_mask;
-};
-
-struct IconFileInfo
-{
-  char *picture_filename;
-  char *picturemask_filename;
-};
-
-static int sound_process_id = 0;
-
-static void InitLevelAndPlayerInfo(void);
+static void InitPlayerInfo(void);
+static void InitLevelInfo(void);
 static void InitNetworkServer(void);
-static void InitDisplay(void);
 static void InitSound(void);
-static void InitSoundServer(void);
-static void InitWindow(int, char **);
 static void InitGfx(void);
-static void LoadGfx(int, struct PictureFileInfo *);
+static void InitGfxBackground(void);
 static void InitGadgets(void);
 static void InitElementProperties(void);
 
-void OpenAll(int argc, char *argv[])
+void OpenAll(void)
 {
-#ifdef MSDOS
-  initErrorFile();
-#endif
-
   if (options.serveronly)
   {
+#if defined(PLATFORM_UNIX)
     NetworkServer(options.server_port, options.serveronly);
-
-    /* never reached */
-    exit(0);
+#else
+    Error(ERR_WARN, "networking only supported in Unix version");
+#endif
+    exit(0);   /* never reached */
   }
 
+  InitProgramInfo(UNIX_USERDATA_DIRECTORY,
+                 PROGRAM_TITLE_STRING, WINDOW_TITLE_STRING,
+                 ICON_TITLE_STRING, X11_ICON_FILENAME, X11_ICONMASK_FILENAME,
+                 MSDOS_POINTER_FILENAME);
+
+  InitPlayerInfo();
+
   InitCounter();
   InitSound();
-  InitSoundServer();
   InitJoysticks();
   InitRND(NEW_RANDOMIZE);
 
-  signal(SIGINT, CloseAllAndExit);
-  signal(SIGTERM, CloseAllAndExit);
-
-  InitDisplay();
-  InitWindow(argc, argv);
+  InitVideoDisplay();
+  InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH,
+                 setup.fullscreen);
 
-  XMapWindow(display, window);
-  XFlush(display);
+  InitEventFilter(FilterMouseMotionEvents);
 
   InitGfx();
   InitElementProperties();     /* initializes IS_CHAR() for el2gfx() */
 
-  InitLevelAndPlayerInfo();
+  InitLevelInfo();
   InitGadgets();               /* needs to know number of level series */
 
+  InitGfxBackground();
   DrawMainMenu();
 
   InitNetworkServer();
 }
 
-void InitLevelAndPlayerInfo()
+void InitPlayerInfo()
 {
   int i;
 
@@ -108,22 +91,26 @@ void InitLevelAndPlayerInfo()
 
   local_player->connected = TRUE;
 
-  LoadLevelInfo();                             /* global level info */
   LoadSetup();                                 /* global setup info */
+}
+
+void InitLevelInfo()
+{
+  LoadLevelInfo();                             /* global level info */
   LoadLevelSetup_LastSeries();                 /* last played series info */
   LoadLevelSetup_SeriesInfo();                 /* last played level info */
 }
 
 void InitNetworkServer()
 {
-#ifndef MSDOS
+#if defined(PLATFORM_UNIX)
   int nr_wanted;
 #endif
 
   if (!options.network)
     return;
 
-#ifndef MSDOS
+#if defined(PLATFORM_UNIX)
   nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
 
   if (!ConnectToServer(options.server_host, options.server_port))
@@ -141,107 +128,81 @@ void InitSound()
 {
   int i;
 
-  if (sound_status == SOUND_OFF)
-    return;
+  OpenAudio();
 
-#ifndef MSDOS
-  if (access(sound_device_name, W_OK) != 0)
+  for(i=0; i<NUM_SOUNDS; i++)
   {
-    Error(ERR_WARN, "cannot access sound device - no sounds");
-    sound_status = SOUND_OFF;
-    return;
-  }
+    if (!LoadSound(sound_name[i]))
+    {
+      audio.sound_available = FALSE;
+      audio.loops_available = FALSE;
+      audio.sound_enabled = FALSE;
 
-  if ((sound_device = open(sound_device_name,O_WRONLY))<0)
-  {
-    Error(ERR_WARN, "cannot open sound device - no sounds");
-    sound_status = SOUND_OFF;
-    return;
+      return;
+    }
   }
 
-  close(sound_device);
-  sound_status = SOUND_AVAILABLE;
-
-#ifdef VOXWARE
-  sound_loops_allowed = TRUE;
+  num_bg_loops = LoadMusic();
 
-  /*
-  setup.sound_loops_on = TRUE;
-  */
+  StartSoundserver();
+}
 
+void InitJoysticks()
+{
+#if defined(TARGET_SDL)
+  static boolean sdl_joystick_subsystem_initialized = FALSE;
 #endif
-#else /* MSDOS */
-  sound_loops_allowed = TRUE;
 
-  /*
-  setup.sound_loops_on = TRUE;
-  */
+  int i;
 
-#endif /* MSDOS */
+  if (global_joystick_status == JOYSTICK_OFF)
+    return;
 
-  for(i=0; i<NUM_SOUNDS; i++)
+  joystick_status = JOYSTICK_OFF;
+
+#if defined(TARGET_SDL)
+
+  if (!sdl_joystick_subsystem_initialized)
   {
-#ifdef MSDOS
-    sprintf(sound_name[i], "%d", i + 1);
-#endif
+    sdl_joystick_subsystem_initialized = TRUE;
 
-    Sound[i].name = sound_name[i];
-    if (!LoadSound(&Sound[i]))
+    if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
     {
-      sound_status = SOUND_OFF;
+      Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
       return;
     }
   }
-}
-
-void InitSoundServer()
-{
-  if (sound_status == SOUND_OFF)
-    return;
-
-#ifndef MSDOS
-
-  if (pipe(sound_pipe)<0)
-  {
-    Error(ERR_WARN, "cannot create pipe - no sounds");
-    sound_status = SOUND_OFF;
-    return;
-  }
-
-  if ((sound_process_id = fork()) < 0)
-  {       
-    Error(ERR_WARN, "cannot create sound server process - no sounds");
-    sound_status = SOUND_OFF;
-    return;
-  }
 
-  if (!sound_process_id)       /* we are child */
+  for (i=0; i<MAX_PLAYERS; i++)
   {
-    SoundServer();
+    char *device_name = setup.input[i].joy.device_name;
+    int joystick_nr = getJoystickNrFromDeviceName(device_name);
 
-    /* never reached */
-    exit(0);
-  }
-  else                         /* we are parent */
-    close(sound_pipe[0]);      /* no reading from pipe needed */
+    if (joystick_nr >= SDL_NumJoysticks())
+      joystick_nr = -1;
 
-#else /* MSDOS */
+    /* misuse joystick file descriptor variable to store joystick number */
+    stored_player[i].joystick_fd = joystick_nr;
 
-  SoundServer();
+    /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
+    if (Check_SDL_JoystickOpened(joystick_nr))
+      Close_SDL_Joystick(joystick_nr);
 
-#endif /* MSDOS */
-}
+    if (!setup.input[i].use_joystick)
+      continue;
 
-void InitJoysticks()
-{
-  int i;
+    if (!Open_SDL_Joystick(joystick_nr))
+    {
+      Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
+      continue;
+    }
 
-  if (global_joystick_status == JOYSTICK_OFF)
-    return;
+    joystick_status = JOYSTICK_AVAILABLE;
+  }
 
-  joystick_status = JOYSTICK_OFF;
+#else /* !TARGET_SDL */
 
-#ifndef MSDOS
+#if defined(PLATFORM_UNIX)
   for (i=0; i<MAX_PLAYERS; i++)
   {
     char *device_name = setup.input[i].joy.device_name;
@@ -271,7 +232,7 @@ void InitJoysticks()
     joystick_status = JOYSTICK_AVAILABLE;
   }
 
-#else /* MSDOS */
+#else /* !PLATFORM_UNIX */
 
   /* try to access two joysticks; if that fails, try to access just one */
   if (install_joystick(JOY_TYPE_2PADS) == 0 ||
@@ -294,224 +255,51 @@ void InitJoysticks()
     stored_player[i].joystick_fd = joystick_nr;
   }
 #endif
-}
-
-void InitDisplay()
-{
-#ifndef MSDOS
-  XVisualInfo vinfo_template, *vinfo;
-  int num_visuals;
-#endif
-  unsigned int depth;
-
-  /* connect to X server */
-  if (!(display = XOpenDisplay(options.display_name)))
-    Error(ERR_EXIT, "cannot connect to X server %s",
-         XDisplayName(options.display_name));
-
-  screen = DefaultScreen(display);
-  visual = DefaultVisual(display, screen);
-  depth  = DefaultDepth(display, screen);
-  cmap   = DefaultColormap(display, screen);
-
-#ifndef MSDOS
-  /* look for good enough visual */
-  vinfo_template.screen = screen;
-  vinfo_template.class = (depth == 8 ? PseudoColor : TrueColor);
-  vinfo_template.depth = depth;
-  if ((vinfo = XGetVisualInfo(display, VisualScreenMask | VisualClassMask |
-                             VisualDepthMask, &vinfo_template, &num_visuals)))
-  {
-    visual = vinfo->visual;
-    XFree((void *)vinfo);
-  }
-
-  /* got appropriate visual? */
-  if (depth < 8)
-  {
-    printf("Sorry, displays with less than 8 bits per pixel not supported.\n");
-    exit(-1);
-  }
-  else if ((depth ==8 && visual->class != PseudoColor) ||
-          (depth > 8 && visual->class != TrueColor &&
-           visual->class != DirectColor))
-  {
-    printf("Sorry, cannot get appropriate visual.\n");
-    exit(-1);
-  }
-#endif
-}
-
-void InitWindow(int argc, char *argv[])
-{
-  unsigned int border_width = 4;
-  XGCValues gc_values;
-  unsigned long gc_valuemask;
-#ifndef MSDOS
-  XTextProperty windowName, iconName;
-  Pixmap icon_pixmap, iconmask_pixmap;
-  unsigned int icon_width, icon_height;
-  int icon_hot_x, icon_hot_y;
-  char icon_filename[256];
-  XSizeHints size_hints;
-  XWMHints wm_hints;
-  XClassHint class_hints;
-  char *window_name = WINDOW_TITLE_STRING;
-  char *icon_name = WINDOW_TITLE_STRING;
-  long window_event_mask;
-  Atom proto_atom = None, delete_atom = None;
-#endif
-  int screen_width, screen_height;
-  int win_xpos = WIN_XPOS, win_ypos = WIN_YPOS;
-  unsigned long pen_fg = WhitePixel(display,screen);
-  unsigned long pen_bg = BlackPixel(display,screen);
-  const int width = WIN_XSIZE, height = WIN_YSIZE;
-
-#ifndef MSDOS
-  static struct IconFileInfo icon_pic =
-  {
-    "rocks_icon.xbm",
-    "rocks_iconmask.xbm"
-  };
-#endif
-
-  screen_width = XDisplayWidth(display, screen);
-  screen_height = XDisplayHeight(display, screen);
-
-  win_xpos = (screen_width - width) / 2;
-  win_ypos = (screen_height - height) / 2;
-
-  window = XCreateSimpleWindow(display, RootWindow(display, screen),
-                              win_xpos, win_ypos, width, height, border_width,
-                              pen_fg, pen_bg);
-
-#ifndef MSDOS
-  proto_atom = XInternAtom(display, "WM_PROTOCOLS", FALSE);
-  delete_atom = XInternAtom(display, "WM_DELETE_WINDOW", FALSE);
-  if ((proto_atom != None) && (delete_atom != None))
-    XChangeProperty(display, window, proto_atom, XA_ATOM, 32,
-                   PropModePrepend, (unsigned char *) &delete_atom, 1);
-
-  sprintf(icon_filename, "%s/%s/%s",
-         options.ro_base_directory, GRAPHICS_DIRECTORY,
-         icon_pic.picture_filename);
-  XReadBitmapFile(display,window,icon_filename,
-                 &icon_width,&icon_height,
-                 &icon_pixmap,&icon_hot_x,&icon_hot_y);
-  if (!icon_pixmap)
-    Error(ERR_EXIT, "cannot read icon bitmap file '%s'", icon_filename);
-
-  sprintf(icon_filename, "%s/%s/%s",
-         options.ro_base_directory, GRAPHICS_DIRECTORY,
-         icon_pic.picturemask_filename);
-  XReadBitmapFile(display,window,icon_filename,
-                 &icon_width,&icon_height,
-                 &iconmask_pixmap,&icon_hot_x,&icon_hot_y);
-  if (!iconmask_pixmap)
-    Error(ERR_EXIT, "cannot read icon bitmap file '%s'", icon_filename);
-
-  size_hints.width  = size_hints.min_width  = size_hints.max_width  = width;
-  size_hints.height = size_hints.min_height = size_hints.max_height = height;
-  size_hints.flags = PSize | PMinSize | PMaxSize;
-
-  if (win_xpos || win_ypos)
-  {
-    size_hints.x = win_xpos;
-    size_hints.y = win_ypos;
-    size_hints.flags |= PPosition;
-  }
-
-  if (!XStringListToTextProperty(&window_name, 1, &windowName))
-    Error(ERR_EXIT, "structure allocation for windowName failed");
-
-  if (!XStringListToTextProperty(&icon_name, 1, &iconName))
-    Error(ERR_EXIT, "structure allocation for iconName failed");
-
-  wm_hints.initial_state = NormalState;
-  wm_hints.input = True;
-  wm_hints.icon_pixmap = icon_pixmap;
-  wm_hints.icon_mask = iconmask_pixmap;
-  wm_hints.flags = StateHint | IconPixmapHint | IconMaskHint | InputHint;
-
-  class_hints.res_name = program_name;
-  class_hints.res_class = "Rocks'n'Diamonds";
-
-  XSetWMProperties(display, window, &windowName, &iconName, 
-                  argv, argc, &size_hints, &wm_hints, 
-                  &class_hints);
-
-  XFree(windowName.value);
-  XFree(iconName.value);
-
-  /* Select event types wanted */
-  window_event_mask =
-    ExposureMask | StructureNotifyMask | FocusChangeMask |
-    ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
-    PointerMotionHintMask | KeyPressMask | KeyReleaseMask;
-
-  XSelectInput(display, window, window_event_mask);
-#endif
 
-  /* create GC for drawing with window depth */
-  gc_values.graphics_exposures = False;
-  gc_values.foreground = pen_bg;
-  gc_values.background = pen_bg;
-  gc_valuemask = GCGraphicsExposures | GCForeground | GCBackground;
-  gc = XCreateGC(display, window, gc_valuemask, &gc_values);
+#endif /* !TARGET_SDL */
 }
 
 void InitGfx()
 {
-  int i,j;
+  int i;
+
+#if defined(TARGET_X11)
   GC copy_clipmask_gc;
   XGCValues clip_gc_values;
   unsigned long clip_gc_valuemask;
+#endif
 
-#ifdef MSDOS
-  static struct PictureFileInfo pic[NUM_PICTURES] =
-  {
-    { "Screen",        TRUE },
-    { "Door",  TRUE },
-    { "Heroes",        TRUE },
-    { "Toons", TRUE },
-    { "SP",    TRUE },
-    { "DC",    TRUE },
-    { "More",  TRUE },
-    { "Font",  FALSE },
-    { "Font2", FALSE },
-    { "Font3", FALSE }
+#if !defined(PLATFORM_MSDOS)
+  static char *image_filename[NUM_PICTURES] =
+  {
+    "RocksScreen.pcx",
+    "RocksDoor.pcx",
+    "RocksHeroes.pcx",
+    "RocksToons.pcx",
+    "RocksSP.pcx",
+    "RocksDC.pcx",
+    "RocksMore.pcx",
+    "RocksFont.pcx",
+    "RocksFont2.pcx",
+    "RocksFont3.pcx"
   }; 
 #else
-  static struct PictureFileInfo pic[NUM_PICTURES] =
-  {
-    { "RocksScreen",   TRUE },
-    { "RocksDoor",     TRUE },
-    { "RocksHeroes",   TRUE },
-    { "RocksToons",    TRUE },
-    { "RocksSP",       TRUE },
-    { "RocksDC",       TRUE },
-    { "RocksMore",     TRUE },
-    { "RocksFont",     FALSE },
-    { "RocksFont2",    FALSE },
-    { "RocksFont3",    FALSE }
+  static char *image_filename[NUM_PICTURES] =
+  {
+    "Screen.pcx",
+    "Door.pcx",
+    "Heroes.pcx",
+    "Toons.pcx",
+    "SP.pcx",
+    "DC.pcx",
+    "More.pcx",
+    "Font.pcx",
+    "Font2.pcx",
+    "Font3.pcx"
   }; 
 #endif
 
-#ifdef DEBUG
-#if 0
-  static struct PictureFileInfo test_pic1 =
-  {
-    "RocksFont2",
-    FALSE
-  };
-  static struct PictureFileInfo test_pic2 =
-  {
-    "mouse",
-    FALSE
-  };
-#endif
-#endif
-
+#if defined(TARGET_X11_NATIVE)
   static struct
   {
     int start;
@@ -563,68 +351,86 @@ void InitGfx()
     { GFX2_SHIELD_ACTIVE, 3 },
     { -1, 0 }
   };
-
-#if DEBUG_TIMING
-  debug_print_timestamp(0, NULL);      /* initialize timestamp function */
 #endif
 
-#ifdef DEBUG
-#if 0
-  printf("Test: Loading RocksFont2.pcx ...\n");
-  LoadGfx(PIX_SMALLFONT,&test_pic1);
-  printf("Test: Done.\n");
-  printf("Test: Loading mouse.pcx ...\n");
-  LoadGfx(PIX_SMALLFONT,&test_pic2);
-  printf("Test: Done.\n");
-#endif
-#endif
-
-
-
-  LoadGfx(PIX_SMALLFONT,&pic[PIX_SMALLFONT]);
-  DrawInitText(WINDOW_TITLE_STRING,20,FC_YELLOW);
-  DrawInitText(COPYRIGHT_STRING,50,FC_RED);
-#ifdef MSDOS
-  DrawInitText("MSDOS version done by Guido Schulz",210,FC_BLUE);
+  /* initialize some global variables */
+  global.frames_per_second = 0;
+  global.fps_slowdown = FALSE;
+  global.fps_slowdown_factor = 1;
+
+  /* initialize screen properties */
+  InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
+                  REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
+  InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
+  InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
+  InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
+
+  /* create additional image buffers for double-buffering */
+  pix[PIX_DB_DOOR] = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
+  pix[PIX_DB_FIELD] = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
+
+  pix[PIX_SMALLFONT] = LoadImage(image_filename[PIX_SMALLFONT]);
+  InitFontInfo(NULL, NULL, pix[PIX_SMALLFONT]);
+
+  DrawInitText(WINDOW_TITLE_STRING, 20, FC_YELLOW);
+  DrawInitText(WINDOW_SUBTITLE_STRING, 50, FC_RED);
+#if defined(PLATFORM_MSDOS)
+  DrawInitText(PROGRAM_DOS_PORT_STRING, 210, FC_BLUE);
   rest(200);
-#endif /* MSDOS */
+#endif
   DrawInitText("Loading graphics:",120,FC_GREEN);
 
   for(i=0; i<NUM_PICTURES; i++)
+  {
     if (i != PIX_SMALLFONT)
-      LoadGfx(i,&pic[i]);
+    {
+      DrawInitText(image_filename[i], 150, FC_YELLOW);
+      pix[i] = LoadImage(image_filename[i]);
+    }
+  }
 
-#if DEBUG_TIMING
-  debug_print_timestamp(0, "SUMMARY LOADING ALL GRAPHICS:");
-#endif
+  InitFontInfo(pix[PIX_BIGFONT], pix[PIX_MEDIUMFONT], pix[PIX_SMALLFONT]);
 
-  pix[PIX_DB_BACK] = XCreatePixmap(display, window,
-                                  WIN_XSIZE,WIN_YSIZE,
-                                  XDefaultDepth(display,screen));
-  pix[PIX_DB_DOOR] = XCreatePixmap(display, window,
-                                  3*DXSIZE,DYSIZE+VYSIZE,
-                                  XDefaultDepth(display,screen));
-  pix[PIX_DB_FIELD] = XCreatePixmap(display, window,
-                                   FXSIZE,FYSIZE,
-                                   XDefaultDepth(display,screen));
+  /* initialize pixmap array for special X11 tile clipping to Pixmap 'None' */
+  for(i=0; i<NUM_TILES; i++)
+    tile_clipmask[i] = None;
 
+#if defined(TARGET_X11)
+  /* This stuff is needed because X11 (XSetClipOrigin(), to be precise) is
+     often very slow when preparing a masked XCopyArea() for big Pixmaps.
+     To prevent this, create small (tile-sized) mask Pixmaps which will then
+     be set much faster with XSetClipOrigin() and speed things up a lot. */
+
+  /* create graphic context structures needed for clipping */
   clip_gc_values.graphics_exposures = False;
   clip_gc_valuemask = GCGraphicsExposures;
   copy_clipmask_gc =
-    XCreateGC(display,clipmask[PIX_BACK],clip_gc_valuemask,&clip_gc_values);
+    XCreateGC(display, pix[PIX_BACK]->clip_mask,
+             clip_gc_valuemask, &clip_gc_values);
 
   clip_gc_values.graphics_exposures = False;
   clip_gc_valuemask = GCGraphicsExposures;
   tile_clip_gc =
-    XCreateGC(display,window,clip_gc_valuemask,&clip_gc_values);
+    XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
 
-  /* initialize pixmap array to Pixmap 'None' */
-  for(i=0; i<NUM_TILES; i++)
-    tile_clipmask[i] = None;
+  for(i=0; i<NUM_BITMAPS; i++)
+  {
+    if (pix[i]->clip_mask)
+    {
+      clip_gc_values.graphics_exposures = False;
+      clip_gc_values.clip_mask = pix[i]->clip_mask;
+      clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
+      pix[i]->stored_clip_gc = XCreateGC(display, window->drawable,
+                                        clip_gc_valuemask,&clip_gc_values);
+    }
+  }
 
+#if defined(TARGET_X11_NATIVE)
   /* create only those clipping Pixmaps we really need */
   for(i=0; tile_needs_clipping[i].start>=0; i++)
   {
+    int j;
+
     for(j=0; j<tile_needs_clipping[i].count; j++)
     {
       int tile = tile_needs_clipping[i].start + j;
@@ -634,181 +440,38 @@ void InitGfx()
       Pixmap src_pixmap;
 
       getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
-      src_pixmap = clipmask[pixmap_nr];
+      src_pixmap = pix[pixmap_nr]->clip_mask;
 
-      tile_clipmask[tile] = XCreatePixmap(display, window, TILEX,TILEY, 1);
+      tile_clipmask[tile] = XCreatePixmap(display, window->drawable,
+                                         TILEX, TILEY, 1);
 
-      XCopyArea(display,src_pixmap,tile_clipmask[tile],copy_clipmask_gc,
-               src_x,src_y, TILEX,TILEY, 0,0);
+      XCopyArea(display, src_pixmap, tile_clipmask[tile], copy_clipmask_gc,
+               src_x, src_y, TILEX, TILEY, 0, 0);
     }
   }
+#endif /* TARGET_X11_NATIVE */
+#endif /* TARGET_X11 */
+}
 
-  if (!pix[PIX_DB_BACK] || !pix[PIX_DB_DOOR])
-    Error(ERR_EXIT, "cannot create additional pixmaps");
-
-  for(i=0; i<NUM_PIXMAPS; i++)
-  {
-    if (clipmask[i])
-    {
-      clip_gc_values.graphics_exposures = False;
-      clip_gc_values.clip_mask = clipmask[i];
-      clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
-      clip_gc[i] = XCreateGC(display,window,clip_gc_valuemask,&clip_gc_values);
-    }
-  }
+void InitGfxBackground()
+{
+  int x, y;
 
-  drawto = backbuffer = pix[PIX_DB_BACK];
+  drawto = backbuffer;
   fieldbuffer = pix[PIX_DB_FIELD];
   SetDrawtoField(DRAW_BACKBUFFER);
 
-  XCopyArea(display,pix[PIX_BACK],backbuffer,gc,
-           0,0, WIN_XSIZE,WIN_YSIZE, 0,0);
-  XFillRectangle(display,pix[PIX_DB_BACK],gc,
-                REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
-  XFillRectangle(display,pix[PIX_DB_DOOR],gc,
-                0,0, 3*DXSIZE,DYSIZE+VYSIZE);
+  BlitBitmap(pix[PIX_BACK], backbuffer, 0,0, WIN_XSIZE,WIN_YSIZE, 0,0);
+  ClearRectangle(backbuffer, REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
+  ClearRectangle(pix[PIX_DB_DOOR], 0,0, 3*DXSIZE,DYSIZE+VYSIZE);
 
-  for(i=0; i<MAX_BUF_XSIZE; i++)
-    for(j=0; j<MAX_BUF_YSIZE; j++)
-      redraw[i][j] = 0;
+  for(x=0; x<MAX_BUF_XSIZE; x++)
+    for(y=0; y<MAX_BUF_YSIZE; y++)
+      redraw[x][y] = 0;
   redraw_tiles = 0;
   redraw_mask = REDRAW_ALL;
 }
 
-void LoadGfx(int pos, struct PictureFileInfo *pic)
-{
-  char basefilename[256];
-  char filename[256];
-
-#ifdef USE_XPM_LIBRARY
-  int xpm_err, xbm_err;
-  unsigned int width,height;
-  int hot_x,hot_y;
-  Pixmap shapemask;
-  char *picture_ext = ".xpm";
-  char *picturemask_ext = "Mask.xbm";
-#else
-  int pcx_err;
-  char *picture_ext = ".pcx";
-#endif
-
-  /* Grafik laden */
-  if (pic->picture_filename)
-  {
-    sprintf(basefilename, "%s%s", pic->picture_filename, picture_ext);
-    DrawInitText(basefilename, 150, FC_YELLOW);
-    sprintf(filename, "%s/%s/%s",
-           options.ro_base_directory, GRAPHICS_DIRECTORY, basefilename);
-
-#ifdef MSDOS
-    rest(100);
-#endif /* MSDOS */
-
-#if DEBUG_TIMING
-    debug_print_timestamp(1, NULL);    /* initialize timestamp function */
-#endif
-
-#ifdef USE_XPM_LIBRARY
-
-    xpm_att[pos].valuemask = XpmCloseness;
-    xpm_att[pos].closeness = 20000;
-    xpm_err = XpmReadFileToPixmap(display,window,filename,
-                                 &pix[pos],&shapemask,&xpm_att[pos]);
-    switch(xpm_err)
-    {
-      case XpmOpenFailed:
-       Error(ERR_EXIT, "cannot open XPM file '%s'", filename);
-      case XpmFileInvalid:
-       Error(ERR_EXIT, "invalid XPM file '%s'", filename);
-      case XpmNoMemory:
-       Error(ERR_EXIT, "not enough memory for XPM file '%s'", filename);
-      case XpmColorFailed:
-       Error(ERR_EXIT, "cannot get colors for XPM file '%s'", filename);
-      default:
-       break;
-    }
-
-#if DEBUG_TIMING
-    printf("LOADING XPM FILE %s:", filename);
-    debug_print_timestamp(1, "");
-#endif
-
-#else /* !USE_XPM_LIBRARY */
-
-    pcx_err = Read_PCX_to_Pixmap(display, window, gc, filename,
-                                &pix[pos], &clipmask[pos]);
-    switch(pcx_err)
-    {
-      case PCX_Success:
-        break;
-      case PCX_OpenFailed:
-        Error(ERR_EXIT, "cannot open PCX file '%s'", filename);
-      case PCX_ReadFailed:
-        Error(ERR_EXIT, "cannot read PCX file '%s'", filename);
-      case PCX_FileInvalid:
-       Error(ERR_EXIT, "invalid PCX file '%s'", filename);
-      case PCX_NoMemory:
-       Error(ERR_EXIT, "not enough memory for PCX file '%s'", filename);
-      case PCX_ColorFailed:
-       Error(ERR_EXIT, "cannot get colors for PCX file '%s'", filename);
-      default:
-       break;
-    }
-
-#if DEBUG_TIMING
-    printf("SUMMARY LOADING PCX FILE %s:", filename);
-    debug_print_timestamp(1, "");
-#endif
-
-#endif /* !USE_XPM_LIBRARY */
-
-    if (!pix[pos])
-      Error(ERR_EXIT, "cannot get graphics for '%s'", pic->picture_filename);
-  }
-
-  /* zugehörige Maske laden (wenn vorhanden) */
-  if (pic->picture_with_mask)
-  {
-#ifdef USE_XPM_LIBRARY
-
-    sprintf(basefilename, "%s%s", pic->picture_filename, picturemask_ext);
-    DrawInitText(basefilename, 150, FC_YELLOW);
-    sprintf(filename, "%s/%s/%s",
-           options.ro_base_directory, GRAPHICS_DIRECTORY, basefilename);
-
-#if DEBUG_TIMING
-    debug_print_timestamp(1, NULL);    /* initialize timestamp function */
-#endif
-
-    xbm_err = XReadBitmapFile(display,window,filename,
-                             &width,&height,&clipmask[pos],&hot_x,&hot_y);
-    switch(xbm_err)
-    {
-      case BitmapSuccess:
-        break;
-      case BitmapOpenFailed:
-       Error(ERR_EXIT, "cannot open XBM file '%s'", filename);
-      case BitmapFileInvalid:
-       Error(ERR_EXIT, "invalid XBM file '%s'", filename);
-      case BitmapNoMemory:
-       Error(ERR_EXIT, "not enough memory for XBM file '%s'", filename);
-       break;
-      default:
-       break;
-    }
-
-#if DEBUG_TIMING
-    printf("LOADING XBM FILE %s:", filename);
-    debug_print_timestamp(1, "");
-#endif
-
-#endif /* USE_XPM_LIBRARY */
-
-    if (!clipmask[pos])
-      Error(ERR_EXIT, "cannot get clipmask for '%s'", pic->picture_filename);
-  }
-}
-
 void InitGadgets()
 {
   CreateLevelEditorGadgets();
@@ -1962,7 +1625,7 @@ void InitElementProperties()
     for(j=0; j<*(ep2_num[i]); j++)
       Elementeigenschaften2[(ep2_array[i])[j]] |= ep2_bit[i];
 
-  for(i=EL_CHAR_START; i<EL_CHAR_END; i++)
+  for(i=EL_CHAR_START; i<=EL_CHAR_END; i++)
     Elementeigenschaften1[i] |= (EP_BIT_CHAR | EP_BIT_INACTIVE);
 }
 
@@ -1970,45 +1633,15 @@ void CloseAllAndExit(int exit_value)
 {
   int i;
 
-  if (sound_process_id)
-  {
-    StopSounds();
-    kill(sound_process_id, SIGTERM);
-    FreeSounds(NUM_SOUNDS);
-  }
-
-  for(i=0; i<NUM_PIXMAPS; i++)
-  {
-    if (pix[i])
-    {
-#ifdef USE_XPM_LIBRARY
-      if (i < NUM_PICTURES)    /* XPM pictures */
-      {
-       XFreeColors(display,DefaultColormap(display,screen),
-                   xpm_att[i].pixels,xpm_att[i].npixels,0);
-       XpmFreeAttributes(&xpm_att[i]);
-      }
-#endif
-      XFreePixmap(display,pix[i]);
-    }
-    if (clipmask[i])
-      XFreePixmap(display,clipmask[i]);
-    if (clip_gc[i])
-      XFreeGC(display, clip_gc[i]);
-  }
-
-  if (gc)
-    XFreeGC(display, gc);
+  StopSounds();
+  FreeSounds(NUM_SOUNDS);
+  CloseAudio();
 
-  if (display)
-  {
-    XAutoRepeatOn(display);
-    XCloseDisplay(display);
-  }
+  for(i=0; i<NUM_BITMAPS; i++)
+    FreeBitmap(pix[i]);
+  CloseVideoDisplay();
 
-#ifdef MSDOS
-  dumpErrorFile();
-#endif
+  ClosePlatformDependantStuff();
 
   exit(exit_value);
 }
index b8bc9b0b5c04c2f700c90932b651199919927934..e2bee8105953e59902d9f6369025055729e87777 100644 (file)
@@ -1,14 +1,14 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  init.h                                                  *
+* init.h                                                   *
 ***********************************************************/
 
 #ifndef INIT_H
@@ -16,7 +16,7 @@
 
 #include "main.h"
 
-void OpenAll(int, char **);
+void OpenAll(void);
 void CloseAllAndExit(int);
 void InitJoysticks(void);
 
index 3aeb8e9d6163bc6b7dd3ae72e75d3d9c74a06185..9fb92d63d307ce0211ef99c6d349eecc08c3c1cf 100644 (file)
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  joystick.c                                              *
+* joystick.c                                               *
 ***********************************************************/
 
-#ifdef __FreeBSD__
+#if defined(PLATFORM_FREEBSD)
 #include <machine/joystick.h>
 #endif
 
+#include "libgame/libgame.h"
+
 #include "joystick.h"
-#include "misc.h"
 
-void CheckJoystickData()
+#define TRANSLATE_JOYSYMBOL_TO_JOYNAME 0
+#define TRANSLATE_JOYNAME_TO_JOYSYMBOL 1
+
+void translate_joyname(int *joysymbol, char **name, int mode)
 {
+  static struct
+  {
+    int joysymbol;
+    char *name;
+  } translate_joy[] =
+  {
+    { JOY_LEFT,                "joystick_left" },
+    { JOY_RIGHT,       "joystick_right" },
+    { JOY_UP,          "joystick_up" },
+    { JOY_DOWN,                "joystick_down" },
+    { JOY_BUTTON_1,    "joystick_button_1" },
+    { JOY_BUTTON_2,    "joystick_button_2" },
+  };
+
   int i;
-  int distance = 100;
 
-  for(i=0; i<MAX_PLAYERS; i++)
+  if (mode == TRANSLATE_JOYSYMBOL_TO_JOYNAME)
   {
-    if (setup.input[i].joy.xmiddle <= distance)
-      setup.input[i].joy.xmiddle = distance;
-    if (setup.input[i].joy.ymiddle <= distance)
-      setup.input[i].joy.ymiddle = distance;
+    *name = "[undefined]";
+
+    for (i=0; i<6; i++)
+    {
+      if (*joysymbol == translate_joy[i].joysymbol)
+      {
+       *name = translate_joy[i].name;
+       break;
+      }
+    }
+  }
+  else if (mode == TRANSLATE_JOYNAME_TO_JOYSYMBOL)
+  {
+    *joysymbol = 0;
+
+    for (i=0; i<6; i++)
+    {
+      if (strcmp(*name, translate_joy[i].name) == 0)
+      {
+       *joysymbol = translate_joy[i].joysymbol;
+       break;
+      }
+    }
+  }
+}
 
-    if (setup.input[i].joy.xleft >= setup.input[i].joy.xmiddle)
-      setup.input[i].joy.xleft = setup.input[i].joy.xmiddle - distance;
-    if (setup.input[i].joy.xright <= setup.input[i].joy.xmiddle)
-      setup.input[i].joy.xright = setup.input[i].joy.xmiddle + distance;
+char *getJoyNameFromJoySymbol(int joysymbol)
+{
+  char *name;
 
-    if (setup.input[i].joy.yupper >= setup.input[i].joy.ymiddle)
-      setup.input[i].joy.yupper = setup.input[i].joy.ymiddle - distance;
-    if (setup.input[i].joy.ylower <= setup.input[i].joy.ymiddle)
-      setup.input[i].joy.ylower = setup.input[i].joy.ymiddle + distance;
-  }
+  translate_joyname(&joysymbol, &name, TRANSLATE_JOYSYMBOL_TO_JOYNAME);
+  return name;
 }
 
-#ifndef MSDOS
+int getJoySymbolFromJoyName(char *name)
+{
+  int joysymbol;
+
+  translate_joyname(&joysymbol, &name, TRANSLATE_JOYNAME_TO_JOYSYMBOL);
+  return joysymbol;
+}
+
+int getJoystickNrFromDeviceName(char *device_name)
+{
+  char c;
+  int joystick_nr = 0;
+
+  if (device_name == NULL || device_name[0] == '\0')
+    return 0;
+
+  c = device_name[strlen(device_name) - 1];
+
+  if (c >= '0' && c <= '9')
+    joystick_nr = (int)(c - '0');
+
+  if (joystick_nr < 0 || joystick_nr >= MAX_PLAYERS)
+    joystick_nr = 0;
+
+  return joystick_nr;
+}
+
+#if !defined(PLATFORM_MSDOS)
 static int JoystickPosition(int middle, int margin, int actual)
 {
   long range, pos;
@@ -64,7 +125,198 @@ static int JoystickPosition(int middle, int margin, int actual)
 }
 #endif
 
-#ifndef MSDOS
+#if defined(TARGET_SDL)
+
+static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
+static int sdl_js_axis[MAX_PLAYERS][2]   = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
+static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
+
+SDL_Joystick *Get_SDL_Joystick(int nr)
+{
+  return sdl_joystick[nr];
+}
+
+boolean Open_SDL_Joystick(int nr)
+{
+  if (nr < 0 || nr > MAX_PLAYERS)
+    return FALSE;
+
+  return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
+}
+
+void Close_SDL_Joystick(int nr)
+{
+  if (nr < 0 || nr > MAX_PLAYERS)
+    return;
+
+  SDL_JoystickClose(sdl_joystick[nr]);
+}
+
+boolean Check_SDL_JoystickOpened(int nr)
+{
+  if (nr < 0 || nr > MAX_PLAYERS)
+    return FALSE;
+
+  return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
+}
+
+void HandleJoystickEvent(Event *event)
+{
+  switch(event->type)
+  {
+    case SDL_JOYAXISMOTION:
+      if (event->jaxis.axis < 2)
+      {
+       sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
+
+#if 0
+       printf("js_%d %s-axis: %d\n",
+              event->jaxis.which,
+              (event->jaxis.axis == 0 ? "x" : "y"),
+              event->jaxis.value);
+#endif
+      }
+      break;
+
+    case SDL_JOYBUTTONDOWN:
+      if (event->jbutton.button < 2)
+      {
+       sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
+
+#if 0
+        printf("js_%d button %d: pressed\n",
+              event->jbutton.which,
+              event->jbutton.button);
+#endif
+      }
+      break;
+
+    case SDL_JOYBUTTONUP:
+      if (event->jbutton.button < 2)
+      {
+       sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
+
+#if 0
+        printf("js_%d button %d: released\n",
+              event->jbutton.which,
+              event->jbutton.button);
+#endif
+      }
+      break;
+
+    default:
+      break;
+  }
+}
+
+int Get_SDL_Joystick_Axis(int nr, int axis)
+{
+  if (nr < 0 || nr > MAX_PLAYERS)
+    return 0;
+
+  if (axis < 0 || axis > 1)
+    return 0;
+
+  return sdl_js_axis[nr][axis];
+}
+
+void CheckJoystickData()
+{
+}
+
+int Joystick(int player_nr)
+{
+  int joystick_nr = stored_player[player_nr].joystick_fd;
+  int js_x,js_y, js_b1,js_b2;
+  int left, right, up, down;
+  int result = 0;
+
+  if (joystick_status == JOYSTICK_OFF)
+    return 0;
+
+  if (game_status == SETUPINPUT)
+    return 0;
+
+  if (!setup.input[player_nr].use_joystick ||
+      !Check_SDL_JoystickOpened(joystick_nr))
+    return 0;
+
+  js_x  = sdl_js_axis[joystick_nr][0];
+  js_y  = sdl_js_axis[joystick_nr][1];
+
+  js_b1 = sdl_js_button[joystick_nr][0];
+  js_b2 = sdl_js_button[joystick_nr][1];
+
+
+
+#if 0
+  printf("JOYSTICK %d: js_x == %d, js_y == %d, js_b1 == %d, js_b2 == %d\n",
+        joystick_nr, js_x, js_y, js_b1, js_b2);
+#endif
+
+
+
+  left  = JoystickPosition(setup.input[player_nr].joy.xmiddle,
+                          setup.input[player_nr].joy.xleft,  js_x);
+  right = JoystickPosition(setup.input[player_nr].joy.xmiddle,
+                          setup.input[player_nr].joy.xright, js_x);
+  up    = JoystickPosition(setup.input[player_nr].joy.ymiddle,
+                          setup.input[player_nr].joy.yupper, js_y);
+  down  = JoystickPosition(setup.input[player_nr].joy.ymiddle,
+                          setup.input[player_nr].joy.ylower, js_y);
+
+  if (left > JOYSTICK_PERCENT)
+    result |= JOY_LEFT;
+  else if (right > JOYSTICK_PERCENT)
+    result |= JOY_RIGHT;
+  if (up > JOYSTICK_PERCENT)
+    result |= JOY_UP;
+  else if (down > JOYSTICK_PERCENT)
+    result |= JOY_DOWN;
+
+  if (js_b1)
+    result |= JOY_BUTTON_1;
+  if (js_b2)
+    result |= JOY_BUTTON_2;
+
+
+
+#if 0
+  printf("result == 0x%08x\n", result);
+#endif
+
+
+
+  return result;
+}
+
+#else /* !TARGET_SDL */
+
+void CheckJoystickData()
+{
+  int i;
+  int distance = 100;
+
+  for(i=0; i<MAX_PLAYERS; i++)
+  {
+    if (setup.input[i].joy.xmiddle <= distance)
+      setup.input[i].joy.xmiddle = distance;
+    if (setup.input[i].joy.ymiddle <= distance)
+      setup.input[i].joy.ymiddle = distance;
+
+    if (setup.input[i].joy.xleft >= setup.input[i].joy.xmiddle)
+      setup.input[i].joy.xleft = setup.input[i].joy.xmiddle - distance;
+    if (setup.input[i].joy.xright <= setup.input[i].joy.xmiddle)
+      setup.input[i].joy.xright = setup.input[i].joy.xmiddle + distance;
+
+    if (setup.input[i].joy.yupper >= setup.input[i].joy.ymiddle)
+      setup.input[i].joy.yupper = setup.input[i].joy.ymiddle - distance;
+    if (setup.input[i].joy.ylower <= setup.input[i].joy.ymiddle)
+      setup.input[i].joy.ylower = setup.input[i].joy.ymiddle + distance;
+  }
+}
+
+#if defined(PLATFORM_UNIX)
 int Joystick(int player_nr)
 {
 #ifdef __FreeBSD__
@@ -137,7 +389,7 @@ int Joystick(int player_nr)
   return result;
 }
 
-#else /* MSDOS */
+#else /* PLATFORM_MSDOS */
 
 /* allegro global variables for joystick control */
 extern int num_joysticks;
@@ -158,7 +410,7 @@ int Joystick(int player_nr)
     return 0;
 
   /* the allegro global variable 'num_joysticks' contains the number
-     of joysticks found at initialization under MSDOS / Windows */
+     of joysticks found at initialization under MS-DOS / Windows */
 
 #if 0
   if (joystick_nr >= num_joysticks || !setup.input[player_nr].use_joystick)
@@ -194,7 +446,9 @@ int Joystick(int player_nr)
 
   return result;
 }
-#endif /* MSDOS */
+#endif /* PLATFORM_MSDOS */
+
+#endif /* !TARGET_SDL */
 
 int JoystickButton(int player_nr)
 {
index a48c2bb39f2d54d212fc4bb25f41aab51ad54249..ea74c8b451963a045b3eae92d95a320621c9d311 100644 (file)
@@ -1,14 +1,14 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  joystick.h                                              *
+* joystick.h                                               *
 ***********************************************************/
 
 #ifndef JOYSTICK_H
@@ -19,6 +19,7 @@
 /* values for the joystick */
 #define JOYSTICK_OFF           0
 #define        JOYSTICK_AVAILABLE      1
+
 #ifdef __FreeBSD__
 #include <machine/joystick.h>
 #define DEV_JOYSTICK_0         "/dev/joy0"
 
 /* get these values from the program 'js' from the joystick package, */
 /* set JOYSTICK_PERCENT to a threshold appropriate for your joystick */
+
+#ifdef TARGET_SDL
+#define JOYSTICK_XLEFT         -32767
+#define JOYSTICK_XMIDDLE       0
+#define JOYSTICK_XRIGHT                32767
+#define JOYSTICK_YUPPER                -32767
+#define JOYSTICK_YMIDDLE       0
+#define JOYSTICK_YLOWER                32767
+#else
 #define JOYSTICK_XLEFT         30
 #define JOYSTICK_XMIDDLE       530
 #define JOYSTICK_XRIGHT                1250
 #define JOYSTICK_YUPPER                40
 #define JOYSTICK_YMIDDLE       680
 #define JOYSTICK_YLOWER                1440
+#endif
 
 #define JOYSTICK_PERCENT       25
 
 #endif
 
 
+#if defined(TARGET_SDL)
+SDL_Joystick *Get_SDL_Joystick(int);
+boolean Open_SDL_Joystick(int);
+void Close_SDL_Joystick(int);
+boolean Check_SDL_JoystickOpened(int);
+void HandleJoystickEvent(Event *);
+int Get_SDL_Joystick_Axis(int, int);
+#endif
+
 void CheckJoystickData(void);
 int Joystick(int);
 int JoystickButton(int);
 int AnyJoystick(void);
 int AnyJoystickButton(void);
 
-#endif
+#endif /* JOYSTICK_H */
diff --git a/src/libgame/Makefile b/src/libgame/Makefile
new file mode 100644 (file)
index 0000000..b756b27
--- /dev/null
@@ -0,0 +1,56 @@
+#=============================================================================#
+# Makefile for Artsoft Retro-Game Library                                     #
+# (c) 1994-2000 Holger Schemel, info@artsoft.org                              #
+#=============================================================================#
+
+SRCS = system.c        \
+       gadgets.c       \
+       text.c          \
+       sound.c         \
+       pcx.c           \
+       image.c         \
+       random.c        \
+       misc.c          \
+       msdos.c         \
+       x11.c           \
+       sdl.c
+
+OBJS = system.o        \
+       gadgets.o       \
+       text.o          \
+       sound.o         \
+       pcx.o           \
+       image.o         \
+       random.o        \
+       misc.o          \
+       msdos.o         \
+       x11.o           \
+       sdl.o
+
+LIBGAME = libgame.a
+
+
+all: $(LIBGAME)
+
+$(LIBGAME): $(OBJS)
+       $(AR) cru $(LIBGAME) $(OBJS)
+       $(RANLIB) $(LIBGAME)
+
+.c.o:
+       $(CC) $(PROFILING) $(CFLAGS) -c $*.c
+
+clean:
+       $(RM) $(OBJS)
+       $(RM) $(LIBGAME)
+
+
+#-----------------------------------------------------------------------------#
+# development only stuff                                                      #
+#-----------------------------------------------------------------------------#
+
+depend:
+       for i in $(SRCS); do $(CPP) $(CFLAGS) -M $$i; done > .depend
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
diff --git a/src/libgame/gadgets.c b/src/libgame/gadgets.c
new file mode 100644 (file)
index 0000000..6cbf307
--- /dev/null
@@ -0,0 +1,1110 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* gadgets.c                                                *
+***********************************************************/
+
+#include <stdarg.h>
+#include <string.h>
+
+#include "gadgets.h"
+#include "text.h"
+#include "misc.h"
+
+
+/* values for DrawGadget() */
+#define DG_UNPRESSED           0
+#define DG_PRESSED             1
+#define DG_BUFFERED            0
+#define DG_DIRECT              1
+
+static struct GadgetInfo *gadget_list_first_entry = NULL;
+static struct GadgetInfo *gadget_list_last_entry = NULL;
+static int next_free_gadget_id = 1;
+static boolean gadget_id_wrapped = FALSE;
+
+static struct GadgetInfo *getGadgetInfoFromGadgetID(int id)
+{
+  struct GadgetInfo *gi = gadget_list_first_entry;
+
+  while (gi && gi->id != id)
+    gi = gi->next;
+
+  return gi;
+}
+
+static int getNewGadgetID()
+{
+  int id = next_free_gadget_id++;
+
+  if (next_free_gadget_id <= 0)                /* counter overrun */
+  {
+    gadget_id_wrapped = TRUE;          /* now we must check each ID */
+    next_free_gadget_id = 0;
+  }
+
+  if (gadget_id_wrapped)
+  {
+    next_free_gadget_id++;
+    while (getGadgetInfoFromGadgetID(next_free_gadget_id) != NULL)
+      next_free_gadget_id++;
+  }
+
+  if (next_free_gadget_id <= 0)                /* cannot get new gadget id */
+    Error(ERR_EXIT, "too much gadgets -- this should not happen");
+
+  return id;
+}
+
+static struct GadgetInfo *getGadgetInfoFromMousePosition(int mx, int my)
+{
+  struct GadgetInfo *gi = gadget_list_first_entry;
+
+  while (gi)
+  {
+    if (gi->mapped &&
+       mx >= gi->x && mx < gi->x + gi->width &&
+       my >= gi->y && my < gi->y + gi->height)
+       break;
+
+    gi = gi->next;
+  }
+
+  return gi;
+}
+
+static void default_callback_info(void *ptr)
+{
+#if 0
+  if (game_status == LEVELED)
+    HandleEditorGadgetInfoText(ptr);
+#endif
+
+  return;
+}
+
+static void default_callback_action(void *ptr)
+{
+  return;
+}
+
+static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
+{
+  int state = (pressed ? 1 : 0);
+  struct GadgetDesign *gd = (gi->checked ?
+                            &gi->alt_design[state] :
+                            &gi->design[state]);
+
+  switch (gi->type)
+  {
+    case GD_TYPE_NORMAL_BUTTON:
+    case GD_TYPE_CHECK_BUTTON:
+    case GD_TYPE_RADIO_BUTTON:
+      BlitBitmap(gd->bitmap, drawto,
+                gd->x, gd->y, gi->width, gi->height, gi->x, gi->y);
+      if (gi->deco.design.bitmap)
+       BlitBitmap(gi->deco.design.bitmap, drawto,
+                  gi->deco.design.x, gi->deco.design.y,
+                  gi->deco.width, gi->deco.height,
+                  gi->x + gi->deco.x + (pressed ? gi->deco.xshift : 0),
+                  gi->y + gi->deco.y + (pressed ? gi->deco.yshift : 0));
+      break;
+
+    case GD_TYPE_TEXTINPUT_ALPHANUMERIC:
+    case GD_TYPE_TEXTINPUT_NUMERIC:
+      {
+       int i;
+       char cursor_letter;
+       char cursor_string[3];
+       char text[MAX_GADGET_TEXTSIZE + 1];
+       int font_type = gi->text.font_type;
+       int font_width = getFontWidth(FS_SMALL, font_type);
+       int border = gi->border.size;
+       strcpy(text, gi->text.value);
+       strcat(text, " ");
+
+       /* left part of gadget */
+       BlitBitmap(gd->bitmap, drawto,
+                  gd->x, gd->y, border, gi->height, gi->x, gi->y);
+
+       /* middle part of gadget */
+       for (i=0; i<=gi->text.size; i++)
+         BlitBitmap(gd->bitmap, drawto,
+                    gd->x + border, gd->y, font_width, gi->height,
+                    gi->x + border + i * font_width, gi->y);
+
+       /* right part of gadget */
+       BlitBitmap(gd->bitmap, drawto,
+                  gd->x + gi->border.width - border, gd->y,
+                  border, gi->height, gi->x + gi->width - border, gi->y);
+
+       /* gadget text value */
+       DrawText(gi->x + border, gi->y + border, text, FS_SMALL, font_type);
+
+       cursor_letter = gi->text.value[gi->text.cursor_position];
+       cursor_string[0] = '~';
+       cursor_string[1] = (cursor_letter != '\0' ? cursor_letter : ' ');
+       cursor_string[2] = '\0';
+
+       /* draw cursor, if active */
+       if (pressed)
+         DrawText(gi->x + border + gi->text.cursor_position * font_width,
+                  gi->y + border, cursor_string, FS_SMALL, font_type);
+      }
+      break;
+
+    case GD_TYPE_SCROLLBAR_VERTICAL:
+      {
+       int i;
+       int xpos = gi->x;
+       int ypos = gi->y + gi->scrollbar.position;
+       int design_full = gi->width;
+       int design_body = design_full - 2 * gi->border.size;
+       int size_full = gi->scrollbar.size;
+       int size_body = size_full - 2 * gi->border.size;
+       int num_steps = size_body / design_body;
+       int step_size_remain = size_body - num_steps * design_body;
+
+       /* clear scrollbar area */
+       ClearRectangle(backbuffer, gi->x, gi->y, gi->width, gi->height);
+
+       /* upper part of gadget */
+       BlitBitmap(gd->bitmap, drawto,
+                  gd->x, gd->y,
+                  gi->width, gi->border.size,
+                  xpos, ypos);
+
+       /* middle part of gadget */
+       for (i=0; i<num_steps; i++)
+         BlitBitmap(gd->bitmap, drawto,
+                    gd->x, gd->y + gi->border.size,
+                    gi->width, design_body,
+                    xpos, ypos + gi->border.size + i * design_body);
+
+       /* remaining middle part of gadget */
+       if (step_size_remain > 0)
+         BlitBitmap(gd->bitmap, drawto,
+                    gd->x,  gd->y + gi->border.size,
+                    gi->width, step_size_remain,
+                    xpos, ypos + gi->border.size + num_steps * design_body);
+
+       /* lower part of gadget */
+       BlitBitmap(gd->bitmap, drawto,
+                  gd->x, gd->y + design_full - gi->border.size,
+                  gi->width, gi->border.size,
+                  xpos, ypos + size_full - gi->border.size);
+      }
+      break;
+
+    case GD_TYPE_SCROLLBAR_HORIZONTAL:
+      {
+       int i;
+       int xpos = gi->x + gi->scrollbar.position;
+       int ypos = gi->y;
+       int design_full = gi->height;
+       int design_body = design_full - 2 * gi->border.size;
+       int size_full = gi->scrollbar.size;
+       int size_body = size_full - 2 * gi->border.size;
+       int num_steps = size_body / design_body;
+       int step_size_remain = size_body - num_steps * design_body;
+
+       /* clear scrollbar area */
+       ClearRectangle(backbuffer, gi->x, gi->y, gi->width, gi->height);
+
+       /* left part of gadget */
+       BlitBitmap(gd->bitmap, drawto,
+                  gd->x, gd->y,
+                  gi->border.size, gi->height,
+                  xpos, ypos);
+
+       /* middle part of gadget */
+       for (i=0; i<num_steps; i++)
+         BlitBitmap(gd->bitmap, drawto,
+                    gd->x + gi->border.size, gd->y,
+                    design_body, gi->height,
+                    xpos + gi->border.size + i * design_body, ypos);
+
+       /* remaining middle part of gadget */
+       if (step_size_remain > 0)
+         BlitBitmap(gd->bitmap, drawto,
+                    gd->x + gi->border.size, gd->y,
+                    step_size_remain, gi->height,
+                    xpos + gi->border.size + num_steps * design_body, ypos);
+
+       /* right part of gadget */
+       BlitBitmap(gd->bitmap, drawto,
+                  gd->x + design_full - gi->border.size, gd->y,
+                  gi->border.size, gi->height,
+                  xpos + size_full - gi->border.size, ypos);
+      }
+      break;
+
+    default:
+      return;
+  }
+
+  if (direct)
+    BlitBitmap(drawto, window,
+              gi->x, gi->y, gi->width, gi->height, gi->x, gi->y);
+  else
+    redraw_mask |= (gi->x < gfx.sx + gfx.sxsize ? REDRAW_FIELD :
+                   gi->y < gfx.dy + gfx.dysize ? REDRAW_DOOR_1 :
+                   gi->y > gfx.vy ? REDRAW_DOOR_2 : REDRAW_DOOR_3);
+}
+
+static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
+{
+  int tag = first_tag;
+
+  while (tag != GDI_END)
+  {
+    switch(tag)
+    {
+      case GDI_CUSTOM_ID:
+       gi->custom_id = va_arg(ap, int);
+       break;
+
+      case GDI_CUSTOM_TYPE_ID:
+       gi->custom_type_id = va_arg(ap, int);
+       break;
+
+      case GDI_INFO_TEXT:
+       {
+         int max_textsize = MAX_INFO_TEXTSIZE - 1;
+
+         strncpy(gi->info_text, va_arg(ap, char *), max_textsize);
+         gi->info_text[max_textsize] = '\0';
+       }
+       break;
+
+      case GDI_X:
+       gi->x = va_arg(ap, int);
+       break;
+
+      case GDI_Y:
+       gi->y = va_arg(ap, int);
+       break;
+
+      case GDI_WIDTH:
+       gi->width = va_arg(ap, int);
+       break;
+
+      case GDI_HEIGHT:
+       gi->height = va_arg(ap, int);
+       break;
+
+      case GDI_TYPE:
+       gi->type = va_arg(ap, unsigned long);
+       break;
+
+      case GDI_STATE:
+       gi->state = va_arg(ap, unsigned long);
+       break;
+
+      case GDI_CHECKED:
+       gi->checked = va_arg(ap, boolean);
+       break;
+
+      case GDI_RADIO_NR:
+       gi->radio_nr = va_arg(ap, unsigned long);
+       break;
+
+      case GDI_NUMBER_VALUE:
+       gi->text.number_value = va_arg(ap, long);
+       sprintf(gi->text.value, "%d", gi->text.number_value);
+       gi->text.cursor_position = strlen(gi->text.value);
+       break;
+
+      case GDI_NUMBER_MIN:
+       gi->text.number_min = va_arg(ap, long);
+       if (gi->text.number_value < gi->text.number_min)
+       {
+         gi->text.number_value = gi->text.number_min;
+         sprintf(gi->text.value, "%d", gi->text.number_value);
+       }
+       break;
+
+      case GDI_NUMBER_MAX:
+       gi->text.number_max = va_arg(ap, long);
+       if (gi->text.number_value > gi->text.number_max)
+       {
+         gi->text.number_value = gi->text.number_max;
+         sprintf(gi->text.value, "%d", gi->text.number_value);
+       }
+       break;
+
+      case GDI_TEXT_VALUE:
+       {
+         int max_textsize = MAX_GADGET_TEXTSIZE;
+
+         if (gi->text.size)
+           max_textsize = MIN(gi->text.size, MAX_GADGET_TEXTSIZE - 1);
+
+         strncpy(gi->text.value, va_arg(ap, char *), max_textsize);
+         gi->text.value[max_textsize] = '\0';
+         gi->text.cursor_position = strlen(gi->text.value);
+       }
+       break;
+
+      case GDI_TEXT_SIZE:
+       {
+         int tag_value = va_arg(ap, int);
+         int max_textsize = MIN(tag_value, MAX_GADGET_TEXTSIZE - 1);
+
+         gi->text.size = max_textsize;
+         gi->text.value[max_textsize] = '\0';
+       }
+       break;
+
+      case GDI_TEXT_FONT:
+       gi->text.font_type = va_arg(ap, int);
+       break;
+
+      case GDI_DESIGN_UNPRESSED:
+       gi->design[GD_BUTTON_UNPRESSED].bitmap = va_arg(ap, Bitmap *);
+       gi->design[GD_BUTTON_UNPRESSED].x = va_arg(ap, int);
+       gi->design[GD_BUTTON_UNPRESSED].y = va_arg(ap, int);
+       break;
+
+      case GDI_DESIGN_PRESSED:
+       gi->design[GD_BUTTON_PRESSED].bitmap = va_arg(ap, Bitmap *);
+       gi->design[GD_BUTTON_PRESSED].x = va_arg(ap, int);
+       gi->design[GD_BUTTON_PRESSED].y = va_arg(ap, int);
+       break;
+
+      case GDI_ALT_DESIGN_UNPRESSED:
+       gi->alt_design[GD_BUTTON_UNPRESSED].bitmap= va_arg(ap, Bitmap *);
+       gi->alt_design[GD_BUTTON_UNPRESSED].x = va_arg(ap, int);
+       gi->alt_design[GD_BUTTON_UNPRESSED].y = va_arg(ap, int);
+       break;
+
+      case GDI_ALT_DESIGN_PRESSED:
+       gi->alt_design[GD_BUTTON_PRESSED].bitmap = va_arg(ap, Bitmap *);
+       gi->alt_design[GD_BUTTON_PRESSED].x = va_arg(ap, int);
+       gi->alt_design[GD_BUTTON_PRESSED].y = va_arg(ap, int);
+       break;
+
+      case GDI_BORDER_SIZE:
+       gi->border.size = va_arg(ap, int);
+       break;
+
+      case GDI_TEXTINPUT_DESIGN_WIDTH:
+       gi->border.width = va_arg(ap, int);
+       break;
+
+      case GDI_DECORATION_DESIGN:
+       gi->deco.design.bitmap = va_arg(ap, Bitmap *);
+       gi->deco.design.x = va_arg(ap, int);
+       gi->deco.design.y = va_arg(ap, int);
+       break;
+
+      case GDI_DECORATION_POSITION:
+       gi->deco.x = va_arg(ap, int);
+       gi->deco.y = va_arg(ap, int);
+       break;
+
+      case GDI_DECORATION_SIZE:
+       gi->deco.width = va_arg(ap, int);
+       gi->deco.height = va_arg(ap, int);
+       break;
+
+      case GDI_DECORATION_SHIFTING:
+       gi->deco.xshift = va_arg(ap, int);
+       gi->deco.yshift = va_arg(ap, int);
+       break;
+
+      case GDI_EVENT_MASK:
+       gi->event_mask = va_arg(ap, unsigned long);
+       break;
+
+      case GDI_AREA_SIZE:
+       gi->drawing.area_xsize = va_arg(ap, int);
+       gi->drawing.area_ysize = va_arg(ap, int);
+
+       /* determine dependent values for drawing area gadget, if needed */
+       if (gi->width == 0 && gi->height == 0 &&
+           gi->drawing.item_xsize !=0 && gi->drawing.item_ysize !=0)
+       {
+         gi->width = gi->drawing.area_xsize * gi->drawing.item_xsize;
+         gi->height = gi->drawing.area_ysize * gi->drawing.item_ysize;
+       }
+       else if (gi->drawing.item_xsize == 0 && gi->drawing.item_ysize == 0 &&
+                gi->width != 0 && gi->height != 0)
+       {
+         gi->drawing.item_xsize = gi->width / gi->drawing.area_xsize;
+         gi->drawing.item_ysize = gi->height / gi->drawing.area_ysize;
+       }
+       break;
+
+      case GDI_ITEM_SIZE:
+       gi->drawing.item_xsize = va_arg(ap, int);
+       gi->drawing.item_ysize = va_arg(ap, int);
+
+       /* determine dependent values for drawing area gadget, if needed */
+       if (gi->width == 0 && gi->height == 0 &&
+           gi->drawing.area_xsize !=0 && gi->drawing.area_ysize !=0)
+       {
+         gi->width = gi->drawing.area_xsize * gi->drawing.item_xsize;
+         gi->height = gi->drawing.area_ysize * gi->drawing.item_ysize;
+       }
+       else if (gi->drawing.area_xsize == 0 && gi->drawing.area_ysize == 0 &&
+                gi->width != 0 && gi->height != 0)
+       {
+         gi->drawing.area_xsize = gi->width / gi->drawing.item_xsize;
+         gi->drawing.area_ysize = gi->height / gi->drawing.item_ysize;
+       }
+       break;
+
+      case GDI_SCROLLBAR_ITEMS_MAX:
+       gi->scrollbar.items_max = va_arg(ap, int);
+       break;
+
+      case GDI_SCROLLBAR_ITEMS_VISIBLE:
+       gi->scrollbar.items_visible = va_arg(ap, int);
+       break;
+
+      case GDI_SCROLLBAR_ITEM_POSITION:
+       gi->scrollbar.item_position = va_arg(ap, int);
+       break;
+
+      case GDI_CALLBACK_INFO:
+       gi->callback_info = va_arg(ap, gadget_function);
+       break;
+
+      case GDI_CALLBACK_ACTION:
+       gi->callback_action = va_arg(ap, gadget_function);
+       break;
+
+      default:
+       Error(ERR_EXIT, "HandleGadgetTags(): unknown tag %d", tag);
+    }
+
+    tag = va_arg(ap, int);     /* read next tag */
+  }
+
+  /* check if gadget complete */
+  if (gi->type != GD_TYPE_DRAWING_AREA &&
+      (!gi->design[GD_BUTTON_UNPRESSED].bitmap ||
+       !gi->design[GD_BUTTON_PRESSED].bitmap))
+    Error(ERR_EXIT, "gadget incomplete (missing Bitmap)");
+
+  /* adjust gadget values in relation to other gadget values */
+
+  if (gi->type & GD_TYPE_TEXTINPUT)
+  {
+    int font_width = getFontWidth(FS_SMALL, gi->text.font_type);
+    int font_height = getFontHeight(FS_SMALL, gi->text.font_type);
+
+    gi->width = 2 * gi->border.size + (gi->text.size + 1) * font_width;
+    gi->height = 2 * gi->border.size + font_height;
+  }
+
+  if (gi->type & GD_TYPE_TEXTINPUT_NUMERIC)
+  {
+    struct GadgetTextInput *text = &gi->text;
+    int value = text->number_value;
+
+    text->number_value = (value < text->number_min ? text->number_min :
+                         value > text->number_max ? text->number_max :
+                         value);
+
+    sprintf(text->value, "%d", text->number_value);
+  }
+
+  if (gi->type & GD_TYPE_SCROLLBAR)
+  {
+    struct GadgetScrollbar *gs = &gi->scrollbar;
+
+    if (gi->width == 0 || gi->height == 0 ||
+       gs->items_max == 0 || gs->items_visible == 0)
+      Error(ERR_EXIT, "scrollbar gadget incomplete (missing tags)");
+
+    /* calculate internal scrollbar values */
+    gs->size_max = (gi->type == GD_TYPE_SCROLLBAR_VERTICAL ?
+                   gi->height : gi->width);
+    gs->size = gs->size_max * gs->items_visible / gs->items_max;
+    gs->position = gs->size_max * gs->item_position / gs->items_max;
+    gs->position_max = gs->size_max - gs->size;
+    gs->correction = gs->size_max / gs->items_max / 2;
+
+    /* finetuning for maximal right/bottom position */
+    if (gs->item_position == gs->items_max - gs->items_visible)
+      gs->position = gs->position_max;
+  }
+}
+
+void ModifyGadget(struct GadgetInfo *gi, int first_tag, ...)
+{
+  va_list ap;
+
+  va_start(ap, first_tag);
+  HandleGadgetTags(gi, first_tag, ap);
+  va_end(ap);
+
+  RedrawGadget(gi);
+}
+
+void RedrawGadget(struct GadgetInfo *gi)
+{
+  if (gi->mapped)
+    DrawGadget(gi, gi->state, DG_DIRECT);
+}
+
+struct GadgetInfo *CreateGadget(int first_tag, ...)
+{
+  struct GadgetInfo *new_gadget = checked_malloc(sizeof(struct GadgetInfo));
+  va_list ap;
+
+  /* always start with reliable default values */
+  memset(new_gadget, 0, sizeof(struct GadgetInfo));    /* zero all fields */
+  new_gadget->id = getNewGadgetID();
+  new_gadget->callback_info = default_callback_info;
+  new_gadget->callback_action = default_callback_action;
+
+  va_start(ap, first_tag);
+  HandleGadgetTags(new_gadget, first_tag, ap);
+  va_end(ap);
+
+  /* insert new gadget into global gadget list */
+  if (gadget_list_last_entry)
+  {
+    gadget_list_last_entry->next = new_gadget;
+    gadget_list_last_entry = gadget_list_last_entry->next;
+  }
+  else
+    gadget_list_first_entry = gadget_list_last_entry = new_gadget;
+
+  return new_gadget;
+}
+
+void FreeGadget(struct GadgetInfo *gi)
+{
+  struct GadgetInfo *gi_previous = gadget_list_first_entry;
+
+  while (gi_previous && gi_previous->next != gi)
+    gi_previous = gi_previous->next;
+
+  if (gi == gadget_list_first_entry)
+    gadget_list_first_entry = gi->next;
+
+  if (gi == gadget_list_last_entry)
+    gadget_list_last_entry = gi_previous;
+
+  gi_previous->next = gi->next;
+  free(gi);
+}
+
+static void CheckRangeOfNumericInputGadget(struct GadgetInfo *gi)
+{
+  if (gi->type != GD_TYPE_TEXTINPUT_NUMERIC)
+    return;
+
+  gi->text.number_value = atoi(gi->text.value);
+
+  if (gi->text.number_value < gi->text.number_min)
+    gi->text.number_value = gi->text.number_min;
+  if (gi->text.number_value > gi->text.number_max)
+    gi->text.number_value = gi->text.number_max;
+
+  sprintf(gi->text.value, "%d", gi->text.number_value);
+
+  if (gi->text.cursor_position < 0)
+    gi->text.cursor_position = 0;
+  else if (gi->text.cursor_position > strlen(gi->text.value))
+    gi->text.cursor_position = strlen(gi->text.value);
+}
+
+/* global pointer to gadget actually in use (when mouse button pressed) */
+static struct GadgetInfo *last_gi = NULL;
+
+static void MapGadgetExt(struct GadgetInfo *gi, boolean redraw)
+{
+  if (gi == NULL || gi->mapped)
+    return;
+
+  gi->mapped = TRUE;
+
+  if (redraw)
+    DrawGadget(gi, DG_UNPRESSED, DG_BUFFERED);
+}
+
+void MapGadget(struct GadgetInfo *gi)
+{
+  MapGadgetExt(gi, TRUE);
+}
+
+void UnmapGadget(struct GadgetInfo *gi)
+{
+  if (gi == NULL || !gi->mapped)
+    return;
+
+  gi->mapped = FALSE;
+
+  if (gi == last_gi)
+    last_gi = NULL;
+}
+
+#define MAX_NUM_GADGETS                1024
+#define MULTIMAP_UNMAP         (1 << 0)
+#define MULTIMAP_REMAP         (1 << 1)
+#define MULTIMAP_REDRAW                (1 << 2)
+#define MULTIMAP_PLAYFIELD     (1 << 3)
+#define MULTIMAP_DOOR_1                (1 << 4)
+#define MULTIMAP_DOOR_2                (1 << 5)
+#define MULTIMAP_ALL           (MULTIMAP_PLAYFIELD | \
+                                MULTIMAP_DOOR_1 | \
+                                MULTIMAP_DOOR_2)
+
+static void MultiMapGadgets(int mode)
+{
+  struct GadgetInfo *gi = gadget_list_first_entry;
+  static boolean map_state[MAX_NUM_GADGETS];
+  int map_count = 0;
+
+  while (gi)
+  {
+    if ((mode & MULTIMAP_PLAYFIELD &&
+        gi->x < gfx.sx + gfx.sxsize) ||
+       (mode & MULTIMAP_DOOR_1 &&
+        gi->x >= gfx.dx && gi->y < gfx.dy + gfx.dysize) ||
+       (mode & MULTIMAP_DOOR_2 &&
+        gi->x >= gfx.dx && gi->y > gfx.dy + gfx.dysize) ||
+       (mode & MULTIMAP_ALL) == MULTIMAP_ALL)
+    {
+      if (mode & MULTIMAP_UNMAP)
+      {
+       map_state[map_count++ % MAX_NUM_GADGETS] = gi->mapped;
+       UnmapGadget(gi);
+      }
+      else
+      {
+       if (map_state[map_count++ % MAX_NUM_GADGETS])
+         MapGadgetExt(gi, (mode & MULTIMAP_REDRAW));
+      }
+    }
+
+    gi = gi->next;
+  }
+}
+
+void UnmapAllGadgets()
+{
+  MultiMapGadgets(MULTIMAP_ALL | MULTIMAP_UNMAP);
+}
+
+void RemapAllGadgets()
+{
+  MultiMapGadgets(MULTIMAP_ALL | MULTIMAP_REMAP);
+}
+
+boolean anyTextGadgetActive()
+{
+  return (last_gi && last_gi->type & GD_TYPE_TEXTINPUT && last_gi->mapped);
+}
+
+void ClickOnGadget(struct GadgetInfo *gi, int button)
+{
+  /* simulate releasing mouse button over last gadget, if still pressed */
+  if (button_status)
+    HandleGadgets(-1, -1, 0);
+
+  /* simulate pressing mouse button over specified gadget */
+  HandleGadgets(gi->x, gi->y, button);
+
+  /* simulate releasing mouse button over specified gadget */
+  HandleGadgets(gi->x, gi->y, 0);
+}
+
+void HandleGadgets(int mx, int my, int button)
+{
+  static struct GadgetInfo *last_info_gi = NULL;
+  static unsigned long pressed_delay = 0;
+  static int last_button = 0;
+  static int last_mx = 0, last_my = 0;
+  int scrollbar_mouse_pos = 0;
+  struct GadgetInfo *new_gi, *gi;
+  boolean press_event;
+  boolean release_event;
+  boolean mouse_moving;
+  boolean gadget_pressed;
+  boolean gadget_pressed_repeated;
+  boolean gadget_moving;
+  boolean gadget_moving_inside;
+  boolean gadget_moving_off_borders;
+  boolean gadget_released;
+  boolean gadget_released_inside;
+  boolean gadget_released_off_borders;
+  boolean changed_position = FALSE;
+
+  /* check if there are any gadgets defined */
+  if (gadget_list_first_entry == NULL)
+    return;
+
+  /* check which gadget is under the mouse pointer */
+  new_gi = getGadgetInfoFromMousePosition(mx, my);
+
+  /* check if button state has changed since last invocation */
+  press_event = (button != 0 && last_button == 0);
+  release_event = (button == 0 && last_button != 0);
+  last_button = button;
+
+  /* check if mouse has been moved since last invocation */
+  mouse_moving = ((mx != last_mx || my != last_my) && motion_status);
+  last_mx = mx;
+  last_my = my;
+
+  /* special treatment for text and number input gadgets */
+  if (anyTextGadgetActive() && button != 0 && !motion_status)
+  {
+    struct GadgetInfo *gi = last_gi;
+
+    if (new_gi == last_gi)
+    {
+      /* if mouse button pressed inside activated text gadget, set cursor */
+      gi->text.cursor_position =
+       (mx - gi->x - gi->border.size) /
+       getFontWidth(FS_SMALL, gi->text.font_type);
+
+      if (gi->text.cursor_position < 0)
+       gi->text.cursor_position = 0;
+      else if (gi->text.cursor_position > strlen(gi->text.value))
+       gi->text.cursor_position = strlen(gi->text.value);
+
+      DrawGadget(gi, DG_PRESSED, DG_DIRECT);
+    }
+    else
+    {
+      /* if mouse button pressed outside text input gadget, deactivate it */
+      CheckRangeOfNumericInputGadget(gi);
+      DrawGadget(gi, DG_UNPRESSED, DG_DIRECT);
+
+      gi->event.type = GD_EVENT_TEXT_LEAVING;
+
+      if (gi->event_mask & GD_EVENT_TEXT_LEAVING)
+       gi->callback_action(gi);
+
+      last_gi = NULL;
+    }
+  }
+
+  gadget_pressed =
+    (button != 0 && last_gi == NULL && new_gi != NULL && press_event);
+  gadget_pressed_repeated =
+    (button != 0 && last_gi != NULL && new_gi == last_gi);
+
+  gadget_released =            (release_event && last_gi != NULL);
+  gadget_released_inside =     (gadget_released && new_gi == last_gi);
+  gadget_released_off_borders =        (gadget_released && new_gi != last_gi);
+
+  gadget_moving =            (button != 0 && last_gi != NULL && mouse_moving);
+  gadget_moving_inside =      (gadget_moving && new_gi == last_gi);
+  gadget_moving_off_borders = (gadget_moving && new_gi != last_gi);
+
+  /* if new gadget pressed, store this gadget  */
+  if (gadget_pressed)
+    last_gi = new_gi;
+
+  /* 'gi' is actually handled gadget */
+  gi = last_gi;
+
+  /* if gadget is scrollbar, choose mouse position value */
+  if (gi && gi->type & GD_TYPE_SCROLLBAR)
+    scrollbar_mouse_pos =
+      (gi->type == GD_TYPE_SCROLLBAR_HORIZONTAL ? mx - gi->x : my - gi->y);
+
+  /* if mouse button released, no gadget needs to be handled anymore */
+  if (button == 0 && last_gi && !(last_gi->type & GD_TYPE_TEXTINPUT))
+    last_gi = NULL;
+
+  /* modify event position values even if no gadget is pressed */
+  if (button == 0 && !release_event)
+    gi = new_gi;
+
+  if (gi)
+  {
+    int last_x = gi->event.x;
+    int last_y = gi->event.y;
+
+    gi->event.x = mx - gi->x;
+    gi->event.y = my - gi->y;
+
+    if (gi->type == GD_TYPE_DRAWING_AREA)
+    {
+      gi->event.x /= gi->drawing.item_xsize;
+      gi->event.y /= gi->drawing.item_ysize;
+
+      if (last_x != gi->event.x || last_y != gi->event.y)
+       changed_position = TRUE;
+    }
+  }
+
+  /* handle gadget popup info text */
+  if (last_info_gi != new_gi ||
+      (new_gi && new_gi->type == GD_TYPE_DRAWING_AREA && changed_position))
+  {
+    last_info_gi = new_gi;
+
+    if (new_gi != NULL && (button == 0 || new_gi == last_gi))
+    {
+      new_gi->event.type = 0;
+      new_gi->callback_info(new_gi);
+    }
+    else
+      default_callback_info(NULL);
+  }
+
+  if (gadget_pressed)
+  {
+    if (gi->type == GD_TYPE_CHECK_BUTTON)
+    {
+      gi->checked = !gi->checked;
+    }
+    else if (gi->type == GD_TYPE_RADIO_BUTTON)
+    {
+      struct GadgetInfo *rgi = gadget_list_first_entry;
+
+      while (rgi)
+      {
+       if (rgi->mapped &&
+           rgi->type == GD_TYPE_RADIO_BUTTON &&
+           rgi->radio_nr == gi->radio_nr &&
+           rgi != gi)
+       {
+         rgi->checked = FALSE;
+         DrawGadget(rgi, DG_UNPRESSED, DG_DIRECT);
+       }
+
+       rgi = rgi->next;
+      }
+
+      gi->checked = TRUE;
+    }
+    else if (gi->type & GD_TYPE_SCROLLBAR)
+    {
+      int mpos, gpos;
+
+      if (gi->type == GD_TYPE_SCROLLBAR_HORIZONTAL)
+      {
+       mpos = mx;
+       gpos = gi->x;
+      }
+      else
+      {
+       mpos = my;
+       gpos = gi->y;
+      }
+
+      if (mpos >= gpos + gi->scrollbar.position &&
+         mpos < gpos + gi->scrollbar.position + gi->scrollbar.size)
+      {
+       /* drag scrollbar */
+       gi->scrollbar.drag_position =
+         scrollbar_mouse_pos - gi->scrollbar.position;
+      }
+      else
+      {
+       /* click scrollbar one scrollbar length up/left or down/right */
+
+       struct GadgetScrollbar *gs = &gi->scrollbar;
+       int old_item_position = gs->item_position;
+
+       changed_position = FALSE;
+
+       gs->item_position +=
+         gs->items_visible * (mpos < gpos + gi->scrollbar.position ? -1 : +1);
+
+       if (gs->item_position < 0)
+         gs->item_position = 0;
+       if (gs->item_position > gs->items_max - gs->items_visible)
+         gs->item_position = gs->items_max - gs->items_visible;
+
+       if (old_item_position != gs->item_position)
+       {
+         gi->event.item_position = gs->item_position;
+         changed_position = TRUE;
+       }
+
+       ModifyGadget(gi, GDI_SCROLLBAR_ITEM_POSITION, gs->item_position,
+                    GDI_END);
+
+       gi->state = GD_BUTTON_UNPRESSED;
+       gi->event.type = GD_EVENT_MOVING;
+       gi->event.off_borders = FALSE;
+
+       if (gi->event_mask & GD_EVENT_MOVING && changed_position)
+         gi->callback_action(gi);
+
+       /* don't handle this scrollbar anymore while mouse button pressed */
+       last_gi = NULL;
+
+       return;
+      }
+    }
+
+    DrawGadget(gi, DG_PRESSED, DG_DIRECT);
+
+    gi->state = GD_BUTTON_PRESSED;
+    gi->event.type = GD_EVENT_PRESSED;
+    gi->event.button = button;
+    gi->event.off_borders = FALSE;
+
+    /* initialize delay counter */
+    DelayReached(&pressed_delay, 0);
+
+    if (gi->event_mask & GD_EVENT_PRESSED)
+      gi->callback_action(gi);
+  }
+
+  if (gadget_pressed_repeated)
+  {
+    gi->event.type = GD_EVENT_PRESSED;
+
+    if (gi->event_mask & GD_EVENT_REPEATED &&
+       DelayReached(&pressed_delay, GADGET_FRAME_DELAY))
+      gi->callback_action(gi);
+  }
+
+  if (gadget_moving)
+  {
+    if (gi->type & GD_TYPE_BUTTON)
+    {
+      if (gadget_moving_inside && gi->state == GD_BUTTON_UNPRESSED)
+       DrawGadget(gi, DG_PRESSED, DG_DIRECT);
+      else if (gadget_moving_off_borders && gi->state == GD_BUTTON_PRESSED)
+       DrawGadget(gi, DG_UNPRESSED, DG_DIRECT);
+    }
+
+    if (gi->type & GD_TYPE_SCROLLBAR)
+    {
+      struct GadgetScrollbar *gs = &gi->scrollbar;
+      int old_item_position = gs->item_position;
+
+      gs->position = scrollbar_mouse_pos - gs->drag_position;
+
+      if (gs->position < 0)
+       gs->position = 0;
+      if (gs->position > gs->position_max)
+       gs->position = gs->position_max;
+
+      gs->item_position =
+       gs->items_max * (gs->position + gs->correction) / gs->size_max;
+
+      if (gs->item_position < 0)
+       gs->item_position = 0;
+      if (gs->item_position > gs->items_max - 1)
+       gs->item_position = gs->items_max - 1;
+
+      if (old_item_position != gs->item_position)
+      {
+       gi->event.item_position = gs->item_position;
+       changed_position = TRUE;
+      }
+
+      DrawGadget(gi, DG_PRESSED, DG_DIRECT);
+    }
+
+    gi->state = (gadget_moving_inside || gi->type & GD_TYPE_SCROLLBAR ?
+                GD_BUTTON_PRESSED : GD_BUTTON_UNPRESSED);
+    gi->event.type = GD_EVENT_MOVING;
+    gi->event.off_borders = gadget_moving_off_borders;
+
+    if (gi->event_mask & GD_EVENT_MOVING && changed_position &&
+       (gadget_moving_inside || gi->event_mask & GD_EVENT_OFF_BORDERS))
+      gi->callback_action(gi);
+  }
+
+  if (gadget_released_inside)
+  {
+    if (!(gi->type & GD_TYPE_TEXTINPUT))
+      DrawGadget(gi, DG_UNPRESSED, DG_DIRECT);
+
+    gi->state = GD_BUTTON_UNPRESSED;
+    gi->event.type = GD_EVENT_RELEASED;
+
+    if (gi->event_mask & GD_EVENT_RELEASED)
+      gi->callback_action(gi);
+  }
+
+  if (gadget_released_off_borders)
+  {
+    if (gi->type & GD_TYPE_SCROLLBAR)
+      DrawGadget(gi, DG_UNPRESSED, DG_DIRECT);
+
+    gi->event.type = GD_EVENT_RELEASED;
+
+    if (gi->event_mask & GD_EVENT_RELEASED &&
+       gi->event_mask & GD_EVENT_OFF_BORDERS)
+      gi->callback_action(gi);
+  }
+}
+
+void HandleGadgetsKeyInput(Key key)
+{
+  struct GadgetInfo *gi = last_gi;
+  char text[MAX_GADGET_TEXTSIZE];
+  int text_length;
+  int cursor_pos;
+  char letter;
+  boolean legal_letter;
+
+  if (gi == NULL || !(gi->type & GD_TYPE_TEXTINPUT) || !gi->mapped)
+    return;
+
+  text_length = strlen(gi->text.value);
+  cursor_pos = gi->text.cursor_position;
+  letter = getCharFromKey(key);
+  legal_letter = (gi->type == GD_TYPE_TEXTINPUT_NUMERIC ?
+                 letter >= '0' && letter <= '9' :
+                 letter != 0);
+
+  if (legal_letter && text_length < gi->text.size)
+  {
+    strcpy(text, gi->text.value);
+    strcpy(&gi->text.value[cursor_pos + 1], &text[cursor_pos]);
+    gi->text.value[cursor_pos] = letter;
+    gi->text.cursor_position++;
+    DrawGadget(gi, DG_PRESSED, DG_DIRECT);
+  }
+  else if (key == KSYM_Left && cursor_pos > 0)
+  {
+    gi->text.cursor_position--;
+    DrawGadget(gi, DG_PRESSED, DG_DIRECT);
+  }
+  else if (key == KSYM_Right && cursor_pos < text_length)
+  {
+    gi->text.cursor_position++;
+    DrawGadget(gi, DG_PRESSED, DG_DIRECT);
+  }
+  else if (key == KSYM_BackSpace && cursor_pos > 0)
+  {
+    strcpy(text, gi->text.value);
+    strcpy(&gi->text.value[cursor_pos - 1], &text[cursor_pos]);
+    gi->text.cursor_position--;
+    DrawGadget(gi, DG_PRESSED, DG_DIRECT);
+  }
+  else if (key == KSYM_Delete && cursor_pos < text_length)
+  {
+    strcpy(text, gi->text.value);
+    strcpy(&gi->text.value[cursor_pos], &text[cursor_pos + 1]);
+    DrawGadget(gi, DG_PRESSED, DG_DIRECT);
+  }
+  else if (key == KSYM_Return)
+  {
+    CheckRangeOfNumericInputGadget(gi);
+    DrawGadget(gi, DG_UNPRESSED, DG_DIRECT);
+
+    gi->event.type = GD_EVENT_TEXT_RETURN;
+
+    if (gi->event_mask & GD_EVENT_TEXT_RETURN)
+      gi->callback_action(gi);
+
+    last_gi = NULL;
+  }
+}
diff --git a/src/libgame/gadgets.h b/src/libgame/gadgets.h
new file mode 100644 (file)
index 0000000..faa7c9d
--- /dev/null
@@ -0,0 +1,201 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* gadgets.h                                                *
+***********************************************************/
+
+#ifndef GADGETS_H
+#define GADGETS_H
+
+#include "system.h"
+
+
+#define GADGET_FRAME_DELAY     150     /* delay between gadget actions */
+
+/* gadget types */
+#define GD_TYPE_NORMAL_BUTTON          (1 << 0)
+#define GD_TYPE_CHECK_BUTTON           (1 << 1)
+#define GD_TYPE_RADIO_BUTTON           (1 << 2)
+#define GD_TYPE_DRAWING_AREA           (1 << 3)
+#define GD_TYPE_TEXTINPUT_ALPHANUMERIC (1 << 4)
+#define GD_TYPE_TEXTINPUT_NUMERIC      (1 << 5)
+#define GD_TYPE_SCROLLBAR_VERTICAL     (1 << 6)
+#define GD_TYPE_SCROLLBAR_HORIZONTAL   (1 << 7)
+
+#define GD_TYPE_BUTTON                 (GD_TYPE_NORMAL_BUTTON | \
+                                        GD_TYPE_CHECK_BUTTON | \
+                                        GD_TYPE_RADIO_BUTTON)
+#define GD_TYPE_SCROLLBAR              (GD_TYPE_SCROLLBAR_VERTICAL | \
+                                        GD_TYPE_SCROLLBAR_HORIZONTAL)
+#define GD_TYPE_TEXTINPUT              (GD_TYPE_TEXTINPUT_ALPHANUMERIC | \
+                                        GD_TYPE_TEXTINPUT_NUMERIC)
+
+/* gadget events */
+#define GD_EVENT_PRESSED               (1 << 0)
+#define GD_EVENT_RELEASED              (1 << 1)
+#define GD_EVENT_MOVING                        (1 << 2)
+#define GD_EVENT_REPEATED              (1 << 3)
+#define GD_EVENT_OFF_BORDERS           (1 << 4)
+#define GD_EVENT_TEXT_RETURN           (1 << 5)
+#define GD_EVENT_TEXT_LEAVING          (1 << 6)
+
+/* gadget button states */
+#define GD_BUTTON_UNPRESSED            0
+#define GD_BUTTON_PRESSED              1
+
+/* gadget structure constants */
+#define MAX_GADGET_TEXTSIZE            1024
+#define MAX_INFO_TEXTSIZE              1024
+
+/* gadget creation tags */
+#define GDI_END                                0
+#define GDI_CUSTOM_ID                  1
+#define GDI_CUSTOM_TYPE_ID             2
+#define GDI_X                          3
+#define GDI_Y                          4
+#define GDI_WIDTH                      5
+#define GDI_HEIGHT                     6
+#define GDI_TYPE                       7
+#define GDI_STATE                      8
+#define GDI_CHECKED                    9
+#define GDI_RADIO_NR                   10
+#define GDI_NUMBER_VALUE               11
+#define GDI_NUMBER_MIN                 12
+#define GDI_NUMBER_MAX                 13
+#define GDI_TEXT_VALUE                 14
+#define GDI_TEXT_SIZE                  15
+#define GDI_TEXT_FONT                  16
+#define GDI_DESIGN_UNPRESSED           17
+#define GDI_DESIGN_PRESSED             18
+#define GDI_ALT_DESIGN_UNPRESSED       19
+#define GDI_ALT_DESIGN_PRESSED         20
+#define GDI_BORDER_SIZE                        21
+#define GDI_TEXTINPUT_DESIGN_WIDTH     22
+#define GDI_DECORATION_DESIGN          23
+#define GDI_DECORATION_POSITION                24
+#define GDI_DECORATION_SIZE            25
+#define GDI_DECORATION_SHIFTING                26
+#define GDI_EVENT_MASK                 27
+#define GDI_EVENT                      28
+#define GDI_CALLBACK_INFO              29
+#define GDI_CALLBACK_ACTION            30
+#define GDI_AREA_SIZE                  31
+#define GDI_ITEM_SIZE                  32
+#define GDI_SCROLLBAR_ITEMS_MAX                33
+#define GDI_SCROLLBAR_ITEMS_VISIBLE    34
+#define GDI_SCROLLBAR_ITEM_POSITION    35
+#define GDI_INFO_TEXT                  36
+
+typedef void (*gadget_function)(void *);
+
+struct GadgetBorder
+{
+  int size;                            /* size of gadget border */
+  int width;                           /* for text input gadgets */
+};
+
+struct GadgetDesign
+{
+  Bitmap *bitmap;                      /* Bitmap with gadget surface */
+  int x, y;                            /* position of rectangle in Bitmap */
+};
+
+struct GadgetDecoration
+{
+  struct GadgetDesign design;          /* decoration design structure */
+  int x, y;                            /* position of deco on the gadget */
+  int width, height;                   /* width and height of decoration */
+  int xshift, yshift;                  /* deco shifting when gadget pressed */
+};
+
+struct GadgetEvent
+{
+  unsigned long type;                  /* event type */
+  int button;                          /* button number for button events */
+  int x, y;                            /* gadget position at event time */
+  boolean off_borders;                 /* mouse pointer outside gadget? */
+  int item_x, item_y, item_position;   /* new item position */
+};
+
+struct GadgetDrawingArea
+{
+  int area_xsize, area_ysize;          /* size of drawing area (in items) */
+  int item_xsize, item_ysize;          /* size of each item in drawing area */
+};
+
+struct GadgetTextInput
+{
+  char value[MAX_GADGET_TEXTSIZE];     /* text string in input field */
+  int number_value;                    /* integer value, if numeric */
+  int number_min;                      /* minimal allowed numeric value */
+  int number_max;                      /* maximal allowed numeric value */
+  int size;                            /* maximal size of input text */
+  int cursor_position;                 /* actual cursor position */
+  int font_type;                       /* font to use for text input */
+};
+
+struct GadgetScrollbar
+{
+  int items_max;                       /* number of items to access */
+  int items_visible;                   /* number of visible items */
+  int item_position;                   /* actual item position */
+  int size_max;                                /* this is either width or height */
+  int size;                            /* scrollbar size on screen */
+  int position;                                /* scrollbar position on screen */
+  int position_max;                    /* bottom/right scrollbar position */
+  int drag_position;                   /* drag position on scrollbar */
+  int correction;                      /* scrollbar position correction */
+};
+
+struct GadgetInfo
+{
+  int id;                              /* internal gadget identifier */
+  int custom_id;                       /* custom gadget identifier */
+  int custom_type_id;                  /* custom gadget type identifier */
+  char info_text[MAX_INFO_TEXTSIZE];   /* short popup info text */
+  int x, y;                            /* gadget position */
+  int width, height;                   /* gadget size */
+  unsigned long type;                  /* type (button, text input, ...) */
+  unsigned long state;                 /* state (pressed, released, ...) */
+  boolean checked;                     /* check/radio button state */
+  int radio_nr;                                /* number of radio button series */
+  boolean mapped;                      /* gadget is active */
+  struct GadgetBorder border;          /* gadget border design */
+  struct GadgetDesign design[2];       /* 0: normal; 1: pressed */
+  struct GadgetDesign alt_design[2];   /* alternative design */
+  struct GadgetDecoration deco;                /* decoration on top of gadget */
+  unsigned long event_mask;            /* possible events for this gadget */
+  struct GadgetEvent event;            /* actual gadget event */
+  gadget_function callback_info;       /* function for pop-up info text */
+  gadget_function callback_action;     /* function for gadget action */
+  struct GadgetDrawingArea drawing;    /* fields for drawing area gadget */
+  struct GadgetTextInput text;         /* fields for text input gadget */
+  struct GadgetScrollbar scrollbar;    /* fields for scrollbar gadget */
+  struct GadgetInfo *next;             /* next list entry */
+};
+
+struct GadgetInfo *CreateGadget(int, ...);
+void FreeGadget(struct GadgetInfo *);
+
+void ModifyGadget(struct GadgetInfo *, int, ...);
+void RedrawGadget(struct GadgetInfo *);
+
+void MapGadget(struct GadgetInfo *);
+void UnmapGadget(struct GadgetInfo *);
+void UnmapAllGadgets();
+void RemapAllGadgets();
+
+boolean anyTextGadgetActive();
+void ClickOnGadget(struct GadgetInfo *, int);
+
+void HandleGadgets(int, int, int);
+void HandleGadgetsKeyInput(Key);
+
+#endif /* GADGETS_H */
diff --git a/src/libgame/image.c b/src/libgame/image.c
new file mode 100644 (file)
index 0000000..d4fa1d8
--- /dev/null
@@ -0,0 +1,555 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* image.c                                                  *
+***********************************************************/
+
+#include "image.h"
+#include "pcx.h"
+#include "misc.h"
+
+
+#if defined(TARGET_X11)
+
+/* for MS-DOS/Allegro, exclude all except newImage() and freeImage() */
+
+Image *newImage(unsigned int width, unsigned int height, unsigned int depth)
+{
+  Image *image;
+  const unsigned int bytes_per_pixel = 1;
+  int i;
+
+  if (depth > 8)
+    Error(ERR_EXIT, "images with more than 256 colors are not supported");
+
+  depth = 8;
+  image = checked_malloc(sizeof(Image));
+  image->data = checked_malloc(width * height * bytes_per_pixel);
+  image->width = width;
+  image->height = height;
+  image->depth = depth;
+  image->rgb.used = 0;
+  for (i=0; i<MAX_COLORS; i++)
+    image->rgb.color_used[i] = FALSE;
+
+  return image;
+}
+
+void freeImage(Image *image)
+{
+  free(image->data);
+  free(image);
+}
+
+#if defined(PLATFORM_UNIX)
+
+/* extra colors to try allocating in private color maps to minimize flashing */
+#define NOFLASH_COLORS 256
+
+/* architecture independent value-to-memory conversion
+   note: the internal format is big endian */
+
+#define value_to_memory(value, ptr, length) (                          \
+(length) == 1 ? (*( (byte *)(ptr)   ) = ( value     ) ) :              \
+(length) == 2 ? (*( (byte *)(ptr)   ) = (((unsigned long)(value))>> 8),        \
+                *(((byte *)(ptr))+1) = ( value     ) ) :               \
+(length) == 3 ? (*( (byte *)(ptr)   ) = (((unsigned long)(value))>>16),        \
+                *(((byte *)(ptr))+1) = (((unsigned long)(value))>> 8), \
+                *(((byte *)(ptr))+2) = ( value     ) ) :               \
+                (*( (byte *)(ptr)   ) = (((unsigned long)(value))>>24),        \
+                *(((byte *)(ptr))+1) = (((unsigned long)(value))>>16), \
+                *(((byte *)(ptr))+2) = (((unsigned long)(value))>> 8), \
+                *(((byte *)(ptr))+3) = ( value     ) ))
+
+static Pixmap Image_to_Mask(Image *image, Display *display, Window window)
+{
+  byte *src_ptr, *dst_ptr, *dst_ptr2;
+  unsigned int bytes_per_row;
+  unsigned int x, y;
+  byte bitmask;
+  byte *mask_data;
+  Pixmap mask_pixmap;
+
+  bytes_per_row = (image->width + 7) / 8;
+  mask_data = checked_calloc(bytes_per_row * image->height);
+
+  src_ptr = image->data;
+  dst_ptr = mask_data;
+
+  /* create bitmap data which can be used by 'XCreateBitmapFromData()'
+   * directly to create a pixmap of depth 1 for use as a clip mask for
+   * the corresponding image pixmap
+   */
+
+  for (y=0; y<image->height; y++)
+  {
+    bitmask = 0x01;            /* start with leftmost bit in the byte     */
+    dst_ptr2 = dst_ptr;                /* start with leftmost byte in the row     */
+
+    for (x=0; x<image->width; x++)
+    {
+      if (*src_ptr++)          /* source pixel solid? (pixel index != 0)  */
+       *dst_ptr2 |= bitmask;   /* then write a bit into the image mask    */
+
+      if ((bitmask <<= 1) == 0)        /* bit at rightmost byte position reached? */
+      {
+       bitmask = 0x01;         /* start again with leftmost bit position  */
+       dst_ptr2++;             /* continue with next byte in image mask   */
+      }
+    }
+
+    dst_ptr += bytes_per_row;  /* continue with leftmost byte of next row */
+  }
+
+  mask_pixmap = XCreateBitmapFromData(display, window, (char *)mask_data,
+                                     image->width, image->height);
+  free(mask_data);
+
+  return mask_pixmap;
+}
+
+static int bitsPerPixelAtDepth(Display *display, int screen, int depth)
+{
+  XPixmapFormatValues *pixmap_format;
+  int i, num_pixmap_formats, bits_per_pixel = -1;
+
+  /* get Pixmap formats supported by the X server */
+  pixmap_format = XListPixmapFormats(display, &num_pixmap_formats);
+
+  /* find format that matches the given depth */
+  for (i=0; i<num_pixmap_formats; i++)
+    if (pixmap_format[i].depth == depth)
+      bits_per_pixel = pixmap_format[i].bits_per_pixel;
+
+  XFree(pixmap_format);
+
+  if (bits_per_pixel == -1)
+    Error(ERR_EXIT, "cannot find pixmap format for depth %d", depth);
+
+  return bits_per_pixel;
+}
+
+XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual,
+                           Window window, GC gc, int depth, Image *image)
+{
+  static XColor xcolor_private[NOFLASH_COLORS];
+  static int colorcell_used[NOFLASH_COLORS];
+  static Colormap global_cmap = 0;
+  static Pixel *global_cmap_index;
+  static int num_cmap_entries, free_cmap_entries;
+  static boolean private_cmap = FALSE;
+  Pixel *redvalue, *greenvalue, *bluevalue;
+  unsigned int a, c = 0, x, y, bytes_per_pixel, bits_per_pixel;
+  XColor xcolor;
+  XImage *ximage;
+  XImageInfo *ximageinfo;
+  byte *src_ptr, *dst_ptr;
+
+  if (!global_cmap)
+  {
+    if (visual == DefaultVisual(display, screen))
+      global_cmap = DefaultColormap(display, screen);
+    else
+    {
+      global_cmap = XCreateColormap(display, RootWindow(display, screen),
+                                   visual, AllocNone);
+      private_cmap = TRUE;
+    }
+  }
+
+  xcolor.flags = DoRed | DoGreen | DoBlue;
+  redvalue = greenvalue = bluevalue = NULL;
+  ximageinfo = checked_malloc(sizeof(XImageInfo));
+  ximageinfo->display = display;
+  ximageinfo->depth = depth;
+
+  switch (visual->class)
+  {
+    case TrueColor:
+    case DirectColor:
+    {
+      Pixel pixval;
+      unsigned int redcolors, greencolors, bluecolors;
+      unsigned int redstep, greenstep, bluestep;
+      unsigned int redbottom, greenbottom, bluebottom;
+      unsigned int redtop, greentop, bluetop;
+
+      redvalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
+      greenvalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
+      bluevalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
+
+      ximageinfo->cmap = global_cmap;
+
+      retry_direct: /* tag we hit if a DirectColor allocation fails on
+                    * default colormap */
+
+      /* calculate number of distinct colors in each band */
+
+      redcolors = greencolors = bluecolors = 1;
+      for (pixval=1; pixval; pixval <<= 1)
+      {
+       if (pixval & visual->red_mask)
+         redcolors <<= 1;
+       if (pixval & visual->green_mask)
+         greencolors <<= 1;
+       if (pixval & visual->blue_mask)
+         bluecolors <<= 1;
+      }
+      
+      /* consistency check */
+      if (redcolors > visual->map_entries ||
+         greencolors > visual->map_entries ||
+         bluecolors > visual->map_entries)
+       Error(ERR_WARN, "inconsistency in color information");
+
+      redstep = 256 / redcolors;
+      greenstep = 256 / greencolors;
+      bluestep = 256 / bluecolors;
+      redbottom = greenbottom = bluebottom = 0;
+      redtop = greentop = bluetop = 0;
+      for (a=0; a<visual->map_entries; a++)
+      {
+       if (redbottom < 256)
+         redtop = redbottom + redstep;
+       if (greenbottom < 256)
+         greentop = greenbottom + greenstep;
+       if (bluebottom < 256)
+         bluetop = bluebottom + bluestep;
+
+       xcolor.red = (redtop - 1) << 8;
+       xcolor.green = (greentop - 1) << 8;
+       xcolor.blue = (bluetop - 1) << 8;
+       if (!XAllocColor(display, ximageinfo->cmap, &xcolor))
+       {
+         /* if an allocation fails for a DirectColor default visual then
+            we should create a private colormap and try again. */
+
+         if ((visual->class == DirectColor) &&
+             (visual == DefaultVisual(display, screen)))
+         {
+           global_cmap = XCopyColormapAndFree(display, global_cmap);
+           ximageinfo->cmap = global_cmap;
+           private_cmap = TRUE;
+
+           goto retry_direct;
+         }
+
+         /* something completely unexpected happened */
+
+         fprintf(stderr, "imageToXImage: XAllocColor failed on a TrueColor/Directcolor visual\n");
+          free(redvalue);
+          free(greenvalue);
+          free(bluevalue);
+          free(ximageinfo);
+         return NULL;
+       }
+
+       /* fill in pixel values for each band at this intensity */
+
+       while ((redbottom < 256) && (redbottom < redtop))
+         redvalue[redbottom++] = xcolor.pixel & visual->red_mask;
+       while ((greenbottom < 256) && (greenbottom < greentop))
+         greenvalue[greenbottom++] = xcolor.pixel & visual->green_mask;
+       while ((bluebottom < 256) && (bluebottom < bluetop))
+         bluevalue[bluebottom++] = xcolor.pixel & visual->blue_mask;
+      }
+      break;
+    }
+
+    case PseudoColor:
+
+      ximageinfo->cmap = global_cmap;
+
+      for (a=0; a<MAX_COLORS; a++)
+      {
+       XColor xcolor2;
+       unsigned short mask;
+       int color_found;
+       int i;
+
+       if (!image->rgb.color_used[a])
+         continue;
+
+       xcolor.red = *(image->rgb.red + a);
+       xcolor.green = *(image->rgb.green + a);
+       xcolor.blue = *(image->rgb.blue + a);
+  
+       /* look if this color already exists in our colormap */
+       if (!XAllocColor(display, ximageinfo->cmap, &xcolor))
+       {
+         if (!private_cmap)
+         {
+           if (options.verbose)
+             Error(ERR_RETURN, "switching to private colormap");
+
+           /* we just filled up the default colormap -- get a private one
+              which contains all already allocated colors */
+
+           global_cmap = XCopyColormapAndFree(display, global_cmap);
+           ximageinfo->cmap = global_cmap;
+           private_cmap = TRUE;
+
+           /* allocate the rest of the color cells read/write */
+           global_cmap_index =
+             (Pixel *)checked_malloc(sizeof(Pixel) * NOFLASH_COLORS);
+           for (i=0; i<NOFLASH_COLORS; i++)
+             if (!XAllocColorCells(display, global_cmap, FALSE, NULL, 0,
+                                   global_cmap_index + i, 1))
+               break;
+           num_cmap_entries = free_cmap_entries = i;
+
+           /*
+           printf("We've got %d free colormap entries.\n", free_cmap_entries);
+           */
+
+           /* to minimize colormap flashing, copy default colors and try
+              to keep them as near as possible to the old values */
+
+           for(i=0; i<num_cmap_entries; i++)
+           {
+             xcolor2.pixel = *(global_cmap_index + i);
+             XQueryColor(display, DefaultColormap(display, screen), &xcolor2);
+             XStoreColor(display, global_cmap, &xcolor2);
+             xcolor_private[xcolor2.pixel] = xcolor2;
+             colorcell_used[xcolor2.pixel] = FALSE;
+           }
+
+           /* now we have the default colormap private: all colors we
+              successfully allocated so far are read-only, which is okay,
+              because we don't want to change them anymore -- if we need
+              an existing color again, we get it by XAllocColor; all other
+              colors are read/write and we can set them by XStoreColor,
+              but we will try to overwrite those color cells with our new
+              color which are as close as possible to our new color */
+         }
+
+         /* look for an existing default color close the one we want */
+
+         mask = 0xf000;
+         color_found = FALSE;
+
+         while (!color_found)
+         {
+           for (i=num_cmap_entries-1; i>=0; i--)
+           {
+             xcolor2.pixel = *(global_cmap_index + i);
+             xcolor2 = xcolor_private[xcolor2.pixel];
+
+             if (colorcell_used[xcolor2.pixel])
+               continue;
+
+             if ((xcolor.red & mask) == (xcolor2.red & mask) &&
+                 (xcolor.green & mask) == (xcolor2.green & mask) &&
+                 (xcolor.blue & mask) == (xcolor2.blue & mask))
+             {
+               /*
+               printf("replacing color cell %ld with a close color\n",
+                      xcolor2.pixel);
+                      */
+               color_found = TRUE;
+               break;
+             }
+           }
+
+           if (mask == 0x0000)
+             break;
+
+           mask = (mask << 1) & 0xffff;
+         }
+
+         if (!color_found)             /* no more free color cells */
+           Error(ERR_EXIT, "cannot allocate enough color cells");
+
+         xcolor.pixel = xcolor2.pixel;
+         xcolor_private[xcolor.pixel] = xcolor;
+         colorcell_used[xcolor.pixel] = TRUE;
+         XStoreColor(display, ximageinfo->cmap, &xcolor);
+         free_cmap_entries--;
+       }
+
+       *(ximageinfo->index + a) = xcolor.pixel;
+      }
+
+      /*
+      printf("still %d free colormap entries\n", free_cmap_entries);
+      */
+
+      ximageinfo->no = a;      /* number of pixels allocated for this image */
+      break;
+  
+    default:
+      Error(ERR_RETURN, "display class not supported");
+      Error(ERR_EXIT, "DirectColor, TrueColor or PseudoColor display needed");
+      break;
+  }
+
+#if DEBUG_TIMING
+  debug_print_timestamp(2, "   ALLOCATING IMAGE COLORS:   ");
+#endif
+
+  /* create XImage from internal image structure and convert it to Pixmap */
+
+  bits_per_pixel = bitsPerPixelAtDepth(display, screen, depth);
+  bytes_per_pixel = (bits_per_pixel + 7) / 8;
+
+  ximage = XCreateImage(display, visual, depth, ZPixmap, 0,
+                       NULL, image->width, image->height,
+                       8, image->width * bytes_per_pixel);
+  ximage->data =
+    checked_malloc(image->width * image->height * bytes_per_pixel);
+  ximage->byte_order = MSBFirst;
+
+  src_ptr = image->data;
+  dst_ptr = (byte *)ximage->data;
+
+  switch (visual->class)
+  {
+    case DirectColor:
+    case TrueColor:
+    {
+      Pixel pixval;
+
+      for (y=0; y<image->height; y++)          /* general case */
+      {
+       for (x=0; x<image->width; x++)
+       {
+         pixval = *src_ptr++;
+         pixval =
+           redvalue[image->rgb.red[pixval] >> 8] |
+           greenvalue[image->rgb.green[pixval] >> 8] |
+           bluevalue[image->rgb.blue[pixval] >> 8];
+         value_to_memory(pixval, dst_ptr, bytes_per_pixel);
+         dst_ptr += bytes_per_pixel;
+       }
+      }
+      break;
+    }
+
+    case PseudoColor:
+    {
+      if (bytes_per_pixel == 1)                        /* (common) special case */
+      {
+       for (y=0; y<image->height; y++)
+         for (x=0; x<image->width; x++)
+           *dst_ptr++ = ximageinfo->index[c + *src_ptr++];
+      }
+      else                                     /* general case */
+      {
+       for (y=0; y<image->height; y++)
+       {
+         for (x=0; x<image->width; x++)
+         {
+           value_to_memory(ximageinfo->index[c + *src_ptr++],
+                           dst_ptr, bytes_per_pixel);
+           dst_ptr += bytes_per_pixel;
+         }
+       }
+      }
+      break;
+    }
+
+    default:
+      Error(ERR_RETURN, "display class not supported");
+      Error(ERR_EXIT, "DirectColor, TrueColor or PseudoColor display needed");
+      break;
+  }
+
+  if (redvalue)
+  {
+    free((byte *)redvalue);
+    free((byte *)greenvalue);
+    free((byte *)bluevalue);
+  }
+
+#if DEBUG_TIMING
+  debug_print_timestamp(2, "   CONVERTING IMAGE TO XIMAGE:");
+#endif
+
+  ximageinfo->pixmap = XCreatePixmap(display, window,
+                                    ximage->width, ximage->height,
+                                    ximageinfo->depth);
+
+  XPutImage(ximageinfo->display, ximageinfo->pixmap, gc,
+           ximage, 0, 0, 0, 0, ximage->width, ximage->height);
+
+  free(ximage->data);
+  ximage->data = NULL;
+  XDestroyImage(ximage);
+
+  return(ximageinfo);
+}
+
+void freeXImage(Image *image, XImageInfo *ximageinfo)
+{
+  if (ximageinfo->index != NULL && ximageinfo->no > 0)
+    XFreeColors(ximageinfo->display, ximageinfo->cmap, ximageinfo->index,
+               ximageinfo->no, 0);
+  /* this       ^^^^^^^^^^^^^^ is wrong, because the used color cells
+   * are somewhere between 0 and MAX_COLORS; there are indeed 'ximageinfo->no'
+   * used color cells, but they are not at array position 0 - 'ximageinfo->no'
+   */
+
+  free(ximageinfo);
+}
+
+int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename,
+                      Pixmap *pixmap, Pixmap *pixmap_mask)
+{
+  Image *image;
+  XImageInfo *ximageinfo;
+  int screen;
+  Visual *visual;
+  int depth;
+
+#if DEBUG_TIMING
+  debug_print_timestamp(2, NULL);      /* initialize timestamp function */
+#endif
+
+  /* read the graphic file in PCX format to image structure */
+  if ((image = Read_PCX_to_Image(filename)) == NULL)
+    return errno_pcx;
+
+#if DEBUG_TIMING
+  printf("%s:\n", filename);
+  debug_print_timestamp(2, "   READING PCX FILE TO IMAGE: ");
+#endif
+
+  screen = DefaultScreen(display);
+  visual = DefaultVisual(display, screen);
+  depth = DefaultDepth(display, screen);
+
+  /* convert image structure to X11 Pixmap */
+  if (!(ximageinfo = Image_to_Pixmap(display, screen, visual,
+                                    window, gc, depth, image)))
+    Error(ERR_EXIT, "cannot convert Image to Pixmap");
+
+  /* if a private colormap has been created, install it */
+  if (ximageinfo->cmap != DefaultColormap(display, screen))
+    XSetWindowColormap(display, window, ximageinfo->cmap);
+
+#if DEBUG_TIMING
+  debug_print_timestamp(2, "   CONVERTING IMAGE TO PIXMAP:");
+#endif
+
+  /* create clip mask for the image */
+  ximageinfo->pixmap_mask = Image_to_Mask(image, display, window);
+
+#if DEBUG_TIMING
+  debug_print_timestamp(2, "   CONVERTING IMAGE TO MASK:  ");
+#endif
+
+  *pixmap = ximageinfo->pixmap;
+  *pixmap_mask = ximageinfo->pixmap_mask;
+
+  return PCX_Success;
+}
+
+#endif /* PLATFORM_UNIX */
+#endif /* TARGET_X11 */
diff --git a/src/libgame/image.h b/src/libgame/image.h
new file mode 100644 (file)
index 0000000..e6259f5
--- /dev/null
@@ -0,0 +1,62 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* image.h                                                  *
+***********************************************************/
+
+#ifndef IMAGE_H
+#define IMAGE_H
+
+#include "system.h"
+
+
+#if defined(TARGET_X11)
+
+#define MAX_COLORS     256     /* maximal number of colors for each image */
+
+typedef unsigned short Intensity;      /* RGB intensity for X11 */
+
+typedef struct
+{
+  Display  *display;           /* destination display             */
+  int       depth;             /* depth of destination drawable   */
+  Pixel     index[MAX_COLORS]; /* array of pixel values           */
+  int       no;                        /* number of pixels in the array   */
+  Colormap  cmap;              /* colormap used for image         */
+  Pixmap   pixmap;             /* final pixmap                    */
+  Pixmap   pixmap_mask;                /* final pixmap of mask            */
+} XImageInfo;
+
+struct RGBMap
+{
+  unsigned int used;                   /* number of colors used in RGB map */
+  Intensity    red[MAX_COLORS];                /* color values in X style          */
+  Intensity    green[MAX_COLORS];
+  Intensity    blue[MAX_COLORS];
+  boolean      color_used[MAX_COLORS]; /* flag if color cell is used       */
+};
+
+typedef struct
+{
+  struct RGBMap rgb;           /* RGB map of image if IRGB type       */
+  unsigned int  width;         /* width of image in pixels            */
+  unsigned int  height;                /* height of image in pixels           */
+  unsigned int  depth;         /* depth of image in bits if IRGB type */
+  byte         *data;          /* image data                          */
+} Image;
+
+Image *newImage(unsigned int, unsigned int, unsigned int);
+void freeImage(Image *);
+void freeXImage(Image *, XImageInfo *);
+int Read_PCX_to_Pixmap(Display *, Window, GC, char *, Pixmap *, Pixmap *);
+
+#endif /* TARGET_X11 */
+
+#endif /* IMAGE_H */
diff --git a/src/libgame/libgame.h b/src/libgame/libgame.h
new file mode 100644 (file)
index 0000000..26cfb69
--- /dev/null
@@ -0,0 +1,30 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* libgame.h                                                *
+***********************************************************/
+
+#ifndef LIBGAME_H
+#define LIBGAME_H
+
+#define LIBGAME_VERSION_1_0_0
+
+#include "platform.h"
+#include "types.h"
+#include "system.h"
+#include "random.h"
+#include "gadgets.h"
+#include "text.h"
+#include "sound.h"
+#include "image.h"
+#include "pcx.h"
+#include "misc.h"
+
+#endif /* LIBGAME_H */
diff --git a/src/libgame/misc.c b/src/libgame/misc.c
new file mode 100644 (file)
index 0000000..5673dce
--- /dev/null
@@ -0,0 +1,1377 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* misc.c                                                   *
+***********************************************************/
+
+#include <time.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "platform.h"
+
+#if !defined(PLATFORM_WIN32)
+#include <pwd.h>
+#include <sys/param.h>
+#endif
+
+#include "misc.h"
+#include "random.h"
+
+
+#if defined(PLATFORM_MSDOS)
+volatile unsigned long counter = 0;
+
+void increment_counter()
+{
+  counter++;
+}
+
+END_OF_FUNCTION(increment_counter);
+#endif
+
+
+/* maximal allowed length of a command line option */
+#define MAX_OPTION_LEN         256
+
+#ifdef TARGET_SDL
+static unsigned long mainCounter(int mode)
+{
+  static unsigned long base_ms = 0;
+  unsigned long current_ms;
+  unsigned long counter_ms;
+
+  current_ms = SDL_GetTicks();
+
+  /* reset base time in case of counter initializing or wrap-around */
+  if (mode == INIT_COUNTER || current_ms < base_ms)
+    base_ms = current_ms;
+
+  counter_ms = current_ms - base_ms;
+
+  return counter_ms;           /* return milliseconds since last init */
+}
+
+#else /* !TARGET_SDL */
+
+#if defined(PLATFORM_UNIX)
+static unsigned long mainCounter(int mode)
+{
+  static struct timeval base_time = { 0, 0 };
+  struct timeval current_time;
+  unsigned long counter_ms;
+
+  gettimeofday(&current_time, NULL);
+
+  /* reset base time in case of counter initializing or wrap-around */
+  if (mode == INIT_COUNTER || current_time.tv_sec < base_time.tv_sec)
+    base_time = current_time;
+
+  counter_ms = (current_time.tv_sec  - base_time.tv_sec)  * 1000
+             + (current_time.tv_usec - base_time.tv_usec) / 1000;
+
+  return counter_ms;           /* return milliseconds since last init */
+}
+#endif /* PLATFORM_UNIX */
+#endif /* !TARGET_SDL */
+
+void InitCounter()             /* set counter back to zero */
+{
+#if !defined(PLATFORM_MSDOS)
+  mainCounter(INIT_COUNTER);
+#else
+  LOCK_VARIABLE(counter);
+  LOCK_FUNCTION(increment_counter);
+  install_int_ex(increment_counter, BPS_TO_TIMER(100));
+#endif
+}
+
+unsigned long Counter()        /* get milliseconds since last call of InitCounter() */
+{
+#if !defined(PLATFORM_MSDOS)
+  return mainCounter(READ_COUNTER);
+#else
+  return (counter * 10);
+#endif
+}
+
+static void sleep_milliseconds(unsigned long milliseconds_delay)
+{
+  boolean do_busy_waiting = (milliseconds_delay < 5 ? TRUE : FALSE);
+
+#if defined(PLATFORM_MSDOS)
+  /* don't use select() to perform waiting operations under DOS/Windows
+     environment; always use a busy loop for waiting instead */
+  do_busy_waiting = TRUE;
+#endif
+
+  if (do_busy_waiting)
+  {
+    /* we want to wait only a few ms -- if we assume that we have a
+       kernel timer resolution of 10 ms, we would wait far to long;
+       therefore it's better to do a short interval of busy waiting
+       to get our sleeping time more accurate */
+
+    unsigned long base_counter = Counter(), actual_counter = Counter();
+
+    while (actual_counter < base_counter + milliseconds_delay &&
+          actual_counter >= base_counter)
+      actual_counter = Counter();
+  }
+  else
+  {
+#if defined(TARGET_SDL)
+    SDL_Delay(milliseconds_delay);
+#else
+    struct timeval delay;
+
+    delay.tv_sec  = milliseconds_delay / 1000;
+    delay.tv_usec = 1000 * (milliseconds_delay % 1000);
+
+    if (select(0, NULL, NULL, NULL, &delay) != 0)
+      Error(ERR_WARN, "sleep_milliseconds(): select() failed");
+#endif
+  }
+}
+
+void Delay(unsigned long delay)        /* Sleep specified number of milliseconds */
+{
+  sleep_milliseconds(delay);
+}
+
+boolean FrameReached(unsigned long *frame_counter_var,
+                    unsigned long frame_delay)
+{
+  unsigned long actual_frame_counter = FrameCounter;
+
+  if (actual_frame_counter < *frame_counter_var+frame_delay &&
+      actual_frame_counter >= *frame_counter_var)
+    return(FALSE);
+
+  *frame_counter_var = actual_frame_counter;
+  return(TRUE);
+}
+
+boolean DelayReached(unsigned long *counter_var,
+                    unsigned long delay)
+{
+  unsigned long actual_counter = Counter();
+
+  if (actual_counter < *counter_var + delay &&
+      actual_counter >= *counter_var)
+    return(FALSE);
+
+  *counter_var = actual_counter;
+  return(TRUE);
+}
+
+void WaitUntilDelayReached(unsigned long *counter_var, unsigned long delay)
+{
+  unsigned long actual_counter;
+
+  while(1)
+  {
+    actual_counter = Counter();
+
+    if (actual_counter < *counter_var + delay &&
+       actual_counter >= *counter_var)
+      sleep_milliseconds((*counter_var + delay - actual_counter) / 2);
+    else
+      break;
+  }
+
+  *counter_var = actual_counter;
+}
+
+/* int2str() returns a number converted to a string;
+   the used memory is static, but will be overwritten by later calls,
+   so if you want to save the result, copy it to a private string buffer;
+   there can be 10 local calls of int2str() without buffering the result --
+   the 11th call will then destroy the result from the first call and so on.
+*/
+
+char *int2str(int number, int size)
+{
+  static char shift_array[10][40];
+  static int shift_counter = 0;
+  char *s = shift_array[shift_counter];
+
+  shift_counter = (shift_counter + 1) % 10;
+
+  if (size > 20)
+    size = 20;
+
+  if (size)
+  {
+    sprintf(s, "                    %09d", number);
+    return &s[strlen(s) - size];
+  }
+  else
+  {
+    sprintf(s, "%d", number);
+    return s;
+  }
+}
+
+unsigned int SimpleRND(unsigned int max)
+{
+#if defined(TARGET_SDL)
+  static unsigned long root = 654321;
+  unsigned long current_ms;
+
+  current_ms = SDL_GetTicks();
+  root = root * 4253261 + current_ms;
+  return (root % max);
+#else
+  static unsigned long root = 654321;
+  struct timeval current_time;
+
+  gettimeofday(&current_time, NULL);
+  root = root * 4253261 + current_time.tv_sec + current_time.tv_usec;
+  return (root % max);
+#endif
+}
+
+#ifdef DEBUG
+static unsigned int last_RND_value = 0;
+
+unsigned int last_RND()
+{
+  return last_RND_value;
+}
+#endif
+
+unsigned int RND(unsigned int max)
+{
+#ifdef DEBUG
+  return (last_RND_value = random_linux_libc() % max);
+#else
+  return (random_linux_libc() % max);
+#endif
+}
+
+unsigned int InitRND(long seed)
+{
+#if defined(TARGET_SDL)
+  unsigned long current_ms;
+
+  if (seed == NEW_RANDOMIZE)
+  {
+    current_ms = SDL_GetTicks();
+    srandom_linux_libc((unsigned int) current_ms);
+    return (unsigned int) current_ms;
+  }
+  else
+  {
+    srandom_linux_libc((unsigned int) seed);
+    return (unsigned int) seed;
+  }
+#else
+  struct timeval current_time;
+
+  if (seed == NEW_RANDOMIZE)
+  {
+    gettimeofday(&current_time, NULL);
+    srandom_linux_libc((unsigned int) current_time.tv_usec);
+    return (unsigned int) current_time.tv_usec;
+  }
+  else
+  {
+    srandom_linux_libc((unsigned int) seed);
+    return (unsigned int) seed;
+  }
+#endif
+}
+
+char *getLoginName()
+{
+#if defined(PLATFORM_WIN32)
+  return ANONYMOUS_NAME;
+#else
+  struct passwd *pwd;
+
+  if ((pwd = getpwuid(getuid())) == NULL)
+    return ANONYMOUS_NAME;
+  else
+    return pwd->pw_name;
+#endif
+}
+
+char *getRealName()
+{
+#if defined(PLATFORM_UNIX)
+  struct passwd *pwd;
+
+  if ((pwd = getpwuid(getuid())) == NULL || strlen(pwd->pw_gecos) == 0)
+    return ANONYMOUS_NAME;
+  else
+  {
+    static char real_name[1024];
+    char *from_ptr = pwd->pw_gecos, *to_ptr = real_name;
+
+    if (strchr(pwd->pw_gecos, 'ß') == NULL)
+      return pwd->pw_gecos;
+
+    /* the user's real name contains a 'ß' character (german sharp s),
+       which has no equivalent in upper case letters (which our fonts use) */
+    while (*from_ptr != '\0' && (long)(to_ptr - real_name) < 1024 - 2)
+    {
+      if (*from_ptr != 'ß')
+       *to_ptr++ = *from_ptr++;
+      else
+      {
+       from_ptr++;
+       *to_ptr++ = 's';
+       *to_ptr++ = 's';
+      }
+    }
+    *to_ptr = '\0';
+
+    return real_name;
+  }
+#else /* !PLATFORM_UNIX */
+  return ANONYMOUS_NAME;
+#endif
+}
+
+char *getHomeDir()
+{
+#if defined(PLATFORM_UNIX)
+  static char *home_dir = NULL;
+
+  if (!home_dir)
+  {
+    if (!(home_dir = getenv("HOME")))
+    {
+      struct passwd *pwd;
+
+      if ((pwd = getpwuid(getuid())))
+       home_dir = pwd->pw_dir;
+      else
+       home_dir = ".";
+    }
+  }
+
+  return home_dir;
+#else
+  return ".";
+#endif
+}
+
+char *getPath2(char *path1, char *path2)
+{
+  char *complete_path = checked_malloc(strlen(path1) + 1 +
+                                      strlen(path2) + 1);
+
+  sprintf(complete_path, "%s/%s", path1, path2);
+  return complete_path;
+}
+
+char *getPath3(char *path1, char *path2, char *path3)
+{
+  char *complete_path = checked_malloc(strlen(path1) + 1 +
+                                      strlen(path2) + 1 +
+                                      strlen(path3) + 1);
+
+  sprintf(complete_path, "%s/%s/%s", path1, path2, path3);
+  return complete_path;
+}
+
+char *getStringCopy(char *s)
+{
+  char *s_copy;
+
+  if (s == NULL)
+    return NULL;
+
+  s_copy = checked_malloc(strlen(s) + 1);
+
+  strcpy(s_copy, s);
+  return s_copy;
+}
+
+char *getStringToLower(char *s)
+{
+  char *s_copy = checked_malloc(strlen(s) + 1);
+  char *s_ptr = s_copy;
+
+  while (*s)
+    *s_ptr++ = tolower(*s++);
+  *s_ptr = '\0';
+
+  return s_copy;
+}
+
+void GetOptions(char *argv[])
+{
+  char **options_left = &argv[1];
+
+  /* initialize global program options */
+  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 = RO_BASE_PATH "/" LEVELS_DIRECTORY;
+  options.serveronly = FALSE;
+  options.network = FALSE;
+  options.verbose = FALSE;
+  options.debug = FALSE;
+
+  while (*options_left)
+  {
+    char option_str[MAX_OPTION_LEN];
+    char *option = options_left[0];
+    char *next_option = options_left[1];
+    char *option_arg = NULL;
+    int option_len = strlen(option);
+
+    if (option_len >= MAX_OPTION_LEN)
+      Error(ERR_EXIT_HELP, "unrecognized option '%s'", option);
+
+    strcpy(option_str, option);                        /* copy argument into buffer */
+    option = option_str;
+
+    if (strcmp(option, "--") == 0)             /* stop scanning arguments */
+      break;
+
+    if (strncmp(option, "--", 2) == 0)         /* treat '--' like '-' */
+      option++;
+
+    option_arg = strchr(option, '=');
+    if (option_arg == NULL)                    /* no '=' in option */
+      option_arg = next_option;
+    else
+    {
+      *option_arg++ = '\0';                    /* cut argument from option */
+      if (*option_arg == '\0')                 /* no argument after '=' */
+       Error(ERR_EXIT_HELP, "option '%s' has invalid argument", option_str);
+    }
+
+    option_len = strlen(option);
+
+    if (strcmp(option, "-") == 0)
+      Error(ERR_EXIT_HELP, "unrecognized option '%s'", option);
+    else if (strncmp(option, "-help", option_len) == 0)
+    {
+      printf("Usage: %s [options] [server.name [port]]\n"
+            "Options:\n"
+            "  -d, --display machine:0       X server display\n"
+            "  -b, --basepath directory      alternative base directory\n"
+            "  -l, --level directory         alternative level directory\n"
+            "  -s, --serveronly              only start network server\n"
+            "  -n, --network                 network multiplayer game\n"
+            "  -v, --verbose                 verbose mode\n",
+            program.command_basename);
+      exit(0);
+    }
+    else if (strncmp(option, "-display", option_len) == 0)
+    {
+      if (option_arg == NULL)
+       Error(ERR_EXIT_HELP, "option '%s' requires an argument", option_str);
+
+      options.display_name = option_arg;
+      if (option_arg == next_option)
+       options_left++;
+    }
+    else if (strncmp(option, "-basepath", option_len) == 0)
+    {
+      if (option_arg == NULL)
+       Error(ERR_EXIT_HELP, "option '%s' requires an argument", option_str);
+
+      /* this should be extended to separate options for ro and rw data */
+      options.ro_base_directory = option_arg;
+      options.rw_base_directory = option_arg;
+      if (option_arg == next_option)
+       options_left++;
+
+      /* adjust path for level directory accordingly */
+      options.level_directory =
+       getPath2(options.ro_base_directory, LEVELS_DIRECTORY);
+    }
+    else if (strncmp(option, "-levels", option_len) == 0)
+    {
+      if (option_arg == NULL)
+       Error(ERR_EXIT_HELP, "option '%s' requires an argument", option_str);
+
+      options.level_directory = option_arg;
+      if (option_arg == next_option)
+       options_left++;
+    }
+    else if (strncmp(option, "-network", option_len) == 0)
+    {
+      options.network = TRUE;
+    }
+    else if (strncmp(option, "-serveronly", option_len) == 0)
+    {
+      options.serveronly = TRUE;
+    }
+    else if (strncmp(option, "-verbose", option_len) == 0)
+    {
+      options.verbose = TRUE;
+    }
+    else if (strncmp(option, "-debug", option_len) == 0)
+    {
+      options.debug = TRUE;
+    }
+    else if (*option == '-')
+    {
+      Error(ERR_EXIT_HELP, "unrecognized option '%s'", option_str);
+    }
+    else if (options.server_host == NULL)
+    {
+      options.server_host = *options_left;
+    }
+    else if (options.server_port == 0)
+    {
+      options.server_port = atoi(*options_left);
+      if (options.server_port < 1024)
+       Error(ERR_EXIT_HELP, "bad port number '%d'", options.server_port);
+    }
+    else
+      Error(ERR_EXIT_HELP, "too many arguments");
+
+    options_left++;
+  }
+}
+
+void Error(int mode, char *format, ...)
+{
+  char *process_name = "";
+  FILE *error = stderr;
+  char *newline = "\n";
+
+  /* display warnings only when running in verbose mode */
+  if (mode & ERR_WARN && !options.verbose)
+    return;
+
+#if !defined(PLATFORM_UNIX)
+  newline = "\r\n";
+
+  if ((error = openErrorFile()) == NULL)
+  {
+    printf("Cannot write to error output file!%s", newline);
+    program.exit_function(1);
+  }
+#endif
+
+  if (mode & ERR_SOUND_SERVER)
+    process_name = " sound server";
+  else if (mode & ERR_NETWORK_SERVER)
+    process_name = " network server";
+  else if (mode & ERR_NETWORK_CLIENT)
+    process_name = " network client **";
+
+  if (format)
+  {
+    va_list ap;
+
+    fprintf(error, "%s%s: ", program.command_basename, process_name);
+
+    if (mode & ERR_WARN)
+      fprintf(error, "warning: ");
+
+    va_start(ap, format);
+    vfprintf(error, format, ap);
+    va_end(ap);
+  
+    fprintf(error, "%s", newline);
+  }
+  
+  if (mode & ERR_HELP)
+    fprintf(error, "%s: Try option '--help' for more information.%s",
+           program.command_basename, newline);
+
+  if (mode & ERR_EXIT)
+    fprintf(error, "%s%s: aborting%s",
+           program.command_basename, process_name, newline);
+
+  if (error != stderr)
+    fclose(error);
+
+  if (mode & ERR_EXIT)
+  {
+    if (mode & ERR_FROM_SERVER)
+      exit(1);                         /* child process: normal exit */
+    else
+      program.exit_function(1);                /* main process: clean up stuff */
+  }
+}
+
+void *checked_malloc(unsigned long size)
+{
+  void *ptr;
+
+  ptr = malloc(size);
+
+  if (ptr == NULL)
+    Error(ERR_EXIT, "cannot allocate %d bytes -- out of memory", size);
+
+  return ptr;
+}
+
+void *checked_calloc(unsigned long size)
+{
+  void *ptr;
+
+  ptr = calloc(1, size);
+
+  if (ptr == NULL)
+    Error(ERR_EXIT, "cannot allocate %d bytes -- out of memory", size);
+
+  return ptr;
+}
+
+void *checked_realloc(void *ptr, unsigned long size)
+{
+  ptr = realloc(ptr, size);
+
+  if (ptr == NULL)
+    Error(ERR_EXIT, "cannot allocate %d bytes -- out of memory", size);
+
+  return ptr;
+}
+
+short getFile16BitInteger(FILE *file, int byte_order)
+{
+  if (byte_order == BYTE_ORDER_BIG_ENDIAN)
+    return ((fgetc(file) <<  8) |
+           (fgetc(file) <<  0));
+  else          /* BYTE_ORDER_LITTLE_ENDIAN */
+    return ((fgetc(file) <<  0) |
+           (fgetc(file) <<  8));
+}
+
+void putFile16BitInteger(FILE *file, short value, int byte_order)
+{
+  if (byte_order == BYTE_ORDER_BIG_ENDIAN)
+  {
+    fputc((value >>  8) & 0xff, file);
+    fputc((value >>  0) & 0xff, file);
+  }
+  else          /* BYTE_ORDER_LITTLE_ENDIAN */
+  {
+    fputc((value >>  0) & 0xff, file);
+    fputc((value >>  8) & 0xff, file);
+  }
+}
+
+int getFile32BitInteger(FILE *file, int byte_order)
+{
+  if (byte_order == BYTE_ORDER_BIG_ENDIAN)
+    return ((fgetc(file) << 24) |
+           (fgetc(file) << 16) |
+           (fgetc(file) <<  8) |
+           (fgetc(file) <<  0));
+  else          /* BYTE_ORDER_LITTLE_ENDIAN */
+    return ((fgetc(file) <<  0) |
+           (fgetc(file) <<  8) |
+           (fgetc(file) << 16) |
+           (fgetc(file) << 24));
+}
+
+void putFile32BitInteger(FILE *file, int value, int byte_order)
+{
+  if (byte_order == BYTE_ORDER_BIG_ENDIAN)
+  {
+    fputc((value >> 24) & 0xff, file);
+    fputc((value >> 16) & 0xff, file);
+    fputc((value >>  8) & 0xff, file);
+    fputc((value >>  0) & 0xff, file);
+  }
+  else          /* BYTE_ORDER_LITTLE_ENDIAN */
+  {
+    fputc((value >>  0) & 0xff, file);
+    fputc((value >>  8) & 0xff, file);
+    fputc((value >> 16) & 0xff, file);
+    fputc((value >> 24) & 0xff, file);
+  }
+}
+
+void getFileChunk(FILE *file, char *chunk_buffer, int *chunk_length,
+                 int byte_order)
+{
+  const int chunk_identifier_length = 4;
+
+  /* read chunk identifier */
+  fgets(chunk_buffer, chunk_identifier_length + 1, file);
+
+  /* read chunk length */
+  *chunk_length = getFile32BitInteger(file, byte_order);
+}
+
+void putFileChunk(FILE *file, char *chunk_name, int chunk_length,
+                 int byte_order)
+{
+  /* write chunk identifier */
+  fputs(chunk_name, file);
+
+  /* write chunk length */
+  putFile32BitInteger(file, chunk_length, byte_order);
+}
+
+#define TRANSLATE_KEYSYM_TO_KEYNAME    0
+#define TRANSLATE_KEYSYM_TO_X11KEYNAME 1
+#define TRANSLATE_X11KEYNAME_TO_KEYSYM 2
+
+void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
+{
+  static struct
+  {
+    Key key;
+    char *x11name;
+    char *name;
+  } translate_key[] =
+  {
+    /* normal cursor keys */
+    { KSYM_Left,       "XK_Left",              "cursor left" },
+    { KSYM_Right,      "XK_Right",             "cursor right" },
+    { KSYM_Up,         "XK_Up",                "cursor up" },
+    { KSYM_Down,       "XK_Down",              "cursor down" },
+
+    /* keypad cursor keys */
+#ifdef KSYM_KP_Left
+    { KSYM_KP_Left,    "XK_KP_Left",           "keypad left" },
+    { KSYM_KP_Right,   "XK_KP_Right",          "keypad right" },
+    { KSYM_KP_Up,      "XK_KP_Up",             "keypad up" },
+    { KSYM_KP_Down,    "XK_KP_Down",           "keypad down" },
+#endif
+
+    /* other keypad keys */
+#ifdef KSYM_KP_Enter
+    { KSYM_KP_Enter,   "XK_KP_Enter",          "keypad enter" },
+    { KSYM_KP_Add,     "XK_KP_Add",            "keypad +" },
+    { KSYM_KP_Subtract,        "XK_KP_Subtract",       "keypad -" },
+    { KSYM_KP_Multiply,        "XK_KP_Multiply",       "keypad mltply" },
+    { KSYM_KP_Divide,  "XK_KP_Divide",         "keypad /" },
+    { KSYM_KP_Separator,"XK_KP_Separator",     "keypad ," },
+#endif
+
+    /* modifier keys */
+    { KSYM_Shift_L,    "XK_Shift_L",           "left shift" },
+    { KSYM_Shift_R,    "XK_Shift_R",           "right shift" },
+    { KSYM_Control_L,  "XK_Control_L",         "left control" },
+    { KSYM_Control_R,  "XK_Control_R",         "right control" },
+    { KSYM_Meta_L,     "XK_Meta_L",            "left meta" },
+    { KSYM_Meta_R,     "XK_Meta_R",            "right meta" },
+    { KSYM_Alt_L,      "XK_Alt_L",             "left alt" },
+    { KSYM_Alt_R,      "XK_Alt_R",             "right alt" },
+    { KSYM_Super_L,    "XK_Super_L",           "left super" },  /* Win-L */
+    { KSYM_Super_R,    "XK_Super_R",           "right super" }, /* Win-R */
+    { KSYM_Mode_switch,        "XK_Mode_switch",       "mode switch" }, /* Alt-R */
+    { KSYM_Multi_key,  "XK_Multi_key",         "multi key" },   /* Ctrl-R */
+
+    /* some special keys */
+    { KSYM_BackSpace,  "XK_BackSpace",         "backspace" },
+    { KSYM_Delete,     "XK_Delete",            "delete" },
+    { KSYM_Insert,     "XK_Insert",            "insert" },
+    { KSYM_Tab,                "XK_Tab",               "tab" },
+    { KSYM_Home,       "XK_Home",              "home" },
+    { KSYM_End,                "XK_End",               "end" },
+    { KSYM_Page_Up,    "XK_Page_Up",           "page up" },
+    { KSYM_Page_Down,  "XK_Page_Down",         "page down" },
+    { KSYM_Menu,       "XK_Menu",              "menu" },        /* Win-Menu */
+
+    /* ASCII 0x20 to 0x40 keys (except numbers) */
+    { KSYM_space,      "XK_space",             "space" },
+    { KSYM_exclam,     "XK_exclam",            "!" },
+    { KSYM_quotedbl,   "XK_quotedbl",          "\"" },
+    { KSYM_numbersign, "XK_numbersign",        "#" },
+    { KSYM_dollar,     "XK_dollar",            "$" },
+    { KSYM_percent,    "XK_percent",           "%" },
+    { KSYM_ampersand,  "XK_ampersand",         "&" },
+    { KSYM_apostrophe, "XK_apostrophe",        "'" },
+    { KSYM_parenleft,  "XK_parenleft",         "(" },
+    { KSYM_parenright, "XK_parenright",        ")" },
+    { KSYM_asterisk,   "XK_asterisk",          "*" },
+    { KSYM_plus,       "XK_plus",              "+" },
+    { KSYM_comma,      "XK_comma",             "," },
+    { KSYM_minus,      "XK_minus",             "-" },
+    { KSYM_period,     "XK_period",            "." },
+    { KSYM_slash,      "XK_slash",             "/" },
+    { KSYM_colon,      "XK_colon",             ":" },
+    { KSYM_semicolon,  "XK_semicolon",         ";" },
+    { KSYM_less,       "XK_less",              "<" },
+    { KSYM_equal,      "XK_equal",             "=" },
+    { KSYM_greater,    "XK_greater",           ">" },
+    { KSYM_question,   "XK_question",          "?" },
+    { KSYM_at,         "XK_at",                "@" },
+
+    /* more ASCII keys */
+    { KSYM_bracketleft,        "XK_bracketleft",       "[" },
+    { KSYM_backslash,  "XK_backslash",         "backslash" },
+    { KSYM_bracketright,"XK_bracketright",     "]" },
+    { KSYM_asciicircum,        "XK_asciicircum",       "circumflex" },
+    { KSYM_underscore, "XK_underscore",        "_" },
+    { KSYM_grave,      "XK_grave",             "grave" },
+    { KSYM_quoteleft,  "XK_quoteleft",         "quote left" },
+    { KSYM_braceleft,  "XK_braceleft",         "brace left" },
+    { KSYM_bar,                "XK_bar",               "bar" },
+    { KSYM_braceright, "XK_braceright",        "brace right" },
+    { KSYM_asciitilde, "XK_asciitilde",        "ascii tilde" },
+
+    /* special (non-ASCII) keys */
+    { KSYM_Adiaeresis, "XK_Adiaeresis",        "Ä" },
+    { KSYM_Odiaeresis, "XK_Odiaeresis",        "Ö" },
+    { KSYM_Udiaeresis, "XK_Udiaeresis",        "Ãœ" },
+    { KSYM_adiaeresis, "XK_adiaeresis",        "ä" },
+    { KSYM_odiaeresis, "XK_odiaeresis",        "ö" },
+    { KSYM_udiaeresis, "XK_udiaeresis",        "ü" },
+    { KSYM_ssharp,     "XK_ssharp",            "sharp s" },
+
+    /* end-of-array identifier */
+    { 0,                NULL,                  NULL }
+  };
+
+  int i;
+
+  if (mode == TRANSLATE_KEYSYM_TO_KEYNAME)
+  {
+    static char name_buffer[30];
+    Key key = *keysym;
+
+    if (key >= KSYM_A && key <= KSYM_Z)
+      sprintf(name_buffer, "%c", 'A' + (char)(key - KSYM_A));
+    else if (key >= KSYM_a && key <= KSYM_z)
+      sprintf(name_buffer, "%c", 'a' + (char)(key - KSYM_a));
+    else if (key >= KSYM_0 && key <= KSYM_9)
+      sprintf(name_buffer, "%c", '0' + (char)(key - KSYM_0));
+    else if (key >= KSYM_KP_0 && key <= KSYM_KP_9)
+      sprintf(name_buffer, "keypad %c", '0' + (char)(key - KSYM_KP_0));
+    else if (key >= KSYM_F1 && key <= KSYM_F24)
+      sprintf(name_buffer, "function F%d", (int)(key - KSYM_F1 + 1));
+    else if (key == KSYM_UNDEFINED)
+      strcpy(name_buffer, "(undefined)");
+    else
+    {
+      i = 0;
+
+      do
+      {
+       if (key == translate_key[i].key)
+       {
+         strcpy(name_buffer, translate_key[i].name);
+         break;
+       }
+      }
+      while (translate_key[++i].name);
+
+      if (!translate_key[i].name)
+       strcpy(name_buffer, "(unknown)");
+    }
+
+    *name = name_buffer;
+  }
+  else if (mode == TRANSLATE_KEYSYM_TO_X11KEYNAME)
+  {
+    static char name_buffer[30];
+    Key key = *keysym;
+
+    if (key >= KSYM_A && key <= KSYM_Z)
+      sprintf(name_buffer, "XK_%c", 'A' + (char)(key - KSYM_A));
+    else if (key >= KSYM_a && key <= KSYM_z)
+      sprintf(name_buffer, "XK_%c", 'a' + (char)(key - KSYM_a));
+    else if (key >= KSYM_0 && key <= KSYM_9)
+      sprintf(name_buffer, "XK_%c", '0' + (char)(key - KSYM_0));
+    else if (key >= KSYM_KP_0 && key <= KSYM_KP_9)
+      sprintf(name_buffer, "XK_KP_%c", '0' + (char)(key - KSYM_KP_0));
+    else if (key >= KSYM_F1 && key <= KSYM_F24)
+      sprintf(name_buffer, "XK_F%d", (int)(key - KSYM_F1 + 1));
+    else if (key == KSYM_UNDEFINED)
+      strcpy(name_buffer, "[undefined]");
+    else
+    {
+      i = 0;
+
+      do
+      {
+       if (key == translate_key[i].key)
+       {
+         strcpy(name_buffer, translate_key[i].x11name);
+         break;
+       }
+      }
+      while (translate_key[++i].x11name);
+
+      if (!translate_key[i].x11name)
+       sprintf(name_buffer, "0x%04lx", (unsigned long)key);
+    }
+
+    *x11name = name_buffer;
+  }
+  else if (mode == TRANSLATE_X11KEYNAME_TO_KEYSYM)
+  {
+    Key key = KSYM_UNDEFINED;
+    char *name_ptr = *x11name;
+
+    if (strncmp(name_ptr, "XK_", 3) == 0 && strlen(name_ptr) == 4)
+    {
+      char c = name_ptr[3];
+
+      if (c >= 'A' && c <= 'Z')
+       key = KSYM_A + (Key)(c - 'A');
+      else if (c >= 'a' && c <= 'z')
+       key = KSYM_a + (Key)(c - 'a');
+      else if (c >= '0' && c <= '9')
+       key = KSYM_0 + (Key)(c - '0');
+    }
+    else if (strncmp(name_ptr, "XK_KP_", 6) == 0 && strlen(name_ptr) == 7)
+    {
+      char c = name_ptr[6];
+
+      if (c >= '0' && c <= '9')
+       key = KSYM_0 + (Key)(c - '0');
+    }
+    else if (strncmp(name_ptr, "XK_F", 4) == 0 && strlen(name_ptr) <= 6)
+    {
+      char c1 = name_ptr[4];
+      char c2 = name_ptr[5];
+      int d = 0;
+
+      if ((c1 >= '0' && c1 <= '9') &&
+         ((c2 >= '0' && c1 <= '9') || c2 == '\0'))
+       d = atoi(&name_ptr[4]);
+
+      if (d >=1 && d <= 24)
+       key = KSYM_F1 + (Key)(d - 1);
+    }
+    else if (strncmp(name_ptr, "XK_", 3) == 0)
+    {
+      i = 0;
+
+      do
+      {
+       if (strcmp(name_ptr, translate_key[i].x11name) == 0)
+       {
+         key = translate_key[i].key;
+         break;
+       }
+      }
+      while (translate_key[++i].x11name);
+    }
+    else if (strncmp(name_ptr, "0x", 2) == 0)
+    {
+      unsigned long value = 0;
+
+      name_ptr += 2;
+
+      while (name_ptr)
+      {
+       char c = *name_ptr++;
+       int d = -1;
+
+       if (c >= '0' && c <= '9')
+         d = (int)(c - '0');
+       else if (c >= 'a' && c <= 'f')
+         d = (int)(c - 'a' + 10);
+       else if (c >= 'A' && c <= 'F')
+         d = (int)(c - 'A' + 10);
+
+       if (d == -1)
+       {
+         value = -1;
+         break;
+       }
+
+       value = value * 16 + d;
+      }
+
+      if (value != -1)
+       key = (Key)value;
+    }
+
+    *keysym = key;
+  }
+}
+
+char *getKeyNameFromKey(Key key)
+{
+  char *name;
+
+  translate_keyname(&key, NULL, &name, TRANSLATE_KEYSYM_TO_KEYNAME);
+  return name;
+}
+
+char *getX11KeyNameFromKey(Key key)
+{
+  char *x11name;
+
+  translate_keyname(&key, &x11name, NULL, TRANSLATE_KEYSYM_TO_X11KEYNAME);
+  return x11name;
+}
+
+Key getKeyFromX11KeyName(char *x11name)
+{
+  Key key;
+
+  translate_keyname(&key, &x11name, NULL, TRANSLATE_X11KEYNAME_TO_KEYSYM);
+  return key;
+}
+
+char getCharFromKey(Key key)
+{
+  char *keyname = getKeyNameFromKey(key);
+  char letter = 0;
+
+  if (strlen(keyname) == 1)
+    letter = keyname[0];
+  else if (strcmp(keyname, "space") == 0)
+    letter = ' ';
+  else if (strcmp(keyname, "circumflex") == 0)
+    letter = '^';
+
+  return letter;
+}
+
+/* ------------------------------------------------------------------------- */
+/* some functions to handle lists of level directories                       */
+/* ------------------------------------------------------------------------- */
+
+struct LevelDirInfo *newLevelDirInfo()
+{
+  return checked_calloc(sizeof(struct LevelDirInfo));
+}
+
+void pushLevelDirInfo(struct LevelDirInfo **node_first,
+                     struct LevelDirInfo *node_new)
+{
+  node_new->next = *node_first;
+  *node_first = node_new;
+}
+
+int numLevelDirInfo(struct LevelDirInfo *node)
+{
+  int num = 0;
+
+  while (node)
+  {
+    num++;
+    node = node->next;
+  }
+
+  return num;
+}
+
+boolean validLevelSeries(struct LevelDirInfo *node)
+{
+  return (node != NULL && !node->node_group && !node->parent_link);
+}
+
+struct LevelDirInfo *getFirstValidLevelSeries(struct LevelDirInfo *node)
+{
+  if (node == NULL)
+  {
+    if (leveldir_first)                /* start with first level directory entry */
+      return getFirstValidLevelSeries(leveldir_first);
+    else
+      return NULL;
+  }
+  else if (node->node_group)   /* enter level group (step down into tree) */
+    return getFirstValidLevelSeries(node->node_group);
+  else if (node->parent_link)  /* skip start entry of level group */
+  {
+    if (node->next)            /* get first real level series entry */
+      return getFirstValidLevelSeries(node->next);
+    else                       /* leave empty level group and go on */
+      return getFirstValidLevelSeries(node->node_parent->next);
+  }
+  else                         /* this seems to be a regular level series */
+    return node;
+}
+
+struct LevelDirInfo *getLevelDirInfoFirstGroupEntry(struct LevelDirInfo *node)
+{
+  if (node == NULL)
+    return NULL;
+
+  if (node->node_parent == NULL)               /* top level group */
+    return leveldir_first;
+  else                                         /* sub level group */
+    return node->node_parent->node_group;
+}
+
+int numLevelDirInfoInGroup(struct LevelDirInfo *node)
+{
+  return numLevelDirInfo(getLevelDirInfoFirstGroupEntry(node));
+}
+
+int posLevelDirInfo(struct LevelDirInfo *node)
+{
+  struct LevelDirInfo *node_cmp = getLevelDirInfoFirstGroupEntry(node);
+  int pos = 0;
+
+  while (node_cmp)
+  {
+    if (node_cmp == node)
+      return pos;
+
+    pos++;
+    node_cmp = node_cmp->next;
+  }
+
+  return 0;
+}
+
+struct LevelDirInfo *getLevelDirInfoFromPos(struct LevelDirInfo *node, int pos)
+{
+  struct LevelDirInfo *node_default = node;
+  int pos_cmp = 0;
+
+  while (node)
+  {
+    if (pos_cmp == pos)
+      return node;
+
+    pos_cmp++;
+    node = node->next;
+  }
+
+  return node_default;
+}
+
+struct LevelDirInfo *getLevelDirInfoFromFilenameExt(struct LevelDirInfo *node,
+                                                   char *filename)
+{
+  if (filename == NULL)
+    return NULL;
+
+  while (node)
+  {
+    if (node->node_group)
+    {
+      struct LevelDirInfo *node_group;
+
+      node_group = getLevelDirInfoFromFilenameExt(node->node_group, filename);
+
+      if (node_group)
+       return node_group;
+    }
+    else if (!node->parent_link)
+    {
+      if (strcmp(filename, node->filename) == 0)
+       return node;
+    }
+
+    node = node->next;
+  }
+
+  return NULL;
+}
+
+struct LevelDirInfo *getLevelDirInfoFromFilename(char *filename)
+{
+  return getLevelDirInfoFromFilenameExt(leveldir_first, filename);
+}
+
+void dumpLevelDirInfo(struct LevelDirInfo *node, int depth)
+{
+  int i;
+
+  while (node)
+  {
+    for (i=0; i<depth * 3; i++)
+      printf(" ");
+
+    printf("filename == '%s'\n", node->filename);
+
+    if (node->node_group != NULL)
+      dumpLevelDirInfo(node->node_group, depth + 1);
+
+    node = node->next;
+  }
+}
+
+void sortLevelDirInfo(struct LevelDirInfo **node_first,
+                     int (*compare_function)(const void *, const void *))
+{
+  int num_nodes = numLevelDirInfo(*node_first);
+  struct LevelDirInfo **sort_array;
+  struct LevelDirInfo *node = *node_first;
+  int i = 0;
+
+  if (num_nodes == 0)
+    return;
+
+  /* allocate array for sorting structure pointers */
+  sort_array = checked_calloc(num_nodes * sizeof(struct LevelDirInfo *));
+
+  /* writing structure pointers to sorting array */
+  while (i < num_nodes && node)                /* double boundary check... */
+  {
+    sort_array[i] = node;
+
+    i++;
+    node = node->next;
+  }
+
+  /* sorting the structure pointers in the sorting array */
+  qsort(sort_array, num_nodes, sizeof(struct LevelDirInfo *),
+       compare_function);
+
+  /* update the linkage of list elements with the sorted node array */
+  for (i=0; i<num_nodes - 1; i++)
+    sort_array[i]->next = sort_array[i + 1];
+  sort_array[num_nodes - 1]->next = NULL;
+
+  /* update the linkage of the main list anchor pointer */
+  *node_first = sort_array[0];
+
+  free(sort_array);
+
+  /* now recursively sort the level group structures */
+  node = *node_first;
+  while (node)
+  {
+    if (node->node_group != NULL)
+      sortLevelDirInfo(&node->node_group, compare_function);
+
+    node = node->next;
+  }
+}
+
+inline void swap_numbers(int *i1, int *i2)
+{
+  int help = *i1;
+
+  *i1 = *i2;
+  *i2 = help;
+}
+
+inline void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
+{
+  int help_x = *x1;
+  int help_y = *y1;
+
+  *x1 = *x2;
+  *x2 = help_x;
+
+  *y1 = *y2;
+  *y2 = help_y;
+}
+
+
+/* ========================================================================= */
+/* some stuff from "files.c"                                                 */
+/* ========================================================================= */
+
+#define MODE_R_ALL             (S_IRUSR | S_IRGRP | S_IROTH)
+#define MODE_W_ALL             (S_IWUSR | S_IWGRP | S_IWOTH)
+#define MODE_X_ALL             (S_IXUSR | S_IXGRP | S_IXOTH)
+#define USERDATA_DIR_MODE      (MODE_R_ALL | MODE_X_ALL | S_IWUSR)
+
+char *getUserDataDir(void)
+{
+  static char *userdata_dir = NULL;
+
+  if (!userdata_dir)
+  {
+    char *home_dir = getHomeDir();
+    char *data_dir = program.userdata_directory;
+
+    userdata_dir = getPath2(home_dir, data_dir);
+  }
+
+  return userdata_dir;
+}
+
+void createDirectory(char *dir, char *text)
+{
+  if (access(dir, F_OK) != 0)
+#if defined(PLATFORM_WIN32)
+    if (mkdir(dir) != 0)
+#else
+    if (mkdir(dir, USERDATA_DIR_MODE) != 0)
+#endif
+      Error(ERR_WARN, "cannot create %s directory '%s'", text, dir);
+}
+
+void InitUserDataDirectory()
+{
+  createDirectory(getUserDataDir(), "user data");
+}
+
+
+/* ========================================================================= */
+/* functions only needed for non-Unix (non-command-line) systems */
+/* ========================================================================= */
+
+#if !defined(PLATFORM_UNIX)
+
+#define ERROR_FILENAME         "error.out"
+
+void initErrorFile()
+{
+  char *filename;
+
+  InitUserDataDirectory();
+
+  filename = getPath2(getUserDataDir(), ERROR_FILENAME);
+  unlink(filename);
+  free(filename);
+}
+
+FILE *openErrorFile()
+{
+  char *filename;
+  FILE *error_file;
+
+  filename = getPath2(getUserDataDir(), ERROR_FILENAME);
+  error_file = fopen(filename, MODE_APPEND);
+  free(filename);
+
+  return error_file;
+}
+
+void dumpErrorFile()
+{
+  char *filename;
+  FILE *error_file;
+
+  filename = getPath2(getUserDataDir(), ERROR_FILENAME);
+  error_file = fopen(filename, MODE_READ);
+  free(filename);
+
+  if (error_file != NULL)
+  {
+    while (!feof(error_file))
+      fputc(fgetc(error_file), stderr);
+
+    fclose(error_file);
+  }
+}
+#endif
+
+
+/* ========================================================================= */
+/* the following is only for debugging purpose and normally not used         */
+/* ========================================================================= */
+
+#define DEBUG_NUM_TIMESTAMPS   3
+
+void debug_print_timestamp(int counter_nr, char *message)
+{
+  static long counter[DEBUG_NUM_TIMESTAMPS][2];
+
+  if (counter_nr >= DEBUG_NUM_TIMESTAMPS)
+    Error(ERR_EXIT, "debugging: increase DEBUG_NUM_TIMESTAMPS in misc.c");
+
+  counter[counter_nr][0] = Counter();
+
+  if (message)
+    printf("%s %.2f seconds\n", message,
+          (float)(counter[counter_nr][0] - counter[counter_nr][1]) / 1000);
+
+  counter[counter_nr][1] = Counter();
+}
diff --git a/src/libgame/misc.h b/src/libgame/misc.h
new file mode 100644 (file)
index 0000000..880c83e
--- /dev/null
@@ -0,0 +1,113 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* misc.h                                                   *
+***********************************************************/
+
+#ifndef MISC_H
+#define MISC_H
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "system.h"
+
+
+/* values for InitCounter() and Counter() */
+#define INIT_COUNTER                   0
+#define READ_COUNTER                   1
+
+/* values for InitRND() */
+#define NEW_RANDOMIZE                  -1
+
+/* values for Error() */
+#define ERR_RETURN                     0
+#define ERR_WARN                       (1 << 0)
+#define ERR_EXIT                       (1 << 1)
+#define ERR_HELP                       (1 << 2)
+#define ERR_SOUND_SERVER               (1 << 3)
+#define ERR_NETWORK_SERVER             (1 << 4)
+#define ERR_NETWORK_CLIENT             (1 << 5)
+#define ERR_FROM_SERVER                        (ERR_SOUND_SERVER | ERR_NETWORK_SERVER)
+#define ERR_EXIT_HELP                  (ERR_EXIT | ERR_HELP)
+#define ERR_EXIT_SOUND_SERVER          (ERR_EXIT | ERR_SOUND_SERVER)
+#define ERR_EXIT_NETWORK_SERVER                (ERR_EXIT | ERR_NETWORK_SERVER)
+#define ERR_EXIT_NETWORK_CLIENT                (ERR_EXIT | ERR_NETWORK_CLIENT)
+
+/* values for getFile...() and putFile...() */
+#define BYTE_ORDER_BIG_ENDIAN          0
+#define BYTE_ORDER_LITTLE_ENDIAN       1
+
+void InitCounter(void);
+unsigned long Counter(void);
+void Delay(unsigned long);
+boolean FrameReached(unsigned long *, unsigned long);
+boolean DelayReached(unsigned long *, unsigned long);
+void WaitUntilDelayReached(unsigned long *, unsigned long);
+char *int2str(int, int);
+unsigned int SimpleRND(unsigned int);
+unsigned int RND(unsigned int);
+unsigned int InitRND(long);
+char *getLoginName(void);
+char *getRealName(void);
+char *getHomeDir(void);
+char *getPath2(char *, char *);
+char *getPath3(char *, char *, char*);
+char *getStringCopy(char *);
+char *getStringToLower(char *);
+void GetOptions(char **);
+void Error(int, char *, ...);
+void *checked_malloc(unsigned long);
+void *checked_calloc(unsigned long);
+void *checked_realloc(void *, unsigned long);
+short getFile16BitInteger(FILE *, int);
+void putFile16BitInteger(FILE *, short, int);
+int getFile32BitInteger(FILE *, int);
+void putFile32BitInteger(FILE *, int, int);
+void getFileChunk(FILE *, char *, int *, int);
+void putFileChunk(FILE *, char *, int, int);
+char *getKeyNameFromKey(Key);
+char *getX11KeyNameFromKey(Key);
+Key getKeyFromX11KeyName(char *);
+char getCharFromKey(Key);
+char *getJoyNameFromJoySymbol(int);
+int getJoySymbolFromJoyName(char *);
+int getJoystickNrFromDeviceName(char *);
+
+struct LevelDirInfo *newLevelDirInfo();
+void pushLevelDirInfo(struct LevelDirInfo **, struct LevelDirInfo *);
+int numLevelDirInfo(struct LevelDirInfo *);
+boolean validLevelSeries(struct LevelDirInfo *);
+struct LevelDirInfo *getFirstValidLevelSeries(struct LevelDirInfo *);
+struct LevelDirInfo *getLevelDirInfoFirstGroupEntry(struct LevelDirInfo *);
+int numLevelDirInfoInGroup(struct LevelDirInfo *);
+int posLevelDirInfo(struct LevelDirInfo *);
+struct LevelDirInfo *getLevelDirInfoFromPos(struct LevelDirInfo *, int);
+struct LevelDirInfo *getLevelDirInfoFromFilename(char *);
+void dumpLevelDirInfo(struct LevelDirInfo *, int);
+void sortLevelDirInfo(struct LevelDirInfo **,
+                     int (*compare_function)(const void *, const void *));
+
+inline void swap_numbers(int *, int *);
+inline void swap_number_pairs(int *, int *, int *, int *);
+
+char *getUserDataDir(void);
+void createDirectory(char *, char *);
+void InitUserDataDirectory(void);
+
+#if !defined(PLATFORM_UNIX)
+void initErrorFile();
+FILE *openErrorFile();
+void dumpErrorFile();
+#endif
+
+void debug_print_timestamp(int, char *);
+
+#endif /* MISC_H */
diff --git a/src/libgame/msdos.c b/src/libgame/msdos.c
new file mode 100644 (file)
index 0000000..cf49ec3
--- /dev/null
@@ -0,0 +1,997 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* msdos.c                                                  *
+***********************************************************/
+
+#include "system.h"
+
+
+#if defined(PLATFORM_MSDOS)
+
+#include "sound.h"
+#include "misc.h"
+#include "pcx.h"
+
+#define AllegroDefaultScreen() (display->screens[display->default_screen])
+
+/* allegro driver declarations */
+DECLARE_GFX_DRIVER_LIST(GFX_DRIVER_VBEAF GFX_DRIVER_VESA2L GFX_DRIVER_VESA1)
+DECLARE_COLOR_DEPTH_LIST(COLOR_DEPTH_8)
+DECLARE_DIGI_DRIVER_LIST(DIGI_DRIVER_SB)
+DECLARE_MIDI_DRIVER_LIST()
+DECLARE_JOYSTICK_DRIVER_LIST(JOYSTICK_DRIVER_STANDARD)
+
+/* allegro global variables */
+extern volatile int key_shifts;
+extern int num_joysticks;
+extern JOYSTICK_INFO joy[];
+extern int i_love_bill;
+
+/* internal variables of msdos.c */
+static boolean keyboard_auto_repeat = TRUE;
+static int key_press_state[MAX_SCANCODES];
+static XEvent event_buffer[MAX_EVENT_BUFFER];
+static int pending_events;
+static boolean joystick_event;
+static boolean mouse_installed = FALSE;
+static int last_mouse_pos;
+static int last_mouse_b;
+static int last_joystick_state;
+static BITMAP* video_bitmap;
+
+static RGB global_colormap[MAX_COLORS];
+static int global_colormap_entries_used = 0;
+
+boolean wait_for_vsync;
+
+/*
+extern int playing_sounds;
+extern struct SoundControl playlist[MAX_SOUNDS_PLAYING];
+extern struct SoundControl emptySoundControl;
+*/
+
+static BITMAP *Read_PCX_to_AllegroBitmap(char *);
+
+static void allegro_init_drivers()
+{
+  int i;
+
+  for (i=0; i<MAX_EVENT_BUFFER; i++)
+    event_buffer[i].type = 0;
+
+  for (i=0; i<MAX_SCANCODES; i++)
+    key_press_state[i] = KeyReleaseMask;
+
+  last_mouse_pos = mouse_pos;
+  last_mouse_b = 0;
+
+  pending_events = 0;
+  clear_keybuf();
+
+  /* enable Windows friendly timer mode (already default under Windows) */
+  i_love_bill = TRUE;
+
+  install_keyboard();
+  install_timer();
+  if (install_mouse() > 0)
+    mouse_installed = TRUE;
+
+  last_joystick_state = 0;
+  joystick_event = FALSE;
+}
+
+static boolean allegro_init_audio()
+{
+  reserve_voices(MAX_SOUNDS_PLAYING, 0);
+
+  if (install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL) == -1)
+    if (install_sound(DIGI_SB, MIDI_NONE, NULL) == -1)
+      return FALSE;
+
+  return TRUE;
+}
+
+static boolean hide_mouse(Display *display, int x, int y,
+                         unsigned int width, unsigned int height)
+{
+  if (mouse_x + display->mouse_ptr->w < x || mouse_x > x + width)
+    return FALSE;
+  if (mouse_y + display->mouse_ptr->h < y || mouse_y > y + height)
+    return FALSE;
+
+  show_mouse(NULL);
+
+  return TRUE;
+}
+
+static void unhide_mouse(Display *display)
+{
+  if (mouse_installed)
+    show_mouse(video_bitmap);
+}
+
+static KeySym ScancodeToKeySym(byte scancode)
+{
+  switch(scancode)
+  {
+    case KEY_ESC:              return XK_Escape;
+    case KEY_1:                        return XK_1;
+    case KEY_2:                        return XK_2;
+    case KEY_3:                        return XK_3;
+    case KEY_4:                        return XK_4;
+    case KEY_5:                        return XK_5;
+    case KEY_6:                        return XK_6;
+    case KEY_7:                        return XK_7;
+    case KEY_8:                        return XK_8;
+    case KEY_9:                        return XK_9;
+    case KEY_0:                        return XK_0;
+    case KEY_MINUS:            return XK_minus;
+    case KEY_EQUALS:           return XK_equal;
+    case KEY_BACKSPACE:                return XK_BackSpace;
+    case KEY_TAB:              return XK_Tab;
+    case KEY_Q:                        return XK_q;
+    case KEY_W:                        return XK_w;
+    case KEY_E:                        return XK_e;
+    case KEY_R:                        return XK_r;
+    case KEY_T:                        return XK_t;
+    case KEY_Y:                        return XK_y;
+    case KEY_U:                        return XK_u;
+    case KEY_I:                        return XK_i;
+    case KEY_O:                        return XK_o;
+    case KEY_P:                        return XK_p;
+    case KEY_OPENBRACE:                return XK_braceleft;
+    case KEY_CLOSEBRACE:       return XK_braceright;
+    case KEY_ENTER:            return XK_Return;
+    case KEY_LCONTROL:         return XK_Control_L;
+    case KEY_A:                        return XK_a;
+    case KEY_S:                        return XK_s;
+    case KEY_D:                        return XK_d;
+    case KEY_F:                        return XK_f;
+    case KEY_G:                        return XK_g;
+    case KEY_H:                        return XK_h;
+    case KEY_J:                        return XK_j;
+    case KEY_K:                        return XK_k;
+    case KEY_L:                        return XK_l;
+    case KEY_COLON:            return XK_colon;
+    case KEY_QUOTE:            return XK_apostrophe;
+    case KEY_TILDE:            return XK_asciitilde;
+    case KEY_LSHIFT:           return XK_Shift_L;
+    case KEY_BACKSLASH:                return XK_backslash;
+    case KEY_Z:                        return XK_z;
+    case KEY_X:                        return XK_x;
+    case KEY_C:                        return XK_c;
+    case KEY_V:                        return XK_v;
+    case KEY_B:                        return XK_b;
+    case KEY_N:                        return XK_n;
+    case KEY_M:                        return XK_m;
+    case KEY_COMMA:            return XK_comma;
+    case KEY_STOP:             return XK_period;
+    case KEY_SLASH:            return XK_slash;
+    case KEY_RSHIFT:           return XK_Shift_R;
+    case KEY_ASTERISK:         return XK_KP_Multiply;
+    case KEY_ALT:              return XK_Alt_L;
+    case KEY_SPACE:            return XK_space;
+    case KEY_CAPSLOCK:         return XK_Caps_Lock;
+    case KEY_F1:               return XK_F1;
+    case KEY_F2:               return XK_F2;
+    case KEY_F3:               return XK_F3;
+    case KEY_F4:               return XK_F4;
+    case KEY_F5:               return XK_F5;
+    case KEY_F6:               return XK_F6;
+    case KEY_F7:               return XK_F7;
+    case KEY_F8:               return XK_F8;
+    case KEY_F9:               return XK_F9;
+    case KEY_F10:              return XK_F10;
+    case KEY_NUMLOCK:          return XK_Num_Lock;
+    case KEY_SCRLOCK:          return XK_Scroll_Lock;
+    case KEY_HOME:             return XK_Home;
+    case KEY_UP:               return XK_Up;
+    case KEY_PGUP:             return XK_Page_Up;
+    case KEY_MINUS_PAD:                return XK_KP_Subtract;
+    case KEY_LEFT:             return XK_Left;
+    case KEY_5_PAD:            return XK_KP_5;
+    case KEY_RIGHT:            return XK_Right;
+    case KEY_PLUS_PAD:         return XK_KP_Add;
+    case KEY_END:              return XK_End;
+    case KEY_DOWN:             return XK_Down;
+    case KEY_PGDN:             return XK_Page_Down;
+    case KEY_INSERT:           return XK_Insert;
+    case KEY_DEL:              return XK_Delete;
+    case KEY_PRTSCR:           return XK_Print;
+    case KEY_F11:              return XK_F11;
+    case KEY_F12:              return XK_F12;
+    case KEY_LWIN:             return XK_Meta_L;
+    case KEY_RWIN:             return XK_Meta_R;
+    case KEY_MENU:             return XK_Menu;
+    case KEY_PAD:              return XK_VoidSymbol;
+    case KEY_RCONTROL:         return XK_Control_R;
+    case KEY_ALTGR:            return XK_Alt_R;
+    case KEY_SLASH2:           return XK_KP_Divide;
+    case KEY_PAUSE:            return XK_Pause;
+
+    case NEW_KEY_BACKSLASH:    return XK_backslash;
+    case NEW_KEY_1_PAD:                return XK_KP_1;
+    case NEW_KEY_2_PAD:                return XK_KP_2;
+    case NEW_KEY_3_PAD:                return XK_KP_3;
+    case NEW_KEY_4_PAD:                return XK_KP_4;
+    case NEW_KEY_5_PAD:                return XK_KP_5;
+    case NEW_KEY_6_PAD:                return XK_KP_6;
+    case NEW_KEY_7_PAD:                return XK_KP_7;
+    case NEW_KEY_8_PAD:                return XK_KP_8;
+    case NEW_KEY_9_PAD:                return XK_KP_9;
+    case NEW_KEY_0_PAD:                return XK_KP_0;
+    case NEW_KEY_STOP_PAD:     return XK_KP_Separator;
+    case NEW_KEY_EQUALS_PAD:   return XK_KP_Equal;
+    case NEW_KEY_SLASH_PAD:    return XK_KP_Divide;
+    case NEW_KEY_ASTERISK_PAD: return XK_KP_Multiply;
+    case NEW_KEY_ENTER_PAD:    return XK_KP_Enter;
+
+    default:                   return XK_VoidSymbol;
+  }
+}
+
+Pixel AllegroAllocColorCell(int r, int g, int b)
+{
+  byte pixel_mapping = 0;
+  int i;
+
+  r >>= 10;
+  g >>= 10;
+  b >>= 10;
+
+  /* try to use existing colors from the global colormap */
+  for (i=0; i<global_colormap_entries_used; i++)
+  {
+    if (r == global_colormap[i].r &&
+       g == global_colormap[i].g &&
+       b == global_colormap[i].b)              /* color found */
+    {
+      pixel_mapping = i;
+      break;
+    }
+  }
+
+  if (i == global_colormap_entries_used)       /* color not found */
+  {
+    if (global_colormap_entries_used < MAX_COLORS)
+      global_colormap_entries_used++;
+
+    i = global_colormap_entries_used - 1;
+
+    global_colormap[i].r = r;
+    global_colormap[i].g = g;
+    global_colormap[i].b = b;
+
+    set_palette(global_colormap);
+
+    pixel_mapping = i;
+  }
+
+  return pixel_mapping;
+}
+
+void XMapWindow(Display *display, Window window)
+{
+  int x, y;
+  unsigned int width, height;
+  boolean mouse_off;
+
+  x = AllegroDefaultScreen().x;
+  y = AllegroDefaultScreen().y;
+  width = AllegroDefaultScreen().width;
+  height = AllegroDefaultScreen().height;
+
+  mouse_off = hide_mouse(display, x, y, width, height);
+  blit((BITMAP *)window, video_bitmap, 0, 0, x, y, width, height);
+
+  if (mouse_off)
+    unhide_mouse(display);
+}
+
+Display *XOpenDisplay(char *display_name)
+{
+  Screen *screen;
+  Display *display;
+  BITMAP *mouse_bitmap = NULL;
+
+  mouse_bitmap = Read_PCX_to_AllegroBitmap(program.msdos_pointer_filename);
+  if (mouse_bitmap == NULL)
+    return NULL;
+
+  screen = malloc(sizeof(Screen));
+  display = malloc(sizeof(Display));
+
+  screen[0].cmap = 0;
+  screen[0].root = 0;
+#if 0
+  screen[0].white_pixel = 0xFF;
+  screen[0].black_pixel = 0x00;
+#else
+  screen[0].white_pixel = AllegroAllocColorCell(0xFFFF, 0xFFFF, 0xFFFF);
+  screen[0].black_pixel = AllegroAllocColorCell(0x0000, 0x0000, 0x0000);
+#endif
+  screen[0].video_bitmap = NULL;
+
+  display->default_screen = 0;
+  display->screens = screen;
+  display->mouse_ptr = mouse_bitmap;
+
+  allegro_init();
+  allegro_init_drivers();
+  set_color_depth(8);
+
+  /* force Windows 95 to switch to fullscreen mode */
+  set_gfx_mode(GFX_AUTODETECT, 320, 200, 0, 0);
+  rest(200);
+  set_gfx_mode(GFX_AUTODETECT, XRES, YRES, 0, 0);
+
+  return display;
+}
+
+Window XCreateSimpleWindow(Display *display, Window parent, int x, int y,
+                          unsigned int width, unsigned int height,
+                          unsigned int border_width, unsigned long border,
+                          unsigned long background)
+{
+  video_bitmap = create_video_bitmap(XRES, YRES);
+  clear_to_color(video_bitmap, background);
+
+  AllegroDefaultScreen().video_bitmap = video_bitmap;
+  AllegroDefaultScreen().x = x;
+  AllegroDefaultScreen().y = y;
+  AllegroDefaultScreen().width = XRES;
+  AllegroDefaultScreen().height = YRES;
+
+  set_mouse_sprite(display->mouse_ptr);
+
+#if 0
+  set_mouse_sprite_focus(1, 1);
+#endif
+
+  set_mouse_speed(1, 1);
+  set_mouse_range(AllegroDefaultScreen().x + 1,
+                 AllegroDefaultScreen().y + 1,
+                 AllegroDefaultScreen().x + video.width + 1,
+                 AllegroDefaultScreen().y + video.height + 1);
+
+  show_video_bitmap(video_bitmap);
+
+  return (Window)video_bitmap;
+}
+
+Status XStringListToTextProperty(char **list, int count,
+                                XTextProperty *text_prop_return)
+{
+  char *string;
+
+  if (count >= 1)
+  {
+    string = malloc(strlen(list[0] + 1));
+    strcpy(string, list[0]);
+    text_prop_return->value = (unsigned char *)string;
+    return 1;
+  }
+  else
+    text_prop_return = NULL;
+
+  return 0;
+}
+
+void XFree(void *data)
+{
+  if (data)
+    free(data);
+}
+
+GC XCreateGC(Display *display, Drawable d, unsigned long value_mask,
+            XGCValues *values)
+{
+  XGCValues *gcv;
+  gcv = malloc(sizeof(XGCValues));
+  gcv->foreground = values->foreground;
+  gcv->background = values->background;
+  gcv->graphics_exposures = values->graphics_exposures;
+  gcv->clip_mask = values->clip_mask;
+  gcv->clip_x_origin = values->clip_x_origin;
+  gcv->clip_y_origin = values->clip_y_origin;
+  gcv->value_mask = value_mask;
+  return (GC)gcv;
+}
+
+void XSetClipMask(Display *display, GC gc, Pixmap pixmap)
+{
+  XGCValues *gcv = (XGCValues *)gc;
+
+  gcv->clip_mask = pixmap;
+  gcv->value_mask |= GCClipMask;
+}
+
+void XSetClipOrigin(Display *display, GC gc, int x, int y)
+{
+  XGCValues *gcv = (XGCValues *)gc;
+
+  gcv->clip_x_origin = x;
+  gcv->clip_x_origin = y;
+}
+
+void XFillRectangle(Display *display, Drawable d, GC gc, int x, int y,
+                   unsigned int width, unsigned int height)
+{
+  boolean mouse_off = FALSE;
+
+  if ((BITMAP *)d == video_bitmap)
+  {
+    x += AllegroDefaultScreen().x;
+    y += AllegroDefaultScreen().y;
+    freeze_mouse_flag = TRUE;
+    mouse_off = hide_mouse(display, x, y, width, height);
+  }
+
+  rectfill((BITMAP *)d, x, y, x + width - 1, y + height - 1,
+          ((XGCValues *)gc)->foreground);
+
+  if (mouse_off)
+    unhide_mouse(display);
+
+  freeze_mouse_flag = FALSE;
+}
+
+Pixmap XCreatePixmap(Display *display, Drawable d, unsigned int width,
+                    unsigned int height, unsigned int depth)
+{
+  BITMAP *bitmap = NULL;
+
+  if (gfx_capabilities & GFX_HW_VRAM_BLIT &&
+      width  == gfx.scrollbuffer_width && height == gfx.scrollbuffer_height)
+    bitmap = create_video_bitmap(width, height);
+
+  if (bitmap == NULL)
+    bitmap = create_bitmap(width, height);
+
+  return (Pixmap)bitmap;
+}
+
+void XSync(Display *display, Bool discard_events)
+{
+  wait_for_vsync = TRUE;
+}
+
+inline void XCopyArea(Display *display, Drawable src, Drawable dest, GC gc,
+                     int src_x, int src_y,
+                     unsigned int width, unsigned int height,
+                     int dest_x, int dest_y)
+{
+  boolean mouse_off = FALSE;
+
+  if ((BITMAP *)src == video_bitmap)
+  {
+    src_x += AllegroDefaultScreen().x;
+    src_y += AllegroDefaultScreen().y;
+  }
+
+  if ((BITMAP *)dest == video_bitmap)
+  {
+    dest_x += AllegroDefaultScreen().x;
+    dest_y += AllegroDefaultScreen().y;
+    freeze_mouse_flag = TRUE;
+    mouse_off = hide_mouse(display, dest_x, dest_y, width, height);
+  }
+
+  if (wait_for_vsync)
+  {
+    wait_for_vsync = FALSE;
+    vsync();
+  }
+
+  if (((XGCValues *)gc)->value_mask & GCClipMask)
+    masked_blit((BITMAP *)src, (BITMAP *)dest, src_x, src_y, dest_x, dest_y,
+               width, height);
+  else
+    blit((BITMAP *)src, (BITMAP *)dest, src_x, src_y, dest_x, dest_y,
+        width, height);
+
+  if (mouse_off)
+    unhide_mouse(display);
+
+  freeze_mouse_flag = FALSE;
+}
+
+static BITMAP *Image_to_AllegroBitmap(Image *image)
+{
+  BITMAP *bitmap;
+  byte *src_ptr = image->data;
+  byte pixel_mapping[MAX_COLORS];
+  unsigned int depth = 8;
+
+#if 0
+  int i, j, x, y;
+#else
+  int i, x, y;
+#endif
+
+  /* allocate new allegro bitmap structure */
+  if ((bitmap = create_bitmap_ex(depth, image->width, image->height)) == NULL)
+  {
+    errno_pcx = PCX_NoMemory;
+    return NULL;
+  }
+
+  clear(bitmap);
+
+  /* try to use existing colors from the global colormap */
+  for (i=0; i<MAX_COLORS; i++)
+  {
+
+#if 0
+    int r, g, b;
+#endif
+
+    if (!image->rgb.color_used[i])
+      continue;
+
+
+#if 0
+    r = image->rgb.red[i] >> 10;
+    g = image->rgb.green[i] >> 10;
+    b = image->rgb.blue[i] >> 10;
+
+    for (j=0; j<global_colormap_entries_used; j++)
+    {
+      if (r == global_colormap[j].r &&
+         g == global_colormap[j].g &&
+         b == global_colormap[j].b)            /* color found */
+      {
+       pixel_mapping[i] = j;
+       break;
+      }
+    }
+
+    if (j == global_colormap_entries_used)     /* color not found */
+    {
+      if (global_colormap_entries_used < MAX_COLORS)
+       global_colormap_entries_used++;
+
+      global_colormap[j].r = r;
+      global_colormap[j].g = g;
+      global_colormap[j].b = b;
+
+      pixel_mapping[i] = j;
+    }
+#else
+    pixel_mapping[i] = AllegroAllocColorCell(image->rgb.red[i],
+                                            image->rgb.green[i],
+                                            image->rgb.blue[i]);
+#endif
+
+  }
+
+  /* copy bitmap data */
+  for (y=0; y<image->height; y++)
+    for (x=0; x<image->width; x++)
+      putpixel(bitmap, x, y, pixel_mapping[*src_ptr++]);
+
+  return bitmap;
+}
+
+static BITMAP *Read_PCX_to_AllegroBitmap(char *filename)
+{
+  BITMAP *bitmap;
+  Image *image;
+
+  /* read the graphic file in PCX format to internal image structure */
+  if ((image = Read_PCX_to_Image(filename)) == NULL)
+    return NULL;
+
+  /* convert internal image structure to allegro bitmap structure */
+  if ((bitmap = Image_to_AllegroBitmap(image)) == NULL)
+    return NULL;
+
+  set_palette(global_colormap);
+
+  return bitmap;
+}
+
+int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename,
+                      Pixmap *pixmap, Pixmap *pixmap_mask)
+{
+  BITMAP *bitmap;
+
+  if ((bitmap = Read_PCX_to_AllegroBitmap(filename)) == NULL)
+    return errno_pcx;
+
+  *pixmap = (Pixmap)bitmap;
+#if 0
+  *pixmap_mask = (Pixmap)bitmap;
+  /* !!! two pointers on same bitmap => second free() fails !!! */
+#else
+  /* pixmap_mask will never be used in Allegro (which uses masked_blit()),
+     so use non-NULL dummy pointer to empty Pixmap */
+  /*
+  *pixmap_mask = (Pixmap)checked_calloc(sizeof(Pixmap));
+  */
+  *pixmap_mask = (Pixmap)DUMMY_MASK;
+#endif
+
+  return PCX_Success;
+}
+
+int XReadBitmapFile(Display *display, Drawable d, char *filename,
+                   unsigned int *width_return, unsigned int *height_return,
+                   Pixmap *bitmap_return,
+                   int *x_hot_return, int *y_hot_return)
+{
+  BITMAP *bitmap;
+
+  if ((bitmap = Read_PCX_to_AllegroBitmap(filename)) == NULL)
+    return BitmapOpenFailed;
+
+  *width_return = bitmap->w;
+  *height_return = bitmap->h;
+  *x_hot_return = -1;
+  *y_hot_return = -1;
+  *bitmap_return = (Pixmap)bitmap;
+
+  return BitmapSuccess;
+}
+
+void XFreePixmap(Display *display, Pixmap pixmap)
+{
+  if (pixmap != DUMMY_MASK &&
+      (is_memory_bitmap((BITMAP *)pixmap) ||
+       is_screen_bitmap((BITMAP *)pixmap)))
+    destroy_bitmap((BITMAP *)pixmap);
+}
+
+void XFreeGC(Display *display, GC gc)
+{
+  XGCValues *gcv;
+
+  gcv = (XGCValues *)gc;
+  if (gcv)
+    free(gcv);
+}
+
+void XUnmapWindow(Display *display, Window window)
+{
+}
+
+void XCloseDisplay(Display *display)
+{
+  BITMAP *bitmap = video_bitmap;
+
+  if (is_screen_bitmap(bitmap))
+    destroy_bitmap(bitmap);
+
+  if (display->screens)
+    free(display->screens);
+
+  if (display)
+    free(display);
+
+  /* return to text mode (or DOS box on Windows screen) */
+  set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
+}
+
+void XNextEvent(Display *display, XEvent *event_return)
+{
+  while (!pending_events)
+    XPending(display);
+
+  memcpy(event_return, &event_buffer[pending_events], sizeof(XEvent));
+  pending_events--;
+}
+
+static void NewKeyEvent(int key_press_state, KeySym keysym)
+{
+  XKeyEvent *xkey;
+
+  if (pending_events >= MAX_EVENT_BUFFER)
+    return;
+
+  pending_events++;
+  xkey = (XKeyEvent *)&event_buffer[pending_events];
+  xkey->type = key_press_state;
+  xkey->state = (unsigned int)keysym;
+}
+
+#define HANDLE_RAW_KB_ALL_KEYS                 0
+#define HANDLE_RAW_KB_MODIFIER_KEYS_ONLY       1
+
+static int modifier_scancode[] =
+{
+  KEY_LSHIFT,
+  KEY_RSHIFT,
+  KEY_LCONTROL,
+  KEY_RCONTROL,
+  KEY_ALT,
+  KEY_ALTGR,
+  KEY_LWIN,
+  KEY_RWIN,
+  KEY_CAPSLOCK,
+  KEY_NUMLOCK,
+  KEY_SCRLOCK,
+  -1
+};
+
+static void HandleKeyboardRaw(int mode)
+{
+  int i;
+
+  for (i=0; i<MAX_SCANCODES; i++)
+  {
+    int scancode, new_state, event_type;
+    char key_pressed;
+
+    if (mode == HANDLE_RAW_KB_MODIFIER_KEYS_ONLY)
+    {
+      if ((scancode = modifier_scancode[i]) == -1)
+       return;
+    }
+    else
+      scancode = i;
+
+    key_pressed = key[scancode];
+    new_state = (key_pressed ? KeyPressMask : KeyReleaseMask);
+    event_type = (key_pressed ? KeyPress : KeyRelease);
+
+    if (key_press_state[i] == new_state)       /* state not changed */
+      continue;
+
+    key_press_state[i] = new_state;
+
+    NewKeyEvent(event_type, ScancodeToKeySym(scancode));
+  }
+}
+
+static void HandleKeyboardEvent()
+{
+  if (keypressed())
+  {
+    int key_info = readkey();
+    int scancode = (key_info >> 8);
+    int ascii = (key_info & 0xff);
+    KeySym keysym = ScancodeToKeySym(scancode);
+
+    if (scancode == KEY_PAD)
+    {
+      /* keys on the numeric keypad return just scancode 'KEY_PAD'
+        for some reason, so we must handle them separately */
+
+      if (ascii >= '0' && ascii <= '9')
+       keysym = XK_KP_0 + (KeySym)(ascii - '0');
+      else if (ascii == '.')
+       keysym = XK_KP_Separator;
+    }
+    else if (ascii >= ' ' && ascii <= 'Z')
+      keysym = XK_space + (KeySym)(ascii - ' ');
+    else if (ascii == '^')
+      keysym = XK_asciicircum;
+    else if (ascii == '_')
+      keysym = XK_underscore;
+    else if (ascii == 'Ä')
+      keysym = XK_Adiaeresis;
+    else if (ascii == 'Ö')
+      keysym = XK_Odiaeresis;
+    else if (ascii == 'Ãœ')
+      keysym = XK_Udiaeresis;
+    else if (ascii == 'ä')
+      keysym = XK_adiaeresis;
+    else if (ascii == 'ö')
+      keysym = XK_odiaeresis;
+    else if (ascii == 'ü')
+      keysym = XK_udiaeresis;
+    else if (ascii == 'ß')
+      keysym = XK_ssharp;
+
+    NewKeyEvent(KeyPress, keysym);
+  }
+  else if (key_shifts & (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG))
+  {
+    /* the allegro function keypressed() does not give us single pressed
+       modifier keys, so we must detect them with the internal global
+       allegro variable 'key_shifts' and then handle them separately */
+
+    HandleKeyboardRaw(HANDLE_RAW_KB_MODIFIER_KEYS_ONLY);
+  }
+}
+
+int XPending(Display *display)
+{
+  XButtonEvent *xbutton;
+  XMotionEvent *xmotion;
+  int i;
+
+  /* When using 'HandleKeyboardRaw()', keyboard input is also stored in
+     the allegro keyboard input buffer and would be available a second
+     time by calling 'HandleKeyboardEvent()'. To avoid double keyboard
+     events, the allegro function 'clear_keybuf()' must be called each
+     time when switching from calling 'HandleKeyboardRaw()' to calling
+     'HandleKeyboardEvent()' to get keyboard input, which is actually
+     done by 'XAutoRepeatOn()' which sets keyboard_auto_repeat to TRUE. */
+
+  /* keyboard event */
+  if (keyboard_auto_repeat)
+    HandleKeyboardEvent();
+  else
+    HandleKeyboardRaw(HANDLE_RAW_KB_ALL_KEYS);
+
+  /* mouse motion event */
+  if (mouse_pos != last_mouse_pos)
+  {
+    last_mouse_pos = mouse_pos;
+    pending_events++;
+    xmotion = (XMotionEvent *)&event_buffer[pending_events];
+    xmotion->type = MotionNotify;
+    xmotion->x = mouse_x - AllegroDefaultScreen().x;
+    xmotion->y = mouse_y - AllegroDefaultScreen().y;
+  }
+
+  /* mouse button event */
+  if (mouse_b != last_mouse_b)
+  {
+    for (i=0; i<3; i++)                /* check all three mouse buttons */
+    {
+      int bitmask = (1 << i);
+
+      if ((last_mouse_b & bitmask) != (mouse_b & bitmask))
+      {
+       int mapping[3] = { 1, 3, 2 };
+
+       pending_events++;
+        xbutton = (XButtonEvent *)&event_buffer[pending_events];
+        xbutton->type = (mouse_b & bitmask ? ButtonPress : ButtonRelease);
+        xbutton->button = mapping[i];
+       xbutton->x = mouse_x - AllegroDefaultScreen().x;
+       xbutton->y = mouse_y - AllegroDefaultScreen().y;
+      }
+    }
+    last_mouse_b = mouse_b;
+  }
+
+  return pending_events;
+}
+
+KeySym XLookupKeysym(XKeyEvent *key_event, int index)
+{
+  return key_event->state;
+}
+
+int XLookupString(XKeyEvent *key_event, char *buffer, int buffer_size,
+                 KeySym *key, XComposeStatus *compose)
+{
+  *key = key_event->state;
+  return 0;
+}
+
+void XSetForeground(Display *display, GC gc, unsigned long pixel)
+{
+  XGCValues *gcv = (XGCValues *)gc;
+
+  gcv->foreground = pixel;
+}
+
+void XDrawLine(Display *display, Drawable d, GC gc,
+              int x1, int y1, int x2, int y2)
+{
+  XGCValues *gcv = (XGCValues *)gc;
+  boolean mouse_off = FALSE;
+
+  if ((BITMAP *)d == video_bitmap)
+  {
+    x1 += AllegroDefaultScreen().x;
+    y1 += AllegroDefaultScreen().y;
+    x2 += AllegroDefaultScreen().x;
+    y2 += AllegroDefaultScreen().y;
+    freeze_mouse_flag = TRUE;
+    mouse_off = hide_mouse(display, MIN(x1, x2), MIN(y1, y2),
+                          MAX(x1, x2) - MIN(x1, x2),
+                          MAX(y1, y2) - MIN(y1, y2));
+  }
+
+  line((BITMAP *)d, x1, y1, x2, y2, gcv->foreground);
+
+  if (mouse_off)
+    unhide_mouse(display);
+
+  freeze_mouse_flag = FALSE;
+}
+
+void XDestroyImage(XImage *ximage)
+{
+}
+
+void XDestroyWindow(Display *display, Window window)
+{
+}
+
+Bool XQueryPointer(Display *display, Window window,
+                  Window *root, Window *child, int *root_x, int *root_y,
+                  int *win_x, int *win_y, unsigned int *mask)
+{
+  *win_x = mouse_x - AllegroDefaultScreen().x;
+  *win_y = mouse_y - AllegroDefaultScreen().y;
+
+  return True;
+}
+
+void XAutoRepeatOn(Display *display)
+{
+  keyboard_auto_repeat = TRUE;
+  clear_keybuf();
+}
+
+void XAutoRepeatOff(Display *display)
+{
+  keyboard_auto_repeat = FALSE;
+}
+
+void AllegroDrawLine(Drawable d, int from_x, int from_y, int to_x, int to_y,
+                    Pixel color)
+{
+  boolean mouse_off = FALSE;
+
+  if ((BITMAP *)d == video_bitmap)
+  {
+    int dx = AllegroDefaultScreen().x;
+    int dy = AllegroDefaultScreen().y;
+    int x1, y1, x2, y2;
+
+    from_x += dx;
+    from_y += dy;
+    to_x += dx;
+    to_y += dy;
+
+    x1 = (from_x < to_x ? from_x : to_x);
+    y1 = (from_y < to_y ? from_y : to_y);
+    x2 = (from_x < to_x ? to_x : from_x);
+    y2 = (from_y < to_y ? to_y : from_y);
+
+    freeze_mouse_flag = TRUE;
+    mouse_off = hide_mouse(display, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
+  }
+
+  line((BITMAP *)d, from_x, from_y, to_x, to_y, color);
+
+  if (mouse_off)
+    unhide_mouse(display);
+
+  freeze_mouse_flag = FALSE;
+}
+
+Pixel AllegroGetPixel(Drawable d, int x, int y)
+{
+  return getpixel((BITMAP *)d, x, y);
+}
+
+void MSDOSOpenAudio(void)
+{
+  if (allegro_init_audio())
+  {
+    audio.sound_available = TRUE;
+    audio.music_available = TRUE;
+    audio.loops_available = TRUE;
+    audio.sound_enabled = TRUE;
+  }
+
+  InitPlaylist();
+}
+
+void MSDOSCloseAudio(void)
+{
+  /* nothing to be done here */
+}
+
+void NetworkServer(int port, int serveronly)
+{
+  Error(ERR_WARN, "networking not supported in DOS version");
+}
+
+#endif /* PLATFORM_MSDOS */
diff --git a/src/libgame/msdos.h b/src/libgame/msdos.h
new file mode 100644 (file)
index 0000000..40a42da
--- /dev/null
@@ -0,0 +1,744 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* msdos.h                                                  *
+***********************************************************/
+
+#ifndef MSDOS_H
+#define MSDOS_H
+
+#include <time.h>
+#include "allegro.h"
+
+
+/* symbol 'window' is defined in DJGPP cross-compiler in libc.a(conio.o) */
+#define window window_djgpp
+
+/* symbol 'font' is defined in "allegro.h" */
+#define font font_allegro
+
+/* system dependent definitions */
+
+#define TARGET_STRING          "DOS"
+
+/* allegro defines TRUE as -1 */
+#ifdef TRUE
+#undef TRUE
+#undef FALSE
+#endif
+
+#define TRUE   1
+#define FALSE  0
+
+#define XRES   800
+#define YRES   600
+
+/* additional Allegro keyboard mapping */
+
+/* The following are all undefined in Allegro */
+#define NEW_KEY_BACKSLASH      86
+#define NEW_KEY_1_PAD          101
+#define NEW_KEY_2_PAD          102
+#define NEW_KEY_3_PAD          103
+#define NEW_KEY_4_PAD          104
+#define NEW_KEY_5_PAD          105
+#define NEW_KEY_6_PAD          106
+#define NEW_KEY_7_PAD          107
+#define NEW_KEY_8_PAD          108
+#define NEW_KEY_9_PAD          109
+#define NEW_KEY_0_PAD          110
+#define NEW_KEY_STOP_PAD       111
+#define NEW_KEY_EQUALS_PAD     112
+#define NEW_KEY_SLASH_PAD      113
+#define NEW_KEY_ASTERISK_PAD   114
+#define NEW_KEY_ENTER_PAD      115
+
+/* X11 keyboard mapping (from 'keysymdef.h') */
+
+#define XK_VoidSymbol          0xFFFFFF        /* void symbol */
+
+/*
+ * TTY Functions, cleverly chosen to map to ascii, for convenience of
+ * programming, but could have been arbitrary (at the cost of lookup
+ * tables in client code.
+ */
+
+#define XK_BackSpace           0xFF08  /* back space, back char */
+#define XK_Tab                 0xFF09
+#define XK_Linefeed            0xFF0A  /* Linefeed, LF */
+#define XK_Clear               0xFF0B
+#define XK_Return              0xFF0D  /* Return, enter */
+#define XK_Pause               0xFF13  /* Pause, hold */
+#define XK_Scroll_Lock         0xFF14
+#define XK_Sys_Req             0xFF15
+#define XK_Escape              0xFF1B
+#define XK_Delete              0xFFFF  /* Delete, rubout */
+
+/* International & multi-key character composition */
+
+#define XK_Multi_key           0xFF20  /* Multi-key character compose */
+#define XK_SingleCandidate     0xFF3C
+#define XK_MultipleCandidate   0xFF3D
+#define XK_PreviousCandidate   0xFF3E
+
+/* Cursor control & motion */
+
+#define XK_Home                        0xFF50
+#define XK_Left                        0xFF51  /* Move left, left arrow */
+#define XK_Up                  0xFF52  /* Move up, up arrow */
+#define XK_Right               0xFF53  /* Move right, right arrow */
+#define XK_Down                        0xFF54  /* Move down, down arrow */
+#define XK_Prior               0xFF55  /* Prior, previous */
+#define XK_Page_Up             0xFF55
+#define XK_Next                        0xFF56  /* Next */
+#define XK_Page_Down           0xFF56
+#define XK_End                 0xFF57  /* EOL */
+#define XK_Begin               0xFF58  /* BOL */
+
+/* Misc Functions */
+
+#define XK_Select              0xFF60  /* Select, mark */
+#define XK_Print               0xFF61
+#define XK_Execute             0xFF62  /* Execute, run, do */
+#define XK_Insert              0xFF63  /* Insert, insert here */
+#define XK_Undo                        0xFF65  /* Undo, oops */
+#define XK_Redo                        0xFF66  /* redo, again */
+#define XK_Menu                        0xFF67
+#define XK_Find                        0xFF68  /* Find, search */
+#define XK_Cancel              0xFF69  /* Cancel, stop, abort, exit */
+#define XK_Help                        0xFF6A  /* Help */
+#define XK_Break               0xFF6B
+#define XK_Mode_switch         0xFF7E  /* Character set switch */
+#define XK_script_switch        0xFF7E  /* Alias for mode_switch */
+#define XK_Num_Lock            0xFF7F
+
+/* Keypad Functions, keypad numbers cleverly chosen to map to ascii */
+
+#define XK_KP_Space            0xFF80  /* space */
+#define XK_KP_Tab              0xFF89
+#define XK_KP_Enter            0xFF8D  /* enter */
+#define XK_KP_F1               0xFF91  /* PF1, KP_A, ... */
+#define XK_KP_F2               0xFF92
+#define XK_KP_F3               0xFF93
+#define XK_KP_F4               0xFF94
+#define XK_KP_Home             0xFF95
+#define XK_KP_Left             0xFF96
+#define XK_KP_Up               0xFF97
+#define XK_KP_Right            0xFF98
+#define XK_KP_Down             0xFF99
+#define XK_KP_Prior            0xFF9A
+#define XK_KP_Page_Up          0xFF9A
+#define XK_KP_Next             0xFF9B
+#define XK_KP_Page_Down                0xFF9B
+#define XK_KP_End              0xFF9C
+#define XK_KP_Begin            0xFF9D
+#define XK_KP_Insert           0xFF9E
+#define XK_KP_Delete           0xFF9F
+#define XK_KP_Equal            0xFFBD  /* equals */
+#define XK_KP_Multiply         0xFFAA
+#define XK_KP_Add              0xFFAB
+#define XK_KP_Separator                0xFFAC  /* separator, often comma */
+#define XK_KP_Subtract         0xFFAD
+#define XK_KP_Decimal          0xFFAE
+#define XK_KP_Divide           0xFFAF
+
+#define XK_KP_0                        0xFFB0
+#define XK_KP_1                        0xFFB1
+#define XK_KP_2                        0xFFB2
+#define XK_KP_3                        0xFFB3
+#define XK_KP_4                        0xFFB4
+#define XK_KP_5                        0xFFB5
+#define XK_KP_6                        0xFFB6
+#define XK_KP_7                        0xFFB7
+#define XK_KP_8                        0xFFB8
+#define XK_KP_9                        0xFFB9
+
+/*
+ * Auxilliary Functions; note the duplicate definitions for left and right
+ * function keys;  Sun keyboards and a few other manufactures have such
+ * function key groups on the left and/or right sides of the keyboard.
+ * We've not found a keyboard with more than 35 function keys total.
+ */
+
+#define XK_F1                  0xFFBE
+#define XK_F2                  0xFFBF
+#define XK_F3                  0xFFC0
+#define XK_F4                  0xFFC1
+#define XK_F5                  0xFFC2
+#define XK_F6                  0xFFC3
+#define XK_F7                  0xFFC4
+#define XK_F8                  0xFFC5
+#define XK_F9                  0xFFC6
+#define XK_F10                 0xFFC7
+#define XK_F11                 0xFFC8
+#define XK_L1                  0xFFC8
+#define XK_F12                 0xFFC9
+#define XK_L2                  0xFFC9
+#define XK_F13                 0xFFCA
+#define XK_L3                  0xFFCA
+#define XK_F14                 0xFFCB
+#define XK_L4                  0xFFCB
+#define XK_F15                 0xFFCC
+#define XK_L5                  0xFFCC
+#define XK_F16                 0xFFCD
+#define XK_L6                  0xFFCD
+#define XK_F17                 0xFFCE
+#define XK_L7                  0xFFCE
+#define XK_F18                 0xFFCF
+#define XK_L8                  0xFFCF
+#define XK_F19                 0xFFD0
+#define XK_L9                  0xFFD0
+#define XK_F20                 0xFFD1
+#define XK_L10                 0xFFD1
+#define XK_F21                 0xFFD2
+#define XK_R1                  0xFFD2
+#define XK_F22                 0xFFD3
+#define XK_R2                  0xFFD3
+#define XK_F23                 0xFFD4
+#define XK_R3                  0xFFD4
+#define XK_F24                 0xFFD5
+#define XK_R4                  0xFFD5
+#define XK_F25                 0xFFD6
+#define XK_R5                  0xFFD6
+#define XK_F26                 0xFFD7
+#define XK_R6                  0xFFD7
+#define XK_F27                 0xFFD8
+#define XK_R7                  0xFFD8
+#define XK_F28                 0xFFD9
+#define XK_R8                  0xFFD9
+#define XK_F29                 0xFFDA
+#define XK_R9                  0xFFDA
+#define XK_F30                 0xFFDB
+#define XK_R10                 0xFFDB
+#define XK_F31                 0xFFDC
+#define XK_R11                 0xFFDC
+#define XK_F32                 0xFFDD
+#define XK_R12                 0xFFDD
+#define XK_F33                 0xFFDE
+#define XK_R13                 0xFFDE
+#define XK_F34                 0xFFDF
+#define XK_R14                 0xFFDF
+#define XK_F35                 0xFFE0
+#define XK_R15                 0xFFE0
+
+/* Modifiers */
+
+#define XK_Shift_L             0xFFE1  /* Left shift */
+#define XK_Shift_R             0xFFE2  /* Right shift */
+#define XK_Control_L           0xFFE3  /* Left control */
+#define XK_Control_R           0xFFE4  /* Right control */
+#define XK_Caps_Lock           0xFFE5  /* Caps lock */
+#define XK_Shift_Lock          0xFFE6  /* Shift lock */
+
+#define XK_Meta_L              0xFFE7  /* Left meta */
+#define XK_Meta_R              0xFFE8  /* Right meta */
+#define XK_Alt_L               0xFFE9  /* Left alt */
+#define XK_Alt_R               0xFFEA  /* Right alt */
+#define XK_Super_L             0xFFEB  /* Left super */
+#define XK_Super_R             0xFFEC  /* Right super */
+#define XK_Hyper_L             0xFFED  /* Left hyper */
+#define XK_Hyper_R             0xFFEE  /* Right hyper */
+
+/*
+ *  Latin 1
+ *  Byte 3 = 0
+ */
+
+#define XK_space               0x020
+#define XK_exclam              0x021
+#define XK_quotedbl            0x022
+#define XK_numbersign          0x023
+#define XK_dollar              0x024
+#define XK_percent             0x025
+#define XK_ampersand           0x026
+#define XK_apostrophe          0x027
+#define XK_quoteright          0x027   /* deprecated */
+#define XK_parenleft           0x028
+#define XK_parenright          0x029
+#define XK_asterisk            0x02a
+#define XK_plus                0x02b
+#define XK_comma               0x02c
+#define XK_minus               0x02d
+#define XK_period              0x02e
+#define XK_slash               0x02f
+#define XK_0                   0x030
+#define XK_1                   0x031
+#define XK_2                   0x032
+#define XK_3                   0x033
+#define XK_4                   0x034
+#define XK_5                   0x035
+#define XK_6                   0x036
+#define XK_7                   0x037
+#define XK_8                   0x038
+#define XK_9                   0x039
+#define XK_colon               0x03a
+#define XK_semicolon           0x03b
+#define XK_less                0x03c
+#define XK_equal               0x03d
+#define XK_greater             0x03e
+#define XK_question            0x03f
+#define XK_at                  0x040
+#define XK_A                   0x041
+#define XK_B                   0x042
+#define XK_C                   0x043
+#define XK_D                   0x044
+#define XK_E                   0x045
+#define XK_F                   0x046
+#define XK_G                   0x047
+#define XK_H                   0x048
+#define XK_I                   0x049
+#define XK_J                   0x04a
+#define XK_K                   0x04b
+#define XK_L                   0x04c
+#define XK_M                   0x04d
+#define XK_N                   0x04e
+#define XK_O                   0x04f
+#define XK_P                   0x050
+#define XK_Q                   0x051
+#define XK_R                   0x052
+#define XK_S                   0x053
+#define XK_T                   0x054
+#define XK_U                   0x055
+#define XK_V                   0x056
+#define XK_W                   0x057
+#define XK_X                   0x058
+#define XK_Y                   0x059
+#define XK_Z                   0x05a
+#define XK_bracketleft         0x05b
+#define XK_backslash           0x05c
+#define XK_bracketright        0x05d
+#define XK_asciicircum         0x05e
+#define XK_underscore          0x05f
+#define XK_grave               0x060
+#define XK_quoteleft           0x060   /* deprecated */
+#define XK_a                   0x061
+#define XK_b                   0x062
+#define XK_c                   0x063
+#define XK_d                   0x064
+#define XK_e                   0x065
+#define XK_f                   0x066
+#define XK_g                   0x067
+#define XK_h                   0x068
+#define XK_i                   0x069
+#define XK_j                   0x06a
+#define XK_k                   0x06b
+#define XK_l                   0x06c
+#define XK_m                   0x06d
+#define XK_n                   0x06e
+#define XK_o                   0x06f
+#define XK_p                   0x070
+#define XK_q                   0x071
+#define XK_r                   0x072
+#define XK_s                   0x073
+#define XK_t                   0x074
+#define XK_u                   0x075
+#define XK_v                   0x076
+#define XK_w                   0x077
+#define XK_x                   0x078
+#define XK_y                   0x079
+#define XK_z                   0x07a
+#define XK_braceleft           0x07b
+#define XK_bar                 0x07c
+#define XK_braceright          0x07d
+#define XK_asciitilde          0x07e
+
+#define XK_nobreakspace        0x0a0
+#define XK_exclamdown          0x0a1
+#define XK_cent                       0x0a2
+#define XK_sterling            0x0a3
+#define XK_currency            0x0a4
+#define XK_yen                 0x0a5
+#define XK_brokenbar           0x0a6
+#define XK_section             0x0a7
+#define XK_diaeresis           0x0a8
+#define XK_copyright           0x0a9
+#define XK_ordfeminine         0x0aa
+#define XK_guillemotleft       0x0ab   /* left angle quotation mark */
+#define XK_notsign             0x0ac
+#define XK_hyphen              0x0ad
+#define XK_registered          0x0ae
+#define XK_macron              0x0af
+#define XK_degree              0x0b0
+#define XK_plusminus           0x0b1
+#define XK_twosuperior         0x0b2
+#define XK_threesuperior       0x0b3
+#define XK_acute               0x0b4
+#define XK_mu                  0x0b5
+#define XK_paragraph           0x0b6
+#define XK_periodcentered      0x0b7
+#define XK_cedilla             0x0b8
+#define XK_onesuperior         0x0b9
+#define XK_masculine           0x0ba
+#define XK_guillemotright      0x0bb   /* right angle quotation mark */
+#define XK_onequarter          0x0bc
+#define XK_onehalf             0x0bd
+#define XK_threequarters       0x0be
+#define XK_questiondown        0x0bf
+#define XK_Agrave              0x0c0
+#define XK_Aacute              0x0c1
+#define XK_Acircumflex         0x0c2
+#define XK_Atilde              0x0c3
+#define XK_Adiaeresis          0x0c4
+#define XK_Aring               0x0c5
+#define XK_AE                  0x0c6
+#define XK_Ccedilla            0x0c7
+#define XK_Egrave              0x0c8
+#define XK_Eacute              0x0c9
+#define XK_Ecircumflex         0x0ca
+#define XK_Ediaeresis          0x0cb
+#define XK_Igrave              0x0cc
+#define XK_Iacute              0x0cd
+#define XK_Icircumflex         0x0ce
+#define XK_Idiaeresis          0x0cf
+#define XK_ETH                 0x0d0
+#define XK_Eth                 0x0d0   /* deprecated */
+#define XK_Ntilde              0x0d1
+#define XK_Ograve              0x0d2
+#define XK_Oacute              0x0d3
+#define XK_Ocircumflex         0x0d4
+#define XK_Otilde              0x0d5
+#define XK_Odiaeresis          0x0d6
+#define XK_multiply            0x0d7
+#define XK_Ooblique            0x0d8
+#define XK_Ugrave              0x0d9
+#define XK_Uacute              0x0da
+#define XK_Ucircumflex         0x0db
+#define XK_Udiaeresis          0x0dc
+#define XK_Yacute              0x0dd
+#define XK_THORN               0x0de
+#define XK_Thorn               0x0de   /* deprecated */
+#define XK_ssharp              0x0df
+#define XK_agrave              0x0e0
+#define XK_aacute              0x0e1
+#define XK_acircumflex         0x0e2
+#define XK_atilde              0x0e3
+#define XK_adiaeresis          0x0e4
+#define XK_aring               0x0e5
+#define XK_ae                  0x0e6
+#define XK_ccedilla            0x0e7
+#define XK_egrave              0x0e8
+#define XK_eacute              0x0e9
+#define XK_ecircumflex         0x0ea
+#define XK_ediaeresis          0x0eb
+#define XK_igrave              0x0ec
+#define XK_iacute              0x0ed
+#define XK_icircumflex         0x0ee
+#define XK_idiaeresis          0x0ef
+#define XK_eth                 0x0f0
+#define XK_ntilde              0x0f1
+#define XK_ograve              0x0f2
+#define XK_oacute              0x0f3
+#define XK_ocircumflex         0x0f4
+#define XK_otilde              0x0f5
+#define XK_odiaeresis          0x0f6
+#define XK_division            0x0f7
+#define XK_oslash              0x0f8
+#define XK_ugrave              0x0f9
+#define XK_uacute              0x0fa
+#define XK_ucircumflex         0x0fb
+#define XK_udiaeresis          0x0fc
+#define XK_yacute              0x0fd
+#define XK_thorn               0x0fe
+#define XK_ydiaeresis          0x0ff
+
+/* end of X11 keyboard mapping */
+
+#define JOYSTICK_FILENAME      "joystick.cnf"
+
+#define screen myscreen
+
+#define XFlush(a)
+#define XGetImage(a,b,c,d,e,f,g,h)             ((XImage *) NULL)
+#define XDisplayName(a)                                ((char *) NULL)
+#define XFreeColors(a,b,c,d,e)
+#define XSelectInput(a,b,c)
+#define XDefaultDepth(a,b)                     (8)
+#define XSetWMProperties(a,b,c,d,e,f,g,h,i)
+
+#define MAX_EVENT_BUFFER       256
+#define MAX_SCANCODES          128
+
+#define True                   1
+#define False                  0
+#define None                   0L
+
+#define DUMMY_FILE             ((void *) -1)
+#define DUMMY_MASK             (-1)
+
+#define KeyPressMask           (1L << 0)  
+#define KeyReleaseMask         (1L << 1)  
+#define ButtonPressMask                (1L << 2)  
+#define ButtonReleaseMask      (1L << 3)  
+#define ButtonMotionMask       (1L << 13) 
+#define ExposureMask           (1L << 15) 
+#define StructureNotifyMask    (1L << 17) 
+#define FocusChangeMask                (1L << 21) 
+
+#define KeyPress               2
+#define KeyRelease             3
+#define ButtonPress            4
+#define ButtonRelease          5
+#define MotionNotify           6
+#define FocusIn                        9
+#define FocusOut               10
+#define Expose                 12
+#define UnmapNotify            18
+#define MapNotify              19
+#define ClientMessage          33
+
+#define LineSolid               0
+#define LineOnOffDash           1
+#define LineDoubleDash          2
+
+#define CapNotLast              0
+#define CapButt                 1
+#define CapRound                2
+#define CapProjecting           3
+
+#define JoinMiter               0
+#define JoinRound               1
+#define JoinBevel               2
+
+#define GCForeground            (1L << 2)
+#define GCBackground            (1L << 3)
+#define GCLineWidth             (1L << 4)
+#define GCLineStyle             (1L << 5)
+#define GCCapStyle              (1L << 6)
+#define GCJoinStyle             (1L << 7)
+#define GCGraphicsExposures     (1L << 16)
+#define GCClipMask             (1L << 19)
+
+#define NormalState    1       /* most applications want to start this way */
+#define InputHint              (1L << 0)
+#define StateHint              (1L << 1)
+#define IconPixmapHint         (1L << 2)
+#define IconMaskHint           (1L << 5)
+#define PSize                  (1L << 3) /* program specified size */
+#define PMinSize               (1L << 4) /* program specified minimum size */
+#define PMaxSize               (1L << 5) /* program specified maximum size */
+
+#define PCX_Success             0
+#define PCX_OpenFailed         -1
+#define PCX_ReadFailed         -2
+#define        PCX_FileInvalid         -3
+#define PCX_NoMemory           -4
+#define PCX_ColorFailed                -5
+
+#define BitmapSuccess          0
+#define BitmapOpenFailed       1
+#define BitmapFileInvalid      2
+#define BitmapNoMemory         3
+
+#define ZPixmap                        2       /* depth == drawable depth */
+
+#define DefaultScreen(dpy)       (((_XPrivDisplay)dpy)->default_screen)
+#define DefaultColormap(dpy, scr) (ScreenOfDisplay(dpy,scr)->cmap)
+#define ScreenOfDisplay(dpy, scr) (&((_XPrivDisplay)dpy)->screens[scr])
+#define BlackPixel(dpy, scr)     (ScreenOfDisplay(dpy,scr)->black_pixel)
+#define WhitePixel(dpy, scr)     (ScreenOfDisplay(dpy,scr)->white_pixel)
+#define RootWindow(dpy, scr)     (ScreenOfDisplay(dpy,scr)->root)
+#define AllPlanes                ((unsigned long)~0L)
+
+#define DefaultVisual(dpy, scr)          (NULL)
+#define DefaultDepth(dpy, scr)   (NULL)
+#define XDisplayWidth(dpy, scr)          (XRES)
+#define XDisplayHeight(dpy, scr)  (YRES)
+
+#define XGetPixel(ximage, x, y) \
+        ((*((ximage)->f.get_pixel))((ximage), (x), (y)))
+
+typedef unsigned long Pixel;   /* Index into colormap */
+typedef unsigned long XID;
+typedef XID Window;
+typedef XID Drawable;
+typedef XID Pixmap;
+typedef XID Colormap;
+typedef XID KeySym;
+typedef XID GContext;
+typedef struct _XDisplay Display;
+typedef long Visual;
+typedef long XVisualInfo;
+typedef long Atom;
+typedef int Status;
+typedef int Bool;
+typedef int XComposeStatus;    /* we don't need the real type */
+
+typedef struct _XGC
+{
+  GContext gid;                        /* protocol ID for graphics context */
+} *GC;
+
+typedef struct
+{
+  Colormap cmap;               /* default color map */
+  Window root;                 /* root window id */
+  unsigned long white_pixel;   /* white pixel value */
+  unsigned long black_pixel;   /* black pixel value */
+  int x;
+  int y;
+  unsigned int width;
+  unsigned int height;
+  BITMAP *video_bitmap;
+} Screen;
+
+typedef struct _XDisplay
+{
+  int default_screen;          /* default screen for operations */
+  Screen *screens;             /* pointer to list of screens */
+  BITMAP *mouse_ptr;
+} *_XPrivDisplay;
+
+typedef struct _XImage
+{
+  struct funcs
+  {
+    unsigned long (*get_pixel) (struct _XImage *, int, int);
+  } f;
+} XImage;
+
+typedef struct
+{
+  long flags;          /* marks which fields in this structure are defined */
+  int width, height;   /* should set so old wm's don't mess up */
+  int min_width, min_height;
+  int max_width, max_height;
+} XSizeHints;
+
+typedef struct
+{
+  long flags;          /* marks which fields in this structure are defined */
+  Bool input;          /* does this application rely on the window manager to
+                          get keyboard input? */
+  int initial_state;   /* see below */
+  Pixmap icon_pixmap;  /* pixmap to be used as icon */
+  Pixmap icon_mask;    /* icon mask bitmap */
+} XWMHints;
+
+typedef struct
+{
+  char *res_name;
+  char *res_class;
+} XClassHint;
+
+typedef struct
+{
+  unsigned char *value;                /* same as Property routines */
+} XTextProperty;
+
+typedef struct
+{
+  unsigned long foreground;    /* foreground pixel */
+  unsigned long background;    /* background pixel */
+  Bool graphics_exposures;     /* boolean, should exposures be generated */
+  Pixmap clip_mask;            /* bitmap clipping; other calls for rects */
+  int clip_x_origin;           /* x origin for clipping */
+  int clip_y_origin;           /* y origin for clipping */
+  unsigned long value_mask;
+  int line_width;              /* line width */
+  int line_style;              /* LineSolid, LineOnOffDash, LineDoubleDash */
+  int cap_style;               /* CapNotLast, CapButt, 
+                                  CapRound, CapProjecting */
+  int join_style;              /* JoinMiter, JoinRound, JoinBevel */
+
+} XGCValues;
+
+typedef struct
+{
+  int type;
+  int x, y;
+  int width, height;
+} XExposeEvent;
+
+typedef struct
+{
+  int type;                    /* of event */
+  int x, y;                    /* pointer x, y coordinates in event window */
+  unsigned int button;         /* detail */
+} XButtonEvent;
+
+typedef struct
+{
+  int type;
+  int x, y;                    /* pointer x, y coordinates in event window */
+} XMotionEvent;
+
+typedef struct
+{
+  int type;                    /* of event */
+  unsigned int state;          /* key or button mask */
+} XKeyEvent;
+
+typedef struct
+{
+  int type;                    /* FocusIn or FocusOut */
+} XFocusChangeEvent;
+
+typedef struct
+{
+  int type;                    /* ClientMessage */
+} XClientMessageEvent;
+
+typedef union _XEvent
+{
+  int type;                    /* must not be changed; first element */
+  XExposeEvent xexpose;
+  XButtonEvent xbutton;
+  XMotionEvent xmotion;
+  XKeyEvent xkey;
+} XEvent;
+
+Pixel AllegroAllocColorCell(int, int, int);
+
+void XMapWindow(Display *, Window);
+Display *XOpenDisplay(char *);
+Window XCreateSimpleWindow(Display *, Window, int, int,
+                          unsigned int, unsigned int, unsigned int,
+                          unsigned long, unsigned long);
+Status XStringListToTextProperty(char **, int, XTextProperty *);
+void XFree(void *);
+GC XCreateGC(Display *, Drawable, unsigned long, XGCValues *);
+void XSetClipMask(Display *, GC, Pixmap);
+void XSetClipOrigin(Display *, GC, int, int);
+void XFillRectangle(Display *, Drawable, GC, int, int,
+                   unsigned int, unsigned int);
+Pixmap XCreatePixmap(Display *, Drawable, unsigned int, unsigned int,
+                    unsigned int);
+void XSync(Display *, Bool);
+inline void XCopyArea(Display *, Drawable, Drawable, GC, int, int,
+                     unsigned int, unsigned int, int, int);
+int Read_PCX_to_Pixmap(Display *, Window, GC, char *, Pixmap *, Pixmap *);
+int XReadBitmapFile(Display *, Drawable, char *,
+                   unsigned int *, unsigned int *, Pixmap *, int *, int *);
+void XFreePixmap(Display *, Pixmap);
+void XFreeGC(Display *, GC);
+void XUnmapWindow(Display *, Window);
+void XCloseDisplay(Display *);
+void XNextEvent(Display *, XEvent *);
+int XPending(Display *);
+KeySym XLookupKeysym(XKeyEvent *, int);
+int XLookupString(XKeyEvent *, char *, int, KeySym *, XComposeStatus *);
+void XSetForeground(Display *, GC, unsigned long);
+void XDrawLine(Display *, Drawable, GC, int, int, int, int);
+void XDestroyImage(XImage *);
+void XDestroyWindow(Display *, Window);
+Bool XQueryPointer(Display *, Window, Window *, Window *, int *, int *,
+                  int *, int *, unsigned int *);
+void XAutoRepeatOn(Display *);
+void XAutoRepeatOff(Display *);
+
+void AllegroDrawLine(Drawable, int, int, int, int, Pixel);
+Pixel AllegroGetPixel(Drawable, int, int);
+
+void MSDOSOpenAudio(void);
+void MSDOSCloseAudio(void);
+
+void NetworkServer(int, int);
+
+#endif /* MSDOS_H */
diff --git a/src/libgame/pcx.c b/src/libgame/pcx.c
new file mode 100644 (file)
index 0000000..f50e2c9
--- /dev/null
@@ -0,0 +1,267 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* pcx.c                                                    *
+***********************************************************/
+
+#ifndef TARGET_SDL
+
+#include <stdio.h>
+
+#include "pcx.h"
+#include "misc.h"
+
+
+#define PCX_DEBUG              FALSE
+
+#define PCX_MAGIC              0x0a    /* first byte in a PCX image file    */
+#define PCX_LAST_VERSION       5       /* last acceptable version number    */
+#define PCX_ENCODING           1       /* PCX encoding method               */
+#define PCX_256COLORS_MAGIC    0x0c    /* first byte of a PCX 256 color map */
+#define PCX_MAXDEPTH           8       /* supports up to 8 bits per pixel   */
+#define PCX_MAXCOLORS          256     /* maximum number of colors          */
+
+#define PCX_HEADER_SIZE                128
+#define PCX_COLORMAP_SIZE      (3 * PCX_MAXCOLORS)
+
+struct PCX_Header
+{
+  unsigned char signature;     /* PCX file identifier                 */
+  unsigned char version;       /* version compatibility level         */
+  unsigned char encoding;      /* encoding method                     */
+  unsigned char bits_per_pixel;        /* bits per pixel, or depth            */
+  unsigned short xmin;         /* X position of left edge             */
+  unsigned short ymin;         /* Y position of top edge              */
+  unsigned short xmax;         /* X position of right edge            */
+  unsigned short ymax;         /* Y position of bottom edge           */
+  unsigned short hres;         /* X screen resolution of source image */
+  unsigned short vres;         /* Y screen resolution of source image */
+  unsigned char palette[16][3];        /* PCX color map                       */
+  unsigned char reserved;      /* should be 0, 1 if std res fax       */
+  unsigned char color_planes;  /* bit planes in image                 */
+  unsigned short bytes_per_line;/* byte delta between scanlines        */
+  unsigned short palette_type; /* 0 = undef, 1 = color, 2 = grayscale */
+  unsigned char filler[58];    /* fill to struct size of 128          */
+};
+
+/* global PCX error value */
+int errno_pcx = PCX_Success;
+
+static byte *PCX_ReadBitmap(Image *image, byte *buffer_ptr, byte *buffer_last)
+{
+  /* Run Length Encoding: If the two high bits are set,
+   * then the low 6 bits contain a repeat count, and the byte to
+   * repeat is the next byte in the file.  If the two high bits are
+   * not set, then this is the byte to write.
+   */
+
+  unsigned int bytes_per_pixel = (image->depth + 7) / 8;
+  register byte *bitmap_ptr, *bitmap_last;
+  register byte value, count;
+
+  bitmap_ptr = image->data;
+  bitmap_last = bitmap_ptr + (image->width * image->height * bytes_per_pixel);
+
+  while (bitmap_ptr < bitmap_last && buffer_ptr < buffer_last)
+  {
+    value = *buffer_ptr++;
+
+    if ((value & 0xc0) == 0xc0)                /* this is a repeat count byte */
+    {
+      count = value & 0x3f;            /* extract repeat count from byte */
+      value = *buffer_ptr++;           /* next byte is value to repeat */
+
+      for (; count && bitmap_ptr < bitmap_last; count--)
+       *bitmap_ptr++ = value;
+
+      if (count)                       /* repeat count spans end of bitmap */
+       return NULL;
+    }
+    else
+      *bitmap_ptr++ = value;
+
+    image->rgb.color_used[value] = TRUE;
+  }
+
+  /* check if end of buffer was reached before end of bitmap */
+  if (bitmap_ptr < bitmap_last)
+    return NULL;
+
+  /* return current buffer position for next decoding function */
+  return buffer_ptr;
+}
+
+static byte *PCX_ReadColormap(Image *image,byte *buffer_ptr, byte *buffer_last)
+{
+  int i, magic;
+
+  /* read colormap magic byte */
+  magic = *buffer_ptr++;
+
+  /* check magic colormap header byte */
+  if (magic != PCX_256COLORS_MAGIC)
+    return NULL;
+
+  /* check if enough bytes left for a complete colormap */
+  if (buffer_ptr + PCX_COLORMAP_SIZE > buffer_last)
+    return NULL;
+
+  /* read 256 colors from PCX colormap */
+  for (i=0; i<PCX_MAXCOLORS; i++)
+  {
+    image->rgb.red[i]   = *buffer_ptr++ << 8;
+    image->rgb.green[i] = *buffer_ptr++ << 8;
+    image->rgb.blue[i]  = *buffer_ptr++ << 8;
+  }
+
+  /* return current buffer position for next decoding function */
+  return buffer_ptr;
+}
+
+Image *Read_PCX_to_Image(char *filename)
+{
+  FILE *file;
+  byte *file_buffer;
+  byte *buffer_ptr, *buffer_last;
+  unsigned int file_length;
+  struct PCX_Header pcx;
+  Image *image;
+  int width, height, depth;
+  int i;
+
+  errno_pcx = PCX_Success;
+
+  if (!(file = fopen(filename, MODE_READ)))
+  {
+    errno_pcx = PCX_OpenFailed;
+    return NULL;
+  }
+
+  if (fseek(file, 0, SEEK_END) == -1)
+  {
+    fclose(file);
+    errno_pcx = PCX_ReadFailed;
+    return NULL;
+  }
+
+  file_length = ftell(file);
+  rewind(file);
+
+  if (file_length < PCX_HEADER_SIZE)
+  {
+    /* PCX file is too short to contain a valid PCX header */
+    fclose(file);
+
+    errno_pcx = PCX_FileInvalid;
+    return NULL;
+  }
+
+  file_buffer = checked_malloc(file_length);
+
+  if (fread(file_buffer, 1, file_length, file) != file_length)
+  {
+    fclose(file);
+    errno_pcx = PCX_ReadFailed;
+    return NULL;
+  }
+
+  fclose(file);
+
+  pcx.signature      = file_buffer[0];
+  pcx.version        = file_buffer[1];
+  pcx.encoding       = file_buffer[2];
+  pcx.bits_per_pixel = file_buffer[3];
+  pcx.xmin           = file_buffer[4]  + 256 * file_buffer[5];
+  pcx.ymin           = file_buffer[6]  + 256 * file_buffer[7];
+  pcx.xmax           = file_buffer[8]  + 256 * file_buffer[9];
+  pcx.ymax           = file_buffer[10] + 256 * file_buffer[11];
+  pcx.color_planes   = file_buffer[65];
+  pcx.bytes_per_line = file_buffer[66] + 256 * file_buffer[67];
+  pcx.palette_type   = file_buffer[68] + 256 * file_buffer[69];
+
+  width  = pcx.xmax - pcx.xmin + 1;
+  height = pcx.ymax - pcx.ymin + 1;
+  depth  = pcx.bits_per_pixel;
+
+  if (pcx.signature != PCX_MAGIC || pcx.version > PCX_LAST_VERSION ||
+      pcx.encoding != PCX_ENCODING || pcx.color_planes > PCX_MAXDEPTH ||
+      width < 0 || height < 0)
+  {
+    free(file_buffer);
+
+    errno_pcx = PCX_FileInvalid;
+    return NULL;
+  }
+
+#if PCX_DEBUG
+  if (options.verbose)
+  {
+    printf("%s is a %dx%d PC Paintbrush image with %d bitplanes\n",
+          filename, width, height,
+          pcx.color_planes);
+    printf("depth: %d\n", pcx.bits_per_pixel);
+    printf("color_planes: %d\n", pcx.color_planes);
+    printf("bytes_per_line: %d\n", pcx.bytes_per_line);
+    printf("palette type: %s\n",
+          (pcx.palette_type == 1 ? "color" :
+           pcx.palette_type == 2 ? "grayscale" : "undefined"));
+  }
+#endif
+
+  /* allocate new image structure */
+  image = newImage(width, height, depth);
+
+  buffer_ptr  = file_buffer + PCX_HEADER_SIZE;
+  buffer_last = file_buffer + file_length;
+
+  /* read compressed bitmap data */
+  if ((buffer_ptr = PCX_ReadBitmap(image, buffer_ptr, buffer_last)) == NULL)
+  {
+    free(file_buffer);
+    freeImage(image);
+
+    errno_pcx = PCX_FileInvalid;
+    return NULL;
+  }
+
+  if (file_length < PCX_HEADER_SIZE + PCX_COLORMAP_SIZE)
+  {
+    /* PCX file is too short to contain a valid 256 colors colormap */
+    fclose(file);
+    errno_pcx = PCX_ColorFailed;
+    return NULL;
+  }
+
+  /* read colormap data */
+  if (!PCX_ReadColormap(image, buffer_ptr, buffer_last))
+  {
+    free(file_buffer);
+    freeImage(image);
+    errno_pcx = PCX_ColorFailed;
+    return NULL;
+  }
+
+  free(file_buffer);
+
+  /* determine number of used colormap entries */
+  image->rgb.used = 0;
+  for (i=0; i<PCX_MAXCOLORS; i++)
+    if (image->rgb.color_used[i])
+      image->rgb.used++;
+
+#if PCX_DEBUG
+  if (options.verbose)
+    printf("Read_PCX_to_Image: %d colors found\n", image->rgb.used);
+#endif
+
+  return image;
+}
+
+#endif /* !TARGET_SDL */
diff --git a/src/libgame/pcx.h b/src/libgame/pcx.h
new file mode 100644 (file)
index 0000000..8014dd2
--- /dev/null
@@ -0,0 +1,36 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* pcx.h                                                    *
+***********************************************************/
+
+#ifndef PCX_H
+#define PCX_H
+
+#include "system.h"
+#include "image.h"
+
+
+#if !defined(TARGET_SDL)
+
+#define PCX_Success             0
+#define PCX_OpenFailed         -1
+#define PCX_ReadFailed         -2
+#define        PCX_FileInvalid         -3
+#define PCX_NoMemory           -4
+#define PCX_ColorFailed                -5
+
+/* global PCX error value */
+extern int errno_pcx;
+
+Image *Read_PCX_to_Image(char *);
+
+#endif /* !TARGET_SDL */
+#endif /* PCX_H */
diff --git a/src/libgame/platform.h b/src/libgame/platform.h
new file mode 100644 (file)
index 0000000..ea95673
--- /dev/null
@@ -0,0 +1,69 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* platform.h                                               *
+***********************************************************/
+
+#ifndef PLATFORM_H
+#define PLATFORM_H
+
+/* define keywords for supported main platforms */
+
+#if defined(MSDOS)
+#define PLATFORM_MSDOS
+#elif defined(WIN32)
+#define PLATFORM_WIN32
+#else
+#define PLATFORM_UNIX
+#endif
+
+/* ========================================================================= */
+/* define additional keywords for MS-DOS platform                            */
+/* ========================================================================= */
+
+#if defined(PLATFORM_MSDOS)
+
+#ifndef TARGET_ALLEGRO
+#define TARGET_ALLEGRO
+#endif
+
+#ifndef TARGET_X11
+#define TARGET_X11
+#endif
+
+#endif
+
+/* ========================================================================= */
+/* define additional keywords for several Unix platforms                     */
+/* ========================================================================= */
+
+#if defined(PLATFORM_UNIX) && defined(TARGET_X11)
+#define TARGET_X11_NATIVE
+#endif
+
+#if defined(linux)
+#define PLATFORM_LINUX
+#endif
+
+#if defined(__FreeBSD__)
+#define PLATFORM_FREEBSD
+#endif
+
+/* detecting HP-UX by the following compiler keyword definitions:
+   - in K&R mode (the default), the HP C compiler defines "hpux"
+   - in ANSI mode (-Aa or -Ae), the HP C compiler defines "__hpux"
+   - the gcc (Gnu) C compiler defines "__hpux__"
+   Thanks to Jarkko Hietaniemi  for this note. */
+
+#if defined(__hpux__) || defined(__hpux) || defined(hpux)
+#define PLATFORM_HPUX
+#endif
+
+#endif /* PLATFORM_H */
diff --git a/src/libgame/random.c b/src/libgame/random.c
new file mode 100644 (file)
index 0000000..2049ed5
--- /dev/null
@@ -0,0 +1,238 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* random.c                                                 *
+***********************************************************/
+
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * This is derived from the Berkeley source:
+ *     @(#)random.c    5.5 (Berkeley) 7/6/88
+ * It was reworked for the GNU C Library by Roland McGrath.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include "random.h"
+
+
+/* An improved random number generation package.  In addition to the standard
+   rand()/srand() like interface, this package also has a special state info
+   interface.  The initstate() routine is called with a seed, an array of
+   bytes, and a count of how many bytes are being passed in; this array is
+   then initialized to contain information for random number generation with
+   that much state information.  Good sizes for the amount of state
+   information are 32, 64, 128, and 256 bytes.  The state can be switched by
+   calling the setstate() function with the same array as was initiallized
+   with initstate().  By default, the package runs with 128 bytes of state
+   information and generates far better random numbers than a linear
+   congruential generator.  If the amount of state information is less than
+   32 bytes, a simple linear congruential R.N.G. is used.  Internally, the
+   state information is treated as an array of longs; the zeroeth element of
+   the array is the type of R.N.G. being used (small integer); the remainder
+   of the array is the state information for the R.N.G.  Thus, 32 bytes of
+   state information will give 7 longs worth of state information, which will
+   allow a degree seven polynomial.  (Note: The zeroeth word of state
+   information also has some other information stored in it; see setstate
+   for details).  The random number generation technique is a linear feedback
+   shift register approach, employing trinomials (since there are fewer terms
+   to sum up that way).  In this approach, the least significant bit of all
+   the numbers in the state table will act as a linear feedback shift register,
+   and will have period 2^deg - 1 (where deg is the degree of the polynomial
+   being used, assuming that the polynomial is irreducible and primitive).
+   The higher order bits will have longer periods, since their values are
+   also influenced by pseudo-random carries out of the lower bits.  The
+   total period of the generator is approximately deg*(2**deg - 1); thus
+   doubling the amount of state information has a vast influence on the
+   period of the generator.  Note: The deg*(2**deg - 1) is an approximation
+   only good for large deg, when the period of the shift register is the
+   dominant factor.  With deg equal to seven, the period is actually much
+   longer than the 7*(2**7 - 1) predicted by this formula.  */
+
+
+
+/* For each of the currently supported random number generators, we have a
+   break value on the amount of state information (you need at least thi
+   bytes of state info to support this random number generator), a degree for
+   the polynomial (actually a trinomial) that the R.N.G. is based on, and
+   separation between the two lower order coefficients of the trinomial.  */
+
+/* Linear congruential.  */
+#define        TYPE_0          0
+#define        BREAK_0         8
+#define        DEG_0           0
+#define        SEP_0           0
+
+/* x**7 + x**3 + 1.  */
+#define        TYPE_1          1
+#define        BREAK_1         32
+#define        DEG_1           7
+#define        SEP_1           3
+
+/* x**15 + x + 1.  */
+#define        TYPE_2          2
+#define        BREAK_2         64
+#define        DEG_2           15
+#define        SEP_2           1
+
+/* x**31 + x**3 + 1.  */
+#define        TYPE_3          3
+#define        BREAK_3         128
+#define        DEG_3           31
+#define        SEP_3           3
+
+/* x**63 + x + 1.  */
+#define        TYPE_4          4
+#define        BREAK_4         256
+#define        DEG_4           63
+#define        SEP_4           1
+
+
+/* Array versions of the above information to make code run faster.
+   Relies on fact that TYPE_i == i.  */
+
+#define        MAX_TYPES       5       /* Max number of types above.  */
+
+
+
+/* Initially, everything is set up as if from:
+       initstate(1, randtbl, 128);
+   Note that this initialization takes advantage of the fact that srandom
+   advances the front and rear pointers 10*rand_deg times, and hence the
+   rear pointer which starts at 0 will also end up at zero; thus the zeroeth
+   element of the state information, which contains info about the current
+   position of the rear pointer is just
+       (MAX_TYPES * (rptr - state)) + TYPE_3 == TYPE_3.  */
+
+static long int randtbl[DEG_3 + 1] =
+{
+  TYPE_3,
+  -851904987, -43806228, -2029755270, 1390239686, -1912102820,
+  -485608943, 1969813258, -1590463333, -1944053249, 455935928, 508023712,
+  -1714531963, 1800685987, -2015299881, 654595283, -1149023258,
+  -1470005550, -1143256056, -1325577603, -1568001885, 1275120390,
+  -607508183, -205999574, -1696891592, 1492211999, -1528267240,
+  -952028296, -189082757, 362343714, 1424981831, 2039449641,
+};
+
+/* FPTR and RPTR are two pointers into the state info, a front and a rear
+   pointer.  These two pointers are always rand_sep places aparts, as they
+   cycle through the state information.  (Yes, this does mean we could get
+   away with just one pointer, but the code for random is more efficient
+   this way).  The pointers are left positioned as they would be from the call:
+       initstate(1, randtbl, 128);
+   (The position of the rear pointer, rptr, is really 0 (as explained above
+   in the initialization of randtbl) because the state table pointer is set
+   to point to randtbl[1] (as explained below).)  */
+
+static long int *fptr = &randtbl[SEP_3 + 1];
+static long int *rptr = &randtbl[1];
+
+
+
+/* The following things are the pointer to the state information table,
+   the type of the current generator, the degree of the current polynomial
+   being used, and the separation between the two pointers.
+   Note that for efficiency of random, we remember the first location of
+   the state information, not the zeroeth.  Hence it is valid to access
+   state[-1], which is used to store the type of the R.N.G.
+   Also, we remember the last location, since this is more efficient than
+   indexing every time to find the address of the last element to see if
+   the front and rear pointers have wrapped.  */
+
+static long int *state = &randtbl[1];
+
+static int rand_type = TYPE_3;
+static int rand_deg = DEG_3;
+static int rand_sep = SEP_3;
+
+static long int *end_ptr = &randtbl[sizeof(randtbl) / sizeof(randtbl[0])];
+
+/* Initialize the random number generator based on the given seed.  If the
+   type is the trivial no-state-information type, just remember the seed.
+   Otherwise, initializes state[] based on the given "seed" via a linear
+   congruential generator.  Then, the pointers are set to known locations
+   that are exactly rand_sep places apart.  Lastly, it cycles the state
+   information a given number of times to get rid of any initial dependencies
+   introduced by the L.C.R.N.G.  Note that the initialization of randtbl[]
+   for default usage relies on values produced by this routine.  */
+
+void srandom_linux_libc(unsigned int x)
+{
+  state[0] = x;
+  if (rand_type != TYPE_0)
+  {
+    register long int i;
+    for (i = 1; i < rand_deg; ++i)
+      state[i] = (1103515145 * state[i - 1]) + 12345;
+    fptr = &state[rand_sep];
+    rptr = &state[0];
+    for (i = 0; i < 10 * rand_deg; ++i)
+      (void) random_linux_libc();
+  }
+}
+
+/* If we are using the trivial TYPE_0 R.N.G., just do the old linear
+   congruential bit.  Otherwise, we do our fancy trinomial stuff, which is the
+   same in all ther other cases due to all the global variables that have been
+   set up.  The basic operation is to add the number at the rear pointer into
+   the one at the front pointer.  Then both pointers are advanced to the next
+   location cyclically in the table.  The value returned is the sum generated,
+   reduced to 31 bits by throwing away the "least random" low bit.
+   Note: The code takes advantage of the fact that both the front and
+   rear pointers can't wrap on the same call by not testing the rear
+   pointer if the front one has wrapped.  Returns a 31-bit random number.  */
+
+long int random_linux_libc()
+{
+  if (rand_type == TYPE_0)
+  {
+    state[0] = ((state[0] * 1103515245) + 12345) & LONG_MAX;
+    return state[0];
+  }
+  else
+  {
+    long int i;
+    *fptr += *rptr;
+    /* Chucking least random bit.  */
+    i = (*fptr >> 1) & LONG_MAX;
+    ++fptr;
+    if (fptr >= end_ptr)
+    {
+      fptr = state;
+      ++rptr;
+    }
+    else
+    {
+      ++rptr;
+      if (rptr >= end_ptr)
+       rptr = state;
+    }
+    return i;
+  }
+}
diff --git a/src/libgame/random.h b/src/libgame/random.h
new file mode 100644 (file)
index 0000000..04b7d68
--- /dev/null
@@ -0,0 +1,20 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* random.h                                                 *
+***********************************************************/
+
+#ifndef RANDOM_H
+#define RANDOM_H
+
+void srandom_linux_libc(unsigned int);
+long int random_linux_libc(void);
+
+#endif
diff --git a/src/libgame/sdl.c b/src/libgame/sdl.c
new file mode 100644 (file)
index 0000000..4835d1f
--- /dev/null
@@ -0,0 +1,749 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* sdl.c                                                    *
+***********************************************************/
+
+#include "system.h"
+#include "sound.h"
+#include "misc.h"
+
+
+#if defined(TARGET_SDL)
+
+/* ========================================================================= */
+/* video functions                                                           */
+/* ========================================================================= */
+
+inline void SDLInitVideoDisplay(void)
+{
+  /* initialize SDL video */
+  if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
+    Error(ERR_EXIT, "SDL_InitSubSystem() failed: %s", SDL_GetError());
+
+  /* set default SDL depth */
+  video.default_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
+}
+
+inline void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
+                              boolean fullscreen)
+{
+  /* open SDL video output device (window or fullscreen mode) */
+  if (!SDLSetVideoMode(backbuffer, fullscreen))
+    Error(ERR_EXIT, "setting video mode failed");
+
+  /* set window and icon title */
+  SDL_WM_SetCaption(program.window_title, program.window_title);
+
+  /* SDL cannot directly draw to the visible video framebuffer like X11,
+     but always uses a backbuffer, which is then blitted to the visible
+     video framebuffer with 'SDL_UpdateRect' (or replaced with the current
+     visible video framebuffer with 'SDL_Flip', if the hardware supports
+     this). Therefore do not use an additional backbuffer for drawing, but
+     use a symbolic buffer (distinguishable from the SDL backbuffer) called
+     'window', which indicates that the SDL backbuffer should be updated to
+     the visible video framebuffer when attempting to blit to it.
+
+     For convenience, it seems to be a good idea to create this symbolic
+     buffer 'window' at the same size as the SDL backbuffer. Although it
+     should never be drawn to directly, it would do no harm nevertheless. */
+
+  /* create additional (symbolic) buffer for double-buffering */
+  *window = CreateBitmap(video.width, video.height, video.depth);
+}
+
+inline boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
+{
+  boolean success = TRUE;
+  int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
+  int surface_flags_window = SURFACE_FLAGS;
+  SDL_Surface *new_surface = NULL;
+
+  if (*backbuffer == NULL)
+    *backbuffer = CreateBitmapStruct();
+
+  if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
+  {
+    /* switch display to fullscreen mode, if available */
+    if ((new_surface = SDL_SetVideoMode(video.width, video.height,
+                                       video.depth, surface_flags_fullscreen))
+       == NULL)
+    {
+      /* switching display to fullscreen mode failed */
+      Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
+
+      /* do not try it again */
+      video.fullscreen_available = FALSE;
+      success = FALSE;
+    }
+    else
+    {
+      (*backbuffer)->surface = new_surface;
+
+      video.fullscreen_enabled = TRUE;
+      success = TRUE;
+    }
+  }
+
+  if ((!fullscreen && video.fullscreen_enabled) || new_surface == NULL)
+  {
+    /* switch display to window mode */
+    if ((new_surface = SDL_SetVideoMode(video.width, video.height,
+                                       video.depth, surface_flags_window))
+       == NULL)
+    {
+      /* switching display to window mode failed -- should not happen */
+      Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
+
+      success = FALSE;
+    }
+    else
+    {
+      (*backbuffer)->surface = new_surface;
+
+      video.fullscreen_enabled = FALSE;
+      success = TRUE;
+    }
+  }
+
+  return success;
+}
+
+inline void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
+                       int src_x, int src_y,
+                       int width, int height,
+                       int dst_x, int dst_y, int copy_mode)
+{
+  Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
+  SDL_Rect src_rect, dst_rect;
+
+  src_rect.x = src_x;
+  src_rect.y = src_y;
+  src_rect.w = width;
+  src_rect.h = height;
+
+  dst_rect.x = dst_x;
+  dst_rect.y = dst_y;
+  dst_rect.w = width;
+  dst_rect.h = height;
+
+  if (src_bitmap != backbuffer || dst_bitmap != window)
+    SDL_BlitSurface((copy_mode == SDLCOPYAREA_MASKED ?
+                    src_bitmap->surface_masked : src_bitmap->surface),
+                   &src_rect, real_dst_bitmap->surface, &dst_rect);
+
+  if (dst_bitmap == window)
+    SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
+}
+
+inline void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y,
+                            int width, int height, unsigned int color)
+{
+  Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
+  SDL_Rect rect;
+  unsigned int color_r = (color >> 16) && 0xff;
+  unsigned int color_g = (color >>  8) && 0xff;
+  unsigned int color_b = (color >>  0) && 0xff;
+
+  rect.x = x;
+  rect.y = y;
+  rect.w = width;
+  rect.h = height;
+
+  SDL_FillRect(real_dst_bitmap->surface, &rect,
+              SDL_MapRGB(real_dst_bitmap->surface->format,
+                         color_r, color_g, color_b));
+
+  if (dst_bitmap == window)
+    SDL_UpdateRect(backbuffer->surface, x, y, width, height);
+}
+
+inline void SDLDrawSimpleLine(SDL_Surface *surface, int from_x, int from_y,
+                             int to_x, int to_y, unsigned int color)
+{
+  SDL_Rect rect;
+  unsigned int color_r = (color >> 16) & 0xff;
+  unsigned int color_g = (color >>  8) & 0xff;
+  unsigned int color_b = (color >>  0) & 0xff;
+
+  if (from_x > to_x)
+    swap_numbers(&from_x, &to_x);
+
+  if (from_y > to_y)
+    swap_numbers(&from_y, &to_y);
+
+  rect.x = from_x;
+  rect.y = from_y;
+  rect.w = (to_x - from_x + 1);
+  rect.h = (to_y - from_y + 1);
+
+  SDL_FillRect(surface, &rect,
+               SDL_MapRGB(surface->format, color_r, color_g, color_b));
+}
+
+inline void SDLDrawLine(SDL_Surface *surface, int from_x, int from_y,
+                       int to_x, int to_y, Uint32 color)
+{
+  sge_Line(surface, from_x, from_y, to_x, to_y, color);
+}
+
+#if 0
+inline void SDLDrawLines(SDL_Surface *surface, struct XY *points,
+                        int num_points, Uint32 color)
+{
+  int i, x, y;
+  int line_width = 4;
+
+  for (i=0; i<num_points - 1; i++)
+  {
+    for (x=0; x<line_width; x++)
+    {
+      for (y=0; y<line_width; y++)
+      {
+       int dx = x - line_width / 2;
+       int dy = y - line_width / 2;
+
+       if ((x == 0 && y == 0) ||
+           (x == 0 && y == line_width - 1) ||
+           (x == line_width - 1 && y == 0) ||
+           (x == line_width - 1 && y == line_width - 1))
+         continue;
+
+       sge_Line(surface, points[i].x + dx, points[i].y + dy,
+                points[i+1].x + dx, points[i+1].y + dy, color);
+      }
+    }
+  }
+}
+#endif
+
+
+/* ========================================================================= */
+/* The following functions have been taken from the SGE library              */
+/* (SDL Graphics Extension Library) by Anders Lindström                      */
+/* http://www.etek.chalmers.se/~e8cal1/sge/index.html                        */
+/* ========================================================================= */
+
+void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
+{
+  if (x >= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1)
+  {
+    switch (surface->format->BytesPerPixel)
+    {
+      case 1:
+      {
+       /* Assuming 8-bpp */
+       *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
+      }
+      break;
+
+      case 2:
+      {
+       /* Probably 15-bpp or 16-bpp */
+       *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
+      }
+      break;
+
+      case 3:
+      {
+       /* Slow 24-bpp mode, usually not used */
+       Uint8 *pix;
+       int shift;
+
+       /* Gack - slow, but endian correct */
+       pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
+       shift = surface->format->Rshift;
+       *(pix+shift/8) = color>>shift;
+       shift = surface->format->Gshift;
+       *(pix+shift/8) = color>>shift;
+       shift = surface->format->Bshift;
+       *(pix+shift/8) = color>>shift;
+      }
+      break;
+
+      case 4:
+      {
+       /* Probably 32-bpp */
+       *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
+      }
+      break;
+    }
+  }
+}
+
+void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
+                 Uint8 R, Uint8 G, Uint8 B)
+{
+  _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
+}
+
+void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
+{
+  *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
+}
+
+void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
+{
+  *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
+}
+
+void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
+{
+  Uint8 *pix;
+  int shift;
+
+  /* Gack - slow, but endian correct */
+  pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
+  shift = surface->format->Rshift;
+  *(pix+shift/8) = color>>shift;
+  shift = surface->format->Gshift;
+  *(pix+shift/8) = color>>shift;
+  shift = surface->format->Bshift;
+  *(pix+shift/8) = color>>shift;
+}
+
+void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
+{
+  *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
+}
+
+void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
+{
+  switch (dest->format->BytesPerPixel)
+  {
+    case 1:
+      *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
+      break;
+
+    case 2:
+      *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
+      break;
+
+    case 3:
+      _PutPixel24(dest,x,y,color);
+      break;
+
+    case 4:
+      *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
+      break;
+  }
+}
+
+void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
+{
+  if (SDL_MUSTLOCK(surface))
+  {
+    if (SDL_LockSurface(surface) < 0)
+    {
+      return;
+    }
+  }
+
+  _PutPixel(surface, x, y, color);
+
+  if (SDL_MUSTLOCK(surface))
+  {
+    SDL_UnlockSurface(surface);
+  }
+}
+
+void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
+                 Uint8 R, Uint8 G, Uint8 B)
+{
+  sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
+}
+
+Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
+{
+  if (y >= 0 && y <= dest->h - 1)
+  {
+    switch (dest->format->BytesPerPixel)
+    {
+      case 1:
+       return y*dest->pitch;
+       break;
+
+      case 2:
+       return y*dest->pitch/2;
+       break;
+
+      case 3:
+       return y*dest->pitch;
+       break;
+
+      case 4:
+       return y*dest->pitch/4;
+       break;
+    }
+  }
+
+  return -1;
+}
+
+void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
+{
+  if (x >= 0 && x <= surface->w - 1 && ypitch >= 0)
+  {
+    switch (surface->format->BytesPerPixel)
+    {
+      case 1:
+      {
+       /* Assuming 8-bpp */
+       *((Uint8 *)surface->pixels + ypitch + x) = color;
+      }
+      break;
+
+      case 2:
+      {
+       /* Probably 15-bpp or 16-bpp */
+       *((Uint16 *)surface->pixels + ypitch + x) = color;
+      }
+      break;
+
+      case 3:
+      {
+       /* Slow 24-bpp mode, usually not used */
+       Uint8 *pix;
+       int shift;
+
+       /* Gack - slow, but endian correct */
+       pix = (Uint8 *)surface->pixels + ypitch + x*3;
+       shift = surface->format->Rshift;
+       *(pix+shift/8) = color>>shift;
+       shift = surface->format->Gshift;
+       *(pix+shift/8) = color>>shift;
+       shift = surface->format->Bshift;
+       *(pix+shift/8) = color>>shift;
+      }
+      break;
+
+      case 4:
+      {
+       /* Probably 32-bpp */
+       *((Uint32 *)surface->pixels + ypitch + x) = color;
+      }
+      break;
+    }
+  }
+}
+
+void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
+              Uint32 Color)
+{
+  SDL_Rect l;
+
+  if (SDL_MUSTLOCK(Surface))
+  {
+    if (SDL_LockSurface(Surface) < 0)
+    {
+      return;
+    }
+  }
+
+  if (x1 > x2)
+  {
+    Sint16 tmp = x1;
+    x1 = x2;
+    x2 = tmp;
+  }
+
+  /* Do the clipping */
+  if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
+    return;
+  if (x1 < 0)
+    x1 = 0;
+  if (x2 > Surface->w - 1)
+    x2 = Surface->w - 1;
+
+  l.x = x1;
+  l.y = y;
+  l.w = x2 - x1 + 1;
+  l.h = 1;
+
+  SDL_FillRect(Surface, &l, Color);
+
+  if (SDL_MUSTLOCK(Surface))
+  {
+    SDL_UnlockSurface(Surface);
+  }
+}
+
+void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
+                 Uint8 R, Uint8 G, Uint8 B)
+{
+  sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
+}
+
+void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
+{
+  SDL_Rect l;
+
+  if (x1 > x2)
+  {
+    Sint16 tmp = x1;
+    x1 = x2;
+    x2 = tmp;
+  }
+
+  /* Do the clipping */
+  if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
+    return;
+  if (x1 < 0)
+    x1 = 0;
+  if (x2 > Surface->w - 1)
+    x2 = Surface->w - 1;
+
+  l.x = x1;
+  l.y = y;
+  l.w = x2 - x1 + 1;
+  l.h = 1;
+
+  SDL_FillRect(Surface, &l, Color);
+}
+
+void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
+              Uint32 Color)
+{
+  SDL_Rect l;
+
+  if (SDL_MUSTLOCK(Surface))
+  {
+    if (SDL_LockSurface(Surface) < 0)
+    {
+      return;
+    }
+  }
+
+  if (y1 > y2)
+  {
+    Sint16 tmp = y1;
+    y1 = y2;
+    y2 = tmp;
+  }
+
+  /* Do the clipping */
+  if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
+    return;
+  if (y1 < 0)
+    y1 = 0;
+  if (y2 > Surface->h - 1)
+    y2 = Surface->h - 1;
+
+  l.x = x;
+  l.y = y1;
+  l.w = 1;
+  l.h = y2 - y1 + 1;
+
+  SDL_FillRect(Surface, &l, Color);
+
+  if (SDL_MUSTLOCK(Surface))
+  {
+    SDL_UnlockSurface(Surface);
+  }
+}
+
+void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
+                 Uint8 R, Uint8 G, Uint8 B)
+{
+  sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
+}
+
+void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
+{
+  SDL_Rect l;
+
+  if (y1 > y2)
+  {
+    Sint16 tmp = y1;
+    y1 = y2;
+    y2 = tmp;
+  }
+
+  /* Do the clipping */
+  if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
+    return;
+  if (y1 < 0)
+    y1 = 0;
+  if (y2 > Surface->h - 1)
+    y2 = Surface->h - 1;
+
+  l.x = x;
+  l.y = y1;
+  l.w = 1;
+  l.h = y2 - y1 + 1;
+
+  SDL_FillRect(Surface, &l, Color);
+}
+
+void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1,
+               Sint16 x2, Sint16 y2, Uint32 Color,
+               void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
+                             Uint32 Color))
+{
+  Sint16 dx, dy, sdx, sdy, x, y, px, py;
+
+  dx = x2 - x1;
+  dy = y2 - y1;
+
+  sdx = (dx < 0) ? -1 : 1;
+  sdy = (dy < 0) ? -1 : 1;
+
+  dx = sdx * dx + 1;
+  dy = sdy * dy + 1;
+
+  x = y = 0;
+
+  px = x1;
+  py = y1;
+
+  if (dx >= dy)
+  {
+    for (x = 0; x < dx; x++)
+    {
+      Callback(Surface, px, py, Color);
+
+      y += dy;
+      if (y >= dx)
+      {
+       y -= dx;
+       py += sdy;
+      }
+
+      px += sdx;
+    }
+  }
+  else
+  {
+    for (y = 0; y < dy; y++)
+    {
+      Callback(Surface, px, py, Color);
+
+      x += dx;
+      if (x >= dy)
+      {
+       x -= dy;
+       px += sdx;
+      }
+
+      py += sdy;
+    }
+  }
+}
+
+void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1,
+                  Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
+                  void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
+                                Uint32 Color))
+{
+  sge_DoLine(Surface, X1, Y1, X2, Y2,
+            SDL_MapRGB(Surface->format, R, G, B), Callback);
+}
+
+void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
+             Uint32 Color)
+{
+  if (SDL_MUSTLOCK(Surface))
+  {
+    if (SDL_LockSurface(Surface) < 0)
+      return;
+   }
+
+   /* Draw the line */
+   sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel);
+
+   /* unlock the display */
+   if (SDL_MUSTLOCK(Surface))
+   {
+      SDL_UnlockSurface(Surface);
+   }
+}
+
+void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
+                Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
+{
+  sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
+}
+
+Bitmap *SDLLoadImage(char *filename)
+{
+  Bitmap *new_bitmap = CreateBitmapStruct();
+  SDL_Surface *sdl_image_tmp;
+
+  /* load image to temporary surface */
+  if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
+    Error(ERR_EXIT, "IMG_Load() failed: %s", SDL_GetError());
+
+  /* create native non-transparent surface for current image */
+  if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
+    Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
+
+  /* create native transparent surface for current image */
+  SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
+                 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
+  if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
+    Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
+
+  /* free temporary surface */
+  SDL_FreeSurface(sdl_image_tmp);
+
+  return new_bitmap;
+}
+
+
+/* ========================================================================= */
+/* audio functions                                                           */
+/* ========================================================================= */
+
+inline void SDLOpenAudio(void)
+{
+  if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
+  {
+    Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
+    return;
+  }
+
+  if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, AUDIO_S16,
+                   AUDIO_STEREO_CHANNELS,
+                   DEFAULT_AUDIO_FRAGMENT_SIZE) < 0)
+  {
+    Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
+    return;
+  }
+
+  audio.sound_available = TRUE;
+  audio.music_available = TRUE;
+  audio.loops_available = TRUE;
+  audio.sound_enabled = TRUE;
+
+  /* determine number of available channels */
+  audio.channels = Mix_AllocateChannels(MIX_CHANNELS);
+
+  if (!audio.mods_available)   /* reserve first channel for music loops */
+  {
+    if (Mix_ReserveChannels(1) == 1)
+      audio.music_channel = 0;
+    else
+      audio.music_available = FALSE;
+  }
+
+  Mix_Volume(-1, SOUND_MAX_VOLUME);
+  Mix_VolumeMusic(SOUND_MAX_VOLUME);
+}
+
+inline void SDLCloseAudio(void)
+{
+  Mix_HaltMusic();
+  Mix_HaltChannel(-1);
+
+  Mix_CloseAudio();
+  SDL_QuitSubSystem(SDL_INIT_AUDIO);
+}
+
+#endif /* TARGET_SDL */
diff --git a/src/libgame/sdl.h b/src/libgame/sdl.h
new file mode 100644 (file)
index 0000000..e650885
--- /dev/null
@@ -0,0 +1,332 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* sdl.h                                                    *
+***********************************************************/
+
+#ifndef SDL_H
+#define SDL_H
+
+#include "SDL.h"
+#include "SDL_image.h"
+#include "SDL_mixer.h"
+
+
+/* definitions needed for "system.c" */
+
+#define SURFACE_FLAGS          (SDL_SWSURFACE)
+
+#define SDLCOPYAREA_OPAQUE     0
+#define SDLCOPYAREA_MASKED     1
+
+/* system dependent definitions */
+
+#define TARGET_STRING          "SDL"
+#define FULLSCREEN_STATUS      FULLSCREEN_AVAILABLE
+
+
+/* SDL type definitions */
+
+typedef struct SDLSurfaceInfo  Bitmap;
+typedef struct SDLSurfaceInfo  DrawBuffer;
+typedef struct SDLSurfaceInfo  DrawWindow;
+typedef Uint32                 Pixel;
+
+typedef SDLKey                 Key;
+
+typedef SDL_Event              Event;
+typedef SDL_MouseButtonEvent   ButtonEvent;
+typedef SDL_MouseMotionEvent   MotionEvent;
+typedef SDL_KeyboardEvent      KeyEvent;
+typedef SDL_Event              ExposeEvent;
+typedef SDL_Event              FocusChangeEvent;
+typedef SDL_Event              ClientMessageEvent;
+
+typedef int                    GC;
+typedef int                    Pixmap;
+typedef int                    Display;
+typedef int                    Visual;
+typedef int                    Colormap;
+
+
+/* structure definitions */
+
+struct SDLSurfaceInfo
+{
+  SDL_Surface *surface;
+  SDL_Surface *surface_masked;
+  GC gc;
+  GC stored_clip_gc;
+};
+
+struct XY
+{
+  short x, y;
+};
+
+
+/* SDL symbol definitions */
+
+#define None                   0L
+
+#define EVENT_BUTTONPRESS      SDL_MOUSEBUTTONDOWN
+#define EVENT_BUTTONRELEASE    SDL_MOUSEBUTTONUP
+#define EVENT_MOTIONNOTIFY     SDL_MOUSEMOTION
+#define EVENT_KEYPRESS         SDL_KEYDOWN
+#define EVENT_KEYRELEASE       SDL_KEYUP
+#define EVENT_EXPOSE           SDL_USEREVENT + 0
+#define EVENT_FOCUSIN          SDL_USEREVENT + 1
+#define EVENT_FOCUSOUT         SDL_USEREVENT + 2
+#define EVENT_CLIENTMESSAGE    SDL_QUIT
+#define EVENT_MAPNOTIFY                SDL_USEREVENT + 4
+#define EVENT_UNMAPNOTIFY      SDL_USEREVENT + 5
+
+#define KSYM_UNDEFINED         SDLK_UNKNOWN
+
+#define KSYM_Return            SDLK_RETURN
+#define KSYM_Escape            SDLK_ESCAPE
+
+#define KSYM_Left              SDLK_LEFT
+#define KSYM_Right             SDLK_RIGHT
+#define KSYM_Up                        SDLK_UP
+#define KSYM_Down              SDLK_DOWN
+
+#ifdef SDLK_KP_LEFT
+#define KSYM_KP_Left           SDLK_KP_LEFT
+#define KSYM_KP_Right          SDLK_KP_RIGHT
+#define KSYM_KP_Up             SDLK_KP_UP
+#define KSYM_KP_Down           SDLK_KP_DOWN
+#endif
+
+#define KSYM_KP_Enter          SDLK_KP_ENTER
+#define KSYM_KP_Add            SDLK_KP_PLUS
+#define KSYM_KP_Subtract       SDLK_KP_MINUS
+#define KSYM_KP_Multiply       SDLK_KP_MULTIPLY
+#define KSYM_KP_Divide         SDLK_KP_DIVIDE
+#define KSYM_KP_Separator      SDLK_KP_PERIOD
+
+#define KSYM_Shift_L           SDLK_LSHIFT
+#define KSYM_Shift_R           SDLK_RSHIFT
+#define KSYM_Control_L         SDLK_LCTRL
+#define KSYM_Control_R         SDLK_RCTRL
+#define KSYM_Meta_L            SDLK_LMETA
+#define KSYM_Meta_R            SDLK_RMETA
+#define KSYM_Alt_L             SDLK_LALT
+#define KSYM_Alt_R             SDLK_RALT
+#define KSYM_Super_L           SDLK_LSUPER
+#define KSYM_Super_R           SDLK_RSUPER
+#define KSYM_Mode_switch       SDLK_MODE
+#define KSYM_Multi_key         SDLK_RCTRL
+
+#define KSYM_BackSpace         SDLK_BACKSPACE
+#define KSYM_Delete            SDLK_DELETE
+#define KSYM_Insert            SDLK_INSERT
+#define KSYM_Tab               SDLK_TAB
+#define KSYM_Home              SDLK_HOME
+#define KSYM_End               SDLK_END
+#define KSYM_Page_Up           SDLK_PAGEUP
+#define KSYM_Page_Down         SDLK_PAGEDOWN
+#define KSYM_Menu              SDLK_MENU
+
+#define KSYM_space             SDLK_SPACE
+#define KSYM_exclam            SDLK_EXCLAIM
+#define KSYM_quotedbl          SDLK_QUOTEDBL
+#define KSYM_numbersign                SDLK_HASH
+#define KSYM_dollar            SDLK_DOLLAR
+#define KSYM_percent           KSYM_UNDEFINED          /* undefined */
+#define KSYM_ampersand         SDLK_AMPERSAND
+#define KSYM_apostrophe                SDLK_QUOTE
+#define KSYM_parenleft         SDLK_LEFTPAREN
+#define KSYM_parenright                SDLK_RIGHTPAREN
+#define KSYM_asterisk          SDLK_ASTERISK
+#define KSYM_plus              SDLK_PLUS
+#define KSYM_comma             SDLK_COMMA
+#define KSYM_minus             SDLK_MINUS
+#define KSYM_period            SDLK_PERIOD
+#define KSYM_slash             SDLK_SLASH
+
+#define KSYM_colon             SDLK_COLON
+#define KSYM_semicolon         SDLK_SEMICOLON
+#define KSYM_less              SDLK_LESS
+#define KSYM_equal             SDLK_EQUALS
+#define KSYM_greater           SDLK_GREATER
+#define KSYM_question          SDLK_QUESTION
+#define KSYM_at                        SDLK_AT
+
+#define KSYM_bracketleft       SDLK_LEFTBRACKET
+#define KSYM_backslash         SDLK_BACKSLASH
+#define KSYM_bracketright      SDLK_RIGHTBRACKET
+#define KSYM_asciicircum       SDLK_CARET
+#define KSYM_underscore                SDLK_UNDERSCORE
+#define KSYM_grave             SDLK_BACKQUOTE
+
+#define KSYM_quoteleft         KSYM_UNDEFINED          /* undefined */
+#define KSYM_braceleft         KSYM_UNDEFINED          /* undefined */
+#define KSYM_bar               KSYM_UNDEFINED          /* undefined */
+#define KSYM_braceright                KSYM_UNDEFINED          /* undefined */
+#define KSYM_asciitilde                KSYM_UNDEFINED          /* undefined */
+
+#define KSYM_Adiaeresis                SDLK_WORLD_36
+#define KSYM_Odiaeresis                SDLK_WORLD_54
+#define KSYM_Udiaeresis                SDLK_WORLD_60
+#define KSYM_adiaeresis                SDLK_WORLD_68
+#define KSYM_odiaeresis                SDLK_WORLD_86
+#define KSYM_udiaeresis                SDLK_WORLD_92
+#define KSYM_ssharp            SDLK_WORLD_63
+
+#ifndef SDLK_A
+#define SDLK_A                 65
+#define SDLK_B                 66
+#define SDLK_C                 67
+#define SDLK_D                 68
+#define SDLK_E                 69
+#define SDLK_F                 70
+#define SDLK_G                 71
+#define SDLK_H                 72
+#define SDLK_I                 73
+#define SDLK_J                 74
+#define SDLK_K                 75
+#define SDLK_L                 76
+#define SDLK_M                 77
+#define SDLK_N                 78
+#define SDLK_O                 79
+#define SDLK_P                 80
+#define SDLK_Q                 81
+#define SDLK_R                 82
+#define SDLK_S                 83
+#define SDLK_T                 84
+#define SDLK_U                 85
+#define SDLK_V                 86
+#define SDLK_W                 87
+#define SDLK_X                 88
+#define SDLK_Y                 89
+#define SDLK_Z                 90
+#endif
+
+#define KSYM_A                 SDLK_A
+#define KSYM_B                 SDLK_B
+#define KSYM_C                 SDLK_C
+#define KSYM_D                 SDLK_D
+#define KSYM_E                 SDLK_E
+#define KSYM_F                 SDLK_F
+#define KSYM_G                 SDLK_G
+#define KSYM_H                 SDLK_H
+#define KSYM_I                 SDLK_I
+#define KSYM_J                 SDLK_J
+#define KSYM_K                 SDLK_K
+#define KSYM_L                 SDLK_L
+#define KSYM_M                 SDLK_M
+#define KSYM_N                 SDLK_N
+#define KSYM_O                 SDLK_O
+#define KSYM_P                 SDLK_P
+#define KSYM_Q                 SDLK_Q
+#define KSYM_R                 SDLK_R
+#define KSYM_S                 SDLK_S
+#define KSYM_T                 SDLK_T
+#define KSYM_U                 SDLK_U
+#define KSYM_V                 SDLK_V
+#define KSYM_W                 SDLK_W
+#define KSYM_X                 SDLK_X
+#define KSYM_Y                 SDLK_Y
+#define KSYM_Z                 SDLK_Z
+
+#define KSYM_a                 SDLK_a
+#define KSYM_b                 SDLK_b
+#define KSYM_c                 SDLK_c
+#define KSYM_d                 SDLK_d
+#define KSYM_e                 SDLK_e
+#define KSYM_f                 SDLK_f
+#define KSYM_g                 SDLK_g
+#define KSYM_h                 SDLK_h
+#define KSYM_i                 SDLK_i
+#define KSYM_j                 SDLK_j
+#define KSYM_k                 SDLK_k
+#define KSYM_l                 SDLK_l
+#define KSYM_m                 SDLK_m
+#define KSYM_n                 SDLK_n
+#define KSYM_o                 SDLK_o
+#define KSYM_p                 SDLK_p
+#define KSYM_q                 SDLK_q
+#define KSYM_r                 SDLK_r
+#define KSYM_s                 SDLK_s
+#define KSYM_t                 SDLK_t
+#define KSYM_u                 SDLK_u
+#define KSYM_v                 SDLK_v
+#define KSYM_w                 SDLK_w
+#define KSYM_x                 SDLK_x
+#define KSYM_y                 SDLK_y
+#define KSYM_z                 SDLK_z
+
+#define KSYM_0                 SDLK_0
+#define KSYM_1                 SDLK_1
+#define KSYM_2                 SDLK_2
+#define KSYM_3                 SDLK_3
+#define KSYM_4                 SDLK_4
+#define KSYM_5                 SDLK_5
+#define KSYM_6                 SDLK_6
+#define KSYM_7                 SDLK_7
+#define KSYM_8                 SDLK_8
+#define KSYM_9                 SDLK_9
+
+#define KSYM_KP_0              SDLK_KP0
+#define KSYM_KP_1              SDLK_KP1
+#define KSYM_KP_2              SDLK_KP2
+#define KSYM_KP_3              SDLK_KP3
+#define KSYM_KP_4              SDLK_KP4
+#define KSYM_KP_5              SDLK_KP5
+#define KSYM_KP_6              SDLK_KP6
+#define KSYM_KP_7              SDLK_KP7
+#define KSYM_KP_8              SDLK_KP8
+#define KSYM_KP_9              SDLK_KP9
+
+#define KSYM_F1                        SDLK_F1
+#define KSYM_F2                        SDLK_F2
+#define KSYM_F3                        SDLK_F3
+#define KSYM_F4                        SDLK_F4
+#define KSYM_F5                        SDLK_F5
+#define KSYM_F6                        SDLK_F6
+#define KSYM_F7                        SDLK_F7
+#define KSYM_F8                        SDLK_F8
+#define KSYM_F9                        SDLK_F9
+#define KSYM_F10               SDLK_F10
+#define KSYM_F11               SDLK_F11
+#define KSYM_F12               SDLK_F12
+#define KSYM_F13               SDLK_F13
+#define KSYM_F14               SDLK_F14
+#define KSYM_F15               SDLK_F15
+#define KSYM_F16               KSYM_UNDEFINED
+#define KSYM_F17               KSYM_UNDEFINED
+#define KSYM_F18               KSYM_UNDEFINED
+#define KSYM_F19               KSYM_UNDEFINED
+#define KSYM_F20               KSYM_UNDEFINED
+#define KSYM_F21               KSYM_UNDEFINED
+#define KSYM_F22               KSYM_UNDEFINED
+#define KSYM_F23               KSYM_UNDEFINED
+#define KSYM_F24               KSYM_UNDEFINED
+
+
+/* SDL function definitions */
+
+inline void SDLInitVideoDisplay(void);
+inline void SDLInitVideoBuffer(DrawBuffer **, DrawWindow **, boolean);
+inline boolean SDLSetVideoMode(DrawBuffer **, boolean);
+inline void SDLCopyArea(Bitmap *, Bitmap *, int, int, int, int, int, int, int);
+inline void SDLFillRectangle(Bitmap *, int, int, int, int, unsigned int);
+inline void SDLDrawSimpleLine(SDL_Surface *, int, int, int, int, unsigned int);
+inline void SDLDrawLine(SDL_Surface *, int, int, int, int, Uint32);
+/* functions from SGE library */
+void sge_Line(SDL_Surface *, Sint16, Sint16, Sint16, Sint16, Uint32);
+
+Bitmap *SDLLoadImage(char *);
+
+inline void SDLOpenAudio(void);
+inline void SDLCloseAudio(void);
+
+#endif /* SDL_H */
diff --git a/src/libgame/sound.c b/src/libgame/sound.c
new file mode 100644 (file)
index 0000000..e038f03
--- /dev/null
@@ -0,0 +1,1245 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* sound.c                                                  *
+***********************************************************/
+
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <signal.h>
+
+#include "system.h"
+#include "sound.h"
+#include "misc.h"
+
+
+static int num_sounds = 0, num_music = 0;
+static struct SampleInfo *Sound = NULL;
+#if defined(TARGET_SDL)
+static int num_mods = 0;
+static struct SampleInfo *Mod = NULL;
+#endif
+
+
+/*** THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
+
+static int playing_sounds = 0;
+static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
+static struct SoundControl emptySoundControl =
+{
+  -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE, 0,0L,0L,NULL
+};
+
+#if defined(PLATFORM_UNIX)
+static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
+static char premix_first_buffer[SND_BLOCKSIZE];
+#if defined(AUDIO_STREAMING_DSP)
+static char premix_left_buffer[SND_BLOCKSIZE];
+static char premix_right_buffer[SND_BLOCKSIZE];
+static int premix_last_buffer[SND_BLOCKSIZE];
+#endif
+static unsigned char playing_buffer[SND_BLOCKSIZE];
+#endif
+
+/* forward declaration of internal functions */
+#if defined(AUDIO_STREAMING_DSP)
+static void SoundServer_InsertNewSound(struct SoundControl);
+#elif defined(PLATFORM_UNIX)
+static unsigned char linear_to_ulaw(int);
+static int ulaw_to_linear(unsigned char);
+#endif
+
+#if defined(PLATFORM_HPUX)
+static void HPUX_Audio_Control();
+#endif
+
+#if defined(PLATFORM_MSDOS)
+static void SoundServer_InsertNewSound(struct SoundControl);
+static void SoundServer_StopSound(int);
+static void SoundServer_StopAllSounds();
+#endif
+
+#if defined(PLATFORM_UNIX)
+static int OpenAudioDevice(char *audio_device_name)
+{
+  int audio_fd;
+
+  /* check if desired audio device is accessible */
+  if (access(audio_device_name, W_OK) != 0)
+    return -1;
+
+  /* try to open audio device in non-blocking mode */
+  if ((audio_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
+    return audio_fd;
+
+  /* re-open audio device in blocking mode */
+  close(audio_fd);
+  audio_fd = open(audio_device_name, O_WRONLY);
+
+  return audio_fd;
+}
+
+static boolean TestAudioDevices(void)
+{
+  static char *audio_device_name[] =
+  {
+    DEVICENAME_DSP,
+    DEVICENAME_AUDIO
+  };
+  int audio_fd = -1;
+  int i;
+
+  /* look for available audio devices, starting with preferred ones */
+  for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
+    if ((audio_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
+      break;
+
+  if (audio_fd < 0)
+  {
+    Error(ERR_WARN, "cannot open audio device - no sound");
+    return FALSE;
+  }
+
+  close(audio_fd);
+
+  audio.device_name = audio_device_name[i];
+
+  return TRUE;
+}
+
+#if !defined(TARGET_SDL)
+static boolean ForkAudioProcess(void)
+{
+  if (pipe(audio.soundserver_pipe) < 0)
+  {
+    Error(ERR_WARN, "cannot create pipe - no sounds");
+    return FALSE;
+  }
+
+  if ((audio.soundserver_pid = fork()) < 0)
+  {       
+    Error(ERR_WARN, "cannot create sound server process - no sounds");
+    return FALSE;
+  }
+
+  if (audio.soundserver_pid == 0)      /* we are child */
+  {
+    SoundServer();
+
+    /* never reached */
+    exit(0);
+  }
+  else                                 /* we are parent */
+    close(audio.soundserver_pipe[0]); /* no reading from pipe needed */
+
+  return TRUE;
+}
+#endif
+
+void UnixOpenAudio(void)
+{
+  if (!TestAudioDevices())
+    return;
+
+  audio.sound_available = TRUE;
+  audio.sound_enabled = TRUE;
+
+#if defined(AUDIO_STREAMING_DSP)
+  audio.music_available = TRUE;
+  audio.loops_available = TRUE;
+#endif
+}
+
+void UnixCloseAudio(void)
+{
+  if (audio.device_fd)
+    close(audio.device_fd);
+
+  if (audio.soundserver_pid)
+    kill(audio.soundserver_pid, SIGTERM);
+}
+#endif /* PLATFORM_UNIX */
+
+void InitPlaylist(void)
+{
+  int i;
+
+  for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+    playlist[i] = emptySoundControl;
+  playing_sounds = 0;
+}
+
+void StartSoundserver(void)
+{
+#if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
+  if (!ForkAudioProcess())
+    audio.sound_available = FALSE;
+#endif
+}
+
+#if defined(PLATFORM_UNIX)
+void SoundServer(void)
+{
+  int i;
+
+  struct SoundControl snd_ctrl;
+  fd_set sound_fdset;
+
+  close(audio.soundserver_pipe[1]);    /* no writing into pipe needed */
+
+  InitPlaylist();
+
+  stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
+  for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
+    stereo_volume[i] =
+      (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
+
+#if defined(PLATFORM_HPUX)
+  HPUX_Audio_Control();
+#endif
+
+  FD_ZERO(&sound_fdset); 
+  FD_SET(audio.soundserver_pipe[0], &sound_fdset);
+
+  while(1)     /* wait for sound playing commands from client */
+  {
+    FD_SET(audio.soundserver_pipe[0], &sound_fdset);
+    select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
+    if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
+      continue;
+    if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
+       != sizeof(snd_ctrl))
+      Error(ERR_EXIT_SOUND_SERVER, "broken pipe - no sounds");
+
+#if defined(AUDIO_STREAMING_DSP)
+
+    if (snd_ctrl.fade_sound)
+    {
+      if (!playing_sounds)
+       continue;
+
+      for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+       if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
+         playlist[i].fade_sound = TRUE;
+    }
+    else if (snd_ctrl.stop_all_sounds)
+    {
+      if (!playing_sounds)
+       continue;
+
+      for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+       playlist[i]=emptySoundControl;
+      playing_sounds=0;
+
+      close(audio.device_fd);
+    }
+    else if (snd_ctrl.stop_sound)
+    {
+      if (!playing_sounds)
+       continue;
+
+      for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+       if (playlist[i].nr == snd_ctrl.nr)
+       {
+         playlist[i]=emptySoundControl;
+         playing_sounds--;
+       }
+
+      if (!playing_sounds)
+       close(audio.device_fd);
+    }
+
+    if (playing_sounds || snd_ctrl.active)
+    {
+      struct timeval delay = { 0, 0 };
+      byte *sample_ptr;
+      long sample_size;
+      static long max_sample_size = 0;
+      static long fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
+      int sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
+      int stereo = TRUE;
+      /* 'ioctl()' expects pointer to integer value for stereo flag
+        (boolean is defined as 'char', which will not work here) */
+
+      if (playing_sounds ||
+         (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
+      {
+       if (!playing_sounds)    /* we just opened the audio device */
+       {
+         unsigned long fragment_spec = 0;
+
+         /* determine logarithm (log2) of the fragment size */
+         for (fragment_spec=0; (1 << fragment_spec) < fragment_size;
+              fragment_spec++);
+
+         /* use two fragments (play one fragment, prepare the other);
+            one fragment would result in interrupted audio output, more
+            than two fragments would raise audio output latency to much */
+         fragment_spec |= 0x00020000;
+
+         /* Example for fragment specification:
+            - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
+            - (with stereo the effective buffer size will shrink to 256)
+            => fragment_size = 0x00020009 */
+
+         if (ioctl(audio.device_fd,SNDCTL_DSP_SETFRAGMENT,&fragment_spec) < 0)
+           Error(ERR_EXIT_SOUND_SERVER,
+                 "cannot set fragment size of /dev/dsp - no sounds");
+
+         /* try if we can use stereo sound */
+         if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
+         {
+#ifdef DEBUG
+           static boolean reported = FALSE;
+
+           if (!reported)
+           {
+             Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
+             reported = TRUE;
+           }
+#endif
+           stereo = FALSE;
+         }
+
+         if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
+           Error(ERR_EXIT_SOUND_SERVER,
+                 "cannot set sample rate of /dev/dsp - no sounds");
+
+         /* get the real fragmentation size; this should return 512 */
+         if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE,&fragment_size) < 0)
+           Error(ERR_EXIT_SOUND_SERVER,
+                 "cannot get fragment size of /dev/dsp - no sounds");
+
+         max_sample_size = fragment_size / (stereo ? 2 : 1);
+       }
+
+       if (snd_ctrl.active)    /* new sound has arrived */
+         SoundServer_InsertNewSound(snd_ctrl);
+
+       while(playing_sounds &&
+             select(audio.soundserver_pipe[0] + 1,
+                    &sound_fdset, NULL, NULL, &delay) < 1)
+       {       
+         FD_SET(audio.soundserver_pipe[0], &sound_fdset);
+
+         /* first clear the last premixing buffer */
+         memset(premix_last_buffer, 0, fragment_size * sizeof(int));
+
+         for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+         {
+           int j;
+
+           if (!playlist[i].active)
+             continue;
+
+           /* get pointer and size of the actual sound sample */
+           sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
+           sample_size =
+             MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
+           playlist[i].playingpos += sample_size;
+
+           /* fill the first mixing buffer with original sample */
+           memcpy(premix_first_buffer,sample_ptr,sample_size);
+
+           /* are we about to restart a looping sound? */
+           if (playlist[i].loop && sample_size<max_sample_size)
+           {
+             playlist[i].playingpos = max_sample_size-sample_size;
+             memcpy(premix_first_buffer+sample_size,
+                    playlist[i].data_ptr,max_sample_size-sample_size);
+             sample_size = max_sample_size;
+           }
+
+           /* decrease volume if sound is fading out */
+           if (playlist[i].fade_sound &&
+               playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
+             playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
+
+           /* adjust volume of actual sound sample */
+           if (playlist[i].volume != PSND_MAX_VOLUME)
+             for(j=0;j<sample_size;j++)
+               premix_first_buffer[j] =
+                 (playlist[i].volume * (int)premix_first_buffer[j])
+                   >> PSND_MAX_VOLUME_BITS;
+
+           /* fill the last mixing buffer with stereo or mono sound */
+           if (stereo)
+           {
+             int middle_pos = PSND_MAX_LEFT2RIGHT/2;
+             int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
+             int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
+
+             for(j=0;j<sample_size;j++)
+             {
+               premix_left_buffer[j] =
+                 (left_volume * (int)premix_first_buffer[j])
+                   >> PSND_MAX_LEFT2RIGHT_BITS;
+               premix_right_buffer[j] =
+                 (right_volume * (int)premix_first_buffer[j])
+                   >> PSND_MAX_LEFT2RIGHT_BITS;
+               premix_last_buffer[2*j+0] += premix_left_buffer[j];
+               premix_last_buffer[2*j+1] += premix_right_buffer[j];
+             }
+           }
+           else
+           {
+             for(j=0;j<sample_size;j++)
+               premix_last_buffer[j] += (int)premix_first_buffer[j];
+           }
+
+           /* delete completed sound entries from the playlist */
+           if (playlist[i].playingpos >= playlist[i].data_len)
+           {
+             if (playlist[i].loop)
+               playlist[i].playingpos = 0;
+             else
+             {
+               playlist[i] = emptySoundControl;
+               playing_sounds--;
+             }
+           }
+           else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
+           {
+             playlist[i] = emptySoundControl;
+             playing_sounds--;
+           }
+         }
+
+         /* put last mixing buffer to final playing buffer */
+         for(i=0; i<fragment_size; i++)
+         {
+           if (premix_last_buffer[i]<-255)
+             playing_buffer[i] = 0;
+           else if (premix_last_buffer[i]>255)
+             playing_buffer[i] = 255;
+           else
+             playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
+         }
+
+         /* finally play the sound fragment */
+         write(audio.device_fd, playing_buffer, fragment_size);
+       }
+
+       /* if no sounds playing, free device for other sound programs */
+       if (!playing_sounds)
+         close(audio.device_fd);
+      }
+    }
+
+#else /* !AUDIO_STREAMING_DSP */
+
+    if (snd_ctrl.active && !snd_ctrl.loop)
+    {
+      struct timeval delay = { 0, 0 };
+      byte *sample_ptr;
+      long sample_size, max_sample_size = SND_BLOCKSIZE;
+      long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
+      int wait_percent = 90;   /* wait 90% of the real playing time */
+      int i;
+
+      if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
+      {
+       playing_sounds = 1;
+
+       while(playing_sounds &&
+             select(audio.soundserver_pipe[0] + 1,
+                    &sound_fdset, NULL, NULL, &delay) < 1)
+       {       
+         FD_SET(audio.soundserver_pipe[0], &sound_fdset);
+
+         /* get pointer and size of the actual sound sample */
+         sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
+         sample_size =
+           MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
+         snd_ctrl.playingpos += sample_size;
+
+         /* fill the first mixing buffer with original sample */
+         memcpy(premix_first_buffer,sample_ptr,sample_size);
+
+
+         /* adjust volume of actual sound sample */
+         if (snd_ctrl.volume != PSND_MAX_VOLUME)
+           for(i=0;i<sample_size;i++)
+             premix_first_buffer[i] =
+               (snd_ctrl.volume * (int)premix_first_buffer[i])
+                 >> PSND_MAX_VOLUME_BITS;
+
+         for(i=0;i<sample_size;i++)
+           playing_buffer[i] =
+             linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
+
+         if (snd_ctrl.playingpos >= snd_ctrl.data_len)
+           playing_sounds = 0;
+
+         /* finally play the sound fragment */
+         write(audio.device_fd,playing_buffer,sample_size);
+
+         delay.tv_sec = 0;
+         delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
+       }
+       close(audio.device_fd);
+      }
+    }
+#endif /* !AUDIO_STREAMING_DSP */
+  }
+}
+#endif /* PLATFORM_UNIX */
+
+#if defined(PLATFORM_MSDOS)
+static void sound_handler(struct SoundControl snd_ctrl)
+{
+  int i;
+
+  if (snd_ctrl.fade_sound)
+  {
+    if (!playing_sounds)
+      return;
+
+    for (i=0; i<MAX_SOUNDS_PLAYING; i++)
+      if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
+         !playlist[i].fade_sound)
+      {
+       playlist[i].fade_sound = TRUE;
+       if (voice_check(playlist[i].voice))
+         voice_ramp_volume(playlist[i].voice, 1000, 0);
+       playlist[i].loop = PSND_NO_LOOP;
+      }
+  }
+  else if (snd_ctrl.stop_all_sounds)
+  {
+    if (!playing_sounds)
+      return;
+    SoundServer_StopAllSounds();
+  }
+  else if (snd_ctrl.stop_sound)
+  {
+    if (!playing_sounds)
+      return;
+    SoundServer_StopSound(snd_ctrl.nr);
+  }
+
+  for (i=0; i<MAX_SOUNDS_PLAYING; i++)
+  {
+    if (!playlist[i].active || playlist[i].loop)
+      continue;
+
+    playlist[i].playingpos = voice_get_position(playlist[i].voice);
+    playlist[i].volume = voice_get_volume(playlist[i].voice);
+    if (playlist[i].playingpos == -1 || !playlist[i].volume)
+    {
+      deallocate_voice(playlist[i].voice);
+      playlist[i] = emptySoundControl;
+      playing_sounds--;
+    }
+  }
+
+  if (snd_ctrl.active)
+    SoundServer_InsertNewSound(snd_ctrl);
+}
+#endif /* PLATFORM_MSDOS */
+
+#if !defined(PLATFORM_WIN32)
+static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
+{
+  int i, k;
+
+  /* if playlist is full, remove oldest sound */
+  if (playing_sounds==MAX_SOUNDS_PLAYING)
+  {
+    int longest=0, longest_nr=0;
+
+    for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+    {
+#if !defined(PLATFORM_MSDOS)
+      int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
+#else
+      int actual = playlist[i].playingpos;
+#endif
+
+      if (!playlist[i].loop && actual>longest)
+      {
+       longest=actual;
+       longest_nr=i;
+      }
+    }
+#if defined(PLATFORM_MSDOS)
+    voice_set_volume(playlist[longest_nr].voice, 0);
+    deallocate_voice(playlist[longest_nr].voice);
+#endif
+    playlist[longest_nr] = emptySoundControl;
+    playing_sounds--;
+  }
+
+  /* check if sound is already being played (and how often) */
+  for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
+  {
+    if (playlist[i].nr == snd_ctrl.nr)
+      k++;
+  }
+
+  /* restart loop sounds only if they are just fading out */
+  if (k>=1 && snd_ctrl.loop)
+  {
+    for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+    {
+      if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
+      {
+       playlist[i].fade_sound = FALSE;
+       playlist[i].volume = PSND_MAX_VOLUME;
+#if defined(PLATFORM_MSDOS)
+        playlist[i].loop = PSND_LOOP;
+        voice_stop_volumeramp(playlist[i].voice);
+        voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
+#endif
+      }
+    }
+    return;
+  }
+
+  /* don't play sound more than n times simultaneously (with n == 2 for now) */
+  if (k>=2)
+  {
+    int longest=0, longest_nr=0;
+
+    /* look for oldest equal sound */
+    for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+    {
+      int actual;
+
+      if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
+       continue;
+
+#if !defined(PLATFORM_MSDOS)
+      actual = 100 * playlist[i].playingpos / playlist[i].data_len;
+#else
+      actual = playlist[i].playingpos;
+#endif
+      if (actual>=longest)
+      {
+       longest=actual;
+       longest_nr=i;
+      }
+    }
+
+#if defined(PLATFORM_MSDOS)
+    voice_set_volume(playlist[longest_nr].voice, 0);
+    deallocate_voice(playlist[longest_nr].voice);
+#endif
+    playlist[longest_nr] = emptySoundControl;
+    playing_sounds--;
+  }
+
+  /* neuen Sound in Liste packen */
+  for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+  {
+    if (!playlist[i].active)
+    {
+      playlist[i] = snd_ctrl;
+      playing_sounds++;
+
+#if defined(PLATFORM_MSDOS)
+      playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
+      if(snd_ctrl.loop)
+        voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
+      voice_set_volume(playlist[i].voice, snd_ctrl.volume);
+      voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
+      voice_start(playlist[i].voice);       
+#endif
+      break;
+    }
+  }
+}
+#endif /* !PLATFORM_WIN32 */
+
+/*
+void SoundServer_FadeSound(int nr)
+{
+  int i;
+
+  if (!playing_sounds)
+    return;
+
+  for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+    if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
+      playlist[i].fade_sound = TRUE;
+}
+*/
+
+#if !defined(PLATFORM_WIN32)
+#if defined(PLATFORM_MSDOS)
+static void SoundServer_StopSound(int nr)
+{
+  int i;
+
+  if (!playing_sounds)
+    return;
+
+  for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+    if (playlist[i].nr == nr)
+    {
+#if defined(PLATFORM_MSDOS)
+      voice_set_volume(playlist[i].voice, 0);
+      deallocate_voice(playlist[i].voice);
+#endif
+      playlist[i] = emptySoundControl;
+      playing_sounds--;
+    }
+
+#if !defined(PLATFORM_MSDOS)
+  if (!playing_sounds)
+    close(audio.device_fd);
+#endif
+}
+
+static void SoundServer_StopAllSounds()
+{
+  int i;
+
+  for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+  {
+#if defined(PLATFORM_MSDOS)
+    voice_set_volume(playlist[i].voice, 0);
+    deallocate_voice(playlist[i].voice);
+#endif
+    playlist[i]=emptySoundControl;
+  }
+  playing_sounds = 0;
+
+#if !defined(PLATFORM_MSDOS)
+  close(audio.device_fd);
+#endif
+}
+#endif /* PLATFORM_MSDOS */
+#endif /* !PLATFORM_WIN32 */
+
+#if defined(PLATFORM_HPUX)
+static void HPUX_Audio_Control()
+{
+  struct audio_describe ainfo;
+  int audio_ctl;
+
+  audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
+  if (audio_ctl == -1)
+    Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl - no sounds");
+
+  if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
+    Error(ERR_EXIT_SOUND_SERVER, "no audio info - no sounds");
+
+  if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
+    Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available - no sounds");
+
+  ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
+  ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
+
+  close(audio_ctl);
+}
+#endif /* PLATFORM_HPUX */
+
+#if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
+
+/* these two are stolen from "sox"... :) */
+
+/*
+** This routine converts from linear to ulaw.
+**
+** Craig Reese: IDA/Supercomputing Research Center
+** Joe Campbell: Department of Defense
+** 29 September 1989
+**
+** References:
+** 1) CCITT Recommendation G.711  (very difficult to follow)
+** 2) "A New Digital Technique for Implementation of Any
+**     Continuous PCM Companding Law," Villeret, Michel,
+**     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
+**     1973, pg. 11.12-11.17
+** 3) MIL-STD-188-113,"Interoperability and Performance Standards
+**     for Analog-to_Digital Conversion Techniques,"
+**     17 February 1987
+**
+** Input: Signed 16 bit linear sample
+** Output: 8 bit ulaw sample
+*/
+
+#define ZEROTRAP    /* turn on the trap as per the MIL-STD */
+#define BIAS 0x84   /* define the add-in bias for 16 bit samples */
+#define CLIP 32635
+
+static unsigned char linear_to_ulaw(int sample)
+{
+  static int exp_lut[256] =
+  {
+    0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
+    4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+  };
+
+  int sign, exponent, mantissa;
+  unsigned char ulawbyte;
+
+  /* Get the sample into sign-magnitude. */
+  sign = (sample >> 8) & 0x80;         /* set aside the sign */
+  if (sign != 0)
+    sample = -sample;                  /* get magnitude */
+  if (sample > CLIP)
+    sample = CLIP;                     /* clip the magnitude */
+
+  /* Convert from 16 bit linear to ulaw. */
+  sample = sample + BIAS;
+  exponent = exp_lut[( sample >> 7 ) & 0xFF];
+  mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
+  ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
+#ifdef ZEROTRAP
+  if (ulawbyte == 0)
+    ulawbyte = 0x02;                   /* optional CCITT trap */
+#endif
+
+  return(ulawbyte);
+}
+
+/*
+** This routine converts from ulaw to 16 bit linear.
+**
+** Craig Reese: IDA/Supercomputing Research Center
+** 29 September 1989
+**
+** References:
+** 1) CCITT Recommendation G.711  (very difficult to follow)
+** 2) MIL-STD-188-113,"Interoperability and Performance Standards
+**     for Analog-to_Digital Conversion Techniques,"
+**     17 February 1987
+**
+** Input: 8 bit ulaw sample
+** Output: signed 16 bit linear sample
+*/
+
+static int ulaw_to_linear(unsigned char ulawbyte)
+{
+  static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
+  int sign, exponent, mantissa, sample;
+
+  ulawbyte = ~ ulawbyte;
+  sign = ( ulawbyte & 0x80 );
+  exponent = ( ulawbyte >> 4 ) & 0x07;
+  mantissa = ulawbyte & 0x0F;
+  sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
+  if (sign != 0)
+    sample = -sample;
+
+  return(sample);
+}
+#endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
+
+/*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
+
+/*===========================================================================*/
+
+/*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
+
+#define CHUNK_ID_LEN            4       /* IFF style chunk id length */
+#define WAV_HEADER_SIZE                20      /* size of WAV file header */
+
+static boolean LoadSoundExt(char *sound_name, boolean is_music)
+{
+  struct SampleInfo *snd_info;
+  char filename[256];
+#if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
+  byte sound_header_buffer[WAV_HEADER_SIZE];
+  char chunk[CHUNK_ID_LEN + 1];
+  int chunk_length, dummy;
+  FILE *file;
+  int i;
+#endif
+
+  num_sounds++;
+  Sound = checked_realloc(Sound, num_sounds * sizeof(struct SampleInfo));
+
+  snd_info = &Sound[num_sounds - 1];
+  snd_info->name = sound_name;
+
+  sprintf(filename, "%s/%s/%s", options.ro_base_directory,
+         (is_music ? MUSIC_DIRECTORY : SOUNDS_DIRECTORY), snd_info->name);
+
+#if defined(TARGET_SDL)
+
+  if ((snd_info->mix_chunk = Mix_LoadWAV(filename)) == NULL)
+  {
+    Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
+    return FALSE;
+  }
+
+#elif defined(PLATFORM_UNIX)
+
+  if ((file = fopen(filename, MODE_READ)) == NULL)
+  {
+    Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
+    return FALSE;
+  }
+
+  /* read chunk "RIFF" */
+  getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
+  if (strcmp(chunk, "RIFF") != 0)
+  {
+    Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
+    fclose(file);
+    return FALSE;
+  }
+
+  /* read chunk "WAVE" */
+  getFileChunk(file, chunk, &dummy, BYTE_ORDER_LITTLE_ENDIAN);
+  if (strcmp(chunk, "WAVE") != 0)
+  {
+    Error(ERR_WARN, "missing 'WAVE' chunk of sound file '%s'", filename);
+    fclose(file);
+    return FALSE;
+  }
+
+  /* read header information */
+  for (i=0; i<WAV_HEADER_SIZE; i++)
+    sound_header_buffer[i] = fgetc(file);
+
+  /* read chunk "data" */
+  getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
+  if (strcmp(chunk, "data") != 0)
+  {
+    Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
+    fclose(file);
+    return FALSE;
+  }
+
+  snd_info->data_len = chunk_length;
+  snd_info->data_ptr = checked_malloc(snd_info->data_len);
+
+  /* read sound data */
+  if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
+      snd_info->data_len)
+  {
+    Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
+    fclose(file);
+    return FALSE;
+  }
+
+  fclose(file);
+
+  for (i=0; i<snd_info->data_len; i++)
+    snd_info->data_ptr[i] = snd_info->data_ptr[i] ^ 0x80;
+
+#else /* PLATFORM_MSDOS */
+
+  snd_info->sample_ptr = load_sample(filename);
+  if (!snd_info->sample_ptr)
+  {
+    Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
+    return FALSE;
+  }
+
+#endif
+
+  return TRUE;
+}
+
+boolean LoadSound(char *sound_name)
+{
+  return LoadSoundExt(sound_name, FALSE);
+}
+
+boolean LoadMod(char *mod_name)
+{
+#if defined(TARGET_SDL)
+  struct SampleInfo *mod_info;
+  char filename[256];
+
+  num_mods++;
+  Mod = checked_realloc(Mod, num_mods * sizeof(struct SampleInfo));
+
+  mod_info = &Mod[num_mods - 1];
+  mod_info->name = mod_name;
+
+  sprintf(filename, "%s/%s/%s", options.ro_base_directory,
+         MUSIC_DIRECTORY, mod_info->name);
+
+  if ((mod_info->mix_music = Mix_LoadMUS(filename)) == NULL)
+  {
+    Error(ERR_WARN, "cannot read music file '%s' - no music", filename);
+    return FALSE;
+  }
+
+  return TRUE;
+#else
+  return FALSE;
+#endif
+}
+
+int LoadMusic(void)
+{
+  DIR *dir;
+  struct dirent *dir_entry;
+  char *music_directory = getPath2(options.ro_base_directory, MUSIC_DIRECTORY);
+  int num_wav_music = 0;
+  int num_mod_music = 0;
+
+  if ((dir = opendir(music_directory)) == NULL)
+  {
+    Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
+    audio.music_available = FALSE;
+    free(music_directory);
+    return 0;
+  }
+
+  while ((dir_entry = readdir(dir)) != NULL)   /* loop until last dir entry */
+  {
+    char *filename = dir_entry->d_name;
+
+    if (strlen(filename) > 4 &&
+       strcmp(&filename[strlen(filename) - 4], ".wav") == 0)
+    {
+      if (LoadSoundExt(filename, TRUE))
+       num_wav_music++;
+    }
+    else if (strlen(filename) > 4 &&
+            (strcmp(&filename[strlen(filename) - 4], ".mod") == 0 ||
+             strcmp(&filename[strlen(filename) - 4], ".MOD") == 0 ||
+             strncmp(filename, "mod.", 4) == 0 ||
+             strncmp(filename, "MOD.", 4) == 0))
+    {
+      if (LoadMod(filename))
+       num_mod_music++;
+    }
+  }
+
+  closedir(dir);
+
+  if (num_wav_music == 0 && num_mod_music == 0)
+    Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
+         music_directory);
+
+  free(music_directory);
+
+  num_music = (num_mod_music > 0 ? num_mod_music : num_wav_music);
+
+  audio.mods_available = (num_mod_music > 0);
+  audio.music_available = (num_music > 0);
+
+  return num_music;
+}
+
+void PlayMusic(int nr)
+{
+  if (!audio.music_available)
+    return;
+
+  if (!audio.mods_available)
+    nr = num_sounds - num_music + nr;
+
+#if defined(TARGET_SDL)
+  if (audio.mods_available)    /* play MOD music */
+  {
+    Mix_VolumeMusic(SOUND_MAX_VOLUME);
+    Mix_PlayMusic(Mod[nr].mix_music, -1);
+  }
+  else                         /* play WAV music loop */
+  {
+    Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
+    Mix_PlayChannel(audio.music_channel, Sound[nr].mix_chunk, -1);
+  }
+#else
+  audio.music_nr = nr;
+  PlaySoundLoop(nr);
+#endif
+}
+
+void PlaySound(int nr)
+{
+  PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
+}
+
+void PlaySoundStereo(int nr, int stereo)
+{
+  PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
+}
+
+void PlaySoundLoop(int nr)
+{
+  PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
+}
+
+void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
+{
+  struct SoundControl snd_ctrl = emptySoundControl;
+
+  if (!audio.sound_available || !audio.sound_enabled)
+    return;
+
+  if (volume<PSND_MIN_VOLUME)
+    volume = PSND_MIN_VOLUME;
+  else if (volume>PSND_MAX_VOLUME)
+    volume = PSND_MAX_VOLUME;
+
+  if (stereo<PSND_MAX_LEFT)
+    stereo = PSND_MAX_LEFT;
+  else if (stereo>PSND_MAX_RIGHT)
+    stereo = PSND_MAX_RIGHT;
+
+  snd_ctrl.nr          = nr;
+  snd_ctrl.volume      = volume;
+  snd_ctrl.stereo      = stereo;
+  snd_ctrl.loop                = loop;
+  snd_ctrl.active      = TRUE;
+  snd_ctrl.data_ptr    = Sound[nr].data_ptr;
+  snd_ctrl.data_len    = Sound[nr].data_len;
+
+#if defined(TARGET_SDL)
+  Mix_Volume(-1, SOUND_MAX_VOLUME);
+  Mix_PlayChannel(-1, Sound[nr].mix_chunk, (loop ? -1 : 0));
+#elif defined(PLATFORM_UNIX)
+  if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
+  {
+    Error(ERR_WARN, "cannot pipe to child process - no sounds");
+    audio.sound_available = audio.sound_enabled = FALSE;
+    return;
+  }
+#elif defined(PLATFORM_MSDOS)
+  sound_handler(snd_ctrl);
+#endif
+}
+
+void FadeMusic(void)
+{
+#if defined(TARGET_SDL)
+  if (audio.mods_available)
+    Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
+  else
+    Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
+#else
+  FadeSound(audio.music_nr);
+#endif
+}
+
+void FadeSound(int nr)
+{
+  StopSoundExt(nr, SSND_FADE_SOUND);
+}
+
+void FadeSounds()
+{
+  FadeMusic();
+  StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
+}
+
+void StopMusic(void)
+{
+#if defined(TARGET_SDL)
+  if (audio.mods_available)
+    Mix_HaltMusic();
+  else
+    Mix_HaltChannel(audio.music_channel);
+#else
+  StopSound(audio.music_nr);
+#endif
+}
+
+void StopSound(int nr)
+{
+  StopSoundExt(nr, SSND_STOP_SOUND);
+}
+
+void StopSounds()
+{
+  StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
+}
+
+void StopSoundExt(int nr, int method)
+{
+  struct SoundControl snd_ctrl = emptySoundControl;
+
+  if (!audio.sound_available)
+    return;
+
+  if (SSND_FADING(method))
+    snd_ctrl.fade_sound = TRUE;
+
+  if (SSND_ALL(method))
+    snd_ctrl.stop_all_sounds = TRUE;
+  else
+  {
+    snd_ctrl.nr = nr;
+    snd_ctrl.stop_sound = TRUE;
+  }
+
+#if defined(TARGET_SDL)
+
+  if (SSND_FADING(method))
+  {
+    int i;
+
+    for (i=0; i<audio.channels; i++)
+      if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
+       Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
+    if (snd_ctrl.stop_all_sounds)
+      Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
+  }
+  else
+  {
+    int i;
+
+    for (i=0; i<audio.channels; i++)
+      if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
+       Mix_HaltChannel(i);
+    if (snd_ctrl.stop_all_sounds)
+      Mix_HaltMusic();
+  }
+
+#else
+#if !defined(PLATFORM_MSDOS)
+  if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
+  {
+    Error(ERR_WARN, "cannot pipe to child process - no sounds");
+    audio.sound_available = audio.sound_enabled = FALSE;
+    return;
+  }
+#else
+  sound_handler(snd_ctrl);
+#endif
+#endif
+}
+
+void FreeSounds(int num_sounds)
+{
+  int i;
+
+  if (!audio.sound_available)
+    return;
+
+  for(i=0; i<num_sounds; i++)
+#if defined(TARGET_SDL)
+    free(Sound[i].mix_chunk);
+#elif !defined(PLATFORM_MSDOS)
+    free(Sound[i].data_ptr);
+#else
+    destroy_sample(Sound[i].sample_ptr);
+#endif
+}
+
+/*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/
diff --git a/src/libgame/sound.h b/src/libgame/sound.h
new file mode 100644 (file)
index 0000000..b297062
--- /dev/null
@@ -0,0 +1,215 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* sound.h                                                  *
+***********************************************************/
+
+#ifndef SOUND_H
+#define SOUND_H
+
+#include <math.h>
+
+#include "platform.h"
+
+#if defined(PLATFORM_LINUX)
+#include <sys/ioctl.h>
+#endif
+
+#if defined(PLATFORM_LINUX)
+#include <linux/soundcard.h>
+#elif defined(PLATFORM_FREEBSD)
+#include <machine/soundcard.h>
+#elif defined(PLATFORM_HPUX)
+#include <sys/audio.h>
+#endif
+
+#include "system.h"
+
+
+#if defined(PLATFORM_LINUX) || defined(PLATFORM_FREEBSD) || defined(VOXWARE)
+#define AUDIO_STREAMING_DSP
+#endif
+
+#define AUDIO_SAMPLE_RATE_8000                 8000
+#define AUDIO_SAMPLE_RATE_22050                        22050
+
+#define AUDIO_FRAGMENT_SIZE_512                        512
+#define AUDIO_FRAGMENT_SIZE_1024               1024
+#define AUDIO_FRAGMENT_SIZE_2048               2048
+#define AUDIO_FRAGMENT_SIZE_4096               4096
+
+#define AUDIO_MONO_CHANNEL                     1
+#define AUDIO_STEREO_CHANNELS                  2
+
+#if defined(TARGET_SDL)
+/* one second fading interval == 1000 ticks (milliseconds) */
+#define SOUND_FADING_INTERVAL                  1000
+#define SOUND_MAX_VOLUME                       (SDL_MIX_MAXVOLUME / 4)
+#endif
+
+#if defined(AUDIO_STREAMING_DSP)
+#define SOUND_FADING_VOLUME_STEP               (PSND_MAX_VOLUME / 40)
+#define SOUND_FADING_VOLUME_THRESHOLD          (SOUND_FADING_VOLUME_STEP * 2)
+#endif
+
+#define DEFAULT_AUDIO_SAMPLE_RATE              AUDIO_SAMPLE_RATE_22050
+#define DEFAULT_AUDIO_FRAGMENT_SIZE_UNIX       AUDIO_FRAGMENT_SIZE_512
+#define DEFAULT_AUDIO_FRAGMENT_SIZE_WIN32      AUDIO_FRAGMENT_SIZE_2048
+
+#if defined(PLATFORM_UNIX)
+#define DEFAULT_AUDIO_FRAGMENT_SIZE    DEFAULT_AUDIO_FRAGMENT_SIZE_UNIX
+#else
+#define DEFAULT_AUDIO_FRAGMENT_SIZE    DEFAULT_AUDIO_FRAGMENT_SIZE_WIN32
+#endif
+
+#if !defined(PLATFORM_MSDOS)
+#define MAX_SOUNDS_PLAYING                     16
+#else
+#define MAX_SOUNDS_PLAYING                     8
+#endif
+
+#if !defined(PLATFORM_HPUX)
+#define SND_BLOCKSIZE 4096
+#else
+#define SND_BLOCKSIZE 32768
+#endif
+
+/* some values for PlaySound(), StopSound() and friends */
+#if !defined(PLATFORM_MSDOS)
+#define PSND_SILENCE           0
+#define PSND_MAX_VOLUME_BITS   7
+#define PSND_MIN_VOLUME                0
+#define PSND_MAX_VOLUME                (1 << PSND_MAX_VOLUME_BITS)
+#define PSND_NO_LOOP           0
+#define PSND_LOOP              1
+#define PSND_MIDDLE            0
+#define PSND_MAX_STEREO_BITS   7
+#define PSND_MAX_STEREO                (1 << PSND_MAX_STEREO_BITS)
+#define PSND_MAX_LEFT          (-PSND_MAX_STEREO)
+#define PSND_MAX_RIGHT         (+PSND_MAX_STEREO)
+#define PSND_MAX_LEFT2RIGHT_BITS (PSND_MAX_STEREO_BITS+1)
+#define PSND_MAX_LEFT2RIGHT    (1 << PSND_MAX_LEFT2RIGHT_BITS)
+#else
+#define PSND_SILENCE           0
+#define PSND_MIN_VOLUME                0
+#define PSND_MAX_VOLUME                255
+#define PSND_NO_LOOP           0
+#define PSND_LOOP              1
+#define PSND_MAX_LEFT          0
+#define PSND_MAX_RIGHT         255
+#define PSND_MIDDLE            128
+#endif
+
+#define SSND_FADE_SOUND                (1<<0)
+#define SSND_FADE_ALL_SOUNDS   (1<<1)
+#define SSND_FADING(x)         (x & (SSND_FADE_SOUND | SSND_FADE_ALL_SOUNDS))
+#define SSND_STOP_SOUND                (1<<2)
+#define SSND_STOP_ALL_SOUNDS   (1<<3)
+#define SSND_STOPPING(x)       (x & (SSND_STOP_SOUND | SSND_STOP_ALL_SOUNDS))
+#define SSND_ALL(x)            (x&(SSND_FADE_ALL_SOUNDS|SSND_STOP_ALL_SOUNDS))
+
+/* settings for sound path, sound device, etc. */
+#ifndef SND_PATH
+#define SND_PATH       "./sounds"
+#endif
+
+#define DEVICENAME_DSP         "/dev/dsp"
+#define DEVICENAME_AUDIO       "/dev/audio"
+#define DEVICENAME_AUDIOCTL    "/dev/audioCtl"
+
+#if 0
+#if defined(AUDIO_STREAMING_DSP)
+#define AUDIO_DEVICE           DEVICENAME_DSP
+#else
+#define AUDIO_DEVICE   DEVICENAME_AUDIO
+#endif
+#endif
+
+struct SoundHeader_SUN
+{
+  unsigned long magic;
+  unsigned long hdr_size;
+  unsigned long data_size;
+  unsigned long encoding;
+  unsigned long sample_rate;
+  unsigned long channels;
+};
+
+struct SoundHeader_8SVX
+{
+  char magic_FORM[4];
+  unsigned long chunk_size;
+  char magic_8SVX[4];
+};
+
+struct SampleInfo
+{ 
+  char *name;
+  byte *data_ptr;
+  long data_len;
+
+#if defined(PLATFORM_MSDOS)
+  SAMPLE *sample_ptr;
+#endif
+
+#if defined(TARGET_SDL)
+  Mix_Chunk *mix_chunk;
+  Mix_Music *mix_music;
+#endif
+};
+
+struct SoundControl
+{
+  int nr;
+  int volume;
+  int stereo;
+  boolean active;
+  boolean loop;
+  boolean fade_sound;
+  boolean stop_sound;
+  boolean stop_all_sounds;
+  int playingtime;
+  long playingpos;
+  long data_len;
+  byte *data_ptr;
+
+#if defined(PLATFORM_MSDOS)
+  int voice;
+#endif
+};
+
+/* general sound functions */
+void UnixOpenAudio(void);
+void UnixCloseAudio(void);
+
+/* sound server functions */ 
+void InitPlaylist(void);
+void StartSoundserver(void);
+void SoundServer(void);
+
+/* sound client functions */
+boolean LoadSound(char *);
+boolean LoadMod(char *);
+int LoadMusic(void);
+void PlayMusic(int);
+void PlaySound(int);
+void PlaySoundStereo(int, int);
+void PlaySoundLoop(int);
+void PlaySoundExt(int, int, int, boolean);
+void FadeMusic(void);
+void FadeSound(int);
+void FadeSounds(void);
+void StopMusic(void);
+void StopSound(int);
+void StopSounds(void);
+void StopSoundExt(int, int);
+void FreeSounds(int);
+
+#endif
diff --git a/src/libgame/system.c b/src/libgame/system.c
new file mode 100644 (file)
index 0000000..585780b
--- /dev/null
@@ -0,0 +1,712 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* system.c                                                 *
+***********************************************************/
+
+#include <string.h>
+#include <signal.h>
+
+#include "platform.h"
+
+#if defined(PLATFORM_MSDOS)
+#include <fcntl.h>
+#endif
+
+#include "system.h"
+#include "sound.h"
+#include "misc.h"
+
+
+/* ========================================================================= */
+/* exported variables                                                        */
+/* ========================================================================= */
+
+struct ProgramInfo     program;
+struct OptionInfo      options;
+struct VideoSystemInfo video;
+struct AudioSystemInfo audio;
+struct GfxInfo         gfx;
+
+struct LevelDirInfo    *leveldir_first = NULL;
+struct LevelDirInfo    *leveldir_current = NULL;
+
+Display        *display = NULL;
+Visual        *visual = NULL;
+int            screen = 0;
+Colormap       cmap = None;
+
+DrawWindow     *window = NULL;
+DrawBuffer     *backbuffer = NULL;
+DrawBuffer     *drawto = NULL;
+
+int            button_status = MB_NOT_PRESSED;
+boolean                motion_status = FALSE;
+
+int            redraw_mask = REDRAW_NONE;
+int            redraw_tiles = 0;
+
+int            FrameCounter = 0;
+
+
+/* ========================================================================= */
+/* init/close functions                                                      */
+/* ========================================================================= */
+
+void InitCommandName(char *argv0)
+{
+  program.command_basename =
+    (strrchr(argv0, '/') ? strrchr(argv0, '/') + 1 : argv0);
+}
+
+void InitExitFunction(void (*exit_function)(int))
+{
+  program.exit_function = exit_function;
+
+  /* set signal handlers to custom exit function */
+  signal(SIGINT, exit_function);
+  signal(SIGTERM, exit_function);
+
+#if defined(TARGET_SDL)
+  /* set exit function to automatically cleanup SDL stuff after exit() */
+  atexit(SDL_Quit);
+#endif
+}
+
+void InitPlatformDependantStuff(void)
+{
+#if defined(PLATFORM_MSDOS)
+  _fmode = O_BINARY;
+#endif
+
+#if !defined(PLATFORM_UNIX)
+  program.userdata_directory = "userdata";
+  initErrorFile();
+#endif
+
+#if defined(TARGET_SDL)
+  if (SDL_Init(SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE) < 0)
+    Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
+#endif
+}
+
+void ClosePlatformDependantStuff(void)
+{
+#if !defined(PLATFORM_UNIX)
+  dumpErrorFile();
+#endif
+}
+
+void InitProgramInfo(char *unix_userdata_directory, char *program_title,
+                    char *window_title, char *icon_title,
+                    char *x11_icon_basename, char *x11_iconmask_basename,
+                    char *msdos_pointer_basename)
+{
+  char *gfx_dir = getPath2(options.ro_base_directory, GRAPHICS_DIRECTORY);
+  char *x11_icon_filename = getPath2(gfx_dir, x11_icon_basename);
+  char *x11_iconmask_filename = getPath2(gfx_dir, x11_iconmask_basename);
+  char *msdos_pointer_filename = getPath2(gfx_dir, msdos_pointer_basename);
+
+  free(gfx_dir);
+
+#if defined(PLATFORM_UNIX)
+  program.userdata_directory = unix_userdata_directory;
+#else
+  program.userdata_directory = "userdata";
+#endif
+
+  program.program_title = program_title;
+  program.window_title = window_title;
+  program.icon_title = icon_title;
+  program.x11_icon_filename = x11_icon_filename;
+  program.x11_iconmask_filename = x11_iconmask_filename;
+  program.msdos_pointer_filename = msdos_pointer_filename;
+}
+
+void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize,
+                     int real_sx, int real_sy,
+                     int full_sxsize, int full_sysize)
+{
+  gfx.sx = sx;
+  gfx.sy = sy;
+  gfx.sxsize = sxsize;
+  gfx.sysize = sysize;
+  gfx.real_sx = real_sx;
+  gfx.real_sy = real_sy;
+  gfx.full_sxsize = full_sxsize;
+  gfx.full_sysize = full_sysize;
+}
+
+void InitGfxDoor1Info(int dx, int dy, int dxsize, int dysize)
+{
+  gfx.dx = dx;
+  gfx.dy = dy;
+  gfx.dxsize = dxsize;
+  gfx.dysize = dysize;
+}
+
+void InitGfxDoor2Info(int vx, int vy, int vxsize, int vysize)
+{
+  gfx.vx = vx;
+  gfx.vy = vy;
+  gfx.vxsize = vxsize;
+  gfx.vysize = vysize;
+}
+
+void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height)
+{
+  /* currently only used by MSDOS code to alloc VRAM buffer, if available */
+  gfx.scrollbuffer_width = scrollbuffer_width;
+  gfx.scrollbuffer_height = scrollbuffer_height;
+}
+
+
+/* ========================================================================= */
+/* video functions                                                           */
+/* ========================================================================= */
+
+inline static int GetRealDepth(int depth)
+{
+  return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
+}
+
+inline void InitVideoDisplay(void)
+{
+#if defined(TARGET_SDL)
+  SDLInitVideoDisplay();
+#else
+  X11InitVideoDisplay();
+#endif
+}
+
+inline void CloseVideoDisplay(void)
+{
+  KeyboardAutoRepeatOn();
+
+#if defined(TARGET_SDL)
+  SDL_QuitSubSystem(SDL_INIT_VIDEO);
+#else
+  if (display)
+    XCloseDisplay(display);
+#endif
+}
+
+inline void InitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
+                           int width, int height, int depth,
+                           boolean fullscreen)
+{
+  video.width = width;
+  video.height = height;
+  video.depth = GetRealDepth(depth);
+  video.fullscreen_available = FULLSCREEN_STATUS;
+  video.fullscreen_enabled = FALSE;
+
+#ifdef TARGET_SDL
+  SDLInitVideoBuffer(backbuffer, window, fullscreen);
+#else
+  X11InitVideoBuffer(backbuffer, window);
+#endif
+}
+
+inline Bitmap *CreateBitmapStruct(void)
+{
+#ifdef TARGET_SDL
+  return checked_calloc(sizeof(struct SDLSurfaceInfo));
+#else
+  return checked_calloc(sizeof(struct X11DrawableInfo));
+#endif
+}
+
+inline Bitmap *CreateBitmap(int width, int height, int depth)
+{
+  Bitmap *new_bitmap = CreateBitmapStruct();
+  int real_depth = GetRealDepth(depth);
+
+#ifdef TARGET_SDL
+  SDL_Surface *surface_tmp, *surface_native;
+
+  if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height,
+                                         real_depth, 0, 0, 0, 0))
+      == NULL)
+    Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
+
+  if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
+    Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
+
+  SDL_FreeSurface(surface_tmp);
+
+  new_bitmap->surface = surface_native;
+#else
+  Pixmap pixmap;
+
+  if ((pixmap = XCreatePixmap(display, window->drawable,
+                             width, height, real_depth))
+      == None)
+    Error(ERR_EXIT, "cannot create pixmap");
+
+  new_bitmap->drawable = pixmap;
+
+  if (window == NULL)
+    Error(ERR_EXIT, "Window GC needed for Bitmap -- create Window first");
+
+  new_bitmap->gc = window->gc;
+
+  new_bitmap->line_gc[0] = window->line_gc[0];
+  new_bitmap->line_gc[1] = window->line_gc[1];
+#endif
+
+  return new_bitmap;
+}
+
+inline void FreeBitmap(Bitmap *bitmap)
+{
+  if (bitmap == NULL)
+    return;
+
+#ifdef TARGET_SDL
+  if (bitmap->surface)
+    SDL_FreeSurface(bitmap->surface);
+  if (bitmap->surface_masked)
+    SDL_FreeSurface(bitmap->surface_masked);
+#else
+  if (bitmap->drawable)
+    XFreePixmap(display, bitmap->drawable);
+  if (bitmap->clip_mask)
+    XFreePixmap(display, bitmap->clip_mask);
+  if (bitmap->stored_clip_gc)
+    XFreeGC(display, bitmap->stored_clip_gc);
+#endif
+
+  free(bitmap);
+}
+
+inline void CloseWindow(DrawWindow *window)
+{
+#ifdef TARGET_X11
+  if (window->drawable)
+  {
+    XUnmapWindow(display, window->drawable);
+    XDestroyWindow(display, window->drawable);
+  }
+  if (window->gc)
+    XFreeGC(display, window->gc);
+#endif
+}
+
+inline void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
+                      int src_x, int src_y,
+                      int width, int height,
+                      int dst_x, int dst_y)
+{
+#ifdef TARGET_SDL
+  SDLCopyArea(src_bitmap, dst_bitmap,
+             src_x, src_y, width, height, dst_x, dst_y, SDLCOPYAREA_OPAQUE);
+#else
+  XCopyArea(display, src_bitmap->drawable, dst_bitmap->drawable,
+           dst_bitmap->gc, src_x, src_y, width, height, dst_x, dst_y);
+#endif
+}
+
+inline void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
+{
+#ifdef TARGET_SDL
+  SDLFillRectangle(bitmap, x, y, width, height, 0x000000);
+#else
+  XFillRectangle(display, bitmap->drawable, bitmap->gc, x, y, width, height);
+#endif
+}
+
+#if 0
+#ifndef TARGET_SDL
+static GC last_clip_gc = 0;    /* needed for XCopyArea() through clip mask */
+#endif
+#endif
+
+inline void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
+{
+#ifdef TARGET_X11
+  if (clip_gc)
+  {
+    bitmap->clip_gc = clip_gc;
+    XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
+  }
+#if 0
+  last_clip_gc = clip_gc;
+#endif
+#endif
+}
+
+inline void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
+{
+#ifdef TARGET_X11
+  if (clip_gc)
+  {
+    bitmap->clip_gc = clip_gc;
+    XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
+  }
+#if 0
+  last_clip_gc = clip_gc;
+#endif
+#endif
+}
+
+inline void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
+                            int src_x, int src_y,
+                            int width, int height,
+                            int dst_x, int dst_y)
+{
+#ifdef TARGET_SDL
+  SDLCopyArea(src_bitmap, dst_bitmap,
+             src_x, src_y, width, height, dst_x, dst_y, SDLCOPYAREA_MASKED);
+#else
+  XCopyArea(display, src_bitmap->drawable, dst_bitmap->drawable,
+           src_bitmap->clip_gc, src_x, src_y, width, height, dst_x, dst_y);
+#endif
+}
+
+inline void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
+                               int to_x, int to_y)
+{
+#ifdef TARGET_SDL
+  SDLDrawSimpleLine(bitmap->surface, from_x, from_y, to_x, to_y, 0xffffff);
+#else
+  XSetForeground(display, bitmap->gc, WhitePixel(display, screen));
+  XDrawLine(display, bitmap->drawable, bitmap->gc, from_x, from_y, to_x, to_y);
+  XSetForeground(display, bitmap->gc, BlackPixel(display, screen));
+#endif
+}
+
+#if !defined(TARGET_X11_NATIVE)
+inline void DrawLine(Bitmap *bitmap, int from_x, int from_y,
+                    int to_x, int to_y, Pixel pixel, int line_width)
+{
+  int x, y;
+
+  for (x=0; x<line_width; x++)
+  {
+    for (y=0; y<line_width; y++)
+    {
+      int dx = x - line_width / 2;
+      int dy = y - line_width / 2;
+
+      if ((x == 0 && y == 0) ||
+         (x == 0 && y == line_width - 1) ||
+         (x == line_width - 1 && y == 0) ||
+         (x == line_width - 1 && y == line_width - 1))
+       continue;
+
+#if defined(TARGET_SDL)
+      sge_Line(bitmap->surface,
+              from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
+#elif defined(TARGET_ALLEGRO)
+      AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
+                     to_x + dx, to_y + dy, pixel);
+#endif
+    }
+  }
+}
+#endif
+
+inline void DrawLines(Bitmap *bitmap, struct XY *points, int num_points,
+                     Pixel pixel)
+{
+#if !defined(TARGET_X11_NATIVE)
+  int line_width = 4;
+  int i;
+
+  for (i=0; i<num_points - 1; i++)
+    DrawLine(bitmap, points[i].x, points[i].y,
+            points[i + 1].x, points[i + 1].y, pixel, line_width);
+
+  /*
+  SDLDrawLines(bitmap->surface, points, num_points, pixel);
+  */
+#else
+  XSetForeground(display, bitmap->line_gc[1], pixel);
+  XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
+            (XPoint *)points, num_points, CoordModeOrigin);
+  /*
+  XSetForeground(display, gc, BlackPixel(display, screen));
+  */
+#endif
+}
+
+inline Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
+                            unsigned int color_g, unsigned int color_b)
+{
+  Pixel pixel;
+
+#if defined(TARGET_SDL)
+  pixel = SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
+#elif defined(TARGET_ALLEGRO)
+  pixel = AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
+#elif defined(TARGET_X11_NATIVE)
+  XColor xcolor;
+
+  xcolor.flags = DoRed | DoGreen | DoBlue;
+  xcolor.red = (color_r << 8);
+  xcolor.green = (color_g << 8);
+  xcolor.blue = (color_b << 8);
+  XAllocColor(display, cmap, &xcolor);
+  pixel = xcolor.pixel;
+#endif
+
+  return pixel;
+}
+
+inline Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
+{
+  unsigned int color_r = (color >> 16) & 0xff;
+  unsigned int color_g = (color >>  8) & 0xff;
+  unsigned int color_b = (color >>  0) & 0xff;
+
+  return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
+}
+
+/* execute all pending screen drawing operations */
+inline void FlushDisplay(void)
+{
+#ifndef TARGET_SDL
+  XFlush(display);
+#endif
+}
+
+/* execute and wait for all pending screen drawing operations */
+inline void SyncDisplay(void)
+{
+#ifndef TARGET_SDL
+  XSync(display, FALSE);
+#endif
+}
+
+inline void KeyboardAutoRepeatOn(void)
+{
+#ifdef TARGET_SDL
+  SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
+                     SDL_DEFAULT_REPEAT_INTERVAL / 2);
+  SDL_EnableUNICODE(1);
+#else
+  if (display)
+    XAutoRepeatOn(display);
+#endif
+}
+
+inline void KeyboardAutoRepeatOff(void)
+{
+#ifdef TARGET_SDL
+  SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
+  SDL_EnableUNICODE(0);
+#else
+  if (display)
+    XAutoRepeatOff(display);
+#endif
+}
+
+inline boolean PointerInWindow(DrawWindow *window)
+{
+#ifdef TARGET_SDL
+  return TRUE;
+#else
+  Window root, child;
+  int root_x, root_y;
+  unsigned int mask;
+  int win_x, win_y;
+
+  /* if XQueryPointer() returns False, the pointer
+     is not on the same screen as the specified window */
+  return XQueryPointer(display, window->drawable, &root, &child,
+                      &root_x, &root_y, &win_x, &win_y, &mask);
+#endif
+}
+
+inline boolean SetVideoMode(boolean fullscreen)
+{
+#ifdef TARGET_SDL
+  return SDLSetVideoMode(&backbuffer, fullscreen);
+#else
+  boolean success = TRUE;
+
+  if (fullscreen && video.fullscreen_available)
+  {
+    Error(ERR_WARN, "fullscreen not available in X11 version");
+
+    /* display error message only once */
+    video.fullscreen_available = FALSE;
+
+    success = FALSE;
+  }
+
+  return success;
+#endif
+}
+
+inline boolean ChangeVideoModeIfNeeded(boolean fullscreen)
+{
+#ifdef TARGET_SDL
+  if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
+      (!fullscreen && video.fullscreen_enabled))
+    fullscreen = SetVideoMode(fullscreen);
+#endif
+
+  return fullscreen;
+}
+
+Bitmap *LoadImage(char *basename)
+{
+  Bitmap *new_bitmap;
+  char *filename = getPath3(options.ro_base_directory, GRAPHICS_DIRECTORY,
+                           basename);
+
+#if defined(TARGET_SDL)
+  new_bitmap = SDLLoadImage(filename);
+#else
+  new_bitmap = X11LoadImage(filename);
+#endif
+
+  free(filename);
+
+  return new_bitmap;
+}
+
+
+/* ========================================================================= */
+/* audio functions                                                           */
+/* ========================================================================= */
+
+inline void OpenAudio(void)
+{
+  /* always start with reliable default values */
+  audio.sound_available = FALSE;
+  audio.music_available = FALSE;
+  audio.loops_available = FALSE;
+  audio.mods_available = FALSE;
+  audio.sound_enabled = FALSE;
+
+  audio.soundserver_pipe[0] = audio.soundserver_pipe[1] = 0;
+  audio.soundserver_pid = 0;
+  audio.device_name = NULL;
+  audio.device_fd = 0;
+
+  audio.channels = 0;
+  audio.music_channel = 0;
+  audio.music_nr = 0;
+
+#if defined(TARGET_SDL)
+  SDLOpenAudio();
+#elif defined(PLATFORM_MSDOS)
+  MSDOSOpenAudio();
+#elif defined(PLATFORM_UNIX)
+  UnixOpenAudio();
+#endif
+}
+
+inline void CloseAudio(void)
+{
+#if defined(TARGET_SDL)
+  SDLCloseAudio();
+#elif defined(PLATFORM_MSDOS)
+  MSDOSCloseAudio();
+#elif defined(PLATFORM_UNIX)
+  UnixCloseAudio();
+#endif
+
+  audio.sound_enabled = FALSE;
+}
+
+inline void SetAudioMode(boolean enabled)
+{
+  if (!audio.sound_available)
+    return;
+
+  audio.sound_enabled = enabled;
+}
+
+
+/* ========================================================================= */
+/* event functions                                                           */
+/* ========================================================================= */
+
+inline void InitEventFilter(EventFilter filter_function)
+{
+#ifdef TARGET_SDL
+  /* set event filter to filter out certain events */
+  SDL_SetEventFilter(filter_function);
+#endif
+}
+
+inline boolean PendingEvent(void)
+{
+#ifdef TARGET_SDL
+  return (SDL_PollEvent(NULL) ? TRUE : FALSE);
+#else
+  return (XPending(display) ? TRUE : FALSE);
+#endif
+}
+
+inline void NextEvent(Event *event)
+{
+#ifdef TARGET_SDL
+  SDL_WaitEvent(event);
+#else
+  XNextEvent(display, event);
+#endif
+}
+
+inline Key GetEventKey(KeyEvent *event, boolean with_modifiers)
+{
+#ifdef TARGET_SDL
+#if 0
+  printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
+        (int)event->keysym.unicode,
+        (int)event->keysym.sym,
+        (int)SDL_GetModState());
+#endif
+
+  if (with_modifiers && event->keysym.unicode != 0)
+    return event->keysym.unicode;
+  else
+    return event->keysym.sym;
+#else
+#if 0
+  printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
+        (int)XLookupKeysym(event, event->state),
+        (int)XLookupKeysym(event, 0));
+#endif
+
+  if (with_modifiers)
+    return XLookupKeysym(event, event->state);
+  else
+    return XLookupKeysym(event, 0);
+#endif
+}
+
+inline boolean CheckCloseWindowEvent(ClientMessageEvent *event)
+{
+  if (event->type != EVENT_CLIENTMESSAGE)
+    return FALSE;
+
+#if defined(TARGET_SDL)
+  return TRUE;         /* the only possible message here is SDL_QUIT */
+#elif defined(PLATFORM_UNIX)
+  if ((event->window == window->drawable) &&
+      (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
+    return TRUE;
+#endif
+
+  return FALSE;
+}
+
+
+inline void dummy(void)
+{
+#ifdef TARGET_SDL
+#else
+#endif
+}
diff --git a/src/libgame/system.h b/src/libgame/system.h
new file mode 100644 (file)
index 0000000..5556760
--- /dev/null
@@ -0,0 +1,317 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* system.h                                                 *
+***********************************************************/
+
+#ifndef SYSTEM_H
+#define SYSTEM_H
+
+#include "platform.h"
+#include "types.h"
+
+#if defined(PLATFORM_MSDOS)
+#include "msdos.h"
+#endif
+
+#if defined(TARGET_SDL)
+#include "sdl.h"
+#elif defined(TARGET_X11)
+#include "x11.h"
+#endif
+
+
+/* contant definitions */
+
+/* the additional 'b' is needed for Win32 to open files in binary mode */
+#define MODE_READ              "rb"
+#define MODE_WRITE             "wb"
+#define MODE_APPEND            "ab"
+
+#define DEFAULT_DEPTH          0
+
+#define FULLSCREEN_NOT_AVAILABLE FALSE
+#define FULLSCREEN_AVAILABLE    TRUE
+
+/* values for button_status */
+#define MB_NOT_PRESSED         FALSE
+#define MB_NOT_RELEASED                TRUE
+#define MB_RELEASED            FALSE
+#define MB_PRESSED             TRUE
+#define MB_MENU_CHOICE         FALSE
+#define MB_MENU_MARK           TRUE
+#define MB_MENU_INITIALIZE     (-1)
+#define MB_LEFTBUTTON          1
+#define MB_MIDDLEBUTTON                2
+#define MB_RIGHTBUTTON         3
+
+/* values for redraw_mask */
+#define REDRAW_NONE            (0)
+#define REDRAW_ALL             (1 << 0)
+#define REDRAW_FIELD           (1 << 1)
+#define REDRAW_TILES           (1 << 2)
+#define REDRAW_DOOR_1          (1 << 3)
+#define REDRAW_VIDEO_1         (1 << 4)
+#define REDRAW_VIDEO_2         (1 << 5)
+#define REDRAW_VIDEO_3         (1 << 6)
+#define REDRAW_MICROLEVEL      (1 << 7)
+#define REDRAW_MICROLABEL      (1 << 8)
+#define REDRAW_FROM_BACKBUFFER (1 << 9)
+#define REDRAW_DOOR_2          (REDRAW_VIDEO_1 | \
+                                REDRAW_VIDEO_2 | \
+                                REDRAW_VIDEO_3)
+#define REDRAW_DOOR_3          (1 << 10)
+#define REDRAW_DOORS           (REDRAW_DOOR_1 | \
+                                REDRAW_DOOR_2 | \
+                                REDRAW_DOOR_3)
+#define REDRAW_MAIN            (REDRAW_FIELD | \
+                                REDRAW_TILES | \
+                                REDRAW_MICROLEVEL)
+#define REDRAW_FPS             (1 << 11)
+#define REDRAWTILES_THRESHOLD  (SCR_FIELDX * SCR_FIELDY / 2)
+
+
+/* default name for empty highscore entry */
+#define EMPTY_PLAYER_NAME      "no name"
+
+/* default name for unknown player names */
+#define ANONYMOUS_NAME         "anonymous"
+
+/* default name for new levels */
+#define NAMELESS_LEVEL_NAME    "nameless level"
+
+/* definitions for game sub-directories */
+#ifndef RO_GAME_DIR
+#define RO_GAME_DIR            "."
+#endif
+
+#ifndef RW_GAME_DIR
+#define RW_GAME_DIR            "."
+#endif
+
+#define RO_BASE_PATH           RO_GAME_DIR
+#define RW_BASE_PATH           RW_GAME_DIR
+
+#define GRAPHICS_DIRECTORY     "graphics"
+#define MUSIC_DIRECTORY                "music"
+#define SOUNDS_DIRECTORY       "sounds"
+#define LEVELS_DIRECTORY       "levels"
+#define TAPES_DIRECTORY                "tapes"
+#define SCORES_DIRECTORY       "scores"
+
+/* areas in bitmap PIX_DOOR */
+/* meaning in PIX_DB_DOOR: (3 PAGEs)
+   PAGEX1: 1. buffer for DOOR_1
+   PAGEX2: 2. buffer for DOOR_1
+   PAGEX3: buffer for animations
+*/
+
+#define DOOR_GFX_PAGESIZE      (gfx.dxsize)
+#define DOOR_GFX_PAGEX1                (0 * DOOR_GFX_PAGESIZE)
+#define DOOR_GFX_PAGEX2                (1 * DOOR_GFX_PAGESIZE)
+#define DOOR_GFX_PAGEX3                (2 * DOOR_GFX_PAGESIZE)
+#define DOOR_GFX_PAGEX4                (3 * DOOR_GFX_PAGESIZE)
+#define DOOR_GFX_PAGEX5                (4 * DOOR_GFX_PAGESIZE)
+#define DOOR_GFX_PAGEX6                (5 * DOOR_GFX_PAGESIZE)
+#define DOOR_GFX_PAGEX7                (6 * DOOR_GFX_PAGESIZE)
+#define DOOR_GFX_PAGEX8                (7 * DOOR_GFX_PAGESIZE)
+#define DOOR_GFX_PAGEY1                (0)
+#define DOOR_GFX_PAGEY2                (gfx.dysize)
+
+
+/* type definitions */
+
+typedef int (*EventFilter)(const Event *);
+
+
+/* structure definitions */
+
+struct ProgramInfo
+{
+  char *command_basename;
+  char *userdata_directory;
+
+  char *program_title;
+  char *window_title;
+  char *icon_title;
+  char *x11_icon_filename;
+  char *x11_iconmask_filename;
+  char *msdos_pointer_filename;
+
+  void (*exit_function)(int);
+};
+
+struct OptionInfo
+{
+  char *display_name;
+  char *server_host;
+  int server_port;
+  char *ro_base_directory;
+  char *rw_base_directory;
+  char *level_directory;
+  boolean serveronly;
+  boolean network;
+  boolean verbose;
+  boolean debug;
+};
+
+struct VideoSystemInfo
+{
+  int default_depth;
+  int width, height, depth;
+  boolean fullscreen_available;
+  boolean fullscreen_enabled;
+};
+
+struct AudioSystemInfo
+{
+  boolean sound_available;
+  boolean music_available;
+  boolean loops_available;
+  boolean mods_available;
+  boolean sound_enabled;
+
+  int soundserver_pipe[2];
+  int soundserver_pid;
+  char *device_name;
+  int device_fd;
+
+  int channels;
+  int music_channel;
+  int music_nr;
+};
+
+struct GfxInfo
+{
+  int sx, sy;
+  int sxsize, sysize;
+  int real_sx, real_sy;
+  int full_sxsize, full_sysize;
+  int scrollbuffer_width, scrollbuffer_height;
+
+  int dx, dy;
+  int dxsize, dysize;
+
+  int vx, vy;
+  int vxsize, vysize;
+};
+
+struct LevelDirInfo
+{
+  char *filename;      /* level series single directory name */
+  char *fullpath;      /* complete path relative to level directory */
+  char *basepath;      /* absolute base path of level directory */
+  char *name;          /* level series name, as displayed on main screen */
+  char *name_short;    /* optional short name for level selection screen */
+  char *name_sorting;  /* optional sorting name for correct level sorting */
+  char *author;                /* level series author name levels without author */
+  char *imported_from; /* optional comment for imported level series */
+  int levels;          /* number of levels in level series */
+  int first_level;     /* first level number (to allow start with 0 or 1) */
+  int last_level;      /* last level number (automatically calculated) */
+  int sort_priority;   /* sort levels by 'sort_priority' and then by name */
+  boolean level_group; /* directory contains more level series directories */
+  boolean parent_link; /* entry links back to parent directory */
+  boolean user_defined;        /* user defined levels are stored in home directory */
+  boolean readonly;    /* readonly levels can not be changed with editor */
+  int color;           /* color to use on selection screen for this level */
+  char *class_desc;    /* description of level series class */
+  int handicap_level;  /* number of the lowest unsolved level */
+  int cl_first;                /* internal control field for "choose level" screen */
+  int cl_cursor;       /* internal control field for "choose level" screen */
+
+  struct LevelDirInfo *node_parent;    /* parent level directory info */
+  struct LevelDirInfo *node_group;     /* level group sub-directory info */
+  struct LevelDirInfo *next;           /* next level series structure node */
+};
+
+
+/* ========================================================================= */
+/* exported variables                                                        */
+/* ========================================================================= */
+
+extern struct ProgramInfo      program;
+extern struct OptionInfo       options;
+extern struct VideoSystemInfo  video;
+extern struct AudioSystemInfo  audio;
+extern struct GfxInfo          gfx;
+
+extern struct LevelDirInfo     *leveldir_first;
+extern struct LevelDirInfo     *leveldir_current;
+
+extern Display        *display;
+extern Visual         *visual;
+extern int             screen;
+extern Colormap                cmap;
+
+extern DrawWindow      *window;
+extern DrawBuffer      *backbuffer;
+extern DrawBuffer      *drawto;
+
+extern int             button_status;
+extern boolean         motion_status;
+
+extern int             redraw_mask;
+extern int             redraw_tiles;
+
+extern int             FrameCounter;
+
+
+/* function definitions */
+
+void InitCommandName(char *);
+void InitExitFunction(void (*exit_function)(int));
+void InitPlatformDependantStuff(void);
+void ClosePlatformDependantStuff(void);
+
+void InitProgramInfo(char *, char *, char *, char *, char *, char *, char *);
+
+void InitGfxFieldInfo(int, int, int, int, int, int, int, int);
+void InitGfxDoor1Info(int, int, int, int);
+void InitGfxDoor2Info(int, int, int, int);
+void InitGfxScrollbufferInfo(int, int);
+
+inline void InitVideoDisplay(void);
+inline void CloseVideoDisplay(void);
+inline void InitVideoBuffer(DrawBuffer **,DrawWindow **, int,int,int, boolean);
+inline Bitmap *CreateBitmapStruct(void);
+inline Bitmap *CreateBitmap(int, int, int);
+inline void FreeBitmap(Bitmap *);
+inline void BlitBitmap(Bitmap *, Bitmap *, int, int, int, int, int, int);
+inline void ClearRectangle(Bitmap *, int, int, int, int);
+inline void SetClipMask(Bitmap *, GC, Pixmap);
+inline void SetClipOrigin(Bitmap *, GC, int, int);
+inline void BlitBitmapMasked(Bitmap *, Bitmap *, int, int, int, int, int, int);
+inline void DrawSimpleWhiteLine(Bitmap *, int, int, int, int);
+inline void DrawLines(Bitmap *, struct XY *, int, Pixel);
+inline Pixel GetPixelFromRGB(Bitmap *, unsigned int,unsigned int,unsigned int);
+inline Pixel GetPixelFromRGBcompact(Bitmap *, unsigned int);
+
+inline void FlushDisplay(void);
+inline void SyncDisplay(void);
+inline void KeyboardAutoRepeatOn(void);
+inline void KeyboardAutoRepeatOff(void);
+inline boolean PointerInWindow(DrawWindow *);
+inline boolean SetVideoMode(boolean);
+inline boolean ChangeVideoModeIfNeeded(boolean);
+
+Bitmap *LoadImage(char *);
+
+inline void OpenAudio(void);
+inline void CloseAudio(void);
+inline void SetAudioMode(boolean);
+
+inline void InitEventFilter(EventFilter);
+inline boolean PendingEvent(void);
+inline void NextEvent(Event *event);
+inline Key GetEventKey(KeyEvent *, boolean);
+inline boolean CheckCloseWindowEvent(ClientMessageEvent *);
+
+#endif /* SYSTEM_H */
diff --git a/src/libgame/text.c b/src/libgame/text.c
new file mode 100644 (file)
index 0000000..ff95b3c
--- /dev/null
@@ -0,0 +1,182 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* text.c                                                   *
+***********************************************************/
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "text.h"
+
+
+/* ========================================================================= */
+/* exported variables                                                        */
+/* ========================================================================= */
+
+struct FontInfo                font;
+
+
+/* ========================================================================= */
+/* font functions                                                            */
+/* ========================================================================= */
+
+void InitFontInfo(Bitmap *bitmap_big, Bitmap *bitmap_medium,
+                 Bitmap *bitmap_small)
+{
+  font.bitmap_big = bitmap_big;
+  font.bitmap_medium = bitmap_medium;
+  font.bitmap_small = bitmap_small;
+}
+
+int getFontWidth(int font_size, int font_type)
+{
+  return (font_size == FS_BIG ? FONT1_XSIZE :
+         font_size == FS_MEDIUM ? FONT6_XSIZE :
+         font_type == FC_SPECIAL1 ? FONT3_XSIZE :
+         font_type == FC_SPECIAL2 ? FONT4_XSIZE :
+         font_type == FC_SPECIAL3 ? FONT5_XSIZE :
+         FONT2_XSIZE);
+}
+
+int getFontHeight(int font_size, int font_type)
+{
+  return (font_size == FS_BIG ? FONT1_YSIZE :
+         font_size == FS_MEDIUM ? FONT6_YSIZE :
+         font_type == FC_SPECIAL1 ? FONT3_YSIZE :
+         font_type == FC_SPECIAL2 ? FONT4_YSIZE :
+         font_type == FC_SPECIAL3 ? FONT5_YSIZE :
+         FONT2_YSIZE);
+}
+
+void DrawInitText(char *text, int ypos, int color)
+{
+  if (window && font.bitmap_small)
+  {
+    ClearRectangle(window, 0, ypos, video.width, FONT2_YSIZE);
+    DrawTextExt(window, (video.width - strlen(text) * FONT2_XSIZE)/2,
+               ypos, text, FS_SMALL, color);
+    FlushDisplay();
+  }
+}
+
+void DrawTextFCentered(int y, int font_type, char *format, ...)
+{
+  char buffer[MAX_OUTPUT_LINESIZE + 1];
+  int font_width = getFontWidth(FS_SMALL, font_type);
+  va_list ap;
+
+  va_start(ap, format);
+  vsprintf(buffer, format, ap);
+  va_end(ap);
+
+  DrawText(gfx.sx + (gfx.sxsize - strlen(buffer) * font_width) / 2,
+          gfx.sy + y, buffer, FS_SMALL, font_type);
+}
+
+void DrawTextF(int x, int y, int font_type, char *format, ...)
+{
+  char buffer[MAX_OUTPUT_LINESIZE + 1];
+  va_list ap;
+
+  va_start(ap, format);
+  vsprintf(buffer, format, ap);
+  va_end(ap);
+
+  DrawText(gfx.sx + x, gfx.sy + y, buffer, FS_SMALL, font_type);
+}
+
+void DrawText(int x, int y, char *text, int font_size, int font_type)
+{
+  DrawTextExt(drawto, x, y, text, font_size, font_type);
+
+  if (x < gfx.dx)
+    redraw_mask |= REDRAW_FIELD;
+  else if (y < gfx.vy || gfx.vy == 0)
+    redraw_mask |= REDRAW_DOOR_1;
+}
+
+void DrawTextExt(DrawBuffer *bitmap, int x, int y,
+                char *text, int font_size, int font_type)
+{
+  Bitmap *font_bitmap;
+  int font_width, font_height, font_start;
+  boolean print_inverse = FALSE;
+
+  if (font_size != FS_SMALL && font_size != FS_BIG && font_size != FS_MEDIUM)
+    font_size = FS_SMALL;
+  if (font_type < FC_RED || font_type > FC_SPECIAL3)
+    font_type = FC_RED;
+
+  font_width = getFontWidth(font_size, font_type);
+  font_height = getFontHeight(font_size, font_type);
+
+  font_bitmap = (font_size == FS_BIG ? font.bitmap_big :
+                font_size == FS_MEDIUM ? font.bitmap_medium :
+                font.bitmap_small);
+  font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE :
+                            font_size == FS_MEDIUM ? FONT6_YSIZE :
+                            FONT2_YSIZE) *
+               FONT_LINES_PER_FONT);
+
+  if (font_type == FC_SPECIAL3)
+    font_start += (FONT4_YSIZE - FONT2_YSIZE) * FONT_LINES_PER_FONT;
+
+  while (*text)
+  {
+    char c = *text++;
+
+    if (c == '~' && font_size == FS_SMALL)
+    {
+      print_inverse = TRUE;
+      continue;
+    }
+
+    if (c >= 'a' && c <= 'z')
+      c = 'A' + (c - 'a');
+    else if (c == 'ä' || c == 'Ä')
+      c = 91;
+    else if (c == 'ö' || c == 'Ö')
+      c = 92;
+    else if (c == 'ü' || c == 'Ãœ')
+      c = 93;
+
+    if ((c >= 32 && c <= 95) || c == '°')
+    {
+      int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
+      int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
+      int dest_x = x, dest_y = y;
+
+      if (c == '°')
+      {
+       src_x = (FONT_CHARS_PER_LINE + 1) * font_width;
+       src_y = 3 * font_height + font_start;
+      }
+
+      if (print_inverse)
+      {
+       BlitBitmap(font_bitmap, bitmap,
+                  FONT_CHARS_PER_LINE * font_width,
+                  3 * font_height + font_start,
+                  font_width, font_height, x, y);
+
+       SetClipOrigin(font_bitmap, font_bitmap->stored_clip_gc,
+                     dest_x - src_x, dest_y - src_y);
+       BlitBitmapMasked(font_bitmap, bitmap,
+                        0, 0, font_width, font_height, dest_x, dest_y);
+      }
+      else
+       BlitBitmap(font_bitmap, bitmap,
+                  src_x, src_y, font_width, font_height, dest_x, dest_y);
+    }
+
+    x += font_width;
+  }
+}
diff --git a/src/libgame/text.h b/src/libgame/text.h
new file mode 100644 (file)
index 0000000..c6d3c9f
--- /dev/null
@@ -0,0 +1,73 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* text.h                                                   *
+***********************************************************/
+
+#ifndef TEXT_H
+#define TEXT_H
+
+#include "system.h"
+
+
+/* font types */
+#define FS_SMALL               0
+#define FS_BIG                 1
+#define FS_MEDIUM              2
+
+/* font colors */
+#define FC_RED                 0
+#define FC_BLUE                        1
+#define FC_GREEN               2
+#define FC_YELLOW              3
+#define FC_SPECIAL1            4
+#define FC_SPECIAL2            5
+#define FC_SPECIAL3            6
+
+/* font graphics definitions */
+#define FONT1_XSIZE            32
+#define FONT1_YSIZE            32
+#define FONT2_XSIZE            14
+#define FONT2_YSIZE            14
+#define FONT3_XSIZE            11
+#define FONT3_YSIZE            14
+#define FONT4_XSIZE            16
+#define FONT4_YSIZE            16
+#define FONT5_XSIZE            10
+#define FONT5_YSIZE            14
+#define FONT6_XSIZE            16
+#define FONT6_YSIZE            32
+
+#define FONT_CHARS_PER_LINE    16
+#define FONT_LINES_PER_FONT    4
+
+/* text output definitions */
+#define MAX_OUTPUT_LINESIZE    256
+
+/* font structure definitions */
+
+struct FontInfo
+{
+  Bitmap *bitmap_big;
+  Bitmap *bitmap_medium;
+  Bitmap *bitmap_small;
+};
+
+
+void InitFontInfo(Bitmap *, Bitmap *, Bitmap *);
+int getFontWidth(int, int);
+int getFontHeight(int, int);
+void DrawInitText(char *, int, int);
+void DrawTextF(int, int, int, char *, ...);
+void DrawTextFCentered(int, int, char *, ...);
+void DrawText(int, int, char *, int, int);
+void DrawTextExt(DrawBuffer *, int, int, char *, int, int);
+
+#endif /* TEXT_H */
diff --git a/src/libgame/types.h b/src/libgame/types.h
new file mode 100644 (file)
index 0000000..5722e05
--- /dev/null
@@ -0,0 +1,41 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* types.h                                                  *
+***********************************************************/
+
+#ifndef TYPES_H
+#define TYPES_H
+
+typedef unsigned char boolean;
+typedef unsigned char byte;
+
+#ifndef FALSE
+#define FALSE          0
+#define TRUE           (!FALSE)
+#endif
+
+#ifndef MIN
+#define MIN(a,b)       ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a,b)       ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef ABS
+#define ABS(a)         ((a) < 0 ? -(a) : (a))
+#endif
+
+#ifndef SIGN
+#define SIGN(a)                ((a) < 0 ? -1 : ((a)>0 ? 1 : 0))
+#endif
+
+#endif /* TYPES_H */
diff --git a/src/libgame/x11.c b/src/libgame/x11.c
new file mode 100644 (file)
index 0000000..d8356fb
--- /dev/null
@@ -0,0 +1,283 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* x11.c                                                    *
+***********************************************************/
+
+#include "system.h"
+#include "pcx.h"
+#include "misc.h"
+
+
+#if defined(TARGET_X11)
+
+static void X11InitDisplay();
+static DrawWindow *X11InitWindow();
+
+inline void X11InitVideoDisplay(void)
+{
+  /* initialize X11 video */
+  X11InitDisplay();
+
+  /* set default X11 depth */
+  video.default_depth = XDefaultDepth(display, screen);
+}
+
+inline void X11InitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window)
+{
+  *window = X11InitWindow();
+
+  XMapWindow(display, (*window)->drawable);
+  FlushDisplay();
+
+  /* create additional (off-screen) buffer for double-buffering */
+  *backbuffer = CreateBitmap(video.width, video.height, video.depth);
+}
+
+static void X11InitDisplay()
+{
+#if !defined(PLATFORM_MSDOS)
+  XVisualInfo vinfo_template, *vinfo;
+  int num_visuals;
+#endif
+  unsigned int depth;
+
+  /* connect to X server */
+  if (!(display = XOpenDisplay(options.display_name)))
+    Error(ERR_EXIT, "cannot connect to X server %s",
+         XDisplayName(options.display_name));
+
+  screen = DefaultScreen(display);
+  visual = DefaultVisual(display, screen);
+  depth  = DefaultDepth(display, screen);
+  cmap   = DefaultColormap(display, screen);
+
+#if !defined(PLATFORM_MSDOS)
+  /* look for good enough visual */
+  vinfo_template.screen = screen;
+  vinfo_template.class = (depth == 8 ? PseudoColor : TrueColor);
+  vinfo_template.depth = depth;
+  if ((vinfo = XGetVisualInfo(display, VisualScreenMask | VisualClassMask |
+                             VisualDepthMask, &vinfo_template, &num_visuals)))
+  {
+    visual = vinfo->visual;
+    XFree((void *)vinfo);
+  }
+
+  /* got appropriate visual? */
+  if (depth < 8)
+  {
+    printf("Sorry, displays with less than 8 bits per pixel not supported.\n");
+    exit(-1);
+  }
+  else if ((depth ==8 && visual->class != PseudoColor) ||
+          (depth > 8 && visual->class != TrueColor &&
+           visual->class != DirectColor))
+  {
+    printf("Sorry, cannot get appropriate visual.\n");
+    exit(-1);
+  }
+#endif /* !PLATFORM_MSDOS */
+}
+
+static DrawWindow *X11InitWindow()
+{
+  DrawWindow *new_window = CreateBitmapStruct();
+  unsigned int border_width = 4;
+  XGCValues gc_values;
+  unsigned long gc_valuemask;
+#if !defined(PLATFORM_MSDOS)
+  XTextProperty windowName, iconName;
+  Pixmap icon_pixmap, iconmask_pixmap;
+  unsigned int icon_width, icon_height;
+  int icon_hot_x, icon_hot_y;
+#if 0
+  char icon_filename[256];
+#endif
+  XSizeHints size_hints;
+  XWMHints wm_hints;
+  XClassHint class_hints;
+  char *window_name = program.window_title;
+  char *icon_name = program.window_title;
+  long window_event_mask;
+  Atom proto_atom = None, delete_atom = None;
+#endif
+  int screen_width, screen_height;
+  int win_xpos, win_ypos;
+  unsigned long pen_fg = WhitePixel(display,screen);
+  unsigned long pen_bg = BlackPixel(display,screen);
+  const int width = video.width, height = video.height;
+  int i;
+
+#if 0
+#if !defined(PLATFORM_MSDOS)
+  static struct IconFileInfo icon_pic =
+  {
+    "rocks_icon.xbm",
+    "rocks_iconmask.xbm"
+  };
+#endif
+#endif
+
+  screen_width = XDisplayWidth(display, screen);
+  screen_height = XDisplayHeight(display, screen);
+
+  win_xpos = (screen_width - width) / 2;
+  win_ypos = (screen_height - height) / 2;
+
+  new_window->drawable = XCreateSimpleWindow(display,
+                                            RootWindow(display, screen),
+                                            win_xpos, win_ypos,
+                                            width, height, border_width,
+                                            pen_fg, pen_bg);
+
+#if !defined(PLATFORM_MSDOS)
+  proto_atom = XInternAtom(display, "WM_PROTOCOLS", FALSE);
+  delete_atom = XInternAtom(display, "WM_DELETE_WINDOW", FALSE);
+  if ((proto_atom != None) && (delete_atom != None))
+    XChangeProperty(display, new_window->drawable, proto_atom, XA_ATOM, 32,
+                   PropModePrepend, (unsigned char *) &delete_atom, 1);
+
+#if 0
+  sprintf(icon_filename, "%s/%s/%s",
+         options.ro_base_directory, GRAPHICS_DIRECTORY,
+         icon_pic.picture_filename);
+#endif
+  if (XReadBitmapFile(display, new_window->drawable,
+                     program.x11_icon_filename,
+                     &icon_width, &icon_height, &icon_pixmap,
+                     &icon_hot_x, &icon_hot_y) != BitmapSuccess)
+    Error(ERR_EXIT, "cannot read icon bitmap file '%s'",
+         program.x11_icon_filename);
+
+#if 0
+  sprintf(icon_filename, "%s/%s/%s",
+         options.ro_base_directory, GRAPHICS_DIRECTORY,
+         icon_pic.picturemask_filename);
+#endif
+  if (XReadBitmapFile(display, new_window->drawable,
+                     program.x11_iconmask_filename,
+                     &icon_width, &icon_height, &iconmask_pixmap,
+                     &icon_hot_x, &icon_hot_y) != BitmapSuccess)
+    Error(ERR_EXIT, "cannot read icon bitmap file '%s'",
+         program.x11_iconmask_filename);
+
+  size_hints.width  = size_hints.min_width  = size_hints.max_width  = width;
+  size_hints.height = size_hints.min_height = size_hints.max_height = height;
+  size_hints.flags = PSize | PMinSize | PMaxSize;
+
+  if (win_xpos || win_ypos)
+  {
+    size_hints.x = win_xpos;
+    size_hints.y = win_ypos;
+    size_hints.flags |= PPosition;
+  }
+
+  if (!XStringListToTextProperty(&window_name, 1, &windowName))
+    Error(ERR_EXIT, "structure allocation for windowName failed");
+
+  if (!XStringListToTextProperty(&icon_name, 1, &iconName))
+    Error(ERR_EXIT, "structure allocation for iconName failed");
+
+  wm_hints.initial_state = NormalState;
+  wm_hints.input = True;
+  wm_hints.icon_pixmap = icon_pixmap;
+  wm_hints.icon_mask = iconmask_pixmap;
+  wm_hints.flags = StateHint | IconPixmapHint | IconMaskHint | InputHint;
+
+  class_hints.res_name = program.command_basename;
+  class_hints.res_class = program.program_title;
+
+  XSetWMProperties(display, new_window->drawable, &windowName, &iconName, 
+                  NULL, 0, &size_hints, &wm_hints, 
+                  &class_hints);
+
+  XFree(windowName.value);
+  XFree(iconName.value);
+
+  /* Select event types wanted */
+  window_event_mask =
+    ExposureMask | StructureNotifyMask | FocusChangeMask |
+    ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
+    PointerMotionHintMask | KeyPressMask | KeyReleaseMask;
+
+  XSelectInput(display, new_window->drawable, window_event_mask);
+#endif
+
+  /* create GC for drawing with window depth and background color (black) */
+  gc_values.graphics_exposures = False;
+  gc_values.foreground = pen_bg;
+  gc_values.background = pen_bg;
+  gc_valuemask = GCGraphicsExposures | GCForeground | GCBackground;
+  new_window->gc =
+    XCreateGC(display, new_window->drawable, gc_valuemask, &gc_values);
+
+  /* create GCs for line drawing (black and white) */
+  for(i=0; i<2; i++)
+  {
+    gc_values.graphics_exposures = False;
+    gc_values.foreground = (i ? pen_fg : pen_bg);
+    gc_values.background = pen_bg;
+    gc_values.line_width = 4;
+    gc_values.line_style = LineSolid;
+    gc_values.cap_style = CapRound;
+    gc_values.join_style = JoinRound;
+
+    gc_valuemask = GCGraphicsExposures | GCForeground | GCBackground |
+                   GCLineWidth | GCLineStyle | GCCapStyle | GCJoinStyle;
+    new_window->line_gc[i] =
+      XCreateGC(display, new_window->drawable, gc_valuemask, &gc_values);
+  }
+
+  return new_window;
+}
+
+Bitmap *X11LoadImage(char *filename)
+{
+  Bitmap *new_bitmap = CreateBitmapStruct();
+  int pcx_err;
+
+#if defined(PLATFORM_MSDOS)
+  rest(100);
+#endif
+
+  pcx_err = Read_PCX_to_Pixmap(display, window->drawable, window->gc, filename,
+                              &new_bitmap->drawable, &new_bitmap->clip_mask);
+  switch(pcx_err)
+  {
+    case PCX_Success:
+      break;
+    case PCX_OpenFailed:
+      Error(ERR_EXIT, "cannot open PCX file '%s'", filename);
+    case PCX_ReadFailed:
+      Error(ERR_EXIT, "cannot read PCX file '%s'", filename);
+    case PCX_FileInvalid:
+      Error(ERR_EXIT, "invalid PCX file '%s'", filename);
+    case PCX_NoMemory:
+      Error(ERR_EXIT, "not enough memory for PCX file '%s'", filename);
+    case PCX_ColorFailed:
+      Error(ERR_EXIT, "cannot get colors for PCX file '%s'", filename);
+    default:
+      break;
+  }
+
+  if (!new_bitmap->drawable)
+    Error(ERR_EXIT, "cannot get graphics for '%s'", filename);
+
+  if (!new_bitmap->clip_mask)
+    Error(ERR_EXIT, "cannot get clipmask for '%s'", filename);
+
+  /* set GraphicContext inheritated from Window */
+  new_bitmap->gc = window->gc;
+
+  return new_bitmap;
+}
+
+#endif /* TARGET_X11 */
diff --git a/src/libgame/x11.h b/src/libgame/x11.h
new file mode 100644 (file)
index 0000000..4f36b19
--- /dev/null
@@ -0,0 +1,293 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* x11.h                                                    *
+***********************************************************/
+
+#ifndef X11_H
+#define X11_H
+
+#if !defined(PLATFORM_MSDOS)
+#define XK_MISCELLANY
+#define XK_LATIN1
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/Xos.h>
+#include <X11/Intrinsic.h>
+#include <X11/keysymdef.h>
+#endif
+
+
+/* system dependent definitions */
+
+/* MS-DOS header file also defines "TARGET_STRING" */
+#ifndef TARGET_STRING
+#define TARGET_STRING          "X11"
+#endif
+
+#define FULLSCREEN_STATUS      FULLSCREEN_NOT_AVAILABLE
+
+
+/* X11 type definitions */
+
+typedef struct X11DrawableInfo Bitmap;
+typedef struct X11DrawableInfo DrawWindow;
+typedef struct X11DrawableInfo DrawBuffer;
+/* "Pixel" is already defined in X11/Intrinsic.h */
+
+typedef KeySym                 Key;
+
+typedef XEvent                 Event;
+typedef XButtonEvent           ButtonEvent;
+typedef XMotionEvent           MotionEvent;
+typedef XKeyEvent              KeyEvent;
+typedef XExposeEvent           ExposeEvent;
+typedef XFocusChangeEvent      FocusChangeEvent;
+typedef XClientMessageEvent    ClientMessageEvent;
+
+
+/* structure definitions */
+
+struct X11DrawableInfo
+{
+  Drawable drawable;
+  Drawable clip_mask;
+  GC gc;               /* GC for normal drawing (inheritated from 'window') */
+  GC line_gc[2];       /* GC for foreground and background line drawing     */
+  GC stored_clip_gc;   /* GC for masked drawing (used for whole Pixmap)     */
+  GC clip_gc;          /* can be 'stored_clip_gc' or one-tile-only clip GC  */
+};
+
+struct XY
+{
+  short x, y;
+};
+
+
+/* X11 symbol definitions */
+
+#define EVENT_BUTTONPRESS      ButtonPress
+#define EVENT_BUTTONRELEASE    ButtonRelease
+#define EVENT_MOTIONNOTIFY     MotionNotify
+#define EVENT_KEYPRESS         KeyPress
+#define EVENT_KEYRELEASE       KeyRelease
+#define EVENT_EXPOSE           Expose
+#define EVENT_FOCUSIN          FocusIn
+#define EVENT_FOCUSOUT         FocusOut
+#define EVENT_CLIENTMESSAGE    ClientMessage
+#define EVENT_MAPNOTIFY                MapNotify
+#define EVENT_UNMAPNOTIFY      UnmapNotify
+
+#define KSYM_UNDEFINED         XK_VoidSymbol
+
+#define KSYM_Return            XK_Return
+#define KSYM_Escape            XK_Escape
+
+#define KSYM_Left              XK_Left
+#define KSYM_Right             XK_Right
+#define KSYM_Up                        XK_Up
+#define KSYM_Down              XK_Down
+
+#ifdef XK_KP_Left
+#define KSYM_KP_Left           XK_KP_Left
+#define KSYM_KP_Right          XK_KP_Right
+#define KSYM_KP_Up             XK_KP_Up
+#define KSYM_KP_Down           XK_KP_Down
+#endif
+
+#ifdef XK_KP_Enter
+#define KSYM_KP_Enter          XK_KP_Enter
+#define KSYM_KP_Add            XK_KP_Add
+#define KSYM_KP_Subtract       XK_KP_Subtract
+#define KSYM_KP_Multiply       XK_KP_Multiply
+#define KSYM_KP_Divide         XK_KP_Divide
+#define KSYM_KP_Separator      XK_KP_Separator
+#endif
+
+#define KSYM_Shift_L           XK_Shift_L
+#define KSYM_Shift_R           XK_Shift_R
+#define KSYM_Control_L         XK_Control_L
+#define KSYM_Control_R         XK_Control_R
+#define KSYM_Meta_L            XK_Meta_L
+#define KSYM_Meta_R            XK_Meta_R
+#define KSYM_Alt_L             XK_Alt_L
+#define KSYM_Alt_R             XK_Alt_R
+#define KSYM_Super_L           XK_Super_L
+#define KSYM_Super_R           XK_Super_R
+#define KSYM_Mode_switch       XK_Mode_switch
+#define KSYM_Multi_key         XK_Multi_key
+
+#define KSYM_BackSpace         XK_BackSpace
+#define KSYM_Delete            XK_Delete
+#define KSYM_Insert            XK_Insert
+#define KSYM_Tab               XK_Tab
+#define KSYM_Home              XK_Home
+#define KSYM_End               XK_End
+#define KSYM_Page_Up           XK_Page_Up
+#define KSYM_Page_Down         XK_Page_Down
+#define KSYM_Menu              XK_Menu
+
+#define KSYM_space             XK_space
+#define KSYM_exclam            XK_exclam
+#define KSYM_quotedbl          XK_quotedbl
+#define KSYM_numbersign                XK_numbersign
+#define KSYM_dollar            XK_dollar
+#define KSYM_percent           XK_percent
+#define KSYM_ampersand         XK_ampersand
+#define KSYM_apostrophe                XK_apostrophe
+#define KSYM_parenleft         XK_parenleft
+#define KSYM_parenright                XK_parenright
+#define KSYM_asterisk          XK_asterisk
+#define KSYM_plus              XK_plus
+#define KSYM_comma             XK_comma
+#define KSYM_minus             XK_minus
+#define KSYM_period            XK_period
+#define KSYM_slash             XK_slash
+
+#define KSYM_colon             XK_colon
+#define KSYM_semicolon         XK_semicolon
+#define KSYM_less              XK_less
+#define KSYM_equal             XK_equal
+#define KSYM_greater           XK_greater
+#define KSYM_question          XK_question
+#define KSYM_at                        XK_at
+
+#define KSYM_bracketleft       XK_bracketleft
+#define KSYM_backslash         XK_backslash
+#define KSYM_bracketright      XK_bracketright
+#define KSYM_asciicircum       XK_asciicircum
+#define KSYM_underscore                XK_underscore
+#define KSYM_grave             XK_grave
+
+#define KSYM_quoteleft         XK_quoteleft
+#define KSYM_braceleft         XK_braceleft
+#define KSYM_bar               XK_bar
+#define KSYM_braceright                XK_braceright
+#define KSYM_asciitilde                XK_asciitilde
+
+#define KSYM_Adiaeresis                XK_Adiaeresis
+#define KSYM_Odiaeresis                XK_Odiaeresis
+#define KSYM_Udiaeresis                XK_Udiaeresis
+#define KSYM_adiaeresis                XK_adiaeresis
+#define KSYM_odiaeresis                XK_odiaeresis
+#define KSYM_udiaeresis                XK_udiaeresis
+#define KSYM_ssharp            XK_ssharp
+
+#define KSYM_A                 XK_A
+#define KSYM_B                 XK_B
+#define KSYM_C                 XK_C
+#define KSYM_D                 XK_D
+#define KSYM_E                 XK_E
+#define KSYM_F                 XK_F
+#define KSYM_G                 XK_G
+#define KSYM_H                 XK_H
+#define KSYM_I                 XK_I
+#define KSYM_J                 XK_J
+#define KSYM_K                 XK_K
+#define KSYM_L                 XK_L
+#define KSYM_M                 XK_M
+#define KSYM_N                 XK_N
+#define KSYM_O                 XK_O
+#define KSYM_P                 XK_P
+#define KSYM_Q                 XK_Q
+#define KSYM_R                 XK_R
+#define KSYM_S                 XK_S
+#define KSYM_T                 XK_T
+#define KSYM_U                 XK_U
+#define KSYM_V                 XK_V
+#define KSYM_W                 XK_W
+#define KSYM_X                 XK_X
+#define KSYM_Y                 XK_Y
+#define KSYM_Z                 XK_Z
+
+#define KSYM_a                 XK_a
+#define KSYM_b                 XK_b
+#define KSYM_c                 XK_c
+#define KSYM_d                 XK_d
+#define KSYM_e                 XK_e
+#define KSYM_f                 XK_f
+#define KSYM_g                 XK_g
+#define KSYM_h                 XK_h
+#define KSYM_i                 XK_i
+#define KSYM_j                 XK_j
+#define KSYM_k                 XK_k
+#define KSYM_l                 XK_l
+#define KSYM_m                 XK_m
+#define KSYM_n                 XK_n
+#define KSYM_o                 XK_o
+#define KSYM_p                 XK_p
+#define KSYM_q                 XK_q
+#define KSYM_r                 XK_r
+#define KSYM_s                 XK_s
+#define KSYM_t                 XK_t
+#define KSYM_u                 XK_u
+#define KSYM_v                 XK_v
+#define KSYM_w                 XK_w
+#define KSYM_x                 XK_x
+#define KSYM_y                 XK_y
+#define KSYM_z                 XK_z
+
+#define KSYM_0                 XK_0
+#define KSYM_1                 XK_1
+#define KSYM_2                 XK_2
+#define KSYM_3                 XK_3
+#define KSYM_4                 XK_4
+#define KSYM_5                 XK_5
+#define KSYM_6                 XK_6
+#define KSYM_7                 XK_7
+#define KSYM_8                 XK_8
+#define KSYM_9                 XK_9
+
+#define KSYM_KP_0              XK_KP_0
+#define KSYM_KP_1              XK_KP_1
+#define KSYM_KP_2              XK_KP_2
+#define KSYM_KP_3              XK_KP_3
+#define KSYM_KP_4              XK_KP_4
+#define KSYM_KP_5              XK_KP_5
+#define KSYM_KP_6              XK_KP_6
+#define KSYM_KP_7              XK_KP_7
+#define KSYM_KP_8              XK_KP_8
+#define KSYM_KP_9              XK_KP_9
+
+#define KSYM_F1                        XK_F1
+#define KSYM_F2                        XK_F2
+#define KSYM_F3                        XK_F3
+#define KSYM_F4                        XK_F4
+#define KSYM_F5                        XK_F5
+#define KSYM_F6                        XK_F6
+#define KSYM_F7                        XK_F7
+#define KSYM_F8                        XK_F8
+#define KSYM_F9                        XK_F9
+#define KSYM_F10               XK_F10
+#define KSYM_F11               XK_F11
+#define KSYM_F12               XK_F12
+#define KSYM_F13               XK_F13
+#define KSYM_F14               XK_F14
+#define KSYM_F15               XK_F15
+#define KSYM_F16               XK_F16
+#define KSYM_F17               XK_F17
+#define KSYM_F18               XK_F18
+#define KSYM_F19               XK_F19
+#define KSYM_F20               XK_F20
+#define KSYM_F21               XK_F21
+#define KSYM_F22               XK_F22
+#define KSYM_F23               XK_F23
+#define KSYM_F24               XK_F24
+
+
+/* X11 function definitions */
+
+inline void X11InitVideoDisplay(void);
+inline void X11InitVideoBuffer(DrawBuffer **, DrawWindow **);
+Bitmap *X11LoadImage(char *);
+
+#endif /* X11_H */
index 94287fa08d729657518c51830e3837d0d2b11073..521e4b351d76f254b31ec6b14d28850d1fd31fd2 100644 (file)
@@ -1,46 +1,30 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  main.c                                                  *
+* main.c                                                   *
 ***********************************************************/
 
+#include "libgame/libgame.h"
+
 #include "main.h"
 #include "init.h"
 #include "game.h"
 #include "events.h"
-#include "sound.h"
 #include "joystick.h"
-#include "misc.h"
-
-#ifdef MSDOS
-#include <fcntl.h>
-#endif
-
-Display        *display;
-Visual        *visual;
-int            screen;
-Window         window;
-GC             gc, clip_gc[NUM_PIXMAPS], tile_clip_gc;
-Pixmap         pix[NUM_PIXMAPS];
-Pixmap         clipmask[NUM_PIXMAPS], tile_clipmask[NUM_TILES];
-
-#ifdef USE_XPM_LIBRARY
-XpmAttributes  xpm_att[NUM_PICTURES];
-#endif
 
-Drawable        drawto, drawto_field, backbuffer, fieldbuffer;
-Colormap       cmap;
+GC             tile_clip_gc;
+Bitmap        *pix[NUM_BITMAPS];
+Pixmap         tile_clipmask[NUM_TILES];
+DrawBuffer     *fieldbuffer;
+DrawBuffer     *drawto_field;
 
-int            sound_pipe[2];
-int            sound_device;
-char          *sound_device_name = SOUND_DEVICE;
 int            joystick_device = 0;
 char          *joystick_device_name[MAX_PLAYERS] =
 {
@@ -50,23 +34,16 @@ char               *joystick_device_name[MAX_PLAYERS] =
   DEV_JOYSTICK_3
 };
 
-char          *program_name = NULL;
-
 int            game_status = MAINMENU;
 boolean                level_editor_test_game = FALSE;
 boolean                network_playing = FALSE;
-int            button_status = MB_NOT_PRESSED;
-boolean                motion_status = FALSE;
+
 int            key_joystick_mapping = 0;
 int            global_joystick_status = JOYSTICK_STATUS;
 int            joystick_status = JOYSTICK_STATUS;
-int            sound_status = SOUND_STATUS;
-boolean                sound_loops_allowed = FALSE;
 
 boolean                redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
 int            redraw_x1 = 0, redraw_y1 = 0;
-int            redraw_mask;
-int            redraw_tiles;
 
 short          Feld[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 short          Ur[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
@@ -98,91 +75,83 @@ int         SBX_Left, SBX_Right;
 int            SBY_Upper, SBY_Lower;
 int            ZX,ZY, ExitX,ExitY;
 int            AllPlayersGone;
-int            FrameCounter, TimeFrames, TimePlayed, TimeLeft;
+
+int            TimeFrames, TimePlayed, TimeLeft;
 
 boolean                network_player_action_received = FALSE;
 
-struct LevelDirInfo    *leveldir_first = NULL, *leveldir_current = NULL;
 struct LevelInfo       level;
 struct PlayerInfo      stored_player[MAX_PLAYERS], *local_player = NULL;
 struct HiScore         highscore[MAX_SCORE_ENTRIES];
-struct SoundInfo       Sound[NUM_SOUNDS];
 struct TapeInfo                tape;
-struct OptionInfo      options;
 struct SetupInfo       setup;
 struct GameInfo                game;
 struct GlobalInfo      global;
 
-/* data needed for playing sounds */
+/* filenames of sound effects */
 char *sound_name[NUM_SOUNDS] =
 {
-  "alchemy",
-  "amoebe",
-  "antigrav",
-  "autsch",
-  "blurb",
-  "bong",
-  "buing",
-  "chase",
-  "czardasz",
-  "deng",
-  "fuel",
-  "gong",
-  "halloffame",
-  "holz",
-  "hui",
-  "kabumm",
-  "kink",
-  "klapper",
-  "kling",
-  "klopf",
-  "klumpf",
-  "knack",
-  "knurk",
-  "krach",
-  "lachen",
-  "laser",
-  "miep",
-  "network",
-  "njam",
-  "oeffnen",
-  "pling",
-  "pong",
-  "pusch",
-  "quiek",
-  "quirk",
-  "rhythmloop",
-  "roaaar",
-  "roehr",
-  "rumms",
-  "schlopp",
-  "schlurf",
-  "schrff",
-  "schwirr",
-  "sirr",
-  "slurp",
-  "sproing",
-  "twilight",
-  "tyger",
-  "voyager",
-  "warnton",
-  "whoosh",
-  "zisch",
-  "base",
-  "infotron",
-  "zonkdown",
-  "zonkpush",
-  "bug",
-  "boom",
-  "booom",
-  "exit",
-  "empty",
-  "gate"
+  "amoebe.wav",
+  "antigrav.wav",
+  "autsch.wav",
+  "blurb.wav",
+  "bong.wav",
+  "buing.wav",
+  "deng.wav",
+  "fuel.wav",
+  "gong.wav",
+  "halloffame.wav",
+  "holz.wav",
+  "hui.wav",
+  "kabumm.wav",
+  "kink.wav",
+  "klapper.wav",
+  "kling.wav",
+  "klopf.wav",
+  "klumpf.wav",
+  "knack.wav",
+  "knurk.wav",
+  "krach.wav",
+  "lachen.wav",
+  "laser.wav",
+  "miep.wav",
+  "njam.wav",
+  "oeffnen.wav",
+  "pling.wav",
+  "pong.wav",
+  "pusch.wav",
+  "quiek.wav",
+  "quirk.wav",
+  "rhythmloop.wav",
+  "roaaar.wav",
+  "roehr.wav",
+  "rumms.wav",
+  "schlopp.wav",
+  "schlurf.wav",
+  "schrff.wav",
+  "schwirr.wav",
+  "sirr.wav",
+  "slurp.wav",
+  "sproing.wav",
+  "warnton.wav",
+  "whoosh.wav",
+  "zisch.wav",
+  "base.wav",
+  "infotron.wav",
+  "zonkdown.wav",
+  "zonkpush.wav",
+  "bug.wav",
+  "boom.wav",
+  "booom.wav",
+  "exit.wav",
+  "empty.wav",
+  "gate.wav"
 };
 
 /* background music */
 int background_loop[] =
 {
+#if 0
   SND_ALCHEMY,
   SND_CHASE,
   SND_NETWORK,
@@ -190,6 +159,7 @@ int background_loop[] =
   SND_TYGER,
   SND_VOYAGER,
   SND_TWILIGHT
+#endif
 };
 int num_bg_loops = sizeof(background_loop)/sizeof(int);
 
@@ -303,7 +273,7 @@ char *element_info[] =
   "normal wall (BD style)",
   "rock (BD style)",
   "open exit",
-  "unknown",
+  "black orb bomb",
   "amoeba",
   "mole",                                      /* 110 */
   "penguin",
@@ -314,7 +284,7 @@ char *element_info[] =
   "arrow down",
   "pig",
   "fire breathing dragon",
-  "unknown",
+  "red key (EM style)",
   "letter ' '",                                        /* 120 */
   "letter '!'",
   "letter '\"'",
@@ -398,13 +368,13 @@ char *element_info[] =
   "growing wall (horizontal)",                 /* 200 */
   "growing wall (vertical)",
   "growing wall (all directions)",
-  "unused",
-  "unused",
-  "unused",
-  "unused",
-  "unused",
-  "unused",
-  "unused",
+  "red door (EM style)",
+  "yellow door (EM style)",
+  "green door (EM style)",
+  "blue door (EM style)",
+  "yellow key (EM style)",
+  "green key (EM style)",
+  "blue key (EM style)",
   "empty space",                               /* 210 */
   "zonk",
   "base",
@@ -445,10 +415,10 @@ char *element_info[] =
   "hardware",
   "chip (upper half)",
   "chip (lower half)",
-  "unknown",                                   /* 250 */
-  "unknown",
-  "unknown",
-  "unknown",
+  "gray door (EM style, red key)",             /* 250 */
+  "gray door (EM style, yellow key)",
+  "gray door (EM style, green key)",
+  "gray door (EM style, blue key)",
   "unknown",
   "unknown",
 
@@ -562,17 +532,22 @@ char *element_info[] =
   "-------------------------------",
   */
 };
+int num_element_info = sizeof(element_info)/sizeof(char *);
+
+
+/* ========================================================================= */
+/* main()                                                                    */
+/* ========================================================================= */
 
 int main(int argc, char *argv[])
 {
-  program_name = (strrchr(argv[0],'/') ? strrchr(argv[0],'/') + 1 : argv[0]);
-
-#ifdef MSDOS
-  _fmode = O_BINARY;
-#endif
+  InitCommandName(argv[0]);
+  InitExitFunction(CloseAllAndExit);
+  InitPlatformDependantStuff();
 
   GetOptions(argv);
-  OpenAll(argc,argv);
+  OpenAll();
+
   EventLoop();
   CloseAllAndExit(0);
   exit(0);     /* to keep compilers happy */
index add49d76a76f13b59fcfa5d6cd06bb7b401aee4b..96c62a664ff34538cd0110724777f733ec22d604 100644 (file)
@@ -1,14 +1,14 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  main.h                                                  *
+* main.h                                                   *
 ***********************************************************/
 
 #ifndef MAIN_H
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/time.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
 
-#ifndef MSDOS
-#define XK_MISCELLANY
-#define XK_LATIN1
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#include <X11/Xos.h>
-#include <X11/Intrinsic.h>
-#include <X11/keysymdef.h>
-
-#ifdef   XPM_INCLUDE_FILE
-#define  USE_XPM_LIBRARY
-#include XPM_INCLUDE_FILE
-#endif
-#else  /* MSDOS */
-#include "msdos.h"
-#endif  /* MSDOS */
-
-#ifdef DEBUG
-#define DEBUG_TIMING   0
-#endif
-
-typedef unsigned char boolean;
-typedef unsigned char byte;
-
-#ifndef FALSE
-#define FALSE          0
-#define TRUE           (!FALSE)
-#endif
+#include "libgame/libgame.h"
 
 #define WIN_XSIZE      672
 #define WIN_YSIZE      560
-#ifndef MSDOS
+
+#if !defined(PLATFORM_MSDOS)
 #define WIN_XPOS       0
 #define WIN_YPOS       0
-#else  /* MSDOS */
+#else
 #define WIN_XPOS       ((XRES - WIN_XSIZE) / 2)
 #define WIN_YPOS       ((YRES - WIN_YSIZE) / 2)
-#endif /* MSDOS */
+#endif
+
 #define SCR_FIELDX     17
 #define SCR_FIELDY     17
 #define MAX_BUF_XSIZE  (SCR_FIELDX + 2)
@@ -74,19 +50,6 @@ typedef unsigned char byte;
 
 #define MAX_PLAYERS    4
 
-#ifndef MIN
-#define MIN(a,b)       ((a) < (b) ? (a) : (b))
-#endif
-#ifndef MAX
-#define MAX(a,b)       ((a) > (b) ? (a) : (b))
-#endif
-#ifndef ABS
-#define ABS(a)         ((a) < 0 ? -(a) : (a))
-#endif
-#ifndef SIGN
-#define SIGN(a)                ((a) < 0 ? -1 : ((a)>0 ? 1 : 0))
-#endif
-
 #define SCREENX(a)     ((a) - scroll_x)
 #define SCREENY(a)     ((a) - scroll_y)
 #define LEVELX(a)      ((a) + scroll_x)
@@ -200,7 +163,7 @@ typedef unsigned char byte;
 #define PLAYER_PROTECTED(x,y)  (SHIELD_ON(PLAYERINFO(x, y)) ||         \
                                 PROTECTED_FIELD(x, y))
 
-/* Pixmaps with graphic file */
+/* Bitmaps with graphic file */
 #define PIX_BACK               0
 #define PIX_DOOR               1
 #define PIX_HEROES             2
@@ -211,13 +174,12 @@ typedef unsigned char byte;
 #define        PIX_BIGFONT             7
 #define PIX_SMALLFONT          8
 #define PIX_MEDIUMFONT         9
-/* Pixmaps without graphic file */
-#define PIX_DB_BACK            10
-#define PIX_DB_DOOR            11
-#define PIX_DB_FIELD           12
+/* Bitmaps without graphic file */
+#define PIX_DB_DOOR            10
+#define PIX_DB_FIELD           11
 
 #define NUM_PICTURES           10
-#define NUM_PIXMAPS            13
+#define NUM_BITMAPS            12
 
 /* boundaries of arrays etc. */
 #define MAX_PLAYER_NAME_LEN    10
@@ -239,7 +201,6 @@ typedef unsigned char byte;
 #define GAME_FRAME_DELAY       20      /* frame delay in milliseconds */
 #define FFWD_FRAME_DELAY       10      /* 200% speed for fast forward */
 #define FRAMES_PER_SECOND      (1000 / GAME_FRAME_DELAY)
-#define GADGET_FRAME_DELAY     150     /* delay between gadget actions */
 #define MICROLEVEL_SCROLL_DELAY        50      /* delay for scrolling micro level */
 #define MICROLEVEL_LABEL_DELAY 250     /* delay for micro level label */
 
@@ -249,19 +210,6 @@ struct HiScore
   int Score;
 };
 
-struct OptionInfo
-{
-  char *display_name;
-  char *server_host;
-  int server_port;
-  char *ro_base_directory;
-  char *rw_base_directory;
-  char *level_directory;
-  boolean serveronly;
-  boolean network;
-  boolean verbose;
-};
-
 struct SetupJoystickInfo
 {
   char *device_name;
@@ -273,12 +221,12 @@ struct SetupJoystickInfo
 
 struct SetupKeyboardInfo
 {
-  KeySym left;
-  KeySym right;
-  KeySym up;
-  KeySym down;
-  KeySym snap;
-  KeySym bomb;
+  Key left;
+  Key right;
+  Key up;
+  Key down;
+  Key snap;
+  Key bomb;
 };
 
 struct SetupInputInfo
@@ -307,6 +255,7 @@ struct SetupInfo
   boolean team_mode;
   boolean handicap;
   boolean time_limit;
+  boolean fullscreen;
 
   struct SetupInputInfo input[MAX_PLAYERS];
 };
@@ -389,35 +338,6 @@ struct LevelInfo
   boolean gravity;
 };
 
-struct LevelDirInfo
-{
-  char *filename;      /* level series single directory name */
-  char *fullpath;      /* complete path relative to level directory */
-  char *basepath;      /* absolute base path of level directory */
-  char *name;          /* level series name, as displayed on main screen */
-  char *name_short;    /* optional short name for level selection screen */
-  char *name_sorting;  /* optional sorting name for correct level sorting */
-  char *author;                /* level series author name levels without author */
-  char *imported_from; /* optional comment for imported level series */
-  int levels;          /* number of levels in level series */
-  int first_level;     /* first level number (to allow start with 0 or 1) */
-  int last_level;      /* last level number (automatically calculated) */
-  int sort_priority;   /* sort levels by 'sort_priority' and then by name */
-  boolean level_group; /* directory contains more level series directories */
-  boolean parent_link; /* entry links back to parent directory */
-  boolean user_defined;        /* user defined levels are stored in home directory */
-  boolean readonly;    /* readonly levels can not be changed with editor */
-  int color;           /* color to use on selection screen for this level */
-  char *class_desc;    /* description of level series class */
-  int handicap_level;  /* number of the lowest unsolved level */
-  int cl_first;                /* internal control field for "choose level" screen */
-  int cl_cursor;       /* internal control field for "choose level" screen */
-
-  struct LevelDirInfo *node_parent;    /* parent level directory info */
-  struct LevelDirInfo *node_group;     /* level group sub-directory info */
-  struct LevelDirInfo *next;           /* next level series structure node */
-};
-
 struct TapeInfo
 {
   int level_nr;
@@ -455,46 +375,29 @@ struct GameInfo
 
 struct GlobalInfo
 {
-  int dummy;
+  float frames_per_second;
+  boolean fps_slowdown;
+  int fps_slowdown_factor;
 };
 
-extern Display        *display;
-extern Visual         *visual;
-extern int             screen;
-extern Window                  window;
-extern GC              gc, clip_gc[], tile_clip_gc;
-extern Pixmap          pix[];
-extern Pixmap          clipmask[], tile_clipmask[];
-
-#ifdef USE_XPM_LIBRARY
-extern XpmAttributes   xpm_att[];
-#endif
-
-extern Drawable        drawto, drawto_field, backbuffer, fieldbuffer;
-extern Colormap                cmap;
+extern GC              tile_clip_gc;
+extern Bitmap         *pix[];
+extern Pixmap          tile_clipmask[];
+extern DrawBuffer      *fieldbuffer;
+extern DrawBuffer      *drawto_field;
 
-extern int             sound_pipe[2];
-extern int             sound_device;
-extern char           *sound_device_name;
 extern int             joystick_device;
 extern char           *joystick_device_name[];
 
-extern char           *program_name;
-
 extern int             game_status;
 extern boolean         level_editor_test_game;
 extern boolean         network_playing;
-extern int             button_status;
-extern boolean         motion_status;
+
 extern int             key_joystick_mapping;
 extern int             global_joystick_status, joystick_status;
-extern int             sound_status;
-extern boolean         sound_loops_allowed;
 
 extern boolean         redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
 extern int             redraw_x1, redraw_y1;
-extern int             redraw_mask;
-extern int             redraw_tiles;
 
 extern short           Feld[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 extern short           Ur[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
@@ -525,20 +428,18 @@ extern int                SBX_Left, SBX_Right;
 extern int             SBY_Upper, SBY_Lower;
 extern int             ZX,ZY, ExitX,ExitY;
 extern int             AllPlayersGone;
-extern int             FrameCounter, TimeFrames, TimePlayed, TimeLeft;
+
+extern int             TimeFrames, TimePlayed, TimeLeft;
 extern boolean         SiebAktiv;
 extern int             SiebCount;
 
 extern boolean         network_player_action_received;
 
-extern struct LevelDirInfo     *leveldir_first, *leveldir_current;
 extern struct LevelInfo                level;
 extern struct PlayerInfo       stored_player[], *local_player;
 extern struct HiScore          highscore[];
 extern struct TapeInfo         tape;
-extern struct SoundInfo                Sound[];
 extern struct JoystickInfo     joystick[];
-extern struct OptionInfo       options;
 extern struct SetupInfo                setup;
 extern struct GameInfo         game;
 extern struct GlobalInfo       global;
@@ -547,7 +448,7 @@ extern char         *sound_name[];
 extern int             background_loop[];
 extern int             num_bg_loops;
 extern char            *element_info[];
-
+extern int             num_element_info;
 
 /* often used screen positions */
 #define SX                     8
@@ -585,18 +486,6 @@ extern char                *element_info[];
 #define MICROLEV_XPOS          (SX + (SXSIZE - MICROLEV_XSIZE) / 2)
 #define MICROLEV_YPOS          (SX + 12 * TILEY - MICRO_TILEY)
 #define MICROLABEL_YPOS                (MICROLEV_YPOS + MICROLEV_YSIZE + 7)
-#define FONT1_XSIZE            32
-#define FONT1_YSIZE            32
-#define FONT2_XSIZE            14
-#define FONT2_YSIZE            14
-#define FONT3_XSIZE            11
-#define FONT3_YSIZE            14
-#define FONT4_XSIZE            16
-#define FONT4_YSIZE            16
-#define FONT5_XSIZE            10
-#define FONT5_YSIZE            14
-#define FONT6_XSIZE            16
-#define FONT6_YSIZE            32
 
 #define GFX_STARTX             SX
 #define GFX_STARTY             SY
@@ -634,9 +523,6 @@ extern char         *element_info[];
 #define MINI_MORE_PER_LINE     16
 #define MICRO_MORE_PER_LINE    16
 
-#define FONT_CHARS_PER_LINE    16
-#define FONT_LINES_PER_FONT    4
-
 /* game elements:
 **       0 - 499: real elements, stored in level file
 **      500 - 699: flag elements, only used at runtime
@@ -1536,81 +1422,73 @@ extern char             *element_info[];
 
 
 /* the names of the sounds */
-#define SND_ALCHEMY            0
-#define SND_AMOEBE             1
-#define SND_ANTIGRAV           2
-#define SND_AUTSCH             3
-#define SND_BLURB              4
-#define SND_BONG               5
-#define SND_BUING              6
-#define SND_CHASE              7
-#define SND_CZARDASZ           8
-#define SND_DENG               9
-#define SND_FUEL               10
-#define SND_GONG               11
-#define SND_HALLOFFAME         12
-#define SND_HOLZ               13
-#define SND_HUI                        14
-#define SND_KABUMM             15
-#define SND_KINK               16
-#define SND_KLAPPER            17
-#define SND_KLING              18
-#define SND_KLOPF              19
-#define SND_KLUMPF             20
-#define SND_KNACK              21
-#define SND_KNURK              22
-#define SND_KRACH              23
-#define SND_LACHEN             24
-#define SND_LASER              25
-#define SND_MIEP               26
-#define SND_NETWORK            27
-#define SND_NJAM               28
-#define SND_OEFFNEN            29
-#define SND_PLING              30
-#define SND_PONG               31
-#define SND_PUSCH              32
-#define SND_QUIEK              33
-#define SND_QUIRK              34
-#define SND_RHYTHMLOOP         35
-#define SND_ROAAAR             36
-#define SND_ROEHR              37
-#define SND_RUMMS              38
-#define SND_SCHLOPP            39
-#define SND_SCHLURF            40
-#define SND_SCHRFF             41
-#define SND_SCHWIRR            42
-#define SND_SIRR               43
-#define SND_SLURP              44
-#define SND_SPROING            45
-#define SND_TWILIGHT           46
-#define SND_TYGER              47
-#define SND_VOYAGER            48
-#define SND_WARNTON            49
-#define SND_WHOOSH             50
-#define SND_ZISCH              51
-#define SND_SP_BASE            52
-#define SND_SP_INFOTRON                53
-#define SND_SP_ZONKDOWN                54
-#define SND_SP_ZONKPUSH                55
-#define SND_SP_BUG             56
-#define SND_SP_BOOM            57
-#define SND_SP_BOOOM           58
-#define SND_SP_EXIT            59
-#define SND_EMPTY              60
-#define SND_GATE               61
-
-#define NUM_SOUNDS             62
+#define SND_AMOEBE             0
+#define SND_ANTIGRAV           1
+#define SND_AUTSCH             2
+#define SND_BLURB              3
+#define SND_BONG               4
+#define SND_BUING              5
+#define SND_DENG               6
+#define SND_FUEL               7
+#define SND_GONG               8
+#define SND_HALLOFFAME         9
+#define SND_HOLZ               10
+#define SND_HUI                        11
+#define SND_KABUMM             12
+#define SND_KINK               13
+#define SND_KLAPPER            14
+#define SND_KLING              15
+#define SND_KLOPF              16
+#define SND_KLUMPF             17
+#define SND_KNACK              18
+#define SND_KNURK              19
+#define SND_KRACH              20
+#define SND_LACHEN             21
+#define SND_LASER              22
+#define SND_MIEP               23
+#define SND_NJAM               24
+#define SND_OEFFNEN            25
+#define SND_PLING              26
+#define SND_PONG               27
+#define SND_PUSCH              28
+#define SND_QUIEK              29
+#define SND_QUIRK              30
+#define SND_RHYTHMLOOP         31
+#define SND_ROAAAR             32
+#define SND_ROEHR              33
+#define SND_RUMMS              34
+#define SND_SCHLOPP            35
+#define SND_SCHLURF            36
+#define SND_SCHRFF             37
+#define SND_SCHWIRR            38
+#define SND_SIRR               39
+#define SND_SLURP              40
+#define SND_SPROING            41
+#define SND_WARNTON            42
+#define SND_WHOOSH             43
+#define SND_ZISCH              44
+#define SND_SP_BASE            45
+#define SND_SP_INFOTRON                46
+#define SND_SP_ZONKDOWN                47
+#define SND_SP_ZONKPUSH                48
+#define SND_SP_BUG             49
+#define SND_SP_BOOM            50
+#define SND_SP_BOOOM           51
+#define SND_SP_EXIT            52
+#define SND_EMPTY              53
+#define SND_GATE               54
+
+#define NUM_SOUNDS             55
 
 /* default input keys */
-#define KEY_UNDEFINDED         XK_VoidSymbol
-#define DEFAULT_KEY_LEFT       XK_Left
-#define DEFAULT_KEY_RIGHT      XK_Right
-#define DEFAULT_KEY_UP         XK_Up
-#define DEFAULT_KEY_DOWN       XK_Down
-#define DEFAULT_KEY_SNAP       XK_Shift_L
-#define DEFAULT_KEY_BOMB       XK_Shift_R
-#define DEFAULT_KEY_OKAY       XK_Return
-#define DEFAULT_KEY_CANCEL     XK_Escape
+#define DEFAULT_KEY_LEFT       KSYM_Left
+#define DEFAULT_KEY_RIGHT      KSYM_Right
+#define DEFAULT_KEY_UP         KSYM_Up
+#define DEFAULT_KEY_DOWN       KSYM_Down
+#define DEFAULT_KEY_SNAP       KSYM_Shift_L
+#define DEFAULT_KEY_BOMB       KSYM_Shift_R
+#define DEFAULT_KEY_OKAY       KSYM_Return
+#define DEFAULT_KEY_CANCEL     KSYM_Escape
 
 /* directions for moving */
 #define MV_NO_MOVING           0
@@ -1619,19 +1497,6 @@ extern char              *element_info[];
 #define MV_UP                  (1 << 2)
 #define MV_DOWN                        (1 << 3)
 
-/* font types */
-#define FS_SMALL               0
-#define FS_BIG                 1
-#define FS_MEDIUM              2
-/* font colors */
-#define FC_RED                 0
-#define FC_BLUE                        1
-#define FC_GREEN               2
-#define FC_YELLOW              3
-#define FC_SPECIAL1            4
-#define FC_SPECIAL2            5
-#define FC_SPECIAL3            6
-
 /* values for game_status */
 #define EXITGAME               0
 #define MAINMENU               1
@@ -1645,89 +1510,20 @@ extern char             *element_info[];
 #define SETUPINPUT             9
 #define CALIBRATION            10
 
-#ifndef RO_GAME_DIR
-#define RO_GAME_DIR            "."
-#endif
-
-#ifndef RW_GAME_DIR
-#define RW_GAME_DIR            "."
-#endif
-
-#define RO_BASE_PATH           RO_GAME_DIR
-#define RW_BASE_PATH           RW_GAME_DIR
-
-#define GRAPHICS_DIRECTORY     "graphics"
-#define SOUNDS_DIRECTORY       "sounds"
-#define LEVELS_DIRECTORY       "levels"
-#define TAPES_DIRECTORY                "tapes"
-#define SCORES_DIRECTORY       "scores"
-
-#define PROGRAM_VERSION_STRING "1.4.0"
+#define PROGRAM_VERSION_STRING "2.0.0"
 #define PROGRAM_TITLE_STRING   "Rocks'n'Diamonds"
 #define PROGRAM_AUTHOR_STRING  "Holger Schemel"
-#define WINDOW_TITLE_STRING    PROGRAM_TITLE_STRING " " PROGRAM_VERSION_STRING
-#define COPYRIGHT_STRING       "Copyright ^1995-99 by " PROGRAM_AUTHOR_STRING
-
-/* default name for empty highscore entry */
-#define EMPTY_PLAYER_NAME      "no name"
-
-/* default name for unknown player names */
-#define ANONYMOUS_NAME         "anonymous"
-
-/* default name for new levels */
-#define NAMELESS_LEVEL_NAME    "nameless level"
-
-/* values for button_status */
-#define MB_NOT_PRESSED         FALSE
-#define MB_RELEASED            FALSE
-#define MB_PRESSED             TRUE
-#define MB_MENU_CHOICE         FALSE
-#define MB_MENU_MARK           TRUE
-#define MB_MENU_INITIALIZE     (-1)
-#define MB_LEFT                        1
-#define MB_MIDDLE              2
-#define MB_RIGHT               3
-
-/* values for redraw_mask */
-#define REDRAW_ALL             (1 << 0)
-#define REDRAW_FIELD           (1 << 1)
-#define REDRAW_TILES           (1 << 2)
-#define REDRAW_DOOR_1          (1 << 3)
-#define REDRAW_VIDEO_1         (1 << 4)
-#define REDRAW_VIDEO_2         (1 << 5)
-#define REDRAW_VIDEO_3         (1 << 6)
-#define REDRAW_MICROLEVEL      (1 << 7)
-#define REDRAW_FROM_BACKBUFFER (1 << 8)
-#define REDRAW_DOOR_2          (REDRAW_VIDEO_1 | \
-                                REDRAW_VIDEO_2 | \
-                                REDRAW_VIDEO_3)
-#define REDRAW_DOOR_3          (1 << 9)
-#define REDRAW_DOORS           (REDRAW_DOOR_1 | \
-                                REDRAW_DOOR_2 | \
-                                REDRAW_DOOR_3)
-#define REDRAW_MAIN            (REDRAW_FIELD | \
-                                REDRAW_TILES | \
-                                REDRAW_MICROLEVEL)
-#define REDRAWTILES_THRESHOLD  (SCR_FIELDX * SCR_FIELDY / 2)
-
-/* areas in pixmap PIX_DOOR */
-/* meaning in PIX_DB_DOOR: (3 PAGEs)
-   PAGEX1: 1. buffer for DOOR_1
-   PAGEX2: 2. buffer for DOOR_1
-   PAGEX3: buffer for animations
-*/
-
-#define DOOR_GFX_PAGESIZE      DXSIZE
-#define DOOR_GFX_PAGEX1                (0 * DOOR_GFX_PAGESIZE)
-#define DOOR_GFX_PAGEX2                (1 * DOOR_GFX_PAGESIZE)
-#define DOOR_GFX_PAGEX3                (2 * DOOR_GFX_PAGESIZE)
-#define DOOR_GFX_PAGEX4                (3 * DOOR_GFX_PAGESIZE)
-#define DOOR_GFX_PAGEX5                (4 * DOOR_GFX_PAGESIZE)
-#define DOOR_GFX_PAGEX6                (5 * DOOR_GFX_PAGESIZE)
-#define DOOR_GFX_PAGEX7                (6 * DOOR_GFX_PAGESIZE)
-#define DOOR_GFX_PAGEX8                (7 * DOOR_GFX_PAGESIZE)
-#define DOOR_GFX_PAGEY1                0
-#define DOOR_GFX_PAGEY2                DYSIZE
+#define PROGRAM_RIGHTS_STRING  "Copyright ^1995-2000 by"
+#define PROGRAM_DOS_PORT_STRING        "DOS port done by Guido Schulz"
+#define PROGRAM_IDENT_STRING   PROGRAM_VERSION_STRING " " TARGET_STRING
+#define WINDOW_TITLE_STRING    PROGRAM_TITLE_STRING " " PROGRAM_IDENT_STRING
+#define WINDOW_SUBTITLE_STRING PROGRAM_RIGHTS_STRING " " PROGRAM_AUTHOR_STRING
+#define ICON_TITLE_STRING      PROGRAM_TITLE_STRING
+#define UNIX_USERDATA_DIRECTORY        ".rocksndiamonds"
+
+#define X11_ICON_FILENAME      "rocks_icon.xbm"
+#define X11_ICONMASK_FILENAME  "rocks_iconmask.xbm"
+#define MSDOS_POINTER_FILENAME "mouse.pcx"
 
 /* for DrawGraphicAnimation() [tools.c] and AnimateToon() [cartoons.c] */
 #define ANIM_NORMAL            0
diff --git a/src/misc.c b/src/misc.c
deleted file mode 100644 (file)
index c32aa55..0000000
+++ /dev/null
@@ -1,1297 +0,0 @@
-/***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
-*----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
-*----------------------------------------------------------*
-*  misc.c                                                  *
-***********************************************************/
-
-#include <pwd.h>
-#include <unistd.h>
-#include <time.h>
-#include <sys/time.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <stdarg.h>
-#include <ctype.h>
-
-#include "misc.h"
-#include "init.h"
-#include "tools.h"
-#include "sound.h"
-#include "random.h"
-#include "joystick.h"
-#include "files.h"
-
-#ifdef MSDOS
-volatile unsigned long counter = 0;
-
-void increment_counter()
-{
-  counter++;
-}
-
-END_OF_FUNCTION(increment_counter);
-#endif
-
-
-
-/* maximal allowed length of a command line option */
-#define MAX_OPTION_LEN         256
-
-#ifndef MSDOS
-static unsigned long mainCounter(int mode)
-{
-  static struct timeval base_time = { 0, 0 };
-  struct timeval current_time;
-  unsigned long counter_ms;
-
-  gettimeofday(&current_time, NULL);
-
-  if (mode == INIT_COUNTER || current_time.tv_sec < base_time.tv_sec)
-    base_time = current_time;
-
-  counter_ms = (current_time.tv_sec  - base_time.tv_sec)  * 1000
-             + (current_time.tv_usec - base_time.tv_usec) / 1000;
-
-  return counter_ms;           /* return milliseconds since last init */
-}
-#endif
-
-void InitCounter()             /* set counter back to zero */
-{
-#ifndef MSDOS
-  mainCounter(INIT_COUNTER);
-#else
-  LOCK_VARIABLE(counter);
-  LOCK_FUNCTION(increment_counter);
-  install_int_ex(increment_counter, BPS_TO_TIMER(100));
-#endif
-}
-
-unsigned long Counter()        /* get milliseconds since last call of InitCounter() */
-{
-#ifndef MSDOS
-  return mainCounter(READ_COUNTER);
-#else
-  return (counter * 10);
-#endif
-}
-
-static void sleep_milliseconds(unsigned long milliseconds_delay)
-{
-  boolean do_busy_waiting = (milliseconds_delay < 5 ? TRUE : FALSE);
-
-#ifdef MSDOS
-  /* donït use select() to perform waiting operations under DOS/Windows
-     environment; always use a busy loop for waiting instead */
-  do_busy_waiting = TRUE;
-#endif
-
-  if (do_busy_waiting)
-  {
-    /* we want to wait only a few ms -- if we assume that we have a
-       kernel timer resolution of 10 ms, we would wait far to long;
-       therefore it's better to do a short interval of busy waiting
-       to get our sleeping time more accurate */
-
-    unsigned long base_counter = Counter(), actual_counter = Counter();
-
-    while (actual_counter < base_counter + milliseconds_delay &&
-          actual_counter >= base_counter)
-      actual_counter = Counter();
-  }
-  else
-  {
-    struct timeval delay;
-
-    delay.tv_sec  = milliseconds_delay / 1000;
-    delay.tv_usec = 1000 * (milliseconds_delay % 1000);
-
-    if (select(0, NULL, NULL, NULL, &delay) != 0)
-      Error(ERR_WARN, "sleep_milliseconds(): select() failed");
-  }
-}
-
-void Delay(unsigned long delay)        /* Sleep specified number of milliseconds */
-{
-  sleep_milliseconds(delay);
-}
-
-boolean FrameReached(unsigned long *frame_counter_var,
-                    unsigned long frame_delay)
-{
-  unsigned long actual_frame_counter = FrameCounter;
-
-  if (actual_frame_counter < *frame_counter_var+frame_delay &&
-      actual_frame_counter >= *frame_counter_var)
-    return(FALSE);
-
-  *frame_counter_var = actual_frame_counter;
-  return(TRUE);
-}
-
-boolean DelayReached(unsigned long *counter_var,
-                    unsigned long delay)
-{
-  unsigned long actual_counter = Counter();
-
-  if (actual_counter < *counter_var + delay &&
-      actual_counter >= *counter_var)
-    return(FALSE);
-
-  *counter_var = actual_counter;
-  return(TRUE);
-}
-
-void WaitUntilDelayReached(unsigned long *counter_var, unsigned long delay)
-{
-  unsigned long actual_counter;
-
-  while(1)
-  {
-    actual_counter = Counter();
-
-    if (actual_counter < *counter_var + delay &&
-       actual_counter >= *counter_var)
-      sleep_milliseconds((*counter_var + delay - actual_counter) / 2);
-    else
-      break;
-  }
-
-  *counter_var = actual_counter;
-}
-
-/* int2str() returns a number converted to a string;
-   the used memory is static, but will be overwritten by later calls,
-   so if you want to save the result, copy it to a private string buffer;
-   there can be 10 local calls of int2str() without buffering the result --
-   the 11th call will then destroy the result from the first call and so on.
-*/
-
-char *int2str(int number, int size)
-{
-  static char shift_array[10][40];
-  static int shift_counter = 0;
-  char *s = shift_array[shift_counter];
-
-  shift_counter = (shift_counter + 1) % 10;
-
-  if (size > 20)
-    size = 20;
-
-  if (size)
-  {
-    sprintf(s, "                    %09d", number);
-    return &s[strlen(s) - size];
-  }
-  else
-  {
-    sprintf(s, "%d", number);
-    return s;
-  }
-}
-
-unsigned int SimpleRND(unsigned int max)
-{
-  static unsigned long root = 654321;
-  struct timeval current_time;
-
-  gettimeofday(&current_time,NULL);
-  root = root * 4253261 + current_time.tv_sec + current_time.tv_usec;
-  return (root % max);
-}
-
-#ifdef DEBUG
-static unsigned int last_RND_value = 0;
-
-unsigned int last_RND()
-{
-  return last_RND_value;
-}
-#endif
-
-unsigned int RND(unsigned int max)
-{
-#ifdef DEBUG
-  return (last_RND_value = random_linux_libc() % max);
-#else
-  return (random_linux_libc() % max);
-#endif
-}
-
-unsigned int InitRND(long seed)
-{
-  struct timeval current_time;
-
-  if (seed == NEW_RANDOMIZE)
-  {
-    gettimeofday(&current_time,NULL);
-    srandom_linux_libc((unsigned int) current_time.tv_usec);
-    return (unsigned int)current_time.tv_usec;
-  }
-  else
-  {
-    srandom_linux_libc((unsigned int) seed);
-    return (unsigned int)seed;
-  }
-}
-
-char *getLoginName()
-{
-  struct passwd *pwd;
-
-  if ((pwd = getpwuid(getuid())) == NULL)
-    return ANONYMOUS_NAME;
-  else
-    return pwd->pw_name;
-}
-
-char *getRealName()
-{
-#ifndef MSDOS
-  struct passwd *pwd;
-
-  if ((pwd = getpwuid(getuid())) == NULL || strlen(pwd->pw_gecos) == 0)
-    return ANONYMOUS_NAME;
-  else
-  {
-    static char real_name[1024];
-    char *from_ptr = pwd->pw_gecos, *to_ptr = real_name;
-
-    if (strchr(pwd->pw_gecos, 'ß') == NULL)
-      return pwd->pw_gecos;
-
-    /* the user's real name contains a 'ß' character (german sharp s),
-       which has no equivalent in upper case letters (which our fonts use) */
-    while (*from_ptr != '\0' && (long)(to_ptr - real_name) < 1024 - 2)
-    {
-      if (*from_ptr != 'ß')
-       *to_ptr++ = *from_ptr++;
-      else
-      {
-       from_ptr++;
-       *to_ptr++ = 's';
-       *to_ptr++ = 's';
-      }
-    }
-    *to_ptr = '\0';
-
-    return real_name;
-  }
-#else
-  return ANONYMOUS_NAME;
-#endif
-}
-
-char *getHomeDir()
-{
-#ifndef MSDOS
-  static char *home_dir = NULL;
-
-  if (!home_dir)
-  {
-    if (!(home_dir = getenv("HOME")))
-    {
-      struct passwd *pwd;
-
-      if ((pwd = getpwuid(getuid())))
-       home_dir = pwd->pw_dir;
-      else
-       home_dir = ".";
-    }
-  }
-
-  return home_dir;
-#else
-  return ".";
-#endif
-}
-
-char *getPath2(char *path1, char *path2)
-{
-  char *complete_path = checked_malloc(strlen(path1) + 1 +
-                                      strlen(path2) + 1);
-
-  sprintf(complete_path, "%s/%s", path1, path2);
-  return complete_path;
-}
-
-char *getPath3(char *path1, char *path2, char *path3)
-{
-  char *complete_path = checked_malloc(strlen(path1) + 1 +
-                                      strlen(path2) + 1 +
-                                      strlen(path3) + 1);
-
-  sprintf(complete_path, "%s/%s/%s", path1, path2, path3);
-  return complete_path;
-}
-
-char *getStringCopy(char *s)
-{
-  char *s_copy;
-
-  if (s == NULL)
-    return NULL;
-
-  s_copy = checked_malloc(strlen(s) + 1);
-
-  strcpy(s_copy, s);
-  return s_copy;
-}
-
-char *getStringToLower(char *s)
-{
-  char *s_copy = checked_malloc(strlen(s) + 1);
-  char *s_ptr = s_copy;
-
-  while (*s)
-    *s_ptr++ = tolower(*s++);
-  *s_ptr = '\0';
-
-  return s_copy;
-}
-
-void MarkTileDirty(int x, int y)
-{
-  int xx = redraw_x1 + x;
-  int yy = redraw_y1 + y;
-
-  if (!redraw[xx][yy])
-    redraw_tiles++;
-
-  redraw[xx][yy] = TRUE;
-  redraw_mask |= REDRAW_TILES;
-}
-
-void SetBorderElement()
-{
-  int x, y;
-
-  BorderElement = EL_LEERRAUM;
-
-  for(y=0; y<lev_fieldy && BorderElement == EL_LEERRAUM; y++)
-  {
-    for(x=0; x<lev_fieldx; x++)
-    {
-      if (!IS_MASSIVE(Feld[x][y]))
-       BorderElement = EL_BETON;
-
-      if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
-       x = lev_fieldx - 2;
-    }
-  }
-}
-
-void GetOptions(char *argv[])
-{
-  char **options_left = &argv[1];
-
-  /* initialize global program options */
-  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 = RO_BASE_PATH "/" LEVELS_DIRECTORY;
-  options.serveronly = FALSE;
-  options.network = FALSE;
-  options.verbose = FALSE;
-
-  while (*options_left)
-  {
-    char option_str[MAX_OPTION_LEN];
-    char *option = options_left[0];
-    char *next_option = options_left[1];
-    char *option_arg = NULL;
-    int option_len = strlen(option);
-
-    if (option_len >= MAX_OPTION_LEN)
-      Error(ERR_EXIT_HELP, "unrecognized option '%s'", option);
-
-    strcpy(option_str, option);                        /* copy argument into buffer */
-    option = option_str;
-
-    if (strcmp(option, "--") == 0)             /* stop scanning arguments */
-      break;
-
-    if (strncmp(option, "--", 2) == 0)         /* treat '--' like '-' */
-      option++;
-
-    option_arg = strchr(option, '=');
-    if (option_arg == NULL)                    /* no '=' in option */
-      option_arg = next_option;
-    else
-    {
-      *option_arg++ = '\0';                    /* cut argument from option */
-      if (*option_arg == '\0')                 /* no argument after '=' */
-       Error(ERR_EXIT_HELP, "option '%s' has invalid argument", option_str);
-    }
-
-    option_len = strlen(option);
-
-    if (strcmp(option, "-") == 0)
-      Error(ERR_EXIT_HELP, "unrecognized option '%s'", option);
-    else if (strncmp(option, "-help", option_len) == 0)
-    {
-      printf("Usage: %s [options] [server.name [port]]\n"
-            "Options:\n"
-            "  -d, --display machine:0       X server display\n"
-            "  -b, --basepath directory      alternative base directory\n"
-            "  -l, --level directory        alternative level directory\n"
-            "  -s, --serveronly              only start network server\n"
-            "  -n, --network                 network multiplayer game\n"
-            "  -v, --verbose                 verbose mode\n",
-            program_name);
-      exit(0);
-    }
-    else if (strncmp(option, "-display", option_len) == 0)
-    {
-      if (option_arg == NULL)
-       Error(ERR_EXIT_HELP, "option '%s' requires an argument", option_str);
-
-      options.display_name = option_arg;
-      if (option_arg == next_option)
-       options_left++;
-    }
-    else if (strncmp(option, "-basepath", option_len) == 0)
-    {
-      if (option_arg == NULL)
-       Error(ERR_EXIT_HELP, "option '%s' requires an argument", option_str);
-
-      /* this should be extended to separate options for ro and rw data */
-      options.ro_base_directory = option_arg;
-      options.rw_base_directory = option_arg;
-      if (option_arg == next_option)
-       options_left++;
-
-      /* adjust path for level directory accordingly */
-      options.level_directory =
-       getPath2(options.ro_base_directory, LEVELS_DIRECTORY);
-    }
-    else if (strncmp(option, "-levels", option_len) == 0)
-    {
-      if (option_arg == NULL)
-       Error(ERR_EXIT_HELP, "option '%s' requires an argument", option_str);
-
-      options.level_directory = option_arg;
-      if (option_arg == next_option)
-       options_left++;
-    }
-    else if (strncmp(option, "-network", option_len) == 0)
-    {
-      options.network = TRUE;
-    }
-    else if (strncmp(option, "-serveronly", option_len) == 0)
-    {
-      options.serveronly = TRUE;
-    }
-    else if (strncmp(option, "-verbose", option_len) == 0)
-    {
-      options.verbose = TRUE;
-    }
-    else if (*option == '-')
-    {
-      Error(ERR_EXIT_HELP, "unrecognized option '%s'", option_str);
-    }
-    else if (options.server_host == NULL)
-    {
-      options.server_host = *options_left;
-    }
-    else if (options.server_port == 0)
-    {
-      options.server_port = atoi(*options_left);
-      if (options.server_port < 1024)
-       Error(ERR_EXIT_HELP, "bad port number '%d'", options.server_port);
-    }
-    else
-      Error(ERR_EXIT_HELP, "too many arguments");
-
-    options_left++;
-  }
-}
-
-void Error(int mode, char *format, ...)
-{
-  char *process_name = "";
-  FILE *error = stderr;
-
-  /* display warnings only when running in verbose mode */
-  if (mode & ERR_WARN && !options.verbose)
-    return;
-
-#ifdef MSDOS
-  if ((error = openErrorFile()) == NULL)
-  {
-    printf("Cannot write to error output file!\n");
-    CloseAllAndExit(1);
-  }
-#endif
-
-  if (mode & ERR_SOUND_SERVER)
-    process_name = " sound server";
-  else if (mode & ERR_NETWORK_SERVER)
-    process_name = " network server";
-  else if (mode & ERR_NETWORK_CLIENT)
-    process_name = " network client **";
-
-  if (format)
-  {
-    va_list ap;
-
-    fprintf(error, "%s%s: ", program_name, process_name);
-
-    if (mode & ERR_WARN)
-      fprintf(error, "warning: ");
-
-    va_start(ap, format);
-    vfprintf(error, format, ap);
-    va_end(ap);
-  
-    fprintf(error, "\n");
-  }
-  
-  if (mode & ERR_HELP)
-    fprintf(error, "%s: Try option '--help' for more information.\n",
-           program_name);
-
-  if (mode & ERR_EXIT)
-    fprintf(error, "%s%s: aborting\n", program_name, process_name);
-
-  if (error != stderr)
-    fclose(error);
-
-  if (mode & ERR_EXIT)
-  {
-    if (mode & ERR_FROM_SERVER)
-      exit(1);                         /* child process: normal exit */
-    else
-      CloseAllAndExit(1);              /* main process: clean up stuff */
-  }
-}
-
-void *checked_malloc(unsigned long size)
-{
-  void *ptr;
-
-  ptr = malloc(size);
-
-  if (ptr == NULL)
-    Error(ERR_EXIT, "cannot allocate %d bytes -- out of memory", size);
-
-  return ptr;
-}
-
-void *checked_calloc(unsigned long size)
-{
-  void *ptr;
-
-  ptr = calloc(1, size);
-
-  if (ptr == NULL)
-    Error(ERR_EXIT, "cannot allocate %d bytes -- out of memory", size);
-
-  return ptr;
-}
-
-short getFile16BitInteger(FILE *file, int byte_order)
-{
-  if (byte_order == BYTE_ORDER_BIG_ENDIAN)
-    return ((fgetc(file) <<  8) |
-           (fgetc(file) <<  0));
-  else          /* BYTE_ORDER_LITTLE_ENDIAN */
-    return ((fgetc(file) <<  0) |
-           (fgetc(file) <<  8));
-}
-
-void putFile16BitInteger(FILE *file, short value, int byte_order)
-{
-  if (byte_order == BYTE_ORDER_BIG_ENDIAN)
-  {
-    fputc((value >>  8) & 0xff, file);
-    fputc((value >>  0) & 0xff, file);
-  }
-  else          /* BYTE_ORDER_LITTLE_ENDIAN */
-  {
-    fputc((value >>  0) & 0xff, file);
-    fputc((value >>  8) & 0xff, file);
-  }
-}
-
-int getFile32BitInteger(FILE *file, int byte_order)
-{
-  if (byte_order == BYTE_ORDER_BIG_ENDIAN)
-    return ((fgetc(file) << 24) |
-           (fgetc(file) << 16) |
-           (fgetc(file) <<  8) |
-           (fgetc(file) <<  0));
-  else          /* BYTE_ORDER_LITTLE_ENDIAN */
-    return ((fgetc(file) <<  0) |
-           (fgetc(file) <<  8) |
-           (fgetc(file) << 16) |
-           (fgetc(file) << 24));
-}
-
-void putFile32BitInteger(FILE *file, int value, int byte_order)
-{
-  if (byte_order == BYTE_ORDER_BIG_ENDIAN)
-  {
-    fputc((value >> 24) & 0xff, file);
-    fputc((value >> 16) & 0xff, file);
-    fputc((value >>  8) & 0xff, file);
-    fputc((value >>  0) & 0xff, file);
-  }
-  else          /* BYTE_ORDER_LITTLE_ENDIAN */
-  {
-    fputc((value >>  0) & 0xff, file);
-    fputc((value >>  8) & 0xff, file);
-    fputc((value >> 16) & 0xff, file);
-    fputc((value >> 24) & 0xff, file);
-  }
-}
-
-void getFileChunk(FILE *file, char *chunk_buffer, int *chunk_length,
-                 int byte_order)
-{
-  const int chunk_identifier_length = 4;
-
-  /* read chunk identifier */
-  fgets(chunk_buffer, chunk_identifier_length + 1, file);
-
-  /* read chunk length */
-  *chunk_length = getFile32BitInteger(file, byte_order);
-}
-
-void putFileChunk(FILE *file, char *chunk_name, int chunk_length,
-                 int byte_order)
-{
-  /* write chunk identifier */
-  fputs(chunk_name, file);
-
-  /* write chunk length */
-  putFile32BitInteger(file, chunk_length, byte_order);
-}
-
-#define TRANSLATE_KEYSYM_TO_KEYNAME    0
-#define TRANSLATE_KEYSYM_TO_X11KEYNAME 1
-#define TRANSLATE_X11KEYNAME_TO_KEYSYM 2
-
-void translate_keyname(KeySym *keysym, char **x11name, char **name, int mode)
-{
-  static struct
-  {
-    KeySym keysym;
-    char *x11name;
-    char *name;
-  } translate_key[] =
-  {
-    /* normal cursor keys */
-    { XK_Left,         "XK_Left",              "cursor left" },
-    { XK_Right,                "XK_Right",             "cursor right" },
-    { XK_Up,           "XK_Up",                "cursor up" },
-    { XK_Down,         "XK_Down",              "cursor down" },
-
-    /* keypad cursor keys */
-#ifdef XK_KP_Left
-    { XK_KP_Left,      "XK_KP_Left",           "keypad left" },
-    { XK_KP_Right,     "XK_KP_Right",          "keypad right" },
-    { XK_KP_Up,                "XK_KP_Up",             "keypad up" },
-    { XK_KP_Down,      "XK_KP_Down",           "keypad down" },
-#endif
-
-    /* other keypad keys */
-#ifdef XK_KP_Enter
-    { XK_KP_Enter,     "XK_KP_Enter",          "keypad enter" },
-    { XK_KP_Add,       "XK_KP_Add",            "keypad +" },
-    { XK_KP_Subtract,  "XK_KP_Subtract",       "keypad -" },
-    { XK_KP_Multiply,  "XK_KP_Multiply",       "keypad mltply" },
-    { XK_KP_Divide,    "XK_KP_Divide",         "keypad /" },
-    { XK_KP_Separator, "XK_KP_Separator",      "keypad ," },
-#endif
-
-    /* modifier keys */
-    { XK_Shift_L,      "XK_Shift_L",           "left shift" },
-    { XK_Shift_R,      "XK_Shift_R",           "right shift" },
-    { XK_Control_L,    "XK_Control_L",         "left control" },
-    { XK_Control_R,    "XK_Control_R",         "right control" },
-    { XK_Meta_L,       "XK_Meta_L",            "left meta" },
-    { XK_Meta_R,       "XK_Meta_R",            "right meta" },
-    { XK_Alt_L,                "XK_Alt_L",             "left alt" },
-    { XK_Alt_R,                "XK_Alt_R",             "right alt" },
-    { XK_Mode_switch,  "XK_Mode_switch",       "mode switch" },
-    { XK_Multi_key,    "XK_Multi_key",         "multi key" },
-
-    /* some special keys */
-    { XK_BackSpace,    "XK_BackSpace",         "backspace" },
-    { XK_Delete,       "XK_Delete",            "delete" },
-    { XK_Insert,       "XK_Insert",            "insert" },
-    { XK_Tab,          "XK_Tab",               "tab" },
-    { XK_Home,         "XK_Home",              "home" },
-    { XK_End,          "XK_End",               "end" },
-    { XK_Page_Up,      "XK_Page_Up",           "page up" },
-    { XK_Page_Down,    "XK_Page_Down",         "page down" },
-
-
-    /* ASCII 0x20 to 0x40 keys (except numbers) */
-    { XK_space,                "XK_space",             "space" },
-    { XK_exclam,       "XK_exclam",            "!" },
-    { XK_quotedbl,     "XK_quotedbl",          "\"" },
-    { XK_numbersign,   "XK_numbersign",        "#" },
-    { XK_dollar,       "XK_dollar",            "$" },
-    { XK_percent,      "XK_percent",           "%" },
-    { XK_ampersand,    "XK_ampersand",         "&" },
-    { XK_apostrophe,   "XK_apostrophe",        "'" },
-    { XK_parenleft,    "XK_parenleft",         "(" },
-    { XK_parenright,   "XK_parenright",        ")" },
-    { XK_asterisk,     "XK_asterisk",          "*" },
-    { XK_plus,         "XK_plus",              "+" },
-    { XK_comma,                "XK_comma",             "," },
-    { XK_minus,                "XK_minus",             "-" },
-    { XK_period,       "XK_period",            "." },
-    { XK_slash,                "XK_slash",             "/" },
-    { XK_colon,                "XK_colon",             ":" },
-    { XK_semicolon,    "XK_semicolon",         ";" },
-    { XK_less,         "XK_less",              "<" },
-    { XK_equal,                "XK_equal",             "=" },
-    { XK_greater,      "XK_greater",           ">" },
-    { XK_question,     "XK_question",          "?" },
-    { XK_at,           "XK_at",                "@" },
-
-    /* more ASCII keys */
-    { XK_bracketleft,  "XK_bracketleft",       "[" },
-    { XK_backslash,    "XK_backslash",         "backslash" },
-    { XK_bracketright, "XK_bracketright",      "]" },
-    { XK_asciicircum,  "XK_asciicircum",       "circumflex" },
-    { XK_underscore,   "XK_underscore",        "_" },
-    { XK_grave,                "XK_grave",             "grave" },
-    { XK_quoteleft,    "XK_quoteleft",         "quote left" },
-    { XK_braceleft,    "XK_braceleft",         "brace left" },
-    { XK_bar,          "XK_bar",               "bar" },
-    { XK_braceright,   "XK_braceright",        "brace right" },
-    { XK_asciitilde,   "XK_asciitilde",        "ascii tilde" },
-
-    /* special (non-ASCII) keys */
-    { XK_Adiaeresis,   "XK_Adiaeresis",        "Ä" },
-    { XK_Odiaeresis,   "XK_Odiaeresis",        "Ö" },
-    { XK_Udiaeresis,   "XK_Udiaeresis",        "Ãœ" },
-    { XK_adiaeresis,   "XK_adiaeresis",        "ä" },
-    { XK_odiaeresis,   "XK_odiaeresis",        "ö" },
-    { XK_udiaeresis,   "XK_udiaeresis",        "ü" },
-    { XK_ssharp,       "XK_ssharp",            "sharp s" },
-
-    /* end-of-array identifier */
-    { 0,                NULL,                  NULL }
-  };
-
-  int i;
-
-  if (mode == TRANSLATE_KEYSYM_TO_KEYNAME)
-  {
-    static char name_buffer[30];
-    KeySym key = *keysym;
-
-    if (key >= XK_A && key <= XK_Z)
-      sprintf(name_buffer, "%c", 'A' + (char)(key - XK_A));
-    else if (key >= XK_a && key <= XK_z)
-      sprintf(name_buffer, "%c", 'a' + (char)(key - XK_a));
-    else if (key >= XK_0 && key <= XK_9)
-      sprintf(name_buffer, "%c", '0' + (char)(key - XK_0));
-    else if (key >= XK_KP_0 && key <= XK_KP_9)
-      sprintf(name_buffer, "keypad %c", '0' + (char)(key - XK_KP_0));
-    else if (key >= XK_F1 && key <= XK_F24)
-      sprintf(name_buffer, "function F%d", (int)(key - XK_F1 + 1));
-    else if (key == KEY_UNDEFINDED)
-      strcpy(name_buffer, "(undefined)");
-    else
-    {
-      i = 0;
-
-      do
-      {
-       if (key == translate_key[i].keysym)
-       {
-         strcpy(name_buffer, translate_key[i].name);
-         break;
-       }
-      }
-      while (translate_key[++i].name);
-
-      if (!translate_key[i].name)
-       strcpy(name_buffer, "(unknown)");
-    }
-
-    *name = name_buffer;
-  }
-  else if (mode == TRANSLATE_KEYSYM_TO_X11KEYNAME)
-  {
-    static char name_buffer[30];
-    KeySym key = *keysym;
-
-    if (key >= XK_A && key <= XK_Z)
-      sprintf(name_buffer, "XK_%c", 'A' + (char)(key - XK_A));
-    else if (key >= XK_a && key <= XK_z)
-      sprintf(name_buffer, "XK_%c", 'a' + (char)(key - XK_a));
-    else if (key >= XK_0 && key <= XK_9)
-      sprintf(name_buffer, "XK_%c", '0' + (char)(key - XK_0));
-    else if (key >= XK_KP_0 && key <= XK_KP_9)
-      sprintf(name_buffer, "XK_KP_%c", '0' + (char)(key - XK_KP_0));
-    else if (key >= XK_F1 && key <= XK_F24)
-      sprintf(name_buffer, "XK_F%d", (int)(key - XK_F1 + 1));
-    else if (key == KEY_UNDEFINDED)
-      strcpy(name_buffer, "[undefined]");
-    else
-    {
-      i = 0;
-
-      do
-      {
-       if (key == translate_key[i].keysym)
-       {
-         strcpy(name_buffer, translate_key[i].x11name);
-         break;
-       }
-      }
-      while (translate_key[++i].x11name);
-
-      if (!translate_key[i].x11name)
-       sprintf(name_buffer, "0x%04lx", (unsigned long)key);
-    }
-
-    *x11name = name_buffer;
-  }
-  else if (mode == TRANSLATE_X11KEYNAME_TO_KEYSYM)
-  {
-    KeySym key = XK_VoidSymbol;
-    char *name_ptr = *x11name;
-
-    if (strncmp(name_ptr, "XK_", 3) == 0 && strlen(name_ptr) == 4)
-    {
-      char c = name_ptr[3];
-
-      if (c >= 'A' && c <= 'Z')
-       key = XK_A + (KeySym)(c - 'A');
-      else if (c >= 'a' && c <= 'z')
-       key = XK_a + (KeySym)(c - 'a');
-      else if (c >= '0' && c <= '9')
-       key = XK_0 + (KeySym)(c - '0');
-    }
-    else if (strncmp(name_ptr, "XK_KP_", 6) == 0 && strlen(name_ptr) == 7)
-    {
-      char c = name_ptr[6];
-
-      if (c >= '0' && c <= '9')
-       key = XK_0 + (KeySym)(c - '0');
-    }
-    else if (strncmp(name_ptr, "XK_F", 4) == 0 && strlen(name_ptr) <= 6)
-    {
-      char c1 = name_ptr[4];
-      char c2 = name_ptr[5];
-      int d = 0;
-
-      if ((c1 >= '0' && c1 <= '9') &&
-         ((c2 >= '0' && c1 <= '9') || c2 == '\0'))
-       d = atoi(&name_ptr[4]);
-
-      if (d >=1 && d <= 24)
-       key = XK_F1 + (KeySym)(d - 1);
-    }
-    else if (strncmp(name_ptr, "XK_", 3) == 0)
-    {
-      i = 0;
-
-      do
-      {
-       if (strcmp(name_ptr, translate_key[i].x11name) == 0)
-       {
-         key = translate_key[i].keysym;
-         break;
-       }
-      }
-      while (translate_key[++i].x11name);
-    }
-    else if (strncmp(name_ptr, "0x", 2) == 0)
-    {
-      unsigned long value = 0;
-
-      name_ptr += 2;
-
-      while (name_ptr)
-      {
-       char c = *name_ptr++;
-       int d = -1;
-
-       if (c >= '0' && c <= '9')
-         d = (int)(c - '0');
-       else if (c >= 'a' && c <= 'f')
-         d = (int)(c - 'a' + 10);
-       else if (c >= 'A' && c <= 'F')
-         d = (int)(c - 'A' + 10);
-
-       if (d == -1)
-       {
-         value = -1;
-         break;
-       }
-
-       value = value * 16 + d;
-      }
-
-      if (value != -1)
-       key = (KeySym)value;
-    }
-
-    *keysym = key;
-  }
-}
-
-char *getKeyNameFromKeySym(KeySym keysym)
-{
-  char *name;
-
-  translate_keyname(&keysym, NULL, &name, TRANSLATE_KEYSYM_TO_KEYNAME);
-  return name;
-}
-
-char *getX11KeyNameFromKeySym(KeySym keysym)
-{
-  char *x11name;
-
-  translate_keyname(&keysym, &x11name, NULL, TRANSLATE_KEYSYM_TO_X11KEYNAME);
-  return x11name;
-}
-
-KeySym getKeySymFromX11KeyName(char *x11name)
-{
-  KeySym keysym;
-
-  translate_keyname(&keysym, &x11name, NULL, TRANSLATE_X11KEYNAME_TO_KEYSYM);
-  return keysym;
-}
-
-char getCharFromKeySym(KeySym keysym)
-{
-  char *keyname = getKeyNameFromKeySym(keysym);
-  char letter = 0;
-
-  if (strlen(keyname) == 1)
-    letter = keyname[0];
-  else if (strcmp(keyname, "space") == 0)
-    letter = ' ';
-  else if (strcmp(keyname, "circumflex") == 0)
-    letter = '^';
-
-  return letter;
-}
-
-#define TRANSLATE_JOYSYMBOL_TO_JOYNAME 0
-#define TRANSLATE_JOYNAME_TO_JOYSYMBOL 1
-
-void translate_joyname(int *joysymbol, char **name, int mode)
-{
-  static struct
-  {
-    int joysymbol;
-    char *name;
-  } translate_joy[] =
-  {
-    { JOY_LEFT,                "joystick_left" },
-    { JOY_RIGHT,       "joystick_right" },
-    { JOY_UP,          "joystick_up" },
-    { JOY_DOWN,                "joystick_down" },
-    { JOY_BUTTON_1,    "joystick_button_1" },
-    { JOY_BUTTON_2,    "joystick_button_2" },
-  };
-
-  int i;
-
-  if (mode == TRANSLATE_JOYSYMBOL_TO_JOYNAME)
-  {
-    *name = "[undefined]";
-
-    for (i=0; i<6; i++)
-    {
-      if (*joysymbol == translate_joy[i].joysymbol)
-      {
-       *name = translate_joy[i].name;
-       break;
-      }
-    }
-  }
-  else if (mode == TRANSLATE_JOYNAME_TO_JOYSYMBOL)
-  {
-    *joysymbol = 0;
-
-    for (i=0; i<6; i++)
-    {
-      if (strcmp(*name, translate_joy[i].name) == 0)
-      {
-       *joysymbol = translate_joy[i].joysymbol;
-       break;
-      }
-    }
-  }
-}
-
-char *getJoyNameFromJoySymbol(int joysymbol)
-{
-  char *name;
-
-  translate_joyname(&joysymbol, &name, TRANSLATE_JOYSYMBOL_TO_JOYNAME);
-  return name;
-}
-
-int getJoySymbolFromJoyName(char *name)
-{
-  int joysymbol;
-
-  translate_joyname(&joysymbol, &name, TRANSLATE_JOYNAME_TO_JOYSYMBOL);
-  return joysymbol;
-}
-
-int getJoystickNrFromDeviceName(char *device_name)
-{
-  char c;
-  int joystick_nr = 0;
-
-  if (device_name == NULL || device_name[0] == '\0')
-    return 0;
-
-  c = device_name[strlen(device_name) - 1];
-
-  if (c >= '0' && c <= '9')
-    joystick_nr = (int)(c - '0');
-
-  if (joystick_nr < 0 || joystick_nr >= MAX_PLAYERS)
-    joystick_nr = 0;
-
-  return joystick_nr;
-}
-
-/* ------------------------------------------------------------------------- */
-/* some functions to handle lists of level directories                       */
-/* ------------------------------------------------------------------------- */
-
-struct LevelDirInfo *newLevelDirInfo()
-{
-  return checked_calloc(sizeof(struct LevelDirInfo));
-}
-
-void pushLevelDirInfo(struct LevelDirInfo **node_first,
-                     struct LevelDirInfo *node_new)
-{
-  node_new->next = *node_first;
-  *node_first = node_new;
-}
-
-int numLevelDirInfo(struct LevelDirInfo *node)
-{
-  int num = 0;
-
-  while (node)
-  {
-    num++;
-    node = node->next;
-  }
-
-  return num;
-}
-
-boolean validLevelSeries(struct LevelDirInfo *node)
-{
-  return (node != NULL && !node->node_group && !node->parent_link);
-}
-
-struct LevelDirInfo *getFirstValidLevelSeries(struct LevelDirInfo *node)
-{
-  if (node == NULL)            /* start with first level directory entry */
-    return getFirstValidLevelSeries(leveldir_first);
-  else if (node->node_group)   /* enter level group (step down into tree) */
-    return getFirstValidLevelSeries(node->node_group);
-  else if (node->parent_link)  /* skip start entry of level group */
-  {
-    if (node->next)            /* get first real level series entry */
-      return getFirstValidLevelSeries(node->next);
-    else                       /* leave empty level group and go on */
-      return getFirstValidLevelSeries(node->node_parent->next);
-  }
-  else                         /* this seems to be a regular level series */
-    return node;
-}
-
-struct LevelDirInfo *getLevelDirInfoFirstGroupEntry(struct LevelDirInfo *node)
-{
-  if (node == NULL)
-    return NULL;
-
-  if (node->node_parent == NULL)               /* top level group */
-    return leveldir_first;
-  else                                         /* sub level group */
-    return node->node_parent->node_group;
-}
-
-int numLevelDirInfoInGroup(struct LevelDirInfo *node)
-{
-  return numLevelDirInfo(getLevelDirInfoFirstGroupEntry(node));
-}
-
-int posLevelDirInfo(struct LevelDirInfo *node)
-{
-  struct LevelDirInfo *node_cmp = getLevelDirInfoFirstGroupEntry(node);
-  int pos = 0;
-
-  while (node_cmp)
-  {
-    if (node_cmp == node)
-      return pos;
-
-    pos++;
-    node_cmp = node_cmp->next;
-  }
-
-  return 0;
-}
-
-struct LevelDirInfo *getLevelDirInfoFromPos(struct LevelDirInfo *node, int pos)
-{
-  struct LevelDirInfo *node_default = node;
-  int pos_cmp = 0;
-
-  while (node)
-  {
-    if (pos_cmp == pos)
-      return node;
-
-    pos_cmp++;
-    node = node->next;
-  }
-
-  return node_default;
-}
-
-struct LevelDirInfo *getLevelDirInfoFromFilenameExt(struct LevelDirInfo *node,
-                                                   char *filename)
-{
-  if (filename == NULL)
-    return NULL;
-
-  while (node)
-  {
-    if (node->node_group)
-    {
-      struct LevelDirInfo *node_group;
-
-      node_group = getLevelDirInfoFromFilenameExt(node->node_group, filename);
-
-      if (node_group)
-       return node_group;
-    }
-    else if (!node->parent_link)
-    {
-      if (strcmp(filename, node->filename) == 0)
-       return node;
-    }
-
-    node = node->next;
-  }
-
-  return NULL;
-}
-
-struct LevelDirInfo *getLevelDirInfoFromFilename(char *filename)
-{
-  return getLevelDirInfoFromFilenameExt(leveldir_first, filename);
-}
-
-void dumpLevelDirInfo(struct LevelDirInfo *node, int depth)
-{
-  int i;
-
-  while (node)
-  {
-    for (i=0; i<depth * 3; i++)
-      printf(" ");
-
-    printf("filename == '%s'\n", node->filename);
-
-    if (node->node_group != NULL)
-      dumpLevelDirInfo(node->node_group, depth + 1);
-
-    node = node->next;
-  }
-}
-
-void sortLevelDirInfo(struct LevelDirInfo **node_first,
-                     int (*compare_function)(const void *, const void *))
-{
-  int num_nodes = numLevelDirInfo(*node_first);
-  struct LevelDirInfo **sort_array;
-  struct LevelDirInfo *node = *node_first;
-  int i = 0;
-
-  if (num_nodes == 0)
-    return;
-
-  /* allocate array for sorting structure pointers */
-  sort_array = checked_calloc(num_nodes * sizeof(struct LevelDirInfo *));
-
-  /* writing structure pointers to sorting array */
-  while (i < num_nodes && node)                /* double boundary check... */
-  {
-    sort_array[i] = node;
-
-    i++;
-    node = node->next;
-  }
-
-  /* sorting the structure pointers in the sorting array */
-  qsort(sort_array, num_nodes, sizeof(struct LevelDirInfo *),
-       compare_function);
-
-  /* update the linkage of list elements with the sorted node array */
-  for (i=0; i<num_nodes - 1; i++)
-    sort_array[i]->next = sort_array[i + 1];
-  sort_array[num_nodes - 1]->next = NULL;
-
-  /* update the linkage of the main list anchor pointer */
-  *node_first = sort_array[0];
-
-  free(sort_array);
-
-  /* now recursively sort the level group structures */
-  node = *node_first;
-  while (node)
-  {
-    if (node->node_group != NULL)
-      sortLevelDirInfo(&node->node_group, compare_function);
-
-    node = node->next;
-  }
-}
-
-
-/* ------------------------------------------------------------------------- */
-/* the following is only for debugging purpose and normally not used         */
-/* ------------------------------------------------------------------------- */
-
-#define DEBUG_NUM_TIMESTAMPS   3
-
-void debug_print_timestamp(int counter_nr, char *message)
-{
-  static long counter[DEBUG_NUM_TIMESTAMPS][2];
-
-  if (counter_nr >= DEBUG_NUM_TIMESTAMPS)
-    Error(ERR_EXIT, "debugging: increase DEBUG_NUM_TIMESTAMPS in misc.c");
-
-  counter[counter_nr][0] = Counter();
-
-  if (message)
-    printf("%s %.2f seconds\n", message,
-          (float)(counter[counter_nr][0] - counter[counter_nr][1]) / 1000);
-
-  counter[counter_nr][1] = Counter();
-}
diff --git a/src/misc.h b/src/misc.h
deleted file mode 100644 (file)
index d274922..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
-*----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
-*----------------------------------------------------------*
-*  misc.h                                                  *
-***********************************************************/
-
-#ifndef MISC_H
-#define MISC_H
-
-#include "main.h"
-
-/* values for InitCounter() and Counter() */
-#define INIT_COUNTER                   0
-#define READ_COUNTER                   1
-
-/* values for InitRND() */
-#define NEW_RANDOMIZE                  -1
-
-/* values for Error() */
-#define ERR_RETURN                     0
-#define ERR_WARN                       (1 << 0)
-#define ERR_EXIT                       (1 << 1)
-#define ERR_HELP                       (1 << 2)
-#define ERR_SOUND_SERVER               (1 << 3)
-#define ERR_NETWORK_SERVER             (1 << 4)
-#define ERR_NETWORK_CLIENT             (1 << 5)
-#define ERR_FROM_SERVER                        (ERR_SOUND_SERVER | ERR_NETWORK_SERVER)
-#define ERR_EXIT_HELP                  (ERR_EXIT | ERR_HELP)
-#define ERR_EXIT_SOUND_SERVER          (ERR_EXIT | ERR_SOUND_SERVER)
-#define ERR_EXIT_NETWORK_SERVER                (ERR_EXIT | ERR_NETWORK_SERVER)
-#define ERR_EXIT_NETWORK_CLIENT                (ERR_EXIT | ERR_NETWORK_CLIENT)
-
-/* values for getFile...() and putFile...() */
-#define BYTE_ORDER_BIG_ENDIAN          0
-#define BYTE_ORDER_LITTLE_ENDIAN       1
-
-void InitCounter(void);
-unsigned long Counter(void);
-void Delay(unsigned long);
-boolean FrameReached(unsigned long *, unsigned long);
-boolean DelayReached(unsigned long *, unsigned long);
-void WaitUntilDelayReached(unsigned long *, unsigned long);
-char *int2str(int, int);
-unsigned int SimpleRND(unsigned int);
-unsigned int RND(unsigned int);
-unsigned int InitRND(long);
-char *getLoginName(void);
-char *getRealName(void);
-char *getHomeDir(void);
-char *getPath2(char *, char *);
-char *getPath3(char *, char *, char*);
-char *getStringCopy(char *);
-char *getStringToLower(char *);
-void MarkTileDirty(int, int);
-void SetBorderElement();
-void GetOptions(char **);
-void Error(int, char *, ...);
-void *checked_malloc(unsigned long);
-void *checked_calloc(unsigned long);
-short getFile16BitInteger(FILE *, int);
-void putFile16BitInteger(FILE *, short, int);
-int getFile32BitInteger(FILE *, int);
-void putFile32BitInteger(FILE *, int, int);
-void getFileChunk(FILE *, char *, int *, int);
-void putFileChunk(FILE *, char *, int, int);
-char *getKeyNameFromKeySym(KeySym);
-char *getX11KeyNameFromKeySym(KeySym);
-KeySym getKeySymFromX11KeyName(char *);
-char getCharFromKeySym(KeySym);
-char *getJoyNameFromJoySymbol(int);
-int getJoySymbolFromJoyName(char *);
-int getJoystickNrFromDeviceName(char *);
-
-struct LevelDirInfo *newLevelDirInfo();
-void pushLevelDirInfo(struct LevelDirInfo **, struct LevelDirInfo *);
-int numLevelDirInfo(struct LevelDirInfo *);
-boolean validLevelSeries(struct LevelDirInfo *);
-struct LevelDirInfo *getFirstValidLevelSeries(struct LevelDirInfo *);
-struct LevelDirInfo *getLevelDirInfoFirstGroupEntry(struct LevelDirInfo *);
-int numLevelDirInfoInGroup(struct LevelDirInfo *);
-int posLevelDirInfo(struct LevelDirInfo *);
-struct LevelDirInfo *getLevelDirInfoFromPos(struct LevelDirInfo *, int);
-struct LevelDirInfo *getLevelDirInfoFromFilename(char *);
-void dumpLevelDirInfo(struct LevelDirInfo *, int);
-void sortLevelDirInfo(struct LevelDirInfo **,
-                     int (*compare_function)(const void *, const void *));
-
-void debug_print_timestamp(int, char *);
-
-#endif /* MISC_H */
diff --git a/src/msdos.c b/src/msdos.c
deleted file mode 100644 (file)
index d9dd5e7..0000000
+++ /dev/null
@@ -1,934 +0,0 @@
-/***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
-*----------------------------------------------------------*
-*  Â©1995 Artsoft Development                               *
-*        Holger Schemel                                    *
-*        33659 Bielefeld-Senne                             *
-*        Telefon: (0521) 493245                            *
-*        eMail: aeglos@valinor.owl.de                      *
-*               aeglos@uni-paderborn.de                    *
-*               q99492@pbhrzx.uni-paderborn.de             *
-*----------------------------------------------------------*
-*  msdos.c                                                 *
-***********************************************************/
-
-#ifdef MSDOS
-
-#include "main.h"
-#include "misc.h"
-#include "tools.h"
-#include "sound.h"
-#include "files.h"
-#include "joystick.h"
-#include "image.h"
-#include "pcx.h"
-
-/* allegro driver declarations */
-DECLARE_GFX_DRIVER_LIST(GFX_DRIVER_VBEAF GFX_DRIVER_VESA2L GFX_DRIVER_VESA1)
-DECLARE_COLOR_DEPTH_LIST(COLOR_DEPTH_8)
-DECLARE_DIGI_DRIVER_LIST(DIGI_DRIVER_SB)
-DECLARE_MIDI_DRIVER_LIST()
-DECLARE_JOYSTICK_DRIVER_LIST(JOYSTICK_DRIVER_STANDARD)
-
-/* allegro global variables */
-extern volatile int key_shifts;
-extern int num_joysticks;
-extern JOYSTICK_INFO joy[];
-extern int i_love_bill;
-
-/* internal variables of msdos.c */
-static boolean keyboard_auto_repeat = TRUE;
-static int key_press_state[MAX_SCANCODES];
-static XEvent event_buffer[MAX_EVENT_BUFFER];
-static int pending_events;
-static boolean joystick_event;
-static boolean mouse_installed = FALSE;
-static int last_mouse_pos;
-static int last_mouse_b;
-static int last_joystick_state;
-static BITMAP* video_bitmap;
-
-static RGB global_colormap[MAX_COLORS];
-static int global_colormap_entries_used = 0;
-
-boolean wait_for_vsync;
-
-/*
-extern int playing_sounds;
-extern struct SoundControl playlist[MAX_SOUNDS_PLAYING];
-extern struct SoundControl emptySoundControl;
-*/
-
-static BITMAP *Read_PCX_to_AllegroBitmap(char *);
-
-static void allegro_drivers()
-{
-  int i;
-
-  for (i=0; i<MAX_EVENT_BUFFER; i++)
-    event_buffer[i].type = 0;
-
-  for (i=0; i<MAX_SCANCODES; i++)
-    key_press_state[i] = KeyReleaseMask;
-
-  last_mouse_pos = mouse_pos;
-  last_mouse_b = 0;
-
-  pending_events = 0;
-  clear_keybuf();
-
-  /* enable Windows friendly timer mode (already default under Windows) */
-  i_love_bill = TRUE;
-
-  install_keyboard();
-  install_timer();
-  if (install_mouse() > 0)
-    mouse_installed = TRUE;
-
-  last_joystick_state = 0;
-  joystick_event = FALSE;
-
-  reserve_voices(MAX_SOUNDS_PLAYING, 0);
-  if (install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL) == -1)
-    if (install_sound(DIGI_SB, MIDI_NONE, NULL) == -1)
-      sound_status = SOUND_OFF;
-}
-
-static boolean hide_mouse(Display *display, int x, int y,
-                         unsigned int width, unsigned int height)
-{
-  if (mouse_x + display->mouse_ptr->w < x || mouse_x > x + width)
-    return FALSE;
-  if (mouse_y + display->mouse_ptr->h < y || mouse_y > y + height)
-    return FALSE;
-
-  show_mouse(NULL);
-
-  return TRUE;
-}
-
-static void unhide_mouse(Display *display)
-{
-  if (mouse_installed)
-    show_mouse(video_bitmap);
-}
-
-static KeySym ScancodeToKeySym(byte scancode)
-{
-  switch(scancode)
-  {
-    case KEY_ESC:              return XK_Escape;
-    case KEY_1:                        return XK_1;
-    case KEY_2:                        return XK_2;
-    case KEY_3:                        return XK_3;
-    case KEY_4:                        return XK_4;
-    case KEY_5:                        return XK_5;
-    case KEY_6:                        return XK_6;
-    case KEY_7:                        return XK_7;
-    case KEY_8:                        return XK_8;
-    case KEY_9:                        return XK_9;
-    case KEY_0:                        return XK_0;
-    case KEY_MINUS:            return XK_minus;
-    case KEY_EQUALS:           return XK_equal;
-    case KEY_BACKSPACE:                return XK_BackSpace;
-    case KEY_TAB:              return XK_Tab;
-    case KEY_Q:                        return XK_q;
-    case KEY_W:                        return XK_w;
-    case KEY_E:                        return XK_e;
-    case KEY_R:                        return XK_r;
-    case KEY_T:                        return XK_t;
-    case KEY_Y:                        return XK_y;
-    case KEY_U:                        return XK_u;
-    case KEY_I:                        return XK_i;
-    case KEY_O:                        return XK_o;
-    case KEY_P:                        return XK_p;
-    case KEY_OPENBRACE:                return XK_braceleft;
-    case KEY_CLOSEBRACE:       return XK_braceright;
-    case KEY_ENTER:            return XK_Return;
-    case KEY_LCONTROL:         return XK_Control_L;
-    case KEY_A:                        return XK_a;
-    case KEY_S:                        return XK_s;
-    case KEY_D:                        return XK_d;
-    case KEY_F:                        return XK_f;
-    case KEY_G:                        return XK_g;
-    case KEY_H:                        return XK_h;
-    case KEY_J:                        return XK_j;
-    case KEY_K:                        return XK_k;
-    case KEY_L:                        return XK_l;
-    case KEY_COLON:            return XK_colon;
-    case KEY_QUOTE:            return XK_apostrophe;
-    case KEY_TILDE:            return XK_asciitilde;
-    case KEY_LSHIFT:           return XK_Shift_L;
-    case KEY_BACKSLASH:                return XK_backslash;
-    case KEY_Z:                        return XK_z;
-    case KEY_X:                        return XK_x;
-    case KEY_C:                        return XK_c;
-    case KEY_V:                        return XK_v;
-    case KEY_B:                        return XK_b;
-    case KEY_N:                        return XK_n;
-    case KEY_M:                        return XK_m;
-    case KEY_COMMA:            return XK_comma;
-    case KEY_STOP:             return XK_period;
-    case KEY_SLASH:            return XK_slash;
-    case KEY_RSHIFT:           return XK_Shift_R;
-    case KEY_ASTERISK:         return XK_KP_Multiply;
-    case KEY_ALT:              return XK_Alt_L;
-    case KEY_SPACE:            return XK_space;
-    case KEY_CAPSLOCK:         return XK_Caps_Lock;
-    case KEY_F1:               return XK_F1;
-    case KEY_F2:               return XK_F2;
-    case KEY_F3:               return XK_F3;
-    case KEY_F4:               return XK_F4;
-    case KEY_F5:               return XK_F5;
-    case KEY_F6:               return XK_F6;
-    case KEY_F7:               return XK_F7;
-    case KEY_F8:               return XK_F8;
-    case KEY_F9:               return XK_F9;
-    case KEY_F10:              return XK_F10;
-    case KEY_NUMLOCK:          return XK_Num_Lock;
-    case KEY_SCRLOCK:          return XK_Scroll_Lock;
-    case KEY_HOME:             return XK_Home;
-    case KEY_UP:               return XK_Up;
-    case KEY_PGUP:             return XK_Page_Up;
-    case KEY_MINUS_PAD:                return XK_KP_Subtract;
-    case KEY_LEFT:             return XK_Left;
-    case KEY_5_PAD:            return XK_KP_5;
-    case KEY_RIGHT:            return XK_Right;
-    case KEY_PLUS_PAD:         return XK_KP_Add;
-    case KEY_END:              return XK_End;
-    case KEY_DOWN:             return XK_Down;
-    case KEY_PGDN:             return XK_Page_Down;
-    case KEY_INSERT:           return XK_Insert;
-    case KEY_DEL:              return XK_Delete;
-    case KEY_PRTSCR:           return XK_Print;
-    case KEY_F11:              return XK_F11;
-    case KEY_F12:              return XK_F12;
-    case KEY_LWIN:             return XK_Meta_L;
-    case KEY_RWIN:             return XK_Meta_R;
-    case KEY_MENU:             return XK_Menu;
-    case KEY_PAD:              return XK_VoidSymbol;
-    case KEY_RCONTROL:         return XK_Control_R;
-    case KEY_ALTGR:            return XK_Alt_R;
-    case KEY_SLASH2:           return XK_KP_Divide;
-    case KEY_PAUSE:            return XK_Pause;
-
-    case NEW_KEY_BACKSLASH:    return XK_backslash;
-    case NEW_KEY_1_PAD:                return XK_KP_1;
-    case NEW_KEY_2_PAD:                return XK_KP_2;
-    case NEW_KEY_3_PAD:                return XK_KP_3;
-    case NEW_KEY_4_PAD:                return XK_KP_4;
-    case NEW_KEY_5_PAD:                return XK_KP_5;
-    case NEW_KEY_6_PAD:                return XK_KP_6;
-    case NEW_KEY_7_PAD:                return XK_KP_7;
-    case NEW_KEY_8_PAD:                return XK_KP_8;
-    case NEW_KEY_9_PAD:                return XK_KP_9;
-    case NEW_KEY_0_PAD:                return XK_KP_0;
-    case NEW_KEY_STOP_PAD:     return XK_KP_Separator;
-    case NEW_KEY_EQUALS_PAD:   return XK_KP_Equal;
-    case NEW_KEY_SLASH_PAD:    return XK_KP_Divide;
-    case NEW_KEY_ASTERISK_PAD: return XK_KP_Multiply;
-    case NEW_KEY_ENTER_PAD:    return XK_KP_Enter;
-
-    default:                   return XK_VoidSymbol;
-  }
-}
-
-void XMapWindow(Display *display, Window window)
-{
-  int x, y;
-  unsigned int width, height;
-  boolean mouse_off;
-
-  x = display->screens[display->default_screen].x;
-  y = display->screens[display->default_screen].y;
-  width = display->screens[display->default_screen].width;
-  height = display->screens[display->default_screen].height;
-
-  mouse_off = hide_mouse(display, x, y, width, height);
-  blit((BITMAP *)window, video_bitmap, 0, 0, x, y, width, height);
-
-  if (mouse_off)
-    unhide_mouse(display);
-}
-
-static unsigned long AllocColorCell(int r, int g, int b)
-{
-  byte pixel_mapping = 0;
-  int i;
-
-  r >>= 10;
-  g >>= 10;
-  b >>= 10;
-
-  /* try to use existing colors from the global colormap */
-  for (i=0; i<global_colormap_entries_used; i++)
-  {
-    if (r == global_colormap[i].r &&
-       g == global_colormap[i].g &&
-       b == global_colormap[i].b)              /* color found */
-    {
-      pixel_mapping = i;
-      break;
-    }
-  }
-
-  if (i == global_colormap_entries_used)       /* color not found */
-  {
-    if (global_colormap_entries_used < MAX_COLORS)
-      global_colormap_entries_used++;
-
-    global_colormap[i].r = r;
-    global_colormap[i].g = g;
-    global_colormap[i].b = b;
-
-    pixel_mapping = i;
-  }
-
-  return pixel_mapping;
-}
-
-Display *XOpenDisplay(char *display_name)
-{
-  Screen *screen;
-  Display *display;
-  BITMAP *mouse_bitmap = NULL;
-  char *filename;
-
-  filename = getPath3(options.ro_base_directory, GRAPHICS_DIRECTORY,
-                     MOUSE_FILENAME);
-
-  mouse_bitmap = Read_PCX_to_AllegroBitmap(filename);
-  free(filename);
-
-  if (mouse_bitmap == NULL)
-    return NULL;
-
-  screen = malloc(sizeof(Screen));
-  display = malloc(sizeof(Display));
-
-  screen[0].cmap = 0;
-  screen[0].root = 0;
-#if 0
-  screen[0].white_pixel = 0xFF;
-  screen[0].black_pixel = 0x00;
-#else
-  screen[0].white_pixel = AllocColorCell(0xFFFF, 0xFFFF, 0xFFFF);
-  screen[0].black_pixel = AllocColorCell(0x0000, 0x0000, 0x0000);
-#endif
-  screen[0].video_bitmap = NULL;
-
-  display->default_screen = 0;
-  display->screens = screen;
-  display->mouse_ptr = mouse_bitmap;
-
-  allegro_init();
-  allegro_drivers();
-  set_color_depth(8);
-
-  /* force Windows 95 to switch to fullscreen mode */
-  set_gfx_mode(GFX_AUTODETECT, 320, 200, 0, 0);
-  rest(200);
-  set_gfx_mode(GFX_AUTODETECT, XRES, YRES, 0, 0);
-
-  return display;
-}
-
-Window XCreateSimpleWindow(Display *display, Window parent, int x, int y,
-                          unsigned int width, unsigned int height,
-                          unsigned int border_width, unsigned long border,
-                          unsigned long background)
-{
-  video_bitmap = create_video_bitmap(XRES, YRES);
-  clear_to_color(video_bitmap, background);
-
-  display->screens[display->default_screen].video_bitmap = video_bitmap;
-  display->screens[display->default_screen].x = x;
-  display->screens[display->default_screen].y = y;
-  display->screens[display->default_screen].width = XRES;
-  display->screens[display->default_screen].height = YRES;
-
-  set_mouse_sprite(display->mouse_ptr);
-
-#if 0
-  set_mouse_sprite_focus(1, 1);
-#endif
-
-  set_mouse_speed(1, 1);
-  set_mouse_range(display->screens[display->default_screen].x + 1,
-                 display->screens[display->default_screen].y + 1,
-                 display->screens[display->default_screen].x + WIN_XSIZE + 1,
-                 display->screens[display->default_screen].y + WIN_YSIZE + 1);
-
-  show_video_bitmap(video_bitmap);
-
-  return (Window)video_bitmap;
-}
-
-Status XStringListToTextProperty(char **list, int count,
-                                XTextProperty *text_prop_return)
-{
-  char *string;
-
-  if (count >= 1)
-  {
-    string = malloc(strlen(list[0] + 1));
-    strcpy(string, list[0]);
-    text_prop_return->value = (unsigned char *)string;
-    return 1;
-  }
-  else
-    text_prop_return = NULL;
-
-  return 0;
-}
-
-void XFree(void *data)
-{
-  if (data)
-    free(data);
-}
-
-GC XCreateGC(Display *display, Drawable d, unsigned long value_mask,
-            XGCValues *values)
-{
-  XGCValues *gcv;
-  gcv = malloc(sizeof(XGCValues));
-  gcv->foreground = values->foreground;
-  gcv->background = values->background;
-  gcv->graphics_exposures = values->graphics_exposures;
-  gcv->clip_mask = values->clip_mask;
-  gcv->clip_x_origin = values->clip_x_origin;
-  gcv->clip_y_origin = values->clip_y_origin;
-  gcv->value_mask = value_mask;
-  return (GC)gcv;
-}
-
-void XSetClipMask(Display *display, GC gc, Pixmap pixmap)
-{
-  XGCValues *gcv = (XGCValues *)gc;
-
-  gcv->clip_mask = pixmap;
-  gcv->value_mask |= GCClipMask;
-}
-
-void XSetClipOrigin(Display *display, GC gc, int x, int y)
-{
-  XGCValues *gcv = (XGCValues *)gc;
-
-  gcv->clip_x_origin = x;
-  gcv->clip_x_origin = y;
-}
-
-void XFillRectangle(Display *display, Drawable d, GC gc, int x, int y,
-                   unsigned int width, unsigned int height)
-{
-  boolean mouse_off = FALSE;
-
-  if ((BITMAP *)d == video_bitmap)
-  {
-    x += display->screens[display->default_screen].x;
-    y += display->screens[display->default_screen].y;
-    freeze_mouse_flag = TRUE;
-    mouse_off = hide_mouse(display, x, y, width, height);
-  }
-
-  rectfill((BITMAP *)d, x, y, x + width - 1, y + height - 1,
-          ((XGCValues *)gc)->foreground);
-
-  if (mouse_off)
-    unhide_mouse(display);
-
-  freeze_mouse_flag = FALSE;
-}
-
-Pixmap XCreatePixmap(Display *display, Drawable d, unsigned int width,
-                    unsigned int height, unsigned int depth)
-{
-  BITMAP *bitmap = NULL;
-
-  if (gfx_capabilities & GFX_HW_VRAM_BLIT &&
-      width == FXSIZE && height == FYSIZE)
-    bitmap = create_video_bitmap(width, height);
-
-  if (bitmap == NULL)
-    bitmap = create_bitmap(width, height);
-
-  return (Pixmap)bitmap;
-}
-
-void XSync(Display *display, Bool discard_events)
-{
-  wait_for_vsync = TRUE;
-}
-
-inline void XCopyArea(Display *display, Drawable src, Drawable dest, GC gc,
-                     int src_x, int src_y,
-                     unsigned int width, unsigned int height,
-                     int dest_x, int dest_y)
-{
-  boolean mouse_off = FALSE;
-
-  if ((BITMAP *)src == video_bitmap)
-  {
-    src_x += display->screens[display->default_screen].x;
-    src_y += display->screens[display->default_screen].y;
-  }
-
-  if ((BITMAP *)dest == video_bitmap)
-  {
-    dest_x += display->screens[display->default_screen].x;
-    dest_y += display->screens[display->default_screen].y;
-    freeze_mouse_flag = TRUE;
-    mouse_off = hide_mouse(display, dest_x, dest_y, width, height);
-  }
-
-  if (wait_for_vsync)
-  {
-    wait_for_vsync = FALSE;
-    vsync();
-  }
-
-  if (((XGCValues *)gc)->value_mask & GCClipMask)
-    masked_blit((BITMAP *)src, (BITMAP *)dest, src_x, src_y, dest_x, dest_y,
-               width, height);
-  else
-    blit((BITMAP *)src, (BITMAP *)dest, src_x, src_y, dest_x, dest_y,
-        width, height);
-
-  if (mouse_off)
-    unhide_mouse(display);
-
-  freeze_mouse_flag = FALSE;
-}
-
-static BITMAP *Image_to_AllegroBitmap(Image *image)
-{
-  BITMAP *bitmap;
-  byte *src_ptr = image->data;
-  byte pixel_mapping[MAX_COLORS];
-  unsigned int depth = 8;
-
-#if 0
-  int i, j, x, y;
-#else
-  int i, x, y;
-#endif
-
-  /* allocate new allegro bitmap structure */
-  if ((bitmap = create_bitmap_ex(depth, image->width, image->height)) == NULL)
-  {
-    errno_pcx = PCX_NoMemory;
-    return NULL;
-  }
-
-  clear(bitmap);
-
-  /* try to use existing colors from the global colormap */
-  for (i=0; i<MAX_COLORS; i++)
-  {
-
-#if 0
-    int r, g, b;
-#endif
-
-    if (!image->rgb.color_used[i])
-      continue;
-
-
-#if 0
-    r = image->rgb.red[i] >> 10;
-    g = image->rgb.green[i] >> 10;
-    b = image->rgb.blue[i] >> 10;
-
-    for (j=0; j<global_colormap_entries_used; j++)
-    {
-      if (r == global_colormap[j].r &&
-         g == global_colormap[j].g &&
-         b == global_colormap[j].b)            /* color found */
-      {
-       pixel_mapping[i] = j;
-       break;
-      }
-    }
-
-    if (j == global_colormap_entries_used)     /* color not found */
-    {
-      if (global_colormap_entries_used < MAX_COLORS)
-       global_colormap_entries_used++;
-
-      global_colormap[j].r = r;
-      global_colormap[j].g = g;
-      global_colormap[j].b = b;
-
-      pixel_mapping[i] = j;
-    }
-#else
-    pixel_mapping[i] = AllocColorCell(image->rgb.red[i],
-                                     image->rgb.green[i],
-                                     image->rgb.blue[i]);
-#endif
-
-  }
-
-  /* copy bitmap data */
-  for (y=0; y<image->height; y++)
-    for (x=0; x<image->width; x++)
-      putpixel(bitmap, x, y, pixel_mapping[*src_ptr++]);
-
-  return bitmap;
-}
-
-static BITMAP *Read_PCX_to_AllegroBitmap(char *filename)
-{
-  BITMAP *bitmap;
-  Image *image;
-
-  /* read the graphic file in PCX format to internal image structure */
-  if ((image = Read_PCX_to_Image(filename)) == NULL)
-    return NULL;
-
-  /* convert internal image structure to allegro bitmap structure */
-  if ((bitmap = Image_to_AllegroBitmap(image)) == NULL)
-    return NULL;
-
-  set_palette(global_colormap);
-
-  return bitmap;
-}
-
-int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename,
-                      Pixmap *pixmap, Pixmap *pixmap_mask)
-{
-  BITMAP *bitmap;
-
-  if ((bitmap = Read_PCX_to_AllegroBitmap(filename)) == NULL)
-    return errno_pcx;
-
-  *pixmap = (Pixmap)bitmap;
-  *pixmap_mask = (Pixmap)bitmap;
-
-  return PCX_Success;
-}
-
-int XpmReadFileToPixmap(Display *display, Drawable d, char *filename,
-                       Pixmap *pixmap_return, Pixmap *shapemask_return,
-                       XpmAttributes *attributes)
-{
-  BITMAP *bitmap;
-
-  if ((bitmap = Read_PCX_to_AllegroBitmap(filename)) == NULL)
-    return XpmOpenFailed;
-
-  *pixmap_return = (Pixmap)bitmap;
-
-  return XpmSuccess;
-}
-
-int XReadBitmapFile(Display *display, Drawable d, char *filename,
-                   unsigned int *width_return, unsigned int *height_return,
-                   Pixmap *bitmap_return,
-                   int *x_hot_return, int *y_hot_return)
-{
-  BITMAP *bitmap;
-
-  if ((bitmap = Read_PCX_to_AllegroBitmap(filename)) == NULL)
-    return BitmapOpenFailed;
-
-  *width_return = bitmap->w;
-  *height_return = bitmap->h;
-  *x_hot_return = -1;
-  *y_hot_return = -1;
-  *bitmap_return = (Pixmap)bitmap;
-
-  return BitmapSuccess;
-}
-
-void XFreePixmap(Display *display, Pixmap pixmap)
-{
-  if (pixmap != DUMMY_MASK &&
-      (is_memory_bitmap((BITMAP *)pixmap) ||
-       is_screen_bitmap((BITMAP *)pixmap)))
-    destroy_bitmap((BITMAP *)pixmap);
-}
-
-void XFreeGC(Display *display, GC gc)
-{
-  XGCValues *gcv;
-
-  gcv = (XGCValues *)gc;
-  if (gcv)
-    free(gcv);
-}
-
-void XCloseDisplay(Display *display)
-{
-  BITMAP *bitmap = video_bitmap;
-
-  if (is_screen_bitmap(bitmap))
-    destroy_bitmap(bitmap);
-
-  if (display->screens)
-    free(display->screens);
-
-  if (display)
-    free(display);
-
-  /* return to text mode (or DOS box on Windows screen) */
-  set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
-}
-
-void XNextEvent(Display *display, XEvent *event_return)
-{
-  while (!pending_events)
-    XPending(display);
-
-  memcpy(event_return, &event_buffer[pending_events], sizeof(XEvent));
-  pending_events--;
-}
-
-static void NewKeyEvent(int key_press_state, KeySym keysym)
-{
-  XKeyEvent *xkey;
-
-  if (pending_events >= MAX_EVENT_BUFFER)
-    return;
-
-  pending_events++;
-  xkey = (XKeyEvent *)&event_buffer[pending_events];
-  xkey->type = key_press_state;
-  xkey->state = (unsigned int)keysym;
-}
-
-#define HANDLE_RAW_KB_ALL_KEYS                 0
-#define HANDLE_RAW_KB_MODIFIER_KEYS_ONLY       1
-
-static int modifier_scancode[] =
-{
-  KEY_LSHIFT,
-  KEY_RSHIFT,
-  KEY_LCONTROL,
-  KEY_RCONTROL,
-  KEY_ALT,
-  KEY_ALTGR,
-  KEY_LWIN,
-  KEY_RWIN,
-  KEY_CAPSLOCK,
-  KEY_NUMLOCK,
-  KEY_SCRLOCK,
-  -1
-};
-
-static void HandleKeyboardRaw(int mode)
-{
-  int i;
-
-  for (i=0; i<MAX_SCANCODES; i++)
-  {
-    int scancode, new_state, event_type;
-    char key_pressed;
-
-    if (mode == HANDLE_RAW_KB_MODIFIER_KEYS_ONLY)
-    {
-      if ((scancode = modifier_scancode[i]) == -1)
-       return;
-    }
-    else
-      scancode = i;
-
-    key_pressed = key[scancode];
-    new_state = (key_pressed ? KeyPressMask : KeyReleaseMask);
-    event_type = (key_pressed ? KeyPress : KeyRelease);
-
-    if (key_press_state[i] == new_state)       /* state not changed */
-      continue;
-
-    key_press_state[i] = new_state;
-
-    NewKeyEvent(event_type, ScancodeToKeySym(scancode));
-  }
-}
-
-static void HandleKeyboardEvent()
-{
-  if (keypressed())
-  {
-    int key_info = readkey();
-    int scancode = (key_info >> 8);
-    int ascii = (key_info & 0xff);
-    KeySym keysym = ScancodeToKeySym(scancode);
-
-    if (scancode == KEY_PAD)
-    {
-      /* keys on the numeric keypad return just scancode 'KEY_PAD'
-        for some reason, so we must handle them separately */
-
-      if (ascii >= '0' && ascii <= '9')
-       keysym = XK_KP_0 + (KeySym)(ascii - '0');
-      else if (ascii == '.')
-       keysym = XK_KP_Separator;
-    }
-    else if (ascii >= ' ' && ascii <= 'Z')
-      keysym = XK_space + (KeySym)(ascii - ' ');
-    else if (ascii == '^')
-      keysym = XK_asciicircum;
-    else if (ascii == '_')
-      keysym = XK_underscore;
-    else if (ascii == 'Ä')
-      keysym = XK_Adiaeresis;
-    else if (ascii == 'Ö')
-      keysym = XK_Odiaeresis;
-    else if (ascii == 'Ãœ')
-      keysym = XK_Udiaeresis;
-    else if (ascii == 'ä')
-      keysym = XK_adiaeresis;
-    else if (ascii == 'ö')
-      keysym = XK_odiaeresis;
-    else if (ascii == 'ü')
-      keysym = XK_udiaeresis;
-    else if (ascii == 'ß')
-      keysym = XK_ssharp;
-
-    NewKeyEvent(KeyPress, keysym);
-  }
-  else if (key_shifts & (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG))
-  {
-    /* the allegro function keypressed() does not give us single pressed
-       modifier keys, so we must detect them with the internal global
-       allegro variable 'key_shifts' and then handle them separately */
-
-    HandleKeyboardRaw(HANDLE_RAW_KB_MODIFIER_KEYS_ONLY);
-  }
-}
-
-int XPending(Display *display)
-{
-  XButtonEvent *xbutton;
-  XMotionEvent *xmotion;
-  int i;
-
-  /* When using 'HandleKeyboardRaw()', keyboard input is also stored in
-     the allegro keyboard input buffer and would be available a second
-     time by calling 'HandleKeyboardEvent()'. To avoid double keyboard
-     events, the allegro function 'clear_keybuf()' must be called each
-     time when switching from calling 'HandleKeyboardRaw()' to calling
-     'HandleKeyboardEvent()' to get keyboard input, which is actually
-     done by 'XAutoRepeatOn()' which sets keyboard_auto_repeat to TRUE. */
-
-  /* keyboard event */
-  if (keyboard_auto_repeat)
-    HandleKeyboardEvent();
-  else
-    HandleKeyboardRaw(HANDLE_RAW_KB_ALL_KEYS);
-
-  /* mouse motion event */
-  if (mouse_pos != last_mouse_pos)
-  {
-    last_mouse_pos = mouse_pos;
-    pending_events++;
-    xmotion = (XMotionEvent *)&event_buffer[pending_events];
-    xmotion->type = MotionNotify;
-    xmotion->x = mouse_x - display->screens[display->default_screen].x;
-    xmotion->y = mouse_y - display->screens[display->default_screen].y;
-  }
-
-  /* mouse button event */
-  if (mouse_b != last_mouse_b)
-  {
-    for (i=0; i<3; i++)                /* check all three mouse buttons */
-    {
-      int bitmask = (1 << i);
-
-      if ((last_mouse_b & bitmask) != (mouse_b & bitmask))
-      {
-       int mapping[3] = { 1, 3, 2 };
-
-       pending_events++;
-        xbutton = (XButtonEvent *)&event_buffer[pending_events];
-        xbutton->type = (mouse_b & bitmask ? ButtonPress : ButtonRelease);
-        xbutton->button = mapping[i];
-       xbutton->x = mouse_x - display->screens[display->default_screen].x;
-       xbutton->y = mouse_y - display->screens[display->default_screen].y;
-      }
-    }
-    last_mouse_b = mouse_b;
-  }
-
-  return pending_events;
-}
-
-KeySym XLookupKeysym(XKeyEvent *key_event, int index)
-{
-  return key_event->state;
-}
-
-int XLookupString(XKeyEvent *key_event, char *buffer, int buffer_size,
-                 KeySym *key, XComposeStatus *compose)
-{
-  *key = key_event->state;
-  return 0;
-}
-
-void XSetForeground(Display *display, GC gc, unsigned long pixel)
-{
-  XGCValues *gcv = (XGCValues *)gc;
-
-  gcv->foreground = pixel;
-}
-
-void XDrawLine(Display *display, Drawable d, GC gc,
-              int x1, int y1, int x2, int y2)
-{
-  XGCValues *gcv = (XGCValues *)gc;
-  boolean mouse_off = FALSE;
-
-  if ((BITMAP *)d == video_bitmap)
-  {
-    x1 += display->screens[display->default_screen].x;
-    y1 += display->screens[display->default_screen].y;
-    x2 += display->screens[display->default_screen].x;
-    y2 += display->screens[display->default_screen].y;
-    freeze_mouse_flag = TRUE;
-    mouse_off = hide_mouse(display, MIN(x1, x2), MIN(y1, y2),
-                          MAX(x1, x2) - MIN(x1, x2),
-                          MAX(y1, y2) - MIN(y1, y2));
-  }
-
-  line((BITMAP *)d, x1, y1, x2, y2, gcv->foreground);
-
-  if (mouse_off)
-    unhide_mouse(display);
-
-  freeze_mouse_flag = FALSE;
-}
-
-void XDestroyImage(XImage *ximage)
-{
-}
-
-Bool XQueryPointer(Display *display, Window window,
-                  Window *root, Window *child, int *root_x, int *root_y,
-                  int *win_x, int *win_y, unsigned int *mask)
-{
-  *win_x = mouse_x - display->screens[display->default_screen].x;
-  *win_y = mouse_y - display->screens[display->default_screen].y;
-
-  return True;
-}
-
-void XAutoRepeatOn(Display *display)
-{
-  keyboard_auto_repeat = TRUE;
-  clear_keybuf();
-}
-
-void XAutoRepeatOff(Display *display)
-{
-  keyboard_auto_repeat = FALSE;
-}
-
-void NetworkServer(int port, int serveronly)
-{
-  Error(ERR_WARN, "networking not supported in DOS version");
-}
-
-#endif /* MSDOS */
diff --git a/src/msdos.h b/src/msdos.h
deleted file mode 100644 (file)
index 508bb84..0000000
+++ /dev/null
@@ -1,716 +0,0 @@
-/***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
-*----------------------------------------------------------*
-*  Â©1995 Artsoft Development                               *
-*        Holger Schemel                                    *
-*        33659 Bielefeld-Senne                             *
-*        Telefon: (0521) 493245                            *
-*        eMail: aeglos@valinor.owl.de                      *
-*               aeglos@uni-paderborn.de                    *
-*               q99492@pbhrzx.uni-paderborn.de             *
-*----------------------------------------------------------*
-*  msdos.h                                                 *
-***********************************************************/
-
-#include <allegro.h>
-#include <time.h>
-
-/* allegro defines TRUE as -1 */
-#ifdef TRUE
-#undef TRUE
-#undef FALSE
-#endif
-
-#define TRUE   1
-#define FALSE  0
-
-#define XRES   800
-#define YRES   600
-
-/* additional Allegro keyboard mapping */
-
-/* The following are all undefined in Allegro */
-#define NEW_KEY_BACKSLASH      86
-#define NEW_KEY_1_PAD          101
-#define NEW_KEY_2_PAD          102
-#define NEW_KEY_3_PAD          103
-#define NEW_KEY_4_PAD          104
-#define NEW_KEY_5_PAD          105
-#define NEW_KEY_6_PAD          106
-#define NEW_KEY_7_PAD          107
-#define NEW_KEY_8_PAD          108
-#define NEW_KEY_9_PAD          109
-#define NEW_KEY_0_PAD          110
-#define NEW_KEY_STOP_PAD       111
-#define NEW_KEY_EQUALS_PAD     112
-#define NEW_KEY_SLASH_PAD      113
-#define NEW_KEY_ASTERISK_PAD   114
-#define NEW_KEY_ENTER_PAD      115
-
-/* X11 keyboard mapping (from 'keysymdef.h') */
-
-#define XK_VoidSymbol          0xFFFFFF        /* void symbol */
-
-/*
- * TTY Functions, cleverly chosen to map to ascii, for convenience of
- * programming, but could have been arbitrary (at the cost of lookup
- * tables in client code.
- */
-
-#define XK_BackSpace           0xFF08  /* back space, back char */
-#define XK_Tab                 0xFF09
-#define XK_Linefeed            0xFF0A  /* Linefeed, LF */
-#define XK_Clear               0xFF0B
-#define XK_Return              0xFF0D  /* Return, enter */
-#define XK_Pause               0xFF13  /* Pause, hold */
-#define XK_Scroll_Lock         0xFF14
-#define XK_Sys_Req             0xFF15
-#define XK_Escape              0xFF1B
-#define XK_Delete              0xFFFF  /* Delete, rubout */
-
-/* International & multi-key character composition */
-
-#define XK_Multi_key           0xFF20  /* Multi-key character compose */
-#define XK_SingleCandidate     0xFF3C
-#define XK_MultipleCandidate   0xFF3D
-#define XK_PreviousCandidate   0xFF3E
-
-/* Cursor control & motion */
-
-#define XK_Home                        0xFF50
-#define XK_Left                        0xFF51  /* Move left, left arrow */
-#define XK_Up                  0xFF52  /* Move up, up arrow */
-#define XK_Right               0xFF53  /* Move right, right arrow */
-#define XK_Down                        0xFF54  /* Move down, down arrow */
-#define XK_Prior               0xFF55  /* Prior, previous */
-#define XK_Page_Up             0xFF55
-#define XK_Next                        0xFF56  /* Next */
-#define XK_Page_Down           0xFF56
-#define XK_End                 0xFF57  /* EOL */
-#define XK_Begin               0xFF58  /* BOL */
-
-/* Misc Functions */
-
-#define XK_Select              0xFF60  /* Select, mark */
-#define XK_Print               0xFF61
-#define XK_Execute             0xFF62  /* Execute, run, do */
-#define XK_Insert              0xFF63  /* Insert, insert here */
-#define XK_Undo                        0xFF65  /* Undo, oops */
-#define XK_Redo                        0xFF66  /* redo, again */
-#define XK_Menu                        0xFF67
-#define XK_Find                        0xFF68  /* Find, search */
-#define XK_Cancel              0xFF69  /* Cancel, stop, abort, exit */
-#define XK_Help                        0xFF6A  /* Help */
-#define XK_Break               0xFF6B
-#define XK_Mode_switch         0xFF7E  /* Character set switch */
-#define XK_script_switch        0xFF7E  /* Alias for mode_switch */
-#define XK_Num_Lock            0xFF7F
-
-/* Keypad Functions, keypad numbers cleverly chosen to map to ascii */
-
-#define XK_KP_Space            0xFF80  /* space */
-#define XK_KP_Tab              0xFF89
-#define XK_KP_Enter            0xFF8D  /* enter */
-#define XK_KP_F1               0xFF91  /* PF1, KP_A, ... */
-#define XK_KP_F2               0xFF92
-#define XK_KP_F3               0xFF93
-#define XK_KP_F4               0xFF94
-#define XK_KP_Home             0xFF95
-#define XK_KP_Left             0xFF96
-#define XK_KP_Up               0xFF97
-#define XK_KP_Right            0xFF98
-#define XK_KP_Down             0xFF99
-#define XK_KP_Prior            0xFF9A
-#define XK_KP_Page_Up          0xFF9A
-#define XK_KP_Next             0xFF9B
-#define XK_KP_Page_Down                0xFF9B
-#define XK_KP_End              0xFF9C
-#define XK_KP_Begin            0xFF9D
-#define XK_KP_Insert           0xFF9E
-#define XK_KP_Delete           0xFF9F
-#define XK_KP_Equal            0xFFBD  /* equals */
-#define XK_KP_Multiply         0xFFAA
-#define XK_KP_Add              0xFFAB
-#define XK_KP_Separator                0xFFAC  /* separator, often comma */
-#define XK_KP_Subtract         0xFFAD
-#define XK_KP_Decimal          0xFFAE
-#define XK_KP_Divide           0xFFAF
-
-#define XK_KP_0                        0xFFB0
-#define XK_KP_1                        0xFFB1
-#define XK_KP_2                        0xFFB2
-#define XK_KP_3                        0xFFB3
-#define XK_KP_4                        0xFFB4
-#define XK_KP_5                        0xFFB5
-#define XK_KP_6                        0xFFB6
-#define XK_KP_7                        0xFFB7
-#define XK_KP_8                        0xFFB8
-#define XK_KP_9                        0xFFB9
-
-/*
- * Auxilliary Functions; note the duplicate definitions for left and right
- * function keys;  Sun keyboards and a few other manufactures have such
- * function key groups on the left and/or right sides of the keyboard.
- * We've not found a keyboard with more than 35 function keys total.
- */
-
-#define XK_F1                  0xFFBE
-#define XK_F2                  0xFFBF
-#define XK_F3                  0xFFC0
-#define XK_F4                  0xFFC1
-#define XK_F5                  0xFFC2
-#define XK_F6                  0xFFC3
-#define XK_F7                  0xFFC4
-#define XK_F8                  0xFFC5
-#define XK_F9                  0xFFC6
-#define XK_F10                 0xFFC7
-#define XK_F11                 0xFFC8
-#define XK_L1                  0xFFC8
-#define XK_F12                 0xFFC9
-#define XK_L2                  0xFFC9
-#define XK_F13                 0xFFCA
-#define XK_L3                  0xFFCA
-#define XK_F14                 0xFFCB
-#define XK_L4                  0xFFCB
-#define XK_F15                 0xFFCC
-#define XK_L5                  0xFFCC
-#define XK_F16                 0xFFCD
-#define XK_L6                  0xFFCD
-#define XK_F17                 0xFFCE
-#define XK_L7                  0xFFCE
-#define XK_F18                 0xFFCF
-#define XK_L8                  0xFFCF
-#define XK_F19                 0xFFD0
-#define XK_L9                  0xFFD0
-#define XK_F20                 0xFFD1
-#define XK_L10                 0xFFD1
-#define XK_F21                 0xFFD2
-#define XK_R1                  0xFFD2
-#define XK_F22                 0xFFD3
-#define XK_R2                  0xFFD3
-#define XK_F23                 0xFFD4
-#define XK_R3                  0xFFD4
-#define XK_F24                 0xFFD5
-#define XK_R4                  0xFFD5
-#define XK_F25                 0xFFD6
-#define XK_R5                  0xFFD6
-#define XK_F26                 0xFFD7
-#define XK_R6                  0xFFD7
-#define XK_F27                 0xFFD8
-#define XK_R7                  0xFFD8
-#define XK_F28                 0xFFD9
-#define XK_R8                  0xFFD9
-#define XK_F29                 0xFFDA
-#define XK_R9                  0xFFDA
-#define XK_F30                 0xFFDB
-#define XK_R10                 0xFFDB
-#define XK_F31                 0xFFDC
-#define XK_R11                 0xFFDC
-#define XK_F32                 0xFFDD
-#define XK_R12                 0xFFDD
-#define XK_F33                 0xFFDE
-#define XK_R13                 0xFFDE
-#define XK_F34                 0xFFDF
-#define XK_R14                 0xFFDF
-#define XK_F35                 0xFFE0
-#define XK_R15                 0xFFE0
-
-/* Modifiers */
-
-#define XK_Shift_L             0xFFE1  /* Left shift */
-#define XK_Shift_R             0xFFE2  /* Right shift */
-#define XK_Control_L           0xFFE3  /* Left control */
-#define XK_Control_R           0xFFE4  /* Right control */
-#define XK_Caps_Lock           0xFFE5  /* Caps lock */
-#define XK_Shift_Lock          0xFFE6  /* Shift lock */
-
-#define XK_Meta_L              0xFFE7  /* Left meta */
-#define XK_Meta_R              0xFFE8  /* Right meta */
-#define XK_Alt_L               0xFFE9  /* Left alt */
-#define XK_Alt_R               0xFFEA  /* Right alt */
-#define XK_Super_L             0xFFEB  /* Left super */
-#define XK_Super_R             0xFFEC  /* Right super */
-#define XK_Hyper_L             0xFFED  /* Left hyper */
-#define XK_Hyper_R             0xFFEE  /* Right hyper */
-
-/*
- *  Latin 1
- *  Byte 3 = 0
- */
-
-#define XK_space               0x020
-#define XK_exclam              0x021
-#define XK_quotedbl            0x022
-#define XK_numbersign          0x023
-#define XK_dollar              0x024
-#define XK_percent             0x025
-#define XK_ampersand           0x026
-#define XK_apostrophe          0x027
-#define XK_quoteright          0x027   /* deprecated */
-#define XK_parenleft           0x028
-#define XK_parenright          0x029
-#define XK_asterisk            0x02a
-#define XK_plus                0x02b
-#define XK_comma               0x02c
-#define XK_minus               0x02d
-#define XK_period              0x02e
-#define XK_slash               0x02f
-#define XK_0                   0x030
-#define XK_1                   0x031
-#define XK_2                   0x032
-#define XK_3                   0x033
-#define XK_4                   0x034
-#define XK_5                   0x035
-#define XK_6                   0x036
-#define XK_7                   0x037
-#define XK_8                   0x038
-#define XK_9                   0x039
-#define XK_colon               0x03a
-#define XK_semicolon           0x03b
-#define XK_less                0x03c
-#define XK_equal               0x03d
-#define XK_greater             0x03e
-#define XK_question            0x03f
-#define XK_at                  0x040
-#define XK_A                   0x041
-#define XK_B                   0x042
-#define XK_C                   0x043
-#define XK_D                   0x044
-#define XK_E                   0x045
-#define XK_F                   0x046
-#define XK_G                   0x047
-#define XK_H                   0x048
-#define XK_I                   0x049
-#define XK_J                   0x04a
-#define XK_K                   0x04b
-#define XK_L                   0x04c
-#define XK_M                   0x04d
-#define XK_N                   0x04e
-#define XK_O                   0x04f
-#define XK_P                   0x050
-#define XK_Q                   0x051
-#define XK_R                   0x052
-#define XK_S                   0x053
-#define XK_T                   0x054
-#define XK_U                   0x055
-#define XK_V                   0x056
-#define XK_W                   0x057
-#define XK_X                   0x058
-#define XK_Y                   0x059
-#define XK_Z                   0x05a
-#define XK_bracketleft         0x05b
-#define XK_backslash           0x05c
-#define XK_bracketright        0x05d
-#define XK_asciicircum         0x05e
-#define XK_underscore          0x05f
-#define XK_grave               0x060
-#define XK_quoteleft           0x060   /* deprecated */
-#define XK_a                   0x061
-#define XK_b                   0x062
-#define XK_c                   0x063
-#define XK_d                   0x064
-#define XK_e                   0x065
-#define XK_f                   0x066
-#define XK_g                   0x067
-#define XK_h                   0x068
-#define XK_i                   0x069
-#define XK_j                   0x06a
-#define XK_k                   0x06b
-#define XK_l                   0x06c
-#define XK_m                   0x06d
-#define XK_n                   0x06e
-#define XK_o                   0x06f
-#define XK_p                   0x070
-#define XK_q                   0x071
-#define XK_r                   0x072
-#define XK_s                   0x073
-#define XK_t                   0x074
-#define XK_u                   0x075
-#define XK_v                   0x076
-#define XK_w                   0x077
-#define XK_x                   0x078
-#define XK_y                   0x079
-#define XK_z                   0x07a
-#define XK_braceleft           0x07b
-#define XK_bar                 0x07c
-#define XK_braceright          0x07d
-#define XK_asciitilde          0x07e
-
-#define XK_nobreakspace        0x0a0
-#define XK_exclamdown          0x0a1
-#define XK_cent                       0x0a2
-#define XK_sterling            0x0a3
-#define XK_currency            0x0a4
-#define XK_yen                 0x0a5
-#define XK_brokenbar           0x0a6
-#define XK_section             0x0a7
-#define XK_diaeresis           0x0a8
-#define XK_copyright           0x0a9
-#define XK_ordfeminine         0x0aa
-#define XK_guillemotleft       0x0ab   /* left angle quotation mark */
-#define XK_notsign             0x0ac
-#define XK_hyphen              0x0ad
-#define XK_registered          0x0ae
-#define XK_macron              0x0af
-#define XK_degree              0x0b0
-#define XK_plusminus           0x0b1
-#define XK_twosuperior         0x0b2
-#define XK_threesuperior       0x0b3
-#define XK_acute               0x0b4
-#define XK_mu                  0x0b5
-#define XK_paragraph           0x0b6
-#define XK_periodcentered      0x0b7
-#define XK_cedilla             0x0b8
-#define XK_onesuperior         0x0b9
-#define XK_masculine           0x0ba
-#define XK_guillemotright      0x0bb   /* right angle quotation mark */
-#define XK_onequarter          0x0bc
-#define XK_onehalf             0x0bd
-#define XK_threequarters       0x0be
-#define XK_questiondown        0x0bf
-#define XK_Agrave              0x0c0
-#define XK_Aacute              0x0c1
-#define XK_Acircumflex         0x0c2
-#define XK_Atilde              0x0c3
-#define XK_Adiaeresis          0x0c4
-#define XK_Aring               0x0c5
-#define XK_AE                  0x0c6
-#define XK_Ccedilla            0x0c7
-#define XK_Egrave              0x0c8
-#define XK_Eacute              0x0c9
-#define XK_Ecircumflex         0x0ca
-#define XK_Ediaeresis          0x0cb
-#define XK_Igrave              0x0cc
-#define XK_Iacute              0x0cd
-#define XK_Icircumflex         0x0ce
-#define XK_Idiaeresis          0x0cf
-#define XK_ETH                 0x0d0
-#define XK_Eth                 0x0d0   /* deprecated */
-#define XK_Ntilde              0x0d1
-#define XK_Ograve              0x0d2
-#define XK_Oacute              0x0d3
-#define XK_Ocircumflex         0x0d4
-#define XK_Otilde              0x0d5
-#define XK_Odiaeresis          0x0d6
-#define XK_multiply            0x0d7
-#define XK_Ooblique            0x0d8
-#define XK_Ugrave              0x0d9
-#define XK_Uacute              0x0da
-#define XK_Ucircumflex         0x0db
-#define XK_Udiaeresis          0x0dc
-#define XK_Yacute              0x0dd
-#define XK_THORN               0x0de
-#define XK_Thorn               0x0de   /* deprecated */
-#define XK_ssharp              0x0df
-#define XK_agrave              0x0e0
-#define XK_aacute              0x0e1
-#define XK_acircumflex         0x0e2
-#define XK_atilde              0x0e3
-#define XK_adiaeresis          0x0e4
-#define XK_aring               0x0e5
-#define XK_ae                  0x0e6
-#define XK_ccedilla            0x0e7
-#define XK_egrave              0x0e8
-#define XK_eacute              0x0e9
-#define XK_ecircumflex         0x0ea
-#define XK_ediaeresis          0x0eb
-#define XK_igrave              0x0ec
-#define XK_iacute              0x0ed
-#define XK_icircumflex         0x0ee
-#define XK_idiaeresis          0x0ef
-#define XK_eth                 0x0f0
-#define XK_ntilde              0x0f1
-#define XK_ograve              0x0f2
-#define XK_oacute              0x0f3
-#define XK_ocircumflex         0x0f4
-#define XK_otilde              0x0f5
-#define XK_odiaeresis          0x0f6
-#define XK_division            0x0f7
-#define XK_oslash              0x0f8
-#define XK_ugrave              0x0f9
-#define XK_uacute              0x0fa
-#define XK_ucircumflex         0x0fb
-#define XK_udiaeresis          0x0fc
-#define XK_yacute              0x0fd
-#define XK_thorn               0x0fe
-#define XK_ydiaeresis          0x0ff
-
-/* end of X11 keyboard mapping */
-
-#define MOUSE_FILENAME         "mouse.pcx"
-#define JOYSTICK_FILENAME      "joystick.cnf"
-
-#define screen myscreen
-
-#define XFlush(a)
-#define XGetImage(a,b,c,d,e,f,g,h)             ((XImage *) NULL)
-#define XDisplayName(a)                                ((char *) NULL)
-#define XFreeColors(a,b,c,d,e)
-#define XpmFreeAttributes(a)
-#define XSelectInput(a,b,c)
-#define XDefaultDepth(a,b)                     (8)
-#define XSetWMProperties(a,b,c,d,e,f,g,h,i)
-
-#define MAX_EVENT_BUFFER       256
-#define MAX_SCANCODES          128
-
-#define True                   1
-#define False                  0
-#define None                   0L
-
-#define DUMMY_FILE             ((void *) -1)
-#define DUMMY_MASK             (-1)
-
-#define KeyPressMask           (1L << 0)  
-#define KeyReleaseMask         (1L << 1)  
-#define ButtonPressMask                (1L << 2)  
-#define ButtonReleaseMask      (1L << 3)  
-#define ButtonMotionMask       (1L << 13) 
-#define ExposureMask           (1L << 15) 
-#define StructureNotifyMask    (1L << 17) 
-#define FocusChangeMask                (1L << 21) 
-
-#define KeyPress               2
-#define KeyRelease             3
-#define ButtonPress            4
-#define ButtonRelease          5
-#define MotionNotify           6
-#define FocusIn                        9
-#define FocusOut               10
-#define Expose                 12
-#define UnmapNotify            18
-#define MapNotify              19
-#define ClientMessage          33
-
-#define GCForeground            (1L << 2)
-#define GCBackground            (1L << 3)
-#define GCGraphicsExposures     (1L << 16)
-#define GCClipMask             (1L << 19)
-
-#define NormalState    1       /* most applications want to start this way */
-#define InputHint              (1L << 0)
-#define StateHint              (1L << 1)
-#define IconPixmapHint         (1L << 2)
-#define IconMaskHint           (1L << 5)
-#define PSize                  (1L << 3) /* program specified size */
-#define PMinSize               (1L << 4) /* program specified minimum size */
-#define PMaxSize               (1L << 5) /* program specified maximum size */
-
-#define XpmSuccess              0
-#define XpmOpenFailed          -1
-#define XpmFileInvalid         -2
-#define XpmNoMemory            -3
-#define XpmColorFailed         -4
-
-#define XpmCloseness           (1L << 12)
-
-#define PCX_Success             0
-#define PCX_OpenFailed         -1
-#define PCX_ReadFailed         -2
-#define        PCX_FileInvalid         -3
-#define PCX_NoMemory           -4
-#define PCX_ColorFailed                -5
-
-#define BitmapSuccess          0
-#define BitmapOpenFailed       1
-#define BitmapFileInvalid      2
-#define BitmapNoMemory         3
-
-#define ZPixmap                        2       /* depth == drawable depth */
-
-#define DefaultScreen(dpy)       (((_XPrivDisplay)dpy)->default_screen)
-#define DefaultColormap(dpy, scr) (ScreenOfDisplay(dpy,scr)->cmap)
-#define ScreenOfDisplay(dpy, scr) (&((_XPrivDisplay)dpy)->screens[scr])
-#define BlackPixel(dpy, scr)     (ScreenOfDisplay(dpy,scr)->black_pixel)
-#define WhitePixel(dpy, scr)     (ScreenOfDisplay(dpy,scr)->white_pixel)
-#define RootWindow(dpy, scr)     (ScreenOfDisplay(dpy,scr)->root)
-#define AllPlanes                ((unsigned long)~0L)
-
-#define DefaultVisual(dpy, scr)          (NULL)
-#define DefaultDepth(dpy, scr)   (NULL)
-#define XDisplayWidth(dpy, scr)          (XRES)
-#define XDisplayHeight(dpy, scr)  (YRES)
-
-#define XGetPixel(ximage, x, y) \
-        ((*((ximage)->f.get_pixel))((ximage), (x), (y)))
-
-typedef unsigned long Pixel;   /* Index into colormap */
-typedef unsigned long XID;
-typedef XID Window;
-typedef XID Drawable;
-typedef XID Pixmap;
-typedef XID Colormap;
-typedef XID KeySym;
-typedef XID GContext;
-typedef struct _XDisplay Display;
-typedef long Visual;
-typedef long XVisualInfo;
-typedef long Atom;
-typedef int Status;
-typedef int Bool;
-typedef int XComposeStatus;    /* we don't need the real type */
-
-typedef struct _XGC
-{
-  GContext gid;                        /* protocol ID for graphics context */
-} *GC;
-
-typedef struct
-{
-  Colormap cmap;               /* default color map */
-  Window root;                 /* root window id */
-  unsigned long white_pixel;   /* white pixel value */
-  unsigned long black_pixel;   /* black pixel value */
-  int x;
-  int y;
-  unsigned int width;
-  unsigned int height;
-  BITMAP *video_bitmap;
-} Screen;
-
-typedef struct _XDisplay
-{
-  int default_screen;          /* default screen for operations */
-  Screen *screens;             /* pointer to list of screens */
-  BITMAP *mouse_ptr;
-} *_XPrivDisplay;
-
-typedef struct _XImage
-{
-  struct funcs
-  {
-    unsigned long (*get_pixel) (struct _XImage *, int, int);
-  } f;
-} XImage;
-
-typedef struct
-{
-  long flags;          /* marks which fields in this structure are defined */
-  int width, height;   /* should set so old wm's don't mess up */
-  int min_width, min_height;
-  int max_width, max_height;
-} XSizeHints;
-
-typedef struct
-{
-  long flags;          /* marks which fields in this structure are defined */
-  Bool input;          /* does this application rely on the window manager to
-                          get keyboard input? */
-  int initial_state;   /* see below */
-  Pixmap icon_pixmap;  /* pixmap to be used as icon */
-  Pixmap icon_mask;    /* icon mask bitmap */
-} XWMHints;
-
-typedef struct
-{
-  char *res_name;
-  char *res_class;
-} XClassHint;
-
-typedef struct
-{
-  unsigned char *value;                /* same as Property routines */
-} XTextProperty;
-
-typedef struct
-{
-  unsigned long foreground;    /* foreground pixel */
-  unsigned long background;    /* background pixel */
-  Bool graphics_exposures;     /* boolean, should exposures be generated */
-  Pixmap clip_mask;            /* bitmap clipping; other calls for rects */
-  int clip_x_origin;           /* x origin for clipping */
-  int clip_y_origin;           /* y origin for clipping */
-  unsigned long value_mask;
-} XGCValues;
-
-typedef struct
-{
-  unsigned long valuemask;     /* specifies which attributes are */
-  unsigned int closeness;      /* allowable RGB deviation */
-  Pixel *pixels;               /* list of used color pixels */
-  unsigned int npixels;                /* number of used pixels */
-} XpmAttributes;
-
-typedef struct
-{
-  int type;
-  int x, y;
-  int width, height;
-} XExposeEvent;
-
-typedef struct
-{
-  int type;                    /* of event */
-  int x, y;                    /* pointer x, y coordinates in event window */
-  unsigned int button;         /* detail */
-} XButtonEvent;
-
-typedef struct
-{
-  int type;
-  int x, y;                    /* pointer x, y coordinates in event window */
-} XMotionEvent;
-
-typedef struct
-{
-  int type;                    /* of event */
-  unsigned int state;          /* key or button mask */
-} XKeyEvent;
-
-typedef struct
-{
-  int type;                    /* FocusIn or FocusOut */
-} XFocusChangeEvent;
-
-typedef struct
-{
-  int type;                    /* ClientMessage */
-} XClientMessageEvent;
-
-typedef union _XEvent
-{
-  int type;                    /* must not be changed; first element */
-  XExposeEvent xexpose;
-  XButtonEvent xbutton;
-  XMotionEvent xmotion;
-  XKeyEvent xkey;
-} XEvent;
-
-unsigned char get_ascii(KeySym);
-void XMapWindow(Display *, Window);
-Display *XOpenDisplay(char *);
-Window XCreateSimpleWindow(Display *, Window, int, int,
-                          unsigned int, unsigned int, unsigned int,
-                          unsigned long, unsigned long);
-Status XStringListToTextProperty(char **, int, XTextProperty *);
-void XFree(void *);
-GC XCreateGC(Display *, Drawable, unsigned long, XGCValues *);
-void XSetClipMask(Display *, GC, Pixmap);
-void XSetClipOrigin(Display *, GC, int, int);
-void XFillRectangle(Display *, Drawable, GC, int, int,
-                   unsigned int, unsigned int);
-Pixmap XCreatePixmap(Display *, Drawable, unsigned int, unsigned int,
-                    unsigned int);
-void XSync(Display *, Bool);
-inline void XCopyArea(Display *, Drawable, Drawable, GC, int, int,
-                     unsigned int, unsigned int, int, int);
-int Read_PCX_to_Pixmap(Display *, Window, GC, char *, Pixmap *, Pixmap *);
-int XpmReadFileToPixmap(Display *, Drawable, char *, Pixmap *, Pixmap *,
-                       XpmAttributes *);
-int XReadBitmapFile(Display *, Drawable, char *,
-                   unsigned int *, unsigned int *, Pixmap *, int *, int *);
-void XFreePixmap(Display *, Pixmap);
-void XFreeGC(Display *, GC);
-void XCloseDisplay(Display *);
-void XNextEvent(Display *, XEvent *);
-int XPending(Display *);
-KeySym XLookupKeysym(XKeyEvent *, int);
-int XLookupString(XKeyEvent *, char *, int, KeySym *, XComposeStatus *);
-void XSetForeground(Display *, GC, unsigned long);
-void XDrawLine(Display *, Drawable, GC, int, int, int, int);
-void XDestroyImage(XImage *);
-Bool XQueryPointer(Display *, Window, Window *, Window *, int *, int *,
-                  int *, int *, unsigned int *);
-void XAutoRepeatOn(Display *);
-void XAutoRepeatOff(Display *);
-void NetworkServer(int, int);
index a9ffa6a74ab9fdf8353d14e523b42fe874d308c0..e6e9b10410dc1ee0f48e4aa2de53d1a3ce0c00c1 100644 (file)
@@ -1,19 +1,20 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  network.c                                               *
+* network.c                                                *
 ***********************************************************/
 
-#ifndef MSDOS
+#include "libgame/libgame.h"
+
+#if defined(PLATFORM_UNIX)
 
-#include <unistd.h>
 #include <fcntl.h>
 #include <sys/time.h>
 #include <signal.h>
 #include <arpa/inet.h>
 #include <netdb.h>
 
+#if 0
+#include "libgame/libgame.h"
+#endif
+
 #include "netserv.h"
-#include "misc.h"
 
 static int clients = 0;
 static int onceonly = 0;
@@ -662,4 +666,4 @@ void NetworkServer(int port, int serveronly)
   }
 }
 
-#endif /* !MSDOS */
+#endif /* PLATFORM_UNIX */
index 5177fb4ab2aca8acb48d864c1d59767c97fad367..5c251c77227df5c0e665136e3038ca7d9bd8c83f 100644 (file)
@@ -1,14 +1,14 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  netserv.h                                               *
+* netserv.h                                                *
 ***********************************************************/
 
 #ifndef NETSERV_H
index 1c593270d2e1462fe15287c01dc581c21a02ed5c..822b7ee02bdf8f85e14942463ba8540ccb1e4200 100644 (file)
@@ -1,19 +1,20 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  network.c                                               *
+* network.c                                                *
 ***********************************************************/
 
-#ifndef MSDOS
+#include "libgame/libgame.h"
+
+#if defined(PLATFORM_UNIX)
 
-#include <unistd.h>
 #include <signal.h>
 #include <sys/time.h>
 #include <sys/wait.h>
 #include <arpa/inet.h>
 #include <netdb.h>
 
+#if 0
+#include "libgame/libgame.h"
+#endif
+
 #include "network.h"
 #include "netserv.h"
 #include "game.h"
 #include "tape.h"
 #include "files.h"
 #include "tools.h"
-#include "buttons.h"
 #include "screens.h"
-#include "misc.h"
 
 struct NetworkClientPlayerInfo
 {
@@ -237,9 +240,9 @@ void SendToServer_StartPlaying()
   buffer[8] = (unsigned char)((new_random_seed >>  8) & 0xff);
   buffer[9] = (unsigned char)((new_random_seed >>  0) & 0xff);
 
-  strcpy((char *)&buffer[10], leveldir_current->name);
+  strcpy((char *)&buffer[10], leveldir_current->filename);
 
-  SendBufferToServer(10 + strlen(leveldir_current->name) + 1);
+  SendBufferToServer(10 + strlen(leveldir_current->filename) + 1);
 }
 
 void SendToServer_PausePlaying()
@@ -416,18 +419,18 @@ static void Handle_OP_START_PLAYING()
   int new_level_nr;
   int dummy;                           /* !!! HAS NO MEANING ANYMORE !!! */
   unsigned long new_random_seed;
-  char *new_leveldir_name;
+  char *new_leveldir_filename;
 
   new_level_nr = (buffer[2] << 8) + buffer[3];
   dummy = (buffer[4] << 8) + buffer[5];
   new_random_seed =
     (buffer[6] << 24) | (buffer[7] << 16) | (buffer[8] << 8) | (buffer[9]);
-  new_leveldir_name = (char *)&buffer[10];
+  new_leveldir_filename = (char *)&buffer[10];
 
-  new_leveldir = getLevelDirInfoFromFilename(new_leveldir_name);
+  new_leveldir = getLevelDirInfoFromFilename(new_leveldir_filename);
   if (new_leveldir == NULL)
   {
-    Error(ERR_WARN, "no such level directory: '%s'", new_leveldir_name);
+    Error(ERR_WARN, "no such level directory: '%s'", new_leveldir_filename);
 
     new_leveldir = leveldir_first;
     Error(ERR_WARN, "using default level directory: '%s'", new_leveldir->name);
@@ -616,4 +619,4 @@ void HandleNetworking()
   }
 }
 
-#endif /* !MSDOS */
+#endif /* PLATFORM_UNIX */
index 162f0f7df98d28e12fa1fd774dd61bbc44836a12..4a47091af39ffef2a13e46da0fe204681d512b9b 100644 (file)
@@ -1,14 +1,14 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  network.h                                               *
+* network.h                                                *
 ***********************************************************/
 
 #ifndef NETWORK_H
diff --git a/src/pcx.c b/src/pcx.c
deleted file mode 100644 (file)
index b26e442..0000000
--- a/src/pcx.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
-*----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
-*----------------------------------------------------------*
-*  pcx.c                                                   *
-***********************************************************/
-
-#include "pcx.h"
-#include "image.h"
-#include "misc.h"
-
-#define PCX_DEBUG              FALSE
-
-#define PCX_MAGIC              0x0a    /* first byte in a PCX image file    */
-#define PCX_LAST_VERSION       5       /* last acceptable version number    */
-#define PCX_ENCODING           1       /* PCX encoding method               */
-#define PCX_256COLORS_MAGIC    0x0c    /* first byte of a PCX 256 color map */
-#define PCX_MAXDEPTH           8       /* supports up to 8 bits per pixel   */
-#define PCX_MAXCOLORS          256     /* maximum number of colors          */
-
-#define PCX_HEADER_SIZE                128
-#define PCX_COLORMAP_SIZE      (3 * PCX_MAXCOLORS)
-
-struct PCX_Header
-{
-  unsigned char signature;     /* PCX file identifier                 */
-  unsigned char version;       /* version compatibility level         */
-  unsigned char encoding;      /* encoding method                     */
-  unsigned char bits_per_pixel;        /* bits per pixel, or depth            */
-  unsigned short xmin;         /* X position of left edge             */
-  unsigned short ymin;         /* Y position of top edge              */
-  unsigned short xmax;         /* X position of right edge            */
-  unsigned short ymax;         /* Y position of bottom edge           */
-  unsigned short hres;         /* X screen resolution of source image */
-  unsigned short vres;         /* Y screen resolution of source image */
-  unsigned char palette[16][3];        /* PCX color map                       */
-  unsigned char reserved;      /* should be 0, 1 if std res fax       */
-  unsigned char color_planes;  /* bit planes in image                 */
-  unsigned short bytes_per_line;/* byte delta between scanlines        */
-  unsigned short palette_type; /* 0 = undef, 1 = color, 2 = grayscale */
-  unsigned char filler[58];    /* fill to struct size of 128          */
-};
-
-/* global PCX error value */
-int errno_pcx = PCX_Success;
-
-static byte *PCX_ReadBitmap(Image *image, byte *buffer_ptr, byte *buffer_last)
-{
-  /* Run Length Encoding: If the two high bits are set,
-   * then the low 6 bits contain a repeat count, and the byte to
-   * repeat is the next byte in the file.  If the two high bits are
-   * not set, then this is the byte to write.
-   */
-
-  unsigned int bytes_per_pixel = (image->depth + 7) / 8;
-  register byte *bitmap_ptr, *bitmap_last;
-  register byte value, count;
-
-  bitmap_ptr = image->data;
-  bitmap_last = bitmap_ptr + (image->width * image->height * bytes_per_pixel);
-
-  while (bitmap_ptr < bitmap_last && buffer_ptr < buffer_last)
-  {
-    value = *buffer_ptr++;
-
-    if ((value & 0xc0) == 0xc0)                /* this is a repeat count byte */
-    {
-      count = value & 0x3f;            /* extract repeat count from byte */
-      value = *buffer_ptr++;           /* next byte is value to repeat */
-
-      for (; count && bitmap_ptr < bitmap_last; count--)
-       *bitmap_ptr++ = value;
-
-      if (count)                       /* repeat count spans end of bitmap */
-       return NULL;
-    }
-    else
-      *bitmap_ptr++ = value;
-
-    image->rgb.color_used[value] = TRUE;
-  }
-
-  /* check if end of buffer was reached before end of bitmap */
-  if (bitmap_ptr < bitmap_last)
-    return NULL;
-
-  /* return current buffer position for next decoding function */
-  return buffer_ptr;
-}
-
-static byte *PCX_ReadColormap(Image *image,byte *buffer_ptr, byte *buffer_last)
-{
-  int i, magic;
-
-  /* read colormap magic byte */
-  magic = *buffer_ptr++;
-
-  /* check magic colormap header byte */
-  if (magic != PCX_256COLORS_MAGIC)
-    return NULL;
-
-  /* check if enough bytes left for a complete colormap */
-  if (buffer_ptr + PCX_COLORMAP_SIZE > buffer_last)
-    return NULL;
-
-  /* read 256 colors from PCX colormap */
-  for (i=0; i<PCX_MAXCOLORS; i++)
-  {
-    image->rgb.red[i]   = *buffer_ptr++ << 8;
-    image->rgb.green[i] = *buffer_ptr++ << 8;
-    image->rgb.blue[i]  = *buffer_ptr++ << 8;
-  }
-
-  /* return current buffer position for next decoding function */
-  return buffer_ptr;
-}
-
-Image *Read_PCX_to_Image(char *filename)
-{
-  FILE *file;
-  byte *file_buffer;
-  byte *buffer_ptr, *buffer_last;
-  unsigned int file_length;
-  struct PCX_Header pcx;
-  Image *image;
-  int width, height, depth;
-  int i;
-
-  errno_pcx = PCX_Success;
-
-  if (!(file = fopen(filename, "r")))
-  {
-    errno_pcx = PCX_OpenFailed;
-    return NULL;
-  }
-
-  if (fseek(file, 0, SEEK_END) == -1)
-  {
-    fclose(file);
-    errno_pcx = PCX_ReadFailed;
-    return NULL;
-  }
-
-  file_length = ftell(file);
-  rewind(file);
-
-  if (file_length < PCX_HEADER_SIZE)
-  {
-    /* PCX file is too short to contain a valid PCX header */
-    fclose(file);
-
-    errno_pcx = PCX_FileInvalid;
-    return NULL;
-  }
-
-  file_buffer = checked_malloc(file_length);
-
-  if (fread(file_buffer, 1, file_length, file) != file_length)
-  {
-    fclose(file);
-    errno_pcx = PCX_ReadFailed;
-    return NULL;
-  }
-
-  fclose(file);
-
-  pcx.signature      = file_buffer[0];
-  pcx.version        = file_buffer[1];
-  pcx.encoding       = file_buffer[2];
-  pcx.bits_per_pixel = file_buffer[3];
-  pcx.xmin           = file_buffer[4]  + 256 * file_buffer[5];
-  pcx.ymin           = file_buffer[6]  + 256 * file_buffer[7];
-  pcx.xmax           = file_buffer[8]  + 256 * file_buffer[9];
-  pcx.ymax           = file_buffer[10] + 256 * file_buffer[11];
-  pcx.color_planes   = file_buffer[65];
-  pcx.bytes_per_line = file_buffer[66] + 256 * file_buffer[67];
-  pcx.palette_type   = file_buffer[68] + 256 * file_buffer[69];
-
-  width  = pcx.xmax - pcx.xmin + 1;
-  height = pcx.ymax - pcx.ymin + 1;
-  depth  = pcx.bits_per_pixel;
-
-  if (pcx.signature != PCX_MAGIC || pcx.version > PCX_LAST_VERSION ||
-      pcx.encoding != PCX_ENCODING || pcx.color_planes > PCX_MAXDEPTH ||
-      width < 0 || height < 0)
-  {
-    free(file_buffer);
-
-    errno_pcx = PCX_FileInvalid;
-    return NULL;
-  }
-
-#if PCX_DEBUG
-  if (options.verbose)
-  {
-    printf("%s is a %dx%d PC Paintbrush image with %d bitplanes\n",
-          filename, width, height,
-          pcx.color_planes);
-    printf("depth: %d\n", pcx.bits_per_pixel);
-    printf("color_planes: %d\n", pcx.color_planes);
-    printf("bytes_per_line: %d\n", pcx.bytes_per_line);
-    printf("palette type: %s\n",
-          (pcx.palette_type == 1 ? "color" :
-           pcx.palette_type == 2 ? "grayscale" : "undefined"));
-  }
-#endif
-
-  /* allocate new image structure */
-  image = newImage(width, height, depth);
-
-  buffer_ptr  = file_buffer + PCX_HEADER_SIZE;
-  buffer_last = file_buffer + file_length;
-
-  /* read compressed bitmap data */
-  if ((buffer_ptr = PCX_ReadBitmap(image, buffer_ptr, buffer_last)) == NULL)
-  {
-    free(file_buffer);
-    freeImage(image);
-
-    errno_pcx = PCX_FileInvalid;
-    return NULL;
-  }
-
-  if (file_length < PCX_HEADER_SIZE + PCX_COLORMAP_SIZE)
-  {
-    /* PCX file is too short to contain a valid 256 colors colormap */
-    fclose(file);
-    errno_pcx = PCX_ColorFailed;
-    return NULL;
-  }
-
-  /* read colormap data */
-  if (!PCX_ReadColormap(image, buffer_ptr, buffer_last))
-  {
-    free(file_buffer);
-    freeImage(image);
-    errno_pcx = PCX_ColorFailed;
-    return NULL;
-  }
-
-  free(file_buffer);
-
-  /* determine number of used colormap entries */
-  image->rgb.used = 0;
-  for (i=0; i<PCX_MAXCOLORS; i++)
-    if (image->rgb.color_used[i])
-      image->rgb.used++;
-
-#if PCX_DEBUG
-  if (options.verbose)
-    printf("Read_PCX_to_Image: %d colors found\n", image->rgb.used);
-#endif
-
-  return image;
-}
diff --git a/src/pcx.h b/src/pcx.h
deleted file mode 100644 (file)
index 44217ed..0000000
--- a/src/pcx.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
-*----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
-*----------------------------------------------------------*
-*  pcx.h                                                   *
-***********************************************************/
-
-#ifndef PCX_H
-#define PCX_H
-
-#include "main.h"
-#include "image.h"
-
-#define PCX_Success             0
-#define PCX_OpenFailed         -1
-#define PCX_ReadFailed         -2
-#define        PCX_FileInvalid         -3
-#define PCX_NoMemory           -4
-#define PCX_ColorFailed                -5
-
-/* global PCX error value */
-extern int errno_pcx;
-
-Image *Read_PCX_to_Image(char *);
-
-#endif /* PCX_H */
diff --git a/src/random.c b/src/random.c
deleted file mode 100644 (file)
index 864f3dc..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-/*
- * This is derived from the Berkeley source:
- *     @(#)random.c    5.5 (Berkeley) 7/6/88
- * It was reworked for the GNU C Library by Roland McGrath.
- */
-
-#include <errno.h>
-#include <limits.h>
-#include <stdlib.h>
-
-#include "random.h"
-
-
-/* An improved random number generation package.  In addition to the standard
-   rand()/srand() like interface, this package also has a special state info
-   interface.  The initstate() routine is called with a seed, an array of
-   bytes, and a count of how many bytes are being passed in; this array is
-   then initialized to contain information for random number generation with
-   that much state information.  Good sizes for the amount of state
-   information are 32, 64, 128, and 256 bytes.  The state can be switched by
-   calling the setstate() function with the same array as was initiallized
-   with initstate().  By default, the package runs with 128 bytes of state
-   information and generates far better random numbers than a linear
-   congruential generator.  If the amount of state information is less than
-   32 bytes, a simple linear congruential R.N.G. is used.  Internally, the
-   state information is treated as an array of longs; the zeroeth element of
-   the array is the type of R.N.G. being used (small integer); the remainder
-   of the array is the state information for the R.N.G.  Thus, 32 bytes of
-   state information will give 7 longs worth of state information, which will
-   allow a degree seven polynomial.  (Note: The zeroeth word of state
-   information also has some other information stored in it; see setstate
-   for details).  The random number generation technique is a linear feedback
-   shift register approach, employing trinomials (since there are fewer terms
-   to sum up that way).  In this approach, the least significant bit of all
-   the numbers in the state table will act as a linear feedback shift register,
-   and will have period 2^deg - 1 (where deg is the degree of the polynomial
-   being used, assuming that the polynomial is irreducible and primitive).
-   The higher order bits will have longer periods, since their values are
-   also influenced by pseudo-random carries out of the lower bits.  The
-   total period of the generator is approximately deg*(2**deg - 1); thus
-   doubling the amount of state information has a vast influence on the
-   period of the generator.  Note: The deg*(2**deg - 1) is an approximation
-   only good for large deg, when the period of the shift register is the
-   dominant factor.  With deg equal to seven, the period is actually much
-   longer than the 7*(2**7 - 1) predicted by this formula.  */
-
-
-
-/* For each of the currently supported random number generators, we have a
-   break value on the amount of state information (you need at least thi
-   bytes of state info to support this random number generator), a degree for
-   the polynomial (actually a trinomial) that the R.N.G. is based on, and
-   separation between the two lower order coefficients of the trinomial.  */
-
-/* Linear congruential.  */
-#define        TYPE_0          0
-#define        BREAK_0         8
-#define        DEG_0           0
-#define        SEP_0           0
-
-/* x**7 + x**3 + 1.  */
-#define        TYPE_1          1
-#define        BREAK_1         32
-#define        DEG_1           7
-#define        SEP_1           3
-
-/* x**15 + x + 1.  */
-#define        TYPE_2          2
-#define        BREAK_2         64
-#define        DEG_2           15
-#define        SEP_2           1
-
-/* x**31 + x**3 + 1.  */
-#define        TYPE_3          3
-#define        BREAK_3         128
-#define        DEG_3           31
-#define        SEP_3           3
-
-/* x**63 + x + 1.  */
-#define        TYPE_4          4
-#define        BREAK_4         256
-#define        DEG_4           63
-#define        SEP_4           1
-
-
-/* Array versions of the above information to make code run faster.
-   Relies on fact that TYPE_i == i.  */
-
-#define        MAX_TYPES       5       /* Max number of types above.  */
-
-
-
-/* Initially, everything is set up as if from:
-       initstate(1, randtbl, 128);
-   Note that this initialization takes advantage of the fact that srandom
-   advances the front and rear pointers 10*rand_deg times, and hence the
-   rear pointer which starts at 0 will also end up at zero; thus the zeroeth
-   element of the state information, which contains info about the current
-   position of the rear pointer is just
-       (MAX_TYPES * (rptr - state)) + TYPE_3 == TYPE_3.  */
-
-static long int randtbl[DEG_3 + 1] =
-{
-  TYPE_3,
-  -851904987, -43806228, -2029755270, 1390239686, -1912102820,
-  -485608943, 1969813258, -1590463333, -1944053249, 455935928, 508023712,
-  -1714531963, 1800685987, -2015299881, 654595283, -1149023258,
-  -1470005550, -1143256056, -1325577603, -1568001885, 1275120390,
-  -607508183, -205999574, -1696891592, 1492211999, -1528267240,
-  -952028296, -189082757, 362343714, 1424981831, 2039449641,
-};
-
-/* FPTR and RPTR are two pointers into the state info, a front and a rear
-   pointer.  These two pointers are always rand_sep places aparts, as they
-   cycle through the state information.  (Yes, this does mean we could get
-   away with just one pointer, but the code for random is more efficient
-   this way).  The pointers are left positioned as they would be from the call:
-       initstate(1, randtbl, 128);
-   (The position of the rear pointer, rptr, is really 0 (as explained above
-   in the initialization of randtbl) because the state table pointer is set
-   to point to randtbl[1] (as explained below).)  */
-
-static long int *fptr = &randtbl[SEP_3 + 1];
-static long int *rptr = &randtbl[1];
-
-
-
-/* The following things are the pointer to the state information table,
-   the type of the current generator, the degree of the current polynomial
-   being used, and the separation between the two pointers.
-   Note that for efficiency of random, we remember the first location of
-   the state information, not the zeroeth.  Hence it is valid to access
-   state[-1], which is used to store the type of the R.N.G.
-   Also, we remember the last location, since this is more efficient than
-   indexing every time to find the address of the last element to see if
-   the front and rear pointers have wrapped.  */
-
-static long int *state = &randtbl[1];
-
-static int rand_type = TYPE_3;
-static int rand_deg = DEG_3;
-static int rand_sep = SEP_3;
-
-static long int *end_ptr = &randtbl[sizeof(randtbl) / sizeof(randtbl[0])];
-
-/* Initialize the random number generator based on the given seed.  If the
-   type is the trivial no-state-information type, just remember the seed.
-   Otherwise, initializes state[] based on the given "seed" via a linear
-   congruential generator.  Then, the pointers are set to known locations
-   that are exactly rand_sep places apart.  Lastly, it cycles the state
-   information a given number of times to get rid of any initial dependencies
-   introduced by the L.C.R.N.G.  Note that the initialization of randtbl[]
-   for default usage relies on values produced by this routine.  */
-
-void srandom_linux_libc(unsigned int x)
-{
-  state[0] = x;
-  if (rand_type != TYPE_0)
-  {
-    register long int i;
-    for (i = 1; i < rand_deg; ++i)
-      state[i] = (1103515145 * state[i - 1]) + 12345;
-    fptr = &state[rand_sep];
-    rptr = &state[0];
-    for (i = 0; i < 10 * rand_deg; ++i)
-      (void) random_linux_libc();
-  }
-}
-
-/* If we are using the trivial TYPE_0 R.N.G., just do the old linear
-   congruential bit.  Otherwise, we do our fancy trinomial stuff, which is the
-   same in all ther other cases due to all the global variables that have been
-   set up.  The basic operation is to add the number at the rear pointer into
-   the one at the front pointer.  Then both pointers are advanced to the next
-   location cyclically in the table.  The value returned is the sum generated,
-   reduced to 31 bits by throwing away the "least random" low bit.
-   Note: The code takes advantage of the fact that both the front and
-   rear pointers can't wrap on the same call by not testing the rear
-   pointer if the front one has wrapped.  Returns a 31-bit random number.  */
-
-long int random_linux_libc()
-{
-  if (rand_type == TYPE_0)
-  {
-    state[0] = ((state[0] * 1103515245) + 12345) & LONG_MAX;
-    return state[0];
-  }
-  else
-  {
-    long int i;
-    *fptr += *rptr;
-    /* Chucking least random bit.  */
-    i = (*fptr >> 1) & LONG_MAX;
-    ++fptr;
-    if (fptr >= end_ptr)
-    {
-      fptr = state;
-      ++rptr;
-    }
-    else
-    {
-      ++rptr;
-      if (rptr >= end_ptr)
-       rptr = state;
-    }
-    return i;
-  }
-}
diff --git a/src/random.h b/src/random.h
deleted file mode 100644 (file)
index 366d1ff..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
-*----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
-*----------------------------------------------------------*
-*  random.h                                                *
-***********************************************************/
-
-#ifndef RANDOM_H
-#define RANDOM_H
-
-void srandom_linux_libc(unsigned int);
-long int random_linux_libc(void);
-
-#endif
index f2335cac639ab23a52c3e2e5e3854f5f2aba8649..f90b6e55dc882487691298f5cf74e69992eeeb36 100644 (file)
@@ -1,25 +1,24 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  screens.c                                               *
+* screens.c                                                *
 ***********************************************************/
 
+#include "libgame/libgame.h"
+
 #include "screens.h"
 #include "events.h"
-#include "sound.h"
 #include "game.h"
 #include "tools.h"
 #include "editor.h"
-#include "misc.h"
 #include "files.h"
-#include "buttons.h"
 #include "tape.h"
 #include "joystick.h"
 #include "cartoons.h"
@@ -55,16 +54,35 @@ static void HandleScreenGadgets(struct GadgetInfo *);
 
 static struct GadgetInfo *screen_gadget[NUM_SCREEN_GADGETS];
 
-#ifdef MSDOS
-extern unsigned char get_ascii(KeySym);
-#endif
-
 void DrawHeadline()
 {
   int x = SX + (SXSIZE - strlen(PROGRAM_TITLE_STRING) * FONT1_XSIZE) / 2;
 
   DrawText(x, SY + 8, PROGRAM_TITLE_STRING, FS_BIG, FC_YELLOW);
-  DrawTextFCentered(46, FC_RED, COPYRIGHT_STRING);
+  DrawTextFCentered(46, FC_RED, WINDOW_SUBTITLE_STRING);
+}
+
+static void ToggleFullscreenIfNeeded()
+{
+  if (setup.fullscreen != video.fullscreen_enabled)
+  {
+    /* save old door content */
+    BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
+              DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+
+    /* toggle fullscreen */
+    ChangeVideoModeIfNeeded(setup.fullscreen);
+    setup.fullscreen = video.fullscreen_enabled;
+
+    /* redraw background to newly created backbuffer */
+    BlitBitmap(pix[PIX_BACK], backbuffer, 0,0, WIN_XSIZE,WIN_YSIZE, 0,0);
+
+    /* restore old door content */
+    BlitBitmap(pix[PIX_DB_DOOR], backbuffer,
+              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY);
+
+    redraw_mask = REDRAW_ALL;
+  }
 }
 
 void DrawMainMenu()
@@ -75,7 +93,7 @@ void DrawMainMenu()
 
   UnmapAllGadgets();
   FadeSounds();
-  XAutoRepeatOn(display);
+  KeyboardAutoRepeatOn();
 
   /* needed if last screen was the playing screen, invoked from level editor */
   if (level_editor_test_game)
@@ -88,6 +106,13 @@ void DrawMainMenu()
   /* needed if last screen was the editor screen */
   UndrawSpecialEditorDoor();
 
+  /* needed if last screen was the setup screen and fullscreen state changed */
+  ToggleFullscreenIfNeeded();
+
+#ifdef TARGET_SDL
+  SetDrawtoField(DRAW_BACKBUFFER);
+#endif
+
   /* map gadgets for main menu screen */
   MapTapeButtons();
 
@@ -260,9 +285,9 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
 
     level_nr = new_level_nr;
 
-    DrawTextExt(drawto, gc, SX + 11 * 32, SY + 3 * 32,
+    DrawTextExt(drawto, SX + 11 * 32, SY + 3 * 32,
                int2str(level_nr, 3), FS_BIG, font_color);
-    DrawTextExt(window, gc, SX + 11 * 32, SY + 3 * 32,
+    DrawTextExt(window, SX + 11 * 32, SY + 3 * 32,
                int2str(level_nr, 3), FS_BIG, font_color);
 
     LoadLevel(level_nr);
@@ -274,7 +299,7 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
 
     /* needed because DrawMicroLevel() takes some time */
     BackToFront();
-    XSync(display, FALSE);
+    SyncDisplay();
     DelayReached(&level_delay, 0);     /* reset delay counter */
   }
   else if (x == 1 && y >= 3 && y <= 10)
@@ -331,7 +356,7 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
        if (setup.autorecord)
          TapeStartRecording();
 
-#ifndef MSDOS
+#if defined(PLATFORM_UNIX)
        if (options.network)
          SendToServer_StartPlaying();
        else
@@ -561,6 +586,7 @@ static char *helpscreen_music[][3] =
   { "Voyager",                 "The Alan Parsons Project","Pyramid" },
   { "Twilight Painter",                "Tangerine Dream",      "Heartbreakers" }
 };
+static int num_helpscreen_music = 7;
 static int helpscreen_musicpos;
 
 void DrawHelpScreenElAction(int start)
@@ -615,7 +641,7 @@ void DrawHelpScreenElAction(int start)
     }
     j++;
 
-    DrawGraphicExt(drawto, gc, xstart, ystart+(i-start)*ystep, graphic+frame);
+    DrawGraphicExt(drawto, xstart, ystart+(i-start)*ystep, graphic+frame);
     i++;
   }
 
@@ -675,7 +701,9 @@ void DrawHelpScreenMusicText(int num)
 
   DrawTextFCentered(ybottom, FC_BLUE, "Press any key or button for next page");
 
+#if 0
   PlaySoundLoop(background_loop[num]);
+#endif
 }
 
 void DrawHelpScreenCreditsText()
@@ -690,7 +718,7 @@ void DrawHelpScreenCreditsText()
   DrawTextFCentered(100, FC_GREEN,
                    "Credits:");
   DrawTextFCentered(ystart + 0 * ystep, FC_YELLOW,
-                   "DOS/Windows port of the game:");
+                   "DOS port of the game:");
   DrawTextFCentered(ystart + 1 * ystep, FC_RED,
                    "Guido Schulz");
   DrawTextFCentered(ystart + 2 * ystep, FC_YELLOW,
@@ -720,13 +748,13 @@ void DrawHelpScreenContactText()
   DrawTextFCentered(ystart + 1 * ystep, FC_YELLOW,
                    "If you like it, send e-mail to:");
   DrawTextFCentered(ystart + 2 * ystep, FC_RED,
-                   "aeglos@valinor.owl.de");
+                   "info@artsoft.org");
   DrawTextFCentered(ystart + 3 * ystep, FC_YELLOW,
                    "or SnailMail to:");
   DrawTextFCentered(ystart + 4 * ystep + 0, FC_RED,
                    "Holger Schemel");
   DrawTextFCentered(ystart + 4 * ystep + 20, FC_RED,
-                   "Oststrasse 11a");
+                   "Detmolder Strasse 189");
   DrawTextFCentered(ystart + 4 * ystep + 40, FC_RED,
                    "33604 Bielefeld");
   DrawTextFCentered(ystart + 4 * ystep + 60, FC_RED,
@@ -779,17 +807,20 @@ void HandleHelpScreen(int button)
       DrawHelpScreenElText(helpscreen_state*MAX_HELPSCREEN_ELS);
       DrawHelpScreenElAction(helpscreen_state*MAX_HELPSCREEN_ELS);
     }
-    else if (helpscreen_state < num_helpscreen_els_pages + num_bg_loops - 1)
+    else if (helpscreen_state <
+            num_helpscreen_els_pages + num_helpscreen_music - 1)
     {
       helpscreen_state++;
       DrawHelpScreenMusicText(helpscreen_state - num_helpscreen_els_pages);
     }
-    else if (helpscreen_state == num_helpscreen_els_pages + num_bg_loops - 1)
+    else if (helpscreen_state ==
+            num_helpscreen_els_pages + num_helpscreen_music - 1)
     {
       helpscreen_state++;
       DrawHelpScreenCreditsText();
     }
-    else if (helpscreen_state == num_helpscreen_els_pages + num_bg_loops)
+    else if (helpscreen_state ==
+            num_helpscreen_els_pages + num_helpscreen_music)
     {
       helpscreen_state++;
       DrawHelpScreenContactText();
@@ -814,7 +845,7 @@ void HandleHelpScreen(int button)
   BackToFront();
 }
 
-void HandleTypeName(int newxpos, KeySym key)
+void HandleTypeName(int newxpos, Key key)
 {
   static int xpos = 0, ypos = 2;
 
@@ -826,33 +857,34 @@ void HandleTypeName(int newxpos, KeySym key)
     return;
   }
 
-  if (((key >= XK_A && key <= XK_Z) || (key >= XK_a && key <= XK_z)) && 
+  if (((key >= KSYM_A && key <= KSYM_Z) ||
+       (key >= KSYM_a && key <= KSYM_z)) && 
       xpos < MAX_PLAYER_NAME_LEN)
   {
     char ascii;
 
-    if (key >= XK_A && key <= XK_Z)
-      ascii = 'A' + (char)(key - XK_A);
+    if (key >= KSYM_A && key <= KSYM_Z)
+      ascii = 'A' + (char)(key - KSYM_A);
     else
-      ascii = 'a' + (char)(key - XK_a);
+      ascii = 'a' + (char)(key - KSYM_a);
 
     setup.player_name[xpos] = ascii;
     setup.player_name[xpos + 1] = 0;
     xpos++;
-    DrawTextExt(drawto, gc, SX + 6*32, SY + ypos*32,
+    DrawTextExt(drawto, SX + 6*32, SY + ypos*32,
                setup.player_name, FS_BIG, FC_YELLOW);
-    DrawTextExt(window, gc, SX + 6*32, SY + ypos*32,
+    DrawTextExt(window, SX + 6*32, SY + ypos*32,
                setup.player_name, FS_BIG, FC_YELLOW);
     DrawGraphic(xpos + 6, ypos, GFX_KUGEL_ROT);
   }
-  else if ((key == XK_Delete || key == XK_BackSpace) && xpos > 0)
+  else if ((key == KSYM_Delete || key == KSYM_BackSpace) && xpos > 0)
   {
     xpos--;
     setup.player_name[xpos] = 0;
     DrawGraphic(xpos + 6, ypos, GFX_KUGEL_ROT);
     DrawGraphic(xpos + 7, ypos, GFX_LEERRAUM);
   }
-  else if (key == XK_Return && xpos > 0)
+  else if (key == KSYM_Return && xpos > 0)
   {
     DrawText(SX + 6*32, SY + ypos*32, setup.player_name, FS_BIG, FC_RED);
     DrawGraphic(xpos + 6, ypos, GFX_LEERRAUM);
@@ -927,7 +959,7 @@ static void drawChooseLevelList(int first_entry, int num_page_entries)
   int max_buffer_len = (SCR_FIELDX - 2) * 2;
   int num_leveldirs = numLevelDirInfoInGroup(leveldir_current);
 
-  XFillRectangle(display, backbuffer, gc, SX, SY, SXSIZE - 32, SYSIZE);
+  ClearRectangle(backbuffer, SX, SY, SXSIZE - 32, SYSIZE);
   redraw_mask |= REDRAW_FIELD;
 
   DrawText(SX, SY, "Level Directories", FS_BIG, FC_GREEN);
@@ -969,7 +1001,7 @@ static void drawChooseLevelInfo(int leveldir_pos)
   node_first = getLevelDirInfoFirstGroupEntry(leveldir_current);
   node = getLevelDirInfoFromPos(node_first, leveldir_pos);
 
-  XFillRectangle(display, drawto, gc, SX + 32, SY + 32, SXSIZE - 64, 32);
+  ClearRectangle(drawto, SX + 32, SY + 32, SXSIZE - 64, 32);
 
   if (node->parent_link)
     DrawTextFCentered(40, FC_RED, "leave group \"%s\"", node->class_desc);
@@ -1040,7 +1072,7 @@ void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
     else
       x = y = 0;       /* no action */
 
-    if (ABS(dy) == SCR_FIELDY) /* handle XK_Page_Up, XK_Page_Down */
+    if (ABS(dy) == SCR_FIELDY) /* handle KSYM_Page_Up, KSYM_Page_Down */
     {
       dy = SIGN(dy);
       step = num_page_entries - 1;
@@ -1228,7 +1260,7 @@ void HandleHallOfFame(int mx, int my, int dx, int dy, int button)
     return;
   }
 
-  if (ABS(dy) == SCR_FIELDY)   /* handle XK_Page_Up, XK_Page_Down */
+  if (ABS(dy) == SCR_FIELDY)   /* handle KSYM_Page_Up, KSYM_Page_Down */
     step = MAX_LEVEL_SERIES_ON_SCREEN - 1;
 
   if (dy < 0)
@@ -1287,7 +1319,10 @@ void DrawSetupScreen()
 #endif
     { &setup.scroll_delay,     "Scroll Delay:" },
     { &setup.soft_scrolling,   "Soft Scroll.:" },
+#if 0
     { &setup.fading,           "Fading:"       },
+#endif
+    { &setup.fullscreen,       "Fullscreen:"   },
     { &setup.quick_doors,      "Quick Doors:"  },
     { &setup.autorecord,       "Auto-Record:"  },
     { &setup.team_mode,                "Team-Mode:"    },
@@ -1403,7 +1438,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
     {
       int yy = y-1;
 
-      if (y==3 && sound_status==SOUND_AVAILABLE)
+      if (y == 3 && audio.sound_available)
       {
        if (setup.sound)
        {
@@ -1417,7 +1452,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.sound = !setup.sound;
       }
-      else if (y==4 && sound_loops_allowed)
+      else if (y == 4 && audio.loops_available)
       {
        if (setup.sound_loops)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1429,7 +1464,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
        }
        setup.sound_loops = !setup.sound_loops;
       }
-      else if (y==5 && sound_loops_allowed)
+      else if (y == 5 && audio.loops_available)
       {
        if (setup.sound_music)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1443,7 +1478,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
       }
 
 #if 0
-      else if (y==6)
+      else if (y == 6)
       {
        if (setup.toons)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1451,7 +1486,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.toons = !setup.toons;
       }
-      else if (y==7)
+      else if (y == 7)
       {
 #if 0
        if (setup.double_buffering)
@@ -1468,7 +1503,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
       }
 #endif
 
-      else if (y==6)
+      else if (y == 6)
       {
        if (setup.scroll_delay)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1476,7 +1511,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.scroll_delay = !setup.scroll_delay;
       }
-      else if (y==7)
+      else if (y == 7)
       {
        if (setup.soft_scrolling)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1484,7 +1519,8 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.soft_scrolling = !setup.soft_scrolling;
       }
-      else if (y==8)
+#if 0
+      else if (y == 8)
       {
        if (setup.fading)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1492,7 +1528,16 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.fading = !setup.fading;
       }
-      else if (y==9)
+#endif
+      else if (y == 8 && video.fullscreen_available)
+      {
+       if (setup.fullscreen)
+         DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+       else
+         DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+       setup.fullscreen = !setup.fullscreen;
+      }
+      else if (y == 9)
       {
        if (setup.quick_doors)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1500,7 +1545,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.quick_doors = !setup.quick_doors;
       }
-      else if (y==10)
+      else if (y == 10)
       {
        if (setup.autorecord)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1508,7 +1553,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.autorecord = !setup.autorecord;
       }
-      else if (y==11)
+      else if (y == 11)
       {
        if (setup.team_mode)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1516,7 +1561,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.team_mode = !setup.team_mode;
       }
-      else if (y==12)
+      else if (y == 12)
       {
        if (setup.handicap)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1524,7 +1569,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.handicap = !setup.handicap;
       }
-      else if (y==13)
+      else if (y == 13)
       {
        if (setup.time_limit)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1532,7 +1577,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.time_limit = !setup.time_limit;
       }
-      else if (y==14)
+      else if (y == 14)
       {
        game_status = SETUPINPUT;
        DrawSetupInputScreen();
@@ -1548,7 +1593,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          SaveJoystickData();
          */
 
-#ifdef MSDOS
+#if defined(PLATFORM_MSDOS)
          save_joystick_data(JOYSTICK_FILENAME);
 #endif
 
@@ -1618,7 +1663,7 @@ static void drawPlayerSetupInputInfo(int player_nr)
   static struct SetupKeyboardInfo custom_key;
   static struct
   {
-    KeySym *keysym;
+    Key *key;
     char *text;
   } custom[] =
   {
@@ -1678,7 +1723,7 @@ static void drawPlayerSetupInputInfo(int player_nr)
     DrawText(SX + 3*32, SY + ypos*32,
             (setup.input[player_nr].use_joystick ?
              custom[i].text :
-             getKeyNameFromKeySym(*custom[i].keysym)),
+             getKeyNameFromKey(*custom[i].key)),
             FS_BIG, FC_YELLOW);
   }
 }
@@ -1858,7 +1903,7 @@ void CustomizeKeyboard(int player_nr)
   static struct SetupKeyboardInfo custom_key;
   static struct
   {
-    KeySym *keysym;
+    Key *key;
     char *text;
   } customize_step[] =
   {
@@ -1885,47 +1930,50 @@ void CustomizeKeyboard(int player_nr)
   DrawText(SX, SY + (2+2*step_nr+1)*32,
           "Key:", FS_BIG, FC_RED);
   DrawText(SX + 4*32, SY + (2+2*step_nr+1)*32,
-          getKeyNameFromKeySym(*customize_step[step_nr].keysym),
+          getKeyNameFromKey(*customize_step[step_nr].key),
           FS_BIG, FC_BLUE);
 
   while(!finished)
   {
-    if (XPending(display))     /* got event from X server */
+    if (PendingEvent())                /* got event */
     {
-      XEvent event;
+      Event event;
 
-      XNextEvent(display, &event);
+      NextEvent(&event);
 
       switch(event.type)
       {
-        case KeyPress:
+        case EVENT_KEYPRESS:
          {
-           KeySym key = XLookupKeysym((XKeyEvent *)&event,
-                                      ((XKeyEvent *)&event)->state);
+           Key key = GetEventKey((KeyEvent *)&event, TRUE);
 
-           if (key == XK_Escape || (key == XK_Return && step_nr == 6))
+           if (key == KSYM_Escape || (key == KSYM_Return && step_nr == 6))
            {
              finished = TRUE;
              break;
            }
 
+           /* all keys configured -- wait for "Escape" or "Return" key */
+           if (step_nr == 6)
+             break;
+
            /* press 'Enter' to keep the existing key binding */
-           if (key == XK_Return || step_nr == 6)
-             key = *customize_step[step_nr].keysym;
+           if (key == KSYM_Return)
+             key = *customize_step[step_nr].key;
 
            /* check if key already used */
            for (i=0; i<step_nr; i++)
-             if (*customize_step[i].keysym == key)
+             if (*customize_step[i].key == key)
                break;
            if (i < step_nr)
              break;
 
            /* got new key binding */
-           *customize_step[step_nr].keysym = key;
+           *customize_step[step_nr].key = key;
            DrawText(SX + 4*32, SY + (2+2*step_nr+1)*32,
                     "             ", FS_BIG, FC_YELLOW);
            DrawText(SX + 4*32, SY + (2+2*step_nr+1)*32,
-                    getKeyNameFromKeySym(key), FS_BIG, FC_YELLOW);
+                    getKeyNameFromKey(key), FS_BIG, FC_YELLOW);
            step_nr++;
 
            /* un-highlight last query */
@@ -1948,12 +1996,12 @@ void CustomizeKeyboard(int player_nr)
            DrawText(SX, SY+(2+2*step_nr+1)*32,
                     "Key:", FS_BIG, FC_RED);
            DrawText(SX + 4*32, SY+(2+2*step_nr+1)*32,
-                    getKeyNameFromKeySym(*customize_step[step_nr].keysym),
+                    getKeyNameFromKey(*customize_step[step_nr].key),
                     FS_BIG, FC_BLUE);
          }
          break;
 
-        case KeyRelease:
+        case EVENT_KEYRELEASE:
          key_joystick_mapping = 0;
          break;
 
@@ -1990,7 +2038,7 @@ void CalibrateJoystick(int player_nr)
   } joy_ctrl;
 #endif
 
-#ifndef MSDOS
+#if !defined(PLATFORM_MSDOS)
   int new_joystick_xleft = 128, new_joystick_xright = 128;
   int new_joystick_yupper = 128, new_joystick_ylower = 128;
   int new_joystick_xmiddle, new_joystick_ymiddle;
@@ -2012,7 +2060,7 @@ void CalibrateJoystick(int player_nr)
 
   ClearWindow();
 
-#ifndef MSDOS
+#if !defined(PLATFORM_MSDOS)
   DrawText(SX,      SY +  6*32, " ROTATE JOYSTICK ", FS_BIG, FC_YELLOW);
   DrawText(SX,      SY +  7*32, "IN ALL DIRECTIONS", FS_BIG, FC_YELLOW);
   DrawText(SX + 16, SY +  9*32, "  IF ALL BALLS  ",  FS_BIG, FC_YELLOW);
@@ -2056,24 +2104,23 @@ void CalibrateJoystick(int player_nr)
 
   while(result < 0)
   {
-    if (XPending(display))     /* got event from X server */
+    if (PendingEvent())                /* got event */
     {
-      XEvent event;
+      Event event;
 
-      XNextEvent(display, &event);
+      NextEvent(&event);
 
       switch(event.type)
       {
-       case KeyPress:
-         switch(XLookupKeysym((XKeyEvent *)&event,
-                              ((XKeyEvent *)&event)->state))
+       case EVENT_KEYPRESS:
+         switch(GetEventKey((KeyEvent *)&event, TRUE))
          {
-           case XK_Return:
+           case KSYM_Return:
              if (check_remaining == 0)
                result = 1;
              break;
 
-           case XK_Escape:
+           case KSYM_Escape:
              result = 0;
              break;
 
@@ -2082,7 +2129,7 @@ void CalibrateJoystick(int player_nr)
          }
          break;
 
-       case KeyRelease:
+       case EVENT_KEYRELEASE:
          key_joystick_mapping = 0;
          break;
 
@@ -2092,12 +2139,18 @@ void CalibrateJoystick(int player_nr)
       }
     }
 
-#ifndef MSDOS
+#if !defined(PLATFORM_MSDOS)
+
+#if defined(TARGET_SDL)
+    joy_ctrl.x = Get_SDL_Joystick_Axis(joystick_fd, 0);
+    joy_ctrl.y = Get_SDL_Joystick_Axis(joystick_fd, 1);
+#else
     if (read(joystick_fd, &joy_ctrl, sizeof(joy_ctrl)) != sizeof(joy_ctrl))
     {
       joystick_status = JOYSTICK_OFF;
       goto error_out;
     }
+#endif
 
     new_joystick_xleft  = MIN(new_joystick_xleft,  joy_ctrl.x);
     new_joystick_xright = MAX(new_joystick_xright, joy_ctrl.x);
@@ -2125,7 +2178,7 @@ void CalibrateJoystick(int player_nr)
     {
       result = 1;
 
-#ifdef MSDOS
+#if defined(PLATFORM_MSDOS)
       if (calibration_step == 1)
       {
        remove_joystick();
@@ -2166,7 +2219,7 @@ void CalibrateJoystick(int player_nr)
 
     if (x != last_x || y != last_y)
     {
-#ifndef MSDOS
+#if !defined(PLATFORM_MSDOS)
       DrawGraphic(xpos + last_x, ypos + last_y, GFX_KUGEL_GELB);
 #else
       DrawGraphic(xpos + last_x, ypos + last_y, GFX_KUGEL_BLAU);
@@ -2205,7 +2258,20 @@ void CalibrateJoystick(int player_nr)
   StopAnimation();
 
   DrawSetupInputScreen();
-  while(Joystick(player_nr) & JOY_BUTTON);
+
+  /* wait until the last pressed button was released */
+  while(Joystick(player_nr) & JOY_BUTTON)
+  {
+    if (PendingEvent())                /* got event */
+    {
+      Event event;
+
+      NextEvent(&event);
+      HandleOtherEvents(&event);
+
+      Delay(10);
+    }
+  }
   return;
 
   error_out:
@@ -2300,7 +2366,7 @@ static struct
 
 static void CreateScreenScrollbuttons()
 {
-  Pixmap gd_pixmap = pix[PIX_MORE];
+  Bitmap *gd_bitmap = pix[PIX_MORE];
   struct GadgetInfo *gi;
   unsigned long event_mask;
   int i;
@@ -2334,8 +2400,8 @@ static void CreateScreenScrollbuttons()
                      GDI_HEIGHT, height,
                      GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
                      GDI_STATE, GD_BUTTON_UNPRESSED,
-                     GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
-                     GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
+                     GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y1,
+                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y2,
                      GDI_EVENT_MASK, event_mask,
                      GDI_CALLBACK_ACTION, HandleScreenGadgets,
                      GDI_END);
@@ -2354,7 +2420,7 @@ static void CreateScreenScrollbars()
   for (i=0; i<NUM_SCREEN_SCROLLBARS; i++)
   {
     int id = scrollbar_info[i].gadget_id;
-    Pixmap gd_pixmap = pix[PIX_MORE];
+    Bitmap *gd_bitmap = pix[PIX_MORE];
     int gd_x1, gd_x2, gd_y1, gd_y2;
     struct GadgetInfo *gi;
     int items_max, items_visible, item_position;
@@ -2395,8 +2461,8 @@ static void CreateScreenScrollbars()
                      GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible,
                      GDI_SCROLLBAR_ITEM_POSITION, item_position,
                      GDI_STATE, GD_BUTTON_UNPRESSED,
-                     GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
-                     GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
+                     GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y1,
+                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y2,
                      GDI_BORDER_SIZE, SC_BORDER_SIZE,
                      GDI_EVENT_MASK, event_mask,
                      GDI_CALLBACK_ACTION, HandleScreenGadgets,
index d40432737ff7fc3b65f99d741510d2be2f3bcf28..0cae1835db918ff6baf49573e14651cc204d4c4a 100644 (file)
@@ -1,14 +1,14 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  screens.h                                               *
+* screens.h                                                *
 ***********************************************************/
 
 #ifndef SCREENS_H
@@ -25,7 +25,7 @@ void DrawHelpScreenMusicText(int);
 void DrawHelpScreenCreditsText(void);
 void DrawHelpScreen(void);
 void HandleHelpScreen(int);
-void HandleTypeName(int, KeySym);
+void HandleTypeName(int, Key);
 void DrawChooseLevel(void);
 void HandleChooseLevel(int, int, int, int, int);
 void DrawHallOfFame(int);
diff --git a/src/sound.c b/src/sound.c
deleted file mode 100644 (file)
index 7839902..0000000
+++ /dev/null
@@ -1,917 +0,0 @@
-/***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
-*----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
-*----------------------------------------------------------*
-*  sound.c                                                 *
-***********************************************************/
-
-#include "sound.h"
-#include "misc.h"
-
-/*** THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
-
-static int playing_sounds = 0;
-static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
-static struct SoundControl emptySoundControl =
-{
-  -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE, 0,0L,0L,NULL
-};
-
-#ifndef MSDOS
-static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
-static char premix_first_buffer[SND_BLOCKSIZE];
-#ifdef VOXWARE
-static char premix_left_buffer[SND_BLOCKSIZE];
-static char premix_right_buffer[SND_BLOCKSIZE];
-static int premix_last_buffer[SND_BLOCKSIZE];
-#endif /* VOXWARE */
-static unsigned char playing_buffer[SND_BLOCKSIZE];
-#endif /* MSDOS */
-
-/* forward declaration of internal functions */
-#ifdef VOXWARE
-static void SoundServer_InsertNewSound(struct SoundControl);
-#endif
-#ifndef VOXWARE
-#ifndef MSDOS
-static unsigned char linear_to_ulaw(int);
-static int ulaw_to_linear(unsigned char);
-#endif
-#endif
-#ifdef HPUX_AUDIO
-static void HPUX_Audio_Control();
-#endif
-#ifdef MSDOS
-static void SoundServer_InsertNewSound(struct SoundControl);
-static void SoundServer_StopSound(int);
-static void SoundServer_StopAllSounds();
-#endif
-
-void SoundServer()
-{
-  int i;
-#ifndef MSDOS
-  struct SoundControl snd_ctrl;
-  fd_set sound_fdset;
-
-  close(sound_pipe[1]);                /* no writing into pipe needed */
-#endif
-
-  for(i=0;i<MAX_SOUNDS_PLAYING;i++)
-    playlist[i] = emptySoundControl;
-  playing_sounds = 0;
-
-#ifndef MSDOS
-  stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
-  for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
-    stereo_volume[i] =
-      (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
-
-#ifdef HPUX_AUDIO
-  HPUX_Audio_Control();
-#endif
-
-  FD_ZERO(&sound_fdset); 
-  FD_SET(sound_pipe[0], &sound_fdset);
-
-  while(1)     /* wait for sound playing commands from client */
-  {
-    FD_SET(sound_pipe[0], &sound_fdset);
-    select(sound_pipe[0]+1, &sound_fdset, NULL, NULL, NULL);
-    if (!FD_ISSET(sound_pipe[0], &sound_fdset))
-      continue;
-    if (read(sound_pipe[0], &snd_ctrl, sizeof(snd_ctrl)) != sizeof(snd_ctrl))
-      Error(ERR_EXIT_SOUND_SERVER, "broken pipe - no sounds");
-
-#ifdef VOXWARE
-
-    if (snd_ctrl.fade_sound)
-    {
-      if (!playing_sounds)
-       continue;
-
-      for(i=0;i<MAX_SOUNDS_PLAYING;i++)
-       if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
-         playlist[i].fade_sound = TRUE;
-    }
-    else if (snd_ctrl.stop_all_sounds)
-    {
-      if (!playing_sounds)
-       continue;
-
-      for(i=0;i<MAX_SOUNDS_PLAYING;i++)
-       playlist[i]=emptySoundControl;
-      playing_sounds=0;
-
-      close(sound_device);
-    }
-    else if (snd_ctrl.stop_sound)
-    {
-      if (!playing_sounds)
-       continue;
-
-      for(i=0;i<MAX_SOUNDS_PLAYING;i++)
-       if (playlist[i].nr == snd_ctrl.nr)
-       {
-         playlist[i]=emptySoundControl;
-         playing_sounds--;
-       }
-
-      if (!playing_sounds)
-       close(sound_device);
-    }
-
-    if (playing_sounds || snd_ctrl.active)
-    {
-      struct timeval delay = { 0, 0 };
-      byte *sample_ptr;
-      long sample_size;
-      static long max_sample_size = 0;
-      static long fragment_size = 0;
-      /* Even if the stereo flag is used as being boolean, it must be
-        defined as an integer, else 'ioctl()' will fail! */
-      int stereo = TRUE;
-      int sample_rate = 8000;
-
-      if (playing_sounds || (sound_device=open(sound_device_name,O_WRONLY))>=0)
-      {
-       if (!playing_sounds)    /* we just opened the audio device */
-       {
-         /* 2 buffers / 512 bytes, giving 1/16 second resolution */
-         /* (with stereo the effective buffer size will shrink to 256) */
-         fragment_size = 0x00020009;
-
-         if (ioctl(sound_device, SNDCTL_DSP_SETFRAGMENT, &fragment_size) < 0)
-           Error(ERR_EXIT_SOUND_SERVER,
-                 "cannot set fragment size of /dev/dsp - no sounds");
-
-         /* try if we can use stereo sound */
-         if (ioctl(sound_device, SNDCTL_DSP_STEREO, &stereo) < 0)
-         {
-#ifdef DEBUG
-           static boolean reported = FALSE;
-
-           if (!reported)
-           {
-             Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
-             reported = TRUE;
-           }
-#endif
-           stereo = FALSE;
-         }
-
-         if (ioctl(sound_device, SNDCTL_DSP_SPEED, &sample_rate) < 0)
-           Error(ERR_EXIT_SOUND_SERVER,
-                 "cannot set sample rate of /dev/dsp - no sounds");
-
-         /* get the real fragmentation size; this should return 512 */
-         if (ioctl(sound_device, SNDCTL_DSP_GETBLKSIZE, &fragment_size) < 0)
-           Error(ERR_EXIT_SOUND_SERVER,
-                 "cannot get fragment size of /dev/dsp - no sounds");
-
-         max_sample_size = fragment_size / (stereo ? 2 : 1);
-       }
-
-       if (snd_ctrl.active)    /* new sound has arrived */
-         SoundServer_InsertNewSound(snd_ctrl);
-
-       while(playing_sounds &&
-             select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
-       {       
-         FD_SET(sound_pipe[0], &sound_fdset);
-
-         /* first clear the last premixing buffer */
-         memset(premix_last_buffer,0,fragment_size*sizeof(int));
-
-         for(i=0;i<MAX_SOUNDS_PLAYING;i++)
-         {
-           int j;
-
-           if (!playlist[i].active)
-             continue;
-
-           /* get pointer and size of the actual sound sample */
-           sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
-           sample_size =
-             MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
-           playlist[i].playingpos += sample_size;
-
-           /* fill the first mixing buffer with original sample */
-           memcpy(premix_first_buffer,sample_ptr,sample_size);
-
-           /* are we about to restart a looping sound? */
-           if (playlist[i].loop && sample_size<max_sample_size)
-           {
-             playlist[i].playingpos = max_sample_size-sample_size;
-             memcpy(premix_first_buffer+sample_size,
-                    playlist[i].data_ptr,max_sample_size-sample_size);
-             sample_size = max_sample_size;
-           }
-
-           /* decrease volume if sound is fading out */
-           if (playlist[i].fade_sound &&
-               playlist[i].volume>=PSND_MAX_VOLUME/10)
-             playlist[i].volume-=PSND_MAX_VOLUME/20;
-
-           /* adjust volume of actual sound sample */
-           if (playlist[i].volume != PSND_MAX_VOLUME)
-             for(j=0;j<sample_size;j++)
-               premix_first_buffer[j] =
-                 (playlist[i].volume * (int)premix_first_buffer[j])
-                   >> PSND_MAX_VOLUME_BITS;
-
-           /* fill the last mixing buffer with stereo or mono sound */
-           if (stereo)
-           {
-             int middle_pos = PSND_MAX_LEFT2RIGHT/2;
-             int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
-             int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
-
-             for(j=0;j<sample_size;j++)
-             {
-               premix_left_buffer[j] =
-                 (left_volume * (int)premix_first_buffer[j])
-                   >> PSND_MAX_LEFT2RIGHT_BITS;
-               premix_right_buffer[j] =
-                 (right_volume * (int)premix_first_buffer[j])
-                   >> PSND_MAX_LEFT2RIGHT_BITS;
-               premix_last_buffer[2*j+0] += premix_left_buffer[j];
-               premix_last_buffer[2*j+1] += premix_right_buffer[j];
-             }
-           }
-           else
-           {
-             for(j=0;j<sample_size;j++)
-               premix_last_buffer[j] += (int)premix_first_buffer[j];
-           }
-
-           /* delete completed sound entries from the playlist */
-           if (playlist[i].playingpos >= playlist[i].data_len)
-           {
-             if (playlist[i].loop)
-               playlist[i].playingpos = 0;
-             else
-             {
-               playlist[i] = emptySoundControl;
-               playing_sounds--;
-             }
-           }
-           else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
-           {
-             playlist[i] = emptySoundControl;
-             playing_sounds--;
-           }
-         }
-
-         /* put last mixing buffer to final playing buffer */
-         for(i=0;i<fragment_size;i++)
-         {
-           if (premix_last_buffer[i]<-255)
-             playing_buffer[i] = 0;
-           else if (premix_last_buffer[i]>255)
-             playing_buffer[i] = 255;
-           else
-             playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
-         }
-
-         /* finally play the sound fragment */
-         write(sound_device,playing_buffer,fragment_size);
-       }
-
-       /* if no sounds playing, free device for other sound programs */
-       if (!playing_sounds)
-         close(sound_device);
-      }
-    }
-
-#else /* !VOXWARE */
-
-    if (snd_ctrl.active && !snd_ctrl.loop)
-    {
-      struct timeval delay = { 0, 0 };
-      byte *sample_ptr;
-      long sample_size, max_sample_size = SND_BLOCKSIZE;
-      long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
-      int wait_percent = 90;   /* wait 90% of the real playing time */
-      int i;
-
-      if ((sound_device=open(sound_device_name,O_WRONLY))>=0)
-      {
-       playing_sounds = 1;
-
-       while(playing_sounds &&
-             select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
-       {       
-         FD_SET(sound_pipe[0], &sound_fdset);
-
-         /* get pointer and size of the actual sound sample */
-         sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
-         sample_size =
-           MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
-         snd_ctrl.playingpos += sample_size;
-
-         /* fill the first mixing buffer with original sample */
-         memcpy(premix_first_buffer,sample_ptr,sample_size);
-
-
-         /* adjust volume of actual sound sample */
-         if (snd_ctrl.volume != PSND_MAX_VOLUME)
-           for(i=0;i<sample_size;i++)
-             premix_first_buffer[i] =
-               (snd_ctrl.volume * (int)premix_first_buffer[i])
-                 >> PSND_MAX_VOLUME_BITS;
-
-         for(i=0;i<sample_size;i++)
-           playing_buffer[i] =
-             linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
-
-         if (snd_ctrl.playingpos >= snd_ctrl.data_len)
-           playing_sounds = 0;
-
-         /* finally play the sound fragment */
-         write(sound_device,playing_buffer,sample_size);
-
-         delay.tv_sec = 0;
-         delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
-       }
-       close(sound_device);
-      }
-    }
-
-#endif /* !VOXWARE */
-
-  }
-#endif /* !MSDOS */
-}
-
-#ifdef MSDOS
-static void sound_handler(struct SoundControl snd_ctrl)
-{
-  int i;
-
-  if (snd_ctrl.fade_sound)
-  {
-    if (!playing_sounds)
-      return;
-
-    for (i=0; i<MAX_SOUNDS_PLAYING; i++)
-      if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
-         !playlist[i].fade_sound)
-      {
-       playlist[i].fade_sound = TRUE;
-       if (voice_check(playlist[i].voice))
-         voice_ramp_volume(playlist[i].voice, 1000, 0);
-       playlist[i].loop = PSND_NO_LOOP;
-      }
-  }
-  else if (snd_ctrl.stop_all_sounds)
-  {
-    if (!playing_sounds)
-      return;
-    SoundServer_StopAllSounds();
-  }
-  else if (snd_ctrl.stop_sound)
-  {
-    if (!playing_sounds)
-      return;
-    SoundServer_StopSound(snd_ctrl.nr);
-  }
-
-  for (i=0; i<MAX_SOUNDS_PLAYING; i++)
-  {
-    if (!playlist[i].active || playlist[i].loop)
-      continue;
-
-    playlist[i].playingpos = voice_get_position(playlist[i].voice);
-    playlist[i].volume = voice_get_volume(playlist[i].voice);
-    if (playlist[i].playingpos == -1 || !playlist[i].volume)
-    {
-      deallocate_voice(playlist[i].voice);
-      playlist[i] = emptySoundControl;
-      playing_sounds--;
-    }
-  }
-
-  if (snd_ctrl.active)
-    SoundServer_InsertNewSound(snd_ctrl);
-}
-#endif /* MSDOS */
-
-static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
-{
-  int i, k;
-
-  /* if playlist is full, remove oldest sound */
-  if (playing_sounds==MAX_SOUNDS_PLAYING)
-  {
-    int longest=0, longest_nr=0;
-
-    for(i=0;i<MAX_SOUNDS_PLAYING;i++)
-    {
-#ifndef MSDOS
-      int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
-#else
-      int actual = playlist[i].playingpos;
-#endif
-
-      if (!playlist[i].loop && actual>longest)
-      {
-       longest=actual;
-       longest_nr=i;
-      }
-    }
-#ifdef MSDOS
-    voice_set_volume(playlist[longest_nr].voice, 0);
-    deallocate_voice(playlist[longest_nr].voice);
-#endif
-    playlist[longest_nr] = emptySoundControl;
-    playing_sounds--;
-  }
-
-  /* check if sound is already being played (and how often) */
-  for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
-  {
-    if (playlist[i].nr == snd_ctrl.nr)
-      k++;
-  }
-
-  /* restart loop sounds only if they are just fading out */
-  if (k>=1 && snd_ctrl.loop)
-  {
-    for(i=0;i<MAX_SOUNDS_PLAYING;i++)
-    {
-      if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
-      {
-       playlist[i].fade_sound = FALSE;
-       playlist[i].volume = PSND_MAX_VOLUME;
-#ifdef MSDOS
-        playlist[i].loop = PSND_LOOP;
-        voice_stop_volumeramp(playlist[i].voice);
-        voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
-#endif
-      }
-    }
-    return;
-  }
-
-  /* don't play sound more than n times simultaneously (with n == 2 for now) */
-  if (k>=2)
-  {
-    int longest=0, longest_nr=0;
-
-    /* look for oldest equal sound */
-    for(i=0;i<MAX_SOUNDS_PLAYING;i++)
-    {
-      int actual;
-
-      if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
-       continue;
-
-#ifndef MSDOS
-      actual = 100 * playlist[i].playingpos / playlist[i].data_len;
-#else
-      actual = playlist[i].playingpos;
-#endif
-      if (actual>=longest)
-      {
-       longest=actual;
-       longest_nr=i;
-      }
-    }
-#ifdef MSDOS
-    voice_set_volume(playlist[longest_nr].voice, 0);
-    deallocate_voice(playlist[longest_nr].voice);
-#endif
-    playlist[longest_nr] = emptySoundControl;
-    playing_sounds--;
-  }
-
-  /* neuen Sound in Liste packen */
-  for(i=0;i<MAX_SOUNDS_PLAYING;i++)
-  {
-    if (!playlist[i].active)
-    {
-      playlist[i] = snd_ctrl;
-      playing_sounds++;
-#ifdef MSDOS
-      playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
-      if(snd_ctrl.loop)
-        voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
-      voice_set_volume(playlist[i].voice, snd_ctrl.volume);
-      voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
-      voice_start(playlist[i].voice);       
-#endif
-      break;
-    }
-  }
-}
-
-/*
-void SoundServer_FadeSound(int nr)
-{
-  int i;
-
-  if (!playing_sounds)
-    return;
-
-  for(i=0;i<MAX_SOUNDS_PLAYING;i++)
-    if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
-      playlist[i].fade_sound = TRUE;
-}
-*/
-
-#ifdef MSDOS
-static void SoundServer_StopSound(int nr)
-{
-  int i;
-
-  if (!playing_sounds)
-    return;
-
-  for(i=0;i<MAX_SOUNDS_PLAYING;i++)
-    if (playlist[i].nr == nr)
-    {
-#ifdef MSDOS
-      voice_set_volume(playlist[i].voice, 0);
-      deallocate_voice(playlist[i].voice);
-#endif
-      playlist[i] = emptySoundControl;
-      playing_sounds--;
-    }
-
-#ifndef MSDOS
-  if (!playing_sounds)
-    close(sound_device);
-#endif
-}
-
-static void SoundServer_StopAllSounds()
-{
-  int i;
-
-  for(i=0;i<MAX_SOUNDS_PLAYING;i++)
-  {
-#ifdef MSDOS
-    voice_set_volume(playlist[i].voice, 0);
-    deallocate_voice(playlist[i].voice);
-#endif
-    playlist[i]=emptySoundControl;
-  }
-  playing_sounds = 0;
-
-#ifndef MSDOS
-  close(sound_device);
-#endif
-}
-#endif /* MSDOS */
-
-#ifdef HPUX_AUDIO
-static void HPUX_Audio_Control()
-{
-  struct audio_describe ainfo;
-  int audio_ctl;
-
-  audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
-  if (audio_ctl == -1)
-    Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl - no sounds");
-
-  if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
-    Error(ERR_EXIT_SOUND_SERVER, "no audio info - no sounds");
-
-  if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
-    Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available - no sounds");
-
-  ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
-  ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
-
-  close(audio_ctl);
-}
-#endif /* HPUX_AUDIO */
-
-#ifndef VOXWARE
-#ifndef MSDOS
-/* these two are stolen from "sox"... :) */
-
-/*
-** This routine converts from linear to ulaw.
-**
-** Craig Reese: IDA/Supercomputing Research Center
-** Joe Campbell: Department of Defense
-** 29 September 1989
-**
-** References:
-** 1) CCITT Recommendation G.711  (very difficult to follow)
-** 2) "A New Digital Technique for Implementation of Any
-**     Continuous PCM Companding Law," Villeret, Michel,
-**     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
-**     1973, pg. 11.12-11.17
-** 3) MIL-STD-188-113,"Interoperability and Performance Standards
-**     for Analog-to_Digital Conversion Techniques,"
-**     17 February 1987
-**
-** Input: Signed 16 bit linear sample
-** Output: 8 bit ulaw sample
-*/
-
-#define ZEROTRAP    /* turn on the trap as per the MIL-STD */
-#define BIAS 0x84   /* define the add-in bias for 16 bit samples */
-#define CLIP 32635
-
-static unsigned char linear_to_ulaw(int sample)
-{
-  static int exp_lut[256] =
-  {
-    0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
-    4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
-    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
-  };
-
-  int sign, exponent, mantissa;
-  unsigned char ulawbyte;
-
-  /* Get the sample into sign-magnitude. */
-  sign = (sample >> 8) & 0x80;         /* set aside the sign */
-  if (sign != 0)
-    sample = -sample;                  /* get magnitude */
-  if (sample > CLIP)
-    sample = CLIP;                     /* clip the magnitude */
-
-  /* Convert from 16 bit linear to ulaw. */
-  sample = sample + BIAS;
-  exponent = exp_lut[( sample >> 7 ) & 0xFF];
-  mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
-  ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
-#ifdef ZEROTRAP
-  if (ulawbyte == 0)
-    ulawbyte = 0x02;                   /* optional CCITT trap */
-#endif
-
-  return(ulawbyte);
-}
-
-/*
-** This routine converts from ulaw to 16 bit linear.
-**
-** Craig Reese: IDA/Supercomputing Research Center
-** 29 September 1989
-**
-** References:
-** 1) CCITT Recommendation G.711  (very difficult to follow)
-** 2) MIL-STD-188-113,"Interoperability and Performance Standards
-**     for Analog-to_Digital Conversion Techniques,"
-**     17 February 1987
-**
-** Input: 8 bit ulaw sample
-** Output: signed 16 bit linear sample
-*/
-
-static int ulaw_to_linear(unsigned char ulawbyte)
-{
-  static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
-  int sign, exponent, mantissa, sample;
-
-  ulawbyte = ~ ulawbyte;
-  sign = ( ulawbyte & 0x80 );
-  exponent = ( ulawbyte >> 4 ) & 0x07;
-  mantissa = ulawbyte & 0x0F;
-  sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
-  if (sign != 0)
-    sample = -sample;
-
-  return(sample);
-}
-#endif /* !MSDOS */
-#endif /* !VOXWARE */
-
-/*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
-
-/*===========================================================================*/
-
-/*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
-
-#define CHUNK_ID_LEN            4       /* IFF style chunk id length */
-#define WAV_HEADER_SIZE                20      /* size of WAV file header */
-
-boolean LoadSound(struct SoundInfo *snd_info)
-{
-  char filename[256];
-  char *sound_ext = "wav";
-#ifndef MSDOS
-  byte sound_header_buffer[WAV_HEADER_SIZE];
-  char chunk[CHUNK_ID_LEN + 1];
-  int chunk_length, dummy;
-  FILE *file;
-  int i;
-#endif
-
-  sprintf(filename, "%s/%s/%s.%s",
-         options.ro_base_directory, SOUNDS_DIRECTORY,
-         snd_info->name, sound_ext);
-
-#ifndef MSDOS
-
-  if ((file = fopen(filename, "r")) == NULL)
-  {
-    Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
-    return FALSE;
-  }
-
-  /* read chunk "RIFF" */
-  getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
-  if (strcmp(chunk, "RIFF") != 0)
-  {
-    Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
-    fclose(file);
-    return FALSE;
-  }
-
-  /* read chunk "WAVE" */
-  getFileChunk(file, chunk, &dummy, BYTE_ORDER_LITTLE_ENDIAN);
-  if (strcmp(chunk, "WAVE") != 0)
-  {
-    Error(ERR_WARN, "missing 'WAVE' chunk of sound file '%s'", filename);
-    fclose(file);
-    return FALSE;
-  }
-
-  /* read header information */
-  for (i=0; i<WAV_HEADER_SIZE; i++)
-    sound_header_buffer[i] = fgetc(file);
-
-  /* read chunk "data" */
-  getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
-  if (strcmp(chunk, "data") != 0)
-  {
-    Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
-    fclose(file);
-    return FALSE;
-  }
-
-  snd_info->data_len = chunk_length;
-  snd_info->data_ptr = checked_malloc(snd_info->data_len);
-
-  /* read sound data */
-  if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
-      snd_info->data_len)
-  {
-    Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
-    fclose(file);
-    return FALSE;
-  }
-
-  fclose(file);
-
-  for (i=0; i<snd_info->data_len; i++)
-    snd_info->data_ptr[i] = snd_info->data_ptr[i] ^ 0x80;
-
-#else /* MSDOS */
-
-  snd_info->sample_ptr = load_sample(filename);
-  if (!snd_info->sample_ptr)
-  {
-    Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
-    return(FALSE);
-  }
-
-#endif /* MSDOS */
-
-  return(TRUE);
-}
-
-void PlaySound(int nr)
-{
-  PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
-}
-
-void PlaySoundStereo(int nr, int stereo)
-{
-  PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
-}
-
-void PlaySoundLoop(int nr)
-{
-  PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
-}
-
-void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
-{
-  struct SoundControl snd_ctrl = emptySoundControl;
-
-  if (sound_status==SOUND_OFF || !setup.sound)
-    return;
-
-  if (volume<PSND_MIN_VOLUME)
-    volume = PSND_MIN_VOLUME;
-  else if (volume>PSND_MAX_VOLUME)
-    volume = PSND_MAX_VOLUME;
-
-  if (stereo<PSND_MAX_LEFT)
-    stereo = PSND_MAX_LEFT;
-  else if (stereo>PSND_MAX_RIGHT)
-    stereo = PSND_MAX_RIGHT;
-
-  snd_ctrl.nr          = nr;
-  snd_ctrl.volume      = volume;
-  snd_ctrl.stereo      = stereo;
-  snd_ctrl.loop                = loop;
-  snd_ctrl.active      = TRUE;
-  snd_ctrl.data_ptr    = Sound[nr].data_ptr;
-  snd_ctrl.data_len    = Sound[nr].data_len;
-
-#ifndef MSDOS
-  if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
-  {
-    Error(ERR_WARN, "cannot pipe to child process - no sounds");
-    sound_status = SOUND_OFF;
-    return;
-  }
-#else
-  sound_handler(snd_ctrl);
-#endif
-}
-
-void FadeSound(int nr)
-{
-  StopSoundExt(nr, SSND_FADE_SOUND);
-}
-
-void FadeSounds()
-{
-  StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
-}
-
-void StopSound(int nr)
-{
-  StopSoundExt(nr, SSND_STOP_SOUND);
-}
-
-void StopSounds()
-{
-  StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
-}
-
-void StopSoundExt(int nr, int method)
-{
-  struct SoundControl snd_ctrl = emptySoundControl;
-
-  if (sound_status==SOUND_OFF)
-    return;
-
-  if (SSND_FADING(method))
-    snd_ctrl.fade_sound = TRUE;
-
-  if (SSND_ALL(method))
-    snd_ctrl.stop_all_sounds = TRUE;
-  else
-  {
-    snd_ctrl.nr = nr;
-    snd_ctrl.stop_sound = TRUE;
-  }
-
-#ifndef MSDOS
-  if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
-  {
-    Error(ERR_WARN, "cannot pipe to child process - no sounds");
-    sound_status = SOUND_OFF;
-    return;
-  }
-#else
-  sound_handler(snd_ctrl);
-#endif
-}
-
-void FreeSounds(int num_sounds)
-{
-  int i;
-
-  if (sound_status == SOUND_OFF)
-    return;
-
-  for(i=0; i<num_sounds; i++)
-#ifndef MSDOS
-    free(Sound[i].data_ptr);
-#else
-    destroy_sample(Sound[i].sample_ptr);
-#endif
-}
-
-/*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/
diff --git a/src/sound.h b/src/sound.h
deleted file mode 100644 (file)
index 2e93470..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
-*----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
-*----------------------------------------------------------*
-*  sound.c                                                 *
-***********************************************************/
-
-#ifndef SOUND_H
-#define SOUND_H
-
-#include <math.h>
-#include "main.h"
-
-#ifdef linux
-#include <linux/soundcard.h>
-#ifndef VOXWARE
-#define VOXWARE
-#endif
-
-#if 0
-/* where is the right declaration for 'ioctl'? */
-extern void ioctl(long, long, void *);
-#else
-#include <sys/ioctl.h>
-#endif
-
-#endif
-
-#ifdef __FreeBSD__
-#include <machine/soundcard.h>
-#endif
-
-#define SND_BLOCKSIZE 4096
-
-#ifdef _HPUX_SOURCE
-#include <sys/audio.h>
-#undef  SND_BLOCKSIZE
-#define SND_BLOCKSIZE 32768
-#define HPUX_AUDIO
-#endif /* _HPUX_SOURCE */
-
-#ifndef MSDOS
-#define MAX_SOUNDS_PLAYING     16
-#else
-#define MAX_SOUNDS_PLAYING     8
-#endif
-
-/* some values for PlaySound(), StopSound() and friends */
-#ifndef MSDOS
-#define PSND_SILENCE           0
-#define PSND_MAX_VOLUME_BITS   7
-#define PSND_MIN_VOLUME                0
-#define PSND_MAX_VOLUME                (1 << PSND_MAX_VOLUME_BITS)
-#define PSND_NO_LOOP           0
-#define PSND_LOOP              1
-#define PSND_MIDDLE            0
-#define PSND_MAX_STEREO_BITS   7
-#define PSND_MAX_STEREO                (1 << PSND_MAX_STEREO_BITS)
-#define PSND_MAX_LEFT          (-PSND_MAX_STEREO)
-#define PSND_MAX_RIGHT         (+PSND_MAX_STEREO)
-#define PSND_MAX_LEFT2RIGHT_BITS (PSND_MAX_STEREO_BITS+1)
-#define PSND_MAX_LEFT2RIGHT    (1 << PSND_MAX_LEFT2RIGHT_BITS)
-#else
-#define PSND_SILENCE           0
-#define PSND_MIN_VOLUME                0
-#define PSND_MAX_VOLUME                255
-#define PSND_NO_LOOP           0
-#define PSND_LOOP              1
-#define PSND_MAX_LEFT          0
-#define PSND_MAX_RIGHT         255
-#define PSND_MIDDLE            128
-#endif
-
-#define SSND_FADE_SOUND                (1<<0)
-#define SSND_FADE_ALL_SOUNDS   (1<<1)
-#define SSND_FADING(x)         (x & (SSND_FADE_SOUND | SSND_FADE_ALL_SOUNDS))
-#define SSND_STOP_SOUND                (1<<2)
-#define SSND_STOP_ALL_SOUNDS   (1<<3)
-#define SSND_STOPPING(x)       (x & (SSND_STOP_SOUND | SSND_STOP_ALL_SOUNDS))
-#define SSND_ALL(x)            (x&(SSND_FADE_ALL_SOUNDS|SSND_STOP_ALL_SOUNDS))
-
-/* settings for sound path, sound device, etc. */
-#ifndef SND_PATH
-#define SND_PATH       "./sounds"
-#endif
-
-#define DEV_AUDIO      "/dev/audio"
-#define DEV_DSP                "/dev/dsp"
-
-#ifdef VOXWARE
-#define SOUND_DEVICE           DEV_DSP
-#else
-#define SOUND_DEVICE   DEV_AUDIO
-#endif
-
-#define SOUND_OFF      0
-#define        SOUND_AVAILABLE 1
-
-#ifdef NO_SOUNDS
-#define SOUND_STATUS   SOUND_OFF
-#else
-#define SOUND_STATUS   SOUND_AVAILABLE
-#endif
-
-struct SoundHeader_SUN
-{
-  unsigned long magic;
-  unsigned long hdr_size;
-  unsigned long data_size;
-  unsigned long encoding;
-  unsigned long sample_rate;
-  unsigned long channels;
-};
-
-struct SoundHeader_8SVX
-{
-  char magic_FORM[4];
-  unsigned long chunk_size;
-  char magic_8SVX[4];
-};
-
-struct SoundInfo
-{ 
-  char *name;
-  byte *data_ptr;
-  long data_len;
-#ifdef MSDOS
-  SAMPLE *sample_ptr;
-#endif
-};
-
-struct SoundControl
-{
-  int nr;
-  int volume;
-  int stereo;
-  boolean active;
-  boolean loop;
-  boolean fade_sound;
-  boolean stop_sound;
-  boolean stop_all_sounds;
-  int playingtime;
-  long playingpos;
-  long data_len;
-  byte *data_ptr;
-#ifdef MSDOS
-  int voice;
-#endif
-};
-
-/* start sound server */
-void SoundServer(void);
-
-/* client functions */
-boolean LoadSound(struct SoundInfo *);
-void PlaySound(int);
-void PlaySoundStereo(int, int);
-void PlaySoundLoop(int);
-void PlaySoundExt(int, int, int, boolean);
-void FadeSound(int);
-void FadeSounds(void);
-void StopSound(int);
-void StopSounds(void);
-void StopSoundExt(int, int);
-void FreeSounds(int);
-
-#endif
index 15a8dc2098973ee82bf3654264fac7f5e4a7657d..05d5956cb117dcf5a25061652a424587f1c6f05c 100644 (file)
@@ -1,20 +1,20 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  tape.c                                                  *
+* tape.c                                                   *
 ***********************************************************/
 
+#include "libgame/libgame.h"
+
 #include "tape.h"
-#include "misc.h"
 #include "game.h"
-#include "buttons.h"
 #include "tools.h"
 #include "files.h"
 #include "network.h"
@@ -33,6 +33,258 @@ static void HandleTapeButtons(struct GadgetInfo *);
 
 static struct GadgetInfo *tape_gadget[NUM_TAPE_BUTTONS];
 
+
+/* ========================================================================= */
+/* video tape definitions                                                    */
+/* ========================================================================= */
+
+/* some positions in the video tape control window */
+#define VIDEO_DATE_LABEL_XPOS  (VIDEO_DISPLAY1_XPOS)
+#define VIDEO_DATE_LABEL_YPOS  (VIDEO_DISPLAY1_YPOS)
+#define VIDEO_DATE_LABEL_XSIZE (VIDEO_DISPLAY_XSIZE)
+#define VIDEO_DATE_LABEL_YSIZE (VIDEO_DISPLAY_YSIZE)
+#define VIDEO_DATE_XPOS                (VIDEO_DISPLAY1_XPOS + 1)
+#define VIDEO_DATE_YPOS                (VIDEO_DISPLAY1_YPOS + 14)
+#define VIDEO_DATE_XSIZE       (VIDEO_DISPLAY_XSIZE)
+#define VIDEO_DATE_YSIZE       16
+#define VIDEO_REC_LABEL_XPOS   (VIDEO_DISPLAY2_XPOS)
+#define VIDEO_REC_LABEL_YPOS   (VIDEO_DISPLAY2_YPOS)
+#define VIDEO_REC_LABEL_XSIZE  20
+#define VIDEO_REC_LABEL_YSIZE  12
+#define VIDEO_REC_SYMBOL_XPOS  (VIDEO_DISPLAY2_XPOS + 20)
+#define VIDEO_REC_SYMBOL_YPOS  (VIDEO_DISPLAY2_YPOS)
+#define VIDEO_REC_SYMBOL_XSIZE 16
+#define VIDEO_REC_SYMBOL_YSIZE 16
+#define VIDEO_PLAY_LABEL_XPOS  (VIDEO_DISPLAY2_XPOS + 65)
+#define VIDEO_PLAY_LABEL_YPOS  (VIDEO_DISPLAY2_YPOS)
+#define VIDEO_PLAY_LABEL_XSIZE 22
+#define VIDEO_PLAY_LABEL_YSIZE 12
+#define VIDEO_PLAY_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS + 52)
+#define VIDEO_PLAY_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS)
+#define VIDEO_PLAY_SYMBOL_XSIZE        11
+#define VIDEO_PLAY_SYMBOL_YSIZE        13
+#define VIDEO_PAUSE_LABEL_XPOS (VIDEO_DISPLAY2_XPOS)
+#define VIDEO_PAUSE_LABEL_YPOS (VIDEO_DISPLAY2_YPOS + 20)
+#define VIDEO_PAUSE_LABEL_XSIZE        35
+#define VIDEO_PAUSE_LABEL_YSIZE        8
+#define VIDEO_PAUSE_SYMBOL_XPOS        (VIDEO_DISPLAY2_XPOS + 35)
+#define VIDEO_PAUSE_SYMBOL_YPOS        (VIDEO_DISPLAY2_YPOS)
+#define VIDEO_PAUSE_SYMBOL_XSIZE 17
+#define VIDEO_PAUSE_SYMBOL_YSIZE 13
+#define VIDEO_TIME_XPOS                (VIDEO_DISPLAY2_XPOS + 38)
+#define VIDEO_TIME_YPOS                (VIDEO_DISPLAY2_YPOS + 14)
+#define VIDEO_TIME_XSIZE       50
+#define VIDEO_TIME_YSIZE       16
+
+/* special */
+#define VIDEO_PBEND_LABEL_XPOS 6
+#define VIDEO_PBEND_LABEL_YPOS 220
+#define VIDEO_PBEND_LABEL_XSIZE        35
+#define VIDEO_PBEND_LABEL_YSIZE        30
+
+#define VIDEO_STATE_OFF                (VIDEO_STATE_PLAY_OFF   |       \
+                                VIDEO_STATE_REC_OFF    |       \
+                                VIDEO_STATE_PAUSE_OFF  |       \
+                                VIDEO_STATE_FFWD_OFF   |       \
+                                VIDEO_STATE_PBEND_OFF  |       \
+                                VIDEO_STATE_DATE_OFF   |       \
+                                VIDEO_STATE_TIME_OFF)
+#define VIDEO_PRESS_OFF                (VIDEO_PRESS_PLAY_OFF   |       \
+                                VIDEO_PRESS_REC_OFF    |       \
+                                VIDEO_PRESS_PAUSE_OFF  |       \
+                                VIDEO_PRESS_STOP_OFF   |       \
+                                VIDEO_PRESS_EJECT_OFF)
+#define VIDEO_ALL_OFF          (VIDEO_STATE_OFF | VIDEO_PRESS_OFF)
+
+#define VIDEO_STATE_ON         (VIDEO_STATE_PLAY_ON    |       \
+                                VIDEO_STATE_REC_ON     |       \
+                                VIDEO_STATE_PAUSE_ON   |       \
+                                VIDEO_STATE_FFWD_ON    |       \
+                                VIDEO_STATE_PBEND_ON   |       \
+                                VIDEO_STATE_DATE_ON    |       \
+                                VIDEO_STATE_TIME_ON)
+#define VIDEO_PRESS_ON         (VIDEO_PRESS_PLAY_ON    |       \
+                                VIDEO_PRESS_REC_ON     |       \
+                                VIDEO_PRESS_PAUSE_ON   |       \
+                                VIDEO_PRESS_STOP_ON    |       \
+                                VIDEO_PRESS_EJECT_ON)
+#define VIDEO_ALL_ON           (VIDEO_STATE_ON | VIDEO_PRESS_ON)
+
+#define VIDEO_STATE            (VIDEO_STATE_ON | VIDEO_STATE_OFF)
+#define VIDEO_PRESS            (VIDEO_PRESS_ON | VIDEO_PRESS_OFF)
+#define VIDEO_ALL              (VIDEO_ALL_ON | VIDEO_ALL_OFF)
+
+
+/* ========================================================================= */
+/* video display functions                                                   */
+/* ========================================================================= */
+
+void DrawVideoDisplay(unsigned long state, unsigned long value)
+{
+  int i;
+  int part_label = 0, part_symbol = 1;
+  int xpos = 0, ypos = 1, xsize = 2, ysize = 3;
+  static char *monatsname[12] =
+  {
+    "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
+    "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
+  };
+  static int video_pos[5][2][4] =
+  {
+    {{ VIDEO_PLAY_LABEL_XPOS, VIDEO_PLAY_LABEL_YPOS,
+       VIDEO_PLAY_LABEL_XSIZE,VIDEO_PLAY_LABEL_YSIZE },
+     { VIDEO_PLAY_SYMBOL_XPOS, VIDEO_PLAY_SYMBOL_YPOS,
+       VIDEO_PLAY_SYMBOL_XSIZE,VIDEO_PLAY_SYMBOL_YSIZE }},
+
+    {{ VIDEO_REC_LABEL_XPOS, VIDEO_REC_LABEL_YPOS,
+       VIDEO_REC_LABEL_XSIZE,VIDEO_REC_LABEL_YSIZE },
+     { VIDEO_REC_SYMBOL_XPOS, VIDEO_REC_SYMBOL_YPOS,
+       VIDEO_REC_SYMBOL_XSIZE,VIDEO_REC_SYMBOL_YSIZE }},
+
+    {{ VIDEO_PAUSE_LABEL_XPOS, VIDEO_PAUSE_LABEL_YPOS,
+       VIDEO_PAUSE_LABEL_XSIZE,VIDEO_PAUSE_LABEL_YSIZE },
+     { VIDEO_PAUSE_SYMBOL_XPOS, VIDEO_PAUSE_SYMBOL_YPOS,
+       VIDEO_PAUSE_SYMBOL_XSIZE,VIDEO_PAUSE_SYMBOL_YSIZE }},
+
+    {{ VIDEO_DATE_LABEL_XPOS, VIDEO_DATE_LABEL_YPOS,
+       VIDEO_DATE_LABEL_XSIZE,VIDEO_DATE_LABEL_YSIZE },
+     { VIDEO_DATE_XPOS, VIDEO_DATE_YPOS,
+       VIDEO_DATE_XSIZE,VIDEO_DATE_YSIZE }},
+
+    {{ 0,0,
+       0,0 },
+     { VIDEO_TIME_XPOS, VIDEO_TIME_YPOS,
+       VIDEO_TIME_XSIZE,VIDEO_TIME_YSIZE }}
+  };
+
+  if (state & VIDEO_STATE_PBEND_OFF)
+  {
+    int cx = DOOR_GFX_PAGEX3, cy = DOOR_GFX_PAGEY2;
+
+    BlitBitmap(pix[PIX_DOOR], drawto,
+              cx + VIDEO_REC_LABEL_XPOS,
+              cy + VIDEO_REC_LABEL_YPOS,
+              VIDEO_PBEND_LABEL_XSIZE,
+              VIDEO_PBEND_LABEL_YSIZE,
+              VX + VIDEO_REC_LABEL_XPOS,
+              VY + VIDEO_REC_LABEL_YPOS);
+  }
+
+  for(i=0;i<10;i++)
+  {
+    if (state & (1<<i))
+    {
+      int pos = i/2, cx, cy = DOOR_GFX_PAGEY2;
+
+      if (i%2)                 /* i ungerade => STATE_ON / PRESS_OFF */
+       cx = DOOR_GFX_PAGEX4;
+      else
+       cx = DOOR_GFX_PAGEX3;   /* i gerade => STATE_OFF / PRESS_ON */
+
+      if (video_pos[pos][part_label][0] && value != VIDEO_DISPLAY_SYMBOL_ONLY)
+       BlitBitmap(pix[PIX_DOOR], drawto,
+                  cx + video_pos[pos][part_label][xpos],
+                  cy + video_pos[pos][part_label][ypos],
+                  video_pos[pos][part_label][xsize],
+                  video_pos[pos][part_label][ysize],
+                  VX + video_pos[pos][part_label][xpos],
+                  VY + video_pos[pos][part_label][ypos]);
+      if (video_pos[pos][part_symbol][0] && value != VIDEO_DISPLAY_LABEL_ONLY)
+       BlitBitmap(pix[PIX_DOOR], drawto,
+                  cx + video_pos[pos][part_symbol][xpos],
+                  cy + video_pos[pos][part_symbol][ypos],
+                  video_pos[pos][part_symbol][xsize],
+                  video_pos[pos][part_symbol][ysize],
+                  VX + video_pos[pos][part_symbol][xpos],
+                  VY + video_pos[pos][part_symbol][ypos]);
+    }
+  }
+
+  if (state & VIDEO_STATE_FFWD_ON)
+  {
+    int cx = DOOR_GFX_PAGEX4, cy = DOOR_GFX_PAGEY2;
+
+    BlitBitmap(pix[PIX_DOOR], drawto,
+              cx + VIDEO_PLAY_SYMBOL_XPOS,
+              cy + VIDEO_PLAY_SYMBOL_YPOS,
+              VIDEO_PLAY_SYMBOL_XSIZE - 2,
+              VIDEO_PLAY_SYMBOL_YSIZE,
+              VX + VIDEO_PLAY_SYMBOL_XPOS - 9,
+              VY + VIDEO_PLAY_SYMBOL_YPOS);
+  }
+
+  if (state & VIDEO_STATE_PBEND_ON)
+  {
+    int cx = DOOR_GFX_PAGEX6, cy = DOOR_GFX_PAGEY1;
+
+    BlitBitmap(pix[PIX_DOOR], drawto,
+              cx + VIDEO_PBEND_LABEL_XPOS,
+              cy + VIDEO_PBEND_LABEL_YPOS,
+              VIDEO_PBEND_LABEL_XSIZE,
+              VIDEO_PBEND_LABEL_YSIZE,
+              VX + VIDEO_REC_LABEL_XPOS,
+              VY + VIDEO_REC_LABEL_YPOS);
+  }
+
+  if (state & VIDEO_STATE_DATE_ON)
+  {
+    int tag = value % 100;
+    int monat = (value/100) % 100;
+    int jahr = (value/10000);
+
+    DrawText(VX+VIDEO_DATE_XPOS,VY+VIDEO_DATE_YPOS,
+            int2str(tag,2),FS_SMALL,FC_SPECIAL1);
+    DrawText(VX+VIDEO_DATE_XPOS+27,VY+VIDEO_DATE_YPOS,
+            monatsname[monat],FS_SMALL,FC_SPECIAL1);
+    DrawText(VX+VIDEO_DATE_XPOS+64,VY+VIDEO_DATE_YPOS,
+            int2str(jahr,2),FS_SMALL,FC_SPECIAL1);
+  }
+
+  if (state & VIDEO_STATE_TIME_ON)
+  {
+    int min = value / 60;
+    int sec = value % 60;
+
+    DrawText(VX+VIDEO_TIME_XPOS,VY+VIDEO_TIME_YPOS,
+            int2str(min,2),FS_SMALL,FC_SPECIAL1);
+    DrawText(VX+VIDEO_TIME_XPOS+27,VY+VIDEO_TIME_YPOS,
+            int2str(sec,2),FS_SMALL,FC_SPECIAL1);
+  }
+
+  if (state & VIDEO_STATE_DATE)
+    redraw_mask |= REDRAW_VIDEO_1;
+  if ((state & ~VIDEO_STATE_DATE) & VIDEO_STATE)
+    redraw_mask |= REDRAW_VIDEO_2;
+  if (state & VIDEO_PRESS)
+    redraw_mask |= REDRAW_VIDEO_3;
+}
+
+void DrawCompleteVideoDisplay()
+{
+  BlitBitmap(pix[PIX_DOOR], drawto, DOOR_GFX_PAGEX3, DOOR_GFX_PAGEY2,
+            gfx.vxsize, gfx.vysize, gfx.vx, gfx.vy);
+  BlitBitmap(pix[PIX_DOOR], drawto,
+            DOOR_GFX_PAGEX4 + VIDEO_CONTROL_XPOS,
+            DOOR_GFX_PAGEY2 + VIDEO_CONTROL_YPOS,
+            VIDEO_CONTROL_XSIZE, VIDEO_CONTROL_YSIZE,
+            gfx.vx + VIDEO_CONTROL_XPOS, gfx.vy + VIDEO_CONTROL_YPOS);
+
+  DrawVideoDisplay(VIDEO_ALL_OFF, 0);
+  if (tape.date && tape.length)
+  {
+    DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
+    DrawVideoDisplay(VIDEO_STATE_TIME_ON, tape.length_seconds);
+  }
+
+  BlitBitmap(drawto, pix[PIX_DB_DOOR], gfx.vx, gfx.vy, gfx.vxsize, gfx.vysize,
+            DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
+}
+
+
+/* ========================================================================= */
+/* tape control functions                                                    */
+/* ========================================================================= */
+
 void TapeStartRecording()
 {
   time_t zeit1 = time(NULL);
@@ -220,7 +472,7 @@ boolean TapePlayDelay()
        DrawVideoDisplay(VIDEO_STATE_PBEND_OFF, VIDEO_DISPLAY_LABEL_ONLY);
     }
 
-    if (TimePlayed > tape.length_seconds - PAUSE_SECONDS_BEFORE_DEATH)
+    if (TimePlayed > tape.length_seconds - TAPE_PAUSE_SECONDS_BEFORE_DEATH)
     {
       TapeTogglePause();
       return(FALSE);
@@ -328,7 +580,7 @@ void CreateTapeButtons()
 
   for (i=0; i<NUM_TAPE_BUTTONS; i++)
   {
-    Pixmap gd_pixmap = pix[PIX_DOOR];
+    Bitmap *gd_bitmap = pix[PIX_DOOR];
     struct GadgetInfo *gi;
     int gd_xoffset, gd_yoffset;
     int gd_x1, gd_x2, gd_y;
@@ -348,8 +600,8 @@ void CreateTapeButtons()
                      GDI_HEIGHT, TAPE_BUTTON_YSIZE,
                      GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
                      GDI_STATE, GD_BUTTON_UNPRESSED,
-                     GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
-                     GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
+                     GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
+                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
                      GDI_EVENT_MASK, GD_EVENT_RELEASED,
                      GDI_CALLBACK_ACTION, HandleTapeButtons,
                      GDI_END);
@@ -416,7 +668,7 @@ static void HandleTapeButtons(struct GadgetInfo *gi)
       {
        TapeStartRecording();
 
-#ifndef MSDOS
+#if defined(PLATFORM_UNIX)
        if (options.network)
          SendToServer_StartPlaying();
        else
index 1f2a4d8fe6a5b09cf03161ff10d766cf164b9753..b41d9f3cd951d79ba1fe059224b3e1bc3f56f1e8 100644 (file)
@@ -1,14 +1,14 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  tape.c                                                  *
+* tape.h                                                   *
 ***********************************************************/
 
 #ifndef TAPE_H
 
 #include "main.h"
 
-#define PAUSE_SECONDS_BEFORE_DEATH     3
+#define TAPE_PAUSE_SECONDS_BEFORE_DEATH                3
+
+/* some positions in the video tape control window */
+#define VIDEO_DISPLAY1_XPOS    5
+#define VIDEO_DISPLAY1_YPOS    5
+#define VIDEO_DISPLAY2_XPOS    5
+#define VIDEO_DISPLAY2_YPOS    41
+#define VIDEO_DISPLAY_XSIZE    90
+#define VIDEO_DISPLAY_YSIZE    31
+#define VIDEO_BUTTON_XSIZE     18
+#define VIDEO_BUTTON_YSIZE     18
+#define VIDEO_CONTROL_XPOS     5
+#define VIDEO_CONTROL_YPOS     77
+#define VIDEO_CONTROL_XSIZE    VIDEO_DISPLAY_XSIZE
+#define VIDEO_CONTROL_YSIZE    VIDEO_BUTTON_YSIZE
+
+/* values for video tape control */
+#define VIDEO_STATE_PLAY_OFF   (1L << 0)
+#define VIDEO_STATE_PLAY_ON    (1L << 1)
+#define VIDEO_STATE_PLAY       (VIDEO_STATE_PLAY_OFF   | VIDEO_STATE_PLAY_ON)
+#define VIDEO_STATE_REC_OFF    (1L << 2)
+#define VIDEO_STATE_REC_ON     (1L << 3)
+#define VIDEO_STATE_REC                (VIDEO_STATE_REC_OFF    | VIDEO_STATE_REC_ON)
+#define VIDEO_STATE_PAUSE_OFF  (1L << 4)
+#define VIDEO_STATE_PAUSE_ON   (1L << 5)
+#define VIDEO_STATE_PAUSE      (VIDEO_STATE_PAUSE_OFF  | VIDEO_STATE_PAUSE_ON)
+#define VIDEO_STATE_DATE_OFF   (1L << 6)
+#define VIDEO_STATE_DATE_ON    (1L << 7)
+#define VIDEO_STATE_DATE       (VIDEO_STATE_DATE_OFF   | VIDEO_STATE_DATE_ON)
+#define VIDEO_STATE_TIME_OFF   (1L << 8)
+#define VIDEO_STATE_TIME_ON    (1L << 9)
+#define VIDEO_STATE_TIME       (VIDEO_STATE_TIME_OFF   | VIDEO_STATE_TIME_ON)
+#define VIDEO_PRESS_PLAY_ON    (1L << 10)
+#define VIDEO_PRESS_PLAY_OFF   (1L << 11)
+#define VIDEO_PRESS_PLAY       (VIDEO_PRESS_PLAY_OFF   | VIDEO_PRESS_PLAY_ON)
+#define VIDEO_PRESS_REC_ON     (1L << 12)
+#define VIDEO_PRESS_REC_OFF    (1L << 13)
+#define VIDEO_PRESS_REC                (VIDEO_PRESS_REC_OFF    | VIDEO_PRESS_REC_ON)
+#define VIDEO_PRESS_PAUSE_ON   (1L << 14)
+#define VIDEO_PRESS_PAUSE_OFF  (1L << 15)
+#define VIDEO_PRESS_PAUSE      (VIDEO_PRESS_PAUSE_OFF  | VIDEO_PRESS_PAUSE_ON)
+#define VIDEO_PRESS_STOP_ON    (1L << 16)
+#define VIDEO_PRESS_STOP_OFF   (1L << 17)
+#define VIDEO_PRESS_STOP       (VIDEO_PRESS_STOP_OFF   | VIDEO_PRESS_STOP_ON)
+#define VIDEO_PRESS_EJECT_ON   (1L << 18)
+#define VIDEO_PRESS_EJECT_OFF  (1L << 19)
+#define VIDEO_PRESS_EJECT      (VIDEO_PRESS_EJECT_OFF  | VIDEO_PRESS_EJECT_ON)
+
+/* special */
+#define VIDEO_STATE_FFWD_OFF   ((1L << 20) | VIDEO_STATE_PAUSE_OFF)
+#define VIDEO_STATE_FFWD_ON    (1L << 21)
+#define VIDEO_STATE_FFWD       (VIDEO_STATE_FFWD_OFF   | VIDEO_STATE_FFWD_ON)
+#define VIDEO_STATE_PBEND_OFF  (1L << 22)
+#define VIDEO_STATE_PBEND_ON   (1L << 23)
+#define VIDEO_STATE_PBEND      (VIDEO_STATE_PBEND_OFF  | VIDEO_STATE_PBEND_ON)
+
+/* tags to draw video display labels or symbols only */
+#define VIDEO_DISPLAY_DEFAULT          0
+#define VIDEO_DISPLAY_LABEL_ONLY       1
+#define VIDEO_DISPLAY_SYMBOL_ONLY      2
+
+
+void DrawVideoDisplay(unsigned long, unsigned long);
+void DrawCompleteVideoDisplay(void);
 
 void TapeStartRecording(void);
 void TapeStopRecording(void);
index 775bc0dc9dae4c4e3997e9143784a5ac893d7b05..3bd370dcfd4c0993863f6b2f4b58093ea31d90ef 100644 (file)
@@ -1,33 +1,33 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  tools.c                                                 *
+* tools.c                                                  *
 ***********************************************************/
 
 #include <stdarg.h>
 
-#ifdef __FreeBSD__
+#if defined(PLATFORM_FREEBSD)
 #include <machine/joystick.h>
 #endif
 
+#include "libgame/libgame.h"
+
 #include "tools.h"
 #include "game.h"
 #include "events.h"
-#include "sound.h"
-#include "misc.h"
-#include "buttons.h"
 #include "joystick.h"
 #include "cartoons.h"
 #include "network.h"
+#include "tape.h"
 
-#ifdef MSDOS
+#if defined(PLATFORM_MSDOS)
 extern boolean wait_for_vsync;
 #endif
 
@@ -85,7 +85,7 @@ void SetDrawtoField(int mode)
 void BackToFront()
 {
   int x,y;
-  Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
+  DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
 
   if (setup.direct_draw && game_status == PLAYING)
     redraw_mask &= ~REDRAW_MAIN;
@@ -99,18 +99,46 @@ void BackToFront()
   if (!redraw_mask)
     return;
 
+  if (global.fps_slowdown && game_status == PLAYING)
+  {
+    static boolean last_frame_skipped = FALSE;
+    boolean skip_even_when_not_scrolling = TRUE;
+    boolean just_scrolling = (ScreenMovDir != 0);
+    boolean verbose = FALSE;
+
+    if (global.fps_slowdown_factor > 1 &&
+       (FrameCounter % global.fps_slowdown_factor) &&
+       (just_scrolling || skip_even_when_not_scrolling))
+    {
+      redraw_mask &= ~REDRAW_MAIN;
+
+      last_frame_skipped = TRUE;
+
+      if (verbose)
+       printf("FRAME SKIPPED\n");
+    }
+    else
+    {
+      if (last_frame_skipped)
+       redraw_mask |= REDRAW_FIELD;
+
+      last_frame_skipped = FALSE;
+
+      if (verbose)
+       printf("frame not skipped\n");
+    }
+  }
+
   /* synchronize X11 graphics at this point; if we would synchronize the
      display immediately after the buffer switching (after the XFlush),
      this could mean that we have to wait for the graphics to complete,
      although we could go on doing calculations for the next frame */
 
-  XSync(display, FALSE);
+  SyncDisplay();
 
   if (redraw_mask & REDRAW_ALL)
   {
-    XCopyArea(display, backbuffer, window, gc,
-             0, 0, WIN_XSIZE, WIN_YSIZE,
-             0, 0);
+    BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
     redraw_mask = 0;
   }
 
@@ -118,9 +146,8 @@ void BackToFront()
   {
     if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
     {
-      XCopyArea(display, backbuffer, window, gc,
-               REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
-               REAL_SX, REAL_SY);
+      BlitBitmap(backbuffer, window,
+                REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
     }
     else
     {
@@ -137,7 +164,7 @@ void BackToFront()
          ABS(ScreenMovPos) == ScrollStepSize ||
          redraw_tiles > REDRAWTILES_THRESHOLD)
       {
-       XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
+       BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
 
 #ifdef DEBUG
 #if 0
@@ -154,55 +181,50 @@ void BackToFront()
 #endif
       }
     }
+
     redraw_mask &= ~REDRAW_MAIN;
   }
 
   if (redraw_mask & REDRAW_DOORS)
   {
     if (redraw_mask & REDRAW_DOOR_1)
-      XCopyArea(display, backbuffer, window, gc,
-               DX, DY, DXSIZE, DYSIZE,
-               DX, DY);
+      BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
     if (redraw_mask & REDRAW_DOOR_2)
     {
       if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
-       XCopyArea(display,backbuffer,window,gc,
-                 VX,VY, VXSIZE,VYSIZE,
-                 VX,VY);
+       BlitBitmap(backbuffer, window, VX,VY, VXSIZE,VYSIZE, VX,VY);
       else
       {
        if (redraw_mask & REDRAW_VIDEO_1)
-         XCopyArea(display,backbuffer,window,gc,
-                   VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
-                   VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
-                   VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
+         BlitBitmap(backbuffer, window,
+                    VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
+                    VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
+                    VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
        if (redraw_mask & REDRAW_VIDEO_2)
-         XCopyArea(display,backbuffer,window,gc,
-                   VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
-                   VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
-                   VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
+         BlitBitmap(backbuffer, window,
+                    VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
+                    VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
+                    VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
        if (redraw_mask & REDRAW_VIDEO_3)
-         XCopyArea(display,backbuffer,window,gc,
-                   VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
-                   VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
-                   VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
+         BlitBitmap(backbuffer, window,
+                    VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
+                    VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
+                    VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
       }
     }
     if (redraw_mask & REDRAW_DOOR_3)
-      XCopyArea(display, backbuffer, window, gc,
-               EX, EY, EXSIZE, EYSIZE,
-               EX, EY);
+      BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
     redraw_mask &= ~REDRAW_DOORS;
   }
 
   if (redraw_mask & REDRAW_MICROLEVEL)
   {
-    XCopyArea(display,backbuffer,window,gc,
-             MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
-             MICROLEV_XPOS, MICROLEV_YPOS);
-    XCopyArea(display,backbuffer,window,gc,
-             SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
-             SX, MICROLABEL_YPOS);
+    BlitBitmap(backbuffer, window,
+              MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
+              MICROLEV_XPOS, MICROLEV_YPOS);
+    BlitBitmap(backbuffer, window,
+              SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
+              SX, MICROLABEL_YPOS);
     redraw_mask &= ~REDRAW_MICROLEVEL;
   }
 
@@ -211,12 +233,25 @@ void BackToFront()
     for(x=0; x<SCR_FIELDX; x++)
       for(y=0; y<SCR_FIELDY; y++)
        if (redraw[redraw_x1 + x][redraw_y1 + y])
-         XCopyArea(display, buffer, window, gc,
-                   FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
-                   SX + x * TILEX, SY + y * TILEY);
+         BlitBitmap(buffer, window,
+                    FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
+                    SX + x * TILEX, SY + y * TILEY);
+  }
+
+  if (redraw_mask & REDRAW_FPS)                /* display frames per second */
+  {
+    char text[100];
+    char info1[100];
+
+    sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
+    if (!global.fps_slowdown)
+      info1[0] = '\0';
+
+    sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
+    DrawTextExt(window, SX, SY, text, FS_SMALL, FC_YELLOW);
   }
 
-  XFlush(display);
+  FlushDisplay();
 
   for(x=0; x<MAX_BUF_XSIZE; x++)
     for(y=0; y<MAX_BUF_YSIZE; y++)
@@ -227,80 +262,82 @@ void BackToFront()
 
 void FadeToFront()
 {
-/*
+#if 0
   long fading_delay = 300;
 
   if (setup.fading && (redraw_mask & REDRAW_FIELD))
   {
-*/
+#endif
 
-/*
+#if 0
     int x,y;
 
-    XFillRectangle(display,window,gc,
-                  REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
-    XFlush(display);
+    ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
+    FlushDisplay();
 
     for(i=0;i<2*FULL_SYSIZE;i++)
     {
       for(y=0;y<FULL_SYSIZE;y++)
       {
-       XCopyArea(display,backbuffer,window,gc,
-                 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
+       BlitBitmap(backbuffer, window,
+                  REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
       }
-      XFlush(display);
+      FlushDisplay();
       Delay(10);
     }
-*/
+#endif
 
-/*
+#if 0
     for(i=1;i<FULL_SYSIZE;i+=2)
-      XCopyArea(display,backbuffer,window,gc,
-               REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
-    XFlush(display);
+      BlitBitmap(backbuffer, window,
+                REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
+    FlushDisplay();
     Delay(fading_delay);
-*/
+#endif
 
-/*
-    XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
-    XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
-             REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
-    XFlush(display);
+#if 0
+    SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
+    BlitBitmapMasked(backbuffer, window,
+                    REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
+                    REAL_SX,REAL_SY);
+    FlushDisplay();
     Delay(fading_delay);
 
-    XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
-    XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
-             REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
-    XFlush(display);
+    SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
+    BlitBitmapMasked(backbuffer, window,
+                    REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
+                    REAL_SX,REAL_SY);
+    FlushDisplay();
     Delay(fading_delay);
 
-    XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
-    XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
-             REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
-    XFlush(display);
+    SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
+    BlitBitmapMasked(backbuffer, window,
+                    REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
+                    REAL_SX,REAL_SY);
+    FlushDisplay();
     Delay(fading_delay);
 
-    XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
-    XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
-             REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
-    XFlush(display);
+    SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
+    BlitBitmapMasked(backbuffer, window,
+                    REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
+                    REAL_SX,REAL_SY);
+    FlushDisplay();
     Delay(fading_delay);
 
     redraw_mask &= ~REDRAW_MAIN;
   }
-*/
+#endif
 
   BackToFront();
 }
 
 void ClearWindow()
 {
-  XFillRectangle(display, backbuffer, gc,
-                REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
+  ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
 
   if (setup.soft_scrolling && game_status == PLAYING)
   {
-    XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
+    ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
     SetDrawtoField(DRAW_BUFFERED);
   }
   else
@@ -308,150 +345,41 @@ void ClearWindow()
 
   if (setup.direct_draw && game_status == PLAYING)
   {
-    XFillRectangle(display, window, gc,
-                  REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
+    ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
     SetDrawtoField(DRAW_DIRECT);
   }
 
   redraw_mask |= REDRAW_FIELD;
 }
 
-int getFontWidth(int font_size, int font_type)
-{
-  return (font_size == FS_BIG ? FONT1_XSIZE :
-         font_size == FS_MEDIUM ? FONT6_XSIZE :
-         font_type == FC_SPECIAL1 ? FONT3_XSIZE :
-         font_type == FC_SPECIAL2 ? FONT4_XSIZE :
-         font_type == FC_SPECIAL3 ? FONT5_XSIZE :
-         FONT2_XSIZE);
-}
-
-int getFontHeight(int font_size, int font_type)
-{
-  return (font_size == FS_BIG ? FONT1_YSIZE :
-         font_size == FS_MEDIUM ? FONT6_YSIZE :
-         font_type == FC_SPECIAL1 ? FONT3_YSIZE :
-         font_type == FC_SPECIAL2 ? FONT4_YSIZE :
-         font_type == FC_SPECIAL3 ? FONT5_YSIZE :
-         FONT2_YSIZE);
-}
-
-void DrawInitText(char *text, int ypos, int color)
-{
-  if (display && window && pix[PIX_SMALLFONT])
-  {
-    XFillRectangle(display, window, gc, 0, ypos, WIN_XSIZE, FONT2_YSIZE);
-    DrawTextExt(window, gc, (WIN_XSIZE - strlen(text) * FONT2_XSIZE)/2,
-               ypos,text,FS_SMALL,color);
-    XFlush(display);
-  }
-}
-
-void DrawTextFCentered(int y, int font_type, char *format, ...)
-{
-  char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
-  int font_width = getFontWidth(FS_SMALL, font_type);
-  va_list ap;
-
-  va_start(ap, format);
-  vsprintf(buffer, format, ap);
-  va_end(ap);
-
-  DrawText(SX + (SXSIZE - strlen(buffer) * font_width) / 2, SY + y,
-          buffer, FS_SMALL, font_type);
-}
-
-void DrawTextF(int x, int y, int font_type, char *format, ...)
+void MarkTileDirty(int x, int y)
 {
-  char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
-  va_list ap;
+  int xx = redraw_x1 + x;
+  int yy = redraw_y1 + y;
 
-  va_start(ap, format);
-  vsprintf(buffer, format, ap);
-  va_end(ap);
+  if (!redraw[xx][yy])
+    redraw_tiles++;
 
-  DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
+  redraw[xx][yy] = TRUE;
+  redraw_mask |= REDRAW_TILES;
 }
 
-void DrawText(int x, int y, char *text, int font_size, int font_type)
+void SetBorderElement()
 {
-  DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
-
-  if (x < DX)
-    redraw_mask |= REDRAW_FIELD;
-  else if (y < VY)
-    redraw_mask |= REDRAW_DOOR_1;
-}
-
-void DrawTextExt(Drawable d, GC gc, int x, int y,
-                char *text, int font_size, int font_type)
-{
-  int font_width, font_height, font_start;
-  int font_pixmap;
-  boolean print_inverse = FALSE;
-
-  if (font_size != FS_SMALL && font_size != FS_BIG && font_size != FS_MEDIUM)
-    font_size = FS_SMALL;
-  if (font_type < FC_RED || font_type > FC_SPECIAL3)
-    font_type = FC_RED;
-
-  font_width = getFontWidth(font_size, font_type);
-  font_height = getFontHeight(font_size, font_type);
-
-  font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT :
-                font_size == FS_MEDIUM ? PIX_MEDIUMFONT :
-                PIX_SMALLFONT);
-  font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE :
-                            font_size == FS_MEDIUM ? FONT6_YSIZE :
-                            FONT2_YSIZE) *
-               FONT_LINES_PER_FONT);
+  int x, y;
 
-  if (font_type == FC_SPECIAL3)
-    font_start += (FONT4_YSIZE - FONT2_YSIZE) * FONT_LINES_PER_FONT;
+  BorderElement = EL_LEERRAUM;
 
-  while (*text)
+  for(y=0; y<lev_fieldy && BorderElement == EL_LEERRAUM; y++)
   {
-    char c = *text++;
-
-    if (c == '~' && font_size == FS_SMALL)
-    {
-      print_inverse = TRUE;
-      continue;
-    }
-
-    if (c >= 'a' && c <= 'z')
-      c = 'A' + (c - 'a');
-    else if (c == 'ä' || c == 'Ä')
-      c = 91;
-    else if (c == 'ö' || c == 'Ö')
-      c = 92;
-    else if (c == 'ü' || c == 'Ãœ')
-      c = 93;
-
-    if (c >= 32 && c <= 95)
+    for(x=0; x<lev_fieldx; x++)
     {
-      int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
-      int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
-      int dest_x = x, dest_y = y;
+      if (!IS_MASSIVE(Feld[x][y]))
+       BorderElement = EL_BETON;
 
-      if (print_inverse)
-      {
-       XCopyArea(display, pix[font_pixmap], d, gc,
-                 FONT_CHARS_PER_LINE * font_width,
-                 3 * font_height + font_start,
-                 font_width, font_height, x, y);
-
-       XSetClipOrigin(display, clip_gc[font_pixmap],
-                      dest_x - src_x, dest_y - src_y);
-       XCopyArea(display, pix[font_pixmap], d, clip_gc[font_pixmap],
-                 0, 0, font_width, font_height, dest_x, dest_y);
-      }
-      else
-       XCopyArea(display, pix[font_pixmap], d, gc,
-                 src_x, src_y, font_width, font_height, dest_x, dest_y);
+      if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
+       x = lev_fieldx - 2;
     }
-
-    x += font_width;
   }
 }
 
@@ -711,8 +639,8 @@ void DrawPlayer(struct PlayerInfo *player)
     int x_size = TILEX * (1 + ABS(jx - last_jx));
     int y_size = TILEY * (1 + ABS(jy - last_jy));
 
-    XCopyArea(display, drawto_field, window, gc,
-             dest_x, dest_y, x_size, y_size, dest_x, dest_y);
+    BlitBitmap(drawto_field, window,
+              dest_x, dest_y, x_size, y_size, dest_x, dest_y);
     SetDrawtoField(DRAW_DIRECT);
   }
 
@@ -775,54 +703,54 @@ static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
   DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
 }
 
-void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
+void getGraphicSource(int graphic, int *bitmap_nr, int *x, int *y)
 {
   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
   {
     graphic -= GFX_START_ROCKSSCREEN;
-    *pixmap_nr = PIX_BACK;
+    *bitmap_nr = PIX_BACK;
     *x = SX + (graphic % GFX_PER_LINE) * TILEX;
     *y = SY + (graphic / GFX_PER_LINE) * TILEY;
   }
   else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
   {
     graphic -= GFX_START_ROCKSHEROES;
-    *pixmap_nr = PIX_HEROES;
+    *bitmap_nr = PIX_HEROES;
     *x = (graphic % HEROES_PER_LINE) * TILEX;
     *y = (graphic / HEROES_PER_LINE) * TILEY;
   }
   else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
   {
     graphic -= GFX_START_ROCKSSP;
-    *pixmap_nr = PIX_SP;
+    *bitmap_nr = PIX_SP;
     *x = (graphic % SP_PER_LINE) * TILEX;
     *y = (graphic / SP_PER_LINE) * TILEY;
   }
   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
   {
     graphic -= GFX_START_ROCKSDC;
-    *pixmap_nr = PIX_DC;
+    *bitmap_nr = PIX_DC;
     *x = (graphic % DC_PER_LINE) * TILEX;
     *y = (graphic / DC_PER_LINE) * TILEY;
   }
   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
   {
     graphic -= GFX_START_ROCKSMORE;
-    *pixmap_nr = PIX_MORE;
+    *bitmap_nr = PIX_MORE;
     *x = (graphic % MORE_PER_LINE) * TILEX;
     *y = (graphic / MORE_PER_LINE) * TILEY;
   }
   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
   {
     graphic -= GFX_START_ROCKSFONT;
-    *pixmap_nr = PIX_BIGFONT;
+    *bitmap_nr = PIX_BIGFONT;
     *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
     *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
          FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
   }
   else
   {
-    *pixmap_nr = PIX_SP;
+    *bitmap_nr = PIX_SP;
     *x = 0;
     *y = 0;
   }
@@ -839,18 +767,17 @@ void DrawGraphic(int x, int y, int graphic)
   }
 #endif
 
-  DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
+  DrawGraphicExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
   MarkTileDirty(x,y);
 }
 
-void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
+void DrawGraphicExt(DrawBuffer *bitmap, int x, int y, int graphic)
 {
-  int pixmap_nr;
+  int bitmap_nr;
   int src_x, src_y;
 
-  getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
-  XCopyArea(display, pix[pixmap_nr], d, gc,
-           src_x, src_y, TILEX, TILEY, x, y);
+  getGraphicSource(graphic, &bitmap_nr, &src_x, &src_y);
+  BlitBitmap(pix[bitmap_nr], bitmap, src_x, src_y, TILEX, TILEY, x, y);
 }
 
 void DrawGraphicThruMask(int x, int y, int graphic)
@@ -868,52 +795,54 @@ void DrawGraphicThruMask(int x, int y, int graphic)
   MarkTileDirty(x,y);
 }
 
-void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
+void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
 {
   int tile = graphic;
-  int pixmap_nr;
+  int bitmap_nr;
   int src_x, src_y;
-  Pixmap src_pixmap;
+  Bitmap *src_bitmap;
   GC drawing_gc;
 
   if (graphic == GFX_LEERRAUM)
     return;
 
-  getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
-  src_pixmap = pix[pixmap_nr];
-  drawing_gc = clip_gc[pixmap_nr];
+  getGraphicSource(graphic, &bitmap_nr, &src_x, &src_y);
+  src_bitmap = pix[bitmap_nr];
+  drawing_gc = pix[bitmap_nr]->stored_clip_gc;
 
   if (tile_clipmask[tile] != None)
   {
-    XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
-    XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
-    XCopyArea(display, src_pixmap, d, tile_clip_gc,
-             src_x, src_y, TILEX, TILEY, dest_x, dest_y);
+    SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
+    SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
+    BlitBitmapMasked(src_bitmap, d,
+                    src_x, src_y, TILEX, TILEY, dest_x, dest_y);
   }
   else
   {
 #if DEBUG
+#ifndef TARGET_SDL
     printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
+#endif
 #endif
 
-    XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
-    XCopyArea(display, src_pixmap, d, drawing_gc,
-             src_x, src_y, TILEX, TILEY, dest_x, dest_y);
+    SetClipOrigin(src_bitmap, drawing_gc, dest_x-src_x, dest_y-src_y);
+    BlitBitmapMasked(src_bitmap, d,
+                    src_x, src_y, TILEX, TILEY, dest_x, dest_y);
   }
 }
 
 void DrawMiniGraphic(int x, int y, int graphic)
 {
-  DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
+  DrawMiniGraphicExt(drawto, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
   MarkTileDirty(x/2, y/2);
 }
 
-void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
+void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
 {
   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
   {
     graphic -= GFX_START_ROCKSSCREEN;
-    *pixmap = pix[PIX_BACK];
+    *bitmap = pix[PIX_BACK];
     *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
     *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
   }
@@ -921,48 +850,47 @@ void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
   {
     graphic -= GFX_START_ROCKSSP;
     graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
-    *pixmap = pix[PIX_SP];
+    *bitmap = pix[PIX_SP];
     *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
     *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
   }
   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
   {
     graphic -= GFX_START_ROCKSDC;
-    *pixmap = pix[PIX_DC];
+    *bitmap = pix[PIX_DC];
     *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
     *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
   }
   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
   {
     graphic -= GFX_START_ROCKSMORE;
-    *pixmap = pix[PIX_MORE];
+    *bitmap = pix[PIX_MORE];
     *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
     *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
   }
   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
   {
     graphic -= GFX_START_ROCKSFONT;
-    *pixmap = pix[PIX_SMALLFONT];
+    *bitmap = pix[PIX_SMALLFONT];
     *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
     *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
              FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
   }
   else
   {
-    *pixmap = pix[PIX_SP];
+    *bitmap = pix[PIX_SP];
     *x = MINI_SP_STARTX;
     *y = MINI_SP_STARTY;
   }
 }
 
-void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
+void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
 {
-  Pixmap pixmap;
+  Bitmap *bitmap;
   int src_x, src_y;
 
-  getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
-  XCopyArea(display, pixmap, d, gc,
-           src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
+  getMiniGraphicSource(graphic, &bitmap, &src_x, &src_y);
+  BlitBitmap(bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
 }
 
 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
@@ -972,8 +900,8 @@ void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
   int cx = 0, cy = 0;
   int src_x, src_y, dest_x, dest_y;
   int tile = graphic;
-  int pixmap_nr;
-  Pixmap src_pixmap;
+  int bitmap_nr;
+  Bitmap *src_bitmap;
   GC drawing_gc;
 
   if (graphic < 0)
@@ -1046,9 +974,9 @@ void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
       MarkTileDirty(x, y + SIGN(dy));
   }
 
-  getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
-  src_pixmap = pix[pixmap_nr];
-  drawing_gc = clip_gc[pixmap_nr];
+  getGraphicSource(graphic, &bitmap_nr, &src_x, &src_y);
+  src_bitmap = pix[bitmap_nr];
+  drawing_gc = pix[bitmap_nr]->stored_clip_gc;
 
   src_x += cx;
   src_y += cy;
@@ -1069,25 +997,27 @@ void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
   {
     if (tile_clipmask[tile] != None)
     {
-      XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
-      XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
-      XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
-               src_x, src_y, TILEX, TILEY, dest_x, dest_y);
+      SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
+      SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
+      BlitBitmapMasked(src_bitmap, drawto_field,
+                      src_x, src_y, TILEX, TILEY, dest_x, dest_y);
     }
     else
     {
 #if DEBUG
+#ifndef        TARGET_SDL
       printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
+#endif
 #endif
 
-      XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
-      XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
-               src_x, src_y, width, height, dest_x, dest_y);
+      SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
+      BlitBitmapMasked(src_bitmap, drawto_field,
+                      src_x, src_y, width, height, dest_x, dest_y);
     }
   }
   else
-    XCopyArea(display, src_pixmap, drawto_field, gc,
-             src_x, src_y, width, height, dest_x, dest_y);
+    BlitBitmap(pix[bitmap_nr], drawto_field,
+              src_x, src_y, width, height, dest_x, dest_y);
 
   MarkTileDirty(x,y);
 }
@@ -1337,10 +1267,10 @@ void ErdreichAnbroeckeln(int x, int y)
        cy = (i == 3 ? TILEY - snip : 0);
       }
 
-      XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
-               SX + (graphic % GFX_PER_LINE) * TILEX + cx,
-               SY + (graphic / GFX_PER_LINE) * TILEY + cy,
-               width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
+      BlitBitmap(pix[PIX_BACK], drawto_field,
+                SX + (graphic % GFX_PER_LINE) * TILEX + cx,
+                SY + (graphic / GFX_PER_LINE) * TILEY + cy,
+                width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
     }
 
     MarkTileDirty(x, y);
@@ -1381,10 +1311,10 @@ void ErdreichAnbroeckeln(int x, int y)
        cy = (i==0 ? TILEY-snip : 0);
       }
 
-      XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
-               SX + (graphic % GFX_PER_LINE) * TILEX + cx,
-               SY + (graphic / GFX_PER_LINE) * TILEY + cy,
-               width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
+      BlitBitmap(pix[PIX_BACK], drawto_field,
+                SX + (graphic % GFX_PER_LINE) * TILEX + cx,
+                SY + (graphic / GFX_PER_LINE) * TILEY + cy,
+                width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
 
       MarkTileDirty(xx, yy);
     }
@@ -1565,32 +1495,32 @@ void DrawMicroElement(int xpos, int ypos, int element)
   {
     graphic -= GFX_START_ROCKSSP;
     graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
-    XCopyArea(display, pix[PIX_SP], drawto, gc,
-             MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
-             MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
-             MICRO_TILEX, MICRO_TILEY, xpos, ypos);
+    BlitBitmap(pix[PIX_SP], drawto,
+              MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
+              MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
+              MICRO_TILEX, MICRO_TILEY, xpos, ypos);
   }
   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
   {
     graphic -= GFX_START_ROCKSDC;
-    XCopyArea(display, pix[PIX_DC], drawto, gc,
-             MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
-             MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
-             MICRO_TILEX, MICRO_TILEY, xpos, ypos);
+    BlitBitmap(pix[PIX_DC], drawto,
+              MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
+              MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
+              MICRO_TILEX, MICRO_TILEY, xpos, ypos);
   }
   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
   {
     graphic -= GFX_START_ROCKSMORE;
-    XCopyArea(display, pix[PIX_MORE], drawto, gc,
-             MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
-             MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
-             MICRO_TILEX, MICRO_TILEY, xpos, ypos);
+    BlitBitmap(pix[PIX_MORE], drawto,
+              MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE)*MICRO_TILEX,
+              MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE)*MICRO_TILEY,
+              MICRO_TILEX, MICRO_TILEY, xpos, ypos);
   }
   else
-    XCopyArea(display, pix[PIX_BACK], drawto, gc,
-             MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
-             MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
-             MICRO_TILEX, MICRO_TILEY, xpos, ypos);
+    BlitBitmap(pix[PIX_BACK], drawto,
+              MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
+              MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
+              MICRO_TILEX, MICRO_TILEY, xpos, ypos);
 }
 
 void DrawLevel()
@@ -1621,8 +1551,7 @@ static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
 {
   int x, y;
 
-  XFillRectangle(display, drawto, gc,
-                xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
+  ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
 
   if (lev_fieldx < STD_LEV_FIELDX)
     xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
@@ -1663,8 +1592,7 @@ static void DrawMicroLevelLabelExt(int mode)
 {
   char label_text[MAX_MICROLABEL_SIZE + 1];
 
-  XFillRectangle(display, drawto,gc,
-                SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
+  ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
 
   strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
                       mode == MICROLABEL_CREATED_BY ? "created by" :
@@ -1794,7 +1722,7 @@ boolean Request(char *text, unsigned int req_state)
   int mx, my, ty, result = -1;
   unsigned int old_door_state;
 
-#ifndef MSDOS
+#if defined(PLATFORM_UNIX)
   /* pause network game while waiting for request to answer */
   if (options.network &&
       game_status == PLAYING &&
@@ -1809,12 +1737,12 @@ boolean Request(char *text, unsigned int req_state)
   CloseDoor(DOOR_CLOSE_1);
 
   /* save old door content */
-  XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
-           DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
-           DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
+  BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
+            DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
+            DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
 
   /* clear door drawing field */
-  XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
+  ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
 
   /* write text for request */
   for(ty=0; ty<13; ty++)
@@ -1839,8 +1767,7 @@ boolean Request(char *text, unsigned int req_state)
     }
     sprintf(txt, text); 
     txt[tl] = 0;
-    DrawTextExt(drawto, gc,
-               DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
+    DrawTextExt(drawto, DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
                txt, FS_SMALL, FC_YELLOW);
     text += tl + (tc == 32 ? 1 : 0);
   }
@@ -1863,9 +1790,9 @@ boolean Request(char *text, unsigned int req_state)
   }
 
   /* copy request gadgets to door backbuffer */
-  XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
-           DX, DY, DXSIZE, DYSIZE,
-           DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+  BlitBitmap(drawto, pix[PIX_DB_DOOR],
+            DX, DY, DXSIZE, DYSIZE,
+            DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
 
   OpenDoor(DOOR_OPEN_1);
 
@@ -1885,43 +1812,37 @@ boolean Request(char *text, unsigned int req_state)
 
   while(result < 0)
   {
-    if (XPending(display))
+    if (PendingEvent())
     {
-      XEvent event;
+      Event event;
 
-      XNextEvent(display, &event);
+      NextEvent(&event);
 
       switch(event.type)
       {
-       case ButtonPress:
-       case ButtonRelease:
-       case MotionNotify:
+       case EVENT_BUTTONPRESS:
+       case EVENT_BUTTONRELEASE:
+       case EVENT_MOTIONNOTIFY:
        {
-         if (event.type == MotionNotify)
+         if (event.type == EVENT_MOTIONNOTIFY)
          {
-           Window root, child;
-           int root_x, root_y;
-           int win_x, win_y;
-           unsigned int mask;
-
-           if (!XQueryPointer(display, window, &root, &child,
-                              &root_x, &root_y, &win_x, &win_y, &mask))
-             continue;
+           if (!PointerInWindow(window))
+             continue; /* window and pointer are on different screens */
 
            if (!button_status)
              continue;
 
            motion_status = TRUE;
-           mx = ((XMotionEvent *) &event)->x;
-           my = ((XMotionEvent *) &event)->y;
+           mx = ((MotionEvent *) &event)->x;
+           my = ((MotionEvent *) &event)->y;
          }
          else
          {
            motion_status = FALSE;
-           mx = ((XButtonEvent *) &event)->x;
-           my = ((XButtonEvent *) &event)->y;
-           if (event.type==ButtonPress)
-             button_status = ((XButtonEvent *) &event)->button;
+           mx = ((ButtonEvent *) &event)->x;
+           my = ((ButtonEvent *) &event)->y;
+           if (event.type == EVENT_BUTTONPRESS)
+             button_status = ((ButtonEvent *) &event)->button;
            else
              button_status = MB_RELEASED;
          }
@@ -1961,15 +1882,14 @@ boolean Request(char *text, unsigned int req_state)
          break;
        }
 
-       case KeyPress:
-         switch(XLookupKeysym((XKeyEvent *)&event,
-                              ((XKeyEvent *)&event)->state))
+       case EVENT_KEYPRESS:
+         switch(GetEventKey((KeyEvent *)&event, TRUE))
          {
-           case XK_Return:
+           case KSYM_Return:
              result = 1;
              break;
 
-           case XK_Escape:
+           case KSYM_Escape:
              result = 0;
              break;
 
@@ -1980,7 +1900,7 @@ boolean Request(char *text, unsigned int req_state)
            result = 0;
          break;
 
-       case KeyRelease:
+       case EVENT_KEYRELEASE:
          key_joystick_mapping = 0;
          break;
 
@@ -2016,16 +1936,16 @@ boolean Request(char *text, unsigned int req_state)
 
     if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
     {
-      XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
-               DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
-               DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
+      BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
+                DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
+                DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
       OpenDoor(DOOR_OPEN_1);
     }
   }
 
   RemapAllGadgets();
 
-#ifndef MSDOS
+#if defined(PLATFORM_UNIX)
   /* continue network game after request */
   if (options.network &&
       game_status == PLAYING &&
@@ -2042,9 +1962,9 @@ unsigned int OpenDoor(unsigned int door_state)
 
   if (door_state & DOOR_COPY_BACK)
   {
-    XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
-             DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
-             DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+    BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
+              DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
+              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
     door_state &= ~DOOR_COPY_BACK;
   }
 
@@ -2057,10 +1977,10 @@ unsigned int CloseDoor(unsigned int door_state)
 {
   unsigned int new_door_state;
 
-  XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
-           DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
-  XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
-           VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
+  BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
+            DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+  BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
+            VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
 
   new_door_state = MoveDoor(door_state);
 
@@ -2108,6 +2028,9 @@ unsigned int MoveDoor(unsigned int door_state)
 
     for(x=start; x<=DXSIZE; x+=stepsize)
     {
+      Bitmap *bitmap = pix[PIX_DOOR];
+      GC gc = bitmap->stored_clip_gc;
+
       WaitUntilDelayReached(&door_delay, door_delay_value);
 
       if (door_state & DOOR_ACTION_1)
@@ -2115,40 +2038,40 @@ unsigned int MoveDoor(unsigned int door_state)
        int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
        int j = (DXSIZE - i) / 3;
 
-       XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
-                 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
-                 DXSIZE,DYSIZE - i/2, DX, DY);
-
-       XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
-
-       XSetClipOrigin(display, clip_gc[PIX_DOOR],
-                      DX - i, (DY + j) - DOOR_GFX_PAGEY1);
-       XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
-                 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
-                 DY + 140 + j);
-       XSetClipOrigin(display, clip_gc[PIX_DOOR],
-                      DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
-
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
-                 DX, DY + 77 - j);
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
-                 DX, DY + 203 - j);
-       XSetClipOrigin(display, clip_gc[PIX_DOOR],
-                      DX - i, (DY + j) - DOOR_GFX_PAGEY1);
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
-                 DX + DXSIZE - i, DY + 77 + j);
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
-                 DX + DXSIZE - i, DY + 203 + j);
+       BlitBitmap(pix[PIX_DB_DOOR], drawto,
+                  DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
+                  DXSIZE,DYSIZE - i/2, DX, DY);
+
+       ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
+
+       SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
+       BlitBitmapMasked(bitmap, drawto,
+                        DXSIZE, DOOR_GFX_PAGEY1, i, 77,
+                        DX + DXSIZE - i, DY + j);
+       BlitBitmapMasked(bitmap, drawto,
+                        DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
+                        DX + DXSIZE - i, DY + 140 + j);
+       SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
+       BlitBitmapMasked(bitmap, drawto,
+                        DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
+                        DX, DY);
+       BlitBitmapMasked(bitmap, drawto,
+                        DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
+                        DX, DY + 140 - j);
+
+       BlitBitmapMasked(bitmap, drawto,
+                        DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
+                        DX, DY + 77 - j);
+       BlitBitmapMasked(bitmap, drawto,
+                        DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
+                        DX, DY + 203 - j);
+       SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
+       BlitBitmapMasked(bitmap, drawto,
+                        DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
+                        DX + DXSIZE - i, DY + 77 + j);
+       BlitBitmapMasked(bitmap, drawto,
+                        DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
+                        DX + DXSIZE - i, DY + 203 + j);
 
        redraw_mask |= REDRAW_DOOR_1;
       }
@@ -2158,29 +2081,30 @@ unsigned int MoveDoor(unsigned int door_state)
        int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
        int j = (VXSIZE - i) / 3;
 
-       XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
-                 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
-                 VXSIZE, VYSIZE - i/2, VX, VY);
-
-       XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
-
-       XSetClipOrigin(display, clip_gc[PIX_DOOR],
-                      VX - i, (VY + j) - DOOR_GFX_PAGEY2);
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
-       XSetClipOrigin(display, clip_gc[PIX_DOOR],
-                      VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
-       XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
-                 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
-
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
-                 VX, VY + VYSIZE / 2 - j);
-       XSetClipOrigin(display, clip_gc[PIX_DOOR],
-                      VX - i, (VY + j) - DOOR_GFX_PAGEY2);
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
-                 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
+       BlitBitmap(pix[PIX_DB_DOOR], drawto,
+                  DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
+                  VXSIZE, VYSIZE - i/2, VX, VY);
+
+       ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
+
+       SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
+       BlitBitmapMasked(bitmap, drawto,
+                        VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
+                        VX + VXSIZE-i, VY+j);
+       SetClipOrigin(bitmap, gc,
+                     VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
+       BlitBitmapMasked(bitmap, drawto,
+                        VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
+                        VX, VY);
+
+       BlitBitmapMasked(bitmap, drawto,
+                        VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
+                        i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
+       SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
+       BlitBitmapMasked(bitmap, drawto,
+                        VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
+                        i, VYSIZE / 2 - j,
+                        VX + VXSIZE - i, VY + VYSIZE / 2 + j);
 
        redraw_mask |= REDRAW_DOOR_2;
       }
@@ -2206,8 +2130,8 @@ unsigned int MoveDoor(unsigned int door_state)
 void DrawSpecialEditorDoor()
 {
   /* draw bigger toolbox window */
-  XCopyArea(display, pix[PIX_DOOR], drawto, gc,
-           DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
+  BlitBitmap(pix[PIX_DOOR], drawto,
+            DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
 
   redraw_mask |= REDRAW_ALL;
 }
@@ -2215,24 +2139,27 @@ void DrawSpecialEditorDoor()
 void UndrawSpecialEditorDoor()
 {
   /* draw normal tape recorder window */
-  XCopyArea(display, pix[PIX_BACK], drawto, gc,
-           562, 344, 108, 56, EX - 4, EY - 12);
+  BlitBitmap(pix[PIX_BACK], drawto,
+            562, 344, 108, 56, EX - 4, EY - 12);
 
   redraw_mask |= REDRAW_ALL;
 }
 
-int ReadPixel(Drawable d, int x, int y)
+#ifndef        TARGET_SDL
+int ReadPixel(DrawBuffer *bitmap, int x, int y)
 {
   XImage *pixel_image;
   unsigned long pixel_value;
 
-  pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
+  pixel_image = XGetImage(display, bitmap->drawable,
+                         x, y, 1, 1, AllPlanes, ZPixmap);
   pixel_value = XGetPixel(pixel_image, 0, 0);
 
   XDestroyImage(pixel_image);
 
   return pixel_value;
 }
+#endif
 
 /* ---------- new tool button stuff ---------------------------------------- */
 
@@ -2335,10 +2262,12 @@ static struct
   }
 };
 
+#if 0
 static void DoNotDisplayInfoText(void *ptr)
 {
   return;
 }
+#endif
 
 void CreateToolButtons()
 {
@@ -2346,8 +2275,8 @@ void CreateToolButtons()
 
   for (i=0; i<NUM_TOOL_BUTTONS; i++)
   {
-    Pixmap gd_pixmap = pix[PIX_DOOR];
-    Pixmap deco_pixmap = None;
+    Bitmap *gd_bitmap = pix[PIX_DOOR];
+    Bitmap *deco_bitmap = None;
     int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
     struct GadgetInfo *gi;
     unsigned long event_mask;
@@ -2366,7 +2295,7 @@ void CreateToolButtons()
     if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
     {
       getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
-                          &deco_pixmap, &deco_x, &deco_y);
+                          &deco_bitmap, &deco_x, &deco_y);
       deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
       deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
     }
@@ -2379,15 +2308,19 @@ void CreateToolButtons()
                      GDI_HEIGHT, toolbutton_info[i].height,
                      GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
                      GDI_STATE, GD_BUTTON_UNPRESSED,
-                     GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
-                     GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
-                     GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
+                     GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
+                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
+                     GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
                      GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
                      GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
                      GDI_DECORATION_SHIFTING, 1, 1,
                      GDI_EVENT_MASK, event_mask,
-                     GDI_CALLBACK_ACTION, HandleToolButtons,
+
+#if 0
                      GDI_CALLBACK_INFO, DoNotDisplayInfoText,
+#endif
+
+                     GDI_CALLBACK_ACTION, HandleToolButtons,
                      GDI_END);
 
     if (gi == NULL)
index 18bce3b31fccef78ff8d00de5192e46be3f38550..5501d705f84a2b83626f92968a8682c68b7daa7c 100644 (file)
@@ -1,14 +1,14 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2000 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  tools.h                                                 *
+* tools.h                                                  *
 ***********************************************************/
 
 #ifndef TOOLS_H
@@ -62,13 +62,10 @@ void SetDrawtoField(int);
 void BackToFront();
 void FadeToFront();
 void ClearWindow();
-int getFontWidth(int, int);
-int getFontHeight(int, int);
-void DrawInitText(char *, int, int);
-void DrawTextF(int, int, int, char *, ...);
-void DrawTextFCentered(int, int, char *, ...);
-void DrawText(int, int, char *, int, int);
-void DrawTextExt(Drawable, GC, int, int, char *, int, int);
+
+void MarkTileDirty(int, int);
+void SetBorderElement();
+
 void DrawAllPlayers(void);
 void DrawPlayerField(int, int);
 void DrawPlayer(struct PlayerInfo *);
@@ -77,12 +74,12 @@ void DrawGraphicAnimation(int, int, int, int, int, int);
 void DrawGraphicAnimationThruMask(int, int, int, int, int, int);
 void getGraphicSource(int, int *, int *, int *);
 void DrawGraphic(int, int, int);
-void DrawGraphicExt(Drawable, GC, int, int, int);
+void DrawGraphicExt(DrawBuffer *, int, int, int);
 void DrawGraphicThruMask(int, int, int);
-void DrawGraphicThruMaskExt(Drawable, int, int, int);
+void DrawGraphicThruMaskExt(DrawBuffer *, int, int, int);
 void DrawMiniGraphic(int, int, int);
-void getMiniGraphicSource(int, Pixmap *, int *, int *);
-void DrawMiniGraphicExt(Drawable, GC, int, int, int);
+void getMiniGraphicSource(int, Bitmap **, int *, int *);
+void DrawMiniGraphicExt(DrawBuffer *, int, int, int);
 void DrawGraphicShifted(int, int, int, int, int, int, int);
 void DrawGraphicShiftedThruMask(int, int, int, int, int, int);
 void DrawScreenElementExt(int, int, int, int, int, int, int);
@@ -110,10 +107,10 @@ unsigned int GetDoorState(void);
 unsigned int MoveDoor(unsigned int);
 void DrawSpecialEditorDoor();
 void UndrawSpecialEditorDoor();
-int ReadPixel(Drawable, int, int);
+int ReadPixel(DrawBuffer *, int, int);
 
 void CreateToolButtons();
 
 int el2gfx(int);
 
-#endif
+#endif /* TOOLS_H */