]> icculus.org git repositories - crow/jumpnbump.git/blob - main.c
Refactored to simplify things a little bit.
[crow/jumpnbump.git] / main.c
1 /*
2  * main.c
3  * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/
4  *
5  * Copyright (C) 2001 Chuck Mason <cemason@users.sourceforge.net>
6  *
7  * Copyright (C) 2002 Florian Schulze <crow@icculus.org>
8  *
9  * This file is part of Jump'n'Bump.
10  *
11  * Jump'n'Bump is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * Jump'n'Bump is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26 #include "globals.h"
27 #include <fcntl.h>
28 #ifndef _MSC_VER
29 #include <unistd.h>
30 #endif
31
32 #ifdef BZLIB_SUPPORT
33 #include "bzlib.h"
34 #endif
35
36 #ifdef ZLIB_SUPPORT
37 #include "zlib.h"
38 #endif
39
40 #ifdef USE_NET
41 #include "SDL_net.h"
42 #endif /* USE_NET */
43
44 #ifndef M_PI
45 #define M_PI            3.14159265358979323846
46 #endif
47
48 gob_t rabbit_gobs = { 0 };
49 gob_t font_gobs = { 0 };
50 gob_t object_gobs = { 0 };
51 gob_t number_gobs = { 0 };
52
53 main_info_t main_info;
54 player_t player[JNB_MAX_PLAYERS];
55 player_anim_t player_anims[7];
56 object_t objects[NUM_OBJECTS];
57 joy_t joy;
58 mouse_t mouse;
59
60 char datfile_name[2048];
61
62 char *background_pic;
63 char *mask_pic;
64 int flip = 0;
65 char pal[768];
66 char cur_pal[768];
67
68 unsigned int ban_map[17][22] = {
69         {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
70         {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0},
71         {1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
72         {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1},
73         {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
74         {1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
75         {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1},
76         {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
77         {1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
78         {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 1},
79         {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1},
80         {1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1},
81         {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
82         {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
83         {2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0, 1, 3, 3, 3, 1, 1, 1},
84         {2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
85         {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
86 };
87
88 #define GET_BAN_MAP_XY(x,y) ban_map[(y) >> 4][(x) >> 4]
89
90 struct {
91         int num_frames;
92         int restart_frame;
93         struct {
94                 int image;
95                 int ticks;
96         } frame[10];
97 } object_anims[8] = {
98         {
99                 6, 0, {
100                         {
101                         0, 3}, {
102                         1, 3}, {
103                         2, 3}, {
104                         3, 3}, {
105                         4, 3}, {
106                         5, 3}, {
107                         0, 0}, {
108                         0, 0}, {
109                         0, 0}, {
110                         0, 0}
111                 }
112         }, {
113                 9, 0, {
114                         {
115                         6, 2}, {
116                         7, 2}, {
117                         8, 2}, {
118                         9, 2}, {
119                         10, 2}, {
120                         11, 2}, {
121                         12, 2}, {
122                         13, 2}, {
123                         14, 2}, {
124                         0, 0}
125                 }
126         }, {
127                 5, 0, {
128                         {
129                         15, 3}, {
130                         16, 3}, {
131                         16, 3}, {
132                         17, 3}, {
133                         18, 3}, {
134                         19, 3}, {
135                         0, 0}, {
136                         0, 0}, {
137                         0, 0}, {
138                         0, 0}
139                 }
140         }, {
141                 10, 0, {
142                         {
143                         20, 2}, {
144                         21, 2}, {
145                         22, 2}, {
146                         23, 2}, {
147                         24, 2}, {
148                         25, 2}, {
149                         24, 2}, {
150                         23, 2}, {
151                         22, 2}, {
152                         21, 2}
153                 }
154         }, {
155                 10, 0, {
156                         {
157                         26, 2}, {
158                         27, 2}, {
159                         28, 2}, {
160                         29, 2}, {
161                         30, 2}, {
162                         31, 2}, {
163                         30, 2}, {
164                         29, 2}, {
165                         28, 2}, {
166                         27, 2}
167                 }
168         }, {
169                 10, 0, {
170                         {
171                         32, 2}, {
172                         33, 2}, {
173                         34, 2}, {
174                         35, 2}, {
175                         36, 2}, {
176                         37, 2}, {
177                         36, 2}, {
178                         35, 2}, {
179                         34, 2}, {
180                         33, 2}
181                 }
182         }, {
183                 10, 0, {
184                         {
185                         38, 2}, {
186                         39, 2}, {
187                         40, 2}, {
188                         41, 2}, {
189                         42, 2}, {
190                         43, 2}, {
191                         42, 2}, {
192                         41, 2}, {
193                         40, 2}, {
194                         39, 2}
195                 }
196         }, {
197                 4, 0, {
198                         {
199                         76, 4}, {
200                         77, 4}, {
201                         78, 4}, {
202                         79, 4}, {
203                         0, 0}, {
204                         0, 0}, {
205                         0, 0}, {
206                         0, 0}, {
207                         0, 0}, {
208                         0, 0}
209                 }
210         }
211 };
212
213 int flies_enabled = 1;
214
215 struct {
216         int x, y;
217         int old_x, old_y;
218         int old_draw_x, old_draw_y;
219         int back[2];
220         int back_defined[2];
221 } flies[NUM_FLIES];
222
223 struct {
224         struct {
225                 short num_pobs;
226                 struct {
227                         int x, y;
228                         int image;
229                         gob_t *pob_data;
230                 } pobs[NUM_LEFTOVERS];
231         } page[2];
232 } leftovers;
233
234 int pogostick, bunnies_in_space, jetpack, lord_of_the_flies, blood_is_thicker_than_water;
235
236
237 #ifndef _MSC_VER
238 int filelength(int handle)
239 {
240         struct stat buf;
241
242         if (fstat(handle, &buf) == -1) {
243                 perror("filelength");
244                 exit(EXIT_FAILURE);
245         }
246
247         return buf.st_size;
248 }
249 #endif
250
251
252 /* networking shite. */
253
254 int client_player_num = -1;
255 int is_server = 1;
256 int is_net = 0;
257
258 #ifdef USE_NET
259 TCPsocket sock = NULL;
260 SDLNet_SocketSet socketset = NULL;
261
262 typedef struct
263 {
264         TCPsocket sock;
265         IPaddress addr;
266         SDLNet_SocketSet socketset;
267 } NetInfo;
268
269 NetInfo net_info[JNB_MAX_PLAYERS];
270 #endif
271
272 typedef struct
273 {
274         unsigned long cmd;
275         long arg;
276         long arg2;
277         long arg3;
278         long arg4;
279 } NetPacket;
280
281 #define NETPKTBUFSIZE (4 + 4 + 4 + 4 + 4)
282
283 #define NETCMD_NACK         (0xF00DF00D + 0)
284 #define NETCMD_ACK          (0xF00DF00D + 1)
285 #define NETCMD_HELLO        (0xF00DF00D + 2)
286 #define NETCMD_GREENLIGHT   (0xF00DF00D + 3)
287 #define NETCMD_MOVE         (0xF00DF00D + 4)
288 #define NETCMD_BYE          (0xF00DF00D + 5)
289 #define NETCMD_POSITION     (0xF00DF00D + 6)
290 #define NETCMD_ALIVE        (0xF00DF00D + 7)
291 #define NETCMD_KILL         (0xF00DF00D + 8)
292
293
294 #ifdef USE_NET
295 void bufToPacket(const char *buf, NetPacket *pkt)
296 {
297         SDLNet_Write32(*((Uint32*) (buf +  0)), &pkt->cmd);
298         SDLNet_Write32(*((Uint32*) (buf +  4)), &pkt->arg);
299         SDLNet_Write32(*((Uint32*) (buf +  8)), &pkt->arg2);
300         SDLNet_Write32(*((Uint32*) (buf + 12)), &pkt->arg3);
301         SDLNet_Write32(*((Uint32*) (buf + 16)), &pkt->arg4);
302 /*
303         pkt->cmd               =        ntohl(*((unsigned long *) (buf +  0)));
304         pkt->arg               = (long) ntohl(*((unsigned long *) (buf +  4)));
305         pkt->arg2              = (long) ntohl(*((unsigned long *) (buf +  8)));
306         pkt->arg3              = (long) ntohl(*((unsigned long *) (buf + 12)));
307         pkt->arg4              = (long) ntohl(*((unsigned long *) (buf + 16)));
308 */
309 }
310
311
312 void packetToBuf(const NetPacket *pkt, char *buf)
313 {
314         *((Uint32*) (buf +  0)) = SDLNet_Read32(&pkt->cmd);
315         *((Uint32*) (buf +  4)) = SDLNet_Read32(&pkt->arg);
316         *((Uint32*) (buf +  8)) = SDLNet_Read32(&pkt->arg2);
317         *((Uint32*) (buf + 12)) = SDLNet_Read32(&pkt->arg3);
318         *((Uint32*) (buf + 16)) = SDLNet_Read32(&pkt->arg4);
319 /*
320         *((unsigned long *) (buf +  0)) = htonl(pkt->cmd);
321         *((unsigned long *) (buf +  4)) = htonl((unsigned long) pkt->arg);
322         *((unsigned long *) (buf +  8)) = htonl((unsigned long) pkt->arg2);
323         *((unsigned long *) (buf + 12)) = htonl((unsigned long) pkt->arg3);
324         *((unsigned long *) (buf + 16)) = htonl((unsigned long) pkt->arg4);
325 */
326 }
327
328
329 void sendPacketToSock(TCPsocket s, NetPacket *pkt)
330 {
331         int bytes_left = NETPKTBUFSIZE;
332         int bw;
333         char buf[NETPKTBUFSIZE];
334         char *ptr = buf;
335
336         packetToBuf(pkt, buf);
337         while (bytes_left > 0) {
338                 bw = SDLNet_TCP_Send(s, ptr, bytes_left);
339                 if (bw < 0) {
340                         fprintf(stderr, "SERVER: SDLNet_TCP_Send(): %s\n", SDLNet_GetError());
341                         SDLNet_TCP_Close(s);
342                         exit(42);
343                 } else if (bw == 0) {
344                         SDL_Delay(1);
345                 } else {
346                         bytes_left -= bw;
347                         ptr += bw;
348                 }
349         }
350 }
351
352
353 void sendPacket(int playerid, NetPacket *pkt)
354 {
355         if ( (playerid < JNB_MAX_PLAYERS) && (playerid >= 0)) {
356                 if ((player[playerid].enabled) && (playerid != client_player_num)) {
357                         sendPacketToSock(net_info[playerid].sock, pkt);
358                 }
359         }
360 }
361
362
363 void sendPacketToAll(NetPacket *pkt)
364 {
365         int i;
366
367         for (i = 0; i < JNB_MAX_PLAYERS; i++) {
368                 sendPacket(i, pkt);
369         }
370 }
371
372 /** read a packet from the given TCPsocket
373 Returns -1 if some error occured, 0 if there was no data available and 1 if a
374 packet was successfully read.
375 Note: the socket has to be in the supplied socketset.
376 TODO: this function will bomb if a packet arrives in pieces, there is no
377 inherent guarantee that the next call will be made on the same socket. */
378 int grabPacket(TCPsocket s, SDLNet_SocketSet ss, NetPacket *pkt)
379 {
380         static char buf[NETPKTBUFSIZE];
381         static int buf_count = 0;
382         int rc;
383
384         if (SDLNet_CheckSockets(ss, 0) <= 0)
385                 return 0;
386
387         if(!SDLNet_SocketReady(s))
388                 return 0;
389
390         rc = SDLNet_TCP_Recv(s, &buf[buf_count], NETPKTBUFSIZE - buf_count);
391         if (rc <= 0) {
392                 /* closed connection? */
393                 return -1;
394         } else if (rc != NETPKTBUFSIZE) {
395                 /* we got a partial packet. Store what we got in the static buffer and
396                 return so that the next call can read the rest. Hopefully. */
397                 buf_count = rc;
398                 return 0;
399         } else {
400                 buf_count = 0;
401                 bufToPacket(buf, pkt);
402                 return 1;
403         }
404 }
405
406
407 int serverRecvPacket(NetPacket *pkt)
408 {
409         int rc;
410         int i;
411
412         assert(is_server);
413
414         for (i = 0; i < JNB_MAX_PLAYERS; i++) {
415                 TCPsocket s = net_info[i].sock;
416
417                 if ((i == client_player_num) || (!player[i].enabled))
418                         continue;
419
420                 rc = grabPacket(s, net_info[i].socketset, pkt);
421                 if (rc < 0) {
422                         NetPacket pkt;
423
424                         player[i].enabled = 0;
425                         SDLNet_TCP_Close(s);
426                         pkt.cmd = NETCMD_BYE;
427                         pkt.arg = i;
428                         pkt.arg2 = 0;
429                         pkt.arg3 = 0;
430                         pkt.arg4 = 0;
431                         sendPacketToAll(&pkt);
432                 } else if (rc > 0) {
433                         return(i);  /* it's all good. */
434                 }
435         }
436
437         return(-1);  /* no packets available currently. */
438 }
439
440
441 void wait_for_greenlight(void)
442 {
443         NetPacket pkt;
444         int i;
445
446         printf("CLIENT: Waiting for greenlight...\n");
447
448         do {
449                 int rc;
450                 while ((rc = grabPacket(sock, socketset, &pkt)) == 0) {
451                         SDL_Delay(100);  /* nap and then try again. */
452                 }
453
454                 if (rc < 0) {
455                         printf("CLIENT: Lost connection.\n");
456                         SDLNet_TCP_Close(sock);
457                         exit(42);
458                 }
459         } while (pkt.cmd != NETCMD_GREENLIGHT);
460
461         printf("CLIENT: Got greenlight.\n");
462
463         for (i = 0; i < JNB_MAX_PLAYERS; i++) {
464                 if (pkt.arg & (1 << i)) {
465                         printf("CLIENT: There is a player #%d.\n", i);
466                         player[i].enabled = 1;
467                 }
468         }
469 }
470
471
472 static int buggered_off = 0;
473
474
475 void tellServerGoodbye(void)
476 {
477         NetPacket pkt;
478
479         if (!buggered_off) {
480                 buggered_off = 1;
481                 pkt.cmd = NETCMD_BYE;
482                 pkt.arg = client_player_num;
483                 pkt.arg2 = 0;
484                 pkt.arg3 = 0;
485                 pkt.arg4 = 0;
486                 sendPacketToSock(sock, &pkt);
487         }
488 }
489 #endif /* USE_NET */
490
491
492 void processMovePacket(NetPacket *pkt)
493 {
494         int playerid = pkt->arg;
495         int movetype = ((pkt->arg2 >> 16) & 0xFF);
496         int newval   = ((pkt->arg2 >>  0) & 0xFF);
497
498         if (movetype == MOVEMENT_LEFT) {
499                 player[playerid].action_left = newval;
500         } else if (movetype == MOVEMENT_RIGHT) {
501                 player[playerid].action_right = newval;
502         } else if (movetype == MOVEMENT_UP) {
503                 player[playerid].action_up = newval;
504         } else {
505                 printf("bogus MOVE packet!\n");
506         }
507
508         player[playerid].x = pkt->arg3;
509         player[playerid].y = pkt->arg4;
510 }
511
512
513 void tellServerPlayerMoved(int playerid, int movement_type, int newval)
514 {
515         NetPacket pkt;
516
517         pkt.cmd = NETCMD_MOVE;
518         pkt.arg = playerid;
519         pkt.arg2 = ( ((movement_type & 0xFF) << 16) | ((newval & 0xFF) << 0) );
520         pkt.arg3 = player[playerid].x;
521         pkt.arg4 = player[playerid].y;
522
523         if (is_server) {
524                 processMovePacket(&pkt);
525 #ifdef USE_NET
526                 if (is_net)
527                         sendPacketToAll(&pkt);
528         } else {
529                 sendPacketToSock(sock, &pkt);
530 #endif
531         }
532 }
533
534
535 #ifdef USE_NET
536 void tellServerNewPosition(void)
537 {
538         NetPacket pkt;
539         pkt.cmd = NETCMD_POSITION;
540         pkt.arg = client_player_num;
541         pkt.arg2 = player[client_player_num].x;
542         pkt.arg3 = player[client_player_num].y;
543
544         if (is_server) {
545                 sendPacketToAll(&pkt);
546         } else {
547                 sendPacketToSock(sock, &pkt);
548         }
549 }
550 #endif /* USE_NET */
551
552
553 void processKillPacket(NetPacket *pkt)
554 {
555         int c1 = pkt->arg;
556         int c2 = pkt->arg2;
557         int x = pkt->arg3;
558         int y = pkt->arg4;
559         int c4 = 0;
560         int s1 = 0;
561
562         player[c1].y_add = -player[c1].y_add;
563         if (player[c1].y_add > -262144L)
564                 player[c1].y_add = -262144L;
565         player[c1].jump_abort = 1;
566         player[c2].dead_flag = 1;
567         if (player[c2].anim != 6) {
568                 player[c2].anim = 6;
569                 player[c2].frame = 0;
570                 player[c2].frame_tick = 0;
571                 player[c2].image = player_anims[player[c2].anim].frame[player[c2].frame].image + player[c2].direction * 9;
572                 if (main_info.no_gore == 0) {
573                         for (c4 = 0; c4 < 6; c4++)
574                                 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);
575                         for (c4 = 0; c4 < 6; c4++)
576                                 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 76);
577                         for (c4 = 0; c4 < 6; c4++)
578                                 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 77);
579                         for (c4 = 0; c4 < 8; c4++)
580                                 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 78);
581                         for (c4 = 0; c4 < 10; c4++)
582                                 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 79);
583                 }
584                 dj_play_sfx(SFX_DEATH, (unsigned short)(SFX_DEATH_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
585                 player[c1].bumps++;
586                 player[c1].bumped[c2]++;
587                 s1 = player[c1].bumps % 100;
588                 add_leftovers(0, 360, 34 + c1 * 64, s1 / 10, &number_gobs);
589                 add_leftovers(1, 360, 34 + c1 * 64, s1 / 10, &number_gobs);
590                 add_leftovers(0, 376, 34 + c1 * 64, s1 - (s1 / 10) * 10, &number_gobs);
591                 add_leftovers(1, 376, 34 + c1 * 64, s1 - (s1 / 10) * 10, &number_gobs);
592         }
593 }
594
595
596 #ifdef USE_NET
597 void processPositionPacket(NetPacket *pkt)
598 {
599         int playerid = pkt->arg;
600
601         player[playerid].x = pkt->arg2;
602         player[playerid].y = pkt->arg3;
603 }
604
605
606 void processAlivePacket(NetPacket *pkt)
607 {
608         int playerid = pkt->arg;
609
610         player[playerid].dead_flag = 0;
611         player[playerid].x = pkt->arg2;
612         player[playerid].y = pkt->arg3;
613 }
614
615
616 void serverTellEveryoneGoodbye(void)
617 {
618         int i;
619
620         if (!buggered_off) {
621                 buggered_off = 1;
622                 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
623                         if (player[i].enabled) {
624                                 NetPacket pkt;
625
626                                 pkt.cmd = NETCMD_BYE;
627                                 pkt.arg = i;
628                                 pkt.arg2 = 0;
629                                 pkt.arg3 = 0;
630                                 pkt.arg4 = 0;
631                                 sendPacketToAll(&pkt);
632                         }
633                 }
634         }
635 }
636
637
638 int server_said_bye = 0;
639
640
641 int update_players_from_server(void)
642 {
643         NetPacket pkt;
644         int rc;
645
646         assert(!is_server);
647
648         while ((rc = grabPacket(sock, socketset, &pkt)) != 0) {
649                 if (rc < 0) {
650                         printf("CLIENT: Lost connection.\n");
651                         pkt.cmd = NETCMD_BYE;
652                         pkt.arg = client_player_num;
653                 }
654
655                 if (pkt.cmd == NETCMD_BYE) {
656                         if (pkt.arg == client_player_num) {
657                                 SDLNet_FreeSocketSet(socketset);
658                                 SDLNet_TCP_Close(sock);
659                                 sock = NULL;
660                                 server_said_bye = 1;
661                                 return(0);
662                         } else {
663                                 player[pkt.arg].enabled = 0;
664                         }
665                 } else if (pkt.cmd == NETCMD_MOVE) {
666                         processMovePacket(&pkt);
667                 } else if (pkt.cmd == NETCMD_ALIVE) {
668                         processAlivePacket(&pkt);
669                 } else if (pkt.cmd == NETCMD_POSITION) {
670                         processPositionPacket(&pkt);
671                 } else if (pkt.cmd == NETCMD_KILL) {
672                         processKillPacket(&pkt);
673                 } else {
674                         printf("CLIENT: Got an unknown packet: 0x%lX.\n", pkt.cmd);
675                 }
676         }
677
678         return(1);
679 }
680
681
682 void serverSendAlive(int playerid)
683 {
684         NetPacket pkt;
685
686         assert(is_server);
687         pkt.cmd = NETCMD_ALIVE;
688         pkt.arg = playerid;
689         pkt.arg2 = player[playerid].x;
690         pkt.arg3 = player[playerid].y;
691         sendPacketToAll(&pkt);
692 }
693 #endif /* USE_NET */
694
695
696 void serverSendKillPacket(int killer, int victim)
697 {
698         NetPacket pkt;
699
700         assert(is_server);
701         pkt.cmd = NETCMD_KILL;
702         pkt.arg = killer;
703         pkt.arg2 = victim;
704         pkt.arg3 = player[victim].x;
705         pkt.arg4 = player[victim].y;
706         processKillPacket(&pkt);
707 #ifdef USE_NET
708         if (is_net)
709                 sendPacketToAll(&pkt);
710 #endif
711 }
712
713
714 #ifdef USE_NET
715 void update_players_from_clients(void)
716 {
717         int i;
718         NetPacket pkt;
719         int playerid;
720
721         assert(is_server);
722
723         while ((playerid = serverRecvPacket(&pkt)) >= 0) {
724                 if (pkt.cmd == NETCMD_BYE) {
725                         pkt.arg = playerid;  /* just in case. */
726                         sendPacketToAll(&pkt);
727                         player[playerid].enabled = 0;
728                         SDLNet_FreeSocketSet(net_info[playerid].socketset);
729                         SDLNet_TCP_Close(net_info[playerid].sock);
730                 } else if (pkt.cmd == NETCMD_POSITION) {
731                         pkt.arg = playerid;  /* just in case. */
732                         processPositionPacket(&pkt);
733                         for (i = 0; i < JNB_MAX_PLAYERS; i++) {
734                                 if (i != playerid) {
735                                         sendPacket(i, &pkt);
736                                 }
737                         }
738                 } else if (pkt.cmd == NETCMD_MOVE) {
739                         pkt.arg = playerid;  /* just in case. */
740                         /*
741                         pkt.arg3 = player[playerid].x;
742                         pkt.arg4 = player[playerid].y;
743                         */
744                         processMovePacket(&pkt);
745                         sendPacketToAll(&pkt);
746                 } else {
747                         printf("SERVER: Got unknown packet (0x%lX).\n", pkt.cmd);
748                 }
749         }
750 }
751
752
753 void init_server(const char *netarg)
754 {
755         NetPacket pkt;
756         IPaddress addr;
757         int i;
758         int wait_for_clients = ((netarg == NULL) ? 0 : atoi(netarg));
759         char *ipstr;
760
761         /** assign player number zero as default for the server */
762         if(-1 == client_player_num)
763                 client_player_num = 0;
764
765         if ((wait_for_clients >= JNB_MAX_PLAYERS) || (wait_for_clients < 0)) {
766                 printf("SERVER: Waiting for bogus client count (%d).\n", wait_for_clients);
767                 exit(42);
768         }
769
770         if (SDLNet_Init() < 0) {
771                 exit(42);
772         }
773         atexit(SDLNet_Quit);
774
775         SDLNet_ResolveHost(&addr, NULL, JNB_INETPORT);
776         ipstr = SDLNet_ResolveIP(&addr);
777         SDLNet_ResolveHost(&addr, ipstr, JNB_INETPORT);
778         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);
779         net_info[client_player_num].addr = addr;
780
781         addr.host = INADDR_ANY;
782         sock = SDLNet_TCP_Open(&addr);
783         if (sock == NULL) {
784                 fprintf(stderr, "SERVER: SDLNet_TCP_Open(): %s\n", SDLNet_GetError());
785                 exit(42);
786         }
787
788         player[client_player_num].enabled = 1;
789
790         printf("SERVER: waiting for (%d) clients...\n", wait_for_clients);
791
792         socketset = SDLNet_AllocSocketSet(JNB_MAX_PLAYERS + 1);
793         SDLNet_TCP_AddSocket(socketset, sock);
794
795         while (wait_for_clients > 0)
796         {
797                 char buf[NETPKTBUFSIZE];
798                 IPaddress *from;
799                 int negatory = 1;
800                 int br;
801                 TCPsocket s;
802
803                 /* Wait for events */
804                 SDLNet_CheckSockets(socketset, ~0);
805                 if ( SDLNet_SocketReady(sock) ) {
806                         s = SDLNet_TCP_Accept(sock);
807
808                         if (s == NULL)
809                         {
810                                 fprintf(stderr, "SERVER: SDLNet_TCP_Accept(): %s", SDLNet_GetError());
811                                 SDLNet_TCP_Close(sock);
812                                 exit(42);
813                         }
814                 } else
815                         continue;
816
817                 br = SDLNet_TCP_Recv(s, buf, NETPKTBUFSIZE);
818                 if (br < 0) {
819                         fprintf(stderr, "SERVER: SDLNet_TCP_Recv(): %s\n", SDLNet_GetError());
820                         SDLNet_TCP_Close(s);
821                         SDLNet_TCP_Close(sock);
822                         exit(42);
823                 }
824
825                 from = SDLNet_TCP_GetPeerAddress(s);
826                 ipstr = SDLNet_ResolveIP(from);
827                 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);
828
829                 if (br != NETPKTBUFSIZE) {
830                         printf("SERVER: Bogus packet.\n");
831                         continue;
832                 }
833
834                 bufToPacket(buf, &pkt);
835                 if (pkt.cmd != NETCMD_HELLO) {
836                         printf("SERVER: Bogus packet.\n");
837                         continue;
838                 }
839
840                 printf("SERVER: Client claims to be player #%ld.\n", pkt.arg);
841
842                 if (-1 == pkt.arg) {
843                         int i;
844                         for(i=0; i!=JNB_MAX_PLAYERS; ++i) {
845                                 if(!player[i].enabled) {
846                                         printf("SERVER: assigning %d as player number\n", i);
847                                         pkt.arg = i;
848                                         break;
849                                 }
850                         }
851                 }
852
853                 if ((pkt.arg>=JNB_MAX_PLAYERS)||(pkt.arg<0)) {
854                         printf("SERVER:  (that's an invalid player number.)\n");
855                 } else if (player[pkt.arg].enabled) {
856                         printf("SERVER:  (that player number is already taken.)\n");
857                 } else {
858                         negatory = 0;
859                 }
860
861                 if (negatory) {
862                         printf("SERVER: Forbidding connection.\n");
863                         pkt.cmd = NETCMD_NACK;
864                         sendPacketToSock(s, &pkt);
865                         SDLNet_TCP_Close(s);
866                 } else {
867                         player[pkt.arg].enabled = 1;
868                         net_info[pkt.arg].sock = s;
869                         net_info[pkt.arg].addr = *from;
870                         net_info[pkt.arg].socketset = SDLNet_AllocSocketSet(1);
871                         SDLNet_TCP_AddSocket(net_info[pkt.arg].socketset, net_info[pkt.arg].sock);
872                         wait_for_clients--;
873                         printf("SERVER: Granting connection. (%d) to go.\n", wait_for_clients);
874                         pkt.cmd = NETCMD_ACK;
875                         sendPacket(pkt.arg, &pkt);
876                 }
877         }
878
879         SDLNet_TCP_Close(sock);  /* done with the listen socket. */
880         SDLNet_FreeSocketSet(socketset);
881         sock = NULL;
882         socketset = NULL;
883
884         printf("SERVER: Got all our connections. Greenlighting clients...\n");
885
886         pkt.cmd = NETCMD_GREENLIGHT;
887         pkt.arg = 0;
888         for (i = 0; i < JNB_MAX_PLAYERS; i++) {
889                 if (player[i].enabled) {
890                         pkt.arg |= (1 << i);
891                 }
892         }
893         sendPacketToAll(&pkt);
894 }
895
896
897 void connect_to_server(char *netarg)
898 {
899         NetPacket pkt;
900         char buf[NETPKTBUFSIZE];
901         char *ipstr;
902         IPaddress hent;
903         IPaddress addr;
904         int br;
905
906         if (netarg == NULL) {
907                 printf("CLIENT: Need to specify host to connect to.\n");
908                 exit(42);
909         }
910
911         if (SDLNet_Init() < 0) {
912                 exit(42);
913         }
914         atexit(SDLNet_Quit);
915
916         SDLNet_ResolveHost(&addr, NULL, JNB_INETPORT);
917         ipstr = SDLNet_ResolveIP(&addr);
918         SDLNet_ResolveHost(&addr, ipstr, JNB_INETPORT);
919         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);
920
921         if (SDLNet_ResolveHost(&hent, netarg, JNB_INETPORT) < 0) {
922                 fprintf(stderr, "CLIENT: couldn't find host: %s\n", SDLNet_GetError());
923                 exit(42);
924         }
925
926         sock = SDLNet_TCP_Open(&hent);
927         if (sock == NULL) {
928                 fprintf(stderr, "CLIENT: SDLNet_TCP_Open(): %s\n", SDLNet_GetError());
929                 exit(42);
930         }
931
932         socketset = SDLNet_AllocSocketSet(1);
933         SDLNet_TCP_AddSocket(socketset, sock);
934
935         printf("CLIENT: connected to %s...\n", SDLNet_ResolveIP(&hent));
936
937         printf("CLIENT: Sending HELLO packet...\n");
938         pkt.cmd = NETCMD_HELLO;
939         pkt.arg = client_player_num;
940         sendPacketToSock(sock, &pkt);
941
942         printf("CLIENT: Waiting for ACK from server...\n");
943
944         br = SDLNet_TCP_Recv(sock, buf, NETPKTBUFSIZE);
945         if (br < 0) {
946                 fprintf(stderr, "CLIENT: recv(): %s\n", SDLNet_GetError());
947                 SDLNet_FreeSocketSet(socketset);
948                 SDLNet_TCP_Close(sock);
949                 exit(42);
950         }
951
952         if (br != NETPKTBUFSIZE) {
953                 printf("CLIENT: Bogus packet size (%d of %d). FIXME.\n", br, NETPKTBUFSIZE);
954                 SDLNet_FreeSocketSet(socketset);
955                 SDLNet_TCP_Close(sock);
956                 exit(42);
957         }
958
959         bufToPacket(buf, &pkt);
960
961         if (pkt.cmd == NETCMD_NACK) {
962                 printf("CLIENT: Server forbid us from playing.\n");
963                 SDLNet_FreeSocketSet(socketset);
964                 SDLNet_TCP_Close(sock);
965                 exit(42);
966         }
967
968         if (pkt.cmd != NETCMD_ACK) {
969                 printf("CLIENT: Unexpected packet (cmd=0x%lX).\n", pkt.cmd);
970                 SDLNet_FreeSocketSet(socketset);
971                 SDLNet_TCP_Close(sock);
972                 exit(42);
973         }
974
975         client_player_num = pkt.arg;
976         player[client_player_num].enabled = 1;
977         net_info[client_player_num].addr = addr;
978         printf("CLIENT: Server accepted our connection.\n");
979
980         wait_for_greenlight();
981 }
982 #endif /* USE_NET */
983
984
985 static void flip_pixels(unsigned char *pixels)
986 {
987         int x,y;
988         unsigned char temp;
989
990         assert(pixels);
991         for (y = 0; y < JNB_HEIGHT; y++) {
992                 for (x = 0; x < (352/2); x++) {
993                         temp = pixels[y*JNB_WIDTH+x];
994                         pixels[y*JNB_WIDTH+x] = pixels[y*JNB_WIDTH+(352-x)-1];
995                         pixels[y*JNB_WIDTH+(352-x)-1] = temp;
996                 }
997         }
998 }
999
1000
1001 void get_closest_player_to_point(int x,int y,int *dist,int *closest_player)
1002 {
1003         int c1;
1004         int cur_dist = 0;
1005
1006         *dist = 0x7fff;
1007         for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1008                 if (player[c1].enabled == 1) {
1009                         cur_dist = (int)sqrt((x - ((player[c1].x >> 16) + 8)) * (x - ((player[c1].x >> 16) + 8)) + (y - ((player[c1].y >> 16) + 8)) * (y - ((player[c1].y >> 16) + 8)));
1010                         if (cur_dist < *dist) {
1011                                 *closest_player = c1;
1012                                 *dist = cur_dist;
1013                         }
1014                 }
1015         }
1016 }
1017
1018
1019 static void update_flies(int update_count)
1020 {
1021         int c1;
1022         int closest_player = 0, dist;
1023         int s1, s2, s3, s4;
1024
1025         /* get center of fly swarm */
1026         s1 = s2 = 0;
1027         for (c1 = 0; c1 < NUM_FLIES; c1++) {
1028                 s1 += flies[c1].x;
1029                 s2 += flies[c1].y;
1030         }
1031         s1 /= NUM_FLIES;
1032         s2 /= NUM_FLIES;
1033
1034         if (update_count == 1) {
1035                 /* get closest player to fly swarm */
1036                 get_closest_player_to_point(s1, s2, &dist, &closest_player);
1037                 /* update fly swarm sound */
1038                 s3 = 32 - dist / 3;
1039                 if (s3 < 0)
1040                         s3 = 0;
1041                 dj_set_sfx_channel_volume(4, (char)(s3));
1042         }
1043
1044         for (c1 = 0; c1 < NUM_FLIES; c1++) {
1045                 /* get closest player to fly */
1046                 get_closest_player_to_point(flies[c1].x, flies[c1].y, &dist, &closest_player);
1047                 flies[c1].old_x = flies[c1].x;
1048                 flies[c1].old_y = flies[c1].y;
1049                 s3 = 0;
1050                 if ((s1 - flies[c1].x) > 30)
1051                         s3 += 1;
1052                 else if ((s1 - flies[c1].x) < -30)
1053                         s3 -= 1;
1054                 if (dist < 30) {
1055                         if (((player[closest_player].x >> 16) + 8) > flies[c1].x) {
1056                                 if (lord_of_the_flies == 0)
1057                                         s3 -= 1;
1058                                 else
1059                                         s3 += 1;
1060                         } else {
1061                                 if (lord_of_the_flies == 0)
1062                                         s3 += 1;
1063                                 else
1064                                         s3 -= 1;
1065                         }
1066                 }
1067                 s4 = rnd(3) - 1 + s3;
1068                 if ((flies[c1].x + s4) < 16)
1069                         s4 = 0;
1070                 if ((flies[c1].x + s4) > 351)
1071                         s4 = 0;
1072                 if (GET_BAN_MAP_XY(flies[c1].x + s4, flies[c1].y) != BAN_VOID)
1073                         s4 = 0;
1074                 flies[c1].x += s4;
1075                 s3 = 0;
1076                 if ((s2 - flies[c1].y) > 30)
1077                         s3 += 1;
1078                 else if ((s2 - flies[c1].y) < -30)
1079                         s3 -= 1;
1080                 if (dist < 30) {
1081                         if (((player[closest_player].y >> 16) + 8) > flies[c1].y) {
1082                                 if (lord_of_the_flies == 0)
1083                                         s3 -= 1;
1084                                 else
1085                                         s3 += 1;
1086                         } else {
1087                                 if (lord_of_the_flies == 0)
1088                                         s3 += 1;
1089                                 else
1090                                         s3 -= 1;
1091                         }
1092                 }
1093                 s4 = rnd(3) - 1 + s3;
1094                 if ((flies[c1].y + s4) < 0)
1095                         s4 = 0;
1096                 if ((flies[c1].y + s4) > 239)
1097                         s4 = 0;
1098                 if (GET_BAN_MAP_XY(flies[c1].x, flies[c1].y + s4) != BAN_VOID)
1099                         s4 = 0;
1100                 flies[c1].y += s4;
1101         }
1102 }
1103
1104
1105 static void player_kill(int c1, int c2)
1106 {
1107         if (player[c1].y_add >= 0) {
1108                 if (is_server)
1109                         serverSendKillPacket(c1, c2);
1110         } else {
1111                 if (player[c2].y_add < 0)
1112                         player[c2].y_add = 0;
1113         }
1114 }
1115
1116
1117 static void check_cheats(void)
1118 {
1119         if (strncmp(last_keys, "kcitsogop", strlen("kcitsogop")) == 0) {
1120                 pogostick ^= 1;
1121                 last_keys[0] = 0;
1122         }
1123         if (strncmp(last_keys, "ecapsniseinnub", strlen("ecapsniseinnub")) == 0) {
1124                 bunnies_in_space ^= 1;
1125                 last_keys[0] = 0;
1126         }
1127         if (strncmp(last_keys, "kcaptej", strlen("kcaptej")) == 0) {
1128                 jetpack ^= 1;
1129                 last_keys[0] = 0;
1130         }
1131         if (strncmp(last_keys, "seilfehtfodrol", strlen("seilfehtfodrol")) == 0) {
1132                 lord_of_the_flies ^= 1;
1133                 last_keys[0] = 0;
1134         }
1135         if (strncmp(last_keys, "retawnahtrekcihtsidoolb", strlen("retawnahtrekcihtsidoolb")) == 0) {
1136                 char blood[32] = {
1137                         63,32,32,53,17,17,42, 7,
1138                          7,28, 0, 0,24, 0, 0,19,
1139                          0, 0,12, 0, 0, 7, 0, 0
1140                 };
1141                 char water[32] = {
1142                         63,63,63,40,53,62,19,42,
1143                         60, 0,33,60, 3,32,46, 3,
1144                         26,33, 3,19,21, 1, 8, 8
1145                 };
1146                 int i;
1147
1148                 blood_is_thicker_than_water ^= 1;
1149                 if (blood_is_thicker_than_water == 1) {
1150                         for (i=0; i<32; i++)
1151                                 pal[432+i] = blood[i];
1152                 } else {
1153                         for (i=0; i<32; i++)
1154                                 pal[432+i] = water[i];
1155                 }
1156                 register_background(background_pic, pal);
1157                 recalculate_gob(&object_gobs, pal);
1158                 last_keys[0] = 0;
1159         }
1160 }
1161
1162
1163 static void collision_check(void)
1164 {
1165         int c1 = 0, c2 = 0, c3 = 0;
1166         int l1;
1167
1168         /* collision check */
1169         for (c3 = 0; c3 < 6; c3++) {
1170                 if (c3 == 0) {
1171                         c1 = 0;
1172                         c2 = 1;
1173                 } else if (c3 == 1) {
1174                         c1 = 0;
1175                         c2 = 2;
1176                 } else if (c3 == 2) {
1177                         c1 = 0;
1178                         c2 = 3;
1179                 } else if (c3 == 3) {
1180                         c1 = 1;
1181                         c2 = 2;
1182                 } else if (c3 == 4) {
1183                         c1 = 1;
1184                         c2 = 3;
1185                 } else if (c3 == 5) {
1186                         c1 = 2;
1187                         c2 = 3;
1188                 }
1189                 if (player[c1].enabled == 1 && player[c2].enabled == 1) {
1190                         if (labs(player[c1].x - player[c2].x) < (12L << 16) && labs(player[c1].y - player[c2].y) < (12L << 16)) {
1191                                 if ((labs(player[c1].y - player[c2].y) >> 16) > 5) {
1192                                         if (player[c1].y < player[c2].y) {
1193                                                 player_kill(c1,c2);
1194                                         } else {
1195                                                 player_kill(c2,c1);
1196                                         }
1197                                 } else {
1198                                         if (player[c1].x < player[c2].x) {
1199                                                 if (player[c1].x_add > 0)
1200                                                         player[c1].x = player[c2].x - (12L << 16);
1201                                                 else if (player[c2].x_add < 0)
1202                                                         player[c2].x = player[c1].x + (12L << 16);
1203                                                 else {
1204                                                         player[c1].x -= player[c1].x_add;
1205                                                         player[c2].x -= player[c2].x_add;
1206                                                 }
1207                                                 l1 = player[c2].x_add;
1208                                                 player[c2].x_add = player[c1].x_add;
1209                                                 player[c1].x_add = l1;
1210                                                 if (player[c1].x_add > 0)
1211                                                         player[c1].x_add = -player[c1].x_add;
1212                                                 if (player[c2].x_add < 0)
1213                                                         player[c2].x_add = -player[c2].x_add;
1214                                         } else {
1215                                                 if (player[c1].x_add > 0)
1216                                                         player[c2].x = player[c1].x - (12L << 16);
1217                                                 else if (player[c2].x_add < 0)
1218                                                         player[c1].x = player[c2].x + (12L << 16);
1219                                                 else {
1220                                                         player[c1].x -= player[c1].x_add;
1221                                                         player[c2].x -= player[c2].x_add;
1222                                                 }
1223                                                 l1 = player[c2].x_add;
1224                                                 player[c2].x_add = player[c1].x_add;
1225                                                 player[c1].x_add = l1;
1226                                                 if (player[c1].x_add < 0)
1227                                                         player[c1].x_add = -player[c1].x_add;
1228                                                 if (player[c2].x_add > 0)
1229                                                         player[c2].x_add = -player[c2].x_add;
1230                                         }
1231                                 }
1232                         }
1233                 }
1234         }
1235 }
1236
1237 static void game_loop(void) {
1238         int mod_vol, sfx_vol;
1239         int update_count = 1;
1240         int end_loop_flag = 0;
1241         int fade_flag = 0;
1242         int update_palette = 0;
1243         int mod_fade_direction;
1244         int i;
1245
1246         mod_vol = sfx_vol = 0;
1247         mod_fade_direction = 1;
1248         dj_ready_mod(MOD_GAME);
1249         dj_set_mod_volume((char)mod_vol);
1250         dj_set_sfx_volume((char)mod_vol);
1251         dj_start_mod();
1252
1253         intr_sysupdate();
1254
1255         while (1) {
1256                 while (update_count) {
1257
1258                         if (key_pressed(1) == 1) {
1259 #ifdef USE_NET
1260                                 if (is_net) {
1261                                         if (is_server) {
1262                                                 serverTellEveryoneGoodbye();
1263                                         } else {
1264                                                 tellServerGoodbye();
1265                                         }
1266                                 }
1267 #endif
1268                                 end_loop_flag = 1;
1269                                 memset(pal, 0, 768);
1270                                 mod_fade_direction = 0;
1271                         }
1272
1273                         check_cheats();
1274
1275 #ifdef USE_NET
1276                         if (is_net) {
1277                                 if (is_server) {
1278                                         update_players_from_clients();
1279                                 } else {
1280                                         if (!update_players_from_server()) {
1281                                                 break;  /* got a BYE packet */
1282                                         }
1283                                 }
1284                         }
1285 #endif
1286
1287                         steer_players();
1288
1289                         dj_mix();
1290
1291                         collision_check();
1292
1293                         dj_mix();
1294
1295                         main_info.page_info[main_info.draw_page].num_pobs = 0;
1296                         for (i = 0; i < JNB_MAX_PLAYERS; i++) {
1297                                 if (player[i].enabled == 1)
1298                                         main_info.page_info[main_info.draw_page].num_pobs++;
1299                         }
1300
1301                         update_objects();
1302
1303                         dj_mix();
1304
1305                         if (flies_enabled) {
1306                                 update_flies(update_count);
1307                         }
1308
1309                         dj_mix();
1310
1311                         if (update_count == 1) {
1312                                 int c2;
1313
1314                                 for (i = 0, c2 = 0; i < JNB_MAX_PLAYERS; i++) {
1315                                         if (player[i].enabled == 1) {
1316                                                 main_info.page_info[main_info.draw_page].pobs[c2].x = player[i].x >> 16;
1317                                                 main_info.page_info[main_info.draw_page].pobs[c2].y = player[i].y >> 16;
1318                                                 main_info.page_info[main_info.draw_page].pobs[c2].image = player[i].image + i * 18;
1319                                                 main_info.page_info[main_info.draw_page].pobs[c2].pob_data = &rabbit_gobs;
1320                                                 c2++;
1321                                         }
1322                                 }
1323
1324                                 draw_begin();
1325
1326                                 draw_pobs(main_info.draw_page);
1327
1328                                 dj_mix();
1329
1330                                 if (flies_enabled)
1331                                         draw_flies(main_info.draw_page);
1332
1333                                 draw_end();
1334                         }
1335
1336                         if (mod_fade_direction == 1) {
1337                                 if (mod_vol < 30) {
1338                                         mod_vol++;
1339                                         dj_set_mod_volume((char)mod_vol);
1340                                 }
1341                                 if (sfx_vol < 64) {
1342                                         sfx_vol++;
1343                                         dj_set_sfx_volume((char)sfx_vol);
1344                                 }
1345                         } else {
1346                                 if (mod_vol > 0) {
1347                                         mod_vol--;
1348                                         dj_set_mod_volume((char)mod_vol);
1349                                 }
1350                                 if (sfx_vol > 0) {
1351                                         sfx_vol--;
1352                                         dj_set_sfx_volume((char)sfx_vol);
1353                                 }
1354                         }
1355
1356                         fade_flag = 0;
1357                         for (i = 0; i < 768; i++) {
1358                                 if (cur_pal[i] < pal[i]) {
1359                                         cur_pal[i]++;
1360                                         fade_flag = 1;
1361                                 } else if (cur_pal[i] > pal[i]) {
1362                                         cur_pal[i]--;
1363                                         fade_flag = 1;
1364                                 }
1365                         }
1366                         if (fade_flag == 1)
1367                                 update_palette = 1;
1368                         if (fade_flag == 0 && end_loop_flag == 1)
1369                                 break;
1370
1371                         if (update_count == 1) {
1372                                 if (update_palette == 1) {
1373                                         setpalette(0, 256, cur_pal);
1374                                         update_palette = 0;
1375                                 }
1376
1377                                 main_info.draw_page ^= 1;
1378                                 main_info.view_page ^= 1;
1379
1380                                 flippage(main_info.view_page);
1381
1382                                 wait_vrt(1);
1383
1384                                 draw_begin();
1385
1386                                 if (flies_enabled)
1387                                         redraw_flies_background(main_info.draw_page);
1388
1389                                 redraw_pob_backgrounds(main_info.draw_page);
1390
1391                                 draw_leftovers(main_info.draw_page);
1392
1393                                 draw_end();
1394                         }
1395
1396                         update_count--;
1397                 }
1398
1399 #ifdef USE_NET
1400                 if (is_net) {
1401                         if ( (player[client_player_num].dead_flag == 0) &&
1402                                 (
1403                                  (player[client_player_num].action_left) ||
1404                                  (player[client_player_num].action_right) ||
1405                                  (player[client_player_num].action_up) ||
1406                                  (player[client_player_num].jump_ready == 0)
1407                                 )
1408                            ) {
1409                                 tellServerNewPosition();
1410                         }
1411                 }
1412 #endif
1413
1414                 update_count = intr_sysupdate();
1415
1416 #ifdef USE_NET
1417                 if (is_net) {
1418                         if ((server_said_bye) || ((fade_flag == 0) && (end_loop_flag == 1)))
1419                                 break;
1420                 } else
1421 #endif
1422                 if ((fade_flag == 0) && (end_loop_flag == 1))
1423                         break;
1424         }
1425 }
1426
1427
1428 static int menu_loop(void)
1429 {
1430         unsigned char *handle;
1431         int mod_vol;
1432         int c1, c2;
1433         int s1, s2;
1434
1435         while (1) {
1436
1437                 if (!is_net)
1438                         if (menu() != 0)
1439                                 deinit_program();
1440
1441                 if (key_pressed(1) == 1) {
1442                         return 0;
1443                 }
1444                 if (init_level(0, pal) != 0) {
1445                         deinit_level();
1446                         deinit_program();
1447                 }
1448
1449                 memset(cur_pal, 0, 768);
1450                 setpalette(0, 256, cur_pal);
1451
1452                 recalculate_gob(&rabbit_gobs, pal);
1453                 recalculate_gob(&object_gobs, pal);
1454                 recalculate_gob(&number_gobs, pal);
1455
1456                 flippage(1);
1457                 register_background(background_pic, pal);
1458                 flippage(0);
1459
1460                 if (flies_enabled) {
1461                         s1 = rnd(250) + 50;
1462                         s2 = rnd(150) + 50;
1463
1464                         for (c1 = 0; c1 < NUM_FLIES; c1++) {
1465                                 while (1) {
1466                                         flies[c1].x = s1 + rnd(101) - 50;
1467                                         flies[c1].y = s2 + rnd(101) - 50;
1468                                         if (GET_BAN_MAP_XY(flies[c1].x, flies[c1].y) == BAN_VOID)
1469                                                 break;
1470                                 }
1471                                 flies[c1].back_defined[0] = 0;
1472                                 flies[c1].back_defined[1] = 0;
1473                         }
1474                 }
1475
1476                 if (flies_enabled)
1477                         dj_play_sfx(SFX_FLY, SFX_FLY_FREQ, 0, 0, 0, 4);
1478
1479                 dj_set_nosound(0);
1480
1481                 lord_of_the_flies = bunnies_in_space = jetpack = pogostick = blood_is_thicker_than_water = 0;
1482                 main_info.page_info[0].num_pobs = 0;
1483                 main_info.page_info[1].num_pobs = 0;
1484                 main_info.view_page = 0;
1485                 main_info.draw_page = 1;
1486
1487                 game_loop();
1488
1489 #ifdef USE_NET
1490                 if (is_net) {
1491                         if (is_server) {
1492                                 serverTellEveryoneGoodbye();
1493                                 SDLNet_TCP_Close(sock);
1494                                 sock = NULL;
1495                         } else {
1496                                 if (!server_said_bye) {
1497                                         tellServerGoodbye();
1498                                 }
1499
1500                                 SDLNet_TCP_Close(sock);
1501                                 sock = NULL;
1502                         }
1503                 }
1504 #endif
1505
1506                 main_info.view_page = 0;
1507                 main_info.draw_page = 1;
1508
1509                 dj_stop_sfx_channel(4);
1510
1511                 deinit_level();
1512
1513                 memset(mask_pic, 0, JNB_WIDTH*JNB_HEIGHT);
1514                 register_mask(mask_pic);
1515
1516                 register_background(NULL, NULL);
1517
1518                 draw_begin();
1519
1520                 put_text(main_info.view_page, 100, 50, "DOTT", 2);
1521                 put_text(main_info.view_page, 160, 50, "JIFFY", 2);
1522                 put_text(main_info.view_page, 220, 50, "FIZZ", 2);
1523                 put_text(main_info.view_page, 280, 50, "MIJJI", 2);
1524                 put_text(main_info.view_page, 40, 80, "DOTT", 2);
1525                 put_text(main_info.view_page, 40, 110, "JIFFY", 2);
1526                 put_text(main_info.view_page, 40, 140, "FIZZ", 2);
1527                 put_text(main_info.view_page, 40, 170, "MIJJI", 2);
1528
1529                 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1530                         char str1[100];
1531
1532                         for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++) {
1533                                 if (c2 != c1) {
1534                                         sprintf(str1, "%d", player[c1].bumped[c2]);
1535                                         put_text(main_info.view_page, 100 + c2 * 60, 80 + c1 * 30, str1, 2);
1536                                 } else
1537                                         put_text(main_info.view_page, 100 + c2 * 60, 80 + c1 * 30, "-", 2);
1538                         }
1539                         sprintf(str1, "%d", player[c1].bumps);
1540                         put_text(main_info.view_page, 350, 80 + c1 * 30, str1, 2);
1541                 }
1542
1543                 put_text(main_info.view_page, 200, 230, "Press ESC to continue", 2);
1544
1545                 draw_end();
1546
1547                 flippage(main_info.view_page);
1548
1549                 if ((handle = dat_open("menu.pcx")) == 0) {
1550                         strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
1551                         return 1;
1552                 }
1553                 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
1554                         strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
1555                         return 1;
1556                 }
1557
1558                 /* fix dark font */
1559                 for (c1 = 0; c1 < 16; c1++) {
1560                         pal[(240 + c1) * 3 + 0] = c1 << 2;
1561                         pal[(240 + c1) * 3 + 1] = c1 << 2;
1562                         pal[(240 + c1) * 3 + 2] = c1 << 2;
1563                 }
1564
1565                 memset(cur_pal, 0, 768);
1566
1567                 setpalette(0, 256, cur_pal);
1568
1569                 mod_vol = 0;
1570                 dj_ready_mod(MOD_SCORES);
1571                 dj_set_mod_volume((char)mod_vol);
1572                 dj_start_mod();
1573                 dj_set_nosound(0);
1574
1575                 while (key_pressed(1) == 0) {
1576                         if (mod_vol < 35)
1577                                 mod_vol++;
1578                         dj_set_mod_volume((char)mod_vol);
1579                         for (c1 = 0; c1 < 768; c1++) {
1580                                 if (cur_pal[c1] < pal[c1])
1581                                         cur_pal[c1]++;
1582                         }
1583                         dj_mix();
1584                         intr_sysupdate();
1585                         wait_vrt(0);
1586                         setpalette(0, 256, cur_pal);
1587                         flippage(main_info.view_page);
1588                 }
1589                 while (key_pressed(1) == 1) {
1590                         dj_mix();
1591                         intr_sysupdate();
1592                 }
1593
1594                 memset(pal, 0, 768);
1595
1596                 while (mod_vol > 0) {
1597                         mod_vol--;
1598                         dj_set_mod_volume((char)mod_vol);
1599                         for (c1 = 0; c1 < 768; c1++) {
1600                                 if (cur_pal[c1] > pal[c1])
1601                                         cur_pal[c1]--;
1602                         }
1603                         dj_mix();
1604                         wait_vrt(0);
1605                         setpalette(0, 256, cur_pal);
1606                         flippage(main_info.view_page);
1607                 }
1608
1609                 fillpalette(0, 0, 0);
1610
1611                 dj_set_nosound(1);
1612                 dj_stop_mod();
1613
1614                 if (is_net)
1615                         return 0; /* don't go back to menu if in net game. */
1616         }
1617 }
1618
1619
1620 int main(int argc, char *argv[])
1621 {
1622         int result;
1623
1624         if (init_program(argc, argv, pal) != 0)
1625                 deinit_program();
1626
1627         if (main_info.fireworks == 1) {
1628                 fireworks();
1629                 deinit_program();
1630         }
1631
1632         result = menu_loop();
1633
1634         deinit_program();
1635
1636         return result;
1637 }
1638
1639
1640 static void player_action_left(int c1)
1641 {
1642         int s1 = 0, s2 = 0;
1643         int below_left, below, below_right;
1644
1645     s1 = (player[c1].x >> 16);
1646     s2 = (player[c1].y >> 16);
1647         below_left = GET_BAN_MAP_XY(s1, s2 + 16);
1648         below = GET_BAN_MAP_XY(s1 + 8, s2 + 16);
1649         below_right = GET_BAN_MAP_XY(s1 + 15, s2 + 16);
1650
1651     if (below == BAN_ICE) {
1652         if (player[c1].x_add > 0)
1653             player[c1].x_add -= 1024;
1654         else
1655             player[c1].x_add -= 768;
1656     } else if ((below_left != BAN_SOLID && below_right == BAN_ICE) || (below_left == BAN_ICE && below_right != BAN_SOLID)) {
1657         if (player[c1].x_add > 0)
1658             player[c1].x_add -= 1024;
1659         else
1660             player[c1].x_add -= 768;
1661     } else {
1662         if (player[c1].x_add > 0) {
1663             player[c1].x_add -= 16384;
1664             if (player[c1].x_add > -98304L && player[c1].in_water == 0 && below == BAN_SOLID)
1665                 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);
1666         } else
1667             player[c1].x_add -= 12288;
1668     }
1669     if (player[c1].x_add < -98304L)
1670         player[c1].x_add = -98304L;
1671     player[c1].direction = 1;
1672     if (player[c1].anim == 0) {
1673         player[c1].anim = 1;
1674         player[c1].frame = 0;
1675         player[c1].frame_tick = 0;
1676         player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1677     }
1678 }
1679
1680
1681 static void player_action_right(int c1)
1682 {
1683         int s1 = 0, s2 = 0;
1684         int below_left, below, below_right;
1685
1686     s1 = (player[c1].x >> 16);
1687     s2 = (player[c1].y >> 16);
1688         below_left = GET_BAN_MAP_XY(s1, s2 + 16);
1689         below = GET_BAN_MAP_XY(s1 + 8, s2 + 16);
1690         below_right = GET_BAN_MAP_XY(s1 + 15, s2 + 16);
1691
1692     if (below == BAN_ICE) {
1693         if (player[c1].x_add < 0)
1694             player[c1].x_add += 1024;
1695         else
1696             player[c1].x_add += 768;
1697     } else if ((below_left != BAN_SOLID && below_right == BAN_ICE) || (below_left == BAN_ICE && below_right != BAN_SOLID)) {
1698         if (player[c1].x_add > 0)
1699             player[c1].x_add += 1024;
1700         else
1701             player[c1].x_add += 768;
1702     } else {
1703         if (player[c1].x_add < 0) {
1704             player[c1].x_add += 16384;
1705             if (player[c1].x_add < 98304L && player[c1].in_water == 0 && below == BAN_SOLID)
1706                 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);
1707         } else
1708             player[c1].x_add += 12288;
1709     }
1710     if (player[c1].x_add > 98304L)
1711         player[c1].x_add = 98304L;
1712     player[c1].direction = 0;
1713     if (player[c1].anim == 0) {
1714         player[c1].anim = 1;
1715         player[c1].frame = 0;
1716         player[c1].frame_tick = 0;
1717         player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1718     }
1719 }
1720
1721
1722 #define GET_BAN_MAP_IN_WATER(s1, s2) (GET_BAN_MAP_XY((s1), ((s2) + 7)) == BAN_VOID || GET_BAN_MAP_XY(((s1) + 15), ((s2) + 7)) == BAN_VOID) && (GET_BAN_MAP_XY((s1), ((s2) + 8)) == BAN_WATER || GET_BAN_MAP_XY(((s1) + 15), ((s2) + 8)) == BAN_WATER)
1723
1724
1725 void steer_players(void)
1726 {
1727         int c1, c2;
1728         int s1 = 0, s2 = 0;
1729
1730         update_player_actions();
1731
1732         for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1733
1734                 if (player[c1].enabled == 1) {
1735
1736                         if (player[c1].dead_flag == 0) {
1737
1738                                 if (player[c1].action_left && player[c1].action_right) {
1739                                         if (player[c1].direction == 0) {
1740                                                 if (player[c1].action_right) {
1741                                                         player_action_right(c1);
1742                                                 }
1743                                         } else {
1744                                                 if (player[c1].action_left) {
1745                                                         player_action_left(c1);
1746                                                 }
1747                                         }
1748                                 } else if (player[c1].action_left) {
1749                                         player_action_left(c1);
1750                                 } else if (player[c1].action_right) {
1751                                         player_action_right(c1);
1752                                 } else if ((!player[c1].action_left) && (!player[c1].action_right)) {
1753                                         int below_left, below, below_right;
1754
1755                                         s1 = (player[c1].x >> 16);
1756                                         s2 = (player[c1].y >> 16);
1757                                         below_left = GET_BAN_MAP_XY(s1, s2 + 16);
1758                                         below = GET_BAN_MAP_XY(s1 + 8, s2 + 16);
1759                                         below_right = GET_BAN_MAP_XY(s1 + 15, s2 + 16);
1760                                         if (below == BAN_SOLID || below == BAN_SPRING || (((below_left == BAN_SOLID || below_left == BAN_SPRING) && below_right != BAN_ICE) || (below_left != BAN_ICE && (below_right == BAN_SOLID || below_right == BAN_SPRING)))) {
1761                                                 if (player[c1].x_add < 0) {
1762                                                         player[c1].x_add += 16384;
1763                                                         if (player[c1].x_add > 0)
1764                                                                 player[c1].x_add = 0;
1765                                                 } else {
1766                                                         player[c1].x_add -= 16384;
1767                                                         if (player[c1].x_add < 0)
1768                                                                 player[c1].x_add = 0;
1769                                                 }
1770                                                 if (player[c1].x_add != 0 && GET_BAN_MAP_XY((s1 + 8), (s2 + 16)) == BAN_SOLID)
1771                                                         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);
1772                                         }
1773                                         if (player[c1].anim == 1) {
1774                                                 player[c1].anim = 0;
1775                                                 player[c1].frame = 0;
1776                                                 player[c1].frame_tick = 0;
1777                                                 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1778                                         }
1779                                 }
1780                                 if (jetpack == 0) {
1781                                         /* no jetpack */
1782                                         if (pogostick == 1 || (player[c1].jump_ready == 1 && player[c1].action_up)) {
1783                                                 s1 = (player[c1].x >> 16);
1784                                                 s2 = (player[c1].y >> 16);
1785                                                 if (s2 < -16)
1786                                                         s2 = -16;
1787                                                 /* jump */
1788                                                 if (GET_BAN_MAP_XY(s1, (s2 + 16)) == BAN_SOLID || GET_BAN_MAP_XY(s1, (s2 + 16)) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), (s2 + 16)) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), (s2 + 16)) == BAN_ICE) {
1789                                                         player[c1].y_add = -280000L;
1790                                                         player[c1].anim = 2;
1791                                                         player[c1].frame = 0;
1792                                                         player[c1].frame_tick = 0;
1793                                                         player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1794                                                         player[c1].jump_ready = 0;
1795                                                         player[c1].jump_abort = 1;
1796                                                         if (pogostick == 0)
1797                                                                 dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1798                                                         else
1799                                                                 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1800                                                 }
1801                                                 /* jump out of water */
1802                                                 if (GET_BAN_MAP_IN_WATER(s1, s2)) {
1803                                                         player[c1].y_add = -196608L;
1804                                                         player[c1].in_water = 0;
1805                                                         player[c1].anim = 2;
1806                                                         player[c1].frame = 0;
1807                                                         player[c1].frame_tick = 0;
1808                                                         player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1809                                                         player[c1].jump_ready = 0;
1810                                                         player[c1].jump_abort = 1;
1811                                                         if (pogostick == 0)
1812                                                                 dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1813                                                         else
1814                                                                 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1815                                                 }
1816                                         }
1817                                         /* fall down by gravity */
1818                                         if (pogostick == 0 && (!player[c1].action_up)) {
1819                                                 player[c1].jump_ready = 1;
1820                                                 if (player[c1].in_water == 0 && player[c1].y_add < 0 && player[c1].jump_abort == 1) {
1821                                                         if (bunnies_in_space == 0)
1822                                                                 /* normal gravity */
1823                                                                 player[c1].y_add += 32768;
1824                                                         else
1825                                                                 /* light gravity */
1826                                                                 player[c1].y_add += 16384;
1827                                                         if (player[c1].y_add > 0)
1828                                                                 player[c1].y_add = 0;
1829                                                 }
1830                                         }
1831                                 } else {
1832                                         /* with jetpack */
1833                                         if (player[c1].action_up) {
1834                                                 player[c1].y_add -= 16384;
1835                                                 if (player[c1].y_add < -400000L)
1836                                                         player[c1].y_add = -400000L;
1837                                                 if (GET_BAN_MAP_IN_WATER(s1, s2))
1838                                                         player[c1].in_water = 0;
1839                                                 if (rnd(100) < 50)
1840                                                         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);
1841                                         }
1842                                 }
1843
1844                                 player[c1].x += player[c1].x_add;
1845                                 if ((player[c1].x >> 16) < 0) {
1846                                         player[c1].x = 0;
1847                                         player[c1].x_add = 0;
1848                                 }
1849                                 if ((player[c1].x >> 16) + 15 > 351) {
1850                                         player[c1].x = 336L << 16;
1851                                         player[c1].x_add = 0;
1852                                 }
1853                                 {
1854                                         if (player[c1].y > 0) {
1855                                                 s2 = (player[c1].y >> 16);
1856                                         } else {
1857                                                 /* check top line only */
1858                                                 s2 = 0;
1859                                         }
1860
1861                                         s1 = (player[c1].x >> 16);
1862                                         if (GET_BAN_MAP_XY(s1, s2) == BAN_SOLID || GET_BAN_MAP_XY(s1, s2) == BAN_ICE || GET_BAN_MAP_XY(s1, s2) == BAN_SPRING || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SPRING) {
1863                                                 player[c1].x = (((s1 + 16) & 0xfff0)) << 16;
1864                                                 player[c1].x_add = 0;
1865                                         }
1866
1867                                         s1 = (player[c1].x >> 16);
1868                                         if (GET_BAN_MAP_XY((s1 + 15), s2) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_SPRING || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SPRING) {
1869                                                 player[c1].x = (((s1 + 16) & 0xfff0) - 16) << 16;
1870                                                 player[c1].x_add = 0;
1871                                         }
1872                                 }
1873
1874                                 player[c1].y += player[c1].y_add;
1875
1876                                 s1 = (player[c1].x >> 16);
1877                                 s2 = (player[c1].y >> 16);
1878                                 if (GET_BAN_MAP_XY((s1 + 8), (s2 + 15)) == BAN_SPRING || ((GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SPRING && GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) != BAN_SOLID) || (GET_BAN_MAP_XY(s1, (s2 + 15)) != BAN_SOLID && GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SPRING))) {
1879                                         player[c1].y = ((player[c1].y >> 16) & 0xfff0) << 16;
1880                                         player[c1].y_add = -400000L;
1881                                         player[c1].anim = 2;
1882                                         player[c1].frame = 0;
1883                                         player[c1].frame_tick = 0;
1884                                         player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1885                                         player[c1].jump_ready = 0;
1886                                         player[c1].jump_abort = 0;
1887                                         for (c2 = 0; c2 < NUM_OBJECTS; c2++) {
1888                                                 if (objects[c2].used == 1 && objects[c2].type == OBJ_SPRING) {
1889                                                         if (GET_BAN_MAP_XY((s1 + 8), (s2 + 15)) == BAN_SPRING) {
1890                                                                 if ((objects[c2].x >> 20) == ((s1 + 8) >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
1891                                                                         objects[c2].frame = 0;
1892                                                                         objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
1893                                                                         objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
1894                                                                         break;
1895                                                                 }
1896                                                         } else {
1897                                                                 if (GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SPRING) {
1898                                                                         if ((objects[c2].x >> 20) == (s1 >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
1899                                                                                 objects[c2].frame = 0;
1900                                                                                 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
1901                                                                                 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
1902                                                                                 break;
1903                                                                         }
1904                                                                 } else if (GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SPRING) {
1905                                                                         if ((objects[c2].x >> 20) == ((s1 + 15) >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
1906                                                                                 objects[c2].frame = 0;
1907                                                                                 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
1908                                                                                 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
1909                                                                                 break;
1910                                                                         }
1911                                                                 }
1912                                                         }
1913                                                 }
1914                                         }
1915                                         dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1916                                 }
1917                                 s1 = (player[c1].x >> 16);
1918                                 s2 = (player[c1].y >> 16);
1919                                 if (s2 < 0)
1920                                         s2 = 0;
1921                                 if (GET_BAN_MAP_XY(s1, s2) == BAN_SOLID || GET_BAN_MAP_XY(s1, s2) == BAN_ICE || GET_BAN_MAP_XY(s1, s2) == BAN_SPRING || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_SPRING) {
1922                                         player[c1].y = (((s2 + 16) & 0xfff0)) << 16;
1923                                         player[c1].y_add = 0;
1924                                         player[c1].anim = 0;
1925                                         player[c1].frame = 0;
1926                                         player[c1].frame_tick = 0;
1927                                         player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1928                                 }
1929                                 s1 = (player[c1].x >> 16);
1930                                 s2 = (player[c1].y >> 16);
1931                                 if (s2 < 0)
1932                                         s2 = 0;
1933                                 if (GET_BAN_MAP_XY((s1 + 8), (s2 + 8)) == BAN_WATER) {
1934                                         if (player[c1].in_water == 0) {
1935                                                 /* falling into water */
1936                                                 player[c1].in_water = 1;
1937                                                 player[c1].anim = 4;
1938                                                 player[c1].frame = 0;
1939                                                 player[c1].frame_tick = 0;
1940                                                 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1941                                                 if (player[c1].y_add >= 32768) {
1942                                                         add_object(OBJ_SPLASH, (player[c1].x >> 16) + 8, ((player[c1].y >> 16) & 0xfff0) + 15, 0, 0, OBJ_ANIM_SPLASH, 0);
1943                                                         if (blood_is_thicker_than_water == 0)
1944                                                                 dj_play_sfx(SFX_SPLASH, (unsigned short)(SFX_SPLASH_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1945                                                         else
1946                                                                 dj_play_sfx(SFX_SPLASH, (unsigned short)(SFX_SPLASH_FREQ + rnd(2000) - 5000), 64, 0, 0, -1);
1947                                                 }
1948                                         }
1949                                         /* slowly move up to water surface */
1950                                         player[c1].y_add -= 1536;
1951                                         if (player[c1].y_add < 0 && player[c1].anim != 5) {
1952                                                 player[c1].anim = 5;
1953                                                 player[c1].frame = 0;
1954                                                 player[c1].frame_tick = 0;
1955                                                 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1956                                         }
1957                                         if (player[c1].y_add < -65536L)
1958                                                 player[c1].y_add = -65536L;
1959                                         if (player[c1].y_add > 65535L)
1960                                                 player[c1].y_add = 65535L;
1961                                         if (GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_ICE) {
1962                                                 player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16;
1963                                                 player[c1].y_add = 0;
1964                                         }
1965                                 } else if (GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SPRING || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SPRING) {
1966                                         player[c1].in_water = 0;
1967                                         player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16;
1968                                         player[c1].y_add = 0;
1969                                         if (player[c1].anim != 0 && player[c1].anim != 1) {
1970                                                 player[c1].anim = 0;
1971                                                 player[c1].frame = 0;
1972                                                 player[c1].frame_tick = 0;
1973                                                 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1974                                         }
1975                                 } else {
1976                                         if (player[c1].in_water == 0) {
1977                                                 if (bunnies_in_space == 0)
1978                                                         player[c1].y_add += 12288;
1979                                                 else
1980                                                         player[c1].y_add += 6144;
1981                                                 if (player[c1].y_add > 327680L)
1982                                                         player[c1].y_add = 327680L;
1983                                         } else {
1984                                                 player[c1].y = (player[c1].y & 0xffff0000) + 0x10000;
1985                                                 player[c1].y_add = 0;
1986                                         }
1987                                         player[c1].in_water = 0;
1988                                 }
1989                                 if (player[c1].y_add > 36864 && player[c1].anim != 3 && player[c1].in_water == 0) {
1990                                         player[c1].anim = 3;
1991                                         player[c1].frame = 0;
1992                                         player[c1].frame_tick = 0;
1993                                         player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1994                                 }
1995
1996                         }
1997
1998                         player[c1].frame_tick++;
1999                         if (player[c1].frame_tick >= player_anims[player[c1].anim].frame[player[c1].frame].ticks) {
2000                                 player[c1].frame++;
2001                                 if (player[c1].frame >= player_anims[player[c1].anim].num_frames) {
2002                                         if (player[c1].anim != 6)
2003                                                 player[c1].frame = player_anims[player[c1].anim].restart_frame;
2004                                         else
2005                                                 position_player(c1);
2006                                 }
2007                                 player[c1].frame_tick = 0;
2008                         }
2009                         player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2010
2011                 }
2012
2013         }
2014
2015 }
2016
2017
2018 void position_player(int player_num)
2019 {
2020         int c1;
2021         int s1, s2;
2022
2023         while (1) {
2024                 while (1) {
2025                         s1 = rnd(22);
2026                         s2 = rnd(16);
2027                         if (ban_map[s2][s1] == BAN_VOID && (ban_map[s2 + 1][s1] == BAN_SOLID || ban_map[s2 + 1][s1] == BAN_ICE))
2028                                 break;
2029                 }
2030                 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
2031                         if (c1 != player_num && player[c1].enabled == 1) {
2032                                 if (abs((s1 << 4) - (player[c1].x >> 16)) < 32 && abs((s2 << 4) - (player[c1].y >> 16)) < 32)
2033                                         break;
2034                         }
2035                 }
2036                 if (c1 == JNB_MAX_PLAYERS) {
2037                         player[player_num].x = (long) s1 << 20;
2038                         player[player_num].y = (long) s2 << 20;
2039                         player[player_num].x_add = player[player_num].y_add = 0;
2040                         player[player_num].direction = 0;
2041                         player[player_num].jump_ready = 1;
2042                         player[player_num].in_water = 0;
2043                         player[player_num].anim = 0;
2044                         player[player_num].frame = 0;
2045                         player[player_num].frame_tick = 0;
2046                         player[player_num].image = player_anims[player[player_num].anim].frame[player[player_num].frame].image;
2047
2048                         if (is_server) {
2049 #ifdef USE_NET
2050                                 if (is_net)
2051                                         serverSendAlive(player_num);
2052 #endif
2053                                 player[player_num].dead_flag = 0;
2054                         }
2055
2056                         break;
2057                 }
2058         }
2059
2060 }
2061
2062
2063 void add_object(int type, int x, int y, int x_add, int y_add, int anim, int frame)
2064 {
2065         int c1;
2066
2067         for (c1 = 0; c1 < NUM_OBJECTS; c1++) {
2068                 if (objects[c1].used == 0) {
2069                         objects[c1].used = 1;
2070                         objects[c1].type = type;
2071                         objects[c1].x = (long) x << 16;
2072                         objects[c1].y = (long) y << 16;
2073                         objects[c1].x_add = x_add;
2074                         objects[c1].y_add = y_add;
2075                         objects[c1].x_acc = 0;
2076                         objects[c1].y_acc = 0;
2077                         objects[c1].anim = anim;
2078                         objects[c1].frame = frame;
2079                         objects[c1].ticks = object_anims[anim].frame[frame].ticks;
2080                         objects[c1].image = object_anims[anim].frame[frame].image;
2081                         break;
2082                 }
2083         }
2084
2085 }
2086
2087
2088 void update_objects(void)
2089 {
2090         int c1;
2091         int s1 = 0;
2092
2093         for (c1 = 0; c1 < NUM_OBJECTS; c1++) {
2094                 if (objects[c1].used == 1) {
2095                         switch (objects[c1].type) {
2096                         case OBJ_SPRING:
2097                                 objects[c1].ticks--;
2098                                 if (objects[c1].ticks <= 0) {
2099                                         objects[c1].frame++;
2100                                         if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames) {
2101                                                 objects[c1].frame--;
2102                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2103                                         } else {
2104                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2105                                                 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2106                                         }
2107                                 }
2108                                 if (objects[c1].used == 1)
2109                                         add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2110                                 break;
2111                         case OBJ_SPLASH:
2112                                 objects[c1].ticks--;
2113                                 if (objects[c1].ticks <= 0) {
2114                                         objects[c1].frame++;
2115                                         if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2116                                                 objects[c1].used = 0;
2117                                         else {
2118                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2119                                                 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2120                                         }
2121                                 }
2122                                 if (objects[c1].used == 1)
2123                                         add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2124                                 break;
2125                         case OBJ_SMOKE:
2126                                 objects[c1].x += objects[c1].x_add;
2127                                 objects[c1].y += objects[c1].y_add;
2128                                 objects[c1].ticks--;
2129                                 if (objects[c1].ticks <= 0) {
2130                                         objects[c1].frame++;
2131                                         if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2132                                                 objects[c1].used = 0;
2133                                         else {
2134                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2135                                                 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2136                                         }
2137                                 }
2138                                 if (objects[c1].used == 1)
2139                                         add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2140                                 break;
2141                         case OBJ_YEL_BUTFLY:
2142                         case OBJ_PINK_BUTFLY:
2143                                 objects[c1].x_acc += rnd(128) - 64;
2144                                 if (objects[c1].x_acc < -1024)
2145                                         objects[c1].x_acc = -1024;
2146                                 if (objects[c1].x_acc > 1024)
2147                                         objects[c1].x_acc = 1024;
2148                                 objects[c1].x_add += objects[c1].x_acc;
2149                                 if (objects[c1].x_add < -32768)
2150                                         objects[c1].x_add = -32768;
2151                                 if (objects[c1].x_add > 32768)
2152                                         objects[c1].x_add = 32768;
2153                                 objects[c1].x += objects[c1].x_add;
2154                                 if ((objects[c1].x >> 16) < 16) {
2155                                         objects[c1].x = 16 << 16;
2156                                         objects[c1].x_add = -objects[c1].x_add >> 2;
2157                                         objects[c1].x_acc = 0;
2158                                 } else if ((objects[c1].x >> 16) > 350) {
2159                                         objects[c1].x = 350 << 16;
2160                                         objects[c1].x_add = -objects[c1].x_add >> 2;
2161                                         objects[c1].x_acc = 0;
2162                                 }
2163                                 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0) {
2164                                         if (objects[c1].x_add < 0) {
2165                                                 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2166                                         } else {
2167                                                 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2168                                         }
2169                                         objects[c1].x_add = -objects[c1].x_add >> 2;
2170                                         objects[c1].x_acc = 0;
2171                                 }
2172                                 objects[c1].y_acc += rnd(64) - 32;
2173                                 if (objects[c1].y_acc < -1024)
2174                                         objects[c1].y_acc = -1024;
2175                                 if (objects[c1].y_acc > 1024)
2176                                         objects[c1].y_acc = 1024;
2177                                 objects[c1].y_add += objects[c1].y_acc;
2178                                 if (objects[c1].y_add < -32768)
2179                                         objects[c1].y_add = -32768;
2180                                 if (objects[c1].y_add > 32768)
2181                                         objects[c1].y_add = 32768;
2182                                 objects[c1].y += objects[c1].y_add;
2183                                 if ((objects[c1].y >> 16) < 0) {
2184                                         objects[c1].y = 0;
2185                                         objects[c1].y_add = -objects[c1].y_add >> 2;
2186                                         objects[c1].y_acc = 0;
2187                                 } else if ((objects[c1].y >> 16) > 255) {
2188                                         objects[c1].y = 255 << 16;
2189                                         objects[c1].y_add = -objects[c1].y_add >> 2;
2190                                         objects[c1].y_acc = 0;
2191                                 }
2192                                 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0) {
2193                                         if (objects[c1].y_add < 0) {
2194                                                 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2195                                         } else {
2196                                                 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2197                                         }
2198                                         objects[c1].y_add = -objects[c1].y_add >> 2;
2199                                         objects[c1].y_acc = 0;
2200                                 }
2201                                 if (objects[c1].type == OBJ_YEL_BUTFLY) {
2202                                         if (objects[c1].x_add < 0 && objects[c1].anim != OBJ_ANIM_YEL_BUTFLY_LEFT) {
2203                                                 objects[c1].anim = OBJ_ANIM_YEL_BUTFLY_LEFT;
2204                                                 objects[c1].frame = 0;
2205                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2206                                                 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2207                                         } else if (objects[c1].x_add > 0 && objects[c1].anim != OBJ_ANIM_YEL_BUTFLY_RIGHT) {
2208                                                 objects[c1].anim = OBJ_ANIM_YEL_BUTFLY_RIGHT;
2209                                                 objects[c1].frame = 0;
2210                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2211                                                 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2212                                         }
2213                                 } else {
2214                                         if (objects[c1].x_add < 0 && objects[c1].anim != OBJ_ANIM_PINK_BUTFLY_LEFT) {
2215                                                 objects[c1].anim = OBJ_ANIM_PINK_BUTFLY_LEFT;
2216                                                 objects[c1].frame = 0;
2217                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2218                                                 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2219                                         } else if (objects[c1].x_add > 0 && objects[c1].anim != OBJ_ANIM_PINK_BUTFLY_RIGHT) {
2220                                                 objects[c1].anim = OBJ_ANIM_PINK_BUTFLY_RIGHT;
2221                                                 objects[c1].frame = 0;
2222                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2223                                                 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2224                                         }
2225                                 }
2226                                 objects[c1].ticks--;
2227                                 if (objects[c1].ticks <= 0) {
2228                                         objects[c1].frame++;
2229                                         if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2230                                                 objects[c1].frame = object_anims[objects[c1].anim].restart_frame;
2231                                         else {
2232                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2233                                                 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2234                                         }
2235                                 }
2236                                 if (objects[c1].used == 1)
2237                                         add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2238                                 break;
2239                         case OBJ_FUR:
2240                                 if (rnd(100) < 30)
2241                                         add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 0);
2242                                 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 0) {
2243                                         objects[c1].y_add += 3072;
2244                                         if (objects[c1].y_add > 196608L)
2245                                                 objects[c1].y_add = 196608L;
2246                                 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 2) {
2247                                         if (objects[c1].x_add < 0) {
2248                                                 if (objects[c1].x_add < -65536L)
2249                                                         objects[c1].x_add = -65536L;
2250                                                 objects[c1].x_add += 1024;
2251                                                 if (objects[c1].x_add > 0)
2252                                                         objects[c1].x_add = 0;
2253                                         } else {
2254                                                 if (objects[c1].x_add > 65536L)
2255                                                         objects[c1].x_add = 65536L;
2256                                                 objects[c1].x_add -= 1024;
2257                                                 if (objects[c1].x_add < 0)
2258                                                         objects[c1].x_add = 0;
2259                                         }
2260                                         objects[c1].y_add += 1024;
2261                                         if (objects[c1].y_add < -65536L)
2262                                                 objects[c1].y_add = -65536L;
2263                                         if (objects[c1].y_add > 65536L)
2264                                                 objects[c1].y_add = 65536L;
2265                                 }
2266                                 objects[c1].x += objects[c1].x_add;
2267                                 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)) {
2268                                         if (objects[c1].x_add < 0) {
2269                                                 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2270                                                 objects[c1].x_add = -objects[c1].x_add >> 2;
2271                                         } else {
2272                                                 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2273                                                 objects[c1].x_add = -objects[c1].x_add >> 2;
2274                                         }
2275                                 }
2276                                 objects[c1].y += objects[c1].y_add;
2277                                 if ((objects[c1].x >> 16) < -5 || (objects[c1].x >> 16) > 405 || (objects[c1].y >> 16) > 260)
2278                                         objects[c1].used = 0;
2279                                 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0)) {
2280                                         if (objects[c1].y_add < 0) {
2281                                                 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 2) {
2282                                                         objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2283                                                         objects[c1].x_add >>= 2;
2284                                                         objects[c1].y_add = -objects[c1].y_add >> 2;
2285                                                 }
2286                                         } else {
2287                                                 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1) {
2288                                                         if (objects[c1].y_add > 131072L) {
2289                                                                 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2290                                                                 objects[c1].x_add >>= 2;
2291                                                                 objects[c1].y_add = -objects[c1].y_add >> 2;
2292                                                         } else
2293                                                                 objects[c1].used = 0;
2294                                                 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3) {
2295                                                         objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2296                                                         if (objects[c1].y_add > 131072L)
2297                                                                 objects[c1].y_add = -objects[c1].y_add >> 2;
2298                                                         else
2299                                                                 objects[c1].y_add = 0;
2300                                                 }
2301                                         }
2302                                 }
2303                                 if (objects[c1].x_add < 0 && objects[c1].x_add > -16384)
2304                                         objects[c1].x_add = -16384;
2305                                 if (objects[c1].x_add > 0 && objects[c1].x_add < 16384)
2306                                         objects[c1].x_add = 16384;
2307                                 if (objects[c1].used == 1) {
2308                                         s1 = (int)(atan2(objects[c1].y_add, objects[c1].x_add) * 4 / M_PI);
2309                                         if (s1 < 0)
2310                                                 s1 += 8;
2311                                         if (s1 < 0)
2312                                                 s1 = 0;
2313                                         if (s1 > 7)
2314                                                 s1 = 7;
2315                                         add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].frame + s1, &object_gobs);
2316                                 }
2317                                 break;
2318                         case OBJ_FLESH:
2319                                 if (rnd(100) < 30) {
2320                                         if (objects[c1].frame == 76)
2321                                                 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 1);
2322                                         else if (objects[c1].frame == 77)
2323                                                 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 2);
2324                                         else if (objects[c1].frame == 78)
2325                                                 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 3);
2326                                 }
2327                                 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 0) {
2328                                         objects[c1].y_add += 3072;
2329                                         if (objects[c1].y_add > 196608L)
2330                                                 objects[c1].y_add = 196608L;
2331                                 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 2) {
2332                                         if (objects[c1].x_add < 0) {
2333                                                 if (objects[c1].x_add < -65536L)
2334                                                         objects[c1].x_add = -65536L;
2335                                                 objects[c1].x_add += 1024;
2336                                                 if (objects[c1].x_add > 0)
2337                                                         objects[c1].x_add = 0;
2338                                         } else {
2339                                                 if (objects[c1].x_add > 65536L)
2340                                                         objects[c1].x_add = 65536L;
2341                                                 objects[c1].x_add -= 1024;
2342                                                 if (objects[c1].x_add < 0)
2343                                                         objects[c1].x_add = 0;
2344                                         }
2345                                         objects[c1].y_add += 1024;
2346                                         if (objects[c1].y_add < -65536L)
2347                                                 objects[c1].y_add = -65536L;
2348                                         if (objects[c1].y_add > 65536L)
2349                                                 objects[c1].y_add = 65536L;
2350                                 }
2351                                 objects[c1].x += objects[c1].x_add;
2352                                 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)) {
2353                                         if (objects[c1].x_add < 0) {
2354                                                 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2355                                                 objects[c1].x_add = -objects[c1].x_add >> 2;
2356                                         } else {
2357                                                 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2358                                                 objects[c1].x_add = -objects[c1].x_add >> 2;
2359                                         }
2360                                 }
2361                                 objects[c1].y += objects[c1].y_add;
2362                                 if ((objects[c1].x >> 16) < -5 || (objects[c1].x >> 16) > 405 || (objects[c1].y >> 16) > 260)
2363                                         objects[c1].used = 0;
2364                                 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0)) {
2365                                         if (objects[c1].y_add < 0) {
2366                                                 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 2) {
2367                                                         objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2368                                                         objects[c1].x_add >>= 2;
2369                                                         objects[c1].y_add = -objects[c1].y_add >> 2;
2370                                                 }
2371                                         } else {
2372                                                 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1) {
2373                                                         if (objects[c1].y_add > 131072L) {
2374                                                                 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2375                                                                 objects[c1].x_add >>= 2;
2376                                                                 objects[c1].y_add = -objects[c1].y_add >> 2;
2377                                                         } else {
2378                                                                 if (rnd(100) < 10) {
2379                                                                         s1 = rnd(4) - 2;
2380                                                                         add_leftovers(0, objects[c1].x >> 16, (objects[c1].y >> 16) + s1, objects[c1].frame, &object_gobs);
2381                                                                         add_leftovers(1, objects[c1].x >> 16, (objects[c1].y >> 16) + s1, objects[c1].frame, &object_gobs);
2382                                                                 }
2383                                                                 objects[c1].used = 0;
2384                                                         }
2385                                                 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3) {
2386                                                         objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2387                                                         if (objects[c1].y_add > 131072L)
2388                                                                 objects[c1].y_add = -objects[c1].y_add >> 2;
2389                                                         else
2390                                                                 objects[c1].y_add = 0;
2391                                                 }
2392                                         }
2393                                 }
2394                                 if (objects[c1].x_add < 0 && objects[c1].x_add > -16384)
2395                                         objects[c1].x_add = -16384;
2396                                 if (objects[c1].x_add > 0 && objects[c1].x_add < 16384)
2397                                         objects[c1].x_add = 16384;
2398                                 if (objects[c1].used == 1)
2399                                         add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].frame, &object_gobs);
2400                                 break;
2401                         case OBJ_FLESH_TRACE:
2402                                 objects[c1].ticks--;
2403                                 if (objects[c1].ticks <= 0) {
2404                                         objects[c1].frame++;
2405                                         if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2406                                                 objects[c1].used = 0;
2407                                         else {
2408                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2409                                                 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2410                                         }
2411                                 }
2412                                 if (objects[c1].used == 1)
2413                                         add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2414                                 break;
2415                         }
2416                 }
2417         }
2418
2419 }
2420
2421
2422 int add_pob(int page, int x, int y, int image, gob_t *pob_data)
2423 {
2424
2425         if (main_info.page_info[page].num_pobs >= NUM_POBS)
2426                 return 1;
2427
2428         main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].x = x;
2429         main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].y = y;
2430         main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].image = image;
2431         main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].pob_data = pob_data;
2432         main_info.page_info[page].num_pobs++;
2433
2434         return 0;
2435
2436 }
2437
2438
2439 void draw_flies(int page)
2440 {
2441         int c2;
2442
2443         for (c2 = 0; c2 < NUM_FLIES; c2++) {
2444                 flies[c2].back[main_info.draw_page] = get_pixel(main_info.draw_page, flies[c2].x, flies[c2].y);
2445                 flies[c2].back_defined[main_info.draw_page] = 1;
2446                 if (mask_pic[(flies[c2].y * JNB_WIDTH) + flies[c2].x] == 0)
2447                         set_pixel(main_info.draw_page, flies[c2].x, flies[c2].y, 0);
2448         }
2449 }
2450
2451 void draw_pobs(int page)
2452 {
2453         int c1;
2454         int back_buf_ofs;
2455
2456         back_buf_ofs = 0;
2457
2458         for (c1 = main_info.page_info[page].num_pobs - 1; c1 >= 0; c1--) {
2459                 main_info.page_info[page].pobs[c1].back_buf_ofs = back_buf_ofs;
2460                 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);
2461                 if (scale_up)
2462                         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;
2463                 else
2464                         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);
2465                 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);
2466         }
2467
2468 }
2469
2470
2471 void redraw_flies_background(int page)
2472 {
2473         int c2;
2474
2475         for (c2 = NUM_FLIES - 1; c2 >= 0; c2--) {
2476                 if (flies[c2].back_defined[page] == 1)
2477                         set_pixel(page, flies[c2].old_draw_x, flies[c2].old_draw_y, flies[c2].back[page]);
2478                 flies[c2].old_draw_x = flies[c2].x;
2479                 flies[c2].old_draw_y = flies[c2].y;
2480         }
2481 }
2482
2483
2484 void redraw_pob_backgrounds(int page)
2485 {
2486         int c1;
2487
2488         for (c1 = 0; c1 < main_info.page_info[page].num_pobs; c1++)
2489                 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);
2490
2491 }
2492
2493
2494 int add_leftovers(int page, int x, int y, int image, gob_t *pob_data)
2495 {
2496
2497         if (leftovers.page[page].num_pobs >= NUM_LEFTOVERS)
2498                 return 1;
2499
2500         leftovers.page[page].pobs[leftovers.page[page].num_pobs].x = x;
2501         leftovers.page[page].pobs[leftovers.page[page].num_pobs].y = y;
2502         leftovers.page[page].pobs[leftovers.page[page].num_pobs].image = image;
2503         leftovers.page[page].pobs[leftovers.page[page].num_pobs].pob_data = pob_data;
2504         leftovers.page[page].num_pobs++;
2505
2506         return 0;
2507
2508 }
2509
2510
2511 void draw_leftovers(int page)
2512 {
2513         int c1;
2514
2515         for (c1 = leftovers.page[page].num_pobs - 1; c1 >= 0; c1--)
2516                 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);
2517
2518         leftovers.page[page].num_pobs = 0;
2519
2520 }
2521
2522
2523 int init_level(int level, char *pal)
2524 {
2525         unsigned char *handle;
2526         int c1, c2;
2527         int s1, s2;
2528
2529         if ((handle = dat_open("level.pcx")) == 0) {
2530                 strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n");
2531                 return 1;
2532         }
2533         if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
2534                 strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n");
2535                 return 1;
2536         }
2537         if (flip)
2538                 flip_pixels(background_pic);
2539         if ((handle = dat_open("mask.pcx")) == 0) {
2540                 strcpy(main_info.error_str, "Error loading 'mask.pcx', aborting...\n");
2541                 return 1;
2542         }
2543         if (read_pcx(handle, mask_pic, JNB_WIDTH*JNB_HEIGHT, 0) != 0) {
2544                 strcpy(main_info.error_str, "Error loading 'mask.pcx', aborting...\n");
2545                 return 1;
2546         }
2547         if (flip)
2548                 flip_pixels(mask_pic);
2549         register_mask(mask_pic);
2550
2551         for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
2552                 if (player[c1].enabled == 1) {
2553                         player[c1].bumps = 0;
2554                         for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++)
2555                                 player[c1].bumped[c2] = 0;
2556                         position_player(c1);
2557                 }
2558         }
2559
2560         for (c1 = 0; c1 < NUM_OBJECTS; c1++)
2561                 objects[c1].used = 0;
2562
2563         for (c1 = 0; c1 < 16; c1++) {
2564                 for (c2 = 0; c2 < 22; c2++) {
2565                         if (ban_map[c1][c2] == BAN_SPRING)
2566                                 add_object(OBJ_SPRING, c2 << 4, c1 << 4, 0, 0, OBJ_ANIM_SPRING, 5);
2567                 }
2568         }
2569
2570         while (1) {
2571                 s1 = rnd(22);
2572                 s2 = rnd(16);
2573                 if (ban_map[s2][s1] == BAN_VOID) {
2574                         add_object(OBJ_YEL_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2575                         break;
2576                 }
2577         }
2578         while (1) {
2579                 s1 = rnd(22);
2580                 s2 = rnd(16);
2581                 if (ban_map[s2][s1] == BAN_VOID) {
2582                         add_object(OBJ_YEL_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2583                         break;
2584                 }
2585         }
2586         while (1) {
2587                 s1 = rnd(22);
2588                 s2 = rnd(16);
2589                 if (ban_map[s2][s1] == BAN_VOID) {
2590                         add_object(OBJ_PINK_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2591                         break;
2592                 }
2593         }
2594         while (1) {
2595                 s1 = rnd(22);
2596                 s2 = rnd(16);
2597                 if (ban_map[s2][s1] == BAN_VOID) {
2598                         add_object(OBJ_PINK_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2599                         break;
2600                 }
2601         }
2602
2603         return 0;
2604
2605 }
2606
2607
2608 void deinit_level(void)
2609 {
2610         dj_set_nosound(1);
2611         dj_stop_mod();
2612 }
2613
2614
2615 #ifndef PATH_MAX
2616 #define PATH_MAX 1024
2617 #endif
2618 #ifndef O_BINARY
2619 #define O_BINARY 0
2620 #endif
2621
2622 unsigned char *datafile_buffer = NULL;
2623
2624 static void preread_datafile(const char *fname)
2625 {
2626     int fd = 0;
2627     int len;
2628
2629 #ifdef ZLIB_SUPPORT
2630     char *gzfilename;
2631     gzFile gzf;
2632 #endif
2633
2634 #ifdef BZLIB_SUPPORT
2635     char *bzfilename;
2636     BZFILE *bzf;
2637 #endif
2638
2639 #ifdef BZLIB_SUPPORT
2640     bzfilename = malloc(strlen(fname) + 5);
2641     strcpy(bzfilename, fname);
2642     strcat(bzfilename, ".bz2");
2643     bzf = BZ2_bzopen(bzfilename, "rb");
2644     free(bzfilename);
2645     bzfilename = NULL;
2646
2647     if (bzf != NULL) {
2648         int bufsize = 0;
2649         int bufpos = 0;
2650         int br;
2651         unsigned char *ptr;
2652         do {
2653             if (bufpos >= bufsize) {
2654                 bufsize += 1024 * 1024;
2655                 datafile_buffer = (unsigned char *) realloc(datafile_buffer, bufsize);
2656                 if (datafile_buffer == NULL) {
2657                     perror("realloc()");
2658                     exit(42);
2659                 }
2660             }
2661
2662             br = BZ2_bzread(bzf, datafile_buffer + bufpos, bufsize - bufpos);
2663             if (br == -1) {
2664                 fprintf(stderr, "gzread failed.\n");
2665                 exit(42);
2666             }
2667
2668             bufpos += br;
2669         } while (br>0);
2670
2671         /* try to shrink buffer... */
2672         ptr = (unsigned char *) realloc(datafile_buffer, bufpos);
2673         if (ptr != NULL)
2674             datafile_buffer = ptr;
2675
2676         BZ2_bzclose(bzf);
2677         return;
2678     }
2679
2680     /* drop through and try for an gzip compressed or uncompressed datafile... */
2681 #endif
2682
2683 #ifdef ZLIB_SUPPORT
2684     gzfilename = malloc(strlen(fname) + 4);
2685     strcpy(gzfilename, fname);
2686     strcat(gzfilename, ".gz");
2687     gzf = gzopen(gzfilename, "rb");
2688     free(gzfilename);
2689     gzfilename = NULL;
2690
2691     if (gzf != NULL) {
2692         int bufsize = 0;
2693         int bufpos = 0;
2694         unsigned char *ptr;
2695         do {
2696             int br;
2697             if (bufpos >= bufsize) {
2698                 bufsize += 1024 * 1024;
2699                 datafile_buffer = (unsigned char *) realloc(datafile_buffer, bufsize);
2700                 if (datafile_buffer == NULL) {
2701                     perror("realloc()");
2702                     exit(42);
2703                 }
2704             }
2705
2706             br = gzread(gzf, datafile_buffer + bufpos, bufsize - bufpos);
2707             if (br == -1) {
2708                 fprintf(stderr, "gzread failed.\n");
2709                 exit(42);
2710             }
2711
2712             bufpos += br;
2713         } while (!gzeof(gzf));
2714
2715         /* try to shrink buffer... */
2716         ptr = (unsigned char *) realloc(datafile_buffer, bufpos);
2717         if (ptr != NULL)
2718             datafile_buffer = ptr;
2719
2720         gzclose(gzf);
2721         return;
2722     }
2723
2724     /* drop through and try for an uncompressed datafile... */
2725 #endif
2726
2727     fd = open(fname, O_RDONLY | O_BINARY);
2728     if (fd == -1) {
2729         fprintf(stderr, "can't open %s:", fname);
2730         perror("");
2731         exit(42);
2732     }
2733
2734     len = filelength(fd);
2735     datafile_buffer = (unsigned char *) malloc(len);
2736     if (datafile_buffer == NULL) {
2737         perror("malloc()");
2738         close(fd);
2739         exit(42);
2740     }
2741
2742     if (read(fd, datafile_buffer, len) != len) {
2743         perror("read()");
2744         close(fd);
2745         exit(42);
2746     }
2747
2748     close(fd);
2749 }
2750
2751
2752 int init_program(int argc, char *argv[], char *pal)
2753 {
2754         char *netarg = NULL;
2755         unsigned char *handle = (unsigned char *) NULL;
2756         int c1 = 0, c2 = 0;
2757         int load_flag = 0;
2758         int force2, force3;
2759         sfx_data fly;
2760         int player_anim_data[] = {
2761                 1, 0, 0, 0x7fff, 0, 0, 0, 0, 0, 0,
2762                 4, 0, 0, 4, 1, 4, 2, 4, 3, 4,
2763                 1, 0, 4, 0x7fff, 0, 0, 0, 0, 0, 0,
2764                 4, 2, 5, 8, 6, 10, 7, 3, 6, 3,
2765                 1, 0, 6, 0x7fff, 0, 0, 0, 0, 0, 0,
2766                 2, 1, 5, 8, 4, 0x7fff, 0, 0, 0, 0,
2767                 1, 0, 8, 5, 0, 0, 0, 0, 0, 0
2768         };
2769
2770 #ifdef USE_NET
2771         memset(&net_info, 0, sizeof(net_info));
2772 #endif
2773
2774 #ifdef DOS
2775         if (__djgpp_nearptr_enable() == 0)
2776                 return 1;
2777 #endif
2778
2779         srand(time(NULL));
2780
2781         if (hook_keyb_handler() != 0)
2782                 return 1;
2783
2784         memset(&main_info, 0, sizeof(main_info));
2785
2786         strcpy(datfile_name, DATA_PATH);
2787
2788         force2 = force3 = 0;
2789
2790         if (argc > 1) {
2791                 for (c1 = 1; c1 < argc; c1++) {
2792                         if (stricmp(argv[c1], "-nosound") == 0)
2793                                 main_info.no_sound = 1;
2794                         else if (stricmp(argv[c1], "-musicnosound") == 0)
2795                                 main_info.music_no_sound = 1;
2796                         else if (stricmp(argv[c1], "-nogore") == 0)
2797                                 main_info.no_gore = 1;
2798                         else if (stricmp(argv[c1], "-noflies") == 0)
2799                                 flies_enabled = 0;
2800                         else if (stricmp(argv[c1], "-nojoy") == 0)
2801                                 main_info.joy_enabled = 0;
2802                         else if (stricmp(argv[c1], "-fireworks") == 0)
2803                                 main_info.fireworks = 1;
2804 #ifdef USE_SDL
2805                         else if (stricmp(argv[c1], "-fullscreen") == 0)
2806                                 fs_toggle();
2807 #endif
2808                         else if (stricmp(argv[c1], "-scaleup") == 0)
2809                                 set_scaling(1);
2810                         else if (stricmp(argv[c1], "-mirror") == 0)
2811                                 flip = 1;
2812                         else if (stricmp(argv[c1], "-dat") == 0) {
2813                                 if (c1 < (argc - 1)) {
2814                                         FILE *f;
2815
2816                                         if ((f = fopen(argv[c1 + 1], "rb")) != NULL) {
2817                                                 fclose(f);
2818                                                 strcpy(datfile_name, argv[c1 + 1]);
2819                                         }
2820                                 }
2821                         } else if (stricmp(argv[c1], "-player") == 0) {
2822                                 if (c1 < (argc - 1)) {
2823                                         if (client_player_num < 0)
2824                                                 client_player_num = atoi(argv[c1 + 1]);
2825                                 }
2826 #ifdef USE_NET
2827                         } else if (stricmp(argv[c1], "-server") == 0) {
2828                                 if (c1 < (argc - 1)) {
2829                                         is_server = 1;
2830                                         is_net = 1;
2831                                         netarg = argv[c1 + 1];
2832                                 }
2833                         } else if (stricmp(argv[c1], "-connect") == 0) {
2834                                 if (c1 < (argc - 1)) {
2835                                         is_server = 0;
2836                                         is_net = 1;
2837                                         netarg = argv[c1 + 1];
2838                                 }
2839 #endif
2840                         } else if (stricmp(argv[c1], "-mouse") == 0) {
2841                                 if (c1 < (argc - 1)) {
2842                                         if (stricmp(argv[c1 + 1], "2") == 0)
2843                                                 force2 = 1;
2844                                         if (stricmp(argv[c1 + 1], "3") == 0)
2845                                                 force3 = 1;
2846                                 }
2847                         }
2848                         else if (strstr(argv[1],"-v")) {
2849                                 printf("jumpnbump %s compiled %s at %s with",JNB_VERSION,__DATE__,__TIME__);
2850 #ifndef USE_NET
2851                                 printf("out");
2852 #endif
2853                                 printf(" network support.\n");
2854                                 return 1;
2855                         }
2856                         else if (strstr(argv[1],"-h")) {
2857                                 printf("Usage: jumpnbump [OPTION]...\n");
2858                                 printf("\n");
2859                                 printf("  -h                       this help\n");
2860                                 printf("  -v                       print version\n");
2861                                 printf("  -dat level.dat           play a different level\n");
2862 #ifdef USE_NET
2863                                 printf("  -server playercount      start as server waiting for players\n");
2864                                 printf("  -connect host            connect to server\n");
2865 #endif
2866                                 printf("  -player num              set main player to num (0-3). Needed for networking\n");
2867                                 printf("  -fireworks               screensaver mode\n");
2868                                 printf("  -fullscreen              run in fullscreen mode\n");
2869                                 printf("  -nosound                 play without sound\n");
2870                                 printf("  -nogore                  play without blood\n");
2871                                 printf("  -noflies                 disable flies\n");
2872                                 printf("  -mirror                  play with mirrored level\n");
2873                                 printf("  -scaleup                 play with doubled resolution (800x512)\n");
2874                                 printf("  -musicnosound            play with music but without sound\n");
2875                                 printf("\n");
2876                                 return 1;
2877                         }
2878                 }
2879         }
2880
2881         preread_datafile(datfile_name);
2882
2883 #if 0
2884 /** It should not be necessary to assign a default player number here. The
2885 server assigns one in init_server, the client gets one assigned by the server,
2886 all provided the user didn't choose one on the commandline. */
2887         if (is_net) {
2888                 if (client_player_num < 0)
2889                         client_player_num = 0;
2890                 player[client_player_num].enabled = 1;
2891         }
2892 #endif
2893
2894         main_info.pob_backbuf[0] = malloc(screen_pitch*screen_height);
2895         main_info.pob_backbuf[1] = malloc(screen_pitch*screen_height);
2896
2897         for (c1 = 0; c1 < 7; c1++) {
2898                 player_anims[c1].num_frames = player_anim_data[c1 * 10];
2899                 player_anims[c1].restart_frame = player_anim_data[c1 * 10 + 1];
2900                 for (c2 = 0; c2 < 4; c2++) {
2901                         player_anims[c1].frame[c2].image = player_anim_data[c1 * 10 + c2 * 2 + 2];
2902                         player_anims[c1].frame[c2].ticks = player_anim_data[c1 * 10 + c2 * 2 + 3];
2903                 }
2904         }
2905
2906         if ((handle = dat_open("menu.pcx")) == 0) {
2907                 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
2908                 return 1;
2909         }
2910         if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
2911                 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
2912                 return 1;
2913         }
2914
2915         if ((handle = dat_open("rabbit.gob")) == 0) {
2916                 strcpy(main_info.error_str, "Error loading 'rabbit.gob', aborting...\n");
2917                 return 1;
2918         }
2919         if (register_gob(handle, &rabbit_gobs, dat_filelen("rabbit.gob"))) {
2920                 /* error */
2921                 return 1;
2922         }
2923
2924         if ((handle = dat_open("objects.gob")) == 0) {
2925                 strcpy(main_info.error_str, "Error loading 'objects.gob', aborting...\n");
2926                 return 1;
2927         }
2928         if (register_gob(handle, &object_gobs, dat_filelen("objects.gob"))) {
2929                 /* error */
2930                 return 1;
2931         }
2932
2933         if ((handle = dat_open("font.gob")) == 0) {
2934                 strcpy(main_info.error_str, "Error loading 'font.gob', aborting...\n");
2935                 return 1;
2936         }
2937         if (register_gob(handle, &font_gobs, dat_filelen("font.gob"))) {
2938                 /* error */
2939                 return 1;
2940         }
2941
2942         if ((handle = dat_open("numbers.gob")) == 0) {
2943                 strcpy(main_info.error_str, "Error loading 'numbers.gob', aborting...\n");
2944                 return 1;
2945         }
2946         if (register_gob(handle, &number_gobs, dat_filelen("numbers.gob"))) {
2947                 /* error */
2948                 return 1;
2949         }
2950
2951         if (read_level() != 0) {
2952                 strcpy(main_info.error_str, "Error loading 'levelmap.txt', aborting...\n");
2953                 return 1;
2954         }
2955
2956         dj_init();
2957
2958         if (main_info.no_sound == 0) {
2959                 dj_autodetect_sd();
2960                 dj_set_mixing_freq(20000);
2961                 dj_set_stereo(0);
2962                 dj_set_auto_mix(0);
2963                 dj_set_dma_time(8);
2964                 dj_set_num_sfx_channels(5);
2965                 dj_set_sfx_volume(64);
2966                 dj_set_nosound(1);
2967                 dj_start();
2968
2969                 if ((handle = dat_open("jump.mod")) == 0) {
2970                         strcpy(main_info.error_str, "Error loading 'jump.mod', aborting...\n");
2971                         return 1;
2972                 }
2973                 if (dj_load_mod(handle, 0, MOD_MENU) != 0) {
2974                         strcpy(main_info.error_str, "Error loading 'jump.mod', aborting...\n");
2975                         return 1;
2976                 }
2977
2978                 if ((handle = dat_open("bump.mod")) == 0) {
2979                         strcpy(main_info.error_str, "Error loading 'bump.mod', aborting...\n");
2980                         return 1;
2981                 }
2982                 if (dj_load_mod(handle, 0, MOD_GAME) != 0) {
2983                         strcpy(main_info.error_str, "Error loading 'bump.mod', aborting...\n");
2984                         return 1;
2985                 }
2986
2987                 if ((handle = dat_open("scores.mod")) == 0) {
2988                         strcpy(main_info.error_str, "Error loading 'scores.mod', aborting...\n");
2989                         return 1;
2990                 }
2991                 if (dj_load_mod(handle, 0, MOD_SCORES) != 0) {
2992                         strcpy(main_info.error_str, "Error loading 'scores.mod', aborting...\n");
2993                         return 1;
2994                 }
2995
2996                 if ((handle = dat_open("jump.smp")) == 0) {
2997                         strcpy(main_info.error_str, "Error loading 'jump.smp', aborting...\n");
2998                         return 1;
2999                 }
3000                 if (dj_load_sfx(handle, 0, dat_filelen("jump.smp"), DJ_SFX_TYPE_SMP, SFX_JUMP) != 0) {
3001                         strcpy(main_info.error_str, "Error loading 'jump.smp', aborting...\n");
3002                         return 1;
3003                 }
3004
3005                 if ((handle = dat_open("death.smp")) == 0) {
3006                         strcpy(main_info.error_str, "Error loading 'death.smp', aborting...\n");
3007                         return 1;
3008                 }
3009                 if (dj_load_sfx(handle, 0, dat_filelen("death.smp"), DJ_SFX_TYPE_SMP, SFX_DEATH) != 0) {
3010                         strcpy(main_info.error_str, "Error loading 'death.smp', aborting...\n");
3011                         return 1;
3012                 }
3013
3014                 if ((handle = dat_open("spring.smp")) == 0) {
3015                         strcpy(main_info.error_str, "Error loading 'spring.smp', aborting...\n");
3016                         return 1;
3017                 }
3018                 if (dj_load_sfx(handle, 0, dat_filelen("spring.smp"), DJ_SFX_TYPE_SMP, SFX_SPRING) != 0) {
3019                         strcpy(main_info.error_str, "Error loading 'spring.smp', aborting...\n");
3020                         return 1;
3021                 }
3022
3023                 if ((handle = dat_open("splash.smp")) == 0) {
3024                         strcpy(main_info.error_str, "Error loading 'splash.smp', aborting...\n");
3025                         return 1;
3026                 }
3027                 if (dj_load_sfx(handle, 0, dat_filelen("splash.smp"), DJ_SFX_TYPE_SMP, SFX_SPLASH) != 0) {
3028                         strcpy(main_info.error_str, "Error loading 'splash.smp', aborting...\n");
3029                         return 1;
3030                 }
3031
3032                 if ((handle = dat_open("fly.smp")) == 0) {
3033                         strcpy(main_info.error_str, "Error loading 'fly.smp', aborting...\n");
3034                         return 1;
3035                 }
3036                 if (dj_load_sfx(handle, 0, dat_filelen("fly.smp"), DJ_SFX_TYPE_SMP, SFX_FLY) != 0) {
3037                         strcpy(main_info.error_str, "Error loading 'fly.smp', aborting...\n");
3038                         return 1;
3039                 }
3040
3041                 dj_get_sfx_settings(SFX_FLY, &fly);
3042                 fly.priority = 10;
3043                 fly.default_freq = SFX_FLY_FREQ;
3044                 fly.loop = 1;
3045                 fly.loop_start = 0;
3046                 fly.loop_length = fly.length;
3047                 dj_set_sfx_settings(SFX_FLY, &fly);
3048         }
3049
3050         if ((background_pic = malloc(JNB_WIDTH*JNB_HEIGHT)) == NULL)
3051                 return 1;
3052         if ((mask_pic = malloc(JNB_WIDTH*JNB_HEIGHT)) == NULL)
3053                 return 1;
3054         memset(mask_pic, 0, JNB_WIDTH*JNB_HEIGHT);
3055         register_mask(mask_pic);
3056
3057         /* fix dark font */
3058         for (c1 = 0; c1 < 16; c1++) {
3059                 pal[(240 + c1) * 3 + 0] = c1 << 2;
3060                 pal[(240 + c1) * 3 + 1] = c1 << 2;
3061                 pal[(240 + c1) * 3 + 2] = c1 << 2;
3062         }
3063
3064         setpalette(0, 256, pal);
3065
3066         init_inputs();
3067
3068         recalculate_gob(&font_gobs, pal);
3069
3070         if (main_info.joy_enabled == 1 && main_info.fireworks == 0) {
3071                 load_flag = 0;
3072                 put_text(0, 200, 40, "JOYSTICK CALIBRATION", 2);
3073                 put_text(0, 200, 100, "Move the joystick to the", 2);
3074                 put_text(0, 200, 115, "UPPER LEFT", 2);
3075                 put_text(0, 200, 130, "and press button A", 2);
3076                 put_text(0, 200, 200, "Or press ESC to use", 2);
3077                 put_text(0, 200, 215, "previous settings", 2);
3078                 if (calib_joy(0) != 0)
3079                         load_flag = 1;
3080                 else {
3081                         register_background(NULL, NULL);
3082
3083                         main_info.view_page = 1;
3084                         flippage(1);
3085
3086                         wait_vrt(0);
3087
3088                         put_text(1, 200, 40, "JOYSTICK CALIBRATION", 2);
3089                         put_text(1, 200, 100, "Move the joystick to the", 2);
3090                         put_text(1, 200, 115, "LOWER RIGHT", 2);
3091                         put_text(1, 200, 130, "and press button A", 2);
3092                         put_text(1, 200, 200, "Or press ESC to use", 2);
3093                         put_text(1, 200, 215, "previous settings", 2);
3094                         if (calib_joy(1) != 0)
3095                                 load_flag = 1;
3096                         else {
3097                                 register_background(NULL, NULL);
3098                                 flippage(0);
3099
3100                                 wait_vrt(0);
3101
3102                                 put_text(0, 200, 40, "JOYSTICK CALIBRATION", 2);
3103                                 put_text(0, 200, 100, "Move the joystick to the", 2);
3104                                 put_text(0, 200, 115, "CENTER", 2);
3105                                 put_text(0, 200, 130, "and press button A", 2);
3106                                 put_text(0, 200, 200, "Or press ESC to use", 2);
3107                                 put_text(0, 200, 215, "previous settings", 2);
3108                                 if (calib_joy(2) != 0)
3109                                         load_flag = 1;
3110                                 else {
3111                                         if (joy.calib_data.x1 == joy.calib_data.x2)
3112                                                 joy.calib_data.x1 -= 10;
3113                                         if (joy.calib_data.x3 == joy.calib_data.x2)
3114                                                 joy.calib_data.x3 += 10;
3115                                         if (joy.calib_data.y1 == joy.calib_data.y2)
3116                                                 joy.calib_data.y1 -= 10;
3117                                         if (joy.calib_data.y3 == joy.calib_data.y2)
3118                                                 joy.calib_data.y3 += 10;
3119                                         write_calib_data();
3120                                 }
3121                         }
3122                 }
3123                 if (load_flag == 1) {
3124                         if ((handle = dat_open("calib.dat")) == 0) {
3125                                 strcpy(main_info.error_str, "Error loading 'calib.dat', aborting...\n");
3126                                 return 1;
3127                         }
3128                         joy.calib_data.x1 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3129                         joy.calib_data.x2 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3130                         joy.calib_data.x3 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3131                         joy.calib_data.y1 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3132                         joy.calib_data.y2 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3133                         joy.calib_data.y3 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3134                 }
3135         }
3136
3137 #ifdef USE_NET
3138         if (is_net) {
3139                 if (is_server) {
3140                         init_server(netarg);
3141                 } else {
3142                         connect_to_server(netarg);
3143                 }
3144         }
3145 #endif
3146
3147         return 0;
3148
3149 }
3150
3151 void deinit_program(void)
3152 {
3153 #ifdef DOS
3154         __dpmi_regs regs;
3155 #endif
3156
3157         dj_stop();
3158         dj_free_mod(MOD_MENU);
3159         dj_free_mod(MOD_GAME);
3160         dj_free_sfx(SFX_DEATH);
3161         dj_free_sfx(SFX_SPRING);
3162         dj_free_sfx(SFX_SPLASH);
3163         dj_deinit();
3164
3165         if (background_pic != 0)
3166                 free(background_pic);
3167         if (mask_pic != 0)
3168                 free(mask_pic);
3169
3170         remove_keyb_handler();
3171
3172 #ifdef DOS
3173         regs.x.ax = 0x3;
3174         __dpmi_int(0x10, &regs);
3175 #endif
3176
3177         if (main_info.error_str[0] != 0) {
3178                 printf(main_info.error_str);
3179 #ifdef _MSC_VER
3180                 MessageBox(0, main_info.error_str, "Jump'n'Bump", 0);
3181 #endif
3182                 exit(1);
3183         } else
3184                 exit(0);
3185
3186 }
3187
3188
3189 unsigned short rnd(unsigned short max)
3190 {
3191 #if (RAND_MAX < 0x7fff)
3192 #error "rand returns too small values"
3193 #elif (RAND_MAX == 0x7fff)
3194         return (unsigned short)((rand()*2) % (int)max);
3195 #else
3196         return (unsigned short)(rand() % (int)max);
3197 #endif
3198 }
3199
3200
3201 int read_level(void)
3202 {
3203         unsigned char *handle;
3204         int c1, c2;
3205         int chr;
3206
3207         if ((handle = dat_open("levelmap.txt")) == 0) {
3208                 strcpy(main_info.error_str, "Error loading 'levelmap.txt', aborting...\n");
3209                 return 1;
3210         }
3211
3212         for (c1 = 0; c1 < 16; c1++) {
3213                 for (c2 = 0; c2 < 22; c2++) {
3214                         while (1) {
3215                                 chr = (int) *(handle++);
3216                                 if (chr >= '0' && chr <= '4')
3217                                         break;
3218                         }
3219                         if (flip)
3220                                 ban_map[c1][21-c2] = chr - '0';
3221                         else
3222                                 ban_map[c1][c2] = chr - '0';
3223                 }
3224         }
3225
3226         for (c2 = 0; c2 < 22; c2++)
3227                 ban_map[16][c2] = BAN_SOLID;
3228
3229         return 0;
3230
3231 }
3232
3233
3234 unsigned char *dat_open(char *file_name)
3235 {
3236         int num;
3237         int c1;
3238         char name[21];
3239         int ofs;
3240         unsigned char *ptr;
3241
3242         if (datafile_buffer == NULL)
3243                 return 0;
3244
3245         memset(name, 0, sizeof(name));
3246
3247         num = ( (datafile_buffer[0] <<  0) +
3248                 (datafile_buffer[1] <<  8) +
3249                 (datafile_buffer[2] << 16) +
3250                 (datafile_buffer[3] << 24) );
3251
3252         ptr = datafile_buffer + 4;
3253
3254         for (c1 = 0; c1 < num; c1++) {
3255
3256                 memcpy(name, ptr, 12);
3257                 ptr += 12;
3258
3259                 if (strnicmp(name, file_name, strlen(file_name)) == 0) {
3260                         ofs = ( (ptr[0] <<  0) +
3261                                 (ptr[1] <<  8) +
3262                                 (ptr[2] << 16) +
3263                                 (ptr[3] << 24) );
3264
3265                         return (datafile_buffer + ofs);
3266                 }
3267                 ptr += 8;
3268         }
3269
3270         return 0;
3271 }
3272
3273
3274 int dat_filelen(char *file_name)
3275 {
3276         unsigned char *ptr;
3277         int num;
3278         int c1;
3279         char name[21];
3280         int len;
3281
3282         memset(name, 0, sizeof(name));
3283
3284         num = ( (datafile_buffer[0] <<  0) +
3285                 (datafile_buffer[1] <<  8) +
3286                 (datafile_buffer[2] << 16) +
3287                 (datafile_buffer[3] << 24) );
3288
3289         ptr = datafile_buffer + 4;
3290
3291         for (c1 = 0; c1 < num; c1++) {
3292
3293                 memcpy(name, ptr, 12);
3294                 ptr += 12;
3295
3296                 if (strnicmp(name, file_name, strlen(file_name)) == 0) {
3297
3298                         ptr += 4;
3299                         len = ( (ptr[0] <<  0) +
3300                                 (ptr[1] <<  8) +
3301                                 (ptr[2] << 16) +
3302                                 (ptr[3] << 24) );
3303
3304                         return len;
3305                 }
3306                 ptr += 8;
3307         }
3308
3309         return 0;
3310 }
3311
3312
3313 void write_calib_data(void)
3314 {
3315         FILE *handle;
3316         int c1;
3317         int len, num;
3318         char *mem;
3319         int ofs;
3320
3321         if ((handle = fopen(datfile_name, "rb")) == NULL)
3322                 return;
3323         len = filelength(fileno(handle));
3324         if ((mem = malloc(len)) == NULL)
3325                 return;
3326         fread(mem, 1, len, handle);
3327         fclose(handle);
3328
3329         ofs = 4;
3330         num = *(int *) (&mem[0]);
3331         for (c1 = 0; c1 < num; c1++) {
3332                 if (strnicmp(&mem[ofs], "calib.dat", strlen("calib.dat")) == 0) {
3333                         ofs = *(int *) (&mem[ofs + 12]);
3334                         break;
3335                 }
3336                 ofs += 20;
3337         }
3338
3339         mem[ofs] = joy.calib_data.x1 & 0xff;
3340         mem[ofs + 1] = (joy.calib_data.x1 >> 8) & 0xff;
3341         mem[ofs + 2] = (joy.calib_data.x1 >> 16) & 0xff;
3342         mem[ofs + 3] = (joy.calib_data.x1 >> 24) & 0xff;
3343         mem[ofs + 4] = joy.calib_data.x2 & 0xff;
3344         mem[ofs + 5] = (joy.calib_data.x2 >> 8) & 0xff;
3345         mem[ofs + 6] = (joy.calib_data.x2 >> 16) & 0xff;
3346         mem[ofs + 7] = (joy.calib_data.x2 >> 24) & 0xff;
3347         mem[ofs + 8] = joy.calib_data.x3 & 0xff;
3348         mem[ofs + 9] = (joy.calib_data.x3 >> 8) & 0xff;
3349         mem[ofs + 10] = (joy.calib_data.x3 >> 16) & 0xff;
3350         mem[ofs + 11] = (joy.calib_data.x3 >> 24) & 0xff;
3351         mem[ofs + 12] = joy.calib_data.y1 & 0xff;
3352         mem[ofs + 13] = (joy.calib_data.y1 >> 8) & 0xff;
3353         mem[ofs + 14] = (joy.calib_data.y1 >> 16) & 0xff;
3354         mem[ofs + 15] = (joy.calib_data.y1 >> 24) & 0xff;
3355         mem[ofs + 16] = joy.calib_data.y2 & 0xff;
3356         mem[ofs + 17] = (joy.calib_data.y2 >> 8) & 0xff;
3357         mem[ofs + 18] = (joy.calib_data.y2 >> 16) & 0xff;
3358         mem[ofs + 19] = (joy.calib_data.y2 >> 24) & 0xff;
3359         mem[ofs + 20] = joy.calib_data.y3 & 0xff;
3360         mem[ofs + 21] = (joy.calib_data.y3 >> 8) & 0xff;
3361         mem[ofs + 22] = (joy.calib_data.y3 >> 16) & 0xff;
3362         mem[ofs + 23] = (joy.calib_data.y3 >> 24) & 0xff;
3363
3364         if ((handle = fopen(datfile_name, "wb")) == NULL)
3365                 return;
3366         fwrite(mem, 1, len, handle);
3367         fclose(handle);
3368
3369 }