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 * Portions of this code are from the MPEG software simulation group
10 * idct implementation. This code will be replaced with a new
11 * implementation soon.
13 * This file is part of Jump'n'Bump.
15 * Jump'n'Bump is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * Jump'n'Bump is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 #define EAGAIN TRY_AGAIN
39 #define net_error WSAGetLastError()
44 #include <sys/types.h>
45 #include <sys/socket.h>
47 #include <netinet/in.h>
48 #include <arpa/inet.h>
52 #define net_error errno
57 #define M_PI 3.14159265358979323846
60 gob_t rabbit_gobs = { 0 };
61 gob_t font_gobs = { 0 };
62 gob_t object_gobs = { 0 };
63 gob_t number_gobs = { 0 };
65 main_info_t main_info;
66 player_t player[JNB_MAX_PLAYERS];
67 player_anim_t player_anims[7];
68 object_t objects[NUM_OBJECTS];
72 char datfile_name[2048];
78 unsigned int ban_map[17][22] = {
79 {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
80 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0},
81 {1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
82 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1},
83 {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
84 {1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
85 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1},
86 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
87 {1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
88 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 1},
89 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1},
90 {1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1},
91 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
92 {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
93 {2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0, 1, 3, 3, 3, 1, 1, 1},
94 {2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
95 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
105 } object_anims[8] = {
221 int flies_enabled = 1;
226 int old_draw_x, old_draw_y;
238 } pobs[NUM_LEFTOVERS];
242 int pogostick, bunnies_in_space, jetpack, lord_of_the_flies, blood_is_thicker_than_water;
246 int filelength(int handle)
250 if (fstat(handle, &buf) == -1) {
251 perror("filelength");
260 /* networking shite. */
262 int client_player_num = -1;
271 /*struct timeval last_timestamp;*/
272 struct sockaddr *addr;
276 NetInfo net_info[JNB_MAX_PLAYERS];
288 #define NETPKTBUFSIZE (4 + 4 + 4 + 4 + 4)
290 #define NETCMD_NACK (0xF00DF00D + 0)
291 #define NETCMD_ACK (0xF00DF00D + 1)
292 #define NETCMD_HELLO (0xF00DF00D + 2)
293 #define NETCMD_GREENLIGHT (0xF00DF00D + 3)
294 #define NETCMD_MOVE (0xF00DF00D + 4)
295 #define NETCMD_BYE (0xF00DF00D + 5)
296 #define NETCMD_POSITION (0xF00DF00D + 6)
297 #define NETCMD_ALIVE (0xF00DF00D + 7)
298 #define NETCMD_KILL (0xF00DF00D + 8)
302 void bufToPacket(const char *buf, NetPacket *pkt)
305 SDLNet_Write32(*((unsigned long *) (buf + 0)), pkt->cmd);
306 SDLNet_Write32(*((unsigned long *) (buf + 4)), pkt->arg);
307 SDLNet_Write32(*((unsigned long *) (buf + 8)), pkt->arg2);
308 SDLNet_Write32(*((unsigned long *) (buf + 12)), pkt->arg3);
309 SDLNet_Write32(*((unsigned long *) (buf + 16)), pkt->arg4);
311 pkt->cmd = ntohl(*((unsigned long *) (buf + 0)));
312 pkt->arg = (long) ntohl(*((unsigned long *) (buf + 4)));
313 pkt->arg2 = (long) ntohl(*((unsigned long *) (buf + 8)));
314 pkt->arg3 = (long) ntohl(*((unsigned long *) (buf + 12)));
315 pkt->arg4 = (long) ntohl(*((unsigned long *) (buf + 16)));
319 void packetToBuf(const NetPacket *pkt, char *buf)
322 *((unsigned long *) (buf + 0)) = SDLNet_Read32(pkt->cmd);
323 *((unsigned long *) (buf + 4)) = SDLNet_Read32((unsigned long) pkt->arg);
324 *((unsigned long *) (buf + 8)) = SDLNet_Read32((unsigned long) pkt->arg2);
325 *((unsigned long *) (buf + 12)) = SDLNet_Read32((unsigned long) pkt->arg3);
326 *((unsigned long *) (buf + 16)) = SDLNet_Read32((unsigned long) pkt->arg4);
328 *((unsigned long *) (buf + 0)) = htonl(pkt->cmd);
329 *((unsigned long *) (buf + 4)) = htonl((unsigned long) pkt->arg);
330 *((unsigned long *) (buf + 8)) = htonl((unsigned long) pkt->arg2);
331 *((unsigned long *) (buf + 12)) = htonl((unsigned long) pkt->arg3);
332 *((unsigned long *) (buf + 16)) = htonl((unsigned long) pkt->arg4);
336 void sendPacketToSock(int s, NetPacket *pkt)
339 int bytes_left = NETPKTBUFSIZE;
341 char buf[NETPKTBUFSIZE];
344 packetToBuf(pkt, buf);
345 while (bytes_left > 0) {
346 bw = send(s, ptr, bytes_left, 0); /* this might block. For now, we'll deal. */
348 if (h_errno != EAGAIN) {
349 fprintf(stderr, "SERVER: send(): %i", net_error);
350 //perror("SERVER: write()");
354 } else if (bw == 0) {
365 void sendPacket(int playerid, NetPacket *pkt)
367 if ( playerid < JNB_MAX_PLAYERS ) {
368 if ((player[playerid].enabled) && (playerid != client_player_num)) {
369 sendPacketToSock(net_info[playerid].sock, pkt);
375 void sendPacketToAll(NetPacket *pkt)
379 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
385 int grabPacket(int s, NetPacket *pkt)
388 char buf[NETPKTBUFSIZE];
396 tv.tv_sec = tv.tv_usec = 0; /* don't block. */
397 if (select(s + 1, &rfds, NULL, NULL, &tv)) {
398 rc = recv(s, buf, NETPKTBUFSIZE, 0);
399 if (rc <= 0) { /* closed connection? */
401 } else if (rc != NETPKTBUFSIZE) { // !!! FIXME: buffer these?
402 printf("NETWORK: -BUG- ... dropped a packet! (had %d of %d bytes).\b",
405 bufToPacket(buf, pkt);
417 int serverRecvPacket(NetPacket *pkt)
424 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
425 int s = net_info[i].sock;
427 if ((i == client_player_num) || (!player[i].enabled))
430 rc = grabPacket(s, pkt);
434 player[i].enabled = 0;
436 pkt.cmd = NETCMD_BYE;
441 sendPacketToAll(&pkt);
443 return(i); /* it's all good. */
447 return(-1); /* no packets available currently. */
451 void wait_for_greenlight(void)
456 printf("CLIENT: Waiting for greenlight...\n");
460 while ((rc = grabPacket(sock, &pkt)) == 0) {
461 SDL_Delay(100); /* nap and then try again. */
465 printf("CLIENT: Lost connection.\n");
469 } while (pkt.cmd != NETCMD_GREENLIGHT);
471 printf("CLIENT: Got greenlight.\n");
473 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
474 if (pkt.arg & (1 << i)) {
475 printf("CLIENT: There is a player #%d.\n", i);
476 player[i].enabled = 1;
482 static int buggered_off = 0;
485 void tellServerGoodbye(void)
491 pkt.cmd = NETCMD_BYE;
492 pkt.arg = client_player_num;
496 sendPacketToSock(sock, &pkt);
502 void processMovePacket(NetPacket *pkt)
504 int playerid = pkt->arg;
505 int movetype = ((pkt->arg2 >> 16) & 0xFF);
506 int newval = ((pkt->arg2 >> 0) & 0xFF);
508 if (movetype == MOVEMENT_LEFT) {
509 player[playerid].action_left = newval;
510 } else if (movetype == MOVEMENT_RIGHT) {
511 player[playerid].action_right = newval;
512 } else if (movetype == MOVEMENT_UP) {
513 player[playerid].action_up = newval;
515 printf("bogus MOVE packet!\n");
518 player[playerid].x = pkt->arg3;
519 player[playerid].y = pkt->arg4;
523 void tellServerPlayerMoved(int playerid, int movement_type, int newval)
527 pkt.cmd = NETCMD_MOVE;
529 pkt.arg2 = ( ((movement_type & 0xFF) << 16) | ((newval & 0xFF) << 0) );
530 pkt.arg3 = player[playerid].x;
531 pkt.arg4 = player[playerid].y;
534 processMovePacket(&pkt);
537 sendPacketToAll(&pkt);
539 sendPacketToSock(sock, &pkt);
546 void tellServerNewPosition(void)
549 pkt.cmd = NETCMD_POSITION;
550 pkt.arg = client_player_num;
551 pkt.arg2 = player[client_player_num].x;
552 pkt.arg3 = player[client_player_num].y;
555 sendPacketToAll(&pkt);
557 sendPacketToSock(sock, &pkt);
563 void processKillPacket(NetPacket *pkt)
572 player[c1].y_add = -player[c1].y_add;
573 if (player[c1].y_add > -262144L)
574 player[c1].y_add = -262144L;
575 player[c1].jump_abort = 1;
576 player[c2].dead_flag = 1;
577 if (player[c2].anim != 6) {
579 player[c2].frame = 0;
580 player[c2].frame_tick = 0;
581 player[c2].image = player_anims[player[c2].anim].frame[player[c2].frame].image + player[c2].direction * 9;
582 if (main_info.no_gore == 0) {
583 for (c4 = 0; c4 < 6; c4++)
584 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);
585 for (c4 = 0; c4 < 6; c4++)
586 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 76);
587 for (c4 = 0; c4 < 6; c4++)
588 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 77);
589 for (c4 = 0; c4 < 8; c4++)
590 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 78);
591 for (c4 = 0; c4 < 10; c4++)
592 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 79);
594 dj_play_sfx(SFX_DEATH, (unsigned short)(SFX_DEATH_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
596 player[c1].bumped[c2]++;
597 s1 = player[c1].bumps % 100;
598 add_leftovers(0, 360, 34 + c1 * 64, s1 / 10, &number_gobs);
599 add_leftovers(1, 360, 34 + c1 * 64, s1 / 10, &number_gobs);
600 add_leftovers(0, 376, 34 + c1 * 64, s1 - (s1 / 10) * 10, &number_gobs);
601 add_leftovers(1, 376, 34 + c1 * 64, s1 - (s1 / 10) * 10, &number_gobs);
607 void processPositionPacket(NetPacket *pkt)
609 int playerid = pkt->arg;
611 player[playerid].x = pkt->arg2;
612 player[playerid].y = pkt->arg3;
616 void processAlivePacket(NetPacket *pkt)
618 int playerid = pkt->arg;
620 player[playerid].dead_flag = 0;
621 player[playerid].x = pkt->arg2;
622 player[playerid].y = pkt->arg3;
626 void serverTellEveryoneGoodbye(void)
632 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
633 if (player[i].enabled) {
636 pkt.cmd = NETCMD_BYE;
641 sendPacketToAll(&pkt);
648 int server_said_bye = 0;
651 int update_players_from_server(void)
658 while ((rc = grabPacket(sock, &pkt)) != 0) {
660 printf("CLIENT: Lost connection.\n");
661 pkt.cmd = NETCMD_BYE;
662 pkt.arg = client_player_num;
665 if (pkt.cmd == NETCMD_BYE) {
666 if (pkt.arg == client_player_num) {
672 player[pkt.arg].enabled = 0;
674 } else if (pkt.cmd == NETCMD_MOVE) {
675 processMovePacket(&pkt);
676 } else if (pkt.cmd == NETCMD_ALIVE) {
677 processAlivePacket(&pkt);
678 } else if (pkt.cmd == NETCMD_POSITION) {
679 processPositionPacket(&pkt);
680 } else if (pkt.cmd == NETCMD_KILL) {
681 processKillPacket(&pkt);
683 printf("CLIENT: Got an unknown packet: 0x%lX.\n", pkt.cmd);
691 void serverSendAlive(int playerid)
696 pkt.cmd = NETCMD_ALIVE;
698 pkt.arg2 = player[playerid].x;
699 pkt.arg3 = player[playerid].y;
700 sendPacketToAll(&pkt);
705 void serverSendKillPacket(int killer, int victim)
710 pkt.cmd = NETCMD_KILL;
713 pkt.arg3 = player[victim].x;
714 pkt.arg4 = player[victim].y;
715 processKillPacket(&pkt);
718 sendPacketToAll(&pkt);
724 void update_players_from_clients(void)
733 while ((playerid = serverRecvPacket(&pkt)) >= 0) {
734 if (pkt.cmd == NETCMD_BYE) {
735 pkt.arg = playerid; /* just in case. */
736 sendPacketToAll(&pkt);
737 player[playerid].enabled = 0;
738 close(net_info[playerid].sock);
739 } else if (pkt.cmd == NETCMD_POSITION) {
740 pkt.arg = playerid; /* just in case. */
741 processPositionPacket(&pkt);
742 for (i = 0; i < (sizeof (net_info) / sizeof (net_info[0])); i++) {
747 } else if (pkt.cmd == NETCMD_MOVE) {
748 pkt.arg = playerid; /* just in case. */
749 //pkt.arg3 = player[playerid].x;
750 //pkt.arg4 = player[playerid].y;
751 processMovePacket(&pkt);
752 sendPacketToAll(&pkt);
754 printf("SERVER: Got unknown packet (0x%lX).\n", pkt.cmd);
761 void init_server(const char *netarg)
766 struct hostent *hent;
767 struct sockaddr_in addr;
768 struct in_addr inaddr;
770 int wait_for_clients = ((netarg == NULL) ? 0 : atoi(netarg));
772 WORD wVersionRequested;
776 wVersionRequested = MAKEWORD( 2, 2 );
778 err = WSAStartup( wVersionRequested, &wsaData );
780 /* Tell the user that we could not find a usable */
782 fprintf(stderr, "SERVER: WSAStartup failed!");
787 if ((wait_for_clients > (JNB_MAX_PLAYERS - 1)) || (wait_for_clients < 0)) {
788 printf("SERVER: Waiting for bogus client count (%d).\n", wait_for_clients);
792 sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
794 fprintf(stderr, "SERVER: socket(): %i", net_error);
795 //perror("SERVER: socket()");
799 memset(&addr, '\0', sizeof (addr));
800 addr.sin_family = AF_INET;
801 addr.sin_port = htons(JNB_INETPORT);
802 addr.sin_addr.s_addr = INADDR_ANY;
803 if (bind(sock, (struct sockaddr *) &addr,
804 sizeof (addr)) == -1) {
805 fprintf(stderr, "SERVER: bind(): %i", net_error);
806 //perror("SERVER: bind()");
811 if (listen(sock, wait_for_clients) == -1) {
812 fprintf(stderr, "SERVER: listen(): %i", net_error);
813 //perror("SERVER: listen()");
818 player[client_player_num].enabled = 1;
820 gethostname(ipstr, sizeof (ipstr));
821 hent = gethostbyname(ipstr);
823 memcpy(&inaddr, hent->h_addr, hent->h_length);
824 strncpy(ipstr, inet_ntoa(inaddr), sizeof (ipstr));
827 printf("SERVER: we are [%s].\n", ipstr);
829 addr.sin_addr.s_addr = inaddr.s_addr;
830 addr.sin_family = AF_INET;
831 addr.sin_port = htons(JNB_INETPORT);
832 net_info[client_player_num].addr = malloc(sizeof (addr));
833 memcpy(net_info[client_player_num].addr, &addr, sizeof (addr));
834 net_info[client_player_num].addrlen = sizeof (addr);
835 /*gettimeofday(&net_info[client_player_num].last_timestamp, NULL);*/
837 printf("SERVER: waiting for (%d) clients...\n", wait_for_clients);
839 while (wait_for_clients > 0)
841 char buf[NETPKTBUFSIZE];
842 struct sockaddr_in from;
843 int fromlen = sizeof (from);
848 s = accept(sock, (struct sockaddr *) &from, &fromlen);
851 fprintf(stderr, "SERVER: accept(): %i", net_error);
852 //perror("SERVER: accept()");
857 br = recv(s, buf, NETPKTBUFSIZE, 0);
859 fprintf(stderr, "SERVER: recv(): %i", net_error);
865 strncpy(ipstr, inet_ntoa(from.sin_addr), sizeof (ipstr));
866 printf("SERVER: Got data from [%s].\n", ipstr);
868 if (br != NETPKTBUFSIZE) {
869 printf("SERVER: Bogus packet.\n");
873 bufToPacket(buf, &pkt);
874 if (pkt.cmd != NETCMD_HELLO) {
875 printf("SERVER: Bogus packet.\n");
879 printf("SERVER: Client claims to be player #%ld.\n", pkt.arg);
881 if (pkt.arg > (sizeof (player) / sizeof (player[0]))) {
882 printf("SERVER: (that's an invalid player number.)\n");
884 if (player[pkt.arg].enabled) {
885 printf("SERVER: (that player number is already taken.)\n");
892 printf("SERVER: Forbidding connection.\n");
893 pkt.cmd = NETCMD_NACK;
894 sendPacketToSock(s, &pkt);
897 player[pkt.arg].enabled = 1;
898 net_info[pkt.arg].sock = s;
899 net_info[pkt.arg].addr = malloc(fromlen);
900 memcpy(net_info[pkt.arg].addr, &from, fromlen);
901 net_info[pkt.arg].addrlen = fromlen;
902 /*memcpy(&net_info[pkt.arg].last_timestamp, &pkt.timestamp, sizeof (pkt.timestamp));*/
904 printf("SERVER: Granting connection. (%d) to go.\n", wait_for_clients);
905 pkt.cmd = NETCMD_ACK;
906 sendPacket(pkt.arg, &pkt);
910 close(sock); /* done with the listen socket. */
913 printf("SERVER: Got all our connections. Greenlighting clients...\n");
915 pkt.cmd = NETCMD_GREENLIGHT;
917 for (i = 0; i < (sizeof (net_info) / sizeof (net_info[0])); i++) {
918 if (player[i].enabled) {
922 sendPacketToAll(&pkt);
927 void connect_to_server(char *netarg)
931 char buf[NETPKTBUFSIZE];
933 struct hostent *hent;
934 struct sockaddr_in addr;
935 struct in_addr inaddr;
939 WORD wVersionRequested;
943 wVersionRequested = MAKEWORD( 2, 2 );
945 err = WSAStartup( wVersionRequested, &wsaData );
947 /* Tell the user that we could not find a usable */
949 fprintf(stderr, "SERVER: WSAStartup failed!");
954 if (netarg == NULL) {
955 printf("CLIENT: Need to specify host to connect to.\n");
959 player[client_player_num].enabled = 1;
960 gethostname(ipstr, sizeof (ipstr));
961 hent = gethostbyname(ipstr);
963 net_info[client_player_num].addr = malloc(hent->h_length);
964 memcpy(&net_info[client_player_num].addr, &hent->h_addr, hent->h_length);
965 net_info[client_player_num].addrlen = hent->h_length;
966 memcpy(&inaddr, hent->h_addr, hent->h_length);
967 strncpy(ipstr, inet_ntoa(inaddr), sizeof (ipstr));
969 printf("CLIENT: we are [%s].\n", ipstr);
971 /*gettimeofday(&net_info[client_player_num].last_timestamp, NULL);*/
973 hent = gethostbyname(netarg);
975 fprintf(stderr, "CLIENT: couldn't find host: %i", net_error);
976 //perror("CLIENT: couldn't find host");
980 sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
982 fprintf(stderr, "CLIENT: socket(): %i", net_error);
983 //perror("CLIENT: socket()");
987 memcpy(&inaddr, hent->h_addr, hent->h_length);
988 printf("CLIENT: connecting to [%s]...\n", inet_ntoa(inaddr));
990 addr.sin_family = AF_INET;
991 addr.sin_port = htons(JNB_INETPORT);
992 memcpy(&addr.sin_addr.s_addr, hent->h_addr, hent->h_length);
993 if (connect(sock, (struct sockaddr *) &addr, sizeof (addr)) == -1) {
994 fprintf(stderr, "CLIENT: connect(): %i", net_error);
995 //perror("CLIENT: connect()");
999 printf("CLIENT: Got socket. Sending HELLO packet...\n");
1000 pkt.cmd = NETCMD_HELLO;
1001 pkt.arg = client_player_num;
1002 sendPacketToSock(sock, &pkt);
1004 printf("CLIENT: Waiting for ACK from server...\n");
1006 addrlen = sizeof (addr);
1007 br = recv(sock, buf, NETPKTBUFSIZE, 0);
1009 fprintf(stderr, "CLIENT: recv(): %i", net_error);
1010 //perror("CLIENT: recv()");
1015 if (br != NETPKTBUFSIZE) {
1016 printf("CLIENT: Bogus packet size (%d of %d). FIXME.\n",
1022 bufToPacket(buf, &pkt);
1024 if (pkt.cmd == NETCMD_NACK) {
1025 printf("CLIENT: Server forbid us from playing.\n");
1030 if (pkt.cmd != NETCMD_ACK) {
1031 printf("CLIENT: Unexpected packet (cmd=0x%lX).\n", pkt.cmd);
1036 printf("CLIENT: Server accepted our connection.\n");
1038 wait_for_greenlight();
1044 static flip_pixels(unsigned char *pixels)
1050 for (y = 0; y < JNB_HEIGHT; y++) {
1051 for (x = 0; x < (352/2); x++) {
1052 temp = pixels[y*JNB_WIDTH+x];
1053 pixels[y*JNB_WIDTH+x] = pixels[y*JNB_WIDTH+(352-x)-1];
1054 pixels[y*JNB_WIDTH+(352-x)-1] = temp;
1060 int main(int argc, char *argv[])
1062 unsigned char *handle;
1063 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
1066 int closest_player = 0, dist, cur_dist = 0;
1067 int end_loop_flag = 0, fade_flag;
1068 int mod_vol, sfx_vol, mod_fade_direction;
1074 if (init_program(argc, argv, pal) != 0)
1077 if (main_info.fireworks == 1) {
1088 if (key_pressed(1) == 1) {
1091 if (init_level(0, pal) != 0) {
1096 memset(cur_pal, 0, 768);
1097 setpalette(0, 256, cur_pal);
1099 recalculate_gob(&rabbit_gobs, pal);
1100 //recalculate_gob(&font_gobs, pal);
1101 recalculate_gob(&object_gobs, pal);
1102 recalculate_gob(&number_gobs, pal);
1105 register_background(background_pic, pal);
1108 if (flies_enabled) {
1112 for (c1 = 0; c1 < NUM_FLIES; c1++) {
1114 flies[c1].x = s1 + rnd(101) - 50;
1115 flies[c1].y = s2 + rnd(101) - 50;
1116 if (ban_map[flies[c1].y >> 4][flies[c1].x >> 4] == BAN_VOID)
1119 flies[c1].back_defined[0] = 0;
1120 flies[c1].back_defined[1] = 0;
1124 mod_vol = sfx_vol = 10;
1125 mod_fade_direction = 1;
1126 dj_ready_mod(MOD_GAME);
1127 dj_set_mod_volume((char)mod_vol);
1128 dj_set_sfx_volume((char)mod_vol);
1132 dj_play_sfx(SFX_FLY, SFX_FLY_FREQ, 0, 0, 0, 4);
1136 lord_of_the_flies = bunnies_in_space = jetpack = pogostick = blood_is_thicker_than_water = 0;
1138 main_info.page_info[0].num_pobs = 0;
1139 main_info.page_info[1].num_pobs = 0;
1140 main_info.view_page = 0;
1141 main_info.draw_page = 1;
1145 while (update_count) {
1147 if (key_pressed(1) == 1) {
1151 serverTellEveryoneGoodbye();
1153 tellServerGoodbye();
1158 memset(pal, 0, 768);
1159 mod_fade_direction = 0;
1162 if (strncmp(last_keys, "kcitsogop", strlen("kcitsogop")) == 0) {
1166 if (strncmp(last_keys, "ecapsniseinnub", strlen("ecapsniseinnub")) == 0) {
1167 bunnies_in_space ^= 1;
1170 if (strncmp(last_keys, "kcaptej", strlen("kcaptej")) == 0) {
1174 if (strncmp(last_keys, "seilfehtfodrol", strlen("seilfehtfodrol")) == 0) {
1175 lord_of_the_flies ^= 1;
1178 if (strncmp(last_keys, "retawnahtrekcihtsidoolb", strlen("retawnahtrekcihtsidoolb")) == 0) {
1179 blood_is_thicker_than_water ^= 1;
1180 if (blood_is_thicker_than_water == 1) {
1231 register_background(background_pic, pal);
1232 recalculate_gob(&object_gobs, pal);
1239 update_players_from_clients();
1241 if (!update_players_from_server()) {
1242 break; /* got a BYE packet */
1252 for (c3 = 0; c3 < 6; c3++) {
1256 } else if (c3 == 1) {
1259 } else if (c3 == 2) {
1262 } else if (c3 == 3) {
1265 } else if (c3 == 4) {
1268 } else if (c3 == 5) {
1272 if (player[c1].enabled == 1 && player[c2].enabled == 1) {
1273 if (labs(player[c1].x - player[c2].x) < (12L << 16) && labs(player[c1].y - player[c2].y) < (12L << 16)) {
1274 if ((labs(player[c1].y - player[c2].y) >> 16) > 5) {
1275 if (player[c1].y < player[c2].y) {
1276 if (player[c1].y_add >= 0) {
1278 serverSendKillPacket(c1, c2);
1280 if (player[c2].y_add < 0)
1281 player[c2].y_add = 0;
1284 if (player[c2].y_add >= 0) {
1286 serverSendKillPacket(c2, c1);
1288 if (player[c1].y_add < 0)
1289 player[c1].y_add = 0;
1293 if (player[c1].x < player[c2].x) {
1294 if (player[c1].x_add > 0)
1295 player[c1].x = player[c2].x - (12L << 16);
1296 else if (player[c2].x_add < 0)
1297 player[c2].x = player[c1].x + (12L << 16);
1299 player[c1].x -= player[c1].x_add;
1300 player[c2].x -= player[c2].x_add;
1302 l1 = player[c2].x_add;
1303 player[c2].x_add = player[c1].x_add;
1304 player[c1].x_add = l1;
1305 if (player[c1].x_add > 0)
1306 player[c1].x_add = -player[c1].x_add;
1307 if (player[c2].x_add < 0)
1308 player[c2].x_add = -player[c2].x_add;
1310 if (player[c1].x_add > 0)
1311 player[c2].x = player[c1].x - (12L << 16);
1312 else if (player[c2].x_add < 0)
1313 player[c1].x = player[c2].x + (12L << 16);
1315 player[c1].x -= player[c1].x_add;
1316 player[c2].x -= player[c2].x_add;
1318 l1 = player[c2].x_add;
1319 player[c2].x_add = player[c1].x_add;
1320 player[c1].x_add = l1;
1321 if (player[c1].x_add < 0)
1322 player[c1].x_add = -player[c1].x_add;
1323 if (player[c2].x_add > 0)
1324 player[c2].x_add = -player[c2].x_add;
1333 main_info.page_info[main_info.draw_page].num_pobs = 0;
1334 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1335 if (player[c1].enabled == 1)
1336 main_info.page_info[main_info.draw_page].num_pobs++;
1343 if (flies_enabled) {
1344 /* get center of fly swarm */
1346 for (c1 = 0; c1 < NUM_FLIES; c1++) {
1353 if (update_count == 1) {
1354 /* get closest player to fly swarm */
1356 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1357 if (player[c1].enabled == 1) {
1358 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)));
1359 if (cur_dist < dist) {
1360 closest_player = c1;
1365 /* update fly swarm sound */
1369 dj_set_sfx_channel_volume(4, (char)(s3));
1372 for (c1 = 0; c1 < NUM_FLIES; c1++) {
1373 /* get closest player to fly */
1375 for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++) {
1376 if (player[c2].enabled == 1) {
1377 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)));
1378 if (cur_dist < dist) {
1379 closest_player = c2;
1384 flies[c1].old_x = flies[c1].x;
1385 flies[c1].old_y = flies[c1].y;
1387 if ((s1 - flies[c1].x) > 30)
1389 else if ((s1 - flies[c1].x) < -30)
1392 if (((player[closest_player].x >> 16) + 8) > flies[c1].x) {
1393 if (lord_of_the_flies == 0)
1398 if (lord_of_the_flies == 0)
1404 s4 = rnd(3) - 1 + s3;
1405 if ((flies[c1].x + s4) < 16)
1407 if ((flies[c1].x + s4) > 351)
1409 if (ban_map[flies[c1].y >> 4][(flies[c1].x + s4) >> 4] != BAN_VOID)
1413 if ((s2 - flies[c1].y) > 30)
1415 else if ((s2 - flies[c1].y) < -30)
1418 if (((player[closest_player].y >> 16) + 8) > flies[c1].y) {
1419 if (lord_of_the_flies == 0)
1424 if (lord_of_the_flies == 0)
1430 s4 = rnd(3) - 1 + s3;
1431 if ((flies[c1].y + s4) < 0)
1433 if ((flies[c1].y + s4) > 239)
1435 if (ban_map[(flies[c1].y + s4) >> 4][flies[c1].x >> 4] != BAN_VOID)
1444 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1445 if (player[c1].enabled == 1) {
1446 main_info.page_info[main_info.draw_page].pobs[s1].x = player[c1].x >> 16;
1447 main_info.page_info[main_info.draw_page].pobs[s1].y = player[c1].y >> 16;
1448 main_info.page_info[main_info.draw_page].pobs[s1].image = player[c1].image + c1 * 18;
1449 main_info.page_info[main_info.draw_page].pobs[s1].pob_data = &rabbit_gobs;
1454 if (update_count == 1) {
1457 draw_pobs(main_info.draw_page);
1462 draw_flies(main_info.draw_page);
1467 if (mod_fade_direction == 1) {
1470 dj_set_mod_volume((char)mod_vol);
1475 dj_set_mod_volume((char)mod_vol);
1479 if (mod_fade_direction == 1) {
1482 dj_set_sfx_volume((char)sfx_vol);
1487 dj_set_sfx_volume((char)sfx_vol);
1492 for (c1 = 0; c1 < 768; c1++) {
1493 if (cur_pal[c1] < pal[c1]) {
1496 } else if (cur_pal[c1] > pal[c1]) {
1501 if (fade_flag == 0 && end_loop_flag == 1)
1504 if (update_count == 1) {
1505 main_info.draw_page ^= 1;
1506 main_info.view_page ^= 1;
1508 flippage(main_info.view_page);
1514 setpalette(0, 256, cur_pal);
1516 if (update_count == 1) {
1520 redraw_flies_background(main_info.draw_page);
1522 redraw_pob_backgrounds(main_info.draw_page);
1524 draw_leftovers(main_info.draw_page);
1534 if ( (player[client_player_num].dead_flag == 0) &&
1536 (player[client_player_num].action_left) ||
1537 (player[client_player_num].action_right) ||
1538 (player[client_player_num].action_up) ||
1539 (player[client_player_num].jump_ready == 0)
1542 tellServerNewPosition();
1547 update_count = intr_sysupdate();
1551 if ((server_said_bye) || ((fade_flag == 0) && (end_loop_flag == 1)))
1555 if ((fade_flag == 0) && (end_loop_flag == 1))
1562 serverTellEveryoneGoodbye();
1566 if (!server_said_bye) {
1567 tellServerGoodbye();
1576 main_info.view_page = 0;
1577 main_info.draw_page = 1;
1579 dj_stop_sfx_channel(4);
1583 memset(mask_pic, 0, JNB_WIDTH*JNB_HEIGHT);
1584 register_mask(mask_pic);
1586 //recalculate_gob(&font_gobs, pal);
1587 register_background(NULL, NULL);
1591 put_text(main_info.view_page, 100, 50, "DOTT", 2);
1592 put_text(main_info.view_page, 160, 50, "JIFFY", 2);
1593 put_text(main_info.view_page, 220, 50, "FIZZ", 2);
1594 put_text(main_info.view_page, 280, 50, "MIJJI", 2);
1595 put_text(main_info.view_page, 40, 80, "DOTT", 2);
1596 put_text(main_info.view_page, 40, 110, "JIFFY", 2);
1597 put_text(main_info.view_page, 40, 140, "FIZZ", 2);
1598 put_text(main_info.view_page, 40, 170, "MIJJI", 2);
1600 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1601 for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++) {
1603 sprintf(str1, "%d", player[c1].bumped[c2]);
1604 put_text(main_info.view_page, 100 + c2 * 60, 80 + c1 * 30, str1, 2);
1606 put_text(main_info.view_page, 100 + c2 * 60, 80 + c1 * 30, "-", 2);
1608 sprintf(str1, "%d", player[c1].bumps);
1609 put_text(main_info.view_page, 350, 80 + c1 * 30, str1, 2);
1612 put_text(main_info.view_page, 200, 230, "Press ESC to continue", 2);
1616 flippage(main_info.view_page);
1618 if ((handle = dat_open("menu.pcx", datfile_name, "rb")) == 0) {
1619 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
1622 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
1623 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
1627 for (c1 = 0; c1 < 16; c1++) { // fix dark font
1628 pal[(240 + c1) * 3 + 0] = c1 << 2;
1629 pal[(240 + c1) * 3 + 1] = c1 << 2;
1630 pal[(240 + c1) * 3 + 2] = c1 << 2;
1633 memset(cur_pal, 0, 768);
1635 setpalette(0, 256, cur_pal);
1638 dj_ready_mod(MOD_SCORES);
1639 dj_set_mod_volume((char)mod_vol);
1643 while (key_pressed(1) == 0) {
1646 dj_set_mod_volume((char)mod_vol);
1647 for (c1 = 0; c1 < 768; c1++) {
1648 if (cur_pal[c1] < pal[c1])
1654 setpalette(0, 256, cur_pal);
1655 flippage(main_info.view_page);
1657 while (key_pressed(1) == 1) {
1662 memset(pal, 0, 768);
1664 while (mod_vol > 0) {
1666 dj_set_mod_volume((char)mod_vol);
1667 for (c1 = 0; c1 < 768; c1++) {
1668 if (cur_pal[c1] > pal[c1])
1673 setpalette(0, 256, cur_pal);
1674 flippage(main_info.view_page);
1677 fillpalette(0, 0, 0);
1683 break; /* don't go back to menu if in net game. */
1692 void steer_players(void)
1697 update_player_actions();
1699 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1701 if (player[c1].enabled == 1) {
1703 if (player[c1].dead_flag == 0) {
1705 if (player[c1].action_left && player[c1].action_right) {
1706 if (player[c1].direction == 0) {
1707 if (player[c1].action_right) {
1708 s1 = (player[c1].x >> 16);
1709 s2 = (player[c1].y >> 16);
1710 if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) {
1711 if (player[c1].x_add < 0)
1712 player[c1].x_add += 1024;
1714 player[c1].x_add += 768;
1715 } 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)) {
1716 if (player[c1].x_add > 0)
1717 player[c1].x_add += 1024;
1719 player[c1].x_add += 768;
1721 if (player[c1].x_add < 0) {
1722 player[c1].x_add += 16384;
1723 if (player[c1].x_add < 98304L && player[c1].in_water == 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1724 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);
1726 player[c1].x_add += 12288;
1728 if (player[c1].x_add > 98304L)
1729 player[c1].x_add = 98304L;
1730 player[c1].direction = 0;
1731 if (player[c1].anim == 0) {
1732 player[c1].anim = 1;
1733 player[c1].frame = 0;
1734 player[c1].frame_tick = 0;
1735 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1739 if (player[c1].action_left) {
1740 s1 = (player[c1].x >> 16);
1741 s2 = (player[c1].y >> 16);
1742 if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) {
1743 if (player[c1].x_add > 0)
1744 player[c1].x_add -= 1024;
1746 player[c1].x_add -= 768;
1747 } 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)) {
1748 if (player[c1].x_add > 0)
1749 player[c1].x_add -= 1024;
1751 player[c1].x_add -= 768;
1753 if (player[c1].x_add > 0) {
1754 player[c1].x_add -= 16384;
1755 if (player[c1].x_add > -98304L && player[c1].in_water == 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1756 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);
1758 player[c1].x_add -= 12288;
1760 if (player[c1].x_add < -98304L)
1761 player[c1].x_add = -98304L;
1762 player[c1].direction = 1;
1763 if (player[c1].anim == 0) {
1764 player[c1].anim = 1;
1765 player[c1].frame = 0;
1766 player[c1].frame_tick = 0;
1767 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1771 } else if (player[c1].action_left) {
1772 s1 = (player[c1].x >> 16);
1773 s2 = (player[c1].y >> 16);
1774 if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) {
1775 if (player[c1].x_add > 0)
1776 player[c1].x_add -= 1024;
1778 player[c1].x_add -= 768;
1779 } 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)) {
1780 if (player[c1].x_add > 0)
1781 player[c1].x_add -= 1024;
1783 player[c1].x_add -= 768;
1785 if (player[c1].x_add > 0) {
1786 player[c1].x_add -= 16384;
1787 if (player[c1].x_add > -98304L && player[c1].in_water == 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1788 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);
1790 player[c1].x_add -= 12288;
1792 if (player[c1].x_add < -98304L)
1793 player[c1].x_add = -98304L;
1794 player[c1].direction = 1;
1795 if (player[c1].anim == 0) {
1796 player[c1].anim = 1;
1797 player[c1].frame = 0;
1798 player[c1].frame_tick = 0;
1799 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1801 } else if (player[c1].action_right) {
1802 s1 = (player[c1].x >> 16);
1803 s2 = (player[c1].y >> 16);
1804 if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) {
1805 if (player[c1].x_add < 0)
1806 player[c1].x_add += 1024;
1808 player[c1].x_add += 768;
1809 } 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)) {
1810 if (player[c1].x_add > 0)
1811 player[c1].x_add += 1024;
1813 player[c1].x_add += 768;
1815 if (player[c1].x_add < 0) {
1816 player[c1].x_add += 16384;
1817 if (player[c1].x_add < 98304L && player[c1].in_water == 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1818 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);
1820 player[c1].x_add += 12288;
1822 if (player[c1].x_add > 98304L)
1823 player[c1].x_add = 98304L;
1824 player[c1].direction = 0;
1825 if (player[c1].anim == 0) {
1826 player[c1].anim = 1;
1827 player[c1].frame = 0;
1828 player[c1].frame_tick = 0;
1829 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1831 } else if ((!player[c1].action_left) && (!player[c1].action_right)) {
1832 s1 = (player[c1].x >> 16);
1833 s2 = (player[c1].y >> 16);
1834 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)))) {
1835 if (player[c1].x_add < 0) {
1836 player[c1].x_add += 16384;
1837 if (player[c1].x_add > 0)
1838 player[c1].x_add = 0;
1840 player[c1].x_add -= 16384;
1841 if (player[c1].x_add < 0)
1842 player[c1].x_add = 0;
1844 if (player[c1].x_add != 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1845 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);
1847 if (player[c1].anim == 1) {
1848 player[c1].anim = 0;
1849 player[c1].frame = 0;
1850 player[c1].frame_tick = 0;
1851 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1855 if (pogostick == 1 || (player[c1].jump_ready == 1 && player[c1].action_up)) {
1856 s1 = (player[c1].x >> 16);
1857 s2 = (player[c1].y >> 16);
1860 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) {
1861 player[c1].y_add = -280000L;
1862 player[c1].anim = 2;
1863 player[c1].frame = 0;
1864 player[c1].frame_tick = 0;
1865 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1866 player[c1].jump_ready = 0;
1867 player[c1].jump_abort = 1;
1869 dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1871 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1873 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)) {
1874 player[c1].y_add = -196608L;
1875 player[c1].in_water = 0;
1876 player[c1].anim = 2;
1877 player[c1].frame = 0;
1878 player[c1].frame_tick = 0;
1879 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1880 player[c1].jump_ready = 0;
1881 player[c1].jump_abort = 1;
1883 dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1885 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1888 if (pogostick == 0 && (!player[c1].action_up)) {
1889 player[c1].jump_ready = 1;
1890 if (player[c1].in_water == 0 && player[c1].y_add < 0 && player[c1].jump_abort == 1) {
1891 if (bunnies_in_space == 0)
1892 player[c1].y_add += 32768;
1894 player[c1].y_add += 16384;
1895 if (player[c1].y_add > 0)
1896 player[c1].y_add = 0;
1901 if (player[c1].action_up) {
1902 player[c1].y_add -= 16384;
1903 if (player[c1].y_add < -400000L)
1904 player[c1].y_add = -400000L;
1905 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))
1906 player[c1].in_water = 0;
1908 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);
1913 player[c1].x += player[c1].x_add;
1914 if ((player[c1].x >> 16) < 0) {
1916 player[c1].x_add = 0;
1918 if ((player[c1].x >> 16) + 15 > 351) {
1919 player[c1].x = 336L << 16;
1920 player[c1].x_add = 0;
1922 if (player[c1].y > 0) {
1923 s1 = (player[c1].x >> 16);
1924 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 + 15) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SPRING) {
1926 player[c1].x = (((s1 + 16) & 0xfff0)) << 16;
1927 player[c1].x_add = 0;
1929 s1 = (player[c1].x >> 16);
1930 s2 = (player[c1].y >> 16);
1931 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) {
1932 player[c1].x = (((s1 + 16) & 0xfff0) - 16) << 16;
1933 player[c1].x_add = 0;
1936 s1 = (player[c1].x >> 16);
1938 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) {
1939 player[c1].x = (((s1 + 16) & 0xfff0)) << 16;
1940 player[c1].x_add = 0;
1942 s1 = (player[c1].x >> 16);
1944 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) {
1945 player[c1].x = (((s1 + 16) & 0xfff0) - 16) << 16;
1946 player[c1].x_add = 0;
1950 player[c1].y += player[c1].y_add;
1952 s1 = (player[c1].x >> 16);
1953 s2 = (player[c1].y >> 16);
1954 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))) {
1955 player[c1].y = ((player[c1].y >> 16) & 0xfff0) << 16;
1956 player[c1].y_add = -400000L;
1957 player[c1].anim = 2;
1958 player[c1].frame = 0;
1959 player[c1].frame_tick = 0;
1960 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1961 player[c1].jump_ready = 0;
1962 player[c1].jump_abort = 0;
1963 for (c2 = 0; c2 < NUM_OBJECTS; c2++) {
1964 if (objects[c2].used == 1 && objects[c2].type == OBJ_SPRING) {
1965 if (ban_map[(s2 + 15) >> 4][(s1 + 8) >> 4] == BAN_SPRING) {
1966 if ((objects[c2].x >> 20) == ((s1 + 8) >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
1967 objects[c2].frame = 0;
1968 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
1969 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
1973 if (ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SPRING) {
1974 if ((objects[c2].x >> 20) == (s1 >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
1975 objects[c2].frame = 0;
1976 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
1977 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
1980 } else if (ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SPRING) {
1981 if ((objects[c2].x >> 20) == ((s1 + 15) >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
1982 objects[c2].frame = 0;
1983 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
1984 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
1991 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1993 s1 = (player[c1].x >> 16);
1994 s2 = (player[c1].y >> 16);
1997 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) {
1998 player[c1].y = (((s2 + 16) & 0xfff0)) << 16;
1999 player[c1].y_add = 0;
2000 player[c1].anim = 0;
2001 player[c1].frame = 0;
2002 player[c1].frame_tick = 0;
2003 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2005 s1 = (player[c1].x >> 16);
2006 s2 = (player[c1].y >> 16);
2009 if (ban_map[(s2 + 8) >> 4][(s1 + 8) >> 4] == BAN_WATER) {
2010 if (player[c1].in_water == 0) {
2011 player[c1].in_water = 1;
2012 player[c1].anim = 4;
2013 player[c1].frame = 0;
2014 player[c1].frame_tick = 0;
2015 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2016 if (player[c1].y_add >= 32768) {
2017 add_object(OBJ_SPLASH, (player[c1].x >> 16) + 8, ((player[c1].y >> 16) & 0xfff0) + 15, 0, 0, OBJ_ANIM_SPLASH, 0);
2018 if (blood_is_thicker_than_water == 0)
2019 dj_play_sfx(SFX_SPLASH, (unsigned short)(SFX_SPLASH_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
2021 dj_play_sfx(SFX_SPLASH, (unsigned short)(SFX_SPLASH_FREQ + rnd(2000) - 5000), 64, 0, 0, -1);
2024 player[c1].y_add -= 1536;
2025 if (player[c1].y_add < 0 && player[c1].anim != 5) {
2026 player[c1].anim = 5;
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;
2031 if (player[c1].y_add < -65536L)
2032 player[c1].y_add = -65536L;
2033 if (player[c1].y_add > 65535L)
2034 player[c1].y_add = 65535L;
2035 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) {
2036 player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16;
2037 player[c1].y_add = 0;
2039 } 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) {
2040 player[c1].in_water = 0;
2041 player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16;
2042 player[c1].y_add = 0;
2043 if (player[c1].anim != 0 && player[c1].anim != 1) {
2044 player[c1].anim = 0;
2045 player[c1].frame = 0;
2046 player[c1].frame_tick = 0;
2047 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2050 if (player[c1].in_water == 0) {
2051 if (bunnies_in_space == 0)
2052 player[c1].y_add += 12288;
2054 player[c1].y_add += 6144;
2055 if (player[c1].y_add > 327680L)
2056 player[c1].y_add = 327680L;
2058 player[c1].y = (player[c1].y & 0xffff0000) + 0x10000;
2059 player[c1].y_add = 0;
2061 player[c1].in_water = 0;
2063 if (player[c1].y_add > 36864 && player[c1].anim != 3 && player[c1].in_water == 0) {
2064 player[c1].anim = 3;
2065 player[c1].frame = 0;
2066 player[c1].frame_tick = 0;
2067 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2072 player[c1].frame_tick++;
2073 if (player[c1].frame_tick >= player_anims[player[c1].anim].frame[player[c1].frame].ticks) {
2075 if (player[c1].frame >= player_anims[player[c1].anim].num_frames) {
2076 if (player[c1].anim != 6)
2077 player[c1].frame = player_anims[player[c1].anim].restart_frame;
2079 position_player(c1);
2081 player[c1].frame_tick = 0;
2083 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2092 void position_player(int player_num)
2101 if (ban_map[s2][s1] == BAN_VOID && (ban_map[s2 + 1][s1] == BAN_SOLID || ban_map[s2 + 1][s1] == BAN_ICE))
2104 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
2105 if (c1 != player_num && player[c1].enabled == 1) {
2106 if (abs((s1 << 4) - (player[c1].x >> 16)) < 32 && abs((s2 << 4) - (player[c1].y >> 16)) < 32)
2110 if (c1 == JNB_MAX_PLAYERS) {
2111 player[player_num].x = (long) s1 << 20;
2112 player[player_num].y = (long) s2 << 20;
2113 player[player_num].x_add = player[player_num].y_add = 0;
2114 player[player_num].direction = 0;
2115 player[player_num].jump_ready = 1;
2116 player[player_num].in_water = 0;
2117 player[player_num].anim = 0;
2118 player[player_num].frame = 0;
2119 player[player_num].frame_tick = 0;
2120 player[player_num].image = player_anims[player[player_num].anim].frame[player[player_num].frame].image;
2125 serverSendAlive(player_num);
2127 player[player_num].dead_flag = 0;
2137 void add_object(int type, int x, int y, int x_add, int y_add, int anim, int frame)
2141 for (c1 = 0; c1 < NUM_OBJECTS; c1++) {
2142 if (objects[c1].used == 0) {
2143 objects[c1].used = 1;
2144 objects[c1].type = type;
2145 objects[c1].x = (long) x << 16;
2146 objects[c1].y = (long) y << 16;
2147 objects[c1].x_add = x_add;
2148 objects[c1].y_add = y_add;
2149 objects[c1].x_acc = 0;
2150 objects[c1].y_acc = 0;
2151 objects[c1].anim = anim;
2152 objects[c1].frame = frame;
2153 objects[c1].ticks = object_anims[anim].frame[frame].ticks;
2154 objects[c1].image = object_anims[anim].frame[frame].image;
2162 void update_objects(void)
2167 for (c1 = 0; c1 < NUM_OBJECTS; c1++) {
2168 if (objects[c1].used == 1) {
2169 switch (objects[c1].type) {
2171 objects[c1].ticks--;
2172 if (objects[c1].ticks <= 0) {
2173 objects[c1].frame++;
2174 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames) {
2175 objects[c1].frame--;
2176 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2178 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2179 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2182 if (objects[c1].used == 1)
2183 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2186 objects[c1].ticks--;
2187 if (objects[c1].ticks <= 0) {
2188 objects[c1].frame++;
2189 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2190 objects[c1].used = 0;
2192 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2193 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2196 if (objects[c1].used == 1)
2197 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2200 objects[c1].x += objects[c1].x_add;
2201 objects[c1].y += objects[c1].y_add;
2202 objects[c1].ticks--;
2203 if (objects[c1].ticks <= 0) {
2204 objects[c1].frame++;
2205 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2206 objects[c1].used = 0;
2208 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2209 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2212 if (objects[c1].used == 1)
2213 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2215 case OBJ_YEL_BUTFLY:
2216 case OBJ_PINK_BUTFLY:
2217 objects[c1].x_acc += rnd(128) - 64;
2218 if (objects[c1].x_acc < -1024)
2219 objects[c1].x_acc = -1024;
2220 if (objects[c1].x_acc > 1024)
2221 objects[c1].x_acc = 1024;
2222 objects[c1].x_add += objects[c1].x_acc;
2223 if (objects[c1].x_add < -32768)
2224 objects[c1].x_add = -32768;
2225 if (objects[c1].x_add > 32768)
2226 objects[c1].x_add = 32768;
2227 objects[c1].x += objects[c1].x_add;
2228 if ((objects[c1].x >> 16) < 16) {
2229 objects[c1].x = 16 << 16;
2230 objects[c1].x_add = -objects[c1].x_add >> 2;
2231 objects[c1].x_acc = 0;
2232 } else if ((objects[c1].x >> 16) > 350) {
2233 objects[c1].x = 350 << 16;
2234 objects[c1].x_add = -objects[c1].x_add >> 2;
2235 objects[c1].x_acc = 0;
2237 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0) {
2238 if (objects[c1].x_add < 0) {
2239 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2241 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2243 objects[c1].x_add = -objects[c1].x_add >> 2;
2244 objects[c1].x_acc = 0;
2246 objects[c1].y_acc += rnd(64) - 32;
2247 if (objects[c1].y_acc < -1024)
2248 objects[c1].y_acc = -1024;
2249 if (objects[c1].y_acc > 1024)
2250 objects[c1].y_acc = 1024;
2251 objects[c1].y_add += objects[c1].y_acc;
2252 if (objects[c1].y_add < -32768)
2253 objects[c1].y_add = -32768;
2254 if (objects[c1].y_add > 32768)
2255 objects[c1].y_add = 32768;
2256 objects[c1].y += objects[c1].y_add;
2257 if ((objects[c1].y >> 16) < 0) {
2259 objects[c1].y_add = -objects[c1].y_add >> 2;
2260 objects[c1].y_acc = 0;
2261 } else if ((objects[c1].y >> 16) > 255) {
2262 objects[c1].y = 255 << 16;
2263 objects[c1].y_add = -objects[c1].y_add >> 2;
2264 objects[c1].y_acc = 0;
2266 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0) {
2267 if (objects[c1].y_add < 0) {
2268 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2270 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2272 objects[c1].y_add = -objects[c1].y_add >> 2;
2273 objects[c1].y_acc = 0;
2275 if (objects[c1].type == OBJ_YEL_BUTFLY) {
2276 if (objects[c1].x_add < 0 && objects[c1].anim != OBJ_ANIM_YEL_BUTFLY_LEFT) {
2277 objects[c1].anim = OBJ_ANIM_YEL_BUTFLY_LEFT;
2278 objects[c1].frame = 0;
2279 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2280 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2281 } else if (objects[c1].x_add > 0 && objects[c1].anim != OBJ_ANIM_YEL_BUTFLY_RIGHT) {
2282 objects[c1].anim = OBJ_ANIM_YEL_BUTFLY_RIGHT;
2283 objects[c1].frame = 0;
2284 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2285 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2288 if (objects[c1].x_add < 0 && objects[c1].anim != OBJ_ANIM_PINK_BUTFLY_LEFT) {
2289 objects[c1].anim = OBJ_ANIM_PINK_BUTFLY_LEFT;
2290 objects[c1].frame = 0;
2291 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2292 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2293 } else if (objects[c1].x_add > 0 && objects[c1].anim != OBJ_ANIM_PINK_BUTFLY_RIGHT) {
2294 objects[c1].anim = OBJ_ANIM_PINK_BUTFLY_RIGHT;
2295 objects[c1].frame = 0;
2296 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2297 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2300 objects[c1].ticks--;
2301 if (objects[c1].ticks <= 0) {
2302 objects[c1].frame++;
2303 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2304 objects[c1].frame = object_anims[objects[c1].anim].restart_frame;
2306 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2307 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2310 if (objects[c1].used == 1)
2311 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2315 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 0);
2316 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 0) {
2317 objects[c1].y_add += 3072;
2318 if (objects[c1].y_add > 196608L)
2319 objects[c1].y_add = 196608L;
2320 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 2) {
2321 if (objects[c1].x_add < 0) {
2322 if (objects[c1].x_add < -65536L)
2323 objects[c1].x_add = -65536L;
2324 objects[c1].x_add += 1024;
2325 if (objects[c1].x_add > 0)
2326 objects[c1].x_add = 0;
2328 if (objects[c1].x_add > 65536L)
2329 objects[c1].x_add = 65536L;
2330 objects[c1].x_add -= 1024;
2331 if (objects[c1].x_add < 0)
2332 objects[c1].x_add = 0;
2334 objects[c1].y_add += 1024;
2335 if (objects[c1].y_add < -65536L)
2336 objects[c1].y_add = -65536L;
2337 if (objects[c1].y_add > 65536L)
2338 objects[c1].y_add = 65536L;
2340 objects[c1].x += objects[c1].x_add;
2341 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)) {
2342 if (objects[c1].x_add < 0) {
2343 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2344 objects[c1].x_add = -objects[c1].x_add >> 2;
2346 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2347 objects[c1].x_add = -objects[c1].x_add >> 2;
2350 objects[c1].y += objects[c1].y_add;
2351 if ((objects[c1].x >> 16) < -5 || (objects[c1].x >> 16) > 405 || (objects[c1].y >> 16) > 260)
2352 objects[c1].used = 0;
2353 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0)) {
2354 if (objects[c1].y_add < 0) {
2355 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 2) {
2356 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2357 objects[c1].x_add >>= 2;
2358 objects[c1].y_add = -objects[c1].y_add >> 2;
2361 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1) {
2362 if (objects[c1].y_add > 131072L) {
2363 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2364 objects[c1].x_add >>= 2;
2365 objects[c1].y_add = -objects[c1].y_add >> 2;
2367 objects[c1].used = 0;
2368 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3) {
2369 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2370 if (objects[c1].y_add > 131072L)
2371 objects[c1].y_add = -objects[c1].y_add >> 2;
2373 objects[c1].y_add = 0;
2377 if (objects[c1].x_add < 0 && objects[c1].x_add > -16384)
2378 objects[c1].x_add = -16384;
2379 if (objects[c1].x_add > 0 && objects[c1].x_add < 16384)
2380 objects[c1].x_add = 16384;
2381 if (objects[c1].used == 1) {
2382 s1 = (int)(atan2(objects[c1].y_add, objects[c1].x_add) * 4 / M_PI);
2389 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].frame + s1, &object_gobs);
2393 if (rnd(100) < 30) {
2394 if (objects[c1].frame == 76)
2395 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 1);
2396 else if (objects[c1].frame == 77)
2397 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 2);
2398 else if (objects[c1].frame == 78)
2399 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 3);
2401 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 0) {
2402 objects[c1].y_add += 3072;
2403 if (objects[c1].y_add > 196608L)
2404 objects[c1].y_add = 196608L;
2405 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 2) {
2406 if (objects[c1].x_add < 0) {
2407 if (objects[c1].x_add < -65536L)
2408 objects[c1].x_add = -65536L;
2409 objects[c1].x_add += 1024;
2410 if (objects[c1].x_add > 0)
2411 objects[c1].x_add = 0;
2413 if (objects[c1].x_add > 65536L)
2414 objects[c1].x_add = 65536L;
2415 objects[c1].x_add -= 1024;
2416 if (objects[c1].x_add < 0)
2417 objects[c1].x_add = 0;
2419 objects[c1].y_add += 1024;
2420 if (objects[c1].y_add < -65536L)
2421 objects[c1].y_add = -65536L;
2422 if (objects[c1].y_add > 65536L)
2423 objects[c1].y_add = 65536L;
2425 objects[c1].x += objects[c1].x_add;
2426 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)) {
2427 if (objects[c1].x_add < 0) {
2428 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2429 objects[c1].x_add = -objects[c1].x_add >> 2;
2431 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2432 objects[c1].x_add = -objects[c1].x_add >> 2;
2435 objects[c1].y += objects[c1].y_add;
2436 if ((objects[c1].x >> 16) < -5 || (objects[c1].x >> 16) > 405 || (objects[c1].y >> 16) > 260)
2437 objects[c1].used = 0;
2438 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0)) {
2439 if (objects[c1].y_add < 0) {
2440 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 2) {
2441 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2442 objects[c1].x_add >>= 2;
2443 objects[c1].y_add = -objects[c1].y_add >> 2;
2446 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1) {
2447 if (objects[c1].y_add > 131072L) {
2448 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2449 objects[c1].x_add >>= 2;
2450 objects[c1].y_add = -objects[c1].y_add >> 2;
2452 if (rnd(100) < 10) {
2454 add_leftovers(0, objects[c1].x >> 16, (objects[c1].y >> 16) + s1, objects[c1].frame, &object_gobs);
2455 add_leftovers(1, objects[c1].x >> 16, (objects[c1].y >> 16) + s1, objects[c1].frame, &object_gobs);
2457 objects[c1].used = 0;
2459 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3) {
2460 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2461 if (objects[c1].y_add > 131072L)
2462 objects[c1].y_add = -objects[c1].y_add >> 2;
2464 objects[c1].y_add = 0;
2468 if (objects[c1].x_add < 0 && objects[c1].x_add > -16384)
2469 objects[c1].x_add = -16384;
2470 if (objects[c1].x_add > 0 && objects[c1].x_add < 16384)
2471 objects[c1].x_add = 16384;
2472 if (objects[c1].used == 1)
2473 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].frame, &object_gobs);
2475 case OBJ_FLESH_TRACE:
2476 objects[c1].ticks--;
2477 if (objects[c1].ticks <= 0) {
2478 objects[c1].frame++;
2479 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2480 objects[c1].used = 0;
2482 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2483 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2486 if (objects[c1].used == 1)
2487 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2496 int add_pob(int page, int x, int y, int image, gob_t *pob_data)
2499 if (main_info.page_info[page].num_pobs >= NUM_POBS)
2502 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].x = x;
2503 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].y = y;
2504 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].image = image;
2505 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].pob_data = pob_data;
2506 main_info.page_info[page].num_pobs++;
2513 void draw_flies(int page)
2517 for (c2 = 0; c2 < NUM_FLIES; c2++) {
2518 flies[c2].back[main_info.draw_page] = get_pixel(main_info.draw_page, flies[c2].x, flies[c2].y);
2519 flies[c2].back_defined[main_info.draw_page] = 1;
2520 if (mask_pic[(flies[c2].y * JNB_WIDTH) + flies[c2].x] == 0)
2521 set_pixel(main_info.draw_page, flies[c2].x, flies[c2].y, 0);
2525 void draw_pobs(int page)
2532 for (c1 = main_info.page_info[page].num_pobs - 1; c1 >= 0; c1--) {
2533 main_info.page_info[page].pobs[c1].back_buf_ofs = back_buf_ofs;
2534 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);
2536 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 * bytes_per_pixel;
2538 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) * bytes_per_pixel;
2539 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);
2545 void redraw_flies_background(int page)
2549 for (c2 = NUM_FLIES - 1; c2 >= 0; c2--) {
2550 if (flies[c2].back_defined[page] == 1)
2551 set_pixel(page, flies[c2].old_draw_x, flies[c2].old_draw_y, flies[c2].back[page]);
2552 flies[c2].old_draw_x = flies[c2].x;
2553 flies[c2].old_draw_y = flies[c2].y;
2558 void redraw_pob_backgrounds(int page)
2562 for (c1 = 0; c1 < main_info.page_info[page].num_pobs; c1++)
2563 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);
2568 int add_leftovers(int page, int x, int y, int image, gob_t *pob_data)
2571 if (leftovers.page[page].num_pobs >= NUM_LEFTOVERS)
2574 leftovers.page[page].pobs[leftovers.page[page].num_pobs].x = x;
2575 leftovers.page[page].pobs[leftovers.page[page].num_pobs].y = y;
2576 leftovers.page[page].pobs[leftovers.page[page].num_pobs].image = image;
2577 leftovers.page[page].pobs[leftovers.page[page].num_pobs].pob_data = pob_data;
2578 leftovers.page[page].num_pobs++;
2585 void draw_leftovers(int page)
2589 for (c1 = leftovers.page[page].num_pobs - 1; c1 >= 0; c1--)
2590 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);
2592 leftovers.page[page].num_pobs = 0;
2597 int init_level(int level, char *pal)
2599 unsigned char *handle;
2603 if ((handle = dat_open("level.pcx", datfile_name, "rb")) == 0) {
2604 strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n");
2607 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
2608 strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n");
2612 flip_pixels(background_pic);
2613 if ((handle = dat_open("mask.pcx", datfile_name, "rb")) == 0) {
2614 strcpy(main_info.error_str, "Error loading 'mask.pcx', aborting...\n");
2617 if (read_pcx(handle, mask_pic, JNB_WIDTH*JNB_HEIGHT, 0) != 0) {
2618 strcpy(main_info.error_str, "Error loading 'mask.pcx', aborting...\n");
2622 flip_pixels(mask_pic);
2623 register_mask(mask_pic);
2625 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
2626 if (player[c1].enabled == 1) {
2627 player[c1].bumps = 0;
2628 for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++)
2629 player[c1].bumped[c2] = 0;
2630 position_player(c1);
2634 for (c1 = 0; c1 < NUM_OBJECTS; c1++)
2635 objects[c1].used = 0;
2637 for (c1 = 0; c1 < 16; c1++) {
2638 for (c2 = 0; c2 < 22; c2++) {
2639 if (ban_map[c1][c2] == BAN_SPRING)
2640 add_object(OBJ_SPRING, c2 << 4, c1 << 4, 0, 0, OBJ_ANIM_SPRING, 5);
2647 if (ban_map[s2][s1] == BAN_VOID) {
2648 add_object(OBJ_YEL_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2655 if (ban_map[s2][s1] == BAN_VOID) {
2656 add_object(OBJ_YEL_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2663 if (ban_map[s2][s1] == BAN_VOID) {
2664 add_object(OBJ_PINK_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2671 if (ban_map[s2][s1] == BAN_VOID) {
2672 add_object(OBJ_PINK_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2682 void deinit_level(void)
2690 #define PATH_MAX 1024
2696 unsigned char *datafile_buffer = NULL;
2698 static void preread_datafile(const char *fname)
2704 char *gzfilename = alloca(strlen(fname) + 4);
2709 strcpy(gzfilename, fname);
2710 strcat(gzfilename, ".gz");
2712 gzf = gzopen(gzfilename, "rb");
2717 if (bufpos >= bufsize) {
2718 bufsize += 1024 * 1024;
2719 datafile_buffer = (unsigned char *) realloc(datafile_buffer, bufsize);
2720 if (datafile_buffer == NULL) {
2721 perror("realloc()");
2726 br = gzread(gzf, datafile_buffer + bufpos, bufsize - bufpos);
2728 fprintf(stderr, "gzread failed.\n");
2733 } while (!gzeof(gzf));
2735 /* try to shrink buffer... */
2736 ptr = (unsigned char *) realloc(datafile_buffer, bufpos);
2738 datafile_buffer = ptr;
2744 /* drop through and try for an uncompressed datafile... */
2747 fd = open(fname, O_RDONLY | O_BINARY);
2749 fprintf(stderr, "can't open %s: %s\n", fname, strerror(errno));
2753 len = filelength(fd);
2754 datafile_buffer = (unsigned char *) malloc(len);
2755 if (datafile_buffer == NULL) {
2761 if (read(fd, datafile_buffer, len) != len) {
2771 int init_program(int argc, char *argv[], char *pal)
2773 char *netarg = NULL;
2774 unsigned char *handle = (unsigned char *) NULL;
2779 int player_anim_data[] = {
2780 1, 0, 0, 0x7fff, 0, 0, 0, 0, 0, 0,
2781 4, 0, 0, 4, 1, 4, 2, 4, 3, 4,
2782 1, 0, 4, 0x7fff, 0, 0, 0, 0, 0, 0,
2783 4, 2, 5, 8, 6, 10, 7, 3, 6, 3,
2784 1, 0, 6, 0x7fff, 0, 0, 0, 0, 0, 0,
2785 2, 1, 5, 8, 4, 0x7fff, 0, 0, 0, 0,
2786 1, 0, 8, 5, 0, 0, 0, 0, 0, 0
2790 memset(&net_info, 0, sizeof(net_info));
2794 if (__djgpp_nearptr_enable() == 0)
2800 if (hook_keyb_handler() != 0)
2803 memset(&main_info, 0, sizeof(main_info));
2805 strcpy(datfile_name, DATA_PATH);
2807 force2 = force3 = 0;
2810 for (c1 = 1; c1 < argc; c1++) {
2811 if (stricmp(argv[c1], "-nosound") == 0)
2812 main_info.no_sound = 1;
2813 else if (stricmp(argv[c1], "-musicnosound") == 0)
2814 main_info.music_no_sound = 1;
2815 else if (stricmp(argv[c1], "-nogore") == 0)
2816 main_info.no_gore = 1;
2817 else if (stricmp(argv[c1], "-noflies") == 0)
2819 else if (stricmp(argv[c1], "-nojoy") == 0)
2820 main_info.joy_enabled = 0;
2821 else if (stricmp(argv[c1], "-fireworks") == 0)
2822 main_info.fireworks = 1;
2824 else if (stricmp(argv[c1], "-fullscreen") == 0)
2827 else if (stricmp(argv[c1], "-scaleup") == 0)
2829 else if (stricmp(argv[c1], "-mirror") == 0)
2831 else if (stricmp(argv[c1], "-dat") == 0) {
2832 if (c1 < (argc - 1)) {
2835 if ((f = fopen(argv[c1 + 1], "rb")) != NULL) {
2837 strcpy(datfile_name, argv[c1 + 1]);
2840 } else if (stricmp(argv[c1], "-player") == 0) {
2841 if (c1 < (argc - 1)) {
2842 if (client_player_num < 0)
2843 client_player_num = atoi(argv[c1 + 1]);
2845 } else if (stricmp(argv[c1], "-server") == 0) {
2846 if (c1 < (argc - 1)) {
2849 netarg = argv[c1 + 1];
2851 } else if (stricmp(argv[c1], "-connect") == 0) {
2852 if (c1 < (argc - 1)) {
2855 netarg = argv[c1 + 1];
2857 } else if (stricmp(argv[c1], "-mouse") == 0) {
2858 if (c1 < (argc - 1)) {
2859 if (stricmp(argv[c1 + 1], "2") == 0)
2861 if (stricmp(argv[c1 + 1], "3") == 0)
2865 else if (strstr(argv[1],"-v")) {
2866 printf("jumpnbump %s compiled %s at %s with",JNB_VERSION,__DATE__,__TIME__);
2870 printf(" network support.\n");
2873 else if (strstr(argv[1],"-h")) {
2874 printf("Usage: jumpnbump [OPTION]...\n");
2876 printf(" -h this help\n");
2877 printf(" -v print version\n");
2878 printf(" -dat level.dat play a different level\n");
2879 printf(" -port port define listen port\n");
2880 printf(" -net player host rport define network players\n");
2881 printf(" -fireworks screensaver mode\n");
2882 printf(" -fullscreen run in fullscreen mode\n");
2883 printf(" -nosound play without sound\n");
2884 printf(" -nogore play without blood\n");
2885 printf(" -noflies disable flies\n");
2886 printf(" -mirror play with mirrored level\n");
2887 printf(" -scaleup play with doubled resolution (800x512)\n");
2888 printf(" -musicnosound play with music but without sound\n");
2895 preread_datafile(datfile_name);
2898 if (client_player_num < 0)
2899 client_player_num = 0;
2900 player[client_player_num].enabled = 1;
2903 main_info.pob_backbuf[0] = malloc(screen_pitch*screen_height*bytes_per_pixel);
2904 main_info.pob_backbuf[1] = malloc(screen_pitch*screen_height*bytes_per_pixel);
2906 for (c1 = 0; c1 < 7; c1++) {
2907 player_anims[c1].num_frames = player_anim_data[c1 * 10];
2908 player_anims[c1].restart_frame = player_anim_data[c1 * 10 + 1];
2909 for (c2 = 0; c2 < 4; c2++) {
2910 player_anims[c1].frame[c2].image = player_anim_data[c1 * 10 + c2 * 2 + 2];
2911 player_anims[c1].frame[c2].ticks = player_anim_data[c1 * 10 + c2 * 2 + 3];
2915 if ((handle = dat_open("menu.pcx", datfile_name, "rb")) == 0) {
2916 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
2919 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
2920 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
2924 if ((handle = dat_open("rabbit.gob", datfile_name, "rb")) == 0) {
2925 strcpy(main_info.error_str, "Error loading 'rabbit.gob', aborting...\n");
2928 if (register_gob(handle, &rabbit_gobs, dat_filelen("rabbit.gob", datfile_name))) {
2933 if ((handle = dat_open("objects.gob", datfile_name, "rb")) == 0) {
2934 strcpy(main_info.error_str, "Error loading 'objects.gob', aborting...\n");
2937 if (register_gob(handle, &object_gobs, dat_filelen("objects.gob", datfile_name))) {
2942 if ((handle = dat_open("font.gob", datfile_name, "rb")) == 0) {
2943 strcpy(main_info.error_str, "Error loading 'font.gob', aborting...\n");
2946 if (register_gob(handle, &font_gobs, dat_filelen("font.gob", datfile_name))) {
2951 if ((handle = dat_open("numbers.gob", datfile_name, "rb")) == 0) {
2952 strcpy(main_info.error_str, "Error loading 'numbers.gob', aborting...\n");
2955 if (register_gob(handle, &number_gobs, dat_filelen("numbers.gob", datfile_name))) {
2960 if (read_level() != 0) {
2961 strcpy(main_info.error_str, "Error loading 'levelmap.txt', aborting...\n");
2967 if (main_info.no_sound == 0) {
2969 dj_set_mixing_freq(20000);
2973 dj_set_num_sfx_channels(5);
2974 dj_set_sfx_volume(64);
2978 if ((handle = dat_open("jump.mod", datfile_name, "rb")) == 0) {
2979 strcpy(main_info.error_str, "Error loading 'jump.mod', aborting...\n");
2982 if (dj_load_mod(handle, 0, MOD_MENU) != 0) {
2983 strcpy(main_info.error_str, "Error loading 'jump.mod', aborting...\n");
2987 if ((handle = dat_open("bump.mod", datfile_name, "rb")) == 0) {
2988 strcpy(main_info.error_str, "Error loading 'bump.mod', aborting...\n");
2991 if (dj_load_mod(handle, 0, MOD_GAME) != 0) {
2992 strcpy(main_info.error_str, "Error loading 'bump.mod', aborting...\n");
2996 if ((handle = dat_open("scores.mod", datfile_name, "rb")) == 0) {
2997 strcpy(main_info.error_str, "Error loading 'scores.mod', aborting...\n");
3000 if (dj_load_mod(handle, 0, MOD_SCORES) != 0) {
3001 strcpy(main_info.error_str, "Error loading 'scores.mod', aborting...\n");
3005 if ((handle = dat_open("jump.smp", datfile_name, "rb")) == 0) {
3006 strcpy(main_info.error_str, "Error loading 'jump.smp', aborting...\n");
3009 if (dj_load_sfx(handle, 0, dat_filelen("jump.smp", datfile_name), DJ_SFX_TYPE_SMP, SFX_JUMP) != 0) {
3010 strcpy(main_info.error_str, "Error loading 'jump.smp', aborting...\n");
3014 if ((handle = dat_open("death.smp", datfile_name, "rb")) == 0) {
3015 strcpy(main_info.error_str, "Error loading 'death.smp', aborting...\n");
3018 if (dj_load_sfx(handle, 0, dat_filelen("death.smp", datfile_name), DJ_SFX_TYPE_SMP, SFX_DEATH) != 0) {
3019 strcpy(main_info.error_str, "Error loading 'death.smp', aborting...\n");
3023 if ((handle = dat_open("spring.smp", datfile_name, "rb")) == 0) {
3024 strcpy(main_info.error_str, "Error loading 'spring.smp', aborting...\n");
3027 if (dj_load_sfx(handle, 0, dat_filelen("spring.smp", datfile_name), DJ_SFX_TYPE_SMP, SFX_SPRING) != 0) {
3028 strcpy(main_info.error_str, "Error loading 'spring.smp', aborting...\n");
3032 if ((handle = dat_open("splash.smp", datfile_name, "rb")) == 0) {
3033 strcpy(main_info.error_str, "Error loading 'splash.smp', aborting...\n");
3036 if (dj_load_sfx(handle, 0, dat_filelen("splash.smp", datfile_name), DJ_SFX_TYPE_SMP, SFX_SPLASH) != 0) {
3037 strcpy(main_info.error_str, "Error loading 'splash.smp', aborting...\n");
3041 if ((handle = dat_open("fly.smp", datfile_name, "rb")) == 0) {
3042 strcpy(main_info.error_str, "Error loading 'fly.smp', aborting...\n");
3045 if (dj_load_sfx(handle, 0, dat_filelen("fly.smp", datfile_name), DJ_SFX_TYPE_SMP, SFX_FLY) != 0) {
3046 strcpy(main_info.error_str, "Error loading 'fly.smp', aborting...\n");
3050 dj_get_sfx_settings(SFX_FLY, &fly);
3052 fly.default_freq = SFX_FLY_FREQ;
3055 fly.loop_length = fly.length;
3056 dj_set_sfx_settings(SFX_FLY, &fly);
3059 if ((background_pic = malloc(JNB_WIDTH*JNB_HEIGHT)) == NULL)
3061 if ((mask_pic = malloc(JNB_WIDTH*JNB_HEIGHT)) == NULL)
3063 memset(mask_pic, 0, JNB_WIDTH*JNB_HEIGHT);
3064 register_mask(mask_pic);
3066 for (c1 = 0; c1 < 16; c1++) { // fix dark font
3067 pal[(240 + c1) * 3 + 0] = c1 << 2;
3068 pal[(240 + c1) * 3 + 1] = c1 << 2;
3069 pal[(240 + c1) * 3 + 2] = c1 << 2;
3072 setpalette(0, 256, pal);
3076 recalculate_gob(&font_gobs, pal);
3078 if (main_info.joy_enabled == 1 && main_info.fireworks == 0) {
3080 put_text(0, 200, 40, "JOYSTICK CALIBRATION", 2);
3081 put_text(0, 200, 100, "Move the joystick to the", 2);
3082 put_text(0, 200, 115, "UPPER LEFT", 2);
3083 put_text(0, 200, 130, "and press button A", 2);
3084 put_text(0, 200, 200, "Or press ESC to use", 2);
3085 put_text(0, 200, 215, "previous settings", 2);
3086 if (calib_joy(0) != 0)
3089 register_background(NULL, NULL);
3091 main_info.view_page = 1;
3096 put_text(1, 200, 40, "JOYSTICK CALIBRATION", 2);
3097 put_text(1, 200, 100, "Move the joystick to the", 2);
3098 put_text(1, 200, 115, "LOWER RIGHT", 2);
3099 put_text(1, 200, 130, "and press button A", 2);
3100 put_text(1, 200, 200, "Or press ESC to use", 2);
3101 put_text(1, 200, 215, "previous settings", 2);
3102 if (calib_joy(1) != 0)
3105 register_background(NULL, NULL);
3110 put_text(0, 200, 40, "JOYSTICK CALIBRATION", 2);
3111 put_text(0, 200, 100, "Move the joystick to the", 2);
3112 put_text(0, 200, 115, "CENTER", 2);
3113 put_text(0, 200, 130, "and press button A", 2);
3114 put_text(0, 200, 200, "Or press ESC to use", 2);
3115 put_text(0, 200, 215, "previous settings", 2);
3116 if (calib_joy(2) != 0)
3119 if (joy.calib_data.x1 == joy.calib_data.x2)
3120 joy.calib_data.x1 -= 10;
3121 if (joy.calib_data.x3 == joy.calib_data.x2)
3122 joy.calib_data.x3 += 10;
3123 if (joy.calib_data.y1 == joy.calib_data.y2)
3124 joy.calib_data.y1 -= 10;
3125 if (joy.calib_data.y3 == joy.calib_data.y2)
3126 joy.calib_data.y3 += 10;
3131 if (load_flag == 1) {
3132 if ((handle = dat_open("calib.dat", datfile_name, "rb")) == 0) {
3133 strcpy(main_info.error_str, "Error loading 'calib.dat', aborting...\n");
3136 joy.calib_data.x1 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3137 joy.calib_data.x2 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3138 joy.calib_data.x3 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3139 joy.calib_data.y1 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3140 joy.calib_data.y2 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3141 joy.calib_data.y3 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3148 init_server(netarg);
3150 connect_to_server(netarg);
3159 void deinit_program(void)
3166 dj_free_mod(MOD_MENU);
3167 dj_free_mod(MOD_GAME);
3168 dj_free_sfx(SFX_DEATH);
3169 dj_free_sfx(SFX_SPRING);
3170 dj_free_sfx(SFX_SPLASH);
3173 if (background_pic != 0)
3174 free(background_pic);
3178 remove_keyb_handler();
3182 __dpmi_int(0x10, ®s);
3185 if (main_info.error_str[0] != 0) {
3186 printf(main_info.error_str);
3188 MessageBox(0, main_info.error_str, "Jump'n'Bump", 0);
3197 unsigned short rnd(unsigned short max)
3199 return (rand() % max);
3203 int read_level(void)
3205 unsigned char *handle;
3209 if ((handle = dat_open("levelmap.txt", datfile_name, "rb")) == 0) {
3210 strcpy(main_info.error_str, "Error loading 'levelmap.txt', aborting...\n");
3214 for (c1 = 0; c1 < 16; c1++) {
3215 for (c2 = 0; c2 < 22; c2++) {
3217 chr = (int) *(handle++);
3218 if (chr >= '0' && chr <= '4')
3222 ban_map[c1][21-c2] = chr - '0';
3224 ban_map[c1][c2] = chr - '0';
3228 for (c2 = 0; c2 < 22; c2++)
3229 ban_map[16][c2] = BAN_SOLID;
3236 unsigned char *dat_open(char *file_name, char *dat_name, char *mode)
3244 if (datafile_buffer == NULL)
3247 memset(name, 0, sizeof(name));
3249 num = ( (datafile_buffer[0] << 0) +
3250 (datafile_buffer[1] << 8) +
3251 (datafile_buffer[2] << 16) +
3252 (datafile_buffer[3] << 24) );
3254 ptr = datafile_buffer + 4;
3256 for (c1 = 0; c1 < num; c1++) {
3258 memcpy(name, ptr, 12);
3261 if (strnicmp(name, file_name, strlen(file_name)) == 0) {
3262 ofs = ( (ptr[0] << 0) +
3267 return (datafile_buffer + ofs);
3276 int dat_filelen(char *file_name, char *dat_name)
3284 memset(name, 0, sizeof(name));
3286 num = ( (datafile_buffer[0] << 0) +
3287 (datafile_buffer[1] << 8) +
3288 (datafile_buffer[2] << 16) +
3289 (datafile_buffer[3] << 24) );
3291 ptr = datafile_buffer + 4;
3293 for (c1 = 0; c1 < num; c1++) {
3295 memcpy(name, ptr, 12);
3298 if (strnicmp(name, file_name, strlen(file_name)) == 0) {
3301 len = ( (ptr[0] << 0) +
3315 void write_calib_data(void)
3323 if ((handle = fopen(datfile_name, "rb")) == NULL)
3325 len = filelength(fileno(handle));
3326 if ((mem = malloc(len)) == NULL)
3328 fread(mem, 1, len, handle);
3332 num = *(int *) (&mem[0]);
3333 for (c1 = 0; c1 < num; c1++) {
3334 if (strnicmp(&mem[ofs], "calib.dat", strlen("calib.dat")) == 0) {
3335 ofs = *(int *) (&mem[ofs + 12]);
3341 mem[ofs] = joy.calib_data.x1 & 0xff;
3342 mem[ofs + 1] = (joy.calib_data.x1 >> 8) & 0xff;
3343 mem[ofs + 2] = (joy.calib_data.x1 >> 16) & 0xff;
3344 mem[ofs + 3] = (joy.calib_data.x1 >> 24) & 0xff;
3345 mem[ofs + 4] = joy.calib_data.x2 & 0xff;
3346 mem[ofs + 5] = (joy.calib_data.x2 >> 8) & 0xff;
3347 mem[ofs + 6] = (joy.calib_data.x2 >> 16) & 0xff;
3348 mem[ofs + 7] = (joy.calib_data.x2 >> 24) & 0xff;
3349 mem[ofs + 8] = joy.calib_data.x3 & 0xff;
3350 mem[ofs + 9] = (joy.calib_data.x3 >> 8) & 0xff;
3351 mem[ofs + 10] = (joy.calib_data.x3 >> 16) & 0xff;
3352 mem[ofs + 11] = (joy.calib_data.x3 >> 24) & 0xff;
3353 mem[ofs + 12] = joy.calib_data.y1 & 0xff;
3354 mem[ofs + 13] = (joy.calib_data.y1 >> 8) & 0xff;
3355 mem[ofs + 14] = (joy.calib_data.y1 >> 16) & 0xff;
3356 mem[ofs + 15] = (joy.calib_data.y1 >> 24) & 0xff;
3357 mem[ofs + 16] = joy.calib_data.y2 & 0xff;
3358 mem[ofs + 17] = (joy.calib_data.y2 >> 8) & 0xff;
3359 mem[ofs + 18] = (joy.calib_data.y2 >> 16) & 0xff;
3360 mem[ofs + 19] = (joy.calib_data.y2 >> 24) & 0xff;
3361 mem[ofs + 20] = joy.calib_data.y3 & 0xff;
3362 mem[ofs + 21] = (joy.calib_data.y3 >> 8) & 0xff;
3363 mem[ofs + 22] = (joy.calib_data.y3 >> 16) & 0xff;
3364 mem[ofs + 23] = (joy.calib_data.y3 >> 24) & 0xff;
3366 if ((handle = fopen(datfile_name, "wb")) == NULL)
3368 fwrite(mem, 1, len, handle);