From dadd9561acc21afb76aad60a5e9dae9958356092 Mon Sep 17 00:00:00 2001 From: maxcodehack Date: Thu, 7 Jan 2021 12:53:28 +0000 Subject: [PATCH] Upload Jump'n'Bump sources git-svn-id: svn://kolibrios.org@8526 a494cfbc-eb01-0410-851d-a64ba20cac60 --- contrib/other/jumpnbump/AUTHORS | 61 + contrib/other/jumpnbump/COPYING | 340 ++ contrib/other/jumpnbump/ChangeLog | 95 + contrib/other/jumpnbump/LINKS | 8 + contrib/other/jumpnbump/Makefile | 24 + contrib/other/jumpnbump/SDL_mixer.h | 235 ++ contrib/other/jumpnbump/TODO | 5 + contrib/other/jumpnbump/config.h | 29 + contrib/other/jumpnbump/dj.h | 135 + contrib/other/jumpnbump/filter.c | 251 ++ contrib/other/jumpnbump/filter.h | 34 + contrib/other/jumpnbump/fireworks.c | 249 ++ contrib/other/jumpnbump/globals.h | 369 ++ contrib/other/jumpnbump/main.c | 3590 ++++++++++++++++++ contrib/other/jumpnbump/menu.c | 637 ++++ contrib/other/jumpnbump/sdl/Makefile | 23 + contrib/other/jumpnbump/sdl/gfx.c | 865 +++++ contrib/other/jumpnbump/sdl/input.c | 113 + contrib/other/jumpnbump/sdl/interrpt.c | 462 +++ contrib/other/jumpnbump/sdl/jumpnbump128.xpm | 196 + contrib/other/jumpnbump/sdl/jumpnbump32.xpm | 100 + contrib/other/jumpnbump/sdl/jumpnbump64.xpm | 132 + contrib/other/jumpnbump/sdl/sound.c | 568 +++ contrib/other/jumpnbump/stub.c | 24 + 24 files changed, 8545 insertions(+) create mode 100755 contrib/other/jumpnbump/AUTHORS create mode 100755 contrib/other/jumpnbump/COPYING create mode 100755 contrib/other/jumpnbump/ChangeLog create mode 100755 contrib/other/jumpnbump/LINKS create mode 100755 contrib/other/jumpnbump/Makefile create mode 100755 contrib/other/jumpnbump/SDL_mixer.h create mode 100755 contrib/other/jumpnbump/TODO create mode 100755 contrib/other/jumpnbump/config.h create mode 100755 contrib/other/jumpnbump/dj.h create mode 100755 contrib/other/jumpnbump/filter.c create mode 100755 contrib/other/jumpnbump/filter.h create mode 100755 contrib/other/jumpnbump/fireworks.c create mode 100755 contrib/other/jumpnbump/globals.h create mode 100755 contrib/other/jumpnbump/main.c create mode 100755 contrib/other/jumpnbump/menu.c create mode 100755 contrib/other/jumpnbump/sdl/Makefile create mode 100755 contrib/other/jumpnbump/sdl/gfx.c create mode 100755 contrib/other/jumpnbump/sdl/input.c create mode 100755 contrib/other/jumpnbump/sdl/interrpt.c create mode 100755 contrib/other/jumpnbump/sdl/jumpnbump128.xpm create mode 100755 contrib/other/jumpnbump/sdl/jumpnbump32.xpm create mode 100755 contrib/other/jumpnbump/sdl/jumpnbump64.xpm create mode 100755 contrib/other/jumpnbump/sdl/sound.c create mode 100755 contrib/other/jumpnbump/stub.c diff --git a/contrib/other/jumpnbump/AUTHORS b/contrib/other/jumpnbump/AUTHORS new file mode 100755 index 0000000000..35ea1bbae6 --- /dev/null +++ b/contrib/other/jumpnbump/AUTHORS @@ -0,0 +1,61 @@ +Jump'n'Bump is done by many people. The authors and contributors are listed +below. Invented and implemented was Jump'n'Bump by Brainchild Design as a +DOS game. Later the source was released and Chuck Mason did the port to +Linux using SDL. Some people contributed various stuff to it. +The current maintainer is Florian Schulze. + +Mattias Brynervall + Original DOS code. + +Andreas Brynervall +Martin Magnusson + Original Graphics. + +Anders Nilsson + Original Music. + +Chuck Mason + The first Linux port using SDL. + +Philippe Brochard + The jbmenu.tcl script. + +Joe Wreschnig + The manual page + +"timecop" + pack and unpack. + +Jon Atkins + The network code of the Linux version. + +Gürkan Sengün + Made the website http://www.jumpbump.mine.nu/ and hosts it. Promotion. + +Florian Schulze + Cleaned up code. Added scaling graphics mode (800x512). Fixed sound. + +Ben Hines + MacOS X fixes. + +Gil Megidish + Made the Kaillera network version. + +David García Rodríguez + Level making tutorial. + +Ryan C. Gordon + Made networking possible again. + +Martin Willemoes Hansen + The python frontend. + http://mwh.sysrq.dk/programs/programs.phtml + +Alessandro Gatti + FreeBSD fixes. + +Ulrich Eckhardt + Cleanup and small patches for enhanced networking. + +Ricardo Cruz + AI functions diff --git a/contrib/other/jumpnbump/COPYING b/contrib/other/jumpnbump/COPYING new file mode 100755 index 0000000000..d60c31a97a --- /dev/null +++ b/contrib/other/jumpnbump/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + 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 +convey 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This 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 Library General +Public License instead of this License. diff --git a/contrib/other/jumpnbump/ChangeLog b/contrib/other/jumpnbump/ChangeLog new file mode 100755 index 0000000000..e1c4617876 --- /dev/null +++ b/contrib/other/jumpnbump/ChangeLog @@ -0,0 +1,95 @@ +27 Jun 2004 - 1.51 + - refactored code to make it a bit simpler + - Added AI by Ricardo Cruz + +30 Mar 2004 - 1.42 + - added support for gzip and bzip2 packed levels. + +21 Mar 2003 - 1.41 + - new scaling filter which works with 8bit graphics. Removed the old scaler + completely, now fading and everything else works in scaled up mode. + - another attempt to fix sound on big endian systems. + +Sep 2002 - 1.40 + - manpage update + - joystick support added + - freebsd ports (thanks rigel from #demoscene) + - a while back network code using kaillera was send to me by Gil Megidish, + it's not enabled, because it doesn't seem to work good enough. + +17 Aug 2002 - 1.39 + - added -noflies option + - added client/server networking. Thanks to Ryan C. Gordon who did the base + work for it. + +11 Aug 2002 - 1.35 + - gobpack added + - documentation updated + - little fixes here and there + +2 Aug 2002 - 1.34 + - fixed too dark font + - attempt to fix sound and scaleup on big endian systems + +5 Jul 2002 - 1.33 + - added -musicnosound option + +15 Jun 2002 - 1.32 + - fix for off by one in -mirror + add icon for application (macosx,windows,x) + +10 Jun 2002 - 1.31 + - rename jbmenu.tcl to jnbmenu.tcl, make it +x, add + options for -mirror and -scaleup + update manpage and -h with -scaleup + update makefiles accordingly + rename pack/unpack to jnbpack/jnbunpack + set gametitle + +9 Jun 2002 - 1.3 + - Added -mirror commandline option to play the level mirrored + - Deleting temporary music file + +- 1.2 + - MacOS X fixes + - some endian fixes + +24 Feb 2002 - 1.1 + - fixed timing problems + - fixed crash when temporary music can't be written + +22 Feb 2002 - 1.0 + - working sound + - new scaling graphics mode + - cleaned up code + +=========================================================================== +This is the changelog of the linux version from which this port is derived. + +25 Feb 2001 - 0.69 + initial linux port, worked fine with freebsd too (chuck mason) + +26 Feb 2001 - 0.69 + made sound be played (chuck mason) + +03 Mar 2001 - 0.70 + fixing fps (longislandman) + changing player input: 4 player at one keyboard (tarzeau) + pack/unpack which packs/unpacks the leveldata (timecop) + +?? Mar 2001 - 0.70 + network code has been written (longislandman, jonatkins.org) + it werks but we won't release it until it's good for the masses, + for test and fun play come join #keen on irc.linux.com + (be sure to have one udp port open if you have a firewall, + and also have sdl-mixer, sdl and sdl-net) + +16 Mar 2001 - 0.70 + did a new screenshot http://jumpbump.mine.nu/port/jumpbumprocks.jpg + wrote a little faq http://jumpbump.mine.nu/port/jumpbumpfaq.txt + put online level-selector-menu http://jumpbump.mine.nu/port/jbmenu.tcl + (received from philippe brochard, thank you!) + +20 Mar 2001 - 0.72 + repackaged tarballs with network code jnb-net.tar.gz, + menusystem and unpack/pack diff --git a/contrib/other/jumpnbump/LINKS b/contrib/other/jumpnbump/LINKS new file mode 100755 index 0000000000..423609639f --- /dev/null +++ b/contrib/other/jumpnbump/LINKS @@ -0,0 +1,8 @@ +http://www.jumpbump.mine.nu/ +http://www.icculus.org/jumpnbump/ +http://freshmeat.net/projects/jumpnbump/ +http://www.geocities.com/bkron2000 +http://bloodybunnies.8m.com/ +http://gohanz.www7.50megs.com/jumpbump/ +http://brainchilddesign.com/games/jumpnbump/index.html +http://www.libsdl.org/ diff --git a/contrib/other/jumpnbump/Makefile b/contrib/other/jumpnbump/Makefile new file mode 100755 index 0000000000..c5f331ea42 --- /dev/null +++ b/contrib/other/jumpnbump/Makefile @@ -0,0 +1,24 @@ +CC = kos32-gcc +LD = kos32-ld + +SDK_DIR = $(abspath ../../sdk) + +CFLAGS = -c -fno-ident -O2 -fomit-frame-pointer -fno-ident -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 -Dstricmp=strcasecmp -DZLIB_SUPPORT -Dstrnicmp=strncasecmp -DUSE_SDL -DNDEBUG +LDFLAGS = -static -S -nostdlib -T $(SDK_DIR)/sources/newlib/app.lds --image-base 0 + +INCLUDES = -I $(SDK_DIR)/sources/newlib/libc/include -I. -I$(SDK_DIR)/sources/SDL-1.2.2_newlib/include -I $(SDK_DIR)/sources/zlib +LIBPATH = -L $(SDK_DIR)/lib -L /home/autobuild/tools/win32/mingw32/lib -Lsdl + +SRC = fireworks.c main.c menu.c filter.c stub.c + +OBJECTS = $(patsubst %.c, %.o, $(SRC)) + +default: $(patsubst %.c,%.o,$(SRC)) + kos32-ld $(LDFLAGS) $(LIBPATH) --subsystem native -o jumpnbump $(OBJECTS) -ls -lSDLn -lsound -lz -lgcc -lc.dll + objcopy jumpnbump -O binary + +%.o : %.c Makefile $(SRC) + $(CC) $(CFLAGS) $(INCLUDES) -o $@ $< + +clean: + rm *.o diff --git a/contrib/other/jumpnbump/SDL_mixer.h b/contrib/other/jumpnbump/SDL_mixer.h new file mode 100755 index 0000000000..b186e7226c --- /dev/null +++ b/contrib/other/jumpnbump/SDL_mixer.h @@ -0,0 +1,235 @@ +/* + MIXERLIB: An audio mixer library based on the SDL library + Copyright (C) 1997-1999 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + 5635-34 Springhouse Dr. + Pleasanton, CA 94588 (USA) + slouken@devolution.com +*/ + +#ifndef _MIXER_H_ +#define _MIXER_H_ + +#include "SDL_types.h" +#include "SDL_rwops.h" +#include "SDL_audio.h" +#include "SDL_byteorder.h" +#include "begin_code.h" + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/* The default mixer has 8 simultaneous mixing channels */ +#ifndef MIX_CHANNELS +#define MIX_CHANNELS 8 +#endif + +/* Good default values for a PC soundcard */ +#define MIX_DEFAULT_FREQUENCY 22050 +#if SDL_BYTEORDER == SDL_LIL_ENDIAN +#define MIX_DEFAULT_FORMAT AUDIO_S16LSB +#else +#define MIX_DEFAULT_FORMAT AUDIO_S16MSB +#endif +#define MIX_DEFAULT_CHANNELS 2 +#define MIX_MAX_VOLUME 128 /* Volume of a chunk */ + +/* The internal format for an audio chunk */ +typedef struct { + int allocated; + Uint8 *abuf; + Uint32 alen; + Uint8 volume; /* Per-sample volume, 0-128 */ +} Mix_Chunk; + +/* The different fading types supported */ +typedef enum { + MIX_NO_FADING, + MIX_FADING_OUT, + MIX_FADING_IN +} Mix_Fading; + +/* The internal format for a music chunk interpreted via mikmod */ +typedef struct _Mix_Music Mix_Music; + +/* Open the mixer with a certain audio format */ +extern DECLSPEC int Mix_OpenAudio(int frequency, Uint16 format, int channels, + int chunksize); + +/* Dynamically change the number of channels managed by the mixer. + If decreasing the number of channels, the upper channels are + stopped. + This function returns the new number of allocated channels. + */ +extern DECLSPEC int Mix_AllocateChannels(int numchans); + +/* Find out what the actual audio device parameters are. + This function returns 1 if the audio has been opened, 0 otherwise. + */ +extern DECLSPEC int Mix_QuerySpec(int *frequency,Uint16 *format,int *channels); + +/* Load a wave file or a music (.mod .s3m .it .xm) file */ +extern DECLSPEC Mix_Chunk *Mix_LoadWAV_RW(SDL_RWops *src, int freesrc); +#define Mix_LoadWAV(file) Mix_LoadWAV_RW(SDL_RWFromFile(file, "rb"), 1) +extern DECLSPEC Mix_Music *Mix_LoadMUS(const char *file); + +#if 0 /* This hasn't been hooked into music.c yet */ +/* Load a music file from an SDL_RWop object (MikMod-specific currently) + Matt Campbell (matt@campbellhome.dhs.org) April 2000 */ +extern DECLSPEC Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw); +#endif + +/* Load a wave file of the mixer format from a memory buffer */ +extern DECLSPEC Mix_Chunk *Mix_QuickLoad_WAV(Uint8 *mem); + +/* Free an audio chunk previously loaded */ +extern DECLSPEC void Mix_FreeChunk(Mix_Chunk *chunk); +extern DECLSPEC void Mix_FreeMusic(Mix_Music *music); + +/* Set a function that is called after all mixing is performed. + This can be used to provide real-time visual display of the audio stream + or add a custom mixer filter for the stream data. +*/ +extern DECLSPEC void Mix_SetPostMix(void (*mix_func) + (void *udata, Uint8 *stream, int len), void *arg); + +/* Add your own music player or additional mixer function. + If 'mix_func' is NULL, the default music player is re-enabled. + */ +extern DECLSPEC void Mix_HookMusic(void (*mix_func) + (void *udata, Uint8 *stream, int len), void *arg); + +/* Add your own callback when the music has finished playing. + */ +extern DECLSPEC void Mix_HookMusicFinished(void (*music_finished)(void)); + +/* Get a pointer to the user data for the current music hook */ +extern DECLSPEC void *Mix_GetMusicHookData(void); + +/* Reserve the first channels (0 -> n-1) for the application, i.e. don't allocate + them dynamically to the next sample if requested with a -1 value below. + Returns the number of reserved channels. + */ +extern DECLSPEC int Mix_ReserveChannels(int num); + +/* Channel grouping functions */ + +/* Attach a tag to a channel. A tag can be assigned to several mixer + channels, to form groups of channels. + If 'tag' is -1, the tag is removed (actually -1 is the tag used to + represent the group of all the channels). + Returns true if everything was OK. + */ +extern DECLSPEC int Mix_GroupChannel(int which, int tag); +/* Assign several consecutive channels to a group */ +extern DECLSPEC int Mix_GroupChannels(int from, int to, int tag); +/* Finds the first available channel in a group of channels */ +extern DECLSPEC int Mix_GroupAvailable(int tag); +/* Returns the number of channels in a group. This is also a subtle + way to get the total number of channels when 'tag' is -1 + */ +extern DECLSPEC int Mix_GroupCount(int tag); +/* Finds the "oldest" sample playing in a group of channels */ +extern DECLSPEC int Mix_GroupOldest(int tag); +/* Finds the "most recent" (i.e. last) sample playing in a group of channels */ +extern DECLSPEC int Mix_GroupNewer(int tag); + +/* Play an audio chunk on a specific channel. + If the specified channel is -1, play on the first free channel. + If 'loops' is greater than zero, loop the sound that many times. + If 'loops' is -1, loop inifinitely (~65000 times). + Returns which channel was used to play the sound. +*/ +#define Mix_PlayChannel(channel,chunk,loops) Mix_PlayChannelTimed(channel,chunk,loops,-1) +/* The same as above, but the sound is played at most 'ticks' milliseconds */ +extern DECLSPEC int Mix_PlayChannelTimed(int channel, Mix_Chunk *chunk, int loops, int ticks); +extern DECLSPEC int Mix_PlayMusic(Mix_Music *music, int loops); + +/* Fade in music or a channel over "ms" milliseconds, same semantics as the "Play" functions */ +extern DECLSPEC int Mix_FadeInMusic(Mix_Music *music, int loops, int ms); +#define Mix_FadeInChannel(channel,chunk,loops,ms) Mix_FadeInChannelTimed(channel,chunk,loops,ms,-1) +extern DECLSPEC int Mix_FadeInChannelTimed(int channel, Mix_Chunk *chunk, int loops, int ms, int ticks); + +/* Set the volume in the range of 0-128 of a specific channel or chunk. + If the specified channel is -1, set volume for all channels. + Returns the original volume. + If the specified volume is -1, just return the current volume. +*/ +extern DECLSPEC int Mix_Volume(int channel, int volume); +extern DECLSPEC int Mix_VolumeChunk(Mix_Chunk *chunk, int volume); +extern DECLSPEC int Mix_VolumeMusic(int volume); + +/* Halt playing of a particular channel */ +extern DECLSPEC int Mix_HaltChannel(int channel); +extern DECLSPEC int Mix_HaltGroup(int tag); +extern DECLSPEC int Mix_HaltMusic(void); + +/* Change the expiration delay for a particular channel. + The sample will stop playing after the 'ticks' milliseconds have elapsed, + or remove the expiration if 'ticks' is -1 +*/ +extern DECLSPEC int Mix_ExpireChannel(int channel, int ticks); + +/* Halt a channel, fading it out progressively till it's silent + The ms parameter indicates the number of milliseconds the fading + will take. + */ +extern DECLSPEC int Mix_FadeOutChannel(int which, int ms); +extern DECLSPEC int Mix_FadeOutGroup(int tag, int ms); +extern DECLSPEC int Mix_FadeOutMusic(int ms); + +/* Query the fading status of a channel */ +extern DECLSPEC Mix_Fading Mix_FadingMusic(void); +extern DECLSPEC Mix_Fading Mix_FadingChannel(int which); + +/* Pause/Resume a particular channel */ +extern DECLSPEC void Mix_Pause(int channel); +extern DECLSPEC void Mix_Resume(int channel); +extern DECLSPEC int Mix_Paused(int channel); + +/* Pause/Resume the music stream */ +extern DECLSPEC void Mix_PauseMusic(void); +extern DECLSPEC void Mix_ResumeMusic(void); +extern DECLSPEC void Mix_RewindMusic(void); +extern DECLSPEC int Mix_PausedMusic(void); + +/* Check the status of a specific channel. + If the specified channel is -1, check all channels. +*/ +extern DECLSPEC int Mix_Playing(int channel); +extern DECLSPEC int Mix_PlayingMusic(void); + +/* Stop music and set external music playback command */ +extern DECLSPEC int Mix_SetMusicCMD(const char *command); + +/* Close the mixer, halting all playing audio */ +extern DECLSPEC void Mix_CloseAudio(void); + +/* We'll use SDL for reporting errors */ +#define Mix_SetError SDL_SetError +#define Mix_GetError SDL_GetError + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include "close_code.h" + +#endif /* _MIXER_H_ */ diff --git a/contrib/other/jumpnbump/TODO b/contrib/other/jumpnbump/TODO new file mode 100755 index 0000000000..d48380905d --- /dev/null +++ b/contrib/other/jumpnbump/TODO @@ -0,0 +1,5 @@ +- add network code back in +- port for dreamcast + +Debian: +- the game isn't in update-menus diff --git a/contrib/other/jumpnbump/config.h b/contrib/other/jumpnbump/config.h new file mode 100755 index 0000000000..b4914b589a --- /dev/null +++ b/contrib/other/jumpnbump/config.h @@ -0,0 +1,29 @@ +/* + * config.h + * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/ + * + * Copyright (C) 2001 Chuck Mason + * + * Copyright (C) 2002 Florian Schulze + * + * This file is part of Jump'n'Bump. + * + * Jump'n'Bump 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. + * + * Jump'n'Bump 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#endif diff --git a/contrib/other/jumpnbump/dj.h b/contrib/other/jumpnbump/dj.h new file mode 100755 index 0000000000..c5d6b5aaa3 --- /dev/null +++ b/contrib/other/jumpnbump/dj.h @@ -0,0 +1,135 @@ +/* + * dj.h + * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/ + * + * Copyright (C) 2002 Florian Schulze - crow@icculus.org + * + * This file is part of Jump'n'Bump. + * + * Jump'n'Bump 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. + * + * Jump'n'Bump 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#ifdef DOS +#include +#include +#include +#include +#endif + +#define DJ_SD_TYPE_NOSOUND 0 +#define DJ_SD_TYPE_SBLASTER 1 + +#define DJ_SFX_TYPE_SSS 0 +#define DJ_SFX_TYPE_WAV 1 +#define DJ_SFX_TYPE_SMP 2 + + +typedef struct dj_hardware_info { + char sd_type; + short sd_version; + short port; + char irq; + char dma; +} dj_hardware_info; + +typedef struct dj_mixing_info { + char sfx_volume, num_sfx_channels; + char mod_volume, num_mod_channels; + char stereo_mix, auto_mix; + unsigned short mixing_freq; + unsigned short dma_time, dmabuf_len; + char cur_dmabuf; + unsigned long dmabuf_address[2]; + char *mixed_buf; +} dj_mixing_info; + +typedef struct sfx_data { + char priority; + unsigned short default_freq; + char default_volume; + unsigned long length; + char loop; + unsigned long loop_start, loop_length; + unsigned char *buf; +} sfx_data; + +typedef struct dj_mod_info { + char num_channels; + char speed; + short bpm; + char order_pos; + char pat_pos; + char name[20]; + struct { + char name[22]; + unsigned short length; + char finetune; + char volume; + unsigned short loop_start; + unsigned short loop_length; + char *buf; + } samples[31]; + char song_length; + char num_pat; + char pat_order[128]; + char *pat[128]; +} dj_mod_info; + + +extern char dj_init(void); +extern void dj_deinit(void); +extern void dj_start(void); +extern void dj_stop(void); +extern void dj_set_nosound(char flag); +extern char dj_set_sd(char sd_type, short port, char irq, char dma); +extern char dj_autodetect_sd(void); +extern void dj_get_sd_string(char *strbuf); +extern char dj_set_stereo(char flag); +extern void dj_reverse_stereo(char flag); +extern void dj_set_auto_mix(char flag); +extern unsigned short dj_set_mixing_freq(unsigned short freq); +extern void dj_set_dma_time(unsigned short time); +extern char dj_get_hardware_info(dj_hardware_info *ptr); +extern char dj_get_mixing_info(dj_mixing_info *ptr); +extern char dj_get_mod_info(char mod_num, dj_mod_info *ptr); +extern void dj_set_fake_vu_speed(unsigned char speed); +extern unsigned char dj_get_fake_vu(char channel); +extern char dj_reset_sd(void); + +extern char dj_mix_needed(void); +extern void dj_mix(void); + +extern char dj_set_num_sfx_channels(char num_channels); +extern void dj_set_sfx_volume(char volume); +extern char dj_get_sfx_volume(void); +extern void dj_play_sfx(unsigned char sfx_num, unsigned short freq, char volume, char panning, unsigned short delay, char channel); +extern char dj_get_sfx_settings(unsigned char sfx_num, sfx_data *data); +extern char dj_set_sfx_settings(unsigned char sfx_num, sfx_data *data); +extern void dj_set_sfx_channel_volume(char channel_num, char volume); +extern void dj_stop_sfx_channel(char channel_num); +extern char dj_load_sfx(unsigned char *file_handle, char *filename, int file_length, char sfx_type, unsigned char sfx_num); +extern void dj_free_sfx(unsigned char sfx_num); + +extern char dj_ready_mod(char mod_num); +extern char dj_start_mod(void); +extern void dj_stop_mod(void); +extern void dj_set_mod_volume(char volume); +extern char dj_get_mod_volume(void); +extern char dj_load_mod(unsigned char *file_handle, char *filename, char mod_num); +extern void dj_free_mod(char mod_num); + diff --git a/contrib/other/jumpnbump/filter.c b/contrib/other/jumpnbump/filter.c new file mode 100755 index 0000000000..988788c28e --- /dev/null +++ b/contrib/other/jumpnbump/filter.c @@ -0,0 +1,251 @@ +/* + * filter.c + * Copyright (C) 2003 Florian Schulze + * + * This file is part of Jump'n'Bump. + * + * Jump'n'Bump 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. + * + * Jump'n'Bump 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + The following scaling filter is called advancedmame2x. + The implementation found here was possible because of the great ideas of + Lucas Pope. + */ + +typedef unsigned char byte; +static int scale2x_inited = 0; +static byte lookup_map[4*16]; + +void init_scale2x(void) +{ + int i; + + if (scale2x_inited) + return; + + //------------------------------------------------------------------------- + // scale2x takes the following source: + // A B C + // D E F + // G H I + // + // and doubles the size of E to produce: + // E0 E1 + // E2 E3 + // + // E0 = D == B && B != F && D != H ? D : E; + // E1 = B == F && B != D && F != H ? F : E; + // E2 = D == H && D != B && H != F ? D : E; + // E3 = H == F && D != H && B != F ? F : E; + // + // to make this comparison regimen faster, we encode source color + // equivalency into a single byte with the getCode() macro + // + // #define getCode(b,f,h,d) ( (b == f)<<0 | (f == h)<<1 | (h == d)<<2 | (d == b)<<3 ) + + // encode the scale2x conditionals into a lookup code + for (i=0; i<16; i++) { + // E0 = D == B && B != F && D != H ? D : E; // 10-0 => 1000 or 1010 => 8 or A + lookup_map[0*16+i] = (i == 0x8 || i == 0xA) ? 0 : 1; + // E1 = B == F && B != D && F != H ? F : E; // 0-01 => 0101 or 0001 => 5 or 1 + lookup_map[1*16+i] = (i == 0x5 || i == 0x1) ? 2 : 1; + // E2 = D == H && D != B && H != F ? D : E; // 010- => 0101 or 0100 => 5 or 4 + lookup_map[2*16+i] = (i == 0x4 || i == 0x5) ? 0 : 1; + // E3 = H == F && D != H && B != F ? F : E; // -010 => 1010 or 0010 => A or 2 + lookup_map[3*16+i] = (i == 0xA || i == 0x2) ? 2 : 1; + } +} + +void do_scale2x(unsigned char *src, + int src_width, + int src_height, + unsigned char *dst) +{ + int x; + int y; + int dst_width = src_width * 2; + int dst_height = src_height * 2; + int code; + byte rowColors[3]; + byte *e0; + byte *e1; + byte *e2; + byte *e3; + + if (!scale2x_inited) + init_scale2x(); + + // special top case - b is always unknown + { + byte *d; + byte *e; + byte *f; + byte *h; + + e0 = &dst[0]; + e1 = &dst[1]; + e2 = &dst[dst_width]; + e3 = &dst[dst_width + 1]; + e = &src[0]; + f = &src[1]; + h = &src[src_width]; + + // special left case - d is unknown + rowColors[0] = *e; + rowColors[1] = *e; + rowColors[2] = *f; + code = ( (*f == *h)<<1 ); + *e0 = rowColors[lookup_map[0*16+code]]; + *e1 = rowColors[lookup_map[1*16+code]]; + *e2 = rowColors[lookup_map[2*16+code]]; + *e3 = rowColors[lookup_map[3*16+code]]; + e++; f++; h++; + d = &src[src_width]; // (src_width - 1) + 1 + e0+=2; e1+=2; e2+=2; e3+=2; + + // normal case + for (x=1; x<(src_width-1); x++) { + rowColors[0] = *d; + rowColors[1] = *e; + rowColors[2] = *f; + code = ( (*f == *h)<<1 | (*h == *d)<<2 ); + *e0 = rowColors[lookup_map[0*16+code]]; + *e1 = rowColors[lookup_map[1*16+code]]; + *e2 = rowColors[lookup_map[2*16+code]]; + *e3 = rowColors[lookup_map[3*16+code]]; + d++; e++; f++; h++; + e0+=2; e1+=2; e2+=2; e3+=2; + } + + // special right case - f is unknown + rowColors[0] = *d; + rowColors[1] = *e; + rowColors[2] = *e; + code = ( (*h == *d)<<2 ); + *e0 = rowColors[lookup_map[0*16+code]]; + *e1 = rowColors[lookup_map[1*16+code]]; + *e2 = rowColors[lookup_map[2*16+code]]; + *e3 = rowColors[lookup_map[3*16+code]]; + } + + // top and bottom always known + for (y=1; y<(src_height-1); y++) { + byte *b; + byte *d; + byte *e; + byte *f; + byte *h; + + e0 = &dst[y*dst_width*2]; + e1 = &dst[y*dst_width*2 + 1]; + e2 = &dst[y*dst_width*2 + dst_width]; + e3 = &dst[y*dst_width*2 + dst_width + 1]; + b = &src[y * src_width - src_width]; + e = &src[y * src_width]; + f = &src[y * src_width + 1]; + h = &src[y * src_width + src_width]; + + // special left case - d is unknown + rowColors[0] = *e; + rowColors[1] = *e; + rowColors[2] = *f; + code = ( (*b == *f)<<0 | (*f == *h)<<1 ); + *e0 = rowColors[lookup_map[0*16+code]]; + *e1 = rowColors[lookup_map[1*16+code]]; + *e2 = rowColors[lookup_map[2*16+code]]; + *e3 = rowColors[lookup_map[3*16+code]]; + b++; e++; f++; h++; + d = &src[y * src_width]; // (y * src_width - 1) + 1 + e0+=2; e1+=2; e2+=2; e3+=2; + + // normal case + for (x=1; x<(src_width-1); x++) { + rowColors[0] = *d; + rowColors[1] = *e; + rowColors[2] = *f; + code = ( (*b == *f)<<0 | (*f == *h)<<1 | (*h == *d)<<2 | (*d == *b)<<3 ); + *e0 = rowColors[lookup_map[0*16+code]]; + *e1 = rowColors[lookup_map[1*16+code]]; + *e2 = rowColors[lookup_map[2*16+code]]; + *e3 = rowColors[lookup_map[3*16+code]]; + b++; d++; e++; f++; h++; + e0+=2; e1+=2; e2+=2; e3+=2; + } + + // special right case - f is unknown + rowColors[0] = *d; + rowColors[1] = *e; + rowColors[2] = *e; + code = ( (*h == *d)<<2 | (*d == *b)<<3 ); + *e0 = rowColors[lookup_map[0*16+code]]; + *e1 = rowColors[lookup_map[1*16+code]]; + *e2 = rowColors[lookup_map[2*16+code]]; + *e3 = rowColors[lookup_map[3*16+code]]; + } + + // special bottom case - h is always unknown + { + byte *b; + byte *d; + byte *e; + byte *f; + + e0 = &dst[y*dst_width*2]; + e1 = &dst[y*dst_width*2 + 1]; + e2 = &dst[y*dst_width*2 + dst_width]; + e3 = &dst[y*dst_width*2 + dst_width + 1]; + b = &src[y * src_width - src_width]; + e = &src[y * src_width]; + f = &src[y * src_width + 1]; + + // special left case - d is unknown + rowColors[0] = *e; + rowColors[1] = *e; + rowColors[2] = *f; + code = ( (*b == *f)<<0 ); + *e0 = rowColors[lookup_map[0*16+code]]; + *e1 = rowColors[lookup_map[1*16+code]]; + *e2 = rowColors[lookup_map[2*16+code]]; + *e3 = rowColors[lookup_map[3*16+code]]; + b++; e++; f++; + d = &src[y * src_width]; // (y * src_width - 1) + 1 + e0+=2; e1+=2; e2+=2; e3+=2; + + // normal case + for (x=1; x<(src_width-1); x++) { + rowColors[0] = *d; + rowColors[1] = *e; + rowColors[2] = *f; + code = ( (*b == *f)<<0 | (*d == *b)<<3 ); + *e0 = rowColors[lookup_map[0*16+code]]; + *e1 = rowColors[lookup_map[1*16+code]]; + *e2 = rowColors[lookup_map[2*16+code]]; + *e3 = rowColors[lookup_map[3*16+code]]; + b++; d++; e++; f++; + e0+=2; e1+=2; e2+=2; e3+=2; + } + + // special right case - f is unknown + rowColors[0] = *d; + rowColors[1] = *e; + rowColors[2] = *e; + code = ( (*d == *b)<<3 ); + *e0 = rowColors[lookup_map[0*16+code]]; + *e1 = rowColors[lookup_map[1*16+code]]; + *e2 = rowColors[lookup_map[2*16+code]]; + *e3 = rowColors[lookup_map[3*16+code]]; + } +} diff --git a/contrib/other/jumpnbump/filter.h b/contrib/other/jumpnbump/filter.h new file mode 100755 index 0000000000..42d87d36a0 --- /dev/null +++ b/contrib/other/jumpnbump/filter.h @@ -0,0 +1,34 @@ +/* + * config.h + * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/ + * + * Copyright (C) 2001 Chuck Mason + * + * Copyright (C) 2002 Florian Schulze + * + * This file is part of Jump'n'Bump. + * + * Jump'n'Bump 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. + * + * Jump'n'Bump 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __FILTER_H__ +#define __FILTER_H__ + +void do_scale2x(unsigned char *src, + int src_width, + int src_height, + unsigned char *dst); + +#endif // __FILTER_H__ diff --git a/contrib/other/jumpnbump/fireworks.c b/contrib/other/jumpnbump/fireworks.c new file mode 100755 index 0000000000..e106b085ae --- /dev/null +++ b/contrib/other/jumpnbump/fireworks.c @@ -0,0 +1,249 @@ +/* + * fireworks.c + * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/ + * + * Copyright (C) 2001 Chuck Mason + * + * Copyright (C) 2002 Florian Schulze + * + * This file is part of Jump'n'Bump. + * + * Jump'n'Bump 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. + * + * Jump'n'Bump 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "globals.h" + +extern unsigned int ban_map[17][22]; + +void fireworks(void) +{ + char *handle; + int c1, c2; + int s1, s2, s3; + char pal[768]; + struct { + int used, direction, colour; + int x, y; + int x_add, y_add; + int timer; + int anim, frame, frame_tick, image; + } rabbits[20]; + struct { + int x, y; + int old_x, old_y; + int col; + int back[2]; + } stars[300]; + + register_background(NULL, NULL); + + if ((handle = dat_open("level.pcx")) == 0) { + strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n"); + return; + } + read_pcx(handle, mask_pic, JNB_WIDTH*JNB_HEIGHT, pal); + + memset(mask_pic, 0, JNB_WIDTH*JNB_HEIGHT); + register_mask(mask_pic); + + recalculate_gob(&rabbit_gobs, pal); + recalculate_gob(&object_gobs, pal); + + memset(ban_map, 0, sizeof(ban_map)); + + fillpalette(0, 0, 0); + + draw_begin(); + + for (c2 = JNB_HEIGHT - 63; c2 < JNB_HEIGHT; c2++) { + clear_lines(0, c2, 1, get_color((c2 - 192) >> 2, pal)); + clear_lines(1, c2, 1, get_color((c2 - 192) >> 2, pal)); + } + + draw_end(); + + setpalette(0, 256, pal); + + for (c1 = 0; c1 < 20; c1++) + rabbits[c1].used = 0; + + rabbits[0].used = 1; + rabbits[0].colour = rnd(4); + rabbits[0].x = (int) (150 + rnd(100)) << 16; + rabbits[0].y = 256 << 16; + rabbits[0].x_add = ((int) rnd(65535) << 1) - 65536; + if (rabbits[0].x_add > 0) + rabbits[0].direction = 0; + else + rabbits[0].direction = 1; + rabbits[0].y_add = -262144 + (rnd(16384) * 5); + rabbits[0].timer = 30 + rnd(150); + rabbits[0].anim = 2; + rabbits[0].frame = 0; + rabbits[0].frame_tick = 0; + rabbits[0].image = player_anims[rabbits[0].anim].frame[rabbits[0].frame].image + rabbits[0].colour * 18 + rabbits[0].direction * 9; + + draw_begin(); + for (c1 = 0; c1 < 300; c1++) { + s1 = rnd(JNB_WIDTH); + s2 = rnd(JNB_HEIGHT); + s3 = 30 - rnd(7); + stars[c1].x = stars[c1].old_x = (s1 << 16); + stars[c1].y = stars[c1].old_y = (s2 << 16); + stars[c1].col = s3; + stars[c1].back[0] = stars[c1].back[1] = get_pixel(0, s1, s2); + } + draw_end(); + + dj_set_nosound(0); + + main_info.page_info[0].num_pobs = 0; + main_info.page_info[1].num_pobs = 0; + main_info.view_page = 0; + main_info.draw_page = 1; + + while (key_pressed(1) == 0) { + + dj_mix(); + intr_sysupdate(); + + for (c1 = 0; c1 < 300; c1++) { + stars[c1].old_x = stars[c1].x; + stars[c1].old_y = stars[c1].y; + stars[c1].y -= (int) (31 - stars[c1].col) * 16384; + if ((stars[c1].y >> 16) < 0) + stars[c1].y += JNB_HEIGHT << 16; + if ((stars[c1].y >> 16) >= JNB_HEIGHT) + stars[c1].y -= JNB_HEIGHT << 16; + } + + for (c1 = 0, c2 = 0; c1 < 20; c1++) { + if (rabbits[c1].used == 1) + c2++; + } + if ((c2 == 0 && rnd(10000) < 200) || (c2 == 1 && rnd(10000) < 150) || (c2 == 2 && rnd(10000) < 100) || (c2 == 3 && rnd(10000) < 50)) { + for (c1 = 0; c1 < 20; c1++) { + if (rabbits[c1].used == 0) { + rabbits[c1].used = 1; + rabbits[c1].colour = rnd(4); + rabbits[c1].x = (int) (150 + rnd(100)) << 16; + rabbits[c1].y = 256 << 16; + rabbits[c1].x_add = ((int) rnd(65535) << 1) - 65536; + if (rabbits[c1].x_add > 0) + rabbits[c1].direction = 0; + else + rabbits[c1].direction = 1; + rabbits[c1].y_add = -262144 + (rnd(16384) * 5); + rabbits[c1].timer = 30 + rnd(150); + rabbits[c1].anim = 2; + rabbits[c1].frame = 0; + rabbits[c1].frame_tick = 0; + rabbits[c1].image = player_anims[rabbits[c1].anim].frame[rabbits[c1].frame].image + rabbits[c1].colour * 18 + rabbits[c1].direction * 9; + break; + } + } + } + + dj_mix(); + + main_info.page_info[main_info.draw_page].num_pobs = 0; + + for (c1 = 0; c1 < 20; c1++) { + if (rabbits[c1].used == 1) { + rabbits[c1].y_add += 2048; + if (rabbits[c1].y_add > 36864 && rabbits[c1].anim != 3) { + rabbits[c1].anim = 3; + rabbits[c1].frame = 0; + rabbits[c1].frame_tick = 0; + rabbits[c1].image = player_anims[rabbits[c1].anim].frame[rabbits[c1].frame].image + rabbits[c1].colour * 18 + rabbits[c1].direction * 9; + } + rabbits[c1].x += rabbits[c1].x_add; + rabbits[c1].y += rabbits[c1].y_add; + if ((rabbits[c1].x >> 16) < 16 || (rabbits[c1].x >> 16) > JNB_WIDTH || (rabbits[c1].y >> 16) > JNB_HEIGHT) { + rabbits[c1].used = 0; + continue; + } + rabbits[c1].timer--; + if (rabbits[c1].timer <= 0) { + rabbits[c1].used = 0; + for (c2 = 0; c2 < 6; c2++) + add_object(OBJ_FUR, (rabbits[c1].x >> 16) + 6 + rnd(5), (rabbits[c1].y >> 16) + 6 + rnd(5), rabbits[c1].x_add + (rnd(65535) - 32768) * 3, rabbits[c1].y_add + (rnd(65535) - 32768) * 3, 0, 44 + rabbits[c1].colour * 8); + for (c2 = 0; c2 < 6; c2++) + add_object(OBJ_FLESH, (rabbits[c1].x >> 16) + 6 + rnd(5), (rabbits[c1].y >> 16) + 6 + rnd(5), rabbits[c1].x_add + (rnd(65535) - 32768) * 3, rabbits[c1].y_add + (rnd(65535) - 32768) * 3, 0, 76); + for (c2 = 0; c2 < 6; c2++) + add_object(OBJ_FLESH, (rabbits[c1].x >> 16) + 6 + rnd(5), (rabbits[c1].y >> 16) + 6 + rnd(5), rabbits[c1].x_add + (rnd(65535) - 32768) * 3, rabbits[c1].y_add + (rnd(65535) - 32768) * 3, 0, 77); + for (c2 = 0; c2 < 8; c2++) + add_object(OBJ_FLESH, (rabbits[c1].x >> 16) + 6 + rnd(5), (rabbits[c1].y >> 16) + 6 + rnd(5), rabbits[c1].x_add + (rnd(65535) - 32768) * 3, rabbits[c1].y_add + (rnd(65535) - 32768) * 3, 0, 78); + for (c2 = 0; c2 < 10; c2++) + add_object(OBJ_FLESH, (rabbits[c1].x >> 16) + 6 + rnd(5), (rabbits[c1].y >> 16) + 6 + rnd(5), rabbits[c1].x_add + (rnd(65535) - 32768) * 3, rabbits[c1].y_add + (rnd(65535) - 32768) * 3, 0, 79); + dj_play_sfx(SFX_DEATH, SFX_DEATH_FREQ, 64, 0, 0, -1); + continue; + } + rabbits[c1].frame_tick++; + if (rabbits[c1].frame_tick >= player_anims[rabbits[c1].anim].frame[rabbits[c1].frame].ticks) { + rabbits[c1].frame++; + if (rabbits[c1].frame >= player_anims[rabbits[c1].anim].num_frames) + rabbits[c1].frame = player_anims[rabbits[c1].anim].restart_frame; + rabbits[c1].frame_tick = 0; + } + rabbits[c1].image = player_anims[rabbits[c1].anim].frame[rabbits[c1].frame].image + rabbits[c1].colour * 18 + rabbits[c1].direction * 9; + if (rabbits[c1].used == 1) + add_pob(main_info.draw_page, rabbits[c1].x >> 16, rabbits[c1].y >> 16, rabbits[c1].image, &rabbit_gobs); + } + } + + dj_mix(); + + update_objects(); + + draw_begin(); + + for (c1 = 0; c1 < 300; c1++) { + stars[c1].back[main_info.draw_page] = get_pixel(main_info.draw_page, stars[c1].x >> 16, stars[c1].y >> 16); + set_pixel(main_info.draw_page, stars[c1].x >> 16, stars[c1].y >> 16, get_color(stars[c1].col, pal)); + } + + dj_mix(); + + draw_pobs(main_info.draw_page); + + draw_end(); + + main_info.draw_page ^= 1; + main_info.view_page ^= 1; + + flippage(main_info.view_page); + + wait_vrt(1); + + draw_begin(); + + redraw_pob_backgrounds(main_info.draw_page); + + dj_mix(); + intr_sysupdate(); + + for (c1 = 299; c1 >= 0; c1--) { + set_pixel(main_info.draw_page, stars[c1].old_x >> 16, stars[c1].old_y >> 16, stars[c1].back[main_info.draw_page]); + } + + draw_end(); + + } + + dj_set_nosound(1); + +} + diff --git a/contrib/other/jumpnbump/globals.h b/contrib/other/jumpnbump/globals.h new file mode 100755 index 0000000000..0ee087a464 --- /dev/null +++ b/contrib/other/jumpnbump/globals.h @@ -0,0 +1,369 @@ +/* + * globals.h + * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/ + * + * Copyright (C) 2001 Chuck Mason + * + * Copyright (C) 2002 Florian Schulze + * + * This file is part of Jump'n'Bump. + * + * Jump'n'Bump 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. + * + * Jump'n'Bump 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GLOBALS_H +#define __GLOBALS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "config.h" + +#include +#include +#include +#include +#ifndef _MSC_VER +#include +#endif +#include +#include +#include + +#ifdef DOS +# include +# include +# include +# include +#endif + +#ifdef _MSC_VER +# define WIN32_LEAN_AND_MEAN +# include +# include +# include +# include "SDL.h" +# if USE_SDL_MIXER +# include "SDL_mixer.h" +# endif +#else +# ifdef USE_SDL +# include +# include "SDL.h" +# if USE_SDL_MIXER +# include "SDL_mixer.h" +# endif +# endif +#endif + +#define JNB_MAX_PLAYERS 4 + +#define JNB_INETPORT 11111 + +extern int client_player_num; +void tellServerPlayerMoved(int playerid, int movement_type, int newval); +#define MOVEMENT_LEFT 1 +#define MOVEMENT_RIGHT 2 +#define MOVEMENT_UP 3 + +#define JNB_VERSION "1.51" + +#define JNB_WIDTH 400 +#define JNB_HEIGHT 256 + +extern int screen_width; +extern int screen_height; +extern int screen_pitch; +extern int scale_up; + +extern int ai[JNB_MAX_PLAYERS]; + +#ifndef USE_SDL +#define KEY_PL1_LEFT 0xcb +#define KEY_PL1_RIGHT 0xcd +#define KEY_PL1_JUMP 0xc8 +#define KEY_PL2_LEFT 0x1e +#define KEY_PL2_RIGHT 0x20 +#define KEY_PL2_JUMP 0x11 +#else +#define KEY_PL1_LEFT SDLK_LEFT +#define KEY_PL1_RIGHT SDLK_RIGHT +#define KEY_PL1_JUMP SDLK_UP +#define KEY_PL2_LEFT SDLK_a +#define KEY_PL2_RIGHT SDLK_d +#define KEY_PL2_JUMP SDLK_w +#define KEY_PL3_LEFT SDLK_j +#define KEY_PL3_RIGHT SDLK_l +#define KEY_PL3_JUMP SDLK_i +#define KEY_PL4_LEFT SDLK_KP4 +#define KEY_PL4_RIGHT SDLK_KP6 +#define KEY_PL4_JUMP SDLK_KP8 +#endif + +#define NUM_POBS 200 +#define NUM_OBJECTS 200 +#define NUM_FLIES 20 +#define NUM_LEFTOVERS 50 + +#define OBJ_SPRING 0 +#define OBJ_SPLASH 1 +#define OBJ_SMOKE 2 +#define OBJ_YEL_BUTFLY 3 +#define OBJ_PINK_BUTFLY 4 +#define OBJ_FUR 5 +#define OBJ_FLESH 6 +#define OBJ_FLESH_TRACE 7 + +#define OBJ_ANIM_SPRING 0 +#define OBJ_ANIM_SPLASH 1 +#define OBJ_ANIM_SMOKE 2 +#define OBJ_ANIM_YEL_BUTFLY_RIGHT 3 +#define OBJ_ANIM_YEL_BUTFLY_LEFT 4 +#define OBJ_ANIM_PINK_BUTFLY_RIGHT 5 +#define OBJ_ANIM_PINK_BUTFLY_LEFT 6 +#define OBJ_ANIM_FLESH_TRACE 7 + +#define MOD_MENU 0 +#define MOD_GAME 1 +#define MOD_SCORES 2 + +#define SFX_JUMP 0 +#define SFX_LAND 1 +#define SFX_DEATH 2 +#define SFX_SPRING 3 +#define SFX_SPLASH 4 +#define SFX_FLY 5 + +#define NUM_SFX 6 + +#define SFX_JUMP_FREQ 15000 +#define SFX_LAND_FREQ 15000 +#define SFX_DEATH_FREQ 20000 +#define SFX_SPRING_FREQ 15000 +#define SFX_SPLASH_FREQ 12000 +#define SFX_FLY_FREQ 12000 + +#define BAN_VOID 0 +#define BAN_SOLID 1 +#define BAN_WATER 2 +#define BAN_ICE 3 +#define BAN_SPRING 4 + +#ifndef DATA_PATH +#ifdef __APPLE__ +#define DATA_PATH "data/jumpbump.dat" +#elif _WIN32 +#define DATA_PATH "data/jumpbump.dat" +#else +#define DATA_PATH "jumpbump.dat" +#endif +#endif + +typedef struct { + int num_images; + int *width; + int *height; + int *hs_x; + int *hs_y; + void **data; + void **orig_data; +} gob_t; + +typedef struct { + int joy_enabled, mouse_enabled; + int no_sound, music_no_sound, no_gore, fireworks; + char error_str[256]; + int draw_page, view_page; + struct { + int num_pobs; + struct { + int x, y; + int image; + gob_t *pob_data; + int back_buf_ofs; + } pobs[NUM_POBS]; + } page_info[2]; + void *pob_backbuf[2]; +} main_info_t; + +typedef struct { + int action_left,action_up,action_right; + int enabled, dead_flag; + int bumps; + int bumped[JNB_MAX_PLAYERS]; + int x, y; + int x_add, y_add; + int direction, jump_ready, jump_abort, in_water; + int anim, frame, frame_tick, image; +} player_t; + +typedef struct { + int num_frames; + int restart_frame; + struct { + int image; + int ticks; + } frame[4]; +} player_anim_t; + +typedef struct { + int used, type; + int x, y; + int x_add, y_add; + int x_acc, y_acc; + int anim; + int frame, ticks; + int image; +} object_t; + +typedef struct { + int x, y; + int raw_x, raw_y; + int but1, but2; + struct { + int x1, x2, x3; + int y1, y2, y3; + } calib_data; +} joy_t; + +typedef struct { + int but1, but2, but3; +} mouse_t; + +extern main_info_t main_info; +extern player_t player[JNB_MAX_PLAYERS]; +extern player_anim_t player_anims[7]; +extern object_t objects[NUM_OBJECTS]; +extern joy_t joy; +extern mouse_t mouse; + +extern char datfile_name[2048]; + +extern char *background_pic; +extern char *mask_pic; + +extern gob_t rabbit_gobs; +extern gob_t font_gobs; +extern gob_t object_gobs; +extern gob_t number_gobs; + + +/* fireworks.c */ + +void fireworks(void); + + +/* main.c */ + +void steer_players(void); +void position_player(int player_num); +void fireworks(void); +void add_object(int type, int x, int y, int x_add, int y_add, int anim, int frame); +void update_objects(void); +int add_pob(int page, int x, int y, int image, gob_t *pob_data); +void draw_flies(int page); +void draw_pobs(int page); +void redraw_flies_background(int page); +void redraw_pob_backgrounds(int page); +int add_leftovers(int page, int x, int y, int image, gob_t *pob_data); +void draw_leftovers(int page); +int init_level(int level, char *pal); +void deinit_level(void); +int init_program(int argc, char *argv[], char *pal); +void deinit_program(void); +unsigned short rnd(unsigned short max); +int read_level(void); +unsigned char *dat_open(char *file_name); +int dat_filelen(char *file_name); +void write_calib_data(void); + + +/* input.c */ + +void update_player_actions(void); +void init_inputs(void); +int calib_joy(int type); + +/* menu.c */ + +int menu(void); +int menu_init(void); +void menu_deinit(void); + + +/* gfx.c */ + +void set_scaling(int scale); +void open_screen(void); +void wait_vrt(int mix); +void draw_begin(void); +void draw_end(void); +void flippage(int page); +void draw_begin(void); +void draw_end(void); +void clear_lines(int page, int y, int count, int color); +int get_color(int color, char pal[768]); +int get_pixel(int page, int x, int y); +void set_pixel(int page, int x, int y, int color); +void setpalette(int index, int count, char *palette); +void fillpalette(int red, int green, int blue); +#ifdef DOS +void get_block(char page, short x, short y, short width, short height, char *buffer); +void put_block(char page, short x, short y, short width, short height, char *buffer); +#else +void get_block(int page, int x, int y, int width, int height, void *buffer); +void put_block(int page, int x, int y, int width, int height, void *buffer); +#endif +void put_text(int page, int x, int y, char *text, int align); +void put_pob(int page, int x, int y, int image, gob_t *gob, int mask, void *mask_pic); +int pob_width(int image, gob_t *gob); +int pob_height(int image, gob_t *gob); +int pob_hs_x(int image, gob_t *gob); +int pob_hs_y(int image, gob_t *gob); +int read_pcx(unsigned char * handle, void *buffer, int buf_len, char *pal); +void register_background(char *pixels, char pal[768]); +int register_gob(unsigned char *handle, gob_t *gob, int len); +void recalculate_gob(gob_t *gob, char pal[768]); +void register_mask(void *pixels); + +/* gfx.c */ + +#ifdef USE_SDL +/* long filelength(int handle); */ +void fs_toggle(); +int intr_sysupdate(); +#endif + +/* interrpt.c */ + +extern char last_keys[50]; + +int hook_keyb_handler(void); +void remove_keyb_handler(void); +int key_pressed(int key); +int addkey(unsigned int key); + +/* sound-linux.c */ +#ifdef LINUX + + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/contrib/other/jumpnbump/main.c b/contrib/other/jumpnbump/main.c new file mode 100755 index 0000000000..7cb4a094f6 --- /dev/null +++ b/contrib/other/jumpnbump/main.c @@ -0,0 +1,3590 @@ +/* + * main.c + * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/ + * + * Copyright (C) 2001 Chuck Mason + * + * Copyright (C) 2002 Florian Schulze + * + * This file is part of Jump'n'Bump. + * + * Jump'n'Bump 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. + * + * Jump'n'Bump 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "globals.h" +#include +#ifndef _MSC_VER +#include +#endif + +#ifdef BZLIB_SUPPORT +#include "bzlib.h" +#endif + +#ifdef ZLIB_SUPPORT +#include "zlib.h" +#endif + +#ifdef USE_NET +#include "SDL_net.h" +#endif /* USE_NET */ + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +gob_t rabbit_gobs = { 0 }; +gob_t font_gobs = { 0 }; +gob_t object_gobs = { 0 }; +gob_t number_gobs = { 0 }; + +main_info_t main_info; +player_t player[JNB_MAX_PLAYERS]; +player_anim_t player_anims[7]; +object_t objects[NUM_OBJECTS]; +joy_t joy; +mouse_t mouse; + +char datfile_name[2048]; + +char *background_pic; +char *mask_pic; +int flip = 0; +char pal[768]; +char cur_pal[768]; + +int ai[JNB_MAX_PLAYERS]; + +unsigned int ban_map[17][22] = { + {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 1}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1}, + {1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0, 1, 3, 3, 3, 1, 1, 1}, + {2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} +}; + +#define GET_BAN_MAP_XY(x,y) ban_map[(y) >> 4][(x) >> 4] + +struct { + int num_frames; + int restart_frame; + struct { + int image; + int ticks; + } frame[10]; +} object_anims[8] = { + { + 6, 0, { + { + 0, 3}, { + 1, 3}, { + 2, 3}, { + 3, 3}, { + 4, 3}, { + 5, 3}, { + 0, 0}, { + 0, 0}, { + 0, 0}, { + 0, 0} + } + }, { + 9, 0, { + { + 6, 2}, { + 7, 2}, { + 8, 2}, { + 9, 2}, { + 10, 2}, { + 11, 2}, { + 12, 2}, { + 13, 2}, { + 14, 2}, { + 0, 0} + } + }, { + 5, 0, { + { + 15, 3}, { + 16, 3}, { + 16, 3}, { + 17, 3}, { + 18, 3}, { + 19, 3}, { + 0, 0}, { + 0, 0}, { + 0, 0}, { + 0, 0} + } + }, { + 10, 0, { + { + 20, 2}, { + 21, 2}, { + 22, 2}, { + 23, 2}, { + 24, 2}, { + 25, 2}, { + 24, 2}, { + 23, 2}, { + 22, 2}, { + 21, 2} + } + }, { + 10, 0, { + { + 26, 2}, { + 27, 2}, { + 28, 2}, { + 29, 2}, { + 30, 2}, { + 31, 2}, { + 30, 2}, { + 29, 2}, { + 28, 2}, { + 27, 2} + } + }, { + 10, 0, { + { + 32, 2}, { + 33, 2}, { + 34, 2}, { + 35, 2}, { + 36, 2}, { + 37, 2}, { + 36, 2}, { + 35, 2}, { + 34, 2}, { + 33, 2} + } + }, { + 10, 0, { + { + 38, 2}, { + 39, 2}, { + 40, 2}, { + 41, 2}, { + 42, 2}, { + 43, 2}, { + 42, 2}, { + 41, 2}, { + 40, 2}, { + 39, 2} + } + }, { + 4, 0, { + { + 76, 4}, { + 77, 4}, { + 78, 4}, { + 79, 4}, { + 0, 0}, { + 0, 0}, { + 0, 0}, { + 0, 0}, { + 0, 0}, { + 0, 0} + } + } +}; + +int flies_enabled = 1; + +struct { + int x, y; + int old_x, old_y; + int old_draw_x, old_draw_y; + int back[2]; + int back_defined[2]; +} flies[NUM_FLIES]; + +struct { + struct { + short num_pobs; + struct { + int x, y; + int image; + gob_t *pob_data; + } pobs[NUM_LEFTOVERS]; + } page[2]; +} leftovers; + +int pogostick, bunnies_in_space, jetpack, lord_of_the_flies, blood_is_thicker_than_water; + + +#ifndef _MSC_VER +int filelength(int handle) +{ + struct stat buf; + + if (fstat(handle, &buf) == -1) { + perror("filelength"); + exit(EXIT_FAILURE); + } + + return buf.st_size; +} +#endif + + +/* networking shite. */ + +int client_player_num = -1; +int is_server = 1; +int is_net = 0; + +#ifdef USE_NET +TCPsocket sock = NULL; +SDLNet_SocketSet socketset = NULL; + +typedef struct +{ + TCPsocket sock; + IPaddress addr; + SDLNet_SocketSet socketset; +} NetInfo; + +NetInfo net_info[JNB_MAX_PLAYERS]; +#endif + +typedef struct +{ + unsigned long cmd; + long arg; + long arg2; + long arg3; + long arg4; +} NetPacket; + +#define NETPKTBUFSIZE (4 + 4 + 4 + 4 + 4) + +#define NETCMD_NACK (0xF00DF00D + 0) +#define NETCMD_ACK (0xF00DF00D + 1) +#define NETCMD_HELLO (0xF00DF00D + 2) +#define NETCMD_GREENLIGHT (0xF00DF00D + 3) +#define NETCMD_MOVE (0xF00DF00D + 4) +#define NETCMD_BYE (0xF00DF00D + 5) +#define NETCMD_POSITION (0xF00DF00D + 6) +#define NETCMD_ALIVE (0xF00DF00D + 7) +#define NETCMD_KILL (0xF00DF00D + 8) + + +#ifdef USE_NET +void bufToPacket(const char *buf, NetPacket *pkt) +{ + SDLNet_Write32(*((Uint32*) (buf + 0)), &pkt->cmd); + SDLNet_Write32(*((Uint32*) (buf + 4)), &pkt->arg); + SDLNet_Write32(*((Uint32*) (buf + 8)), &pkt->arg2); + SDLNet_Write32(*((Uint32*) (buf + 12)), &pkt->arg3); + SDLNet_Write32(*((Uint32*) (buf + 16)), &pkt->arg4); +/* + pkt->cmd = ntohl(*((unsigned long *) (buf + 0))); + pkt->arg = (long) ntohl(*((unsigned long *) (buf + 4))); + pkt->arg2 = (long) ntohl(*((unsigned long *) (buf + 8))); + pkt->arg3 = (long) ntohl(*((unsigned long *) (buf + 12))); + pkt->arg4 = (long) ntohl(*((unsigned long *) (buf + 16))); +*/ +} + + +void packetToBuf(const NetPacket *pkt, char *buf) +{ + *((Uint32*) (buf + 0)) = SDLNet_Read32(&pkt->cmd); + *((Uint32*) (buf + 4)) = SDLNet_Read32(&pkt->arg); + *((Uint32*) (buf + 8)) = SDLNet_Read32(&pkt->arg2); + *((Uint32*) (buf + 12)) = SDLNet_Read32(&pkt->arg3); + *((Uint32*) (buf + 16)) = SDLNet_Read32(&pkt->arg4); +/* + *((unsigned long *) (buf + 0)) = htonl(pkt->cmd); + *((unsigned long *) (buf + 4)) = htonl((unsigned long) pkt->arg); + *((unsigned long *) (buf + 8)) = htonl((unsigned long) pkt->arg2); + *((unsigned long *) (buf + 12)) = htonl((unsigned long) pkt->arg3); + *((unsigned long *) (buf + 16)) = htonl((unsigned long) pkt->arg4); +*/ +} + + +void sendPacketToSock(TCPsocket s, NetPacket *pkt) +{ + int bytes_left = NETPKTBUFSIZE; + int bw; + char buf[NETPKTBUFSIZE]; + char *ptr = buf; + + packetToBuf(pkt, buf); + while (bytes_left > 0) { + bw = SDLNet_TCP_Send(s, ptr, bytes_left); + if (bw < 0) { + fprintf(stderr, "SERVER: SDLNet_TCP_Send(): %s\n", SDLNet_GetError()); + SDLNet_TCP_Close(s); + exit(42); + } else if (bw == 0) { + SDL_Delay(1); + } else { + bytes_left -= bw; + ptr += bw; + } + } +} + + +void sendPacket(int playerid, NetPacket *pkt) +{ + if ( (playerid < JNB_MAX_PLAYERS) && (playerid >= 0)) { + if ((player[playerid].enabled) && (playerid != client_player_num)) { + sendPacketToSock(net_info[playerid].sock, pkt); + } + } +} + + +void sendPacketToAll(NetPacket *pkt) +{ + int i; + + for (i = 0; i < JNB_MAX_PLAYERS; i++) { + sendPacket(i, pkt); + } +} + +/** read a packet from the given TCPsocket +Returns -1 if some error occured, 0 if there was no data available and 1 if a +packet was successfully read. +Note: the socket has to be in the supplied socketset. +TODO: this function will bomb if a packet arrives in pieces, there is no +inherent guarantee that the next call will be made on the same socket. */ +int grabPacket(TCPsocket s, SDLNet_SocketSet ss, NetPacket *pkt) +{ + static char buf[NETPKTBUFSIZE]; + static int buf_count = 0; + int rc; + + if (SDLNet_CheckSockets(ss, 0) <= 0) + return 0; + + if(!SDLNet_SocketReady(s)) + return 0; + + rc = SDLNet_TCP_Recv(s, &buf[buf_count], NETPKTBUFSIZE - buf_count); + if (rc <= 0) { + /* closed connection? */ + return -1; + } else if (rc != NETPKTBUFSIZE) { + /* we got a partial packet. Store what we got in the static buffer and + return so that the next call can read the rest. Hopefully. */ + buf_count = rc; + return 0; + } else { + buf_count = 0; + bufToPacket(buf, pkt); + return 1; + } +} + + +int serverRecvPacket(NetPacket *pkt) +{ + int rc; + int i; + + assert(is_server); + + for (i = 0; i < JNB_MAX_PLAYERS; i++) { + TCPsocket s = net_info[i].sock; + + if ((i == client_player_num) || (!player[i].enabled)) + continue; + + rc = grabPacket(s, net_info[i].socketset, pkt); + if (rc < 0) { + NetPacket pkt; + + player[i].enabled = 0; + SDLNet_TCP_Close(s); + pkt.cmd = NETCMD_BYE; + pkt.arg = i; + pkt.arg2 = 0; + pkt.arg3 = 0; + pkt.arg4 = 0; + sendPacketToAll(&pkt); + } else if (rc > 0) { + return(i); /* it's all good. */ + } + } + + return(-1); /* no packets available currently. */ +} + + +void wait_for_greenlight(void) +{ + NetPacket pkt; + int i; + + printf("CLIENT: Waiting for greenlight...\n"); + + do { + int rc; + while ((rc = grabPacket(sock, socketset, &pkt)) == 0) { + SDL_Delay(100); /* nap and then try again. */ + } + + if (rc < 0) { + printf("CLIENT: Lost connection.\n"); + SDLNet_TCP_Close(sock); + exit(42); + } + } while (pkt.cmd != NETCMD_GREENLIGHT); + + printf("CLIENT: Got greenlight.\n"); + + for (i = 0; i < JNB_MAX_PLAYERS; i++) { + if (pkt.arg & (1 << i)) { + printf("CLIENT: There is a player #%d.\n", i); + player[i].enabled = 1; + } + } +} + + +static int buggered_off = 0; + + +void tellServerGoodbye(void) +{ + NetPacket pkt; + + if (!buggered_off) { + buggered_off = 1; + pkt.cmd = NETCMD_BYE; + pkt.arg = client_player_num; + pkt.arg2 = 0; + pkt.arg3 = 0; + pkt.arg4 = 0; + sendPacketToSock(sock, &pkt); + } +} +#endif /* USE_NET */ + + +void processMovePacket(NetPacket *pkt) +{ + int playerid = pkt->arg; + int movetype = ((pkt->arg2 >> 16) & 0xFF); + int newval = ((pkt->arg2 >> 0) & 0xFF); + + if (movetype == MOVEMENT_LEFT) { + player[playerid].action_left = newval; + } else if (movetype == MOVEMENT_RIGHT) { + player[playerid].action_right = newval; + } else if (movetype == MOVEMENT_UP) { + player[playerid].action_up = newval; + } else { + printf("bogus MOVE packet!\n"); + } + + player[playerid].x = pkt->arg3; + player[playerid].y = pkt->arg4; +} + + +void tellServerPlayerMoved(int playerid, int movement_type, int newval) +{ + NetPacket pkt; + + pkt.cmd = NETCMD_MOVE; + pkt.arg = playerid; + pkt.arg2 = ( ((movement_type & 0xFF) << 16) | ((newval & 0xFF) << 0) ); + pkt.arg3 = player[playerid].x; + pkt.arg4 = player[playerid].y; + + if (is_server) { + processMovePacket(&pkt); +#ifdef USE_NET + if (is_net) + sendPacketToAll(&pkt); + } else { + sendPacketToSock(sock, &pkt); +#endif + } +} + + +#ifdef USE_NET +void tellServerNewPosition(void) +{ + NetPacket pkt; + pkt.cmd = NETCMD_POSITION; + pkt.arg = client_player_num; + pkt.arg2 = player[client_player_num].x; + pkt.arg3 = player[client_player_num].y; + + if (is_server) { + sendPacketToAll(&pkt); + } else { + sendPacketToSock(sock, &pkt); + } +} +#endif /* USE_NET */ + + +void processKillPacket(NetPacket *pkt) +{ + int c1 = pkt->arg; + int c2 = pkt->arg2; + int x = pkt->arg3; + int y = pkt->arg4; + int c4 = 0; + int s1 = 0; + + player[c1].y_add = -player[c1].y_add; + if (player[c1].y_add > -262144L) + player[c1].y_add = -262144L; + player[c1].jump_abort = 1; + player[c2].dead_flag = 1; + if (player[c2].anim != 6) { + player[c2].anim = 6; + player[c2].frame = 0; + player[c2].frame_tick = 0; + player[c2].image = player_anims[player[c2].anim].frame[player[c2].frame].image + player[c2].direction * 9; + if (main_info.no_gore == 0) { + for (c4 = 0; c4 < 6; c4++) + add_object(OBJ_FUR, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 44 + c2 * 8); + for (c4 = 0; c4 < 6; c4++) + add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 76); + for (c4 = 0; c4 < 6; c4++) + add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 77); + for (c4 = 0; c4 < 8; c4++) + add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 78); + for (c4 = 0; c4 < 10; c4++) + add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 79); + } + dj_play_sfx(SFX_DEATH, (unsigned short)(SFX_DEATH_FREQ + rnd(2000) - 1000), 64, 0, 0, -1); + player[c1].bumps++; + player[c1].bumped[c2]++; + s1 = player[c1].bumps % 100; + add_leftovers(0, 360, 34 + c1 * 64, s1 / 10, &number_gobs); + add_leftovers(1, 360, 34 + c1 * 64, s1 / 10, &number_gobs); + add_leftovers(0, 376, 34 + c1 * 64, s1 - (s1 / 10) * 10, &number_gobs); + add_leftovers(1, 376, 34 + c1 * 64, s1 - (s1 / 10) * 10, &number_gobs); + } +} + + +#ifdef USE_NET +void processPositionPacket(NetPacket *pkt) +{ + int playerid = pkt->arg; + + player[playerid].x = pkt->arg2; + player[playerid].y = pkt->arg3; +} + + +void processAlivePacket(NetPacket *pkt) +{ + int playerid = pkt->arg; + + player[playerid].dead_flag = 0; + player[playerid].x = pkt->arg2; + player[playerid].y = pkt->arg3; +} + + +void serverTellEveryoneGoodbye(void) +{ + int i; + + if (!buggered_off) { + buggered_off = 1; + for (i = 0; i < JNB_MAX_PLAYERS; i++) { + if (player[i].enabled) { + NetPacket pkt; + + pkt.cmd = NETCMD_BYE; + pkt.arg = i; + pkt.arg2 = 0; + pkt.arg3 = 0; + pkt.arg4 = 0; + sendPacketToAll(&pkt); + } + } + } +} + + +int server_said_bye = 0; + + +int update_players_from_server(void) +{ + NetPacket pkt; + int rc; + + assert(!is_server); + + while ((rc = grabPacket(sock, socketset, &pkt)) != 0) { + if (rc < 0) { + printf("CLIENT: Lost connection.\n"); + pkt.cmd = NETCMD_BYE; + pkt.arg = client_player_num; + } + + if (pkt.cmd == NETCMD_BYE) { + if (pkt.arg == client_player_num) { + SDLNet_FreeSocketSet(socketset); + SDLNet_TCP_Close(sock); + sock = NULL; + server_said_bye = 1; + return(0); + } else { + player[pkt.arg].enabled = 0; + } + } else if (pkt.cmd == NETCMD_MOVE) { + processMovePacket(&pkt); + } else if (pkt.cmd == NETCMD_ALIVE) { + processAlivePacket(&pkt); + } else if (pkt.cmd == NETCMD_POSITION) { + processPositionPacket(&pkt); + } else if (pkt.cmd == NETCMD_KILL) { + processKillPacket(&pkt); + } else { + printf("CLIENT: Got an unknown packet: 0x%lX.\n", pkt.cmd); + } + } + + return(1); +} + + +void serverSendAlive(int playerid) +{ + NetPacket pkt; + + assert(is_server); + pkt.cmd = NETCMD_ALIVE; + pkt.arg = playerid; + pkt.arg2 = player[playerid].x; + pkt.arg3 = player[playerid].y; + sendPacketToAll(&pkt); +} +#endif /* USE_NET */ + + +void serverSendKillPacket(int killer, int victim) +{ + NetPacket pkt; + + assert(is_server); + pkt.cmd = NETCMD_KILL; + pkt.arg = killer; + pkt.arg2 = victim; + pkt.arg3 = player[victim].x; + pkt.arg4 = player[victim].y; + processKillPacket(&pkt); +#ifdef USE_NET + if (is_net) + sendPacketToAll(&pkt); +#endif +} + + +#ifdef USE_NET +void update_players_from_clients(void) +{ + int i; + NetPacket pkt; + int playerid; + + assert(is_server); + + while ((playerid = serverRecvPacket(&pkt)) >= 0) { + if (pkt.cmd == NETCMD_BYE) { + pkt.arg = playerid; /* just in case. */ + sendPacketToAll(&pkt); + player[playerid].enabled = 0; + SDLNet_FreeSocketSet(net_info[playerid].socketset); + SDLNet_TCP_Close(net_info[playerid].sock); + } else if (pkt.cmd == NETCMD_POSITION) { + pkt.arg = playerid; /* just in case. */ + processPositionPacket(&pkt); + for (i = 0; i < JNB_MAX_PLAYERS; i++) { + if (i != playerid) { + sendPacket(i, &pkt); + } + } + } else if (pkt.cmd == NETCMD_MOVE) { + pkt.arg = playerid; /* just in case. */ + /* + pkt.arg3 = player[playerid].x; + pkt.arg4 = player[playerid].y; + */ + processMovePacket(&pkt); + sendPacketToAll(&pkt); + } else { + printf("SERVER: Got unknown packet (0x%lX).\n", pkt.cmd); + } + } +} + + +void init_server(const char *netarg) +{ + NetPacket pkt; + IPaddress addr; + int i; + int wait_for_clients = ((netarg == NULL) ? 0 : atoi(netarg)); + char *ipstr; + + /** assign player number zero as default for the server */ + if(-1 == client_player_num) + client_player_num = 0; + + if ((wait_for_clients >= JNB_MAX_PLAYERS) || (wait_for_clients < 0)) { + printf("SERVER: Waiting for bogus client count (%d).\n", wait_for_clients); + exit(42); + } + + if (SDLNet_Init() < 0) { + exit(42); + } + atexit(SDLNet_Quit); + + SDLNet_ResolveHost(&addr, NULL, JNB_INETPORT); + ipstr = SDLNet_ResolveIP(&addr); + SDLNet_ResolveHost(&addr, ipstr, JNB_INETPORT); + printf("SERVER: we are %s (%i.%i.%i.%i:%i).\n", ipstr, (addr.host >> 0) & 0xff, (addr.host >> 8) & 0xff, (addr.host >> 16) & 0xff, (addr.host >> 24) & 0xff, addr.port); + net_info[client_player_num].addr = addr; + + addr.host = INADDR_ANY; + sock = SDLNet_TCP_Open(&addr); + if (sock == NULL) { + fprintf(stderr, "SERVER: SDLNet_TCP_Open(): %s\n", SDLNet_GetError()); + exit(42); + } + + player[client_player_num].enabled = 1; + + printf("SERVER: waiting for (%d) clients...\n", wait_for_clients); + + socketset = SDLNet_AllocSocketSet(JNB_MAX_PLAYERS + 1); + SDLNet_TCP_AddSocket(socketset, sock); + + while (wait_for_clients > 0) + { + char buf[NETPKTBUFSIZE]; + IPaddress *from; + int negatory = 1; + int br; + TCPsocket s; + + /* Wait for events */ + SDLNet_CheckSockets(socketset, ~0); + if ( SDLNet_SocketReady(sock) ) { + s = SDLNet_TCP_Accept(sock); + + if (s == NULL) + { + fprintf(stderr, "SERVER: SDLNet_TCP_Accept(): %s", SDLNet_GetError()); + SDLNet_TCP_Close(sock); + exit(42); + } + } else + continue; + + br = SDLNet_TCP_Recv(s, buf, NETPKTBUFSIZE); + if (br < 0) { + fprintf(stderr, "SERVER: SDLNet_TCP_Recv(): %s\n", SDLNet_GetError()); + SDLNet_TCP_Close(s); + SDLNet_TCP_Close(sock); + exit(42); + } + + from = SDLNet_TCP_GetPeerAddress(s); + ipstr = SDLNet_ResolveIP(from); + printf("SERVER: Got data from %s (%i.%i.%i.%i:%i).\n", ipstr, (from->host >> 0) & 0xff, (from->host >> 8) & 0xff, (from->host >> 16) & 0xff, (from->host >> 24) & 0xff, from->port); + + if (br != NETPKTBUFSIZE) { + printf("SERVER: Bogus packet.\n"); + continue; + } + + bufToPacket(buf, &pkt); + if (pkt.cmd != NETCMD_HELLO) { + printf("SERVER: Bogus packet.\n"); + continue; + } + + printf("SERVER: Client claims to be player #%ld.\n", pkt.arg); + + if (-1 == pkt.arg) { + int i; + for(i=0; i!=JNB_MAX_PLAYERS; ++i) { + if(!player[i].enabled) { + printf("SERVER: assigning %d as player number\n", i); + pkt.arg = i; + break; + } + } + } + + if ((pkt.arg>=JNB_MAX_PLAYERS)||(pkt.arg<0)) { + printf("SERVER: (that's an invalid player number.)\n"); + } else if (player[pkt.arg].enabled) { + printf("SERVER: (that player number is already taken.)\n"); + } else { + negatory = 0; + } + + if (negatory) { + printf("SERVER: Forbidding connection.\n"); + pkt.cmd = NETCMD_NACK; + sendPacketToSock(s, &pkt); + SDLNet_TCP_Close(s); + } else { + player[pkt.arg].enabled = 1; + net_info[pkt.arg].sock = s; + net_info[pkt.arg].addr = *from; + net_info[pkt.arg].socketset = SDLNet_AllocSocketSet(1); + SDLNet_TCP_AddSocket(net_info[pkt.arg].socketset, net_info[pkt.arg].sock); + wait_for_clients--; + printf("SERVER: Granting connection. (%d) to go.\n", wait_for_clients); + pkt.cmd = NETCMD_ACK; + sendPacket(pkt.arg, &pkt); + } + } + + SDLNet_TCP_Close(sock); /* done with the listen socket. */ + SDLNet_FreeSocketSet(socketset); + sock = NULL; + socketset = NULL; + + printf("SERVER: Got all our connections. Greenlighting clients...\n"); + + pkt.cmd = NETCMD_GREENLIGHT; + pkt.arg = 0; + for (i = 0; i < JNB_MAX_PLAYERS; i++) { + if (player[i].enabled) { + pkt.arg |= (1 << i); + } + } + sendPacketToAll(&pkt); +} + + +void connect_to_server(char *netarg) +{ + NetPacket pkt; + char buf[NETPKTBUFSIZE]; + char *ipstr; + IPaddress hent; + IPaddress addr; + int br; + + if (netarg == NULL) { + printf("CLIENT: Need to specify host to connect to.\n"); + exit(42); + } + + if (SDLNet_Init() < 0) { + exit(42); + } + atexit(SDLNet_Quit); + + SDLNet_ResolveHost(&addr, NULL, JNB_INETPORT); + ipstr = SDLNet_ResolveIP(&addr); + SDLNet_ResolveHost(&addr, ipstr, JNB_INETPORT); + printf("CLIENT: we are %s (%i.%i.%i.%i:%i).\n", ipstr, (addr.host >> 0) & 0xff, (addr.host >> 8) & 0xff, (addr.host >> 16) & 0xff, (addr.host >> 24) & 0xff, addr.port); + + if (SDLNet_ResolveHost(&hent, netarg, JNB_INETPORT) < 0) { + fprintf(stderr, "CLIENT: couldn't find host: %s\n", SDLNet_GetError()); + exit(42); + } + + sock = SDLNet_TCP_Open(&hent); + if (sock == NULL) { + fprintf(stderr, "CLIENT: SDLNet_TCP_Open(): %s\n", SDLNet_GetError()); + exit(42); + } + + socketset = SDLNet_AllocSocketSet(1); + SDLNet_TCP_AddSocket(socketset, sock); + + printf("CLIENT: connected to %s...\n", SDLNet_ResolveIP(&hent)); + + printf("CLIENT: Sending HELLO packet...\n"); + pkt.cmd = NETCMD_HELLO; + pkt.arg = client_player_num; + sendPacketToSock(sock, &pkt); + + printf("CLIENT: Waiting for ACK from server...\n"); + + br = SDLNet_TCP_Recv(sock, buf, NETPKTBUFSIZE); + if (br < 0) { + fprintf(stderr, "CLIENT: recv(): %s\n", SDLNet_GetError()); + SDLNet_FreeSocketSet(socketset); + SDLNet_TCP_Close(sock); + exit(42); + } + + if (br != NETPKTBUFSIZE) { + printf("CLIENT: Bogus packet size (%d of %d). FIXME.\n", br, NETPKTBUFSIZE); + SDLNet_FreeSocketSet(socketset); + SDLNet_TCP_Close(sock); + exit(42); + } + + bufToPacket(buf, &pkt); + + if (pkt.cmd == NETCMD_NACK) { + printf("CLIENT: Server forbid us from playing.\n"); + SDLNet_FreeSocketSet(socketset); + SDLNet_TCP_Close(sock); + exit(42); + } + + if (pkt.cmd != NETCMD_ACK) { + printf("CLIENT: Unexpected packet (cmd=0x%lX).\n", pkt.cmd); + SDLNet_FreeSocketSet(socketset); + SDLNet_TCP_Close(sock); + exit(42); + } + + client_player_num = pkt.arg; + player[client_player_num].enabled = 1; + net_info[client_player_num].addr = addr; + printf("CLIENT: Server accepted our connection.\n"); + + wait_for_greenlight(); +} +#endif /* USE_NET */ + + +static void flip_pixels(unsigned char *pixels) +{ + int x,y; + unsigned char temp; + + assert(pixels); + for (y = 0; y < JNB_HEIGHT; y++) { + for (x = 0; x < (352/2); x++) { + temp = pixels[y*JNB_WIDTH+x]; + pixels[y*JNB_WIDTH+x] = pixels[y*JNB_WIDTH+(352-x)-1]; + pixels[y*JNB_WIDTH+(352-x)-1] = temp; + } + } +} + + +void get_closest_player_to_point(int x,int y,int *dist,int *closest_player) +{ + int c1; + int cur_dist = 0; + + *dist = 0x7fff; + for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) { + if (player[c1].enabled == 1) { + cur_dist = (int)sqrt((x - ((player[c1].x >> 16) + 8)) * (x - ((player[c1].x >> 16) + 8)) + (y - ((player[c1].y >> 16) + 8)) * (y - ((player[c1].y >> 16) + 8))); + if (cur_dist < *dist) { + *closest_player = c1; + *dist = cur_dist; + } + } + } +} + + +static void update_flies(int update_count) +{ + int c1; + int closest_player = 0, dist; + int s1, s2, s3, s4; + + /* get center of fly swarm */ + s1 = s2 = 0; + for (c1 = 0; c1 < NUM_FLIES; c1++) { + s1 += flies[c1].x; + s2 += flies[c1].y; + } + s1 /= NUM_FLIES; + s2 /= NUM_FLIES; + + if (update_count == 1) { + /* get closest player to fly swarm */ + get_closest_player_to_point(s1, s2, &dist, &closest_player); + /* update fly swarm sound */ + s3 = 32 - dist / 3; + if (s3 < 0) + s3 = 0; + dj_set_sfx_channel_volume(4, (char)(s3)); + } + + for (c1 = 0; c1 < NUM_FLIES; c1++) { + /* get closest player to fly */ + get_closest_player_to_point(flies[c1].x, flies[c1].y, &dist, &closest_player); + flies[c1].old_x = flies[c1].x; + flies[c1].old_y = flies[c1].y; + s3 = 0; + if ((s1 - flies[c1].x) > 30) + s3 += 1; + else if ((s1 - flies[c1].x) < -30) + s3 -= 1; + if (dist < 30) { + if (((player[closest_player].x >> 16) + 8) > flies[c1].x) { + if (lord_of_the_flies == 0) + s3 -= 1; + else + s3 += 1; + } else { + if (lord_of_the_flies == 0) + s3 += 1; + else + s3 -= 1; + } + } + s4 = rnd(3) - 1 + s3; + if ((flies[c1].x + s4) < 16) + s4 = 0; + if ((flies[c1].x + s4) > 351) + s4 = 0; + if (GET_BAN_MAP_XY(flies[c1].x + s4, flies[c1].y) != BAN_VOID) + s4 = 0; + flies[c1].x += s4; + s3 = 0; + if ((s2 - flies[c1].y) > 30) + s3 += 1; + else if ((s2 - flies[c1].y) < -30) + s3 -= 1; + if (dist < 30) { + if (((player[closest_player].y >> 16) + 8) > flies[c1].y) { + if (lord_of_the_flies == 0) + s3 -= 1; + else + s3 += 1; + } else { + if (lord_of_the_flies == 0) + s3 += 1; + else + s3 -= 1; + } + } + s4 = rnd(3) - 1 + s3; + if ((flies[c1].y + s4) < 0) + s4 = 0; + if ((flies[c1].y + s4) > 239) + s4 = 0; + if (GET_BAN_MAP_XY(flies[c1].x, flies[c1].y + s4) != BAN_VOID) + s4 = 0; + flies[c1].y += s4; + } +} + + +static void player_kill(int c1, int c2) +{ + if (player[c1].y_add >= 0) { + if (is_server) + serverSendKillPacket(c1, c2); + } else { + if (player[c2].y_add < 0) + player[c2].y_add = 0; + } +} + + +static void check_cheats(void) +{ + if (strncmp(last_keys, "kcitsogop", strlen("kcitsogop")) == 0) { + pogostick ^= 1; + last_keys[0] = 0; + } + if (strncmp(last_keys, "ecapsniseinnub", strlen("ecapsniseinnub")) == 0) { + bunnies_in_space ^= 1; + last_keys[0] = 0; + } + if (strncmp(last_keys, "kcaptej", strlen("kcaptej")) == 0) { + jetpack ^= 1; + last_keys[0] = 0; + } + if (strncmp(last_keys, "seilfehtfodrol", strlen("seilfehtfodrol")) == 0) { + lord_of_the_flies ^= 1; + last_keys[0] = 0; + } + if (strncmp(last_keys, "retawnahtrekcihtsidoolb", strlen("retawnahtrekcihtsidoolb")) == 0) { + char blood[32] = { + 63,32,32,53,17,17,42, 7, + 7,28, 0, 0,24, 0, 0,19, + 0, 0,12, 0, 0, 7, 0, 0 + }; + char water[32] = { + 63,63,63,40,53,62,19,42, + 60, 0,33,60, 3,32,46, 3, + 26,33, 3,19,21, 1, 8, 8 + }; + int i; + + blood_is_thicker_than_water ^= 1; + if (blood_is_thicker_than_water == 1) { + for (i=0; i<32; i++) + pal[432+i] = blood[i]; + } else { + for (i=0; i<32; i++) + pal[432+i] = water[i]; + } + register_background(background_pic, pal); + recalculate_gob(&object_gobs, pal); + last_keys[0] = 0; + } +} + + +static void collision_check(void) +{ + int c1 = 0, c2 = 0, c3 = 0; + int l1; + + /* collision check */ + for (c3 = 0; c3 < 6; c3++) { + if (c3 == 0) { + c1 = 0; + c2 = 1; + } else if (c3 == 1) { + c1 = 0; + c2 = 2; + } else if (c3 == 2) { + c1 = 0; + c2 = 3; + } else if (c3 == 3) { + c1 = 1; + c2 = 2; + } else if (c3 == 4) { + c1 = 1; + c2 = 3; + } else if (c3 == 5) { + c1 = 2; + c2 = 3; + } + if (player[c1].enabled == 1 && player[c2].enabled == 1) { + if (labs(player[c1].x - player[c2].x) < (12L << 16) && labs(player[c1].y - player[c2].y) < (12L << 16)) { + if ((labs(player[c1].y - player[c2].y) >> 16) > 5) { + if (player[c1].y < player[c2].y) { + player_kill(c1,c2); + } else { + player_kill(c2,c1); + } + } else { + if (player[c1].x < player[c2].x) { + if (player[c1].x_add > 0) + player[c1].x = player[c2].x - (12L << 16); + else if (player[c2].x_add < 0) + player[c2].x = player[c1].x + (12L << 16); + else { + player[c1].x -= player[c1].x_add; + player[c2].x -= player[c2].x_add; + } + l1 = player[c2].x_add; + player[c2].x_add = player[c1].x_add; + player[c1].x_add = l1; + if (player[c1].x_add > 0) + player[c1].x_add = -player[c1].x_add; + if (player[c2].x_add < 0) + player[c2].x_add = -player[c2].x_add; + } else { + if (player[c1].x_add > 0) + player[c2].x = player[c1].x - (12L << 16); + else if (player[c2].x_add < 0) + player[c1].x = player[c2].x + (12L << 16); + else { + player[c1].x -= player[c1].x_add; + player[c2].x -= player[c2].x_add; + } + l1 = player[c2].x_add; + player[c2].x_add = player[c1].x_add; + player[c1].x_add = l1; + if (player[c1].x_add < 0) + player[c1].x_add = -player[c1].x_add; + if (player[c2].x_add > 0) + player[c2].x_add = -player[c2].x_add; + } + } + } + } + } +} + +static void game_loop(void) { + int mod_vol, sfx_vol; + int update_count = 1; + int end_loop_flag = 0; + int fade_flag = 0; + int update_palette = 0; + int mod_fade_direction; + int i; + + mod_vol = sfx_vol = 0; + mod_fade_direction = 1; + dj_ready_mod(MOD_GAME); + dj_set_mod_volume((char)mod_vol); + dj_set_sfx_volume((char)mod_vol); + dj_start_mod(); + + intr_sysupdate(); + + while (1) { + while (update_count) { + + if (key_pressed(1) == 1) { +#ifdef USE_NET + if (is_net) { + if (is_server) { + serverTellEveryoneGoodbye(); + } else { + tellServerGoodbye(); + } + } +#endif + end_loop_flag = 1; + memset(pal, 0, 768); + mod_fade_direction = 0; + } + + check_cheats(); + +#ifdef USE_NET + if (is_net) { + if (is_server) { + update_players_from_clients(); + } else { + if (!update_players_from_server()) { + break; /* got a BYE packet */ + } + } + } +#endif + + steer_players(); + + dj_mix(); + + collision_check(); + + dj_mix(); + + main_info.page_info[main_info.draw_page].num_pobs = 0; + for (i = 0; i < JNB_MAX_PLAYERS; i++) { + if (player[i].enabled == 1) + main_info.page_info[main_info.draw_page].num_pobs++; + } + + update_objects(); + + dj_mix(); + + if (flies_enabled) { + update_flies(update_count); + } + + dj_mix(); + + if (update_count == 1) { + int c2; + + for (i = 0, c2 = 0; i < JNB_MAX_PLAYERS; i++) { + if (player[i].enabled == 1) { + main_info.page_info[main_info.draw_page].pobs[c2].x = player[i].x >> 16; + main_info.page_info[main_info.draw_page].pobs[c2].y = player[i].y >> 16; + main_info.page_info[main_info.draw_page].pobs[c2].image = player[i].image + i * 18; + main_info.page_info[main_info.draw_page].pobs[c2].pob_data = &rabbit_gobs; + c2++; + } + } + + draw_begin(); + + draw_pobs(main_info.draw_page); + + dj_mix(); + + if (flies_enabled) + draw_flies(main_info.draw_page); + + draw_end(); + } + + if (mod_fade_direction == 1) { + if (mod_vol < 30) { + mod_vol++; + dj_set_mod_volume((char)mod_vol); + } + if (sfx_vol < 64) { + sfx_vol++; + dj_set_sfx_volume((char)sfx_vol); + } + } else { + if (mod_vol > 0) { + mod_vol--; + dj_set_mod_volume((char)mod_vol); + } + if (sfx_vol > 0) { + sfx_vol--; + dj_set_sfx_volume((char)sfx_vol); + } + } + + fade_flag = 0; + for (i = 0; i < 768; i++) { + if (cur_pal[i] < pal[i]) { + cur_pal[i]++; + fade_flag = 1; + } else if (cur_pal[i] > pal[i]) { + cur_pal[i]--; + fade_flag = 1; + } + } + if (fade_flag == 1) + update_palette = 1; + if (fade_flag == 0 && end_loop_flag == 1) + break; + + if (update_count == 1) { + if (update_palette == 1) { + setpalette(0, 256, cur_pal); + update_palette = 0; + } + + main_info.draw_page ^= 1; + main_info.view_page ^= 1; + + flippage(main_info.view_page); + + wait_vrt(1); + + draw_begin(); + + if (flies_enabled) + redraw_flies_background(main_info.draw_page); + + redraw_pob_backgrounds(main_info.draw_page); + + draw_leftovers(main_info.draw_page); + + draw_end(); + } + + update_count--; + } + +#ifdef USE_NET + if (is_net) { + if ( (player[client_player_num].dead_flag == 0) && + ( + (player[client_player_num].action_left) || + (player[client_player_num].action_right) || + (player[client_player_num].action_up) || + (player[client_player_num].jump_ready == 0) + ) + ) { + tellServerNewPosition(); + } + } +#endif + + update_count = intr_sysupdate(); + +#ifdef USE_NET + if (is_net) { + if ((server_said_bye) || ((fade_flag == 0) && (end_loop_flag == 1))) + break; + } else +#endif + if ((fade_flag == 0) && (end_loop_flag == 1)) + break; + } +} + + +static int menu_loop(void) +{ + unsigned char *handle; + int mod_vol; + int c1, c2; + int s1, s2; + + for(c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) // reset player values + { + ai[c1] = 0; + } + + while (1) { + + if (!is_net) + if (menu() != 0) + deinit_program(); + + if (key_pressed(1) == 1) { + return 0; + } + if (init_level(0, pal) != 0) { + deinit_level(); + deinit_program(); + } + + memset(cur_pal, 0, 768); + setpalette(0, 256, cur_pal); + + recalculate_gob(&rabbit_gobs, pal); + recalculate_gob(&object_gobs, pal); + recalculate_gob(&number_gobs, pal); + + flippage(1); + register_background(background_pic, pal); + flippage(0); + + if (flies_enabled) { + s1 = rnd(250) + 50; + s2 = rnd(150) + 50; + + for (c1 = 0; c1 < NUM_FLIES; c1++) { + while (1) { + flies[c1].x = s1 + rnd(101) - 50; + flies[c1].y = s2 + rnd(101) - 50; + if (GET_BAN_MAP_XY(flies[c1].x, flies[c1].y) == BAN_VOID) + break; + } + flies[c1].back_defined[0] = 0; + flies[c1].back_defined[1] = 0; + } + } + + if (flies_enabled) + dj_play_sfx(SFX_FLY, SFX_FLY_FREQ, 0, 0, 0, 4); + + dj_set_nosound(0); + + lord_of_the_flies = bunnies_in_space = jetpack = pogostick = blood_is_thicker_than_water = 0; + main_info.page_info[0].num_pobs = 0; + main_info.page_info[1].num_pobs = 0; + main_info.view_page = 0; + main_info.draw_page = 1; + + game_loop(); + +#ifdef USE_NET + if (is_net) { + if (is_server) { + serverTellEveryoneGoodbye(); + SDLNet_TCP_Close(sock); + sock = NULL; + } else { + if (!server_said_bye) { + tellServerGoodbye(); + } + + SDLNet_TCP_Close(sock); + sock = NULL; + } + } +#endif + + main_info.view_page = 0; + main_info.draw_page = 1; + + dj_stop_sfx_channel(4); + + deinit_level(); + + memset(mask_pic, 0, JNB_WIDTH*JNB_HEIGHT); + register_mask(mask_pic); + + register_background(NULL, NULL); + + draw_begin(); + + put_text(main_info.view_page, 100, 50, "DOTT", 2); + put_text(main_info.view_page, 160, 50, "JIFFY", 2); + put_text(main_info.view_page, 220, 50, "FIZZ", 2); + put_text(main_info.view_page, 280, 50, "MIJJI", 2); + put_text(main_info.view_page, 40, 80, "DOTT", 2); + put_text(main_info.view_page, 40, 110, "JIFFY", 2); + put_text(main_info.view_page, 40, 140, "FIZZ", 2); + put_text(main_info.view_page, 40, 170, "MIJJI", 2); + + for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) { + char str1[100]; + + for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++) { + if (c2 != c1) { + sprintf(str1, "%d", player[c1].bumped[c2]); + put_text(main_info.view_page, 100 + c2 * 60, 80 + c1 * 30, str1, 2); + } else + put_text(main_info.view_page, 100 + c2 * 60, 80 + c1 * 30, "-", 2); + } + sprintf(str1, "%d", player[c1].bumps); + put_text(main_info.view_page, 350, 80 + c1 * 30, str1, 2); + } + + put_text(main_info.view_page, 200, 230, "Press ESC to continue", 2); + + draw_end(); + + flippage(main_info.view_page); + + if ((handle = dat_open("menu.pcx")) == 0) { + strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n"); + return 1; + } + if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) { + strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n"); + return 1; + } + + /* fix dark font */ + for (c1 = 0; c1 < 16; c1++) { + pal[(240 + c1) * 3 + 0] = c1 << 2; + pal[(240 + c1) * 3 + 1] = c1 << 2; + pal[(240 + c1) * 3 + 2] = c1 << 2; + } + + memset(cur_pal, 0, 768); + + setpalette(0, 256, cur_pal); + + mod_vol = 0; + dj_ready_mod(MOD_SCORES); + dj_set_mod_volume((char)mod_vol); + dj_start_mod(); + dj_set_nosound(0); + + while (key_pressed(1) == 0) { + if (mod_vol < 35) + mod_vol++; + dj_set_mod_volume((char)mod_vol); + for (c1 = 0; c1 < 768; c1++) { + if (cur_pal[c1] < pal[c1]) + cur_pal[c1]++; + } + dj_mix(); + intr_sysupdate(); + wait_vrt(0); + setpalette(0, 256, cur_pal); + flippage(main_info.view_page); + } + while (key_pressed(1) == 1) { + dj_mix(); + intr_sysupdate(); + } + + memset(pal, 0, 768); + + while (mod_vol > 0) { + mod_vol--; + dj_set_mod_volume((char)mod_vol); + for (c1 = 0; c1 < 768; c1++) { + if (cur_pal[c1] > pal[c1]) + cur_pal[c1]--; + } + dj_mix(); + wait_vrt(0); + setpalette(0, 256, cur_pal); + flippage(main_info.view_page); + } + + fillpalette(0, 0, 0); + + dj_set_nosound(1); + dj_stop_mod(); + + if (is_net) + return 0; /* don't go back to menu if in net game. */ + } +} + + +int main(int argc, char *argv[]) +{ + int result; + + if (init_program(argc, argv, pal) != 0) + deinit_program(); + + if (main_info.fireworks == 1) { + fireworks(); + deinit_program(); + } + + result = menu_loop(); + + deinit_program(); + + return result; +} + + +static void player_action_left(int c1) +{ + int s1 = 0, s2 = 0; + int below_left, below, below_right; + + s1 = (player[c1].x >> 16); + s2 = (player[c1].y >> 16); + below_left = GET_BAN_MAP_XY(s1, s2 + 16); + below = GET_BAN_MAP_XY(s1 + 8, s2 + 16); + below_right = GET_BAN_MAP_XY(s1 + 15, s2 + 16); + + if (below == BAN_ICE) { + if (player[c1].x_add > 0) + player[c1].x_add -= 1024; + else + player[c1].x_add -= 768; + } else if ((below_left != BAN_SOLID && below_right == BAN_ICE) || (below_left == BAN_ICE && below_right != BAN_SOLID)) { + if (player[c1].x_add > 0) + player[c1].x_add -= 1024; + else + player[c1].x_add -= 768; + } else { + if (player[c1].x_add > 0) { + player[c1].x_add -= 16384; + if (player[c1].x_add > -98304L && player[c1].in_water == 0 && below == BAN_SOLID) + add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0); + } else + player[c1].x_add -= 12288; + } + if (player[c1].x_add < -98304L) + player[c1].x_add = -98304L; + player[c1].direction = 1; + if (player[c1].anim == 0) { + player[c1].anim = 1; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } +} + + +static void player_action_right(int c1) +{ + int s1 = 0, s2 = 0; + int below_left, below, below_right; + + s1 = (player[c1].x >> 16); + s2 = (player[c1].y >> 16); + below_left = GET_BAN_MAP_XY(s1, s2 + 16); + below = GET_BAN_MAP_XY(s1 + 8, s2 + 16); + below_right = GET_BAN_MAP_XY(s1 + 15, s2 + 16); + + if (below == BAN_ICE) { + if (player[c1].x_add < 0) + player[c1].x_add += 1024; + else + player[c1].x_add += 768; + } else if ((below_left != BAN_SOLID && below_right == BAN_ICE) || (below_left == BAN_ICE && below_right != BAN_SOLID)) { + if (player[c1].x_add > 0) + player[c1].x_add += 1024; + else + player[c1].x_add += 768; + } else { + if (player[c1].x_add < 0) { + player[c1].x_add += 16384; + if (player[c1].x_add < 98304L && player[c1].in_water == 0 && below == BAN_SOLID) + add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0); + } else + player[c1].x_add += 12288; + } + if (player[c1].x_add > 98304L) + player[c1].x_add = 98304L; + player[c1].direction = 0; + if (player[c1].anim == 0) { + player[c1].anim = 1; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } +} + +int map_tile(int pos_x, int pos_y) +{ +int tile; + +pos_x = pos_x >> 4; +pos_y = pos_y >> 4; + +if(pos_x < 0 || pos_x >= 17 || pos_y < 0 || pos_y >= 22) + return BAN_VOID; + +tile = ban_map[pos_y][pos_x]; +return tile; +} + +void cpu_move(void) +{ + int lm, rm, jm; + int i, j; + int cur_posx, cur_posy, tar_posx, tar_posy; + int players_distance; + player_t* target = NULL; + int nearest_distance = -1; + + for (i = 0; i < JNB_MAX_PLAYERS; i++) + { + nearest_distance = -1; + if(ai[i] && player[i].enabled) // this player is a computer + { // get nearest target + for (j = 0; j < JNB_MAX_PLAYERS; j++) + { + int deltax, deltay; + + if(i == j || !player[j].enabled) + continue; + + deltax = player[j].x - player[i].x; + deltay = player[j].y - player[i].y; + players_distance = deltax*deltax + deltay*deltay; + + if (players_distance < nearest_distance || nearest_distance == -1) + { + target = &player[j]; + nearest_distance = players_distance; + } + } + + if(target == NULL) + continue; + + cur_posx = player[i].x >> 16; + cur_posy = player[i].y >> 16; + tar_posx = target->x >> 16; + tar_posy = target->y >> 16; + + /** nearest player found, get him */ + /* here goes the artificial intelligence code */ + + /* X-axis movement */ + if(tar_posx > cur_posx) // if true target is on the right side + { // go after him + lm=0; + rm=1; + } + else // target on the left side + { + lm=1; + rm=0; + } + + if(cur_posy - tar_posy < 32 && cur_posy - tar_posy > 0 && + tar_posx - cur_posx < 32+8 && tar_posx - cur_posx > -32) + { + lm = !lm; + rm = !rm; + } + else if(tar_posx - cur_posx < 4+8 && tar_posx - cur_posx > -4) + { // makes the bunnies less "nervous" + lm=0; + lm=0; + } + + /* Y-axis movement */ + if(map_tile(cur_posx, cur_posy+16) != BAN_VOID && + ((i == 0 && key_pressed(KEY_PL1_JUMP)) || + (i == 1 && key_pressed(KEY_PL2_JUMP)) || + (i == 2 && key_pressed(KEY_PL3_JUMP)) || + (i == 3 && key_pressed(KEY_PL4_JUMP)))) + jm=0; // if we are on ground and jump key is being pressed, + //first we have to release it or else we won't be able to jump more than once + + else if(map_tile(cur_posx, cur_posy-8) != BAN_VOID && + map_tile(cur_posx, cur_posy-8) != BAN_WATER) + jm=0; // don't jump if there is something over it + + else if(map_tile(cur_posx-(lm*8)+(rm*16), cur_posy) != BAN_VOID && + map_tile(cur_posx-(lm*8)+(rm*16), cur_posy) != BAN_WATER && + cur_posx > 16 && cur_posx < 352-16-8) // obstacle, jump + jm=1; // if there is something on the way, jump over it + + else if(((i == 0 && key_pressed(KEY_PL1_JUMP)) || + (i == 1 && key_pressed(KEY_PL2_JUMP)) || + (i == 2 && key_pressed(KEY_PL3_JUMP)) || + (i == 3 && key_pressed(KEY_PL4_JUMP))) && + (map_tile(cur_posx-(lm*8)+(rm*16), cur_posy+8) != BAN_VOID && + map_tile(cur_posx-(lm*8)+(rm*16), cur_posy+8) != BAN_WATER)) + jm=1; // this makes it possible to jump over 2 tiles + + else if(cur_posy - tar_posy < 32 && cur_posy - tar_posy > 0 && + tar_posx - cur_posx < 32+8 && tar_posx - cur_posx > -32) // don't jump - running away + jm=0; + + else if(tar_posy <= cur_posy) // target on the upper side + jm=1; + else // target below + jm=0; + + /** Artificial intelligence done, now apply movements */ + if(lm) + { + SDLKey key; + if(i == 0) + key = KEY_PL1_LEFT; + else if(i == 1) + key = KEY_PL2_LEFT; + else if(i == 2) + key = KEY_PL3_LEFT; + else + key = KEY_PL4_LEFT; + + key &= 0x7f; + addkey(key); + } + else + { + SDLKey key; + if(i == 0) + key = KEY_PL1_LEFT; + else if(i == 1) + key = KEY_PL2_LEFT; + else if(i == 2) + key = KEY_PL3_LEFT; + else + key = KEY_PL4_LEFT; + + key &= 0x7f; + addkey(key | 0x8000); + } + + if(rm) + { + SDLKey key; + if(i == 0) + key = KEY_PL1_RIGHT; + else if(i == 1) + key = KEY_PL2_RIGHT; + else if(i == 2) + key = KEY_PL3_RIGHT; + else + key = KEY_PL4_RIGHT; + + key &= 0x7f; + addkey(key); + } + else + { + SDLKey key; + if(i == 0) + key = KEY_PL1_RIGHT; + else if(i == 1) + key = KEY_PL2_RIGHT; + else if(i == 2) + key = KEY_PL3_RIGHT; + else + key = KEY_PL4_RIGHT; + + key &= 0x7f; + addkey(key | 0x8000); + } + + if(jm) + { + SDLKey key; + if(i == 0) + key = KEY_PL1_JUMP; + else if(i == 1) + key = KEY_PL2_JUMP; + else if(i == 2) + key = KEY_PL3_JUMP; + else + key = KEY_PL4_JUMP; + + key &= 0x7f; + addkey(key); + } + else + { + SDLKey key; + if(i == 0) + key = KEY_PL1_JUMP; + else if(i == 1) + key = KEY_PL2_JUMP; + else if(i == 2) + key = KEY_PL3_JUMP; + else + key = KEY_PL4_JUMP; + + key &= 0x7f; + addkey(key | 0x8000); + } + } + } +} + + +#define GET_BAN_MAP_IN_WATER(s1, s2) (GET_BAN_MAP_XY((s1), ((s2) + 7)) == BAN_VOID || GET_BAN_MAP_XY(((s1) + 15), ((s2) + 7)) == BAN_VOID) && (GET_BAN_MAP_XY((s1), ((s2) + 8)) == BAN_WATER || GET_BAN_MAP_XY(((s1) + 15), ((s2) + 8)) == BAN_WATER) + + +void steer_players(void) +{ + int c1, c2; + int s1 = 0, s2 = 0; + + cpu_move(); + update_player_actions(); + + for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) { + + if (player[c1].enabled == 1) { + + if (player[c1].dead_flag == 0) { + + if (player[c1].action_left && player[c1].action_right) { + if (player[c1].direction == 0) { + if (player[c1].action_right) { + player_action_right(c1); + } + } else { + if (player[c1].action_left) { + player_action_left(c1); + } + } + } else if (player[c1].action_left) { + player_action_left(c1); + } else if (player[c1].action_right) { + player_action_right(c1); + } else if ((!player[c1].action_left) && (!player[c1].action_right)) { + int below_left, below, below_right; + + s1 = (player[c1].x >> 16); + s2 = (player[c1].y >> 16); + below_left = GET_BAN_MAP_XY(s1, s2 + 16); + below = GET_BAN_MAP_XY(s1 + 8, s2 + 16); + below_right = GET_BAN_MAP_XY(s1 + 15, s2 + 16); + if (below == BAN_SOLID || below == BAN_SPRING || (((below_left == BAN_SOLID || below_left == BAN_SPRING) && below_right != BAN_ICE) || (below_left != BAN_ICE && (below_right == BAN_SOLID || below_right == BAN_SPRING)))) { + if (player[c1].x_add < 0) { + player[c1].x_add += 16384; + if (player[c1].x_add > 0) + player[c1].x_add = 0; + } else { + player[c1].x_add -= 16384; + if (player[c1].x_add < 0) + player[c1].x_add = 0; + } + if (player[c1].x_add != 0 && GET_BAN_MAP_XY((s1 + 8), (s2 + 16)) == BAN_SOLID) + add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0); + } + if (player[c1].anim == 1) { + player[c1].anim = 0; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } + } + if (jetpack == 0) { + /* no jetpack */ + if (pogostick == 1 || (player[c1].jump_ready == 1 && player[c1].action_up)) { + s1 = (player[c1].x >> 16); + s2 = (player[c1].y >> 16); + if (s2 < -16) + s2 = -16; + /* jump */ + if (GET_BAN_MAP_XY(s1, (s2 + 16)) == BAN_SOLID || GET_BAN_MAP_XY(s1, (s2 + 16)) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), (s2 + 16)) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), (s2 + 16)) == BAN_ICE) { + player[c1].y_add = -280000L; + player[c1].anim = 2; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + player[c1].jump_ready = 0; + player[c1].jump_abort = 1; + if (pogostick == 0) + dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1); + else + dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1); + } + /* jump out of water */ + if (GET_BAN_MAP_IN_WATER(s1, s2)) { + player[c1].y_add = -196608L; + player[c1].in_water = 0; + player[c1].anim = 2; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + player[c1].jump_ready = 0; + player[c1].jump_abort = 1; + if (pogostick == 0) + dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1); + else + dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1); + } + } + /* fall down by gravity */ + if (pogostick == 0 && (!player[c1].action_up)) { + player[c1].jump_ready = 1; + if (player[c1].in_water == 0 && player[c1].y_add < 0 && player[c1].jump_abort == 1) { + if (bunnies_in_space == 0) + /* normal gravity */ + player[c1].y_add += 32768; + else + /* light gravity */ + player[c1].y_add += 16384; + if (player[c1].y_add > 0) + player[c1].y_add = 0; + } + } + } else { + /* with jetpack */ + if (player[c1].action_up) { + player[c1].y_add -= 16384; + if (player[c1].y_add < -400000L) + player[c1].y_add = -400000L; + if (GET_BAN_MAP_IN_WATER(s1, s2)) + player[c1].in_water = 0; + if (rnd(100) < 50) + add_object(OBJ_SMOKE, (player[c1].x >> 16) + 6 + rnd(5), (player[c1].y >> 16) + 10 + rnd(5), 0, 16384 + rnd(8192), OBJ_ANIM_SMOKE, 0); + } + } + + player[c1].x += player[c1].x_add; + if ((player[c1].x >> 16) < 0) { + player[c1].x = 0; + player[c1].x_add = 0; + } + if ((player[c1].x >> 16) + 15 > 351) { + player[c1].x = 336L << 16; + player[c1].x_add = 0; + } + { + if (player[c1].y > 0) { + s2 = (player[c1].y >> 16); + } else { + /* check top line only */ + s2 = 0; + } + + s1 = (player[c1].x >> 16); + if (GET_BAN_MAP_XY(s1, s2) == BAN_SOLID || GET_BAN_MAP_XY(s1, s2) == BAN_ICE || GET_BAN_MAP_XY(s1, s2) == BAN_SPRING || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SPRING) { + player[c1].x = (((s1 + 16) & 0xfff0)) << 16; + player[c1].x_add = 0; + } + + s1 = (player[c1].x >> 16); + if (GET_BAN_MAP_XY((s1 + 15), s2) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_SPRING || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SPRING) { + player[c1].x = (((s1 + 16) & 0xfff0) - 16) << 16; + player[c1].x_add = 0; + } + } + + player[c1].y += player[c1].y_add; + + s1 = (player[c1].x >> 16); + s2 = (player[c1].y >> 16); + if (GET_BAN_MAP_XY((s1 + 8), (s2 + 15)) == BAN_SPRING || ((GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SPRING && GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) != BAN_SOLID) || (GET_BAN_MAP_XY(s1, (s2 + 15)) != BAN_SOLID && GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SPRING))) { + player[c1].y = ((player[c1].y >> 16) & 0xfff0) << 16; + player[c1].y_add = -400000L; + player[c1].anim = 2; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + player[c1].jump_ready = 0; + player[c1].jump_abort = 0; + for (c2 = 0; c2 < NUM_OBJECTS; c2++) { + if (objects[c2].used == 1 && objects[c2].type == OBJ_SPRING) { + if (GET_BAN_MAP_XY((s1 + 8), (s2 + 15)) == BAN_SPRING) { + if ((objects[c2].x >> 20) == ((s1 + 8) >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) { + objects[c2].frame = 0; + objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks; + objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image; + break; + } + } else { + if (GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SPRING) { + if ((objects[c2].x >> 20) == (s1 >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) { + objects[c2].frame = 0; + objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks; + objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image; + break; + } + } else if (GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SPRING) { + if ((objects[c2].x >> 20) == ((s1 + 15) >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) { + objects[c2].frame = 0; + objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks; + objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image; + break; + } + } + } + } + } + dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1); + } + s1 = (player[c1].x >> 16); + s2 = (player[c1].y >> 16); + if (s2 < 0) + s2 = 0; + if (GET_BAN_MAP_XY(s1, s2) == BAN_SOLID || GET_BAN_MAP_XY(s1, s2) == BAN_ICE || GET_BAN_MAP_XY(s1, s2) == BAN_SPRING || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_SPRING) { + player[c1].y = (((s2 + 16) & 0xfff0)) << 16; + player[c1].y_add = 0; + player[c1].anim = 0; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } + s1 = (player[c1].x >> 16); + s2 = (player[c1].y >> 16); + if (s2 < 0) + s2 = 0; + if (GET_BAN_MAP_XY((s1 + 8), (s2 + 8)) == BAN_WATER) { + if (player[c1].in_water == 0) { + /* falling into water */ + player[c1].in_water = 1; + player[c1].anim = 4; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + if (player[c1].y_add >= 32768) { + add_object(OBJ_SPLASH, (player[c1].x >> 16) + 8, ((player[c1].y >> 16) & 0xfff0) + 15, 0, 0, OBJ_ANIM_SPLASH, 0); + if (blood_is_thicker_than_water == 0) + dj_play_sfx(SFX_SPLASH, (unsigned short)(SFX_SPLASH_FREQ + rnd(2000) - 1000), 64, 0, 0, -1); + else + dj_play_sfx(SFX_SPLASH, (unsigned short)(SFX_SPLASH_FREQ + rnd(2000) - 5000), 64, 0, 0, -1); + } + } + /* slowly move up to water surface */ + player[c1].y_add -= 1536; + if (player[c1].y_add < 0 && player[c1].anim != 5) { + player[c1].anim = 5; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } + if (player[c1].y_add < -65536L) + player[c1].y_add = -65536L; + if (player[c1].y_add > 65535L) + player[c1].y_add = 65535L; + if (GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_ICE) { + player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16; + player[c1].y_add = 0; + } + } else if (GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SPRING || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SPRING) { + player[c1].in_water = 0; + player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16; + player[c1].y_add = 0; + if (player[c1].anim != 0 && player[c1].anim != 1) { + player[c1].anim = 0; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } + } else { + if (player[c1].in_water == 0) { + if (bunnies_in_space == 0) + player[c1].y_add += 12288; + else + player[c1].y_add += 6144; + if (player[c1].y_add > 327680L) + player[c1].y_add = 327680L; + } else { + player[c1].y = (player[c1].y & 0xffff0000) + 0x10000; + player[c1].y_add = 0; + } + player[c1].in_water = 0; + } + if (player[c1].y_add > 36864 && player[c1].anim != 3 && player[c1].in_water == 0) { + player[c1].anim = 3; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } + + } + + player[c1].frame_tick++; + if (player[c1].frame_tick >= player_anims[player[c1].anim].frame[player[c1].frame].ticks) { + player[c1].frame++; + if (player[c1].frame >= player_anims[player[c1].anim].num_frames) { + if (player[c1].anim != 6) + player[c1].frame = player_anims[player[c1].anim].restart_frame; + else + position_player(c1); + } + player[c1].frame_tick = 0; + } + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + + } + + } + +} + + +void position_player(int player_num) +{ + int c1; + int s1, s2; + + while (1) { + while (1) { + s1 = rnd(22); + s2 = rnd(16); + if (ban_map[s2][s1] == BAN_VOID && (ban_map[s2 + 1][s1] == BAN_SOLID || ban_map[s2 + 1][s1] == BAN_ICE)) + break; + } + for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) { + if (c1 != player_num && player[c1].enabled == 1) { + if (abs((s1 << 4) - (player[c1].x >> 16)) < 32 && abs((s2 << 4) - (player[c1].y >> 16)) < 32) + break; + } + } + if (c1 == JNB_MAX_PLAYERS) { + player[player_num].x = (long) s1 << 20; + player[player_num].y = (long) s2 << 20; + player[player_num].x_add = player[player_num].y_add = 0; + player[player_num].direction = 0; + player[player_num].jump_ready = 1; + player[player_num].in_water = 0; + player[player_num].anim = 0; + player[player_num].frame = 0; + player[player_num].frame_tick = 0; + player[player_num].image = player_anims[player[player_num].anim].frame[player[player_num].frame].image; + + if (is_server) { +#ifdef USE_NET + if (is_net) + serverSendAlive(player_num); +#endif + player[player_num].dead_flag = 0; + } + + break; + } + } + +} + + +void add_object(int type, int x, int y, int x_add, int y_add, int anim, int frame) +{ + int c1; + + for (c1 = 0; c1 < NUM_OBJECTS; c1++) { + if (objects[c1].used == 0) { + objects[c1].used = 1; + objects[c1].type = type; + objects[c1].x = (long) x << 16; + objects[c1].y = (long) y << 16; + objects[c1].x_add = x_add; + objects[c1].y_add = y_add; + objects[c1].x_acc = 0; + objects[c1].y_acc = 0; + objects[c1].anim = anim; + objects[c1].frame = frame; + objects[c1].ticks = object_anims[anim].frame[frame].ticks; + objects[c1].image = object_anims[anim].frame[frame].image; + break; + } + } + +} + + +void update_objects(void) +{ + int c1; + int s1 = 0; + + for (c1 = 0; c1 < NUM_OBJECTS; c1++) { + if (objects[c1].used == 1) { + switch (objects[c1].type) { + case OBJ_SPRING: + objects[c1].ticks--; + if (objects[c1].ticks <= 0) { + objects[c1].frame++; + if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames) { + objects[c1].frame--; + objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks; + } else { + objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks; + objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image; + } + } + if (objects[c1].used == 1) + add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs); + break; + case OBJ_SPLASH: + objects[c1].ticks--; + if (objects[c1].ticks <= 0) { + objects[c1].frame++; + if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames) + objects[c1].used = 0; + else { + objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks; + objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image; + } + } + if (objects[c1].used == 1) + add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs); + break; + case OBJ_SMOKE: + objects[c1].x += objects[c1].x_add; + objects[c1].y += objects[c1].y_add; + objects[c1].ticks--; + if (objects[c1].ticks <= 0) { + objects[c1].frame++; + if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames) + objects[c1].used = 0; + else { + objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks; + objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image; + } + } + if (objects[c1].used == 1) + add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs); + break; + case OBJ_YEL_BUTFLY: + case OBJ_PINK_BUTFLY: + objects[c1].x_acc += rnd(128) - 64; + if (objects[c1].x_acc < -1024) + objects[c1].x_acc = -1024; + if (objects[c1].x_acc > 1024) + objects[c1].x_acc = 1024; + objects[c1].x_add += objects[c1].x_acc; + if (objects[c1].x_add < -32768) + objects[c1].x_add = -32768; + if (objects[c1].x_add > 32768) + objects[c1].x_add = 32768; + objects[c1].x += objects[c1].x_add; + if ((objects[c1].x >> 16) < 16) { + objects[c1].x = 16 << 16; + objects[c1].x_add = -objects[c1].x_add >> 2; + objects[c1].x_acc = 0; + } else if ((objects[c1].x >> 16) > 350) { + objects[c1].x = 350 << 16; + objects[c1].x_add = -objects[c1].x_add >> 2; + objects[c1].x_acc = 0; + } + if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0) { + if (objects[c1].x_add < 0) { + objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16; + } else { + objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16; + } + objects[c1].x_add = -objects[c1].x_add >> 2; + objects[c1].x_acc = 0; + } + objects[c1].y_acc += rnd(64) - 32; + if (objects[c1].y_acc < -1024) + objects[c1].y_acc = -1024; + if (objects[c1].y_acc > 1024) + objects[c1].y_acc = 1024; + objects[c1].y_add += objects[c1].y_acc; + if (objects[c1].y_add < -32768) + objects[c1].y_add = -32768; + if (objects[c1].y_add > 32768) + objects[c1].y_add = 32768; + objects[c1].y += objects[c1].y_add; + if ((objects[c1].y >> 16) < 0) { + objects[c1].y = 0; + objects[c1].y_add = -objects[c1].y_add >> 2; + objects[c1].y_acc = 0; + } else if ((objects[c1].y >> 16) > 255) { + objects[c1].y = 255 << 16; + objects[c1].y_add = -objects[c1].y_add >> 2; + objects[c1].y_acc = 0; + } + if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0) { + if (objects[c1].y_add < 0) { + objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16; + } else { + objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16; + } + objects[c1].y_add = -objects[c1].y_add >> 2; + objects[c1].y_acc = 0; + } + if (objects[c1].type == OBJ_YEL_BUTFLY) { + if (objects[c1].x_add < 0 && objects[c1].anim != OBJ_ANIM_YEL_BUTFLY_LEFT) { + objects[c1].anim = OBJ_ANIM_YEL_BUTFLY_LEFT; + objects[c1].frame = 0; + objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks; + objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image; + } else if (objects[c1].x_add > 0 && objects[c1].anim != OBJ_ANIM_YEL_BUTFLY_RIGHT) { + objects[c1].anim = OBJ_ANIM_YEL_BUTFLY_RIGHT; + objects[c1].frame = 0; + objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks; + objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image; + } + } else { + if (objects[c1].x_add < 0 && objects[c1].anim != OBJ_ANIM_PINK_BUTFLY_LEFT) { + objects[c1].anim = OBJ_ANIM_PINK_BUTFLY_LEFT; + objects[c1].frame = 0; + objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks; + objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image; + } else if (objects[c1].x_add > 0 && objects[c1].anim != OBJ_ANIM_PINK_BUTFLY_RIGHT) { + objects[c1].anim = OBJ_ANIM_PINK_BUTFLY_RIGHT; + objects[c1].frame = 0; + objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks; + objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image; + } + } + objects[c1].ticks--; + if (objects[c1].ticks <= 0) { + objects[c1].frame++; + if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames) + objects[c1].frame = object_anims[objects[c1].anim].restart_frame; + else { + objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks; + objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image; + } + } + if (objects[c1].used == 1) + add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs); + break; + case OBJ_FUR: + if (rnd(100) < 30) + add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 0); + if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 0) { + objects[c1].y_add += 3072; + if (objects[c1].y_add > 196608L) + objects[c1].y_add = 196608L; + } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 2) { + if (objects[c1].x_add < 0) { + if (objects[c1].x_add < -65536L) + objects[c1].x_add = -65536L; + objects[c1].x_add += 1024; + if (objects[c1].x_add > 0) + objects[c1].x_add = 0; + } else { + if (objects[c1].x_add > 65536L) + objects[c1].x_add = 65536L; + objects[c1].x_add -= 1024; + if (objects[c1].x_add < 0) + objects[c1].x_add = 0; + } + objects[c1].y_add += 1024; + if (objects[c1].y_add < -65536L) + objects[c1].y_add = -65536L; + if (objects[c1].y_add > 65536L) + objects[c1].y_add = 65536L; + } + objects[c1].x += objects[c1].x_add; + if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1 || ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3)) { + if (objects[c1].x_add < 0) { + objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16; + objects[c1].x_add = -objects[c1].x_add >> 2; + } else { + objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16; + objects[c1].x_add = -objects[c1].x_add >> 2; + } + } + objects[c1].y += objects[c1].y_add; + if ((objects[c1].x >> 16) < -5 || (objects[c1].x >> 16) > 405 || (objects[c1].y >> 16) > 260) + objects[c1].used = 0; + if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0)) { + if (objects[c1].y_add < 0) { + if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 2) { + objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16; + objects[c1].x_add >>= 2; + objects[c1].y_add = -objects[c1].y_add >> 2; + } + } else { + if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1) { + if (objects[c1].y_add > 131072L) { + objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16; + objects[c1].x_add >>= 2; + objects[c1].y_add = -objects[c1].y_add >> 2; + } else + objects[c1].used = 0; + } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3) { + objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16; + if (objects[c1].y_add > 131072L) + objects[c1].y_add = -objects[c1].y_add >> 2; + else + objects[c1].y_add = 0; + } + } + } + if (objects[c1].x_add < 0 && objects[c1].x_add > -16384) + objects[c1].x_add = -16384; + if (objects[c1].x_add > 0 && objects[c1].x_add < 16384) + objects[c1].x_add = 16384; + if (objects[c1].used == 1) { + s1 = (int)(atan2(objects[c1].y_add, objects[c1].x_add) * 4 / M_PI); + if (s1 < 0) + s1 += 8; + if (s1 < 0) + s1 = 0; + if (s1 > 7) + s1 = 7; + add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].frame + s1, &object_gobs); + } + break; + case OBJ_FLESH: + if (rnd(100) < 30) { + if (objects[c1].frame == 76) + add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 1); + else if (objects[c1].frame == 77) + add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 2); + else if (objects[c1].frame == 78) + add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 3); + } + if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 0) { + objects[c1].y_add += 3072; + if (objects[c1].y_add > 196608L) + objects[c1].y_add = 196608L; + } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 2) { + if (objects[c1].x_add < 0) { + if (objects[c1].x_add < -65536L) + objects[c1].x_add = -65536L; + objects[c1].x_add += 1024; + if (objects[c1].x_add > 0) + objects[c1].x_add = 0; + } else { + if (objects[c1].x_add > 65536L) + objects[c1].x_add = 65536L; + objects[c1].x_add -= 1024; + if (objects[c1].x_add < 0) + objects[c1].x_add = 0; + } + objects[c1].y_add += 1024; + if (objects[c1].y_add < -65536L) + objects[c1].y_add = -65536L; + if (objects[c1].y_add > 65536L) + objects[c1].y_add = 65536L; + } + objects[c1].x += objects[c1].x_add; + if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1 || ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3)) { + if (objects[c1].x_add < 0) { + objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16; + objects[c1].x_add = -objects[c1].x_add >> 2; + } else { + objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16; + objects[c1].x_add = -objects[c1].x_add >> 2; + } + } + objects[c1].y += objects[c1].y_add; + if ((objects[c1].x >> 16) < -5 || (objects[c1].x >> 16) > 405 || (objects[c1].y >> 16) > 260) + objects[c1].used = 0; + if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0)) { + if (objects[c1].y_add < 0) { + if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 2) { + objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16; + objects[c1].x_add >>= 2; + objects[c1].y_add = -objects[c1].y_add >> 2; + } + } else { + if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1) { + if (objects[c1].y_add > 131072L) { + objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16; + objects[c1].x_add >>= 2; + objects[c1].y_add = -objects[c1].y_add >> 2; + } else { + if (rnd(100) < 10) { + s1 = rnd(4) - 2; + add_leftovers(0, objects[c1].x >> 16, (objects[c1].y >> 16) + s1, objects[c1].frame, &object_gobs); + add_leftovers(1, objects[c1].x >> 16, (objects[c1].y >> 16) + s1, objects[c1].frame, &object_gobs); + } + objects[c1].used = 0; + } + } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3) { + objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16; + if (objects[c1].y_add > 131072L) + objects[c1].y_add = -objects[c1].y_add >> 2; + else + objects[c1].y_add = 0; + } + } + } + if (objects[c1].x_add < 0 && objects[c1].x_add > -16384) + objects[c1].x_add = -16384; + if (objects[c1].x_add > 0 && objects[c1].x_add < 16384) + objects[c1].x_add = 16384; + if (objects[c1].used == 1) + add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].frame, &object_gobs); + break; + case OBJ_FLESH_TRACE: + objects[c1].ticks--; + if (objects[c1].ticks <= 0) { + objects[c1].frame++; + if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames) + objects[c1].used = 0; + else { + objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks; + objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image; + } + } + if (objects[c1].used == 1) + add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs); + break; + } + } + } + +} + + +int add_pob(int page, int x, int y, int image, gob_t *pob_data) +{ + + if (main_info.page_info[page].num_pobs >= NUM_POBS) + return 1; + + main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].x = x; + main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].y = y; + main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].image = image; + main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].pob_data = pob_data; + main_info.page_info[page].num_pobs++; + + return 0; + +} + + +void draw_flies(int page) +{ + int c2; + + for (c2 = 0; c2 < NUM_FLIES; c2++) { + flies[c2].back[main_info.draw_page] = get_pixel(main_info.draw_page, flies[c2].x, flies[c2].y); + flies[c2].back_defined[main_info.draw_page] = 1; + if (mask_pic[(flies[c2].y * JNB_WIDTH) + flies[c2].x] == 0) + set_pixel(main_info.draw_page, flies[c2].x, flies[c2].y, 0); + } +} + +void draw_pobs(int page) +{ + int c1; + int back_buf_ofs; + + back_buf_ofs = 0; + + for (c1 = main_info.page_info[page].num_pobs - 1; c1 >= 0; c1--) { + main_info.page_info[page].pobs[c1].back_buf_ofs = back_buf_ofs; + get_block(page, main_info.page_info[page].pobs[c1].x - pob_hs_x(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), main_info.page_info[page].pobs[c1].y - pob_hs_y(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), pob_width(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), pob_height(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), (unsigned char *)main_info.pob_backbuf[page] + back_buf_ofs); + if (scale_up) + back_buf_ofs += pob_width(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data) * pob_height(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data) * 4; + else + back_buf_ofs += pob_width(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data) * pob_height(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data); + put_pob(page, main_info.page_info[page].pobs[c1].x, main_info.page_info[page].pobs[c1].y, main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data, 1, mask_pic); + } + +} + + +void redraw_flies_background(int page) +{ + int c2; + + for (c2 = NUM_FLIES - 1; c2 >= 0; c2--) { + if (flies[c2].back_defined[page] == 1) + set_pixel(page, flies[c2].old_draw_x, flies[c2].old_draw_y, flies[c2].back[page]); + flies[c2].old_draw_x = flies[c2].x; + flies[c2].old_draw_y = flies[c2].y; + } +} + + +void redraw_pob_backgrounds(int page) +{ + int c1; + + for (c1 = 0; c1 < main_info.page_info[page].num_pobs; c1++) + put_block(page, main_info.page_info[page].pobs[c1].x - pob_hs_x(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), main_info.page_info[page].pobs[c1].y - pob_hs_y(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), pob_width(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), pob_height(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), (unsigned char *)main_info.pob_backbuf[page] + main_info.page_info[page].pobs[c1].back_buf_ofs); + +} + + +int add_leftovers(int page, int x, int y, int image, gob_t *pob_data) +{ + + if (leftovers.page[page].num_pobs >= NUM_LEFTOVERS) + return 1; + + leftovers.page[page].pobs[leftovers.page[page].num_pobs].x = x; + leftovers.page[page].pobs[leftovers.page[page].num_pobs].y = y; + leftovers.page[page].pobs[leftovers.page[page].num_pobs].image = image; + leftovers.page[page].pobs[leftovers.page[page].num_pobs].pob_data = pob_data; + leftovers.page[page].num_pobs++; + + return 0; + +} + + +void draw_leftovers(int page) +{ + int c1; + + for (c1 = leftovers.page[page].num_pobs - 1; c1 >= 0; c1--) + put_pob(page, leftovers.page[page].pobs[c1].x, leftovers.page[page].pobs[c1].y, leftovers.page[page].pobs[c1].image, leftovers.page[page].pobs[c1].pob_data, 1, mask_pic); + + leftovers.page[page].num_pobs = 0; + +} + + +int init_level(int level, char *pal) +{ + unsigned char *handle; + int c1, c2; + int s1, s2; + + if ((handle = dat_open("level.pcx")) == 0) { + strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n"); + return 1; + } + if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) { + strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n"); + return 1; + } + if (flip) + flip_pixels(background_pic); + if ((handle = dat_open("mask.pcx")) == 0) { + strcpy(main_info.error_str, "Error loading 'mask.pcx', aborting...\n"); + return 1; + } + if (read_pcx(handle, mask_pic, JNB_WIDTH*JNB_HEIGHT, 0) != 0) { + strcpy(main_info.error_str, "Error loading 'mask.pcx', aborting...\n"); + return 1; + } + if (flip) + flip_pixels(mask_pic); + register_mask(mask_pic); + + for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) { + if (player[c1].enabled == 1) { + player[c1].bumps = 0; + for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++) + player[c1].bumped[c2] = 0; + position_player(c1); + } + } + + for (c1 = 0; c1 < NUM_OBJECTS; c1++) + objects[c1].used = 0; + + for (c1 = 0; c1 < 16; c1++) { + for (c2 = 0; c2 < 22; c2++) { + if (ban_map[c1][c2] == BAN_SPRING) + add_object(OBJ_SPRING, c2 << 4, c1 << 4, 0, 0, OBJ_ANIM_SPRING, 5); + } + } + + while (1) { + s1 = rnd(22); + s2 = rnd(16); + if (ban_map[s2][s1] == BAN_VOID) { + add_object(OBJ_YEL_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0); + break; + } + } + while (1) { + s1 = rnd(22); + s2 = rnd(16); + if (ban_map[s2][s1] == BAN_VOID) { + add_object(OBJ_YEL_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0); + break; + } + } + while (1) { + s1 = rnd(22); + s2 = rnd(16); + if (ban_map[s2][s1] == BAN_VOID) { + add_object(OBJ_PINK_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0); + break; + } + } + while (1) { + s1 = rnd(22); + s2 = rnd(16); + if (ban_map[s2][s1] == BAN_VOID) { + add_object(OBJ_PINK_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0); + break; + } + } + + return 0; + +} + + +void deinit_level(void) +{ + dj_set_nosound(1); + dj_stop_mod(); +} + + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +unsigned char *datafile_buffer = NULL; + +static void preread_datafile(const char *fname) +{ + int fd = 0; + int len; + +#ifdef ZLIB_SUPPORT + char *gzfilename; + gzFile gzf; +#endif + +#ifdef BZLIB_SUPPORT + char *bzfilename; + BZFILE *bzf; +#endif + +#ifdef BZLIB_SUPPORT + bzfilename = malloc(strlen(fname) + 5); + strcpy(bzfilename, fname); + strcat(bzfilename, ".bz2"); + bzf = BZ2_bzopen(bzfilename, "rb"); + free(bzfilename); + bzfilename = NULL; + + if (bzf != NULL) { + int bufsize = 0; + int bufpos = 0; + int br; + unsigned char *ptr; + do { + if (bufpos >= bufsize) { + bufsize += 1024 * 1024; + datafile_buffer = (unsigned char *) realloc(datafile_buffer, bufsize); + if (datafile_buffer == NULL) { + perror("realloc()"); + exit(42); + } + } + + br = BZ2_bzread(bzf, datafile_buffer + bufpos, bufsize - bufpos); + if (br == -1) { + fprintf(stderr, "gzread failed.\n"); + exit(42); + } + + bufpos += br; + } while (br>0); + + /* try to shrink buffer... */ + ptr = (unsigned char *) realloc(datafile_buffer, bufpos); + if (ptr != NULL) + datafile_buffer = ptr; + + BZ2_bzclose(bzf); + return; + } + + /* drop through and try for an gzip compressed or uncompressed datafile... */ +#endif + +#ifdef ZLIB_SUPPORT + gzfilename = malloc(strlen(fname) + 4); + strcpy(gzfilename, fname); + strcat(gzfilename, ".gz"); + gzf = gzopen(gzfilename, "rb"); + free(gzfilename); + gzfilename = NULL; + + if (gzf != NULL) { + int bufsize = 0; + int bufpos = 0; + unsigned char *ptr; + do { + int br; + if (bufpos >= bufsize) { + bufsize += 1024 * 1024; + datafile_buffer = (unsigned char *) realloc(datafile_buffer, bufsize); + if (datafile_buffer == NULL) { + perror("realloc()"); + exit(42); + } + } + + br = gzread(gzf, datafile_buffer + bufpos, bufsize - bufpos); + if (br == -1) { + fprintf(stderr, "gzread failed.\n"); + exit(42); + } + + bufpos += br; + } while (!gzeof(gzf)); + + /* try to shrink buffer... */ + ptr = (unsigned char *) realloc(datafile_buffer, bufpos); + if (ptr != NULL) + datafile_buffer = ptr; + + gzclose(gzf); + return; + } + + /* drop through and try for an uncompressed datafile... */ +#endif + + fd = open(fname, O_RDONLY | O_BINARY); + if (fd == -1) { + fprintf(stderr, "can't open %s:", fname); + perror(""); + exit(42); + } + + len = filelength(fd); + datafile_buffer = (unsigned char *) malloc(len); + if (datafile_buffer == NULL) { + perror("malloc()"); + close(fd); + exit(42); + } + + if (read(fd, datafile_buffer, len) != len) { + perror("read()"); + close(fd); + exit(42); + } + + close(fd); +} + + +int init_program(int argc, char *argv[], char *pal) +{ + char *netarg = NULL; + unsigned char *handle = (unsigned char *) NULL; + int c1 = 0, c2 = 0; + int load_flag = 0; + int force2, force3; + sfx_data fly; + int player_anim_data[] = { + 1, 0, 0, 0x7fff, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 4, 1, 4, 2, 4, 3, 4, + 1, 0, 4, 0x7fff, 0, 0, 0, 0, 0, 0, + 4, 2, 5, 8, 6, 10, 7, 3, 6, 3, + 1, 0, 6, 0x7fff, 0, 0, 0, 0, 0, 0, + 2, 1, 5, 8, 4, 0x7fff, 0, 0, 0, 0, + 1, 0, 8, 5, 0, 0, 0, 0, 0, 0 + }; + +#ifdef USE_NET + memset(&net_info, 0, sizeof(net_info)); +#endif + +#ifdef DOS + if (__djgpp_nearptr_enable() == 0) + return 1; +#endif + + srand(time(NULL)); + + if (hook_keyb_handler() != 0) + return 1; + + memset(&main_info, 0, sizeof(main_info)); + + strcpy(datfile_name, DATA_PATH); + + force2 = force3 = 0; + + if (argc > 1) { + for (c1 = 1; c1 < argc; c1++) { + if (stricmp(argv[c1], "-nosound") == 0) + main_info.no_sound = 1; + else if (stricmp(argv[c1], "-musicnosound") == 0) + main_info.music_no_sound = 1; + else if (stricmp(argv[c1], "-nogore") == 0) + main_info.no_gore = 1; + else if (stricmp(argv[c1], "-noflies") == 0) + flies_enabled = 0; + else if (stricmp(argv[c1], "-nojoy") == 0) + main_info.joy_enabled = 0; + else if (stricmp(argv[c1], "-fireworks") == 0) + main_info.fireworks = 1; +#ifdef USE_SDL + else if (stricmp(argv[c1], "-fullscreen") == 0) + fs_toggle(); +#endif + else if (stricmp(argv[c1], "-scaleup") == 0) + set_scaling(1); + else if (stricmp(argv[c1], "-mirror") == 0) + flip = 1; + else if (stricmp(argv[c1], "-dat") == 0) { + if (c1 < (argc - 1)) { + FILE *f; + + if ((f = fopen(argv[c1 + 1], "rb")) != NULL) { + fclose(f); + strcpy(datfile_name, argv[c1 + 1]); + } + } + } else if (stricmp(argv[c1], "-player") == 0) { + if (c1 < (argc - 1)) { + if (client_player_num < 0) + client_player_num = atoi(argv[c1 + 1]); + } +#ifdef USE_NET + } else if (stricmp(argv[c1], "-server") == 0) { + if (c1 < (argc - 1)) { + is_server = 1; + is_net = 1; + netarg = argv[c1 + 1]; + } + } else if (stricmp(argv[c1], "-connect") == 0) { + if (c1 < (argc - 1)) { + is_server = 0; + is_net = 1; + netarg = argv[c1 + 1]; + } +#endif + } else if (stricmp(argv[c1], "-mouse") == 0) { + if (c1 < (argc - 1)) { + if (stricmp(argv[c1 + 1], "2") == 0) + force2 = 1; + if (stricmp(argv[c1 + 1], "3") == 0) + force3 = 1; + } + } + else if (strstr(argv[1],"-v")) { + printf("jumpnbump %s compiled %s at %s with",JNB_VERSION,__DATE__,__TIME__); +#ifndef USE_NET + printf("out"); +#endif + printf(" network support.\n"); + return 1; + } + else if (strstr(argv[1],"-h")) { + printf("Usage: jumpnbump [OPTION]...\n"); + printf("\n"); + printf(" -h this help\n"); + printf(" -v print version\n"); + printf(" -dat level.dat play a different level\n"); +#ifdef USE_NET + printf(" -server playercount start as server waiting for players\n"); + printf(" -connect host connect to server\n"); +#endif + printf(" -player num set main player to num (0-3). Needed for networking\n"); + printf(" -fireworks screensaver mode\n"); + printf(" -fullscreen run in fullscreen mode\n"); + printf(" -nosound play without sound\n"); + printf(" -nogore play without blood\n"); + printf(" -noflies disable flies\n"); + printf(" -mirror play with mirrored level\n"); + printf(" -scaleup play with doubled resolution (800x512)\n"); + printf(" -musicnosound play with music but without sound\n"); + printf("\n"); + return 1; + } + } + } + + preread_datafile(datfile_name); + +#if 0 +/** It should not be necessary to assign a default player number here. The +server assigns one in init_server, the client gets one assigned by the server, +all provided the user didn't choose one on the commandline. */ + if (is_net) { + if (client_player_num < 0) + client_player_num = 0; + player[client_player_num].enabled = 1; + } +#endif + + main_info.pob_backbuf[0] = malloc(screen_pitch*screen_height); + main_info.pob_backbuf[1] = malloc(screen_pitch*screen_height); + + for (c1 = 0; c1 < 7; c1++) { + player_anims[c1].num_frames = player_anim_data[c1 * 10]; + player_anims[c1].restart_frame = player_anim_data[c1 * 10 + 1]; + for (c2 = 0; c2 < 4; c2++) { + player_anims[c1].frame[c2].image = player_anim_data[c1 * 10 + c2 * 2 + 2]; + player_anims[c1].frame[c2].ticks = player_anim_data[c1 * 10 + c2 * 2 + 3]; + } + } + + if ((handle = dat_open("menu.pcx")) == 0) { + strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n"); + return 1; + } + if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) { + strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n"); + return 1; + } + + if ((handle = dat_open("rabbit.gob")) == 0) { + strcpy(main_info.error_str, "Error loading 'rabbit.gob', aborting...\n"); + return 1; + } + if (register_gob(handle, &rabbit_gobs, dat_filelen("rabbit.gob"))) { + /* error */ + return 1; + } + + if ((handle = dat_open("objects.gob")) == 0) { + strcpy(main_info.error_str, "Error loading 'objects.gob', aborting...\n"); + return 1; + } + if (register_gob(handle, &object_gobs, dat_filelen("objects.gob"))) { + /* error */ + return 1; + } + + if ((handle = dat_open("font.gob")) == 0) { + strcpy(main_info.error_str, "Error loading 'font.gob', aborting...\n"); + return 1; + } + if (register_gob(handle, &font_gobs, dat_filelen("font.gob"))) { + /* error */ + return 1; + } + + if ((handle = dat_open("numbers.gob")) == 0) { + strcpy(main_info.error_str, "Error loading 'numbers.gob', aborting...\n"); + return 1; + } + if (register_gob(handle, &number_gobs, dat_filelen("numbers.gob"))) { + /* error */ + return 1; + } + + if (read_level() != 0) { + strcpy(main_info.error_str, "Error loading 'levelmap.txt', aborting...\n"); + return 1; + } + + dj_init(); + + if (main_info.no_sound == 0) { + dj_autodetect_sd(); + dj_set_mixing_freq(20000); + dj_set_stereo(0); + dj_set_auto_mix(0); + dj_set_dma_time(8); + dj_set_num_sfx_channels(5); + dj_set_sfx_volume(64); + dj_set_nosound(1); + dj_start(); + + if ((handle = dat_open("jump.mod")) == 0) { + strcpy(main_info.error_str, "Error loading 'jump.mod', aborting...\n"); + return 1; + } + if (dj_load_mod(handle, 0, MOD_MENU) != 0) { + strcpy(main_info.error_str, "Error loading 'jump.mod', aborting...\n"); + return 1; + } + + if ((handle = dat_open("bump.mod")) == 0) { + strcpy(main_info.error_str, "Error loading 'bump.mod', aborting...\n"); + return 1; + } + if (dj_load_mod(handle, 0, MOD_GAME) != 0) { + strcpy(main_info.error_str, "Error loading 'bump.mod', aborting...\n"); + return 1; + } + + if ((handle = dat_open("scores.mod")) == 0) { + strcpy(main_info.error_str, "Error loading 'scores.mod', aborting...\n"); + return 1; + } + if (dj_load_mod(handle, 0, MOD_SCORES) != 0) { + strcpy(main_info.error_str, "Error loading 'scores.mod', aborting...\n"); + return 1; + } + + if ((handle = dat_open("jump.smp")) == 0) { + strcpy(main_info.error_str, "Error loading 'jump.smp', aborting...\n"); + return 1; + } + if (dj_load_sfx(handle, 0, dat_filelen("jump.smp"), DJ_SFX_TYPE_SMP, SFX_JUMP) != 0) { + strcpy(main_info.error_str, "Error loading 'jump.smp', aborting...\n"); + return 1; + } + + if ((handle = dat_open("death.smp")) == 0) { + strcpy(main_info.error_str, "Error loading 'death.smp', aborting...\n"); + return 1; + } + if (dj_load_sfx(handle, 0, dat_filelen("death.smp"), DJ_SFX_TYPE_SMP, SFX_DEATH) != 0) { + strcpy(main_info.error_str, "Error loading 'death.smp', aborting...\n"); + return 1; + } + + if ((handle = dat_open("spring.smp")) == 0) { + strcpy(main_info.error_str, "Error loading 'spring.smp', aborting...\n"); + return 1; + } + if (dj_load_sfx(handle, 0, dat_filelen("spring.smp"), DJ_SFX_TYPE_SMP, SFX_SPRING) != 0) { + strcpy(main_info.error_str, "Error loading 'spring.smp', aborting...\n"); + return 1; + } + + if ((handle = dat_open("splash.smp")) == 0) { + strcpy(main_info.error_str, "Error loading 'splash.smp', aborting...\n"); + return 1; + } + if (dj_load_sfx(handle, 0, dat_filelen("splash.smp"), DJ_SFX_TYPE_SMP, SFX_SPLASH) != 0) { + strcpy(main_info.error_str, "Error loading 'splash.smp', aborting...\n"); + return 1; + } + + if ((handle = dat_open("fly.smp")) == 0) { + strcpy(main_info.error_str, "Error loading 'fly.smp', aborting...\n"); + return 1; + } + if (dj_load_sfx(handle, 0, dat_filelen("fly.smp"), DJ_SFX_TYPE_SMP, SFX_FLY) != 0) { + strcpy(main_info.error_str, "Error loading 'fly.smp', aborting...\n"); + return 1; + } + + dj_get_sfx_settings(SFX_FLY, &fly); + fly.priority = 10; + fly.default_freq = SFX_FLY_FREQ; + fly.loop = 1; + fly.loop_start = 0; + fly.loop_length = fly.length; + dj_set_sfx_settings(SFX_FLY, &fly); + } + + if ((background_pic = malloc(JNB_WIDTH*JNB_HEIGHT)) == NULL) + return 1; + if ((mask_pic = malloc(JNB_WIDTH*JNB_HEIGHT)) == NULL) + return 1; + memset(mask_pic, 0, JNB_WIDTH*JNB_HEIGHT); + register_mask(mask_pic); + + /* fix dark font */ + for (c1 = 0; c1 < 16; c1++) { + pal[(240 + c1) * 3 + 0] = c1 << 2; + pal[(240 + c1) * 3 + 1] = c1 << 2; + pal[(240 + c1) * 3 + 2] = c1 << 2; + } + + setpalette(0, 256, pal); + + init_inputs(); + + recalculate_gob(&font_gobs, pal); + + if (main_info.joy_enabled == 1 && main_info.fireworks == 0) { + load_flag = 0; + put_text(0, 200, 40, "JOYSTICK CALIBRATION", 2); + put_text(0, 200, 100, "Move the joystick to the", 2); + put_text(0, 200, 115, "UPPER LEFT", 2); + put_text(0, 200, 130, "and press button A", 2); + put_text(0, 200, 200, "Or press ESC to use", 2); + put_text(0, 200, 215, "previous settings", 2); + if (calib_joy(0) != 0) + load_flag = 1; + else { + register_background(NULL, NULL); + + main_info.view_page = 1; + flippage(1); + + wait_vrt(0); + + put_text(1, 200, 40, "JOYSTICK CALIBRATION", 2); + put_text(1, 200, 100, "Move the joystick to the", 2); + put_text(1, 200, 115, "LOWER RIGHT", 2); + put_text(1, 200, 130, "and press button A", 2); + put_text(1, 200, 200, "Or press ESC to use", 2); + put_text(1, 200, 215, "previous settings", 2); + if (calib_joy(1) != 0) + load_flag = 1; + else { + register_background(NULL, NULL); + flippage(0); + + wait_vrt(0); + + put_text(0, 200, 40, "JOYSTICK CALIBRATION", 2); + put_text(0, 200, 100, "Move the joystick to the", 2); + put_text(0, 200, 115, "CENTER", 2); + put_text(0, 200, 130, "and press button A", 2); + put_text(0, 200, 200, "Or press ESC to use", 2); + put_text(0, 200, 215, "previous settings", 2); + if (calib_joy(2) != 0) + load_flag = 1; + else { + if (joy.calib_data.x1 == joy.calib_data.x2) + joy.calib_data.x1 -= 10; + if (joy.calib_data.x3 == joy.calib_data.x2) + joy.calib_data.x3 += 10; + if (joy.calib_data.y1 == joy.calib_data.y2) + joy.calib_data.y1 -= 10; + if (joy.calib_data.y3 == joy.calib_data.y2) + joy.calib_data.y3 += 10; + write_calib_data(); + } + } + } + if (load_flag == 1) { + if ((handle = dat_open("calib.dat")) == 0) { + strcpy(main_info.error_str, "Error loading 'calib.dat', aborting...\n"); + return 1; + } + joy.calib_data.x1 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4; + joy.calib_data.x2 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4; + joy.calib_data.x3 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4; + joy.calib_data.y1 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4; + joy.calib_data.y2 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4; + joy.calib_data.y3 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4; + } + } + +#ifdef USE_NET + if (is_net) { + if (is_server) { + init_server(netarg); + } else { + connect_to_server(netarg); + } + } +#endif + + return 0; + +} + +void deinit_program(void) +{ +#ifdef DOS + __dpmi_regs regs; +#endif + + dj_stop(); + dj_free_mod(MOD_MENU); + dj_free_mod(MOD_GAME); + dj_free_sfx(SFX_DEATH); + dj_free_sfx(SFX_SPRING); + dj_free_sfx(SFX_SPLASH); + dj_deinit(); + + if (background_pic != 0) + free(background_pic); + if (mask_pic != 0) + free(mask_pic); + + remove_keyb_handler(); + +#ifdef DOS + regs.x.ax = 0x3; + __dpmi_int(0x10, ®s); +#endif + + if (main_info.error_str[0] != 0) { + printf(main_info.error_str); +#ifdef _MSC_VER + MessageBox(0, main_info.error_str, "Jump'n'Bump", 0); +#endif + exit(1); + } else + exit(0); + +} + + +unsigned short rnd(unsigned short max) +{ +#if (RAND_MAX < 0x7fff) +#error "rand returns too small values" +#elif (RAND_MAX == 0x7fff) + return (unsigned short)((rand()*2) % (int)max); +#else + return (unsigned short)(rand() % (int)max); +#endif +} + + +int read_level(void) +{ + unsigned char *handle; + int c1, c2; + int chr; + + if ((handle = dat_open("levelmap.txt")) == 0) { + strcpy(main_info.error_str, "Error loading 'levelmap.txt', aborting...\n"); + return 1; + } + + for (c1 = 0; c1 < 16; c1++) { + for (c2 = 0; c2 < 22; c2++) { + while (1) { + chr = (int) *(handle++); + if (chr >= '0' && chr <= '4') + break; + } + if (flip) + ban_map[c1][21-c2] = chr - '0'; + else + ban_map[c1][c2] = chr - '0'; + } + } + + for (c2 = 0; c2 < 22; c2++) + ban_map[16][c2] = BAN_SOLID; + + return 0; + +} + + +unsigned char *dat_open(char *file_name) +{ + int num; + int c1; + char name[21]; + int ofs; + unsigned char *ptr; + + if (datafile_buffer == NULL) + return 0; + + memset(name, 0, sizeof(name)); + + num = ( (datafile_buffer[0] << 0) + + (datafile_buffer[1] << 8) + + (datafile_buffer[2] << 16) + + (datafile_buffer[3] << 24) ); + + ptr = datafile_buffer + 4; + + for (c1 = 0; c1 < num; c1++) { + + memcpy(name, ptr, 12); + ptr += 12; + + if (strnicmp(name, file_name, strlen(file_name)) == 0) { + ofs = ( (ptr[0] << 0) + + (ptr[1] << 8) + + (ptr[2] << 16) + + (ptr[3] << 24) ); + + return (datafile_buffer + ofs); + } + ptr += 8; + } + + return 0; +} + + +int dat_filelen(char *file_name) +{ + unsigned char *ptr; + int num; + int c1; + char name[21]; + int len; + + memset(name, 0, sizeof(name)); + + num = ( (datafile_buffer[0] << 0) + + (datafile_buffer[1] << 8) + + (datafile_buffer[2] << 16) + + (datafile_buffer[3] << 24) ); + + ptr = datafile_buffer + 4; + + for (c1 = 0; c1 < num; c1++) { + + memcpy(name, ptr, 12); + ptr += 12; + + if (strnicmp(name, file_name, strlen(file_name)) == 0) { + + ptr += 4; + len = ( (ptr[0] << 0) + + (ptr[1] << 8) + + (ptr[2] << 16) + + (ptr[3] << 24) ); + + return len; + } + ptr += 8; + } + + return 0; +} + + +void write_calib_data(void) +{ + FILE *handle; + int c1; + int len, num; + char *mem; + int ofs; + + if ((handle = fopen(datfile_name, "rb")) == NULL) + return; + len = filelength(fileno(handle)); + if ((mem = malloc(len)) == NULL) + return; + fread(mem, 1, len, handle); + fclose(handle); + + ofs = 4; + num = *(int *) (&mem[0]); + for (c1 = 0; c1 < num; c1++) { + if (strnicmp(&mem[ofs], "calib.dat", strlen("calib.dat")) == 0) { + ofs = *(int *) (&mem[ofs + 12]); + break; + } + ofs += 20; + } + + mem[ofs] = joy.calib_data.x1 & 0xff; + mem[ofs + 1] = (joy.calib_data.x1 >> 8) & 0xff; + mem[ofs + 2] = (joy.calib_data.x1 >> 16) & 0xff; + mem[ofs + 3] = (joy.calib_data.x1 >> 24) & 0xff; + mem[ofs + 4] = joy.calib_data.x2 & 0xff; + mem[ofs + 5] = (joy.calib_data.x2 >> 8) & 0xff; + mem[ofs + 6] = (joy.calib_data.x2 >> 16) & 0xff; + mem[ofs + 7] = (joy.calib_data.x2 >> 24) & 0xff; + mem[ofs + 8] = joy.calib_data.x3 & 0xff; + mem[ofs + 9] = (joy.calib_data.x3 >> 8) & 0xff; + mem[ofs + 10] = (joy.calib_data.x3 >> 16) & 0xff; + mem[ofs + 11] = (joy.calib_data.x3 >> 24) & 0xff; + mem[ofs + 12] = joy.calib_data.y1 & 0xff; + mem[ofs + 13] = (joy.calib_data.y1 >> 8) & 0xff; + mem[ofs + 14] = (joy.calib_data.y1 >> 16) & 0xff; + mem[ofs + 15] = (joy.calib_data.y1 >> 24) & 0xff; + mem[ofs + 16] = joy.calib_data.y2 & 0xff; + mem[ofs + 17] = (joy.calib_data.y2 >> 8) & 0xff; + mem[ofs + 18] = (joy.calib_data.y2 >> 16) & 0xff; + mem[ofs + 19] = (joy.calib_data.y2 >> 24) & 0xff; + mem[ofs + 20] = joy.calib_data.y3 & 0xff; + mem[ofs + 21] = (joy.calib_data.y3 >> 8) & 0xff; + mem[ofs + 22] = (joy.calib_data.y3 >> 16) & 0xff; + mem[ofs + 23] = (joy.calib_data.y3 >> 24) & 0xff; + + if ((handle = fopen(datfile_name, "wb")) == NULL) + return; + fwrite(mem, 1, len, handle); + fclose(handle); + +} diff --git a/contrib/other/jumpnbump/menu.c b/contrib/other/jumpnbump/menu.c new file mode 100755 index 0000000000..563c25e6d7 --- /dev/null +++ b/contrib/other/jumpnbump/menu.c @@ -0,0 +1,637 @@ +/* + * menu.c + * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/ + * + * Copyright (C) 2001 Chuck Mason + * + * Copyright (C) 2002 Florian Schulze + * + * This file is part of Jump'n'Bump. + * + * Jump'n'Bump 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. + * + * Jump'n'Bump 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "globals.h" + +char *menu_background; + +char menu_pal[768]; +char menu_cur_pal[768]; + +char *message[] = { + "Jump 'n Bump "JNB_VERSION, + "by Brainchild Design in 1998.", + "Code by Mattias Brynervall.", + "Graphics by Martin Magnusson", + "and Andreas Brynervall.", + "Music by Anders Nilsson.", + "Linux port by Chuck Mason.", + "New SDL port by Florian Schulze.", + "http://www.icculus.org/jumpnbump/", + "Ryan C. Gordon made networking possible again!", + "Visit our homepage at:", + "http://www.algonet.se/~mattiasb", + "Jump 'n Bump is e-mailware.", + "That means you're supposed to send us an e-mail!", + "Write for example where you're from", + "and what you thought about this game.", + "If you do that, you will greatly encourage us", + "to make more games for you!", + "Send your e-mail to: matbr656@student.liu.se", + "Oh, and by the way, there're a lot of secrets!", + "If you can't find them, you'd better ask us...", + "If you'd like to contact a specific member of BCD,", + "these are their e-mail addresses:", + "Andreas Brynervall: andreasb@acc.umu.se", + "Mattias Brynervall: matbr656@student.liu.se", + "Martin Magnusson: marma102@student.liu.se", + "Anders Nilsson: equel@swipnet.se", + "" +}; + +#define NUM_MESSAGES (sizeof(message)/sizeof(char *)) + +int menu(void) +{ + int c1; + int esc_pressed; + int end_loop_flag, new_game_flag, fade_flag; + int mod_vol = 0, mod_fade_direction = 0; + int cur_message; + int fade_dir, fade_count, fade_tick; + char fade_pal[48]; + int update_count; + + if (menu_init() != 0) + return 1; + + /* After a game, we have to release the keys, cause AI player + can still be using them */ + addkey((KEY_PL1_LEFT & 0x7f) | 0x8000); + addkey((KEY_PL2_LEFT & 0x7f) | 0x8000); + addkey((KEY_PL3_LEFT & 0x7f) | 0x8000); + addkey((KEY_PL4_LEFT & 0x7f) | 0x8000); + + addkey((KEY_PL1_RIGHT & 0x7f) | 0x8000); + addkey((KEY_PL2_RIGHT & 0x7f) | 0x8000); + addkey((KEY_PL3_RIGHT & 0x7f) | 0x8000); + addkey((KEY_PL4_RIGHT & 0x7f) | 0x8000); + + addkey((KEY_PL1_JUMP & 0x7f) | 0x8000); + addkey((KEY_PL2_JUMP & 0x7f) | 0x8000); + addkey((KEY_PL3_JUMP & 0x7f) | 0x8000); + addkey((KEY_PL4_JUMP & 0x7f) | 0x8000); + + mod_vol = 0; + mod_fade_direction = 1; + dj_ready_mod(MOD_MENU); + dj_set_mod_volume((char)mod_vol); + dj_set_sfx_volume(64); + dj_start_mod(); + dj_set_nosound(0); + + memset(fade_pal, 0, 48); + setpalette(240, 16, fade_pal); + + fade_dir = 0; + fade_count = 0; + fade_tick = 0; + cur_message = NUM_MESSAGES - 1; + + main_info.page_info[0].num_pobs = 0; + main_info.page_info[1].num_pobs = 0; + main_info.view_page = 0; + main_info.draw_page = 1; + + esc_pressed = key_pressed(1); + end_loop_flag = new_game_flag = 0; + + update_count = 1; + while (1) { + + dj_mix(); + + for(c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) // set AI to false + ai[c1] = 0; + + while (update_count) { + + if (key_pressed(1) == 1 && esc_pressed == 0) { + end_loop_flag = 1; + new_game_flag = 0; + memset(menu_pal, 0, 768); + mod_fade_direction = 0; + } else if (key_pressed(1) == 0) + esc_pressed = 0; + + update_player_actions(); + for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) { + if (end_loop_flag == 1 && new_game_flag == 1) { + if ((player[c1].x >> 16) > (165 + c1 * 2)) { + if (player[c1].x_add < 0) + player[c1].x_add += 16384; + else + player[c1].x_add += 12288; + if (player[c1].x_add > 98304L) + player[c1].x_add = 98304L; + player[c1].direction = 0; + if (player[c1].anim == 0) { + player[c1].anim = 1; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } + player[c1].enabled = 1; + } + if (!player[c1].action_up) { + if (player[c1].y_add < 0) { + player[c1].y_add += 32768; + if (player[c1].y_add > 0) + player[c1].y_add = 0; + } + } + player[c1].y_add += 12288; + if (player[c1].y_add > 36864 && player[c1].anim != 3) { + player[c1].anim = 3; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } + player[c1].y += player[c1].y_add; + if ((player[c1].x >> 16) <= (165 + c1 * 2) || (player[c1].x >> 16) >= (208 + c1 * 2)) { + if ((player[c1].y >> 16) > (160 + c1 * 2)) { + player[c1].y = (160L + c1 * 2) << 16; + player[c1].y_add = 0; + if (player[c1].anim != 0 && player[c1].anim != 1) { + player[c1].anim = 0; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } + } + } else { + if ((player[c1].y >> 16) > (138 + c1 * 2)) { + player[c1].y = (138L + c1 * 2) << 16; + player[c1].y_add = 0; + if (player[c1].anim != 0 && player[c1].anim != 1) { + player[c1].anim = 0; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } + if (!player[c1].action_up) + player[c1].jump_ready = 1; + } + } + player[c1].x += player[c1].x_add; + if ((player[c1].y >> 16) > (138 + c1 * 2)) { + if ((player[c1].x >> 16) > (165 + c1 * 2) && (player[c1].x >> 16) < (190 + c1 * 2)) { + player[c1].x = (165L + c1 * 2) << 16; + player[c1].x_add = 0; + } + if ((player[c1].x >> 16) > (190 + c1 * 2) && (player[c1].x >> 16) < (208 + c1 * 2)) { + player[c1].x = (208L + c1 * 2) << 16; + player[c1].x_add = 0; + } + } + } else { + if (player[c1].action_left && player[c1].action_right) { + if (player[c1].direction == 1) { + if ((player[c1].x >> 16) <= (165 + c1 * 2) || (player[c1].x >> 16) >= (208 + c1 * 2)) { + if (player[c1].x_add > 0) { + player[c1].x_add -= 16384; + if ((player[c1].y >> 16) >= (160 + c1 * 2)) + add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0); + } else + player[c1].x_add -= 12288; + } + if ((player[c1].x >> 16) > (165 + c1 * 2) && (player[c1].x >> 16) < (208 + c1 * 2)) { + if (player[c1].x_add > 0) { + player[c1].x_add -= 16384; + if ((player[c1].y >> 16) >= (138 + c1 * 2)) + add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0); + } else + player[c1].x_add -= 12288; + } + if (player[c1].x_add < -98304L) + player[c1].x_add = -98304L; + player[c1].direction = 1; + if (player[c1].anim == 0) { + player[c1].anim = 1; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } + } else { + if ((player[c1].x >> 16) <= (165 + c1 * 2) || (player[c1].x >> 16) >= (208 + c1 * 2)) { + if (player[c1].x_add < 0) { + player[c1].x_add += 16384; + if ((player[c1].y >> 16) >= (160 + c1 * 2)) + add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0); + } else + player[c1].x_add += 12288; + } + if ((player[c1].x >> 16) > (165 + c1 * 2) && (player[c1].x >> 16) < (208 + c1 * 2)) { + if (player[c1].x_add < 0) { + player[c1].x_add += 16384; + if ((player[c1].y >> 16) >= (138 + c1 * 2)) + add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0); + } else + player[c1].x_add += 12288; + } + if (player[c1].x_add > 98304L) + player[c1].x_add = 98304L; + player[c1].direction = 0; + if (player[c1].anim == 0) { + player[c1].anim = 1; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } + } + } else if (player[c1].action_left) { + if ((player[c1].x >> 16) <= (165 + c1 * 2) || (player[c1].x >> 16) >= (208 + c1 * 2)) { + if (player[c1].x_add > 0) { + player[c1].x_add -= 16384; + if ((player[c1].y >> 16) >= (160 + c1 * 2)) + add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0); + } else + player[c1].x_add -= 12288; + } + if ((player[c1].x >> 16) > (165 + c1 * 2) && (player[c1].x >> 16) < (208 + c1 * 2)) { + if (player[c1].x_add > 0) { + player[c1].x_add -= 16384; + if ((player[c1].y >> 16) >= (138 + c1 * 2)) + add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0); + } else + player[c1].x_add -= 12288; + } + if (player[c1].x_add < -98304L) + player[c1].x_add = -98304L; + player[c1].direction = 1; + if (player[c1].anim == 0) { + player[c1].anim = 1; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } + } else if (player[c1].action_right) { + if ((player[c1].x >> 16) <= (165 + c1 * 2) || (player[c1].x >> 16) >= (208 + c1 * 2)) { + if (player[c1].x_add < 0) { + player[c1].x_add += 16384; + if ((player[c1].y >> 16) >= (160 + c1 * 2)) + add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0); + } else + player[c1].x_add += 12288; + } + if ((player[c1].x >> 16) > (165 + c1 * 2) && (player[c1].x >> 16) < (208 + c1 * 2)) { + if (player[c1].x_add < 0) { + player[c1].x_add += 16384; + if ((player[c1].y >> 16) >= (138 + c1 * 2)) + add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0); + } else + player[c1].x_add += 12288; + } + if (player[c1].x_add > 98304L) + player[c1].x_add = 98304L; + player[c1].direction = 0; + if (player[c1].anim == 0) { + player[c1].anim = 1; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } + } else { + if (((player[c1].x >> 16) <= (165 + c1 * 2) || (player[c1].x >> 16) >= (208 + c1 * 2)) && (player[c1].y >> 16) >= (160 + c1 * 2)) { + if (player[c1].x_add < 0) { + player[c1].x_add += 16384; + if (player[c1].x_add > 0) + player[c1].x_add = 0; + add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0); + } else if (player[c1].x_add > 0) { + player[c1].x_add -= 16384; + if (player[c1].x_add < 0) + player[c1].x_add = 0; + add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0); + } + } + if ((((player[c1].x >> 16) > (165 + c1 * 2) && (player[c1].x >> 16) < (208 + c1 * 2)) && (player[c1].y >> 16) >= (138 + c1 * 2))) { + if (player[c1].x_add < 0) { + player[c1].x_add += 16384; + if (player[c1].x_add > 0) + player[c1].x_add = 0; + add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0); + } else if (player[c1].x_add > 0) { + player[c1].x_add -= 16384; + if (player[c1].x_add < 0) + player[c1].x_add = 0; + add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0); + } + } + if (player[c1].anim == 1) { + player[c1].anim = 0; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } + } + if ((player[c1].jump_ready == 1) && player[c1].action_up) { + if ((player[c1].x >> 16) <= (165 + c1 * 2) || (player[c1].x >> 16) >= (208 + c1 * 2)) { + if ((player[c1].y >> 16) >= (160 + c1 * 2)) { + player[c1].y_add = -280000L; + player[c1].anim = 2; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + player[c1].jump_ready = 0; + dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1); + } + } else { + if ((player[c1].y >> 16) >= (138 + c1 * 2)) { + player[c1].y_add = -280000L; + player[c1].anim = 2; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + player[c1].jump_ready = 0; + dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1); + } + } + } + if (!player[c1].action_up) { + if (player[c1].y_add < 0) { + player[c1].y_add += 32768; + if (player[c1].y_add > 0) + player[c1].y_add = 0; + } + } + if (!player[c1].action_up) + player[c1].jump_ready = 1; + player[c1].y_add += 12288; + if (player[c1].y_add > 36864 && player[c1].anim != 3) { + player[c1].anim = 3; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } + player[c1].y += player[c1].y_add; + if ((player[c1].x >> 16) <= (165 + c1 * 2) || (player[c1].x >> 16) >= (208 + c1 * 2)) { + if ((player[c1].y >> 16) > (160 + c1 * 2)) { + player[c1].y = (160L + c1 * 2) << 16; + player[c1].y_add = 0; + if (player[c1].anim != 0 && player[c1].anim != 1) { + player[c1].anim = 0; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } + } + } else { + if ((player[c1].y >> 16) > (138 + c1 * 2)) { + player[c1].y = (138L + c1 * 2) << 16; + player[c1].y_add = 0; + if (player[c1].anim != 0 && player[c1].anim != 1) { + player[c1].anim = 0; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } + } + } + player[c1].x += player[c1].x_add; + if ((player[c1].x >> 16) < 0) { + player[c1].x = 0; + player[c1].x_add = 0; + } + if ((player[c1].x >> 16) > JNB_WIDTH) { + end_loop_flag = 1; + new_game_flag = 1; + memset(menu_pal, 0, 768); + mod_fade_direction = 0; + } + if ((player[c1].y >> 16) > (138 + c1 * 2)) { + if ((player[c1].x >> 16) > (165 + c1 * 2) && (player[c1].x >> 16) < (190 + c1 * 2)) { + player[c1].x = (165L + c1 * 2) << 16; + player[c1].x_add = 0; + } + if ((player[c1].x >> 16) > (190 + c1 * 2) && (player[c1].x >> 16) < (208 + c1 * 2)) { + player[c1].x = (208L + c1 * 2) << 16; + player[c1].x_add = 0; + } + } + } + player[c1].frame_tick++; + if (player[c1].frame_tick >= player_anims[player[c1].anim].frame[player[c1].frame].ticks) { + player[c1].frame++; + if (player[c1].frame >= player_anims[player[c1].anim].num_frames) + player[c1].frame = player_anims[player[c1].anim].restart_frame; + player[c1].frame_tick = 0; + } + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9; + } + + dj_mix(); + + main_info.page_info[main_info.draw_page].num_pobs = 0; + + for (c1 = 3; c1 >= 0; c1--) + add_pob(main_info.draw_page, player[c1].x >> 16, player[c1].y >> 16, player[c1].image + c1 * 18, &rabbit_gobs); + + update_objects(); + + if (update_count == 1) { + draw_begin(); + draw_pobs(main_info.draw_page); + draw_end(); + + dj_mix(); + + if (mod_fade_direction == 1) { + if (mod_vol < 35) { + mod_vol++; + dj_set_mod_volume((char)mod_vol); + } + } else { + if (mod_vol > 0) { + mod_vol--; + dj_set_mod_volume((char)mod_vol); + } + } + } + + fade_flag = 0; + for (c1 = 0; c1 < 720; c1++) { + if (menu_cur_pal[c1] < menu_pal[c1]) { + menu_cur_pal[c1]++; + fade_flag = 1; + } else if (menu_cur_pal[c1] > menu_pal[c1]) { + menu_cur_pal[c1]--; + fade_flag = 2; + } + } + if (fade_flag == 0 && end_loop_flag == 1) { + menu_deinit(); + if (new_game_flag == 1) + return 0; + else + return 1; + } + switch (fade_dir) { + case 0: + if (fade_count < 30) { + for (c1 = 0; c1 < 48; c1++) { + if (fade_pal[c1] > 0) + fade_pal[c1]--; + } + fade_count++; + } else { + draw_begin(); + clear_lines(0, 220, 20, 0); + clear_lines(1, 220, 20, 0); + + cur_message++; + if (cur_message >= NUM_MESSAGES) + cur_message -= NUM_MESSAGES; + put_text(0, 200, 220, message[cur_message], 2); + put_text(1, 200, 220, message[cur_message], 2); + fade_dir = 1; + fade_count = 0; + fade_tick = 0; + draw_end(); + } + break; + case 1: + if (fade_count < 100) { + for (c1 = 0; c1 < 48; c1++) { + if (fade_pal[c1] < menu_pal[c1 + 720]) + fade_pal[c1]++; + } + fade_count++; + } else { + fade_dir = 0; + fade_count = 0; + fade_tick = 0; + } + break; + } + + for (c1 = 0; c1 < 48; c1++) { + if (fade_pal[c1] > menu_pal[c1 + 720]) + fade_pal[c1]--; + } + + if (update_count == 1) { + main_info.draw_page ^= 1; + main_info.view_page ^= 1; + + flippage(main_info.view_page); + + wait_vrt(1); + } + + if (fade_flag != 0) { + setpalette(0, 240, menu_cur_pal); + } + + if (update_count == 1) { + setpalette(240, 16, fade_pal); + + dj_mix(); + + draw_begin(); + redraw_pob_backgrounds(main_info.draw_page); + draw_end(); + } + + update_count--; + } + + update_count = intr_sysupdate(); + + } + + menu_deinit(); + return 0; + +} + + +int menu_init(void) +{ + char *handle; + int c1; + + fillpalette(0, 0, 0); + + if ((handle = dat_open("menu.pcx")) == 0) { + strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n"); + return 1; + } + if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, menu_pal) != 0) { + strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n"); + return 1; + } + if ((handle = dat_open("menumask.pcx")) == 0) { + strcpy(main_info.error_str, "Error loading 'menumask.pcx', aborting...\n"); + return 1; + } + if (read_pcx(handle, mask_pic, JNB_WIDTH*JNB_HEIGHT, 0) != 0) { + strcpy(main_info.error_str, "Error loading 'menumask.pcx', aborting...\n"); + return 1; + } + memset(menu_cur_pal, 0, 768); + + /* fix dark font */ + for (c1 = 0; c1 < 16; c1++) { + menu_pal[(240 + c1) * 3 + 0] = c1 << 2; + menu_pal[(240 + c1) * 3 + 1] = c1 << 2; + menu_pal[(240 + c1) * 3 + 2] = c1 << 2; + } + + recalculate_gob(&rabbit_gobs, menu_pal); + recalculate_gob(&font_gobs, menu_pal); + recalculate_gob(&object_gobs, menu_pal); + register_background(background_pic, menu_pal); + register_mask(mask_pic); + + for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) { + player[c1].enabled = 0; + player[c1].x = (long) rnd(150) << 16; + player[c1].y = (160L + c1 * 2) << 16; + player[c1].x_add = 0; + player[c1].y_add = 0; + player[c1].direction = rnd(2); + player[c1].jump_ready = 1; + player[c1].anim = 0; + player[c1].frame = 0; + player[c1].frame_tick = 0; + player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image; + } + + for (c1 = 0; c1 < NUM_OBJECTS; c1++) + objects[c1].used = 0; + + main_info.page_info[0].num_pobs = 0; + main_info.page_info[1].num_pobs = 0; + + return 0; + +} + + +void menu_deinit(void) +{ + dj_set_nosound(1); +} diff --git a/contrib/other/jumpnbump/sdl/Makefile b/contrib/other/jumpnbump/sdl/Makefile new file mode 100755 index 0000000000..84d76d4cb7 --- /dev/null +++ b/contrib/other/jumpnbump/sdl/Makefile @@ -0,0 +1,23 @@ +CC = kos32-gcc +LD = kos32-ld + +SDK_DIR = $(abspath ../../../sdk) + +CFLAGS = -c -fno-ident -O2 -fomit-frame-pointer -fno-ident -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 -Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -DUSE_SDL +LDFLAGS = -static -S -nostdlib -T $(SDK_DIR)/sources/newlib/app.lds --image-base 0 + +INCLUDES = -I$(SDK_DIR)/sources/newlib/libc/include -I$(SDK_DIR)/sources/SDL-1.2.2_newlib/include -DNDEBUG -I.. +LIBPATH = -L $(SDK_DIR)/lib -L /home/autobuild/tools/win32/mingw32/lib + +SRC = gfx.c interrpt.c sound.c input.c + +OBJECTS = $(patsubst %.c, %.o, $(SRC)) + +default: $(patsubst %.c,%.o,$(SRC)) + ar rcs libs.a *.o + +%.o : %.c Makefile $(SRC) + $(CC) $(CFLAGS) $(INCLUDES) -o $@ $< + +clean: + rm *.o diff --git a/contrib/other/jumpnbump/sdl/gfx.c b/contrib/other/jumpnbump/sdl/gfx.c new file mode 100755 index 0000000000..5c76813700 --- /dev/null +++ b/contrib/other/jumpnbump/sdl/gfx.c @@ -0,0 +1,865 @@ +/* + * gfx.c + * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/ + * + * Copyright (C) 2001 Chuck Mason + * + * Copyright (C) 2002 Florian Schulze + * + * This file is part of Jump'n'Bump. + * + * Jump'n'Bump 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. + * + * Jump'n'Bump 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "globals.h" +#include "SDL_endian.h" +#include "SDL.h" +#include "filter.h" + + +#include "jumpnbump64.xpm" + +SDL_Surface *icon; + +int screen_width=400; +int screen_height=256; +int screen_pitch=400; +int scale_up=0; +int dirty_block_shift=4; + +static SDL_Surface *jnb_surface; +static int fullscreen = 0; +static int vinited = 0; +static void *screen_buffer[2]; +static int drawing_enable = 0; +static void *background = NULL; +static int background_drawn; +static void *mask = NULL; +static int dirty_blocks[2][25*16*2]; + +static SDL_Surface *load_xpm_from_array(char **xpm) +{ +#define NEXT_TOKEN { \ + while ((*p != ' ') && (*p != '\t')) p++; \ + while ((*p == ' ') || (*p == '\t')) p++; } + + SDL_Surface *surface; + char *p; + int width; + int height; + int colors; + int images; + int color; + int pal[256]; + int x,y; + + p = *xpm++; + + width = atoi(p); + if (width <= 0) + return NULL; + NEXT_TOKEN; + + height = atoi(p); + if (height <= 0) + return NULL; + NEXT_TOKEN; + + colors = atoi(p); + if (colors <= 0) + return NULL; + NEXT_TOKEN; + + images = atoi(p); + if (images <= 0) + return NULL; + + surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); + if (!surface) + return NULL; + + SDL_SetColorKey(surface, SDL_SRCCOLORKEY, SDL_MapRGBA(surface->format, 0, 0, 0, 0)); + while (colors--) { + p = *xpm++; + + color = *p++; + NEXT_TOKEN; + + if (*p++ != 'c') { + SDL_FreeSurface(surface); + return NULL; + } + NEXT_TOKEN; + + if (*p == '#') + pal[color] = strtoul(++p, NULL, 16) | 0xff000000; + else + pal[color] = 0; + } + + y = 0; + while (y < height) { + int *pixels; + + p = *xpm++; + + pixels = (int *)&((char *)surface->pixels)[y++ * surface->pitch]; + x = 0; + while (x < width) { + Uint8 r,g,b,a; + + if (*p == '\0') { + SDL_FreeSurface(surface); + return NULL; + } + r = (pal[(int)*p] >> 16) & 0xff; + b = (pal[(int)*p] & 0xff); + g = (pal[(int)*p] >> 8) & 0xff; + a = (pal[(int)*p] >> 24) & 0xff; + pixels[x] = SDL_MapRGBA(surface->format, r, g, b, a); + x++; + p++; + } + } + + return surface; +} + +unsigned char *get_vgaptr(int page, int x, int y) +{ + assert(drawing_enable==1); + + return (unsigned char *)screen_buffer[page] + (y*screen_pitch)+(x); +} + + +void set_scaling(int scale) +{ + if (scale==1) { + screen_width=800; + screen_height=512; + scale_up=1; + dirty_block_shift=5; + screen_pitch=screen_width; + } else { + screen_width=400; + screen_height=256; + scale_up=0; + dirty_block_shift=4; + screen_pitch=screen_width; + } +} + +void open_screen(void) +{ + int lval = 0; + int flags; + + lval = SDL_Init(SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO ); + if (lval < 0) { + fprintf(stderr, "SDL ERROR: %s\n", SDL_GetError()); + //exit(EXIT_FAILURE); + } + + flags = SDL_SWSURFACE; + if (fullscreen) + flags |= SDL_FULLSCREEN; + jnb_surface = SDL_SetVideoMode(screen_width, screen_height, 8, flags); + + if (!jnb_surface) { + fprintf(stderr, "SDL ERROR: %s\n", SDL_GetError()); + exit(EXIT_FAILURE); + } + + if(fullscreen) + SDL_ShowCursor(0); + else + SDL_ShowCursor(1); + + SDL_WM_SetCaption("Jump'n'Bump",""); + + icon=load_xpm_from_array(jumpnbump_xpm); + if (icon==NULL) { + printf("Couldn't load icon\n"); + } else { + SDL_WM_SetIcon(icon,NULL); + } + + vinited = 1; + + memset(dirty_blocks, 0, sizeof(dirty_blocks)); + + screen_buffer[0]=malloc(screen_width*screen_height); + screen_buffer[1]=malloc(screen_width*screen_height); + +/* + dirty_blocks[0]=malloc(sizeof(int)*25*16+1000); + dirty_blocks[1]=malloc(sizeof(int)*25*16+1000); +*/ + + return; +} + + +void fs_toggle() +{ + if (!vinited) { + fullscreen ^= 1; + return; + } + if (SDL_WM_ToggleFullScreen(jnb_surface)) + fullscreen ^= 1; +} + + +void wait_vrt(int mix) +{ + return; +} + + +void clear_page(int page, int color) +{ + int i,j; + unsigned char *buf = get_vgaptr(page, 0, 0); + + assert(drawing_enable==1); + + for (i=0; i<(25*16); i++) + dirty_blocks[page][i] = 1; + + for (i=0; i>dirty_block_shift) - (y>>dirty_block_shift) + 1; + y >>= dirty_block_shift; + for (i=0; iformat, (Uint8)(pal[color*3+0]<<2), (Uint8)(pal[color*3+1]<<2), (Uint8)(pal[color*3+2]<<2)); +} + + +int get_pixel(int page, int x, int y) +{ + assert(drawing_enable==1); + + if (scale_up) { + x *= 2; + y *= 2; + } + + assert(x>dirty_block_shift)*25+(x>>dirty_block_shift)] = 1; + + *(unsigned char *)get_vgaptr(page, x, y) = color; +} + + +void flippage(int page) +{ + int x,y; + unsigned char *src; + unsigned char *dest; + + assert(drawing_enable==0); + + SDL_LockSurface(jnb_surface); + if (!jnb_surface->pixels) { + + for (x=0; x<(25*16); x++) { + dirty_blocks[0][x] = 1; + dirty_blocks[1][x] = 1; + } + + return; + } + dest=(unsigned char *)jnb_surface->pixels; + src=screen_buffer[page]; + for (y=0; y>dirty_block_shift)*25+test_x]) ) { + count++; + test_x++; + } + if (count) { + memcpy( &dest[y*jnb_surface->pitch+(x<>4)*count); + } + x = test_x; + } + } + memset(&dirty_blocks[page], 0, sizeof(int)*25*16); + SDL_UnlockSurface(jnb_surface); + SDL_Flip(jnb_surface); +} + + +void draw_begin(void) +{ + assert(drawing_enable==0); + + drawing_enable = 1; + if (background_drawn == 0) { + if (background) { + put_block(0, 0, 0, JNB_WIDTH, JNB_HEIGHT, background); + put_block(1, 0, 0, JNB_WIDTH, JNB_HEIGHT, background); + } else { + clear_page(0, 0); + clear_page(1, 0); + } + background_drawn = 1; + } +} + + +void draw_end(void) +{ + assert(drawing_enable==1); + + drawing_enable = 0; +} + + +void setpalette(int index, int count, char *palette) +{ + SDL_Color colors[256]; + int i; + + assert(drawing_enable==0); + + for (i = 0; i < count; i++) { + colors[i+index].r = palette[i * 3 + 0] << 2; + colors[i+index].g = palette[i * 3 + 1] << 2; + colors[i+index].b = palette[i * 3 + 2] << 2; + } + SDL_SetColors(jnb_surface, &colors[index], index, count); +} + + +void fillpalette(int red, int green, int blue) +{ + SDL_Color colors[256]; + int i; + + assert(drawing_enable==0); + + for (i = 0; i < 256; i++) { + colors[i].r = red << 2; + colors[i].g = green << 2; + colors[i].b = blue << 2; + } + SDL_SetColors(jnb_surface, colors, 0, 256); +} + + +void get_block(int page, int x, int y, int width, int height, void *buffer) +{ + unsigned char *buffer_ptr, *vga_ptr; + int h; + + assert(drawing_enable==1); + + if (scale_up) { + x *= 2; + y *= 2; + width *= 2; + height *= 2; + } + + if (x < 0) + x = 0; + if (y < 0) + y = 0; + if (y + height >= screen_height) + height = screen_height - y; + if (x + width >= screen_width) + width = screen_width - x; + if (width<=0) + return; + if(height<=0) + return; + + vga_ptr = get_vgaptr(page, x, y); + buffer_ptr = buffer; + for (h = 0; h < height; h++) { + memcpy(buffer_ptr, vga_ptr, width); + vga_ptr += screen_pitch; + buffer_ptr += width; + } + +} + + +void put_block(int page, int x, int y, int width, int height, void *buffer) +{ + int h; + unsigned char *vga_ptr, *buffer_ptr; + + assert(drawing_enable==1); + + if (scale_up) { + x *= 2; + y *= 2; + width *= 2; + height *= 2; + } + + if (x < 0) + x = 0; + if (y < 0) + y = 0; + if (y + height >= screen_height) + height = screen_height - y; + if (x + width >= screen_width) + width = screen_width - x; + if (width<=0) + return; + if(height<=0) + return; + + vga_ptr = get_vgaptr(page, x, y); + buffer_ptr = buffer; + for (h = 0; h < height; h++) { + memcpy(vga_ptr, buffer_ptr, width); + vga_ptr += screen_pitch; + buffer_ptr += width; + } + width = ((x+width)>>dirty_block_shift) - (x>>dirty_block_shift) + 1; + height = ((y+height)>>dirty_block_shift) - (y>>dirty_block_shift) + 1; + x >>= dirty_block_shift; + y >>= dirty_block_shift; + while (width--) + for (h=0; h= 33 && t1 <= 34) + image = t1 - 33; + + else if (t1 >= 39 && t1 <= 41) + image = t1 - 37; + + else if (t1 >= 44 && t1 <= 59) + image = t1 - 39; + + else if (t1 >= 64 && t1 <= 90) + image = t1 - 43; + + else if (t1 >= 97 && t1 <= 122) + image = t1 - 49; + + else if (t1 == '~') + image = 74; + + else if (t1 == 0x84) + image = 75; + + else if (t1 == 0x86) + image = 76; + + else if (t1 == 0x8e) + image = 77; + + else if (t1 == 0x8f) + image = 78; + + else if (t1 == 0x94) + image = 79; + + else if (t1 == 0x99) + image = 80; + + else + continue; + width += pob_width(image, &font_gobs) + 1; + } + + switch (align) { + case 0: + cur_x = x; + break; + case 1: + cur_x = x - width; + break; + case 2: + cur_x = x - width / 2; + break; + default: + cur_x = 0; /* this should cause error? -Chuck */ + break; + } + c1 = 0; + + while (text[c1] != 0) { + t1 = text[c1]; + c1++; + if (t1 == ' ') { + cur_x += 5; + continue; + } + if (t1 >= 33 && t1 <= 34) + image = t1 - 33; + + else if (t1 >= 39 && t1 <= 41) + image = t1 - 37; + + else if (t1 >= 44 && t1 <= 59) + image = t1 - 39; + + else if (t1 >= 64 && t1 <= 90) + image = t1 - 43; + + else if (t1 >= 97 && t1 <= 122) + image = t1 - 49; + + else if (t1 == '~') + image = 74; + + else if (t1 == 0x84) + image = 75; + + else if (t1 == 0x86) + image = 76; + + else if (t1 == 0x8e) + image = 77; + + else if (t1 == 0x8f) + image = 78; + + else if (t1 == 0x94) + image = 79; + + else if (t1 == 0x99) + image = 80; + + else + continue; + put_pob(page, cur_x, y, image, &font_gobs, 1, mask_pic); + cur_x += pob_width(image, &font_gobs) + 1; + } +} + + +void put_pob(int page, int x, int y, int image, gob_t *gob, int use_mask, void *mask_pic) +{ + int c1, c2; + int pob_x, pob_y; + int width, height; + int draw_width, draw_height; + int colour; + unsigned char *vga_ptr; + unsigned char *pob_ptr; + unsigned char *mask_ptr; + + assert(drawing_enable==1); + assert(gob); + assert(image>=0); + assert(imagenum_images); + + if (scale_up) { + x *= 2; + y *= 2; + width = draw_width = gob->width[image]*2; + height = draw_height = gob->height[image]*2; + x -= gob->hs_x[image]*2; + y -= gob->hs_y[image]*2; + } else { + width = draw_width = gob->width[image]; + height = draw_height = gob->height[image]; + x -= gob->hs_x[image]; + y -= gob->hs_y[image]; + } + + if ((x + width) <= 0 || x >= screen_width) + return; + if ((y + height) <= 0 || y >= screen_height) + return; + + pob_x = 0; + pob_y = 0; + if (x < 0) { + pob_x -= x; + draw_width += x; + x = 0; + } + if ((x + width) > screen_width) + draw_width -= x + width - screen_width; + if (y < 0) { + pob_y -= y; + draw_height += y; + y = 0; + } + if ((y + height) > screen_height) + draw_height -= y + height - screen_height; + + vga_ptr = get_vgaptr(page, x, y); + pob_ptr = ((unsigned char *)gob->data[image]) + ((pob_y * width) + pob_x); + mask_ptr = ((unsigned char *)mask) + ((y * screen_pitch) + (x)); + for (c1 = 0; c1 < draw_height; c1++) { + for (c2 = 0; c2 < draw_width; c2++) { + colour = *mask_ptr; + if (use_mask == 0 || (use_mask == 1 && colour == 0)) { + colour = *pob_ptr; + if (colour != 0) { + *vga_ptr = colour; + } + } + vga_ptr++; + pob_ptr++; + mask_ptr++; + } + pob_ptr += width - c2; + vga_ptr += (screen_width - c2); + mask_ptr += (screen_width - c2); + } + draw_width = ((x+draw_width)>>dirty_block_shift) - (x>>dirty_block_shift) + 1; + draw_height = ((y+draw_height)>>dirty_block_shift) - (y>>dirty_block_shift) + 1; + x >>= dirty_block_shift; + y >>= dirty_block_shift; + while (draw_width--) + for (c1=0; c1=0); + assert(imagenum_images); + return gob->width[image]; +} + + +int pob_height(int image, gob_t *gob) +{ + assert(gob); + assert(image>=0); + assert(imagenum_images); + return gob->height[image]; +} + + +int pob_hs_x(int image, gob_t *gob) +{ + assert(gob); + assert(image>=0); + assert(imagenum_images); + return gob->hs_x[image]; +} + + +int pob_hs_y(int image, gob_t *gob) +{ + assert(gob); + assert(image>=0); + assert(imagenum_images); + return gob->hs_y[image]; +} + + +int read_pcx(unsigned char * handle, void *buf, int buf_len, char *pal) +{ + unsigned char *buffer=buf; + short c1; + short a, b; + long ofs1; + if (buffer != 0) { + handle += 128; + ofs1 = 0; + while (ofs1 < buf_len) { + a = *(handle++); + if ((a & 0xc0) == 0xc0) { + b = *(handle++); + a &= 0x3f; + for (c1 = 0; c1 < a && ofs1 < buf_len; c1++) + buffer[ofs1++] = (char) b; + } else + buffer[ofs1++] = (char) a; + } + if (pal != 0) { + handle++; + for (c1 = 0; c1 < 768; c1++) + pal[c1] = *(handle++) /*fgetc(handle)*/ >> 2; + } + } + return 0; +} + + +void register_background(char *pixels, char pal[768]) +{ + if (background) { + free(background); + background = NULL; + } + background_drawn = 0; + if (!pixels) + return; + assert(pal); + if (scale_up) { + background = malloc(screen_pitch*screen_height); + assert(background); + do_scale2x((unsigned char *)pixels, JNB_WIDTH, JNB_HEIGHT, (unsigned char *)background); + } else { + background = malloc(JNB_WIDTH*JNB_HEIGHT); + assert(background); + memcpy(background, pixels, JNB_WIDTH*JNB_HEIGHT); + } +} + +int register_gob(unsigned char *handle, gob_t *gob, int len) +{ + unsigned char *gob_data; + int i; + + gob_data = malloc(len); + memcpy(gob_data, handle, len); + + gob->num_images = (short)((gob_data[0]) + (gob_data[1] << 8)); + + gob->width = malloc(gob->num_images*sizeof(int)); + gob->height = malloc(gob->num_images*sizeof(int)); + gob->hs_x = malloc(gob->num_images*sizeof(int)); + gob->hs_y = malloc(gob->num_images*sizeof(int)); + gob->data = malloc(gob->num_images*sizeof(void *)); + gob->orig_data = malloc(gob->num_images*sizeof(void *)); + for (i=0; inum_images; i++) { + int image_size; + int offset; + + offset = (gob_data[i*4+2]) + (gob_data[i*4+3] << 8) + (gob_data[i*4+4] << 16) + (gob_data[i*4+5] << 24); + + gob->width[i] = (short)((gob_data[offset]) + (gob_data[offset+1] << 8)); offset += 2; + gob->height[i] = (short)((gob_data[offset]) + (gob_data[offset+1] << 8)); offset += 2; + gob->hs_x[i] = (short)((gob_data[offset]) + (gob_data[offset+1] << 8)); offset += 2; + gob->hs_y[i] = (short)((gob_data[offset]) + (gob_data[offset+1] << 8)); offset += 2; + + image_size = gob->width[i] * gob->height[i]; + gob->orig_data[i] = malloc(image_size); + memcpy(gob->orig_data[i], &gob_data[offset], image_size); + if (scale_up) { + image_size = gob->width[i] * gob->height[i] * 4; + gob->data[i] = malloc(image_size); + do_scale2x((unsigned char *)gob->orig_data[i], gob->width[i], gob->height[i], (unsigned char *)gob->data[i]); + } else { + gob->data[i] = (unsigned short *)gob->orig_data[i]; + } + } + free(gob_data); + return 0; +} + + +void recalculate_gob(gob_t *gob, char pal[768]) +{ +} + +void register_mask(void *pixels) +{ + if (mask) { + free(mask); + mask = NULL; + } + assert(pixels); + if (scale_up) { + mask = malloc(screen_pitch*screen_height); + assert(mask); + do_scale2x((unsigned char *)pixels, JNB_WIDTH, JNB_HEIGHT, (unsigned char *)mask); + } else { + mask = malloc(JNB_WIDTH*JNB_HEIGHT); + assert(mask); + memcpy(mask, pixels, JNB_WIDTH*JNB_HEIGHT); + } +} diff --git a/contrib/other/jumpnbump/sdl/input.c b/contrib/other/jumpnbump/sdl/input.c new file mode 100755 index 0000000000..e33e6d38c4 --- /dev/null +++ b/contrib/other/jumpnbump/sdl/input.c @@ -0,0 +1,113 @@ +/* + * input.c + * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/ + * + * Copyright (C) 2001 Chuck Mason + * + * Copyright (C) 2002 Florian Schulze + * + * This file is part of Jump'n'Bump. + * + * Jump'n'Bump 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. + * + * Jump'n'Bump 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "globals.h" + + + + + +static int num_joys=0; +static SDL_Joystick *joys[4]; + +/* assumes joysticks have at least one button, could check numbuttons first? */ +#define JOY_LEFT(num) (num_joys>num && SDL_JoystickGetAxis(joys[num], 0)<-3200) +#define JOY_RIGHT(num) (num_joys>num && SDL_JoystickGetAxis(joys[num], 0)>3200) +/* I find using the vertical axis to be annoying -- dnb */ +#define JOY_JUMP(num) (num_joys>num && SDL_JoystickGetButton(joys[num], 0)) + +int calib_joy(int type) +{ + return 1; +} + +void update_player_actions(void) +{ + int tmp; + + if (client_player_num < 0) { + tmp = (key_pressed(KEY_PL1_LEFT) == 1) || JOY_LEFT(3); + if (tmp != player[0].action_left) + tellServerPlayerMoved(0, MOVEMENT_LEFT, tmp); + tmp = (key_pressed(KEY_PL1_RIGHT) == 1) || JOY_RIGHT(3); + if (tmp != player[0].action_right) + tellServerPlayerMoved(0, MOVEMENT_RIGHT, tmp); + tmp = (key_pressed(KEY_PL1_JUMP) == 1) || JOY_JUMP(3); + if (tmp != player[0].action_up) + tellServerPlayerMoved(0, MOVEMENT_UP, tmp); + + tmp = (key_pressed(KEY_PL2_LEFT) == 1) || JOY_LEFT(2); + if (tmp != player[1].action_left) + tellServerPlayerMoved(1, MOVEMENT_LEFT, tmp); + tmp = (key_pressed(KEY_PL2_RIGHT) == 1) || JOY_RIGHT(2); + if (tmp != player[1].action_right) + tellServerPlayerMoved(1, MOVEMENT_RIGHT, tmp); + tmp = (key_pressed(KEY_PL2_JUMP) == 1) || JOY_JUMP(2); + if (tmp != player[1].action_up) + tellServerPlayerMoved(1, MOVEMENT_UP, tmp); + + tmp = (key_pressed(KEY_PL3_LEFT) == 1) || JOY_LEFT(1); + if (tmp != player[2].action_left) + tellServerPlayerMoved(2, MOVEMENT_LEFT, tmp); + tmp = (key_pressed(KEY_PL3_RIGHT) == 1) || JOY_RIGHT(1); + if (tmp != player[2].action_right) + tellServerPlayerMoved(2, MOVEMENT_RIGHT, tmp); + tmp = (key_pressed(KEY_PL3_JUMP) == 1) || JOY_JUMP(1); + if (tmp != player[2].action_up) + tellServerPlayerMoved(2, MOVEMENT_UP, tmp); + + tmp = (key_pressed(KEY_PL4_LEFT) == 1) || JOY_LEFT(0); + if (tmp != player[3].action_left) + tellServerPlayerMoved(3, MOVEMENT_LEFT, tmp); + tmp = (key_pressed(KEY_PL4_RIGHT) == 1) || JOY_RIGHT(0); + if (tmp != player[3].action_right) + tellServerPlayerMoved(3, MOVEMENT_RIGHT, tmp); + tmp = (key_pressed(KEY_PL4_JUMP) == 1) || JOY_JUMP(0); + if (tmp != player[3].action_up) + tellServerPlayerMoved(3, MOVEMENT_UP, tmp); + } else { + tmp = (key_pressed(KEY_PL1_LEFT) == 1) || JOY_LEFT(0); + if (tmp != player[client_player_num].action_left) + tellServerPlayerMoved(client_player_num, MOVEMENT_LEFT, tmp); + tmp = (key_pressed(KEY_PL1_RIGHT) == 1) || JOY_RIGHT(0); + if (tmp != player[client_player_num].action_right) + tellServerPlayerMoved(client_player_num, MOVEMENT_RIGHT, tmp); + tmp = (key_pressed(KEY_PL1_JUMP) == 1) || JOY_JUMP(0); + if (tmp != player[client_player_num].action_up) + tellServerPlayerMoved(client_player_num, MOVEMENT_UP, tmp); + } +} + +void init_inputs(void) +{ + int i; + + num_joys = SDL_NumJoysticks(); + for(i = 0; i < 4 && i < num_joys; ++i) + joys[i] = SDL_JoystickOpen(i); + + main_info.mouse_enabled = 0; + main_info.joy_enabled = 0; +} diff --git a/contrib/other/jumpnbump/sdl/interrpt.c b/contrib/other/jumpnbump/sdl/interrpt.c new file mode 100755 index 0000000000..91a27ab9a3 --- /dev/null +++ b/contrib/other/jumpnbump/sdl/interrpt.c @@ -0,0 +1,462 @@ +/* + * interrpt.c + * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/ + * + * Copyright (C) 2001 Chuck Mason + * + * Copyright (C) 2002 Florian Schulze + * + * This file is part of Jump'n'Bump. + * + * Jump'n'Bump 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. + * + * Jump'n'Bump 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#ifndef _MSC_VER +#include +#endif +#include "globals.h" + +#ifdef USE_KAILLERA +#include "SDL_thread.h" +#include "SDL_mutex.h" +#include + +char local_keyb[256]; +#endif /* USE_KAILLERA */ + +char keyb[256]; +char last_keys[50]; + +#ifdef USE_KAILLERA + +/* information about the party in this session */ +static int my_player = -1; +static int my_numplayers = -1; + +/* semaphore for controlling kaillera thread */ +static SDL_sem *game_start_sem = NULL; + +/* keys supported on my end */ +static int my_player_up = -1; +static int my_player_left = -1; +static int my_player_right = 1; + +/* values for the kaillera client interface */ +static char kaillera_app_name[] = "Jump 'n Bump"; +static char kaillera_game_name[] = "Jump 'n Bump\0\0"; + +static int player_keys[4][3] = { + { + KEY_PL1_LEFT, + KEY_PL1_RIGHT, + KEY_PL1_JUMP + }, + { + KEY_PL2_LEFT, + KEY_PL2_RIGHT, + KEY_PL2_JUMP + }, + { + KEY_PL3_LEFT, + KEY_PL3_RIGHT, + KEY_PL3_JUMP + }, + { + KEY_PL4_LEFT, + KEY_PL4_RIGHT, + KEY_PL4_JUMP + } +}; + +static int WINAPI kaillera_game_callback(char *game, int player, int numplayers) +{ + int length; + int urand; + unsigned char random[8]; + + if (strcmp(game, kaillera_game_name) != 0) { + printf("unknown game selected: %s\n", game); + + my_player = -1; + goto release; + } + + printf("start network game with %d players\n", numplayers); + printf("I am player %d\n", player); + + my_player = player; + my_numplayers = numplayers; + + my_player_up = player_keys[player-1][0] & 0xff; + my_player_left = player_keys[player-1][1] & 0xff; + my_player_right = player_keys[player-1][2] & 0xff; + + /* initialize randomizer agreed by all players */ + random[0] = time(0) & 0xff; + random[1] = random[2] = random[3] = 0x00; + length = kailleraModifyPlayValues(&random, sizeof(random[0])); + if (length < 0) { + goto release; + } + + urand = random[3] << 24 | random[2] << 16 | random[1] << 8 | random[0]; + srand(urand); + +release: + + SDL_SemPost(game_start_sem); + return 0; +} + +static kailleraInfos kaillera_data = { + kaillera_app_name, + kaillera_game_name, + kaillera_game_callback, + NULL, + NULL, + NULL +}; + +static void print_version() +{ + char version[16]; + + kailleraGetVersion(version); + printf("using kaillera version %s\n", version); +} + +static int kaillera_thread(void *arg) +{ + kailleraInit(); + + /* print_version(); */ + + kailleraSetInfos(&kaillera_data); + + kailleraSelectServerDialog(0); + if (SDL_SemValue(game_start_sem) == 0) { + /* server dialog returned and game didnt start */ + + /* release blocking thread */ + my_player = -1; + SDL_SemPost(game_start_sem); + } + + return 0; +} + +static int start_kaillera_thread(void) +{ + SDL_Thread *thread; + + game_start_sem = SDL_CreateSemaphore(0); + + thread = SDL_CreateThread(kaillera_thread, NULL); + if (!thread) { + printf("SDL_CreateThread failed\n"); + return -1; + } + + return 0; +} + +int addkey(unsigned int key) +{ + /* it doesnt matter if a player presses keys + * that control other bunnies. whatever is sent + * is packed by pack_keys() + */ + if (!(key & 0x8000)) { + local_keyb[key & 0x7fff] = 1; + } else + local_keyb[key & 0x7fff] = 0; + return 0; +} + +void remove_keyb_handler(void) +{ + kailleraShutdown(); +} + +int pack_keys(void) +{ + int rv; + + rv = local_keyb[my_player_up]; + rv |= local_keyb[my_player_left] << 1; + rv |= local_keyb[my_player_right] << 2; + rv |= local_keyb[1] << 3; + return rv; +} + +void unpack_keys(int player, char value) +{ + keyb[player_keys[player][0] & 0xff] = (value >> 0) & 1; + keyb[player_keys[player][1] & 0xff] = (value >> 1) & 1; + keyb[player_keys[player][2] & 0xff] = (value >> 2) & 1; + + /* escape key is shared among all users */ + keyb[1] |= (value >> 3) & 1; +} + +int update_kaillera_keys(void) +{ + char keys[8]; + int length; + int player; + + keys[0] = pack_keys(); + length = kailleraModifyPlayValues(&keys, sizeof(keys[0])); + + if (length < 0) { + /* terminate session */ + printf("** LOST CONNECTION **\n"); + kailleraEndGame(); + my_player = -1; + return -1; + } + + for (player=0; player 0; c1--) + last_keys[c1] = last_keys[c1 - 1]; + last_keys[0] = key & 0x7fff; + } else + keyb[key & 0x7fff] = 0; + return 0; +} + +void remove_keyb_handler(void) +{ +} + +int hook_keyb_handler(void) +{ + SDL_EnableUNICODE(1); + memset((void *) last_keys, 0, sizeof(last_keys)); + + return 0; +} + +int key_pressed(int key) +{ + return keyb[(unsigned char) key]; +} + + +#endif /* USE_KAILLERA */ + +int intr_sysupdate() +{ + SDL_Event e; + int i = 0; + static int last_time = 0; + int now, time_diff; + + while (SDL_PollEvent(&e)) { + switch (e.type) { + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + if(e.button.state == SDL_PRESSED && + ((key_pressed(KEY_PL3_LEFT) && e.button.button == SDL_BUTTON_RIGHT) || + (key_pressed(KEY_PL3_RIGHT) && e.button.button == SDL_BUTTON_LEFT) || + (e.button.button == SDL_BUTTON_LEFT && e.button.button == SDL_BUTTON_RIGHT) || + e.button.button == SDL_BUTTON_MIDDLE)) + { + addkey(KEY_PL3_JUMP & 0x7f); + } + else if(e.button.state == SDL_RELEASED && + ((key_pressed(KEY_PL3_LEFT) && e.button.button == SDL_BUTTON_RIGHT) || + (key_pressed(KEY_PL3_RIGHT) && e.button.button == SDL_BUTTON_LEFT) || + e.button.button == SDL_BUTTON_MIDDLE)) + { + addkey((KEY_PL3_JUMP & 0x7f) | 0x8000); + } + + if(e.button.button == SDL_BUTTON_LEFT) + { + SDLKey sym = KEY_PL3_LEFT; + sym &= 0x7f; + if(e.button.state == SDL_RELEASED) + { + if(key_pressed(KEY_PL3_JUMP) && (SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(SDL_BUTTON_RIGHT))) + addkey(KEY_PL3_RIGHT & 0x7f); + else + sym |= 0x8000; + } + addkey(sym); + } + else if(e.button.button == SDL_BUTTON_RIGHT) + { + SDLKey sym = KEY_PL3_RIGHT; + sym &= 0x7f; + if (e.button.state == SDL_RELEASED) + { + if(key_pressed(KEY_PL3_JUMP) && (SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(SDL_BUTTON_LEFT))) + addkey(KEY_PL3_LEFT & 0x7f); + else + sym |= 0x8000; + } + addkey(sym); + } + break; + case SDL_KEYDOWN: + case SDL_KEYUP: + switch (e.key.keysym.sym) { + case SDLK_F12: + if (e.type == SDL_KEYDOWN) { + SDL_Quit(); + exit(1); + } + break; + case SDLK_F10: + if (e.type == SDL_KEYDOWN) { + fs_toggle(); + } + break; + case SDLK_1: + if (e.type == SDL_KEYUP) + ai[0] = !ai[0]; + + /* Release keys, otherwise it will continue moving that way */ + addkey((KEY_PL1_LEFT & 0x7f) | 0x8000); + addkey((KEY_PL1_RIGHT & 0x7f) | 0x8000); + addkey((KEY_PL1_JUMP & 0x7f) | 0x8000); + break; + case SDLK_2: + if (e.type == SDL_KEYUP) + ai[1] = !ai[1]; + + /* Release keys, otherwise it will continue moving that way */ + addkey((KEY_PL2_LEFT & 0x7f) | 0x8000); + addkey((KEY_PL2_RIGHT & 0x7f) | 0x8000); + addkey((KEY_PL2_JUMP & 0x7f) | 0x8000); + break; + case SDLK_3: + if (e.type == SDL_KEYUP) + ai[2] = !ai[2]; + + /* Release keys, otherwise it will continue moving that way */ + addkey((KEY_PL3_LEFT & 0x7f) | 0x8000); + addkey((KEY_PL3_RIGHT & 0x7f) | 0x8000); + addkey((KEY_PL3_JUMP & 0x7f) | 0x8000); + break; + case SDLK_4: + if (e.type == SDL_KEYUP) + ai[3] = !ai[3]; + + /* Release keys, otherwise it will continue moving that way */ + addkey((KEY_PL4_LEFT & 0x7f) | 0x8000); + addkey((KEY_PL4_RIGHT & 0x7f) | 0x8000); + addkey((KEY_PL4_JUMP & 0x7f) | 0x8000); + break; + case SDLK_ESCAPE: + if (e.type == SDL_KEYUP) + addkey(1 | 0x8000); + else + addkey(1 & 0x7f); + break; + default: + e.key.keysym.sym &= 0x7f; + if (e.type == SDL_KEYUP) + e.key.keysym.sym |= 0x8000; + addkey(e.key.keysym.sym); + + break; + } + break; + default: + break; + } + i++; + } + + SDL_Delay(1); + now = SDL_GetTicks(); + time_diff = now - last_time; + if (time_diff>0) { + i = time_diff / (1000 / 60); + if (i) { + last_time = now; + } else { + int tmp; + + tmp = (1000/60) - i - 10; + if (tmp>0) + SDL_Delay(tmp); + } + } +/* + if (!then) + SDL_Delay(1); + else { + then = (1000 / 60) - (now - then); + if (then > 0 && then < 1000) + SDL_Delay(then); + } + then = now; +*/ + +#ifdef USE_KAILLERA + if (my_player >= 0) { + update_kaillera_keys(); + i=1; + } +#endif /* USE_KAILLERA */ + + return i; +} diff --git a/contrib/other/jumpnbump/sdl/jumpnbump128.xpm b/contrib/other/jumpnbump/sdl/jumpnbump128.xpm new file mode 100755 index 0000000000..2916506bcc --- /dev/null +++ b/contrib/other/jumpnbump/sdl/jumpnbump128.xpm @@ -0,0 +1,196 @@ +/* XPM */ +static char * jumpnbump_xpm[] = { +"128 128 65 1", +" c None", +". c #06070A", +"+ c #B6B6B6", +"@ c #F60202", +"# c #727272", +"$ c #B60202", +"% c #5A5C5D", +"& c #FC8622", +"* c #3A1602", +"= c #C6C6C6", +"- c #A6221A", +"; c #8E8E8E", +"> c #D6D6D6", +", c #FB8E24", +"' c #4A2A1A", +") c #E6E6E6", +"! c #CE7222", +"~ c #505252", +"{ c #A15A1F", +"] c #F79B37", +"^ c #FEB666", +"/ c #AE5A0A", +"( c #D66C16", +"_ c #DE6A18", +": c #EFEEEE", +"< c #7A0202", +"[ c #FEA640", +"} c #664833", +"| c #CCA085", +"1 c #2A2A32", +"2 c #895F38", +"3 c #3C3A3F", +"4 c #EAAE7C", +"5 c #A8805B", +"6 c #9E9E9E", +"7 c #FEC68E", +"8 c #BB5E0F", +"9 c #EE3A3A", +"0 c #AF5207", +"a c #FEAE42", +"b c #5A2A02", +"c c #F8F6F9", +"d c #636262", +"e c #CB6312", +"f c #E67215", +"g c #8E4202", +"h c #1D1C20", +"i c #6A3202", +"j c #7A685D", +"k c #A4500C", +"l c #F5781A", +"m c #7A7A7A", +"n c #F6CEA6", +"o c #4A4242", +"p c #FEDEBF", +"q c #FDFEFD", +"r c #D67A3A", +"s c #FDA64D", +"t c #7A3A02", +"u c #B64242", +"v c #FE7A12", +"w c #6A6A6A", +"x c #DE7A2A", +"y c #150D0C", +"z c #FEAE4C", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" 6;;66 ", +" 6;;66 ", +" 6;;;## ", +" mm 6;;;#### ", +" ##m mm;#dwmm ", +" ##m mm;mw#mm ", +" %%%~ m;;;#~% ", +" mm#=66 ~~~3 ;66#dmm ", +" ;;m+6666 ~~~3 #6;;%w66 ", +" ;;m+;666 + ~~~~3 #;;;%w66 ", +" ;;m+66;6 + ~~~~3 #6;;~w66 ", +" 666+++::66 66d6 ~%~~o m;6~%d6 ", +" 6>;;==qq6 +##~; ~%~%3w #6m~~; ", +" 6:++mm::6 +;ddw6 ~~dd1~ ;;m6#mm6 ", +" 6)++mm::6 +;ddw6 ~~dd1~ ;;m6wmm6 ", +" 6c::##==q6 ==;mddm+ ~%ww33 ;;;;;w666 ", +" ;)qq++66q6 ++6mmm+= %%##%o mmm6;m66; ", +" 6=qq))66:6 7744=+++666+ %%###m66 mm#6;;66 ", +" 6=qq))66)6 7744=+++666+ %%###m66 mmm6m;66 ", +" 6qqcc==)q66[]]]||===>=++= %om#m;;;;mmm6;;6; ", +" 4;::qq))>q66z[4z==>)))===> 33wwmmmmd;;;6;;;; ", +" 4;::qq))>q66a[44==>)))===> 3w#mmmmd;;;6;;;; ", +" 4;::qq))>q66s[44==>)))===> 3wwmmmmd;;;6;;;; ", +" za[[]5))cccc:cqq^[==>>)cc>=>>n^ 1%%mmmm#;;;m;m55 ", +" xszz[[[[[[[aa[|++ccqqcqqqn4==))c))>>==^]77|.oo#mmm##mm;;m55r{}2 ", +" e8zzaz[aa[s[sss[]jj==qqqqqqp=))::c)))>44s[[s,y11w###m;;;66666m1y.ii&&, ", +" 8ezzaas[a[sa[^sz]#j==qqqqqqp=))::c)))>44ss[s,.11d###m;;;66666m1.yii&&& ", +" 22]z[[z[[aas[^^77r|++ccqqqq:>))ccq::>=^4s[,,lb..ow##m;666;;666#yhxx&&&lvv, ", +" /zzzzzz[[z^zsn:ppccqqqcqqq:ccqqc))=^ss]&!!!*hh~w##;66666hw#+633tt,&&&&&&&&,,, ", +" txsszszsz^z77pcqqqqqqqqqqqqqqqqc))n]fffe88}}%ddw##;666661.y66mm''&&&&&&&&&&&&&&&] ", +" ta[zzz^^^7ppcqqqqqqqqqqqqqqqqqcqq4r_((822~~~~%w##m;m;6+w..d+66~}ff&&v&v&&&v&&v&&vlv ", +" t[[zza^^^7ppcqqqqqqqqcqqqqqqqqcqq4!((!822}~~~%d##m;;;6+w..%+66~}lf&&&&&v&&&&&&&&vvv ", +" 'ee^aaazs^:cqqqqqqqqqqqqqqqqqqqqqc^!!e0}t11oo%d##m;;;;6611166;ddflv&&,&&&v&&&&,&vs] ", +" '!!^zzzss^::qqqqqqqqqqqqqcqqqqqqqc^!!ekt}11oo%d##m;;;66611h6662j_l&&,,&&&&&&,,]&x ", +" bb,zszzs^::qqqqqqqqqqqqqqqqqqcqqqn!!e{''yh33%dwwm;;;;;6%dh666jjxx&&,&&v&&&&&&&& ", +" bb]zzzzz^::qqqqqqqqcqqqqqqqqqqqqqn!!ek''yy33%dwwm;m;;;6ddy666#jxxv&&,&&,,x&,&&& ", +" gzzs^s=))qqcc::qqqqccqqqqqqqccqq]]e{**yy33~%dd#mmm;;;mm3;;;mmrr],&&&,]]&,&&] ", +" *//lfr=::cq6666qqqqqqcqqqqqqqqqc44eg...h33o~%%wmm#m#;;;;;;;mm''g_&&,&&,vvss ", +" ikkffx+>>))hh66qqq:;;=qqqqqcqqqq77!g.y.13oo~~%w####mm;;;m55uubb**bb{8eess ", +" ik0ffr+>>))hy66qqq:;;=qqqqqcqqqq77!gy..1ooo~%%d####m#;;;;;5uubby*bbkeeess ", +" g00_fllvvvvlvr++);..::qqq;..>qqqqqqqqqqnnx0*y.1333o%%%ddww##w#m#99@@tttibb*b00&x ", +" kgkl&vvvvlvlvv&lvlrr|~yyccqqq~yhcqqqqqqqqqqnnx8**11*h13oo~%%%ddwwd%2--$$bbgkeef,]]]]zz ", +" t8vvvvvvvvvvvvvv&l822ppccc.ddqqqqqqqqqc:44!eii*yyyh133o~~~%~~oo~o<>>|!feekg*.....y*t!x!l,]s[sz[[[[[[s][[][[[[[[[[]z ", +" {{(vlvvvvll&vvvllvvlv&&^ccccc:>>>|r!eekk*.....*ytf!fl,][[[z[[[[[[[s[[[[[][[[[[]z ", +" ikklf&v&lvvvlvvlvvlvvl,44===>>|!ee__ib..**gevv][sszz[zz[[[[s][[[[[[][[[[[[[[[, ", +" ibi**/&&&vvvl&vllvvvvllvv&l4|4re_(e_gg{l]][saazss[a[z[[s[s]zs[]s[[[[[[[[][[[[[]] ", +" iiiiiiiiiff&,&&lv&vlvllv&lll&l(_((fff&[[aszzasaas[aasa[sz[z[[[[s[[[[[[[[[[[[[[[[[[[ ", +" iiiiiiiiiff&&&&vlvvvvv&v&lllll__f_ffl&[[asazzsaasaaasa[zz[z[[[[[[[]s[[][[[[[[[[[[[[ ", +" iiiiiiiii**i8&&lv&&&&vlvf00ttbbb0e!fazssazzzs[ssaaa[sasaaszs][[azs[[[[s[[s][[[[[[[[ ", +" iiiiiiiiibiiiii((vvfe{kbiiiiiibbkekk]zzzzzasaz[[z[[[a[[zs[[zzs[sz[as]z[[]zs[s[[[[[[[ ", +" iiiiiiiiiiiiiiiiibb*iiiiiiiiiiii/_kk!zzzsszzzsaszzzz[z[aaaszs[[aaszss[sza[][[][][[], ", +" iiiiiiiiiiiiiiiiibb*iiiiiiiiiiii8_kkezzzssazzszazszs[z[aaz[zz[[aasass[saa[s[[s[][[]] ", +" iiiiiiiiiiiiiiiiibi*iiiiiiiiiiii/_kk!zzzzszzzzzzzazz]z[aaz[zzs]a[sas][saa[[[[[[]]] ", +" iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiitt8f//0sszzzzzzszzzzzz[sassas[assaaz]zas[[ass][&! ", +" iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiitte(eek!^^szzzsz[szazzzzs[[saaz[[zz[za]za[sx,!5d# ", +" iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiitte(eek!^aaazzzzs]szzzzasaasazz[[zz[z[[sa[[,r58dw ", +" iiib-iiiiiiiiiiiiiiiiiiiiiiiiiitt_fee/k]]szzzzzzzszzazzz[[asaas]aazz[[]r5m#www#wd ", +" iiiiiibiiiiiiiiiiiiiiiiiiiiiiiigke__(/k//zszzzszzzss]szzssz[zszz[[,!88k2dd#mwww ", +" iiiiiib-iiiiiiiiiiiiiiiiiiiiiiikg(e((8kkk!^szzzsszszzzazzszz[[xx08kk00kwm#ww ", +" iiiiiiiibiiiiiiiiiiiiiiiiiiiiii0k_(((e0k0k]z^[zzzzzzzszszz,!/8k/k00000{w##ww ", +" iiiiiiiiiiib-iiiib-iiib-iiiiiiik0_(((8000g]^^szazzszzzzzzz]!80kk000000{w##ww ", +" iiiiiiiiiiiiibiiiiibiiiiibiiiii08(e((e0//k/[[zsszzzzz],r880k00000000002#m#wwmm ", +" iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiie8(e((e0//0k88s^]]x8//k0k00000000000000######w#w ", +" iiiiiiiiiiiiiiiiiiiiiiiiii-biii88(e((e///0k8ezz]]r08/00/000/000k000000j##m##www; ", +" iiiiiib-iiiiiiiiiiiiiiiiiiiiiii8e_e((e0//0ge8sz]]x/8/0kkk0k0k0000k0000######w#w; ", +" iiiiiibi-biiiiiiiiiiiiiiiiit!!(e((e/k/0/kk{e{0k000000000000k0000k{/w#w######w# ", +" iiiiiiiiiiiib-iiiiiiiiiiiit8e(ee(e/k0/{k0kkkk/kkk00/0k000k/0000022#w#########ww ", +" iiiiiiiiiibiiiiibiiiiikeeeeeee8//k/00/k//00000k0000k0000k0{2jj#############w ", +" iiiiiiiiib-iiiiiiiiiiigeeeeeee8//k/00/k//00k00000000000000{2jj#w############ ", +" iiiiiiiiiiibiiiiiiiiik__!eeee8kk//kk/0/0//kk00k0k/k00{{2jw#m######w#ww#wwwww ", +" b-iiiiiiiii-iiiiiiii0e(eeeeeekk/k00/k0k0kkk000000{22jj##################ww# ", +" iiiiiiiiibiiiiiiii/eeeeee8e00k/kk0k00k/k00/k{{jw##wwww############www;; ", +" iiiiiiiiiiiiiiiiii8ee8ee(8e00//kk0kk0k00k000{{jw#mwwww##m#########w#w;; ", +" iiiiiiiiiiiiiiii0eeee88ee000/kk/k0/k000k2jww#w##w#######ww#####w# ", +" iiiiiiiiiiiiii!eee8!8(888kk/00000k2j2j##ww#www###www#w#mw#dw ", +" iiiiiii-biiiieeee8eee888kk0k000/k2j2###ww#ww###wwwwww#m ", +" iiiibiiiiiiii!eee8eeee88kk000k0k{222j##wwmwww##w#wwwwwm ", +" iiiiiiibtte88!888/80000kk{222#www#ww##ww##wwdd#; ", +" iiiibbgk88e88e880!e{jjjw#ww##wwwmwww#wdd## ", +" tbbbkg!88/0//x wwww#www##mww##wdm ", +" tbbkk088! wwww##wwww#dw;; ", +" }bbk/088! wwww##w#ww#dw;; ", +" 88 ww#wwddd# ", +" www# ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/contrib/other/jumpnbump/sdl/jumpnbump32.xpm b/contrib/other/jumpnbump/sdl/jumpnbump32.xpm new file mode 100755 index 0000000000..dcd5edc43b --- /dev/null +++ b/contrib/other/jumpnbump/sdl/jumpnbump32.xpm @@ -0,0 +1,100 @@ +/* XPM */ +static char * jumpnbump_xpm[] = { +"32 32 65 1", +" c None", +". c #261814", +"+ c #B3B3B2", +"@ c #EC7818", +"# c #747373", +"$ c #B83A18", +"% c #6D6D6B", +"& c #C8C1BB", +"* c #6B3203", +"= c #DB8434", +"- c #E28A32", +"; c #DCCEC6", +"> c #CA7C30", +", c #A05618", +"' c #2A262A", +") c #999998", +"! c #F59239", +"~ c #9B4E10", +"{ c #EFE8E4", +"] c #FDB055", +"^ c #AB530B", +"/ c #3A363A", +"( c #8F8E8D", +"_ c #CE6915", +": c #6A4E3A", +"< c #BEB8B2", +"[ c #EF9A47", +"} c #F4F1F0", +"| c #C0691C", +"1 c #661834", +"2 c #C8A68C", +"3 c #434143", +"4 c #894209", +"5 c #C2610F", +"6 c #F79E3F", +"7 c #848482", +"8 c #504C4C", +"9 c #5E2E06", +"0 c #823E06", +"a c #F6C29E", +"b c #EAB68A", +"c c #967A60", +"d c #D6A67A", +"e c #8B6241", +"f c #B66016", +"g c #FDA542", +"h c #FCFCFD", +"i c #846A54", +"j c #E6A86C", +"k c #ABA7A5", +"l c #BA590C", +"m c #F8DCC2", +"n c #AE9276", +"o c #864C1E", +"p c #585757", +"q c #E0DDDB", +"r c #733403", +"s c #5E3A1E", +"t c #7B7B7B", +"u c #FEAA48", +"v c #F68627", +"w c #F97B13", +"x c #746D6A", +"y c #DAB69E", +"z c #B45A0F", +" ", +" ", +" )) ", +" x (7# ", +" )k p8 (## ", +" k)& ((p3 (%) ", +" }k<< kt(p8 7t( ", +" qq+h b+(+p%)7() ", +" )}{&6y;& 8#t7( ", +" vuuu[q}}bq{;]ppt7(|: ", +" >ugu]kqh{}{&[~3t((tsvwv ", +" ,=]]{hhhhh{-f8p7)px#@vvvvv ", +" ,]]}hhhhhhjo'8t(tp7@vvvvv ", +" ~>j{&{{}hhms.8%t7%cf|w!! ", +" ~__w@@nt})}hhm4./p%%#$*05! ", +" ^@www@=ac ", +" ***9*****~_^-]]]u6=zfi% ", +" ***r**9**l_^^[!=|^^^^x%% ", +" 9********l5z^||^^^^^,##x% ", +" ******r5_l^^^^^^^ex%%x%% ", +" ***r*055fz^^,^e%x####t# ", +" ****0_5l^^,exx%%#%%% ", +" **4555ex%%%%% ", +" *~l %x%## ", +" ", +" ", +" "}; diff --git a/contrib/other/jumpnbump/sdl/jumpnbump64.xpm b/contrib/other/jumpnbump/sdl/jumpnbump64.xpm new file mode 100755 index 0000000000..746eff1938 --- /dev/null +++ b/contrib/other/jumpnbump/sdl/jumpnbump64.xpm @@ -0,0 +1,132 @@ +/* XPM */ +static char * jumpnbump_xpm[] = { +"64 64 65 1", +" c None", +". c #171010", +"+ c #B2B2B2", +"@ c #E61E1A", +"# c #6E6C6B", +"$ c #C20606", +"% c #D0C6C4", +"& c #FA7A12", +"* c #411A05", +"= c #D06D19", +"- c #DA8636", +"; c #5B5B5B", +"> c #979696", +", c #F18A2D", +"' c #D9D6D4", +") c #7D0A5E", +"! c #BD752F", +"~ c #E8DED9", +"{ c #BABABA", +"] c #8B8A88", +"^ c #F28E39", +"/ c #724E32", +"( c #5A2A02", +"_ c #CA6410", +": c #E7E3DF", +"< c #FEB256", +"[ c #AB5309", +"} c #D69256", +"| c #EEEAEA", +"1 c #563216", +"2 c #828282", +"3 c #C26210", +"4 c #6A3202", +"5 c #875F3D", +"6 c #D5B5A0", +"7 c #832907", +"8 c #D9711E", +"9 c #EF9E49", +"0 c #F2F2F2", +"a c #302C2F", +"b c #7A7A7A", +"c c #C6AA92", +"d c #434043", +"e c #FECA96", +"f c #BA5A0A", +"g c #A64911", +"h c #FB8321", +"i c #E5A673", +"j c #AD621E", +"k c #505150", +"l c #7E6552", +"m c #A9A6A3", +"n c #F5B683", +"o c #843F05", +"p c #FAA23A", +"q c #9E5A26", +"r c #FAD6BA", +"s c #92765A", +"t c #974C0A", +"u c #FCFCFD", +"v c #F07616", +"w c #FEA847", +"x c #727272", +"y c #F5993F", +"z c #222026", +" ", +" ", +" ", +" ", +" ", +" >>> ", +" >>2b ", +" #x ]2b#x ", +" k;k 2]2x# ", +" 2+m ;dd ]>b#b ", +" ]mm>> ;ka >>#;> ", +" %>++0 ]] kkkd 22xx ", +" :+>m|> mx] ;k;a 2xx2 ", +" 0:bb': m2#> k;;d ]2b2> ", +" |u+m+u {m2b+ ;;#k 222>> ", +" %0''m0 n6++m> ;;#b> b]>>> ", +" m000%~mpyi6%%%+ ;k#2]]x]>> ", +" >:uu:%cww6%':'% d#bxb]]>] ", +" www!'u000|>>]k.4-h ", +" j-wwww>2b]2dj&h&&, ", +" q-w>#z;>]dv,,hhhhhhh ", +" t9<<]dd]c;8hhh,h,h^hh ", +" o-<>;ax>#8&,,hhhh^h, ", +" 4!ww>#dx>x8h,,&hh,^h ", +" t-ww6:u0u0uuuuuuuuu09j*..d;#b22>bkb>b8^hh,^,hhy ", +" t8,c'0b+{u0{:uuuuuuej..zdk;#xx22xb]jooot=&yy ", +" f8&v=v&-cmz%:u'k:uuuuuur=*.zdd;;###xsxf@41((4_^^ ", +" t[vvv&&&&&v-#.|0u'k0uuuuu0r=*.aaakk;;##x5g$4otf=^yp ", +" [&&&&&&&&&f5~|0'buuuuuu0%=4*..zdkkk;kdk)7t8hpypppp ", +" 3&&&&&&&&&v&&nr+uuuuuu|}=o***.zaaadd/q3vpwwpppwwy ", +" t=&&&&&&&&&&v^ru0uu|:'}_ft*.)..z1q8h^wwwpwwppppww ", +" j8&&&&&&&&&&^n||0:'683g*)))(j8,^py + * + * Copyright (C) 2002 Florian Schulze + * + * This file is part of Jump'n'Bump. + * + * Jump'n'Bump 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. + * + * Jump'n'Bump 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "globals.h" +#include +#ifndef _MSC_VER +#include +#endif +#include "SDL.h" + +#ifndef NO_SDL_MIXER +#include "SDL_mixer.h" + +static Mix_Music *current_music = (Mix_Music *) NULL; +#endif + +sfx_data sounds[NUM_SFX]; + +static int SAMPLECOUNT = 512; + +#define MAX_CHANNELS 32 + +typedef struct { + /* loop flag */ + int loop; + /* The channel step amount... */ + unsigned int step; + /* ... and a 0.16 bit remainder of last step. */ + unsigned int stepremainder; + unsigned int samplerate; + /* The channel data pointers, start and end. */ + signed short* data; + signed short* startdata; + signed short* enddata; + /* Hardware left and right channel volume lookup. */ + int leftvol; + int rightvol; +} channel_info_t; + +channel_info_t channelinfo[MAX_CHANNELS]; + +/* Sample rate in samples/second */ +int audio_rate = 44100; +int global_sfx_volume = 0; +/* +// This function loops all active (internal) sound +// channels, retrieves a given number of samples +// from the raw sound data, modifies it according +// to the current (internal) channel parameters, +// mixes the per channel samples into the given +// mixing buffer, and clamping it to the allowed +// range. +// +// This function currently supports only 16bit. +*/ + +static void stopchan(int i) +{ + if (channelinfo[i].data) { + memset(&channelinfo[i], 0, sizeof(channel_info_t)); + } +} + + +/* +// This function adds a sound to the +// list of currently active sounds, +// which is maintained as a given number +// (eight, usually) of internal channels. +// Returns a handle. +*/ +int addsfx(signed short *data, int len, int loop, int samplerate, int channel) +{ + stopchan(channel); + + /* We will handle the new SFX. */ + /* Set pointer to raw data. */ + channelinfo[channel].data = data; + channelinfo[channel].startdata = data; + + /* Set pointer to end of raw data. */ + channelinfo[channel].enddata = channelinfo[channel].data + len - 1; + channelinfo[channel].samplerate = samplerate; + + channelinfo[channel].loop = loop; + channelinfo[channel].stepremainder = 0; + + return channel; +} + + +static void updateSoundParams(int slot, int volume) +{ + int rightvol; + int leftvol; + + /* + // Set stepping + // MWM 2000-12-24: Calculates proportion of channel samplerate + // to global samplerate for mixing purposes. + // Patched to shift left *then* divide, to minimize roundoff errors + // as well as to use SAMPLERATE as defined above, not to assume 11025 Hz + */ + channelinfo[slot].step = ((channelinfo[slot].samplerate<<16)/audio_rate); + + leftvol = volume; + rightvol= volume; + + /* Sanity check, clamp volume. */ + if (rightvol < 0) + rightvol = 0; + if (rightvol > 127) + rightvol = 127; + + if (leftvol < 0) + leftvol = 0; + if (leftvol > 127) + leftvol = 127; + + channelinfo[slot].leftvol = leftvol; + channelinfo[slot].rightvol = rightvol; +} + + +void mix_sound(void *unused, Uint8 *stream, int len) +{ + /* Mix current sound data. */ + /* Data, from raw sound, for right and left. */ + register int sample; + register int dl; + register int dr; + + /* Pointers in audio stream, left, right, end. */ + signed short* leftout; + signed short* rightout; + signed short* leftend; + /* Step in stream, left and right, thus two. */ + int step; + + /* Mixing channel index. */ + int chan; + + /* Left and right channel */ + /* are in audio stream, alternating. */ + leftout = (signed short *)stream; + rightout = ((signed short *)stream)+1; + step = 2; + + /* Determine end, for left channel only */ + /* (right channel is implicit). */ + leftend = leftout + (len/4)*step; + + /* Mix sounds into the mixing buffer. */ + /* Loop over step*SAMPLECOUNT, */ + /* that is 512 values for two channels. */ + while (leftout != leftend) { + /* Reset left/right value. */ + dl = *leftout * 256; + dr = *rightout * 256; + + /* Love thy L2 chache - made this a loop. */ + /* Now more channels could be set at compile time */ + /* as well. Thus loop those channels. */ + for ( chan = 0; chan < MAX_CHANNELS; chan++ ) { + /* Check channel, if active. */ + if (channelinfo[chan].data) { + /* Get the raw data from the channel. */ + /* no filtering */ + /* sample = *channelinfo[chan].data; */ + /* linear filtering */ + sample = (int)(((int)channelinfo[chan].data[0] * (int)(0x10000 - channelinfo[chan].stepremainder)) + + ((int)channelinfo[chan].data[1] * (int)(channelinfo[chan].stepremainder))) >> 16; + + /* Add left and right part */ + /* for this channel (sound) */ + /* to the current data. */ + /* Adjust volume accordingly. */ + dl += sample * (channelinfo[chan].leftvol * global_sfx_volume) / 128; + dr += sample * (channelinfo[chan].rightvol * global_sfx_volume) / 128; + /* Increment index ??? */ + channelinfo[chan].stepremainder += channelinfo[chan].step; + /* MSB is next sample??? */ + channelinfo[chan].data += channelinfo[chan].stepremainder >> 16; + /* Limit to LSB??? */ + channelinfo[chan].stepremainder &= 0xffff; + + /* Check whether we are done. */ + if (channelinfo[chan].data >= channelinfo[chan].enddata) { + if (channelinfo[chan].loop) { + channelinfo[chan].data = channelinfo[chan].startdata; + } else { + stopchan(chan); + } + } + } + } + + /* Clamp to range. Left hardware channel. */ + /* Has been char instead of short. */ + /* if (dl > 127) *leftout = 127; */ + /* else if (dl < -128) *leftout = -128; */ + /* else *leftout = dl; */ + + dl = dl / 256; + dr = dr / 256; + + if (dl > SHRT_MAX) + *leftout = SHRT_MAX; + else if (dl < SHRT_MIN) + *leftout = SHRT_MIN; + else + *leftout = (signed short)dl; + + /* Same for right hardware channel. */ + if (dr > SHRT_MAX) + *rightout = SHRT_MAX; + else if (dr < SHRT_MIN) + *rightout = SHRT_MIN; + else + *rightout = (signed short)dr; + + /* Increment current pointers in stream */ + leftout += step; + rightout += step; + } +} + +/* misc handling */ + +char dj_init(void) +{ + Uint16 audio_format = MIX_DEFAULT_FORMAT; + int audio_channels = 2; + int audio_buffers = 4096; + + open_screen(); + + if (main_info.no_sound) + return 0; + + audio_buffers = SAMPLECOUNT*audio_rate/11025; + + memset(channelinfo, 0, sizeof(channelinfo)); + memset(sounds, 0, sizeof(sounds)); + +#ifndef NO_SDL_MIXER + if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers) < 0) { + fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError()); + main_info.no_sound = 1; + return 1; + } + + Mix_QuerySpec(&audio_rate, &audio_format, &audio_channels); + printf("Opened audio at %dHz %dbit %s, %d bytes audio buffer\n", audio_rate, (audio_format & 0xFF), (audio_channels > 1) ? "stereo" : "mono", audio_buffers); + + Mix_SetMusicCMD(getenv("MUSIC_CMD")); + + Mix_SetPostMix(mix_sound, NULL); +#else + main_info.no_sound = 1; + return 1; +#endif + + return 0; +} + +void dj_deinit(void) +{ + if (main_info.no_sound) + return; + +#ifndef NO_SDL_MIXER + Mix_HaltMusic(); + if (current_music) + Mix_FreeMusic(current_music); + current_music = NULL; + + Mix_CloseAudio(); +#endif + + SDL_Quit(); +} + +void dj_start(void) +{ +} + +void dj_stop(void) +{ +} + +char dj_autodetect_sd(void) +{ + return 0; +} + +char dj_set_stereo(char flag) +{ + return 0; +} + +void dj_set_auto_mix(char flag) +{ +} + +unsigned short dj_set_mixing_freq(unsigned short freq) +{ + return freq; +} + +void dj_set_dma_time(unsigned short time) +{ +} + +void dj_set_nosound(char flag) +{ +} + +/* mix handling */ + +void dj_mix(void) +{ +} + +/* sfx handling */ + +char dj_set_num_sfx_channels(char num_channels) +{ + return num_channels; +} + +void dj_set_sfx_volume(char volume) +{ + if (main_info.no_sound) + return; + + SDL_LockAudio(); + global_sfx_volume = volume*2; + SDL_UnlockAudio(); +} + +void dj_play_sfx(unsigned char sfx_num, unsigned short freq, char volume, char panning, unsigned short delay, char channel) +{ + int slot; + + if (main_info.music_no_sound || main_info.no_sound) + return; + + if (channel<0) { + for (slot=0; slot=MAX_CHANNELS) + return; + } else + slot = channel; + + SDL_LockAudio(); + addsfx((short *)sounds[sfx_num].buf, sounds[sfx_num].length, sounds[sfx_num].loop, freq, slot); + updateSoundParams(slot, volume*2); + SDL_UnlockAudio(); +} + +char dj_get_sfx_settings(unsigned char sfx_num, sfx_data *data) +{ + if (main_info.no_sound) + return 0; + + memcpy(data, &sounds[sfx_num], sizeof(sfx_data)); + return 0; +} + +char dj_set_sfx_settings(unsigned char sfx_num, sfx_data *data) +{ + if (main_info.no_sound) + return 0; + + memcpy(&sounds[sfx_num], data, sizeof(sfx_data)); + return 0; +} + +void dj_set_sfx_channel_volume(char channel_num, char volume) +{ + if (main_info.no_sound) + return; + + SDL_LockAudio(); + updateSoundParams(channel_num, volume*2); + SDL_UnlockAudio(); +} + +void dj_stop_sfx_channel(char channel_num) +{ + if (main_info.no_sound) + return; + + SDL_LockAudio(); + stopchan(channel_num); + SDL_UnlockAudio(); +} + +char dj_load_sfx(unsigned char * file_handle, char *filename, int file_length, char sfx_type, unsigned char sfx_num) +{ + unsigned int i; + unsigned char *src; + unsigned short *dest; + + if (main_info.no_sound) + return 0; + + sounds[sfx_num].buf = malloc(file_length); + + memcpy(sounds[sfx_num].buf, file_handle, file_length); + + sounds[sfx_num].length = file_length / 2; + src = sounds[sfx_num].buf; + dest = (unsigned short *)sounds[sfx_num].buf; + for (i=0; i