From ffca94d7fd59fd6a7ee0d58174e7415e59822317 Mon Sep 17 00:00:00 2001 From: Ansgar Burchardt Date: Mon, 8 Dec 2008 00:58:46 +0100 Subject: [PATCH] Import jumpnbump/1.50 Source: Debian Etch (http://packages.debian.org/etch/jumpnbump) --- AUTHORS | 62 + COPYING | 340 ++++ ChangeLog | 92 + LINKS | 8 + Makefile | 59 + PB/.DS_Store | Bin 0 -> 6148 bytes PB/English.lproj/InfoPlist.strings | Bin 0 -> 480 bytes PB/JumpNBump.pbproj/.DS_Store | Bin 0 -> 6148 bytes PB/JumpNBump.pbproj/ben.pbxuser | 1146 +++++++++++ PB/JumpNBump.pbproj/project.pbxproj | 671 +++++++ PB/SDLMain.h | 37 + PB/SDLMain.m | 223 +++ README | 62 + TODO | 2 + VisualC6/gobpack/gobpack.dsp | 100 + VisualC6/jumpnbump.dsp | 235 +++ VisualC6/jumpnbump.dsw | 71 + VisualC6/pack/pack.dsp | 102 + VisualC6/resource.h | 16 + VisualC6/ressource.rc | 72 + VisualC6/unpack/unpack.dsp | 102 + XF86Config-4 | 118 ++ config.h | 29 + data/Makefile | 27 + data/bump.mod | Bin 0 -> 71776 bytes data/calib.dat | Bin 0 -> 24 bytes data/death.smp | Bin 0 -> 5110 bytes data/fly.smp | Bin 0 -> 32376 bytes data/font.pcx | Bin 0 -> 12019 bytes data/font.txt | 650 ++++++ data/jump.mod | Bin 0 -> 50206 bytes data/jump.smp | Bin 0 -> 6552 bytes data/level.pcx | Bin 0 -> 36203 bytes data/levelmap.txt | 16 + data/mask.pcx | Bin 0 -> 5530 bytes data/menu.pcx | Bin 0 -> 37443 bytes data/menumask.pcx | Bin 0 -> 4608 bytes data/numbers.pcx | Bin 0 -> 7036 bytes data/numbers.txt | 82 + data/objects.pcx | Bin 0 -> 7243 bytes data/objects.txt | 642 ++++++ data/pack.bat | 6 + data/rabbit.pcx | Bin 0 -> 19583 bytes data/rabbit.txt | 578 ++++++ data/scores.mod | Bin 0 -> 68982 bytes data/splash.smp | Bin 0 -> 8404 bytes data/spring.smp | Bin 0 -> 7775 bytes dj.h | 135 ++ dos/gfx.S | 271 +++ dos/gfx.c | 473 +++++ dos/input.c | 275 +++ dos/interrpt.c | 147 ++ dos/libdj.a | Bin 0 -> 53048 bytes filter.c | 251 +++ filter.h | 34 + fireworks.c | 249 +++ globals.pre | 369 ++++ gob.txt | 52 + indent.txt | 1 + jnbmenu.pre | 228 +++ jumpnbump-kdialog | 52 + jumpnbump-xdialog | 53 + jumpnbump.6 | 134 ++ jumpnbump.fbcon | 4 + jumpnbump.html | 158 ++ jumpnbump.ico | Bin 0 -> 2238 bytes jumpnbump.svgalib | 4 + levelmaking/jumpnbump_levelmaking.htm | 1684 ++++++++++++++++ levelmaking/level.pcx | Bin 0 -> 12837 bytes levelmaking/making1.gif | Bin 0 -> 34638 bytes levelmaking/making2.gif | Bin 0 -> 1588 bytes levelmaking/making3.gif | Bin 0 -> 2997 bytes levelmaking/pack.gif | Bin 0 -> 3028 bytes main.c | 3539 +++++++++++++++++++++++++++++++++ menu.c | 637 ++++++ modify/Makefile | 21 + modify/gobpack.c | 421 ++++ modify/jnbpack.c | 192 ++ modify/jnbunpack.c | 102 + readme-win32.txt | 7 + readme.txt | 75 + sdl/Makefile | 16 + sdl/gfx.c | 868 ++++++++ sdl/input.c | 109 + sdl/interrpt.c | 462 +++++ sdl/jumpnbump128.xpm | 196 ++ sdl/jumpnbump32.xpm | 100 + sdl/jumpnbump64.xpm | 132 ++ sdl/sound.c | 568 ++++++ source.txt | 93 + 90 files changed, 17660 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 LINKS create mode 100644 Makefile create mode 100644 PB/.DS_Store create mode 100644 PB/English.lproj/InfoPlist.strings create mode 100644 PB/JumpNBump.pbproj/.DS_Store create mode 100644 PB/JumpNBump.pbproj/ben.pbxuser create mode 100644 PB/JumpNBump.pbproj/project.pbxproj create mode 100644 PB/SDLMain.h create mode 100644 PB/SDLMain.m create mode 100644 README create mode 100644 TODO create mode 100644 VisualC6/gobpack/gobpack.dsp create mode 100644 VisualC6/jumpnbump.dsp create mode 100644 VisualC6/jumpnbump.dsw create mode 100644 VisualC6/pack/pack.dsp create mode 100644 VisualC6/resource.h create mode 100644 VisualC6/ressource.rc create mode 100644 VisualC6/unpack/unpack.dsp create mode 100644 XF86Config-4 create mode 100644 config.h create mode 100644 data/Makefile create mode 100644 data/bump.mod create mode 100644 data/calib.dat create mode 100644 data/death.smp create mode 100644 data/fly.smp create mode 100644 data/font.pcx create mode 100644 data/font.txt create mode 100644 data/jump.mod create mode 100644 data/jump.smp create mode 100644 data/level.pcx create mode 100644 data/levelmap.txt create mode 100644 data/mask.pcx create mode 100644 data/menu.pcx create mode 100644 data/menumask.pcx create mode 100644 data/numbers.pcx create mode 100644 data/numbers.txt create mode 100644 data/objects.pcx create mode 100644 data/objects.txt create mode 100644 data/pack.bat create mode 100644 data/rabbit.pcx create mode 100644 data/rabbit.txt create mode 100644 data/scores.mod create mode 100644 data/splash.smp create mode 100644 data/spring.smp create mode 100644 dj.h create mode 100644 dos/gfx.S create mode 100644 dos/gfx.c create mode 100644 dos/input.c create mode 100644 dos/interrpt.c create mode 100644 dos/libdj.a create mode 100644 filter.c create mode 100644 filter.h create mode 100644 fireworks.c create mode 100644 globals.pre create mode 100644 gob.txt create mode 100644 indent.txt create mode 100644 jnbmenu.pre create mode 100755 jumpnbump-kdialog create mode 100755 jumpnbump-xdialog create mode 100644 jumpnbump.6 create mode 100755 jumpnbump.fbcon create mode 100644 jumpnbump.html create mode 100644 jumpnbump.ico create mode 100755 jumpnbump.svgalib create mode 100644 levelmaking/jumpnbump_levelmaking.htm create mode 100644 levelmaking/level.pcx create mode 100644 levelmaking/making1.gif create mode 100644 levelmaking/making2.gif create mode 100644 levelmaking/making3.gif create mode 100644 levelmaking/pack.gif create mode 100644 main.c create mode 100644 menu.c create mode 100644 modify/Makefile create mode 100644 modify/gobpack.c create mode 100644 modify/jnbpack.c create mode 100644 modify/jnbunpack.c create mode 100644 readme-win32.txt create mode 100644 readme.txt create mode 100644 sdl/Makefile create mode 100644 sdl/gfx.c create mode 100644 sdl/input.c create mode 100644 sdl/interrpt.c create mode 100644 sdl/jumpnbump128.xpm create mode 100644 sdl/jumpnbump32.xpm create mode 100644 sdl/jumpnbump64.xpm create mode 100644 sdl/sound.c create mode 100644 source.txt diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..aa878b4 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,62 @@ +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. + A few patches here and there. + +Ricardo Cruz + AI Players, level menu for X and KDE dialog. + +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. diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/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/ChangeLog b/ChangeLog new file mode 100644 index 0000000..204bada --- /dev/null +++ b/ChangeLog @@ -0,0 +1,92 @@ +16 Jun 2004 - 1.50 + - AI Bunnies + - Contributed level selectors for KDE and X + +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/LINKS b/LINKS new file mode 100644 index 0000000..4236096 --- /dev/null +++ b/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/Makefile b/Makefile new file mode 100644 index 0000000..cef00ca --- /dev/null +++ b/Makefile @@ -0,0 +1,59 @@ +SDL_CFLAGS = `sdl-config --cflags` +SDL_LIBS = `sdl-config --libs` +CFLAGS = -Wall -O2 -ffast-math -funroll-loops -Dstricmp=strcasecmp \ + -Dstrnicmp=strncasecmp -DUSE_SDL -DNDEBUG -I. $(SDL_CFLAGS) -DUSE_NET +LIBS = -lm $(SDL_LIBS) -lSDL_mixer -lSDL_net +SDL_TARGET = sdl.a +MODIFY_TARGET = gobpack jnbpack jnbunpack +OBJS = fireworks.o main.o menu.o filter.o +TARGET = jumpnbump +BINARIES = $(TARGET) jumpnbump.svgalib jumpnbump.fbcon $(MODIFY_TARGET) \ + jnbmenu.tcl +PREFIX ?= /usr/local + +.PHONY: data + +all: $(BINARIES) + +$(SDL_TARGET): globals.h + cd sdl && make + +$(MODIFY_TARGET): globals.h + cd modify && make + +$(TARGET): $(OBJS) $(SDL_TARGET) data globals.h + $(CC) -o $(TARGET) $(OBJS) $(LIBS) $(SDL_TARGET) + +$(OBJS): globals.h + +globals.h: globals.pre + sed -e "s#%%PREFIX%%#$(PREFIX)#g" < globals.pre > globals.h + +jnbmenu.tcl: jnbmenu.pre + sed -e "s#%%PREFIX%%#$(PREFIX)#g" < jnbmenu.pre > jnbmenu.tcl + +data: jnbpack + cd data && make + +clean: + cd sdl && make clean + cd modify && make clean + cd data && make clean + rm -f $(TARGET) *.o globals.h jnbmenu.tcl + +install: + mkdir -p $(PREFIX)/games/ + mkdir -p $(PREFIX)/share/jumpnbump/ + mkdir -p $(PREFIX)/share/man/man6/ + install -o root -g games -m 755 $(BINARIES) $(PREFIX)/games/ + install -o root -g games -m 644 data/jumpbump.dat \ + $(PREFIX)/share/jumpnbump/jumpbump.dat + install -o root -g root -m 644 jumpnbump.6 $(PREFIX)/share/man/man6/ + +uninstall: + cd $(PREFIX)/games && rm -f $(BINARIES) + rm -rf $(PREFIX)/share/jumpnbump + rm -f $(PREFIX)/share/man/man6/jumpnbump.6 + +doc: + rman jumpnbump.6 -f HTML >jumpnbump.html diff --git a/PB/.DS_Store b/PB/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..a9c40925c6dbf6a5fe5892f77d7a0658cd460628 GIT binary patch literal 6148 zcwX&SO=}ZD7=C8mwyCzV5d=L5d-5Xqakj`dqz6HzSP@U6Nx(+aCe#*slEEJQ3F6Uz zQ2#*$Zwemt;L)SUBs6N&?D)>k+pycL-4+7cIuE=&yOZacnatO_13(nkDwhBcKn{kT zNu(mjF$9NsoI*r(RIb+Q4;ygVyu!1@s?r^qtILEPs`{Y_C zPkFc%aXO|wjs+BP4L)Y6_69i`)Wh_4bPsRGyp!y`K4@(*=@44=WLL*hN*m8(4vUdv zI z*sx(EJ-|mHC5L0XY)lIai~ke)eDIkAW@%XP?+&vY^LWfYbHFSO3)VTzE_06AWA>Q? zW@(rYEy0%$!7U5Ep$L!JXATTwtNZoa_uh}6zxts{0yr`C^bGL%t&@Kyo&3#<>Y$?E z?~gpfFpT0bqSb1REZXh1>U27)+wH1euQwRGe-yMOj+mX{>HI(U=lj2fg~cI;aElAY x0tOd?A?RG|Q{3A&Ao(G{WiD%VDn1n}_n8A`Y4|UF2-y6;zp(j#Z*jo#|8Jm)#Wnx{ literal 0 HcwPel00001 diff --git a/PB/English.lproj/InfoPlist.strings b/PB/English.lproj/InfoPlist.strings new file mode 100644 index 0000000000000000000000000000000000000000..ae9592ab25a50fde39ff53698903f5b7788d7967 GIT binary patch literal 480 zcwVKDOACTP6ot>aUm-3ddbo`?3B3px1??@(qI{qg)Q_(|CkP6QAcpZ?&zw2u+_~P= zQeBp&O0|-&y|%h2Q~-9O<|;r^B~**L<~!zZP2W^z_=OIjJJ@H#s-szBxf-aiBkTZP zC=dOZYN^MzHQ_8q!!xY1v(>G*H`fNY9GAsQqB%%TpD6mG`96oG4#}MlUPJcbIpKc} s4LTPj<6TOXh&jraa@1xya2^>vd`3pg=k^ROpESOfCQ+5bBgqficN7*;N&o-= literal 0 HcwPel00001 diff --git a/PB/JumpNBump.pbproj/.DS_Store b/PB/JumpNBump.pbproj/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..12e20a1fde4bf62c34b3212882b1755b0402f303 GIT binary patch literal 6148 zcwX&Ty>HV%6n}PInid2mDyTvX7AzG5X$K^RsH907lZqx6$4p(CCI$i_vGSo(A&_?% zIxrx_N7)&=uy7URQv1DLiKnl<2yNmPD3e+~Lz%P1wXaC-Nzk7GrJ6{1niZ_e1 z04e~4z_XIu7$700eIom;L~~eBfCgL#8`c=&{l-9c)+c|+SKip5NIMj3|GXn`*%_5p z=LHQ>Keq;O{hgc@e0zc~zVfN#;Eb|{+xK(W-x^fmVORg3@VBXQwXjyMx)r&@L{KlZ zsn856tV15kP=Y%CirC`uO?0MeuER)hFa=_(0N-vkbU_HouHZjQvl7E) zW))wI%B;q0j9JIC67!RpRhSJit1_!G8)Me-EZejscKMJPGrzn@Dzh51F<>%1{u*HH zrDB%~4T#hmwNmB&+{8Fa6i#7p7(QYn%mL8?tMk%Um}ZoPXZj1PW%$l!3C&CzE;a`%t6=}pGu^2z4cA{ z;z?SEN_T;9(TB&E35-W0US_WwFy+Hji42sjXhig(-hfL!JaO0H`Dp>^+yY#N^AP*; zRSqw=;b+FewPA?QOej$m9ShPo<;v*@2i|13Ud z-Dd}N3v~w-^BIU6h#QC-h#QC-h!f-`n4e&Ng86fQg`EHu + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + JumpNBump + CFBundleGetInfoString + JumpNBump 1.2 + CFBundleIconFile + + CFBundleIdentifier + net.sf.jumpnbump + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + JumpNBump + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.2 + CFBundleSignature + jpnb + CFBundleVersion + 1.2 + NSMainNibFile + SDLMain.nib + NSPrincipalClass + NSApplication + + +"; + shouldUseHeadermap = 1; + }; + 29B97327FDCFA39411CA2CEA = { + buildActionMask = 2147483647; + files = ( + F5C435B3026C8997012A168D, + F5C435B4026C8997012A168D, + F5C435B5026C8997012A168D, + ); + isa = PBXHeadersBuildPhase; + }; + 29B97328FDCFA39411CA2CEA = { + buildActionMask = 2147483647; + files = ( + 089C165EFE840E0CC02AAC07, + F57C7C610279FFCF012A168D, + ); + isa = PBXResourcesBuildPhase; + }; + 29B9732BFDCFA39411CA2CEA = { + buildActionMask = 2147483647; + files = ( + F5A47AA301A0483001D3D55B, + F5C435B6026C8997012A168D, + F5C435B7026C8997012A168D, + F59A9B8B026DCE30012A168D, + F556CBA40271DD9A012A168D, + F556CBA50271DD9A012A168D, + F556CBA60271DD9A012A168D, + F556CBA70271DD9A012A168D, + ); + isa = PBXSourcesBuildPhase; + }; + 29B9732DFDCFA39411CA2CEA = { + buildActionMask = 2147483647; + files = ( + 1058C7A3FEA54F0111CA2CBB, + F5CA6B0F026B50C2012A168D, + ); + isa = PBXFrameworksBuildPhase; + }; +//290 +//291 +//292 +//293 +//294 +//4A0 +//4A1 +//4A2 +//4A3 +//4A4 + 4A9504CCFFE6A4B311CA0CBA = { + buildRules = ( + ); + buildSettings = { + COPY_PHASE_STRIP = NO; + OPTIMIZATION_CFLAGS = "-O0"; + }; + isa = PBXBuildStyle; + name = Development; + }; + 4A9504CDFFE6A4B311CA0CBA = { + buildRules = ( + ); + buildSettings = { + COPY_PHASE_STRIP = YES; + }; + isa = PBXBuildStyle; + name = Deployment; + }; +//4A0 +//4A1 +//4A2 +//4A3 +//4A4 +//F50 +//F51 +//F52 +//F53 +//F54 + F556CBA00271DD9A012A168D = { + isa = PBXFileReference; + name = gfx.c; + path = /Users/ben/Desktop/jumpnbumpc/jumpnbump/sdl/gfx.c; + refType = 0; + }; + F556CBA10271DD9A012A168D = { + isa = PBXFileReference; + name = input.c; + path = /Users/ben/Desktop/jumpnbumpc/jumpnbump/sdl/input.c; + refType = 0; + }; + F556CBA20271DD9A012A168D = { + isa = PBXFileReference; + name = interrpt.c; + path = /Users/ben/Desktop/jumpnbumpc/jumpnbump/sdl/interrpt.c; + refType = 0; + }; + F556CBA30271DD9A012A168D = { + isa = PBXFileReference; + name = sound.c; + path = /Users/ben/Desktop/jumpnbumpc/jumpnbump/sdl/sound.c; + refType = 0; + }; + F556CBA40271DD9A012A168D = { + fileRef = F556CBA00271DD9A012A168D; + isa = PBXBuildFile; + settings = { + }; + }; + F556CBA50271DD9A012A168D = { + fileRef = F556CBA10271DD9A012A168D; + isa = PBXBuildFile; + settings = { + }; + }; + F556CBA60271DD9A012A168D = { + fileRef = F556CBA20271DD9A012A168D; + isa = PBXBuildFile; + settings = { + }; + }; + F556CBA70271DD9A012A168D = { + fileRef = F556CBA30271DD9A012A168D; + isa = PBXBuildFile; + settings = { + }; + }; + F57C7C3F0279FEDD012A168D = { + buildActionMask = 2147483647; + files = ( + ); + generatedFileNames = ( + ); + isa = PBXShellScriptBuildPhase; + neededFileNames = ( + ); + shellPath = /bin/sh; + shellScript = "chdir ../data\n${SYMROOT}/pack -o jumpbump.dat bump.mod calib.dat death.smp fly.smp font.gob jump.mod jump.smp levelmap.txt level.pcx mask.pcx menu.pcx menumask.pcx numbers.gob objects.gob rabbit.gob scores.mod splash.smp spring.smp\nmkdir ${SYMROOT}/JumpNBump.app/Contents/Resources/data/\ncp jumpbump.dat ${SYMROOT}/JumpNBump.app/Contents/Resources/data/jumpbump.dat"; + }; + F57C7C600279FFCF012A168D = { + isa = PBXFileReference; + name = SDLMain.nib; + path = /Users/ben/Library/Frameworks/SDL.framework/Versions/A/Resources/SDLMain.nib; + refType = 0; + }; + F57C7C610279FFCF012A168D = { + fileRef = F57C7C600279FFCF012A168D; + isa = PBXBuildFile; + settings = { + }; + }; + F59A9B8B026DCE30012A168D = { + fileRef = F5C435B2026C8997012A168D; + isa = PBXBuildFile; + settings = { + }; + }; + F5A47A9E01A0483001D3D55B = { + isa = PBXFileReference; + path = SDLMain.m; + refType = 2; + }; + F5A47AA301A0483001D3D55B = { + fileRef = F5A47A9E01A0483001D3D55B; + isa = PBXBuildFile; + settings = { + }; + }; + F5C435A6026C8394012A168D = { + children = ( + F5CA6B0A026B5089012A168D, + F5C435B9026C89A2012A168D, + ); + isa = PBXGroup; + name = modify; + refType = 4; + }; + F5C435A7026C8394012A168D = { + isa = PBXTargetDependency; + target = F5CA6B1B026B5376012A168D; + }; + F5C435A8026C8394012A168D = { + isa = PBXTargetDependency; + target = F5CA6B13026B535C012A168D; + }; + F5C435AD026C8997012A168D = { + isa = PBXFileReference; + name = menu.c; + path = /Users/ben/Desktop/jumpnbumpc/jumpnbump/menu.c; + refType = 0; + }; + F5C435AE026C8997012A168D = { + isa = PBXFileReference; + name = config.h; + path = /Users/ben/Desktop/jumpnbumpc/jumpnbump/config.h; + refType = 0; + }; + F5C435AF026C8997012A168D = { + isa = PBXFileReference; + name = dj.h; + path = /Users/ben/Desktop/jumpnbumpc/jumpnbump/dj.h; + refType = 0; + }; + F5C435B0026C8997012A168D = { + isa = PBXFileReference; + name = fireworks.c; + path = /Users/ben/Desktop/jumpnbumpc/jumpnbump/fireworks.c; + refType = 0; + }; + F5C435B1026C8997012A168D = { + isa = PBXFileReference; + name = globals.h; + path = /Users/ben/Desktop/jumpnbumpc/jumpnbump/globals.h; + refType = 0; + }; + F5C435B2026C8997012A168D = { + isa = PBXFileReference; + name = main.c; + path = /Users/ben/Desktop/jumpnbumpc/jumpnbump/main.c; + refType = 0; + }; + F5C435B3026C8997012A168D = { + fileRef = F5C435AE026C8997012A168D; + isa = PBXBuildFile; + settings = { + }; + }; + F5C435B4026C8997012A168D = { + fileRef = F5C435AF026C8997012A168D; + isa = PBXBuildFile; + settings = { + }; + }; + F5C435B5026C8997012A168D = { + fileRef = F5C435B1026C8997012A168D; + isa = PBXBuildFile; + settings = { + }; + }; + F5C435B6026C8997012A168D = { + fileRef = F5C435AD026C8997012A168D; + isa = PBXBuildFile; + settings = { + }; + }; + F5C435B7026C8997012A168D = { + fileRef = F5C435B0026C8997012A168D; + isa = PBXBuildFile; + settings = { + }; + }; + F5C435B9026C89A2012A168D = { + isa = PBXFileReference; + name = unpack.c; + path = /Users/ben/Desktop/jumpnbumpc/jumpnbump/modify/unpack.c; + refType = 0; + }; + F5C435BA026C89A2012A168D = { + fileRef = F5C435B9026C89A2012A168D; + isa = PBXBuildFile; + settings = { + }; + }; + F5CA6AF5026B505E012A168D = { + children = ( + F556CBA00271DD9A012A168D, + F556CBA10271DD9A012A168D, + F556CBA20271DD9A012A168D, + F556CBA30271DD9A012A168D, + ); + isa = PBXGroup; + name = sdl; + refType = 4; + }; + F5CA6B0A026B5089012A168D = { + isa = PBXFileReference; + name = pack.c; + path = ../modify/pack.c; + refType = 2; + }; + F5CA6B0E026B50C2012A168D = { + isa = PBXFrameworkReference; + name = SDL_mixer.framework; + path = /Users/ben/Library/Frameworks/SDL_mixer.framework; + refType = 0; + }; + F5CA6B0F026B50C2012A168D = { + fileRef = F5CA6B0E026B50C2012A168D; + isa = PBXBuildFile; + settings = { + }; + }; + F5CA6B12026B535C012A168D = { + isa = PBXExecutableFileReference; + path = unpack; + refType = 3; + }; + F5CA6B13026B535C012A168D = { + buildPhases = ( + F5CA6B14026B535C012A168D, + F5CA6B15026B535C012A168D, + F5CA6B17026B535C012A168D, + F5CA6B18026B535C012A168D, + ); + buildSettings = { + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = unpack; + REZ_EXECUTABLE = YES; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; + }; + dependencies = ( + ); + isa = PBXToolTarget; + name = unpack; + productInstallPath = /usr/local/bin; + productName = unpack; + productReference = F5CA6B12026B535C012A168D; + shouldUseHeadermap = 0; + }; + F5CA6B14026B535C012A168D = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXHeadersBuildPhase; + }; + F5CA6B15026B535C012A168D = { + buildActionMask = 2147483647; + files = ( + F5C435BA026C89A2012A168D, + ); + isa = PBXSourcesBuildPhase; + }; + F5CA6B17026B535C012A168D = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXFrameworksBuildPhase; + }; + F5CA6B18026B535C012A168D = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXRezBuildPhase; + }; + F5CA6B1A026B5376012A168D = { + isa = PBXExecutableFileReference; + path = pack; + refType = 3; + }; + F5CA6B1B026B5376012A168D = { + buildPhases = ( + F5CA6B1C026B5376012A168D, + F5CA6B1D026B5376012A168D, + F5CA6B1F026B5376012A168D, + F5CA6B20026B5376012A168D, + ); + buildSettings = { + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = pack; + REZ_EXECUTABLE = YES; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; + }; + dependencies = ( + ); + isa = PBXToolTarget; + name = pack; + productInstallPath = /usr/local/bin; + productName = pack; + productReference = F5CA6B1A026B5376012A168D; + shouldUseHeadermap = 0; + }; + F5CA6B1C026B5376012A168D = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXHeadersBuildPhase; + }; + F5CA6B1D026B5376012A168D = { + buildActionMask = 2147483647; + files = ( + F5CA6B1E026B5376012A168D, + ); + isa = PBXSourcesBuildPhase; + }; + F5CA6B1E026B5376012A168D = { + fileRef = F5CA6B0A026B5089012A168D; + isa = PBXBuildFile; + settings = { + }; + }; + F5CA6B1F026B5376012A168D = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXFrameworksBuildPhase; + }; + F5CA6B20026B5376012A168D = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXRezBuildPhase; + }; + }; + rootObject = 29B97313FDCFA39411CA2CEA; +} diff --git a/PB/SDLMain.h b/PB/SDLMain.h new file mode 100644 index 0000000..3b33d77 --- /dev/null +++ b/PB/SDLMain.h @@ -0,0 +1,37 @@ +/* + * SDLMain.m + * 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 + */ + + +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser + Non-NIB-Code & other changes: Max Horn + + Feel free to customize this file to suit your needs +*/ + +#import + +@interface SDLMain : NSObject +@end diff --git a/PB/SDLMain.m b/PB/SDLMain.m new file mode 100644 index 0000000..a8952a1 --- /dev/null +++ b/PB/SDLMain.m @@ -0,0 +1,223 @@ +/* + * SDLMain.m + * 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 + */ + +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + + These files turn an SDL app into a double-clickable Cocoa app on mac os X. + + Initial Version: Darrell Walisser + Non-NIB-Code & other changes: Max Horn + + Feel free to customize this file to suit your needs +*/ + +#import "SDL.h" + +/* SDLMain.h */ +#import + +@interface SDLMain : NSObject +@end +/* SDLMain.h */ + +#import /* for MAXPATHLEN */ +#import + + +static int gArgc; +static char **gArgv; +static BOOL gFinderLaunch; + +/* A helper category for NSString */ +@interface NSString (ReplaceSubString) +- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; +@end + +@interface SDLApplication : NSApplication +@end + +@implementation SDLApplication +/* Invoked from the Quit menu item */ +- (void)terminate:(id)sender +{ + /* Post a SDL_QUIT event */ + SDL_Event event; + event.type = SDL_QUIT; + SDL_PushEvent(&event); +} +@end + + +/* The main class of the application, the application's delegate */ +@implementation SDLMain +- (void)quit:(id)sender +{ + /* Post a SDL_QUIT event */ + SDL_Event event; + event.type = SDL_QUIT; + SDL_PushEvent(&event); + + // uMenu::quickexit=true; +} +//this changes the current working directory to the resource folder of +//the .app bundle in Mac OS X +void MacOSX_SetCWD(char **argv) { + char buffer[300]; + int count = 2, i; + strcpy(buffer, argv[0]); + + if ( !strstr( buffer, ".app") ) { + //it's not a .app bundle + return; + } + + for (i = strlen(buffer); i > 0 && count > 0; i--) { + if (buffer[i] == '/') + count--; + } + if (i == 0) + return; + i+=2; + buffer[i] = 0; + strcat( buffer, "Resources"); + printf(buffer); + chdir( buffer ); +} + + +/* Fix menu to contain the real app name instead of "SDL App" */ +- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName +{ + NSRange aRange; + NSEnumerator *enumerator; + NSMenuItem *menuItem; + + aRange = [[aMenu title] rangeOfString:@"SDL App"]; + if (aRange.length != 0) + [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; + + enumerator = [[aMenu itemArray] objectEnumerator]; + while ((menuItem = [enumerator nextObject])) + { + aRange = [[menuItem title] rangeOfString:@"SDL App"]; + if (aRange.length != 0) + [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; + if ([menuItem hasSubmenu]) + [self fixMenu:[menuItem submenu] withAppName:appName]; + } + [ aMenu sizeToFit ]; +} + +/* Called when the internal event loop has just started running */ +- (void) applicationDidFinishLaunching: (NSNotification *) note +{ + int status; + + /* Set the main menu to contain the real app name instead of "SDL App" */ + [self fixMenu:[NSApp mainMenu] withAppName:[[NSProcessInfo processInfo] processName]]; + + /* Hand off to main application code */ + status = SDL_main (gArgc, gArgv); + + /* We're done, thank you for playing */ + exit(status); +} +@end + + +@implementation NSString (ReplaceSubString) + +- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString +{ + unsigned int bufferSize; + unsigned int selfLen = [self length]; + unsigned int aStringLen = [aString length]; + unichar *buffer; + NSRange localRange; + NSString *result; + + bufferSize = selfLen + aStringLen - aRange.length; + buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); + + /* Get first part into buffer */ + localRange.location = 0; + localRange.length = aRange.location; + [self getCharacters:buffer range:localRange]; + + /* Get middle part into buffer */ + localRange.location = 0; + localRange.length = aStringLen; + [aString getCharacters:(buffer+aRange.location) range:localRange]; + + /* Get last part into buffer */ + localRange.location = aRange.location + aRange.length; + localRange.length = selfLen - localRange.location; + [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; + + /* Build output string */ + result = [NSString stringWithCharacters:buffer length:bufferSize]; + + NSDeallocateMemoryPages(buffer, bufferSize); + + return result; +} + +@end + + + +#ifdef main +# undef main +#endif + + +/* Main entry point to executable - should *not* be SDL_main! */ +int main (int argc, char **argv) +{ + + /* Copy the arguments into a global variable */ + int i; + + /* This is passed if we are launched by double-clicking */ + if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { + gArgc = 1; + gFinderLaunch = YES; + } else { + gArgc = argc; + gFinderLaunch = NO; + } + gArgv = (char**) malloc (sizeof(*gArgv) * (gArgc+1)); + assert (gArgv != NULL); + for (i = 0; i < gArgc; i++) + gArgv[i] = argv[i]; + gArgv[i] = NULL; + + MacOSX_SetCWD(gArgv); + + [SDLApplication poseAsClass:[NSApplication class]]; + NSApplicationMain (argc, argv); + + return 0; +} diff --git a/README b/README new file mode 100644 index 0000000..c19723d --- /dev/null +++ b/README @@ -0,0 +1,62 @@ +Jump n Bump + +This is a game for the whole family. You are cute fluffy little bunnies +and hop on the other bunnies' heads. + +At the beginning you are in the menu, where you have to jump +over the tree trunk if you want to play and walk right. +Then you'll enter the arena. The aim is to jump on the +other bunnies' heads... + +a,w,d to steer Dott +arrows to steer Jiffy +j,i,l to steer Fizz +4,8,6 to steer Mijji (on the numeric pad) + +Thanks to sabrewulf (chuck mason) in irc.linux.com #keen +who did port this wonderful game! find him, longislandman +and me (tarzeau) on irc.linux.com +Thanks also to longisland for working on network code +and timecop for the pack/unpacker +Thanks to florian for adding scale mode, fixing the sound +bug and having alot of patience and maintaining everything. +Thanks to ben for making patches to run it on mac os x. +Thanks to ivo for doing debian packages. + +f10 change between windowed/fullscreen mode +(see the XF86Config-4, copy n paste the modeline 400x256 +then add the mode "400x256" to whatever bpp you have by default, restart x) +example: add following line in Section "Monitor" of your +/etc/X11/XF86Config (or XF86Config-4) +Modeline "400x256" 22.00 400 416 480 504 256 259 262 269 doublescan +then in Section "Screen" if your DefaultDepth is 24 do be sure you have +something like: +Modes "1024x768" "640x480" "512x384" "400x256" "320x240" +esc/f12 exit + +For compilation you will need: +do following on a debian gnu/linux system (www.debian.org) +apt-get install libsdl-dev libsdl-mixer-dev +sdl libraries are needed, you might find it at www.libsdl.org + +You can find more levels at http://www.jumpbump.mine.nu/cgi-bin/jb.sh +which you can start with: jumpnbump -dat levelname.dat +there's a screensaver mode as well: +jumpnbump -fireworks -fullscreen + +Network play works like this, oh well here's an example +Player 1: jumpnbump -port 7777 -net 0 ip_or_hostname_of_player2 port_of_player2 +Player 2: jumpnbump -port 7777 -net 1 ip_or_hostname_of_player1 port_of_player1 +just take port 7777 for all ports and hope it's open and you aren't +firewalled (it's all udp!) +You can add -net 3 and -net 4 for 3rd and 4th player, and be sure. +All the players use the same -dat level.dat +(the scoreboards is different on each player and strange things like +that, but longislandman is working on it (isn't it? longislandman? you alive?)) + +You can find the original dos game (which runs in dos/win9x (dosextender!)) +at http://www.brainchilddesign.com/games/jumpnbump/index.html + +If you like the game or have any ideas don't hesitate to contact me +gurkan@linuks.mine.nu + diff --git a/TODO b/TODO new file mode 100644 index 0000000..fe8f787 --- /dev/null +++ b/TODO @@ -0,0 +1,2 @@ +- fix network code +- port for dreamcast diff --git a/VisualC6/gobpack/gobpack.dsp b/VisualC6/gobpack/gobpack.dsp new file mode 100644 index 0000000..296c1ee --- /dev/null +++ b/VisualC6/gobpack/gobpack.dsp @@ -0,0 +1,100 @@ +# Microsoft Developer Studio Project File - Name="gobpack" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=gobpack - Win32 Debug +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "gobpack.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "gobpack.mak" CFG="gobpack - Win32 Debug" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "gobpack - Win32 Release" (basierend auf "Win32 (x86) Console Application") +!MESSAGE "gobpack - Win32 Debug" (basierend auf "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "gobpack - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "gobpack - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "gobpack - Win32 Release" +# Name "gobpack - Win32 Debug" +# Begin Group "Quellcodedateien" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\modify\gobpack.c +# End Source File +# End Group +# Begin Group "Header-Dateien" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Ressourcendateien" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/VisualC6/jumpnbump.dsp b/VisualC6/jumpnbump.dsp new file mode 100644 index 0000000..50efec3 --- /dev/null +++ b/VisualC6/jumpnbump.dsp @@ -0,0 +1,235 @@ +# Microsoft Developer Studio Project File - Name="jumpnbump" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=jumpnbump - Win32 Debug +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "jumpnbump.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "jumpnbump.mak" CFG="jumpnbump - Win32 Debug" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "jumpnbump - Win32 Release" (basierend auf "Win32 (x86) Application") +!MESSAGE "jumpnbump - Win32 Debug" (basierend auf "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "jumpnbump - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "USE_SDL" /D "USE_NET" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib SDLmain.lib SDL.lib SDL_mixer.lib SDL_net.lib /nologo /subsystem:windows /profile /machine:I386 +# SUBTRACT LINK32 /debug +# Begin Custom Build +ProjDir=. +InputPath=.\Release\jumpnbump.exe +SOURCE="$(InputPath)" + +BuildCmds= \ + call "$(ProjDir)\..\data\pack.bat" "$(ProjDir)\..\data" "..\VisualC6\gobpack\Release\gobpack.exe" "..\VisualC6\pack\Release\jnbpack.exe" + +"$(ProjDir)\..\data\font.gob" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(ProjDir)\..\data\rabbit.gob" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(ProjDir)\..\data\numbers.gob" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(ProjDir)\..\data\objects.gob" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(ProjDir)\..\data\jumpbump.dat" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "jumpnbump - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "USE_SDL" /D "USE_NET" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib SDLmain.lib SDL.lib SDL_mixer.lib SDL_net.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# Begin Custom Build +ProjDir=. +InputPath=.\Debug\jumpnbump.exe +SOURCE="$(InputPath)" + +BuildCmds= \ + call "$(ProjDir)\..\data\pack.bat" "$(ProjDir)\..\data" "..\VisualC6\gobpack\Debug\gobpack.exe" "..\VisualC6\pack\Debug\jnbpack.exe" + +"$(ProjDir)\..\data\font.gob" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(ProjDir)\..\data\rabbit.gob" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(ProjDir)\..\data\numbers.gob" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(ProjDir)\..\data\objects.gob" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(ProjDir)\..\data\jumpbump.dat" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# Begin Target + +# Name "jumpnbump - Win32 Release" +# Name "jumpnbump - Win32 Debug" +# Begin Group "Quellcodedateien" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\filter.c +# End Source File +# Begin Source File + +SOURCE=..\fireworks.c +# End Source File +# Begin Source File + +SOURCE=..\sdl\gfx.c +# End Source File +# Begin Source File + +SOURCE=..\sdl\input.c +# End Source File +# Begin Source File + +SOURCE=..\sdl\interrpt.c +# End Source File +# Begin Source File + +SOURCE=..\main.c +# End Source File +# Begin Source File + +SOURCE=..\menu.c +# End Source File +# Begin Source File + +SOURCE=..\sdl\sound.c +# End Source File +# End Group +# Begin Group "Header-Dateien" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\config.h +# End Source File +# Begin Source File + +SOURCE=..\dj.h +# End Source File +# Begin Source File + +SOURCE=..\filter.h +# End Source File +# Begin Source File + +SOURCE=..\globals.pre + +!IF "$(CFG)" == "jumpnbump - Win32 Release" + +# Begin Custom Build +ProjDir=. +InputPath=..\globals.pre + +"$(ProjDir)\..\globals.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + copy "$(ProjDir)\..\globals.pre" "$(ProjDir)\..\globals.h" + +# End Custom Build + +!ELSEIF "$(CFG)" == "jumpnbump - Win32 Debug" + +# Begin Custom Build +ProjDir=. +InputPath=..\globals.pre + +"$(ProjDir)\..\globals.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + copy "$(ProjDir)\..\globals.pre" "$(ProjDir)\..\globals.h" + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# End Group +# Begin Group "Ressourcendateien" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=..\jumpnbump.ico +# End Source File +# Begin Source File + +SOURCE=.\ressource.rc +# End Source File +# End Group +# End Target +# End Project diff --git a/VisualC6/jumpnbump.dsw b/VisualC6/jumpnbump.dsw new file mode 100644 index 0000000..71c28fc --- /dev/null +++ b/VisualC6/jumpnbump.dsw @@ -0,0 +1,71 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN! + +############################################################################### + +Project: "gobpack"=.\gobpack\gobpack.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "jumpnbump"=.\jumpnbump.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name pack + End Project Dependency + Begin Project Dependency + Project_Dep_Name gobpack + End Project Dependency +}}} + +############################################################################### + +Project: "pack"=.\pack\pack.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "unpack"=.\unpack\unpack.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/VisualC6/pack/pack.dsp b/VisualC6/pack/pack.dsp new file mode 100644 index 0000000..46ada16 --- /dev/null +++ b/VisualC6/pack/pack.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="pack" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=pack - Win32 Debug +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "pack.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "pack.mak" CFG="pack - Win32 Debug" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "pack - Win32 Release" (basierend auf "Win32 (x86) Console Application") +!MESSAGE "pack - Win32 Debug" (basierend auf "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "pack - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/jnbpack.exe" + +!ELSEIF "$(CFG)" == "pack - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/jnbpack.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "pack - Win32 Release" +# Name "pack - Win32 Debug" +# Begin Group "Quellcodedateien" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\modify\jnbpack.c +# End Source File +# End Group +# Begin Group "Header-Dateien" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Ressourcendateien" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/VisualC6/resource.h b/VisualC6/resource.h new file mode 100644 index 0000000..88ce220 --- /dev/null +++ b/VisualC6/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by ressource.rc +// +#define IDI_ICON1 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/VisualC6/ressource.rc b/VisualC6/ressource.rc new file mode 100644 index 0000000..af470c3 --- /dev/null +++ b/VisualC6/ressource.rc @@ -0,0 +1,72 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON DISCARDABLE "../jumpnbump.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/VisualC6/unpack/unpack.dsp b/VisualC6/unpack/unpack.dsp new file mode 100644 index 0000000..57684a7 --- /dev/null +++ b/VisualC6/unpack/unpack.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="unpack" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=unpack - Win32 Debug +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "unpack.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "unpack.mak" CFG="unpack - Win32 Debug" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "unpack - Win32 Release" (basierend auf "Win32 (x86) Console Application") +!MESSAGE "unpack - Win32 Debug" (basierend auf "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "unpack - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/jnbunpack.exe" + +!ELSEIF "$(CFG)" == "unpack - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/jnbunpack.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "unpack - Win32 Release" +# Name "unpack - Win32 Debug" +# Begin Group "Quellcodedateien" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\modify\jnbunpack.c +# End Source File +# End Group +# Begin Group "Header-Dateien" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Ressourcendateien" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/XF86Config-4 b/XF86Config-4 new file mode 100644 index 0000000..561bb31 --- /dev/null +++ b/XF86Config-4 @@ -0,0 +1,118 @@ +# XF86Config-4 (XFree86 server configuration file) generated by Dexconf, the +# Debian X Configuration tool, using values from the debconf database. +# +# Edit this file with caution, and see the XF86Config manual page. +# (Type "man XF86Config" at the shell prompt.) + +Section "Files" + FontPath "unix/:7100" # local font server + # if the local font server has problems, we can fall back on these + FontPath "/usr/lib/X11/fonts/misc" + FontPath "/usr/lib/X11/fonts/cyrillic" + FontPath "/usr/lib/X11/fonts/100dpi/:unscaled" + FontPath "/usr/lib/X11/fonts/75dpi/:unscaled" + FontPath "/usr/lib/X11/fonts/Type1" + FontPath "/usr/lib/X11/fonts/Speedo" + FontPath "/usr/lib/X11/fonts/100dpi" + FontPath "/usr/lib/X11/fonts/75dpi" +EndSection + +Section "ServerFlags" +EndSection + +Section "Module" + Load "ddc" + Load "GLcore" + Load "dbe" + Load "dri" + Load "extmod" + Load "glx" + Load "pex5" + Load "record" + Load "xie" + Load "bitmap" + Load "freetype" + Load "speedo" + Load "type1" + Load "vbe" + Load "int10" +EndSection + +Section "InputDevice" + Identifier "Generic Keyboard" + Driver "keyboard" + Option "CoreKeyboard" + Option "XkbRules" "xfree86" + Option "XkbModel" "pc105" + Option "XkbLayout" "de_CH" +EndSection + +Section "InputDevice" + Identifier "Generic Mouse" + Driver "mouse" + Option "CorePointer" + Option "Device" "/dev/ttyS0" + Option "Protocol" "Microsoft" +EndSection + +Section "Device" + Identifier "Generic Video Card" + Driver "nvidia" +EndSection + +Section "Monitor" + Identifier "Generic Monitor" + HorizSync 28-57 + VertRefresh 43-90 + Option "DPMS" + #Modeline "320x240" 15.75 320 336 384 400 240 244 246 262 doublescan + Modeline "320x240" 12.588 320 336 384 400 240 245 246 262 doublescan + Modeline "400x256" 22.00 400 416 480 504 256 259 262 269 doublescan + Modeline "512x384" 22.00 512 528 592 640 384 385 388 404 -hsync -vsync + #Modeline "320x240" 15.750 320 336 384 400 240 244 246 262 doublescan +EndSection + +Section "Screen" + Identifier "Default Screen" + Device "Generic Video Card" + Monitor "Generic Monitor" + DefaultDepth 24 + SubSection "Display" + Depth 1 + Modes "1152x864" "1024x768" "640x480" "320x240" + EndSubSection + SubSection "Display" + Depth 4 + Modes "1152x864" "1024x768" "640x480" "320x240" + EndSubSection + SubSection "Display" + Depth 8 + Modes "1152x864" "1024x768" "640x480" "320x240" + EndSubSection + SubSection "Display" + Depth 15 + Modes "1152x864" "1024x768" "640x480" "320x240" + EndSubSection + SubSection "Display" + Depth 16 + Modes "1152x864" "1024x768" "640x480" "320x240" + EndSubSection + SubSection "Display" + Depth 24 + Modes "1024x768" "640x480" "512x384" "400x256" "320x240" +#"1280x1024" "1152x864" + EndSubSection +EndSection + +Section "ServerLayout" + Identifier "Default Layout" + Screen "Default Screen" + InputDevice "Generic Keyboard" + InputDevice "Generic Mouse" +EndSection + +Section "DRI" + Mode 0666 +EndSection + +# end of XF86Config diff --git a/config.h b/config.h new file mode 100644 index 0000000..b4914b5 --- /dev/null +++ b/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/data/Makefile b/data/Makefile new file mode 100644 index 0000000..de362fe --- /dev/null +++ b/data/Makefile @@ -0,0 +1,27 @@ +GOBS = numbers.gob objects.gob rabbit.gob +DATAFILES = bump.mod calib.dat death.smp fly.smp font.gob jump.mod \ + jump.smp levelmap.txt level.pcx mask.pcx menu.pcx \ + menumask.pcx $(GOBS) scores.mod splash.smp spring.smp + +all: jumpbump.dat + +font.gob: + ../gobpack font + +rabbit.gob: + ../gobpack rabbit + +numbers.gob: + ../gobpack numbers + +objects.gob: + ../gobpack objects + +jumpbump.dat: $(DATAFILES) ../jnbpack + ../jnbpack -o jumpbump.dat $(DATAFILES) + +../jnbpack: + cd ../modify && make + +clean: + rm -f jumpbump.dat $(GOBS) diff --git a/data/bump.mod b/data/bump.mod new file mode 100644 index 0000000000000000000000000000000000000000..286847de90d432435f0e2ae61154618b40bd79e5 GIT binary patch literal 71776 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 literal 0 HcwPel00001 diff --git a/data/calib.dat b/data/calib.dat new file mode 100644 index 0000000000000000000000000000000000000000..1934f520bfc1150fe90fe5f1d8b37aef0010a38f GIT binary patch literal 24 ZcwS>;U|_fi#GXtH44gnZ7l`$MYycWO0m%RW literal 0 HcwPel00001 diff --git a/data/death.smp b/data/death.smp new file mode 100644 index 0000000000000000000000000000000000000000..3e9b588de2a9798a4a2180a3cb8ff8d8a7ea961a GIT binary patch literal 5110 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 literal 0 HcwPel00001 diff --git a/data/fly.smp b/data/fly.smp new file mode 100644 index 0000000000000000000000000000000000000000..dc9d3e17e62635d87c72aa7e8bd2e0e697140e22 GIT binary patch literal 32376 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 literal 0 HcwPel00001 diff --git a/data/font.pcx b/data/font.pcx new file mode 100644 index 0000000000000000000000000000000000000000..cda12ef9250e2f1222903544c7ebe20c986c1edf GIT binary patch literal 12019 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 KdQ+5YYwds0b$E3E literal 0 HcwPel00001 diff --git a/data/jump.smp b/data/jump.smp new file mode 100644 index 0000000000000000000000000000000000000000..92661e51caaed3448c51fe5d1f5bc34398c43980 GIT binary patch literal 6552 zcwXI^J8#1<41{CXMi2z(ki}E~|NqL=r9*(AFcRBnQ$NH=qWCb?8oi14-H|e~X1DWn zUi1cahT2$yMNQMZ12s=V6Byu0wiS8sE05R(rw^bL6c#{^1{|J$VZ&Tlhg?|4&s-M0 z0y&Cd$PvuALSsN>*r05CLR41LOO#^WXm@2tJG&@+1EhFPVVt=5Rz~U zKVwB~D)()MNJo)ZrQa37XySU{oud&F( zEE~U^3?*HL6I4f2mi>>)Nl&h~aDB|tYhw3jQLGm+nw`Xtmc#U+L0j@$#HsYM)y$}* zXGVoTYbr=vh=+%YhX!vfC@Lwe8HXs17yJ>2er^F76T9e5?BeQWW=*m{BJ!#>BkKb@ TD}o`65*LZVo$>#v_}BUZP#HOM literal 0 HcwPel00001 diff --git a/data/level.pcx b/data/level.pcx new file mode 100644 index 0000000000000000000000000000000000000000..ba30d9211576f1f7a489d1616b7adb29f7baf33c GIT binary patch literal 36203 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 R(s9A>Km7I%r2qf_`@i^F*$@B# literal 0 HcwPel00001 diff --git a/data/levelmap.txt b/data/levelmap.txt new file mode 100644 index 0000000..e87448f --- /dev/null +++ b/data/levelmap.txt @@ -0,0 +1,16 @@ +1110000000000000000000 +1000000000001000011000 +1000111100001100000000 +1000000000011110000011 +1100000000111000000001 +1110001111110000000001 +1000000000000011110001 +1000000000000000000011 +1110011100000000000111 +1000000000003100000001 +1000000000031110000001 +1011110000311111111001 +1000000000000000000001 +1100000000000000000011 +2222222214000001333111 +1111111111111111111111 \ No newline at end of file diff --git a/data/mask.pcx b/data/mask.pcx new file mode 100644 index 0000000000000000000000000000000000000000..8e5856f8fb9ba93b8abd36868cd37824047f0fe0 GIT binary patch literal 5530 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

PNSW0UlNAy-zg3uqrUieHo|FoV1{lPOdU+@-uo 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

F6{xVjIgrm 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

xTus!`} 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 Ky=3XXZ$AOj&KKtZ literal 0 HcwPel00001 diff --git a/data/numbers.pcx b/data/numbers.pcx new file mode 100644 index 0000000000000000000000000000000000000000..d080bac3e438458299cc14d7719d028c307ae43e GIT binary patch literal 7036 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 Wk3YWp;iU_d_p@)_aP)-xhOXLs)ms1h z-~avI@BRL@t8&{TUwEkbi_JH{7orwxKe?{Cch|0+#Hy&DBMzXi*MIR-hraS~^PSBb zn{W8a1E2lk!Owj5^PeKjpC)>Uw++)VzQ`0VF*zvU=xHjW0lySjGRKSFk}f63ka_CN9a_4|{yW7TJ+~YAe#>9LKd%1^ z{^N*Sp0N_|{fp%vdM~`bd&TR!;q}K>y#5%x{@jY!pM%%e2+{%CbQ^ z$L}IEH-Yo_mS)J$=T;wk{%>>mE7FJ09UzG3s;^O?*WZEHKZ5h0g5ytZB8Vre$Dcf0 zM?AHc!{7fXYObA6Ivyvg$F2B$6f4L7@^iK06#n|yRpUST4&$G$9zXpK}p^WPvSib%(&$#h;X#8Kn@vqnJ|El9CPQ&pp8|N>Lzw-FX@eftUuf^%B z=3m3(Q1$+=p8uih@q=(2%^#h=V*YPAAI)dg_$$u;k1+nB!*#31KXlkzeV;Sdk9lI% z_~^B9oHEuQ9bYki?Klejnj=?^Pp^H5xH`zYR;+(5R;(Y{v%LQF+W*tPbiB$h(y_e$ ztIod`|K2W^?tewpUay+}ins>up{D0hd^KJ8=SU!G@{9nEP#_`|#|7*YFW*=5zZ8D`*nR$0^Z)XF zMtwnn=Kt7z;Z^+q@_ltn$Bpx&SB>9Dtc=I*YsO!f&u_iz{PtDjf9G$P&wVHSucd#7 zR@7${U#`{L>h&KxygWa={)fY>`;Y4SpkrwKFCUJsn*U>m8<&ow@xF7od1-v({MM!8 z#`x{a`H#o%Fz%<;{~hjFmH*HGt$FDlO1SpZ*78b(oJBKVQB7 ze{cOe_;KQz@oSF1D&A@RuQmSL#jiR3zj^+LK2E$P{{K|}uQh)ZzvlR>;y>g1AN)9R zb^O-#zjk~@{$F$bXJGt~RnLF^Ibv1R>fLqK`+w@H`iJV>ci{Z5SMjga>&I5q-|xWu zYv<=4C#uJn>+j0(4?R~qZq(n;T{Zq=?=XI?UO)d1<3Im4;q5rFoqj(;UAF7^T8-L~T88}`W|K95OwRrxj`PcBccg6nM%K6`0 zJ-)ZP|Ax+AIsdEANAp=Z|CQ(eM;QO!YCW%=e{asJ^c0=gQ-?*Q@tmmya9xuh!pdoxghjWqE!$t{&ff z;4SB`-v2Q#9lz%I=GWeG{_63sdUkr1|F4bzcK)BR+uw40)&5^~{FTR7kMAT_#cw=+ z_tNp-ZvLzN_isMFf9d#dH~zA}$MGAFA6`2C+l{~6AK_rG+W&v+`d_vG7hO7Dz5Z(d zzheDAcRPiSt8a;NHa2|e^pTf;{?mW@(GULSyZ_IhKl%7l{MSGJ>%afMmtOtgM}PIk z(92K1(tq^KNkK2={M)-*8}9nz1DoIb^{;>R(AQVR*WkYof8gElZ#dZb@lU;{y^iC8 z>$h)k^v4U~=3sVW@bZO$NQ3y}e|V9yOUbFDKRiaP)6Tte_UyFkPMrDG#N6O~dhx_7 zZ)S6omnM>f=lXI|VKFT*)fjv8+O_NV-hShO8{d7$dq4Q0`#*C3hwi@fwww39 z@9sO+_gsI=bv<33j``UuFMaRvx5QI__7{Ki>hb=*@$`HmA-Y2K;m)n=H@)Y&w$_fW zmb&Q19lLtFyS8uL@!t3E>)iLATdu!h_tp)&Z@g*mzU%hv*nR!GZrjznao=_OZoF<= zOKbbaO&d3D*|1^T-dp!~T7!*lS|c>Y=_W1?XA9}n#IctXV*c1G$F5v_bE1$M8oG3O zCY8^pe(}>&CcCvTHo+wv`s$n8*KWA} z&iAZayX!;u-2I^s+`4ts&iB3lUEOQe?A&wUwi|bC+`RvRd#>y3Xz%K2kA!^A|5BKl+R3emN7HI@>oPnf!h`tC6l?Q)@%Zj-A_YylMZMrq(?-y=(W5-kzTIt?lh~ z;kvNP!Vom4YYJZ}#uxIb*?2N7$^tEucRM+>ss zsxVIG(z)SW{QS{@v7;yY&%gYme|q)ki@!SY!p~2hJ$`y2xi~T{t?OC8Y1iHxZu{^T zK6=abx8L=F_uX;JEjRDpcgvl(-n@VN<{iB)zDQUti-cIxtxmJaWOj%AE@pmgBq_7W zOGo=-f{iVnIyp+2m{i}9Gb0Pd)Y#G2&(70!dFF-Zk1pm?r(StwATEp3=T4owk`sht zHj$GVGbxlS6?1e=G#qYTyP-J}@CE9-x9{G$eanVTTiQE&HgvSM)Cavzhu>|ZRE1E= zv1DOkbTpryygV{FJUEhAoEn{qr80$LVnJbul47#kEHp)tjG3b}*5Na&vd-9ONj8b| zgQG(yPMtsc`o(l+ad_a|vCA_vgQri8X7cGQMG~&)`fXdb?Af*BraSMs^Sa$P9z5{g zd)~Ww`N@kHM|GP+E5_%t3a2EmTplXvR5_DK<`uWwB8sw3u}XS+Iw@Ff z7Oj%4XlgPROC(YPpB|f-932^-nVF8I3&mo&keZ)~rHg`YcREZatA(W;Ucbu|j7CD? zy1GCp+7b=AeSttA=yrNM7K)%qRpKQ{P6EPEE`$4xfX`UmO~~a`g3M7yB+>I(zcM(B$kwN+wMiL6dYvx65d4A1A%@r8wi zX0{VTA(_g_ayd31D~U=apGxzT-NMS{e6~<7WV3>zDT-W7C(^lGI+H8qQ}IM%VrXD! zbTX02m&>JmIR!4>0^V-xXo8b;tng*BNOwNlYd7FJg&b2wUWQF+2-m2UE{G? zJzf{9%c4qKIW4s?yRf)8F>tYOcp7Gw%N1mT6kxu&0?(JziFhho6hxV%8B#-7vlR_PL5PnP1jUasuc6Zaz4E{GXqykPLGYurg^!XEh&_Vqa|J-IWudr zx?N7U$Llb&x~40YY;1mRVr1a*<^EyNiF21mM~5z5x-ye2N&*j)4AnP8>l@Z>+O`YO z*tz%CJKlZWj?J5TH+Qu~EF9->fdES~x=wCxYJ6;bY@mN&Y&upbl}g1zu`CEYTHIVN zlS*VuB1zLAKAIxJLTegK5X6g+_=+gW1VxjYluyU!W@qN(>0&XTN+weXihPCVA(Lel z;X#{#&{nvApU>-d!ljKl8T~n7MsoC^7{QQyTxjEaDGoC$PLNQPqwxtPx^Ept6&6+&Hx~7))u8muE@7=e5|9&W}TY7ssS{fsvpdX0pa#>B3RLL(c z%+1Zs1H)(LpqQnyc~A$T1jP_(RtDxGijoL7Q|1xdVck?fq6Eo8k`&y%D#Crjq%)8i zp#Dh!C7sQ}$=O1w!oyEiM2&!Y$XXpPm($^J!W=w4KN3-p3`i6=de>nEyFfuAk}8_8 zP(Uj*yNF2!0>qbKRf<3`NtAR*H#5hXZNLnhnFWdprF3D-BRS>N5eW&7^kyLau}v1LS8&(2H( zHD=~wsa&B{2Bj#1P^6$VmU#dMX-5TsfHj~gLKb;J)=2b%1}s2CfF$K|F`LQcfJl%f zNl3M9CYy!I3Q^`o73jor;NZ+=$OfC;;qv)|LAVEx$Ln?5E$Cei=mrIwq0sdz7kZo9sT^1G!tiqR2M$OO7jE@cv^!E=!43A7s&&Cod z07E5co68$%Xj$9Uvw7>b?K^hv*xJ2*O>0Y2w7wo{S-|HqF{H#pT}a0eDW<2VXJSdP zcO|$H&>~bQQ6309o~fjfjG>>ZidBPR;kNNgDk2ZwvQ*6H5FJtgMG6OE6%?a#6#-w0Q29y)%Jw2u)dXAu2$nCx)ls&IAfbS( z2`*x_xu6)@Eez%<2v#ZqD>^YYGCVvqG(0joHa-h9Pv^>lL^39)Cs5zmy1skk=B)t6 zc3{Ptj<&{zC?F9I`kgj20rd+38pjC&8M2tp6<}KMCQ`i;LIN}tz<`^e7&LhjfdQ*S zFdPTi&`46Dae$kLnuC%GvOEr1l0>Bh=NQTq8DRlu7`y=AS26fXm^W zgPQ^#7ISG3oKz-**;Rte!|kAoq$5-<0H?zVDPp&pX;j_#LKf`I!tB(<=m>xTsyRA2 zJu|E5_$^Oh}JxAbmU*V)q4SPu>-9Q1jdW|ou%@W|OX;swMU z7~njn1%e`PV1dj-31$OH$1)^90Zo&l=rA*b7BmSdgP?$w0W4BjM60AQSOHa40aCGC zH9zc#+yRhGzYnLX3*G@ZSm-fm1{jaDsaymj4g?4NflB~Cq0l4U0Vp(`fdY(*D(F90 zP!iDsoLw@pfKmiO0WmT@IWspOPiD%3tdor0?TbX4I@fIgPqAh5=1n~tI@?;JkRM@S z1sFXuI458>(hH2m{6ai~!~*yIX{6iqZn{ z9af@@@&mI1XrZI~tg-@D2dyCF3-X>C{)q|zk;TecRSB#V$j%qbqNL~qq7?!HODE6* z!~z1;0<47%+djY=m`5OYA;N7XKsFJz@_2dRhIqIRa_J<8MaSU;qlFNJ6UqgooC|Za zQh^NYk7iembAedJr%v2z$3<|7iz%L}fz%6L>IR=;tRSaYs=sgF% zU=pD*IR$k9GAxIxxlTbV>j&ioUaarh(B0j&er;Pz6R;u}2>8%qSU`S}xdZu4Ae#~c z$;}~e1ak*QRx1d?0-0ZM#&Dwu3dj&J zDTV{M0jh^_aJk&o5(3VNM#s_2px*;u1sx5h6-KjyJT77d$`Hncp@6fYhJb=;3a*7I z@VRr-RbEUWqqGR^GOFfqh65{Sd*>R2#fC1Zrp=A@$mRtC&=*=!D zAxJHG3|aitqycZMgUC!E3BMYE({>BQUEIo7z*qypjI+0R!<9v z9-;;C0utT>DAw>``>^4LTw4!Lg2xbB9 zV$z7IDP*8wLQqdp)p7fR(WchUwd*h~)^&hbMC&jXC`G_#L2FemqEdt!pv5?JmEbIR z%nHB)We7?T0luoJVFFfY*k&o!CY2zugd?>;rZA77K$@AUqLIh*fU6*-MZfN6SS>K( z(2pS5gm7S5m^qe02?tb#-b)1EgqqxJ?Gh*uq)05l)>PFOP6drY{=0(N9bZZj$dK8E zSR5Q$ML-VG>Tn0c^(}23>(&D=y4J0ME(D1MN)eA6x;tPu$ThelUr}2 z-9$A6=7wNEPgy`LM4mU`GYV?9CY-ntDWTmB_;I8Z99K0LP)`l9aJd{HoIrRJhs!A{ zjxZcwEyIodL?OU7oG#QJLiC{PWdt73unE@BI~qnd*JK<*%sgqkQAV&U?J z>Kao?UM9gu@C?QBWQ4t}HXL`DVrL}@s zTrH@8f}xp+71(fUs07stDypZbh`5|6AVDw|9BpI>focdOF7|2YBFN()C?M@+)RO5m z)?d_@nN3jE&^{E*0(BxW++0pgV<^C-WpN3C&IRNN>S+_uqI1pKwQG=U0x6(F2B+tA z04tz`7>Z-;K_$^n15!)elHwkunja$eRY)ietuSa|K!KB6Fzg7<5kn-5HXR`WS5dK8 zR8s`NKq=zHNI)5Y{DAjZ>{Nhw8nzZ_+a!}UE`yC9(sNWoU}W(9hH(Wy0`bLXc+C@pv^3}1qSaxpk4|!QVFzs zlPgq~pjg5}6pYyr)h0y2@`bl@b(AqOrUj34q=?gG2?!(4uvm}=7#I#D7Y?*{t#nP!Ny`)EU-|LxSRqj zRHCL9y0MIc;ZhACYJtJP%c-u!!YBZk6aWUI1s01c7HI#}poNhjOHl9z6t$)wWrzj0 zAzF1sffk?^b4#>HfHT2jL9ix^%j1vKH?*|2b#!#Jw>C947<+nNylVn(7iLjG`&Ljy z&^ALhUo9a#9(qNFNO(uzC?STkAZh_M1Yv=gR5Eg81r#XLt0{sUD#O%hfuL}puv?9e z47DLxEOhjY0n=iM73C@vhRM=NgBBLUrlQ3_H7AesKL)fw0Z=T&@r01GASjc??(v7} z8=3$MpatH?iUiRXk{2`!Z7QP85>VeN7Eryg5vYj;`c6c8j=m^(^4M4)!>QtY!T%VV zZ`f}GjFkz3L`TBnQdJ8idAOg#tZ<+V!LrGq4Ni)zibWZTMaHnK_$rlh6$@nds#t&@ z0dIy2I@)o_Ama=j6%Hhu8Ps8-ompsH9B!zm(I%WC?QN)-LIuIBsEP$PoCSQ5s#xIm z98C*G7nalltt+mby5X`g;cMm_z>$`CVF<<&6jg(A6)UiD#!6vBNPtvu(0~wze??HB zqikJy)l*(v-0C5Xpk*=DoDlG)un@VV&A{Gm5vT!{Gu`oOq-rK@R2o>Cw zEy+a!h2Y#m?GiCtRM}skg@s31`AyR84K)vs|ivQ3xER7L$p8{ zg;zAbXru_H1)5M1?^C14F-}h~T-VSDInvtN46SJ-h-K650mJFx0oFHgH5wTUx&`qYABB+Kq3@{Ka z5Ed+j%PE1oQvtQ!xEm`jl~Y_p6t(7E5f~`3D73F9AhiJF3|?^oJzQIe;S!R=VxbZg zXSRWGhU=n@P0a|3#s+A|@NP4D27&g`YDKxa?P8P=LpWDE3tU48(ohS-a1vEo;2MI# zFq9L4v4ljm$3?~j@7Wn(n5wiu`!>*n)T*grU=uC}b>OzheiG_+TQo@^Y=~Nm} zG`2Mb-f%VIwQ7jrz4cnBP7pP*Si)k3R@AHo)*6bgrUc+ zXk?5wc?k+^zR^X@#%3Ub0^}d+DM}H%;{eQn{D>!U#>40uqJ;>Qa7V+TM+&%kK}8Hbs6Z>4 zM!h9!sX#SR#uticPZ7+w$>MN%f}u#X0dk}X71I#f&@)&8@=GC~E0j@Q8my@LO=DV1 zP{2GTY@Z3#hE%awMGK^y)f6eOh62f*Pz92zVu5@CeiUF^h61s|sLw>ThTsQdRqe$Y zQe}lwC|3d z+yXO=8e*ugvHxUj^%^@i#yTv8A(hvp1-zCFYf)K=MX8F#N?K4gC~z^vNFXSXBWJ4H zK?HUxSkBSr&oUI~b`)&BN!;j~YTgVNbfK0aNz`0oC{V`Z-SQ<`1fZZojx;n>iz!9| zb;oGS7>NbK(|{sZ6^rV=KZZg!%IQ)KL0I6mS(zbnEkjmdQC@-qEhoqwNg8s2MX!nl zekQbn6%>BpVsz>SWHqaLgS1=_P&GAbh(Qap*(g0VS{ODfj(HJB_5g_m)R1Lbgn<`P zh-!kMPg$UXUVV}Pw1A5k8*zoIv%s_v@TPYS3S;u9gcvns84E+`j0~w5yY(vqv%)an zm=+idtejOO%qwVtGelR6dRjERX0=Ziu;;@Wq8rZ>peUO#6aXI3sEpO3N{cv75Y$Vc z4KNMS!iMT;(14;Ix2B+))vW@wkA~D2E>bWyCUeHNH^Rcu?Ao@TAr?lbezjPvq(v2r zl}O;KZ1iw%rNt^J=&Ep5Ye1TpTXYB-I@2^b3+iIfLsBpr^zKKpql0jhFE~S zU|M+5$KvWB(1r!tu5dbx4J4+z-(I6du0{*PJ}!xcjG<6#ox0JItrm-AwOCG(N_E%8 zm;yHIOIR2WQGpZH5`rpA&3hZ&u7G!gR%%5JiYhG_4mU3~u`pZg6sR^gP#0q5vE%3wCn$4;b zqp}y70B($ffp8BDn0vHh_n|R0DV1=1AJ{)IU1V8^>W<`~e1{AWiN-UOZh+fy+)l7C!Jjo#Au z^bZyb<7uT%GaPzK>GcOeI>X_bY&!5xfyH=`fN4=Sw(j%z30d_iy0DxeGWsNMO)Rup zd#W3aI(nxD#WEIGLs9MFmS|yoEXjx(6jbf;ii&$O9z#*CF-xqmLc`{}N(q9zu`{)h3*jjf7>yqXsH19BPT z<5b2r9L;i8yTjx48MHtTLcBHEL|Y%UVb%Cb4T|bVZj2?qmRM9P2+k0L7H`2~1sJs* zsH#{jWeAN$uL=aJ1Ithl_<@UTZ0yyxd8?m&sfoohEsUNPD{YMy_@iMM3EWDQ4Y437 zs9JWYr|1KdA&3BW-b<`NVu8{Ot8bzD%-6_})#VhkVyQdTs^)u1IE{}o)>32@FRET` zi55$8f$bs&Vo59L>Z7Jwc{ZL|R%*|(alS5#MRn>W@2hoHuM1ZZ6YCgNbR5{D@A` zEcC-px5p3C84T7Q6dF6MwY|aGMeq~8B62h}u~>$pDi->ZSg5OO$UD&jPA6)?_@ZsS zdv3eu!AF*V`R4#5$;|VzYji;VH{OZ60>F>VnqmO<4w~NOf zI&{w+`?q(s_}vUqj8BgYoI3I9OFudM!|y-)%v0a~HXi5Kizl9V;v3)i_ES$i{me7Z ze*cF*Jp7XvUV8P&iBsnX21lkB;@KikkcBYmYtl$U~p|+=GV>ee@&u+We`_LC^B}r15sW;5 zH26=pidV(gmR8kBL|E75M650?PQ}4NBN@@^R+slb+4{asfCzs3+f@xb3`>vK9xXmv zeYE^o2!R2J0>A+v0k8mQ06YL9026=;A3cOc@u5flO|tmEIKK8Ztiwo%krE>c00-{4 z4Op;$59D`mcXt;sp(P4jz+^zrP`p>tFOL#1Tp2*dBl~$kr70fg*YNi5v&SwYYec) z;&%HGaiWMiz@4t{ZbTp8&z}AJ5ru9;B!a>UJOUyClMX!yf!Kuj1cU-gLA=vy{`<$* zFkyf)C>}z*LCgW_Ao2iv5PyI{cLIliL{QX$M~F!vDcdodfKFX)ZNMm?RMZcFXa&Tw z0JRw7DL3L5L>6%@j(+!U8u1J<4X8G7{yeY^_y%zV1uOwDugbljKpaN#Lmc17@vITg z;COl|o~p*T-xA+=hq&s;YZrQI`P$D^x5XdQM_3~UViKZgL(zq! z8%HmW?bX;*js3MaxFT-5I_~)G<2KBct77F~2bXSPf9T0WoG1V4h z-k5Kgawv??B3HK~Ef_Lp=@~L%@DN4y>9GNJyc!F&m^NZ$DF&BgU`3o?ic?p`iMI`4 z!jWsniX(4-_R6?=%qq85$H1ysF^`c|F})%dRz-X{va4eG8N9*NY7i@eyegQt1X?4@ zTf%*<@U4gyD~?}8@vABk{O=e(<3D^x^`E6L##gr??*1C1mPWqjtu4n}=Yr#{6JHru z!$dA2N4!n&*9^Q8#j9g^tyZmD_P2n5QTm1Z+UflPbq`r6r0Frk#1rHtlwdaSfRI_{7ZhTiV(p84aSJpPSu{mHk! z`AzhH5PyQ>Pyh0bpZ(nn)1tlgt{d;aY3=f z^vgee^~pbd?pxpd*3`^l5;cj zWzno|+e|j>-FVlXx8MIqk9_)%4t?SsRt$Q=i_ zKKl9Q^*cj8vn!~aI)C=U-~Y`kfBfH`eDcX};`kQ6-M{)Xbi04@y+8T0KmW6T`Qa~K z`_YTPnjL&$a%!lkMaArGO`Es2edTkX`oll`qd$bebAVw`{J|eQ0{{EiS0DZKCqH}t zgBw5C;biFi@Wjx-tK*kW|MJR_KmLo6m%jbIfBfd3z3}Syzx9_d{`gzp`_@1F>5spA zX6EN7j{oy(Fi79j6)|smtOwc^OwH&*RRbc zPygMk3w`H~l!e(h`j2X<1(LGWx7;u`q&hc-y$zd*taH7kx6Lo~+|YW%ZNBij{kz}i zaDMoU>)N}bA9>gQTi32%*L}-=d3)RXb-KhY_V z#FLZfV`t`)<8wm;LnBPz8^^U5=H-_z{!*GcGCf}K=IF7pQDLkhEuP5?rCoh8S0qmK zYia$o?vY2PQfFm;Zh@RjR8CEriq7Jw)LAE17Sf?svnA>>x325mn(wf9Zr@SAS=q35 z_xrc+yX96#)4QYHU6lWZ?r5jKcl-6>)?IhGJ8s>c4>v^JD&c4S3K?N)=>c;V+~ zC+CjPvp<`le|Y(s+0^T~;lE8x{p{73jtvY99rtrDUYI@GH!@9~emy-nBBsyJ4V*F4 z+{^&CII?zjZfM83LS)vrpx2qh-kpusdN~^HzNK}2i^I9*wmZxY^XBOOU0v)Zx1;T@ z{Zud)zIlz%V480+*L%fAzumXaOLNYdLeqv=d}5)@MJ^2_%-NC3oaMDR5&!40*?e3% z_KTc}B(#B8+2uP{9Cd5vVueYl&iJAmY!}P z5(^>TX^D1a67?Nh+q0~L3wCb|)koPD#qYVjAx+sFK04Yfskh$ZJ+O}t+L>-^UH#4t zWJ@vIre&>7>&>Bv-Fwa(RX0dpAw3sk^@!W{FTdIrt+3~^!>M#~B2iu(98bSILtP%4 z7cbMyk4`ea8g%k%!w@v}26n+kFw7q83_=aU|7(A7NdnI^i{BqY&WFKcU~-rmGs zZrWq3+tj+j*|f>y-^sG3*4F5T`jCyxb=CXAJr!50(@NAk0`vxAh@Oa)eG>vZC%Q9v zVX@*FJuzRY%nGrQgfNnt88M~E_{@;LaDnl^D9;wi0vF&W7D_SYV+Z*Y|5b5)02(qc&7SQY1f-}_QcSM_mQkM{4tFnTFoVe3>if_Ht zoGH_V961@COIF09DZxo`A~%~DlFGzT#Zxg2o==w*D#>{L=E5Lxe1>hESu7V?$&s;g z(7`vg4TqhwMIeQ)GHJ=P3HLe+(eDlFi&EC<;&e-elckEQO{}QsSK55+g<_ zlCHD{D|FD7AjAl-mE}z%j7`e8bA%-y@Jj=o#JSW3Z=I+JdoD~=G}%}5RHR}|B&{xo ziB;LTxL@U_E2Cy^PLy>arD{&iA!NzyV$RRZW>{7iD)ypk%4I`JYiclPA56Gd)ihs{ z*Kh@;T=FxdUZ^L0xqQSNv#lkYQ?8Jb4S9MBBXuRs*1jg5-V|zyu$03krL%gFOsbtc zshcS&TV`Ct4t~;Vrrq;SazW3=E270VGZWziy>lTTj?R|2T-q+kbX=NOIfBfqb6VIV zRw`wiIWG9A1aB>-=m4QbnzK$W-^rUIGDEtub``6e5DP+8Ph8IYe+gwg0T!fw#S+ndY^2J84$jCZxmFJ7uv5>}A#srz6WK}Dc%?cl5 z0;1$i&*q4*%gHVhCc3B)3Eg5P=HztQleY0eDW63jSPz?}qAl+tNRz;+jGqxyhpesF zawa+*ZY3;!Q$-<7SzBYd$f{1V>{-moz80%lOF8`ZiaEyU1u3TaiZ(6J5fN>+ZG6f~ ziL^7}ux9fX&1NlIwQx2@=A_J&;I1&@ED5CyI0woUbR9wiY#A zsyIo(&XK-FF>i{>siKxuy^2$CW)?NYEa%glsX)Ztx>nMyJjIv`mc#_jvJO_270n?p zz=VNJ;dlRbiEqrzny(O|NJH&Z_5~r5RR~)PzM# zQRM(f5@J~roE0rW+8{@Hu`IKqE>KE^mh`k;b(jP}A{0(D>23jVk_nn*E2@d%T@s-> zMQ4$vIaQP#ZYCd;NlS?%HAG)XW#s{_J>l@T>fqDY5_FSE1&>;u3mw5k$i^oc;N;CG^RTn7- zA(~_lQ=th-BPo{^{Zb{FGid_BA>0@RkdSGepkzr?tu)C<3N69pH4`gX92LrA&N_S< zNmNPzzKMgA(BCH0XtQLt2yUAWpeQWGs3I>YJY{AH!AxtM06!sWR*kmFGT=ZFc{yUu zqhFraSxRMD%EBw?uQ=!wEop=*aIlD!NUBtYq$Hj*k+eiAifAWP6CrSRs;ny-X{7~8 zHIX_Gw_u^Df?^XY6vxV%EL+Svqwp|6S=R*&H|u1rITFQ#3(Amz}={_PHXT2CPNdXu2ZC@upFQ! zsjNoo1dDE$qjZ&^bb>U)1%Zz$`h9%#2`x>bVP-nKAPE_L97Tbl&|g0T7zs^5KcV5z zO3O4FnbgteCKO78ixR+AnvvmZ@B=V1t%wv{i-zTA(1|KS0ItHo4=4mfz^$q91_3{# zaWc$;(BV9tqI5%dN!7me>s)nTbg z^w~%>qE6sHQGh;FqTo+cz;*E_PE-<)MG}b4a2_O}*YIze04C`A_(L12Mxt9G(6{J)()bhyT%EvofhcOci(hN# z3;G6MpxW!A>FH=*I$8ao6#A7fxF6DZLFoA2mOf~>6uMsf*Z3^WiYx1S?JceLF`M5c zjE|$hzhu*?7AbgaH>_1$3pp&^cb5X13&t)q6UOBkS zG?`(id>zSsOenFCs%R6;xW9dtTvL8y)7lNriavVr`abo_#DSTKk!Xh+II=aeVUG0$ zy9VQT_j5uy?b_(FPkW>DnZAX&3tMjAN$AZ)T}PXck}_vZlXgpcFgHy4wl9M38>g*G zra-UlXd&m*?!=@tbgy%;Zu7ZN?BLdpV0Jw;(V5$aZhGaUc*S;p(}H)=#`2}CH(`%m zit%%k{jDw1jp{ZDd)dtgf#c9~W%4#8$dzBAlS-XVgrtLG;?pw;szb=9Pk@ zq_x^&v6eb<+k#1Juhb>1S8~p5&q#m@tY3U{+eA(&L2J->W}slt1lq@X^@VX_;_|#t zIXIr_v1Du{;g>8u!>O#<94Z7B^L-(Ajw{T!XFQ8-{Vx|rTE_z8Gdw6>`qm)_lX8Js zr?<{++&Y-cCwbbd&6gL&bUr6`Uz&6^L`6jn*JUH~9z9oAZi;BGnN8|oBzCaEPx5*u z-%((F?O`_~3LIa^jYZk=*hoD}17@(O7Y=hY%>}9t%)8F6n~Rob~1ULu*ig7 zQN{ygx-H|Rh?1H#gBWGJ{`K?-uE1hs`AB^x2x1w{etK{H{}V-|QQFlrg(RJ7@`Cok}?HkdC-E=sCw<{8mmBA^Q( zNmWnad0*mnHB7P@Wh< zsn|72BSk2T8Y6R(s#L(GNHo|qXaTZNT6Hj2P-qxUqu^d;@P)c6A|ZzPnH4ZT8Y93> zK&c^Ri6Jq{ZVvVB$A50{^NONm+a@LT1r#jcah@CKK2blCcE5w8-*cX<@+> zlZDb`g0%+xW`U`Q;8ZkK;;fV=609TWcknd&qiEn+M8-<%@TN29a|={SP{GK6Nwv_V zK(MZ$*DI6gO$9uR4i-<)7-z`q)wLoI$ZFu5Okfxl#u4#)7#00lT@8J9n+0-7w7ntV zwaD2L*dkQ|JIs)(NZFdhKDU(0OEL*YRV7%IDb|*#KPW6_M2SRyUzR|>heeoMnu86( zY=RdF4gJ}opF)}fYdSj`&tJ)-KcieKFfOoeIu}~IeqHCe zvuQb0JAP5z?aqHHty}6ghGom6EvUz8K zEb~Icww=A3l$S;_yd>pw8LQt~sFb7I_H5k9ywaa3iDDs_GWlGkQZcl1-^Om+8yB)g zp;F1EDW6Bo=Y6~PZ|riNJ(Vg|3IYhL$E#(t&fNz#b$N%5#VVzYoK4FvKajr=B_;9hDDHqbR*=1JK zmA%(*=?;}n_vecFQZB2Q>?S&s+k3;7?l6C`FI6a&Ga1EfHJS5?-3NL%M1-O9F%a=& zQn8s#&dS`b{hPY#rRlTNX+ccJWGBnHwApQYdp1PmgT%v5dv3(jK~T z=Nfp^GI4UKB$bmH+Nl#RXXDn6^>v~>c48nS7t=Y_PUtRwYj1N`NU{}=Ux~~4OhK?v zq^oYt#`^W}rt;>cn1J47XwKEJabut}B-+T+XXgurbWYSMyQg_qkEbatSm{frXEOO@ zR@8J?pyfc1D-`A}+{l@+bS9n=XvI_4cGFgeCm@*3Q|AV-(xq~pxG<*U0z5`#43<99cvDJ$VYHIV-l}io=T0*m1&yjTz}yH z#)?)XEZXp;(d5WfktXQQo`WCXoT+4G8$ES?XkmIRL#xcXO*cJob37d{+sw1)u1v*; z7a5uC-hA_?-k)Ba%GzwPa~DQ4qf?BaZrX9vr|+-K3?$6%jRPcSPoJO5FUCZ{z3+|(?!S$HaU8nw{u37`^XXVgwC=j|!H>Mh z^0T25p^lxrG@35N@)Eo0_AlK3p1Kz<6%=9i%*CNZC6<@TweNc9lkaVP^-M-8$IhQ0 zT;vl_iJ~`u`7?KSoH?H0OPP!3`ses$QC3_xe(?+Ub`Bk%EfoqE&koM;38*8?fiFCC z-}<=|V})#`|HSZgB_$}ju=n#{xxY7cdN7+7$KDv8DrUH=n3#n4<_}S@Fp-9lP?Vo()zFUNa%Tvix{LJx*a-k@5bM+s8 z)si!NCPuTFmIo4eH}$QkQt5VPQQGqVC5H!dh2~3 zysLw!eDcI>{`^bl({^d0q}G4Lo zpPc3BR6()bb??3F1=0~H&o7Mr?9C~PD&|z?-S^+SQP6Bba&}?lXGf8ZONq2n7IJ2M@a*JNS|JJZ-cMZDBBF)sB)los?RxK;=1kFIpz!KC#S>2{JMIEC*KRHw63EH=QTVs19Ri$sB4A z6kh(tSXSnVhW2&QXj>&oI6|!v_069S zIwhaAH`O<}CV%v1S|}Hq*Z6~V>&Rlx)ZEYzNd1o^@iL!nT;p>zt~KY1Oha>hSa|-W zxq^_X?{u?mYu#yq3ANRSnO{9Wk>|644yV?+E|`$a-j-<4e&(m6*<#VtYU4Y*A}Pu4 zjy43{!#^2F<;$*SOSYpYniX8`P(#48_|uDte8t(s#9BAE=6R1hSQqq^e|{>SFWZ}m z@rG?{ie;ZW=nr~{Bgf`*6X-J})W-k`_lwG1B} zf+sb}^JEj-H`};&11qrgey`iZ#m`^P=nb~M@kr+e zr>N9{%XB)kmoCJWde@Z^Z)aCPE(b$Fw>?lCJUb`UyM_i$Yd1uQoF^FZ*uwJI*@D=WFqK+QpG`XFT-_Cv(27 z8+_2mxf?^i4r=1;o3@6<<0;>^^**(rJL@9B4%^JxH@Il(wMEyibsoAb+Jkj zN6B#h)p`4#ZWpT-t=>p|S2%Izs1hh1ndWwHbx>@Pa|P=*HD=Bolih{aN7(JV+^R_+ z9RBd;j{K!#vORyipX%Kg2Cl1Ccc^z`;mQfwl09`v?cU#7fab$w_ix%(?msV@l4s8g z>-MgN=8!a*J)5>`SB3;8arRuLZO;a!$WdmKqh|-#KP8ZhXU-Su_HLky1ZA;W)@^qU z&uUui%!Q15Z;we7S=ME0-Qk^@H>opcE~HI+daO#BBR#h0mf-xNiMfJ6UCfl%Zt@8ohugJNgq8qnj>36ia^^*H4tp{ zCf&Q-Z=UT>%MD?zNSiH$!_ykdTX#gxUg}Gf>mo#kVVtbV-X7sin_Bw^`et*%2%98n zmz_4XG-~E`9aAHhCsMA6c~PbuUW#sLW^C;p$%+2)7+2?5s4&(bMMat%wzk&F%+UC( zTIXKK(dHn-_!I#O#?m9mu zO-#ooU7qZW#&|4&dVjzZ@|wu8x%epOE{&^DLhD<6Zg0qCv5w89#$=Z~B2jj0<2tX? z6LOk8v$NUpf{hq1QYJ^k7Ps9Mbg};QOm-?^Vn>oB>#W=7vABF5$}7#LW)~>)#H>!c zA~yzDkIP3mnDqSIoNAdFlSp^yT~Xa@^O7cuG&40PSr+@tx;J!dhwQVvC>V2QcwV$- zE@c&O_?Atg%V{SGTOigqEtv}!<|TLi!9AkQZG*l)n!PllnfQyNg0tcJgNn&*S9H2r zxN?aw%a{8~&gk{;A}O~WTH9u-|D0kc{y&=DJHCxOy%Qev-g_fJ00an-Xav~6DoRwh z<+Ap!H@lnNWOtKIHp#uodzZWWBkQ~Ol1sLE*WI$^B70qB%d(2C-bIRHr&s}yAbQ6D z17Ls|4Db%*JN=>0N5j!?o_T&x`F@8p&v$h$&sB^cWi&Y)6l-X>tMg?6VeLVZB_BT~ ztTT8>9h1q{m+~SqUMi@vktY>33cp&f3$^~Gw1~dG5Fm+%pK3?Qd>qYjjNzr2khih0 zg>i~c^j_AU4-^x3p3nYeZHUvgVzwGSu~$OUmMAk_cPU%r23{^!qE-y#BCLEnw#& zFiQfImN6l3Wua1#9dsF_tlVymD)09W;%+*+6w47&Ix@=wSxIfV-u=ve-i581i3oJ{g(?XB#M(Rb5 zxIrrb@fcjDJB)o+N;n#>l{gZNQLd$;aGB~h^mh?=;*oNht!U8D67HJnxqW$j&_UhZlTc_Mb`#Z8_l>sP8#kTwaKPe;baIW89l6g z0|3@n3PX?e+S((FyUB2pW>@A>B4K+a+4p3>)sR{VMj~O7#RS1bQsiOC`Sg&*m|qQs zb_0O1yHRRV5*t4AGs9i_@@g>b-)v|cObDT60_)oE3_JA5#&&FTwJvptD?{M<*3o zo!yGZ3l)<|LZ-x%46CchL`Hr0w&LMpS=*_kv0@3T#o;ysX!!1WayMU9nKWE>GDhlj z^q2u8HMN)wrfX`wR>sc80AuUSQgLP`9*Vj?y$p5DkoRFk>OLXLubN2e8w)N1!{Kg7Yb(d@L*B3Yip+|i6w2(veq z@&$6csmH?$#|3ti4v3T}%h%?!AX#g4c@^QHxZA7(B1OvP)wxuT(5|-+TO*sIZj-DT zDGR=f^*9JadoPn&-%r9+&MPy-RH=H5& zxJboou6|xh-o`EZaydBk zAW@7KRO3#QM+wT*>|7w1EhT57)l^0>-fyz&5wV()_UF@u-2EN27^92~Svxx@LNz14 zSxRJ}SwB*bR{O{7MiXD8Vn$YLi9~r}114q)-4jleK`vI)Bg@rfq`bCPBvw-Ty-tf> zsZdel^Of{&ac3nDG*a@3o-U(8r=lk3pzLlgzL>=TkT>e?Hp|Q^T5KVo38ykkNwiVr z^m)3wB;6`{bTONb#0#s@8d~Q%db=GGmzohcTFM)g^Q37>R`_xEqJJ z{H1D5)aA4|RSpw9xwxATMbYhzLb)ck**op+wr)mhF_4W%vFLKPR1?@8CX2b-!AdM{ zB~x(}oQ*>;ue+zCqr1x`h%atM(s>x2-i0ch&R%o7z1uC1&u{IdD^pSHD@!)tJ=s+(x8CQ;&P(wn3|E=fYwZrO=U;wGc>_j|@vK zUYjEM^@B73&^xE>-dRy$A&%a5A&L zY?acxPp=(xw-u-F?2_vkw>rI=tu!5b&29Z|U18-$0BE8d>hwakR5wp_>HA!UqW_v7 zBi2~l`TMC7Y8dY__S!m1p=+CUQjIBEy&Emn+eW%f{aqb!^!h^-KPV2|+AcOU-Y%2Z z+Kwh}Eg>Y7DT&|O$^x1`OUFo;8c5$;tP)X{IDcy`3TQn>@DnZ2hZu`rU!B`xSPeq%paahFX&Wh+z~-aA`7OFp$6*b*YDGSGEndbr zd^9{4q-s@k`j8u|2m~7;2xW5`sRuENN=l&&yNRekyoDnrCY=O6NYP~iB4NzMAP6P? zO%S1xXwY1WE97AHF&CFAmiabv2nA!nOGz<@S%b$s0+v+j+sYus8UtOA$=P(MIMOfV z%SAq48o^*{b33f!Qu0}^S1MA9@KmbRDkMU5Tf--3;(enkky5<1o2tR(1~Id(78BCJ zo-u=|me{e4b@OEMNFWPCP?cB-%hhPi-#PB#iWHfRe7Ojf2yjBy zhJ*r!u|Y0RQCVpnEH&Az8Y#FeeYaOgrs}c>evD-F2EM!RO%jrsM!cY|u ztKhX=^&YQ?F6OKx%LS+cRv2PAyb@CG^NMIWBDtG=^` zR+CHOE73B5<`HXGX?f{n6t>07}Hp;<;9BZbQk3x>&IZj;`gzP=4N z8@0N9w0dE=WZ38B66u=kHD9eYrNS}NJhxaf?(1XI=&Ia}jat3hzvnl~{(T$=+WUQdI}WmOkK=}JB$ zoa_a57xI#RHvynC>r0Ugl+TC`_B4_Yvl5SkS|>7ql~^{P&xj8@u>59H+SA2A>U7d- zESm!}k|TB$3dY4QE2~x|Q#bLpP)y4Xb|d9@On@J(RGTzkFj*{S``x;O;{ zrEmKarD9gP*Iq9n36jgk&D2rq&PK8Vg7R@k9U`XdPCGY+*2&vznMxi~dTkg)2Wxga zH(hNKw^y^}Y(>*+1InyQsmspJl?a5u!(1s-)w!(z%)|oH&7-S z?6A?`LLCUr;|J@8UOm=iGC-r12A8VM*jxrmVWvI}Ufh|W-b5?GWh^zDETtOe0ab+{ zWP$BQMgf8Asre|B0xVu-5m2xSZ3bqphN8)(ND)6cB+ob6I0dDFk%0j;wh{wVK(|+x zs~dQr+`veeNI-Nc0j8RcK}ojWAq1s*db&s^N9Ggw)!lufOx-AgM0#olq|jrt5jcx^ zJi>HSFR2LI$@v_Wm3**MgX%qQUXrAhAwo4JpQf=gvzyf#VDqqIbd?+v%Fuk4#s=pe zLJgYPLyZYEil#t>w*EV`w3s6b+a08sTq|yJ#R!-qGb;}l6M$N0A|zBDJb*2(7IP$e zZGAb^FdLPPw8qK+n4$^<66tl{@^-zun~&r*4tkR*EES6Yy}q*;s5zaqa!KoCG*|+t zP-@cZp@m?@?Iz}7otq6X`GrCmpfsYhA-K1vk*ex@xg@F}mxl?&X6$|#b-R!htRLXf zNWxsEMkF-j(_y01R>@S_hXgF5D3?S?Kr?YK%ye`XvQ^EnghS?o5ro{t;&(zkXL~+_ z$VZi21{Vs!R05i~6O!~ObIH1Rtewl@l!HYY8BW{_D&3My9OI9g`Fu`gJ4dCIl2gGp zw=fk$c%yb9UkLj%WEvEo-qyQB@mQ5T<`MIx@MapImE$wp9S(6gUSW)Tr94G>D^aJy z(Yfu8Zc!*vri@Lo0SpERM4KI9=ZbF4i=i_{N}F8N>1eATKC~`CLh_}&7)9ZC#dLbq>8ml z=fT5#dOZ-ym7!92S8lFlDs{*>c}z}f_!8MdsT2!IjpYnN$Qk!O(N3suX4BbHITjP^ zis=R^-9B;5Ohh)obh1>ACxvP-O`s;)_C9VWA#24I2Br$)B>=-((`(?CEKmsoK?nkK5R}Vg!CV2%A^=<= z0Il)bNVS4eC}akMLclPffmAA`Lhf5Vxe`VuQ@9d|RAz#fETuSJPQGAE}KQ6unCn4?glx5B9zh#WHw7c6Bz7PiM8J;WLxxv zib${28tgU=*U&BEDZP^>o5!G&lb5481n`9lP+|2(G`#8aCBf;H(EQD-m#&_>wGh~x z{W`d^wD}-~fiMD+F(3o8D+R0&kAhJcinDapDw{|qS8+#cc>13YRBT>flPUb+AAoLRpB#qG=Ueg+x0rWVE}62Kv2Y zhrCBd4n8;e^!I=9s+A{|R&q89=g8nNKdht4pvf&#(a4cKHe*AHB5Xw?4hhJF z6oDsE;NFumOaM!v7STo3B%NR)RwNoBm&{WbdhL6Fg<#6JIx~Ii^2XGS>E)@Z8DDTV znv54x5Q2kr0)a45ZSp`~~{oXOA_r3wmy8>=uB%#kS-wg?pnPytPD^GG!VM-Mq| zKmW_I$G`u>AODjy$2DMRqW}OY2qgm0jz1U%ppqZFe{ zr4^z?t>mdk_UJ5+A9d+z9xlOtP|w!xJ2a-9ct%<(QP^~t0>BsrC=notS7kHUWCWx0 z3V={2(QuJc6$(x-FRZLhZ>%oQJXi{@&abQ$GO+@KN2H6Cj8#A)0?2fcUMe!~J2L7X z8nrtG=1KbHAQrzon^|6+f8bwR-6(A?uc4@agG~v;6pYIVh7l}RMKk0^HC_*DKs2Qi#=lWm9G9|0Zfv!3-jS% zXl-hKHk5*r0W_Y97qWm}!efAHJeDy!P%1I-G+|3c)_qRf#ED2&%wrgVp48+52t!(aGn2cqE1iplku>Ebd8X_Y*(<&rcl+QcB?*#3tu_acC)4^=;;o zjj%sZsYYW#nt*UC?2i`WRjCkZKrju-QIrY>21q1qGD~MwcI)thMwd%P-e<368c>cv zq)8ME36E`13pLLE$qAZd^nlH!G##1FF~6hx85dvKy#Y6~uf!dW&q7)q6pl~sQU3`diz$wF`~4)Ab5u@c-|&0rJ+ zK(hdW0aFZ4sZe6mne;yNHSr7$63m65CmMGfbwIzRWWu?`=ccJ2h9Y!^P^wd?jlG8cG4I5&?;U-{?bb@2o_;P*tEA_u zK%+sxK!}ip;1-?&;u|~F=vuM@`)*A6)*dYTcXCKB2e%~b;u)wxfTI{drpT2B9)b|) zDgREa1ZSf0SZH-;Cm!|30?SLw^O<-735H>8WhYtzhz&BE!5|Bya*eLrqO=Z}EdAbz zeOB9qMZ?or$RY-v%$2ekTC-83*139}y(4=jp4c-vVb{vF2BV0^U;%IehD$J(je=0J zkWA$e1cx&jC{ig|3Y5*| zG6-A-MIupHta{7H=+J?KM~^*m!WxAFTmtd?D`cQ-CYKCs zL^F8b4<&)!?NE64{vw0AGjku)K#Oa&PSv)LVsQ~ejJ^>)z}WLtzl1aJaHKqNXpTMp@UWc3_VIM)4HcuA$A=-#Q$U-!s5&R8nqnUtul$(WR1f@ ziw&NL0Z_zh`H)!G)onK0`v>J$7I$KiP&l4UwR9N^kJN;L)+o-FNVQn9*P?1Sc6N0; zT#{=G8#}wZk5v9z%3Uqx_tsq7)~P&!SUPlAp*MBgT|K>u+bjN1C>)MNS|Uc@DiKv5 z3E|OM9KJ~E{H081wAvi59@(vB-!6V?G}e-}!OttV)G%8DV&7ih@Lxr;wvJ9~w_SXD z#TSZ%qtW;y`D3u9#?TT(B~fUt%Zs%CVwUMlT{eePHMP1OdZgPNZCRRW>C0EkP#HmM zbqY^Jq5sq4Qklr$>9zB(2hw=?O~HjkqSz$D5XRy&5=oQ{RI3yohf4dap9+Lxo!xEc z-`+~5!@DV*sHJn&It*1w3|cx~1_<>!h0ABNAOB~wSl-^{aA=lSg0V7`^Qdyg^ zgA&;e#UE)#lsKhg1!-NfnT1*+kB@XAS=J|>>r;qiY8^G^+ev1U;YbaJ%Jc-!51!;Laq786ZNTHc$d7mrmf$trj5!Bk=nlpKPO( z*+yx`x1G#q6Zq{?giSOJ%hmGoI!VUEb`i6Nw41X2=ot@zVv>^*%h~eAod+3OY0XDB zNsG~%!XivY2{IlSuS;Z5n6&R_Ps^%Iossl#vxp=&wqYuofOv9tC5s5;KqP`!c_?3J zQ;JmAGe7k5NL-aLu@Q);qPyXA9&cnc01r3@msZEI=c7s3B#`Sl`oyr5OrjCPYinD9 zo!xLOnZ=# zo&Z%HkA3$kw~Wtc7VwDwRtqcz0!(@nBT$*G5Wu-Qg+WFO`L2Tp_c-KCEWaBJ`_}_F z%S&WXkw(ho$kmcs;gL7%q$XU5$`2elFsv7|>iKj&mrNB}v+ZG)OhPB(FuWK^OH^`!Kq^6?mgMZCPxTsrv}<_Jpc2@b zUEXYo-N(~8h(Y0~3G-kt~===4&LWL}avgDTOj#DVHhKP`FTpt97Q*Dez@c%~ z8hV|=DD4IkFtMI5Hc3o@rpr4yu1;@e@`-4^Qp&_~2$8Rlwp;W<4v$g=a}Wm9zU zk%*O6wgc_jc&4qQu6g4zkCrQFlVgzx zOecep42BlyY(ch6-vQA|Dv?JT6_lj%^xF;Xa&~DuRBSX6xXI*ctOm8gNH4?!yUAp_ z2v_o%B1#d9Iy@r-79pjPO~%s2YPFCn&~yqiMyVzIbBntmo-=hKg-YXe^bGAgaA4FT zqU4hQSLK?d(sD_}a&&j?;cn|oITS6IssN|0t*d{?C8v@~iFg{ufgDPd^?2I&Tw*r7 zzLBlq{;bxZLJ6g4IyyZ=0|pkc8js?aFM;VaBGz(hU}W>*{Cu#4AQ+j+VzLDa+r-}e z$By->*vx7y6w6l%(MVaS7gX~R-^1Al8^vk?uPu#gvE1P39S*nGr64yE2uDOj942x) z2fXdfLM##UZ=?|fYDsLD3J_85?CRwutFF{F!i)DFOij-$MeB`H9-+`0MVQy& z_Kxfs9dqz&MSzTzYb>3!$8Kw9#Afbo<`QdLS&UeTML>YiBnx|w9(Ec!4LoprC!Nnk z6GTOutiJx>-pzX(!QDiiE0KtVN~6i*@gDn&KR+_qZx=znt=))!ZL7lOGi&SDuUxq{ zyW!tXlnzq4CG0(TRs_->RaQ_JX?m1|dT%=*Le9Ku#=loGk#KH%MZ=+B-zGUPV#knM+S z+rgc5ohhJ2ZlC_@`t;Xm|0v8hLccw*T1w%YG*ewd;=r`0hfk%V=%S5zBs*E z1xn$i=^&?;qp(;!nbzDharDWjpFA`+G=AhUL6ynka;R_|hrFpwsgh5Z7~Is=v*+(q z#Pmj$Cg6#rDz$<`7m$mQWK(TX1OA!$%_6zr-&~Ig4HW=ue0cT2RxA-oX49Ecogr46 z9R^}35Y1%6+xTrx-&@Nf<#eCyyREa`^G@v1)XVn9pof$Re56WR%up8@_lV50fn4-^*n2 z7b0m2jVSNme`wS$V=&D}$A>jw4y|Wm@%7!*gHJ!a8WwUGz0U6Le?OPqT@7xotjye= zxpQ;s&g}Bsm5WpNXJ&5STVD4C!jTLF)f7K{tQuy@Na?DCXB-@#ICAK~h?XUEAAIt= zov~=$FeHonAX+0E<6F53tz*zTwCC`Xk3aY4-<_PI$e4Kf!?!VmgN@MA%U_*4cWr9L zH}mCZ@gMxHw!-s%@0lJ01EgAe`uiMRau$_m+IO&nJb!lGvaerU#gu*ajxM0tZn^p( z0W_c@m^gF!%r}=#fByN0AAWi1=H<^nId$gamBW)a+zFjU?n!Qi``APXkr{)KrGnaPqWJS9{gped{9j=kFA*V_qZxqyr zfAsSwOx6L9*VEN8I6kbe)ONpI@)t{l22pw!uie4T)f->D{oCW`uV1hu{rstOr(geH|N835k3aeB<5QGvr#^LbUrFfZ0rqSsX2H$k#nZ13T7VndP{fqBB`Rrl4R;%W{7(vkN;{5Yp zef9Y_cUJ>}_4_x@pE-STdUfN$g^%C=@RKjEPH)7aS}{?!{_dJ*{GwZu)5QN~m z>@j@N|N58TIk8mpj?q0um`ipbd?k@Smp|yM8T*mRsPBaB!6oK<6t@+r${Qlwbew$thl%Wbq z;q>mA+&gGBxsUz$DVLNbu}wVrodf$`T3?xdu>AZx@4ouN3$MKU`RUVNeEP|!r@y{* z?cQo6yn65Uz5C0)ok$krDD~c-J({}x_s@=7#0)9|7AfkUvAu^Ln;h)j^Yjm&9oI<| zma%7l_KTnW@RQjG_vatnpZOmzAAjS`cRu*=Td7*?s$+gy7N9C_@}$k6_y&phTe7UQ8-Mex9{pWxE z;#())_~Y+i`27nnz4`vfpMLtuCue4NvzbIF5D55p^MFWa?;SkwlSk9Z|Ega?fXfJ( zBQv{4Cl4LiGd_9jJC6;UwT4dT=&>LDr(Z4QeD`OkF245sYaf65?n}S@_3vJM?fp|< zocjEWFE7pcvk+9kvtc_~B@2x`1K#~V_!oT5e>vJlER_jDO?$i1;q~@7dx!V$9d+v4 z+6_9KHh$-?|7kwuo11<9<(FRl@bqUNy#B}Ez3}?GAAff0)MsCuzq7Cd)=2;q*-cjf z9K?GD`$m88Xrl&Y089`W9esWMqvKw;-R>Fidfkq$F00Ksc=Tu20H7FMxcU5xZ@zir zy_4_0`upF$c>IGe&VF_J%ZoRsR>D<=kVmdUaFZdk^bYk89{8KqqEB_QFp|LF?Cl>O z#tm&PWpTLs`|RCj=it!3Lr-tR^~CAtUwZ5P_g;VV_^U7c`u8uteEhwSKKkI)g{yZK zqD`Tc&!$nRA`RZ-M)w?g?jKtoJ!s-FI1;_vJ32Dt9dy~u`gWbh>~#0Kojrq-Z$vVg zD*VFnS6+VY)fa#BAOHJb|JVPJ}B9jS$l_H&7Y+_Y55i3!cm6iZ_smP&J5eQ`~(=ige zkj5%mgvQ7w1)_QZB49-XD^;4!T0>mO0qJ5RDPSk*l0a0eM8R^SUIwc;a;yMkUM;vr z=dwsx0W48)z#Qadw|UfEDh;NQF)D#dt5LIgdIc8eHbELpF0Y3R%RCjS0>!rZYHFEK zMOh?TBgf)4Fm`J+2Fj!qA&f<5Eu$2kAdu#3Pc@}uLBJtn~J2PVVw}=r`K}KvXq*kQecF|ECQSwRglTq z3@`@N^dhQ+4wa}(UK<+C31w`0J`2VnNs+_>@)ZhByK`hF8-XaCLcUf9R1yKXNyKwb zRZR-@olR84YC;9NK*A*^BcNPgN(I-b3LY8{rlDdHtd(nxWI+PO>)AvJ;LGT!Z=)#X z5Xj9;89{_%W+>LA^2J=7mBb(lMM|w^h%6=tg|bBgQ%NNdY6!W8lIeAfPUZ0EE#Xd# z#i0<$EJmHkBx5`giNd7P*(8+87RdN48kcEY~R^{wq}9YZSF6j;JReS=7*3&mmq zpNQ2sLXlWRCkrG>rJT!VGnqmWm(S<%aVRGd@E8mRPa@_DSuCMaCBlEokq9L+kx1U& zuF`7w61jv6SIQvF;c@B2CY&usgImFnFP_^C?)nz*PtQ#+%wNBD{qp_!g@t?frl%e( zOy9eG<38T1Vl4&d?QkrLI~8{Uk^D%2mc|oEWMVN-EY}(g?OK&m*Vd+KP24wjbaZIj z)LLD;sl#YgDJ2q_K%|n&m2xFlET*u9OgdjG=Wyjbs!+sdv7{WffX`u}#C$pzPS!C1 zsniPTTw--*e&xYdWNmq2=I*s?cfUS&`O~vsee%`W^Iv^__UjAR=a!b{m*?+q21B`A zgHWZgXiNrM%#(I#+bx}z4pXueYze)6nvqL8sM7xLhWU(!_ZrvnA?EA(H?i(xg%u z0)dRn)$$ZNDVvW2Laj@!vN>=bVAZS4CY^*Uq#+b68Y&Umy+B%GSK8HqZ)|(Ux9-9&lZeFuqr4jI)k#htJ4y#?k5=z@8 zDtC|Kk$LV8rO}`jF{Mlt%cCSRlU74g@#xy(wM#c{+{4Yg_Raav-g)o+_uqNpt(X7s z`iJko{`!0Go;Zt>tZ$|kcS5`VtzhdRdkyBOG}=yMTZh$barQVJ!{g%zj!fXFYjm*R z(`~UBOy*8IP7PY-5ix*@drvIo(Y`g0PR0|JBhs*$It5!OX_r_$CS9k^(Pit^DD}EF zF;mQ}Rr7TUnS~ekWIVP$bLsNUn^TK3cdws2d+ME&C*Obll@o9N;q{L`c>VPg@4khb zcj@b?g`H5SWnMf}tHLDQJhQP)gL}&EbUKE{#t$6cGtn}y&)sG2)SJv^Teq>D&tx735 z!5CSo(wj{xoyBB!xNVNHvC)IA%^e%__PM&PCIh~?-4=t2&ts8@4HAVe6ye32+M0O; zGZ-|y#))wAxC$9dq%g{)?hduZVYhVkbSw2ngNBVarb;eHBGHL;tP%=u-MjJijhojO zmhN7=a`9t4V_!c0)@!f5^u~v;zV@4_3db+2v;x~Q!Wr2WhQHf z-RbG;c8`wio7}r^bYNt7wAbY{nyeOEm&qvL^4UxZi9({bbnLl!WdVqFl*MH51rmX% zO~F-hnS6sut#x#2Ts;<(vAa`cG#hm+HWP+Z2@;8lcja<09=Uz(+?}b5zIzv^uADph z_US+U?xT}0y#C7Z6R*Dg<{NK+_|4rbw{PEkcza=OHI~Q#0L)_JO+YS^IJ?ZfZXDhX zq*>pOCz~-@V=tXFWk`tO-4uiv$h&k;V2A&;K zqq$9OvTEHft4?Dzv|GAOdb&Uem4Z=#NGCNL;BGu{{p{IW=U0Q*ZcJVHWA-ahf>`)96RotmF{aP7jm%R7+-(rgf=3IVD0+}G0GJ1{obJ3KJFcmIKddj@;^ zM@L6`yK$E6!CfdI5gA+_hsU6^IV^GmK` z-g^6;Pp;m$@^E%`?(!t3)hsfj&Q+Ux@XhQW81?k;-*b5X@L;cZYuy}uaUQz z?G~5Yre!nedAu4oC>&`Gg#!Mi8>c_MclYwj!%LShoImsON2gwX>yIzI@IU|c#Ooh? z@Y#*a_cs@pZ+!IWm-kka2%*W5%fwVtvx=|m9o;uRJnkJF9pATic&OhqJTg3DclOx( z`a9HE9UxFS0s)81XHc<95yS{&HjBxlGC55$Ln!Afn51@{!qC~(sUGsGO&VqEx7SvO z%OqtIs_DcIh|$FS2C=@iK7Z$v^EbY^DW^7S((KK$(6myf^p>wo|CACABI!P##v z-CkbXocij6_fOwjz(F-rj;9=(0+Ph?&XI}9@%A+?xa%kwBN=m_Q;Dbec5=i^F8|bjy@Dkm&4pcK28foElOJ#ljUf zlfy=;n=2bPE`0sf)!TO$uHC(N`r}jYzI)=$H=qC47ysjTADq7S&83Cet;N%ypFI7| z-9)v)YSXD$Ok#%0=2%=4`}ZC?I6gT%I65-e-#gUf9Q5=J^bL9p?aC$!BUtM-aD|8t z7c=oVRHZU_ViA`@rsGISAm#|Pe14Z+)9JLE4LzO0Hm%O!8FF+xE$xg-wHQf8VLDB~ zf=ki0hqrH@`t=+6j8XX(*WP`TM<;Ou$3}Yl2L=XvdR#8g$Z(&tL(FO*l`6*IO4J%Y70M=J zi2`mO?l3luM5f^J$K&xeD!I;}GdW$>_D-Wvr8AnGy?wTBvl6J43YmB&i{RA~%A{8w zEZ+I-!j+5PTz`1u+@&wxedkZ_{`R+j_|0$rc;eEPOEa@eOZP8+b?S>V7v|!5fmYup ztaa7fJ5YOP6UiP}_bVm=j1riv)Q zbEa5@c2TlUZFF#8y#*7-oC{Oo!R8@cq|s9oL_?q=~yORXE7--m|0j{y>a@& zrHhyEthC-OfB(Hdz5TlvUi|IvUq1Qy)oTxCm!@xAJoDw5vr|iP0$0~AlhEo7GC`;? z4UQZ-a_F(6`}Xy_+vZhoM)zTY+AXrO|3CmteyBqYc)bzrCfpX(P*JbXu!F+e|`DZl zeDdLYue|iiA76Oo-P31p&CV}OZ>om z_{aA?I(_lx{34D4&z!q<FP9hS`2v6XHgNPlusp+P_16gW)n*b^Ort9^YxW$cW16&x$woCuN{BmwO8Kw`OBY;{brT&Xs@$M!w-#IYlL2Krn*J?ryZu z%|0fR7%Vo6(S(bsWHJXMO&T4yj@gnqClY8prMgYuuI;oMTliR_#IcIC(_}L1q*5`9 zR@+ za?T`3kRU;F@@QmPvcgumYW-WbYVDQ0w!CtZXEd5T3}6I65G0655IHnL=bUrSVef0I z+*LCqADig&oqO-O=YFA|UZ+*Tz|0_EtGQUj6N;D0`Fzf8I^KQx=+U#e4S=^i_x+#$ z_{V?$_bmwQR6CQpwHOPzJfTd!Sctl8N9(WV9zC94-rQVyarZm$?|=N$*AE`dzgT&* z_H_2)lf}0OXBXCBJXazRi7cK-D%Wb%x{l$?AAItYPwq@znHU)w1S^2L?vPf_BN4E8 z3WZE16R^!nA)P{dSD_my2}ClLMkj-lq0mHfg;LkvX3%TIQiWUz@Y>o9YPno06aqYA zt(5aSJ;8LboQrwv$D3<&vk#s_Pg{BZ?1!&D|NM*Zethr<48qFGM-Lx9eX)OHvbjRh zOree^viU-VRx3y`sCC1Ze5!k9UkoO8=1I#b)vsp!)KGw)ms{kjKfq5`CK}c zN@rWQ!+|@e(kKKB%-0N|Os)YyT9sTRRjE|%ooxn#ULlr<1OkbeNv`KJK8MQ_LAOZ6 zY)9Lha}OUaEUj&<%|E^W-Pd1!^I-PL^B2p@^G_Z;eEfXv3%c7E9)cWrmKn zHho*y*wl>=KDa$|ee%*se{VmKH!%o31#J;Rq)-?Pa;=i+BuoOP5OdmXzGyL@O+>9Hds~Z-9?!jawXrh) z?Ebf3e{=82lV^)d%P$rl-h1?9>FvJN7fZxphD_tpwX+V$6kU7w$kplh-kZ63WAgG) zch|u1<;x>I?GiqlNkfr^hE&ccWAQZFSsv|%4)hU86ts0amBHZ&6wqTk)Jhq|R%b9k z;^{OpnAJsMsZ7GfH**oc-RzG-?j`(Z#>3^sr%#?PF0U>xJbm=tw+|jaU08gzJoos) zz5CA=U+$gyBdKJ}>j|ftEWX;%-qqD+=gT=s9(?NeIkuO$2#fpVo zzEVfG6p_$91zf&R1)OOCom8f2N6|1Sw{5tU~Ka0O$hGP z2x#8u_(+#Q#AdOfvohgDsT5*9Unrg~qc2*{XVE=yO&p#?gMJ9`#Bv>|vQ#97s_pD< zgEUl1gj}vr0qspDB$x6LH+)|jA3uAs^y2yA($dS7m6fIW@4)#zSX$XWH3bvNc))yN4<(6$ zw$8r3zJYNoM5fjoy1GIBg45#!R~e`+L?;U6-y-| zE}@x=LwLYQff_eU#audrZr5p$X?&4LCc<=VQ6I%5s%AxchMN<;L5c-R!VbEyWd&eiQU%!5B>eBe2LCs@=VPf+nGMRvdspcXYRZ9Ck24eZ@t+}Ji6Pfm`u)*k=x)mPs>dbYlA zbo+w=pUdfVdi;qdNuuu@f>P*f*P))?KXGYl`o{ERPrHClArPrFmOvzzFex<%t=H=d zrLtA9yyap(lS-y?MYIvU1f`uwz=QG?sgaNBY}YI0XopgfTqcz%gO zj3(3RxYu#8{_5e~`?K?J_s>kGv*Wc_vp;uTaJoI7P_jYf8@h%^ zhll#xbuxw0&@(nMb>rssiB6r63L_!~eHWfw#KV{45x>vp3!~e|8ud!K1utJBF!(}= z9E4XU;Ba_ixw@^r6UfslB#289Gz_UsjJ{oxSWU+KRPb*x2{t>XX^KcON}n+}N@C0s*hh z>h$`-Q01yjzM*$uVzjSYr&37e8h!8Oshc;(2em934$}m9Y@SHOqE%Aypg(|auFVyz zwR){u$fOb(Xu2$}M4@Hi|=r5N{F%_fH@kxIn^ z7bhD_3lC;rtn5KLI_-O}AJ5*Kef0d*_JP?K@VhM*dmt1~B=a>o7vQ0b0|tc*<_%r< zrK>luU+q!Ca0oV&%Hr_(JUXtPjsydtXf%<^<;$(-;?v1=wt^*c_>lZcg_zG~bHUWM zA!nvh$)J(}7tkjLX-2MsQZ2>3PAkBRAb97;+pnHKdb+T2Xm|OXmaP|$9?m|Sf4O#G zwEO%>Q=Fk_G6&-pgQxBr93ARM4g>mg ziDV`ZRl9U0j(`+tJac2ec4VkqER9rZgTL9*@VM)$?he%VKi) z!-+&BU_ID*y)gHDW&gzG_uGz_pFey2WN~S2d*5XDcw9EC-5pJ2!4uW7JatdsP=9Zy z0h**(qU{}?gi%AqV-Yb}JTz1;n@%NEiit=VBAZCW6KQC*)nXo+Q=y6{vjLu3E)jrr z;E6OkFe+M&0)7zuD4a0NT~$uhN^FT^73H2noY&S_yY|UCT)BJ zX8c$*8c!w@v3QHVLLRzWsZJm>gc7AvA%x5W5!M>O&Z`i2kabd-9L69nn~mVH0A4!i zvRlxNriqx>da%3sdU@^bp4shlpKPr?pNBzXYvsyId%j@;P)DbpuOdf_TU!5Lymb ztkmiBdYw`R?L#b+0XnIW4`z(V=W;nTY#|#1UAB4y@mR!bGwpA0u5a!g+Pp5CadUNX z@x{vK{*l>Yv6|1$O-^?#2NhUv;HWHxuA>X!8PsB-NTux?8R_qkiRctEfkb1lm~?y{ z=7V%9kxXVXao{ipa#w_jC|{~HadZ~6Td|PC0Z%1S>huP!8hn8W{ENIr9tbiMz;Rk% zqk!O99N}m<;Ip0{>~C*v9h|w`j+6cM<(IEkx3-PvXe;rv^9zf|2cm`cC&E#gGHrWD zcV~wI#7d&k_YL&JWY1?(C?ql!T_A0i3fW951>mxoXgCy!rm~1S$lG!Q;DI9mcGw)~ zU`n+X23x5}1W5uyEt5i{esX!j7S<9o@ECU@D zP)0)0)}u`MBD%G>L8P#_LLm=v2O^>XYljQ~l4H3-CY1^WT(o62kIQ1v2(?Ti2#VqI z2Sa|Z!)m=S9v+^V%ooPJoi`hsTRSIbW~=4Gcnm|N)1S;#F?c)<;IViLps&LKvaC>P z_2^fzkj-k{8{8^d@Wr`YYqRHcJc6EzOGC-Gp37>IXyBAv2>xPDplA_!kdJbRIiHUv z0eA=eG<+qK3_?*lT!En9=XSYlW~0$~c6xGnu(Q3hvv+)Ivs+AOM~A0omp78lH}C`) zuL&e32hGpzdYxLSRJBf!fLL)kOa`DML&{{+nJl{7I-5x+0`?MF09R>Uvm!x)(wHE50+G0NSX?+VfCpv42T*h-^Dl!Q z4UfsELVm}^g~J<&Li0()qF&qK-q!Z+@!5sd?(%p&F4GCnXtqaEg;KTkP0mC-o(Psh zqlK4V4^usdfv!yg8$2$XOsEyXHf7*Yz#gX(01aA4IG%$E61r}^fyJY9Ky((28t6O^ zgc5?uhr*D_BmxebL8H-O(1T?p?U+1_{noP!n?IC<($A)oo{Qr*>pT1BR=Wr6d(h>8 zS~)U0yvb~#24;jprQk6*B3&d?YczU8n?b>6Q{H`?NFwGkunib^l8J1-g2B{^kayv5 zC>U&=cx-JSgLcZn6Uj^%d996A*aP4V5NhB`l> zgB}Q25tRb42*4g0y%;Q{Qbd@;-FD-N*^xp?i*1&?*0*b`Z;sslM6QrehyC{RGvhg^ zcDC4fm(&z&vsxokIC7N%eg6c9-YA#rcm`Vl!C_-+xkMZs6u_%v>i-Qd7|vC31ayN< z1IoG9pui*t7J$oyxru^^7ee_$X+b$aUnCQWs53(I0eCT|_2k&o}757*#&d-6oNWRoSXI-IdVH;oyNGyfg(AlY#(unnZzJ?>gU@H~S2+$*A z=+WB(+BLJ9OC?(HLXljRK!TEQ)+&WUwL#wJed!42*}th)P5YD3n(M=Udp5Zo<9J?Mzukr!l6}4d4Naa0@q;o zz(Ej54CuT<=(FgQ5y&--3h+o|^b84&f=S2RmWxwsB2Q*<*yL=?dAPf^d*Fyd9n{L; zVJsFKIOkX*3v)h^L;_K1R!YS(fhL03YL!fUsgTYU@eI%fJ_lb;BJ%|8t5gOBu9UNh zNGKQz$CByFJ9wo67=tE>%a@=shl3>oJT7`-iN$0v!HGdO!lw|40FT9_V4$bLtl>-* z2wXmg*a$n0_ID0W+^HrOUn_;&HmlX?_60-e=|>!NGqgWx1w95!6++o6BvcIerfdPv zPG`5^ zp;Mj${#3_A1-3hJ7$4rEhEm~t`(RwbCk zkf3Vn*@V|&GFd#q62PmbVm^<@8)$u@K)wP-4@9+rY1VR?d=1N$NX0A)u~y1vGSw!C z7YoQKLdQr$U4VR)s?c)*9(vd@lPi|7L=q8KuawIbWU0VTG3e;R8ks_c77P9wni(KO zcTtj&B_g5jNx)RW@I=DVOo0eduVs@Vzte6HMoUdBrjkko(Ve4cQpgmmXg|~%bfrcW z@~4Jj2?SgQ5f2b@P?lska3a(+%ETgicCF<+%f&1@=aWNT3ImCY0aH+`H*pjy16dmi z6B@ZRbRnNFnka$jqpiQf2wVcD zQy`<+K$j)zXg{-j9YbTWnb1L?JPXAt^eHkChpkt@;pGeH0s+`|G}z|SnOr_!D3mJ5 zW;d#pYReP=CMucKLPv%c27v@cg%_0q$iQ)+=#oizET#s@3a++ThxKM1VNFCL$y}k{ zsFn-x2lOmzDuwRbhK^oE_^RmiKiD=3m5hfria?<6k-%Z0V?k;ma7A#U5Z!9Elm`nB z;Ltt5khma)RkX`4WIm}SALx=>3l|0b3jZOmi^C!INa&I!2C|`2DYd@d09%JaIS=6h zSuKD$gRntfAv@kWB@B@TXf3@!cpz9fv~@Eqwm3zb`l7!>RZ#+dk^8I^i-|8BZ#g`?aCr1kVynac1#0Vsw5vrQ^gt{ea-#uG0)9ID{8|+~tq!<~$iARwBU@h< zm_-yIp#XGc^cU!mfK6ZnB_lA1AffeY3tYl|PW z4>v@h1X}a%3n&^0YwI7hvJd`w%fr9J-};EZJlfxEqDMMW6%ZiX029C?5>Q(rAX*9U z{v)=cPQU_VY+oXvoIw)SzXz5BRU^_3B?00NyY0n=1y;X$@DpGu}Pt#819 z1Z`TlsPgi`b#KL0iz>yuK7ZZ5qd zo*8Qw5wotHxmm|(yO^B!)TkxZ&0zx{m$JWkyb>Sl5EFB52c;;!Ii%%c;^y`H8{Nb0 zB7D}hOUH?(`_=4vV9W25RvaOM1{A=BETG@BB zIIEG5>UnS!>tQYTDj+I&4xZ&yk`Wybo3L!|b#M{PoO}O~P|X{LY+`PS4g%DT<)%;-Q3;+LS$F3CMTl=+?-#>6IZQQLG&{EE{+*7ePxs5-AJlTFtwq0MXYP;j zreS(Of!;|{!QxTSu`~b0NxlEdfbu4U5|7?_kaX_Meg3j}<@!MTtsxz!0XRcPMaS;k zpPu1AxHi}~4ezY07}d~0&bd4P#gp=f(*vV3!+LI61Ml3gxc270cx3u?dSLq22rO#h zoySG@{`{8@U;S!o;P&*0fmdl`*22e-LknL$xck@F`#-rg3X29rb!s{`}S$Eb3s=rPZqp~ zi(mi8tnzyQZ*Gsb3+gI%En3O>VDS%kYwr#G^1bm6VME2PhZ{x6^{;>bDF5-$|9JmW zhp;K<)I*e#|M|2&tQnf%oUmpVmQ1*Z|Bl>*00-~QkE-0=0EqeYyQ(+o1ofs>{0 z{%N7eeeahaOm>M0B6c&xhcGRD|GTG+#7}?y(UmR`r)_pb^G7_>Z7S{DT&O(X1KNR+42v+U99_l^Q(`idSqlAA6sIAbiBU% zyC)U@jo+X}3RZw?a2nBzmAn76i1T;;?Z?;p7*RKg>zUq_dK@~kG!*&btDck15fBO@YARzpFdPqahNpZa* zeA>SC=s&)oGX%BYz#=23#sUKw$J@vM`9~H{SpVsbAuS`XB=(9)S?BhXKmIF4EhJpO zHLPP6)Ks7)=iYhx`R^%uFJyJ^Ev-|Ax-{RqSxm#m;c1b4clfmNN+~W3x6YsFQ$aY77r*)kYOjh_Enn7i8?4CzRCUKMzWxU)NNCM} zP0zU$d>=0ndH=x36k<(Y-|BgDKHM-tRF(An<8(JD)(GLH{TTk^6mW6k0*X$q^B`P);av z8?*lw8SX^XhQ$QQ?Xh+tJ`IukPutZl87b%4RuE;k#@mI2jQ!1{&(E%Q$teZzh77O% zaH2y5k=uIwo$*eWf?D)$2?>VxCpyK%taIzh{oNU8UM2rN4rlmuqDxH5xwfA^+kd}X z2`nDDu$`Y=?vjx65YCmiH~Um9D2lffSnQUPQ8?eMU+Yt${D02Xe>B-GgU{T1y1#m5 z00<4AEy%jxztSV87Jd73rq`DSHC)L5m!yt6S0S=R-@&u<*W*Ko(2G@n=dEkK2*}|x z^XkwrBrtTMi|(1JJ_Q|sJh!j(kLU$xalhyGwf>e~E?GAXBhUwv*3F}V>r(?r!cSf~ zHWVX3Xv((X?3%nb067poedBmTA87*`?3)4h`1L^)tSO@K{a)B;A!wO*9K>9lL@qgD!;E1^^KbT1@usFHPW4UM)zHaHsL z^NSHk@M@5l^KSDd+C_x4w-&iL@9))cY5`K-cTl_p4kQzOEl&Lo2HX~ycf)oOFk7FGM2|0_!By5L-5eQO@U5yyyoOUTW z%fKWZyZK8x0WQskVu>c8&a)g`%CVQdWDw#D(ETrBwh<{cDFc6}qA5`tDl$h&R+Jv|KvJ>S0{9O#r0JB6gY z#}YYKGni6pDR26MT%$?ua> z`=r!z@GNQBS#uUAfoBm`$h?N=iA7|aZ) zoGN$LaW0u zq8WxTH{xdn_u4UtICGoY zfm-*zN3XvF`35X!L#KXYhY&35epsq+ncJK*6F!YvRfyW12&emfltp=WDteZ85(T7! zcRz_8ygkt=0hUv-v%EJfB^SNB>B89UOI_g6ywUh+$#<+mK}v?E?p*4UL1-c|Q_cI< zKrQ|X9 zYq8mgTh}?2@LBZymmf_bmSfgDu9>jC#nq#xsOcAce~9%7sv`2>jqE@eTv?KynbOjzs{!^f~F zz(YJFklRNuGI6UFEB!e_U} zIv^fyoCMPJbnSl8cEYXy?DlvkXuJm}p;bfY>)+KK2cp_v-yTOA@1@FU)$qmU{fJ{< zQvLOvOWmk`*fItj;+sc@u3c&4m#xL3pC@NFV&<(UPhER*%&*^rcu-4zsgeZ@Y(M?N zeWJvD20=olAXl5o+6cy0A1W!i`TuIPq<4Xtx;P zZf^bM10k_%dbC4CGVuD99LT%9xwo%onK;Ewh%v>$?@@zhI`^L)yq>KR**BrpvD*0^ zYA!DAI#@VenRSrKkPT9yUeKmNEFUfyS05a(%I{5dNo8#!y$-Q_^xU-m;4Q2C;Y63L ztzE3s@j-o$m&_Zp`{dlGkPY2!QjJ~!t>xs^#pc7qbpDfxZb^TqRHYY@3V!37_06MW zW9qX@J+g^Txm*uv8#vpuY(F{LEPOEDBN^|Miw(eX@a)jC{q*oOHo-g@d*D@ID`y1z-;Qy}l zsyRJUdNq2Ua2+n~Z!T*l`r6TAuMFaGk#QZp+}(I6nC$Pq)Td$h${`--Su3a6_v3gXjX3|m!oNX*` zy?B13=hn3WJsZRslk$`U=bJCLmwtG^_minXw8+7xL#2@E&C<@&*Y9_IbbZLc8$|Jl zRl?@27rRT}%yj?s#&8>d0L3F;jac3;?!Ej`)&1!-IDuX$g>0=7weCFMeRaRw4f4<~ z?AAh%aP^pNXW?LZ);09mjnQ^dhn7#wG8+lU-u(XShsR@|-UJbD(+Nl!MkDFmUpRUF zcyILMneh&(-XJ7rAfF&1PF5aob$&Dh386KJ$T&_BIcex8l?kXgIfD!|qo=n4SBZN6SZkT5%kd zpijf=QL+(t>&E3%8?&bAH}Ly4;yx7zxI0=mzP6q+8st`tmHlciKI=VRJ$>ysGJue z^9>}Cs#C1jjt}U8(BRpM<*jRnhs$9)C0gy3At*bjux0DMdxt~J2im179VDN)MX3GM zc|a!?-Q6;k_S&#P4B}>5cUs)XWOB*dEs^POjZm(prc z%Nu*xdtRheqD`5g4b(`6Sl%+neP;=3HRjcFI%h^ZWr*ds=DgqJrB>q?2JXnsu`W4c zdB;=?m@KqL+^A-c-57_(CQyG?3Ym}Sjf9oMzBV)7tzco2&I40DWZ7jmlgP-WnQAfH2KYtqw)m&F zCVLU}o)c3k?%3wxvc5y=Pi{~4sdW~g(FnAWnXZ@!^G9>Wv#2siZ(1AjyNm4#=VIx-}W}E2F)L(*>fS_HR(CSf} zulniKaGQi$iI@_UV#vHph2sjRe>yb`K>{*Tv|`x&h6S!Y6Z>>}1O&4hb*CAnh-IDK zNZ7LJ$?LEPLGmV<<*02#&`jF$Y2_3OQY{|K&?`Wb0F!o9Q^Xr%ouG}0e1=|)JKpj! zX=f!-zBSr~w6T<<)Dliev8<~aE#DdIRx+D$Oo7};xb~=+tiKk+OpbOV!6X#O&7}K? zh|5PR5rP3l4wE32h#-*1d0akKkCTa)yHy-aoKYcR)85krCSR(@smUw7;0O}*3J$n4 zx(LO3JwZub?NM=Y33?5K&HB$zu>}GqLCp^Kr~wGGRwv~AXZzFw9h;<-1tu;Q~bd6VmFjAW-87vA}xEu`#eZ#8=C}m0`U4um_8=s{C zp>OF}A+0W~YpWsl#ztJtB>WTIAqzfzwEzoQ)1HY6(!aVp@rf2Oyqq z1shieRk9}VdNIAiAryl4kU_!0=c$#LHIr|bFsf`qG31U2WgL8gR*hRS=?*~0A(Xm$aUkxnw%{=H|4AKt> zdfx0}kaTZ?{NTXdNuVT7WE-+<%O)sF1*+JEVv&U+_A(PVuuYS!Tlb!O?l~od5PH0M zA$D9cMpkI``MT6Y+YUd@otBW zAHRQbu(+BY{m;Rj?e%YOHS(k9qw^1kJg|)4yF=>~#Y`fqgz_8fgw3g!FAS976f!bYO-Hu~*))3XXTJ&k#CHWJvmE^2ieD1mO?@Tb#op2cG04!y2h z&dE!lywv5xOwAiUN5@Ud8d z)u^WH?dUyUBG>nn(nfOR%c=58L1IdZGeT>=K?{^Bzg*tlijE*i?GR&_+lnryuBdbA zQPOj?pW$4$JXJ^3Rl=_qxX5#}jLccdJSH;_rzmp?;>dJJUE{W`wb4jxEVW{)UTATZ zaZ*d7oplqK5%YSMFR+mgTJbZ9eW9382w6NWjJTf4nn1ZRmUKNVbj>v^h3~1siS}}} zAj(Er9h+ss5O!U?WDDNIDIb4C##!-1BBV;Bhthn(LZ(`7tF48VW+GR5iJ@{bxt=GM z=eabR%*Dc@B$JXSiAEO6Eu=Ha6y|JcVXRB73zYLz3;3%}=7}hz#9CW47x^+(!Wh%Y zwalf~9xbs-76e1^nu!#4gq09EgEwkK1TK(P%5ZEDp=Plxu(7a)O#K7Xl zAQoRU$e%V`6iUP%bqvkuaxo1(id4oC%9ZfitE(-fxw~H18JT87-vYam)av5Hj_#q{u3aLa|}7Kn^mQz$7;rf`nsbsEb@#_-<;n zp@`)sLIU!|c++DVvPrZp-L^_2!7>>$;T5*9SROPz4{&Kw+W;`r#8xs31s5c@X~VHi zQ91}aG823Wbxw#)xxSNRa^mGoD)x z);1!>)=DY_{h&E?VQCa}1}@>6okN!hV+pvXF`=-M)}<;6jZh&3G(@#NC2n16VRFlq zDyLfIRYG8sina;1jBOmLXaN_lSelAufp87-Zc_&mX@sN(o`&WTSXDbHAWXxVGytDM zWh%!m;?lB6UPxn9ZeU$)6&!McY-k6J0Bc$xtbf(j!+>CJa1FMj;C2h@rnRkM!_o$% z_>P5bTNhCGA}eLWXOrn<5<@~=YVwR(#BcO=dY!gIiHLz41Fuoj;XGz6BXzIkLmVvS zJkwIh>G0jj%U|A}j}~&u#F*oopYK2TAA`YP_O@<+v)1ftF}{BK!^405dzPTa9|oWP z{o%je+nxRWUzdOQ`QVUwB6&%?tH z)2oU3{G0oC@M~en?cIBS8vJfBxV86L<~4(WE$j2)*~QZXBoaA>B8D&GE1Vk`>@d8{$r=ED;QfI!R^h>zuopX*Yq_n_}k^Ex4U=Ch~+;%h4|$8 zlh+5=@sIpkSdFa*+gsoCdpCc#-n)B8Z-4&n;7{8(JLukE@JC!c(HLOH#%IJwdM10lmF<<5-@MVZTHT=6Tip)aP2Y3G#FaorCv#z@ zZ%+yni}Z96O{SJ-vHI#t$N1EtcM>MJIgWDvrc zI1>)a<|hgu4^T(QDX@?8h-k0t%Yu?RS7~VDh=m>(Gj_ewG8GDaG@C7j;5t!2wglP< ztyq%6m+D@JRZKYX{mffhm(Ff)gY#PpD@M@rkr;l@rO+ zP*^2r8u-#t7aS6kK$im(L4QI6W5)%8;q!%U#}U9DVIxWya<<8nIZ#k0GL}FG!>!cO za2-pg%Us&fe25_Uf*e9S3T14&v_J)6i#7<10t8_gAQJ`TC{R{Vw~jQ#gk|PHWABNQdj{d~!x6&*_JCcWlT+p8;e z;Ne^$m)eR~lM>hxqJ^o1)UOiekCa)i3S9G7NWmhh92-a=V@tS~_!Oohw0^Y;ZP|RW zsE84fR?l0!J5>$8MoFoY=_NC+>l3|9h00*N#G};k%cF783Tk2@4B((J?#e2@d>0Di z09WBUY$!=!TL|*#8=_!&vyW zav3kN4K!T$F;3>`(zCGu%oJt8kOgzYC^jcXS}aT)0$Z0Zp;BkUs4PXgPR%G@CMOx{ zwb>%}Ivp6-Kvqc9S8GdHpzq9dEOVh(eC5eRun^U0Hc8x7D7=ex^)5gTB_JC#Ov!>L zRmOa4X_|3cK=pOW<}D0!0RXKns4~O84N9P-j?h5L&=Cy8281s~jI1V*EGPjFLlQVd z3EU2?V31SY$Dt7LMi>$aX13>}7!;8Ma>U^va~LuxmjGTQ%1rUp0N_<&;8zz)08_L? znJNLsLST^#7qpL2bxmz(o|**l0}DY9iF3f3sN33sQHiR~LeMxcWZMAZOcf5a7WGj9 z@+!B4UMkHcMg-zlOIgD5m{KSewMf-T&{B0#2_0x17$Uhwf^d`rZlw_#h7Cf-G9*Wp zW)*ght4Z_e)leh>gkkcsf(bxZ?ph`e!NJ6R+CsmF>XgEb-N^PJK zHIS63@(pW%l#<1-Izxq(!Nm+zfvy;&_>^T39@Wh`(xokvq7pqBu5=?%1>_s{2#Uri zn*n@)WIk069E~xc%VB$YO+i6G2v_gXsB^JB{q?$!yaqNJ|%rhVk;WpYn(7?G+DHPoWn&34}!Pln7$!yFoSx#NM0bGF9 zbaXMlQg!dfjgCu|jG#w2%YnxkpGj3~bhoxW9Zkb1n#4(|+$OXI2u&YS<6Uq9&?o^04s!QKshknJY|cTM?ttIS3F$=y_S?KJ`T@k z&=Ya#*hFaKwLvNCGi6lln?}>XK+TY4HOX|$lqeUb;o`C8P8O+~ez3m!X@>bK8WzUZ?nT${!B{4D!2E+8jo6+kKp`cQ) z?8UR`s($w9;m`iMcMw=)MnF{Y%07O)m}C_<7&IDgIoCOC_%cl z6irV~-@U$CrM}m9FM2&Oy`qT9)1-&3c~Mix+JqnNdd*6tyH5OM z0y{$SgxIR- zx|lMP?beeV=Up%SwMTTDaibSNA(OGxxUu3EVC_8GE0{|1v$+9kr(k|yY=N70vKR(_ zL!uZ)1$UZOu2fwRRt9T1%mFrsQLEHgq_c=QI_L+T6^zav5zGFMI2~ zJzd+nv%7n5uZQ0sgue*mf2A5dIUZdvy&I&x`tf=6^vUq0oOJ)Z|JU!dS-s=?$h+L| zz$!PRpC%wNPM(imvlZ{F?NxD!*1mM&XQQk2K8&Y};K8>~4;nk?uMb+gU)IFSMZ3Gk zMw1S>iv!dCP_k#!?ax*_P`f9GjBVa?xoV5Y2X*SvAP6Vo+Z{J7#da@HlX0#W2NB)B zJQ(KlMBQwi45Or-ip=Y*lTr5y({ZB{ov3Ny&x@#i*KfO`Y=PhB*OO&Hj%GPySiDHU zS%GU#H$&dvV(fPRYIbo+dY99m-QGA@!NF(yWFCs})nl13wpSN@~KYsT9{cKTp9WYWN=ynkwjrC5zCzJ7{hOgGPc5Y6` zHtOo3Fl~R8eE8L`FRj?x+wofhfr=lofO-wh-=95ty#ANLcfTag>G<9tdi3;AY~I>^ z_u}w)Ywt5k|8VogtDx>5FyFK~Ys<^-Jt;0(5*@vbuGuyf_kvc>e?vv&-=Oc}aU$j5 z*_;1O9;ZCyzrB1eI{((AwBVb&2k)PFxWF+>gWtB|m~J(sw{bMC_59%-4ito!@^R^T5U zO-@*HazRcv_wKzEOKazkor^2I+cAx4>L!z4MxEgP78?C{GMc=(JZ*e)@BWQ;6u*2o z&xfp&Q5+wM!NTJgFSvd%)BN|&!=KGn(CAJ4A6UBA06=EC3p z{jNB8@`g07|H1BT<5245-C&Ny5Pt+FqLMtRV@ytXorR@_o?tY6wjTj zsdfn9ZxZ<19VQaBI7%eQ1|Jies)B>U({?7oV`#QSVR?ntYF*Jkv)P(X6BN?9iq(zJ z?8W&k;<^%TRu3kcl~P;YeDwISwm~-N zHNyoAL$K1|^N}n;9I454V!44O6=<(ax4S-2SORWns@)(kQb#~igWb}1PC^H~qVTj6si=2<~XvGh8=ipR`QSE=?^!^*XaCsSyBgr)X; z5O47;I+s3`7NsS(T8Lf6R#&kL-Ox)REtGPQnxHBr2`Igo=A{#~YlLRU=g-USUhela zz8VfsZr}ZqsG&SM@$S~1M&zy>vet&X3i1Ck{bJ{f?0q<$H##jL{L_Su&u{oA&3?N} z7L@(;Onmd_@A~rlhyS^L_kXQly%WSCVrpqyrC>!Td8_NmeDU_m^T08JFF}e?w~l=^ znI+Y6f)?BHuCJAzD+OBH{r{tHjQ|f;a1hHmOoQbkmJr!Ta$_`e| zRRX?crAw<a?7iy8P_>}NWv*<@v*aE^|V@p-h= z9w^N^$H8!?f7zHd`cb_%OXefnJ!Vu<4W^5h$e}*C&Kg@!8cY!Vaxq!8??NmN*-BKh zsfc26TSu`p4b*D4%uF_F`L$#^r5%P$D9eiK0?6;tErDso_ypok@6Y2Pv7vV}I-C+gg5h ze8UxO9M&)LkO$-H^a06c?iX4UA6G!GIv-n>kr7uqDqOn@?eIAn&ylc#+Txw`8YVVg zp4(s$Q(7JJm_)7mNb|_HiMq_G#z=uB&o!AzVl0}(QrHyit_G8pit41jR7P@bQIfI( zIi4>QZm6@2!Pp2xsF-sN#-2J3*j(rep_IU$gY-3%mNqnj=5v|v){7i~0`^vcD^xt@ zOTp`)w=^at&xD3;NNoY)Q1$tf5**tS1fm6Gmk5JJsK9k+0$G*c2WMMk2@|H;zcO}p z{AD2_tD_7l^XgNxPiG4lrq3lXlXK`3z$P{Wh zIp-y;PHL?d0_}r5YJCb8qE}hfPjyN(q$CHd6WbJA;##fxTm~`$5rJygsz8uoyTq_~ zCK1sEI1(VY>O=>!ju5dS`#P_VTR(krVxWY)2(?V%-PLDBP-n-MDmOWNY5nP7 z)TY(Zj$oNpE48!>T_92&A)36%$^xY6s&&R_gNH!z3~tOhCK!xUj8tNas1hWq$p~9f)#0AZl#~Xj52F87D3}!00iCvO17^DNNdf|| z&aL4&NOnQ0lO}~Kt^ynw01JRvXOO;%;c{J_PwLVbcn)xA?CL{DAV*xCPBLBBF#y`u qFvE>y+fY!koJG0Yq8O!1X-rj3L;(f3UL9RkM{ux3R4xTX|Nj9*nH$gm literal 0 HcwPel00001 diff --git a/data/spring.smp b/data/spring.smp new file mode 100644 index 0000000000000000000000000000000000000000..3c2ca086f7712744d32843d9ba7c8fb7ec832a3a GIT binary patch literal 7775 zcwWs{F^l6$wypx9Lc5C|ngprk0M>~iT8_tQ9xJvp@5r6_A<+I|xIzA3sk&zrVqw(Yp8I@TYyAO8}o;_&

&y9kE(T?XNgM@+?8-}4 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 literal 0 HcwPel00001 diff --git a/dj.h b/dj.h new file mode 100644 index 0000000..c5d6b5a --- /dev/null +++ b/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/dos/gfx.S b/dos/gfx.S new file mode 100644 index 0000000..1b895af --- /dev/null +++ b/dos/gfx.S @@ -0,0 +1,271 @@ +[GLOBAL _get_block] +[GLOBAL _put_block] + +[EXTERN ___djgpp_base_address] + + +[SECTION .text] + + +; void get_block(char page, long x, long y, long width, long height, char *buffer); + +_get_block + push ebp + mov ebp,esp + pusha + + mov eax,[ebp+12] + mov [.x],eax + mov eax,[ebp+16] + mov [.y],eax + mov eax,[ebp+20] + mov [.draw_width],eax + mov eax,[ebp+24] + mov [.draw_height],eax + mov eax,[ebp+28] + mov [.buf_ptr],eax + + mov eax,[.x] + or eax,eax + jns .11 + + neg eax + cmp eax,[ebp+20] + jge near .exit + + mov dword [.x],0 + sub [.draw_width],eax + add [.buf_ptr],eax + +.11 + cmp dword [.x],400 + jge near .exit + + mov eax,[.y] + or eax,eax + jns .12 + + neg eax + cmp eax,[ebp+24] + jge near .exit + + mov dword [.y],0 + sub [.draw_height],eax + imul dword [ebp+20] + add [.buf_ptr],eax + +.12 + cmp eax,256 + jge near .exit + + mov edi,0xa0000 + sub edi,[___djgpp_base_address] + xor eax,eax + mov al,[ebp+8] + shl eax,15 + add edi,eax + mov eax,100 + imul dword [.y] + add edi,eax + mov [.vga_ptr],edi + + mov dword [.c1],0 + +.1 + mov edx,0x3ce + mov eax,[.x] + add eax,[.c1] + shl eax,8 + and ah,3 + mov al,4 + out dx,ax + + mov esi,[.vga_ptr] + mov eax,[.x] + add eax,[.c1] + sar eax,2 + add esi,eax + + mov edi,[.buf_ptr] + add edi,[.c1] + + mov ebx,[.draw_height] + +.2 + mov ecx,[.draw_width] + add ecx,3 + sub ecx,[.c1] + shr ecx,2 + mov edx,ecx + cmp ecx,0 + jle .4 + +.3 + mov al,[esi] + mov [edi],al + inc esi + add edi,4 + dec cx + jnz .3 + +.4 + add esi,100 + sub esi,edx + + add edi,[ebp+20] + mov eax,edx + shl eax,2 + sub edi,eax + + dec ebx + jnz .2 + + inc byte [.c1] + cmp byte [.c1],4 + jl near .1 + +.exit + popa + pop ebp + ret + +.c1 dd 0 +.vga_ptr dd 0 +.x dd 0 +.y dd 0 +.draw_width dd 0 +.draw_height dd 0 +.buf_ptr dd 0 + + +; void put_block(char page, long x, long y, long width, long height, char *buffer); + +_put_block + push ebp + mov ebp,esp + pusha + + mov eax,[ebp+12] + mov [.x],eax + mov eax,[ebp+16] + mov [.y],eax + mov eax,[ebp+20] + mov [.draw_width],eax + mov eax,[ebp+24] + mov [.draw_height],eax + mov eax,[ebp+28] + mov [.buf_ptr],eax + + mov eax,[.x] + or eax,eax + jns .11 + + neg eax + cmp eax,[ebp+20] + jge near .exit + + mov dword [.x],0 + sub [.draw_width],eax + add [.buf_ptr],eax + +.11 + cmp dword [.x],400 + jge near .exit + + mov eax,[.y] + or eax,eax + jns .12 + + neg eax + cmp eax,[ebp+24] + jge near .exit + + mov dword [.y],0 + sub [.draw_height],eax + imul dword [ebp+20] + add [.buf_ptr],eax + +.12 + cmp eax,256 + jge near .exit + + mov edi,0xa0000 + sub edi,[___djgpp_base_address] + xor eax,eax + mov al,[ebp+8] + shl eax,15 + add edi,eax + mov eax,100 + imul dword [.y] + add edi,eax + mov [.vga_ptr],edi + + mov dword [.c1],0 + +.1 + mov edx,0x3c4 + mov eax,0x100 + mov ecx,[.x] + add ecx,[.c1] + and ecx,3 + shl eax,cl + mov al,2 + out dx,ax + + mov esi,[.buf_ptr] + add esi,[.c1] + + mov edi,[.vga_ptr] + mov eax,[.x] + add eax,[.c1] + sar eax,2 + add edi,eax + + mov ebx,[.draw_height] + +.2 + mov ecx,[.draw_width] + add ecx,3 + sub ecx,[.c1] + shr ecx,2 + mov edx,ecx + cmp ecx,0 + jle .4 + +.3 + mov al,[esi] + mov [edi],al + add esi,4 + inc edi + dec ecx + jnz .3 + +.4 + add esi,[ebp+20] + mov eax,edx + shl eax,2 + sub esi,eax + + add edi,100 + sub edi,edx + + dec ebx + jnz .2 + + inc byte [.c1] + cmp byte [.c1],4 + jl near .1 + +.exit + popa + pop ebp + ret + +.c1 dd 0 +.vga_ptr dd 0 +.x dd 0 +.y dd 0 +.draw_width dd 0 +.draw_height dd 0 +.buf_ptr dd 0 + diff --git a/dos/gfx.c b/dos/gfx.c new file mode 100644 index 0000000..5b40d0a --- /dev/null +++ b/dos/gfx.c @@ -0,0 +1,473 @@ +/* + * gfx.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 "globals.h" + + +void open_screen(void) +{ + __dpmi_regs regs; + char *ptr1; + + regs.x.ax = 0x13; + __dpmi_int(0x10, ®s); + + outportw(0x3c4, 0x0604); + outportw(0x3c4, 0x0100); + outportb(0x3c2, 0xe7); + outportw(0x3c4, 0x0300); + + outportb(0x3d4, 0x11); + outportb(0x3d5, inportb(0x3d5) & 0x7f); + + outportw(0x3d4, 0x7100); + outportw(0x3d4, 0x6301); + outportw(0x3d4, 0x6402); + outportw(0x3d4, 0x9203); + outportw(0x3d4, 0x6604); + outportw(0x3d4, 0x8205); + outportw(0x3d4, 0x2b06); + outportw(0x3d4, 0xb207); + outportw(0x3d4, 0x0008); + outportw(0x3d4, 0x6109); + outportw(0x3d4, 0x1310); + outportw(0x3d4, 0xac11); + outportw(0x3d4, 0xff12); + outportw(0x3d4, 0x3213); + outportw(0x3d4, 0x0014); + outportw(0x3d4, 0x0715); + outportw(0x3d4, 0x1a16); + outportw(0x3d4, 0xe317); + + outportw(0x3d4, 0x3213); + + ptr1 = (char *) (0xa0000 + __djgpp_conventional_base); + outportw(0x3c4, 0x0f02); + memset(ptr1, 0, 65535); + +} + + +void wait_vrt(int mix) +{ + if (mix) { + while ((inportb(0x3da) & 8) == 0) + dj_mix(); + while ((inportb(0x3da) & 8) == 8) + dj_mix(); + } else { + while ((inportb(0x3da) & 8) == 0); + while ((inportb(0x3da) & 8) == 8); + } +} + +void clear_page(int page, int color) +{ + outportw(0x3c4, 0x0f02); + memset((char *) (0xa0000 - __djgpp_base_address), 0, 32768); +} + +void clear_lines(int page, int y, int count, int color) +{ + int i; + + outportw(0x3c4, 0x0f02); + for (i=0; i> 2)) + ((long) page << 15) - __djgpp_base_address); +} + +void set_pixel(int page, int x, int y, int color) +{ + //outportw(0x3ce, (((x) & 3) << 8) + 0x04); + outportw(0x3c4, ((1 << ((x) & 3)) << 8) + 0x02); + *(char *) (0xa0000 + (y * 100 + (x >> 2)) + ((long) page << 15) - __djgpp_base_address) = color; +} + +void flippage(int page) +{ + outportw(0x3d4, (page << 23) + 0x0d); + outportw(0x3d4, ((page << 15) & 0xff00) + 0x0c); +} + +#if 0 +void get_block(char page, short x, short y, short width, short height, char *buffer) +{ + short c1, c2, c3; + char *buffer_ptr, *vga_ptr; + + for (c3 = 0; c3 < 4; c3++) { + outportw(0x3ce, (((x + c3) & 3) << 8) + 0x04); + for (c1 = 0; (c1 + c3) < width; c1 += 4) { + buffer_ptr = &buffer[(c1 + c3) * height]; + vga_ptr = (char *) (0xa0000 + ((long) page << 15) + (long) y * 100 + ((x + c1 + c3) >> 2) + __djgpp_conventional_base); + for (c2 = 0; c2 < height; c2++) { + *buffer_ptr = *vga_ptr; + buffer_ptr++; + vga_ptr += 100; + } + } + } + +} +#endif + +#if 0 +void put_block(char page, short x, short y, short width, short height, char *buffer) +{ + short c1, c2, c3; + char *vga_ptr, *buffer_ptr; + + for (c3 = 0; c3 < 4; c3++) { + outportw(0x3c4, ((1 << ((x + c3) & 3)) << 8) + 0x02); + for (c1 = 0; (c1 + c3) < width; c1 += 4) { + vga_ptr = (char *) (0xa0000 + ((long) page << 15) + (long) y * 100 + ((x + c1 + c3) >> 2) + __djgpp_conventional_base); + buffer_ptr = &buffer[(c1 + c3) * height]; + for (c2 = 0; c2 < height; c2++) { + *vga_ptr = *buffer_ptr; + vga_ptr += 100; + buffer_ptr++; + } + } + } + +} +#endif + +void put_text(char page, int x, int y, char *text, char align) +{ + int c1; + int t1; + int width; + int cur_x; + int image; + + if (text == NULL || strlen(text) == 0) + return; + if (font_gobs == NULL) + return; + + width = 0; + c1 = 0; + while (text[c1] != 0) { + t1 = text[c1]; + c1++; + if (t1 == ' ') { + width += 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; + 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; + } + 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(char page, short x, short y, short image, char *pob_data, char mask, char *mask_pic) +{ + long c1, c2, c3; + long pob_offset; + char *pob_ptr, *vga_ptr, *mask_ptr; + long width, height; + long draw_width, draw_height; + char colour; + + if (image < 0 || image >= *(short *) (pob_data)) + return; + + pob_offset = *(long *) (pob_data + image * 4 + 2); + + width = draw_width = *(short *) (pob_data + pob_offset); + height = draw_height = *(short *) (pob_data + pob_offset + 2); + x -= *(short *) (pob_data + pob_offset + 4); + y -= *(short *) (pob_data + pob_offset + 6); + + pob_offset += 8; + + if ((x + width) <= 0 || x >= 400) + return; + if ((y + height) <= 0 || y >= 256) + return; + if (x < 0) { + pob_offset -= x; + draw_width += x; + x = 0; + } + if ((x + width) > 400) + draw_width -= x + width - 400; + if (y < 0) { + pob_offset += -y * width; + draw_height -= -y; + y = 0; + } + if ((y + height) > 256) + draw_height -= y + height - 256; + + for (c3 = 0; c3 < 4; c3++) { + outportw(0x3c4, ((1 << ((x + c3) & 3)) << 8) + 0x02); + pob_ptr = &pob_data[pob_offset + c3]; + vga_ptr = (char *) (0xa0000 + (long) (page << 15) + (long) y * 100L + ((x + c3) >> 2) + __djgpp_conventional_base); + mask_ptr = (char *) (mask_pic + (long) y * 400L + x + c3); + for (c1 = 0; c1 < draw_height; c1++) { + for (c2 = c3; c2 < draw_width; c2 += 4) { + colour = *mask_ptr; + if (mask == 0 || (mask == 1 && colour == 0)) { + colour = *pob_ptr; + if (colour != 0) + *vga_ptr = colour; + } + pob_ptr += 4; + vga_ptr++; + mask_ptr += 4; + } + pob_ptr += width - c2 + c3; + vga_ptr += (400 - c2 + c3) >> 2; + mask_ptr += 400 - c2 + c3; + } + } + +} + + +char pob_col(short x1, short y1, short image1, char *pob_data1, short x2, short y2, short image2, char *pob_data2) +{ + short c1, c2; + long pob_offset1, pob_offset2; + short width1, width2; + short height1, height2; + short check_width, check_height; + char *pob_ptr1, *pob_ptr2; + + pob_offset1 = *(long *) (pob_data1 + image1 * 4 + 2); + width1 = *(short *) (pob_data1 + pob_offset1); + height1 = *(short *) (pob_data1 + pob_offset1 + 2); + x1 -= *(short *) (pob_data1 + pob_offset1 + 4); + y1 -= *(short *) (pob_data1 + pob_offset1 + 6); + pob_offset1 += 8; + + pob_offset2 = *(long *) (pob_data2 + image2 * 4 + 2); + width2 = *(short *) (pob_data2 + pob_offset2); + height2 = *(short *) (pob_data2 + pob_offset2 + 2); + x2 -= *(short *) (pob_data2 + pob_offset2 + 4); + y2 -= *(short *) (pob_data2 + pob_offset2 + 6); + pob_offset2 += 8; + + if (x1 < x2) { + if ((x1 + width1) <= x2) + return 0; + else if ((x1 + width1) <= (x2 + width2)) { + pob_offset1 += x2 - x1; + check_width = x1 + width1 - x2; + } else { + pob_offset1 += x2 - x1; + check_width = width2; + } + } else { + if ((x2 + width2) <= x1) + return 0; + else if ((x2 + width2) <= (x1 + width1)) { + pob_offset2 += x1 - x2; + check_width = x2 + width2 - x1; + } else { + pob_offset2 += x1 - x2; + check_width = width1; + } + } + if (y1 < y2) { + if ((y1 + height1) <= y2) + return 0; + else if ((y1 + height1) <= (y2 + height2)) { + pob_offset1 += (y2 - y1) * width1; + check_height = y1 + height1 - y2; + } else { + pob_offset1 += (y2 - y1) * width1; + check_height = height2; + } + } else { + if ((y2 + height2) <= y1) + return 0; + else if ((y2 + height2) <= (y1 + height1)) { + pob_offset2 += (y1 - y2) * width2; + check_height = y2 + height2 - y1; + } else { + pob_offset2 += (y1 - y2) * width2; + check_height = height1; + } + } + + pob_ptr1 = (char *) (pob_data1 + pob_offset1); + pob_ptr2 = (char *) (pob_data2 + pob_offset2); + for (c1 = 0; c1 < check_height; c1++) { + for (c2 = 0; c2 < check_width; c2++) { + if (*pob_ptr1 != 0 && *pob_ptr2 != 0) + return 1; + pob_ptr1++; + pob_ptr2++; + } + pob_ptr1 += width1 - check_width; + pob_ptr2 += width2 - check_width; + } + + return 0; + +} + + +short pob_width(short image, char *pob_data) +{ + return *(short *) (pob_data + *(long *) (pob_data + image * 4 + 2)); +} + + +short pob_height(short image, char *pob_data) +{ + return *(short *) (pob_data + *(long *) (pob_data + image * 4 + 2) + 2); +} + + +short pob_hs_x(short image, char *pob_data) +{ + return *(short *) (pob_data + *(long *) (pob_data + image * 4 + 2) + 4); +} + + +short pob_hs_y(short image, char *pob_data) +{ + return *(short *) (pob_data + *(long *) (pob_data + image * 4 + 2) + 6); +} + + +char read_pcx(FILE * handle, char *buffer, long buf_len, char *pal) +{ + short c1; + short a, b; + long ofs1; + + if (buffer != 0) { + fseek(handle, 128, SEEK_CUR); + + ofs1 = 0; + + while (ofs1 < buf_len) { + a = fgetc(handle); + if ((a & 0xc0) == 0xc0) { + b = fgetc(handle); + a &= 0x3f; + for (c1 = 0; c1 < a; c1++) + buffer[ofs1++] = b; + } else + buffer[ofs1++] = a; + } + + if (pal != 0) { + fseek(handle, 1, SEEK_CUR); + for (c1 = 0; c1 < 768; c1++) + pal[c1] = fgetc(handle) >> 2; + } + + } + + fclose(handle); + return 0; +} diff --git a/dos/input.c b/dos/input.c new file mode 100644 index 0000000..e7dc6e0 --- /dev/null +++ b/dos/input.c @@ -0,0 +1,275 @@ +/* + * input.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 "globals.h" + +static int num_mouse_buttons; + +int init_joy(void) +{ + int c1; + + outportb(0x201, 0); + while (c1 < 0x7fff) { + if ((inportb(0x201) & 1) == 0) + break; + c1++; + } + if (c1 != 0x7fff) + return 1; + else + return 0; +} + + +void read_joy(void) +{ + int c1; + int x, y; + int s1 = 0; + char flag; + + c1 = x = y = flag = 0; + outportb(0x201, 0); + + while (1) { + + s1 = inportb(0x201); + + if (x == 0) { + if ((s1 & 1) == 0) + x = c1; + } + if (y == 0) { + if ((s1 & 2) == 0) + y = c1; + } + if (x != 0 && y != 0) + break; + + c1++; + if (c1 == 0x7fff) { + flag = 1; + break; + } + + } + + if (flag == 0) { + joy.raw_x = x; + joy.raw_y = y; + + if (joy.raw_x < joy.calib_data.x2) + joy.x = ((long) (joy.raw_x - joy.calib_data.x2) << 10) / (joy.calib_data.x2 - joy.calib_data.x1); + else + joy.x = ((long) (joy.raw_x - joy.calib_data.x2) << 10) / (joy.calib_data.x3 - joy.calib_data.x2); + if (joy.raw_y < joy.calib_data.y2) + joy.y = ((long) (joy.raw_y - joy.calib_data.y2) << 10) / (joy.calib_data.y2 - joy.calib_data.y1); + else + joy.y = ((long) (joy.raw_y - joy.calib_data.y2) << 10) / (joy.calib_data.y3 - joy.calib_data.y2); + + if (joy.x < -1024) + joy.x = -1024; + if (joy.x > 1024) + joy.x = 1024; + if (joy.y < -1024) + joy.y = -1024; + if (joy.y > 1024) + joy.y = 1024; + + s1 = inportb(0x201); + joy.but1 = (((s1 >> 4) & 1) ^ 1); + joy.but2 = (((s1 >> 5) & 1) ^ 1); + } else { + joy.raw_x = joy.calib_data.x2; + joy.raw_y = joy.calib_data.y2; + + joy.x = joy.y = 0; + + joy.but1 = joy.but2 = 0; + } + +} + + +int calib_joy(int type) +{ + int c1; + int x, y; + int s1 = 0; + int num_times; + char flag = 0; + + while (joy.but1 == 1) { + s1 = inportb(0x201); + joy.but1 = (((s1 >> 4) & 1) ^ 1); + if (key_pressed(1) == 1) { + while (key_pressed(1) == 1); + return 1; + } + } + + num_times = 0; + + while (joy.but1 == 0) { + + c1 = x = y = flag = 0; + outportb(0x201, 0); + + while (1) { + + s1 = inportb(0x201); + + if (x == 0) { + if ((s1 & 1) == 0) + x = c1; + } + if (y == 0) { + if ((s1 & 2) == 0) + y = c1; + } + if (x != 0 && y != 0) + break; + + c1++; + if (c1 == 0x7fff) { + flag = 1; + break; + } + + } + + joy.raw_x = x; + joy.raw_y = y; + + s1 = inportb(0x201); + joy.but1 = (((s1 >> 4) & 1) ^ 1); + + if (num_times < 0x7fffffff) + num_times++; + + if (flag == 1) + break; + + if (key_pressed(1) == 1) { + while (key_pressed(1) == 1); + return 1; + } + + } + + if (num_times < 16) + return 1; + + if (flag == 0) { + + switch (type) { + case 0: + joy.calib_data.x1 = joy.raw_x; + joy.calib_data.y1 = joy.raw_y; + break; + case 1: + joy.calib_data.x3 = joy.raw_x; + joy.calib_data.y3 = joy.raw_y; + break; + case 2: + joy.calib_data.x2 = joy.raw_x; + joy.calib_data.y2 = joy.raw_y; + break; + } + + while (joy.but1 == 1) { + s1 = inportb(0x201); + joy.but1 = (((s1 >> 4) & 1) ^ 1); + } + + } + + return 0; + +} + + +int init_mouse(int *_num_buttons) +{ + __dpmi_regs regs; + int mouse_enabled, num_mouse_buttons; + + regs.x.ax = 0; + __dpmi_int(0x33, ®s); + if (regs.x.ax == 0xffff) { + mouse_enabled = 1; + num_mouse_buttons = regs.x.bx; + if (force2 == 1) + num_mouse_buttons = 2; + if (force3 == 1) + num_mouse_buttons = 3; + } else { + mouse_enabled = 0; + } + if (_num_buttons) + _num_buttons = num_mouse_buttons; + + return mouse_enabled; +} + + +void read_mouse(void) +{ + + regs.x.ax = 3; + __dpmi_int(0x33, ®s); + mouse.but1 = regs.x.bx & 1; + mouse.but2 = (regs.x.bx & 2) >> 1; + mouse.but3 = (regs.x.bx & 4) >> 2; + +} + + +void update_player_actions(void) +{ + if (main_info.mouse_enabled == 1) + read_mouse(); + if (main_info.joy_enabled == 1) + read_joy(); + player[0].action_left = key_pressed(KEY_PL1_LEFT) == 1; + player[0].action_right = key_pressed(KEY_PL1_RIGHT) == 1; + player[0].action_up = key_pressed(KEY_PL1_JUMP) == 1; + player[1].action_left = key_pressed(KEY_PL2_LEFT) == 1; + player[1].action_right = key_pressed(KEY_PL2_RIGHT) == 1; + player[1].action_up = key_pressed(KEY_PL2_JUMP) == 1; + player[2].action_left = key_pressed(KEY_PL3_LEFT) == 1; + player[2].action_right = key_pressed(KEY_PL3_RIGHT) == 1; + player[2].action_up = key_pressed(KEY_PL3_JUMP) == 1; + player[3].action_left = key_pressed(KEY_PL4_LEFT) == 1; + player[3].action_right = key_pressed(KEY_PL4_RIGHT) == 1; + player[3].action_up = key_pressed(KEY_PL4_JUMP) == 1; +} + + +void init_inputs(void) +{ + main_info.mouse_enabled = init_mouse(&num_mouse_buttons); + main_info.joy_enabled = init_joy(&num_mouse_buttons); +} + diff --git a/dos/interrpt.c b/dos/interrpt.c new file mode 100644 index 0000000..819ce7f --- /dev/null +++ b/dos/interrpt.c @@ -0,0 +1,147 @@ +/* + * interrpt.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 "globals.h" + + +struct { + char enabled; +} keyb_handler_info; + +volatile char keyb[256]; +volatile char last_keys[50]; + +unsigned char scancode2ascii[256] = { + 0, 0, 49, 50, 51, 52, 53, 54, 55, 56, /* 0-9 */ + 57, 48, 45, 0, 0, 0, 113, 119, 101, 114, /* 10-19 */ + 116, 121, 117, 105, 111, 112, 0, 0, 0, 0, /* 20-29 */ + 97, 115, 100, 102, 103, 104, 106, 107, 108, 0, /* 30-39 */ + 0, 0, 0, 0, 122, 120, 99, 118, 98, 110, /* 40-49 */ + 109, 44, 46, 47, 0, 0, 0, 32, 0, 0, /* 50-59 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; + +_go32_dpmi_seginfo old_keyb_handler_seginfo, new_keyb_handler_seginfo; + + +void keyb_handler() +{ + unsigned char key; + static char extended; + int c1; + + key = inportb(0x60); + + if (key == 0xe0) + extended = 1; + else { + if (extended == 0) { + if ((key & 0x80) == 0) { + keyb[key & 0x7f] = 1; + for (c1 = 48; c1 > 0; c1--) + last_keys[c1] = last_keys[c1 - 1]; + last_keys[0] = scancode2ascii[key & 0x7f]; + } else + keyb[key & 0x7f] = 0; + } else { + if ((key & 0x80) == 0) { + keyb[(key & 0x7f) + 0x80] = 1; + for (c1 = 48; c1 > 0; c1--) + last_keys[c1] = last_keys[c1 - 1]; + last_keys[0] = scancode2ascii[(key & 0x7f) + 0x80]; + } else + keyb[(key & 0x7f) + 0x80] = 0; + } + if (extended == 1) + extended = 0; + } + + outportb(0x20, 0x20); + +} + +void keyb_handler_end() +{ +} + + +char hook_keyb_handler(void) +{ + + if (keyb_handler_info.enabled == 0) { + _go32_dpmi_lock_data((char *) &keyb, sizeof(keyb)); + _go32_dpmi_lock_code(keyb_handler, (unsigned long) keyb_handler_end - (unsigned long) keyb_handler); + _go32_dpmi_get_protected_mode_interrupt_vector(9, &old_keyb_handler_seginfo); + new_keyb_handler_seginfo.pm_offset = (int) keyb_handler; + if (_go32_dpmi_allocate_iret_wrapper(&new_keyb_handler_seginfo) != 0) + return 1; + if (_go32_dpmi_set_protected_mode_interrupt_vector(9, &new_keyb_handler_seginfo) != 0) { + _go32_dpmi_free_iret_wrapper(&new_keyb_handler_seginfo); + return 1; + } + keyb_handler_info.enabled = 1; + memset(last_keys, 0, sizeof(last_keys)); + } + + return 0; + +} + + +void remove_keyb_handler(void) +{ + + if (keyb_handler_info.enabled == 1) { + _go32_dpmi_set_protected_mode_interrupt_vector(9, &old_keyb_handler_seginfo); + _go32_dpmi_free_iret_wrapper(&new_keyb_handler_seginfo); + keyb_handler_info.enabled = 0; + } + +} + + +char key_pressed(unsigned char key) +{ + + return keyb[key]; + +} diff --git a/dos/libdj.a b/dos/libdj.a new file mode 100644 index 0000000000000000000000000000000000000000..e05659aa6af464a6c0b1db963f7f9e3515b11382 GIT binary patch literal 53048 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 z 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 VJ$HTQUwxLCXEbE>bY}&N|9^;Wl$-zn literal 0 HcwPel00001 diff --git a/filter.c b/filter.c new file mode 100644 index 0000000..988788c --- /dev/null +++ b/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/filter.h b/filter.h new file mode 100644 index 0000000..42d87d3 --- /dev/null +++ b/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/fireworks.c b/fireworks.c new file mode 100644 index 0000000..e106b08 --- /dev/null +++ b/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/globals.pre b/globals.pre new file mode 100644 index 0000000..87c5506 --- /dev/null +++ b/globals.pre @@ -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.50" + +#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 "%%PREFIX%%/share/jumpnbump/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/gob.txt b/gob.txt new file mode 100644 index 0000000..06729c2 --- /dev/null +++ b/gob.txt @@ -0,0 +1,52 @@ + THE FORMAT OF GOBFILES + +Do YOU want to make your own GOB-files? +Then you have to know the GOB format! +Here you can find a brief desciption of it. +(this is all about how the file is saved) +Note: Everything is saved in Intel byteorder, +ie the least significant byte first. + + + THE HEADER + +Offset Size Description + 0 2 Number of images in the file + + +For I=1 to Number of images + + Offset Size Description + 2+I*4 4 Offset in file to image data + +End repeat + + +The above offsets are offsets from the beginning of +the file. Each image has it's own image data. +The image data is like this: + + + THE IMAGE DATA + +Offset Size Description + 0 2 Image width in pixels (W) + 2 2 Image height in pixels (H) + 4 2 Hotspot x + 6 2 Hotspot y + 8 W*H Bitmap data + + +The offsets above are offsets in the image data (for each image). + +The Hotspot x/y of a specific image works like this: +Whenever a sprite is drawn at (x, y) with that image, +the image is drawn at (x - hotspot x, y - hotspot y), +where hotspot x/y are the hotspots for that image. + +The bitmap data is just a block of colordata for each pixel. +It scans the image horisontally left/down. This means that +the first byte represents the upper left pixel, the second +represents the pixel to the right of that and so on. +If the width is 10 pixels then the 10th byte of bitmap data +will represent the pixel (0, 1). diff --git a/indent.txt b/indent.txt new file mode 100644 index 0000000..fe87cd3 --- /dev/null +++ b/indent.txt @@ -0,0 +1 @@ +indent -kr -i8 -l1000 -lps -nhnl diff --git a/jnbmenu.pre b/jnbmenu.pre new file mode 100644 index 0000000..8302560 --- /dev/null +++ b/jnbmenu.pre @@ -0,0 +1,228 @@ +#!/usr/bin/wish +#!/usr/bin/wish8.0 +############################################################################# +# Visual Tcl v1.20 Project +# Author : Philippe Brochard + +################################# +# GLOBAL VARIABLES +# +global fireworks; +global fullscreen; +global nogore; +global nosound; +global mirror; +global scaleup; + +global widget; + +################################# +# USER DEFINED PROCEDURES +# +proc init {argc argv} { + +} + +init $argc $argv + + +proc {exec_file} {} { +global fullscreen + global nosound + global mirror + global scaleup + global nogore + global fireworks + + set str_fullscreen "" + if { $fullscreen == 1 } { set str_fullscreen "-fullscreen" } + set str_nosound "" + if { $nosound == 1 } { set str_nosound "-nosound" } + set str_scaleup "" + if { $scaleup == 1 } { set str_scaleup "-scaleup" } + set str_mirror "" + if { $mirror == 1 } { set str_mirror "-mirror" } + set str_nogore "" + if { $nogore == 1 } { set str_nogore "-nogore" } + set str_fireworks "" + if { $fireworks == 1 } { set str_fireworks "-fireworks" } + + set file "" + if { [ .top17.lis26 curselection ] != "" } then { + set file "%%PREFIX%%/games/jumpnbump/[ .top17.lis26 get [.top17.lis26 curselection] ].dat" + } + + exec jumpnbump $str_fullscreen $str_nosound $str_scaleup $str_mirror $str_nogore $str_fireworks -dat $file & +} + +proc {fill_list_box} {} { +if [ catch { exec ls %%PREFIX%%/share/jumpnbump/ } data ] { + puts stderr "Error" + } + + foreach p $data { + .top17.lis26 insert end [ find_name $p ] + } +} + +proc {find_name} {path} { +set alast [ string last "/" $path ]; + + incr alast; + if { $alast != [ string length $path ] } { + set name [ string range $path $alast end ]; + } else { + incr alast -2; + set tmp [ string range $path 0 $alast ]; + set alast [ string last "/" $tmp ]; + incr alast; + set name [ string range $tmp $alast end ]; + } + + set fname [ split $name . ] + set firstname [ lindex $fname 0 ] + + return $firstname; +} + +proc {main} {argc argv} { +fill_list_box + + bind .top17.lis26 { exec_file } +} + +proc {Window} {args} { +global vTcl + set cmd [lindex $args 0] + set name [lindex $args 1] + set newname [lindex $args 2] + set rest [lrange $args 3 end] + if {$name == "" || $cmd == ""} {return} + if {$newname == ""} { + set newname $name + } + set exists [winfo exists $newname] + switch $cmd { + show { + if {$exists == "1" && $name != "."} {wm deiconify $name; return} + if {[info procs vTclWindow(pre)$name] != ""} { + eval "vTclWindow(pre)$name $newname $rest" + } + if {[info procs vTclWindow$name] != ""} { + eval "vTclWindow$name $newname $rest" + } + if {[info procs vTclWindow(post)$name] != ""} { + eval "vTclWindow(post)$name $newname $rest" + } + } + hide { if $exists {wm withdraw $newname; return} } + iconify { if $exists {wm iconify $newname; return} } + destroy { if $exists {destroy $newname; return} } + } +} + +################################# +# VTCL GENERATED GUI PROCEDURES +# + +proc vTclWindow. {base} { + if {$base == ""} { + set base . + } + ################### + # CREATING WIDGETS + ################### + wm focusmodel $base passive + wm geometry $base 1x1+0+0 + wm maxsize $base 1009 738 + wm minsize $base 1 1 + wm overrideredirect $base 0 + wm resizable $base 1 1 + wm resizable $base 0 0 + wm withdraw $base + wm title $base "vt.tcl" + ################### + # SETTING GEOMETRY + ################### +} + +proc vTclWindow.top17 {base} { + if {$base == ""} { + set base .top17 + } + if {[winfo exists $base]} { + wm deiconify $base; return + } + ################### + # CREATING WIDGETS + ################### + toplevel $base -class Toplevel + wm focusmodel $base passive + wm geometry $base 416x314+246+193 + wm maxsize $base 1009 738 + wm minsize $base 1 1 + wm overrideredirect $base 0 + wm resizable $base 1 1 + wm resizable $base 0 0 + wm deiconify $base + wm title $base "Jump n Bump" + label $base.lab18 \ + -borderwidth 1 -relief raised -text {Jump n Bump} + label $base.lab20 \ + -borderwidth 1 -relief sunken + checkbutton $base.che22 \ + -text {full screen} -variable fullscreen + checkbutton $base.che23 \ + -text {no sound} -variable nosound + checkbutton $base.che24 \ + -text {no gore} -variable nogore + checkbutton $base.che25 \ + -text fireworks -variable fireworks + checkbutton $base.che28 \ + -text scaleup -variable scaleup + checkbutton $base.che29 \ + -text mirror -variable mirror + listbox $base.lis26 \ + -yscrollcommand {.top17.scr27 set} + bind $base.lis26 { + exec_file + } + scrollbar $base.scr27 \ + -command {.top17.lis26 yview} + button $base.but28 \ + -command { exec_file } -text Start + button $base.but29 \ + -command { exit } -text Quit + ################### + # SETTING GEOMETRY + ################### + place $base.lab18 \ + -x 25 -y 10 -width 366 -height 17 -anchor nw -bordermode ignore + place $base.lab20 \ + -x 190 -y 40 -width 196 -height 257 -anchor nw -bordermode ignore + place $base.che22 \ + -x 220 -y 54 -anchor nw -bordermode ignore + place $base.che23 \ + -x 220 -y 83 -anchor nw -bordermode ignore + place $base.che24 \ + -x 220 -y 112 -anchor nw -bordermode ignore + place $base.che25 \ + -x 220 -y 141 -anchor nw -bordermode ignore + place $base.che28 \ + -x 220 -y 170 -anchor nw -bordermode ignore + place $base.che29 \ + -x 220 -y 199 -anchor nw -bordermode ignore + place $base.lis26 \ + -x 30 -y 40 -width 103 -height 261 -anchor nw -bordermode ignore + place $base.scr27 \ + -x 145 -y 40 -width 21 -height 262 -anchor nw -bordermode ignore + place $base.but28 \ + -x 230 -y 230 -width 117 -height 25 -anchor nw -bordermode ignore + place $base.but29 \ + -x 230 -y 255 -width 117 -height 25 -anchor nw -bordermode ignore +} + +Window show . +Window show .top17 + +main $argc $argv diff --git a/jumpnbump-kdialog b/jumpnbump-kdialog new file mode 100755 index 0000000..51d8ad1 --- /dev/null +++ b/jumpnbump-kdialog @@ -0,0 +1,52 @@ +#!/bin/bash + +# User: Setup here the location of Jump'n Bump stuff in your system + +JUMPNBUMP_BINARY=/usr/local/games/jumpnbump +JUMPNBUMP_LEVELS_DIR=/usr/local/share/jumpnbump/ + +# Show a welcome message + +kdialog --title "Jump 'n Bump" --msgbox "Welcome to the Jump 'n Bump dialog!\nby Ricardo Cruz \nA few options will be presented in the following dialog.\nThen, you may choose the level you want to play\n\n(In case this isn't working properly, open this file and edit JnB's locations.)" + +# Ask user for Options and parse them + +OPTIONS=`kdialog --title "Select Options - Jump 'n Bump" --checklist "Options:" 1 "Fullscreen" on 2 "Disable sound" off 3 "Disable gore" off 4 "Double resolution" off 5 "Mirror level" off` + +# cancel pressed, quit +if [ $? != 0 ]; then + exit 0 +fi + +ARGUMENTS="" + +for OPT in $OPTIONS +do +case $OPT in + '"1"') ARGUMENTS="$ARGUMENTS -fullscreen";; + '"2"') ARGUMENTS="$ARGUMENTS -nosound";; + '"3"') ARGUMENTS="$ARGUMENTS -nogore";; + '"4"') ARGUMENTS="$ARGUMENTS -scaleup";; + '"5"') ARGUMENTS="$ARGUMENTS -mirror";; + *) echo "Warning: unknown option";; +esac +done + +# Ask user for a level +# (Even after running the game, ask for levels, until user presses Cancel button or Esc key) + +while [ 1 ] + do + +LEVEL_FILE=`kdialog --title "Choose a Level - Jump 'n Bump" --getopenfilename $JUMPNBUMP_LEVELS_DIR "*.dat | Levels"` + +if [ $LEVEL_FILE ]; then + $JUMPNBUMP_BINARY $ARGUMENTS -dat $LEVEL_FILE + +else + exit 0; +fi + +done + + diff --git a/jumpnbump-xdialog b/jumpnbump-xdialog new file mode 100755 index 0000000..de92d75 --- /dev/null +++ b/jumpnbump-xdialog @@ -0,0 +1,53 @@ +#!/bin/bash + +# User: Setup here the location of Jump'n Bump stuff in your system + +JUMPNBUMP_BINARY=/usr/local/games/jumpnbump +JUMPNBUMP_LEVELS_DIR=/usr/local/share/jumpnbump/ + +# Show a welcome message + +Xdialog --title "Jump 'n Bump" --msgbox "Welcome to the Jump 'n Bump dialog!\nby Ricardo Cruz \nA few options will be presented in the following dialog.\nThen, you may choose the level you want to play\n\n(In case this isn't working properly, open this file and edit JnB's locations.)" 0 0 + +# Ask user for Options and parse them + +OPTIONS=`Xdialog --title "Select Options - Jump 'n Bump" --separator " " --checklist "Options:" 0 0 0 1 "Fullscreen" on 2 "Disable sound" off 3 "Disable gore" off 4 "Double resolution" off 5 "Mirror level" off 2>&1` + +# cancel pressed, quit +if [ $? != 0 ]; then + exit 0 +fi + +ARGUMENTS="" + +for OPT in $OPTIONS +do +case $OPT in + '1') ARGUMENTS="$ARGUMENTS -fullscreen";; + '2') ARGUMENTS="$ARGUMENTS -nosound";; + '3') ARGUMENTS="$ARGUMENTS -nogore";; + '4') ARGUMENTS="$ARGUMENTS -scaleup";; + '5') ARGUMENTS="$ARGUMENTS -mirror";; + *) echo "Warning: unknown option";; +esac +done + +# Ask user for a level +# (Even after running the game, ask for levels, until user presses Cancel button or Esc key) + +while [ 1 ] + do + +LEVEL_FILE=`Xdialog --title "Choose a Level - Jump 'n Bump" --fselect $JUMPNBUMP_LEVELS_DIR 0 0 2>&1` +# "*.dat | Levels"` + +if [ $LEVEL_FILE ]; then + $JUMPNBUMP_BINARY $ARGUMENTS -dat $LEVEL_FILE + +else + exit 0; +fi + +done + + diff --git a/jumpnbump.6 b/jumpnbump.6 new file mode 100644 index 0000000..a93092a --- /dev/null +++ b/jumpnbump.6 @@ -0,0 +1,134 @@ +.TH jumpnbump 6 "August 25th, 2002" +.SH NAME +jumpnbump \- Cute multiplayer platform game with bunnies +.SH SYNOPSIS +jumpnbump \fR[\fB-dat \fIlevelname\fR] [\fB-port \fIport \fB-net \fIplayer hostname rport\fR] [\fB-fireworks\fR] [\fB-fullscreen\fR] [\fB-nosound\fR] [\fB-musicnosound\fR] [\fB-nogore\fR] [\fB-noflies\fR] [\fB-mirror\fR] [\fB-scaleup\fR] [\fB-v\fR] [\fB-h\fR] +.SH DESCRIPTION +You, as a bunny, have to jump on your opponents to make them +explode. It's a true multiplayer game, you can't play this alone. +It has network support. +.SH OPTIONS +.IP "-dat \fIlevelname\fR" +Load \fIlevelname\fR and use it as the level for this game. +.IP "-port \fIport\fR" +Use \fIport\fR as the port to listen on for a network game. Use this +with -net. +.IP "-net \fIplayer hostname rport" +Connect (using a network) to another person running jump'n'bump on +\fIhostname\fR, and listening on \fIrport\fR. You will be player +number \fIplayer\fR. +.IP "-fireworks" +Run the program in "screensaver" mode. This is useful with -fullscreen. +.IP "-fullscreen" +Run jump'n'bump in fullscreen mode. +.IP "-nosound" +Run jump'n'bump without sound. +.IP "-musicnosound" +Run jump'n'bump with music but no sound effects. +.IP "-nogore" +Play without blood, familymode. +.IP "-noflies" +Disable flies. +.IP "-mirror" +Play with mirrored level. +.IP "-scaleup" +Play with doublesize resolution (800x512). +.IP "-h" +Print help. +.IP "-v" +Print version, compile time and if network code is compiled in. +.SH USAGE +The goal of the game is to jump on the other players. Each rabbit has +three control keys. +.IP "Player 1 (Dott)" +Left - Left +.br +Right - Right +.br +Jump - Up +.IP "Player 2 (Jiffy)" +Left - A +.br +Right - D +.br +Jump - W +.IP "Player 3 (Fizz)" +Left - J +.br +Right - L +.br +Jump - I +.IP "Player 4 (Mijji)" +Left - 4 +.br +Right - 5 +.br +Jump - 8 +.IP "In the game" +Turn on/off computer play (AI) of bunny 1 - 1 +.br +Turn on/off computer play (AI) of bunny 2 - 2 +.br +Turn on/off computer play (AI) of bunny 3 - 3 +.br +Turn on/off computer play (AI) of bunny 4 - 4 +.br +.SH SECRET CODES +You can type these while in the game +.br +jetpack - you can fly +.br +pogostick - the bunnies keep jumping +.br +bunniesinspace - gravity is lower, you can jump higher +.br +lordoftheflies - the flies are attracted +.br +bloodisthickerthanwater - water turns to blood +.SH LEVELS +There are two programs to help you make your own levels: jnbpack and jnbunpack. +.PP +jnbpack -o /tmp/newlevel.dat etc +.PP +or you can just put all the files in a dir, cd to that dir and do +.PP +jnbpack -o /tmp/newlevel.dat * +.PP +and it will put all the files in the current dir inside the packfile. +Don't try things like jnbpack -o stuff.dat ../file.c because it will add +"../file.c" as the filename in the packfile, which won't work. +.PP +jnbunpack level.dat +.br +will unpack it in the current directory. +.PP +With gobpack you can convert .gob files (which are sprites, described in +gob.txt) into .pcx files which you can edit with gimp for example, then +convert back to a .gob and use it in your own level. +.PP +gobpack -u font menu.pcx +.PP +will unpack font.gob using the color palette from menu.pcx and write the +files font.pcx font.txt. The other gob files should use level.pcx for the +correct palette. +.PP +gobpack font +.PP +will generate font.gob from font.pcx and the specifications in font.txt. +The .pcx files should be resaved with another program, as they are not +packed and are thus very large. +.SH AUTHORS +.PP +Chuck Mason , Jon Atkins , +Philippe Brochard , Gürkan Sengün , +Florian Schulze , Ricardo Cruz and "timecop" are +the authors of jump'n'bump. +.PP +This program is a UNIX port of the old DOS game by brainchilddesign. +.PP +This manual page was written for the Debian GNU/Linux distribution because +the original program does not have a manual page. +.PP +This manual page was written by Joe Wreschnig , for the +Debian GNU/Linux system (but may be used by others). The manual page is kept +up to date by Gürkan Sengün . diff --git a/jumpnbump.fbcon b/jumpnbump.fbcon new file mode 100755 index 0000000..4d04796 --- /dev/null +++ b/jumpnbump.fbcon @@ -0,0 +1,4 @@ +#!/bin/sh +#SDL_AUDIODRIVER can be dsp,dma,esd,artsc | dsound,waveout +#SDL_VIDEODRIVER can be x11,dga,fbcon,directfb,svgalib,ggi,aalib | directx,windib +SDL_VIDEODRIVER=fbcon jumpnbump $@ diff --git a/jumpnbump.html b/jumpnbump.html new file mode 100644 index 0000000..c161954 --- /dev/null +++ b/jumpnbump.html @@ -0,0 +1,158 @@ + + + + + +jumpnbump(6) manual page + + +Table of Contents

+ +

Name

+jumpnbump - Cute multiplayer platform game with bunnies +

Synopsis

+jumpnbump +[-dat levelname] [-port port -net player hostname rport] [-fireworks] [-fullscreen] +[-nosound] [-musicnosound] [-nogore] [-mirror] [-scaleup] [-v] [-h] +

Description

+You, +as a bunny, have to jump on your opponents to make them explode. It's a true +multiplayer game, you can't play this alone. It has network support. +

Options

+ +
+ +
-dat +levelname
+
Load levelname and use it as the level for this game.
+ +
-port port
+
Use +port as the port to listen on for a network game. Use this with -net.
+ +
-net +player hostname rport
+
Connect (using a network) to another person running +jump'n'bump on hostname, and listening on rport. You will be player number +player.
+ +
-fireworks
+
Run the program in "screensaver" mode. This is useful with +-fullscreen.
+ +
-fullscreen
+
Run jump'n'bump in fullscreen mode.
+ +
-nosound
+
Run jump'n'bump +without sound.
+ +
-musicnosound
+
Run jump'n'bump with music but no sound effects. +
+ +
-nogore
+
Play without blood, familymode.
+ +
-mirror
+
Play with mirrored level.
+ +
-scaleup
+
Play +with doublesize resolution (800x512).
+ +
-h
+
Print help.
+ +
-v
+
Print version.
+
+ +

Usage

+The +goal of the game is to jump on the other players. Each rabbit has three +control keys. +
+ +
Player 1 (Dott)
+
Left - Left
+Right - Right
+Jump - Up
+ +
Player 2 (Jiffy)
+
Left - A
+Right - D
+Jump - W
+ +
Player 3 (Fizz)
+
Left - J
+Right - L
+Jump - I
+ +
Player 4 (Mijji)
+
Left - 4
+Right - 5
+Jump - 8
+
+ +

Secret Codes

+You can type these while in the game
+jetpack - you can fly
+pogostick - the bunnies keep jumping
+bunniesinspace - gravity is lower, you can jump higher
+lordoftheflies - the flies are attracted
+bloodisthickerthanwater - water turns to blood +

Levels

+There are two programs +to help you make your own levels: jnbpack and jnbunpack.

+jnbpack -o /tmp/newlevel.dat +<file1> <file2> <file3> etc

+or you can just put all the files in a dir, cd to +that dir and do

+jnbpack -o /tmp/newlevel.dat *

+and it will put all the files +in the current dir inside the packfile. Don't try things like jnbpack -o stuff.dat +../file.c because it will add "../file.c" as the filename in the packfile, which +won't work.

+jnbunpack level.dat
+will unpack it in the current directory.

+With gobpack you can convert .gob +files (which are sprites, described in gob.txt) into .pcx files which you +can edit with gimp for example, then convert back to a .gob and use it in +your own level.

+gobpack -u font menu.pcx

+will unpack font.gob using the color +palette from menu.pcx and write the files font.pcx font.txt. The other gob +files should use level.pcx for the correct palette.

+gobpack font

+will generate +font.gob from font.pcx and the specifications in font.txt. The .pcx files should +be resaved with another program, as they are not packed and are thus very +large. +

Authors

+

+Chuck Mason <cemason@users.sourceforge.net>, Jon Atkins <jcatki@home.com>, +Philippe Brochard <phil.brochard@wanadoo.fr>, Gürkan Sengün <gurkan@linuks.mine.nu>, +Florian Schulze <crow@icculus.org> and "timecop" <timecop@japan.co.jp> are the +authors of jump'n'bump.

+This program is a UNIX port of the old DOS game by +brainchilddesign.

+This manual page was written for the Debian GNU/Linux +distribution because the original program does not have a manual page.

+This +manual page was written by Joe Wreschnig <piman@sacredchao.net>, for the Debian +GNU/Linux system (but may be used by others).

+ +


+Table of Contents

+

+ diff --git a/jumpnbump.ico b/jumpnbump.ico new file mode 100644 index 0000000000000000000000000000000000000000..2ad015cb0816d0d884aee5b626cb1900a1b8f6e2 GIT binary patch literal 2238 zcwX(5O=#0#9LAs8y0kXUTW8y3nl!a-)?~@*y46sM_zhl$2!3D2^dLChNg1Moq9QnN z9>gh#7e7D{6&wREx`PZ49zFO0Lq$Y{c^VtI#edRtQ&&8A@U$m9@7w10y#N23my`kl zx-uDfx)%mgH0xyd)<$vwVUL{+p`j8|E81GyP_?UQD)t~Ogka|p1k1-z-QI^S zo3^04dk6OJ-G?Ln{pjmIj)8#zG_5}esXBtl=1WL-UqpQS4Mca|hqUJwV*5vs>K(?W zgO{)jdbemH}p_des&;ALDJ8p7?n_wo422yPC)!Qk*$JbgZfo1>F>@#-Dkz8}ZvyD5D7 zGJ)x-X*iD4_@NiIs73uxaS4&em=I&EA?BK8S#A+xt{PB|iz~92Or}}{%CO%5d16WDwo&Qn-cn3tlv~B7rcfm7M`}2!(poj!S*%nlU8z7I7>q`iXSIT^ z`Ky(Ts;*`gi}>2+K#-@yUmlLj+T8Oc(rtE^ZQH~nfhc2UY?Y{Fw7EdaFe){*tymIe zCgV*tujcc4A7>52_OP83qr7SHLd>Ogo~ErD?RJH(QX#R7nHF1`&*bOY=iSpR+jd9U z?lO3unWhrKAF^nzzNS>FxZ5-Tq(He$kKa)=i@ac&mbEa@UM$kUEIta8EiBM(mAu*H zm(dVgP{3;UKhSzA(C`OP6TNh%`4{f0(FXrf&ae7--f^A<+<#0q3j}|VztihSW@Oc$ rgTA?O`u>c3cAmNSTyGdhz?lU{4mysMb7t3 + + + +Making levels + + + +
+

 

+ +

HOW TO MAKE A LEVEL

+ +

This is a tutorial where you can learn how to edit all files on +a JnB level or solve your problems.

+ +

 

+ +

+Linux updates: 9 Aug 2002. Tools to make levels on a UNIX, Linux system.

+Last update: 16 +Sep 2001. Added JnB level background for +download

+ +

7 Sep 2001. +Information about water-blood cheat in level.pcx and +splash.smp.

+ +

6 Sep 2001. +How to put blinking things in +menu.pcx.

+ +

 

+
+ +

First of all unpack a level in this way:

+ +

+ +

"unpack.exe [levelname].dat"

+

"jnbunpack [levelname].dat" [Linux]

+ +

 

+ +

I recommend you to unpack jumpbump.dat, so, the files you not +edit, are the default.

+ +

Required programs:

+ + + +On Linux: +
    +
  • The Gimp - www.gimp.org
  • +
  • Soundtracker - www.soundtracker.org/
    +play -traw -r22050 -sb the.smp to play sample files
  • +
  • Your favourite editor (vi, mcedit...)
  • +
  • Please contact your manual page for details about jnbpack, jnbunpack and gobpack (man jumpnbump)
  • +
+ +

These are the files to edit:

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

File Format

+
+

File Name

+
+

Description

+
+

PCX

+
levelThe zone where you play.
maskThe mask of "level.pcx"
menuThe screen where you select players.
menumaskThe mask of "menu.pcx"
+

DAT

+
calibThe joystick/joypad calibration data.
+

TXT

+
levelmapThe map of the zone.
+

GOB

+
fontThe font of the level.
numbersThe displayed numbers on the scoreboard
objectsThe objects of the zone.
rabbitThe movements of the rabbits.
+

SMP

+
deathSample played when a rabbit dies.
flySample played when you are near the flies.
jumpSample played when you jump.
splashSample played when you fall into the water.
springSample played when you jump on a spring.
+

MOD

+
bumpMusic played when you play in the zone.
jumpMusic played on the select players screen.
scoresMusic played in the final scoreboard.
+
+
+ +

 

+ +
    +
  • +

    How to edit all of them:

    +
  • +
+ +

+level.pcx

+ +

Description: The zone where you play.

+ +

Program for edit it: Paint Shop Pro. The Gimp [Linux].

+ +

How to edit: Draw a nice image for make a level with PSP, +and if you want to see the map, do this:

+ +

Click on File/Preferences/General Program Preferences. Then +click on "Rulers and Units" and type, in Grid section, Width=16 and +Height=16. Then Apply. And last, click on View/Grid.

+ +

Now you can see the map and will be useful for make +levelmap.txt

+ +

The map is 16 rows and 22 columns, and another 3 columns at the +right for scoreboard. The image size is 400x256 pixels and uses 256 +colours. Download the original background +here and use it for your own. Remember this: all the image +files on the level (PCXs and GOBs) must have the same colour +palette.

+ +

+

+ +

These are the colour numbers of the default palette +that are changed when using BLOODISTHICKERTHANWATER cheat:

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Water +colour number +
turns +into
+
+
Blood colour +number
+
+145 +
turns into
+
+
176
+
+146 +
turns into
+
+
177
+
+147 +
turns into
+
+
178
+
+148 +
turns into
+
+
179
+
+149 +
turns into
+
+
180
+
+150 +
turns into
+
+
181
+
+151 +
turns into
+
+
182
+
+
+ +

 

+ +

+mask.pcx

+ +

Description: The mask of "level.pcx"

+ +

Program for edit it: Paint Shop Pro. The Gimp [Linux].

+ +

How to edit: This is a black image file with +white parts. The black zone is behind the rabbits and the white +zone hides the rabbits. Be careful, don't make white the three +columns at the right for can see the scoreboard. Here is an +example:

+ + + + + + + + + + + + + + +
+

This is a part of "level.pcx"

+
+

And this is a part of "mask.pcx"

+
+

Look! Dott is behind the box!

+
+ +

menu.pcx

+ +

Description: The screen where you select +players.

+ +

Program for edit it: Paint Shop Pro. The Gimp [Linux].

+ +

How to edit: The easiest you can do here is +this: Type on the top your Nick and your e-mail and the title of +the level. But you can draw too a nice level entrance, but remember +to draw an obstacle for jump it and select players. Something cool: +Everywhere you use the colour No255, will be blinking like the +credits letters. Remember this: all the image files on the level +(PCXs and GOBs) must have the same colour palette. Look here at +each of the rabbit's way for make the menu screen:

+ +

+ +

Get this image file in .PCX format here, put it in your level and it will guide you for +where you must put thee obstacle and the floor where is supposed to +run on the rabbits.

+ +

+menumask.pcx

+ +

Description: The mask of "menu.pcx"

+ +

Program for edit it: Paint Shop Pro. The Gimp [Linux].

+ +

How to edit: This is a black image file with +white parts. The black zone is behind the rabbits and the white +zone hides the rabbits. Be careful, don't make white the bottom for +can see the credits. Here is an example:

+ + + + + + + + + + + + + + +
+

This is a part of "level.pcx"

+
+

And this is a part of "mask.pcx"

+
+

Look! Dott is behind the box!

+
+ +

+calib.dat

+ +

Description: The joystick/joypad calibration data.

+ +

Program for edit it: None

+ +

How to edit: When you pack the .dat file, +just play it, before playing, you calibrate your +joystick/joypad.

+ +

levelmap.txt

+ +

Description: The map of the zone.

+ +

Program for edit it: Notepad.

+ +

How to edit: Just take a look in the PSP Grid of +"level.pcx" and type:0 for air, 1 for ground, 2 for water, 3 for +ice and 4 for a spring (just like "Number Code Land" level). +Remember, is a 22x16 grid. Some useful information:

+ +
    +
  • You can jump up to 3 blocks.
  • + +
  • If you are using the "BUNNIESINSPACE" cheat, you can jump up to +6 blocks.
  • + +
  • And jumping on a spring, 6 blocks too.
  • + +
  • The water is useful for "fly".
  • + +
  • If you alternate ground and air, you can run over there without +falling.
  • +
+ +

font.gob

+ +

Description: The font of the level.

+ +

Program for edit it: Paint Shop Pro & +GOBMaker. The Gimp and gobpack[Linux].

+ +

How to edit: With PSP edit "font.pcx" (found +at GOBMaker Projects in BCD) drawing all letters, numbers and marks +and save the image. Remember this: all the image files on the level +(PCXs and GOBs) must have the same colour palette. Run GOBMaker, +then open "font.gmp" (GOBMaker Project) and change the letters. +These are the frames of "font.gob":

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

1

+
+

2

+
+

3

+
+

4

+
+

5

+
+

6

+
+

7

+
+

8

+
+

9

+
+

10

+
+

11

+
+

12

+
+

13

+
+

14

+
+

15

+
+

16

+
+

17

+
+

18

+
+

!

+
+

"

+
+

'

+
+

(

+
+

)

+
+

,

+
+

-

+
+

.

+
+

/

+
+

0

+
+

1

+
+

2

+
+

3

+
+

4

+
+

5

+
+

6

+
+

7

+
+

8

+
+

19

+
+

20

+
+

21

+
+

22

+
+

23

+
+

24

+
+

25

+
+

26

+
+

27

+
+

28

+
+

29

+
+

30

+
+

31

+
+

32

+
+

33

+
+

34

+
+

35

+
+

36

+
+

9

+
+

:

+
+

;

+
+

@

+
+

A

+
+

B

+
+

C

+
+

D

+
+

E

+
+

F

+
+

G

+
+

H

+
+

I

+
+

J

+
+

K

+
+

L

+
+

M

+
+

N

+
+

37

+
+

38

+
+

39

+
+

40

+
+

41

+
+

42

+
+

43

+
+

44

+
+

45

+
+

46

+
+

47

+
+

48

+
+

49

+
+

50

+
+

51

+
+

52

+
+

53

+
+

54

+
+

O

+
+

P

+
+

Q

+
+

R

+
+

S

+
+

T

+
+

U

+
+

V

+
+

W

+
+

X

+
+

Y

+
+

Z

+
+

a

+
+

b

+
+

c

+
+

d

+
+

e

+
+

f

+
+

55

+
+

56

+
+

57

+
+

58

+
+

59

+
+

60

+
+

61

+
+

62

+
+

63

+
+

64

+
+

65

+
+

66

+
+

67

+
+

68

+
+

69

+
+

70

+
+

71

+
+

72

+
+

g

+
+

h

+
+

i

+
+

j

+
+

k

+
+

l

+
+

m

+
+

n

+
+

o

+
+

p

+
+

q

+
+

r

+
+

s

+
+

t

+
+

u

+
+

v

+
+

w

+
+

x

+
+

73

+
+

74

+
+

75

+
+

76

+
+

77

+
+

78

+
+

79

+
+

80

+
+

81

+
+

y

+
+

z

+
+

~

+
+

ä

+
+

â

+
+

Ä

+
+

Â

+
+

ö

+
+

Ö

+
+ +

+numbers.gob

+ +

Description: The displayed numbers on the +scoreboard

+ +

Program for edit it: Paint Shop Pro & +GOBMaker. The Gimp and gobpack [Linux].

+ +

How to edit: With PSP create a nice PCX +image with the ten numbers starting by zero (each number can't be +bigger than 16x22 pixels) and save it as "numbers.pcx". Remember +this: all the image files on the level (PCXs and GOBs) must have +the same colour palette. Run GOBMaker, open "numbers.pcx" and +create "numbers.gmp". Then make "numbers.gob"

+ +

+objects.gob

+ +

Description: The objects of the zone.

+ +

Program for edit it: Paint Shop Pro & +GOBMaker. The Gimp and gobpack [Linux].

+ +

How to edit: With PSP edit "objects.pcx" +(found at GOBMaker Projects in BCD) drawing all objects of the +level. Remember this: all the image files on the level (PCXs and +GOBs) must have the same colour palette. Run GOBMaker, then open +"objects.gmp" (GOBMaker Project) and change the objects. These are +the frames of "objects.gob":

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Frames

+
+

Objects

+
+

1-6

+
+

Spring working

+
+

6

+
+

Spring stopped

+
+

7-15

+
+

Water Splashing

+
+

16-20

+
+

Dust

+
+

21-25

+
+

1st and 2nd butterfly looking at the right

+
+

27-32

+
+

1st and 2nd butterfly looking at the left

+
+

33-38

+
+

3rd and 4th butterfly looking at the right

+
+

39-44

+
+

3rd and 4th butterfly looking at the left

+
+

45-57

+
+

Pieces of Dott

+
+

53-60

+
+

Pieces of Jiffy

+
+

61-68

+
+

Pieces of Fizz

+
+

69-76

+
+

Pieces of Mijji

+
+

77-80

+
+

Blood

+
+ +

 

+ +

+rabbit.gob

+ +

Description: The movements of the +rabbits.

+ +

Program for edit it: Paint Shop Pro & +GOBMaker. The Gimp and gobpack [Linux].

+ +

How to edit: With PSP edit "Rabbit.pcx" +(found at GOBMaker Projects in BCD) drawing all the frames of the +movements. Remember this: all the image files on the level (PCXs +and GOBs) must have the same colour palette. Run GOBMaker, then +open "rabbit.gmp" (GOBMaker Project) and change the objects. Be +careful, if the frames are bigger than 16x16 pixels, you can't go +up the screen because a frame of the rabbit will stay up blinking. +These are the frames of "rabbit.gob":

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Frames

+
+

Movements

+
+

Direction

+
+

Rabbits

+
+

1

+
+

Standing

+
+

Right

+
+

Dott

+
+

1, 2, 3, 4

+
+

Running

+
+

5, 6, 7, 8

+
+

Jumping/Swimming

+
+

9

+
+

Die

+
+

10

+
+

Standing

+
+

Left

+
+

10, 11, 12, 13

+
+

Running

+
+

14, 15, 16, 17

+
+

Jumping/Swimming

+
+

18

+
+

Die

+
+

19

+
+

Standing

+
+
+

Right

+
+
+

Jiffy

+
+

19, 20, 21, 22

+
+

Running

+
+

23, 24, 25, 26

+
+

Jumping/Swimming

+
+

27

+
+

Die

+
+

28

+
+

Standing

+
+

Left

+
+

28, 29, 30, 31

+
+

Running

+
+

32, 33, 34, 35

+
+

Jumping/Swimming

+
+

36

+
+

Die

+
+

37

+
+

Standing

+
+
+

Right

+
+
+

Fizz

+
+

37, 38, 39, 40

+
+

Running

+
+

41, 42, 43, 44

+
+

Jumping/Swimming

+
+

45

+
+

Die

+
+

46

+
+

Standing

+
+

Left

+
+

46, 47, 48, 49

+
+

Running

+
+

50, 51, 52, 53

+
+

Jumping/Swimming

+
+

54

+
+

Die

+
+

55

+
+

Standing

+
+
+

Right

+
+
+

Mijji

+
+

55, 56, 57, 58

+
+

Running

+
+

59, 60, 61, 62

+
+

Jumping/Swimming

+
+

63

+
+

Die

+
+

64

+
+

Standing

+
+

Left

+
+

64, 65, 66, 67

+
+

Running

+
+

68, 69, 70, 71

+
+

Jumping/Swimming

+
+

72

+
+

Die

+
+ +

 

+ +

+death.smp

+ +

Description: Sample played when a rabbit +dies.

+ +

Program for edit it: FastTracker II. Soundtracker [Linux].

+ +

How to edit: This editing information is the +same for all SMP files. With FastTracker II open a WAV file for a +death and save it as death.smp. It must be an 8-bit sound.

+ +

 

+ +

+fly.smp

+ +

Description: Sample played when you are near +the flies.

+ +

Program for edit it: FastTracker II. Soundtracker [Linux].

+ +

How to edit: This editing information is the +same for all SMP files. With FastTracker II open a WAV file for the +fliues and save it as fly.smp. It must be an 8-bit sound. You must +be near the flies for hear them but if you run to them, they will +fly away. For hear them the best, use the LORDOFTHEFLIES cheat.

+ +

 

+ +

+jump.smp

+ +

Description: Sample played when you +jump.

+ +

Program for edit it: FastTracker II. Soundtracker [Linux].

+ +

How to edit: This editing information is the +same for all SMP files. With FastTracker II open a WAV file for +jumping and save it as jump.smp. It must be an 8-bit sound.

+ +

 

+ +

+splash.smp

+ +

Description: Sample played when you fall +into the water.

+ +

Program for edit it: FastTracker II. Soundtracker [Linux].

+ +

How to edit: This editing information is the +same for all SMP files. With FastTracker II open a WAV file for +splashing and save it as splash.smp. It must be an 8-bit sound. +This sound will be longer and slower if you use +BLOODISTHICKERTHANWATER cheat.

+ +

 

+ +

 

+ +

+spring.smp

+ +

Description: Sample played when you jump on +a spring.

+ +

Program for edit it: FastTracker II. Soundtracker [Linux].

+ +

How to edit: This editing information is the +same for all SMP files. With FastTracker II open a WAV file for a +spring and save it as spring.smp. It must be an 8-bit sound. You +can hear it also in POGOSTICK cheat.

+ +

 

+ +

+bump.mod

+ +

Description: Music played when you play in +the zone.

+ +

Program for edit it: FastTracker II. Soundtracker [Linux].

+ +

How to edit: You can compose your own +playing music, but if you think it's too hard, the best you can do +is downloading a nice one.

+ +

 

+ +

+jump.mod

+ +

Description: Music played on the select +players screen.

+ +

Program for edit it: FastTracker II. Soundtracker [Linux].

+ +

How to edit: You can compose your own intro +music, but if you think it's too hard, the best you can do is +downloading a nice one.

+ +

 

+ +

+scores.mod

+ +

Description: Music played in the final +scoreboard.

+ +

Program for edit it: FastTracker II. Soundtracker [Linux].

+ +

How to edit: You can compose your own +scoreboard music, but if you think it's too hard, the best you can +do is downloading a nice one.

+ +
+

Did you edit all the files you wanted? Type in +DOS mode:

+ +

+ +

"pack.exe [mylevel].dat"

+

"jnbpack -o [mylevel].dat file1 file2 file3" [Linux]

+ +

 

+ +

If this isn't enough and you have problems e-mail +me: bkronb@hotmail.com

+

For Linux related things contact me: gurkan@linuks.mine.nu

+
+ + + diff --git a/levelmaking/level.pcx b/levelmaking/level.pcx new file mode 100644 index 0000000000000000000000000000000000000000..29fe0de3324a5155b2bbdeda25c13403eba085a1 GIT binary patch literal 12837 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 literal 0 HcwPel00001 diff --git a/levelmaking/making2.gif b/levelmaking/making2.gif new file mode 100644 index 0000000000000000000000000000000000000000..ad76340751eb04b0a790116faef5bb940f96acd3 GIT binary patch literal 1588 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 + * + * 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 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; + +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} +}; + +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; + } + } +} + + +int main(int argc, char *argv[]) +{ + unsigned char *handle; + int c1 = 0, c2 = 0, c3 = 0, c4 = 0; + int l1; + int s1, s2, s3, s4; + int closest_player = 0, dist, cur_dist = 0; + int end_loop_flag = 0, fade_flag = 0; + int mod_vol, sfx_vol, mod_fade_direction; + char str1[100]; + char pal[768]; + char cur_pal[768]; + int update_count; + int i; + + if (init_program(argc, argv, pal) != 0) + deinit_program(); + + if (main_info.fireworks == 1) { + fireworks(); + deinit_program(); + } + + for(i = 0; i < JNB_MAX_PLAYERS; i++) // reset player values + { + ai[i] = 0; + } + + while (1) { + + if (!is_net) + if (menu() != 0) + deinit_program(); + + if (key_pressed(1) == 1) { + break; + } + 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 (ban_map[flies[c1].y >> 4][flies[c1].x >> 4] == BAN_VOID) + break; + } + flies[c1].back_defined[0] = 0; + flies[c1].back_defined[1] = 0; + } + } + + mod_vol = sfx_vol = 10; + 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(); + + 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; + end_loop_flag = 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; + + update_count = 1; + 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; + } + + 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) { + blood_is_thicker_than_water ^= 1; + if (blood_is_thicker_than_water == 1) { + pal[432] = 63; + pal[433] = 32; + pal[434] = 32; + pal[435] = 53; + pal[436] = 17; + pal[437] = 17; + pal[438] = 42; + pal[439] = 7; + pal[440] = 7; + pal[441] = 28; + pal[442] = 0; + pal[443] = 0; + pal[444] = 24; + pal[445] = 0; + pal[446] = 0; + pal[447] = 19; + pal[448] = 0; + pal[449] = 0; + pal[450] = 12; + pal[451] = 0; + pal[452] = 0; + pal[453] = 7; + pal[454] = 0; + pal[455] = 0; + } else { + pal[432] = 63; + pal[433] = 63; + pal[434] = 63; + pal[435] = 40; + pal[436] = 53; + pal[437] = 62; + pal[438] = 19; + pal[439] = 42; + pal[440] = 60; + pal[441] = 0; + pal[442] = 33; + pal[443] = 60; + pal[444] = 3; + pal[445] = 32; + pal[446] = 46; + pal[447] = 3; + pal[448] = 26; + pal[449] = 33; + pal[450] = 3; + pal[451] = 19; + pal[452] = 21; + pal[453] = 1; + pal[454] = 8; + pal[455] = 8; + } + register_background(background_pic, pal); + recalculate_gob(&object_gobs, pal); + last_keys[0] = 0; + } + +#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(); + + 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) { + if (player[c1].y_add >= 0) { + if (is_server) + serverSendKillPacket(c1, c2); + } else { + if (player[c2].y_add < 0) + player[c2].y_add = 0; + } + } else { + if (player[c2].y_add >= 0) { + if (is_server) + serverSendKillPacket(c2, c1); + } else { + if (player[c1].y_add < 0) + player[c1].y_add = 0; + } + } + } 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; + } + } + } + } + } + + dj_mix(); + + main_info.page_info[main_info.draw_page].num_pobs = 0; + for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) { + if (player[c1].enabled == 1) + main_info.page_info[main_info.draw_page].num_pobs++; + } + + update_objects(); + + dj_mix(); + + if (flies_enabled) { + /* 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 */ + dist = 0x7fff; + for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) { + if (player[c1].enabled == 1) { + cur_dist = (int)sqrt((s1 - ((player[c1].x >> 16) + 8)) * (s1 - ((player[c1].x >> 16) + 8)) + (s2 - ((player[c1].y >> 16) + 8)) * (s2 - ((player[c1].y >> 16) + 8))); + if (cur_dist < dist) { + closest_player = c1; + dist = cur_dist; + } + } + } + /* 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 */ + dist = 0x7fff; + for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++) { + if (player[c2].enabled == 1) { + cur_dist = (int)sqrt((flies[c1].x - ((player[c2].x >> 16) + 8)) * (flies[c1].x - ((player[c2].x >> 16) + 8)) + (flies[c1].y - ((player[c2].y >> 16) + 8)) * (flies[c1].y - ((player[c2].y >> 16) + 8))); + if (cur_dist < dist) { + closest_player = c2; + dist = cur_dist; + } + } + } + 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 (ban_map[flies[c1].y >> 4][(flies[c1].x + s4) >> 4] != 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 (ban_map[(flies[c1].y + s4) >> 4][flies[c1].x >> 4] != BAN_VOID) + s4 = 0; + flies[c1].y += s4; + } + } + + dj_mix(); + + s1 = 0; + for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) { + if (player[c1].enabled == 1) { + main_info.page_info[main_info.draw_page].pobs[s1].x = player[c1].x >> 16; + main_info.page_info[main_info.draw_page].pobs[s1].y = player[c1].y >> 16; + main_info.page_info[main_info.draw_page].pobs[s1].image = player[c1].image + c1 * 18; + main_info.page_info[main_info.draw_page].pobs[s1].pob_data = &rabbit_gobs; + s1++; + } + } + + if (update_count == 1) { + 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); + } + } else { + if (mod_vol > 0) { + mod_vol--; + dj_set_mod_volume((char)mod_vol); + } + } + + if (mod_fade_direction == 1) { + if (sfx_vol < 64) { + sfx_vol++; + dj_set_sfx_volume((char)sfx_vol); + } + } else { + if (sfx_vol > 0) { + sfx_vol--; + dj_set_sfx_volume((char)sfx_vol); + } + } + + fade_flag = 0; + for (c1 = 0; c1 < 768; c1++) { + if (cur_pal[c1] < pal[c1]) { + cur_pal[c1]++; + fade_flag = 1; + } else if (cur_pal[c1] > pal[c1]) { + cur_pal[c1]--; + fade_flag = 1; + } + } + if (fade_flag == 0 && end_loop_flag == 1) + break; + + 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 == 1) + setpalette(0, 256, cur_pal); + + if (update_count == 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; + } + +#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++) { + 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) + break; /* don't go back to menu if in net game. */ + } + + deinit_program(); + + return 0; +} + +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); + } + } + } +} + + +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) { + s1 = (player[c1].x >> 16); + s2 = (player[c1].y >> 16); + if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) { + if (player[c1].x_add < 0) + player[c1].x_add += 1024; + else + player[c1].x_add += 768; + } else if ((ban_map[(s2 + 16) >> 4][s1 >> 4] != BAN_SOLID && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_ICE) || (ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_ICE && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] != 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 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == 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; + } + } + } else { + if (player[c1].action_left) { + s1 = (player[c1].x >> 16); + s2 = (player[c1].y >> 16); + if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) { + if (player[c1].x_add > 0) + player[c1].x_add -= 1024; + else + player[c1].x_add -= 768; + } else if ((ban_map[(s2 + 16) >> 4][s1 >> 4] != BAN_SOLID && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_ICE) || (ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_ICE && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] != 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 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == 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; + } + } + } + } else if (player[c1].action_left) { + s1 = (player[c1].x >> 16); + s2 = (player[c1].y >> 16); + if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) { + if (player[c1].x_add > 0) + player[c1].x_add -= 1024; + else + player[c1].x_add -= 768; + } else if ((ban_map[(s2 + 16) >> 4][s1 >> 4] != BAN_SOLID && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_ICE) || (ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_ICE && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] != 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 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == 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; + } + } else if (player[c1].action_right) { + s1 = (player[c1].x >> 16); + s2 = (player[c1].y >> 16); + if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) { + if (player[c1].x_add < 0) + player[c1].x_add += 1024; + else + player[c1].x_add += 768; + } else if ((ban_map[(s2 + 16) >> 4][s1 >> 4] != BAN_SOLID && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_ICE) || (ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_ICE && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] != 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 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == 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; + } + } else if ((!player[c1].action_left) && (!player[c1].action_right)) { + s1 = (player[c1].x >> 16); + s2 = (player[c1].y >> 16); + if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID || ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SPRING || (((ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_SPRING) && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] != BAN_ICE) || (ban_map[(s2 + 16) >> 4][s1 >> 4] != BAN_ICE && (ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == 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 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == 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) { + 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; + if (ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_ICE || ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == 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); + } + if ((ban_map[(s2 + 7) >> 4][s1 >> 4] == BAN_VOID || ban_map[(s2 + 7) >> 4][(s1 + 15) >> 4] == BAN_VOID) && (ban_map[(s2 + 8) >> 4][s1 >> 4] == BAN_WATER || ban_map[(s2 + 8) >> 4][(s1 + 15) >> 4] == BAN_WATER)) { + 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); + } + } + 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) + player[c1].y_add += 32768; + else + player[c1].y_add += 16384; + if (player[c1].y_add > 0) + player[c1].y_add = 0; + } + } + } else { + + if (player[c1].action_up) { + player[c1].y_add -= 16384; + if (player[c1].y_add < -400000L) + player[c1].y_add = -400000L; + if ((ban_map[(s2 + 7) >> 4][s1 >> 4] == BAN_VOID || ban_map[(s2 + 7) >> 4][(s1 + 15) >> 4] == BAN_VOID) && (ban_map[(s2 + 8) >> 4][s1 >> 4] == BAN_WATER || ban_map[(s2 + 8) >> 4][(s1 + 15) >> 4] == BAN_WATER)) + 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) { + s1 = (player[c1].x >> 16); + s2 = (player[c1].y >> 16); + if (ban_map[s2 >> 4][s1 >> 4] == BAN_SOLID || ban_map[s2 >> 4][s1 >> 4] == BAN_ICE || ban_map[s2 >> 4][s1 >> 4] == BAN_SPRING || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SPRING) { + player[c1].x = (((s1 + 16) & 0xfff0)) << 16; + player[c1].x_add = 0; + } + s1 = (player[c1].x >> 16); + s2 = (player[c1].y >> 16); + if (ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_ICE || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_SPRING || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SPRING) { + player[c1].x = (((s1 + 16) & 0xfff0) - 16) << 16; + player[c1].x_add = 0; + } + } else { + s1 = (player[c1].x >> 16); + s2 = 0; + if (ban_map[s2 >> 4][s1 >> 4] == BAN_SOLID || ban_map[s2 >> 4][s1 >> 4] == BAN_ICE || ban_map[s2 >> 4][s1 >> 4] == BAN_SPRING || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SPRING) { + player[c1].x = (((s1 + 16) & 0xfff0)) << 16; + player[c1].x_add = 0; + } + s1 = (player[c1].x >> 16); + s2 = 0; + if (ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_ICE || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_SPRING || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == 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 (ban_map[(s2 + 15) >> 4][(s1 + 8) >> 4] == BAN_SPRING || ((ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SPRING && ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] != BAN_SOLID) || (ban_map[(s2 + 15) >> 4][s1 >> 4] != BAN_SOLID && ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == 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 (ban_map[(s2 + 15) >> 4][(s1 + 8) >> 4] == 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 (ban_map[(s2 + 15) >> 4][s1 >> 4] == 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 (ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == 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 (ban_map[s2 >> 4][s1 >> 4] == BAN_SOLID || ban_map[s2 >> 4][s1 >> 4] == BAN_ICE || ban_map[s2 >> 4][s1 >> 4] == BAN_SPRING || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_ICE || ban_map[s2 >> 4][(s1 + 15) >> 4] == 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 (ban_map[(s2 + 8) >> 4][(s1 + 8) >> 4] == BAN_WATER) { + if (player[c1].in_water == 0) { + 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); + } + } + 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 (ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_ICE) { + player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16; + player[c1].y_add = 0; + } + } else if (ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SPRING || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == 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 = alloca(strlen(fname) + 4); + int bufsize = 0; + int bufpos = 0; + gzFile gzf; + + strcpy(gzfilename, fname); + strcat(gzfilename, ".gz"); + + gzf = gzopen(gzfilename, "rb"); + if (gzf != NULL) { + 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/menu.c b/menu.c new file mode 100644 index 0000000..563c25e --- /dev/null +++ b/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/modify/Makefile b/modify/Makefile new file mode 100644 index 0000000..9286e02 --- /dev/null +++ b/modify/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -Wall -ansi -pedantic -O2 -ffast-math -funroll-loops \ + -Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -DNDEBUG \ + -I. -I.. -DUSE_NET -D_BSD_SOURCE +LIBS = -lm +SRCS = gobpack.c jnbpack.c jnbunpack.c +OBJS = gobpack.o jnbpack.o jnbunpack.o +TARGETS = ../gobpack ../jnbpack ../jnbunpack + +all: $(TARGETS) + +../gobpack: gobpack.c + $(CC) $(CFLAGS) -o ../gobpack $(LIBS) gobpack.c + +../jnbpack: jnbpack.c + $(CC) $(CFLAGS) -o ../jnbpack $(LIBS) jnbpack.c + +../jnbunpack: jnbunpack.c + $(CC) $(CFLAGS) -o ../jnbunpack $(LIBS) jnbunpack.c + +clean: + rm -f $(TARGETS) $(OBJS) diff --git a/modify/gobpack.c b/modify/gobpack.c new file mode 100644 index 0000000..7e524a8 --- /dev/null +++ b/modify/gobpack.c @@ -0,0 +1,421 @@ +#include +#include +#include + +typedef struct { + int num_images; + int *width; + int *height; + int *hs_x; + int *hs_y; + void **data; + void **orig_data; +} gob_t; + +static void read_pcx(FILE * handle, void *buf, int buf_len, char *pal) +{ + unsigned char *buffer=buf; + short c1; + short a, b; + long ofs1; + if (buffer != 0) { + fseek(handle, 128, SEEK_CUR); + ofs1 = 0; + while (ofs1 < buf_len) { + a = fgetc(handle); + if ((a & 0xc0) == 0xc0) { + b = fgetc(handle); + a &= 0x3f; + for (c1 = 0; c1 < a && ofs1 < buf_len; c1++) + buffer[ofs1++] = (char) b; + } else + buffer[ofs1++] = (char) a; + } + if (pal != 0) { + fseek(handle, 1, SEEK_CUR); + for (c1 = 0; c1 < 768; c1++) + pal[c1] = fgetc(handle) >> 2; + } + } +} + +static void write_pcx(FILE *pcxfile, unsigned char *data, int width, int height, unsigned char *palette) +{ + int i; + + fputc(0x0a, pcxfile); /* manufacturer */ + fputc(5, pcxfile); /* version */ + fputc(1, pcxfile); /* encoding */ + fputc(8, pcxfile); /* bits_per_pixel */ + fputc(0, pcxfile); /* xmin */ + fputc(0, pcxfile); + fputc(0, pcxfile); /* ymin */ + fputc(0, pcxfile); + fputc((width - 1) & 0xff, pcxfile); /* xmax */ + fputc(((width - 1) >> 8) & 0xff, pcxfile); + fputc((height - 1) & 0xff, pcxfile); /* ymax */ + fputc(((height - 1) >> 8) & 0xff, pcxfile); + fputc(width & 0xff, pcxfile); /* hres */ + fputc((width >> 8) & 0xff, pcxfile); + fputc(height & 0xff, pcxfile); /* vres */ + fputc((height >> 8) & 0xff, pcxfile); + for (i = 0; i < 48; i++) /* palette */ + fputc(0, pcxfile); + fputc(0, pcxfile); /* reserved */ + fputc(1, pcxfile); /* color_planes */ + fputc(width & 0xff, pcxfile); /* bytes_per_line */ + fputc((width >> 8) & 0xff, pcxfile); + fputc(1 & 0xff, pcxfile); /* palette_type */ + fputc((1 >> 8) & 0xff, pcxfile); + for (i = 0; i < 58; i++) /* filler */ + fputc(0, pcxfile); + + /* pack the image */ + + for (i = 0 ; i < width*height ; i++) + if ( (*data & 0xc0) != 0xc0) + fputc(*data++, pcxfile); + else + { + fputc(0xc1, pcxfile); + fputc(*data++, pcxfile); + } + + /* write the palette */ + + fputc(0x0c, pcxfile); /* palette ID byte */ + if (palette) + for (i = 0 ; i < 768 ; i++) + fputc(*palette++, pcxfile); + else + for (i = 0 ; i < 768 ; i++) + fputc(i / 3, pcxfile); +} + +int read_gob(FILE *handle, gob_t *gob, int len) +{ + unsigned char *gob_data; + int i; + + gob_data = malloc(len); + fread(gob_data, 1, len, handle); + + 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); + gob->data[i] = (unsigned short *)gob->orig_data[i]; + } + free(gob_data); + return 0; +} + +int write_gob(FILE *handle, gob_t *gob) +{ + int i; + int offset; + + fputc((gob->num_images >> 0) & 0xff, handle); + fputc((gob->num_images >> 8) & 0xff, handle); + + offset = 2 + (gob->num_images * 4); + + for (i=0; inum_images; i++) { + fputc((offset >> 0) & 0xff, handle); + fputc((offset >> 8) & 0xff, handle); + fputc((offset >> 16) & 0xff, handle); + fputc((offset >> 24) & 0xff, handle); + + offset += 8; + offset += gob->width[i] * gob->height[i]; + } + for (i=0; inum_images; i++) { + fputc((gob->width[i] >> 0) & 0xff, handle); + fputc((gob->width[i] >> 8) & 0xff, handle); + + fputc((gob->height[i] >> 0) & 0xff, handle); + fputc((gob->height[i] >> 8) & 0xff, handle); + + fputc((gob->hs_x[i] >> 0) & 0xff, handle); + fputc((gob->hs_x[i] >> 8) & 0xff, handle); + + fputc((gob->hs_y[i] >> 0) & 0xff, handle); + fputc((gob->hs_y[i] >> 8) & 0xff, handle); + + fwrite(gob->data[i], 1, gob->width[i] * gob->height[i], handle); + } + return 0; +} + +int main(int argc, char **argv) +{ + int usage = 0; + int unpack = 0; + FILE *f; + int len; + gob_t gob; + char *filename = NULL; + + if (argc < 2) + usage = 1; + + if (argc > 1) + if (argv[1][0] == '-') { + if (argv[1][1] == 'u') { + if (argc < 3) + usage = 1; + unpack = 1; + } else + usage = 1; + } + + if (usage) { + printf("Usage: gobpack [-u] [palette.pcx]\n\t-u to unpack the gob\n"); + return 1; + } + + if (unpack) { + int width, height; + int x_count, y_count; + int xi, yi; + int i; + unsigned char *data; + unsigned char *dst; + unsigned char palette[768]; + unsigned char *pal = NULL; + + if (argc > 3) { + f = fopen(argv[3], "rb"); + if (f) { + fseek(f, -769, SEEK_END); + i = fgetc(f); + if (i == 0x0c) { + pal = palette; + fread(pal, 1, 768, f); + } + fclose(f); + } + } + + filename = malloc(strlen(argv[2]) + 5); + if (!filename) { + printf("Not enough memory!\n"); + return -1; + } + + strcpy(filename, argv[2]); + strcat(filename, ".gob"); + f = fopen(filename, "rb"); + if (!f) { + printf("Couldn't open file %s\n", filename); + return -1; + } + fseek(f, 0, SEEK_END); + len = ftell(f); + fseek(f, 0, SEEK_SET); + + read_gob(f, &gob, len); + + fclose(f); + + width = 0; + height = 0; + for (i = 0; i < gob.num_images; i++) { + if (gob.height[i] > height) + height = gob.height[i]; + if (gob.width[i] > width) + width = gob.width[i]; + } + width+=2; + height+=2; + + data = malloc(400*256); + if (!data) { + printf("Not enough memory!\n"); + return -1; + } + memset(data, 0, 400*256); + + x_count = 400 / width; + y_count = 256 / width; + + for (yi = 0; yi < y_count; yi++) { + for (xi = 0; xi < x_count; xi++) { + int x,y; + unsigned char *src; + + i = yi * x_count + xi; + if (i >= gob.num_images) + continue; + + src = gob.data[i]; + dst = &data[(yi * height) * 400 + (xi * width)]; + for (y = 0; y < gob.height[i]; y++) { + for (x = 0; x < gob.width[i]; x++) { + dst[y * 400 + x] = src[y * gob.width[i] + x]; + } + } + } + } + + strcpy(filename, argv[2]); + strcat(filename, ".pcx"); + f = fopen(filename, "wb"); + if (!f) { + printf("Couldn't open file %s\n", filename); + return -1; + } + + write_pcx(f, data, 400, 256, pal); + + fclose(f); + + strcpy(filename, argv[2]); + strcat(filename, ".txt"); + f = fopen(filename, "w"); + if (!f) { + printf("Couldn't open file %s\n", filename); + return -1; + } + + fprintf(f, "num_images: %i\n\n", gob.num_images); + for (yi = 0; yi < y_count; yi++) { + for (xi = 0; xi < x_count; xi++) { + + i = yi * x_count + xi; + if (i >= gob.num_images) + continue; + + fprintf(f, "image: %i\n", i + 1); + fprintf(f, "x: %i\n", (xi * width)); + fprintf(f, "y: %i\n", (yi * height)); + fprintf(f, "width: %i\n", gob.width[i]); + fprintf(f, "height: %i\n", gob.height[i]); + fprintf(f, "hotspot_x: %i\n", gob.hs_x[i]); + fprintf(f, "hotspot_y: %i\n", gob.hs_y[i]); + fprintf(f, "\n"); + } + } + + fclose(f); + } else { + unsigned char *data; + int i = 0; + int x_pos = 0, y_pos = 0; + + data = malloc(400*256); + if (!data) { + printf("Not enough memory!\n"); + return -1; + } + + filename = malloc(strlen(argv[1]) + 5); + if (!filename) { + printf("Not enough memory!\n"); + return -1; + } + + strcpy(filename, argv[1]); + strcat(filename, ".pcx"); + f = fopen(filename, "rb"); + if (!f) { + printf("Couldn't open file %s\n", filename); + return -1; + } + + read_pcx(f, data, 400*256, NULL); + + fclose(f); + + strcpy(filename, argv[1]); + strcat(filename, ".txt"); + f = fopen(filename, "r"); + if (!f) { + printf("Couldn't open file %s\n", filename); + return -1; + } + + gob.num_images = 0; + + while (!feof(f)) { + char buffer[1024]; + int value; + + fscanf(f, "%s %i\n", buffer, &value); + if (strcmp(buffer, "num_images:") == 0) { + if (gob.num_images != 0) { + printf("Parse error in %s\n", filename); + return -1; + } + gob.num_images = value; + 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 *)); + } else if (strcmp(buffer, "image:") == 0) { + i = value - 1; + } else if (strcmp(buffer, "x:") == 0) { + x_pos = value; + } else if (strcmp(buffer, "y:") == 0) { + y_pos = value; + } else if (strcmp(buffer, "width:") == 0) { + gob.width[i] = value; + } else if (strcmp(buffer, "height:") == 0) { + gob.height[i] = value; + } else if (strcmp(buffer, "hotspot_x:") == 0) { + gob.hs_x[i] = value; + } else if (strcmp(buffer, "hotspot_y:") == 0) { + int x, y; + unsigned char *dst; + + gob.hs_y[i] = value; + gob.orig_data[i] = malloc(gob.width[i] * gob.height[i]); + gob.data[i] = gob.orig_data[i]; + dst = gob.data[i]; + for (y = 0; y < gob.height[i]; y++) { + for (x = 0; x < gob.width[i]; x++) { + dst[y * gob.width[i] + x] = data[(y_pos + y) * 400 + (x_pos + x)]; + } + } + } + } + + fclose(f); + + strcpy(filename, argv[1]); + strcat(filename, ".gob"); + f = fopen(filename, "wb"); + if (!f) { + printf("Couldn't open file %s\n", filename); + return -1; + } + + write_gob(f, &gob); + + fclose(f); + + printf("%s build\n", filename); + } + + return 0; +} diff --git a/modify/jnbpack.c b/modify/jnbpack.c new file mode 100644 index 0000000..8067372 --- /dev/null +++ b/modify/jnbpack.c @@ -0,0 +1,192 @@ +/* + * pack.c + * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/ + * + * Copyright (C) 2001 "timecop" + * + * 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 +#include +#include +#include +#ifdef LINUX +#include +#endif +#ifndef _MSC_VER +#include +#else +#include +#endif + +typedef struct { + char filename[12]; + unsigned int offset; + unsigned int size; +} DirEntry; + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +int main(int argc, char **argv) +{ + int fd; + DirEntry *datafile; + int num_entries, i; + int c; + char *outfile = NULL; + int offset = 0; + +#ifdef LINUX + while ((c = getopt(argc, argv, "o:")) != EOF) { + switch (c) { + case 'o': + if (optarg) { + outfile = strdup(optarg); + } + break; + } + } + argc -= optind; + argv += optind; +#else + c = 1; + while (c 12) { + fprintf(stderr, "filename %s is longer than 12 chars\n", argv[i]); + exit(1); + } + strncpy(datafile[i].filename, argv[i], 12); + datafile[i].size = dummy.st_size; + /* num_entries * (12 + 8) */ + datafile[i].offset = offset; + offset += datafile[i].size; + } + + /* here, we checked that all files are ok, and ready to roll the packfile */ + fd = open(outfile, O_RDWR | O_CREAT | O_BINARY, 0644); + if (fd == -1) { + perror("opening packfile"); + exit(1); + } + printf("Opened %s\n", outfile); + + /* write number of entries in this data file */ + { + char temp; + + temp = (num_entries >> 0) & 0xff; + write(fd, &temp, 1); + temp = (num_entries >> 8) & 0xff; + write(fd, &temp, 1); + temp = (num_entries >> 16) & 0xff; + write(fd, &temp, 1); + temp = (num_entries >> 24) & 0xff; + write(fd, &temp, 1); + } + + /* write the directory structure */ + for (i = 0; i < num_entries; i++) { + char temp; + + write(fd, &datafile[i].filename, 12); + temp = (datafile[i].offset >> 0) & 0xff; + write(fd, &temp, 1); + temp = (datafile[i].offset >> 8) & 0xff; + write(fd, &temp, 1); + temp = (datafile[i].offset >> 16) & 0xff; + write(fd, &temp, 1); + temp = (datafile[i].offset >> 24) & 0xff; + write(fd, &temp, 1); + temp = (datafile[i].size >> 0) & 0xff; + write(fd, &temp, 1); + temp = (datafile[i].size >> 8) & 0xff; + write(fd, &temp, 1); + temp = (datafile[i].size >> 16) & 0xff; + write(fd, &temp, 1); + temp = (datafile[i].size >> 24) & 0xff; + write(fd, &temp, 1); + } + + /* write in the actual files */ + for (i = 0; i < num_entries; i++) { + int infd; + char *buf; + + printf("adding %s ", argv[i]); + + infd = open(argv[i], O_RDONLY | O_BINARY); + if (infd == -1) { + perror("opening file"); + exit(1); + } + buf = malloc(datafile[i].size + 16); + read(infd, buf, datafile[i].size); + close(infd); + write(fd, buf, datafile[i].size); + free(buf); + printf(" OK\n"); + } + close(fd); + return 0; +} diff --git a/modify/jnbunpack.c b/modify/jnbunpack.c new file mode 100644 index 0000000..de7c851 --- /dev/null +++ b/modify/jnbunpack.c @@ -0,0 +1,102 @@ +/* + * unpack.c + * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/ + * + * Copyright (C) 2001 "timecop" + * + * 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 +#include +#include +#ifndef _MSC_VER +#include +#else +#include +#endif + +typedef struct { + char filename[12]; + unsigned int offset; + unsigned int size; +} DirEntry; + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +int main(int argc, char **argv) +{ + int fd; + DirEntry *datafile; + int num_entries, i; + + if (argc < 2) { + printf("dumbass, specify filename to unpack\n"); + exit(1); + } + + fd = open(argv[1], O_RDONLY | O_BINARY); + if (fd == -1) { + perror("open datafile"); + exit(1); + } + /* get number of entries */ + read(fd, &num_entries, 4); + + printf("%d entries in datafile\n", num_entries); + + datafile = calloc(num_entries, sizeof(DirEntry)); + read(fd, datafile, num_entries * sizeof(DirEntry)); + printf("Directory Listing:\n"); + for (i = 0; i < num_entries; i++) { + char filename[14]; + memset(filename, 0, sizeof(filename)); + strncpy(filename, datafile[i].filename, 12); + printf("%02d:\t%s (%u bytes)\n", i, filename, + datafile[i].size); + } + + for (i = 0; i < num_entries; i++) { + int outfd; + char filename[14]; + char *buf; + memset(filename, 0, sizeof(filename)); + strncpy(filename, datafile[i].filename, 12); + printf("Extracting %s ", filename); + + outfd = open(filename, O_RDWR | O_CREAT | O_BINARY, 0644); + if (!outfd) { + perror("cant open file"); + exit(1); + } + lseek(fd, datafile[i].offset, SEEK_SET); + buf = calloc(1, datafile[i].size + 16); + read(fd, buf, datafile[i].size); + write(outfd, buf, datafile[i].size); + close(outfd); + free(buf); + printf("OK\n"); + } + close(fd); + return 0; +} diff --git a/readme-win32.txt b/readme-win32.txt new file mode 100644 index 0000000..2ccb179 --- /dev/null +++ b/readme-win32.txt @@ -0,0 +1,7 @@ +This port is done by Florian Schulze (crow@icculus.org). +Homepage: http://www.icculus.org/jumpnbump/ + +There is a new scaled up graphics mode. To use it add -scaleup to the command line. +The sound is now much better than in the old SDL versions. + +Florian Schulze \ No newline at end of file diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..6d3e639 --- /dev/null +++ b/readme.txt @@ -0,0 +1,75 @@ + JUMP 'N BUMP + + by Brainchild Design in 1998 + + +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! + +We encourage you to spread this game to all your friends! +You are also allowed to put this game on your homepage, +on CD:s and magazines. You may even charge money for it. +It would be nice though, if you sent us a copy of your +article, so we know about it. + + + Code by Mattias Brynervall + Graphics by Andreas Brynervall + and Martin Magnusson + Music by Anders Nilsson + + + INSTRUCTIONS + +Leap over the log, and bound off to the right to play. +The different rabbits are controlled with: + + DOTT LEFT/RIGHT/UP + JIFFY A/D/W + FIZZ Mouse Buttons + MIJJI Joystick + +Jump around like crazy and try to get on top of the others. + + + HOMEPAGE + + http://www.algonet.se/~mattiasb + + + BRAINCHILD DESIGN + +Brainchild Design tries to make games with great gameplay. +"Simple but yet addictive" is something of a guideline. +Brainchild Designs members are: + + Andreas Brynervall andreasb@acc.umu.se + Mattias Brynervall matbr656@student.liu.se + Martin Magnusson marma102@student.liu.se + Anders Nilsson equel@swipnet.se + +Andreas, Mattias and Martin are old friends from school in +Nybro, in the south of Sweden. Anders joined a bit later. +He's from Malmö, and we met eachother over the internet. +Now we really don't know where he is, and we have no contact +with him. Where are you, Anders? + + + SECRETS + +Oh, there are some secrets in Jump 'n Bump. +Try and see if you can find them! +If you can't, you could always write and ask us... + + + TECHNICAL INFO + +Program code in C and ASM. Compiled with DJGPP and NASM. +Graphics drawn in Deluxe Paint 2 and Paint Shop Pro 5. +Music made with Fasttracker 2. +Readme written in Notepad. + + + DON'T FORGET TO SEND AN E-MAIL! \ No newline at end of file diff --git a/sdl/Makefile b/sdl/Makefile new file mode 100644 index 0000000..9a7fc7c --- /dev/null +++ b/sdl/Makefile @@ -0,0 +1,16 @@ +SDL_CFLAGS = `sdl-config --cflags` +CFLAGS = -Wall -ansi -pedantic -O2 -ffast-math -funroll-loops \ + -Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -DNDEBUG \ + -I. -I.. $(SDL_CFLAGS) -DUSE_SDL -DUSE_NET + +OBJS = gfx.o interrpt.o sound.o input.o +TARGET = ../sdl.a + +all: $(TARGET) + +$(TARGET): $(OBJS) + ar cru $(TARGET) $(OBJS) + ranlib $(TARGET) + +clean: + rm -f $(TARGET) $(OBJS) diff --git a/sdl/gfx.c b/sdl/gfx.c new file mode 100644 index 0000000..9585632 --- /dev/null +++ b/sdl/gfx.c @@ -0,0 +1,868 @@ +/* + * 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 "filter.h" + +#ifdef _MSC_VER + #include "jumpnbump32.xpm" +#elif __APPLE__ + #include "jumpnbump128.xpm" +#else + #include "jumpnbump64.xpm" +#endif +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 | SDL_INIT_JOYSTICK); + 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/sdl/input.c b/sdl/input.c new file mode 100644 index 0000000..3fa3522 --- /dev/null +++ b/sdl/input.c @@ -0,0 +1,109 @@ +/* + * 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/sdl/interrpt.c b/sdl/interrpt.c new file mode 100644 index 0000000..91a27ab --- /dev/null +++ b/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/sdl/jumpnbump128.xpm b/sdl/jumpnbump128.xpm new file mode 100644 index 0000000..2916506 --- /dev/null +++ b/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/sdl/jumpnbump32.xpm b/sdl/jumpnbump32.xpm new file mode 100644 index 0000000..dcd5edc --- /dev/null +++ b/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/sdl/jumpnbump64.xpm b/sdl/jumpnbump64.xpm new file mode 100644 index 0000000..746eff1 --- /dev/null +++ b/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; iLibraries. Write 'dj' on the first +row, and put an X to the left of it. Now you +should be able to compile. + +Oh, and please don't write to me and ask about +the code. It was almost a year since I wrote it, +and I really don't remember anything about it. + +Of course, I don't take any responsibility +whatsoever to what might happen to you, your +computer or your social life if you choose to +use this. + +'Nuff said! + +Mattias Brynervall, Brainchild Design +http://www.brainchilddesign.com \ No newline at end of file -- 2.11.4.GIT