ballerburg-1.2.0/0000755000175000017500000000000012506012172013177 5ustar thomasthomasballerburg-1.2.0/cmake/0000755000175000017500000000000012506012140014252 5ustar thomasthomasballerburg-1.2.0/cmake/FindSDL2.cmake0000664000175000017500000001413112506012140016563 0ustar thomasthomas# Locate SDL2 library # This module defines # SDL2_LIBRARY, the name of the library to link against # SDL2_FOUND, if false, do not try to link to SDL2 # SDL2_INCLUDE_DIR, where to find SDL.h # # This module responds to the the flag: # SDL2_BUILDING_LIBRARY # If this is defined, then no SDL2main will be linked in because # only applications need main(). # Otherwise, it is assumed you are building an application and this # module will attempt to locate and set the the proper link flags # as part of the returned SDL2_LIBRARY variable. # # Don't forget to include SDLmain.h and SDLmain.m your project for the # OS X framework based version. (Other versions link to -lSDL2main which # this module will try to find on your behalf.) Also for OS X, this # module will automatically add the -framework Cocoa on your behalf. # # # Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration # and no SDL2_LIBRARY, it means CMake did not find your SDL2 library # (SDL2.dll, libsdl2.so, SDL2.framework, etc). # Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again. # Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value # as appropriate. These values are used to generate the final SDL2_LIBRARY # variable, but when these values are unset, SDL2_LIBRARY does not get created. # # # $SDL2DIR is an environment variable that would # correspond to the ./configure --prefix=$SDL2DIR # used in building SDL2. # l.e.galup 9-20-02 # # Modified by Eric Wing. # Added code to assist with automated building by using environmental variables # and providing a more controlled/consistent search behavior. # Added new modifications to recognize OS X frameworks and # additional Unix paths (FreeBSD, etc). # Also corrected the header search path to follow "proper" SDL guidelines. # Added a search for SDL2main which is needed by some platforms. # Added a search for threads which is needed by some platforms. # Added needed compile switches for MinGW. # # On OSX, this will prefer the Framework version (if found) over others. # People will have to manually change the cache values of # SDL2_LIBRARY to override this selection or set the CMake environment # CMAKE_INCLUDE_PATH to modify the search paths. # # Note that the header path has changed from SDL2/SDL.h to just SDL.h # This needed to change because "proper" SDL convention # is #include "SDL.h", not . This is done for portability # reasons because not all systems place things in SDL2/ (see FreeBSD). #============================================================================= # Copyright 2003-2009 Kitware, Inc. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) SET(SDL2_SEARCH_PATHS ~/Library/Frameworks /Library/Frameworks /usr/local /usr /sw # Fink /opt/local # DarwinPorts /opt/csw # Blastwave /opt ) FIND_PATH(SDL2_INCLUDE_DIR SDL_scancode.h HINTS $ENV{SDL2DIR} PATH_SUFFIXES include/SDL2 include PATHS ${SDL2_SEARCH_PATHS} ) FIND_LIBRARY(SDL2_LIBRARY_TEMP NAMES SDL2 HINTS $ENV{SDL2DIR} PATH_SUFFIXES lib64 lib PATHS ${SDL2_SEARCH_PATHS} ) IF(NOT SDL2_BUILDING_LIBRARY) IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") # Non-OS X framework versions expect you to also dynamically link to # SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms # seem to provide SDL2main for compatibility even though they don't # necessarily need it. FIND_LIBRARY(SDL2MAIN_LIBRARY NAMES SDL2main HINTS $ENV{SDL2DIR} PATH_SUFFIXES lib64 lib PATHS ${SDL2_SEARCH_PATHS} ) ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") ENDIF(NOT SDL2_BUILDING_LIBRARY) # SDL2 may require threads on your system. # The Apple build may not need an explicit flag because one of the # frameworks may already provide it. # But for non-OSX systems, I will use the CMake Threads package. IF(NOT APPLE) FIND_PACKAGE(Threads) ENDIF(NOT APPLE) # MinGW needs an additional library, mwindows # It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -lmwindows # (Actually on second look, I think it only needs one of the m* libraries.) IF(MINGW) SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW") ENDIF(MINGW) IF(SDL2_LIBRARY_TEMP) # For SDL2main IF(NOT SDL2_BUILDING_LIBRARY) IF(SDL2MAIN_LIBRARY) SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP}) ENDIF(SDL2MAIN_LIBRARY) ENDIF(NOT SDL2_BUILDING_LIBRARY) # For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa. # CMake doesn't display the -framework Cocoa string in the UI even # though it actually is there if I modify a pre-used variable. # I think it has something to do with the CACHE STRING. # So I use a temporary variable until the end so I can set the # "real" variable in one-shot. IF(APPLE) SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa") ENDIF(APPLE) # For threads, as mentioned Apple doesn't need this. # In fact, there seems to be a problem if I used the Threads package # and try using this line, so I'm just skipping it entirely for OS X. IF(NOT APPLE) SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT}) ENDIF(NOT APPLE) # For MinGW library IF(MINGW) SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP}) ENDIF(MINGW) # Set the final string here so the GUI reflects the final state. SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found") # Set the temp variable to INTERNAL so it is not seen in the CMake GUI SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "") ENDIF(SDL2_LIBRARY_TEMP) INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR) ballerburg-1.2.0/cmake/config-cmake.h0000644000175000017500000000044012506012140016744 0ustar thomasthomas/* CMake config.h for Ballerburg SDL */ /* Relative path from bindir to datadir */ #define BIN2DATADIR "@BIN2DATADIR@" /* Relative path from bindir to localedir */ #define BIN2LOCALEDIR "@BIN2LOCALEDIR@" /* Define if you have the libintl.h header file */ #cmakedefine HAVE_LIBINTL_H 1 ballerburg-1.2.0/cmake/Uninstall.cmake0000644000175000017500000000220112506012140017220 0ustar thomasthomas# # "uninstall" target for reverting "make install" # # cmake_policy(SET CMP0007 NEW) if (NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt") message(FATAL_ERROR "Cannot find install manifest: \"${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt\"") endif() file(READ "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt" files) string(REGEX REPLACE "\n" ";" files "${files}") # list(REVERSE files) foreach (file ${files}) message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") if (EXISTS "$ENV{DESTDIR}${file}") execute_process( COMMAND ${CMAKE_COMMAND} -E remove "$ENV{DESTDIR}${file}" OUTPUT_VARIABLE rm_out RESULT_VARIABLE rm_retval ) if(NOT ${rm_retval} EQUAL 0) message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") endif (NOT ${rm_retval} EQUAL 0) else (EXISTS "$ENV{DESTDIR}${file}") message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") endif (EXISTS "$ENV{DESTDIR}${file}") endforeach(file) execute_process( COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt ) ballerburg-1.2.0/cmake/FindMath.cmake0000644000175000017500000000060112506012140016743 0ustar thomasthomas if(MATH_INCLUDE_DIR) # Already in cache, be silent set(MATH_FIND_QUIETLY TRUE) endif(MATH_INCLUDE_DIR) find_path(MATH_INCLUDE_DIR math.h) find_library(MATH_LIBRARY NAMES m) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(MATH DEFAULT_MSG MATH_LIBRARY MATH_INCLUDE_DIR) mark_as_advanced(MATH_LIBRARY MATH_INCLUDE_DIR) ballerburg-1.2.0/cmake/DistClean.cmake0000644000175000017500000000131512506012140017122 0ustar thomasthomas# # "distclean" target for removing the generated files from CMake # if(UNIX) add_custom_target(distclean COMMENT "Cleaning up for distribution") # Clean up Ballerburg specific files: foreach(CLEAN_FILE config.h src/ballerburg install_manifest.txt po/ballerburg.pot) add_custom_command(TARGET distclean POST_BUILD COMMAND rm -f ${CLEAN_FILE} DEPENDS clean) endforeach(CLEAN_FILE) # Clean up files that can appear at multiple places: foreach(CLEAN_FILE CMakeFiles CMakeCache.txt '*.a' '*.6.gz' '*.mo' cmake_install.cmake Makefile) add_custom_command(TARGET distclean POST_BUILD COMMAND find . -depth -name ${CLEAN_FILE} | xargs rm -rf DEPENDS clean) endforeach(CLEAN_FILE) endif(UNIX) ballerburg-1.2.0/README.txt0000644000175000017500000000543312506012141014676 0ustar thomasthomas ============================ = Ballerburg SDL v1.2.0 = ============================ Copyright (C) 1987, 1989 Eckhard Kruse Copyright (C) 2010, 2015 Thomas Huth For my sister Martina Huth - I will never forget the countless happy hours that we had with this game during our childhood. 1) Lizenz --------- This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . 2) What is Ballerburg? ---------------------- Ballerburg is a classical castle combat game. Two castles, separated by a hill, shoot each other with their cannons until one of the king is hit or surrenders. Ballerburg was originally developed in 1987 by Eckhard Kruse for the Atari ST computers - a cutting-edge 16/32-bit computer at that time. Now, a quarter of a century later, here's the adaption of Ballerburg for recent operating systems that are supported by the SDL library (like GNU/Linux for example) - thanks to the original source code of the old Ballerburg that has kindly been released by Eckhard Kruse to the public. 3) Compiling and installing --------------------------- For compiling the source code of Ballerburg SDL, you need the GCC C-compiler, CMake and the SDL library (preferably version 1.2, see http://www.libsdl.org/). For configuring the build, you've got to run "cmake" first, using the path of the sources as parameter. Alternatively, you can also use the supplied "configure" script or a GUI tool like "cmake-gui". After the configuration step, you can compile the source code with "make" and if everything worked fine, install the program with "make install". 4) Starting the game -------------------- To run the game, simply execute the "ballerburg" program from the folder where you've installed the game into. The game itself should be self-explanatory most of the time, for the details please have a look at the manual in the doc directory. Please press the "ESC" key to enter the main menu (for setting up various game options or for starting a new game). Press "f" to toggle between windowed and fullscreen mode. The key "q" is used for leaving the game. 5) Contact ---------- If you have questions, suggestions or patches, please write a mail to the following address: huth at tuxfamily.org Now have fun with Ballerburg! ballerburg-1.2.0/CMakeLists.txt0000664000175000017500000000714012506012141015737 0ustar thomasthomas# ############################### # CMake build file for Ballerburg # ############################### cmake_minimum_required (VERSION 2.8 FATAL_ERROR) project (ballerburg C) set(VERSION 1.2.0) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") include(CheckIncludeFiles) include(CheckFunctionExists) include(CheckCCompilerFlag) include(DistClean) # Set build type to "Release" if user did not specify any build type yet # Other possible values: Debug, Release, RelWithDebInfo and MinSizeRel if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif(NOT CMAKE_BUILD_TYPE) # #################### # Paths configuration: # #################### if(NOT BINDIR) set(BINDIR bin) endif() if(NOT DATADIR) set(DATADIR share/ballerburg) endif() if(NOT BIN2DATADIR) set(BIN2DATADIR "../share/ballerburg" CACHE STRING "Relative path from bindir to datadir") mark_as_advanced(BIN2DATADIR) endif() if(NOT LOCALEDIR) set(LOCALEDIR share/locale) endif() if(NOT BIN2LOCALEDIR) set(BIN2LOCALEDIR "../share/locale" CACHE STRING "Relative path from bindir to locale directory") mark_as_advanced(BIN2LOCALEDIR) endif() if(NOT MANDIR) set(MANDIR share/man/man6) endif() if(NOT DOCDIR) set(DOCDIR share/doc/ballerburg) endif() # #################### # Check for libraries: # #################### if(ENABLE_SDL2) find_package(SDL2 REQUIRED) if(NOT SDL2_FOUND) message(FATAL_ERROR "SDL2 library not found!") endif(NOT SDL2_FOUND) set(SDL_INCLUDE_DIR ${SDL2_INCLUDE_DIR}) set(SDL_LIBRARY ${SDL2_LIBRARY}) set(SDLMAIN_LIBRARY ${SDL2MAIN_LIBRARY}) else(ENABLE_SDL2) find_package(SDL REQUIRED) if(NOT SDL_FOUND) message(FATAL_ERROR "SDL library not found!") endif(NOT SDL_FOUND) endif(ENABLE_SDL2) find_package(Math REQUIRED) find_package(Gettext) # ################ # CPP Definitions: # ################ # Additional CFLAGS suggested by the SDL library: if(ENABLE_SDL2) add_definitions(-DWITH_SDL2) execute_process(COMMAND pkg-config --cflags-only-other sdl2 OUTPUT_VARIABLE DETECTED_SDL_CFLAGS ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) else(ENABLE_SDL2) execute_process(COMMAND pkg-config --cflags-only-other sdl OUTPUT_VARIABLE DETECTED_SDL_CFLAGS ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) endif(ENABLE_SDL2) if(DETECTED_SDL_CFLAGS) add_definitions(${DETECTED_SDL_CFLAGS}) # message(STATUS "Additional CFLAGS of SDL: ${DETECTED_SDL_CFLAGS}") endif(DETECTED_SDL_CFLAGS) # ########################### # Check for optional headers: # ########################### check_include_files(libintl.h HAVE_LIBINTL_H) # ############### # Various CFLAGS: # ############### if(CMAKE_COMPILER_IS_GNUCC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsigned-char -Wall") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra -Wno-unused-parameter") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-prototypes -Wstrict-prototypes") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wbad-function-cast") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat-security -Wpointer-arith") #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wcast-qual -Wshadow") #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") if (CMAKE_BUILD_TYPE STREQUAL "Debug") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FORTIFY_SOURCE=2") endif(CMAKE_BUILD_TYPE STREQUAL "Debug") endif(CMAKE_COMPILER_IS_GNUCC) # ######################################### # Create config.h and recurse into subdirs: # ######################################### configure_file(${CMAKE_SOURCE_DIR}/cmake/config-cmake.h ${CMAKE_BINARY_DIR}/config.h) add_subdirectory(src) add_subdirectory(doc) add_subdirectory(po) add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/cmake/Uninstall.cmake) ballerburg-1.2.0/configure0000775000175000017500000000367212506012141015114 0ustar thomasthomas#!/bin/sh # NOTE: this is a simple script wrapper around the cmake command line # tools, for those used to the autotools configure script conventions if ! which cmake > /dev/null; then echo "ERROR: You need the 'cmake' program to configure the build process." echo "Please install 'cmake' first, then try again." exit 1 fi print_help() { echo "This is a simple configure script wrapper around cmake build system." echo "Parameters are:" echo " --prefix= Set the install prefix to path" echo " --enable-debug Enable debug (non-optimized) build" echo " --disable-color-make Disable color output for Makefiles" echo " --enable-sdl2 Compile with libsdl 2.0 instead of 1.2" echo echo "Please run cmake directly for full control over the build." echo } cmake_args="" build_type="Release" while [ $# -gt 0 ] do preq=${1%=*} # get part before = case $preq in --help) print_help exit 0 ;; --prefix) prefix=${1##*=} # get part after = cmake_args="$cmake_cmd -DCMAKE_INSTALL_PREFIX:PATH=$prefix" ;; --enable-debug) build_type="Debug" cmake_args="$cmake_args -DCMAKE_BUILD_TYPE:STRING=Debug" ;; --disable-debug) build_type="Release" cmake_args="$cmake_args -DCMAKE_BUILD_TYPE:STRING=Release" ;; --enable-color-make) cmake_args="$cmake_args -DCMAKE_COLOR_MAKEFILE:BOOL=1" ;; --disable-color-make) cmake_args="$cmake_args -DCMAKE_COLOR_MAKEFILE:BOOL=0" ;; --enable-sdl2) cmake_args="$cmake_args -DENABLE_SDL2:BOOL=1" ;; --disable-sdl2) cmake_args="$cmake_args -DENABLE_SDL2:BOOL=0" ;; *) echo "Invalid argument: $preq" echo "Run $0 --help for a list of valid parameters." exit 2 ;; esac shift 1 done cmake `dirname $0` $cmake_args || exit 1 echo echo "Now you must type: make; make install" echo "to actually build and install the software" echo ballerburg-1.2.0/src/0000755000175000017500000000000012506012141013762 5ustar thomasthomasballerburg-1.2.0/src/sdlgfx.h0000664000175000017500000001262612506012141015433 0ustar thomasthomas/* sdlgfx.h: This is a reduced version of Andreas Schiffler's SDL_gfxPrimitives.h, original copyright follows: SDL_gfxPrimitives.h: graphics primitives for SDL Copyright (C) 2001-2012 Andreas Schiffler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Andreas Schiffler -- aschiffler at ferzkopp dot net */ #ifndef _SDL_gfxPrimitives_h #define _SDL_gfxPrimitives_h #include #ifndef M_PI #define M_PI 3.1415926535897932384626433832795 #endif #include /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus extern "C" { #endif /* ----- Versioning */ #define SDL_GFXPRIMITIVES_MAJOR 2 #define SDL_GFXPRIMITIVES_MINOR 0 #define SDL_GFXPRIMITIVES_MICRO 25 /* ---- Function Prototypes */ #ifdef _MSC_VER # if defined(DLL_EXPORT) && !defined(LIBSDL_GFX_DLL_IMPORT) # define SDL_GFXPRIMITIVES_SCOPE __declspec(dllexport) # else # ifdef LIBSDL_GFX_DLL_IMPORT # define SDL_GFXPRIMITIVES_SCOPE __declspec(dllimport) # endif # endif #endif #ifndef SDL_GFXPRIMITIVES_SCOPE # define SDL_GFXPRIMITIVES_SCOPE extern #endif /* Note: all ___Color routines expect the color to be in format 0xRRGGBBAA */ /* Pixel */ SDL_GFXPRIMITIVES_SCOPE int pixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color); SDL_GFXPRIMITIVES_SCOPE int pixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a); /* Horizontal line */ SDL_GFXPRIMITIVES_SCOPE int hlineColor(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color); SDL_GFXPRIMITIVES_SCOPE int hlineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a); /* Vertical line */ SDL_GFXPRIMITIVES_SCOPE int vlineColor(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color); SDL_GFXPRIMITIVES_SCOPE int vlineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a); /* Rectangle */ SDL_GFXPRIMITIVES_SCOPE int rectangleColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color); SDL_GFXPRIMITIVES_SCOPE int rectangleRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a); /* Line */ SDL_GFXPRIMITIVES_SCOPE int lineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color); SDL_GFXPRIMITIVES_SCOPE int lineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a); /* Circle */ SDL_GFXPRIMITIVES_SCOPE int circleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color); SDL_GFXPRIMITIVES_SCOPE int circleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a); /* Filled Circle */ SDL_GFXPRIMITIVES_SCOPE int filledCircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color); SDL_GFXPRIMITIVES_SCOPE int filledCircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a); /* Polygon */ SDL_GFXPRIMITIVES_SCOPE int polygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color); SDL_GFXPRIMITIVES_SCOPE int polygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a); /* AA-Polygon */ SDL_GFXPRIMITIVES_SCOPE int aapolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color); SDL_GFXPRIMITIVES_SCOPE int aapolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a); /* Filled Polygon */ SDL_GFXPRIMITIVES_SCOPE int filledPolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color); SDL_GFXPRIMITIVES_SCOPE int filledPolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a); SDL_GFXPRIMITIVES_SCOPE int texturedPolygon(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface * texture,int texture_dx,int texture_dy); /* (Note: These MT versions are required for multi-threaded operation.) */ SDL_GFXPRIMITIVES_SCOPE int filledPolygonColorMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color, int **polyInts, int *polyAllocated); SDL_GFXPRIMITIVES_SCOPE int filledPolygonRGBAMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a, int **polyInts, int *polyAllocated); SDL_GFXPRIMITIVES_SCOPE int texturedPolygonMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface * texture,int texture_dx,int texture_dy, int **polyInts, int *polyAllocated); /* Ends C function definitions when using C++ */ #ifdef __cplusplus } #endif #endif /* _SDL_gfxPrimitives_h */ ballerburg-1.2.0/src/settings.c0000664000175000017500000002071512506012141015775 0ustar thomasthomas/* settings.c Copyright (C) 2011 Thomas Huth This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include "i18n.h" #include "ballergui.h" #include "baller1.h" #include "baller2.h" #include "sdlgui.h" #include "screen.h" #include "settings.h" #define P1_HUMAN 6 #define P1_COMPUTER 7 #define P1_AISTRATEGYLEFT 10 #define P1_AISTRATEGYSTR 11 #define P1_AISTRATEGYRIGHT 12 #define P1_AISTRENGTHLEFT 15 #define P1_AISTRENGTHSTR 16 #define P1_AISTRENGTHRIGHT 17 #define P2_HUMAN 22 #define P2_COMPUTER 23 #define P2_AISTRATEGYLEFT 26 #define P2_AISTRATEGYSTR 27 #define P2_AISTRATEGYRIGHT 28 #define P2_AISTRENGTHLEFT 31 #define P2_AISTRENGTHSTR 32 #define P2_AISTRENGTHRIGHT 33 #define ROUNDS_20 35 #define ROUNDS_50 36 #define ROUNDS_100 37 #define ROUNDS_NOLIMIT 38 #define GIVEUPALLOWED 39 #define REPAIRALLOWED 40 #define NEWGAME 41 #define CONTINUE 42 #define QUITGAME 43 static char dlg_p1level[2] = "2"; static char dlg_p2level[2] = "3"; static SGOBJ settingsdlg[] = { { SGBOX, 0, 0, 0,0, 71,22, NULL }, { SGTEXT, 0, 0, 27,1, 13,1, N_("Settings") }, { SGBOX, 0, 0, 1,3, 34,11, NULL }, { SGTEXT, 0, 0, 12,4, 9,1, N_("Player 1") }, { SGTEXT, 0, 0, 3,6, 5,1, N_("Name:") }, { SGEDITFIELD, 0, 0, 9,6, 22,1, nsp1 }, { SGRADIOBUT, 0, SG_SELECTED, 3,8, 8,1, N_("Human") }, { SGRADIOBUT, 0, 0, 15,8, 10,1, N_("Computer") }, { SGTEXT, 0, 0, 3,10, 15,1, N_("AI strategy:") }, { SGBOX, 0, 0, 19,10, 15,1, NULL }, { SGBUTTON, SG_EXIT, 0, 19,10, 2,1, SGARROWLEFTSTR }, { SGTEXT, 0, 0, 22,10, 8,1, NULL }, { SGBUTTON, SG_EXIT, 0, 32,10, 2,1, SGARROWRIGHTSTR }, { SGTEXT, 0, 0, 3,12, 15,1, N_("AI strength:") }, { SGBOX, 0, 0, 23,12, 7,1, NULL }, { SGBUTTON, SG_EXIT, 0, 23,12, 2,1, SGARROWLEFTSTR }, { SGTEXT, 0, 0, 26,12, 1,1, dlg_p1level }, { SGBUTTON, SG_EXIT, 0, 28,12, 2,1, SGARROWRIGHTSTR }, { SGBOX, 0, 0, 36,3, 34,11, NULL }, { SGTEXT, 0, 0, 47,4, 9,1, N_("Player 2") }, { SGTEXT, 0, 0, 38,6, 5,1, N_("Name:") }, { SGEDITFIELD, 0, 0, 44,6, 22,1, nsp2 }, { SGRADIOBUT, 0, SG_SELECTED, 38,8, 8,1, N_("Human") }, { SGRADIOBUT, 0, 0, 50,8, 10,1, N_("Computer") }, { SGTEXT, 0, 0, 38,10, 15,1, N_("AI strategy:") }, { SGBOX, 0, 0, 54,10, 15,1, NULL }, { SGBUTTON, SG_EXIT, 0, 54,10, 2,1, SGARROWLEFTSTR }, { SGTEXT, 0, 0, 57,10, 8,1, NULL }, { SGBUTTON, SG_EXIT, 0, 67,10, 2,1, SGARROWRIGHTSTR }, { SGTEXT, 0, 0, 38,12, 15,1, N_("AI strength:") }, { SGBOX, 0, 0, 58,12, 7,1, NULL }, { SGBUTTON, SG_EXIT, 0, 58,12, 2,1, SGARROWLEFTSTR }, { SGTEXT, 0, 0, 61,12, 1,1, dlg_p2level }, { SGBUTTON, SG_EXIT, 0, 63,12, 2,1, SGARROWRIGHTSTR }, { SGTEXT, 0, 0, 3,15, 20,1, N_("Maximum rounds:") }, { SGRADIOBUT, 0, 0, 25,15, 4,1, "20" }, { SGRADIOBUT, 0, 0, 31,15, 4,1, "50" }, { SGRADIOBUT, 0, 0, 37,15, 5,1, "100" }, { SGRADIOBUT, 0, SG_SELECTED, 44,15, 12,1, N_("unlimited") }, { SGCHECKBOX, 0, SG_SELECTED, 3,17, 26,1, N_("King may capitulate") }, { SGCHECKBOX, 0, SG_SELECTED, 36,17, 22,1, N_("Players may build") }, { SGBUTTON, 0, 0, 2,20, 20,1, N_("New game") }, { SGBUTTON, SG_DEFAULT, 0, 24,20, 19,1, N_("Continue game") }, { SGBUTTON, 0, 0, 45,20, 20,1, N_("Exit program") }, { -1, 0, 0, 0,0, 0,0, NULL } }; /** * Settings dialog */ int settings(void) { int retbut; int done = 0; SDLGui_CenterDlg(settingsdlg); do { settingsdlg[P1_AISTRATEGYSTR].txt = (char *)cn[cw[0]]; settingsdlg[P2_AISTRATEGYSTR].txt = (char *)cn[cw[1]]; dlg_p1level[0] = '1' + cx[0]; dlg_p2level[0] = '1' + cx[1]; retbut = SDLGui_DoDialog(settingsdlg, NULL); switch (retbut) { case P1_AISTRATEGYLEFT: if (cw[0] > 0) cw[0] -= 1; break; case P1_AISTRATEGYRIGHT: if (cw[0] < 6) cw[0] += 1; break; case P1_AISTRENGTHLEFT: if (cx[0] > 0) cx[0] -= 1; break; case P1_AISTRENGTHRIGHT: if (cx[0] < 3) cx[0] += 1; break; case P2_AISTRATEGYLEFT: if (cw[1] > 0) cw[1] -= 1; break; case P2_AISTRATEGYRIGHT: if (cw[1] < 6) cw[1] += 1; break; case P2_AISTRENGTHLEFT: if (cx[1] > 0) cx[1] -= 1; break; case P2_AISTRENGTHRIGHT: if (cx[1] < 3) cx[1] += 1; break; default: done = 1; } } while (!done); SDL_UpdateRect(surf, 0,0, 0,0); if (settingsdlg[P1_HUMAN].state & SG_SELECTED) { if (settingsdlg[P2_HUMAN].state & SG_SELECTED) mod = 0; /* Human vs. human */ else mod = 1; /* Human vs. computer */ } else { if (settingsdlg[P2_HUMAN].state & SG_SELECTED) mod = 2; /* Computer vs. human */ else mod = 3; /* Computer vs. computer */ } if (mod < 2) l_nam = nsp1; else l_nam = cn[cw[0]]; if (mod & 1) r_nam = cn[cw[1]]; else r_nam = nsp2; /* Max. amount of rounds */ if (settingsdlg[ROUNDS_20].state & SG_SELECTED) max_rund = 20; else if (settingsdlg[ROUNDS_50].state & SG_SELECTED) max_rund = 50; else if (settingsdlg[ROUNDS_100].state & SG_SELECTED) max_rund = 100; else if (settingsdlg[ROUNDS_NOLIMIT].state & SG_SELECTED) max_rund = 32767; /* Is the king allowed to give up? */ au_kap = settingsdlg[GIVEUPALLOWED].state & SG_SELECTED; /* Is repairing allowed? */ an_erl = settingsdlg[REPAIRALLOWED].state & SG_SELECTED; /* New game? */ if (retbut == NEWGAME) { dlg_new_game(); } /* Quit game? */ else if (retbut == QUITGAME || retbut == SDLGUI_QUIT) { return DlgAlert_Query(_("Quit Ballerburg?"), _("Yes"), _("No")); } return 0; } /* ---------------------------------------------------------------- */ static void draw_castle1(int x, int y, int w, int h); static void draw_castle2(int x, int y, int w, int h); #define NEW_P1_PREV 3 #define NEW_P1_NEXT 4 #define NEW_P2_PREV 6 #define NEW_P2_NEXT 7 #define NEW_OK 8 #define NEW_ABORT 9 static SGOBJ newgamedlg[] = { { SGBOX, 0, 0, 0,0, 58,20, NULL }, { SGTEXT, 0, 0, 24,1, 12,1, N_("New game") }, { SGTEXT, 0, 0, 9,3, 23,1, N_("Player 1") }, { SGBUTTON, SG_EXIT, 0, 2,16, 12,1, "\x04" }, // Arrow left { SGBUTTON, SG_EXIT, 0, 16,16, 12,1, "\x03" }, // Arrow right { SGTEXT, 0, 0, 37,3, 23,1, N_("Player 2") }, { SGBUTTON, SG_EXIT, 0, 30,16, 12,1, "\x04" }, // Arrow left { SGBUTTON, SG_EXIT, 0, 44,16, 12,1, "\x03" }, // Arrow right { SGBUTTON, SG_DEFAULT, 0, 19,18, 8,1, "OK" }, { SGBUTTON, SG_CANCEL, 0, 31,18, 8,1, "Cancel" }, { SGBOX, 0, 0, 2,5, 26,10, NULL }, { SGUSER, 0, 0, 2,5, 26,10, (void*)draw_castle1 }, { SGBOX, 0, 0, 30,5, 26,10, NULL }, { SGUSER, 0, 0, 30,5, 26,10, (void*)draw_castle2 }, { -1, 0, 0, 0,0, 0,0, NULL } }; /** * Draw castle */ static void draw_castle(int n, int x, int y, int w, int h) { SDL_Rect rect; short oy0,oy1; rect.x = x + 1; rect.y = y + 1; rect.w = w - 2; rect.h = h - 2; SDL_FillRect(surf, &rect, SDL_MapRGB(surf->format,0xff,0xff,0xff)); oy0 = by[0]; oy1 = by[1]; bx[0]=x; by[0]=y+h; bx[1]=x+w; by[1]=y+h; burg(n+1); by[0]=oy0; by[1]=oy1; } static void draw_castle1(int x, int y, int w, int h) { draw_castle(1, x, y, w, h); } static void draw_castle2(int x, int y, int w, int h) { draw_castle(2, x, y, w, h); } /** * Dialog for "new game" */ void dlg_new_game(void) { int retbut; short ob0, ob1, ol[8]; /* Sichern der alten Werte */ ob0 = bur[0]; ob1 = bur[1]; ol[0]=ge[0]; ol[1]=ge[1]; ol[2]=pu[0]; ol[3]=pu[1]; ol[4]=ku[0]; ol[5]=ku[1]; ol[6]=vo[0]; ol[7]=vo[1]; SDLGui_CenterDlg(newgamedlg); do { retbut = SDLGui_DoDialog(newgamedlg, NULL); switch (retbut) { case NEW_P1_PREV: bur[0] = (bur[0] - 1 + b_anz) % b_anz; break; case NEW_P1_NEXT: bur[0] = (bur[0] + 1 + b_anz) % b_anz; break; case NEW_P2_PREV: bur[1] = (bur[1] - 1 + b_anz) % b_anz; break; case NEW_P2_NEXT: bur[1] = (bur[1] + 1 + b_anz) % b_anz; break; } } while (retbut != NEW_OK && retbut != NEW_ABORT); ge[0]=ol[0]; ge[1]=ol[1]; pu[0]=ol[2]; pu[1]=ol[3]; ku[0]=ol[4]; ku[1]=ol[5]; vo[0]=ol[6]; vo[1]=ol[7]; fn(); if (retbut == NEW_OK) { neues(); werdran(1); } else /* if (retbut == NEW_ABORT) */ { bur[0]=ob0; bur[1]=ob1; } SDL_UpdateRect(surf, 0,0, 0,0); } ballerburg-1.2.0/src/music.h0000644000175000017500000000211212506012141015247 0ustar thomasthomas/* music.h - prototypes and definitions for music.c Copyright (C) 2011 Thomas Huth This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ void m_laden(const char * string); void m_quit(void); void m_musik(void); void m_wloop(void); void s_note(unsigned int wert); void s_init(void); void s_quit(void); void s_freq(unsigned short freq); void s_laut(short laut); void s_rausch(short periode); void s_t_an(void); void s_t_aus(void); void s_r_an(void); void s_r_aus(void); void s_aus(void); ballerburg-1.2.0/src/ballergui.c0000664000175000017500000000460712506012141016105 0ustar thomasthomas/* ballergui.c - GUI related functions for Ballerburg Copyright (C) 2010, 2013 Thomas Huth This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include "i18n.h" #include "baller1.h" #include "ballergui.h" #include "screen.h" #include "settings.h" static int gui_handle_keys(SDL_Event *ev, int allow_dlgs) { static bool in_table = false; switch (ev->key.keysym.sym) { case SDLK_ESCAPE: if (allow_dlgs) return settings(); break; case SDLK_f: scr_togglefullscreen(); break; case SDLK_t: if (in_table || !allow_dlgs) break; in_table = true; tabelle(); in_table = false; break; case SDLK_q: return DlgAlert_Query(_("Quit Ballerburg?"), _("Yes"), _("No")); default: break; } return 0; } int event(int wait, int allow_dlgs) { int ev_avail; SDL_Event ev; static bool quitflag = false; // printf("event(%i)\n", wait); if (quitflag) return 1; if (wait) ev_avail = SDL_WaitEvent(&ev); else ev_avail = SDL_PollEvent(&ev); while (ev_avail) { // printf("EVENT = %i\n", ev.type); switch(ev.type) { case SDL_QUIT: quitflag = true; return 1; case SDL_MOUSEMOTION: /* Read/Update internal mouse position */ mx = ev.motion.x; my = ev.motion.y; break; case SDL_MOUSEBUTTONDOWN: if (ev.button.button == SDL_BUTTON_LEFT) { bt |= 1; } else if (ev.button.button == SDL_BUTTON_RIGHT) { bt |= 2; } break; case SDL_MOUSEBUTTONUP: if (ev.button.button == SDL_BUTTON_LEFT) { bt &= ~1; } else if (ev.button.button == SDL_BUTTON_RIGHT) { bt &= ~2; } break; case SDL_KEYUP: if (gui_handle_keys(&ev, allow_dlgs)) { quitflag = true; return 1; } break; } ev_avail = SDL_PollEvent(&ev); } return 0; } ballerburg-1.2.0/src/sdlgui.h0000644000175000017500000000513312506012141015424 0ustar thomasthomas/* * sdlgui.h - Header for the tiny graphical user interface for the SDL library. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This file is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * (http://www.gnu.org/licenses/) for more details. */ #ifndef SDLGUI_H #define SDLGUI_H #include enum { SGBOX, SGTEXT, SGEDITFIELD, SGBUTTON, SGRADIOBUT, SGCHECKBOX, SGPOPUP, SGSCROLLBAR, SGUSER }; /* Object flags: */ #define SG_TOUCHEXIT 1 /* Exit immediately when mouse button is pressed down */ #define SG_EXIT 2 /* Exit when mouse button has been pressed (and released) */ #define SG_DEFAULT 4 /* Marks a default button, selectable with return key */ #define SG_CANCEL 8 /* Marks a cancel button, selectable with ESC key */ /* Object states: */ #define SG_SELECTED 1 #define SG_MOUSEDOWN 16 #define SG_MOUSEUP (((int)-1) - SG_MOUSEDOWN) /* Special characters: */ #define SGRADIOBUTTON_NORMAL 12 #define SGRADIOBUTTON_SELECTED 13 #define SGCHECKBOX_NORMAL 14 #define SGCHECKBOX_SELECTED 15 #define SGARROWUP 1 #define SGARROWDOWN 2 #define SGFOLDER 5 #define SGARROWLEFTSTR "\x04" #define SGARROWRIGHTSTR "\x03" /* Return codes: */ #define SDLGUI_ERROR -1 #define SDLGUI_QUIT -2 #define SDLGUI_UNKNOWNEVENT -3 typedef struct { int type; /* What type of object */ int flags; /* Object flags */ int state; /* Object state */ int x, y; /* The offset to the upper left corner */ int w, h; /* Width and height (for scrollbar : height and position) */ char *txt; /* Text string */ } SGOBJ; extern int sdlgui_fontwidth; /* Width of the actual font */ extern int sdlgui_fontheight; /* Height of the actual font */ extern int SDLGui_Init(void); extern int SDLGui_UnInit(void); extern int SDLGui_SetScreen(SDL_Surface *pScrn); extern void SDLGui_GetFontSize(int *width, int *height); extern void SDLGui_Text(int x, int y, const char *txt); extern void SDLGui_DrawDialog(const SGOBJ *dlg); extern int SDLGui_DoDialog(SGOBJ *dlg, SDL_Event *pEventOut); extern void SDLGui_CenterDlg(SGOBJ *dlg); void SDLGui_DrawButton(const SGOBJ *bdlg, int objnum); #endif ballerburg-1.2.0/src/baller2.h0000644000175000017500000000232312506012141015456 0ustar thomasthomas/* baller2.h - prototypes and definitions for baller2.c Copyright (C) 2010 Thomas Huth This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ int comp(void); void z_kn(void); void z_ka(void); void z_ft(void); void z_ge(void); void z_pk(void); void schuss(int k); void expls(int x, int y, int w, int h, int d); int kugel(int x, int y); void baller(unsigned char r); void bild(void); void burg(int nn); void init_ka(int k, int xr); void drw_all(void); void drw_gpk(char w); void draw(short x, short y, short *a); void fturm(void); void koenig(void); int drin(short xk, short yk, short w, short h, short r, short x, short y); ballerburg-1.2.0/src/CMakeLists.txt0000664000175000017500000000106712506012141016530 0ustar thomasthomas include_directories(${CMAKE_BINARY_DIR} ${MATH_INCLUDE_DIR} ${SDL_INCLUDE_DIR} ${SDLGFX_INCLUDE_DIR}) add_executable (ballerburg baller1.c baller2.c ballergui.c cannoneer.c screen.c psg.c dlgAlert.c sdlgui.c market.c music.c paths.c settings.c sdlgfx.c) target_link_libraries(ballerburg ${SDL_LIBRARY} ${MATH_LIBRARY}) if(SDLMAIN_LIBRARY) target_link_libraries(ballerburg ${SDLMAIN_LIBRARY}) endif(SDLMAIN_LIBRARY) install(TARGETS ballerburg RUNTIME DESTINATION ${BINDIR}) install(FILES baller.dat baller.mus DESTINATION ${DATADIR}) ballerburg-1.2.0/src/music.c0000664000175000017500000002340112506012141015250 0ustar thomasthomas/* music.c Copyright (C) 1986 Eckhard Kruse Copyright (C) 2011 Thomas Huth This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /********************************************************************* * Abspielen von Musik-Editor Stcken * * * * Gleich einmal vorweg wie ein Programm aussieht, das die hier * * definierten Routinen verwendet: * * * * extern void m_laden(), m_musik(), m_wloop(); * * main() * * { * * int save_ssp; * * m_laden("DATEI.MUS"); Datei laden * * m_musik(); Musik abspielen * * } * * int m_wait() Warteschleife * * { * * m_wloop(); * * return 0; return 1 um abzubrechen * * } * *********************************************************************/ #include #include #include #include #include "psg.h" #include "music.h" #include "paths.h" extern int m_wait(void); /* Diese Funktion muss in Ihrem Hauptprogramm stehen, * * sie wird von m_musik() nach jedem 1/96 Takt aufgerufen, und sie sollte * * immer eine bestimmte Zeitspanne warten ( bestimmt die Ablaufgeschwindig- * * keit der Musik ). Dies kann durch den Aufruf von m_wloop() geschehen. */ unsigned short *takte; short buffer[100], *liste, max_abl, max_tkt, walz, tempo, temp, w_len, save7, reg7, kanal, tra[3], lau[3]; /**************** Tabellen fr Noten- und Frequenzwerte **********************/ short st_wert[] = { 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 27, 28, 30, 32, 34, 36, 38, 40, 42, 45, 47, 50, 53, 56, 60, 63, 67, 71, 75, 80, 84, 89, 95, 100, 106, 113, 119, 127, 134, 142, 150, 159, 169, 179, 190, 201, 213, 226, 239, 253, 268, 284, 301, 319, 338, 358, 379, 402, 426, 451, 478, 506, 536, 568, 602, 638, 676, 716, 759, 804, 852, 903, 956, 1013, 1073, 1136, 1204, 1276, 1351, 1432, 1517, 1607, 1703, 1804, 1911, 2025, 2145, 2273, 2408, 2553, 2703, 2864, 3034, 3214, 3405, 3608, 3823 } ; char st_ton[] = { 0, 1, 3, 5, 7, 8, 10, 12, 13, 15, 17, 19, 20, 22, 24, 25, 27, 29, 31, 32, 34, 36, 37, 39, 41, 43, 44, 46, 48, 49, 51, 53, 55, 56, 58, 60, 61, 63, 65, 67, 68, 70, 72, 73, 75, 77, 79, 80, 82, 84, 85, 87, 89, 91, 92, 94, 96 } ; /******************** Laden und Speicher reservieren *************************/ void m_laden(const char * string) { FILE *f_handle; int i; char *fname; fname = malloc(FILENAME_MAX); if (!fname) { perror("m_laden"); return; } snprintf(fname, FILENAME_MAX, "%s/%s", Paths_GetDataDir(), string); /* Open file in data directory */ f_handle = fopen(fname, "rb"); free(fname); fname = NULL; if (!f_handle) { /* Try local directory instead */ f_handle = fopen(string, "rb"); if (!f_handle) { perror("Loading music failed"); return; } } if (fread(buffer, 16, 1, f_handle) != 1) { perror("Failed to read music file"); goto out; } for (i = 0; i < 16/2; i++) { buffer[i] = SDL_SwapBE16(buffer[i]); } tempo=buffer[2]; max_abl=buffer[3]; max_tkt=buffer[4]; walz=buffer[7]; if( walz ) w_len=72; else w_len=96; liste=( short *)malloc((max_abl+2)<<3 ); /* Reserviere Speicherbereich der Gre (w_len*2)*(max_tkt+2) und lsch ihn. */ takte=( unsigned short *)calloc( w_len*2, max_tkt+2+2 ); if (fread(buffer, 1, 36, f_handle) != 36) { perror("Failed to read music file"); goto out; } for (i = 0; i < 36/2; i++) { buffer[i] = SDL_SwapBE16(buffer[i]); } if (fread(liste, (max_abl+1)<<3, 1, f_handle) != 1) { perror("Failed to read music file"); goto out; } for (i = 0; i < ((max_abl+1)<<3)/2; i++) { liste[i] = SDL_SwapBE16(liste[i]); } if (fread(&takte[100], (max_tkt+1)*w_len, 2, f_handle) != 2) { perror("Failed to read music file"); goto out; } for (i = 0; i < (max_tkt+1)*w_len; i++) { takte[100+i] = SDL_SwapBE16(takte[100+i]); } out: fclose(f_handle); } void m_quit(void) { free(liste); liste = NULL; free(takte); takte = NULL; } /************************ Stck spielen **************************************/ void m_musik(void) { short buf_ptr, lis_ptr, ende, help, kan1, kan2, kan3, rau; if (!liste || !takte) return; s_init(); buffer[0]=0; buffer[1]=-2; buf_ptr=2; lis_ptr=0; temp=100; lau[0]=lau[1]=lau[2]=100; tra[0]=tra[1]=tra[2]=0; ende=0; while( !ende ) { switch( liste[lis_ptr] ) { case -1: if( buffer[--buf_ptr]==-2 ) ende=1; lis_ptr=buffer[--buf_ptr]; break; case -2: tra[0]=liste[++lis_ptr]; tra[1]=liste[++lis_ptr]; tra[2]=liste[++lis_ptr]; lis_ptr++; break; case -3: lau[0]=liste[++lis_ptr]; lau[1]=liste[++lis_ptr]; lau[2]=liste[++lis_ptr]; lis_ptr++; break; case -4: temp=liste[++lis_ptr]; lis_ptr+=3; break; case -5: lis_ptr+=4; buffer[buf_ptr++]=lis_ptr; buffer[buf_ptr++]=0; break; case -6: lis_ptr+=4; if( buffer[buf_ptr-1]==liste[lis_ptr-3] ) { buf_ptr-=2; help=0; while( help>=0 ) { if( liste[lis_ptr]==-1 ) help=-1; help+=( liste[lis_ptr]==-5 )-( liste[lis_ptr]==-7 ); lis_ptr+=4; } } break; case -7: buffer[buf_ptr-1]++; lis_ptr=buffer[buf_ptr-2]; break; case -8: if( liste[++lis_ptr]<0 ) lis_ptr+=3; else { buffer[buf_ptr++]=lis_ptr+3; buffer[buf_ptr++]=-5; lis_ptr=(liste[lis_ptr]-1)<<2; } break; default: rau =( liste[lis_ptr]>=0 )*(( liste[lis_ptr+0] )*w_len +100); lis_ptr++; kan1=( liste[lis_ptr]>=0 )*(( liste[lis_ptr+0] )*w_len +100); lis_ptr++; kan2=( liste[lis_ptr]>=0 )*(( liste[lis_ptr+0] )*w_len +100); lis_ptr++; kan3=( liste[lis_ptr]>=0 )*(( liste[lis_ptr+0] )*w_len +100); lis_ptr++; for( help=0; help>2 & 63 ]; if( wert & 0x4000 ) ton_nr--; if( wert & 0x8000 ) ton_nr++; if( ( wert & 0xc000 ) == 0xc000 ) { s_rausch( wert&255 ); } else { ton_nr-=tra[kanal]; if( ton_nr<0 ) ton_nr=0; if( ton_nr>95 ) ton_nr=95; s_freq( (st_wert[ton_nr]*(4-(wert&3))+st_wert[ton_nr+1]*(wert&3) )>>2 ); if( wert & 0x1000 ) s_t_an(); else s_t_aus(); if( wert & 0x2000 ) s_r_an(); else s_r_aus(); s_laut( (wert>>8 & 15)*lau[kanal]/100 ); } } /*************************** Sound Ansteuerung *******************************/ /**************************** Initialisierung ********************************/ void s_init(void) { reg7=save7=Giaccess( 0, 0x07 ); s_rausch( 0 ); } /*********************** Wiederherstellen vor Ende ***************************/ void s_quit(void) { s_aus(); Giaccess( save7, 0x87 ); } /************************** Tonfrequenz setzen *******************************/ void s_freq(unsigned short freq) { short kan; kan=kanal<<1; Giaccess( freq&0xff, kan+0x80 ); Giaccess( freq>>8, kan+0x81 ); } /************************** Lautstrke setzen ********************************/ void s_laut(short laut) { Giaccess( laut, kanal+0x88 ); } /************************* Rauschperiode setzen ******************************/ void s_rausch(short periode) { Giaccess( periode, 0x86 ); } /**************************** Ton einschalten ********************************/ void s_t_an(void) { reg7&=( 254-kanal-( kanal==2 ) ); Giaccess( reg7, 0x87 ); } /**************************** Ton ausschalten ********************************/ void s_t_aus(void) { reg7|=( 1+kanal+( kanal==2 ) ); Giaccess( reg7, 0x87 ); } /*************************** Rauschen einschalten ****************************/ void s_r_an(void) { reg7 &= 255 -((1 + kanal + (kanal == 2)) << 3); Giaccess(reg7, 0x87); } /*************************** Rauschen ausschalten ****************************/ void s_r_aus(void) { reg7 |= ((1 + kanal + (kanal == 2)) << 3); Giaccess(reg7, 0x87); } /*************************** Sound abschalten ********************************/ void s_aus(void) { kanal=0; s_laut( 0 ); kanal=1; s_laut( 0 ); kanal=2; s_laut( 0 ); } ballerburg-1.2.0/src/i18n.h0000644000175000017500000000054712506012141014720 0ustar thomasthomas #ifndef BALLER_I18N_H #define BALLER_I18N_H #include #if HAVE_LIBINTL_H #include #define _(string) ((string)[0]?gettext(string):(string)) #define gettext_noop(string) string #define N_(string) gettext_noop(string) #else #define _(string) (string) #define N_(string) string #endif /* HAVE_GETTEXT */ #endif /* BALLER_I18N_H */ ballerburg-1.2.0/src/ballergui.h0000644000175000017500000000007412506012141016102 0ustar thomasthomas int event(int wait, int allow_dlgs); int sch_obj(short k); ballerburg-1.2.0/src/screen.h0000664000175000017500000000376712506012141015431 0ustar thomasthomas/* screen.h - prototypes and definitions for screen.c Copyright (C) 2010, 2013 Thomas Huth This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include extern SDL_Surface *surf; void scr_init(void); void scr_exit(void); void scr_togglefullscreen(void); void scr_clear(void); void scr_l_text(int x, int y, const char *text); void scr_ctr_text(int cx, int y, const char *text); void scr_circle(int x, int y, int w); void scr_sf_interior(short val); void scr_sf_style(short val); void scr_bar(short *xy); void clr(short x, short y, short w, short h); void clr_bg(short x, short y, short w, short h); void scr_fillarea(short num, short *xy); void scr_pline(short num, short *xy); void scr_line(int x1, int y1, int x2, int y2, int rgba); int scr_getpixel(int x, int y); void scr_color(int c); void scr_fillcolor(int c); void color(int a); void scr_init_done_button(int *bx, int *by, int *bw, int *bh); void scr_draw_done_button(int selected); void scr_cannonball(int x, int y); void *scr_save_bg(int x, int y, int w, int h); void scr_restore_bg(void *ps); void scr_update(int x, int y, int w, int h); int DlgAlert_Notice(const char *text, const char *button); int DlgAlert_Query(const char *text, const char *button1, const char *button2); #if WITH_SDL2 void SDL_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects); void SDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Sint32 w, Sint32 h); #endif ballerburg-1.2.0/src/baller2.c0000664000175000017500000003707712506012141015471 0ustar thomasthomas/* baller2.c Copyright (C) 1987, 1989 Eckhard Kruse Copyright (C) 2010, 2014 Thomas Huth This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /***************************************************************************** * B a l l e r b u r g Modul 2 * * Dies ist der zweite Teil des Ballerburg Sourcecode. Hier werden die * * Computer gesteuert und der Flug der Kugel dargestellt. Auerdem sind * * alle Routinen in Zusammenhang mit dem Knig beinhaltet. * *****************************************************************************/ #include #include #include #include #include "i18n.h" #include "baller1.h" #include "baller2.h" #include "screen.h" #include "psg.h" #include "market.h" #define Min(a,b) ((a)<(b)?(a):(b)) #define Max(a,b) ((a)>(b)?(a):(b)) #define hide() /*graf_mouse(256,0)*/ #define show() /*graf_mouse(257,0)*/ void expls(int x, int y, int w, int h, int d); /***************** Grafikdaten fr Trohn, Kanone... **************************/ short trohn[]={ -2,2,2, 8,3,5,12,8,12,12,16,12,17,14,15, 15,15,17,17,17,16,21,11,24,11,21,3,-9, -4, 3,0,5,2,24,2,26,0,-9, 19,4,18,9,-9, 10,4,11,9,-9, 14,4,15,4,-9, 8,10,11,11,-9, 21,10,18,11,-9, 14,17,15,17,-9, 13,19,13,19,-9, 16,19,16,19,-9, 12,22,12,21,15,21,14,22, 17,21,17,22,-9, 6,13,6,17,5,16,5,17,7,17,7,16,-9, -1 }, kanon[]={ -2,1,1, 1,0,3,3,5,0,3,3,3,11,2,11,2,9,4,9,4,11,3,11,3,8,0,5, 3,8,6,5,3,8,3,3,-9, 11,0,13,2,15,0,16,0,17,1,17,2,15,4,19,8,16,11,8,3,-9, -1 }, sack[]={ -4, 1,1,1,4,2,5,2,0,3,0,3,8,2,8,4,8,3,8,3,6,4,6,4,0,5,0, 5,6,6,5,6,1,-9, -1 }, fass[]={ -4, 2,0,6,0,8,3,8,5,6,8,2,8,0,5,0,3,2,0,3,0,3,3,2,4,3,5,3,8, 5,8,5,5,6,4,5,3,5,1,-9, -1 }, kuge[]={ -2,1,1, 1,0,0,1,0,3,1,4,3,4,4,3,4,1,3,0,-9,-1 }, turm[]={ -4, 23,30,27,0,3,10,24,20,6,30,23,30,5,20,26,10,2,0,6,30,-9, 8,0,8,31,9,34,11,36,14,37,15,37,18,36,20,34,21,31,21,29,20,26,18,24,15,23, 14,23,11,24,9,26,8,29,-9, 14,23,15,37,-9, 10,25,19,35,-9, 10,35,19,25,-9, 21,30,21,0,-9, -1 }; /************************ Der Computer agiert: *******************************/ int zx,zy; /* Koordinaten des Zieles */ short *bh; static double vvx,vvy; int comp(void) /* Fhrt einen Zug des Computers durch */ { char wd; int i,t; register double x2=0,x,y,vx2,vx,vy=0,wi; st[n]=16; for ( i=0;i<10;i++ ) if ( ka[n][i].x>-1 ) break; if ( pu[n]<20 && ge[n]>=p[4] ) { pu[n]+=30; /* Pulv. kaufen*/ ge[n]-=p[4]; } if ( !ku[n] && ge[n]>=p[5] ) { ku[n]+=2; /* Kug. kaufen*/ ge[n]-=p[5]; } if ( i>9 && ge[n]>=p[2] ) { init_ka(i=0,639*n); /* Ka. kauf.*/ ge[n]-=p[2]; } if ( (ft[n][0].x<0 || ft[n][1].x<0 || ft[n][2].x<0 ) && ge[n]>=p[1] && cw[n]>2 ) { ge[n]-=p[1]; /* Frderturm kaufen */ fturm(); } drw_all(); if ( i>9 || pu[n]<20 || !ku[n] ) return(-1); /* Jetzt kommen die Berechnungen fr den Schuss: */ bh=burgen[bur[!n]]; do i=rand()%10; while ( ka[n][i].x==-1 ); zx=639*!n-f*(rand()%bh[0]); zy=by[!n]; t=rand()%100; if ( cw[n] ) z_kn(); switch ( cw[n] ) /* Die verschiedenen Strategien */ { case 1: if ( t<30 ) z_ge(); if ( t>60 ) z_pk(); break; case 2: z_ka(); if ( t<90 ) z_ge(); break; case 3: if ( t<50 )z_ka(); else if ( t<70 )z_ge(); else if ( t<90 )z_pk(); if ( !(rand()%3) ) z_ft(); break; case 4: z_ka(); break; case 5: z_ka(); if ( t<90 ) z_ft(); } y=ka[n][i].y-10-zy; t=49-cx[n]*16; /* Berechnen der Distanz */ x=ka[n][i].x+10+7*f-zx -t/2+rand()%t; if ( x<0 ) x=-x; wd=n? -wnd:wnd; x2=-1; for ( vx=.5; vx<7 && ( x2vx ); ) /* Zeitberechnung bei */ { /* verschiedenen X-Geschwindigkeiten */ vx+=.4; t=x2=0; vx2=vx; while ( vx2>0 && x2-1 ) break; if ( i<10 ) { do i=rand()%10; while ( ka[!n][i].x==-1 ); zx=ka[!n][i].x+10; zy=ka[!n][i].y; } } void z_ft(void) { short i; for ( i=0;i<5;i++ ) if ( ft[!n][i].x>-1 ) break; if ( i<5 ) { zx=ft[!n][i].x-15*f; zy=ft[!n][i].y-10; } } void z_ge(void) { if ( ge[!n]>100 ) { zx=!n*639-f*(bh[25]+bh[31]/2); zy=by[!n]-bh[26]; } } void z_pk(void) { short i; if ( ku[!n] || pu[!n]>19 ) { i=rand()&2; zx=!n*639-f*(bh[27+i]+bh[33+i]/2); zy=by[!n]-bh[28+i]; } } /********************************* Ein Schuss ********************************/ /* k = Nr. der Kanone */ void schuss(int k) { double x, y; double ox = 0.0, oy = 0.0; double vx, vy; short v,c,a, j; short oldn; hide(); pu[n]-=ka[n][k].p; ku[n]--; drw_gpk(1); drw_gpk(2); x=ka[n][k].x+10+7*f; y=ka[n][k].y-10; c=2; vx=(.4+0.25*ka[n][k].p)*cos( ka[n][k].w/P57 )*f; vy=(.4+0.25*ka[n][k].p)*sin( ka[n][k].w/P57 ); if ( mod&(2-n) ) { vx=vvx; vy=vvy; } color(1); baller(0); kugel( (int)x,(int)y ); scr_update(x - 3, y - 3, 6, 6); v=1; while ( x>3 && x<637 && y<396 && ( v || c ) ) /* Flugschleife */ { ox=x; oy=y; x+=vx; y-=vy; vy-=G; vx+=(wnd/2-vx)/5000; color(0); kugel( (int)ox,(int)oy ); if (x>=3 && x<=637 && y>= 3 && y <= 397) { int i; v &= !loc((int)x,(int)y); for (i = -1; i <= 1; i++) { v = v & !loc((int)x-2, (int)y+i) & !loc((int)x+2, (int)y+i) & !loc((int)x+i, (int)y+2); } } color(1); kugel( (int)x,(int)y ); scr_update(Min(ox, x)-3, Min(oy, y)-3, abs(ox-x)+7, abs(oy-y)+7); SDL_Delay(8); SDL_PumpEvents(); a=1000+2*y; if ( a<30 ) a=30; Giaccess( 10,137 ); Giaccess( 244,135 ); Giaccess( a&255,130 ); Giaccess( a>>8,131 ); if (c > 0) { c--; if (c == 0) draw(ka[n][k].x+20*n, ka[n][k].y, kanon); } } color( 0 ); kugel( (int)x,(int)y ); scr_update(x - 3, y - 3, 6, 6); draw(ka[n][k].x+20*n, ka[n][k].y, kanon); oldn=n; if ( !v ) for ( c=0;c<4;c++ ) /* Einschlag der Kugel */ { if (ox > 6 && ox < 634) scr_circle((int)ox, (int)oy, 5); baller(22+c*3); for ( n=0;n<2;n++ ) /* Treffer ? */ { bg=burgen[bur[n]]; if ( rand()&1 && (n? x>639-bg[0] : xox && ka[n][j].x>-1 && ka[n][j].y-16oy ) { clr_bg( a=ka[n][j].x,v=ka[n][j].y-12,20,13 ); expls( a+10,v+6,10,8,50 ); color(0); ka[n][j].x=-1; } for ( j=0;j<5;j++ ) if ( ft[n][j].x>-1 && drin( a=639*n+f*ft[n][j].x,v=by[n]-ft[n][j].y, 30,37,2,(int)ox,(int)oy ) ) { if ( drin( a,v,30,37,-2,(int)ox,(int)oy ) ) { expls((a=ft[n][j].x-29*n)+15,(v=ft[n][j].y-40)+20,15,20,120); clr_bg( a,v,30,40 ); ft[n][j].x=-1; } c=4; } if ( ox>wx[n]-11 && oxwy[n]-16 && oy-1) { /* Windfahne getroffen */ clr_bg(wx[n]-10, wy[n]-15, 20, 15); wx[n]=-1; } if ( drin( bg[21],bg[22],30,25,0,(int)ox,(int)oy ) ) { end=n+17; expls( a=639*n+f*(bg[21]+15),v=by[n]-bg[22]-12,17,17,40 ); scr_circle(a, v, 17); expls( a,v,17,17,200 ); c=4; } for ( j=0;j<6;j+=2 ) if ( drin( bg[25+j],bg[26+j],a=bg[31+j],v=bg[32+j],3, (int)ox,(int)oy ) ) break; switch ( j ) { case 0: ge[n]-=Min(200,ge[n]); break; case 2: pu[n]=0; break; case 4: ku[n]-=Min(2,ku[n]); } if ( j<6 ) { expls( 639*n+f*(bg[25+j]+a/2),by[n]-bg[26+j]-v/2, a/2,v/2,60+100*(j==2) ); drw_gpk(j/2); c=4; } } ox+=vx; oy-=vy; } n=oldn; fn(); Giaccess( 0,137 ); show(); } /****************************** Explosion ************************************/ void expls(int x, int y, int w, int h, int d) { int i,j; color(0); for ( i=0;i<32; ) { xy[i++]=x; xy[i++]=y; } while ( d-->0 ) { int fire_col; scr_pline(2, xy); memmove(xy, xy+4, 120); for ( j=28;j<32; ) { xy[j++]=x-w+w*(rand()&511)/256; xy[j++]=y-h+h*(rand()&511)/256; } fire_col = (rand()&0x3f) + 0xc0; fire_col = (fire_col << 16) | ((rand()%fire_col) << 8); scr_line(xy[28], xy[29], xy[30], xy[31], fire_col); scr_update(x-w, y-h, w*2, h*2); baller((d&31)^31); SDL_Delay(10); } for ( i=0;i<32;i+=4 ) { scr_pline(2, xy+i); } } int kugel(int x, int y) { if (x < 3 || x > 637 || y < 3 || y > 397) return 0; scr_cannonball(x, y); return 1; } void baller(unsigned char r) { static unsigned char s_bal[] = { 0,0, 1,15, 6,31, 9,0, 11,0, 12,50, 13,0, 7,192, 8,16, 255,0 }; s_bal[5] = r; Dosound( s_bal ); SDL_Delay(10); } /**************************** Neues Bild zeichnen ****************************/ void bild(void) { short y,x1,x2,v1,v2; hide(); scr_clear(); by[0] = (rand()%80 + 300) & ~3; by[1] = (rand()%80 + 300) & ~3; y=400; x1=0; x2=2556; color( 1 ); v1=v2=2; while ( x120 ) { int green = 0x70 + (400-y)/4; scr_line(x1/4, y, x2/4, y, 0x300030+(green<<8)); if (y == by[0]) { x1 = *burgen[bur[0]] * 4; } if (y == by[1]) { x2 = (639 - *burgen[bur[1]]) << 2; } if ( x1 ) { v1=v1+rand()%5-2; v1=Max(0,v1); v1=Min(7,v1); x1+=v1; } if ( x2<2556 ) { v2=v2+rand()%5-2; v2=Max(0,v2); v2=Min(7,v2); x2-=v2; } } memset(ka, -1, sizeof(ka)); burg(0); burg(1); scr_update(0, 0, 640, 400); scr_l_text(276, 395+16, _(" Round ")); scr_draw_done_button(0); show(); } /***************************** Burg zeichnen *********************************/ void burg(int nn) { short i,xr; short oldn; oldn=n; n=nn; fn(); xr=n&2? bx[n&=1]:639*n; bg=burgen[bur[n]]; ge[n]=bg[37]; pu[n]=bg[38]; ku[n]=bg[39]; vo[n]=bg[40]; color(1); draw( xr,by[n], &bg[45] ); clr( xr+f*bg[21]-n*30,by[n]-bg[22]-25,30,25 ); color(1); draw( xr+f*bg[21],by[n]-bg[22], trohn ); n=nn; for ( i=0; i<10 && bg[i*2+1]>-1; i++ ) init_ka( i,xr ); drw_all(); n=oldn; } void init_ka(int k, int xr) /* Kanone k setzen */ { short x,y; draw( x=xr+bg[1+k*2]*f, y=by[n&1]-bg[2+k*2], kanon ); if ( ~n&2 ) { ka[n][k].x=x-20*n; ka[n][k].y=y; ka[n][k].w=45; ka[n][k].p=12; } } void drw_all(void) /* Geld, Pulver und Kugeln zeichnen */ { drw_gpk(0); drw_gpk(1); drw_gpk(2); } void drw_gpk(char w) { short i = 0,z, x,y, xr,yr, xp = 0, yp = 0, m=n&1; short *a = NULL; switch ( w ) { case 0: a=sack; xp=7; yp=10; i=(ge[m]+149)/150; break; case 1: a=fass; xp=yp=9; i=(pu[m]+29)/30; break; case 2: a=kuge; xp=yp=6; i=ku[m]; } bg=burgen[bur[m]]; w*=2; xr=(n&2? bx[m]:639*m)+f*bg[25+w]; yr=by[m]-bg[26+w]; hide(); clr( xr-bg[31+w]*m-!n,yr-bg[32+w],bg[31+w]+1,bg[32+w]+1 ); color(1); for ( y=z=0; i>0 && y0 && x0 ) /* Maximalbetrag berschritten ? */ switch ( w ) { case 0: ge[m]=z*150; break; case 2: pu[m]=z*30; break; case 4: ku[m]=z; } } /***************************** Zeichenroutine ********************************/ void draw(short x, short y, short *a) { short i,fil=1; hide(); scr_sf_interior(2); scr_sf_style(9); while ( *a!=-1 ) { if ( *a==-2 ) { scr_sf_interior(*++a); scr_sf_style(*++a); } else if ( *a==-4 ) fil=!fil; else { i=0; while ( *a>-1 ) { xy[i++]=x+*a++*f; xy[i++]=y-*a++; } xy[i++]=xy[0]; xy[i++]=xy[1]; if (fil) scr_fillarea(i/2, xy); else scr_pline(i/2-1, xy); } a++; } show(); } /** * Frderturm bauen */ void fturm(void) { short x,y,yy,i,t; hide(); for ( t=0;t<5;t++ ) if ( ft[n][t].x==-1 ) break; x=639*n+f*(bg[0]+20+30*t); y=380; do { while ( loc(x,y) && loc(x+29*f,y--) ); yy=y; for ( i=0;i<40;i++,y-- ) if ( loc(x,y) && loc(x+29*f,y) ) break; } while ( i<40 ); y=yy; clr_bg( x-29*n,y-70,30,70 ); color( 1 ); draw( ft[n][t].x=x,ft[n][t].y=y,turm ); show(); } /* ************************ Audience with the king ************************* */ const char kna[] = N_("The king says:"), kne[] = N_("Humbly acknowledged"), kn0[] = N_("Well...\n alright...\n Carry on..."), kn1[] = N_("We are satisfied\n with your performance!"), kn2[] = N_("Excellent,\n keep at it!"), kn3[] = N_("Maybe you ought to\n lower Our taxes..."), kn4[] = N_("If you keep this up,\n We shall discharge you!"), kn5[] = N_("Why don't you buy\n a shaft tower..."), kn6[] = N_("You ought to\n kindly make more of\n an effort!"), kn7[] = N_("You don't need to visit Us\n in each round."), kn8[] = N_("Are you aware\n that you have already visited Us\n %d times thus far?"), kn9[] = N_("So, are you certain\n that you will manage\n without a weather vane?"), kn10[] = N_("Nice to see you..."), kn11[] = N_("What are We supposed\n to say in such an\n early phase?"), kn12[] = N_("You ought to earn more money,\n build more shaft towers,\n and vanquish the opponent."), kn13[] = N_("We do not have anything new\n to say to you."), kn14[] = N_("We are pleased for you\n to come around and visit Us."); void koenig(void) { char a[300]; static char kn_visited[80]; const char *s[20]; char k, t; int i, j; static const char *ltz[2]; for ( j=k=0;j<10;j++ ) k+=ka[n][j].x>-1; for ( j=t=0;j<5;j++ ) t+=ft[n][j].x>-1; if ( !(rand()%20) || kn[n]&16 || (kn[n]&15)>9 ) DlgAlert_Notice(_("The king is not in the mood\nto talk to you."), _("Too bad.")); else { sprintf(kn_visited, _(kn8), kn[n]/256); j=rand(); i=2; s[0]=j&1 ? _(kn0) : _(kn10); s[1]=j&2 ? _(kn12) : _(kn6); if ( j&4 ) s[i++] = _(kn14); if (ge[n] > p[1] && t < 3) s[i++] = _(kn5); if ((st[n] > 40 && vo[n] < bg[40]) || st[n] > 70) s[i++] = _(kn3); if (wx[n] < 0) s[i++] = _(kn9); if (ge[n] > bg[37] && vo[n] > bg[40] && k > 1) s[1] = t<2 ? _(kn1) : _(kn2); if (t > 2) s[i++] = _(kn2); if (k < 1 && ge[n] < p[2]) s[i++] = _(kn4); if ((kn[n]&15) > 4) { s[i++] = _(kn7); s[i++] = _(kn7); s[i++] = _(kn7); } if ((kn[n]&15) > 6 || (!(rand()&7) && kn[n] > 2048)) { s[i++] = kn_visited; s[i++] = kn_visited; } if (zug < 4) s[1] = s[2] = s[(i=4)-1] = _(kn11); do if (s[j=rand()%i] == ltz[n]) { s[i++] = _(kn13); s[i++] = _(kn13); } while (s[j] == ltz[n]); ltz[n] = s[j]; snprintf(a, sizeof(a), "%s\n'%s'", _(kna), s[j]); DlgAlert_Notice(a, _(kne)); } kn[n]|=16; kn[n]+=256; if ( ~kn[n]&15 ) kn[n]++; } /* Test, ob Koord. innerhalb eines Rechteckes */ int drin(short xk, short yk, short w, short h, short r, short x, short y) { if ( n ) xk=639-xk-w; return( x>xk-r && xby[n]-yk-h-r ); } ballerburg-1.2.0/src/baller1.c0000664000175000017500000003524312506012141015461 0ustar thomasthomas/* baller1.c Copyright (C) 1987, 1989 Eckhard Kruse Copyright (C) 2010, 2013 Thomas Huth This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /********************************************************************** * B a l l e r b u r g Modul 1 * * Dies ist der Hauptteil von Ballerburg. Die Routinen dieses Teils * * dienen im groen und ganzen der Steuerung des Programmes, sowie * * der Ausfhrung elementarer Grafikoperationen. * **********************************************************************/ #include #include #include #include #include #include "baller1.h" #include "baller2.h" #include "ballergui.h" #include "screen.h" #include "psg.h" #include "market.h" #include "music.h" #include "paths.h" #include "i18n.h" #define Min(a,b) ((a)<(b)?(a):(b)) #define Max(a,b) ((a)>(b)?(a):(b)) #define menu(a) /* wind_update(3-a) */ #define hide() /* graf_mouse(256,0) */ #define show() /* graf_mouse(257,0) */ #define COMP_NUM 7 short mx, my, bt, xy[100], bur[2],bx[2],by[2], ge[2],pu[2],ku[2],vo[2],st[2],kn[2], wx[2],wy[2], *bg, zug,n, p[6], max_rund, *burgen[30], b_anz; static short ws, wc, t_gew[COMP_NUM][COMP_NUM+4]; int ftx, fty, ftw, fth; /* Koordinaten von "Fertig" */ void *bur_ad; const char *l_nam, *r_nam; int f; char mod, wnd, end, txt[4], an_erl, au_kap; int cw[2] = { 2, 2 }; /* Computer strategy */ int cx[2] = { 1, 1 }; /* Computer strength */ /* Computer player names (i.e. the strategies) */ const char *cn[COMP_NUM] = { N_("Oaf"), N_("Yokel"), N_("Boor"), N_("Doofus"), N_("Fumbler"), N_("Geezer"), N_("Ruffian") }; char nsp1[22], nsp2[22]; /* Names of the players */ ka_t ka[2][10]; ft_t ft[2][5]; /** * Initialize internationalization support */ static void i18n_init(void) { #if HAVE_LIBINTL_H setlocale(LC_ALL, ""); bindtextdomain("ballerburg", Paths_GetLocaleDir()); textdomain("ballerburg"); #endif } /*****************************************************************************/ int main(int argc, char **argv) { Paths_Init(argv[0]); i18n_init(); scr_init(); scr_init_done_button(&ftx, &fty, &ftw, &fth); m_laden("baller.mus"); /* Laden der Musikdatei mit Funktion aus music.c */ bur_ad = malloc(32000); /* Speicher fr Burgdaten */ if (!bur_ad) { puts(_("Not enough memory for loading the castles.")); exit(-1); } an_erl=1; max_rund=32767; au_kap=1; t_load(); burgen_laden(); psg_audio_init(); strcpy(nsp1, _("William")); strcpy(nsp2, _("Frederick")); l_nam = nsp1; r_nam = nsp2; mod=0; /* Spielmodus ( wer gegen wen ) */ neues(); while ( ein_zug() ); t_save(); scr_exit(); m_quit(); free(bur_ad); return 0; } /**************************** Tabelle ****************************************/ void tabelle(void) { short i,j; void *save_area; save_area = scr_save_bg(17, 55, 640-17*2+1, 400-55*2+24+1); scr_sf_interior(0); box(17,56, 623,367, 1); box(19,58, 621,365, 1); box(20,59, 620,364, 1); line(108,59, 108,364); for (i = 116; i < 584; i += 72) line(i,59,i,364); line(20,84, 620,84); for (i = 92; i < 264; i += 24) line(20,i, 620,i); for (i = 268; i < 364; i += 24) line(20,i, 620,i); for (i = 0; i < COMP_NUM; i++) scr_l_text(124+i*72, 78, _(cn[i])); for (i = 0; i < COMP_NUM; i++) scr_l_text(36, 110+i*24, _(cn[i])); scr_sf_interior(2); scr_sf_style(1); for (i = 0; i < COMP_NUM; i++) { for (j = 0; j < COMP_NUM+4; j++) { z_txt(t_gew[i][j]); if (j == COMP_NUM+3 && !t_gew[i][COMP_NUM]) { txt[0]=32; txt[1]='-'; txt[2]=0; } scr_l_text(140+i*72, 110+j*24+8*(j>=COMP_NUM), txt); if (i == j) box(116+i*72, 92+j*24, 188+i*72, 116+j*24, 1); } } scr_l_text(28, 286, _("Games")); scr_l_text(28, 310, _("Total won")); scr_l_text(28, 334, _("Total lost")); scr_l_text(28, 358, _("Won in %")); line(20, 59, 108, 84); scr_l_text(36, 80, "-"); scr_l_text(88, 72, "+"); while (bt == 0 && event(1, 0) == 0); while (bt != 0 && event(1, 0) == 0); scr_restore_bg(save_area); } void z_txt(short a) { txt[0]=a/100+48; txt[1]=a%100/10+48; txt[2]=a%10+48; if (a<100) { txt[0]=32; if (a<10) txt[1]=32; } } /******************** Initialisierung vor neuem Spiel ************************/ void neues(void) { static short pr[6]={ 200,500,400,150,50,50 }; /* Preise zu Beginn */ short j; wnd=rand()%60-30; st[0]=st[1]=20; kn[0]=kn[1]=0; for ( j=0;j<6;j++ ) p[j]=pr[j]*(95+rand()%11)/100; bild(); for ( n=0;n<2;n++ ) { bg=burgen[bur[n]]; wx[n]=n? 639-bg[23]:bg[23]; wy[n]=by[n]-bg[24]; for ( f=0;f<5; ) ft[n][f++].x=-1; } zug=n=end=0; f=1; } /************************* Durchfhren eines Zuges ***************************/ int ein_zug(void) { short i = 0, fl, a; // puts("ein zug ..."); n=zug&1; fn(); kn[n]&=~16; wnd=wnd*9/10+rand()%12-6; werdran(1); do { fl=0; menu(1); do { if (event(!(mod&(2-n)), 1) != 0) return(0); } while (!bt && !(mod&(2-n))); //printf("ein zug %i %i %i\n", bt, mod, a); menu(0); bg=burgen[bur[n]]; if ( mod&(2-n) ) { hide(); i=comp(); show(); fl=1+(i<0); } else if (mx > ftx && mx < ftx+ftw && my > fty && my < fty+fth) { /* "Fertig"-Knopf wurde gedrueckt */ scr_draw_done_button(1); do { event(1, 0); } while (bt); scr_draw_done_button(0); fl=2; } else { for ( i=0;i<10;i++ ) if ( ka[n][i].x<=mx && ka[n][i].x+20>=mx && ka[n][i].x!=-1 && ka[n][i].y>=my && ka[n][i].y-14<=my ) break; if ( i>9 ) { if (drin( bg[25],bg[26],bg[31],bg[32],0,mx,my) || drin( bg[27],bg[28],bg[33],bg[34],0,mx,my) || drin( bg[29],bg[30],bg[35],bg[36],0,mx,my)) markt(); else if (drin( bg[21],bg[22],30,25,0,mx,my)) koenig(); } else if (pu[n] < 5) { DlgAlert_Notice(_("You don't have enough gunpowder."), _("Cancel")); } else if (ku[n] == 0) { DlgAlert_Notice(_("You don't have any cannonballs left."), _("Cancel")); } else fl=sch_obj(i); } } while ( !fl ); werdran(0); if ( fl<2 ) schuss(i); if ( ~kn[n]&16 ) kn[n]&=~15; rechnen(); zug++; for ( i=0;i<10;i++ ) if ( ka[n][i].x>-1 ) break; n=zug&1; bg=burgen[bur[n]]; for ( a=0;a<10;a++ ) if ( ka[n][a].x>-1 ) break; if ( a==10 && i<10 && bg[40]>vo[n] && ge[n]=max_rund ) { static int h[2]; for (n=0;n<2;n++) { h[n]=ge[n]+pu[n]*p[4]/30+ku[n]*p[5]/2+(wx[n]>-1)*p[3]+vo[n]*4; for (i=0;i<5;i++) if ( ft[n][i].x>-1 ) h[n]+=p[1]; for (i=0;i<10;i++) if ( ka[n][i].x>-1 ) h[n]+=p[2]; } end=65+(h[1]65? 130-j:j)/(150-rand()%50); vo[n]=vo[n]*(95+rand()%11)/100+(21-j+rand()%9)*(8+rand()%5)/20; if ( vo[n]<0 ) { vo[n]=0; end=n+49; } for ( j=0;j<5;j++ ) ge[n]+=(40+rand()%31)*(ft[n][j].x>-1); for ( j=0;j<6;j++ ) { p[j]+=psp[j]*(rand()%99)/98-psp[j]/2; p[j]=Max(p[j],pmi[j]); p[j]=Min(p[j],pma[j]); } drw_gpk(0); } /******************************* Spielende ***********************************/ void ende(void) { char s1[80], s2[80], s3[80]; int a, b; int i; const char *loser; int with_s = 0; snprintf(s1, sizeof(s1), _("!! %s has won !!"), end&2 ? _(l_nam) : _(r_nam)); loser = (end&2) ? _(r_nam) : _(l_nam); if ((end&240) < 48) { a = loser[strlen(loser)-1]; with_s = (a=='s' || a=='S'); } switch ( end&240 ) { case 16: if (with_s) snprintf(s2, sizeof(s2), _("( %s' king was hit,"), loser); else snprintf(s2, sizeof(s2), _("( %s's king was hit,"), loser); strcpy(s3, _("and upon hearing this, the people capitulated. )")); break; case 32: if (with_s) snprintf(s2, sizeof(s2), _("( %s' king has capitulated"), loser); else snprintf(s2, sizeof(s2), _("( %s's king has capitulated"), loser); strcpy(s3, _(" because of the hopeless situation. )")); break; case 48: snprintf(s2, sizeof(s2), _("( %s has no folk left. )"), loser); s3[0]=0; break; case 64: strcpy(s2, _("( The limit of maximum rounds has been reached.")); snprintf(s3, sizeof(s3), _("%s is worse off. )"), loser); } for (a = 0; a < COMP_NUM && strncmp(cn[a], l_nam, 7); a++); for (b = 0; b < COMP_NUM && strncmp(cn[b], r_nam, 7); b++); if (a < COMP_NUM && b < COMP_NUM && a != b) { if (~end&2) { int c; c=a; a=b; b=c; } t_gew[a][b]++; t_gew[b][a]++; t_gew[b][COMP_NUM+2]++; t_gew[a][COMP_NUM+3] = 100 * ++t_gew[a][COMP_NUM+1] / ++t_gew[a][COMP_NUM]; t_gew[b][COMP_NUM+3] = 100 * t_gew[b][COMP_NUM+1] / ++t_gew[b][COMP_NUM]; } scr_color(0x00800000); for (i = 0; i < 8; i++) { short rxy[4]; if (i!=7) scr_fillcolor((i*32)<<16); else scr_fillcolor(0xffffff); rxy[0] = 40 + i*8; rxy[1] = 80 + i*8; rxy[2] = 600 - i*8; rxy[3] = 320 - i*8; scr_bar(rxy); } scr_l_text(140, 170, s1); scr_l_text(140, 210, s2); scr_l_text(140, 230, s3); bt = 0; m_musik(); Giaccess( 0,138 ); Giaccess( 0,139 ); Giaccess( 0,140 ); } /** * Die Routine m_wait() wird von m_musik() nach jedem 1/96 Takt * aufgerufen. * In diesem Fall macht sie nichts anderes als die eigentliche * Warteschleife aufzurufen. In eigenen Programmen knnten Sie hier * whrend der Musik zustzliche Aktionen ablaufen lassen. */ int m_wait(void) { m_wloop(); return (event(0, 0) != 0 || bt); } /** Anzeige des Spielers, der am Zug ist, sowie Darstellung der Windfahnen ***/ void werdran(char c) { char ad[8]; int i; short x, y, w, h, c1, s1, c2, s2; double wk,wl; /* Anzahl der Spielrunden ausgeben */ z_txt(zug/2+1); scr_l_text(332, 395+16, txt); if ( c ) { x = 5+(629-104)*n; y = 410; w = 104; h = 48; /* Wind ausgeben: */ ad[0] = ad[5] = 4+28*!wnd-(wnd>0); i = wnd<0? -wnd:wnd; ad[1] = ad[4] = ' '; ad[2] = 48+i/10; ad[3] = 48+i%10; ad[6] = 0; if ( wx[n]<0 ) { ad[0]=ad[5]=32; ad[2]=ad[3]='?'; } scr_l_text(x+4, y+h+12, _("Wind:")); scr_l_text(x+52, y+h+12, ad); c=wnd>0? 1:-1; wk=c*wnd/15.0; wl=wk*.82; if ( wk>1.57 ) wk=1.57; if ( wl>1.57 ) wl=1.57; s1=c*20*sin(wk); c1=20*cos(wk); s2=c*20*sin(wl); c2=20*cos(wl); ws=s1/2.0; ws+=!ws; wc=c1/2.0; hide(); if ( wx[n]>-1 ) { color(1); x+=w/2; line( x,y+h,x,y+5 ); line( x+1,y+h,x+1,y+5 ); xy[0]=xy[2]=x+1; xy[1]=y+5; xy[3]=y+11; if ( wk<.2 ) { xy[0]=x-1; xy[1]=xy[3]=y+5; xy[2]=x+2; } xy[4]=xy[2]+s1; xy[5]=xy[3]+c1; xy[8]=xy[0]+s1; xy[9]=xy[1]+c1; xy[10]=xy[0]; xy[11]=xy[1]; xy[6] = ((xy[4] + xy[8]) >> 1) + s2; xy[7] = ((xy[5] + xy[9]) >> 1) + c2; scr_pline(6, xy); } fahne(); show(); } else { hide(); clr(5+(629-104)*n,410, 104,48+16); show(); } } /******************* Darstellung der beiden Windfahnen ***********************/ void fahne(void) { int m=-1; while ( ++m<2 ) if ( wx[m]>-1 ) { clr_bg( wx[m]-10,wy[m]-15,20,15 ); color(1); line( wx[m],wy[m],wx[m],wy[m]-15 ); if ( m==n ) { line( wx[m],wy[m]-15,wx[m]+ws,wy[m]-13+wc ); line( wx[m],wy[m]-11,wx[m]+ws,wy[m]-13+wc ); } } } /********************** BALLER.TAB laden/speichern ***************************/ int t_load(void) { #if 1 //printf("t_load does not work yet\n"); #else FILE *f_h; f_h = fopen("baller.tab", "rb"); if (!f_h) { perror("t_load"); return(1); } fread(&an_erl, 1, 1, f_h); fread(&au_kap, 1, 1, f_h); fread(&max_rund, 2, 1, f_h); fread(t_gew, 1, sizeof(t_gew), f_h); fclose(f_h); #endif return(0); } int t_save(void) { #if 1 //printf("t_save not implemented yet\n"); #else FILE *f_h; f_h = fopen("baller.tab", "wb"); if (!f_h) { perror("t_save"); return 1; } fwrite(&an_erl, 1, 1, f_h); fwrite(&au_kap, 1, 1, f_h); fwrite(&max_rund, 2, 1, f_h); fwrite(t_gew, 1, sizeof(t_gew), f_h); fclose(f_h); #endif return(0); } /************************* BALLER.DAT laden **********************************/ /* liest ein char von der Datei */ static char zeichen(FILE *f_h) { char a; if (fread(&a, 1, 1, f_h) != 1) { perror("zeichen"); exit(-1); } return a; } /* liest eine Dezimalzahl von der Datei, Remarks werden berlesen */ static int rdzahl(FILE *f_h) { char a,sign=1,rem=0; /* wird durch * getoggled, und zeigt damit an, */ /* ob man sich in einer Bemerkung befindet */ int val=0; do if ( (a=zeichen(f_h))=='*' ) rem=!rem; while ((a != '-' && a < '0') || a > '9' || rem); if ( a=='-' ) { sign=-1; a=zeichen(f_h); } while ( a>='0' && a<='9' ) { val*=10; val+=a-'0'; a=zeichen(f_h); } return( sign*val ); } void burgen_laden(void) { short *a,j; FILE *f_h; char *dat_name; dat_name = malloc(FILENAME_MAX); if (!dat_name) { perror("burgen_laden"); exit(-1); } snprintf(dat_name, FILENAME_MAX, "%s/baller.dat", Paths_GetDataDir()); f_h = fopen(dat_name, "rb"); free(dat_name); dat_name = NULL; if (!f_h) { /* Try to open in current directory instead */ f_h = fopen( "baller.dat", "rb"); if (!f_h) { perror("'baller.dat'"); exit(-1); } } a = (short *)bur_ad; b_anz = 0; while ((j=rdzahl(f_h)) != -999 && b_anz < (int)(sizeof(burgen)/sizeof(burgen[0]))) { burgen[b_anz++]=a; *a++=j; for ( j=0;j<40;j++ ) *a++=rdzahl(f_h); while ( (*a++=rdzahl(f_h))!=-1 ); } fclose(f_h); } /* Ermittelt, ob Punkt gesetzt ist */ int loc(int x, int y) { int a; a = scr_getpixel(x,y); // printf("loc %i %i = 0x%x\n", x,y, a); return ((a&0xff) != 0xff); } void line(short x1, short y1, short x2, short y2) /* Zeichnet eine Linie */ { xy[0]=x1; xy[1]=y1; xy[2]=x2; xy[3]=y2; scr_pline(2, xy); } void box(short x, short y, short x2, short y2, short c) { color(c); xy[0]=x; xy[1]=y; xy[2]=x2; xy[3]=y2; scr_bar(xy); } ballerburg-1.2.0/src/paths.c0000664000175000017500000002022612506012141015251 0ustar thomasthomas/* * Ballerburg - paths.c * * Set up the various path strings. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This file is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * (http://www.gnu.org/licenses/) for more details. */ const char Paths_fileid[] = "Ballerburg paths.c : " __DATE__ " " __TIME__; #include #include #include #include #include #include #include #include "config.h" #include "paths.h" #if defined(WIN32) && !defined(mkdir) #define mkdir(name,mode) mkdir(name) #endif /* WIN32 */ #ifdef WIN32 #define PATHSEP '\\' #else #define PATHSEP '/' #endif static char sWorkingDir[FILENAME_MAX]; /* Working directory */ static char sDataDir[FILENAME_MAX]; /* Directory where data files can be found */ static char sLocaleDir[FILENAME_MAX]; /* Directory where locale files can be found */ static char sUserHomeDir[FILENAME_MAX]; /* User's home directory ($HOME) */ static char sProgHomeDir[FILENAME_MAX]; /* Program's home directory ($HOME/.config/ballerburg/) */ /** * Return pointer to current working directory string */ const char *Paths_GetWorkingDir(void) { return sWorkingDir; } /** * Return pointer to data directory string */ const char *Paths_GetDataDir(void) { return sDataDir; } /** * Return pointer to data directory string */ const char *Paths_GetLocaleDir(void) { return sLocaleDir; } /** * Return pointer to user's home directory string */ const char *Paths_GetUserHome(void) { return sUserHomeDir; } /** * Return pointer to program's home directory string */ const char *Paths_GetProgHome(void) { return sProgHomeDir; } /** * Return TRUE if file exists, is readable or writable at least and is not * a directory. */ static bool Paths_FileExists(const char *filename) { struct stat buf; if (stat(filename, &buf) == 0 && (buf.st_mode & (S_IRUSR|S_IWUSR)) && !(buf.st_mode & S_IFDIR)) { /* file points to user readable regular file */ return true; } return false; } /** * Return TRUE if directory exists. */ static bool Paths_DirExists(const char *path) { struct stat buf; return (stat(path, &buf) == 0 && S_ISDIR(buf.st_mode)); } /** * Explore the PATH environment variable to see where our executable is * installed. */ static void Paths_GetExecDirFromPATH(const char *argv0, char *pExecDir, int nMaxLen) { char *pPathEnv; char *pAct; char *pTmpName; const char *pToken; /* Get the PATH environment string */ pPathEnv = getenv("PATH"); if (!pPathEnv) return; /* Duplicate the string because strtok destroys it later */ pPathEnv = strdup(pPathEnv); if (!pPathEnv) return; pTmpName = malloc(FILENAME_MAX); if (!pTmpName) { free(pPathEnv); return; } /* If there is a semicolon in the PATH, we assume it is the PATH * separator token (like on Windows), otherwise we use a colon. */ if (strchr((pPathEnv), ';')) pToken = ";"; else pToken = ":"; pAct = strtok (pPathEnv, pToken); while (pAct) { snprintf(pTmpName, FILENAME_MAX, "%s%c%s", pAct, PATHSEP, argv0); if (Paths_FileExists(pTmpName)) { /* Found the executable - so use the corresponding path: */ strncpy(pExecDir, pAct, nMaxLen); pExecDir[nMaxLen-1] = 0; break; } pAct = strtok (0, pToken); } free(pPathEnv); free(pTmpName); } /** * Locate the directory where the executable resides */ static char *Paths_InitExecDir(const char *argv0) { char *psExecDir; /* Path string where the executable can be found */ /* Allocate memory for storing the path string of the executable */ psExecDir = malloc(FILENAME_MAX); if (!psExecDir) { fprintf(stderr, "Out of memory (Paths_Init)\n"); exit(-1); } /* Determine the bindir... * Start with empty string, then try to use OS specific functions, * and finally analyze the PATH variable if it has not been found yet. */ psExecDir[0] = '\0'; #if defined(__linux__) { int i; /* On Linux, we can analyze the symlink /proc/self/exe */ i = readlink("/proc/self/exe", psExecDir, FILENAME_MAX); if (i > 0) { char *p; psExecDir[i] = '\0'; p = strrchr(psExecDir, '/'); /* Search last slash */ if (p) *p = 0; /* Strip file name from path */ } } //#elif defined(WIN32) || defined(__CEGCC__) // /* On Windows we can use GetModuleFileName for getting the exe path */ // GetModuleFileName(NULL, psExecDir, FILENAME_MAX); #endif /* If we do not have the execdir yet, analyze argv[0] and the PATH: */ if (psExecDir[0] == 0) { if (strchr(argv0, PATHSEP) == 0) { /* No separator in argv[0], we have to explore PATH... */ Paths_GetExecDirFromPATH(argv0, psExecDir, FILENAME_MAX); } else { /* There was a path separator in argv[0], so let's assume a * relative or absolute path to the current directory in argv[0] */ char *p; strncpy(psExecDir, argv0, FILENAME_MAX); psExecDir[FILENAME_MAX-1] = 0; p = strrchr(psExecDir, PATHSEP); /* Search last slash */ if (p) *p = 0; /* Strip file name from path */ } } return psExecDir; } /** * Initialize the users home directory string * and program's home directory (~/.config/xxx) */ static void Paths_InitHomeDirs(void) { char *psHome; psHome = getenv("HOME"); if (!psHome) { /* Windows home path? */ psHome = getenv("HOMEPATH"); } if (!psHome) { /* $HOME not set, so let's use current working dir as home */ strcpy(sUserHomeDir, sWorkingDir); strcpy(sProgHomeDir, sWorkingDir); } else { strncpy(sUserHomeDir, psHome, FILENAME_MAX); sUserHomeDir[FILENAME_MAX-1] = 0; /* Try to use a .config directory in the users home directory */ snprintf(sProgHomeDir, FILENAME_MAX, "%s%c./config/ballerburg", sUserHomeDir, PATHSEP); if (!Paths_DirExists(sProgHomeDir)) { /* Program home directory does not exists yet... * ...so let's try to create it: */ if (1 /*mkdir(sProgHomeDir, 0755) != 0*/) { /* Failed to create, so use user's home dir instead */ strcpy(sProgHomeDir, sUserHomeDir); } } } } /** * Initialize the data directory string */ static void Paths_InitPackageDir(char *psPkgDir, const char *psRelPath, const char *psExecDir) { char *pTempName; if (psExecDir && strlen(psExecDir) > 0) { snprintf(psPkgDir, FILENAME_MAX, "%s%c%s", psExecDir, PATHSEP, psRelPath); } else { /* bindir could not be determined, let's assume the destination dir is * relative to current working directory... */ strcpy(psPkgDir, psRelPath); } pTempName = malloc(FILENAME_MAX); if (!pTempName) { perror("Init data dir malloc"); return; } if (realpath(psPkgDir, pTempName) != NULL) { strncpy(psPkgDir, pTempName, FILENAME_MAX); } free(pTempName); } /** * Initialize directory names * * The datadir will be initialized relative to the bindir (where the executable * has been installed to). This means a lot of additional effort since we first * have to find out where the executable is. But thanks to this effort, we get * a relocatable package (we don't have any absolute path names in the program)! */ void Paths_Init(const char *argv0) { char *psExecDir; /* Path string where the executable can be found */ /* Init working directory string */ if (getcwd(sWorkingDir, FILENAME_MAX) == NULL) { /* This should never happen... just in case... */ strcpy(sWorkingDir, "."); } /* Init the user's home directory string */ Paths_InitHomeDirs(); /* Get the directory where the executable resides */ psExecDir = Paths_InitExecDir(argv0); /* Now create the package path names from the bindir path name: */ Paths_InitPackageDir(sDataDir, BIN2DATADIR, psExecDir); Paths_InitPackageDir(sLocaleDir, BIN2LOCALEDIR, psExecDir); free(psExecDir); /*fprintf(stderr, " WorkingDir = %s\n DataDir = %s\n UserHomeDir = %s\n ProgHomeDir = %s\n", sWorkingDir, sDataDir, sUserHomeDir, sProgHomeDir);*/ } ballerburg-1.2.0/src/font8x16.h0000644000175000017500000006240412506012141015536 0ustar thomasthomas/* * 8x16 font data. * * Generated from font8x16.bmp with: * * convert font8x16.bmp xbm:font8x16.h * * font8x16.bmp and this file are in the public domain. */ #define font8x16_width 128 #define font8x16_height 256 static char font8x16_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x00, 0x00, 0x3C, 0xFF, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0xFF, 0xFF, 0x00, 0x24, 0x24, 0x00, 0x00, 0x3C, 0xFF, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x81, 0x81, 0x00, 0x24, 0x24, 0x1C, 0x38, 0xBD, 0xFF, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x81, 0x81, 0x00, 0x24, 0x24, 0x34, 0x2C, 0x99, 0xFF, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x42, 0x5A, 0x81, 0xA1, 0x00, 0x42, 0x24, 0x27, 0xE4, 0xC3, 0x7F, 0x99, 0x00, 0x00, 0x00, 0x00, 0x42, 0x5A, 0x81, 0xA1, 0x00, 0x42, 0x24, 0x41, 0x82, 0xC3, 0x7F, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x81, 0xBD, 0x81, 0xA1, 0x00, 0x42, 0x66, 0x81, 0x81, 0xE7, 0x3F, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x81, 0xBD, 0x81, 0xA1, 0x00, 0x66, 0x42, 0x81, 0x81, 0xE7, 0x3F, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x81, 0xBD, 0x81, 0x91, 0x00, 0x24, 0x42, 0x41, 0x82, 0xC3, 0x9F, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x81, 0xBD, 0x81, 0x91, 0x00, 0x24, 0x42, 0x27, 0xE4, 0xC3, 0x9F, 0x99, 0x00, 0x00, 0x00, 0x00, 0x42, 0x5A, 0x81, 0x95, 0x00, 0x24, 0x24, 0x34, 0x2C, 0x99, 0xCF, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x42, 0x5A, 0x81, 0x95, 0x00, 0x24, 0x24, 0x1C, 0x38, 0xBD, 0xCF, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x81, 0x89, 0x00, 0x24, 0x24, 0x00, 0x00, 0x3C, 0xE7, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x81, 0x81, 0x00, 0x3C, 0x18, 0x00, 0x00, 0x3C, 0xE7, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x24, 0x00, 0x10, 0x00, 0x1C, 0x10, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x24, 0x50, 0x3C, 0x4C, 0x34, 0x10, 0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x10, 0x24, 0x50, 0x52, 0x52, 0x24, 0x10, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x10, 0x24, 0x50, 0x12, 0x32, 0x14, 0x10, 0x08, 0x10, 0x24, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0xFC, 0x12, 0x2C, 0x0C, 0x00, 0x04, 0x20, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x10, 0x00, 0x28, 0x3C, 0x30, 0x0C, 0x00, 0x04, 0x20, 0x7E, 0x7E, 0x00, 0x7E, 0x00, 0x30, 0x00, 0x10, 0x00, 0x28, 0x50, 0x10, 0x1A, 0x00, 0x04, 0x20, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x10, 0x00, 0x7E, 0x50, 0x78, 0xF2, 0x00, 0x08, 0x10, 0x24, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, 0x52, 0xA8, 0x22, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x3C, 0x94, 0x76, 0x00, 0x30, 0x0C, 0x00, 0x00, 0x38, 0x00, 0x38, 0x04, 0x00, 0x10, 0x00, 0x00, 0x10, 0x64, 0xDC, 0x00, 0x20, 0x04, 0x00, 0x00, 0x38, 0x00, 0x38, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x3C, 0x3C, 0x00, 0x7E, 0x3C, 0x7E, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x18, 0x24, 0x24, 0x20, 0x02, 0x24, 0x40, 0x24, 0x24, 0x00, 0x00, 0x20, 0x00, 0x04, 0x24, 0x24, 0x14, 0x42, 0x42, 0x30, 0x02, 0x02, 0x40, 0x42, 0x42, 0x00, 0x00, 0x10, 0x7E, 0x08, 0x42, 0x24, 0x12, 0x42, 0x42, 0x28, 0x02, 0x02, 0x20, 0x42, 0x42, 0x00, 0x00, 0x08, 0x7E, 0x10, 0x42, 0x42, 0x10, 0x40, 0x20, 0x24, 0x3A, 0x3A, 0x20, 0x24, 0x42, 0x30, 0x30, 0x04, 0x00, 0x20, 0x20, 0x42, 0x10, 0x20, 0x38, 0x22, 0x26, 0x26, 0x10, 0x3C, 0x64, 0x30, 0x30, 0x02, 0x00, 0x40, 0x10, 0x42, 0x10, 0x38, 0x20, 0x22, 0x40, 0x42, 0x10, 0x24, 0x5C, 0x00, 0x00, 0x04, 0x00, 0x20, 0x08, 0x42, 0x10, 0x0C, 0x40, 0x7E, 0x40, 0x42, 0x08, 0x42, 0x40, 0x00, 0x00, 0x08, 0x7E, 0x10, 0x08, 0x24, 0x10, 0x02, 0x42, 0x20, 0x42, 0x42, 0x08, 0x42, 0x40, 0x00, 0x00, 0x10, 0x7E, 0x08, 0x00, 0x24, 0x10, 0x02, 0x24, 0x20, 0x24, 0x24, 0x04, 0x24, 0x24, 0x30, 0x30, 0x20, 0x00, 0x04, 0x08, 0x18, 0x7E, 0x7E, 0x3C, 0x20, 0x3C, 0x3C, 0x04, 0x3C, 0x3C, 0x30, 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x18, 0x1E, 0x3C, 0x3E, 0x7E, 0x7E, 0x3C, 0x42, 0x7C, 0xF8, 0x42, 0x02, 0x42, 0x42, 0x3C, 0x24, 0x3C, 0x32, 0x24, 0x22, 0x02, 0x02, 0x24, 0x42, 0x10, 0x20, 0x42, 0x02, 0x42, 0x46, 0x24, 0x42, 0x24, 0x22, 0x42, 0x42, 0x02, 0x02, 0x42, 0x42, 0x10, 0x20, 0x22, 0x02, 0x66, 0x46, 0x42, 0x72, 0x24, 0x22, 0x02, 0x42, 0x02, 0x02, 0x02, 0x42, 0x10, 0x20, 0x22, 0x02, 0x66, 0x4A, 0x42, 0x5A, 0x42, 0x32, 0x02, 0x42, 0x02, 0x02, 0x02, 0x42, 0x10, 0x20, 0x12, 0x02, 0x5A, 0x4A, 0x42, 0x4A, 0x42, 0x1E, 0x02, 0x42, 0x3E, 0x3E, 0x72, 0x7E, 0x10, 0x20, 0x1E, 0x02, 0x5A, 0x52, 0x42, 0x4A, 0x7E, 0x22, 0x02, 0x42, 0x02, 0x02, 0x42, 0x42, 0x10, 0x20, 0x12, 0x02, 0x42, 0x52, 0x42, 0x3A, 0x42, 0x42, 0x02, 0x42, 0x02, 0x02, 0x42, 0x42, 0x10, 0x20, 0x22, 0x02, 0x42, 0x62, 0x42, 0x02, 0x42, 0x42, 0x42, 0x42, 0x02, 0x02, 0x42, 0x42, 0x10, 0x22, 0x22, 0x02, 0x42, 0x62, 0x42, 0x44, 0x42, 0x22, 0x24, 0x22, 0x02, 0x02, 0x64, 0x42, 0x10, 0x24, 0x42, 0x02, 0x42, 0x42, 0x24, 0x3C, 0x42, 0x3E, 0x3C, 0x3E, 0x7E, 0x02, 0x3C, 0x42, 0x7C, 0x18, 0x42, 0x7E, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x3C, 0x3E, 0x3C, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x44, 0x7E, 0x3C, 0x00, 0x3C, 0x18, 0x00, 0x22, 0x24, 0x22, 0x24, 0x10, 0x42, 0x42, 0x42, 0x42, 0x44, 0x40, 0x04, 0x04, 0x20, 0x3C, 0x00, 0x42, 0x42, 0x42, 0x42, 0x10, 0x42, 0x42, 0x42, 0x24, 0x28, 0x40, 0x04, 0x04, 0x20, 0x24, 0x00, 0x42, 0x42, 0x42, 0x02, 0x10, 0x42, 0x42, 0x42, 0x24, 0x28, 0x20, 0x04, 0x0C, 0x20, 0x42, 0x00, 0x42, 0x42, 0x42, 0x04, 0x10, 0x42, 0x24, 0x42, 0x24, 0x38, 0x30, 0x04, 0x18, 0x20, 0x00, 0x00, 0x22, 0x42, 0x22, 0x3C, 0x10, 0x42, 0x24, 0x42, 0x18, 0x10, 0x18, 0x04, 0x18, 0x20, 0x00, 0x00, 0x3E, 0x42, 0x1E, 0x20, 0x10, 0x42, 0x24, 0x5A, 0x18, 0x10, 0x0C, 0x04, 0x30, 0x20, 0x00, 0x00, 0x02, 0x42, 0x12, 0x40, 0x10, 0x42, 0x24, 0x5A, 0x24, 0x10, 0x04, 0x04, 0x30, 0x20, 0x00, 0x00, 0x02, 0x72, 0x22, 0x42, 0x10, 0x42, 0x18, 0x66, 0x24, 0x10, 0x02, 0x04, 0x20, 0x20, 0x00, 0x00, 0x02, 0x24, 0x42, 0x24, 0x10, 0x24, 0x18, 0x42, 0x42, 0x10, 0x02, 0x04, 0x40, 0x20, 0x00, 0x00, 0x02, 0x7C, 0x42, 0x3C, 0x10, 0x3C, 0x18, 0x42, 0x42, 0x10, 0x7E, 0x3C, 0x40, 0x3C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x02, 0x00, 0x40, 0x00, 0x38, 0x00, 0x02, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x40, 0x00, 0x4C, 0x00, 0x02, 0x10, 0x40, 0x02, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x40, 0x00, 0x44, 0x00, 0x02, 0x10, 0x40, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3A, 0x3C, 0x5C, 0x3C, 0x3E, 0x7C, 0x3A, 0x18, 0x70, 0x22, 0x10, 0x2C, 0x3A, 0x3C, 0x00, 0x44, 0x26, 0x44, 0x64, 0x24, 0x04, 0x22, 0x26, 0x10, 0x40, 0x12, 0x10, 0x5A, 0x26, 0x24, 0x00, 0x40, 0x42, 0x02, 0x42, 0x42, 0x04, 0x22, 0x42, 0x10, 0x40, 0x0A, 0x10, 0x4A, 0x42, 0x42, 0x00, 0x7C, 0x42, 0x02, 0x42, 0x7E, 0x04, 0x22, 0x42, 0x10, 0x40, 0x0E, 0x10, 0x4A, 0x42, 0x42, 0x00, 0x42, 0x42, 0x02, 0x42, 0x02, 0x04, 0x3C, 0x42, 0x10, 0x40, 0x12, 0x10, 0x4A, 0x42, 0x42, 0x00, 0x42, 0x26, 0x44, 0x64, 0x44, 0x04, 0x02, 0x42, 0x10, 0x40, 0x22, 0x10, 0x4A, 0x42, 0x24, 0x00, 0x7C, 0x3A, 0x3C, 0x5C, 0x3C, 0x04, 0x3C, 0x42, 0x7E, 0x40, 0x42, 0x7C, 0x4A, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x10, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x4C, 0x00, 0x3A, 0x5C, 0x3A, 0x3C, 0x3E, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7C, 0x08, 0x10, 0x10, 0x5A, 0x00, 0x26, 0x64, 0x4C, 0x42, 0x04, 0x42, 0x42, 0x42, 0x24, 0x42, 0x40, 0x0E, 0x10, 0x70, 0x32, 0x00, 0x42, 0x42, 0x04, 0x02, 0x04, 0x42, 0x24, 0x42, 0x24, 0x42, 0x20, 0x08, 0x10, 0x10, 0x00, 0x00, 0x42, 0x42, 0x04, 0x3C, 0x04, 0x42, 0x24, 0x5A, 0x18, 0x42, 0x30, 0x08, 0x10, 0x10, 0x00, 0x00, 0x42, 0x42, 0x04, 0x40, 0x04, 0x42, 0x24, 0x5A, 0x24, 0x42, 0x0C, 0x18, 0x10, 0x18, 0x00, 0x00, 0x26, 0x64, 0x04, 0x42, 0x4C, 0x64, 0x18, 0x66, 0x24, 0x64, 0x04, 0x10, 0x10, 0x08, 0x00, 0x00, 0x3A, 0x5C, 0x04, 0x3C, 0x38, 0x5C, 0x18, 0x24, 0x42, 0x5C, 0x7C, 0x70, 0x10, 0x0E, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x24, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x38, 0x00, 0x00, 0x18, 0x24, 0x24, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x4C, 0x00, 0x42, 0x18, 0x22, 0x00, 0x3C, 0x40, 0x50, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x18, 0x3C, 0x4C, 0x41, 0x42, 0x18, 0x04, 0x00, 0x24, 0x7C, 0x58, 0x00, 0x00, 0x24, 0x00, 0x00, 0x18, 0x02, 0x0C, 0x3E, 0x3C, 0x00, 0x32, 0x00, 0x7E, 0x42, 0x34, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x18, 0x02, 0x3E, 0x22, 0x3C, 0x00, 0x24, 0x00, 0x66, 0x7C, 0x1A, 0x7E, 0x3C, 0x66, 0x00, 0x00, 0x18, 0x02, 0x0C, 0x22, 0x18, 0x00, 0x4C, 0x00, 0x46, 0x00, 0x0F, 0x40, 0x00, 0x7E, 0x00, 0x00, 0x18, 0x02, 0x0C, 0x22, 0x3C, 0x18, 0x38, 0x00, 0x66, 0x7E, 0x1A, 0x40, 0x00, 0x56, 0x00, 0x00, 0x18, 0x3C, 0x1E, 0x5F, 0x18, 0x18, 0x44, 0x00, 0x42, 0x00, 0x2C, 0x00, 0x00, 0x42, 0x00, 0x00, 0x18, 0x18, 0xF6, 0x41, 0x18, 0x18, 0x24, 0x00, 0x24, 0x00, 0x58, 0x00, 0x00, 0x24, 0x00, 0x00, 0x18, 0x18, 0x66, 0x00, 0x18, 0x18, 0x3C, 0x00, 0x3C, 0x00, 0x50, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x1C, 0x1C, 0x30, 0x00, 0x7C, 0x00, 0x00, 0x0C, 0x1C, 0x00, 0x00, 0x00, 0x06, 0x18, 0x3C, 0x00, 0x34, 0x34, 0x18, 0x00, 0x7E, 0x00, 0x00, 0x0C, 0x34, 0x00, 0x02, 0x02, 0x08, 0x18, 0x24, 0x00, 0x30, 0x30, 0x0C, 0x00, 0x5E, 0x00, 0x00, 0x0C, 0x22, 0x0A, 0x00, 0x00, 0x04, 0x00, 0x24, 0x00, 0x18, 0x18, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x0C, 0x22, 0x1A, 0x20, 0x20, 0x28, 0x18, 0x18, 0x18, 0x04, 0x34, 0x00, 0x00, 0x5C, 0x38, 0x00, 0x0C, 0x34, 0x2C, 0x10, 0x10, 0x14, 0x18, 0x00, 0x7E, 0x3C, 0x1C, 0x00, 0x22, 0x58, 0x38, 0x00, 0x1C, 0x1C, 0x58, 0x08, 0x28, 0x08, 0x0C, 0x00, 0x18, 0x00, 0x00, 0x00, 0x22, 0x58, 0x38, 0x00, 0x00, 0x00, 0xF0, 0x24, 0x54, 0x24, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x22, 0x58, 0x00, 0x00, 0x00, 0x3E, 0x58, 0x10, 0x40, 0x10, 0x42, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x22, 0x58, 0x00, 0x00, 0x00, 0x00, 0x34, 0x30, 0x20, 0x30, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x58, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x70, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x18, 0x0C, 0x24, 0x24, 0x00, 0x00, 0x06, 0x30, 0x18, 0x24, 0x0C, 0x30, 0x18, 0x24, 0x18, 0x18, 0x24, 0x30, 0x00, 0x18, 0x78, 0x3C, 0x18, 0x0C, 0x24, 0x24, 0x30, 0x0C, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x3C, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x18, 0x34, 0x42, 0x7E, 0x7E, 0x7E, 0x7E, 0x7C, 0x7C, 0x7C, 0x7C, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x34, 0x02, 0x02, 0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x10, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x32, 0x02, 0x02, 0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x10, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x02, 0x02, 0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x10, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x32, 0x02, 0x3E, 0x3E, 0x3E, 0x3E, 0x10, 0x10, 0x10, 0x10, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x32, 0x02, 0x02, 0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x10, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x32, 0x42, 0x02, 0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x10, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x32, 0x24, 0x02, 0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x10, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x72, 0x3C, 0x7E, 0x7E, 0x7E, 0x7E, 0x7C, 0x7C, 0x7C, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x30, 0x18, 0x0C, 0x24, 0x00, 0x00, 0x0C, 0x30, 0x18, 0x24, 0x60, 0x00, 0x00, 0x3E, 0x30, 0x30, 0x0C, 0x24, 0x30, 0x00, 0x00, 0x3C, 0x30, 0x0C, 0x24, 0x00, 0x18, 0x04, 0x38, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x24, 0x00, 0x00, 0x00, 0x42, 0x00, 0x04, 0x44, 0x42, 0x42, 0x3C, 0x3C, 0x3C, 0x3C, 0x24, 0x00, 0x62, 0x42, 0x42, 0x42, 0x42, 0x44, 0x04, 0x44, 0x42, 0x46, 0x24, 0x24, 0x24, 0x24, 0x42, 0x00, 0x62, 0x42, 0x42, 0x42, 0x42, 0x44, 0x3C, 0x44, 0x42, 0x46, 0x42, 0x42, 0x42, 0x42, 0x42, 0x02, 0x52, 0x42, 0x42, 0x42, 0x42, 0x28, 0x44, 0x26, 0x4F, 0x4A, 0x42, 0x42, 0x42, 0x42, 0x42, 0x22, 0x52, 0x42, 0x42, 0x42, 0x42, 0x28, 0x44, 0x14, 0x42, 0x4A, 0x42, 0x42, 0x42, 0x42, 0x42, 0x34, 0x4A, 0x42, 0x42, 0x42, 0x42, 0x10, 0x44, 0x24, 0x42, 0x52, 0x42, 0x42, 0x42, 0x42, 0x42, 0x1C, 0x4A, 0x42, 0x42, 0x42, 0x42, 0x10, 0x44, 0x44, 0x42, 0x52, 0x42, 0x42, 0x42, 0x42, 0x42, 0x34, 0x46, 0x42, 0x42, 0x42, 0x42, 0x10, 0x04, 0x44, 0x22, 0x62, 0x24, 0x24, 0x24, 0x24, 0x24, 0x22, 0x24, 0x24, 0x24, 0x24, 0x24, 0x10, 0x04, 0x34, 0x3E, 0x62, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x02, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x10, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x0C, 0x30, 0x18, 0x28, 0x24, 0x24, 0x00, 0x00, 0x0C, 0x30, 0x18, 0x24, 0x18, 0x30, 0x18, 0x24, 0x18, 0x18, 0x24, 0x14, 0x24, 0x18, 0x00, 0x00, 0x18, 0x18, 0x24, 0x24, 0x30, 0x18, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x2C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x5A, 0x44, 0x24, 0x24, 0x24, 0x24, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x58, 0x02, 0x42, 0x42, 0x42, 0x42, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x3C, 0x02, 0x7E, 0x7E, 0x7E, 0x7E, 0x10, 0x10, 0x10, 0x10, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x1A, 0x02, 0x02, 0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x10, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x5A, 0x44, 0x44, 0x44, 0x44, 0x44, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x34, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x7E, 0x7E, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x1A, 0x28, 0x0C, 0x30, 0x18, 0x28, 0x24, 0x00, 0x00, 0x04, 0x20, 0x18, 0x24, 0x60, 0x04, 0x24, 0x0C, 0x14, 0x18, 0x18, 0x24, 0x14, 0x24, 0x18, 0x00, 0x0C, 0x30, 0x24, 0x24, 0x30, 0x04, 0x24, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x04, 0x00, 0x32, 0x3A, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x04, 0x42, 0x3C, 0x26, 0x24, 0x24, 0x24, 0x24, 0x24, 0x7E, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x42, 0x64, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x52, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x52, 0x42, 0x42, 0x42, 0x42, 0x42, 0x44, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x18, 0x4A, 0x42, 0x42, 0x42, 0x42, 0x42, 0x44, 0x42, 0x24, 0x42, 0x24, 0x24, 0x24, 0x24, 0x24, 0x18, 0x24, 0x64, 0x64, 0x64, 0x64, 0x64, 0x24, 0x64, 0x3C, 0x42, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x3C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x3C, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x04, 0x3C, }; ballerburg-1.2.0/src/psg.c0000644000175000017500000002241612506012141014724 0ustar thomasthomas/* * libpsg - a simple YM-2149 soundchip emulation library. * * Copyright (C) 2000 Stefan Berndtsson (NoCrew) * Copyright (C) 2011 Thomas Huth * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include #include #include #include #include #include "psg.h" psg psg_struct; //#define FIXED_MATH 1 #ifdef FIXED_MATH # define FIXED_TYPE int # define FIXED(x) ((int)((x) * 256)) # define DIV(x, y) ((((x) + ((y) >> 1)) << 8) / (y)) # define MOD(x, y) ((x) % (y)) # define FIXED_TO_INT(x) (((x) + 128) >> 8) #else # define FIXED_TYPE double # define FIXED(x) x # define DIV(x, y) ((x) / (y)) # define MOD(x, y) fmod (x, y) # define FIXED_TO_INT(x) (x) #endif #define INLINE static __inline__ #define TYPE_SQUARE 0 #if 0 /* undefined at the moment */ # define TYPE_SINUS 1 # define TYPE_PSGSQR 2 #endif #define MFP_FREQUENCY 2457600 #define PSG_FREQUENCY 2000000 #define QUALITY (1<<14) #define SAMPLE_TYPE TYPE_SQUARE #define SAMPLE_MAX 0x7fff #define SAMPLE_MIN 0x8000 #define NOISE_MAX 0xffff struct frame { int wave_period[3]; int rfreq[3]; int rvol[3]; int tone[3]; int noise[3]; int env[3]; int env_mode; int env_period; double env_freq; int sample_freq; }; #define ONE FIXED (1) #define PI FIXED (M_PI) INLINE FIXED_TYPE env_wave_00XX(FIXED_TYPE in) { if(in < PI) return ONE - DIV (in, PI); else return 0; } INLINE FIXED_TYPE env_wave_01XX(FIXED_TYPE in) { if(in < PI) return DIV (in, PI); else return 0; } INLINE FIXED_TYPE env_wave_1000(FIXED_TYPE in) { return ONE - DIV (MOD (in, PI), PI); } INLINE FIXED_TYPE env_wave_1001(FIXED_TYPE in) { if(in < PI) return ONE - DIV (in, PI); else return 0; } INLINE FIXED_TYPE env_wave_1010(FIXED_TYPE in) { FIXED_TYPE tmp; tmp = MOD (in, PI*2); if(tmp < PI) return ONE - DIV (tmp, PI); else return DIV (tmp - PI, PI); } INLINE FIXED_TYPE env_wave_1011(FIXED_TYPE in) { if(in < PI) return ONE - DIV (in, PI); else return ONE; } INLINE FIXED_TYPE env_wave_1100(FIXED_TYPE in) { return DIV (MOD (in, PI), PI); } INLINE FIXED_TYPE env_wave_1101(FIXED_TYPE in) { if(in < PI) return DIV (in, PI); else return ONE; } INLINE FIXED_TYPE env_wave_1110(FIXED_TYPE in) { FIXED_TYPE tmp; tmp = MOD (in, PI*2); if(tmp < PI) return DIV (tmp, PI); else return ONE - DIV (tmp - PI, PI); } INLINE FIXED_TYPE env_wave_1111(FIXED_TYPE in) { if(in < PI) return DIV (in, PI); else return ONE; } static FIXED_TYPE env_wave(FIXED_TYPE in, int mode) { switch(mode) { case 0: case 1: case 2: case 3: return env_wave_00XX(in); break; case 4: case 5: case 6: case 7: return env_wave_01XX(in); break; case 8: return env_wave_1000(in); break; case 9: return env_wave_1001(in); break; case 10: return env_wave_1010(in); break; case 11: return env_wave_1011(in); break; case 12: return env_wave_1100(in); break; case 13: return env_wave_1101(in); break; case 14: return env_wave_1110(in); break; case 15: return env_wave_1111(in); break; } return 0; } /* Period counter for seamless frames */ struct frame tdata; /* Values stolen from STonX */ static int amps[16]= {0,1,1,2,3,4,5,7,12,20,28,44,70,110,165,255}; static int16_t _clip(int input) { if(input < -32768) return (int16_t)-32768; if(input > 32767) return (int16_t) 32767; return input; } psg *psg_init(int mode, int bits, int freq) { int i; if((bits != 16)) { fprintf(stderr, "Unsupported bitvalue\n"); return (psg *)NULL; } if((mode < 0) || (mode > 1)) { fprintf(stderr, "Unsupported mode\n"); return (psg *)NULL; } if(freq != 44100 && freq != 22050) { fprintf(stderr, "Unsupported frequency\n"); return (psg *)NULL; } psg_struct.output.mode = mode; psg_struct.output.bits = bits; psg_struct.output.freq = freq; tdata.sample_freq = freq; for(i=0; i<3; i++) { tdata.wave_period[i] = 0; } return &psg_struct; } static int16_t _get_one_tonesample(int offset) { if((offset&(QUALITY-1)) < (QUALITY/2)) return SAMPLE_MAX; else return SAMPLE_MIN; } static int16_t _get_one_noisesample(int offset) { return (NOISE_MAX&rand())-SAMPLE_MAX; } static int _get_real_freq(int psgfreq, int sample_freq) { int denominator; if(psgfreq) { denominator = sample_freq * psgfreq; return (QUALITY *(PSG_FREQUENCY/16.0) + (denominator >> 1)) / denominator; } else return 0; } static void psg_update_values(psg *psg) { int i, tmp; for(i=0; i<3; i++) { if(psg->regs[8+i] == 16) { tdata.rvol[i] = 0; tdata.env[i] = 1; if(psg->regs[13] != 0xff) { //tdata.env_period = 0; tdata.env_mode = psg->regs[13]; } } else { tdata.rvol[i] = psg->regs[8+i]; tdata.env[i] = 0; } tmp = psg->regs[11] + (psg->regs[12] << 8); if(tmp) tdata.env_freq = ((double)PSG_FREQUENCY/(256.0 * tmp)); else tdata.env_freq = 0; tdata.rfreq[i] = _get_real_freq((psg->regs[1+i*2]<<8) + psg->regs[0+i*2], psg->output.freq); tdata.tone[i] = !(psg->regs[7] & (1<regs[7] & (8<>8))); } else { tmp = _clip(tmp + ((_get_one_tonesample(tdata.wave_period[i])* amps[tdata.rvol[i]])>>8)); } tdata.wave_period[i] += tdata.rfreq[i]; } if(tdata.noise[i] && !tdata.tone[i]) { if(tdata.env[i]) { tmp = _clip(tmp + ((_get_one_noisesample(tdata.wave_period[i])* amps[(int) (15*env_wave(tdata.env_period*M_PI*2/QUALITY, tdata.env_mode))]>>8))); } else { tmp = _clip(tmp + ((_get_one_noisesample(tdata.wave_period[i])* amps[tdata.rvol[i]])>>8)); } // tdata.wave_period[i] += tdata.rfreq[i]; } if(tdata.noise[i] && tdata.tone[i]) { if(tdata.env[i]) { tmp = _clip(tmp + ((_clip(_get_one_tonesample(tdata.wave_period[i])+ _get_one_noisesample(tdata.wave_period[i]))* amps[(int) (15*env_wave(tdata.env_period*M_PI*2/QUALITY, tdata.env_mode))]>>8))); } else { tmp = _clip(tmp + (_clip(_get_one_tonesample(tdata.wave_period[i])+ _get_one_noisesample(tdata.wave_period[i]))* amps[tdata.rvol[i]]>>8)); } tdata.wave_period[i] += tdata.rfreq[i]; } } if(tdata.env_freq) tdata.env_period += 2*(QUALITY/(tdata.sample_freq * tdata.env_freq)); return tmp; } int psg_create_samples(void *buffer, psg *psg, int samples) { int16_t *tmp; int i, tval; tmp = (int16_t *) buffer; for(i=0; ioutput.mode) *tmp++ = tval; } return 0; } /** * SDL audio callback function - copy emulation sound to audio system. */ static void Audio_CallBack(void *userdata, Uint8 *stream, int len) { psg_create_samples(stream, &psg_struct, len/4); } unsigned int Giaccess(unsigned int data, unsigned int reg) { if (reg & 0x80) { psg_struct.regs[reg&0x0f] = data; psg_update_values(&psg_struct); if ((reg&0x0f) == 13) tdata.env_period = 0; return 0; } else { return psg_struct.regs[reg&0x0f]; } } void Dosound(const unsigned char *buf) { int i = 0; while (buf[i] != 0xff) { if (buf[i] >= 16) { printf("Dosound: Unsupported opcode 0x%02x\n", buf[i]); } else { psg_struct.regs[buf[i]] = buf[i+1]; if (buf[i] == 13) tdata.env_period = 0; } i += 2; } psg_update_values(&psg_struct); } /** * Initialize the audio subsystem. Return true if all OK. */ void psg_audio_init(void) { SDL_AudioSpec desiredAudioSpec; /* We fill in the desired SDL audio options here */ /* Init the SDL's audio subsystem: */ if (SDL_WasInit(SDL_INIT_AUDIO) == 0) { if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { fprintf(stderr, "Could not init audio: %s\n", SDL_GetError() ); return; } } psg_init(1, 16, 44100); /* Set up SDL audio: */ desiredAudioSpec.freq = 22050; desiredAudioSpec.format = AUDIO_S16SYS; /* 16-Bit signed */ desiredAudioSpec.channels = 2; /* stereo */ desiredAudioSpec.callback = Audio_CallBack; desiredAudioSpec.userdata = NULL; desiredAudioSpec.samples = 512; /* buffer size in samples */ if (SDL_OpenAudio(&desiredAudioSpec, NULL)) /* Open audio device */ { fprintf(stderr, "Can't use audio: %s\n", SDL_GetError()); SDL_QuitSubSystem(SDL_INIT_AUDIO); return; } SDL_PauseAudio(0); } ballerburg-1.2.0/src/sdlgfx.c0000664000175000017500000012633012506012141015424 0ustar thomasthomas/* sdlgfx.c: This is a reduced version of Andreas Schiffler's SDL_gfxPrimitives.c, original copyright follows: SDL_gfxPrimitives.c: graphics primitives for SDL surfaces Copyright (C) 2001-2012 Andreas Schiffler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Andreas Schiffler -- aschiffler at ferzkopp dot net */ #include #include #include #include #include "sdlgfx.h" /* -===================- */ #define DEFAULT_ALPHA_PIXEL_ROUTINE #undef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE #undef ALPHA_PIXEL_ADDITIVE_BLEND /* ----- Defines for pixel clipping tests */ #define clip_xmin(surface) surface->clip_rect.x #define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1 #define clip_ymin(surface) surface->clip_rect.y #define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1 /*! \brief Internal pixel drawing function with alpha blending where input color in in destination format. Contains two alternative 32 bit alpha blending routines which can be enabled at the source level with the defines DEFAULT_ALPHA_PIXEL_ROUTINE or EXPERIMENTAL_ALPHA_PIXEL_ROUTINE. Only the bits up to the surface depth are significant in the color value. \param dst The surface to draw on. \param x The horizontal coordinate of the pixel. \param y The vertical position of the pixel. \param color The color value of the pixel to draw. \param alpha The blend factor to apply while drawing. \returns Returns 0 on success, -1 on failure. */ static int _putPixelAlpha(SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha) { SDL_PixelFormat *format; Uint32 Rmask, Gmask, Bmask, Amask; Uint32 Rshift, Gshift, Bshift, Ashift; Uint32 sR, sG, sB; Uint32 dR, dG, dB, dA; if (dst == NULL) { return (-1); } if (x >= clip_xmin(dst) && x <= clip_xmax(dst) && y >= clip_ymin(dst) && y <= clip_ymax(dst)) { format = dst->format; switch (format->BytesPerPixel) { case 1: { /* Assuming 8-bpp */ Uint8 *pixel = (Uint8 *) dst->pixels + y * dst->pitch + x; if (alpha == 255) { *pixel = color; } else { Uint8 R, G, B; SDL_Palette *palette = format->palette; SDL_Color *colors = palette->colors; SDL_Color dColor = colors[*pixel]; SDL_Color sColor = colors[color]; dR = dColor.r; dG = dColor.g; dB = dColor.b; sR = sColor.r; sG = sColor.g; sB = sColor.b; R = dR + ((sR - dR) * alpha >> 8); G = dG + ((sG - dG) * alpha >> 8); B = dB + ((sB - dB) * alpha >> 8); *pixel = SDL_MapRGB(format, R, G, B); } } break; case 2: { /* Probably 15-bpp or 16-bpp */ Uint16 *pixel = (Uint16 *) dst->pixels + y * dst->pitch / 2 + x; if (alpha == 255) { *pixel = color; } else { Uint16 R, G, B, A; Uint16 dc = *pixel; Rmask = format->Rmask; Gmask = format->Gmask; Bmask = format->Bmask; Amask = format->Amask; dR = (dc & Rmask); dG = (dc & Gmask); dB = (dc & Bmask); R = (dR + (((color & Rmask) - dR) * alpha >> 8)) & Rmask; G = (dG + (((color & Gmask) - dG) * alpha >> 8)) & Gmask; B = (dB + (((color & Bmask) - dB) * alpha >> 8)) & Bmask; *pixel = R | G | B; if (Amask!=0) { dA = (dc & Amask); A = (dA + (((color & Amask) - dA) * alpha >> 8)) & Amask; *pixel |= A; } } } break; case 3: { /* Slow 24-bpp mode, usually not used */ Uint8 R, G, B; Uint8 Rshift8, Gshift8, Bshift8; Uint8 *pixel = (Uint8 *) dst->pixels + y * dst->pitch + x * 3; Rshift = format->Rshift; Gshift = format->Gshift; Bshift = format->Bshift; Rshift8 = Rshift >> 3; Gshift8 = Gshift >> 3; Bshift8 = Bshift >> 3; sR = (color >> Rshift) & 0xFF; sG = (color >> Gshift) & 0xFF; sB = (color >> Bshift) & 0xFF; if (alpha == 255) { *(pixel + Rshift8) = sR; *(pixel + Gshift8) = sG; *(pixel + Bshift8) = sB; } else { dR = *((pixel) + Rshift8); dG = *((pixel) + Gshift8); dB = *((pixel) + Bshift8); R = dR + ((sR - dR) * alpha >> 8); G = dG + ((sG - dG) * alpha >> 8); B = dB + ((sB - dB) * alpha >> 8); *((pixel) + Rshift8) = R; *((pixel) + Gshift8) = G; *((pixel) + Bshift8) = B; } } break; #ifdef DEFAULT_ALPHA_PIXEL_ROUTINE case 4: { /* Probably :-) 32-bpp */ Uint32 R, G, B, A; Uint32 *pixel = (Uint32 *) dst->pixels + y * dst->pitch / 4 + x; if (alpha == 255) { *pixel = color; } else { Uint32 dc = *pixel; Rmask = format->Rmask; Gmask = format->Gmask; Bmask = format->Bmask; Amask = format->Amask; Rshift = format->Rshift; Gshift = format->Gshift; Bshift = format->Bshift; Ashift = format->Ashift; dR = (dc & Rmask) >> Rshift; dG = (dc & Gmask) >> Gshift; dB = (dc & Bmask) >> Bshift; R = ((dR + ((((color & Rmask) >> Rshift) - dR) * alpha >> 8)) << Rshift) & Rmask; G = ((dG + ((((color & Gmask) >> Gshift) - dG) * alpha >> 8)) << Gshift) & Gmask; B = ((dB + ((((color & Bmask) >> Bshift) - dB) * alpha >> 8)) << Bshift) & Bmask; *pixel = R | G | B; if (Amask!=0) { dA = (dc & Amask) >> Ashift; #ifdef ALPHA_PIXEL_ADDITIVE_BLEND A = (dA | GFX_ALPHA_ADJUST_ARRAY[alpha & 255]) << Ashift; // make destination less transparent... #else A = ((dA + ((((color & Amask) >> Ashift) - dA) * alpha >> 8)) << Ashift) & Amask; #endif *pixel |= A; } } } break; #endif #ifdef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE case 4:{ /* Probably :-) 32-bpp */ if (alpha == 255) { *((Uint32 *) dst->pixels + y * dst->pitch / 4 + x) = color; } else { Uint32 *pixel = (Uint32 *) dst->pixels + y * dst->pitch / 4 + x; Uint32 dR, dG, dB, dA; Uint32 dc = *pixel; Uint32 surfaceAlpha, preMultR, preMultG, preMultB; Uint32 aTmp; Rmask = format->Rmask; Gmask = format->Gmask; Bmask = format->Bmask; Amask = format->Amask; dR = (color & Rmask); dG = (color & Gmask); dB = (color & Bmask); dA = (color & Amask); Rshift = format->Rshift; Gshift = format->Gshift; Bshift = format->Bshift; Ashift = format->Ashift; preMultR = (alpha * (dR >> Rshift)); preMultG = (alpha * (dG >> Gshift)); preMultB = (alpha * (dB >> Bshift)); surfaceAlpha = ((dc & Amask) >> Ashift); aTmp = (255 - alpha); if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) { aTmp *= surfaceAlpha; R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask; G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask; B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask; } *pixel = R | G | B | (A << Ashift & Amask); } } break; #endif } } return (0); } /*! \brief Pixel draw with blending enabled if a<255. \param dst The surface to draw on. \param x X (horizontal) coordinate of the pixel. \param y Y (vertical) coordinate of the pixel. \param color The color value of the pixel to draw (0xRRGGBBAA). \returns Returns 0 on success, -1 on failure. */ int pixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color) { Uint8 alpha; Uint32 mcolor; int result = 0; /* * Lock the surface */ if (SDL_MUSTLOCK(dst)) { if (SDL_LockSurface(dst) < 0) { return (-1); } } /* * Setup color */ alpha = color & 0x000000ff; mcolor = SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24, (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha); /* * Draw */ result = _putPixelAlpha(dst, x, y, mcolor, alpha); /* * Unlock the surface */ if (SDL_MUSTLOCK(dst)) { SDL_UnlockSurface(dst); } return (result); } /*! \brief Pixel draw with blending enabled if a<255 - no surface locking. \param dst The surface to draw on. \param x X (horizontal) coordinate of the pixel. \param y Y (vertical) coordinate of the pixel. \param color The color value of the pixel to draw (0xRRGGBBAA). \returns Returns 0 on success, -1 on failure. */ static int pixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color) { Uint8 alpha; Uint32 mcolor; int result = 0; /* * Setup color */ alpha = color & 0x000000ff; mcolor = SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24, (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha); /* * Draw */ result = _putPixelAlpha(dst, x, y, mcolor, alpha); return (result); } /*! \brief Internal function to draw filled rectangle with alpha blending. Assumes color is in destination format. \param dst The surface to draw on. \param x1 X coordinate of the first corner (upper left) of the rectangle. \param y1 Y coordinate of the first corner (upper left) of the rectangle. \param x2 X coordinate of the second corner (lower right) of the rectangle. \param y2 Y coordinate of the second corner (lower right) of the rectangle. \param color The color value of the rectangle to draw (0xRRGGBBAA). \param alpha Alpha blending amount for pixels. \returns Returns 0 on success, -1 on failure. */ static int _filledRectAlpha(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha) { SDL_PixelFormat *format; Uint32 Rmask, Gmask, Bmask, Amask; Uint32 Rshift, Gshift, Bshift, Ashift; Uint32 sR, sG, sB, sA; Uint32 dR, dG, dB, dA; Sint16 x, y; if (dst == NULL) { return (-1); } format = dst->format; switch (format->BytesPerPixel) { case 1: { /* Assuming 8-bpp */ Uint8 *row, *pixel; Uint8 R, G, B; SDL_Color *colors = format->palette->colors; SDL_Color dColor; SDL_Color sColor = colors[color]; sR = sColor.r; sG = sColor.g; sB = sColor.b; for (y = y1; y <= y2; y++) { row = (Uint8 *) dst->pixels + y * dst->pitch; for (x = x1; x <= x2; x++) { if (alpha == 255) { *(row + x) = color; } else { pixel = row + x; dColor = colors[*pixel]; dR = dColor.r; dG = dColor.g; dB = dColor.b; R = dR + ((sR - dR) * alpha >> 8); G = dG + ((sG - dG) * alpha >> 8); B = dB + ((sB - dB) * alpha >> 8); *pixel = SDL_MapRGB(format, R, G, B); } } } } break; case 2: { /* Probably 15-bpp or 16-bpp */ Uint16 *row, *pixel; Uint16 R, G, B, A; Uint16 dc; Rmask = format->Rmask; Gmask = format->Gmask; Bmask = format->Bmask; Amask = format->Amask; sR = (color & Rmask); sG = (color & Gmask); sB = (color & Bmask); sA = (color & Amask); for (y = y1; y <= y2; y++) { row = (Uint16 *) dst->pixels + y * dst->pitch / 2; for (x = x1; x <= x2; x++) { if (alpha == 255) { *(row + x) = color; } else { pixel = row + x; dc = *pixel; dR = (dc & Rmask); dG = (dc & Gmask); dB = (dc & Bmask); R = (dR + ((sR - dR) * alpha >> 8)) & Rmask; G = (dG + ((sG - dG) * alpha >> 8)) & Gmask; B = (dB + ((sB - dB) * alpha >> 8)) & Bmask; *pixel = R | G | B; if (Amask!=0) { dA = (dc & Amask); A = (dA + ((sA - dA) * alpha >> 8)) & Amask; *pixel |= A; } } } } } break; case 3: { /* Slow 24-bpp mode, usually not used */ Uint8 *row, *pixel; Uint8 R, G, B; Uint8 Rshift8, Gshift8, Bshift8; Rshift = format->Rshift; Gshift = format->Gshift; Bshift = format->Bshift; Rshift8 = Rshift >> 3; Gshift8 = Gshift >> 3; Bshift8 = Bshift >> 3; sR = (color >> Rshift) & 0xff; sG = (color >> Gshift) & 0xff; sB = (color >> Bshift) & 0xff; for (y = y1; y <= y2; y++) { row = (Uint8 *) dst->pixels + y * dst->pitch; for (x = x1; x <= x2; x++) { pixel = row + x * 3; if (alpha == 255) { *(pixel + Rshift8) = sR; *(pixel + Gshift8) = sG; *(pixel + Bshift8) = sB; } else { dR = *((pixel) + Rshift8); dG = *((pixel) + Gshift8); dB = *((pixel) + Bshift8); R = dR + ((sR - dR) * alpha >> 8); G = dG + ((sG - dG) * alpha >> 8); B = dB + ((sB - dB) * alpha >> 8); *((pixel) + Rshift8) = R; *((pixel) + Gshift8) = G; *((pixel) + Bshift8) = B; } } } } break; #ifdef DEFAULT_ALPHA_PIXEL_ROUTINE case 4: { /* Probably :-) 32-bpp */ Uint32 *row, *pixel; Uint32 R, G, B, A; Uint32 dc; Rmask = format->Rmask; Gmask = format->Gmask; Bmask = format->Bmask; Amask = format->Amask; Rshift = format->Rshift; Gshift = format->Gshift; Bshift = format->Bshift; Ashift = format->Ashift; sR = (color & Rmask) >> Rshift; sG = (color & Gmask) >> Gshift; sB = (color & Bmask) >> Bshift; sA = (color & Amask) >> Ashift; for (y = y1; y <= y2; y++) { row = (Uint32 *) dst->pixels + y * dst->pitch / 4; for (x = x1; x <= x2; x++) { if (alpha == 255) { *(row + x) = color; } else { pixel = row + x; dc = *pixel; dR = (dc & Rmask) >> Rshift; dG = (dc & Gmask) >> Gshift; dB = (dc & Bmask) >> Bshift; R = ((dR + ((sR - dR) * alpha >> 8)) << Rshift) & Rmask; G = ((dG + ((sG - dG) * alpha >> 8)) << Gshift) & Gmask; B = ((dB + ((sB - dB) * alpha >> 8)) << Bshift) & Bmask; *pixel = R | G | B; if (Amask!=0) { dA = (dc & Amask) >> Ashift; #ifdef ALPHA_PIXEL_ADDITIVE_BLEND A = (dA | GFX_ALPHA_ADJUST_ARRAY[sA & 255]) << Ashift; // make destination less transparent... #else A = ((dA + ((sA - dA) * alpha >> 8)) << Ashift) & Amask; #endif *pixel |= A; } } } } } break; #endif #ifdef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE case 4:{ /* Probably :-) 32-bpp */ Uint32 *row, *pixel; Uint32 dR, dG, dB, dA; Uint32 dc; Uint32 surfaceAlpha, preMultR, preMultG, preMultB; Uint32 aTmp; Rmask = format->Rmask; Gmask = format->Gmask; Bmask = format->Bmask; Amask = format->Amask; dR = (color & Rmask); dG = (color & Gmask); dB = (color & Bmask); dA = (color & Amask); Rshift = format->Rshift; Gshift = format->Gshift; Bshift = format->Bshift; Ashift = format->Ashift; preMultR = (alpha * (dR >> Rshift)); preMultG = (alpha * (dG >> Gshift)); preMultB = (alpha * (dB >> Bshift)); for (y = y1; y <= y2; y++) { row = (Uint32 *) dst->pixels + y * dst->pitch / 4; for (x = x1; x <= x2; x++) { if (alpha == 255) { *(row + x) = color; } else { pixel = row + x; dc = *pixel; surfaceAlpha = ((dc & Amask) >> Ashift); aTmp = (255 - alpha); if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) { aTmp *= surfaceAlpha; R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask; G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask; B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask; } *pixel = R | G | B | (A << Ashift & Amask); } } } } break; #endif } return (0); } /*! \brief Draw filled rectangle of RGBA color with alpha blending. \param dst The surface to draw on. \param x1 X coordinate of the first corner (upper left) of the rectangle. \param y1 Y coordinate of the first corner (upper left) of the rectangle. \param x2 X coordinate of the second corner (lower right) of the rectangle. \param y2 Y coordinate of the second corner (lower right) of the rectangle. \param color The color value of the rectangle to draw (0xRRGGBBAA). \returns Returns 0 on success, -1 on failure. */ static int filledRectAlpha(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color) { Uint8 alpha; Uint32 mcolor; int result = 0; /* * Lock the surface */ if (SDL_MUSTLOCK(dst)) { if (SDL_LockSurface(dst) < 0) { return (-1); } } /* * Setup color */ alpha = color & 0x000000ff; mcolor = SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24, (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha); /* * Draw */ result = _filledRectAlpha(dst, x1, y1, x2, y2, mcolor, alpha); /* * Unlock the surface */ if (SDL_MUSTLOCK(dst)) { SDL_UnlockSurface(dst); } return (result); } /*! \brief Internal function to draw horizontal line of RGBA color with alpha blending. \param dst The surface to draw on. \param x1 X coordinate of the first point (i.e. left) of the line. \param x2 X coordinate of the second point (i.e. right) of the line. \param y Y coordinate of the points of the line. \param color The color value of the line to draw (0xRRGGBBAA). \returns Returns 0 on success, -1 on failure. */ static int _HLineAlpha(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color) { return (filledRectAlpha(dst, x1, y, x2, y, color)); } /*! \brief Internal function to draw vertical line of RGBA color with alpha blending. \param dst The surface to draw on. \param x X coordinate of the points of the line. \param y1 Y coordinate of the first point (top) of the line. \param y2 Y coordinate of the second point (bottom) of the line. \param color The color value of the line to draw (0xRRGGBBAA). \returns Returns 0 on success, -1 on failure. */ static int _VLineAlpha(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color) { return (filledRectAlpha(dst, x, y1, x, y2, color)); } /*! \brief Draw horizontal line with blending. \param dst The surface to draw on. \param x1 X coordinate of the first point (i.e. left) of the line. \param x2 X coordinate of the second point (i.e. right) of the line. \param y Y coordinate of the points of the line. \param color The color value of the line to draw (0xRRGGBBAA). \returns Returns 0 on success, -1 on failure. */ int hlineColor(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color) { Sint16 left, right, top, bottom; Uint8 *pixel, *pixellast; int dx; int pixx, pixy; Sint16 xtmp; int result = -1; Uint8 *colorptr; Uint8 color3[3]; /* * Check visibility of clipping rectangle */ if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { return(0); } /* * Swap x1, x2 if required to ensure x1<=x2 */ if (x1 > x2) { xtmp = x1; x1 = x2; x2 = xtmp; } /* * Get clipping boundary and * check visibility of hline */ left = dst->clip_rect.x; if (x2clip_rect.x + dst->clip_rect.w - 1; if (x1>right) { return(0); } top = dst->clip_rect.y; bottom = dst->clip_rect.y + dst->clip_rect.h - 1; if ((ybottom)) { return (0); } /* * Clip x */ if (x1 < left) { x1 = left; } if (x2 > right) { x2 = right; } /* * Calculate width difference */ dx = x2 - x1; /* * Alpha check */ if ((color & 255) == 255) { /* * No alpha-blending required */ /* * Setup color */ colorptr = (Uint8 *) & color; if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); } else { color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); } /* * Lock the surface */ if (SDL_MUSTLOCK(dst)) { if (SDL_LockSurface(dst) < 0) { return (-1); } } /* * More variable setup */ pixx = dst->format->BytesPerPixel; pixy = dst->pitch; pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y; /* * Draw */ switch (dst->format->BytesPerPixel) { case 1: memset(pixel, color, dx + 1); break; case 2: pixellast = pixel + dx + dx; for (; pixel <= pixellast; pixel += pixx) { *(Uint16 *) pixel = color; } break; case 3: pixellast = pixel + dx + dx + dx; if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { color3[0] = (color >> 16) & 0xff; color3[1] = (color >> 8) & 0xff; color3[2] = color & 0xff; } else { color3[0] = color & 0xff; color3[1] = (color >> 8) & 0xff; color3[2] = (color >> 16) & 0xff; } for (; pixel <= pixellast; pixel += pixx) { memcpy(pixel, color3, 3); } break; default: /* case 4 */ dx = dx + dx; pixellast = pixel + dx + dx; for (; pixel <= pixellast; pixel += pixx) { *(Uint32 *) pixel = color; } break; } /* * Unlock surface */ if (SDL_MUSTLOCK(dst)) { SDL_UnlockSurface(dst); } /* * Set result code */ result = 0; } else { /* * Alpha blending blit */ result = _HLineAlpha(dst, x1, x1 + dx, y, color); } return (result); } /*! \brief Draw horizontal line with blending. \param dst The surface to draw on. \param x1 X coordinate of the first point (i.e. left) of the line. \param x2 X coordinate of the second point (i.e. right) of the line. \param y Y coordinate of the points of the line. \param r The red value of the line to draw. \param g The green value of the line to draw. \param b The blue value of the line to draw. \param a The alpha value of the line to draw. \returns Returns 0 on success, -1 on failure. */ #if 0 int hlineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) { /* * Draw */ return (hlineColor(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); } #endif /*! \brief Draw vertical line with blending. \param dst The surface to draw on. \param x X coordinate of the points of the line. \param y1 Y coordinate of the first point (i.e. top) of the line. \param y2 Y coordinate of the second point (i.e. bottom) of the line. \param color The color value of the line to draw (0xRRGGBBAA). \returns Returns 0 on success, -1 on failure. */ int vlineColor(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color) { Sint16 left, right, top, bottom; Uint8 *pixel, *pixellast; int dy; int pixx, pixy; Sint16 h; Sint16 ytmp; int result = -1; Uint8 *colorptr; /* * Check visibility of clipping rectangle */ if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { return(0); } /* * Swap y1, y2 if required to ensure y1<=y2 */ if (y1 > y2) { ytmp = y1; y1 = y2; y2 = ytmp; } /* * Get clipping boundary and * check visibility of vline */ left = dst->clip_rect.x; right = dst->clip_rect.x + dst->clip_rect.w - 1; if ((xright)) { return (0); } top = dst->clip_rect.y; if (y2clip_rect.y + dst->clip_rect.h - 1; if (y1>bottom) { return(0); } /* * Clip x */ if (y1 < top) { y1 = top; } if (y2 > bottom) { y2 = bottom; } /* * Calculate height */ h = y2 - y1; /* * Alpha check */ if ((color & 255) == 255) { /* * No alpha-blending required */ /* * Setup color */ colorptr = (Uint8 *) & color; if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); } else { color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); } /* * Lock the surface */ if (SDL_MUSTLOCK(dst)) { if (SDL_LockSurface(dst) < 0) { return (-1); } } /* * More variable setup */ dy = h; pixx = dst->format->BytesPerPixel; pixy = dst->pitch; pixel = ((Uint8 *) dst->pixels) + pixx * (int) x + pixy * (int) y1; pixellast = pixel + pixy * dy; /* * Draw */ switch (dst->format->BytesPerPixel) { case 1: for (; pixel <= pixellast; pixel += pixy) { *(Uint8 *) pixel = color; } break; case 2: for (; pixel <= pixellast; pixel += pixy) { *(Uint16 *) pixel = color; } break; case 3: for (; pixel <= pixellast; pixel += pixy) { if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { pixel[0] = (color >> 16) & 0xff; pixel[1] = (color >> 8) & 0xff; pixel[2] = color & 0xff; } else { pixel[0] = color & 0xff; pixel[1] = (color >> 8) & 0xff; pixel[2] = (color >> 16) & 0xff; } } break; default: /* case 4 */ for (; pixel <= pixellast; pixel += pixy) { *(Uint32 *) pixel = color; } break; } /* Unlock surface */ if (SDL_MUSTLOCK(dst)) { SDL_UnlockSurface(dst); } /* * Set result code */ result = 0; } else { /* * Alpha blending blit */ result = _VLineAlpha(dst, x, y1, y1 + h, color); } return (result); } /*! \brief Draw vertical line with blending. \param dst The surface to draw on. \param x X coordinate of the points of the line. \param y1 Y coordinate of the first point (i.e. top) of the line. \param y2 Y coordinate of the second point (i.e. bottom) of the line. \param r The red value of the line to draw. \param g The green value of the line to draw. \param b The blue value of the line to draw. \param a The alpha value of the line to draw. \returns Returns 0 on success, -1 on failure. */ #if 0 int vlineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) { /* * Draw */ return (vlineColor(dst, x, y1, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); } #endif /*! \brief Draw rectangle with blending. \param dst The surface to draw on. \param x1 X coordinate of the first point (i.e. top right) of the rectangle. \param y1 Y coordinate of the first point (i.e. top right) of the rectangle. \param x2 X coordinate of the second point (i.e. bottom left) of the rectangle. \param y2 Y coordinate of the second point (i.e. bottom left) of the rectangle. \param color The color value of the rectangle to draw (0xRRGGBBAA). \returns Returns 0 on success, -1 on failure. */ int rectangleColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color) { int result; Sint16 tmp; /* Check destination surface */ if (dst == NULL) { return -1; } /* * Check visibility of clipping rectangle */ if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { return 0; } /* * Test for special cases of straight lines or single point */ if (x1 == x2) { if (y1 == y2) { return (pixelColor(dst, x1, y1, color)); } else { return (vlineColor(dst, x1, y1, y2, color)); } } else { if (y1 == y2) { return (hlineColor(dst, x1, x2, y1, color)); } } /* * Swap x1, x2 if required */ if (x1 > x2) { tmp = x1; x1 = x2; x2 = tmp; } /* * Swap y1, y2 if required */ if (y1 > y2) { tmp = y1; y1 = y2; y2 = tmp; } /* * Draw rectangle */ result = 0; result |= hlineColor(dst, x1, x2, y1, color); result |= hlineColor(dst, x1, x2, y2, color); y1 += 1; y2 -= 1; if (y1 <= y2) { result |= vlineColor(dst, x1, y1, y2, color); result |= vlineColor(dst, x2, y1, y2, color); } return (result); } /*! \brief Draw rectangle with blending. \param dst The surface to draw on. \param x1 X coordinate of the first point (i.e. top right) of the rectangle. \param y1 Y coordinate of the first point (i.e. top right) of the rectangle. \param x2 X coordinate of the second point (i.e. bottom left) of the rectangle. \param y2 Y coordinate of the second point (i.e. bottom left) of the rectangle. \param r The red value of the rectangle to draw. \param g The green value of the rectangle to draw. \param b The blue value of the rectangle to draw. \param a The alpha value of the rectangle to draw. \returns Returns 0 on success, -1 on failure. */ int rectangleRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) { /* * Draw */ return (rectangleColor (dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); } /* --------- Clipping routines for line */ /* Clipping based heavily on code from */ /* http://www.ncsa.uiuc.edu/Vis/Graphics/src/clipCohSuth.c */ #define CLIP_LEFT_EDGE 0x1 #define CLIP_RIGHT_EDGE 0x2 #define CLIP_BOTTOM_EDGE 0x4 #define CLIP_TOP_EDGE 0x8 #define CLIP_INSIDE(a) (!a) #define CLIP_REJECT(a,b) (a&b) #define CLIP_ACCEPT(a,b) (!(a|b)) /*! \brief Internal clip-encoding routine. Calculates a segement-based clipping encoding for a point against a rectangle. \param x X coordinate of point. \param y Y coordinate of point. \param left X coordinate of left edge of the rectangle. \param top Y coordinate of top edge of the rectangle. \param right X coordinate of right edge of the rectangle. \param bottom Y coordinate of bottom edge of the rectangle. */ static int _clipEncode(Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom) { int code = 0; if (x < left) { code |= CLIP_LEFT_EDGE; } else if (x > right) { code |= CLIP_RIGHT_EDGE; } if (y < top) { code |= CLIP_TOP_EDGE; } else if (y > bottom) { code |= CLIP_BOTTOM_EDGE; } return code; } /*! \brief Clip line to a the clipping rectangle of a surface. \param dst Target surface to draw on. \param x1 Pointer to X coordinate of first point of line. \param y1 Pointer to Y coordinate of first point of line. \param x2 Pointer to X coordinate of second point of line. \param y2 Pointer to Y coordinate of second point of line. */ static int _clipLine(SDL_Surface * dst, Sint16 * x1, Sint16 * y1, Sint16 * x2, Sint16 * y2) { Sint16 left, right, top, bottom; int code1, code2; int draw = 0; Sint16 swaptmp; float m; /* * Get clipping boundary */ left = dst->clip_rect.x; right = dst->clip_rect.x + dst->clip_rect.w - 1; top = dst->clip_rect.y; bottom = dst->clip_rect.y + dst->clip_rect.h - 1; while (1) { code1 = _clipEncode(*x1, *y1, left, top, right, bottom); code2 = _clipEncode(*x2, *y2, left, top, right, bottom); if (CLIP_ACCEPT(code1, code2)) { draw = 1; break; } else if (CLIP_REJECT(code1, code2)) break; else { if (CLIP_INSIDE(code1)) { swaptmp = *x2; *x2 = *x1; *x1 = swaptmp; swaptmp = *y2; *y2 = *y1; *y1 = swaptmp; swaptmp = code2; code2 = code1; code1 = swaptmp; } if (*x2 != *x1) { m = (float)(*y2 - *y1) / (float)(*x2 - *x1); } else { m = 1.0f; } if (code1 & CLIP_LEFT_EDGE) { *y1 += (Sint16) ((left - *x1) * m); *x1 = left; } else if (code1 & CLIP_RIGHT_EDGE) { *y1 += (Sint16) ((right - *x1) * m); *x1 = right; } else if (code1 & CLIP_BOTTOM_EDGE) { if (*x2 != *x1) { *x1 += (Sint16) ((bottom - *y1) / m); } *y1 = bottom; } else if (code1 & CLIP_TOP_EDGE) { if (*x2 != *x1) { *x1 += (Sint16) ((top - *y1) / m); } *y1 = top; } } } return draw; } /* ----- Line */ /* Non-alpha line drawing code adapted from routine */ /* by Pete Shinners, pete@shinners.org */ /* Originally from pygame, http://pygame.seul.org */ #define ABS(a) (((a)<0) ? -(a) : (a)) /*! \brief Draw line with alpha blending. \param dst The surface to draw on. \param x1 X coordinate of the first point of the line. \param y1 Y coordinate of the first point of the line. \param x2 X coordinate of the second point of the line. \param y2 Y coordinate of the second point of the line. \param color The color value of the line to draw (0xRRGGBBAA). \returns Returns 0 on success, -1 on failure. */ int lineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color) { int pixx, pixy; int x, y; int dx, dy; int ax, ay; int sx, sy; int swaptmp; Uint8 *pixel; Uint8 *colorptr; /* * Clip line and test if we have to draw */ if (!(_clipLine(dst, &x1, &y1, &x2, &y2))) { return (0); } /* * Test for special cases of straight lines or single point */ if (x1 == x2) { if (y1 < y2) { return (vlineColor(dst, x1, y1, y2, color)); } else if (y1 > y2) { return (vlineColor(dst, x1, y2, y1, color)); } else { return (pixelColor(dst, x1, y1, color)); } } if (y1 == y2) { if (x1 < x2) { return (hlineColor(dst, x1, x2, y1, color)); } else if (x1 > x2) { return (hlineColor(dst, x2, x1, y1, color)); } } /* * Variable setup */ dx = x2 - x1; dy = y2 - y1; sx = (dx >= 0) ? 1 : -1; sy = (dy >= 0) ? 1 : -1; /* Lock surface */ if (SDL_MUSTLOCK(dst)) { if (SDL_LockSurface(dst) < 0) { return (-1); } } /* * Check for alpha blending */ if ((color & 255) == 255) { /* * No alpha blending - use fast pixel routines */ /* * Setup color */ colorptr = (Uint8 *) & color; if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); } else { color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); } /* * More variable setup */ dx = sx * dx + 1; dy = sy * dy + 1; pixx = dst->format->BytesPerPixel; pixy = dst->pitch; pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1; pixx *= sx; pixy *= sy; if (dx < dy) { swaptmp = dx; dx = dy; dy = swaptmp; swaptmp = pixx; pixx = pixy; pixy = swaptmp; } /* * Draw */ x = 0; y = 0; switch (dst->format->BytesPerPixel) { case 1: for (; x < dx; x++, pixel += pixx) { *pixel = color; y += dy; if (y >= dx) { y -= dx; pixel += pixy; } } break; case 2: for (; x < dx; x++, pixel += pixx) { *(Uint16 *) pixel = color; y += dy; if (y >= dx) { y -= dx; pixel += pixy; } } break; case 3: for (; x < dx; x++, pixel += pixx) { if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { pixel[0] = (color >> 16) & 0xff; pixel[1] = (color >> 8) & 0xff; pixel[2] = color & 0xff; } else { pixel[0] = color & 0xff; pixel[1] = (color >> 8) & 0xff; pixel[2] = (color >> 16) & 0xff; } y += dy; if (y >= dx) { y -= dx; pixel += pixy; } } break; default: /* case 4 */ for (; x < dx; x++, pixel += pixx) { *(Uint32 *) pixel = color; y += dy; if (y >= dx) { y -= dx; pixel += pixy; } } break; } } else { /* * Alpha blending required - use single-pixel blits */ ax = ABS(dx) << 1; ay = ABS(dy) << 1; x = x1; y = y1; if (ax > ay) { int d = ay - (ax >> 1); while (x != x2) { pixelColorNolock (dst, x, y, color); if (d > 0 || (d == 0 && sx == 1)) { y += sy; d -= ax; } x += sx; d += ay; } } else { int d = ax - (ay >> 1); while (y != y2) { pixelColorNolock (dst, x, y, color); if (d > 0 || ((d == 0) && (sy == 1))) { x += sx; d -= ay; } y += sy; d += ax; } } pixelColorNolock (dst, x, y, color); } /* Unlock surface */ if (SDL_MUSTLOCK(dst)) { SDL_UnlockSurface(dst); } return (0); } /* ----- Filled Circle */ /*! \brief Draw filled circle with blending. Note: Based on algorithms from sge library with modifications by A. Schiffler for multiple-hline draw removal and other minor speedup changes. \param dst The surface to draw on. \param x X coordinate of the center of the filled circle. \param y Y coordinate of the center of the filled circle. \param rad Radius in pixels of the filled circle. \param color The color value of the filled circle to draw (0xRRGGBBAA). \returns Returns 0 on success, -1 on failure. */ int filledCircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color) { Sint16 left, right, top, bottom; int result; Sint16 x1, y1, x2, y2; Sint16 cx = 0; Sint16 cy = rad; Sint16 ocx = (Sint16) 0xffff; Sint16 ocy = (Sint16) 0xffff; Sint16 df = 1 - rad; Sint16 d_e = 3; Sint16 d_se = -2 * rad + 5; Sint16 xpcx, xmcx, xpcy, xmcy; Sint16 ypcy, ymcy, ypcx, ymcx; /* * Check visibility of clipping rectangle */ if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { return(0); } /* * Sanity check radius */ if (rad < 0) { return (-1); } /* * Special case for rad=0 - draw a point */ if (rad == 0) { return (pixelColor(dst, x, y, color)); } /* * Get circle and clipping boundary and * test if bounding box of circle is visible */ x2 = x + rad; left = dst->clip_rect.x; if (x2clip_rect.x + dst->clip_rect.w - 1; if (x1>right) { return(0); } y2 = y + rad; top = dst->clip_rect.y; if (y2clip_rect.y + dst->clip_rect.h - 1; if (y1>bottom) { return(0); } /* * Draw */ result = 0; do { xpcx = x + cx; xmcx = x - cx; xpcy = x + cy; xmcy = x - cy; if (ocy != cy) { if (cy > 0) { ypcy = y + cy; ymcy = y - cy; result |= hlineColor(dst, xmcx, xpcx, ypcy, color); result |= hlineColor(dst, xmcx, xpcx, ymcy, color); } else { result |= hlineColor(dst, xmcx, xpcx, y, color); } ocy = cy; } if (ocx != cx) { if (cx != cy) { if (cx > 0) { ypcx = y + cx; ymcx = y - cx; result |= hlineColor(dst, xmcy, xpcy, ymcx, color); result |= hlineColor(dst, xmcy, xpcy, ypcx, color); } else { result |= hlineColor(dst, xmcy, xpcy, y, color); } } ocx = cx; } /* * Update */ if (df < 0) { df += d_e; d_e += 2; d_se += 2; } else { df += d_se; d_e += 2; d_se += 4; cy--; } cx++; } while (cx <= cy); return (result); } /*! \brief Draw filled circle with blending. \param dst The surface to draw on. \param x X coordinate of the center of the filled circle. \param y Y coordinate of the center of the filled circle. \param rad Radius in pixels of the filled circle. \param r The red value of the filled circle to draw. \param g The green value of the filled circle to draw. \param b The blue value of the filled circle to draw. \param a The alpha value of the filled circle to draw. \returns Returns 0 on success, -1 on failure. */ #if 0 int filledCircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) { /* * Draw */ return (filledCircleColor (dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); } #endif /* ---- Filled Polygon */ /*! \brief Internal helper qsort callback functions used in filled polygon drawing. \param a The surface to draw on. \param b Vertex array containing X coordinates of the points of the polygon. \returns Returns 0 if a==b, a negative number if ab. */ static int _gfxPrimitivesCompareInt(const void *a, const void *b) { return (*(const int *) a) - (*(const int *) b); } /*! \brief Global vertex array to use if optional parameters are not given in filledPolygonMT calls. Note: Used for non-multithreaded (default) operation of filledPolygonMT. */ static int *gfxPrimitivesPolyIntsGlobal = NULL; /*! \brief Flag indicating if global vertex array was already allocated. Note: Used for non-multithreaded (default) operation of filledPolygonMT. */ static int gfxPrimitivesPolyAllocatedGlobal = 0; /*! \brief Draw filled polygon with alpha blending (multi-threaded capable). Note: The last two parameters are optional; but are required for multithreaded operation. \param dst The surface to draw on. \param vx Vertex array containing X coordinates of the points of the filled polygon. \param vy Vertex array containing Y coordinates of the points of the filled polygon. \param n Number of points in the vertex array. Minimum number is 3. \param color The color value of the filled polygon to draw (0xRRGGBBAA). \param polyInts Preallocated, temporary vertex array used for sorting vertices. Required for multithreaded operation; set to NULL otherwise. \param polyAllocated Flag indicating if temporary vertex array was allocated. Required for multithreaded operation; set to NULL otherwise. \returns Returns 0 on success, -1 on failure. */ int filledPolygonColorMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color, int **polyInts, int *polyAllocated) { int result; int i; int y, xa, xb; int miny, maxy; int x1, y1; int x2, y2; int ind1, ind2; int ints; int *gfxPrimitivesPolyInts = NULL; int *gfxPrimitivesPolyIntsNew = NULL; int gfxPrimitivesPolyAllocated = 0; /* * Check visibility of clipping rectangle */ if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { return(0); } /* * Vertex array NULL check */ if (vx == NULL) { return (-1); } if (vy == NULL) { return (-1); } /* * Sanity check number of edges */ if (n < 3) { return -1; } /* * Map polygon cache */ if ((polyInts==NULL) || (polyAllocated==NULL)) { /* Use global cache */ gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal; gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal; } else { /* Use local cache */ gfxPrimitivesPolyInts = *polyInts; gfxPrimitivesPolyAllocated = *polyAllocated; } /* * Allocate temp array, only grow array */ if (!gfxPrimitivesPolyAllocated) { gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n); gfxPrimitivesPolyAllocated = n; } else { if (gfxPrimitivesPolyAllocated < n) { gfxPrimitivesPolyIntsNew = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n); if (!gfxPrimitivesPolyIntsNew) { if (!gfxPrimitivesPolyInts) { free(gfxPrimitivesPolyInts); gfxPrimitivesPolyInts = NULL; } gfxPrimitivesPolyAllocated = 0; } else { gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsNew; gfxPrimitivesPolyAllocated = n; } } } /* * Check temp array */ if (gfxPrimitivesPolyInts==NULL) { gfxPrimitivesPolyAllocated = 0; } /* * Update cache variables */ if ((polyInts==NULL) || (polyAllocated==NULL)) { gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts; gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated; } else { *polyInts = gfxPrimitivesPolyInts; *polyAllocated = gfxPrimitivesPolyAllocated; } /* * Check temp array again */ if (gfxPrimitivesPolyInts==NULL) { return(-1); } /* * Determine Y maxima */ miny = vy[0]; maxy = vy[0]; for (i = 1; (i < n); i++) { if (vy[i] < miny) { miny = vy[i]; } else if (vy[i] > maxy) { maxy = vy[i]; } } /* * Draw, scanning y */ result = 0; for (y = miny; (y <= maxy); y++) { ints = 0; for (i = 0; (i < n); i++) { if (!i) { ind1 = n - 1; ind2 = 0; } else { ind1 = i - 1; ind2 = i; } y1 = vy[ind1]; y2 = vy[ind2]; if (y1 < y2) { x1 = vx[ind1]; x2 = vx[ind2]; } else if (y1 > y2) { y2 = vy[ind1]; y1 = vy[ind2]; x2 = vx[ind1]; x1 = vx[ind2]; } else { continue; } if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) { gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1); } } qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt); for (i = 0; (i < ints); i += 2) { xa = gfxPrimitivesPolyInts[i] + 1; xa = (xa >> 16) + ((xa & 32768) >> 15); xb = gfxPrimitivesPolyInts[i+1] - 1; xb = (xb >> 16) + ((xb & 32768) >> 15); result |= hlineColor(dst, xa, xb, y, color); } } return (result); } /*! \brief Draw filled polygon with alpha blending. Note: Standard filledPolygon function is calling multithreaded version with NULL parameters to use the global vertex cache. \param dst The surface to draw on. \param vx Vertex array containing X coordinates of the points of the filled polygon. \param vy Vertex array containing Y coordinates of the points of the filled polygon. \param n Number of points in the vertex array. Minimum number is 3. \param color The color value of the filled polygon to draw (0xRRGGBBAA). \returns Returns 0 on success, -1 on failure. */ int filledPolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color) { /* * Draw */ return (filledPolygonColorMT(dst, vx, vy, n, color, NULL, NULL)); } ballerburg-1.2.0/src/baller1.h0000644000175000017500000000341012506012141015453 0ustar thomasthomas/* baller1.h - prototypes and definitions for baller1.c Copyright (C) 2010, 2011 Thomas Huth This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #define P57 57.296 #define G 0.02 /* Fallbeschleunigung ( g/500 ) */ extern short mx, my, bt, xy[100], bur[2],bx[2],by[2], ge[2],pu[2],ku[2],vo[2],st[2],kn[2], wx[2],wy[2], *bg, zug,n, p[6], max_rund, fx,fy,fw,fh, *burgen[], b_anz; extern int ftx, fty, ftw, fth; extern const char *l_nam, *r_nam; extern int f; extern char mod, wnd, end, an_erl, au_kap, nsp1[],nsp2[]; extern int cw[2],cx[2]; extern const char *cn[7]; typedef struct { short x,y,w,p; } ka_t; extern ka_t ka[2][10]; typedef struct { short x,y; } ft_t; extern ft_t ft[2][5]; #define fn() f=1-2*(n&1) int main(int argc, char **argv); void tabelle(void); void z_txt(short a); void neues(void); int ein_zug(void); void rechnen(void); void ende(void); int m_wait(void); void werdran(char c); void fahne(void); int t_load(void); int t_save(void); void burgen_laden(void); int obj_do(int adr); void gem_init(void); int loc(int x, int y); void line(short x1, short y1, short x2, short y2); void box(short x, short y, short x2, short y2, short c); ballerburg-1.2.0/src/baller.mus0000644000175000017500000001173412506012141015757 0ustar thomasthomasi        0   pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppphhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh````````````hhhhhhhhhhhhpppppppppppppppppppppppp||||||||||||||||||||||||||||||||||||||||||||||||xxxxxxxxxxxxxxxxxxxxxxxxttttttttttttttttttttttttppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppD@<988998899DDEEDDEEDDEED@<988998899DDEEDDEEDDEED@<988998899DDEEDDEEDDEEppppppppppppDDDDDDDDDDDD888888888888<<<<<<DDDDDDDDDDDDDDDDDDDDDDDDHHHHHHLLLLLLLLLLLLTTTTTTTTTTTT^D^D@@@@@@@@@@HHHHHHHHHHHHLLLLLLLLLLLLHHHHHHLLLLLLLLLLLLHHHHHHHHHHHHLLLLLLTTTTTTTTTTTTTTTTTTTTTTTT````````````````````````XXXXXXXXXXXXXXXXXXTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<;8;8;8888888888888888888888<8<88888<888888888888888888=8=8=8888888888888888<888888<8<88888888888;888;888;888888;D;DDDDDDDDDDDDDDDDDDDDDDD. */ void markt(void); ballerburg-1.2.0/src/paths.h0000644000175000017500000000075612506012141015262 0ustar thomasthomas/* Ballerburg This file is distributed under the GNU General Public License, version 2 or at your option any later version. Read the file COPYING.txt for details. */ #ifndef BALLER_PATHS_H #define BALLER_PATHS_H extern void Paths_Init(const char *argv0); extern const char *Paths_GetWorkingDir(void); extern const char *Paths_GetDataDir(void); extern const char *Paths_GetLocaleDir(void); extern const char *Paths_GetUserHome(void); extern const char *Paths_GetProgHome(void); #endif ballerburg-1.2.0/src/psg.h0000644000175000017500000000340012506012141014721 0ustar thomasthomas/* * libpsg - a simple YM-2149 soundchip emulation library. * * Copyright (C) 2000 Stefan Berndtsson (NoCrew) * Copyright (C) 2011 Thomas Huth * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef PSG_H #define PSG_H #define SND_MONO 0 #define SND_STEREO 1 struct sndconfig { int mode; int bits; int freq; }; struct spsg { int regs[15]; int env_kept; struct sndconfig output; }; typedef struct spsg psg; /** * PSG *psg_init(int mode, int bits, int freq) * Action: * setup all internal variables. * Parameters: * mode - mono/stereo * bits - 8/16 * freq - frequency for audio output * Return: * psg - empty struct for you to use */ psg *psg_init(int, int, int); /** * psg_create_samples(void *output_buffer, * psg *psg_struct, * int usec); * Action: * builds a sample of length 'usec' into 'output_buffer' * from 'psg_struct' * Parameters: * buffer - allocated output buffer of suitable size * psg_struct - psg as returned from psg_init() * samples - amount of samples to produce * Return: * int - 0 if things go ok */ int psg_create_samples(void *buffer, psg *psgstruct, int samples); void psg_audio_init(void); unsigned int Giaccess(unsigned int data, unsigned int reg); void Dosound(const unsigned char *buf); #endif /* PSG_H */ ballerburg-1.2.0/src/baller.dat0000644000175000017500000001751012506012141015721 0ustar thomasthomas*=============================================================================* * BALLER.DAT : Burgdaten fr Ballerburg * * 28.4.87 Eckhard Kruse * * Einige Informationen vorweg: * * - Bemerkungen mssen in Sternchen eingeschlossen werden * * - Die Zahlen mssen durch Kommata oder Blanks voneinander getrennt sein * * - Alle Angaben beziehen sich direkt auf die Rasterkoordinaten ( RC ) der * * hohen Auflsung * * - Stellen Sie sich die Burgdaten nur fr die linke Burg vor. Die rechte * * Burg wird einfach durch Spiegelung gezeichnet. * * - Der Koordinatenursprung liegt am linken Bildschirmrand an der Unterkante* * der Burg. Es gibt nur positive Koordinaten ( und 0 ). * * - Ballerburg entdeckt keine Fehler in der Burgdatei. Fehlerhafte Daten * * knnen schlimmstenfalls zum Absturz fhren. * * - Zum Erstellen von eigenen Burgen entwerfen Sie diese am besten zuerst * * auf Millimeterpapier und lesen dann die Koordinaten einfach ab. * *=============================================================================* *========================= Daten fr die 1. Burg =============================* 130 * Ausdehnung in X-Richtung ( entspricht dem hchsten X-Wert der * * Zeichendaten. ), darf nicht grer als 200 sein. * 10,31, 70,36, -1,-1, -1,-1, -1,-1, -1,-1, -1,-1, -1,-1, -1,-1, -1,-1 * X,Y-Koordinaten der 10 mglichen Kanonen, nicht verwandte sind mit -1,-1 * * anzugeben. Die Koordinaten beziehen sich auf die linke, untere Ecke. Die * * Mae einer Kanone: 20x12 * * Die nchsten 5 Koordinatenpaare ( auer der Fahne ) beziehen sich auf die * * linke untere Ecke des zu zeichnenden 'Kastens'. * 40,1 * X,Y-Koordinaten des Trohnes * 18,70 * X,Y-Koordinaten der Fahne ( bezogen auf das untere Stangenende. ) * 9,1 * X,Y-Koordinaten des Geldes * 80,3 * X,Y-Koordinaten des Pulvers * 103,25 * X,Y-Koordinaten der Kugeln * 21,20 * Breite, Hhe der Geldkammer ( Gre eines Sackes: 7x10 ) * 27,18 * Breite, Hhe der Pulverkammer ( Gre eines Fasses: 9x9 ) * 24,18 * Breite, Hhe der Kugelkammer ( Gre einer Kugel: 6x6 ) * * Durch die Mae der Kammern wird automatisch die Obergrenze fr Geld, * * Pulver und Kugeln festgelegt. Die Mae mssen jeweils ein Vielfaches der * * Gren der einzelnen Objekte sein. * * Der Trohn hat immer die Mae 30x25, die Windfahne 30x15. * 400 * Startwert fr das Geld * 180 * Startwert fr das Pulver * 12 * Startwert fr die Kugeln * 200 * Startwert fr das Volk * 0,0,0,0 * reservierte, nicht verwandte Werte * *=============================================================================* * Es folgen nun die Daten fr das eigentliche Aussehen der Burg. Die Zeichen- * * routine liest die Zahlen der Reihe nach und interpretiert sie wie folgt: * * - Ist die Zahl >=0, so sei sie das erste Element einer X,Y-Koordinatenliste,* * die mit einer -9 abgeschlossen wird. Diese Koordinaten stellen die * * Eckpunkte einer zu fllenden Flche dar. * * ( Geschieht mit v_fillarea( handle,n,xy ). ) * * - Ist die Zahl eine -2, so werden die beiden folgenden Zahlen als Style und * * Index eines neuen Fllmusters angesehen. Der Startwert vor dem Zeichnen * * ist 2,9 ( Mauerwerk ). Das Zeichnen geschieht brigens im Schreibmodus 4 * * ( reverse transparent ). Dies bewirkt, da die Fllmuster invers erschei- * * nen. Um es Ihnen etwas einfacher zu machen: Sie brauchen sich eigentlich * * nur zu merken, da vor dem Zeichnen von Mauern -2,2,9 und vor dem Zeichnen* * von Dchern -2,2,11 stehen mu. * * - Die -1 schliet die Zeichendaten und gleichzeitig die Daten einer Burg ab.* *=============================================================================* 0,0,0,30,5,55,30,55,10,45,10,30,30,30,75,65,80,60,70,50,70,35,90,35,100,45, 100,60,130,60,130,0,-9, -2,2,11, 5,55,18,70,30,55,-9, 100,60,115,70,130,60,-9, -1 *=============================================================================* * Fr die folgenden Burgen gilt der gleiche Aufbau der Daten. Ich habe daher * * auf die Erluterungen verzichtet. * *========================= Daten fr die 2. Burg =============================* 150 10,11,10,51,50,51,80,46,130,46,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 45,1 135,100 80,1, 52,30, 126,1 35,20, 63,9, 18,36 500,180,12,270 0,0,0,0 0,0,0,70,30,70,10,65,10,50,30,50,10,30,10,10,30,10,50,50,70,50,80,45,120,45, 120,70,150,70,130,60,130,45,150,45,150,0,-9, -2,2,11, 0,70,15,100,30,70,-9, 120,70,135,100,150,70,-9, -1 *========================= Daten fr die 3. Burg =============================* 130 0,70,20,70,50,40,50,16,110,40,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 10,1 95,60 11,30, 50,1, 80,15 28,30, 72,9, 42,18 500,150,14,270 0,0,0,0 0,0,0,70,40,70,50,50,50,40,70,40,50,30,50,15,70,15,80,40,130,40,130,0,-9, -2,2,11, 80,40,95,60,110,40,-9, -1 *========================= Daten fr die 4. Burg =============================* 170 10,36,70,40,90,40,75,80,150,21,150,56,-1,-1,-1,-1,-1,-1,-1,-1 60,1 15,80 15,5, 100,1, 100,20 35,20, 63,9, 36,18 500,190,12,300 0,0,0,0 0,0,0,60,30,60,10,50,10,35,30,35,75,80,95,80,70,55,70,40,110,40,120,70,150,70, 150,55,170,55,150,35,150,20,170,20,170,0,-9, -2,2,11, 0,60,15,80,30,60,-9, 120,70,140,90,160,70,-9, -1 *========================= Daten fr die 5. Burg =============================* 115 10,36,55,31,90,51,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 10,1 27,67 50,1, 85,1, 102,1 28,10, 9,36, 6,36 500,120,6,220 0,0,0,0 0,0,0,55,27,67,30,60,10,50,10,35,30,35,55,60,70,60,55,45,55,30,75,30,85,50, 115,50,115,0,-9, -1 *========================= Daten fr die 6. Burg =============================* 140 10,60,30,60,90,40,110,40,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 90,1 90,85 10,1, 50,1, 15,38 28,20, 27,18, 30,12 500,120,10,240 0,0,0,0 0,0,10,60,50,60,55,30,70,30,70,70,110,70,90,55,90,40,130,40,140,0,-9, -2,2,11, 70,70,90,85,110,70,-9, -1 *==================== Some castles from Ballerburg^2 =========================* 150,40,91,40,61,40,31,40, 1,60, 1,80, 1,-1,-1,-1,-1,-1,-1,-1,-1 114, 3,23,130, 9,82,9,40, 8,3, 28,20, 27,36, 30,30, 800,120,12,500 0,0,0,0 6,0,6,105,2,115,2,130,8,130,8,122,11,122,11,130,17,130,17,122,20,122, 20,130,26,130,26,122,29,122,29,130,35,130,35,122,38,122,38,130,44,130, 44,115,40,105,40,90,60,90,60,85,40,75,40,60,60,60,60,55,40,45,40,30, 60,30,60,25,40,15,40,1,110,1,110,33,150,33,150,0,-9, -2,2,11,108,33,128,50,151,33,-9,-1 160,47,121,70,121,93,121,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 65,2,155,30,69,90,71,56,71,32,21,20,18,18,18,18,500,120,9,500 0,0,0,0 0,0,0,30,15,30,30,35,40,45,45,60,47,120,60,120,60,50,55,35,50,25,35,10, 25,5,5,0,0,0,63,0,64,120,95,120,96,0,155,0,135,5,125,10,110,25,105,35, 100,50,100,120,113,120,115,60,120,45,130,35,145,30,160,30,160,0,-9,-1 185, 82,126,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 80,40, 45,125, 15,45, 125,40, 81,79, 49,30,45,36,24,36,1000,120,12,300 0,0,0,0 30,0,15,13,1,45,1,65,15,100,35,120,45,125,30,100, 30,90,35,85,45,82,50,82,70,95,75,105,75,135, 80,125,105,125,110,135, 110,105,115,95,135,82,140,82,150,85,155,90,155,100,140,125, 150,120,170,100,184,65,184,45,170,13,155,0,160,15,160,20, 155,30,145,35,130,35,120,22,110,35,105,35,92,18,80,35,65,22,55,35, 40,35,30,30,25,20,25,15,30,0,-9,-1 * Hier z.B. koennen Sie Ihre eigenen Kreationen einschieben. Die Anzahl der * * Burgen ist beliebig und wird von Ballerburg automatisch erkannt * -999 * Ende der Burgendatei * ballerburg-1.2.0/src/sdlgui.c0000664000175000017500000006445012506012141015430 0ustar thomasthomas/* * sdlgui.c - A tiny graphical user interface for the SDL library. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This file is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * (http://www.gnu.org/licenses/) for more details. */ const char SDLGui_fileid[] = "sdlgui.c : " __DATE__ " " __TIME__; #include #include #include #include #include #include #include "i18n.h" #include "sdlgui.h" #include "baller1.h" #include "screen.h" #include "font8x16.h" #if WITH_SDL2 #define SDL_SRCCOLORKEY SDL_TRUE #endif int sdlgui_fontwidth; /* Width of the actual font */ int sdlgui_fontheight; /* Height of the actual font */ static SDL_Surface *pSdlGuiScrn; /* Pointer to the actual main SDL screen surface */ //static SDL_Surface *pSmallFontGfx = NULL; /* The small font graphics */ static SDL_Surface *pBigFontGfx = NULL; /* The big font graphics */ static SDL_Surface *pFontGfx = NULL; /* The actual font graphics */ static int current_object = 0; /* Current selected object */ static bool has_utf8; #if WITH_SDL2 static inline int SDL_SetColors(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors) { return SDL_SetPaletteColors(surface->format->palette, colors, firstcolor, ncolors); } #endif /** * Load an 1 plane XBM into a 8 planes SDL_Surface. */ static SDL_Surface *SDLGui_LoadXBM(int w, int h, const void *pXbmBits) { SDL_Surface *bitmap; Uint8 *dstbits; const Uint8 *srcbits; int x, y, srcpitch; int mask; srcbits = pXbmBits; /* Allocate the bitmap */ bitmap = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0); if (bitmap == NULL) { fprintf(stderr, "Failed to allocate bitmap: %s", SDL_GetError()); return NULL; } srcpitch = ((w + 7) / 8); dstbits = (Uint8 *)bitmap->pixels; mask = 1; /* Copy the pixels */ for (y = 0 ; y < h ; y++) { for (x = 0 ; x < w ; x++) { dstbits[x] = (srcbits[x / 8] & mask) ? 1 : 0; mask <<= 1; mask |= (mask >> 8); mask &= 0xFF; } dstbits += bitmap->pitch; srcbits += srcpitch; } return bitmap; } /*-----------------------------------------------------------------------*/ /** * Initialize the GUI. */ int SDLGui_Init(void) { char *lang; SDL_Color blackWhiteColors[2] = {{255, 255, 255, 0}, {0, 0, 0, 0}}; if (/*pSmallFontGfx &&*/ pBigFontGfx) { /* already initialized */ return 0; } /* Initialize the font graphics: */ // pSmallFontGfx = SDLGui_LoadXBM(font5x8_width, font5x8_height, font5x8_bits); pBigFontGfx = SDLGui_LoadXBM(font8x16_width, font8x16_height, font8x16_bits); if (/*pSmallFontGfx == NULL ||*/ pBigFontGfx == NULL) { fprintf(stderr, "Error: Can not init font graphics!\n"); return -1; } /* Set color palette of the font graphics: */ //SDL_SetColors(pSmallFontGfx, blackWhiteColors, 0, 2); SDL_SetColors(pBigFontGfx, blackWhiteColors, 0, 2); /* Set font color 0 as transparent: */ //SDL_SetColorKey(pSmallFontGfx, SDL_SRCCOLORKEY, 0); SDL_SetColorKey(pBigFontGfx, SDL_SRCCOLORKEY, 0); /* Check for UTF-8 locale */ lang = getenv("LANG"); if (lang != NULL) { has_utf8 = (strstr(lang, "utf-8") != NULL) || (strstr(lang, "UTF-8") != NULL) || (strstr(lang, "utf8") != NULL) || (strstr(lang, "UTF8") != NULL); } else { has_utf8 = false; } return 0; } /*-----------------------------------------------------------------------*/ /** * Uninitialize the GUI. */ int SDLGui_UnInit(void) { /* if (pSmallFontGfx) { SDL_FreeSurface(pSmallFontGfx); pSmallFontGfx = NULL; } */ if (pBigFontGfx) { SDL_FreeSurface(pBigFontGfx); pBigFontGfx = NULL; } return 0; } /*-----------------------------------------------------------------------*/ /** * Inform the SDL-GUI about the actual SDL_Surface screen pointer and * prepare the font to suit the actual resolution. */ int SDLGui_SetScreen(SDL_Surface *pScrn) { pSdlGuiScrn = pScrn; /* Decide which font to use - small or big one: */ // if (pSdlGuiScrn->w >= 640 && pSdlGuiScrn->h >= 400 && pBigFontGfx != NULL) { pFontGfx = pBigFontGfx; } /* else { pFontGfx = pSmallFontGfx; } */ if (pFontGfx == NULL) { fprintf(stderr, "Error: A problem with the font occured!\n"); return -1; } /* Get the font width and height: */ sdlgui_fontwidth = pFontGfx->w/16; sdlgui_fontheight = pFontGfx->h/16; return 0; } /*-----------------------------------------------------------------------*/ /** * Return character size for current font in given arguments. */ void SDLGui_GetFontSize(int *width, int *height) { *width = sdlgui_fontwidth; *height = sdlgui_fontheight; } /*-----------------------------------------------------------------------*/ /** * Center a dialog so that it appears in the middle of the screen. * Note: We only store the coordinates in the root box of the dialog, * all other objects in the dialog are positioned relatively to this one. */ void SDLGui_CenterDlg(SGOBJ *dlg) { dlg[0].x = (pSdlGuiScrn->w/sdlgui_fontwidth-dlg[0].w)/2; dlg[0].y = (pSdlGuiScrn->h/sdlgui_fontheight-dlg[0].h)/2; } /** * Convert UTF-8 character to our internal Latin1 representation and * increase the string index. */ static char SDLGui_Utf8ToLatin1(const char *txt, int *i) { unsigned char c; c = txt[*i]; *i += 1; if (c < 0x80 || !has_utf8) { return c; } /* Quick and dirty convertion for latin1 characters only... */ if ((c & 0xc0) == 0xc0) { c = c << 6; c |= (txt[*i] & 0x7f); *i += 1; } else { printf("Unsupported character '%c' (0x%x)\n", c, c); } return c; } /** * Draw a text string. */ void SDLGui_Text(int x, int y, const char *txt) { int i, p; unsigned char c; SDL_Rect sr, dr; sr.w = dr.w = sdlgui_fontwidth; sr.h = dr.h = sdlgui_fontheight; i = p = 0; while (txt[i] != 0) { c = SDLGui_Utf8ToLatin1(txt, &i); sr.x = sdlgui_fontwidth * (c % 16); sr.y = sdlgui_fontheight * (c / 16); dr.x = x + p * sdlgui_fontwidth; dr.y = y; SDL_BlitSurface(pFontGfx, &sr, pSdlGuiScrn, &dr); p += 1; } } /*-----------------------------------------------------------------------*/ /** * Draw a dialog text object. */ static void SDLGui_DrawText(const SGOBJ *tdlg, int objnum) { int x, y; x = (tdlg[0].x+tdlg[objnum].x)*sdlgui_fontwidth; y = (tdlg[0].y+tdlg[objnum].y)*sdlgui_fontheight; SDLGui_Text(x, y, _(tdlg[objnum].txt)); } /*-----------------------------------------------------------------------*/ /** * Draw a edit field object. */ static void SDLGui_DrawEditField(const SGOBJ *edlg, int objnum) { int x, y; SDL_Rect rect; x = (edlg[0].x+edlg[objnum].x)*sdlgui_fontwidth; y = (edlg[0].y+edlg[objnum].y)*sdlgui_fontheight; SDLGui_Text(x, y, edlg[objnum].txt); rect.x = x; rect.y = y + edlg[objnum].h * sdlgui_fontheight; rect.w = edlg[objnum].w * sdlgui_fontwidth; rect.h = 1; SDL_FillRect(pSdlGuiScrn, &rect, SDL_MapRGB(pSdlGuiScrn->format,160,160,160)); } /*-----------------------------------------------------------------------*/ /** * Draw a dialog box object. */ static void SDLGui_DrawBox(const SGOBJ *bdlg, int objnum) { SDL_Rect rect; int x, y, w, h, offset; Uint32 grey = SDL_MapRGB(pSdlGuiScrn->format,192,192,192); Uint32 upleftc, downrightc; x = bdlg[objnum].x*sdlgui_fontwidth; y = bdlg[objnum].y*sdlgui_fontheight; if (objnum > 0) /* Since the root object is a box, too, */ { /* we have to look for it now here and only */ x += bdlg[0].x*sdlgui_fontwidth; /* add its absolute coordinates if we need to */ y += bdlg[0].y*sdlgui_fontheight; } w = bdlg[objnum].w*sdlgui_fontwidth; h = bdlg[objnum].h*sdlgui_fontheight; if (bdlg[objnum].state & SG_SELECTED) { upleftc = SDL_MapRGB(pSdlGuiScrn->format,128,128,128); downrightc = SDL_MapRGB(pSdlGuiScrn->format,255,255,255); } else { upleftc = SDL_MapRGB(pSdlGuiScrn->format,255,255,255); downrightc = SDL_MapRGB(pSdlGuiScrn->format,128,128,128); } /* The root box should be bigger than the screen, so we disable the offset there: */ if (objnum != 0) offset = 1; else offset = 0; /* Draw background: */ rect.x = x; rect.y = y; rect.w = w; rect.h = h; SDL_FillRect(pSdlGuiScrn, &rect, grey); /* Draw upper border: */ rect.x = x; rect.y = y - offset; rect.w = w; rect.h = 1; SDL_FillRect(pSdlGuiScrn, &rect, upleftc); /* Draw left border: */ rect.x = x - offset; rect.y = y; rect.w = 1; rect.h = h; SDL_FillRect(pSdlGuiScrn, &rect, upleftc); /* Draw bottom border: */ rect.x = x; rect.y = y + h - 1 + offset; rect.w = w; rect.h = 1; SDL_FillRect(pSdlGuiScrn, &rect, downrightc); /* Draw right border: */ rect.x = x + w - 1 + offset; rect.y = y; rect.w = 1; rect.h = h; SDL_FillRect(pSdlGuiScrn, &rect, downrightc); } /*-----------------------------------------------------------------------*/ /** * Draw a normal button. */ void SDLGui_DrawButton(const SGOBJ *bdlg, int objnum) { int x,y; char *txt = _(bdlg[objnum].txt); SDLGui_DrawBox(bdlg, objnum); x = (bdlg[0].x + bdlg[objnum].x) * sdlgui_fontwidth + (bdlg[objnum].w - strlen(txt)) * sdlgui_fontwidth / 2; y = (bdlg[0].y + bdlg[objnum].y + (bdlg[objnum].h-1)/2) * sdlgui_fontheight; if (bdlg[objnum].state & SG_SELECTED) { x+=1; y+=1; } SDLGui_Text(x, y, txt); } /*-----------------------------------------------------------------------*/ /** * Draw a dialog radio button object. */ static void SDLGui_DrawRadioButton(const SGOBJ *rdlg, int objnum) { char str[80]; int x, y; x = (rdlg[0].x + rdlg[objnum].x) * sdlgui_fontwidth; y = (rdlg[0].y + rdlg[objnum].y) * sdlgui_fontheight; if (rdlg[objnum].state & SG_SELECTED) str[0]=SGRADIOBUTTON_SELECTED; else str[0]=SGRADIOBUTTON_NORMAL; str[1]=' '; strcpy(&str[2], _(rdlg[objnum].txt)); SDLGui_Text(x, y, str); } /*-----------------------------------------------------------------------*/ /** * Draw a dialog check box object. */ static void SDLGui_DrawCheckBox(const SGOBJ *cdlg, int objnum) { char str[80]; int x, y; x = (cdlg[0].x + cdlg[objnum].x) * sdlgui_fontwidth; y = (cdlg[0].y + cdlg[objnum].y) * sdlgui_fontheight; if ( cdlg[objnum].state&SG_SELECTED ) str[0]=SGCHECKBOX_SELECTED; else str[0]=SGCHECKBOX_NORMAL; str[1]=' '; strcpy(&str[2], _(cdlg[objnum].txt)); SDLGui_Text(x, y, str); } /*-----------------------------------------------------------------------*/ /** * Draw a scrollbar button. */ static void SDLGui_DrawScrollbar(const SGOBJ *bdlg, int objnum) { SDL_Rect rect; int x, y, w, h; Uint32 grey0 = SDL_MapRGB(pSdlGuiScrn->format,128,128,128); Uint32 grey1 = SDL_MapRGB(pSdlGuiScrn->format,196,196,196); Uint32 grey2 = SDL_MapRGB(pSdlGuiScrn->format, 64, 64, 64); x = bdlg[objnum].x * sdlgui_fontwidth; y = bdlg[objnum].y * sdlgui_fontheight + bdlg[objnum].h; x += bdlg[0].x*sdlgui_fontwidth; /* add mainbox absolute coordinates */ y += bdlg[0].y*sdlgui_fontheight; /* add mainbox absolute coordinates */ w = 1 * sdlgui_fontwidth; h = bdlg[objnum].w; /* Draw background: */ rect.x = x; rect.y = y; rect.w = w; rect.h = h; SDL_FillRect(pSdlGuiScrn, &rect, grey0); /* Draw upper border: */ rect.x = x; rect.y = y; rect.w = w; rect.h = 1; SDL_FillRect(pSdlGuiScrn, &rect, grey1); /* Draw bottom border: */ rect.x = x; rect.y = y + h - 1; rect.w = w; rect.h = 1; SDL_FillRect(pSdlGuiScrn, &rect, grey2); } /*-----------------------------------------------------------------------*/ /** * Draw a dialog popup button object. */ static void SDLGui_DrawPopupButton(const SGOBJ *pdlg, int objnum) { int x, y, w; const char *downstr = "\x02"; SDLGui_DrawBox(pdlg, objnum); x = (pdlg[0].x + pdlg[objnum].x) * sdlgui_fontwidth; y = (pdlg[0].y + pdlg[objnum].y) * sdlgui_fontheight; w = pdlg[objnum].w*sdlgui_fontwidth; //h = pdlg[objnum].h*sdlgui_fontheight; SDLGui_Text(x, y, pdlg[objnum].txt); SDLGui_Text(x+w-sdlgui_fontwidth, y, downstr); } /*-----------------------------------------------------------------------*/ /** * Let the user insert text into an edit field object. * NOTE: The dlg[objnum].txt must point to an an array that is big enough * for dlg[objnum].w characters! */ static void SDLGui_EditField(SGOBJ *dlg, int objnum) { size_t cursorPos; /* Position of the cursor in the edit field */ int blinkState = 0; /* Used for cursor blinking */ int bStopEditing = false; /* true if user wants to exit the edit field */ char *txt; /* Shortcut for dlg[objnum].txt */ SDL_Rect rect; Uint32 grey, cursorCol; SDL_Event event; #if !WITH_SDL2 int nOldUnicodeMode; #endif grey = SDL_MapRGB(pSdlGuiScrn->format, 192, 192, 192); cursorCol = SDL_MapRGB(pSdlGuiScrn->format, 128, 128, 128); rect.x = (dlg[0].x + dlg[objnum].x) * sdlgui_fontwidth; rect.y = (dlg[0].y + dlg[objnum].y) * sdlgui_fontheight; rect.w = (dlg[objnum].w + 1) * sdlgui_fontwidth - 1; rect.h = dlg[objnum].h * sdlgui_fontheight; #if WITH_SDL2 SDL_SetTextInputRect(&rect); SDL_StartTextInput(); #else /* Enable unicode translation to get proper characters with SDL_PollEvent */ nOldUnicodeMode = SDL_EnableUNICODE(true); #endif txt = dlg[objnum].txt; cursorPos = strlen(txt); do { /* Look for events */ if (SDL_PollEvent(&event) == 0) { /* No event: Wait some time for cursor blinking */ SDL_Delay(250); blinkState ^= 1; } else { /* Handle events */ do { switch (event.type) { case SDL_QUIT: /* User wants to quit */ // bQuitProgram = true; bStopEditing = true; break; case SDL_MOUSEBUTTONDOWN: /* Mouse pressed -> stop editing */ bStopEditing = true; break; #if WITH_SDL2 case SDL_TEXTINPUT: if (strlen(txt) < (size_t)dlg[objnum].w) { memmove(&txt[cursorPos+1], &txt[cursorPos], strlen(&txt[cursorPos])+1); txt[cursorPos] = event.text.text[0]; cursorPos += 1; } break; #endif case SDL_KEYDOWN: /* Key pressed */ switch (event.key.keysym.sym) { case SDLK_RETURN: case SDLK_KP_ENTER: bStopEditing = true; break; case SDLK_LEFT: if (cursorPos > 0) cursorPos -= 1; break; case SDLK_RIGHT: if (cursorPos < strlen(txt)) cursorPos += 1; break; case SDLK_BACKSPACE: if (cursorPos > 0) { memmove(&txt[cursorPos-1], &txt[cursorPos], strlen(&txt[cursorPos])+1); cursorPos -= 1; } break; case SDLK_DELETE: if (cursorPos < strlen(txt)) memmove(&txt[cursorPos], &txt[cursorPos+1], strlen(&txt[cursorPos+1])+1); break; default: #if !WITH_SDL2 /* If it is a "good" key then insert it into the text field */ if (event.key.keysym.unicode >= 32 && event.key.keysym.unicode < 128 /* && event.key.keysym.unicode != PATHSEP*/) { if (strlen(txt) < (size_t)dlg[objnum].w) { memmove(&txt[cursorPos+1], &txt[cursorPos], strlen(&txt[cursorPos])+1); txt[cursorPos] = event.key.keysym.unicode; cursorPos += 1; } } #endif break; } break; } } while (SDL_PollEvent(&event)); blinkState = 1; } /* Redraw the text field: */ SDL_FillRect(pSdlGuiScrn, &rect, grey); /* Draw background */ /* Draw the cursor: */ if (blinkState && !bStopEditing) { SDL_Rect cursorrect; cursorrect.x = rect.x + cursorPos * sdlgui_fontwidth; cursorrect.y = rect.y; cursorrect.w = sdlgui_fontwidth; cursorrect.h = rect.h; SDL_FillRect(pSdlGuiScrn, &cursorrect, cursorCol); } SDLGui_Text(rect.x, rect.y, dlg[objnum].txt); /* Draw text */ SDL_UpdateRects(pSdlGuiScrn, 1, &rect); } while (!bStopEditing); #if WITH_SDL2 SDL_StopTextInput(); #else SDL_EnableUNICODE(nOldUnicodeMode); #endif } /** * Draw a user object. */ static void SDLGui_DrawUserObj(const SGOBJ *bdlg, int objnum) { int x, y, w, h; char (*userfun)(int x, int y, int w, int h); x = bdlg[objnum].x*sdlgui_fontwidth; y = bdlg[objnum].y*sdlgui_fontheight; /* add absolute coordinates */ x += bdlg[0].x*sdlgui_fontwidth; y += bdlg[0].y*sdlgui_fontheight; w = bdlg[objnum].w*sdlgui_fontwidth; h = bdlg[objnum].h*sdlgui_fontheight; userfun = (void*)bdlg[objnum].txt; userfun(x, y, w, h); } /*-----------------------------------------------------------------------*/ /** * Draw a whole dialog. */ void SDLGui_DrawDialog(const SGOBJ *dlg) { int i; for (i = 0; dlg[i].type != -1; i++) { switch (dlg[i].type) { case SGBOX: SDLGui_DrawBox(dlg, i); break; case SGTEXT: SDLGui_DrawText(dlg, i); break; case SGEDITFIELD: SDLGui_DrawEditField(dlg, i); break; case SGBUTTON: SDLGui_DrawButton(dlg, i); break; case SGRADIOBUT: SDLGui_DrawRadioButton(dlg, i); break; case SGCHECKBOX: SDLGui_DrawCheckBox(dlg, i); break; case SGPOPUP: SDLGui_DrawPopupButton(dlg, i); break; case SGSCROLLBAR: SDLGui_DrawScrollbar(dlg, i); break; case SGUSER: SDLGui_DrawUserObj(dlg, i); break; } } SDL_UpdateRect(pSdlGuiScrn, 0,0,0,0); } /*-----------------------------------------------------------------------*/ /** * Search an object at a certain position. */ static int SDLGui_FindObj(const SGOBJ *dlg, int fx, int fy) { int len, i; int ob = -1; int xpos, ypos; len = 0; while (dlg[len].type != -1) len++; xpos = fx / sdlgui_fontwidth; ypos = fy / sdlgui_fontheight; /* Now search for the object: */ for (i = len; i >= 0; i--) { /* clicked on a scrollbar ? */ if (dlg[i].type == SGSCROLLBAR) { if (xpos >= dlg[0].x+dlg[i].x && xpos < dlg[0].x+dlg[i].x+1) { ypos = dlg[i].y * sdlgui_fontheight + dlg[i].h + dlg[0].y * sdlgui_fontheight; if (fy >= ypos && fy < ypos + dlg[i].w) { ob = i; break; } } } /* clicked on another object ? */ else if (xpos >= dlg[0].x+dlg[i].x && ypos >= dlg[0].y+dlg[i].y && xpos < dlg[0].x+dlg[i].x+dlg[i].w && ypos < dlg[0].y+dlg[i].y+dlg[i].h) { ob = i; break; } } return ob; } /*-----------------------------------------------------------------------*/ /** * Search a button with a special flag (e.g. SG_DEFAULT or SG_CANCEL). */ static int SDLGui_SearchFlaggedButton(const SGOBJ *dlg, int flag) { int i = 0; while (dlg[i].type != -1) { if (dlg[i].flags & flag) return i; i++; } return 0; } /*-----------------------------------------------------------------------*/ /** * Show and process a dialog. Returns the button number that has been * pressed or SDLGUI_UNKNOWNEVENT if an unsupported event occured (will be * stored in parameter pEventOut). */ int SDLGui_DoDialog(SGOBJ *dlg, SDL_Event *pEventOut) { int obj=0; int oldbutton=0; int retbutton=0; int i, j, b; SDL_Event sdlEvent; SDL_Rect rct; Uint32 grey; SDL_Surface *pBgSurface; SDL_Rect dlgrect, bgrect; if (pSdlGuiScrn->h / sdlgui_fontheight < dlg[0].h) { fprintf(stderr, "Screen size too small for dialog!\n"); return SDLGUI_ERROR; } grey = SDL_MapRGB(pSdlGuiScrn->format,192,192,192); dlgrect.x = dlg[0].x * sdlgui_fontwidth; dlgrect.y = dlg[0].y * sdlgui_fontheight; dlgrect.w = dlg[0].w * sdlgui_fontwidth; dlgrect.h = dlg[0].h * sdlgui_fontheight; bgrect.x = bgrect.y = 0; bgrect.w = dlgrect.w; bgrect.h = dlgrect.h; /* Save background */ pBgSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, dlgrect.w, dlgrect.h, pSdlGuiScrn->format->BitsPerPixel, pSdlGuiScrn->format->Rmask, pSdlGuiScrn->format->Gmask, pSdlGuiScrn->format->Bmask, pSdlGuiScrn->format->Amask); if (pSdlGuiScrn->format->palette != NULL) { SDL_SetColors(pBgSurface, pSdlGuiScrn->format->palette->colors, 0, pSdlGuiScrn->format->palette->ncolors-1); } if (pBgSurface != NULL) { SDL_BlitSurface(pSdlGuiScrn, &dlgrect, pBgSurface, &bgrect); } else { fprintf(stderr, "SDLGUI_DoDialog: CreateRGBSurface failed: %s\n", SDL_GetError()); } /* (Re-)draw the dialog */ SDLGui_DrawDialog(dlg); /* Is the left mouse button still pressed? Yes -> Handle TOUCHEXIT objects here */ SDL_PumpEvents(); b = SDL_GetMouseState(&i, &j); /* If current object is the scrollbar, and mouse is still down, we can scroll it */ /* also if the mouse pointer has left the scrollbar */ if (dlg[current_object].type == SGSCROLLBAR) { if (b & SDL_BUTTON(1)) { obj = current_object; dlg[obj].state |= SG_MOUSEDOWN; oldbutton = obj; retbutton = obj; } else { obj = current_object; current_object = 0; dlg[obj].state &= SG_MOUSEUP; retbutton = obj; oldbutton = obj; } } else { obj = SDLGui_FindObj(dlg, i, j); current_object = obj; if (obj > 0 && (dlg[obj].flags&SG_TOUCHEXIT) ) { oldbutton = obj; if (b & SDL_BUTTON(1)) { dlg[obj].state |= SG_SELECTED; retbutton = obj; } } } /* The main loop */ while (retbutton == 0 /*&& !bQuitProgram*/) { if (SDL_WaitEvent(&sdlEvent) == 1) /* Wait for events */ switch (sdlEvent.type) { case SDL_QUIT: retbutton = SDLGUI_QUIT; break; case SDL_MOUSEBUTTONDOWN: if (sdlEvent.button.button != SDL_BUTTON_LEFT) { /* Not left mouse button -> unsupported event */ if (pEventOut) retbutton = SDLGUI_UNKNOWNEVENT; break; } /* It was the left button: Find the object under the mouse cursor */ obj = SDLGui_FindObj(dlg, sdlEvent.button.x, sdlEvent.button.y); if (obj>0) { if (dlg[obj].type==SGBUTTON) { dlg[obj].state |= SG_SELECTED; SDLGui_DrawButton(dlg, obj); SDL_UpdateRect(pSdlGuiScrn, (dlg[0].x+dlg[obj].x)*sdlgui_fontwidth-2, (dlg[0].y+dlg[obj].y)*sdlgui_fontheight-2, dlg[obj].w*sdlgui_fontwidth+4, dlg[obj].h*sdlgui_fontheight+4); oldbutton=obj; } if (dlg[obj].type==SGSCROLLBAR) { dlg[obj].state |= SG_MOUSEDOWN; oldbutton=obj; } if ( dlg[obj].flags&SG_TOUCHEXIT ) { dlg[obj].state |= SG_SELECTED; retbutton = obj; } } break; case SDL_MOUSEBUTTONUP: if (sdlEvent.button.button != SDL_BUTTON_LEFT) { /* Not left mouse button -> unsupported event */ if (pEventOut) retbutton = SDLGUI_UNKNOWNEVENT; break; } /* It was the left button: Find the object under the mouse cursor */ obj = SDLGui_FindObj(dlg, sdlEvent.button.x, sdlEvent.button.y); if (obj>0) { switch (dlg[obj].type) { case SGBUTTON: if (oldbutton==obj) retbutton=obj; break; case SGSCROLLBAR: dlg[obj].state &= SG_MOUSEUP; if (oldbutton==obj) retbutton=obj; break; case SGEDITFIELD: SDLGui_EditField(dlg, obj); break; case SGRADIOBUT: for (i = obj-1; i > 0 && dlg[i].type == SGRADIOBUT; i--) { dlg[i].state &= ~SG_SELECTED; /* Deselect all radio buttons in this group */ rct.x = (dlg[0].x+dlg[i].x)*sdlgui_fontwidth; rct.y = (dlg[0].y+dlg[i].y)*sdlgui_fontheight; rct.w = sdlgui_fontwidth; rct.h = sdlgui_fontheight; SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */ SDLGui_DrawRadioButton(dlg, i); SDL_UpdateRects(pSdlGuiScrn, 1, &rct); } for (i = obj+1; dlg[i].type == SGRADIOBUT; i++) { dlg[i].state &= ~SG_SELECTED; /* Deselect all radio buttons in this group */ rct.x = (dlg[0].x+dlg[i].x)*sdlgui_fontwidth; rct.y = (dlg[0].y+dlg[i].y)*sdlgui_fontheight; rct.w = sdlgui_fontwidth; rct.h = sdlgui_fontheight; SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */ SDLGui_DrawRadioButton(dlg, i); SDL_UpdateRects(pSdlGuiScrn, 1, &rct); } dlg[obj].state |= SG_SELECTED; /* Select this radio button */ rct.x = (dlg[0].x+dlg[obj].x)*sdlgui_fontwidth; rct.y = (dlg[0].y+dlg[obj].y)*sdlgui_fontheight; rct.w = sdlgui_fontwidth; rct.h = sdlgui_fontheight; SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */ SDLGui_DrawRadioButton(dlg, obj); SDL_UpdateRects(pSdlGuiScrn, 1, &rct); break; case SGCHECKBOX: dlg[obj].state ^= SG_SELECTED; rct.x = (dlg[0].x+dlg[obj].x)*sdlgui_fontwidth; rct.y = (dlg[0].y+dlg[obj].y)*sdlgui_fontheight; rct.w = sdlgui_fontwidth; rct.h = sdlgui_fontheight; SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */ SDLGui_DrawCheckBox(dlg, obj); SDL_UpdateRects(pSdlGuiScrn, 1, &rct); break; case SGPOPUP: dlg[obj].state |= SG_SELECTED; SDLGui_DrawPopupButton(dlg, obj); SDL_UpdateRect(pSdlGuiScrn, (dlg[0].x+dlg[obj].x)*sdlgui_fontwidth-2, (dlg[0].y+dlg[obj].y)*sdlgui_fontheight-2, dlg[obj].w*sdlgui_fontwidth+4, dlg[obj].h*sdlgui_fontheight+4); retbutton=obj; break; } } if (oldbutton > 0 && dlg[oldbutton].type == SGBUTTON) { dlg[oldbutton].state &= ~SG_SELECTED; SDLGui_DrawButton(dlg, oldbutton); SDL_UpdateRect(pSdlGuiScrn, (dlg[0].x+dlg[oldbutton].x)*sdlgui_fontwidth-2, (dlg[0].y+dlg[oldbutton].y)*sdlgui_fontheight-2, dlg[oldbutton].w*sdlgui_fontwidth+4, dlg[oldbutton].h*sdlgui_fontheight+4); oldbutton = 0; } if (obj >= 0 && (dlg[obj].flags&SG_EXIT)) { retbutton = obj; } break; case SDL_JOYAXISMOTION: case SDL_JOYBALLMOTION: case SDL_JOYHATMOTION: case SDL_MOUSEMOTION: break; case SDL_KEYDOWN: /* Key pressed */ if (sdlEvent.key.keysym.sym == SDLK_RETURN || sdlEvent.key.keysym.sym == SDLK_KP_ENTER) { retbutton = SDLGui_SearchFlaggedButton(dlg, SG_DEFAULT); } else if (sdlEvent.key.keysym.sym == SDLK_ESCAPE) { retbutton = SDLGui_SearchFlaggedButton(dlg, SG_CANCEL); } else if (pEventOut) { retbutton = SDLGUI_UNKNOWNEVENT; } break; default: if (pEventOut) retbutton = SDLGUI_UNKNOWNEVENT; break; } } /* Restore background */ if (pBgSurface) { SDL_BlitSurface(pBgSurface, &bgrect, pSdlGuiScrn, &dlgrect); SDL_FreeSurface(pBgSurface); } /* Copy event data of unsupported events if caller wants to have it */ if (retbutton == SDLGUI_UNKNOWNEVENT && pEventOut) memcpy(pEventOut, &sdlEvent, sizeof(SDL_Event)); //if (retbutton == SDLGUI_QUIT) // bQuitProgram = true; bt = 0; // FIXME: Hack return retbutton; } ballerburg-1.2.0/src/dlgAlert.c0000644000175000017500000001323512506012141015670 0ustar thomasthomas/* * dlgAlert.c - AES-like AlertBox * * Copyright (c) 2004 Petr Stehlik * Copyright (c) 2004, 2010 Thomas Huth * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This file is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * (http://www.gnu.org/licenses/) for more details. */ const char DlgAlert_fileid[] = "dlgAlert.c : " __DATE__ " " __TIME__; #include #include #include #include "sdlgui.h" #include "screen.h" #define MAX_LINES 4 static char dlglines[MAX_LINES][50+1]; #define DLGALERT_OK 5 #define DLGALERT_CANCEL 6 /* The "Alert"-dialog: */ static SGOBJ alertdlg[] = { { SGBOX, 0, 0, 0,0, 52,8, NULL }, { SGTEXT, 0, 0, 1,1, 50,1, dlglines[0] }, { SGTEXT, 0, 0, 1,2, 50,1, dlglines[1] }, { SGTEXT, 0, 0, 1,3, 50,1, dlglines[2] }, { SGTEXT, 0, 0, 1,4, 50,1, dlglines[3] }, { SGBUTTON, SG_DEFAULT, 0, 5,6, 8,1, "OK" }, { SGBUTTON, SG_CANCEL, 0, 24,6, 8,1, "Cancel" }, { -1, 0, 0, 0,0, 0,0, NULL } }; /*-----------------------------------------------------------------------*/ /** * Breaks long string to several strings of max_width, divided by '\0', * sets text_width to the longest line width and returns the number of lines * you need to display the strings. */ static int DlgAlert_FormatTextToBox(char *text, int max_width, int *text_width) { int columns = 0; int lines = 1; int txtlen; char *p; /* pointer to begin of actual line */ char *q; /* pointer to start of next search */ char *llb; /* pointer to last place suitable for breaking the line */ char *txtend; /* pointer to end of the text */ txtlen = strlen(text); q = p = text; llb = text-1; /* pointer to last line break */ txtend = text + txtlen; if (txtlen <= max_width && strchr(text, '\n') == NULL) { *text_width = txtlen; return lines; } while(q < txtend) /* q was last place suitable for breaking */ { char *r = strpbrk(q, " \t/\\\n"); /* find next suitable place for the break */ if (r == NULL) r = txtend; /* if there's no place then point to the end */ if ((r-p) <= max_width && *r != '\n') /* '\n' is always used for breaking */ { llb = r; /* remember new place suitable for breaking */ q++; if ((r-p) > columns) columns = r - p; continue; /* search again */ } if ((r-p) > max_width) /* too long line already? */ { if (p > llb) /* bad luck - no place for the delimiter. Let's do it the strong way */ llb = p + max_width; /* we loose one character */ } else llb = r; /* break from previous delimiter */ *llb = '\0'; /* BREAK */ if ((llb-p) > columns) columns = llb - p; /* longest line so far */ p = q = llb + 1; /* next line begins here */ lines++; /* increment line counter */ } *text_width = columns; return lines; /* return line counter */ } /*-----------------------------------------------------------------------*/ /** * Show the "alert" dialog. Return true if user pressed "OK". */ static int DlgAlert_ShowDlg(const char *text) { static int maxlen = sizeof(dlglines[0])-1; char *t = (char *)malloc(strlen(text)+1); char *orig_t = t; int lines, i, len, offset; bool bOldMouseVisibility; int nOldMouseX, nOldMouseY; strcpy(t, text); lines = DlgAlert_FormatTextToBox(t, maxlen, &len); offset = (maxlen-len)/2; for(i=0; i. */ #include #include #include #include #include "i18n.h" #include "baller1.h" #include "baller2.h" #include "ballergui.h" #include "screen.h" #include "sdlgui.h" #include "market.h" static char dlg_geld[6]; static char dlg_geschuetze[6]; static char dlg_pulver[6]; static char dlg_volk[6]; static char dlg_ftuerme[6]; static char dlg_fahne[6]; static char dlg_kugeln[6]; static char dlg_steuern[6]; static char dlg_anbauenpreis[6]; static char dlg_fturmpreis[6]; static char dlg_geschuetzpreis[6]; static char dlg_fahnepreis[6]; static char dlg_pulverpreis[6]; static char dlg_kugelpreis[6]; #define SH1 11 /* Geld */ #define SH2 12 /* Frdertrme */ #define SH3 13 /* Geschtze */ #define SH4 14 /* Windfahne */ #define SH5 15 /* Pulver */ #define SH6 16 /* Kugeln */ #define SH7 17 /* Volk */ #define SH8 18 /* Steuern */ #define SHK 19 /* Steuern runter */ #define SHG 20 /* Steuern rauf */ #define SM1 29 /* Preis fr Anbauen */ #define SM2 30 /* Preis fr Frderturm */ #define SM3 31 /* Preis fr Geschtz */ #define SM4 32 /* Preis fr Windfahne */ #define SM5 33 /* Preis fr Pulver */ #define SM6 34 /* Preis fr Kugeln */ #define FERTIG 35 static SGOBJ marktdlg[] = { { SGBOX, 0, 0, 0,0, 54,18, NULL }, { SGBOX, 0, 0, 1,1, 52,7, NULL }, { SGTEXT, 0, 0, 23,1, 8,1, N_("You have:") }, { SGTEXT, 0, 0, 2,3, 10,1, N_("Funds:") }, { SGTEXT, 0, 0, 28,3, 12,1, N_("Shaft towers:") }, { SGTEXT, 0, 0, 2,4, 10,1, N_("Cannons:") }, { SGTEXT, 0, 0, 28,4, 12,1, N_("Weather vane:") }, { SGTEXT, 0, 0, 2,5, 10,1, N_("Gunpowder:") }, { SGTEXT, 0, 0, 28,5, 12,1, N_("Cannonballs:") }, { SGTEXT, 0, 0, 2,6, 10,1, N_("Population:") }, { SGTEXT, 0, 0, 28,6, 12,1, N_("Taxes in %") }, { SGTEXT, 0, 0, 19,3, 5,1, dlg_geld }, { SGTEXT, 0, 0, 47,3, 5,1, dlg_ftuerme }, { SGTEXT, 0, 0, 19,4, 5,1, dlg_geschuetze }, { SGTEXT, 0, 0, 47,4, 5,1, dlg_fahne }, { SGTEXT, 0, 0, 19,5, 5,1, dlg_pulver }, { SGTEXT, 0, 0, 47,5, 5,1, dlg_kugeln }, { SGTEXT, 0, 0, 19,6, 5,1, dlg_volk }, { SGTEXT, 0, 0, 45,6, 5,1, dlg_steuern }, { SGBUTTON, SG_EXIT, 0, 46,6, 1,1, SGARROWLEFTSTR }, { SGBUTTON, SG_EXIT, 0, 51,6, 1,1, SGARROWRIGHTSTR }, { SGBOX, 0, 0, 1,9, 52,6, NULL }, { SGTEXT, 0, 0, 23,9, 8,1, N_("Market:") }, { SGTEXT, 0, 0, 2,11, 10,1, N_("Lay bricks:") }, { SGTEXT, 0, 0, 28,11, 12,1, N_("Shaft tower:") }, { SGTEXT, 0, 0, 2,12, 10,1, N_("Cannon:") }, { SGTEXT, 0, 0, 28,12, 12,1, N_("Weather vane:") }, { SGTEXT, 0, 0, 2,13, 10,1, N_("Powder x30:") }, { SGTEXT, 0, 0, 28,13, 12,1, N_("2 cannonballs:") }, { SGTEXT, 0, 0, 19,11, 5,1, dlg_anbauenpreis }, { SGTEXT, 0, 0, 47,11, 5,1, dlg_fturmpreis }, { SGTEXT, 0, 0, 19,12, 5,1, dlg_geschuetzpreis }, { SGTEXT, 0, 0, 47,12, 5,1, dlg_fahnepreis }, { SGTEXT, 0, 0, 19,13, 5,1, dlg_pulverpreis }, { SGTEXT, 0, 0, 47,13, 5,1, dlg_kugelpreis }, { SGBUTTON, SG_DEFAULT, 0, 21,16, 12,1, N_("Done") }, { -1, 0, 0, 0,0, 0,0, NULL } }; /** * Anbauen */ static void anbau(void) { short s; char brickstr[80]; void *savearea; /* Save background */ savearea = scr_save_bg(220, 375-12, 25*8, 38); color(1); scr_sf_interior(2); scr_sf_style(9); scr_ctr_text(320, 365, _(" Lay bricks: ")); sprintf(brickstr, _(" Bricks left: %02d "), 20); scr_ctr_text(320, 382, brickstr); s=20; scr_color(0x909080); do { if (event(1, 0)) { scr_exit(); exit(0); } if ( bt && (n? mx>624-bg[0] : mx155 ) { if ( !( loc(mx,my) || loc(mx+1,my+1) || loc(mx-1,my-1) ) && ( loc(mx+3,my-1)||loc(mx+3,my+1)||loc(mx-3,my-1)||loc(mx-3,my+1)|| loc(mx+1,my+2)||loc(mx-1,my+2)||loc(mx+1,my-2)||loc(mx-1,my-2) )) { xy[0]=mx-2; xy[1]=my-1; xy[2]=mx+2; xy[3]=my+1; scr_bar(xy); s--; sprintf(brickstr, _(" Bricks left: %02d "), s); scr_ctr_text(320, 382, brickstr); } } } while ( s>0 && bt<2 ); /* Restore background */ scr_restore_bg(savearea); } /** * 5-stellige Zahl, rechtsbndig, ohne fhrende Nullen */ static void zahl(short nr, short wert) { short i,a,b; char *adr; adr = marktdlg[nr].txt; for (b = i = 0, a = 10000; i < 5; i++, a /= 10) { *adr++ = 48 + wert/a - 16*(wert -1); } for (ko = k = 0; k < 10; ) { /* Kanonen zhlen */ ko += (ka[n][k++].x > -1); } for (k = 0; k < 10; k++) { if (bg[1+k*2] > -1 && ka[n][k].x == -1) { /* Platz fr neue Kanone? */ for (a = 1; a < 10; a++) { if (loc(639*n+(bg[1+k*2]+5+a)*f, by[n]-bg[2+k*2]-a)) break; } if (a > 9) break; } } zahl(SH1, ge[n]); zahl(SH2, t); zahl(SH3, ko); zahl(SH4, wx[n]>-1); zahl(SH5, pu[n]); zahl(SH6, ku[n]); zahl(SH7, vo[n]); zahl(SH8, st[n]); for (a = 0; a < 6; a++) { // fprintf(stderr,"a=%i: ge=%i p=%i an_erl=%i bg=%i t=%i k=%i wx=%i\n", // a, ge[n], p[a], an_erl, bg[0], t, k, wx[n]); if (ge[n] < p[a] || (!an_erl && a == 0) || (a == 1 && (bg[0]+t*30 > 265 || t > 4)) || (a == 2 && k > 9) || (a == 3 && wx[n] > -1)) { marktdlg[SM1 + a].type = SGTEXT; } else { marktdlg[SM1 + a].type = SGBUTTON; } } a = SDLGui_DoDialog(marktdlg, NULL); if (a == SHK) { st[n]-=2*(st[n]>0); } else if (a == SHG) { st[n]+=2*(st[n]<100); } else if (a != FERTIG && a >= SM1 && a <= SM6) { ge[n] -= p[a-SM1]; if (a < SM5) { drw_all(); if (a == SM1) anbau(); else if (a == SM2) fturm(); else if (a == SM3) init_ka( k,639*n ); else if (a == SM4) { wx[n]=639*n+f*bg[23]; wy[n]=by[n]-bg[24]; werdran(1); } } else { pu[n]+=30*(a==SM5); ku[n]+=2*(a==SM6); drw_gpk(a-SM4); drw_gpk(0); } } } while (a != FERTIG); SDL_UpdateRect(surf, 0,0, 0,0); } ballerburg-1.2.0/src/screen.c0000664000175000017500000002660612506012141015421 0ustar thomasthomas/* screen.c - Screen functions for Ballerburg Copyright (C) 2010, 2014 Thomas Huth This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include "i18n.h" #include "screen.h" #include "sdlgui.h" #include "sdlgfx.h" #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) #if WITH_SDL2 static SDL_Window *sdlWindow; #define USE_SDL2_RENDERER 0 #if USE_SDL2_RENDERER static SDL_Renderer *sdlRenderer; static SDL_Texture *sdlTexture; #else static SDL_Surface *windowSurf; #endif #endif SDL_Surface *surf; static Uint32 the_color, fill_color; static Uint32 bg_color; static int fill_style, fill_interior; static SGOBJ donebuttondlg[] = { { SGBOX, 0, 0, 36,29, 8,1, NULL }, { SGBUTTON, SG_EXIT, 0, 0,0, 8,1, N_("Done") } }; #if WITH_SDL2 static int fullscreenflag = 0; static void scr_sdl2_init(void) { sdlWindow = SDL_CreateWindow("Ballerburg SDL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, fullscreenflag); #if USE_SDL2_RENDERER sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, 0); if (!sdlWindow || !sdlRenderer) { fprintf(stderr,"Failed to create window or renderer!\n"); exit(-1); } SDL_RenderSetLogicalSize(sdlRenderer, 640, 480); sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, 640, 480); #else windowSurf = SDL_GetWindowSurface(sdlWindow); #endif } #endif void scr_init(void) { if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "Could not initialize the SDL library:\n %s\n", SDL_GetError() ); exit(-1); } #if WITH_SDL2 scr_sdl2_init(); surf = SDL_CreateRGBSurface(SDL_SWSURFACE, 640, 480, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0); #else surf = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE); SDL_WM_SetCaption("Ballerburg SDL", "Ballerburg"); #endif if (!surf) { fprintf(stderr, "Could not initialize the SDL library:\n %s\n", SDL_GetError() ); exit(-1); } bg_color = SDL_MapRGB(surf->format,0xe0,0xf0,0xff); SDLGui_Init(); SDLGui_SetScreen(surf); } void scr_exit(void) { SDLGui_UnInit(); #if WITH_SDL2 if (surf) SDL_FreeSurface(surf); #if USE_SDL2_RENDERER if (sdlTexture) SDL_DestroyTexture(sdlTexture); if (sdlRenderer) SDL_DestroyRenderer(sdlRenderer); #endif if (sdlWindow) SDL_DestroyWindow(sdlWindow); #endif SDL_Quit(); } void scr_togglefullscreen(void) { #if WITH_SDL2 #if USER_SDL2_RENDERER SDL_DestroyTexture(sdlTexture); SDL_DestroyRenderer(sdlRenderer); fullscreenflag ^= SDL_WINDOW_FULLSCREEN_DESKTOP; #else fullscreenflag ^= SDL_WINDOW_FULLSCREEN; #endif SDL_DestroyWindow(sdlWindow); scr_sdl2_init(); SDL_UpdateRect(surf, 0, 0, 640, 480); #else SDL_WM_ToggleFullScreen(surf); #endif } void scr_clear(void) { SDL_Rect rect; Uint32 white; int i; white = SDL_MapRGB(surf->format,0xff,0xff,0xff); rect.x = 0; rect.y = 0; rect.w = 640; rect.h = 400; SDL_FillRect(surf, &rect, bg_color); for (i = 0; i < 80; i += 1) { rect.x = 0; rect.y = 479-i; rect.w = 640; rect.h = 1; SDL_FillRect(surf, &rect, SDL_MapRGB(surf->format,8+i/2,32+i,8+i/2)); } /* Left vane box: */ rect.x = 5; rect.y = 410; rect.w = 104; rect.h = 48+16; for (i = 1; i < 5; i++) { rectangleRGBA(surf, rect.x-i, rect.y-i, rect.x+rect.w-1+i, rect.y+rect.h-1+i, 0xf0, 0xff, 0xf0, 0xff-i*0x3c); } SDL_FillRect(surf, &rect, white); /* Right vane box: */ rect.x = 5+(629-104); rect.y = 410; rect.w = 104; rect.h = 48+16; for (i = 1; i < 5; i++) { rectangleRGBA(surf, rect.x-i, rect.y-i, rect.x+rect.w-1+i, rect.y+rect.h-1+i, 0xf0, 0xff, 0xf0, 0xff-i*0x3c); } SDL_FillRect(surf, &rect, white); } void scr_l_text(int x, int y, const char *text) { SDL_Rect rect; // printf("v_gtext: %s\n", text); y -= 12; rect.x = x; rect.y = y; rect.w = strlen(text) * sdlgui_fontwidth; rect.h = sdlgui_fontheight; SDL_FillRect(surf, &rect, SDL_MapRGB(surf->format,0xff,0xff,0xff)); SDLGui_Text(x, y, text); SDL_UpdateRects(surf, 1, &rect); } /** * Draw centered text */ void scr_ctr_text(int cx, int y, const char *text) { SDL_Rect rect; rect.w = strlen(text) * sdlgui_fontwidth; rect.h = sdlgui_fontheight; rect.x = cx - rect.w / 2; rect.y = y; SDL_FillRect(surf, &rect, SDL_MapRGB(surf->format,0xff,0xff,0xff)); SDLGui_Text(rect.x, rect.y, text); SDL_UpdateRects(surf, 1, &rect); } void scr_circle(int x, int y, int w) { SDL_Rect rect; filledCircleColor(surf, x, y, w, the_color); rect.x = max(x-w, 0); rect.y = max(y-w, 0); rect.w = min(2*w, 640-x+w); rect.h = min(2*w, 480-y+w); SDL_UpdateRects(surf, 1, &rect); } static void update_fill_color(void) { if (fill_interior == 0) { fill_color = 0xffffffff; } else if (fill_interior == 1) { fill_color = 0x000000ff; } else if (fill_interior == 2) { switch (fill_style) { case 1: fill_color = 0xc0b0a0ff; break; // Table color case 2: fill_color = 0x602060ff; break; // King color case 9: fill_color = 0x909080ff; break; // Wall color case 11: fill_color = 0xc04020ff; break; // Roof color } } else { puts("unknown fill interior"); } } void scr_sf_style(short val) { fill_style = val; update_fill_color(); } void scr_sf_interior(short val) { fill_interior = val; update_fill_color(); } void scr_bar(short *xy) { SDL_Rect rect; Uint8 r, g, b; r = fill_color >> 24; g = fill_color >> 16; b = fill_color >> 8; rect.x = xy[0]; rect.y = xy[1]; rect.w = xy[2]-xy[0]+1; rect.h = xy[3]-xy[1]+1; SDL_FillRect(surf, &rect, SDL_MapRGB(surf->format,r,g,b)); rectangleColor(surf, xy[0], xy[1], xy[2], xy[3], the_color); SDL_UpdateRects(surf, 1, &rect); } void clr(short x, short y, short w, short h) { SDL_Rect rect; rect.x = x; rect.y = y; rect.w = w; rect.h = h; SDL_FillRect(surf, &rect, SDL_MapRGB(surf->format,0xff,0xff,0xff)); SDL_UpdateRect(surf, x,y, w,h); } void clr_bg(short x, short y, short w, short h) { SDL_Rect rect; rect.x = x; rect.y = y; rect.w = w; rect.h = h; SDL_FillRect(surf, &rect, bg_color); SDL_UpdateRect(surf, x,y, w,h); } void scr_fillarea(short num, short *xy) { int i; Sint16 vx[512], vy[512]; //printf("v_fillarea %i\n", num); if (num > 512) { puts("v_fillarea overlow"); exit(-2); } for (i = 0; i < num; i++) { vx[i] = xy[i*2]; vy[i] = xy[i*2+1]; } filledPolygonColor(surf, vx, vy, num, fill_color); SDL_UpdateRect(surf, 0,0, 640,480); } void scr_pline(short num, short *xy) { int i; int maxx, maxy; int minx, miny; minx = 639; miny = 399; maxx = 0; maxy = 0; // printf("v_pline %i\n", num); for (i = 0; i < num-1; i++) { if (xy[i*2] < 0 || xy[i*2] > 639 || xy[i*2+1] < 0 || xy[i*2+1] > 479) { printf("bad coordinates!\n"); return; } if (xy[i*2] > maxx) maxx = xy[i*2]; if (xy[i*2+1] > maxy) maxy = xy[i*2+1]; if (xy[i*2] < minx) minx = xy[i*2]; if (xy[i*2+1] < miny) miny = xy[i*2+1]; lineColor(surf, xy[i*2], xy[i*2+1], xy[i*2+2], xy[i*2+3], the_color|0x1000); } if (xy[i*2] > maxx) maxx = xy[i*2]; if (xy[i*2+1] > maxy) maxy = xy[i*2+1]; if (xy[i*2] < minx) minx = xy[i*2]; if (xy[i*2+1] < miny) miny = xy[i*2+1]; //printf("blit %i %i %i %i\n", minx,miny, maxx-minx+1,maxy-miny+1); SDL_UpdateRect(surf, minx,miny, maxx-minx+1,maxy-miny+1); } void scr_line(int x1, int y1, int x2, int y2, int rgb) { lineColor(surf, x1, y1, x2, y2, (rgb<<8)|0xff); } int scr_getpixel(int x, int y) { Uint32 *p = surf->pixels; Uint32 c; SDL_PixelFormat *fmt = surf->format; c = p[y*640+x]; c = ((((c & fmt->Rmask) >> fmt->Rshift) << fmt->Rloss) << 16) | ((((c & fmt->Gmask) >> fmt->Gshift) << fmt->Gloss) << 8) | (((c & fmt->Bmask) >> fmt->Bshift) << fmt->Bloss); return c; } void scr_color(int c) { the_color = (c << 8) | 0xff; } void scr_fillcolor(int c) { fill_color = (c << 8) | 0xff; } /** * Select foreground (1) or background (0) color */ void color(int c) { if (c) the_color = 0x000000ff; else the_color = (bg_color<<8) | 0x0ff; } void scr_init_done_button(int *bx, int *by, int *bw, int *bh) { int fontw, fonth; /* Calculate the "Done" button coordinates */ SDLGui_GetFontSize(&fontw, &fonth); *bx = donebuttondlg[0].x * fontw; *by = donebuttondlg[0].y * fonth; *bw = donebuttondlg[0].w * fontw; *bh = donebuttondlg[0].h * fonth; } void scr_draw_done_button(int selected) { if (selected) donebuttondlg[1].state |= SG_SELECTED; else donebuttondlg[1].state &= ~SG_SELECTED; SDLGui_DrawButton(donebuttondlg, 1); SDL_UpdateRect(surf, 0,0, 0,0); } /** * Draws a fast cannonball */ void scr_cannonball(int x, int y) { lineColor(surf, x-1,y-2, x+1,y-2, the_color); lineColor(surf, x-2,y-1, x+2,y-1, the_color); lineColor(surf, x-2,y , x+2,y , the_color); lineColor(surf, x-2,y+1, x+2,y+1, the_color); lineColor(surf, x-1,y+2, x+1,y+2, the_color); } /** * Stores information about saved background area */ struct savebg { SDL_Rect rect; SDL_Rect bgrect; SDL_Surface *bgsurf; }; /** * Save a part of the background of the screen */ void *scr_save_bg(int x, int y, int w, int h) { struct savebg *s; s = malloc(sizeof(struct savebg)); if (!s) return NULL; s->rect.x = x; s->rect.y = y; s->rect.w = w; s->rect.h = h; s->bgrect.x = s->bgrect.y = 0; s->bgrect.w = s->rect.w; s->bgrect.h = s->rect.h; s->bgsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, surf->format->BitsPerPixel, surf->format->Rmask, surf->format->Gmask, surf->format->Bmask, surf->format->Amask); if (s->bgsurf != NULL) { /* Save background */ SDL_BlitSurface(surf, &s->rect, s->bgsurf, &s->bgrect); } else { fprintf(stderr, "scr_save_bg: CreateRGBSurface failed: %s\n", SDL_GetError()); } return s; } /** * Restore part of the background */ void scr_restore_bg(void *ps) { struct savebg *s = ps; /* Restore background */ if (s != NULL && s->bgsurf != NULL) { SDL_BlitSurface(s->bgsurf, &s->bgrect, surf, &s->rect); SDL_FreeSurface(s->bgsurf); } SDL_UpdateRects(surf, 1, &s->rect); free(ps); } #if WITH_SDL2 void SDL_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects) { #if USE_SDL2_RENDERER SDL_UpdateTexture(sdlTexture, NULL, screen->pixels, screen->pitch); SDL_RenderClear(sdlRenderer); SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL); SDL_RenderPresent(sdlRenderer); #else SDL_BlitSurface(surf, rects, windowSurf, rects); SDL_UpdateWindowSurfaceRects(sdlWindow, rects, numrects); #endif } void SDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Sint32 w, Sint32 h) { SDL_Rect rect; if (w == 0 && h == 0) { w = 640; h = 480; } rect.x = x; rect.y = y; rect.w = w; rect.h = h; SDL_UpdateRects(screen, 1, &rect); } #endif void scr_update(int x, int y, int w, int h) { if (x >= 640 || y >= 480) return; if (x < 0) x = 0; if (y < 0) y = 0; if (x + w > 640) w = 640 - x; if (y + h > 480) h = 480 - y; SDL_UpdateRect(surf, x, y, w, h); } ballerburg-1.2.0/src/cannoneer.c0000664000175000017500000001076212506012141016106 0ustar thomasthomas/* cannoneer.c Copyright (C) 1987, 1989 Eckhard Kruse Copyright (C) 2010 Thomas Huth This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include "i18n.h" #include "ballergui.h" #include "baller1.h" #include "sdlgui.h" #include "screen.h" #include "sdlgfx.h" static void draw_cannoneer(int x, int y, int w, int h); static short wi, pv; /* Winkel und Pulver */ /* The cannoneer dialog data: */ #define WL2 3 /* Winkel um 10 verkleinern */ #define WL1 4 /* Winkel um 1 verkleinern */ #define WR1 6 #define WR2 7 #define PL2 9 #define PL1 10 #define PR1 12 #define PR2 13 #define SOK 14 #define SAB 15 // #define WINK TBD // #define PULV TBD static char dlg_winkel[4]; static char dlg_pulver[3]; static SGOBJ cannoneerdlg[] = { { SGBOX, 0, 0, 0,0, 42,15, NULL }, { SGTEXT, 0, 0, 18,1, 6,1, N_("Cannon") }, { SGTEXT, 0, 0, 2,3, 7,1, N_("Angle:") }, { SGBUTTON, SG_EXIT, 0, 12,3, 4,1, "\x04\04" }, // 2 arrows left { SGBUTTON, SG_EXIT, 0, 17,3, 3,1, "\x04" }, // Arrow left { SGTEXT, 0, 0, 22,3, 4,1, dlg_winkel }, { SGBUTTON, SG_EXIT, 0, 26,3, 3,1, "\x03" }, // Arrow right { SGBUTTON, SG_EXIT, 0, 30,3, 4,1, "\x03\x03" }, // 2 arrows right { SGTEXT, 0, 0, 2,5, 7,1, N_("Gunpowder:") }, { SGBUTTON, SG_EXIT, 0, 12,5, 4,1, "\x04\04" }, // 2 arrows left { SGBUTTON, SG_EXIT, 0, 17,5, 3,1, "\x04" }, // Arrow left { SGTEXT, 0, 0, 22,5, 4,1, dlg_pulver }, { SGBUTTON, SG_EXIT, 0, 26,5, 3,1, "\x03" }, // Arrow right { SGBUTTON, SG_EXIT, 0, 30,5, 4,1, "\x03\x03" }, // 2 arrows right { SGBUTTON, SG_DEFAULT, 0, 33,11, 8,1, "OK" }, { SGBUTTON, SG_CANCEL, 0, 33,13, 8,1, "Cancel" }, { SGBOX, 0, 0, 2,7, 30,7, NULL }, { SGUSER, 0, 0, 2,7, 30,7, (void*)draw_cannoneer }, { -1, 0, 0, 0,0, 0,0, NULL } }; /** * Draw cannoneer */ static void draw_cannoneer(int x, int y, int w, int h) { static short fig[]={ 0,0,15,20,30,20,20,15,10,0,10,-30,18,-18,20,-5,24,-6, 20,-25,10,-40,0,-45, -10,-40,-20,-25,-24,-6,-20,-5,-18,-18,-10,-30,-10,0, -20,15,-30,20,-15,20, -1,-1 }; /* Daten für das Männchen */ int xk,yk; int fl; int i; double s,c; SDL_Rect rect; rect.x = x + 1; rect.y = y + 1; rect.w = w - 2; rect.h = h - 2; SDL_FillRect(surf, &rect, SDL_MapRGB(surf->format,0xff,0xff,0xff)); xk = x + w / 2; yk = y + h / 2 + 40; /* Draw the cannoneer man */ color(1); filledCircleColor(surf, xk-88*f, yk-60, 15, 0x000000ff); i=0; while ( fig[i]!=-1 ) { xy[i]=xk-88*f+fig[i]; i++; xy[i]=yk-5+fig[i]; i++; } xy[i++]=xy[0]; xy[i++]=xy[1]; scr_fillarea(i/2-1, xy); /* Draw the cannon */ color( 1 ); filledCircleColor(surf, xk, yk, 15, 0x000000ff); s=sin(wi/P57); c=cos(wi/P57); fl=-f; if ( wi>90 ) { fl=-fl; c=-c; } xy[0]=xk+fl*(c*14+s*14); xy[1]=yk+s*14-c*14; xy[2]=xk+fl*(c*14+s*40); xy[3]=yk+s*14-c*40; xy[4]=xk-fl*(c*55-s*40); xy[5]=yk-s*55-c*40; xy[6]=xk-fl*(c*55-s*14); xy[7]=yk-s*55-c*14; xy[8]=xy[0]; xy[9]=xy[1]; scr_fillarea(4, xy); } /** * Kanonenobjektbaum, Wahl von Winkel und Pulver */ int sch_obj(short k) { short i = 0; char *aw,*ap; dlg_winkel[0] = dlg_pulver[0] = 0; aw = dlg_winkel; ap = dlg_pulver; *(ap+2)=0; SDLGui_CenterDlg(cannoneerdlg); wi=ka[n][k].w; pv=ka[n][k].p; scr_sf_interior(1); do { if (pv > pu[n]) { pv=pu[n]; } *aw=48+wi/100; *(aw+1)=48+wi%100/10; *(aw+2)=48+wi%10; if (wi < 100) { *aw=*(aw+1); *(aw+1)=*(aw+2); *(aw+2)=0; } *ap=48+pv/10; *(ap+1)=48+pv%10; if (pv<10) { *ap=*(ap+1); *(ap+1)=0; } i = SDLGui_DoDialog(cannoneerdlg, NULL); wi-=10*(i==WL2)-10*(i==WR2)+(i==WL1)-(i==WR1); if ( wi<0 ) wi=0; if ( wi>180 ) wi=180; pv-= 3*(i==PL2)- 3*(i==PR2)+(i==PL1)-(i==PR1); if ( pv<5 ) pv=5; if ( pv>20 ) pv=20; } while (i != SOK && i != SAB); SDL_UpdateRect(surf, 0,0, 0,0); ka[n][k].w=wi; ka[n][k].p=pv; return (i == SOK); } ballerburg-1.2.0/src/font8x16.png0000644000175000017500000000506212506012141016070 0ustar thomasthomasPNG  IHDR^!{bKGD#2 pHYs  tIME39 IDATx]ے S_󐨀23[w&+M (HK{/(hY=R"P[zϒV A3?^R'/쵨1[%@ƆB{I!pԅCMRk=^^JY<9t"驣 ƺ!9Hif=;6BkZ:cOyHCTY¾ VǛ,K%` X,*PXM=([ڀqT}+ CJc~J[K9!0n\KdxK4/.pjAAcLv11؝2C*3d~$ еfԋbmٹT+Q4ILGc_we-HSx)/`H܀;Wcp-ex'4mK]C8,"o(:::"rTu۩ ,lTW:jCk2__!kpHmbA޹һˈKpt;YX TJGҥ#3`i2hHd/Q#HQM** dDwi ۀDi5\f.>+,mHy>S8`&W&E)F"as |@F TǓ[Zz_ eWù(bb` htRcqWhSh<ӣEzg[7[VDg J4c(9IiۻS:FςMB7(+;!Q?ày2e{=X?0J͟Cg-m50jܫu*Z3S7[lԟ/-;x~` bRRnjwAl]d MJ}iSޤ.BMSf2vYnŜuޞ8 3IJS*R1?$<\wt`Lbr8Fkv%V}]_vaD˷hJ&@<& V7ЙLnc=owۀ XROʵ3o];]戇UЂ`tBe6y]sT9ⴊ. 5$G|k6[ Tq,7 "Gn* YȢC|宏((QQ?&q'/r4Z-fC eQnUFe:fS@_rD/}|w'^7!>zG\>i++y*A ڸ@PHGO\ټ( ͼN@s)}Vފp&r61BO GxAL&^ȖSyI3bAw)̴LOarEnwwBVL88:[%@dRVU }0ϣX] 2bILvuټbUW300U]ySn K4 &{@3gZ9Lߩ;!l~^9iRKʪM,~x푋|\ ɀ!Ix8B~y*Lk'·:s,H'hwrYr^~c+KV8e;|sb8KBb/ML#2ùh"DDzPQIENDB`ballerburg-1.2.0/po/0000755000175000017500000000000012506012141013611 5ustar thomasthomasballerburg-1.2.0/po/nl.po0000644000175000017500000001762212506012141014572 0ustar thomasthomas# Dutch translations for ballerburg. # Copyright (C) 2013 Guus Sliepen # This file is distributed under the same license as the ballerburg package. # msgid "" msgstr "" "Project-Id-Version: ballerburg 1.0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-10-05 22:31+0200\n" "PO-Revision-Date: 2013-10-05 22:35+-2--\n" "Last-Translator: Guus Sliepen \n" "Language-Team: Dutch \n" "Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: src/baller1.c:68 msgid "Oaf" msgstr "Pummel" #: src/baller1.c:68 msgid "Yokel" msgstr "Kinkel" #: src/baller1.c:68 msgid "Boor" msgstr "Lummel" #: src/baller1.c:68 msgid "Doofus" msgstr "Vlegel" #: src/baller1.c:69 msgid "Fumbler" msgstr "Lomperd" #: src/baller1.c:69 msgid "Geezer" msgstr "Gozer" #: src/baller1.c:69 msgid "Ruffian" msgstr "Schurk" #: src/baller1.c:105 msgid "Not enough memory for loading the castles." msgstr "Niet genoeg geheugen voor het laden van de kastelen." #: src/baller1.c:117 msgid "William" msgstr "Willem" #: src/baller1.c:118 msgid "Frederick" msgstr "Frederik" #: src/baller1.c:178 msgid "Games" msgstr "Spellen" #: src/baller1.c:179 msgid "Total won" msgstr "Totaal gewonnen" #: src/baller1.c:180 msgid "Total lost" msgstr "Totaal verloren" #: src/baller1.c:181 msgid "Won in %" msgstr "Won in %" #: src/baller1.c:293 msgid "You don't have enough gunpowder." msgstr "Je hebt niet genoeg buskruit." #: src/baller1.c:293 #: src/baller1.c:297 msgid "Cancel" msgstr "Afbreken" #: src/baller1.c:297 msgid "You don't have any cannonballs left." msgstr "Je hebt geen kanonskogels meer." #: src/baller1.c:383 #, c-format msgid "!! %s has won !!" msgstr "!! %s heeft gewonnen !!" #: src/baller1.c:396 #, c-format msgid "( %s' king was hit," msgstr "( %s' koning was geraakt," #: src/baller1.c:398 #, c-format msgid "( %s's king was hit," msgstr "( %s's koning was geraakt," #: src/baller1.c:399 msgid "and upon hearing this, the people capitulated. )" msgstr "en na dit vernomen te hebben, gaf het volk zich over. )" #: src/baller1.c:403 #, c-format msgid "( %s' king has capitulated" msgstr "( %s' koning heeft zich overgegeven" #: src/baller1.c:406 #, c-format msgid "( %s's king has capitulated" msgstr "( %s's koning heeft zich overgegeven" #: src/baller1.c:408 msgid " because of the hopeless situation. )" msgstr " vanwege de hopeloze situatie. )" #: src/baller1.c:411 #, c-format msgid "( %s has no folk left. )" msgstr "( %s heeft geen volk over. )" #: src/baller1.c:415 msgid "( The limit of maximum rounds has been reached." msgstr "( Het maximum aantal rondes is bereikt." #: src/baller1.c:416 #, c-format msgid "%s is worse off. )" msgstr "%s staat er slechter voor. )" #: src/baller2.c:486 msgid " Round " msgstr " Ronde " #: src/baller2.c:660 msgid "The king says:" msgstr "De koning zegt:" #: src/baller2.c:661 msgid "Humbly acknowledged" msgstr "Met welnemen ontvangen" #: src/baller2.c:662 msgid "" "Well...\n" " alright...\n" " Carry on..." msgstr "" "Wel...\n" " vooruit...\n" " Ga zo door..." #: src/baller2.c:663 msgid "" "We are satisfied\n" " with your performance!" msgstr "" "Wij zijn tevreden\n" " met je prestaties!" #: src/baller2.c:664 msgid "" "Excellent,\n" " keep at it!" msgstr "" "Voortreffelijk,\n" " ga zo door!" #: src/baller2.c:665 msgid "" "Maybe you ought to\n" " lower Our taxes..." msgstr "" "Misschien zou je Onze\n" " belasting moeten verlagen..." #: src/baller2.c:666 msgid "" "If you keep this up,\n" " We shall discharge you!" msgstr "" "Als je zo door gaat,\n" " zullen Wij je ontslaan!" #: src/baller2.c:667 msgid "" "Why don't you buy\n" " a shaft tower..." msgstr "" "Waarom koop je\n" " geen boortoren..." #: src/baller2.c:668 msgid "" "You ought to\n" " kindly make more of\n" " an effort!" msgstr "" "Gelieve toch\n" " een beetje beter\n" " je best te doen!" #: src/baller2.c:669 msgid "" "You don't need to visit Us\n" " in each round." msgstr "" "Je hoeft Ons echt niet\n" " elke ronde te bezoeken." #: src/baller2.c:670 #, c-format msgid "" "Are you aware\n" " that you have already visited Us\n" " %d times thus far?" msgstr "" "Wist je dat\n" " je ons tot nu toe al reeds\n" " %d keer hebt bezocht?" #: src/baller2.c:671 msgid "" "So, are you certain\n" " that you will manage\n" " without a weather vane?" msgstr "" "Zeg, ben je zeker\n" " dat je het wel redt\n" " zonder een windvaan?" #: src/baller2.c:672 msgid "Nice to see you..." msgstr "Leuk je te zien..." #: src/baller2.c:673 msgid "" "What are We supposed\n" " to say in such an\n" " early phase?" msgstr "" "Wat zouden Wij\n" " moeten zeggen in zo'n\n" " vroeg stadium?" #: src/baller2.c:674 msgid "" "You ought to earn more money,\n" " build more shaft towers,\n" " and vanquish the opponent." msgstr "" "Je zou meer geld moeten verdienen,\n" " meer boortorens bouwen," " en de vijand verslaan." #: src/baller2.c:675 msgid "" "We do not have anything new\n" " to say to you." msgstr "" "We hebben niets nieuws\n" " tegen je te zeggen." #: src/baller2.c:676 msgid "" "We are pleased for you\n" " to come around and visit Us." msgstr "" "Wij zijn blij dat je\n" " bij ons op visite komt." #: src/baller2.c:691 msgid "" "The king is not in the mood\n" "to talk to you." msgstr "" "De koning is niet in de stemming\n" "om met je te praten." #: src/baller2.c:691 msgid "Too bad." msgstr "Helaas." #: src/ballergui.c:52 #: src/settings.c:223 msgid "Quit Ballerburg?" msgstr "Ballerburg verlaten?" #: src/ballergui.c:52 #: src/settings.c:223 msgid "Yes" msgstr "Ja" #: src/ballergui.c:52 #: src/settings.c:223 msgid "No" msgstr "Nee" #: src/cannoneer.c:59 msgid "Cannon" msgstr "Kanon" #: src/cannoneer.c:61 msgid "Angle:" msgstr "Hoek:" #: src/cannoneer.c:68 #: src/market.c:83 msgid "Gunpowder:" msgstr "Buskruit:" #: src/market.c:77 msgid "You have:" msgstr "Je hebt:" #: src/market.c:79 msgid "Funds:" msgstr "Geld:" #: src/market.c:80 msgid "Shaft towers:" msgstr "Boortorens:" #: src/market.c:81 msgid "Cannons:" msgstr "Kanonnen:" #: src/market.c:82 #: src/market.c:104 msgid "Weather vane:" msgstr "Windvaan:" #: src/market.c:84 msgid "Cannonballs:" msgstr "Kanonskogels:" #: src/market.c:85 msgid "Population:" msgstr "Bevolking:" #: src/market.c:86 msgid "Taxes in %" msgstr "Belasting in %" #: src/market.c:99 msgid "Market:" msgstr "Markt:" #: src/market.c:101 msgid "Lay bricks:" msgstr "Stenen leggen:" #: src/market.c:102 msgid "Shaft tower:" msgstr "Boortoren:" #: src/market.c:103 msgid "Cannon:" msgstr "Kanon:" #: src/market.c:105 msgid "Powder x30:" msgstr "Kruit x30:" #: src/market.c:106 msgid "2 cannonballs:" msgstr "2 kanonskogels:" #: src/market.c:114 #: src/screen.c:40 msgid "Done" msgstr "Klaar" #: src/market.c:135 msgid " Lay bricks: " msgstr " Leg stenen: " #: src/market.c:136 #: src/market.c:159 #, c-format msgid " Bricks left: %02d " msgstr " Stenen over: %02d " #: src/settings.c:65 msgid "Settings" msgstr "Instellingen" #: src/settings.c:68 #: src/settings.c:247 msgid "Player 1" msgstr "Speler 1" #: src/settings.c:69 #: src/settings.c:86 msgid "Name:" msgstr "Naam:" #: src/settings.c:71 #: src/settings.c:88 msgid "Human" msgstr "Mens" #: src/settings.c:72 #: src/settings.c:89 msgid "Computer" msgstr "Computer" #: src/settings.c:73 #: src/settings.c:90 msgid "AI strategy:" msgstr "AI strategie:" #: src/settings.c:78 #: src/settings.c:95 msgid "AI strength:" msgstr "AI sterkte:" #: src/settings.c:85 #: src/settings.c:251 msgid "Player 2" msgstr "Speler 2" #: src/settings.c:101 msgid "Maximum rounds:" msgstr "Maximum aantal rondes:" #: src/settings.c:105 msgid "unlimited" msgstr "ongelimiteerd" #: src/settings.c:107 msgid "King may capitulate" msgstr "Koning mag zich overgeven" #: src/settings.c:108 msgid "Players may build" msgstr "Spelers mogen bouwen" #: src/settings.c:110 #: src/settings.c:245 msgid "New game" msgstr "Nieuw spel" #: src/settings.c:111 msgid "Continue game" msgstr "Doorgaan" #: src/settings.c:112 msgid "Exit program" msgstr "Afsluiten" ballerburg-1.2.0/po/fi.po0000644000175000017500000001745112506012141014557 0ustar thomasthomas# -*- coding: iso-latin-1; -*- # Finnish translations for Ballerburg # # Based on the finnish Atari ST version of Ballerburg by Eero Tamminen. # # This file is distributed under the same license as the ballerburg package. # msgid "" msgstr "" "Project-Id-Version: ballerburg 1.0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-05-10 22:40+0200\n" "PO-Revision-Date: 2012-03-08 22:12+0100\n" "Last-Translator: Eero Tamminen\n" "Language-Team: Finnish\n" "Language: fi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" #: src/baller1.c:68 msgid "Oaf" msgstr "li" #: src/baller1.c:68 msgid "Yokel" msgstr "Juntti" #: src/baller1.c:68 msgid "Boor" msgstr "Moukka" #: src/baller1.c:68 msgid "Doofus" msgstr "Tahvo" #: src/baller1.c:69 msgid "Fumbler" msgstr "Tumpelo" #: src/baller1.c:69 msgid "Geezer" msgstr "Hyypi" #: src/baller1.c:69 msgid "Ruffian" msgstr "Lurjus" #: src/baller1.c:105 msgid "Not enough memory for loading the castles." msgstr "Muisti ei riit linnojen lataukseen!" #: src/baller1.c:117 msgid "William" msgstr "Viljami" #: src/baller1.c:118 msgid "Frederick" msgstr "Reetu" #: src/baller1.c:178 msgid "Games" msgstr "Pelit" #: src/baller1.c:179 msgid "Total won" msgstr "Voitetut" #: src/baller1.c:180 msgid "Total lost" msgstr "Hvityt" #: src/baller1.c:181 msgid "Won in %" msgstr "Voitto-%" #: src/baller1.c:294 msgid "You don't have enough gunpowder." msgstr "Ei tarpeeksi ruutia!" #: src/baller1.c:294 src/baller1.c:298 msgid "Cancel" msgstr "Peru" #: src/baller1.c:298 msgid "You don't have any cannonballs left." msgstr "Ei tykinkuulia!" #: src/baller1.c:384 #, c-format msgid "!! %s has won !!" msgstr "!! %s on voittanut !!" #: src/baller1.c:397 #, c-format msgid "( %s' king was hit," msgstr "( %s: Kuninkaaseen osui, ja" #: src/baller1.c:399 #, c-format msgid "( %s's king was hit," msgstr "( %s: Kuninkaaseen osui, ja" #: src/baller1.c:400 msgid "and upon hearing this, the people capitulated. )" msgstr "sen kuultuaan hnen alamaisensa antautuivat. )" #: src/baller1.c:404 #, c-format msgid "( %s' king has capitulated" msgstr "( %s: Tss tilanteessa Kuningas" #: src/baller1.c:407 #, c-format msgid "( %s's king has capitulated" msgstr "( %s: Tss tilanteessa Kuningas" #: src/baller1.c:409 msgid " because of the hopeless situation. )" msgstr " ei voinut muuta kuin antautua. )" #: src/baller1.c:412 #, c-format msgid "( %s has no folk left. )" msgstr "( %s kaikki alamaiset katosivat. )" #: src/baller1.c:416 msgid "( The limit of maximum rounds has been reached." msgstr "( Kaikki kierrokset on kyty." #: src/baller1.c:417 #, c-format msgid "%s is worse off. )" msgstr "%s oli huonommassa asemassa. )" #: src/baller2.c:486 msgid " Round " msgstr " Vuoro " #: src/baller2.c:660 msgid "The king says:" msgstr "Kuningas lausui:" #: src/baller2.c:661 msgid "Humbly acknowledged" msgstr "Nyrsti huomioitu" #: src/baller2.c:662 msgid "" "Well...\n" " alright...\n" " Carry on..." msgstr "" "Hmm...\n" " No, niin...\n" " Jatkakaa..." #: src/baller2.c:663 msgid "" "We are satisfied\n" " with your performance!" msgstr "" "Olemme tyytyvisi\n" " saavutuksiinne!" #: src/baller2.c:664 msgid "" "Excellent,\n" " keep at it!" msgstr "" "Erinomaista,\n" " jatkakaa toki!" #: src/baller2.c:665 msgid "" "Maybe you ought to\n" " lower Our taxes..." msgstr "" "Ehkp teidn pitisi\n" " alentaa verojamme..." #: src/baller2.c:666 msgid "" "If you keep this up,\n" " We shall discharge you!" msgstr "" "Jatkakaa samalla tavalla\n" " ja lenntte pihalle!" #: src/baller2.c:667 msgid "" "Why don't you buy\n" " a shaft tower..." msgstr "" "Ettek ostaisi\n" " akselitornia..." #: src/baller2.c:668 msgid "" "You ought to\n" " kindly make more of\n" " an effort!" msgstr "" "Voisitteko\n" " ystvllisesti tehd\n" " itsekin jotain!" #: src/baller2.c:669 msgid "" "You don't need to visit Us\n" " in each round." msgstr "" "Miksi vaivaatte\n" " meit jatkuvasti?" #: src/baller2.c:670 #, c-format msgid "" "Are you aware\n" " that you have already visited Us\n" " %d times thus far?" msgstr "" "Tiedttek, ett\n" " olette pyytnyt\n" " audienssiamme %d kertaa?" #: src/baller2.c:671 msgid "" "So, are you certain\n" " that you will manage\n" " without a weather vane?" msgstr "" "Niin, selvittek varmasti\n" " ilman tuuliviiri?" #: src/baller2.c:672 msgid "Nice to see you..." msgstr "Mukava nhd teit taas..." #: src/baller2.c:673 msgid "" "What are We supposed\n" " to say in such an\n" " early phase?" msgstr "" "Mit meidn pitisi\n" " sanoa nin\n" " aikaisessa vaiheessa?" #: src/baller2.c:674 msgid "" "You ought to earn more money,\n" " build more shaft towers,\n" " and vanquish the opponent." msgstr "" "Teidn pitisi tienata lis,\n" "rakentaa akselitorneja,\n" " ja kukistakaa kilpailijanne." #: src/baller2.c:675 msgid "" "We do not have anything new\n" " to say to you." msgstr "" "Meill ei ole teille mitn\n" " uutta sanottavaa." #: src/baller2.c:676 msgid "" "We are pleased for you\n" " to come around and visit Us." msgstr "" "Olipa ystvllist, ett\n" " tulitte luoksemme." #: src/baller2.c:691 msgid "" "The king is not in the mood\n" "to talk to you." msgstr "" "Kuningas ei ole\n" "keskustelutuulella." #: src/baller2.c:691 msgid "Too bad." msgstr "Harmi." #: src/ballergui.c:52 src/settings.c:223 msgid "Quit Ballerburg?" msgstr "Lopetetaanko Ballerburg?" #: src/ballergui.c:52 src/settings.c:223 msgid "Yes" msgstr "Kyll" #: src/ballergui.c:52 src/settings.c:223 msgid "No" msgstr "Ei" #: src/cannoneer.c:59 msgid "Cannon" msgstr "Kanuuna" #: src/cannoneer.c:61 msgid "Angle:" msgstr "Kulma:" #: src/cannoneer.c:68 src/market.c:83 msgid "Gunpowder:" msgstr "Ruuti:" #: src/market.c:77 msgid "You have:" msgstr "Sinulla on:" #: src/market.c:79 msgid "Funds:" msgstr "Varoja:" #: src/market.c:80 msgid "Shaft towers:" msgstr "Akselitorneja:" #: src/market.c:81 msgid "Cannons:" msgstr "Kanuunoita:" #: src/market.c:82 src/market.c:104 msgid "Weather vane:" msgstr "Tuuliviirej:" #: src/market.c:84 msgid "Cannonballs:" msgstr "Kanuunankuulia:" #: src/market.c:85 msgid "Population:" msgstr "Vest:" #: src/market.c:86 msgid "Taxes in %" msgstr "Vero-%" #: src/market.c:99 msgid "Market:" msgstr "Markkinat:" #: src/market.c:101 msgid "Lay bricks:" msgstr "Rakenna:" #: src/market.c:102 msgid "Shaft tower:" msgstr "Akselitorni:" #: src/market.c:103 msgid "Cannon:" msgstr "Kanuuna:" #: src/market.c:105 msgid "Powder x30:" msgstr "Ruutia x30:" #: src/market.c:106 msgid "2 cannonballs:" msgstr "2 kanuunankuulaa:" #: src/market.c:114 src/screen.c:40 msgid "Done" msgstr "Valmis" #: src/market.c:135 msgid " Lay bricks: " msgstr " Rakenna: " #: src/market.c:136 src/market.c:159 #, c-format msgid " Bricks left: %02d " msgstr " Tiili jljell: %02d " #: src/settings.c:65 msgid "Settings" msgstr "Asetukset" #: src/settings.c:68 src/settings.c:247 msgid "Player 1" msgstr "Pelaaja 1" #: src/settings.c:69 src/settings.c:86 msgid "Name:" msgstr "Nimi:" #: src/settings.c:71 src/settings.c:88 msgid "Human" msgstr "Ihminen" #: src/settings.c:72 src/settings.c:89 msgid "Computer" msgstr "Tietokone" #: src/settings.c:73 src/settings.c:90 msgid "AI strategy:" msgstr "Strategia:" #: src/settings.c:78 src/settings.c:95 msgid "AI strength:" msgstr "Tekolykkyys:" #: src/settings.c:85 src/settings.c:251 msgid "Player 2" msgstr "Pelaaja 2" #: src/settings.c:101 msgid "Maximum rounds:" msgstr "Kierroksia enintn:" #: src/settings.c:105 msgid "unlimited" msgstr "rajoittamaton" #: src/settings.c:107 msgid "King may capitulate" msgstr "Kuningas voi antautua" #: src/settings.c:108 msgid "Players may build" msgstr "Pelaajat voivat rakentaa" #: src/settings.c:110 src/settings.c:245 msgid "New game" msgstr "Uusi peli" #: src/settings.c:111 msgid "Continue game" msgstr "Jatka peli" #: src/settings.c:112 msgid "Exit program" msgstr "Lopeta ohjelma" ballerburg-1.2.0/po/de.po0000664000175000017500000001771712506012141014560 0ustar thomasthomas# German translations for Ballerburg package # Copyright (C) 2012 Thomas Huth # This file is distributed under the same license as the ballerburg package. # msgid "" msgstr "" "Project-Id-Version: ballerburg 1.0.1\n" "Report-Msgid-Bugs-To: Thomas Huth\n" "POT-Creation-Date: 2014-10-11 09:04+0200\n" "PO-Revision-Date: 2012-04-26 20:05+0100\n" "Last-Translator: Thomas Huth \n" "Language-Team: German\n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: src/baller1.c:68 msgid "Oaf" msgstr "Tlpel" #: src/baller1.c:68 msgid "Yokel" msgstr "Dummel" #: src/baller1.c:68 msgid "Boor" msgstr "Brubbel" #: src/baller1.c:68 msgid "Doofus" msgstr "Wusel" #: src/baller1.c:69 msgid "Fumbler" msgstr "Brsel" #: src/baller1.c:69 msgid "Geezer" msgstr "Toffel" #: src/baller1.c:69 msgid "Ruffian" msgstr "Rpel" #: src/baller1.c:105 msgid "Not enough memory for loading the castles." msgstr "Nicht genug Speicher um die Burgen zu laden." #: src/baller1.c:117 msgid "William" msgstr "Wilhelm" #: src/baller1.c:118 msgid "Frederick" msgstr "Friedrich" #: src/baller1.c:180 msgid "Games" msgstr "Spiele" #: src/baller1.c:181 msgid "Total won" msgstr "Gewonnen" #: src/baller1.c:182 msgid "Total lost" msgstr "Verloren" #: src/baller1.c:183 msgid "Won in %" msgstr "Siege %" #: src/baller1.c:295 msgid "You don't have enough gunpowder." msgstr "Dein Pulver reicht nicht!" #: src/baller1.c:295 src/baller1.c:299 msgid "Cancel" msgstr "Abbruch" #: src/baller1.c:299 msgid "You don't have any cannonballs left." msgstr "Du hast keine Kugeln mehr!" #: src/baller1.c:385 #, c-format msgid "!! %s has won !!" msgstr "!! %s hat gewonnen !!" #: src/baller1.c:398 #, c-format msgid "( %s' king was hit," msgstr "( %s' Knig wurde getroffen," #: src/baller1.c:400 #, c-format msgid "( %s's king was hit," msgstr "( %ss Knig wurde getroffen," #: src/baller1.c:401 msgid "and upon hearing this, the people capitulated. )" msgstr " daraufhin ergab sich dessen Volk. )" #: src/baller1.c:405 #, c-format msgid "( %s' king has capitulated" msgstr "( %s' Knig hat aufgrund der" #: src/baller1.c:408 #, c-format msgid "( %s's king has capitulated" msgstr "( %ss Knig hat aufgrund der" #: src/baller1.c:410 msgid " because of the hopeless situation. )" msgstr " aussichtslosen Lage kapituliert. )" #: src/baller1.c:413 #, c-format msgid "( %s has no folk left. )" msgstr "( %s hat kein Volk mehr. )" #: src/baller1.c:417 msgid "( The limit of maximum rounds has been reached." msgstr "( Die maximale Rundenzahl ist erreicht." #: src/baller1.c:418 #, c-format msgid "%s is worse off. )" msgstr "%s befindet sich in der schlechteren Lage. )" #: src/baller1.c:514 msgid "Wind:" msgstr "" #: src/baller2.c:507 msgid " Round " msgstr " Runde " #: src/baller2.c:680 msgid "The king says:" msgstr "Der Knig meint:" #: src/baller2.c:681 msgid "Humbly acknowledged" msgstr "Demtig zur Kenntnis genommen" #: src/baller2.c:682 msgid "" "Well...\n" " alright...\n" " Carry on..." msgstr "" "Naja...\n" " Nun gut...\n" " Weiter so..." #: src/baller2.c:683 msgid "" "We are satisfied\n" " with your performance!" msgstr "" "Ich bin zufrieden\n" " mit Ihren Leistungen!" #: src/baller2.c:684 msgid "" "Excellent,\n" " keep at it!" msgstr "" "Hervorragend,\n" " weiter so!" #: src/baller2.c:685 msgid "" "Maybe you ought to\n" " lower Our taxes..." msgstr "" "Vielleicht sollten Sie mal\n" " die Steuern senken..." #: src/baller2.c:686 msgid "" "If you keep this up,\n" " We shall discharge you!" msgstr "" "Wenn Sie so weiter machen\n" " werde ich Sie entlassen!" #: src/baller2.c:687 msgid "" "Why don't you buy\n" " a shaft tower..." msgstr "" "Vielleicht mal 'nen\n" " Frderturm kaufen..." #: src/baller2.c:688 msgid "" "You ought to\n" " kindly make more of\n" " an effort!" msgstr "" "Sie sollten sich\n" " geflligst mehr Mhe\n" " geben!" #: src/baller2.c:689 msgid "" "You don't need to visit Us\n" " in each round." msgstr "" "Sie brauchen nicht\n" " jede Runde zu kommen." #: src/baller2.c:690 #, c-format msgid "" "Are you aware\n" " that you have already visited Us\n" " %d times thus far?" msgstr "" "Wissen Sie eigentlich,\n" " dass Sie mich bereits\n" " %d mal besucht haben?" #: src/baller2.c:691 msgid "" "So, are you certain\n" " that you will manage\n" " without a weather vane?" msgstr "" "Und Sie sind sich sicher,\n" " dass Sie auch ohne eine\n" " Windfahne zurecht kommen?" #: src/baller2.c:692 msgid "Nice to see you..." msgstr "Schn, Sie zu sehen..." #: src/baller2.c:693 msgid "" "What are We supposed\n" " to say in such an\n" " early phase?" msgstr "" "Was soll ich denn in\n" " so einer frhen Phase\n" " schon sagen?" #: src/baller2.c:694 msgid "" "You ought to earn more money,\n" " build more shaft towers,\n" " and vanquish the opponent." msgstr "" "Sie sollten mehr Geld\n" " verdienen, Frdertrme bauen\n" " und den Gegner besiegen." #: src/baller2.c:695 msgid "" "We do not have anything new\n" " to say to you." msgstr "" "Ich habe Ihnen nichts\n" " neues zu sagen." #: src/baller2.c:696 msgid "" "We are pleased for you\n" " to come around and visit Us." msgstr "" "Find' ich nett, dass\n" " Sie mich mal besuchen!" #: src/baller2.c:711 msgid "" "The king is not in the mood\n" "to talk to you." msgstr "" "Der Knig hat keine Lust,\n" "dich zu sprechen." #: src/baller2.c:711 msgid "Too bad." msgstr "Schade" #: src/ballergui.c:52 src/settings.c:222 msgid "Quit Ballerburg?" msgstr "Ballerburg beenden?" #: src/ballergui.c:52 src/settings.c:222 msgid "Yes" msgstr "Ja" #: src/ballergui.c:52 src/settings.c:222 msgid "No" msgstr "Nein" #: src/cannoneer.c:59 msgid "Cannon" msgstr "Kanone" #: src/cannoneer.c:61 msgid "Angle:" msgstr "Winkel:" #: src/cannoneer.c:68 src/market.c:83 msgid "Gunpowder:" msgstr "Pulver:" #: src/market.c:77 msgid "You have:" msgstr "Du hast:" #: src/market.c:79 msgid "Funds:" msgstr "Geld:" #: src/market.c:80 msgid "Shaft towers:" msgstr "Frdertrme:" #: src/market.c:81 msgid "Cannons:" msgstr "Geschtze:" #: src/market.c:82 src/market.c:104 msgid "Weather vane:" msgstr "Windfahne:" #: src/market.c:84 msgid "Cannonballs:" msgstr "Kugeln:" #: src/market.c:85 msgid "Population:" msgstr "Volk:" #: src/market.c:86 msgid "Taxes in %" msgstr "Steuern in %" #: src/market.c:99 msgid "Market:" msgstr "Markt:" #: src/market.c:101 msgid "Lay bricks:" msgstr "Anbauen:" #: src/market.c:102 msgid "Shaft tower:" msgstr "Frderturm:" #: src/market.c:103 msgid "Cannon:" msgstr "Geschtz:" #: src/market.c:105 msgid "Powder x30:" msgstr "30 Pulver:" #: src/market.c:106 msgid "2 cannonballs:" msgstr "2 Kugeln:" #: src/market.c:114 src/screen.c:56 msgid "Done" msgstr "Fertig" #: src/market.c:135 msgid " Lay bricks: " msgstr " Anbauen: " #: src/market.c:136 src/market.c:162 #, c-format msgid " Bricks left: %02d " msgstr " Verbleibende Steine: %02d " #: src/settings.c:64 msgid "Settings" msgstr "Einstellungen" #: src/settings.c:67 src/settings.c:246 msgid "Player 1" msgstr "Spieler 1" #: src/settings.c:68 src/settings.c:85 msgid "Name:" msgstr "Name:" #: src/settings.c:70 src/settings.c:87 msgid "Human" msgstr "Mensch" #: src/settings.c:71 src/settings.c:88 msgid "Computer" msgstr "Computer" #: src/settings.c:72 src/settings.c:89 msgid "AI strategy:" msgstr "KI Strategie:" #: src/settings.c:77 src/settings.c:94 msgid "AI strength:" msgstr "KI Strke:" #: src/settings.c:84 src/settings.c:250 msgid "Player 2" msgstr "Spieler 2" #: src/settings.c:100 msgid "Maximum rounds:" msgstr "Maximale Rundenzahl:" #: src/settings.c:104 msgid "unlimited" msgstr "unbegrenzt" #: src/settings.c:106 msgid "King may capitulate" msgstr "Knig kann kapitulieren" #: src/settings.c:107 msgid "Players may build" msgstr "Anbauen ist erlaubt" #: src/settings.c:109 src/settings.c:244 msgid "New game" msgstr "Neues Spiel" #: src/settings.c:110 msgid "Continue game" msgstr "Weiterspielen" #: src/settings.c:111 msgid "Exit program" msgstr "Programm beenden" ballerburg-1.2.0/po/CMakeLists.txt0000644000175000017500000000232712506012141016355 0ustar thomasthomas# ##################################### # CMake build file for the translations # ##################################### if (GETTEXT_FOUND) # Generate template file add_custom_target(po-template ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}.pot) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}.pot COMMAND xgettext -k_ -kN_ --package-version=${VERSION} --package-name=${CMAKE_PROJECT_NAME} -o ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}.pot ${CMAKE_CURRENT_SOURCE_DIR}/../src/*.c COMMAND sed -i -e s/charset=CHARSET/charset=ISO-8859-1/ -e s%"${CMAKE_CURRENT_SOURCE_DIR}/../"%%g ${CMAKE_PROJECT_NAME}.pot DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../src/*.c ) file(GLOB POFILES *.po) foreach(POFILE ${POFILES}) string(REGEX REPLACE "(.*)/(.*)\\.po" "\\2" LANG ${POFILE}) string(REPLACE ".po" ".mo" MOFILE ${POFILE}) add_custom_command( OUTPUT ${MOFILE} COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} -o ${MOFILE} ${POFILE} DEPENDS ${POFILE} ) add_custom_target(mo-file-${LANG} ALL DEPENDS ${MOFILE}) install(FILES ${MOFILE} RENAME ${CMAKE_PROJECT_NAME}.mo DESTINATION ${LOCALEDIR}/${LANG}/LC_MESSAGES) endforeach() endif (GETTEXT_FOUND) ballerburg-1.2.0/po/it.po0000664000175000017500000001775212506012141014603 0ustar thomasthomas# Italian translations for Ballerburg package # Copyright (C) 2013 Andrea Musuruane . # This file is distributed under the same license as the ballerburg package. # msgid "" msgstr "" "Project-Id-Version: ballerburg 1.0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2014-10-11 16:43+0200\n" "PO-Revision-Date: 2014-10-11 17:27+0100\n" "Last-Translator: Andrea Musuruane \n" "Language-Team: Italian\n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.5.4\n" #: src/baller1.c:68 msgid "Oaf" msgstr "Goffo" #: src/baller1.c:68 msgid "Yokel" msgstr "Bifolco" #: src/baller1.c:68 msgid "Boor" msgstr "Cafone" #: src/baller1.c:68 msgid "Doofus" msgstr "Stupido" #: src/baller1.c:69 msgid "Fumbler" msgstr "Pasticcione" #: src/baller1.c:69 msgid "Geezer" msgstr "Vecchio" #: src/baller1.c:69 msgid "Ruffian" msgstr "Farabutto" #: src/baller1.c:105 msgid "Not enough memory for loading the castles." msgstr "Memoria insufficiente per caricare i castelli." #: src/baller1.c:117 msgid "William" msgstr "William" #: src/baller1.c:118 msgid "Frederick" msgstr "Frederick" #: src/baller1.c:182 msgid "Games" msgstr "Partite" #: src/baller1.c:183 msgid "Total won" msgstr "Totale vinte" #: src/baller1.c:184 msgid "Total lost" msgstr "Totale perse" #: src/baller1.c:185 msgid "Won in %" msgstr "Vittorie in %" #: src/baller1.c:297 msgid "You don't have enough gunpowder." msgstr "Non hai abbastanza polvere da sparo." #: src/baller1.c:297 src/baller1.c:301 msgid "Cancel" msgstr "Annulla" #: src/baller1.c:301 msgid "You don't have any cannonballs left." msgstr "Non hai abbastanza palle di cannone." #: src/baller1.c:387 #, c-format msgid "!! %s has won !!" msgstr "%s ha vinto!!" #: src/baller1.c:400 #, c-format msgid "( %s' king was hit," msgstr "( il Re di %s stato colpito," #: src/baller1.c:402 #, c-format msgid "( %s's king was hit," msgstr "( il Re di %s stato colpito," #: src/baller1.c:403 msgid "and upon hearing this, the people capitulated. )" msgstr "e dopo aver sentito questo, il popolo si arrese. )" #: src/baller1.c:407 #, c-format msgid "( %s' king has capitulated" msgstr "( Il Re di %s si arreso" #: src/baller1.c:410 #, c-format msgid "( %s's king has capitulated" msgstr "( Il Re di %s si arreso" #: src/baller1.c:412 msgid " because of the hopeless situation. )" msgstr " a causa della situazione disperata. )" #: src/baller1.c:415 #, c-format msgid "( %s has no folk left. )" msgstr "( %s non ha pi sudditi. )" #: src/baller1.c:419 msgid "( The limit of maximum rounds has been reached." msgstr "( E' stato raggiunto il limite massimo di turni impostato." #: src/baller1.c:420 #, c-format msgid "%s is worse off. )" msgstr "%s sta peggio. )" #: src/baller1.c:516 msgid "Wind:" msgstr "Vento:" #: src/baller2.c:507 msgid " Round " msgstr " Turno " #: src/baller2.c:680 msgid "The king says:" msgstr "Il Re dice:" #: src/baller2.c:681 msgid "Humbly acknowledged" msgstr "Ringraziato con umilt" #: src/baller2.c:682 msgid "" "Well...\n" " alright...\n" " Carry on..." msgstr "" "Beh...\n" " va bene...\n" " Prosegui..." #: src/baller2.c:683 msgid "" "We are satisfied\n" " with your performance!" msgstr "" "Siamo soddisfatti\n" " del tuo rendimento!" #: src/baller2.c:684 msgid "" "Excellent,\n" " keep at it!" msgstr "" "Eccellente,\n" " continua cos!" #: src/baller2.c:685 msgid "" "Maybe you ought to\n" " lower Our taxes..." msgstr "" "Forse dovresti\n" " abbassare le nostre tasse..." #: src/baller2.c:686 msgid "" "If you keep this up,\n" " We shall discharge you!" msgstr "" "Se continui cos,\n" " dovremo congedarti!" #: src/baller2.c:687 msgid "" "Why don't you buy\n" " a shaft tower..." msgstr "" "Perch non compri\n" " un castelletto?" #: src/baller2.c:688 msgid "" "You ought to\n" " kindly make more of\n" " an effort!" msgstr "" "Cortesemente\n" " dovresti fare pi\n" " di uno sforzo!" #: src/baller2.c:689 msgid "" "You don't need to visit Us\n" " in each round." msgstr "" "Non devi venire a trovarci\n" " ad ogni turno." #: src/baller2.c:690 #, c-format msgid "" "Are you aware\n" " that you have already visited Us\n" " %d times thus far?" msgstr "" "Sei consapevole\n" " che sei gi venuto a trovarci\n" " %d volte fino ad ora?" #: src/baller2.c:691 msgid "" "So, are you certain\n" " that you will manage\n" " without a weather vane?" msgstr "" "Allora, sei certo\n" " di riuscirci\n" " senza una banderuola?" #: src/baller2.c:692 msgid "Nice to see you..." msgstr "Piacere di vederti..." #: src/baller2.c:693 msgid "" "What are We supposed\n" " to say in such an\n" " early phase?" msgstr "" "Cosa dovremmo\n" " dire in una fase\n" " cos precoce?" #: src/baller2.c:694 msgid "" "You ought to earn more money,\n" " build more shaft towers,\n" " and vanquish the opponent." msgstr "" "Dovresti guadagnare pi soldi,\n" " costruire pi castelletti,\n" " e sconfiggere l'avversario." #: src/baller2.c:695 msgid "" "We do not have anything new\n" " to say to you." msgstr "" "Non abbiamo nulla di nuovo\n" " da dirti." #: src/baller2.c:696 msgid "" "We are pleased for you\n" " to come around and visit Us." msgstr "" "Siamo contenti che\n" " tu sia venuto a trovarci." #: src/baller2.c:711 msgid "" "The king is not in the mood\n" "to talk to you." msgstr "" "Il Re non in vena \n" "di parlare con te." #: src/baller2.c:711 msgid "Too bad." msgstr "Peccato." #: src/ballergui.c:52 src/settings.c:222 msgid "Quit Ballerburg?" msgstr "Esci da Ballerburg?" #: src/ballergui.c:52 src/settings.c:222 msgid "Yes" msgstr "S" #: src/ballergui.c:52 src/settings.c:222 msgid "No" msgstr "No" #: src/cannoneer.c:59 msgid "Cannon" msgstr "Cannone" #: src/cannoneer.c:61 msgid "Angle:" msgstr "Angolo:" #: src/cannoneer.c:68 src/market.c:83 msgid "Gunpowder:" msgstr "Polvere:" #: src/market.c:77 msgid "You have:" msgstr "Hai:" #: src/market.c:79 msgid "Funds:" msgstr "Capitale:" #: src/market.c:80 msgid "Shaft towers:" msgstr "Castelletti:" #: src/market.c:81 msgid "Cannons:" msgstr "Cannoni:" #: src/market.c:82 src/market.c:104 msgid "Weather vane:" msgstr "Banderuola:" #: src/market.c:84 msgid "Cannonballs:" msgstr "Palle di cannone:" #: src/market.c:85 msgid "Population:" msgstr "Popolazione:" #: src/market.c:86 msgid "Taxes in %" msgstr "Tasse in %" #: src/market.c:99 msgid "Market:" msgstr "Mercato:" #: src/market.c:101 msgid "Lay bricks:" msgstr "Posare i mattoni:" #: src/market.c:102 msgid "Shaft tower:" msgstr "Castelletto:" #: src/market.c:103 msgid "Cannon:" msgstr "Cannone:" #: src/market.c:105 msgid "Powder x30:" msgstr "Polvere x30:" #: src/market.c:106 msgid "2 cannonballs:" msgstr "2 palle di cannone:" #: src/market.c:114 src/screen.c:56 msgid "Done" msgstr "Fatto" #: src/market.c:135 msgid " Lay bricks: " msgstr " Posa i mattoni: " #: src/market.c:136 src/market.c:162 #, c-format msgid " Bricks left: %02d " msgstr " Mattoni rimasti: %02d " #: src/settings.c:64 msgid "Settings" msgstr "Impostazioni" #: src/settings.c:67 src/settings.c:246 msgid "Player 1" msgstr "Giocatore 1" #: src/settings.c:68 src/settings.c:85 msgid "Name:" msgstr "Nome:" #: src/settings.c:70 src/settings.c:87 msgid "Human" msgstr "Umano" #: src/settings.c:71 src/settings.c:88 msgid "Computer" msgstr "Computer" #: src/settings.c:72 src/settings.c:89 msgid "AI strategy:" msgstr "Strategia IA:" #: src/settings.c:77 src/settings.c:94 msgid "AI strength:" msgstr "Forza IA:" #: src/settings.c:84 src/settings.c:250 msgid "Player 2" msgstr "Giocatore 2" #: src/settings.c:100 msgid "Maximum rounds:" msgstr "Numero di turni:" #: src/settings.c:104 msgid "unlimited" msgstr "illimitato" #: src/settings.c:106 msgid "King may capitulate" msgstr "Il Re pu arrendersi" #: src/settings.c:107 msgid "Players may build" msgstr "I giocatori possono costruire" #: src/settings.c:109 src/settings.c:244 msgid "New game" msgstr "Nuova partita" #: src/settings.c:110 msgid "Continue game" msgstr "Continua la partita" #: src/settings.c:111 msgid "Exit program" msgstr "Esci dal programma" ballerburg-1.2.0/doc/0000755000175000017500000000000012506012141013740 5ustar thomasthomasballerburg-1.2.0/doc/authors.txt0000644000175000017500000000142112506012141016164 0ustar thomasthomas People who contributed to Ballerburg SDL: - Thomas Huth : Main developer of Ballerburg SDL, adapted the old Ballerburg sources to recent systems, maintains the Ballerburg SDL project. - Eero Tamminen : Finnish translations - Jens Ropers : Most of the English translations - Andrea Musuruane : Italian translations - Guus Sliepen : Dutch translations Ballerburg SDL uses source code from other projects which we would like to acknowledge here: - Eckhard Kruse : Wrote the original Ballerburg game for the Atari ST. - Stefan Berndtsson : The original version of the PSG soundchip emulation. - Kolja Koischwitz : Designed some additional castles (used in Ballerburg^2) - Andreas Schiffler : SDL_gfxPrimitives (graphics primitives for SDL surfaces) ballerburg-1.2.0/doc/CMakeLists.txt0000644000175000017500000000066712506012141016511 0ustar thomasthomas INSTALL(FILES de/anleitung.html en/manual.html DESTINATION ${DOCDIR}) add_custom_target(manpages ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ballerburg.6.gz) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ballerburg.6.gz COMMAND gzip -c -9 ${CMAKE_CURRENT_SOURCE_DIR}/ballerburg.6 > ${CMAKE_CURRENT_BINARY_DIR}/ballerburg.6.gz DEPENDS ballerburg.6) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/ballerburg.6.gz DESTINATION ${MANDIR}) ballerburg-1.2.0/doc/ballerburg.60000644000175000017500000000351712506012141016156 0ustar thomasthomas.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH "BALLERBURG" "6" "2015-03-29" "Ballerburg SDL" "" .\" Please adjust this date whenever revising the manpage. .SH "NAME" ballerburg \- A castle combat game .SH "SYNOPSIS" .B ballerburg .SH "DESCRIPTION" Ballerburg is a castle combat game. Two players (which can be human or computer-controlled) try to destroy the opponent's castle with their cannons. .PP There are two ways to win the game: Either by directly hitting the opponents king with a cannonball, or by destroying enough of the opponents commodities so that the king capitulates automatically. .SH "COMMANDS" Beside the intuitive control of the game with the mouse cursor, there are a couple of shortcut keys, too: .TP .B ESC show the settings dialog .TP .B f toggle fullscreen mode .TP .B t show high-score table .TP .B q quit Ballerburg .SH COPYRIGHT Copyright (C) 1987, 1989 Eckhard Kruse .br Copyright (C) 2010, 2015 Thomas Huth .PP This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. .PP This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. .PP You should have received a copy of the GNU General Public License along with this program. If not, see . .SH "SEE ALSO" The main program documentation, usually in /usr/share/doc/ballerburg. .PP The homepage of Ballerburg SDL: http://baller.tuxfamily.org/ ballerburg-1.2.0/doc/de/0000755000175000017500000000000012506012141014330 5ustar thomasthomasballerburg-1.2.0/doc/de/anleitung.html0000644000175000017500000003546112506012141017215 0ustar thomasthomas Ballerburg SDL Anleitung

Spielanleitung zu Ballerburg SDL

1. Sinn des Spieles

Bei dem Spiel Ballerburg geht es darum, dass sich zwei Burgherren mit dem Ziel gegenüber stehen, durch gezielte Kanonenschüsse den Gegner zu besiegen. Dabei haben die Spieler die Möglichkeit, durch Kauf von Fördertürmen Geld zu verdienen, vom Volk Steuern zu fordern und mit diesen Einnahmen zum Beispiel neue Geschütze und Munition zu kaufen.

2. Verschiedene Spielmodi

Über die ESC-Taste erreichen Sie das Einstellungsmenü, in welchem Sie verschiedene Spielmodi auswählen können: Normalerweise kämpfen zwei Spieler gegeneinander. Weiterhin besteht die Möglichkeit, dass ein Spieler gegen einen Computer spielt. Dabei kann der Computer wahlweise auf der linken oder rechten Seite spielen. Schließlich können Sie auch zwei Computer gegeneinander spielen lassen. Da Sie den Modus während des laufenden Spieles ändern können, besteht zum Beispiel die Möglichkeit, dass Sie zwischendurch auch einmal den Computer für sich schießen lassen, oder dass Sie in einem aussichtslosen Kampf gegen den Computer durch vorübergehendes Umschalten auf 'Spieler gegen Spieler' Ihren Gegner durch eigene Entscheidungen schwächen.

3. Spielernamen und Computerspieler

Im Einstellungsmenü können Sie die Namen der menschlichen Spieler bestimmen. Die Namen der Computer legen Sie beim unter 'KI Strategie' fest. Beides kann auch während einer Partie geändert werden. Computer 1 und Spieler 1 spielen immer auf der linken Computer 2 und Spieler 2 auf der rechten Seite. Die Namen der Computer stehen gleichzeitig für eine bestimmte Strategie. Die Zahlen 1-4 unter 'KI Stärke' stellen die Treffsicherheit der Computerspieler dar. Dabei bedeutet 4, dass praktisch jeder Schuss ein Treffer ist. Die Strategien unterscheiden sich darin, dass die Computer den Zielen eine unterschiedliche Priorität geben, d.h. manche Computer schießen grundsätzlich auf Kanonen, wenn welche vorhanden sind, während andere zum Beispiel eher auf das gegnerische Geld zielen.

Tölpel : Kein konkretes Ziel, versucht nur, die Burg irgendwie zu treffen.
Dummel : Geld vor Pulver/Kugeln vor König
Brubbel : Geld vor Kanonen vor König
Wusel : Geld, Pulver, Kugeln, Fördertürme, Kanonen, König: Alle mit gleicher Wahrscheinlichkeit
Brösel : Kanonen vor König
Toffel : Förderturme vor Kanonen vor König
Rüpel : Zielt nur auf den König.

Desweiteren sind nur Wusel, Brösel, Toffel und Rüpel in der Lage, sich Fördertürme zu kaufen.

4. Neues Spiel, Wahl der Burgen

Nach Anklicken von 'Neues Spiel' können Sie für die beiden Seiten Burgen auswählen und anschließend mit 'OK' das Spiel beginnen. Sollten Sie nicht bereits die Burgendatei 'BALLER.DAT' erweitert haben, so stehen Ihnen 9 Burgen zur Verfügung. Bei gleichguten Spielern sollten Sie in der Regel auch gleiche Burgen auswählen, denn sie unterscheiden sich in der Stärke teilweise recht erheblich untereinander. Bei der Wahl von kleineren Burgen wird sich natürlich auch im allgemeinen die Gesamtspieldauer verkürzen.

Hier nun die Werte der Standard-Burgen:

Kanonen Geld Pulver Kugeln Volk
2 400 180 12 200
5 500 180 12 270
5 500 150 14 270
6 500 190 12 300
3 500 120 6 220
4 500 120 10 240
6 800 120 12 500
3 500 120 9 500
1 1000 120 12 300

5. Das Spielfeld: Der Berg und die Burgen

Nachdem Sie nun mit 'Neues Spiel' das Spiel begonnen haben, werden die Burgen und der Berg gezeichnet. Sowohl die Lage der Burgen als auch das Aussehen und die Höhe das Berges sind (innerhalb eines gewissen Rahmens) zufällig. Die Burgen bestehen aus folgenden Teilen:

  • den eigentlichen Gemäuern sowie den Dächern
  • dem Saal, im dem der König thront
  • den verschiedenen Kanonen
  • der Pulverkammer (ein Fass entspricht 30 Pulvereinheiten)
  • der Kammer für die Kugeln
  • der Schatzkammer (ein Sack entspricht 150 Geldeinheiten)
  • der Windfahne (es ist immer nur die Windfahne des Spielers, der an der Reihe ist, gehisst)

Durch die aktive Windanzeige sieht man, wer am Zug ist. Ist der Spieler im Besitz einer Windfahne, so wird sie im Kasten unten vergrößert gezeigt und außerdem die genaue Windgeschwindigkeit und -richtung angegeben.

6. Spielablauf

Nach dem Starten des Spieles führen die Spieler immer abwechselnd Ihre Aktionen aus, bis einer gewonnen hat. Innerhalb eines Zuges kann der Spieler verschiedene Dinge machen: Nach Anklicken einer der Kammern für Pulver, Kugeln oder Geld wird der Besitz des Spielers angezeigt und man hat dann die Möglichkeit, auf dem Markt verschiedene Dinge zu kaufen. Mehr dazu wird im nächsten Abschnitt gesagt. Durch Anklicken des Königs können Sie erfahren, was Ihr Herrscher denn zu Ihren Erfolgen zu sagen hat.

Abgeschlossen werden kann der Zug durch zweierlei Möglichkeiten: Sollten Sie keine Kanone, nicht genügend Pulver bzw. Kugeln oder einfach keine Lust zum Schießen haben, so müssen Sie auf 'Fertig' am unteren Bildschirmrand klicken. Andernfalls wählen Sie die Kanone, mit der Sie schießen wollen, aus, stellen Winkel und Pulver ein und klicken auf 'OK'. (Näheres zum Schießen in Abschnitt 8)

7. Der eigene Besitz und der Markt

Wenn Sie während Ihres Zuges auf eine der drei Kammern klicken, so erscheint eine Übersicht, auf die jetzt näher eingegangen werden soll. Unter 'Du hast' steht eine genaue Aufzählung über Ihren Besitz sowie über die Größe Ihres Volkes. Außerdem können Sie hier die Steuern, die Sie von Ihrem Volk fordern, durch Klicken auf die entsprechenden Pfeile einstellen. Bei hohen Steuern bekommen Sie natürlich mehr Geld als bei niedrigen. Allerdings kann Sie bei zu hohen Steuern ein Teil des Volkes verlassen. Bei niedrigen Steuern hingegen können Sie sich einer gewissen Zahl Einwanderer erfreuen. Um das ganze etwas interessanter zu machen, schwanken allerdings die Zahl der Ein/Auswanderer sowie die Einnahmen auch bei konstanten Steuern innerhalb einer gewissen Bandbreite. Außerdem, seien Sie gewarnt: Bei gar zu hohen Steuern, nehmen Ihre Einnahmen wieder ab. (Welches Volk hat schon Lust, Gewinne zu erwirtschaften, wenn es sowieso wieder alles abgeben muss.)

Der zweite Teil der Anzeige stellt den Markt dar. Hier haben Sie die Möglichkeit, gewisse Dinge zu kaufen oder auch Ihre Burg zu reparieren. Sie führen eine Aktion aus, indem sie einfach auf die entsprechende Bezeichnung klicken. Dies ist jedoch nur dann möglich, wenn der Eintrag aktiv ist. Sollte er nicht anwählbar sein, so liegt es entweder an mangelndem Geld oder an einem der nachfolgenden Gründe:

  • Sie können nur eine Windfahne haben. Besitzen Sie also eine, so ist der Eintrag nicht aktiv.
  • Sie können nie mehr Kanonen haben, als zu Spielbeginn auf der Burg waren. Sollten Sie im Laufe des Spieles Kanonenstandplätze durch 'Anbauen' zugemauert haben, so können auch dort keine Kanonen mehr plaziert werden.
  • Maximal kann ein Spieler fünf Fördertürme besitzen. Je nach Burggröße kann diese Obergrenze auch niedriger liegen, denn Fördertürme dürfen nicht über die Bildschirmmitte hinaus gebaut werden.

Beim Kaufen von Kugeln oder Pulver sollten Sie beachten, dass Sie nur soviel einkaufen können, wie in Ihre Kammern passt. Weiteres Anklicken der entsprechenden Menüpunkte verringert zwar nach wie vor das Geld um den angezeigten Preis, bringt aber keine neuen Kugeln oder Fässer! Ähnliches gilt für die Schatzkammer: Ist sie gefüllt, so können Sie auch mit den schönsten Einnahmen Ihr Vermögen nicht weiter steigern.

Der Kauf von Fördertürmen ist eine langfristige Investition. Pro Runde und pro Turm nehmen Sie ungefähr zwischen 40 und 70 Geldeinheiten ein.

Nun noch zum Anbauen: Wählen Sie diesen Punkt an, so stehen Ihnen 20 Steine zur Verfügung ( die verbleibenen werden unten angezeigt ), die Sie sofort alle anbauen müssen. Beachten Sie, dass Sie nicht 'irgendwo in der Luft' anbauen können, sondern von den vorhanden Wänden ausgehen müssen. Desweiteren brauchen Sie nicht auf den bösen Gedanken zu kommen, bei der Burg des Gegners zum Beispiel die Geschütze zuzumauern - das geht nämlich nicht, Sie können nur im Bereich Ihrer eigenen Burg bauen.

Zu den Preisen ist nur zu sagen, dass Sie alle jeweils in einem bestimmten Bereich schwanken und dass Sie teilweise unterschiedlich starken Sprüngen unterworfen sind. (Mehr möchte ich eigentlich nicht verraten, denn so können Sie noch immer wieder staunen, wie teuer doch Fördertürme sein können...)

8. Schießen

Nach dem Anklicken einer Kanone haben Sie Winkel und Pulver einzustellen. Mit den einfachen Pfeilen stellen Sie in Einerschritten, mit den doppelten in Dreier- ( Pulver ) bzw. Zehnerschritten ( Winkel ) ein. Die Pulvermenge liegt zwischen 5 und 20 Einheiten. ( Wenn Sie insgesamt weniger als 20 Pulvereinheiten haben, liegt die Obergrenze automatisch auch niedriger. ) Pulvermengen im Bereich von 5 werden Sie eigentlich nur selten gebrauchen, nämlich nur dann, wenn Sie Ihre eigenen Fördertürme kaputt schießen wollen?!

Winkel können Sie im Bereich von 0 bis 180 Grad einstellen. Winkel über 90 (bei stärkerem Gegenwind auch schon über 80) und unter 10 Grad sind allerdings erfahrungsgemäß auch nur sehr bedingt brauchbar.

Wenn Sie schließlich mit Ihren Einstellungen zufrieden sind (haben Sie auch den Wind berücksichtigt?), können Sie mit 'OK' den Schuss auslösen.

9. Treffen

Nachdem Sie in Abschnitt 8 lesen konnten, wie man schießt, möchte ich Ihnen nun verraten, was man denn so alles treffen kann: In der größten Zahl der Fälle wird die Kugel wohl nur den Berg oder die Mauern der Burg treffen. In diesem Fall passiert nicht viel: Es entsteht ein in der Tiefe der Aufprallgeschwindigkeit proportionales Loch. Sollten Sie die Burg getroffen haben, so können außerdem ein paar Leute der Bevölkerung sterben.

Interessanter wird es dagegen, wenn Sie eine Kanone treffen. Diese wird dann nämlich mit einer Explosion verschwinden. Gleiches gilt für die Windfahne. Treffen Sie die Kammern für Geld oder Kugeln, so geht ein bestimmter Betrag verloren. Ein Treffer in der Pulverkammer bewirkt, dass das gesamte Pulver explodiert. Wenn Sie den König treffen, ist das besonders effektiv - Sie haben dann nämlich gewonnen.

Die hohe Kunst des Schießens, Fördertürme zu zerstören, ist eine schwierige Angelegenheit. Mitunter sind sie sowieso schon so hinter dem Berg versteckt, dass sie nur mit steilen Schüssen und viel Pulver zu erreichen sind. Nun kommt aber auch noch hinzu, dass man häufig eine ganze Reihe von Schüssen braucht, um einen Turm zu zerstören. Hier ein kleiner Tip: Schüsse, die den Turm seitlich treffen, sind eher von Erfolg gekrönt.

10. Spieloptionen

Da sich bei gleichguten Spielern manchmal Patt-Situationen einstellten, in denen keiner es schaffte, den anderen zu besiegen, kann es zu dem Problem kommen, dass ein Spiel quasi endlos dauern konnte. Insbesondere durch viel Volk und häufiges 'Anbauen' kann es passieren, dass man praktisch unbesiegbar wird.

Für diesen Fall gibt es im Hauptmenü daher noch verschiedene Optionen, mit welchen sich die Spieldauer begrenzen lässt:

  • es besteht die Möglichkeit das 'Anbauen' zu verbieten.
  • man kann eine maximale Rundenzahl festlegen oder auch unbegrenzt spielen. Ist die maximale Rundenzahl erreicht, wird das Spiel automatisch beendet. Sieger ist der, der sich in der besseren Situation befindet. Die Beurteilung erfolgt nach dem Gesamtwert von Kanonen, Fördertürmen, Geld, Pulver, Kugeln, Windfahne und Volk.
  • Man kann wählen, ob der König in einer aussichtslosen Lage von alleine kapituliert und damit das Spiel beendet.

11. Spielende

Wann ist das Spiel denn eigentlich zu Ende? Nun, ganz einfach: Der weit am häufigsten auftretende Fall ist, dass ein König getroffen wird. Es besteht jedoch auch die Möglichkeit, dass sich ein König von ganz alleine ergibt. Dies ist jedoch nur dann der Fall, wenn man keine Kanonen mehr besitzt, die finanziellen Mittel so bescheiden sind, dass man sich in absehbarer Zeit keine Kanone leisten können wird und auch das Volk aufgrund mangelnder Größe nicht die Hoffnung zulässt, durch Steuern genug Einkünfte zu schaffen. Die dritte, letzte und seltenste Möglichkeit für ein Spielende besteht darin, dass man kein Volk mehr hat, denn dann gibt es ja auch nichts mehr zu regieren. Dieser Fall tritt aber wirklich nur dann ein, wenn jemand sein Volk über längere Zeit mit gewaltigen Steuern zum Auswandern veranlasst hat.

ballerburg-1.2.0/doc/en/0000755000175000017500000000000012506012141014342 5ustar thomasthomasballerburg-1.2.0/doc/en/manual.html0000644000175000017500000003253712506012141016517 0ustar thomasthomas Manual for Ballerburg SDL

Manual for Ballerburg SDL

1. Objective of the game

Ballerburg is about two lords of castles pitted against each other, with the goal of defeating the opponent through targeted cannon shots. Players are able to obtain money from mining after buying shaft towers and from their people by levying taxes, and with these funds players may purchase e.g. new cannons and ammunition.

2. Game modes

There are different playing modes available in the game's settings menu, which can be brought up by pressing the Escape key. Ordinarily, the game is played between two human players. Another option is for one player to fight the computer. The computer can be set to be the player on the left or right hand side of the screen. It is also possible to let two computer- controlled players battle each other. Since it is possible to change playing modes mid-game, one can for example momentarily let the computer shoot for one's own side, or, if you're battling a computer-controlled player and the situation's dire, you might for instance momentarily switch modes to human vs. human and weaken the opponent by making bad decisions for him.

3. Player names and computer-controlled player

In the settings menu you can change the name of the human player. The name for the computer-controlled player can be changed under the label 'AI strategy'. Both settings can also safely be changed while a game is already running. The first player is always on the left side of the screen, and the second player is on the right side. The name of the computer-controlled player also stand for a certain strategy. The numbers next to 'AI strength' control the shooting accuracy of the computer players. The highest value 4 here means that almost every shot will hit its goal. The AI strategies differentiate into the priorities of the targets, i.e. some computer players shoot always at the cannons (if available), while some others rather try to hit the money of the opponent.

Oaf : No special target, just tries to hit the castle somewhere.
Yokel : First the money, then gunpowder/cannonballs, then the king
Boor : First the money, then cannons, then the king
Doofus : Money, gunpowder, cannonballs, shaft towers, cannons, king: Everything with the same probability
Fumbler : First cannons, then the king
Geezer : First the shaft towers, then cannons, then the king
Ruffian : Aims only at the king

Note that only Doofus, Fumbler, Geezer and Ruffian are able to buy shaft towers.

4. New game, choosing the castles

By clicking 'New game' in the settings menu, you can choose new castles for both sides and then start the new game by clicking 'OK'. Unless you've already extended the file with the castles, 'BALLER.DAT', you can decide between 9 different standard castles here. If both players are on the same skill level, you should of course select the same castles here, because the different castles have quite different strengths. If you choose smaller castles, the game normally won't last as long as with the bigger castles.

Here are now the values of the 9 standard castles:

Cannons Money Gunpowder Cannonballs People
2 400 180 12 200
5 500 180 12 270
5 500 150 14 270
6 500 190 12 300
3 500 120 6 220
4 500 120 10 240
6 800 120 12 500
3 500 120 9 500
1 1000 120 12 300

5. The battlefield: The mountain and the castles

After you've started a new game, the castles and the mountain will be drawn on the screen. Both, the position of the castles and the shape and height of the mountain are random (within certain limits). The castles consist of the following parts:

  • the walls and the roofs
  • the throne room
  • the various cannons
  • the powder magazine (one barrel contains 30 units of powder)
  • the cannonball magazine
  • the treasure chamber (one bag contains 150 units of money)
  • the vane (only the vane of the active player is hoisted)

The active wind information indicates the active player. If the player still has a vane, a zoomed version of the vane will be shown in the box at the bottom of the screen together with the strength and direction of the wind.

6. Course of the game

After starting the game, the players take their turns until one of them wins. Within a turn, the player can do several things: After clicking on either the powder magazine, the cannonballs magazine or the treasure chamber, the properties of the player will be displayed along with the market where the player can buy various things (more on this topic can be found in the next chapter). By clicking on the throne room, the king will comment on your latest progress.

The round can be completed in two ways: In case you don't have a cannon anymore, or you don't have enough powder or cannonballs or just don't like to shoot, you can simply click on 'Done' at the bottom of the screen. In all other cases you should choose the cannon that you want to shoot with, select the angle and powder and then click 'OK' to fire a cannonball. More on shooting can be found in chapter 8.

7. Your properties and the market

When clicking on one of the three magazines, you get the properties and market dialog which is described here now: In the section titled with 'You have' your properties and the amount of your people are listed. By clicking on the corresponding arrows, you can also adjust the taxes here that you demand from your people. Higher taxes mean more money per subject. But beware, when you raise the taxes, some of your people might leave your kingdom. On the other side, lowering the taxes might render your kingdom more attractive again, so that a certain amount of people might immigrate again. But like in real life, there are no exact values for the amount of immigrants, emmigrants and the amount of money you earn, they fluctuate within certain ranges. And be warned: If you raise the taxes too much, your income declines again – which people are really interested in generating earnings if they have to give everything away again?

The second part of the dialog is used for the market. Here you can buy certain things and repair your castle. You can trigger one of the actions by clicking on the price of the corresponding entry. However, this is only possible if the entry is active. In case it is inactive, you either do not have enough money or one of the following reasons occured:

  • You can have only one vane. If you already have one, the entry for a new vane is disabled.
  • You can not have more cannons than you had at the beginning of the game. In case you built additional walls at the places that are used for the cannons, you even can not fill these places with cannons anymore.
  • You can own five shaft towers at maximum. Depending on the size of your castle, this limit might even be smaller because you are only allowed to built shaft towers on your side of the mountain – and a bigger castle means a smaller mountain.

Please also note that you can not buy more cannonballs and gunpowder than you can store in your magazines. If you try to buy more, you still have to pay the money, but you can not store the bought goods! The treasure chamber behaves in a similar way: If it is completely filled, all additional earned money will be discarded.

Buying a shaft tower is long-term capital investment. For each shaft tower, you earn approximately between 40 and 70 money units each round.

Now a word about laying bricks: When you choose this menu entry, you get 20 bricks (the remeaining are shown at the bottom of the screen) which you have to lay immediately. Please note that you can only extend the existing walls of your castle, i.e. you can not lay the bricks somewhere up in the air. Furthermore, don't even think of laying the bricks at your opponent's castle, e.g. to block the other's cannons – of course this is forbidden, you are only allowed to extend your own castle.

Please also note that the prices at the market vary each round. Goods that are very cheap in one round might become expensive in the next one. (I won't tell more about the price system here, so you can be surprised again and again how expensive those shaft towers can be when you just thought that you were ready to buy one...)

8. Shooting

After clicking on one of the cannons, you have to adjust the cannon angle and the amount of gunpowder. By clicking on the single arrows, you adjust the values with single steps, and by clicking on the double arrows you adjust the powder by three units and the angle by 10 degrees. Powder can be selected from 5 units up to 20 units (unless you have less than 20 powder units in your magazine, then the maximum limit will be adjusted accordingly). Using 5 powder units or something similar is hardly of any use – unless you would like to destroy your own shaft towers!?!

The angle can be adjusted in the range of 0 up to 180 degrees. Angles above 90 degrees (or even 80 degrees if you've got very strong opposing wind) are also only useful for self-destructive players.

When you are satisfied with your settings (did you take the wind into account, too?), then you should press 'OK' to fire your cannonball.

9. Striking

In most cases the cannonballs only hit the mountain or the walls of the opponent's castle. The effect is not too exciting; the cannonball creates a crater with a size proportional to the impact velocity. In case you hit the castle, there is also the chance that you killed some of the opponent's people.

Striking a cannon is more exciting; the cannon is destroyed with a big explosion. The same applies to the vane. If you hit the cannonball magazine or the treasure chamber, a certain amount of the content will be destroyed. In case you hit the powder magazine, the whole stock of powder will explode. And if you hit the king, you can congratulate yourself – in this case you've won the game!

The fine art of shooting is to destroy the shaft towers. This is a very difficult task. First, they are located right behind the mountain anyway, so that you need a big angle and a lot of powder to hit them. But additionally you often have to hit them multiple times until they explode. Here's a little hint: If you hit the towers from the side instead from the top, chances are higher that they will be destroyed.

10. Game options

In case two players are playing at the same level, there can be a dead-lock situation where neither player manages to hit the opponent's king. Especially when both players have a lot of people, shaft towers and lay a lot of bricks, it can happen that they get almost unbeatable and these games last forever.

To avoid such neverending games, there are some options in the settings menu which can be used to limit the duration of a party:

  • You can prohibit the possibility to lay bricks.
  • You can set a maximum number of rounds (or play without limit). Once the maximum number of rounds has been reached, the party is stopped automatically. The player who is in the better situation will win the game. The decision is made according to the total value of available cannons, shaft towers, money, powder, cannonballs, vane and people.
  • You can choose whether the king is allowed to capitulate in hopeless situations.

11. The end of the game

How can a game end? In the most likely case, one of the two kings gets hit by a cannonball. There is also the possibility that one of the kings surrenders. However, this is only the case if you do not have any cannons left, your treasure room is almost empty and your amount of people is also very low – so it is very unlikely that you can buy a new cannon in the near future. Finally there is the possibility that you run out of people. But this case only happens if you're imposing too high taxes for several rounds, so that all your people emigrate.

ballerburg-1.2.0/COPYING.txt0000644000175000017500000010451312506012141015050 0ustar thomasthomas GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ballerburg-1.2.0/LIESMICH.txt0000644000175000017500000000555212506012141015140 0ustar thomasthomas ============================ = Ballerburg SDL v1.2.0 = ============================ Copyright (C) 1987, 1989 Eckhard Kruse Copyright (C) 2010, 2015 Thomas Huth Für meine Schwester Martina Huth - ich werde nie die vielen schönen Stunden vergessen, die wir mit diesem Spiel in unserer Kindheit hatten. 1) Lizenz --------- Dieses Programm ist freie Software. Sie können es unter den Bedingungen der GNU General Public License, wie von der Free Software Foundation veröffentlicht, weitergeben und/oder modifizieren, entweder gemäß Version 3 der Lizenz oder (nach Ihrer Option) jeder späteren Version. Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, dass es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License. Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem Programm erhalten haben. Falls nicht, siehe kann die Lizenz unter eingesehen werden. 2) Was ist Ballerburg? ---------------------- Ballerburg ist ein klassisches Burgenkampfspiel, bei dem sich zwei durch einen Berg getrennte Burgen mit ihren Kanonen gegenseitig bekämpfen müssen. Ballerburg wurde 1987 von Eckhard Kruse für den damals topaktuellen 16/32-Bit Computer Atari ST entwickelt. Jetzt, ein viertel Jahrhundert später liegt mit "Ballerburg SDL" nun die Anpassung des alten Source- codes, welcher von Eckhard Kruse freundlicherweise frei gegeben wurde, an GNU/Linux und andere Systeme mit SDL-Unterstützung vor. 3) Compilieren des Sourcecodes ------------------------------ Zum Compilieren wird der GCC C-Compiler, CMake und die SDL Bibliothek (http://www.libsdl.org/ - bevorzugt Version 1.2) inklusive Header bzw. Development-Paket benötig. Vor dem ersten Compilieren muss "cmake" mit dem Pfad zu den Sourcen als Parameter aufgerufen werden. Alternativ kann das "configure"-Script oder ein Tool wie "cmake-gui" benutzt werden. Nach dem Konfigurationsvorgang kann der Sourcecode mittels Aufruf von "make" compiliert und anschließen mittels "make install" installiert werden. 4) Spielstart ------------- Zum Starten des Spiels muss man das "ballerburg" Programm starten. Der Spielablauf sollte weitgehen selbsterklärend sein, notfalls gibt es im doc-Verzeichnis auch die Anleitung des orginalen Ballerburgs (Datei "anleitung.html"). Über die "ESC"-Taste erreicht man das Hauptmenü zum Einstellen der Spieler und um ein neues Spiel zu starten. Mittels der "f"-Taste kann zwischen dem Fenster- und Vollbildmodus gewechselt werden, und mit "q" kann das Spiel beendet werden. 5) Kontakt ---------- Bei Fragen, Anregung, Patches oder Kritik bitte eine Mail an folgende Adresse schreiben: huth at tuxfamily.org Und nun viel Spaß mit Ballerburg!