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
45 #define M_PI 3.14159265358979323846
48 gob_t rabbit_gobs = { 0 };
49 gob_t font_gobs = { 0 };
50 gob_t object_gobs = { 0 };
51 gob_t number_gobs = { 0 };
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];
60 char datfile_name[2048];
68 int ai[JNB_MAX_PLAYERS];
70 unsigned int ban_map[17][22] = {
71 {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
72 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0},
73 {1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
74 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1},
75 {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
76 {1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
77 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1},
78 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
79 {1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
80 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 1},
81 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1},
82 {1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1},
83 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
84 {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
85 {2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0, 1, 3, 3, 3, 1, 1, 1},
86 {2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
87 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
90 #define GET_BAN_MAP_XY(x,y) ban_map[(y) >> 4][(x) >> 4]
215 int flies_enabled = 1;
220 int old_draw_x, old_draw_y;
232 } pobs[NUM_LEFTOVERS];
236 int pogostick, bunnies_in_space, jetpack, lord_of_the_flies, blood_is_thicker_than_water;
240 int filelength(int handle)
244 if (fstat(handle, &buf) == -1) {
245 perror("filelength");
254 /* networking shite. */
256 int client_player_num = -1;
261 TCPsocket sock = NULL;
262 SDLNet_SocketSet socketset = NULL;
268 SDLNet_SocketSet socketset;
271 NetInfo net_info[JNB_MAX_PLAYERS];
283 #define NETPKTBUFSIZE (4 + 4 + 4 + 4 + 4)
285 #define NETCMD_NACK (0xF00DF00D + 0)
286 #define NETCMD_ACK (0xF00DF00D + 1)
287 #define NETCMD_HELLO (0xF00DF00D + 2)
288 #define NETCMD_GREENLIGHT (0xF00DF00D + 3)
289 #define NETCMD_MOVE (0xF00DF00D + 4)
290 #define NETCMD_BYE (0xF00DF00D + 5)
291 #define NETCMD_POSITION (0xF00DF00D + 6)
292 #define NETCMD_ALIVE (0xF00DF00D + 7)
293 #define NETCMD_KILL (0xF00DF00D + 8)
297 void bufToPacket(const char *buf, NetPacket *pkt)
299 SDLNet_Write32(*((Uint32*) (buf + 0)), &pkt->cmd);
300 SDLNet_Write32(*((Uint32*) (buf + 4)), &pkt->arg);
301 SDLNet_Write32(*((Uint32*) (buf + 8)), &pkt->arg2);
302 SDLNet_Write32(*((Uint32*) (buf + 12)), &pkt->arg3);
303 SDLNet_Write32(*((Uint32*) (buf + 16)), &pkt->arg4);
305 pkt->cmd = ntohl(*((unsigned long *) (buf + 0)));
306 pkt->arg = (long) ntohl(*((unsigned long *) (buf + 4)));
307 pkt->arg2 = (long) ntohl(*((unsigned long *) (buf + 8)));
308 pkt->arg3 = (long) ntohl(*((unsigned long *) (buf + 12)));
309 pkt->arg4 = (long) ntohl(*((unsigned long *) (buf + 16)));
314 void packetToBuf(const NetPacket *pkt, char *buf)
316 *((Uint32*) (buf + 0)) = SDLNet_Read32(&pkt->cmd);
317 *((Uint32*) (buf + 4)) = SDLNet_Read32(&pkt->arg);
318 *((Uint32*) (buf + 8)) = SDLNet_Read32(&pkt->arg2);
319 *((Uint32*) (buf + 12)) = SDLNet_Read32(&pkt->arg3);
320 *((Uint32*) (buf + 16)) = SDLNet_Read32(&pkt->arg4);
322 *((unsigned long *) (buf + 0)) = htonl(pkt->cmd);
323 *((unsigned long *) (buf + 4)) = htonl((unsigned long) pkt->arg);
324 *((unsigned long *) (buf + 8)) = htonl((unsigned long) pkt->arg2);
325 *((unsigned long *) (buf + 12)) = htonl((unsigned long) pkt->arg3);
326 *((unsigned long *) (buf + 16)) = htonl((unsigned long) pkt->arg4);
331 void sendPacketToSock(TCPsocket s, NetPacket *pkt)
333 int bytes_left = NETPKTBUFSIZE;
335 char buf[NETPKTBUFSIZE];
338 packetToBuf(pkt, buf);
339 while (bytes_left > 0) {
340 bw = SDLNet_TCP_Send(s, ptr, bytes_left);
342 fprintf(stderr, "SERVER: SDLNet_TCP_Send(): %s\n", SDLNet_GetError());
345 } else if (bw == 0) {
355 void sendPacket(int playerid, NetPacket *pkt)
357 if ( (playerid < JNB_MAX_PLAYERS) && (playerid >= 0)) {
358 if ((player[playerid].enabled) && (playerid != client_player_num)) {
359 sendPacketToSock(net_info[playerid].sock, pkt);
365 void sendPacketToAll(NetPacket *pkt)
369 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
374 /** read a packet from the given TCPsocket
375 Returns -1 if some error occured, 0 if there was no data available and 1 if a
376 packet was successfully read.
377 Note: the socket has to be in the supplied socketset.
378 TODO: this function will bomb if a packet arrives in pieces, there is no
379 inherent guarantee that the next call will be made on the same socket. */
380 int grabPacket(TCPsocket s, SDLNet_SocketSet ss, NetPacket *pkt)
382 static char buf[NETPKTBUFSIZE];
383 static int buf_count = 0;
386 if (SDLNet_CheckSockets(ss, 0) <= 0)
389 if(!SDLNet_SocketReady(s))
392 rc = SDLNet_TCP_Recv(s, &buf[buf_count], NETPKTBUFSIZE - buf_count);
394 /* closed connection? */
396 } else if (rc != NETPKTBUFSIZE) {
397 /* we got a partial packet. Store what we got in the static buffer and
398 return so that the next call can read the rest. Hopefully. */
403 bufToPacket(buf, pkt);
409 int serverRecvPacket(NetPacket *pkt)
416 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
417 TCPsocket s = net_info[i].sock;
419 if ((i == client_player_num) || (!player[i].enabled))
422 rc = grabPacket(s, net_info[i].socketset, pkt);
426 player[i].enabled = 0;
428 pkt.cmd = NETCMD_BYE;
433 sendPacketToAll(&pkt);
435 return(i); /* it's all good. */
439 return(-1); /* no packets available currently. */
443 void wait_for_greenlight(void)
448 printf("CLIENT: Waiting for greenlight...\n");
452 while ((rc = grabPacket(sock, socketset, &pkt)) == 0) {
453 SDL_Delay(100); /* nap and then try again. */
457 printf("CLIENT: Lost connection.\n");
458 SDLNet_TCP_Close(sock);
461 } while (pkt.cmd != NETCMD_GREENLIGHT);
463 printf("CLIENT: Got greenlight.\n");
465 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
466 if (pkt.arg & (1 << i)) {
467 printf("CLIENT: There is a player #%d.\n", i);
468 player[i].enabled = 1;
474 static int buggered_off = 0;
477 void tellServerGoodbye(void)
483 pkt.cmd = NETCMD_BYE;
484 pkt.arg = client_player_num;
488 sendPacketToSock(sock, &pkt);
494 void processMovePacket(NetPacket *pkt)
496 int playerid = pkt->arg;
497 int movetype = ((pkt->arg2 >> 16) & 0xFF);
498 int newval = ((pkt->arg2 >> 0) & 0xFF);
500 if (movetype == MOVEMENT_LEFT) {
501 player[playerid].action_left = newval;
502 } else if (movetype == MOVEMENT_RIGHT) {
503 player[playerid].action_right = newval;
504 } else if (movetype == MOVEMENT_UP) {
505 player[playerid].action_up = newval;
507 printf("bogus MOVE packet!\n");
510 player[playerid].x = pkt->arg3;
511 player[playerid].y = pkt->arg4;
515 void tellServerPlayerMoved(int playerid, int movement_type, int newval)
519 pkt.cmd = NETCMD_MOVE;
521 pkt.arg2 = ( ((movement_type & 0xFF) << 16) | ((newval & 0xFF) << 0) );
522 pkt.arg3 = player[playerid].x;
523 pkt.arg4 = player[playerid].y;
526 processMovePacket(&pkt);
529 sendPacketToAll(&pkt);
531 sendPacketToSock(sock, &pkt);
538 void tellServerNewPosition(void)
541 pkt.cmd = NETCMD_POSITION;
542 pkt.arg = client_player_num;
543 pkt.arg2 = player[client_player_num].x;
544 pkt.arg3 = player[client_player_num].y;
547 sendPacketToAll(&pkt);
549 sendPacketToSock(sock, &pkt);
555 void processKillPacket(NetPacket *pkt)
564 player[c1].y_add = -player[c1].y_add;
565 if (player[c1].y_add > -262144L)
566 player[c1].y_add = -262144L;
567 player[c1].jump_abort = 1;
568 player[c2].dead_flag = 1;
569 if (player[c2].anim != 6) {
571 player[c2].frame = 0;
572 player[c2].frame_tick = 0;
573 player[c2].image = player_anims[player[c2].anim].frame[player[c2].frame].image + player[c2].direction * 9;
574 if (main_info.no_gore == 0) {
575 for (c4 = 0; c4 < 6; c4++)
576 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);
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, 76);
579 for (c4 = 0; c4 < 6; 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, 77);
581 for (c4 = 0; c4 < 8; 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, 78);
583 for (c4 = 0; c4 < 10; c4++)
584 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 79);
586 dj_play_sfx(SFX_DEATH, (unsigned short)(SFX_DEATH_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
588 player[c1].bumped[c2]++;
589 s1 = player[c1].bumps % 100;
590 add_leftovers(0, 360, 34 + c1 * 64, s1 / 10, &number_gobs);
591 add_leftovers(1, 360, 34 + c1 * 64, s1 / 10, &number_gobs);
592 add_leftovers(0, 376, 34 + c1 * 64, s1 - (s1 / 10) * 10, &number_gobs);
593 add_leftovers(1, 376, 34 + c1 * 64, s1 - (s1 / 10) * 10, &number_gobs);
599 void processPositionPacket(NetPacket *pkt)
601 int playerid = pkt->arg;
603 player[playerid].x = pkt->arg2;
604 player[playerid].y = pkt->arg3;
608 void processAlivePacket(NetPacket *pkt)
610 int playerid = pkt->arg;
612 player[playerid].dead_flag = 0;
613 player[playerid].x = pkt->arg2;
614 player[playerid].y = pkt->arg3;
618 void serverTellEveryoneGoodbye(void)
624 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
625 if (player[i].enabled) {
628 pkt.cmd = NETCMD_BYE;
633 sendPacketToAll(&pkt);
640 int server_said_bye = 0;
643 int update_players_from_server(void)
650 while ((rc = grabPacket(sock, socketset, &pkt)) != 0) {
652 printf("CLIENT: Lost connection.\n");
653 pkt.cmd = NETCMD_BYE;
654 pkt.arg = client_player_num;
657 if (pkt.cmd == NETCMD_BYE) {
658 if (pkt.arg == client_player_num) {
659 SDLNet_FreeSocketSet(socketset);
660 SDLNet_TCP_Close(sock);
665 player[pkt.arg].enabled = 0;
667 } else if (pkt.cmd == NETCMD_MOVE) {
668 processMovePacket(&pkt);
669 } else if (pkt.cmd == NETCMD_ALIVE) {
670 processAlivePacket(&pkt);
671 } else if (pkt.cmd == NETCMD_POSITION) {
672 processPositionPacket(&pkt);
673 } else if (pkt.cmd == NETCMD_KILL) {
674 processKillPacket(&pkt);
676 printf("CLIENT: Got an unknown packet: 0x%lX.\n", pkt.cmd);
684 void serverSendAlive(int playerid)
689 pkt.cmd = NETCMD_ALIVE;
691 pkt.arg2 = player[playerid].x;
692 pkt.arg3 = player[playerid].y;
693 sendPacketToAll(&pkt);
698 void serverSendKillPacket(int killer, int victim)
703 pkt.cmd = NETCMD_KILL;
706 pkt.arg3 = player[victim].x;
707 pkt.arg4 = player[victim].y;
708 processKillPacket(&pkt);
711 sendPacketToAll(&pkt);
717 void update_players_from_clients(void)
725 while ((playerid = serverRecvPacket(&pkt)) >= 0) {
726 if (pkt.cmd == NETCMD_BYE) {
727 pkt.arg = playerid; /* just in case. */
728 sendPacketToAll(&pkt);
729 player[playerid].enabled = 0;
730 SDLNet_FreeSocketSet(net_info[playerid].socketset);
731 SDLNet_TCP_Close(net_info[playerid].sock);
732 } else if (pkt.cmd == NETCMD_POSITION) {
733 pkt.arg = playerid; /* just in case. */
734 processPositionPacket(&pkt);
735 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
740 } else if (pkt.cmd == NETCMD_MOVE) {
741 pkt.arg = playerid; /* just in case. */
743 pkt.arg3 = player[playerid].x;
744 pkt.arg4 = player[playerid].y;
746 processMovePacket(&pkt);
747 sendPacketToAll(&pkt);
749 printf("SERVER: Got unknown packet (0x%lX).\n", pkt.cmd);
755 void init_server(const char *netarg)
760 int wait_for_clients = ((netarg == NULL) ? 0 : atoi(netarg));
763 /** assign player number zero as default for the server */
764 if(-1 == client_player_num)
765 client_player_num = 0;
767 if ((wait_for_clients >= JNB_MAX_PLAYERS) || (wait_for_clients < 0)) {
768 printf("SERVER: Waiting for bogus client count (%d).\n", wait_for_clients);
772 if (SDLNet_Init() < 0) {
777 SDLNet_ResolveHost(&addr, NULL, JNB_INETPORT);
778 ipstr = SDLNet_ResolveIP(&addr);
779 SDLNet_ResolveHost(&addr, ipstr, JNB_INETPORT);
780 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);
781 net_info[client_player_num].addr = addr;
783 addr.host = INADDR_ANY;
784 sock = SDLNet_TCP_Open(&addr);
786 fprintf(stderr, "SERVER: SDLNet_TCP_Open(): %s\n", SDLNet_GetError());
790 player[client_player_num].enabled = 1;
792 printf("SERVER: waiting for (%d) clients...\n", wait_for_clients);
794 socketset = SDLNet_AllocSocketSet(JNB_MAX_PLAYERS + 1);
795 SDLNet_TCP_AddSocket(socketset, sock);
797 while (wait_for_clients > 0)
799 char buf[NETPKTBUFSIZE];
805 /* Wait for events */
806 SDLNet_CheckSockets(socketset, ~0);
807 if ( SDLNet_SocketReady(sock) ) {
808 s = SDLNet_TCP_Accept(sock);
812 fprintf(stderr, "SERVER: SDLNet_TCP_Accept(): %s", SDLNet_GetError());
813 SDLNet_TCP_Close(sock);
819 br = SDLNet_TCP_Recv(s, buf, NETPKTBUFSIZE);
821 fprintf(stderr, "SERVER: SDLNet_TCP_Recv(): %s\n", SDLNet_GetError());
823 SDLNet_TCP_Close(sock);
827 from = SDLNet_TCP_GetPeerAddress(s);
828 ipstr = SDLNet_ResolveIP(from);
829 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);
831 if (br != NETPKTBUFSIZE) {
832 printf("SERVER: Bogus packet.\n");
836 bufToPacket(buf, &pkt);
837 if (pkt.cmd != NETCMD_HELLO) {
838 printf("SERVER: Bogus packet.\n");
842 printf("SERVER: Client claims to be player #%ld.\n", pkt.arg);
846 for(i=0; i!=JNB_MAX_PLAYERS; ++i) {
847 if(!player[i].enabled) {
848 printf("SERVER: assigning %d as player number\n", i);
855 if ((pkt.arg>=JNB_MAX_PLAYERS)||(pkt.arg<0)) {
856 printf("SERVER: (that's an invalid player number.)\n");
857 } else if (player[pkt.arg].enabled) {
858 printf("SERVER: (that player number is already taken.)\n");
864 printf("SERVER: Forbidding connection.\n");
865 pkt.cmd = NETCMD_NACK;
866 sendPacketToSock(s, &pkt);
869 player[pkt.arg].enabled = 1;
870 net_info[pkt.arg].sock = s;
871 net_info[pkt.arg].addr = *from;
872 net_info[pkt.arg].socketset = SDLNet_AllocSocketSet(1);
873 SDLNet_TCP_AddSocket(net_info[pkt.arg].socketset, net_info[pkt.arg].sock);
875 printf("SERVER: Granting connection. (%d) to go.\n", wait_for_clients);
876 pkt.cmd = NETCMD_ACK;
877 sendPacket(pkt.arg, &pkt);
881 SDLNet_TCP_Close(sock); /* done with the listen socket. */
882 SDLNet_FreeSocketSet(socketset);
886 printf("SERVER: Got all our connections. Greenlighting clients...\n");
888 pkt.cmd = NETCMD_GREENLIGHT;
890 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
891 if (player[i].enabled) {
895 sendPacketToAll(&pkt);
899 void connect_to_server(char *netarg)
902 char buf[NETPKTBUFSIZE];
908 if (netarg == NULL) {
909 printf("CLIENT: Need to specify host to connect to.\n");
913 if (SDLNet_Init() < 0) {
918 SDLNet_ResolveHost(&addr, NULL, JNB_INETPORT);
919 ipstr = SDLNet_ResolveIP(&addr);
920 SDLNet_ResolveHost(&addr, ipstr, JNB_INETPORT);
921 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);
923 if (SDLNet_ResolveHost(&hent, netarg, JNB_INETPORT) < 0) {
924 fprintf(stderr, "CLIENT: couldn't find host: %s\n", SDLNet_GetError());
928 sock = SDLNet_TCP_Open(&hent);
930 fprintf(stderr, "CLIENT: SDLNet_TCP_Open(): %s\n", SDLNet_GetError());
934 socketset = SDLNet_AllocSocketSet(1);
935 SDLNet_TCP_AddSocket(socketset, sock);
937 printf("CLIENT: connected to %s...\n", SDLNet_ResolveIP(&hent));
939 printf("CLIENT: Sending HELLO packet...\n");
940 pkt.cmd = NETCMD_HELLO;
941 pkt.arg = client_player_num;
942 sendPacketToSock(sock, &pkt);
944 printf("CLIENT: Waiting for ACK from server...\n");
946 br = SDLNet_TCP_Recv(sock, buf, NETPKTBUFSIZE);
948 fprintf(stderr, "CLIENT: recv(): %s\n", SDLNet_GetError());
949 SDLNet_FreeSocketSet(socketset);
950 SDLNet_TCP_Close(sock);
954 if (br != NETPKTBUFSIZE) {
955 printf("CLIENT: Bogus packet size (%d of %d). FIXME.\n", br, NETPKTBUFSIZE);
956 SDLNet_FreeSocketSet(socketset);
957 SDLNet_TCP_Close(sock);
961 bufToPacket(buf, &pkt);
963 if (pkt.cmd == NETCMD_NACK) {
964 printf("CLIENT: Server forbid us from playing.\n");
965 SDLNet_FreeSocketSet(socketset);
966 SDLNet_TCP_Close(sock);
970 if (pkt.cmd != NETCMD_ACK) {
971 printf("CLIENT: Unexpected packet (cmd=0x%lX).\n", pkt.cmd);
972 SDLNet_FreeSocketSet(socketset);
973 SDLNet_TCP_Close(sock);
977 client_player_num = pkt.arg;
978 player[client_player_num].enabled = 1;
979 net_info[client_player_num].addr = addr;
980 printf("CLIENT: Server accepted our connection.\n");
982 wait_for_greenlight();
987 static void flip_pixels(unsigned char *pixels)
993 for (y = 0; y < JNB_HEIGHT; y++) {
994 for (x = 0; x < (352/2); x++) {
995 temp = pixels[y*JNB_WIDTH+x];
996 pixels[y*JNB_WIDTH+x] = pixels[y*JNB_WIDTH+(352-x)-1];
997 pixels[y*JNB_WIDTH+(352-x)-1] = temp;
1003 void get_closest_player_to_point(int x,int y,int *dist,int *closest_player)
1009 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1010 if (player[c1].enabled == 1) {
1011 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)));
1012 if (cur_dist < *dist) {
1013 *closest_player = c1;
1021 static void update_flies(int update_count)
1024 int closest_player = 0, dist;
1027 /* get center of fly swarm */
1029 for (c1 = 0; c1 < NUM_FLIES; c1++) {
1036 if (update_count == 1) {
1037 /* get closest player to fly swarm */
1038 get_closest_player_to_point(s1, s2, &dist, &closest_player);
1039 /* update fly swarm sound */
1043 dj_set_sfx_channel_volume(4, (char)(s3));
1046 for (c1 = 0; c1 < NUM_FLIES; c1++) {
1047 /* get closest player to fly */
1048 get_closest_player_to_point(flies[c1].x, flies[c1].y, &dist, &closest_player);
1049 flies[c1].old_x = flies[c1].x;
1050 flies[c1].old_y = flies[c1].y;
1052 if ((s1 - flies[c1].x) > 30)
1054 else if ((s1 - flies[c1].x) < -30)
1057 if (((player[closest_player].x >> 16) + 8) > flies[c1].x) {
1058 if (lord_of_the_flies == 0)
1063 if (lord_of_the_flies == 0)
1069 s4 = rnd(3) - 1 + s3;
1070 if ((flies[c1].x + s4) < 16)
1072 if ((flies[c1].x + s4) > 351)
1074 if (GET_BAN_MAP_XY(flies[c1].x + s4, flies[c1].y) != BAN_VOID)
1078 if ((s2 - flies[c1].y) > 30)
1080 else if ((s2 - flies[c1].y) < -30)
1083 if (((player[closest_player].y >> 16) + 8) > flies[c1].y) {
1084 if (lord_of_the_flies == 0)
1089 if (lord_of_the_flies == 0)
1095 s4 = rnd(3) - 1 + s3;
1096 if ((flies[c1].y + s4) < 0)
1098 if ((flies[c1].y + s4) > 239)
1100 if (GET_BAN_MAP_XY(flies[c1].x, flies[c1].y + s4) != BAN_VOID)
1107 static void player_kill(int c1, int c2)
1109 if (player[c1].y_add >= 0) {
1111 serverSendKillPacket(c1, c2);
1113 if (player[c2].y_add < 0)
1114 player[c2].y_add = 0;
1119 static void check_cheats(void)
1121 if (strncmp(last_keys, "kcitsogop", strlen("kcitsogop")) == 0) {
1125 if (strncmp(last_keys, "ecapsniseinnub", strlen("ecapsniseinnub")) == 0) {
1126 bunnies_in_space ^= 1;
1129 if (strncmp(last_keys, "kcaptej", strlen("kcaptej")) == 0) {
1133 if (strncmp(last_keys, "seilfehtfodrol", strlen("seilfehtfodrol")) == 0) {
1134 lord_of_the_flies ^= 1;
1137 if (strncmp(last_keys, "retawnahtrekcihtsidoolb", strlen("retawnahtrekcihtsidoolb")) == 0) {
1139 63,32,32,53,17,17,42, 7,
1140 7,28, 0, 0,24, 0, 0,19,
1141 0, 0,12, 0, 0, 7, 0, 0
1144 63,63,63,40,53,62,19,42,
1145 60, 0,33,60, 3,32,46, 3,
1146 26,33, 3,19,21, 1, 8, 8
1150 blood_is_thicker_than_water ^= 1;
1151 if (blood_is_thicker_than_water == 1) {
1152 for (i=0; i<32; i++)
1153 pal[432+i] = blood[i];
1155 for (i=0; i<32; i++)
1156 pal[432+i] = water[i];
1158 register_background(background_pic, pal);
1159 recalculate_gob(&object_gobs, pal);
1165 static void collision_check(void)
1167 int c1 = 0, c2 = 0, c3 = 0;
1170 /* collision check */
1171 for (c3 = 0; c3 < 6; c3++) {
1175 } else if (c3 == 1) {
1178 } else if (c3 == 2) {
1181 } else if (c3 == 3) {
1184 } else if (c3 == 4) {
1187 } else if (c3 == 5) {
1191 if (player[c1].enabled == 1 && player[c2].enabled == 1) {
1192 if (labs(player[c1].x - player[c2].x) < (12L << 16) && labs(player[c1].y - player[c2].y) < (12L << 16)) {
1193 if ((labs(player[c1].y - player[c2].y) >> 16) > 5) {
1194 if (player[c1].y < player[c2].y) {
1200 if (player[c1].x < player[c2].x) {
1201 if (player[c1].x_add > 0)
1202 player[c1].x = player[c2].x - (12L << 16);
1203 else if (player[c2].x_add < 0)
1204 player[c2].x = player[c1].x + (12L << 16);
1206 player[c1].x -= player[c1].x_add;
1207 player[c2].x -= player[c2].x_add;
1209 l1 = player[c2].x_add;
1210 player[c2].x_add = player[c1].x_add;
1211 player[c1].x_add = l1;
1212 if (player[c1].x_add > 0)
1213 player[c1].x_add = -player[c1].x_add;
1214 if (player[c2].x_add < 0)
1215 player[c2].x_add = -player[c2].x_add;
1217 if (player[c1].x_add > 0)
1218 player[c2].x = player[c1].x - (12L << 16);
1219 else if (player[c2].x_add < 0)
1220 player[c1].x = player[c2].x + (12L << 16);
1222 player[c1].x -= player[c1].x_add;
1223 player[c2].x -= player[c2].x_add;
1225 l1 = player[c2].x_add;
1226 player[c2].x_add = player[c1].x_add;
1227 player[c1].x_add = l1;
1228 if (player[c1].x_add < 0)
1229 player[c1].x_add = -player[c1].x_add;
1230 if (player[c2].x_add > 0)
1231 player[c2].x_add = -player[c2].x_add;
1239 static void game_loop(void) {
1240 int mod_vol, sfx_vol;
1241 int update_count = 1;
1242 int end_loop_flag = 0;
1244 int update_palette = 0;
1245 int mod_fade_direction;
1248 mod_vol = sfx_vol = 0;
1249 mod_fade_direction = 1;
1250 dj_ready_mod(MOD_GAME);
1251 dj_set_mod_volume((char)mod_vol);
1252 dj_set_sfx_volume((char)mod_vol);
1258 while (update_count) {
1260 if (key_pressed(1) == 1) {
1264 serverTellEveryoneGoodbye();
1266 tellServerGoodbye();
1271 memset(pal, 0, 768);
1272 mod_fade_direction = 0;
1280 update_players_from_clients();
1282 if (!update_players_from_server()) {
1283 break; /* got a BYE packet */
1297 main_info.page_info[main_info.draw_page].num_pobs = 0;
1298 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
1299 if (player[i].enabled == 1)
1300 main_info.page_info[main_info.draw_page].num_pobs++;
1307 if (flies_enabled) {
1308 update_flies(update_count);
1313 if (update_count == 1) {
1316 for (i = 0, c2 = 0; i < JNB_MAX_PLAYERS; i++) {
1317 if (player[i].enabled == 1) {
1318 main_info.page_info[main_info.draw_page].pobs[c2].x = player[i].x >> 16;
1319 main_info.page_info[main_info.draw_page].pobs[c2].y = player[i].y >> 16;
1320 main_info.page_info[main_info.draw_page].pobs[c2].image = player[i].image + i * 18;
1321 main_info.page_info[main_info.draw_page].pobs[c2].pob_data = &rabbit_gobs;
1328 draw_pobs(main_info.draw_page);
1333 draw_flies(main_info.draw_page);
1338 if (mod_fade_direction == 1) {
1341 dj_set_mod_volume((char)mod_vol);
1345 dj_set_sfx_volume((char)sfx_vol);
1350 dj_set_mod_volume((char)mod_vol);
1354 dj_set_sfx_volume((char)sfx_vol);
1359 for (i = 0; i < 768; i++) {
1360 if (cur_pal[i] < pal[i]) {
1363 } else if (cur_pal[i] > pal[i]) {
1370 if (fade_flag == 0 && end_loop_flag == 1)
1373 if (update_count == 1) {
1374 if (update_palette == 1) {
1375 setpalette(0, 256, cur_pal);
1379 main_info.draw_page ^= 1;
1380 main_info.view_page ^= 1;
1382 flippage(main_info.view_page);
1389 redraw_flies_background(main_info.draw_page);
1391 redraw_pob_backgrounds(main_info.draw_page);
1393 draw_leftovers(main_info.draw_page);
1403 if ( (player[client_player_num].dead_flag == 0) &&
1405 (player[client_player_num].action_left) ||
1406 (player[client_player_num].action_right) ||
1407 (player[client_player_num].action_up) ||
1408 (player[client_player_num].jump_ready == 0)
1411 tellServerNewPosition();
1416 update_count = intr_sysupdate();
1420 if ((server_said_bye) || ((fade_flag == 0) && (end_loop_flag == 1)))
1424 if ((fade_flag == 0) && (end_loop_flag == 1))
1430 static int menu_loop(void)
1432 unsigned char *handle;
1437 for(c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) // reset player values
1448 if (key_pressed(1) == 1) {
1451 if (init_level(0, pal) != 0) {
1456 memset(cur_pal, 0, 768);
1457 setpalette(0, 256, cur_pal);
1459 recalculate_gob(&rabbit_gobs, pal);
1460 recalculate_gob(&object_gobs, pal);
1461 recalculate_gob(&number_gobs, pal);
1464 register_background(background_pic, pal);
1467 if (flies_enabled) {
1471 for (c1 = 0; c1 < NUM_FLIES; c1++) {
1473 flies[c1].x = s1 + rnd(101) - 50;
1474 flies[c1].y = s2 + rnd(101) - 50;
1475 if (GET_BAN_MAP_XY(flies[c1].x, flies[c1].y) == BAN_VOID)
1478 flies[c1].back_defined[0] = 0;
1479 flies[c1].back_defined[1] = 0;
1484 dj_play_sfx(SFX_FLY, SFX_FLY_FREQ, 0, 0, 0, 4);
1488 lord_of_the_flies = bunnies_in_space = jetpack = pogostick = blood_is_thicker_than_water = 0;
1489 main_info.page_info[0].num_pobs = 0;
1490 main_info.page_info[1].num_pobs = 0;
1491 main_info.view_page = 0;
1492 main_info.draw_page = 1;
1499 serverTellEveryoneGoodbye();
1500 SDLNet_TCP_Close(sock);
1503 if (!server_said_bye) {
1504 tellServerGoodbye();
1507 SDLNet_TCP_Close(sock);
1513 main_info.view_page = 0;
1514 main_info.draw_page = 1;
1516 dj_stop_sfx_channel(4);
1520 memset(mask_pic, 0, JNB_WIDTH*JNB_HEIGHT);
1521 register_mask(mask_pic);
1523 register_background(NULL, NULL);
1527 put_text(main_info.view_page, 100, 50, "DOTT", 2);
1528 put_text(main_info.view_page, 160, 50, "JIFFY", 2);
1529 put_text(main_info.view_page, 220, 50, "FIZZ", 2);
1530 put_text(main_info.view_page, 280, 50, "MIJJI", 2);
1531 put_text(main_info.view_page, 40, 80, "DOTT", 2);
1532 put_text(main_info.view_page, 40, 110, "JIFFY", 2);
1533 put_text(main_info.view_page, 40, 140, "FIZZ", 2);
1534 put_text(main_info.view_page, 40, 170, "MIJJI", 2);
1536 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1539 for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++) {
1541 sprintf(str1, "%d", player[c1].bumped[c2]);
1542 put_text(main_info.view_page, 100 + c2 * 60, 80 + c1 * 30, str1, 2);
1544 put_text(main_info.view_page, 100 + c2 * 60, 80 + c1 * 30, "-", 2);
1546 sprintf(str1, "%d", player[c1].bumps);
1547 put_text(main_info.view_page, 350, 80 + c1 * 30, str1, 2);
1550 put_text(main_info.view_page, 200, 230, "Press ESC to continue", 2);
1554 flippage(main_info.view_page);
1556 if ((handle = dat_open("menu.pcx")) == 0) {
1557 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
1560 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
1561 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
1566 for (c1 = 0; c1 < 16; c1++) {
1567 pal[(240 + c1) * 3 + 0] = c1 << 2;
1568 pal[(240 + c1) * 3 + 1] = c1 << 2;
1569 pal[(240 + c1) * 3 + 2] = c1 << 2;
1572 memset(cur_pal, 0, 768);
1574 setpalette(0, 256, cur_pal);
1577 dj_ready_mod(MOD_SCORES);
1578 dj_set_mod_volume((char)mod_vol);
1582 while (key_pressed(1) == 0) {
1585 dj_set_mod_volume((char)mod_vol);
1586 for (c1 = 0; c1 < 768; c1++) {
1587 if (cur_pal[c1] < pal[c1])
1593 setpalette(0, 256, cur_pal);
1594 flippage(main_info.view_page);
1596 while (key_pressed(1) == 1) {
1601 memset(pal, 0, 768);
1603 while (mod_vol > 0) {
1605 dj_set_mod_volume((char)mod_vol);
1606 for (c1 = 0; c1 < 768; c1++) {
1607 if (cur_pal[c1] > pal[c1])
1612 setpalette(0, 256, cur_pal);
1613 flippage(main_info.view_page);
1616 fillpalette(0, 0, 0);
1622 return 0; /* don't go back to menu if in net game. */
1627 int main(int argc, char *argv[])
1631 if (init_program(argc, argv, pal) != 0)
1634 if (main_info.fireworks == 1) {
1639 result = menu_loop();
1647 static void player_action_left(int c1)
1650 int below_left, below, below_right;
1652 s1 = (player[c1].x >> 16);
1653 s2 = (player[c1].y >> 16);
1654 below_left = GET_BAN_MAP_XY(s1, s2 + 16);
1655 below = GET_BAN_MAP_XY(s1 + 8, s2 + 16);
1656 below_right = GET_BAN_MAP_XY(s1 + 15, s2 + 16);
1658 if (below == BAN_ICE) {
1659 if (player[c1].x_add > 0)
1660 player[c1].x_add -= 1024;
1662 player[c1].x_add -= 768;
1663 } else if ((below_left != BAN_SOLID && below_right == BAN_ICE) || (below_left == BAN_ICE && below_right != BAN_SOLID)) {
1664 if (player[c1].x_add > 0)
1665 player[c1].x_add -= 1024;
1667 player[c1].x_add -= 768;
1669 if (player[c1].x_add > 0) {
1670 player[c1].x_add -= 16384;
1671 if (player[c1].x_add > -98304L && player[c1].in_water == 0 && below == BAN_SOLID)
1672 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);
1674 player[c1].x_add -= 12288;
1676 if (player[c1].x_add < -98304L)
1677 player[c1].x_add = -98304L;
1678 player[c1].direction = 1;
1679 if (player[c1].anim == 0) {
1680 player[c1].anim = 1;
1681 player[c1].frame = 0;
1682 player[c1].frame_tick = 0;
1683 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1688 static void player_action_right(int c1)
1691 int below_left, below, below_right;
1693 s1 = (player[c1].x >> 16);
1694 s2 = (player[c1].y >> 16);
1695 below_left = GET_BAN_MAP_XY(s1, s2 + 16);
1696 below = GET_BAN_MAP_XY(s1 + 8, s2 + 16);
1697 below_right = GET_BAN_MAP_XY(s1 + 15, s2 + 16);
1699 if (below == BAN_ICE) {
1700 if (player[c1].x_add < 0)
1701 player[c1].x_add += 1024;
1703 player[c1].x_add += 768;
1704 } else if ((below_left != BAN_SOLID && below_right == BAN_ICE) || (below_left == BAN_ICE && below_right != BAN_SOLID)) {
1705 if (player[c1].x_add > 0)
1706 player[c1].x_add += 1024;
1708 player[c1].x_add += 768;
1710 if (player[c1].x_add < 0) {
1711 player[c1].x_add += 16384;
1712 if (player[c1].x_add < 98304L && player[c1].in_water == 0 && below == BAN_SOLID)
1713 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);
1715 player[c1].x_add += 12288;
1717 if (player[c1].x_add > 98304L)
1718 player[c1].x_add = 98304L;
1719 player[c1].direction = 0;
1720 if (player[c1].anim == 0) {
1721 player[c1].anim = 1;
1722 player[c1].frame = 0;
1723 player[c1].frame_tick = 0;
1724 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1728 int map_tile(int pos_x, int pos_y)
1735 if(pos_x < 0 || pos_x >= 17 || pos_y < 0 || pos_y >= 22)
1738 tile = ban_map[pos_y][pos_x];
1746 int cur_posx, cur_posy, tar_posx, tar_posy;
1747 int players_distance;
1748 player_t* target = NULL;
1749 int nearest_distance = -1;
1751 for (i = 0; i < JNB_MAX_PLAYERS; i++)
1753 nearest_distance = -1;
1754 if(ai[i] && player[i].enabled) // this player is a computer
1755 { // get nearest target
1756 for (j = 0; j < JNB_MAX_PLAYERS; j++)
1760 if(i == j || !player[j].enabled)
1763 deltax = player[j].x - player[i].x;
1764 deltay = player[j].y - player[i].y;
1765 players_distance = deltax*deltax + deltay*deltay;
1767 if (players_distance < nearest_distance || nearest_distance == -1)
1769 target = &player[j];
1770 nearest_distance = players_distance;
1777 cur_posx = player[i].x >> 16;
1778 cur_posy = player[i].y >> 16;
1779 tar_posx = target->x >> 16;
1780 tar_posy = target->y >> 16;
1782 /** nearest player found, get him */
1783 /* here goes the artificial intelligence code */
1785 /* X-axis movement */
1786 if(tar_posx > cur_posx) // if true target is on the right side
1791 else // target on the left side
1797 if(cur_posy - tar_posy < 32 && cur_posy - tar_posy > 0 &&
1798 tar_posx - cur_posx < 32+8 && tar_posx - cur_posx > -32)
1803 else if(tar_posx - cur_posx < 4+8 && tar_posx - cur_posx > -4)
1804 { // makes the bunnies less "nervous"
1809 /* Y-axis movement */
1810 if(map_tile(cur_posx, cur_posy+16) != BAN_VOID &&
1811 ((i == 0 && key_pressed(KEY_PL1_JUMP)) ||
1812 (i == 1 && key_pressed(KEY_PL2_JUMP)) ||
1813 (i == 2 && key_pressed(KEY_PL3_JUMP)) ||
1814 (i == 3 && key_pressed(KEY_PL4_JUMP))))
1815 jm=0; // if we are on ground and jump key is being pressed,
1816 //first we have to release it or else we won't be able to jump more than once
1818 else if(map_tile(cur_posx, cur_posy-8) != BAN_VOID &&
1819 map_tile(cur_posx, cur_posy-8) != BAN_WATER)
1820 jm=0; // don't jump if there is something over it
1822 else if(map_tile(cur_posx-(lm*8)+(rm*16), cur_posy) != BAN_VOID &&
1823 map_tile(cur_posx-(lm*8)+(rm*16), cur_posy) != BAN_WATER &&
1824 cur_posx > 16 && cur_posx < 352-16-8) // obstacle, jump
1825 jm=1; // if there is something on the way, jump over it
1827 else if(((i == 0 && key_pressed(KEY_PL1_JUMP)) ||
1828 (i == 1 && key_pressed(KEY_PL2_JUMP)) ||
1829 (i == 2 && key_pressed(KEY_PL3_JUMP)) ||
1830 (i == 3 && key_pressed(KEY_PL4_JUMP))) &&
1831 (map_tile(cur_posx-(lm*8)+(rm*16), cur_posy+8) != BAN_VOID &&
1832 map_tile(cur_posx-(lm*8)+(rm*16), cur_posy+8) != BAN_WATER))
1833 jm=1; // this makes it possible to jump over 2 tiles
1835 else if(cur_posy - tar_posy < 32 && cur_posy - tar_posy > 0 &&
1836 tar_posx - cur_posx < 32+8 && tar_posx - cur_posx > -32) // don't jump - running away
1839 else if(tar_posy <= cur_posy) // target on the upper side
1841 else // target below
1844 /** Artificial intelligence done, now apply movements */
1873 addkey(key | 0x8000);
1880 key = KEY_PL1_RIGHT;
1882 key = KEY_PL2_RIGHT;
1884 key = KEY_PL3_RIGHT;
1886 key = KEY_PL4_RIGHT;
1895 key = KEY_PL1_RIGHT;
1897 key = KEY_PL2_RIGHT;
1899 key = KEY_PL3_RIGHT;
1901 key = KEY_PL4_RIGHT;
1904 addkey(key | 0x8000);
1935 addkey(key | 0x8000);
1942 #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)
1945 void steer_players(void)
1951 update_player_actions();
1953 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1955 if (player[c1].enabled == 1) {
1957 if (player[c1].dead_flag == 0) {
1959 if (player[c1].action_left && player[c1].action_right) {
1960 if (player[c1].direction == 0) {
1961 if (player[c1].action_right) {
1962 player_action_right(c1);
1965 if (player[c1].action_left) {
1966 player_action_left(c1);
1969 } else if (player[c1].action_left) {
1970 player_action_left(c1);
1971 } else if (player[c1].action_right) {
1972 player_action_right(c1);
1973 } else if ((!player[c1].action_left) && (!player[c1].action_right)) {
1974 int below_left, below, below_right;
1976 s1 = (player[c1].x >> 16);
1977 s2 = (player[c1].y >> 16);
1978 below_left = GET_BAN_MAP_XY(s1, s2 + 16);
1979 below = GET_BAN_MAP_XY(s1 + 8, s2 + 16);
1980 below_right = GET_BAN_MAP_XY(s1 + 15, s2 + 16);
1981 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)))) {
1982 if (player[c1].x_add < 0) {
1983 player[c1].x_add += 16384;
1984 if (player[c1].x_add > 0)
1985 player[c1].x_add = 0;
1987 player[c1].x_add -= 16384;
1988 if (player[c1].x_add < 0)
1989 player[c1].x_add = 0;
1991 if (player[c1].x_add != 0 && GET_BAN_MAP_XY((s1 + 8), (s2 + 16)) == BAN_SOLID)
1992 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);
1994 if (player[c1].anim == 1) {
1995 player[c1].anim = 0;
1996 player[c1].frame = 0;
1997 player[c1].frame_tick = 0;
1998 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2003 if (pogostick == 1 || (player[c1].jump_ready == 1 && player[c1].action_up)) {
2004 s1 = (player[c1].x >> 16);
2005 s2 = (player[c1].y >> 16);
2009 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) {
2010 player[c1].y_add = -280000L;
2011 player[c1].anim = 2;
2012 player[c1].frame = 0;
2013 player[c1].frame_tick = 0;
2014 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2015 player[c1].jump_ready = 0;
2016 player[c1].jump_abort = 1;
2018 dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
2020 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
2022 /* jump out of water */
2023 if (GET_BAN_MAP_IN_WATER(s1, s2)) {
2024 player[c1].y_add = -196608L;
2025 player[c1].in_water = 0;
2026 player[c1].anim = 2;
2027 player[c1].frame = 0;
2028 player[c1].frame_tick = 0;
2029 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2030 player[c1].jump_ready = 0;
2031 player[c1].jump_abort = 1;
2033 dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
2035 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
2038 /* fall down by gravity */
2039 if (pogostick == 0 && (!player[c1].action_up)) {
2040 player[c1].jump_ready = 1;
2041 if (player[c1].in_water == 0 && player[c1].y_add < 0 && player[c1].jump_abort == 1) {
2042 if (bunnies_in_space == 0)
2043 /* normal gravity */
2044 player[c1].y_add += 32768;
2047 player[c1].y_add += 16384;
2048 if (player[c1].y_add > 0)
2049 player[c1].y_add = 0;
2054 if (player[c1].action_up) {
2055 player[c1].y_add -= 16384;
2056 if (player[c1].y_add < -400000L)
2057 player[c1].y_add = -400000L;
2058 if (GET_BAN_MAP_IN_WATER(s1, s2))
2059 player[c1].in_water = 0;
2061 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);
2065 player[c1].x += player[c1].x_add;
2066 if ((player[c1].x >> 16) < 0) {
2068 player[c1].x_add = 0;
2070 if ((player[c1].x >> 16) + 15 > 351) {
2071 player[c1].x = 336L << 16;
2072 player[c1].x_add = 0;
2075 if (player[c1].y > 0) {
2076 s2 = (player[c1].y >> 16);
2078 /* check top line only */
2082 s1 = (player[c1].x >> 16);
2083 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) {
2084 player[c1].x = (((s1 + 16) & 0xfff0)) << 16;
2085 player[c1].x_add = 0;
2088 s1 = (player[c1].x >> 16);
2089 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) {
2090 player[c1].x = (((s1 + 16) & 0xfff0) - 16) << 16;
2091 player[c1].x_add = 0;
2095 player[c1].y += player[c1].y_add;
2097 s1 = (player[c1].x >> 16);
2098 s2 = (player[c1].y >> 16);
2099 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))) {
2100 player[c1].y = ((player[c1].y >> 16) & 0xfff0) << 16;
2101 player[c1].y_add = -400000L;
2102 player[c1].anim = 2;
2103 player[c1].frame = 0;
2104 player[c1].frame_tick = 0;
2105 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2106 player[c1].jump_ready = 0;
2107 player[c1].jump_abort = 0;
2108 for (c2 = 0; c2 < NUM_OBJECTS; c2++) {
2109 if (objects[c2].used == 1 && objects[c2].type == OBJ_SPRING) {
2110 if (GET_BAN_MAP_XY((s1 + 8), (s2 + 15)) == BAN_SPRING) {
2111 if ((objects[c2].x >> 20) == ((s1 + 8) >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
2112 objects[c2].frame = 0;
2113 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
2114 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
2118 if (GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SPRING) {
2119 if ((objects[c2].x >> 20) == (s1 >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
2120 objects[c2].frame = 0;
2121 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
2122 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
2125 } else if (GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SPRING) {
2126 if ((objects[c2].x >> 20) == ((s1 + 15) >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
2127 objects[c2].frame = 0;
2128 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
2129 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
2136 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
2138 s1 = (player[c1].x >> 16);
2139 s2 = (player[c1].y >> 16);
2142 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) {
2143 player[c1].y = (((s2 + 16) & 0xfff0)) << 16;
2144 player[c1].y_add = 0;
2145 player[c1].anim = 0;
2146 player[c1].frame = 0;
2147 player[c1].frame_tick = 0;
2148 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2150 s1 = (player[c1].x >> 16);
2151 s2 = (player[c1].y >> 16);
2154 if (GET_BAN_MAP_XY((s1 + 8), (s2 + 8)) == BAN_WATER) {
2155 if (player[c1].in_water == 0) {
2156 /* falling into water */
2157 player[c1].in_water = 1;
2158 player[c1].anim = 4;
2159 player[c1].frame = 0;
2160 player[c1].frame_tick = 0;
2161 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2162 if (player[c1].y_add >= 32768) {
2163 add_object(OBJ_SPLASH, (player[c1].x >> 16) + 8, ((player[c1].y >> 16) & 0xfff0) + 15, 0, 0, OBJ_ANIM_SPLASH, 0);
2164 if (blood_is_thicker_than_water == 0)
2165 dj_play_sfx(SFX_SPLASH, (unsigned short)(SFX_SPLASH_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
2167 dj_play_sfx(SFX_SPLASH, (unsigned short)(SFX_SPLASH_FREQ + rnd(2000) - 5000), 64, 0, 0, -1);
2170 /* slowly move up to water surface */
2171 player[c1].y_add -= 1536;
2172 if (player[c1].y_add < 0 && player[c1].anim != 5) {
2173 player[c1].anim = 5;
2174 player[c1].frame = 0;
2175 player[c1].frame_tick = 0;
2176 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2178 if (player[c1].y_add < -65536L)
2179 player[c1].y_add = -65536L;
2180 if (player[c1].y_add > 65535L)
2181 player[c1].y_add = 65535L;
2182 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) {
2183 player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16;
2184 player[c1].y_add = 0;
2186 } 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) {
2187 player[c1].in_water = 0;
2188 player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16;
2189 player[c1].y_add = 0;
2190 if (player[c1].anim != 0 && player[c1].anim != 1) {
2191 player[c1].anim = 0;
2192 player[c1].frame = 0;
2193 player[c1].frame_tick = 0;
2194 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2197 if (player[c1].in_water == 0) {
2198 if (bunnies_in_space == 0)
2199 player[c1].y_add += 12288;
2201 player[c1].y_add += 6144;
2202 if (player[c1].y_add > 327680L)
2203 player[c1].y_add = 327680L;
2205 player[c1].y = (player[c1].y & 0xffff0000) + 0x10000;
2206 player[c1].y_add = 0;
2208 player[c1].in_water = 0;
2210 if (player[c1].y_add > 36864 && player[c1].anim != 3 && player[c1].in_water == 0) {
2211 player[c1].anim = 3;
2212 player[c1].frame = 0;
2213 player[c1].frame_tick = 0;
2214 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2219 player[c1].frame_tick++;
2220 if (player[c1].frame_tick >= player_anims[player[c1].anim].frame[player[c1].frame].ticks) {
2222 if (player[c1].frame >= player_anims[player[c1].anim].num_frames) {
2223 if (player[c1].anim != 6)
2224 player[c1].frame = player_anims[player[c1].anim].restart_frame;
2226 position_player(c1);
2228 player[c1].frame_tick = 0;
2230 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2239 void position_player(int player_num)
2248 if (ban_map[s2][s1] == BAN_VOID && (ban_map[s2 + 1][s1] == BAN_SOLID || ban_map[s2 + 1][s1] == BAN_ICE))
2251 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
2252 if (c1 != player_num && player[c1].enabled == 1) {
2253 if (abs((s1 << 4) - (player[c1].x >> 16)) < 32 && abs((s2 << 4) - (player[c1].y >> 16)) < 32)
2257 if (c1 == JNB_MAX_PLAYERS) {
2258 player[player_num].x = (long) s1 << 20;
2259 player[player_num].y = (long) s2 << 20;
2260 player[player_num].x_add = player[player_num].y_add = 0;
2261 player[player_num].direction = 0;
2262 player[player_num].jump_ready = 1;
2263 player[player_num].in_water = 0;
2264 player[player_num].anim = 0;
2265 player[player_num].frame = 0;
2266 player[player_num].frame_tick = 0;
2267 player[player_num].image = player_anims[player[player_num].anim].frame[player[player_num].frame].image;
2272 serverSendAlive(player_num);
2274 player[player_num].dead_flag = 0;
2284 void add_object(int type, int x, int y, int x_add, int y_add, int anim, int frame)
2288 for (c1 = 0; c1 < NUM_OBJECTS; c1++) {
2289 if (objects[c1].used == 0) {
2290 objects[c1].used = 1;
2291 objects[c1].type = type;
2292 objects[c1].x = (long) x << 16;
2293 objects[c1].y = (long) y << 16;
2294 objects[c1].x_add = x_add;
2295 objects[c1].y_add = y_add;
2296 objects[c1].x_acc = 0;
2297 objects[c1].y_acc = 0;
2298 objects[c1].anim = anim;
2299 objects[c1].frame = frame;
2300 objects[c1].ticks = object_anims[anim].frame[frame].ticks;
2301 objects[c1].image = object_anims[anim].frame[frame].image;
2309 void update_objects(void)
2314 for (c1 = 0; c1 < NUM_OBJECTS; c1++) {
2315 if (objects[c1].used == 1) {
2316 switch (objects[c1].type) {
2318 objects[c1].ticks--;
2319 if (objects[c1].ticks <= 0) {
2320 objects[c1].frame++;
2321 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames) {
2322 objects[c1].frame--;
2323 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2325 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2326 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2329 if (objects[c1].used == 1)
2330 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2333 objects[c1].ticks--;
2334 if (objects[c1].ticks <= 0) {
2335 objects[c1].frame++;
2336 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2337 objects[c1].used = 0;
2339 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2340 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2343 if (objects[c1].used == 1)
2344 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2347 objects[c1].x += objects[c1].x_add;
2348 objects[c1].y += objects[c1].y_add;
2349 objects[c1].ticks--;
2350 if (objects[c1].ticks <= 0) {
2351 objects[c1].frame++;
2352 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2353 objects[c1].used = 0;
2355 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2356 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2359 if (objects[c1].used == 1)
2360 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2362 case OBJ_YEL_BUTFLY:
2363 case OBJ_PINK_BUTFLY:
2364 objects[c1].x_acc += rnd(128) - 64;
2365 if (objects[c1].x_acc < -1024)
2366 objects[c1].x_acc = -1024;
2367 if (objects[c1].x_acc > 1024)
2368 objects[c1].x_acc = 1024;
2369 objects[c1].x_add += objects[c1].x_acc;
2370 if (objects[c1].x_add < -32768)
2371 objects[c1].x_add = -32768;
2372 if (objects[c1].x_add > 32768)
2373 objects[c1].x_add = 32768;
2374 objects[c1].x += objects[c1].x_add;
2375 if ((objects[c1].x >> 16) < 16) {
2376 objects[c1].x = 16 << 16;
2377 objects[c1].x_add = -objects[c1].x_add >> 2;
2378 objects[c1].x_acc = 0;
2379 } else if ((objects[c1].x >> 16) > 350) {
2380 objects[c1].x = 350 << 16;
2381 objects[c1].x_add = -objects[c1].x_add >> 2;
2382 objects[c1].x_acc = 0;
2384 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0) {
2385 if (objects[c1].x_add < 0) {
2386 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2388 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2390 objects[c1].x_add = -objects[c1].x_add >> 2;
2391 objects[c1].x_acc = 0;
2393 objects[c1].y_acc += rnd(64) - 32;
2394 if (objects[c1].y_acc < -1024)
2395 objects[c1].y_acc = -1024;
2396 if (objects[c1].y_acc > 1024)
2397 objects[c1].y_acc = 1024;
2398 objects[c1].y_add += objects[c1].y_acc;
2399 if (objects[c1].y_add < -32768)
2400 objects[c1].y_add = -32768;
2401 if (objects[c1].y_add > 32768)
2402 objects[c1].y_add = 32768;
2403 objects[c1].y += objects[c1].y_add;
2404 if ((objects[c1].y >> 16) < 0) {
2406 objects[c1].y_add = -objects[c1].y_add >> 2;
2407 objects[c1].y_acc = 0;
2408 } else if ((objects[c1].y >> 16) > 255) {
2409 objects[c1].y = 255 << 16;
2410 objects[c1].y_add = -objects[c1].y_add >> 2;
2411 objects[c1].y_acc = 0;
2413 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0) {
2414 if (objects[c1].y_add < 0) {
2415 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2417 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2419 objects[c1].y_add = -objects[c1].y_add >> 2;
2420 objects[c1].y_acc = 0;
2422 if (objects[c1].type == OBJ_YEL_BUTFLY) {
2423 if (objects[c1].x_add < 0 && objects[c1].anim != OBJ_ANIM_YEL_BUTFLY_LEFT) {
2424 objects[c1].anim = OBJ_ANIM_YEL_BUTFLY_LEFT;
2425 objects[c1].frame = 0;
2426 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2427 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2428 } else if (objects[c1].x_add > 0 && objects[c1].anim != OBJ_ANIM_YEL_BUTFLY_RIGHT) {
2429 objects[c1].anim = OBJ_ANIM_YEL_BUTFLY_RIGHT;
2430 objects[c1].frame = 0;
2431 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2432 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2435 if (objects[c1].x_add < 0 && objects[c1].anim != OBJ_ANIM_PINK_BUTFLY_LEFT) {
2436 objects[c1].anim = OBJ_ANIM_PINK_BUTFLY_LEFT;
2437 objects[c1].frame = 0;
2438 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2439 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2440 } else if (objects[c1].x_add > 0 && objects[c1].anim != OBJ_ANIM_PINK_BUTFLY_RIGHT) {
2441 objects[c1].anim = OBJ_ANIM_PINK_BUTFLY_RIGHT;
2442 objects[c1].frame = 0;
2443 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2444 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2447 objects[c1].ticks--;
2448 if (objects[c1].ticks <= 0) {
2449 objects[c1].frame++;
2450 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2451 objects[c1].frame = object_anims[objects[c1].anim].restart_frame;
2453 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2454 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2457 if (objects[c1].used == 1)
2458 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2462 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 0);
2463 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 0) {
2464 objects[c1].y_add += 3072;
2465 if (objects[c1].y_add > 196608L)
2466 objects[c1].y_add = 196608L;
2467 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 2) {
2468 if (objects[c1].x_add < 0) {
2469 if (objects[c1].x_add < -65536L)
2470 objects[c1].x_add = -65536L;
2471 objects[c1].x_add += 1024;
2472 if (objects[c1].x_add > 0)
2473 objects[c1].x_add = 0;
2475 if (objects[c1].x_add > 65536L)
2476 objects[c1].x_add = 65536L;
2477 objects[c1].x_add -= 1024;
2478 if (objects[c1].x_add < 0)
2479 objects[c1].x_add = 0;
2481 objects[c1].y_add += 1024;
2482 if (objects[c1].y_add < -65536L)
2483 objects[c1].y_add = -65536L;
2484 if (objects[c1].y_add > 65536L)
2485 objects[c1].y_add = 65536L;
2487 objects[c1].x += objects[c1].x_add;
2488 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)) {
2489 if (objects[c1].x_add < 0) {
2490 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2491 objects[c1].x_add = -objects[c1].x_add >> 2;
2493 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2494 objects[c1].x_add = -objects[c1].x_add >> 2;
2497 objects[c1].y += objects[c1].y_add;
2498 if ((objects[c1].x >> 16) < -5 || (objects[c1].x >> 16) > 405 || (objects[c1].y >> 16) > 260)
2499 objects[c1].used = 0;
2500 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0)) {
2501 if (objects[c1].y_add < 0) {
2502 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 2) {
2503 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2504 objects[c1].x_add >>= 2;
2505 objects[c1].y_add = -objects[c1].y_add >> 2;
2508 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1) {
2509 if (objects[c1].y_add > 131072L) {
2510 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2511 objects[c1].x_add >>= 2;
2512 objects[c1].y_add = -objects[c1].y_add >> 2;
2514 objects[c1].used = 0;
2515 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3) {
2516 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2517 if (objects[c1].y_add > 131072L)
2518 objects[c1].y_add = -objects[c1].y_add >> 2;
2520 objects[c1].y_add = 0;
2524 if (objects[c1].x_add < 0 && objects[c1].x_add > -16384)
2525 objects[c1].x_add = -16384;
2526 if (objects[c1].x_add > 0 && objects[c1].x_add < 16384)
2527 objects[c1].x_add = 16384;
2528 if (objects[c1].used == 1) {
2529 s1 = (int)(atan2(objects[c1].y_add, objects[c1].x_add) * 4 / M_PI);
2536 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].frame + s1, &object_gobs);
2540 if (rnd(100) < 30) {
2541 if (objects[c1].frame == 76)
2542 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 1);
2543 else if (objects[c1].frame == 77)
2544 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 2);
2545 else if (objects[c1].frame == 78)
2546 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 3);
2548 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 0) {
2549 objects[c1].y_add += 3072;
2550 if (objects[c1].y_add > 196608L)
2551 objects[c1].y_add = 196608L;
2552 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 2) {
2553 if (objects[c1].x_add < 0) {
2554 if (objects[c1].x_add < -65536L)
2555 objects[c1].x_add = -65536L;
2556 objects[c1].x_add += 1024;
2557 if (objects[c1].x_add > 0)
2558 objects[c1].x_add = 0;
2560 if (objects[c1].x_add > 65536L)
2561 objects[c1].x_add = 65536L;
2562 objects[c1].x_add -= 1024;
2563 if (objects[c1].x_add < 0)
2564 objects[c1].x_add = 0;
2566 objects[c1].y_add += 1024;
2567 if (objects[c1].y_add < -65536L)
2568 objects[c1].y_add = -65536L;
2569 if (objects[c1].y_add > 65536L)
2570 objects[c1].y_add = 65536L;
2572 objects[c1].x += objects[c1].x_add;
2573 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)) {
2574 if (objects[c1].x_add < 0) {
2575 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2576 objects[c1].x_add = -objects[c1].x_add >> 2;
2578 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2579 objects[c1].x_add = -objects[c1].x_add >> 2;
2582 objects[c1].y += objects[c1].y_add;
2583 if ((objects[c1].x >> 16) < -5 || (objects[c1].x >> 16) > 405 || (objects[c1].y >> 16) > 260)
2584 objects[c1].used = 0;
2585 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0)) {
2586 if (objects[c1].y_add < 0) {
2587 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 2) {
2588 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2589 objects[c1].x_add >>= 2;
2590 objects[c1].y_add = -objects[c1].y_add >> 2;
2593 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1) {
2594 if (objects[c1].y_add > 131072L) {
2595 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2596 objects[c1].x_add >>= 2;
2597 objects[c1].y_add = -objects[c1].y_add >> 2;
2599 if (rnd(100) < 10) {
2601 add_leftovers(0, objects[c1].x >> 16, (objects[c1].y >> 16) + s1, objects[c1].frame, &object_gobs);
2602 add_leftovers(1, objects[c1].x >> 16, (objects[c1].y >> 16) + s1, objects[c1].frame, &object_gobs);
2604 objects[c1].used = 0;
2606 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3) {
2607 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2608 if (objects[c1].y_add > 131072L)
2609 objects[c1].y_add = -objects[c1].y_add >> 2;
2611 objects[c1].y_add = 0;
2615 if (objects[c1].x_add < 0 && objects[c1].x_add > -16384)
2616 objects[c1].x_add = -16384;
2617 if (objects[c1].x_add > 0 && objects[c1].x_add < 16384)
2618 objects[c1].x_add = 16384;
2619 if (objects[c1].used == 1)
2620 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].frame, &object_gobs);
2622 case OBJ_FLESH_TRACE:
2623 objects[c1].ticks--;
2624 if (objects[c1].ticks <= 0) {
2625 objects[c1].frame++;
2626 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2627 objects[c1].used = 0;
2629 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2630 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2633 if (objects[c1].used == 1)
2634 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2643 int add_pob(int page, int x, int y, int image, gob_t *pob_data)
2646 if (main_info.page_info[page].num_pobs >= NUM_POBS)
2649 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].x = x;
2650 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].y = y;
2651 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].image = image;
2652 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].pob_data = pob_data;
2653 main_info.page_info[page].num_pobs++;
2660 void draw_flies(int page)
2664 for (c2 = 0; c2 < NUM_FLIES; c2++) {
2665 flies[c2].back[main_info.draw_page] = get_pixel(main_info.draw_page, flies[c2].x, flies[c2].y);
2666 flies[c2].back_defined[main_info.draw_page] = 1;
2667 if (mask_pic[(flies[c2].y * JNB_WIDTH) + flies[c2].x] == 0)
2668 set_pixel(main_info.draw_page, flies[c2].x, flies[c2].y, 0);
2672 void draw_pobs(int page)
2679 for (c1 = main_info.page_info[page].num_pobs - 1; c1 >= 0; c1--) {
2680 main_info.page_info[page].pobs[c1].back_buf_ofs = back_buf_ofs;
2681 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);
2683 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;
2685 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);
2686 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);
2692 void redraw_flies_background(int page)
2696 for (c2 = NUM_FLIES - 1; c2 >= 0; c2--) {
2697 if (flies[c2].back_defined[page] == 1)
2698 set_pixel(page, flies[c2].old_draw_x, flies[c2].old_draw_y, flies[c2].back[page]);
2699 flies[c2].old_draw_x = flies[c2].x;
2700 flies[c2].old_draw_y = flies[c2].y;
2705 void redraw_pob_backgrounds(int page)
2709 for (c1 = 0; c1 < main_info.page_info[page].num_pobs; c1++)
2710 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);
2715 int add_leftovers(int page, int x, int y, int image, gob_t *pob_data)
2718 if (leftovers.page[page].num_pobs >= NUM_LEFTOVERS)
2721 leftovers.page[page].pobs[leftovers.page[page].num_pobs].x = x;
2722 leftovers.page[page].pobs[leftovers.page[page].num_pobs].y = y;
2723 leftovers.page[page].pobs[leftovers.page[page].num_pobs].image = image;
2724 leftovers.page[page].pobs[leftovers.page[page].num_pobs].pob_data = pob_data;
2725 leftovers.page[page].num_pobs++;
2732 void draw_leftovers(int page)
2736 for (c1 = leftovers.page[page].num_pobs - 1; c1 >= 0; c1--)
2737 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);
2739 leftovers.page[page].num_pobs = 0;
2744 int init_level(int level, char *pal)
2746 unsigned char *handle;
2750 if ((handle = dat_open("level.pcx")) == 0) {
2751 strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n");
2754 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
2755 strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n");
2759 flip_pixels(background_pic);
2760 if ((handle = dat_open("mask.pcx")) == 0) {
2761 strcpy(main_info.error_str, "Error loading 'mask.pcx', aborting...\n");
2764 if (read_pcx(handle, mask_pic, JNB_WIDTH*JNB_HEIGHT, 0) != 0) {
2765 strcpy(main_info.error_str, "Error loading 'mask.pcx', aborting...\n");
2769 flip_pixels(mask_pic);
2770 register_mask(mask_pic);
2772 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
2773 if (player[c1].enabled == 1) {
2774 player[c1].bumps = 0;
2775 for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++)
2776 player[c1].bumped[c2] = 0;
2777 position_player(c1);
2781 for (c1 = 0; c1 < NUM_OBJECTS; c1++)
2782 objects[c1].used = 0;
2784 for (c1 = 0; c1 < 16; c1++) {
2785 for (c2 = 0; c2 < 22; c2++) {
2786 if (ban_map[c1][c2] == BAN_SPRING)
2787 add_object(OBJ_SPRING, c2 << 4, c1 << 4, 0, 0, OBJ_ANIM_SPRING, 5);
2794 if (ban_map[s2][s1] == BAN_VOID) {
2795 add_object(OBJ_YEL_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2802 if (ban_map[s2][s1] == BAN_VOID) {
2803 add_object(OBJ_YEL_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2810 if (ban_map[s2][s1] == BAN_VOID) {
2811 add_object(OBJ_PINK_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2818 if (ban_map[s2][s1] == BAN_VOID) {
2819 add_object(OBJ_PINK_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2829 void deinit_level(void)
2837 #define PATH_MAX 1024
2843 unsigned char *datafile_buffer = NULL;
2845 static void preread_datafile(const char *fname)
2855 #ifdef BZLIB_SUPPORT
2860 #ifdef BZLIB_SUPPORT
2861 bzfilename = malloc(strlen(fname) + 5);
2862 strcpy(bzfilename, fname);
2863 strcat(bzfilename, ".bz2");
2864 bzf = BZ2_bzopen(bzfilename, "rb");
2874 if (bufpos >= bufsize) {
2875 bufsize += 1024 * 1024;
2876 datafile_buffer = (unsigned char *) realloc(datafile_buffer, bufsize);
2877 if (datafile_buffer == NULL) {
2878 perror("realloc()");
2883 br = BZ2_bzread(bzf, datafile_buffer + bufpos, bufsize - bufpos);
2885 fprintf(stderr, "gzread failed.\n");
2892 /* try to shrink buffer... */
2893 ptr = (unsigned char *) realloc(datafile_buffer, bufpos);
2895 datafile_buffer = ptr;
2901 /* drop through and try for an gzip compressed or uncompressed datafile... */
2905 gzfilename = malloc(strlen(fname) + 4);
2906 strcpy(gzfilename, fname);
2907 strcat(gzfilename, ".gz");
2908 gzf = gzopen(gzfilename, "rb");
2918 if (bufpos >= bufsize) {
2919 bufsize += 1024 * 1024;
2920 datafile_buffer = (unsigned char *) realloc(datafile_buffer, bufsize);
2921 if (datafile_buffer == NULL) {
2922 perror("realloc()");
2927 br = gzread(gzf, datafile_buffer + bufpos, bufsize - bufpos);
2929 fprintf(stderr, "gzread failed.\n");
2934 } while (!gzeof(gzf));
2936 /* try to shrink buffer... */
2937 ptr = (unsigned char *) realloc(datafile_buffer, bufpos);
2939 datafile_buffer = ptr;
2945 /* drop through and try for an uncompressed datafile... */
2948 fd = open(fname, O_RDONLY | O_BINARY);
2950 fprintf(stderr, "can't open %s:", fname);
2955 len = filelength(fd);
2956 datafile_buffer = (unsigned char *) malloc(len);
2957 if (datafile_buffer == NULL) {
2963 if (read(fd, datafile_buffer, len) != len) {
2973 int init_program(int argc, char *argv[], char *pal)
2975 char *netarg = NULL;
2976 unsigned char *handle = (unsigned char *) NULL;
2981 int player_anim_data[] = {
2982 1, 0, 0, 0x7fff, 0, 0, 0, 0, 0, 0,
2983 4, 0, 0, 4, 1, 4, 2, 4, 3, 4,
2984 1, 0, 4, 0x7fff, 0, 0, 0, 0, 0, 0,
2985 4, 2, 5, 8, 6, 10, 7, 3, 6, 3,
2986 1, 0, 6, 0x7fff, 0, 0, 0, 0, 0, 0,
2987 2, 1, 5, 8, 4, 0x7fff, 0, 0, 0, 0,
2988 1, 0, 8, 5, 0, 0, 0, 0, 0, 0
2992 memset(&net_info, 0, sizeof(net_info));
2996 if (__djgpp_nearptr_enable() == 0)
3002 if (hook_keyb_handler() != 0)
3005 memset(&main_info, 0, sizeof(main_info));
3007 strcpy(datfile_name, DATA_PATH);
3009 force2 = force3 = 0;
3012 for (c1 = 1; c1 < argc; c1++) {
3013 if (stricmp(argv[c1], "-nosound") == 0)
3014 main_info.no_sound = 1;
3015 else if (stricmp(argv[c1], "-musicnosound") == 0)
3016 main_info.music_no_sound = 1;
3017 else if (stricmp(argv[c1], "-nogore") == 0)
3018 main_info.no_gore = 1;
3019 else if (stricmp(argv[c1], "-noflies") == 0)
3021 else if (stricmp(argv[c1], "-nojoy") == 0)
3022 main_info.joy_enabled = 0;
3023 else if (stricmp(argv[c1], "-fireworks") == 0)
3024 main_info.fireworks = 1;
3026 else if (stricmp(argv[c1], "-fullscreen") == 0)
3029 else if (stricmp(argv[c1], "-scaleup") == 0)
3031 else if (stricmp(argv[c1], "-mirror") == 0)
3033 else if (stricmp(argv[c1], "-dat") == 0) {
3034 if (c1 < (argc - 1)) {
3037 if ((f = fopen(argv[c1 + 1], "rb")) != NULL) {
3039 strcpy(datfile_name, argv[c1 + 1]);
3042 } else if (stricmp(argv[c1], "-player") == 0) {
3043 if (c1 < (argc - 1)) {
3044 if (client_player_num < 0)
3045 client_player_num = atoi(argv[c1 + 1]);
3048 } else if (stricmp(argv[c1], "-server") == 0) {
3049 if (c1 < (argc - 1)) {
3052 netarg = argv[c1 + 1];
3054 } else if (stricmp(argv[c1], "-connect") == 0) {
3055 if (c1 < (argc - 1)) {
3058 netarg = argv[c1 + 1];
3061 } else if (stricmp(argv[c1], "-mouse") == 0) {
3062 if (c1 < (argc - 1)) {
3063 if (stricmp(argv[c1 + 1], "2") == 0)
3065 if (stricmp(argv[c1 + 1], "3") == 0)
3069 else if (strstr(argv[1],"-v")) {
3070 printf("jumpnbump %s compiled %s at %s with",JNB_VERSION,__DATE__,__TIME__);
3074 printf(" network support.\n");
3077 else if (strstr(argv[1],"-h")) {
3078 printf("Usage: jumpnbump [OPTION]...\n");
3080 printf(" -h this help\n");
3081 printf(" -v print version\n");
3082 printf(" -dat level.dat play a different level\n");
3084 printf(" -server playercount start as server waiting for players\n");
3085 printf(" -connect host connect to server\n");
3087 printf(" -player num set main player to num (0-3). Needed for networking\n");
3088 printf(" -fireworks screensaver mode\n");
3089 printf(" -fullscreen run in fullscreen mode\n");
3090 printf(" -nosound play without sound\n");
3091 printf(" -nogore play without blood\n");
3092 printf(" -noflies disable flies\n");
3093 printf(" -mirror play with mirrored level\n");
3094 printf(" -scaleup play with doubled resolution (800x512)\n");
3095 printf(" -musicnosound play with music but without sound\n");
3102 preread_datafile(datfile_name);
3105 /** It should not be necessary to assign a default player number here. The
3106 server assigns one in init_server, the client gets one assigned by the server,
3107 all provided the user didn't choose one on the commandline. */
3109 if (client_player_num < 0)
3110 client_player_num = 0;
3111 player[client_player_num].enabled = 1;
3115 main_info.pob_backbuf[0] = malloc(screen_pitch*screen_height);
3116 main_info.pob_backbuf[1] = malloc(screen_pitch*screen_height);
3118 for (c1 = 0; c1 < 7; c1++) {
3119 player_anims[c1].num_frames = player_anim_data[c1 * 10];
3120 player_anims[c1].restart_frame = player_anim_data[c1 * 10 + 1];
3121 for (c2 = 0; c2 < 4; c2++) {
3122 player_anims[c1].frame[c2].image = player_anim_data[c1 * 10 + c2 * 2 + 2];
3123 player_anims[c1].frame[c2].ticks = player_anim_data[c1 * 10 + c2 * 2 + 3];
3127 if ((handle = dat_open("menu.pcx")) == 0) {
3128 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
3131 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
3132 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
3136 if ((handle = dat_open("rabbit.gob")) == 0) {
3137 strcpy(main_info.error_str, "Error loading 'rabbit.gob', aborting...\n");
3140 if (register_gob(handle, &rabbit_gobs, dat_filelen("rabbit.gob"))) {
3145 if ((handle = dat_open("objects.gob")) == 0) {
3146 strcpy(main_info.error_str, "Error loading 'objects.gob', aborting...\n");
3149 if (register_gob(handle, &object_gobs, dat_filelen("objects.gob"))) {
3154 if ((handle = dat_open("font.gob")) == 0) {
3155 strcpy(main_info.error_str, "Error loading 'font.gob', aborting...\n");
3158 if (register_gob(handle, &font_gobs, dat_filelen("font.gob"))) {
3163 if ((handle = dat_open("numbers.gob")) == 0) {
3164 strcpy(main_info.error_str, "Error loading 'numbers.gob', aborting...\n");
3167 if (register_gob(handle, &number_gobs, dat_filelen("numbers.gob"))) {
3172 if (read_level() != 0) {
3173 strcpy(main_info.error_str, "Error loading 'levelmap.txt', aborting...\n");
3179 if (main_info.no_sound == 0) {
3181 dj_set_mixing_freq(20000);
3185 dj_set_num_sfx_channels(5);
3186 dj_set_sfx_volume(64);
3190 if ((handle = dat_open("jump.mod")) == 0) {
3191 strcpy(main_info.error_str, "Error loading 'jump.mod', aborting...\n");
3194 if (dj_load_mod(handle, 0, MOD_MENU) != 0) {
3195 strcpy(main_info.error_str, "Error loading 'jump.mod', aborting...\n");
3199 if ((handle = dat_open("bump.mod")) == 0) {
3200 strcpy(main_info.error_str, "Error loading 'bump.mod', aborting...\n");
3203 if (dj_load_mod(handle, 0, MOD_GAME) != 0) {
3204 strcpy(main_info.error_str, "Error loading 'bump.mod', aborting...\n");
3208 if ((handle = dat_open("scores.mod")) == 0) {
3209 strcpy(main_info.error_str, "Error loading 'scores.mod', aborting...\n");
3212 if (dj_load_mod(handle, 0, MOD_SCORES) != 0) {
3213 strcpy(main_info.error_str, "Error loading 'scores.mod', aborting...\n");
3217 if ((handle = dat_open("jump.smp")) == 0) {
3218 strcpy(main_info.error_str, "Error loading 'jump.smp', aborting...\n");
3221 if (dj_load_sfx(handle, 0, dat_filelen("jump.smp"), DJ_SFX_TYPE_SMP, SFX_JUMP) != 0) {
3222 strcpy(main_info.error_str, "Error loading 'jump.smp', aborting...\n");
3226 if ((handle = dat_open("death.smp")) == 0) {
3227 strcpy(main_info.error_str, "Error loading 'death.smp', aborting...\n");
3230 if (dj_load_sfx(handle, 0, dat_filelen("death.smp"), DJ_SFX_TYPE_SMP, SFX_DEATH) != 0) {
3231 strcpy(main_info.error_str, "Error loading 'death.smp', aborting...\n");
3235 if ((handle = dat_open("spring.smp")) == 0) {
3236 strcpy(main_info.error_str, "Error loading 'spring.smp', aborting...\n");
3239 if (dj_load_sfx(handle, 0, dat_filelen("spring.smp"), DJ_SFX_TYPE_SMP, SFX_SPRING) != 0) {
3240 strcpy(main_info.error_str, "Error loading 'spring.smp', aborting...\n");
3244 if ((handle = dat_open("splash.smp")) == 0) {
3245 strcpy(main_info.error_str, "Error loading 'splash.smp', aborting...\n");
3248 if (dj_load_sfx(handle, 0, dat_filelen("splash.smp"), DJ_SFX_TYPE_SMP, SFX_SPLASH) != 0) {
3249 strcpy(main_info.error_str, "Error loading 'splash.smp', aborting...\n");
3253 if ((handle = dat_open("fly.smp")) == 0) {
3254 strcpy(main_info.error_str, "Error loading 'fly.smp', aborting...\n");
3257 if (dj_load_sfx(handle, 0, dat_filelen("fly.smp"), DJ_SFX_TYPE_SMP, SFX_FLY) != 0) {
3258 strcpy(main_info.error_str, "Error loading 'fly.smp', aborting...\n");
3262 dj_get_sfx_settings(SFX_FLY, &fly);
3264 fly.default_freq = SFX_FLY_FREQ;
3267 fly.loop_length = fly.length;
3268 dj_set_sfx_settings(SFX_FLY, &fly);
3271 if ((background_pic = malloc(JNB_WIDTH*JNB_HEIGHT)) == NULL)
3273 if ((mask_pic = malloc(JNB_WIDTH*JNB_HEIGHT)) == NULL)
3275 memset(mask_pic, 0, JNB_WIDTH*JNB_HEIGHT);
3276 register_mask(mask_pic);
3279 for (c1 = 0; c1 < 16; c1++) {
3280 pal[(240 + c1) * 3 + 0] = c1 << 2;
3281 pal[(240 + c1) * 3 + 1] = c1 << 2;
3282 pal[(240 + c1) * 3 + 2] = c1 << 2;
3285 setpalette(0, 256, pal);
3289 recalculate_gob(&font_gobs, pal);
3291 if (main_info.joy_enabled == 1 && main_info.fireworks == 0) {
3293 put_text(0, 200, 40, "JOYSTICK CALIBRATION", 2);
3294 put_text(0, 200, 100, "Move the joystick to the", 2);
3295 put_text(0, 200, 115, "UPPER LEFT", 2);
3296 put_text(0, 200, 130, "and press button A", 2);
3297 put_text(0, 200, 200, "Or press ESC to use", 2);
3298 put_text(0, 200, 215, "previous settings", 2);
3299 if (calib_joy(0) != 0)
3302 register_background(NULL, NULL);
3304 main_info.view_page = 1;
3309 put_text(1, 200, 40, "JOYSTICK CALIBRATION", 2);
3310 put_text(1, 200, 100, "Move the joystick to the", 2);
3311 put_text(1, 200, 115, "LOWER RIGHT", 2);
3312 put_text(1, 200, 130, "and press button A", 2);
3313 put_text(1, 200, 200, "Or press ESC to use", 2);
3314 put_text(1, 200, 215, "previous settings", 2);
3315 if (calib_joy(1) != 0)
3318 register_background(NULL, NULL);
3323 put_text(0, 200, 40, "JOYSTICK CALIBRATION", 2);
3324 put_text(0, 200, 100, "Move the joystick to the", 2);
3325 put_text(0, 200, 115, "CENTER", 2);
3326 put_text(0, 200, 130, "and press button A", 2);
3327 put_text(0, 200, 200, "Or press ESC to use", 2);
3328 put_text(0, 200, 215, "previous settings", 2);
3329 if (calib_joy(2) != 0)
3332 if (joy.calib_data.x1 == joy.calib_data.x2)
3333 joy.calib_data.x1 -= 10;
3334 if (joy.calib_data.x3 == joy.calib_data.x2)
3335 joy.calib_data.x3 += 10;
3336 if (joy.calib_data.y1 == joy.calib_data.y2)
3337 joy.calib_data.y1 -= 10;
3338 if (joy.calib_data.y3 == joy.calib_data.y2)
3339 joy.calib_data.y3 += 10;
3344 if (load_flag == 1) {
3345 if ((handle = dat_open("calib.dat")) == 0) {
3346 strcpy(main_info.error_str, "Error loading 'calib.dat', aborting...\n");
3349 joy.calib_data.x1 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3350 joy.calib_data.x2 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3351 joy.calib_data.x3 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3352 joy.calib_data.y1 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3353 joy.calib_data.y2 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3354 joy.calib_data.y3 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3361 init_server(netarg);
3363 connect_to_server(netarg);
3372 void deinit_program(void)
3379 dj_free_mod(MOD_MENU);
3380 dj_free_mod(MOD_GAME);
3381 dj_free_sfx(SFX_DEATH);
3382 dj_free_sfx(SFX_SPRING);
3383 dj_free_sfx(SFX_SPLASH);
3386 if (background_pic != 0)
3387 free(background_pic);
3391 remove_keyb_handler();
3395 __dpmi_int(0x10, ®s);
3398 if (main_info.error_str[0] != 0) {
3399 printf(main_info.error_str);
3401 MessageBox(0, main_info.error_str, "Jump'n'Bump", 0);
3410 unsigned short rnd(unsigned short max)
3412 #if (RAND_MAX < 0x7fff)
3413 #error "rand returns too small values"
3414 #elif (RAND_MAX == 0x7fff)
3415 return (unsigned short)((rand()*2) % (int)max);
3417 return (unsigned short)(rand() % (int)max);
3422 int read_level(void)
3424 unsigned char *handle;
3428 if ((handle = dat_open("levelmap.txt")) == 0) {
3429 strcpy(main_info.error_str, "Error loading 'levelmap.txt', aborting...\n");
3433 for (c1 = 0; c1 < 16; c1++) {
3434 for (c2 = 0; c2 < 22; c2++) {
3436 chr = (int) *(handle++);
3437 if (chr >= '0' && chr <= '4')
3441 ban_map[c1][21-c2] = chr - '0';
3443 ban_map[c1][c2] = chr - '0';
3447 for (c2 = 0; c2 < 22; c2++)
3448 ban_map[16][c2] = BAN_SOLID;
3455 unsigned char *dat_open(char *file_name)
3463 if (datafile_buffer == NULL)
3466 memset(name, 0, sizeof(name));
3468 num = ( (datafile_buffer[0] << 0) +
3469 (datafile_buffer[1] << 8) +
3470 (datafile_buffer[2] << 16) +
3471 (datafile_buffer[3] << 24) );
3473 ptr = datafile_buffer + 4;
3475 for (c1 = 0; c1 < num; c1++) {
3477 memcpy(name, ptr, 12);
3480 if (strnicmp(name, file_name, strlen(file_name)) == 0) {
3481 ofs = ( (ptr[0] << 0) +
3486 return (datafile_buffer + ofs);
3495 int dat_filelen(char *file_name)
3503 memset(name, 0, sizeof(name));
3505 num = ( (datafile_buffer[0] << 0) +
3506 (datafile_buffer[1] << 8) +
3507 (datafile_buffer[2] << 16) +
3508 (datafile_buffer[3] << 24) );
3510 ptr = datafile_buffer + 4;
3512 for (c1 = 0; c1 < num; c1++) {
3514 memcpy(name, ptr, 12);
3517 if (strnicmp(name, file_name, strlen(file_name)) == 0) {
3520 len = ( (ptr[0] << 0) +
3534 void write_calib_data(void)
3542 if ((handle = fopen(datfile_name, "rb")) == NULL)
3544 len = filelength(fileno(handle));
3545 if ((mem = malloc(len)) == NULL)
3547 fread(mem, 1, len, handle);
3551 num = *(int *) (&mem[0]);
3552 for (c1 = 0; c1 < num; c1++) {
3553 if (strnicmp(&mem[ofs], "calib.dat", strlen("calib.dat")) == 0) {
3554 ofs = *(int *) (&mem[ofs + 12]);
3560 mem[ofs] = joy.calib_data.x1 & 0xff;
3561 mem[ofs + 1] = (joy.calib_data.x1 >> 8) & 0xff;
3562 mem[ofs + 2] = (joy.calib_data.x1 >> 16) & 0xff;
3563 mem[ofs + 3] = (joy.calib_data.x1 >> 24) & 0xff;
3564 mem[ofs + 4] = joy.calib_data.x2 & 0xff;
3565 mem[ofs + 5] = (joy.calib_data.x2 >> 8) & 0xff;
3566 mem[ofs + 6] = (joy.calib_data.x2 >> 16) & 0xff;
3567 mem[ofs + 7] = (joy.calib_data.x2 >> 24) & 0xff;
3568 mem[ofs + 8] = joy.calib_data.x3 & 0xff;
3569 mem[ofs + 9] = (joy.calib_data.x3 >> 8) & 0xff;
3570 mem[ofs + 10] = (joy.calib_data.x3 >> 16) & 0xff;
3571 mem[ofs + 11] = (joy.calib_data.x3 >> 24) & 0xff;
3572 mem[ofs + 12] = joy.calib_data.y1 & 0xff;
3573 mem[ofs + 13] = (joy.calib_data.y1 >> 8) & 0xff;
3574 mem[ofs + 14] = (joy.calib_data.y1 >> 16) & 0xff;
3575 mem[ofs + 15] = (joy.calib_data.y1 >> 24) & 0xff;
3576 mem[ofs + 16] = joy.calib_data.y2 & 0xff;
3577 mem[ofs + 17] = (joy.calib_data.y2 >> 8) & 0xff;
3578 mem[ofs + 18] = (joy.calib_data.y2 >> 16) & 0xff;
3579 mem[ofs + 19] = (joy.calib_data.y2 >> 24) & 0xff;
3580 mem[ofs + 20] = joy.calib_data.y3 & 0xff;
3581 mem[ofs + 21] = (joy.calib_data.y3 >> 8) & 0xff;
3582 mem[ofs + 22] = (joy.calib_data.y3 >> 16) & 0xff;
3583 mem[ofs + 23] = (joy.calib_data.y3 >> 24) & 0xff;
3585 if ((handle = fopen(datfile_name, "wb")) == NULL)
3587 fwrite(mem, 1, len, handle);