3 * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/
5 * Copyright (C) 2001 Chuck Mason <cemason@users.sourceforge.net>
7 * Copyright (C) 2002 Florian Schulze <crow@icculus.org>
9 * This file is part of Jump'n'Bump.
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.
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.
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
37 #define M_PI 3.14159265358979323846
40 gob_t rabbit_gobs = { 0 };
41 gob_t font_gobs = { 0 };
42 gob_t object_gobs = { 0 };
43 gob_t number_gobs = { 0 };
45 main_info_t main_info;
46 player_t player[JNB_MAX_PLAYERS];
47 player_anim_t player_anims[7];
48 object_t objects[NUM_OBJECTS];
52 char datfile_name[2048];
58 unsigned int ban_map[17][22] = {
59 {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
60 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0},
61 {1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
62 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1},
63 {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
64 {1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
65 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1},
66 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
67 {1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
68 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 1},
69 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1},
70 {1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1},
71 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
72 {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
73 {2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0, 1, 3, 3, 3, 1, 1, 1},
74 {2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
75 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
201 int flies_enabled = 1;
206 int old_draw_x, old_draw_y;
218 } pobs[NUM_LEFTOVERS];
222 int pogostick, bunnies_in_space, jetpack, lord_of_the_flies, blood_is_thicker_than_water;
226 int filelength(int handle)
230 if (fstat(handle, &buf) == -1) {
231 perror("filelength");
240 /* networking shite. */
242 int client_player_num = -1;
247 TCPsocket sock = NULL;
248 SDLNet_SocketSet socketset = NULL;
254 SDLNet_SocketSet socketset;
257 NetInfo net_info[JNB_MAX_PLAYERS];
269 #define NETPKTBUFSIZE (4 + 4 + 4 + 4 + 4)
271 #define NETCMD_NACK (0xF00DF00D + 0)
272 #define NETCMD_ACK (0xF00DF00D + 1)
273 #define NETCMD_HELLO (0xF00DF00D + 2)
274 #define NETCMD_GREENLIGHT (0xF00DF00D + 3)
275 #define NETCMD_MOVE (0xF00DF00D + 4)
276 #define NETCMD_BYE (0xF00DF00D + 5)
277 #define NETCMD_POSITION (0xF00DF00D + 6)
278 #define NETCMD_ALIVE (0xF00DF00D + 7)
279 #define NETCMD_KILL (0xF00DF00D + 8)
283 void bufToPacket(const char *buf, NetPacket *pkt)
285 SDLNet_Write32(*((Uint32*) (buf + 0)), &pkt->cmd);
286 SDLNet_Write32(*((Uint32*) (buf + 4)), &pkt->arg);
287 SDLNet_Write32(*((Uint32*) (buf + 8)), &pkt->arg2);
288 SDLNet_Write32(*((Uint32*) (buf + 12)), &pkt->arg3);
289 SDLNet_Write32(*((Uint32*) (buf + 16)), &pkt->arg4);
291 pkt->cmd = ntohl(*((unsigned long *) (buf + 0)));
292 pkt->arg = (long) ntohl(*((unsigned long *) (buf + 4)));
293 pkt->arg2 = (long) ntohl(*((unsigned long *) (buf + 8)));
294 pkt->arg3 = (long) ntohl(*((unsigned long *) (buf + 12)));
295 pkt->arg4 = (long) ntohl(*((unsigned long *) (buf + 16)));
300 void packetToBuf(const NetPacket *pkt, char *buf)
302 *((Uint32*) (buf + 0)) = SDLNet_Read32(&pkt->cmd);
303 *((Uint32*) (buf + 4)) = SDLNet_Read32(&pkt->arg);
304 *((Uint32*) (buf + 8)) = SDLNet_Read32(&pkt->arg2);
305 *((Uint32*) (buf + 12)) = SDLNet_Read32(&pkt->arg3);
306 *((Uint32*) (buf + 16)) = SDLNet_Read32(&pkt->arg4);
308 *((unsigned long *) (buf + 0)) = htonl(pkt->cmd);
309 *((unsigned long *) (buf + 4)) = htonl((unsigned long) pkt->arg);
310 *((unsigned long *) (buf + 8)) = htonl((unsigned long) pkt->arg2);
311 *((unsigned long *) (buf + 12)) = htonl((unsigned long) pkt->arg3);
312 *((unsigned long *) (buf + 16)) = htonl((unsigned long) pkt->arg4);
317 void sendPacketToSock(TCPsocket s, NetPacket *pkt)
319 int bytes_left = NETPKTBUFSIZE;
321 char buf[NETPKTBUFSIZE];
324 packetToBuf(pkt, buf);
325 while (bytes_left > 0) {
326 bw = SDLNet_TCP_Send(s, ptr, bytes_left);
328 fprintf(stderr, "SERVER: SDLNet_TCP_Send(): %s\n", SDLNet_GetError());
331 } else if (bw == 0) {
341 void sendPacket(int playerid, NetPacket *pkt)
343 if ( (playerid < JNB_MAX_PLAYERS) && (playerid >= 0)) {
344 if ((player[playerid].enabled) && (playerid != client_player_num)) {
345 sendPacketToSock(net_info[playerid].sock, pkt);
351 void sendPacketToAll(NetPacket *pkt)
355 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
360 /** read a packet from the given TCPsocket
361 Returns -1 if some error occured, 0 if there was no data available and 1 if a
362 packet was successfully read.
363 Note: the socket has to be in the supplied socketset.
364 TODO: this function will bomb if a packet arrives in pieces, there is no
365 inherent guarantee that the next call will be made on the same socket. */
366 int grabPacket(TCPsocket s, SDLNet_SocketSet ss, NetPacket *pkt)
368 static char buf[NETPKTBUFSIZE];
369 static int buf_count = 0;
372 if (SDLNet_CheckSockets(ss, 0) <= 0)
375 if(!SDLNet_SocketReady(s))
378 rc = SDLNet_TCP_Recv(s, &buf[buf_count], NETPKTBUFSIZE - buf_count);
380 /* closed connection? */
382 } else if (rc != NETPKTBUFSIZE) {
383 /* we got a partial packet. Store what we got in the static buffer and
384 return so that the next call can read the rest. Hopefully. */
389 bufToPacket(buf, pkt);
395 int serverRecvPacket(NetPacket *pkt)
402 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
403 TCPsocket s = net_info[i].sock;
405 if ((i == client_player_num) || (!player[i].enabled))
408 rc = grabPacket(s, net_info[i].socketset, pkt);
412 player[i].enabled = 0;
414 pkt.cmd = NETCMD_BYE;
419 sendPacketToAll(&pkt);
421 return(i); /* it's all good. */
425 return(-1); /* no packets available currently. */
429 void wait_for_greenlight(void)
434 printf("CLIENT: Waiting for greenlight...\n");
438 while ((rc = grabPacket(sock, socketset, &pkt)) == 0) {
439 SDL_Delay(100); /* nap and then try again. */
443 printf("CLIENT: Lost connection.\n");
444 SDLNet_TCP_Close(sock);
447 } while (pkt.cmd != NETCMD_GREENLIGHT);
449 printf("CLIENT: Got greenlight.\n");
451 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
452 if (pkt.arg & (1 << i)) {
453 printf("CLIENT: There is a player #%d.\n", i);
454 player[i].enabled = 1;
460 static int buggered_off = 0;
463 void tellServerGoodbye(void)
469 pkt.cmd = NETCMD_BYE;
470 pkt.arg = client_player_num;
474 sendPacketToSock(sock, &pkt);
480 void processMovePacket(NetPacket *pkt)
482 int playerid = pkt->arg;
483 int movetype = ((pkt->arg2 >> 16) & 0xFF);
484 int newval = ((pkt->arg2 >> 0) & 0xFF);
486 if (movetype == MOVEMENT_LEFT) {
487 player[playerid].action_left = newval;
488 } else if (movetype == MOVEMENT_RIGHT) {
489 player[playerid].action_right = newval;
490 } else if (movetype == MOVEMENT_UP) {
491 player[playerid].action_up = newval;
493 printf("bogus MOVE packet!\n");
496 player[playerid].x = pkt->arg3;
497 player[playerid].y = pkt->arg4;
501 void tellServerPlayerMoved(int playerid, int movement_type, int newval)
505 pkt.cmd = NETCMD_MOVE;
507 pkt.arg2 = ( ((movement_type & 0xFF) << 16) | ((newval & 0xFF) << 0) );
508 pkt.arg3 = player[playerid].x;
509 pkt.arg4 = player[playerid].y;
512 processMovePacket(&pkt);
515 sendPacketToAll(&pkt);
517 sendPacketToSock(sock, &pkt);
524 void tellServerNewPosition(void)
527 pkt.cmd = NETCMD_POSITION;
528 pkt.arg = client_player_num;
529 pkt.arg2 = player[client_player_num].x;
530 pkt.arg3 = player[client_player_num].y;
533 sendPacketToAll(&pkt);
535 sendPacketToSock(sock, &pkt);
541 void processKillPacket(NetPacket *pkt)
550 player[c1].y_add = -player[c1].y_add;
551 if (player[c1].y_add > -262144L)
552 player[c1].y_add = -262144L;
553 player[c1].jump_abort = 1;
554 player[c2].dead_flag = 1;
555 if (player[c2].anim != 6) {
557 player[c2].frame = 0;
558 player[c2].frame_tick = 0;
559 player[c2].image = player_anims[player[c2].anim].frame[player[c2].frame].image + player[c2].direction * 9;
560 if (main_info.no_gore == 0) {
561 for (c4 = 0; c4 < 6; c4++)
562 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);
563 for (c4 = 0; c4 < 6; c4++)
564 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 76);
565 for (c4 = 0; c4 < 6; c4++)
566 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 77);
567 for (c4 = 0; c4 < 8; c4++)
568 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 78);
569 for (c4 = 0; c4 < 10; c4++)
570 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 79);
572 dj_play_sfx(SFX_DEATH, (unsigned short)(SFX_DEATH_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
574 player[c1].bumped[c2]++;
575 s1 = player[c1].bumps % 100;
576 add_leftovers(0, 360, 34 + c1 * 64, s1 / 10, &number_gobs);
577 add_leftovers(1, 360, 34 + c1 * 64, s1 / 10, &number_gobs);
578 add_leftovers(0, 376, 34 + c1 * 64, s1 - (s1 / 10) * 10, &number_gobs);
579 add_leftovers(1, 376, 34 + c1 * 64, s1 - (s1 / 10) * 10, &number_gobs);
585 void processPositionPacket(NetPacket *pkt)
587 int playerid = pkt->arg;
589 player[playerid].x = pkt->arg2;
590 player[playerid].y = pkt->arg3;
594 void processAlivePacket(NetPacket *pkt)
596 int playerid = pkt->arg;
598 player[playerid].dead_flag = 0;
599 player[playerid].x = pkt->arg2;
600 player[playerid].y = pkt->arg3;
604 void serverTellEveryoneGoodbye(void)
610 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
611 if (player[i].enabled) {
614 pkt.cmd = NETCMD_BYE;
619 sendPacketToAll(&pkt);
626 int server_said_bye = 0;
629 int update_players_from_server(void)
636 while ((rc = grabPacket(sock, socketset, &pkt)) != 0) {
638 printf("CLIENT: Lost connection.\n");
639 pkt.cmd = NETCMD_BYE;
640 pkt.arg = client_player_num;
643 if (pkt.cmd == NETCMD_BYE) {
644 if (pkt.arg == client_player_num) {
645 SDLNet_FreeSocketSet(socketset);
646 SDLNet_TCP_Close(sock);
651 player[pkt.arg].enabled = 0;
653 } else if (pkt.cmd == NETCMD_MOVE) {
654 processMovePacket(&pkt);
655 } else if (pkt.cmd == NETCMD_ALIVE) {
656 processAlivePacket(&pkt);
657 } else if (pkt.cmd == NETCMD_POSITION) {
658 processPositionPacket(&pkt);
659 } else if (pkt.cmd == NETCMD_KILL) {
660 processKillPacket(&pkt);
662 printf("CLIENT: Got an unknown packet: 0x%lX.\n", pkt.cmd);
670 void serverSendAlive(int playerid)
675 pkt.cmd = NETCMD_ALIVE;
677 pkt.arg2 = player[playerid].x;
678 pkt.arg3 = player[playerid].y;
679 sendPacketToAll(&pkt);
684 void serverSendKillPacket(int killer, int victim)
689 pkt.cmd = NETCMD_KILL;
692 pkt.arg3 = player[victim].x;
693 pkt.arg4 = player[victim].y;
694 processKillPacket(&pkt);
697 sendPacketToAll(&pkt);
703 void update_players_from_clients(void)
711 while ((playerid = serverRecvPacket(&pkt)) >= 0) {
712 if (pkt.cmd == NETCMD_BYE) {
713 pkt.arg = playerid; /* just in case. */
714 sendPacketToAll(&pkt);
715 player[playerid].enabled = 0;
716 SDLNet_FreeSocketSet(net_info[playerid].socketset);
717 SDLNet_TCP_Close(net_info[playerid].sock);
718 } else if (pkt.cmd == NETCMD_POSITION) {
719 pkt.arg = playerid; /* just in case. */
720 processPositionPacket(&pkt);
721 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
726 } else if (pkt.cmd == NETCMD_MOVE) {
727 pkt.arg = playerid; /* just in case. */
729 pkt.arg3 = player[playerid].x;
730 pkt.arg4 = player[playerid].y;
732 processMovePacket(&pkt);
733 sendPacketToAll(&pkt);
735 printf("SERVER: Got unknown packet (0x%lX).\n", pkt.cmd);
741 void init_server(const char *netarg)
746 int wait_for_clients = ((netarg == NULL) ? 0 : atoi(netarg));
749 /** assign player number zero as default for the server */
750 if(-1 == client_player_num)
751 client_player_num = 0;
753 if ((wait_for_clients >= JNB_MAX_PLAYERS) || (wait_for_clients < 0)) {
754 printf("SERVER: Waiting for bogus client count (%d).\n", wait_for_clients);
758 if (SDLNet_Init() < 0) {
763 SDLNet_ResolveHost(&addr, NULL, JNB_INETPORT);
764 ipstr = SDLNet_ResolveIP(&addr);
765 SDLNet_ResolveHost(&addr, ipstr, JNB_INETPORT);
766 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);
767 net_info[client_player_num].addr = addr;
769 addr.host = INADDR_ANY;
770 sock = SDLNet_TCP_Open(&addr);
772 fprintf(stderr, "SERVER: SDLNet_TCP_Open(): %s\n", SDLNet_GetError());
776 player[client_player_num].enabled = 1;
778 printf("SERVER: waiting for (%d) clients...\n", wait_for_clients);
780 socketset = SDLNet_AllocSocketSet(JNB_MAX_PLAYERS + 1);
781 SDLNet_TCP_AddSocket(socketset, sock);
783 while (wait_for_clients > 0)
785 char buf[NETPKTBUFSIZE];
791 /* Wait for events */
792 SDLNet_CheckSockets(socketset, ~0);
793 if ( SDLNet_SocketReady(sock) ) {
794 s = SDLNet_TCP_Accept(sock);
798 fprintf(stderr, "SERVER: SDLNet_TCP_Accept(): %s", SDLNet_GetError());
799 SDLNet_TCP_Close(sock);
805 br = SDLNet_TCP_Recv(s, buf, NETPKTBUFSIZE);
807 fprintf(stderr, "SERVER: SDLNet_TCP_Recv(): %s\n", SDLNet_GetError());
809 SDLNet_TCP_Close(sock);
813 from = SDLNet_TCP_GetPeerAddress(s);
814 ipstr = SDLNet_ResolveIP(from);
815 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);
817 if (br != NETPKTBUFSIZE) {
818 printf("SERVER: Bogus packet.\n");
822 bufToPacket(buf, &pkt);
823 if (pkt.cmd != NETCMD_HELLO) {
824 printf("SERVER: Bogus packet.\n");
828 printf("SERVER: Client claims to be player #%ld.\n", pkt.arg);
832 for(i=0; i!=JNB_MAX_PLAYERS; ++i) {
833 if(!player[i].enabled) {
834 printf("SERVER: assigning %d as player number\n", i);
841 if ((pkt.arg>=JNB_MAX_PLAYERS)||(pkt.arg<0)) {
842 printf("SERVER: (that's an invalid player number.)\n");
843 } else if (player[pkt.arg].enabled) {
844 printf("SERVER: (that player number is already taken.)\n");
850 printf("SERVER: Forbidding connection.\n");
851 pkt.cmd = NETCMD_NACK;
852 sendPacketToSock(s, &pkt);
855 player[pkt.arg].enabled = 1;
856 net_info[pkt.arg].sock = s;
857 net_info[pkt.arg].addr = *from;
858 net_info[pkt.arg].socketset = SDLNet_AllocSocketSet(1);
859 SDLNet_TCP_AddSocket(net_info[pkt.arg].socketset, net_info[pkt.arg].sock);
861 printf("SERVER: Granting connection. (%d) to go.\n", wait_for_clients);
862 pkt.cmd = NETCMD_ACK;
863 sendPacket(pkt.arg, &pkt);
867 SDLNet_TCP_Close(sock); /* done with the listen socket. */
868 SDLNet_FreeSocketSet(socketset);
872 printf("SERVER: Got all our connections. Greenlighting clients...\n");
874 pkt.cmd = NETCMD_GREENLIGHT;
876 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
877 if (player[i].enabled) {
881 sendPacketToAll(&pkt);
885 void connect_to_server(char *netarg)
888 char buf[NETPKTBUFSIZE];
894 if (netarg == NULL) {
895 printf("CLIENT: Need to specify host to connect to.\n");
899 if (SDLNet_Init() < 0) {
904 SDLNet_ResolveHost(&addr, NULL, JNB_INETPORT);
905 ipstr = SDLNet_ResolveIP(&addr);
906 SDLNet_ResolveHost(&addr, ipstr, JNB_INETPORT);
907 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);
909 if (SDLNet_ResolveHost(&hent, netarg, JNB_INETPORT) < 0) {
910 fprintf(stderr, "CLIENT: couldn't find host: %s\n", SDLNet_GetError());
914 sock = SDLNet_TCP_Open(&hent);
916 fprintf(stderr, "CLIENT: SDLNet_TCP_Open(): %s\n", SDLNet_GetError());
920 socketset = SDLNet_AllocSocketSet(1);
921 SDLNet_TCP_AddSocket(socketset, sock);
923 printf("CLIENT: connected to %s...\n", SDLNet_ResolveIP(&hent));
925 printf("CLIENT: Sending HELLO packet...\n");
926 pkt.cmd = NETCMD_HELLO;
927 pkt.arg = client_player_num;
928 sendPacketToSock(sock, &pkt);
930 printf("CLIENT: Waiting for ACK from server...\n");
932 br = SDLNet_TCP_Recv(sock, buf, NETPKTBUFSIZE);
934 fprintf(stderr, "CLIENT: recv(): %s\n", SDLNet_GetError());
935 SDLNet_FreeSocketSet(socketset);
936 SDLNet_TCP_Close(sock);
940 if (br != NETPKTBUFSIZE) {
941 printf("CLIENT: Bogus packet size (%d of %d). FIXME.\n", br, NETPKTBUFSIZE);
942 SDLNet_FreeSocketSet(socketset);
943 SDLNet_TCP_Close(sock);
947 bufToPacket(buf, &pkt);
949 if (pkt.cmd == NETCMD_NACK) {
950 printf("CLIENT: Server forbid us from playing.\n");
951 SDLNet_FreeSocketSet(socketset);
952 SDLNet_TCP_Close(sock);
956 if (pkt.cmd != NETCMD_ACK) {
957 printf("CLIENT: Unexpected packet (cmd=0x%lX).\n", pkt.cmd);
958 SDLNet_FreeSocketSet(socketset);
959 SDLNet_TCP_Close(sock);
963 client_player_num = pkt.arg;
964 player[client_player_num].enabled = 1;
965 net_info[client_player_num].addr = addr;
966 printf("CLIENT: Server accepted our connection.\n");
968 wait_for_greenlight();
973 static void flip_pixels(unsigned char *pixels)
979 for (y = 0; y < JNB_HEIGHT; y++) {
980 for (x = 0; x < (352/2); x++) {
981 temp = pixels[y*JNB_WIDTH+x];
982 pixels[y*JNB_WIDTH+x] = pixels[y*JNB_WIDTH+(352-x)-1];
983 pixels[y*JNB_WIDTH+(352-x)-1] = temp;
989 int main(int argc, char *argv[])
991 unsigned char *handle;
992 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
995 int closest_player = 0, dist, cur_dist = 0;
996 int end_loop_flag = 0, fade_flag = 0;
997 int mod_vol, sfx_vol, mod_fade_direction;
1003 if (init_program(argc, argv, pal) != 0)
1006 if (main_info.fireworks == 1) {
1017 if (key_pressed(1) == 1) {
1020 if (init_level(0, pal) != 0) {
1025 memset(cur_pal, 0, 768);
1026 setpalette(0, 256, cur_pal);
1028 recalculate_gob(&rabbit_gobs, pal);
1029 recalculate_gob(&object_gobs, pal);
1030 recalculate_gob(&number_gobs, pal);
1033 register_background(background_pic, pal);
1036 if (flies_enabled) {
1040 for (c1 = 0; c1 < NUM_FLIES; c1++) {
1042 flies[c1].x = s1 + rnd(101) - 50;
1043 flies[c1].y = s2 + rnd(101) - 50;
1044 if (ban_map[flies[c1].y >> 4][flies[c1].x >> 4] == BAN_VOID)
1047 flies[c1].back_defined[0] = 0;
1048 flies[c1].back_defined[1] = 0;
1052 mod_vol = sfx_vol = 10;
1053 mod_fade_direction = 1;
1054 dj_ready_mod(MOD_GAME);
1055 dj_set_mod_volume((char)mod_vol);
1056 dj_set_sfx_volume((char)mod_vol);
1060 dj_play_sfx(SFX_FLY, SFX_FLY_FREQ, 0, 0, 0, 4);
1064 lord_of_the_flies = bunnies_in_space = jetpack = pogostick = blood_is_thicker_than_water = 0;
1066 main_info.page_info[0].num_pobs = 0;
1067 main_info.page_info[1].num_pobs = 0;
1068 main_info.view_page = 0;
1069 main_info.draw_page = 1;
1073 while (update_count) {
1075 if (key_pressed(1) == 1) {
1079 serverTellEveryoneGoodbye();
1081 tellServerGoodbye();
1086 memset(pal, 0, 768);
1087 mod_fade_direction = 0;
1090 if (strncmp(last_keys, "kcitsogop", strlen("kcitsogop")) == 0) {
1094 if (strncmp(last_keys, "ecapsniseinnub", strlen("ecapsniseinnub")) == 0) {
1095 bunnies_in_space ^= 1;
1098 if (strncmp(last_keys, "kcaptej", strlen("kcaptej")) == 0) {
1102 if (strncmp(last_keys, "seilfehtfodrol", strlen("seilfehtfodrol")) == 0) {
1103 lord_of_the_flies ^= 1;
1106 if (strncmp(last_keys, "retawnahtrekcihtsidoolb", strlen("retawnahtrekcihtsidoolb")) == 0) {
1107 blood_is_thicker_than_water ^= 1;
1108 if (blood_is_thicker_than_water == 1) {
1159 register_background(background_pic, pal);
1160 recalculate_gob(&object_gobs, pal);
1167 update_players_from_clients();
1169 if (!update_players_from_server()) {
1170 break; /* got a BYE packet */
1180 for (c3 = 0; c3 < 6; c3++) {
1184 } else if (c3 == 1) {
1187 } else if (c3 == 2) {
1190 } else if (c3 == 3) {
1193 } else if (c3 == 4) {
1196 } else if (c3 == 5) {
1200 if (player[c1].enabled == 1 && player[c2].enabled == 1) {
1201 if (labs(player[c1].x - player[c2].x) < (12L << 16) && labs(player[c1].y - player[c2].y) < (12L << 16)) {
1202 if ((labs(player[c1].y - player[c2].y) >> 16) > 5) {
1203 if (player[c1].y < player[c2].y) {
1204 if (player[c1].y_add >= 0) {
1206 serverSendKillPacket(c1, c2);
1208 if (player[c2].y_add < 0)
1209 player[c2].y_add = 0;
1212 if (player[c2].y_add >= 0) {
1214 serverSendKillPacket(c2, c1);
1216 if (player[c1].y_add < 0)
1217 player[c1].y_add = 0;
1221 if (player[c1].x < player[c2].x) {
1222 if (player[c1].x_add > 0)
1223 player[c1].x = player[c2].x - (12L << 16);
1224 else if (player[c2].x_add < 0)
1225 player[c2].x = player[c1].x + (12L << 16);
1227 player[c1].x -= player[c1].x_add;
1228 player[c2].x -= player[c2].x_add;
1230 l1 = player[c2].x_add;
1231 player[c2].x_add = player[c1].x_add;
1232 player[c1].x_add = l1;
1233 if (player[c1].x_add > 0)
1234 player[c1].x_add = -player[c1].x_add;
1235 if (player[c2].x_add < 0)
1236 player[c2].x_add = -player[c2].x_add;
1238 if (player[c1].x_add > 0)
1239 player[c2].x = player[c1].x - (12L << 16);
1240 else if (player[c2].x_add < 0)
1241 player[c1].x = player[c2].x + (12L << 16);
1243 player[c1].x -= player[c1].x_add;
1244 player[c2].x -= player[c2].x_add;
1246 l1 = player[c2].x_add;
1247 player[c2].x_add = player[c1].x_add;
1248 player[c1].x_add = l1;
1249 if (player[c1].x_add < 0)
1250 player[c1].x_add = -player[c1].x_add;
1251 if (player[c2].x_add > 0)
1252 player[c2].x_add = -player[c2].x_add;
1261 main_info.page_info[main_info.draw_page].num_pobs = 0;
1262 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1263 if (player[c1].enabled == 1)
1264 main_info.page_info[main_info.draw_page].num_pobs++;
1271 if (flies_enabled) {
1272 /* get center of fly swarm */
1274 for (c1 = 0; c1 < NUM_FLIES; c1++) {
1281 if (update_count == 1) {
1282 /* get closest player to fly swarm */
1284 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1285 if (player[c1].enabled == 1) {
1286 cur_dist = (int)sqrt((s1 - ((player[c1].x >> 16) + 8)) * (s1 - ((player[c1].x >> 16) + 8)) + (s2 - ((player[c1].y >> 16) + 8)) * (s2 - ((player[c1].y >> 16) + 8)));
1287 if (cur_dist < dist) {
1288 closest_player = c1;
1293 /* update fly swarm sound */
1297 dj_set_sfx_channel_volume(4, (char)(s3));
1300 for (c1 = 0; c1 < NUM_FLIES; c1++) {
1301 /* get closest player to fly */
1303 for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++) {
1304 if (player[c2].enabled == 1) {
1305 cur_dist = (int)sqrt((flies[c1].x - ((player[c2].x >> 16) + 8)) * (flies[c1].x - ((player[c2].x >> 16) + 8)) + (flies[c1].y - ((player[c2].y >> 16) + 8)) * (flies[c1].y - ((player[c2].y >> 16) + 8)));
1306 if (cur_dist < dist) {
1307 closest_player = c2;
1312 flies[c1].old_x = flies[c1].x;
1313 flies[c1].old_y = flies[c1].y;
1315 if ((s1 - flies[c1].x) > 30)
1317 else if ((s1 - flies[c1].x) < -30)
1320 if (((player[closest_player].x >> 16) + 8) > flies[c1].x) {
1321 if (lord_of_the_flies == 0)
1326 if (lord_of_the_flies == 0)
1332 s4 = rnd(3) - 1 + s3;
1333 if ((flies[c1].x + s4) < 16)
1335 if ((flies[c1].x + s4) > 351)
1337 if (ban_map[flies[c1].y >> 4][(flies[c1].x + s4) >> 4] != BAN_VOID)
1341 if ((s2 - flies[c1].y) > 30)
1343 else if ((s2 - flies[c1].y) < -30)
1346 if (((player[closest_player].y >> 16) + 8) > flies[c1].y) {
1347 if (lord_of_the_flies == 0)
1352 if (lord_of_the_flies == 0)
1358 s4 = rnd(3) - 1 + s3;
1359 if ((flies[c1].y + s4) < 0)
1361 if ((flies[c1].y + s4) > 239)
1363 if (ban_map[(flies[c1].y + s4) >> 4][flies[c1].x >> 4] != BAN_VOID)
1372 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1373 if (player[c1].enabled == 1) {
1374 main_info.page_info[main_info.draw_page].pobs[s1].x = player[c1].x >> 16;
1375 main_info.page_info[main_info.draw_page].pobs[s1].y = player[c1].y >> 16;
1376 main_info.page_info[main_info.draw_page].pobs[s1].image = player[c1].image + c1 * 18;
1377 main_info.page_info[main_info.draw_page].pobs[s1].pob_data = &rabbit_gobs;
1382 if (update_count == 1) {
1385 draw_pobs(main_info.draw_page);
1390 draw_flies(main_info.draw_page);
1395 if (mod_fade_direction == 1) {
1398 dj_set_mod_volume((char)mod_vol);
1403 dj_set_mod_volume((char)mod_vol);
1407 if (mod_fade_direction == 1) {
1410 dj_set_sfx_volume((char)sfx_vol);
1415 dj_set_sfx_volume((char)sfx_vol);
1420 for (c1 = 0; c1 < 768; c1++) {
1421 if (cur_pal[c1] < pal[c1]) {
1424 } else if (cur_pal[c1] > pal[c1]) {
1429 if (fade_flag == 0 && end_loop_flag == 1)
1432 if (update_count == 1) {
1433 main_info.draw_page ^= 1;
1434 main_info.view_page ^= 1;
1436 flippage(main_info.view_page);
1442 setpalette(0, 256, cur_pal);
1444 if (update_count == 1) {
1448 redraw_flies_background(main_info.draw_page);
1450 redraw_pob_backgrounds(main_info.draw_page);
1452 draw_leftovers(main_info.draw_page);
1462 if ( (player[client_player_num].dead_flag == 0) &&
1464 (player[client_player_num].action_left) ||
1465 (player[client_player_num].action_right) ||
1466 (player[client_player_num].action_up) ||
1467 (player[client_player_num].jump_ready == 0)
1470 tellServerNewPosition();
1475 update_count = intr_sysupdate();
1479 if ((server_said_bye) || ((fade_flag == 0) && (end_loop_flag == 1)))
1483 if ((fade_flag == 0) && (end_loop_flag == 1))
1490 serverTellEveryoneGoodbye();
1491 SDLNet_TCP_Close(sock);
1494 if (!server_said_bye) {
1495 tellServerGoodbye();
1498 SDLNet_TCP_Close(sock);
1504 main_info.view_page = 0;
1505 main_info.draw_page = 1;
1507 dj_stop_sfx_channel(4);
1511 memset(mask_pic, 0, JNB_WIDTH*JNB_HEIGHT);
1512 register_mask(mask_pic);
1514 register_background(NULL, NULL);
1518 put_text(main_info.view_page, 100, 50, "DOTT", 2);
1519 put_text(main_info.view_page, 160, 50, "JIFFY", 2);
1520 put_text(main_info.view_page, 220, 50, "FIZZ", 2);
1521 put_text(main_info.view_page, 280, 50, "MIJJI", 2);
1522 put_text(main_info.view_page, 40, 80, "DOTT", 2);
1523 put_text(main_info.view_page, 40, 110, "JIFFY", 2);
1524 put_text(main_info.view_page, 40, 140, "FIZZ", 2);
1525 put_text(main_info.view_page, 40, 170, "MIJJI", 2);
1527 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1528 for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++) {
1530 sprintf(str1, "%d", player[c1].bumped[c2]);
1531 put_text(main_info.view_page, 100 + c2 * 60, 80 + c1 * 30, str1, 2);
1533 put_text(main_info.view_page, 100 + c2 * 60, 80 + c1 * 30, "-", 2);
1535 sprintf(str1, "%d", player[c1].bumps);
1536 put_text(main_info.view_page, 350, 80 + c1 * 30, str1, 2);
1539 put_text(main_info.view_page, 200, 230, "Press ESC to continue", 2);
1543 flippage(main_info.view_page);
1545 if ((handle = dat_open("menu.pcx")) == 0) {
1546 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
1549 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
1550 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
1555 for (c1 = 0; c1 < 16; c1++) {
1556 pal[(240 + c1) * 3 + 0] = c1 << 2;
1557 pal[(240 + c1) * 3 + 1] = c1 << 2;
1558 pal[(240 + c1) * 3 + 2] = c1 << 2;
1561 memset(cur_pal, 0, 768);
1563 setpalette(0, 256, cur_pal);
1566 dj_ready_mod(MOD_SCORES);
1567 dj_set_mod_volume((char)mod_vol);
1571 while (key_pressed(1) == 0) {
1574 dj_set_mod_volume((char)mod_vol);
1575 for (c1 = 0; c1 < 768; c1++) {
1576 if (cur_pal[c1] < pal[c1])
1582 setpalette(0, 256, cur_pal);
1583 flippage(main_info.view_page);
1585 while (key_pressed(1) == 1) {
1590 memset(pal, 0, 768);
1592 while (mod_vol > 0) {
1594 dj_set_mod_volume((char)mod_vol);
1595 for (c1 = 0; c1 < 768; c1++) {
1596 if (cur_pal[c1] > pal[c1])
1601 setpalette(0, 256, cur_pal);
1602 flippage(main_info.view_page);
1605 fillpalette(0, 0, 0);
1611 break; /* don't go back to menu if in net game. */
1620 void steer_players(void)
1625 update_player_actions();
1627 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1629 if (player[c1].enabled == 1) {
1631 if (player[c1].dead_flag == 0) {
1633 if (player[c1].action_left && player[c1].action_right) {
1634 if (player[c1].direction == 0) {
1635 if (player[c1].action_right) {
1636 s1 = (player[c1].x >> 16);
1637 s2 = (player[c1].y >> 16);
1638 if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) {
1639 if (player[c1].x_add < 0)
1640 player[c1].x_add += 1024;
1642 player[c1].x_add += 768;
1643 } else if ((ban_map[(s2 + 16) >> 4][s1 >> 4] != BAN_SOLID && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_ICE) || (ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_ICE && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] != BAN_SOLID)) {
1644 if (player[c1].x_add > 0)
1645 player[c1].x_add += 1024;
1647 player[c1].x_add += 768;
1649 if (player[c1].x_add < 0) {
1650 player[c1].x_add += 16384;
1651 if (player[c1].x_add < 98304L && player[c1].in_water == 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1652 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);
1654 player[c1].x_add += 12288;
1656 if (player[c1].x_add > 98304L)
1657 player[c1].x_add = 98304L;
1658 player[c1].direction = 0;
1659 if (player[c1].anim == 0) {
1660 player[c1].anim = 1;
1661 player[c1].frame = 0;
1662 player[c1].frame_tick = 0;
1663 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1667 if (player[c1].action_left) {
1668 s1 = (player[c1].x >> 16);
1669 s2 = (player[c1].y >> 16);
1670 if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) {
1671 if (player[c1].x_add > 0)
1672 player[c1].x_add -= 1024;
1674 player[c1].x_add -= 768;
1675 } else if ((ban_map[(s2 + 16) >> 4][s1 >> 4] != BAN_SOLID && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_ICE) || (ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_ICE && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] != BAN_SOLID)) {
1676 if (player[c1].x_add > 0)
1677 player[c1].x_add -= 1024;
1679 player[c1].x_add -= 768;
1681 if (player[c1].x_add > 0) {
1682 player[c1].x_add -= 16384;
1683 if (player[c1].x_add > -98304L && player[c1].in_water == 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1684 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);
1686 player[c1].x_add -= 12288;
1688 if (player[c1].x_add < -98304L)
1689 player[c1].x_add = -98304L;
1690 player[c1].direction = 1;
1691 if (player[c1].anim == 0) {
1692 player[c1].anim = 1;
1693 player[c1].frame = 0;
1694 player[c1].frame_tick = 0;
1695 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1699 } else if (player[c1].action_left) {
1700 s1 = (player[c1].x >> 16);
1701 s2 = (player[c1].y >> 16);
1702 if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) {
1703 if (player[c1].x_add > 0)
1704 player[c1].x_add -= 1024;
1706 player[c1].x_add -= 768;
1707 } else if ((ban_map[(s2 + 16) >> 4][s1 >> 4] != BAN_SOLID && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_ICE) || (ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_ICE && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] != BAN_SOLID)) {
1708 if (player[c1].x_add > 0)
1709 player[c1].x_add -= 1024;
1711 player[c1].x_add -= 768;
1713 if (player[c1].x_add > 0) {
1714 player[c1].x_add -= 16384;
1715 if (player[c1].x_add > -98304L && player[c1].in_water == 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1716 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);
1718 player[c1].x_add -= 12288;
1720 if (player[c1].x_add < -98304L)
1721 player[c1].x_add = -98304L;
1722 player[c1].direction = 1;
1723 if (player[c1].anim == 0) {
1724 player[c1].anim = 1;
1725 player[c1].frame = 0;
1726 player[c1].frame_tick = 0;
1727 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1729 } else if (player[c1].action_right) {
1730 s1 = (player[c1].x >> 16);
1731 s2 = (player[c1].y >> 16);
1732 if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) {
1733 if (player[c1].x_add < 0)
1734 player[c1].x_add += 1024;
1736 player[c1].x_add += 768;
1737 } else if ((ban_map[(s2 + 16) >> 4][s1 >> 4] != BAN_SOLID && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_ICE) || (ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_ICE && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] != BAN_SOLID)) {
1738 if (player[c1].x_add > 0)
1739 player[c1].x_add += 1024;
1741 player[c1].x_add += 768;
1743 if (player[c1].x_add < 0) {
1744 player[c1].x_add += 16384;
1745 if (player[c1].x_add < 98304L && player[c1].in_water == 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1746 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);
1748 player[c1].x_add += 12288;
1750 if (player[c1].x_add > 98304L)
1751 player[c1].x_add = 98304L;
1752 player[c1].direction = 0;
1753 if (player[c1].anim == 0) {
1754 player[c1].anim = 1;
1755 player[c1].frame = 0;
1756 player[c1].frame_tick = 0;
1757 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1759 } else if ((!player[c1].action_left) && (!player[c1].action_right)) {
1760 s1 = (player[c1].x >> 16);
1761 s2 = (player[c1].y >> 16);
1762 if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID || ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SPRING || (((ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_SPRING) && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] != BAN_ICE) || (ban_map[(s2 + 16) >> 4][s1 >> 4] != BAN_ICE && (ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_SPRING)))) {
1763 if (player[c1].x_add < 0) {
1764 player[c1].x_add += 16384;
1765 if (player[c1].x_add > 0)
1766 player[c1].x_add = 0;
1768 player[c1].x_add -= 16384;
1769 if (player[c1].x_add < 0)
1770 player[c1].x_add = 0;
1772 if (player[c1].x_add != 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1773 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);
1775 if (player[c1].anim == 1) {
1776 player[c1].anim = 0;
1777 player[c1].frame = 0;
1778 player[c1].frame_tick = 0;
1779 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1783 if (pogostick == 1 || (player[c1].jump_ready == 1 && player[c1].action_up)) {
1784 s1 = (player[c1].x >> 16);
1785 s2 = (player[c1].y >> 16);
1788 if (ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_ICE || ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_ICE) {
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;
1797 dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1799 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1801 if ((ban_map[(s2 + 7) >> 4][s1 >> 4] == BAN_VOID || ban_map[(s2 + 7) >> 4][(s1 + 15) >> 4] == BAN_VOID) && (ban_map[(s2 + 8) >> 4][s1 >> 4] == BAN_WATER || ban_map[(s2 + 8) >> 4][(s1 + 15) >> 4] == BAN_WATER)) {
1802 player[c1].y_add = -196608L;
1803 player[c1].in_water = 0;
1804 player[c1].anim = 2;
1805 player[c1].frame = 0;
1806 player[c1].frame_tick = 0;
1807 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1808 player[c1].jump_ready = 0;
1809 player[c1].jump_abort = 1;
1811 dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1813 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1816 if (pogostick == 0 && (!player[c1].action_up)) {
1817 player[c1].jump_ready = 1;
1818 if (player[c1].in_water == 0 && player[c1].y_add < 0 && player[c1].jump_abort == 1) {
1819 if (bunnies_in_space == 0)
1820 player[c1].y_add += 32768;
1822 player[c1].y_add += 16384;
1823 if (player[c1].y_add > 0)
1824 player[c1].y_add = 0;
1829 if (player[c1].action_up) {
1830 player[c1].y_add -= 16384;
1831 if (player[c1].y_add < -400000L)
1832 player[c1].y_add = -400000L;
1833 if ((ban_map[(s2 + 7) >> 4][s1 >> 4] == BAN_VOID || ban_map[(s2 + 7) >> 4][(s1 + 15) >> 4] == BAN_VOID) && (ban_map[(s2 + 8) >> 4][s1 >> 4] == BAN_WATER || ban_map[(s2 + 8) >> 4][(s1 + 15) >> 4] == BAN_WATER))
1834 player[c1].in_water = 0;
1836 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 player[c1].x += player[c1].x_add;
1842 if ((player[c1].x >> 16) < 0) {
1844 player[c1].x_add = 0;
1846 if ((player[c1].x >> 16) + 15 > 351) {
1847 player[c1].x = 336L << 16;
1848 player[c1].x_add = 0;
1850 if (player[c1].y > 0) {
1851 s1 = (player[c1].x >> 16);
1852 s2 = (player[c1].y >> 16);
1853 if (ban_map[s2 >> 4][s1 >> 4] == BAN_SOLID || ban_map[s2 >> 4][s1 >> 4] == BAN_ICE || ban_map[s2 >> 4][s1 >> 4] == BAN_SPRING || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SPRING) {
1854 player[c1].x = (((s1 + 16) & 0xfff0)) << 16;
1855 player[c1].x_add = 0;
1857 s1 = (player[c1].x >> 16);
1858 s2 = (player[c1].y >> 16);
1859 if (ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_ICE || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_SPRING || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SPRING) {
1860 player[c1].x = (((s1 + 16) & 0xfff0) - 16) << 16;
1861 player[c1].x_add = 0;
1864 s1 = (player[c1].x >> 16);
1866 if (ban_map[s2 >> 4][s1 >> 4] == BAN_SOLID || ban_map[s2 >> 4][s1 >> 4] == BAN_ICE || ban_map[s2 >> 4][s1 >> 4] == BAN_SPRING || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SPRING) {
1867 player[c1].x = (((s1 + 16) & 0xfff0)) << 16;
1868 player[c1].x_add = 0;
1870 s1 = (player[c1].x >> 16);
1872 if (ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_ICE || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_SPRING || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SPRING) {
1873 player[c1].x = (((s1 + 16) & 0xfff0) - 16) << 16;
1874 player[c1].x_add = 0;
1878 player[c1].y += player[c1].y_add;
1880 s1 = (player[c1].x >> 16);
1881 s2 = (player[c1].y >> 16);
1882 if (ban_map[(s2 + 15) >> 4][(s1 + 8) >> 4] == BAN_SPRING || ((ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SPRING && ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] != BAN_SOLID) || (ban_map[(s2 + 15) >> 4][s1 >> 4] != BAN_SOLID && ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SPRING))) {
1883 player[c1].y = ((player[c1].y >> 16) & 0xfff0) << 16;
1884 player[c1].y_add = -400000L;
1885 player[c1].anim = 2;
1886 player[c1].frame = 0;
1887 player[c1].frame_tick = 0;
1888 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1889 player[c1].jump_ready = 0;
1890 player[c1].jump_abort = 0;
1891 for (c2 = 0; c2 < NUM_OBJECTS; c2++) {
1892 if (objects[c2].used == 1 && objects[c2].type == OBJ_SPRING) {
1893 if (ban_map[(s2 + 15) >> 4][(s1 + 8) >> 4] == BAN_SPRING) {
1894 if ((objects[c2].x >> 20) == ((s1 + 8) >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
1895 objects[c2].frame = 0;
1896 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
1897 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
1901 if (ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SPRING) {
1902 if ((objects[c2].x >> 20) == (s1 >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
1903 objects[c2].frame = 0;
1904 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
1905 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
1908 } else if (ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SPRING) {
1909 if ((objects[c2].x >> 20) == ((s1 + 15) >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
1910 objects[c2].frame = 0;
1911 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
1912 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
1919 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1921 s1 = (player[c1].x >> 16);
1922 s2 = (player[c1].y >> 16);
1925 if (ban_map[s2 >> 4][s1 >> 4] == BAN_SOLID || ban_map[s2 >> 4][s1 >> 4] == BAN_ICE || ban_map[s2 >> 4][s1 >> 4] == BAN_SPRING || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_ICE || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_SPRING) {
1926 player[c1].y = (((s2 + 16) & 0xfff0)) << 16;
1927 player[c1].y_add = 0;
1928 player[c1].anim = 0;
1929 player[c1].frame = 0;
1930 player[c1].frame_tick = 0;
1931 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1933 s1 = (player[c1].x >> 16);
1934 s2 = (player[c1].y >> 16);
1937 if (ban_map[(s2 + 8) >> 4][(s1 + 8) >> 4] == BAN_WATER) {
1938 if (player[c1].in_water == 0) {
1939 player[c1].in_water = 1;
1940 player[c1].anim = 4;
1941 player[c1].frame = 0;
1942 player[c1].frame_tick = 0;
1943 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1944 if (player[c1].y_add >= 32768) {
1945 add_object(OBJ_SPLASH, (player[c1].x >> 16) + 8, ((player[c1].y >> 16) & 0xfff0) + 15, 0, 0, OBJ_ANIM_SPLASH, 0);
1946 if (blood_is_thicker_than_water == 0)
1947 dj_play_sfx(SFX_SPLASH, (unsigned short)(SFX_SPLASH_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1949 dj_play_sfx(SFX_SPLASH, (unsigned short)(SFX_SPLASH_FREQ + rnd(2000) - 5000), 64, 0, 0, -1);
1952 player[c1].y_add -= 1536;
1953 if (player[c1].y_add < 0 && player[c1].anim != 5) {
1954 player[c1].anim = 5;
1955 player[c1].frame = 0;
1956 player[c1].frame_tick = 0;
1957 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1959 if (player[c1].y_add < -65536L)
1960 player[c1].y_add = -65536L;
1961 if (player[c1].y_add > 65535L)
1962 player[c1].y_add = 65535L;
1963 if (ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_ICE) {
1964 player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16;
1965 player[c1].y_add = 0;
1967 } else if (ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SPRING || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SPRING) {
1968 player[c1].in_water = 0;
1969 player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16;
1970 player[c1].y_add = 0;
1971 if (player[c1].anim != 0 && player[c1].anim != 1) {
1972 player[c1].anim = 0;
1973 player[c1].frame = 0;
1974 player[c1].frame_tick = 0;
1975 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1978 if (player[c1].in_water == 0) {
1979 if (bunnies_in_space == 0)
1980 player[c1].y_add += 12288;
1982 player[c1].y_add += 6144;
1983 if (player[c1].y_add > 327680L)
1984 player[c1].y_add = 327680L;
1986 player[c1].y = (player[c1].y & 0xffff0000) + 0x10000;
1987 player[c1].y_add = 0;
1989 player[c1].in_water = 0;
1991 if (player[c1].y_add > 36864 && player[c1].anim != 3 && player[c1].in_water == 0) {
1992 player[c1].anim = 3;
1993 player[c1].frame = 0;
1994 player[c1].frame_tick = 0;
1995 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2000 player[c1].frame_tick++;
2001 if (player[c1].frame_tick >= player_anims[player[c1].anim].frame[player[c1].frame].ticks) {
2003 if (player[c1].frame >= player_anims[player[c1].anim].num_frames) {
2004 if (player[c1].anim != 6)
2005 player[c1].frame = player_anims[player[c1].anim].restart_frame;
2007 position_player(c1);
2009 player[c1].frame_tick = 0;
2011 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2020 void position_player(int player_num)
2029 if (ban_map[s2][s1] == BAN_VOID && (ban_map[s2 + 1][s1] == BAN_SOLID || ban_map[s2 + 1][s1] == BAN_ICE))
2032 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
2033 if (c1 != player_num && player[c1].enabled == 1) {
2034 if (abs((s1 << 4) - (player[c1].x >> 16)) < 32 && abs((s2 << 4) - (player[c1].y >> 16)) < 32)
2038 if (c1 == JNB_MAX_PLAYERS) {
2039 player[player_num].x = (long) s1 << 20;
2040 player[player_num].y = (long) s2 << 20;
2041 player[player_num].x_add = player[player_num].y_add = 0;
2042 player[player_num].direction = 0;
2043 player[player_num].jump_ready = 1;
2044 player[player_num].in_water = 0;
2045 player[player_num].anim = 0;
2046 player[player_num].frame = 0;
2047 player[player_num].frame_tick = 0;
2048 player[player_num].image = player_anims[player[player_num].anim].frame[player[player_num].frame].image;
2053 serverSendAlive(player_num);
2055 player[player_num].dead_flag = 0;
2065 void add_object(int type, int x, int y, int x_add, int y_add, int anim, int frame)
2069 for (c1 = 0; c1 < NUM_OBJECTS; c1++) {
2070 if (objects[c1].used == 0) {
2071 objects[c1].used = 1;
2072 objects[c1].type = type;
2073 objects[c1].x = (long) x << 16;
2074 objects[c1].y = (long) y << 16;
2075 objects[c1].x_add = x_add;
2076 objects[c1].y_add = y_add;
2077 objects[c1].x_acc = 0;
2078 objects[c1].y_acc = 0;
2079 objects[c1].anim = anim;
2080 objects[c1].frame = frame;
2081 objects[c1].ticks = object_anims[anim].frame[frame].ticks;
2082 objects[c1].image = object_anims[anim].frame[frame].image;
2090 void update_objects(void)
2095 for (c1 = 0; c1 < NUM_OBJECTS; c1++) {
2096 if (objects[c1].used == 1) {
2097 switch (objects[c1].type) {
2099 objects[c1].ticks--;
2100 if (objects[c1].ticks <= 0) {
2101 objects[c1].frame++;
2102 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames) {
2103 objects[c1].frame--;
2104 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2106 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2107 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2110 if (objects[c1].used == 1)
2111 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2114 objects[c1].ticks--;
2115 if (objects[c1].ticks <= 0) {
2116 objects[c1].frame++;
2117 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2118 objects[c1].used = 0;
2120 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2121 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2124 if (objects[c1].used == 1)
2125 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2128 objects[c1].x += objects[c1].x_add;
2129 objects[c1].y += objects[c1].y_add;
2130 objects[c1].ticks--;
2131 if (objects[c1].ticks <= 0) {
2132 objects[c1].frame++;
2133 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2134 objects[c1].used = 0;
2136 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2137 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2140 if (objects[c1].used == 1)
2141 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2143 case OBJ_YEL_BUTFLY:
2144 case OBJ_PINK_BUTFLY:
2145 objects[c1].x_acc += rnd(128) - 64;
2146 if (objects[c1].x_acc < -1024)
2147 objects[c1].x_acc = -1024;
2148 if (objects[c1].x_acc > 1024)
2149 objects[c1].x_acc = 1024;
2150 objects[c1].x_add += objects[c1].x_acc;
2151 if (objects[c1].x_add < -32768)
2152 objects[c1].x_add = -32768;
2153 if (objects[c1].x_add > 32768)
2154 objects[c1].x_add = 32768;
2155 objects[c1].x += objects[c1].x_add;
2156 if ((objects[c1].x >> 16) < 16) {
2157 objects[c1].x = 16 << 16;
2158 objects[c1].x_add = -objects[c1].x_add >> 2;
2159 objects[c1].x_acc = 0;
2160 } else if ((objects[c1].x >> 16) > 350) {
2161 objects[c1].x = 350 << 16;
2162 objects[c1].x_add = -objects[c1].x_add >> 2;
2163 objects[c1].x_acc = 0;
2165 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0) {
2166 if (objects[c1].x_add < 0) {
2167 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2169 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2171 objects[c1].x_add = -objects[c1].x_add >> 2;
2172 objects[c1].x_acc = 0;
2174 objects[c1].y_acc += rnd(64) - 32;
2175 if (objects[c1].y_acc < -1024)
2176 objects[c1].y_acc = -1024;
2177 if (objects[c1].y_acc > 1024)
2178 objects[c1].y_acc = 1024;
2179 objects[c1].y_add += objects[c1].y_acc;
2180 if (objects[c1].y_add < -32768)
2181 objects[c1].y_add = -32768;
2182 if (objects[c1].y_add > 32768)
2183 objects[c1].y_add = 32768;
2184 objects[c1].y += objects[c1].y_add;
2185 if ((objects[c1].y >> 16) < 0) {
2187 objects[c1].y_add = -objects[c1].y_add >> 2;
2188 objects[c1].y_acc = 0;
2189 } else if ((objects[c1].y >> 16) > 255) {
2190 objects[c1].y = 255 << 16;
2191 objects[c1].y_add = -objects[c1].y_add >> 2;
2192 objects[c1].y_acc = 0;
2194 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0) {
2195 if (objects[c1].y_add < 0) {
2196 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2198 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2200 objects[c1].y_add = -objects[c1].y_add >> 2;
2201 objects[c1].y_acc = 0;
2203 if (objects[c1].type == OBJ_YEL_BUTFLY) {
2204 if (objects[c1].x_add < 0 && objects[c1].anim != OBJ_ANIM_YEL_BUTFLY_LEFT) {
2205 objects[c1].anim = OBJ_ANIM_YEL_BUTFLY_LEFT;
2206 objects[c1].frame = 0;
2207 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2208 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2209 } else if (objects[c1].x_add > 0 && objects[c1].anim != OBJ_ANIM_YEL_BUTFLY_RIGHT) {
2210 objects[c1].anim = OBJ_ANIM_YEL_BUTFLY_RIGHT;
2211 objects[c1].frame = 0;
2212 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2213 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2216 if (objects[c1].x_add < 0 && objects[c1].anim != OBJ_ANIM_PINK_BUTFLY_LEFT) {
2217 objects[c1].anim = OBJ_ANIM_PINK_BUTFLY_LEFT;
2218 objects[c1].frame = 0;
2219 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2220 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2221 } else if (objects[c1].x_add > 0 && objects[c1].anim != OBJ_ANIM_PINK_BUTFLY_RIGHT) {
2222 objects[c1].anim = OBJ_ANIM_PINK_BUTFLY_RIGHT;
2223 objects[c1].frame = 0;
2224 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2225 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2228 objects[c1].ticks--;
2229 if (objects[c1].ticks <= 0) {
2230 objects[c1].frame++;
2231 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2232 objects[c1].frame = object_anims[objects[c1].anim].restart_frame;
2234 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2235 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2238 if (objects[c1].used == 1)
2239 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2243 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 0);
2244 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 0) {
2245 objects[c1].y_add += 3072;
2246 if (objects[c1].y_add > 196608L)
2247 objects[c1].y_add = 196608L;
2248 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 2) {
2249 if (objects[c1].x_add < 0) {
2250 if (objects[c1].x_add < -65536L)
2251 objects[c1].x_add = -65536L;
2252 objects[c1].x_add += 1024;
2253 if (objects[c1].x_add > 0)
2254 objects[c1].x_add = 0;
2256 if (objects[c1].x_add > 65536L)
2257 objects[c1].x_add = 65536L;
2258 objects[c1].x_add -= 1024;
2259 if (objects[c1].x_add < 0)
2260 objects[c1].x_add = 0;
2262 objects[c1].y_add += 1024;
2263 if (objects[c1].y_add < -65536L)
2264 objects[c1].y_add = -65536L;
2265 if (objects[c1].y_add > 65536L)
2266 objects[c1].y_add = 65536L;
2268 objects[c1].x += objects[c1].x_add;
2269 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)) {
2270 if (objects[c1].x_add < 0) {
2271 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2272 objects[c1].x_add = -objects[c1].x_add >> 2;
2274 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2275 objects[c1].x_add = -objects[c1].x_add >> 2;
2278 objects[c1].y += objects[c1].y_add;
2279 if ((objects[c1].x >> 16) < -5 || (objects[c1].x >> 16) > 405 || (objects[c1].y >> 16) > 260)
2280 objects[c1].used = 0;
2281 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0)) {
2282 if (objects[c1].y_add < 0) {
2283 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 2) {
2284 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2285 objects[c1].x_add >>= 2;
2286 objects[c1].y_add = -objects[c1].y_add >> 2;
2289 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1) {
2290 if (objects[c1].y_add > 131072L) {
2291 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2292 objects[c1].x_add >>= 2;
2293 objects[c1].y_add = -objects[c1].y_add >> 2;
2295 objects[c1].used = 0;
2296 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3) {
2297 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2298 if (objects[c1].y_add > 131072L)
2299 objects[c1].y_add = -objects[c1].y_add >> 2;
2301 objects[c1].y_add = 0;
2305 if (objects[c1].x_add < 0 && objects[c1].x_add > -16384)
2306 objects[c1].x_add = -16384;
2307 if (objects[c1].x_add > 0 && objects[c1].x_add < 16384)
2308 objects[c1].x_add = 16384;
2309 if (objects[c1].used == 1) {
2310 s1 = (int)(atan2(objects[c1].y_add, objects[c1].x_add) * 4 / M_PI);
2317 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].frame + s1, &object_gobs);
2321 if (rnd(100) < 30) {
2322 if (objects[c1].frame == 76)
2323 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 1);
2324 else if (objects[c1].frame == 77)
2325 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 2);
2326 else if (objects[c1].frame == 78)
2327 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 3);
2329 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 0) {
2330 objects[c1].y_add += 3072;
2331 if (objects[c1].y_add > 196608L)
2332 objects[c1].y_add = 196608L;
2333 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 2) {
2334 if (objects[c1].x_add < 0) {
2335 if (objects[c1].x_add < -65536L)
2336 objects[c1].x_add = -65536L;
2337 objects[c1].x_add += 1024;
2338 if (objects[c1].x_add > 0)
2339 objects[c1].x_add = 0;
2341 if (objects[c1].x_add > 65536L)
2342 objects[c1].x_add = 65536L;
2343 objects[c1].x_add -= 1024;
2344 if (objects[c1].x_add < 0)
2345 objects[c1].x_add = 0;
2347 objects[c1].y_add += 1024;
2348 if (objects[c1].y_add < -65536L)
2349 objects[c1].y_add = -65536L;
2350 if (objects[c1].y_add > 65536L)
2351 objects[c1].y_add = 65536L;
2353 objects[c1].x += objects[c1].x_add;
2354 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)) {
2355 if (objects[c1].x_add < 0) {
2356 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2357 objects[c1].x_add = -objects[c1].x_add >> 2;
2359 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2360 objects[c1].x_add = -objects[c1].x_add >> 2;
2363 objects[c1].y += objects[c1].y_add;
2364 if ((objects[c1].x >> 16) < -5 || (objects[c1].x >> 16) > 405 || (objects[c1].y >> 16) > 260)
2365 objects[c1].used = 0;
2366 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0)) {
2367 if (objects[c1].y_add < 0) {
2368 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 2) {
2369 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2370 objects[c1].x_add >>= 2;
2371 objects[c1].y_add = -objects[c1].y_add >> 2;
2374 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1) {
2375 if (objects[c1].y_add > 131072L) {
2376 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2377 objects[c1].x_add >>= 2;
2378 objects[c1].y_add = -objects[c1].y_add >> 2;
2380 if (rnd(100) < 10) {
2382 add_leftovers(0, objects[c1].x >> 16, (objects[c1].y >> 16) + s1, objects[c1].frame, &object_gobs);
2383 add_leftovers(1, objects[c1].x >> 16, (objects[c1].y >> 16) + s1, objects[c1].frame, &object_gobs);
2385 objects[c1].used = 0;
2387 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3) {
2388 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2389 if (objects[c1].y_add > 131072L)
2390 objects[c1].y_add = -objects[c1].y_add >> 2;
2392 objects[c1].y_add = 0;
2396 if (objects[c1].x_add < 0 && objects[c1].x_add > -16384)
2397 objects[c1].x_add = -16384;
2398 if (objects[c1].x_add > 0 && objects[c1].x_add < 16384)
2399 objects[c1].x_add = 16384;
2400 if (objects[c1].used == 1)
2401 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].frame, &object_gobs);
2403 case OBJ_FLESH_TRACE:
2404 objects[c1].ticks--;
2405 if (objects[c1].ticks <= 0) {
2406 objects[c1].frame++;
2407 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2408 objects[c1].used = 0;
2410 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2411 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2414 if (objects[c1].used == 1)
2415 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2424 int add_pob(int page, int x, int y, int image, gob_t *pob_data)
2427 if (main_info.page_info[page].num_pobs >= NUM_POBS)
2430 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].x = x;
2431 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].y = y;
2432 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].image = image;
2433 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].pob_data = pob_data;
2434 main_info.page_info[page].num_pobs++;
2441 void draw_flies(int page)
2445 for (c2 = 0; c2 < NUM_FLIES; c2++) {
2446 flies[c2].back[main_info.draw_page] = get_pixel(main_info.draw_page, flies[c2].x, flies[c2].y);
2447 flies[c2].back_defined[main_info.draw_page] = 1;
2448 if (mask_pic[(flies[c2].y * JNB_WIDTH) + flies[c2].x] == 0)
2449 set_pixel(main_info.draw_page, flies[c2].x, flies[c2].y, 0);
2453 void draw_pobs(int page)
2460 for (c1 = main_info.page_info[page].num_pobs - 1; c1 >= 0; c1--) {
2461 main_info.page_info[page].pobs[c1].back_buf_ofs = back_buf_ofs;
2462 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);
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) * 4;
2466 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);
2467 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);
2473 void redraw_flies_background(int page)
2477 for (c2 = NUM_FLIES - 1; c2 >= 0; c2--) {
2478 if (flies[c2].back_defined[page] == 1)
2479 set_pixel(page, flies[c2].old_draw_x, flies[c2].old_draw_y, flies[c2].back[page]);
2480 flies[c2].old_draw_x = flies[c2].x;
2481 flies[c2].old_draw_y = flies[c2].y;
2486 void redraw_pob_backgrounds(int page)
2490 for (c1 = 0; c1 < main_info.page_info[page].num_pobs; c1++)
2491 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);
2496 int add_leftovers(int page, int x, int y, int image, gob_t *pob_data)
2499 if (leftovers.page[page].num_pobs >= NUM_LEFTOVERS)
2502 leftovers.page[page].pobs[leftovers.page[page].num_pobs].x = x;
2503 leftovers.page[page].pobs[leftovers.page[page].num_pobs].y = y;
2504 leftovers.page[page].pobs[leftovers.page[page].num_pobs].image = image;
2505 leftovers.page[page].pobs[leftovers.page[page].num_pobs].pob_data = pob_data;
2506 leftovers.page[page].num_pobs++;
2513 void draw_leftovers(int page)
2517 for (c1 = leftovers.page[page].num_pobs - 1; c1 >= 0; c1--)
2518 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);
2520 leftovers.page[page].num_pobs = 0;
2525 int init_level(int level, char *pal)
2527 unsigned char *handle;
2531 if ((handle = dat_open("level.pcx")) == 0) {
2532 strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n");
2535 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
2536 strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n");
2540 flip_pixels(background_pic);
2541 if ((handle = dat_open("mask.pcx")) == 0) {
2542 strcpy(main_info.error_str, "Error loading 'mask.pcx', aborting...\n");
2545 if (read_pcx(handle, mask_pic, JNB_WIDTH*JNB_HEIGHT, 0) != 0) {
2546 strcpy(main_info.error_str, "Error loading 'mask.pcx', aborting...\n");
2550 flip_pixels(mask_pic);
2551 register_mask(mask_pic);
2553 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
2554 if (player[c1].enabled == 1) {
2555 player[c1].bumps = 0;
2556 for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++)
2557 player[c1].bumped[c2] = 0;
2558 position_player(c1);
2562 for (c1 = 0; c1 < NUM_OBJECTS; c1++)
2563 objects[c1].used = 0;
2565 for (c1 = 0; c1 < 16; c1++) {
2566 for (c2 = 0; c2 < 22; c2++) {
2567 if (ban_map[c1][c2] == BAN_SPRING)
2568 add_object(OBJ_SPRING, c2 << 4, c1 << 4, 0, 0, OBJ_ANIM_SPRING, 5);
2575 if (ban_map[s2][s1] == BAN_VOID) {
2576 add_object(OBJ_YEL_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2583 if (ban_map[s2][s1] == BAN_VOID) {
2584 add_object(OBJ_YEL_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2591 if (ban_map[s2][s1] == BAN_VOID) {
2592 add_object(OBJ_PINK_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2599 if (ban_map[s2][s1] == BAN_VOID) {
2600 add_object(OBJ_PINK_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2610 void deinit_level(void)
2618 #define PATH_MAX 1024
2624 unsigned char *datafile_buffer = NULL;
2626 static void preread_datafile(const char *fname)
2632 char *gzfilename = alloca(strlen(fname) + 4);
2637 strcpy(gzfilename, fname);
2638 strcat(gzfilename, ".gz");
2640 gzf = gzopen(gzfilename, "rb");
2645 if (bufpos >= bufsize) {
2646 bufsize += 1024 * 1024;
2647 datafile_buffer = (unsigned char *) realloc(datafile_buffer, bufsize);
2648 if (datafile_buffer == NULL) {
2649 perror("realloc()");
2654 br = gzread(gzf, datafile_buffer + bufpos, bufsize - bufpos);
2656 fprintf(stderr, "gzread failed.\n");
2661 } while (!gzeof(gzf));
2663 /* try to shrink buffer... */
2664 ptr = (unsigned char *) realloc(datafile_buffer, bufpos);
2666 datafile_buffer = ptr;
2672 /* drop through and try for an uncompressed datafile... */
2675 fd = open(fname, O_RDONLY | O_BINARY);
2677 fprintf(stderr, "can't open %s:", fname);
2682 len = filelength(fd);
2683 datafile_buffer = (unsigned char *) malloc(len);
2684 if (datafile_buffer == NULL) {
2690 if (read(fd, datafile_buffer, len) != len) {
2700 int init_program(int argc, char *argv[], char *pal)
2702 char *netarg = NULL;
2703 unsigned char *handle = (unsigned char *) NULL;
2708 int player_anim_data[] = {
2709 1, 0, 0, 0x7fff, 0, 0, 0, 0, 0, 0,
2710 4, 0, 0, 4, 1, 4, 2, 4, 3, 4,
2711 1, 0, 4, 0x7fff, 0, 0, 0, 0, 0, 0,
2712 4, 2, 5, 8, 6, 10, 7, 3, 6, 3,
2713 1, 0, 6, 0x7fff, 0, 0, 0, 0, 0, 0,
2714 2, 1, 5, 8, 4, 0x7fff, 0, 0, 0, 0,
2715 1, 0, 8, 5, 0, 0, 0, 0, 0, 0
2719 memset(&net_info, 0, sizeof(net_info));
2723 if (__djgpp_nearptr_enable() == 0)
2729 if (hook_keyb_handler() != 0)
2732 memset(&main_info, 0, sizeof(main_info));
2734 strcpy(datfile_name, DATA_PATH);
2736 force2 = force3 = 0;
2739 for (c1 = 1; c1 < argc; c1++) {
2740 if (stricmp(argv[c1], "-nosound") == 0)
2741 main_info.no_sound = 1;
2742 else if (stricmp(argv[c1], "-musicnosound") == 0)
2743 main_info.music_no_sound = 1;
2744 else if (stricmp(argv[c1], "-nogore") == 0)
2745 main_info.no_gore = 1;
2746 else if (stricmp(argv[c1], "-noflies") == 0)
2748 else if (stricmp(argv[c1], "-nojoy") == 0)
2749 main_info.joy_enabled = 0;
2750 else if (stricmp(argv[c1], "-fireworks") == 0)
2751 main_info.fireworks = 1;
2753 else if (stricmp(argv[c1], "-fullscreen") == 0)
2756 else if (stricmp(argv[c1], "-scaleup") == 0)
2758 else if (stricmp(argv[c1], "-mirror") == 0)
2760 else if (stricmp(argv[c1], "-dat") == 0) {
2761 if (c1 < (argc - 1)) {
2764 if ((f = fopen(argv[c1 + 1], "rb")) != NULL) {
2766 strcpy(datfile_name, argv[c1 + 1]);
2769 } else if (stricmp(argv[c1], "-player") == 0) {
2770 if (c1 < (argc - 1)) {
2771 if (client_player_num < 0)
2772 client_player_num = atoi(argv[c1 + 1]);
2775 } else if (stricmp(argv[c1], "-server") == 0) {
2776 if (c1 < (argc - 1)) {
2779 netarg = argv[c1 + 1];
2781 } else if (stricmp(argv[c1], "-connect") == 0) {
2782 if (c1 < (argc - 1)) {
2785 netarg = argv[c1 + 1];
2788 } else if (stricmp(argv[c1], "-mouse") == 0) {
2789 if (c1 < (argc - 1)) {
2790 if (stricmp(argv[c1 + 1], "2") == 0)
2792 if (stricmp(argv[c1 + 1], "3") == 0)
2796 else if (strstr(argv[1],"-v")) {
2797 printf("jumpnbump %s compiled %s at %s with",JNB_VERSION,__DATE__,__TIME__);
2801 printf(" network support.\n");
2804 else if (strstr(argv[1],"-h")) {
2805 printf("Usage: jumpnbump [OPTION]...\n");
2807 printf(" -h this help\n");
2808 printf(" -v print version\n");
2809 printf(" -dat level.dat play a different level\n");
2811 printf(" -server playercount start as server waiting for players\n");
2812 printf(" -connect host connect to server\n");
2814 printf(" -player num set main player to num (0-3). Needed for networking\n");
2815 printf(" -fireworks screensaver mode\n");
2816 printf(" -fullscreen run in fullscreen mode\n");
2817 printf(" -nosound play without sound\n");
2818 printf(" -nogore play without blood\n");
2819 printf(" -noflies disable flies\n");
2820 printf(" -mirror play with mirrored level\n");
2821 printf(" -scaleup play with doubled resolution (800x512)\n");
2822 printf(" -musicnosound play with music but without sound\n");
2829 preread_datafile(datfile_name);
2832 /** It should not be necessary to assign a default player number here. The
2833 server assigns one in init_server, the client gets one assigned by the server,
2834 all provided the user didn't choose one on the commandline. */
2836 if (client_player_num < 0)
2837 client_player_num = 0;
2838 player[client_player_num].enabled = 1;
2842 main_info.pob_backbuf[0] = malloc(screen_pitch*screen_height);
2843 main_info.pob_backbuf[1] = malloc(screen_pitch*screen_height);
2845 for (c1 = 0; c1 < 7; c1++) {
2846 player_anims[c1].num_frames = player_anim_data[c1 * 10];
2847 player_anims[c1].restart_frame = player_anim_data[c1 * 10 + 1];
2848 for (c2 = 0; c2 < 4; c2++) {
2849 player_anims[c1].frame[c2].image = player_anim_data[c1 * 10 + c2 * 2 + 2];
2850 player_anims[c1].frame[c2].ticks = player_anim_data[c1 * 10 + c2 * 2 + 3];
2854 if ((handle = dat_open("menu.pcx")) == 0) {
2855 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
2858 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
2859 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
2863 if ((handle = dat_open("rabbit.gob")) == 0) {
2864 strcpy(main_info.error_str, "Error loading 'rabbit.gob', aborting...\n");
2867 if (register_gob(handle, &rabbit_gobs, dat_filelen("rabbit.gob"))) {
2872 if ((handle = dat_open("objects.gob")) == 0) {
2873 strcpy(main_info.error_str, "Error loading 'objects.gob', aborting...\n");
2876 if (register_gob(handle, &object_gobs, dat_filelen("objects.gob"))) {
2881 if ((handle = dat_open("font.gob")) == 0) {
2882 strcpy(main_info.error_str, "Error loading 'font.gob', aborting...\n");
2885 if (register_gob(handle, &font_gobs, dat_filelen("font.gob"))) {
2890 if ((handle = dat_open("numbers.gob")) == 0) {
2891 strcpy(main_info.error_str, "Error loading 'numbers.gob', aborting...\n");
2894 if (register_gob(handle, &number_gobs, dat_filelen("numbers.gob"))) {
2899 if (read_level() != 0) {
2900 strcpy(main_info.error_str, "Error loading 'levelmap.txt', aborting...\n");
2906 if (main_info.no_sound == 0) {
2908 dj_set_mixing_freq(20000);
2912 dj_set_num_sfx_channels(5);
2913 dj_set_sfx_volume(64);
2917 if ((handle = dat_open("jump.mod")) == 0) {
2918 strcpy(main_info.error_str, "Error loading 'jump.mod', aborting...\n");
2921 if (dj_load_mod(handle, 0, MOD_MENU) != 0) {
2922 strcpy(main_info.error_str, "Error loading 'jump.mod', aborting...\n");
2926 if ((handle = dat_open("bump.mod")) == 0) {
2927 strcpy(main_info.error_str, "Error loading 'bump.mod', aborting...\n");
2930 if (dj_load_mod(handle, 0, MOD_GAME) != 0) {
2931 strcpy(main_info.error_str, "Error loading 'bump.mod', aborting...\n");
2935 if ((handle = dat_open("scores.mod")) == 0) {
2936 strcpy(main_info.error_str, "Error loading 'scores.mod', aborting...\n");
2939 if (dj_load_mod(handle, 0, MOD_SCORES) != 0) {
2940 strcpy(main_info.error_str, "Error loading 'scores.mod', aborting...\n");
2944 if ((handle = dat_open("jump.smp")) == 0) {
2945 strcpy(main_info.error_str, "Error loading 'jump.smp', aborting...\n");
2948 if (dj_load_sfx(handle, 0, dat_filelen("jump.smp"), DJ_SFX_TYPE_SMP, SFX_JUMP) != 0) {
2949 strcpy(main_info.error_str, "Error loading 'jump.smp', aborting...\n");
2953 if ((handle = dat_open("death.smp")) == 0) {
2954 strcpy(main_info.error_str, "Error loading 'death.smp', aborting...\n");
2957 if (dj_load_sfx(handle, 0, dat_filelen("death.smp"), DJ_SFX_TYPE_SMP, SFX_DEATH) != 0) {
2958 strcpy(main_info.error_str, "Error loading 'death.smp', aborting...\n");
2962 if ((handle = dat_open("spring.smp")) == 0) {
2963 strcpy(main_info.error_str, "Error loading 'spring.smp', aborting...\n");
2966 if (dj_load_sfx(handle, 0, dat_filelen("spring.smp"), DJ_SFX_TYPE_SMP, SFX_SPRING) != 0) {
2967 strcpy(main_info.error_str, "Error loading 'spring.smp', aborting...\n");
2971 if ((handle = dat_open("splash.smp")) == 0) {
2972 strcpy(main_info.error_str, "Error loading 'splash.smp', aborting...\n");
2975 if (dj_load_sfx(handle, 0, dat_filelen("splash.smp"), DJ_SFX_TYPE_SMP, SFX_SPLASH) != 0) {
2976 strcpy(main_info.error_str, "Error loading 'splash.smp', aborting...\n");
2980 if ((handle = dat_open("fly.smp")) == 0) {
2981 strcpy(main_info.error_str, "Error loading 'fly.smp', aborting...\n");
2984 if (dj_load_sfx(handle, 0, dat_filelen("fly.smp"), DJ_SFX_TYPE_SMP, SFX_FLY) != 0) {
2985 strcpy(main_info.error_str, "Error loading 'fly.smp', aborting...\n");
2989 dj_get_sfx_settings(SFX_FLY, &fly);
2991 fly.default_freq = SFX_FLY_FREQ;
2994 fly.loop_length = fly.length;
2995 dj_set_sfx_settings(SFX_FLY, &fly);
2998 if ((background_pic = malloc(JNB_WIDTH*JNB_HEIGHT)) == NULL)
3000 if ((mask_pic = malloc(JNB_WIDTH*JNB_HEIGHT)) == NULL)
3002 memset(mask_pic, 0, JNB_WIDTH*JNB_HEIGHT);
3003 register_mask(mask_pic);
3006 for (c1 = 0; c1 < 16; c1++) {
3007 pal[(240 + c1) * 3 + 0] = c1 << 2;
3008 pal[(240 + c1) * 3 + 1] = c1 << 2;
3009 pal[(240 + c1) * 3 + 2] = c1 << 2;
3012 setpalette(0, 256, pal);
3016 recalculate_gob(&font_gobs, pal);
3018 if (main_info.joy_enabled == 1 && main_info.fireworks == 0) {
3020 put_text(0, 200, 40, "JOYSTICK CALIBRATION", 2);
3021 put_text(0, 200, 100, "Move the joystick to the", 2);
3022 put_text(0, 200, 115, "UPPER LEFT", 2);
3023 put_text(0, 200, 130, "and press button A", 2);
3024 put_text(0, 200, 200, "Or press ESC to use", 2);
3025 put_text(0, 200, 215, "previous settings", 2);
3026 if (calib_joy(0) != 0)
3029 register_background(NULL, NULL);
3031 main_info.view_page = 1;
3036 put_text(1, 200, 40, "JOYSTICK CALIBRATION", 2);
3037 put_text(1, 200, 100, "Move the joystick to the", 2);
3038 put_text(1, 200, 115, "LOWER RIGHT", 2);
3039 put_text(1, 200, 130, "and press button A", 2);
3040 put_text(1, 200, 200, "Or press ESC to use", 2);
3041 put_text(1, 200, 215, "previous settings", 2);
3042 if (calib_joy(1) != 0)
3045 register_background(NULL, NULL);
3050 put_text(0, 200, 40, "JOYSTICK CALIBRATION", 2);
3051 put_text(0, 200, 100, "Move the joystick to the", 2);
3052 put_text(0, 200, 115, "CENTER", 2);
3053 put_text(0, 200, 130, "and press button A", 2);
3054 put_text(0, 200, 200, "Or press ESC to use", 2);
3055 put_text(0, 200, 215, "previous settings", 2);
3056 if (calib_joy(2) != 0)
3059 if (joy.calib_data.x1 == joy.calib_data.x2)
3060 joy.calib_data.x1 -= 10;
3061 if (joy.calib_data.x3 == joy.calib_data.x2)
3062 joy.calib_data.x3 += 10;
3063 if (joy.calib_data.y1 == joy.calib_data.y2)
3064 joy.calib_data.y1 -= 10;
3065 if (joy.calib_data.y3 == joy.calib_data.y2)
3066 joy.calib_data.y3 += 10;
3071 if (load_flag == 1) {
3072 if ((handle = dat_open("calib.dat")) == 0) {
3073 strcpy(main_info.error_str, "Error loading 'calib.dat', aborting...\n");
3076 joy.calib_data.x1 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3077 joy.calib_data.x2 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3078 joy.calib_data.x3 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3079 joy.calib_data.y1 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3080 joy.calib_data.y2 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3081 joy.calib_data.y3 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3088 init_server(netarg);
3090 connect_to_server(netarg);
3099 void deinit_program(void)
3106 dj_free_mod(MOD_MENU);
3107 dj_free_mod(MOD_GAME);
3108 dj_free_sfx(SFX_DEATH);
3109 dj_free_sfx(SFX_SPRING);
3110 dj_free_sfx(SFX_SPLASH);
3113 if (background_pic != 0)
3114 free(background_pic);
3118 remove_keyb_handler();
3122 __dpmi_int(0x10, ®s);
3125 if (main_info.error_str[0] != 0) {
3126 printf(main_info.error_str);
3128 MessageBox(0, main_info.error_str, "Jump'n'Bump", 0);
3137 unsigned short rnd(unsigned short max)
3139 #if (RAND_MAX < 0x7fff)
3140 #error "rand returns too small values"
3141 #elif (RAND_MAX == 0x7fff)
3142 return (unsigned short)((rand()*2) % (int)max);
3144 return (unsigned short)(rand() % (int)max);
3149 int read_level(void)
3151 unsigned char *handle;
3155 if ((handle = dat_open("levelmap.txt")) == 0) {
3156 strcpy(main_info.error_str, "Error loading 'levelmap.txt', aborting...\n");
3160 for (c1 = 0; c1 < 16; c1++) {
3161 for (c2 = 0; c2 < 22; c2++) {
3163 chr = (int) *(handle++);
3164 if (chr >= '0' && chr <= '4')
3168 ban_map[c1][21-c2] = chr - '0';
3170 ban_map[c1][c2] = chr - '0';
3174 for (c2 = 0; c2 < 22; c2++)
3175 ban_map[16][c2] = BAN_SOLID;
3182 unsigned char *dat_open(char *file_name)
3190 if (datafile_buffer == NULL)
3193 memset(name, 0, sizeof(name));
3195 num = ( (datafile_buffer[0] << 0) +
3196 (datafile_buffer[1] << 8) +
3197 (datafile_buffer[2] << 16) +
3198 (datafile_buffer[3] << 24) );
3200 ptr = datafile_buffer + 4;
3202 for (c1 = 0; c1 < num; c1++) {
3204 memcpy(name, ptr, 12);
3207 if (strnicmp(name, file_name, strlen(file_name)) == 0) {
3208 ofs = ( (ptr[0] << 0) +
3213 return (datafile_buffer + ofs);
3222 int dat_filelen(char *file_name)
3230 memset(name, 0, sizeof(name));
3232 num = ( (datafile_buffer[0] << 0) +
3233 (datafile_buffer[1] << 8) +
3234 (datafile_buffer[2] << 16) +
3235 (datafile_buffer[3] << 24) );
3237 ptr = datafile_buffer + 4;
3239 for (c1 = 0; c1 < num; c1++) {
3241 memcpy(name, ptr, 12);
3244 if (strnicmp(name, file_name, strlen(file_name)) == 0) {
3247 len = ( (ptr[0] << 0) +
3261 void write_calib_data(void)
3269 if ((handle = fopen(datfile_name, "rb")) == NULL)
3271 len = filelength(fileno(handle));
3272 if ((mem = malloc(len)) == NULL)
3274 fread(mem, 1, len, handle);
3278 num = *(int *) (&mem[0]);
3279 for (c1 = 0; c1 < num; c1++) {
3280 if (strnicmp(&mem[ofs], "calib.dat", strlen("calib.dat")) == 0) {
3281 ofs = *(int *) (&mem[ofs + 12]);
3287 mem[ofs] = joy.calib_data.x1 & 0xff;
3288 mem[ofs + 1] = (joy.calib_data.x1 >> 8) & 0xff;
3289 mem[ofs + 2] = (joy.calib_data.x1 >> 16) & 0xff;
3290 mem[ofs + 3] = (joy.calib_data.x1 >> 24) & 0xff;
3291 mem[ofs + 4] = joy.calib_data.x2 & 0xff;
3292 mem[ofs + 5] = (joy.calib_data.x2 >> 8) & 0xff;
3293 mem[ofs + 6] = (joy.calib_data.x2 >> 16) & 0xff;
3294 mem[ofs + 7] = (joy.calib_data.x2 >> 24) & 0xff;
3295 mem[ofs + 8] = joy.calib_data.x3 & 0xff;
3296 mem[ofs + 9] = (joy.calib_data.x3 >> 8) & 0xff;
3297 mem[ofs + 10] = (joy.calib_data.x3 >> 16) & 0xff;
3298 mem[ofs + 11] = (joy.calib_data.x3 >> 24) & 0xff;
3299 mem[ofs + 12] = joy.calib_data.y1 & 0xff;
3300 mem[ofs + 13] = (joy.calib_data.y1 >> 8) & 0xff;
3301 mem[ofs + 14] = (joy.calib_data.y1 >> 16) & 0xff;
3302 mem[ofs + 15] = (joy.calib_data.y1 >> 24) & 0xff;
3303 mem[ofs + 16] = joy.calib_data.y2 & 0xff;
3304 mem[ofs + 17] = (joy.calib_data.y2 >> 8) & 0xff;
3305 mem[ofs + 18] = (joy.calib_data.y2 >> 16) & 0xff;
3306 mem[ofs + 19] = (joy.calib_data.y2 >> 24) & 0xff;
3307 mem[ofs + 20] = joy.calib_data.y3 & 0xff;
3308 mem[ofs + 21] = (joy.calib_data.y3 >> 8) & 0xff;
3309 mem[ofs + 22] = (joy.calib_data.y3 >> 16) & 0xff;
3310 mem[ofs + 23] = (joy.calib_data.y3 >> 24) & 0xff;
3312 if ((handle = fopen(datfile_name, "wb")) == NULL)
3314 fwrite(mem, 1, len, handle);