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);
536 sendPacketToAll(&pkt);
538 sendPacketToSock(sock, &pkt);
545 void tellServerNewPosition(void)
548 pkt.cmd = NETCMD_POSITION;
549 pkt.arg = client_player_num;
550 pkt.arg2 = player[client_player_num].x;
551 pkt.arg3 = player[client_player_num].y;
554 sendPacketToAll(&pkt);
556 sendPacketToSock(sock, &pkt);
562 void processKillPacket(NetPacket *pkt)
571 player[c1].y_add = -player[c1].y_add;
572 if (player[c1].y_add > -262144L)
573 player[c1].y_add = -262144L;
574 player[c1].jump_abort = 1;
575 player[c2].dead_flag = 1;
576 if (player[c2].anim != 6) {
578 player[c2].frame = 0;
579 player[c2].frame_tick = 0;
580 player[c2].image = player_anims[player[c2].anim].frame[player[c2].frame].image + player[c2].direction * 9;
581 if (main_info.no_gore == 0) {
582 for (c4 = 0; c4 < 6; c4++)
583 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);
584 for (c4 = 0; c4 < 6; c4++)
585 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 76);
586 for (c4 = 0; c4 < 6; c4++)
587 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 77);
588 for (c4 = 0; c4 < 8; c4++)
589 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 78);
590 for (c4 = 0; c4 < 10; c4++)
591 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 79);
593 dj_play_sfx(SFX_DEATH, (unsigned short)(SFX_DEATH_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
595 player[c1].bumped[c2]++;
596 s1 = player[c1].bumps % 100;
597 add_leftovers(0, 360, 34 + c1 * 64, s1 / 10, &number_gobs);
598 add_leftovers(1, 360, 34 + c1 * 64, s1 / 10, &number_gobs);
599 add_leftovers(0, 376, 34 + c1 * 64, s1 - (s1 / 10) * 10, &number_gobs);
600 add_leftovers(1, 376, 34 + c1 * 64, s1 - (s1 / 10) * 10, &number_gobs);
606 void processPositionPacket(NetPacket *pkt)
608 int playerid = pkt->arg;
610 player[playerid].x = pkt->arg2;
611 player[playerid].y = pkt->arg3;
615 void processAlivePacket(NetPacket *pkt)
617 int playerid = pkt->arg;
619 player[playerid].dead_flag = 0;
620 player[playerid].x = pkt->arg2;
621 player[playerid].y = pkt->arg3;
625 void serverTellEveryoneGoodbye(void)
631 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
632 if (player[i].enabled) {
635 pkt.cmd = NETCMD_BYE;
640 sendPacketToAll(&pkt);
647 int server_said_bye = 0;
650 int update_players_from_server(void)
657 while ((rc = grabPacket(sock, &pkt)) != 0) {
659 printf("CLIENT: Lost connection.\n");
660 pkt.cmd = NETCMD_BYE;
661 pkt.arg = client_player_num;
664 if (pkt.cmd == NETCMD_BYE) {
665 if (pkt.arg == client_player_num) {
671 player[pkt.arg].enabled = 0;
673 } else if (pkt.cmd == NETCMD_MOVE) {
674 processMovePacket(&pkt);
675 } else if (pkt.cmd == NETCMD_ALIVE) {
676 processAlivePacket(&pkt);
677 } else if (pkt.cmd == NETCMD_POSITION) {
678 processPositionPacket(&pkt);
679 } else if (pkt.cmd == NETCMD_KILL) {
680 processKillPacket(&pkt);
682 printf("CLIENT: Got an unknown packet: 0x%lX.\n", pkt.cmd);
690 void serverSendAlive(int playerid)
695 pkt.cmd = NETCMD_ALIVE;
697 pkt.arg2 = player[playerid].x;
698 pkt.arg3 = player[playerid].y;
699 sendPacketToAll(&pkt);
704 void serverSendKillPacket(int killer, int victim)
709 pkt.cmd = NETCMD_KILL;
712 pkt.arg3 = player[victim].x;
713 pkt.arg4 = player[victim].y;
714 processKillPacket(&pkt);
716 sendPacketToAll(&pkt);
722 void update_players_from_clients(void)
731 while ((playerid = serverRecvPacket(&pkt)) >= 0) {
732 if (pkt.cmd == NETCMD_BYE) {
733 pkt.arg = playerid; /* just in case. */
734 sendPacketToAll(&pkt);
735 player[playerid].enabled = 0;
736 close(net_info[playerid].sock);
737 } else if (pkt.cmd == NETCMD_POSITION) {
738 pkt.arg = playerid; /* just in case. */
739 processPositionPacket(&pkt);
740 for (i = 0; i < (sizeof (net_info) / sizeof (net_info[0])); i++) {
745 } else if (pkt.cmd == NETCMD_MOVE) {
746 pkt.arg = playerid; /* just in case. */
747 //pkt.arg3 = player[playerid].x;
748 //pkt.arg4 = player[playerid].y;
749 processMovePacket(&pkt);
750 sendPacketToAll(&pkt);
752 printf("SERVER: Got unknown packet (0x%lX).\n", pkt.cmd);
759 void init_server(const char *netarg)
764 struct hostent *hent;
765 struct sockaddr_in addr;
766 struct in_addr inaddr;
768 int wait_for_clients = ((netarg == NULL) ? 0 : atoi(netarg));
770 WORD wVersionRequested;
774 wVersionRequested = MAKEWORD( 2, 2 );
776 err = WSAStartup( wVersionRequested, &wsaData );
778 /* Tell the user that we could not find a usable */
780 fprintf(stderr, "SERVER: WSAStartup failed!");
785 if ((wait_for_clients > (JNB_MAX_PLAYERS - 1)) || (wait_for_clients < 0)) {
786 printf("SERVER: Waiting for bogus client count (%d).\n", wait_for_clients);
790 sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
792 fprintf(stderr, "SERVER: socket(): %i", net_error);
793 //perror("SERVER: socket()");
797 memset(&addr, '\0', sizeof (addr));
798 addr.sin_family = AF_INET;
799 addr.sin_port = htons(JNB_INETPORT);
800 addr.sin_addr.s_addr = INADDR_ANY;
801 if (bind(sock, (struct sockaddr *) &addr,
802 sizeof (addr)) == -1) {
803 fprintf(stderr, "SERVER: bind(): %i", net_error);
804 //perror("SERVER: bind()");
809 if (listen(sock, wait_for_clients) == -1) {
810 fprintf(stderr, "SERVER: listen(): %i", net_error);
811 //perror("SERVER: listen()");
816 player[client_player_num].enabled = 1;
818 gethostname(ipstr, sizeof (ipstr));
819 hent = gethostbyname(ipstr);
821 memcpy(&inaddr, hent->h_addr, hent->h_length);
822 strncpy(ipstr, inet_ntoa(inaddr), sizeof (ipstr));
825 printf("SERVER: we are [%s].\n", ipstr);
827 addr.sin_addr.s_addr = inaddr.s_addr;
828 addr.sin_family = AF_INET;
829 addr.sin_port = htons(JNB_INETPORT);
830 net_info[client_player_num].addr = malloc(sizeof (addr));
831 memcpy(net_info[client_player_num].addr, &addr, sizeof (addr));
832 net_info[client_player_num].addrlen = sizeof (addr);
833 /*gettimeofday(&net_info[client_player_num].last_timestamp, NULL);*/
835 printf("SERVER: waiting for (%d) clients...\n", wait_for_clients);
837 while (wait_for_clients > 0)
839 char buf[NETPKTBUFSIZE];
840 struct sockaddr_in from;
841 int fromlen = sizeof (from);
846 s = accept(sock, (struct sockaddr *) &from, &fromlen);
849 fprintf(stderr, "SERVER: accept(): %i", net_error);
850 //perror("SERVER: accept()");
855 br = recv(s, buf, NETPKTBUFSIZE, 0);
857 fprintf(stderr, "SERVER: recv(): %i", net_error);
863 strncpy(ipstr, inet_ntoa(from.sin_addr), sizeof (ipstr));
864 printf("SERVER: Got data from [%s].\n", ipstr);
866 if (br != NETPKTBUFSIZE) {
867 printf("SERVER: Bogus packet.\n");
871 bufToPacket(buf, &pkt);
872 if (pkt.cmd != NETCMD_HELLO) {
873 printf("SERVER: Bogus packet.\n");
877 printf("SERVER: Client claims to be player #%ld.\n", pkt.arg);
879 if (pkt.arg > (sizeof (player) / sizeof (player[0]))) {
880 printf("SERVER: (that's an invalid player number.)\n");
882 if (player[pkt.arg].enabled) {
883 printf("SERVER: (that player number is already taken.)\n");
890 printf("SERVER: Forbidding connection.\n");
891 pkt.cmd = NETCMD_NACK;
892 sendPacketToSock(s, &pkt);
895 player[pkt.arg].enabled = 1;
896 net_info[pkt.arg].sock = s;
897 net_info[pkt.arg].addr = malloc(fromlen);
898 memcpy(net_info[pkt.arg].addr, &from, fromlen);
899 net_info[pkt.arg].addrlen = fromlen;
900 /*memcpy(&net_info[pkt.arg].last_timestamp, &pkt.timestamp, sizeof (pkt.timestamp));*/
902 printf("SERVER: Granting connection. (%d) to go.\n", wait_for_clients);
903 pkt.cmd = NETCMD_ACK;
904 sendPacket(pkt.arg, &pkt);
908 close(sock); /* done with the listen socket. */
911 printf("SERVER: Got all our connections. Greenlighting clients...\n");
913 pkt.cmd = NETCMD_GREENLIGHT;
915 for (i = 0; i < (sizeof (net_info) / sizeof (net_info[0])); i++) {
916 if (player[i].enabled) {
920 sendPacketToAll(&pkt);
925 void connect_to_server(char *netarg)
929 char buf[NETPKTBUFSIZE];
931 struct hostent *hent;
932 struct sockaddr_in addr;
933 struct in_addr inaddr;
937 WORD wVersionRequested;
941 wVersionRequested = MAKEWORD( 2, 2 );
943 err = WSAStartup( wVersionRequested, &wsaData );
945 /* Tell the user that we could not find a usable */
947 fprintf(stderr, "SERVER: WSAStartup failed!");
952 if (netarg == NULL) {
953 printf("CLIENT: Need to specify host to connect to.\n");
957 player[client_player_num].enabled = 1;
958 gethostname(ipstr, sizeof (ipstr));
959 hent = gethostbyname(ipstr);
961 net_info[client_player_num].addr = malloc(hent->h_length);
962 memcpy(&net_info[client_player_num].addr, &hent->h_addr, hent->h_length);
963 net_info[client_player_num].addrlen = hent->h_length;
964 memcpy(&inaddr, hent->h_addr, hent->h_length);
965 strncpy(ipstr, inet_ntoa(inaddr), sizeof (ipstr));
967 printf("CLIENT: we are [%s].\n", ipstr);
969 /*gettimeofday(&net_info[client_player_num].last_timestamp, NULL);*/
971 hent = gethostbyname(netarg);
973 fprintf(stderr, "CLIENT: couldn't find host: %i", net_error);
974 //perror("CLIENT: couldn't find host");
978 sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
980 fprintf(stderr, "CLIENT: socket(): %i", net_error);
981 //perror("CLIENT: socket()");
985 memcpy(&inaddr, hent->h_addr, hent->h_length);
986 printf("CLIENT: connecting to [%s]...\n", inet_ntoa(inaddr));
988 addr.sin_family = AF_INET;
989 addr.sin_port = htons(JNB_INETPORT);
990 memcpy(&addr.sin_addr.s_addr, hent->h_addr, hent->h_length);
991 if (connect(sock, (struct sockaddr *) &addr, sizeof (addr)) == -1) {
992 fprintf(stderr, "CLIENT: connect(): %i", net_error);
993 //perror("CLIENT: connect()");
997 printf("CLIENT: Got socket. Sending HELLO packet...\n");
998 pkt.cmd = NETCMD_HELLO;
999 pkt.arg = client_player_num;
1000 sendPacketToSock(sock, &pkt);
1002 printf("CLIENT: Waiting for ACK from server...\n");
1004 addrlen = sizeof (addr);
1005 br = recv(sock, buf, NETPKTBUFSIZE, 0);
1007 fprintf(stderr, "CLIENT: recv(): %i", net_error);
1008 //perror("CLIENT: recv()");
1013 if (br != NETPKTBUFSIZE) {
1014 printf("CLIENT: Bogus packet size (%d of %d). FIXME.\n",
1020 bufToPacket(buf, &pkt);
1022 if (pkt.cmd == NETCMD_NACK) {
1023 printf("CLIENT: Server forbid us from playing.\n");
1028 if (pkt.cmd != NETCMD_ACK) {
1029 printf("CLIENT: Unexpected packet (cmd=0x%lX).\n", pkt.cmd);
1034 printf("CLIENT: Server accepted our connection.\n");
1036 wait_for_greenlight();
1042 static flip_pixels(unsigned char *pixels)
1048 for (y = 0; y < JNB_HEIGHT; y++) {
1049 for (x = 0; x < (352/2); x++) {
1050 temp = pixels[y*JNB_WIDTH+x];
1051 pixels[y*JNB_WIDTH+x] = pixels[y*JNB_WIDTH+(352-x)-1];
1052 pixels[y*JNB_WIDTH+(352-x)-1] = temp;
1058 int main(int argc, char *argv[])
1060 unsigned char *handle;
1061 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
1064 int closest_player = 0, dist, cur_dist = 0;
1065 int end_loop_flag = 0, fade_flag;
1066 int mod_vol, sfx_vol, mod_fade_direction;
1072 if (init_program(argc, argv, pal) != 0)
1075 if (main_info.fireworks == 1) {
1086 if (key_pressed(1) == 1) {
1089 if (init_level(0, pal) != 0) {
1094 memset(cur_pal, 0, 768);
1095 setpalette(0, 256, cur_pal);
1097 recalculate_gob(&rabbit_gobs, pal);
1098 //recalculate_gob(&font_gobs, pal);
1099 recalculate_gob(&object_gobs, pal);
1100 recalculate_gob(&number_gobs, pal);
1103 register_background(background_pic, pal);
1106 if (flies_enabled) {
1110 for (c1 = 0; c1 < NUM_FLIES; c1++) {
1112 flies[c1].x = s1 + rnd(101) - 50;
1113 flies[c1].y = s2 + rnd(101) - 50;
1114 if (ban_map[flies[c1].y >> 4][flies[c1].x >> 4] == BAN_VOID)
1117 flies[c1].back_defined[0] = 0;
1118 flies[c1].back_defined[1] = 0;
1122 mod_vol = sfx_vol = 10;
1123 mod_fade_direction = 1;
1124 dj_ready_mod(MOD_GAME);
1125 dj_set_mod_volume((char)mod_vol);
1126 dj_set_sfx_volume((char)mod_vol);
1130 dj_play_sfx(SFX_FLY, SFX_FLY_FREQ, 0, 0, 0, 4);
1134 lord_of_the_flies = bunnies_in_space = jetpack = pogostick = blood_is_thicker_than_water = 0;
1136 main_info.page_info[0].num_pobs = 0;
1137 main_info.page_info[1].num_pobs = 0;
1138 main_info.view_page = 0;
1139 main_info.draw_page = 1;
1143 while (update_count) {
1145 if (key_pressed(1) == 1) {
1148 serverTellEveryoneGoodbye();
1150 tellServerGoodbye();
1154 memset(pal, 0, 768);
1155 mod_fade_direction = 0;
1158 if (strncmp(last_keys, "kcitsogop", strlen("kcitsogop")) == 0) {
1162 if (strncmp(last_keys, "ecapsniseinnub", strlen("ecapsniseinnub")) == 0) {
1163 bunnies_in_space ^= 1;
1166 if (strncmp(last_keys, "kcaptej", strlen("kcaptej")) == 0) {
1170 if (strncmp(last_keys, "seilfehtfodrol", strlen("seilfehtfodrol")) == 0) {
1171 lord_of_the_flies ^= 1;
1174 if (strncmp(last_keys, "retawnahtrekcihtsidoolb", strlen("retawnahtrekcihtsidoolb")) == 0) {
1175 blood_is_thicker_than_water ^= 1;
1176 if (blood_is_thicker_than_water == 1) {
1227 register_background(background_pic, pal);
1228 recalculate_gob(&object_gobs, pal);
1234 update_players_from_clients();
1236 if (!update_players_from_server()) {
1237 break; /* got a BYE packet */
1246 for (c3 = 0; c3 < 6; c3++) {
1250 } else if (c3 == 1) {
1253 } else if (c3 == 2) {
1256 } else if (c3 == 3) {
1259 } else if (c3 == 4) {
1262 } else if (c3 == 5) {
1266 if (player[c1].enabled == 1 && player[c2].enabled == 1) {
1267 if (labs(player[c1].x - player[c2].x) < (12L << 16) && labs(player[c1].y - player[c2].y) < (12L << 16)) {
1268 if ((labs(player[c1].y - player[c2].y) >> 16) > 5) {
1269 if (player[c1].y < player[c2].y) {
1270 if (player[c1].y_add >= 0) {
1272 serverSendKillPacket(c1, c2);
1274 if (player[c2].y_add < 0)
1275 player[c2].y_add = 0;
1278 if (player[c2].y_add >= 0) {
1280 serverSendKillPacket(c2, c1);
1282 if (player[c1].y_add < 0)
1283 player[c1].y_add = 0;
1287 if (player[c1].x < player[c2].x) {
1288 if (player[c1].x_add > 0)
1289 player[c1].x = player[c2].x - (12L << 16);
1290 else if (player[c2].x_add < 0)
1291 player[c2].x = player[c1].x + (12L << 16);
1293 player[c1].x -= player[c1].x_add;
1294 player[c2].x -= player[c2].x_add;
1296 l1 = player[c2].x_add;
1297 player[c2].x_add = player[c1].x_add;
1298 player[c1].x_add = l1;
1299 if (player[c1].x_add > 0)
1300 player[c1].x_add = -player[c1].x_add;
1301 if (player[c2].x_add < 0)
1302 player[c2].x_add = -player[c2].x_add;
1304 if (player[c1].x_add > 0)
1305 player[c2].x = player[c1].x - (12L << 16);
1306 else if (player[c2].x_add < 0)
1307 player[c1].x = player[c2].x + (12L << 16);
1309 player[c1].x -= player[c1].x_add;
1310 player[c2].x -= player[c2].x_add;
1312 l1 = player[c2].x_add;
1313 player[c2].x_add = player[c1].x_add;
1314 player[c1].x_add = l1;
1315 if (player[c1].x_add < 0)
1316 player[c1].x_add = -player[c1].x_add;
1317 if (player[c2].x_add > 0)
1318 player[c2].x_add = -player[c2].x_add;
1327 main_info.page_info[main_info.draw_page].num_pobs = 0;
1328 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1329 if (player[c1].enabled == 1)
1330 main_info.page_info[main_info.draw_page].num_pobs++;
1337 if (flies_enabled) {
1338 /* get center of fly swarm */
1340 for (c1 = 0; c1 < NUM_FLIES; c1++) {
1347 if (update_count == 1) {
1348 /* get closest player to fly swarm */
1350 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1351 if (player[c1].enabled == 1) {
1352 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)));
1353 if (cur_dist < dist) {
1354 closest_player = c1;
1359 /* update fly swarm sound */
1363 dj_set_sfx_channel_volume(4, (char)(s3));
1366 for (c1 = 0; c1 < NUM_FLIES; c1++) {
1367 /* get closest player to fly */
1369 for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++) {
1370 if (player[c2].enabled == 1) {
1371 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)));
1372 if (cur_dist < dist) {
1373 closest_player = c2;
1378 flies[c1].old_x = flies[c1].x;
1379 flies[c1].old_y = flies[c1].y;
1381 if ((s1 - flies[c1].x) > 30)
1383 else if ((s1 - flies[c1].x) < -30)
1386 if (((player[closest_player].x >> 16) + 8) > flies[c1].x) {
1387 if (lord_of_the_flies == 0)
1392 if (lord_of_the_flies == 0)
1398 s4 = rnd(3) - 1 + s3;
1399 if ((flies[c1].x + s4) < 16)
1401 if ((flies[c1].x + s4) > 351)
1403 if (ban_map[flies[c1].y >> 4][(flies[c1].x + s4) >> 4] != BAN_VOID)
1407 if ((s2 - flies[c1].y) > 30)
1409 else if ((s2 - flies[c1].y) < -30)
1412 if (((player[closest_player].y >> 16) + 8) > flies[c1].y) {
1413 if (lord_of_the_flies == 0)
1418 if (lord_of_the_flies == 0)
1424 s4 = rnd(3) - 1 + s3;
1425 if ((flies[c1].y + s4) < 0)
1427 if ((flies[c1].y + s4) > 239)
1429 if (ban_map[(flies[c1].y + s4) >> 4][flies[c1].x >> 4] != BAN_VOID)
1438 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1439 if (player[c1].enabled == 1) {
1440 main_info.page_info[main_info.draw_page].pobs[s1].x = player[c1].x >> 16;
1441 main_info.page_info[main_info.draw_page].pobs[s1].y = player[c1].y >> 16;
1442 main_info.page_info[main_info.draw_page].pobs[s1].image = player[c1].image + c1 * 18;
1443 main_info.page_info[main_info.draw_page].pobs[s1].pob_data = &rabbit_gobs;
1448 if (update_count == 1) {
1451 draw_pobs(main_info.draw_page);
1456 draw_flies(main_info.draw_page);
1461 if (mod_fade_direction == 1) {
1464 dj_set_mod_volume((char)mod_vol);
1469 dj_set_mod_volume((char)mod_vol);
1473 if (mod_fade_direction == 1) {
1476 dj_set_sfx_volume((char)sfx_vol);
1481 dj_set_sfx_volume((char)sfx_vol);
1486 for (c1 = 0; c1 < 768; c1++) {
1487 if (cur_pal[c1] < pal[c1]) {
1490 } else if (cur_pal[c1] > pal[c1]) {
1495 if (fade_flag == 0 && end_loop_flag == 1)
1498 if (update_count == 1) {
1499 main_info.draw_page ^= 1;
1500 main_info.view_page ^= 1;
1502 flippage(main_info.view_page);
1508 setpalette(0, 256, cur_pal);
1510 if (update_count == 1) {
1514 redraw_flies_background(main_info.draw_page);
1516 redraw_pob_backgrounds(main_info.draw_page);
1518 draw_leftovers(main_info.draw_page);
1527 if ( (player[client_player_num].dead_flag == 0) &&
1529 (player[client_player_num].action_left) ||
1530 (player[client_player_num].action_right) ||
1531 (player[client_player_num].action_up) ||
1532 (player[client_player_num].jump_ready == 0)
1535 tellServerNewPosition();
1539 update_count = intr_sysupdate();
1542 if ((server_said_bye) || ((fade_flag == 0) && (end_loop_flag == 1)))
1545 if ((fade_flag == 0) && (end_loop_flag == 1))
1552 serverTellEveryoneGoodbye();
1556 if (!server_said_bye) {
1557 tellServerGoodbye();
1565 main_info.view_page = 0;
1566 main_info.draw_page = 1;
1568 dj_stop_sfx_channel(4);
1572 memset(mask_pic, 0, JNB_WIDTH*JNB_HEIGHT);
1573 register_mask(mask_pic);
1575 //recalculate_gob(&font_gobs, pal);
1576 register_background(NULL, NULL);
1580 put_text(main_info.view_page, 100, 50, "DOTT", 2);
1581 put_text(main_info.view_page, 160, 50, "JIFFY", 2);
1582 put_text(main_info.view_page, 220, 50, "FIZZ", 2);
1583 put_text(main_info.view_page, 280, 50, "MIJJI", 2);
1584 put_text(main_info.view_page, 40, 80, "DOTT", 2);
1585 put_text(main_info.view_page, 40, 110, "JIFFY", 2);
1586 put_text(main_info.view_page, 40, 140, "FIZZ", 2);
1587 put_text(main_info.view_page, 40, 170, "MIJJI", 2);
1589 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1590 for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++) {
1592 sprintf(str1, "%d", player[c1].bumped[c2]);
1593 put_text(main_info.view_page, 100 + c2 * 60, 80 + c1 * 30, str1, 2);
1595 put_text(main_info.view_page, 100 + c2 * 60, 80 + c1 * 30, "-", 2);
1597 sprintf(str1, "%d", player[c1].bumps);
1598 put_text(main_info.view_page, 350, 80 + c1 * 30, str1, 2);
1601 put_text(main_info.view_page, 200, 230, "Press ESC to continue", 2);
1605 flippage(main_info.view_page);
1607 if ((handle = dat_open("menu.pcx", datfile_name, "rb")) == 0) {
1608 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
1611 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
1612 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
1616 for (c1 = 0; c1 < 16; c1++) { // fix dark font
1617 pal[(240 + c1) * 3 + 0] = c1 << 2;
1618 pal[(240 + c1) * 3 + 1] = c1 << 2;
1619 pal[(240 + c1) * 3 + 2] = c1 << 2;
1622 memset(cur_pal, 0, 768);
1624 setpalette(0, 256, cur_pal);
1627 dj_ready_mod(MOD_SCORES);
1628 dj_set_mod_volume((char)mod_vol);
1632 while (key_pressed(1) == 0) {
1635 dj_set_mod_volume((char)mod_vol);
1636 for (c1 = 0; c1 < 768; c1++) {
1637 if (cur_pal[c1] < pal[c1])
1643 setpalette(0, 256, cur_pal);
1644 flippage(main_info.view_page);
1646 while (key_pressed(1) == 1) {
1651 memset(pal, 0, 768);
1653 while (mod_vol > 0) {
1655 dj_set_mod_volume((char)mod_vol);
1656 for (c1 = 0; c1 < 768; c1++) {
1657 if (cur_pal[c1] > pal[c1])
1662 setpalette(0, 256, cur_pal);
1663 flippage(main_info.view_page);
1666 fillpalette(0, 0, 0);
1672 break; /* don't go back to menu if in net game. */
1681 void steer_players(void)
1686 update_player_actions();
1688 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1690 if (player[c1].enabled == 1) {
1692 if (player[c1].dead_flag == 0) {
1694 if (player[c1].action_left && player[c1].action_right) {
1695 if (player[c1].direction == 0) {
1696 if (player[c1].action_right) {
1697 s1 = (player[c1].x >> 16);
1698 s2 = (player[c1].y >> 16);
1699 if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) {
1700 if (player[c1].x_add < 0)
1701 player[c1].x_add += 1024;
1703 player[c1].x_add += 768;
1704 } 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)) {
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 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == 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 if (player[c1].action_left) {
1729 s1 = (player[c1].x >> 16);
1730 s2 = (player[c1].y >> 16);
1731 if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) {
1732 if (player[c1].x_add > 0)
1733 player[c1].x_add -= 1024;
1735 player[c1].x_add -= 768;
1736 } 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)) {
1737 if (player[c1].x_add > 0)
1738 player[c1].x_add -= 1024;
1740 player[c1].x_add -= 768;
1742 if (player[c1].x_add > 0) {
1743 player[c1].x_add -= 16384;
1744 if (player[c1].x_add > -98304L && player[c1].in_water == 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1745 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);
1747 player[c1].x_add -= 12288;
1749 if (player[c1].x_add < -98304L)
1750 player[c1].x_add = -98304L;
1751 player[c1].direction = 1;
1752 if (player[c1].anim == 0) {
1753 player[c1].anim = 1;
1754 player[c1].frame = 0;
1755 player[c1].frame_tick = 0;
1756 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1760 } else if (player[c1].action_left) {
1761 s1 = (player[c1].x >> 16);
1762 s2 = (player[c1].y >> 16);
1763 if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) {
1764 if (player[c1].x_add > 0)
1765 player[c1].x_add -= 1024;
1767 player[c1].x_add -= 768;
1768 } 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)) {
1769 if (player[c1].x_add > 0)
1770 player[c1].x_add -= 1024;
1772 player[c1].x_add -= 768;
1774 if (player[c1].x_add > 0) {
1775 player[c1].x_add -= 16384;
1776 if (player[c1].x_add > -98304L && player[c1].in_water == 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1777 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);
1779 player[c1].x_add -= 12288;
1781 if (player[c1].x_add < -98304L)
1782 player[c1].x_add = -98304L;
1783 player[c1].direction = 1;
1784 if (player[c1].anim == 0) {
1785 player[c1].anim = 1;
1786 player[c1].frame = 0;
1787 player[c1].frame_tick = 0;
1788 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1790 } else if (player[c1].action_right) {
1791 s1 = (player[c1].x >> 16);
1792 s2 = (player[c1].y >> 16);
1793 if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) {
1794 if (player[c1].x_add < 0)
1795 player[c1].x_add += 1024;
1797 player[c1].x_add += 768;
1798 } 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)) {
1799 if (player[c1].x_add > 0)
1800 player[c1].x_add += 1024;
1802 player[c1].x_add += 768;
1804 if (player[c1].x_add < 0) {
1805 player[c1].x_add += 16384;
1806 if (player[c1].x_add < 98304L && player[c1].in_water == 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1807 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);
1809 player[c1].x_add += 12288;
1811 if (player[c1].x_add > 98304L)
1812 player[c1].x_add = 98304L;
1813 player[c1].direction = 0;
1814 if (player[c1].anim == 0) {
1815 player[c1].anim = 1;
1816 player[c1].frame = 0;
1817 player[c1].frame_tick = 0;
1818 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1820 } else if ((!player[c1].action_left) && (!player[c1].action_right)) {
1821 s1 = (player[c1].x >> 16);
1822 s2 = (player[c1].y >> 16);
1823 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)))) {
1824 if (player[c1].x_add < 0) {
1825 player[c1].x_add += 16384;
1826 if (player[c1].x_add > 0)
1827 player[c1].x_add = 0;
1829 player[c1].x_add -= 16384;
1830 if (player[c1].x_add < 0)
1831 player[c1].x_add = 0;
1833 if (player[c1].x_add != 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1834 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);
1836 if (player[c1].anim == 1) {
1837 player[c1].anim = 0;
1838 player[c1].frame = 0;
1839 player[c1].frame_tick = 0;
1840 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1844 if (pogostick == 1 || (player[c1].jump_ready == 1 && player[c1].action_up)) {
1845 s1 = (player[c1].x >> 16);
1846 s2 = (player[c1].y >> 16);
1849 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) {
1850 player[c1].y_add = -280000L;
1851 player[c1].anim = 2;
1852 player[c1].frame = 0;
1853 player[c1].frame_tick = 0;
1854 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1855 player[c1].jump_ready = 0;
1856 player[c1].jump_abort = 1;
1858 dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1860 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1862 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)) {
1863 player[c1].y_add = -196608L;
1864 player[c1].in_water = 0;
1865 player[c1].anim = 2;
1866 player[c1].frame = 0;
1867 player[c1].frame_tick = 0;
1868 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1869 player[c1].jump_ready = 0;
1870 player[c1].jump_abort = 1;
1872 dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1874 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1877 if (pogostick == 0 && (!player[c1].action_up)) {
1878 player[c1].jump_ready = 1;
1879 if (player[c1].in_water == 0 && player[c1].y_add < 0 && player[c1].jump_abort == 1) {
1880 if (bunnies_in_space == 0)
1881 player[c1].y_add += 32768;
1883 player[c1].y_add += 16384;
1884 if (player[c1].y_add > 0)
1885 player[c1].y_add = 0;
1890 if (player[c1].action_up) {
1891 player[c1].y_add -= 16384;
1892 if (player[c1].y_add < -400000L)
1893 player[c1].y_add = -400000L;
1894 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))
1895 player[c1].in_water = 0;
1897 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);
1902 player[c1].x += player[c1].x_add;
1903 if ((player[c1].x >> 16) < 0) {
1905 player[c1].x_add = 0;
1907 if ((player[c1].x >> 16) + 15 > 351) {
1908 player[c1].x = 336L << 16;
1909 player[c1].x_add = 0;
1911 if (player[c1].y > 0) {
1912 s1 = (player[c1].x >> 16);
1913 s2 = (player[c1].y >> 16);
1914 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) {
1915 player[c1].x = (((s1 + 16) & 0xfff0)) << 16;
1916 player[c1].x_add = 0;
1918 s1 = (player[c1].x >> 16);
1919 s2 = (player[c1].y >> 16);
1920 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) {
1921 player[c1].x = (((s1 + 16) & 0xfff0) - 16) << 16;
1922 player[c1].x_add = 0;
1925 s1 = (player[c1].x >> 16);
1927 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) {
1928 player[c1].x = (((s1 + 16) & 0xfff0)) << 16;
1929 player[c1].x_add = 0;
1931 s1 = (player[c1].x >> 16);
1933 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) {
1934 player[c1].x = (((s1 + 16) & 0xfff0) - 16) << 16;
1935 player[c1].x_add = 0;
1939 player[c1].y += player[c1].y_add;
1941 s1 = (player[c1].x >> 16);
1942 s2 = (player[c1].y >> 16);
1943 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))) {
1944 player[c1].y = ((player[c1].y >> 16) & 0xfff0) << 16;
1945 player[c1].y_add = -400000L;
1946 player[c1].anim = 2;
1947 player[c1].frame = 0;
1948 player[c1].frame_tick = 0;
1949 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1950 player[c1].jump_ready = 0;
1951 player[c1].jump_abort = 0;
1952 for (c2 = 0; c2 < NUM_OBJECTS; c2++) {
1953 if (objects[c2].used == 1 && objects[c2].type == OBJ_SPRING) {
1954 if (ban_map[(s2 + 15) >> 4][(s1 + 8) >> 4] == BAN_SPRING) {
1955 if ((objects[c2].x >> 20) == ((s1 + 8) >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
1956 objects[c2].frame = 0;
1957 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
1958 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
1962 if (ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SPRING) {
1963 if ((objects[c2].x >> 20) == (s1 >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
1964 objects[c2].frame = 0;
1965 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
1966 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
1969 } else if (ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SPRING) {
1970 if ((objects[c2].x >> 20) == ((s1 + 15) >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
1971 objects[c2].frame = 0;
1972 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
1973 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
1980 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1982 s1 = (player[c1].x >> 16);
1983 s2 = (player[c1].y >> 16);
1986 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) {
1987 player[c1].y = (((s2 + 16) & 0xfff0)) << 16;
1988 player[c1].y_add = 0;
1989 player[c1].anim = 0;
1990 player[c1].frame = 0;
1991 player[c1].frame_tick = 0;
1992 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1994 s1 = (player[c1].x >> 16);
1995 s2 = (player[c1].y >> 16);
1998 if (ban_map[(s2 + 8) >> 4][(s1 + 8) >> 4] == BAN_WATER) {
1999 if (player[c1].in_water == 0) {
2000 player[c1].in_water = 1;
2001 player[c1].anim = 4;
2002 player[c1].frame = 0;
2003 player[c1].frame_tick = 0;
2004 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2005 if (player[c1].y_add >= 32768) {
2006 add_object(OBJ_SPLASH, (player[c1].x >> 16) + 8, ((player[c1].y >> 16) & 0xfff0) + 15, 0, 0, OBJ_ANIM_SPLASH, 0);
2007 if (blood_is_thicker_than_water == 0)
2008 dj_play_sfx(SFX_SPLASH, (unsigned short)(SFX_SPLASH_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
2010 dj_play_sfx(SFX_SPLASH, (unsigned short)(SFX_SPLASH_FREQ + rnd(2000) - 5000), 64, 0, 0, -1);
2013 player[c1].y_add -= 1536;
2014 if (player[c1].y_add < 0 && player[c1].anim != 5) {
2015 player[c1].anim = 5;
2016 player[c1].frame = 0;
2017 player[c1].frame_tick = 0;
2018 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2020 if (player[c1].y_add < -65536L)
2021 player[c1].y_add = -65536L;
2022 if (player[c1].y_add > 65535L)
2023 player[c1].y_add = 65535L;
2024 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) {
2025 player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16;
2026 player[c1].y_add = 0;
2028 } 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) {
2029 player[c1].in_water = 0;
2030 player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16;
2031 player[c1].y_add = 0;
2032 if (player[c1].anim != 0 && player[c1].anim != 1) {
2033 player[c1].anim = 0;
2034 player[c1].frame = 0;
2035 player[c1].frame_tick = 0;
2036 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2039 if (player[c1].in_water == 0) {
2040 if (bunnies_in_space == 0)
2041 player[c1].y_add += 12288;
2043 player[c1].y_add += 6144;
2044 if (player[c1].y_add > 327680L)
2045 player[c1].y_add = 327680L;
2047 player[c1].y = (player[c1].y & 0xffff0000) + 0x10000;
2048 player[c1].y_add = 0;
2050 player[c1].in_water = 0;
2052 if (player[c1].y_add > 36864 && player[c1].anim != 3 && player[c1].in_water == 0) {
2053 player[c1].anim = 3;
2054 player[c1].frame = 0;
2055 player[c1].frame_tick = 0;
2056 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2061 player[c1].frame_tick++;
2062 if (player[c1].frame_tick >= player_anims[player[c1].anim].frame[player[c1].frame].ticks) {
2064 if (player[c1].frame >= player_anims[player[c1].anim].num_frames) {
2065 if (player[c1].anim != 6)
2066 player[c1].frame = player_anims[player[c1].anim].restart_frame;
2068 position_player(c1);
2070 player[c1].frame_tick = 0;
2072 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2081 void position_player(int player_num)
2090 if (ban_map[s2][s1] == BAN_VOID && (ban_map[s2 + 1][s1] == BAN_SOLID || ban_map[s2 + 1][s1] == BAN_ICE))
2093 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
2094 if (c1 != player_num && player[c1].enabled == 1) {
2095 if (abs((s1 << 4) - (player[c1].x >> 16)) < 32 && abs((s2 << 4) - (player[c1].y >> 16)) < 32)
2099 if (c1 == JNB_MAX_PLAYERS) {
2100 player[player_num].x = (long) s1 << 20;
2101 player[player_num].y = (long) s2 << 20;
2102 player[player_num].x_add = player[player_num].y_add = 0;
2103 player[player_num].direction = 0;
2104 player[player_num].jump_ready = 1;
2105 player[player_num].in_water = 0;
2106 player[player_num].anim = 0;
2107 player[player_num].frame = 0;
2108 player[player_num].frame_tick = 0;
2109 player[player_num].image = player_anims[player[player_num].anim].frame[player[player_num].frame].image;
2113 serverSendAlive(player_num);
2115 player[player_num].dead_flag = 0;
2125 void add_object(int type, int x, int y, int x_add, int y_add, int anim, int frame)
2129 for (c1 = 0; c1 < NUM_OBJECTS; c1++) {
2130 if (objects[c1].used == 0) {
2131 objects[c1].used = 1;
2132 objects[c1].type = type;
2133 objects[c1].x = (long) x << 16;
2134 objects[c1].y = (long) y << 16;
2135 objects[c1].x_add = x_add;
2136 objects[c1].y_add = y_add;
2137 objects[c1].x_acc = 0;
2138 objects[c1].y_acc = 0;
2139 objects[c1].anim = anim;
2140 objects[c1].frame = frame;
2141 objects[c1].ticks = object_anims[anim].frame[frame].ticks;
2142 objects[c1].image = object_anims[anim].frame[frame].image;
2150 void update_objects(void)
2155 for (c1 = 0; c1 < NUM_OBJECTS; c1++) {
2156 if (objects[c1].used == 1) {
2157 switch (objects[c1].type) {
2159 objects[c1].ticks--;
2160 if (objects[c1].ticks <= 0) {
2161 objects[c1].frame++;
2162 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames) {
2163 objects[c1].frame--;
2164 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2166 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2167 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2170 if (objects[c1].used == 1)
2171 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2174 objects[c1].ticks--;
2175 if (objects[c1].ticks <= 0) {
2176 objects[c1].frame++;
2177 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2178 objects[c1].used = 0;
2180 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2181 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2184 if (objects[c1].used == 1)
2185 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2188 objects[c1].x += objects[c1].x_add;
2189 objects[c1].y += objects[c1].y_add;
2190 objects[c1].ticks--;
2191 if (objects[c1].ticks <= 0) {
2192 objects[c1].frame++;
2193 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2194 objects[c1].used = 0;
2196 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2197 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2200 if (objects[c1].used == 1)
2201 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2203 case OBJ_YEL_BUTFLY:
2204 case OBJ_PINK_BUTFLY:
2205 objects[c1].x_acc += rnd(128) - 64;
2206 if (objects[c1].x_acc < -1024)
2207 objects[c1].x_acc = -1024;
2208 if (objects[c1].x_acc > 1024)
2209 objects[c1].x_acc = 1024;
2210 objects[c1].x_add += objects[c1].x_acc;
2211 if (objects[c1].x_add < -32768)
2212 objects[c1].x_add = -32768;
2213 if (objects[c1].x_add > 32768)
2214 objects[c1].x_add = 32768;
2215 objects[c1].x += objects[c1].x_add;
2216 if ((objects[c1].x >> 16) < 16) {
2217 objects[c1].x = 16 << 16;
2218 objects[c1].x_add = -objects[c1].x_add >> 2;
2219 objects[c1].x_acc = 0;
2220 } else if ((objects[c1].x >> 16) > 350) {
2221 objects[c1].x = 350 << 16;
2222 objects[c1].x_add = -objects[c1].x_add >> 2;
2223 objects[c1].x_acc = 0;
2225 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0) {
2226 if (objects[c1].x_add < 0) {
2227 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2229 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2231 objects[c1].x_add = -objects[c1].x_add >> 2;
2232 objects[c1].x_acc = 0;
2234 objects[c1].y_acc += rnd(64) - 32;
2235 if (objects[c1].y_acc < -1024)
2236 objects[c1].y_acc = -1024;
2237 if (objects[c1].y_acc > 1024)
2238 objects[c1].y_acc = 1024;
2239 objects[c1].y_add += objects[c1].y_acc;
2240 if (objects[c1].y_add < -32768)
2241 objects[c1].y_add = -32768;
2242 if (objects[c1].y_add > 32768)
2243 objects[c1].y_add = 32768;
2244 objects[c1].y += objects[c1].y_add;
2245 if ((objects[c1].y >> 16) < 0) {
2247 objects[c1].y_add = -objects[c1].y_add >> 2;
2248 objects[c1].y_acc = 0;
2249 } else if ((objects[c1].y >> 16) > 255) {
2250 objects[c1].y = 255 << 16;
2251 objects[c1].y_add = -objects[c1].y_add >> 2;
2252 objects[c1].y_acc = 0;
2254 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0) {
2255 if (objects[c1].y_add < 0) {
2256 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2258 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2260 objects[c1].y_add = -objects[c1].y_add >> 2;
2261 objects[c1].y_acc = 0;
2263 if (objects[c1].type == OBJ_YEL_BUTFLY) {
2264 if (objects[c1].x_add < 0 && objects[c1].anim != OBJ_ANIM_YEL_BUTFLY_LEFT) {
2265 objects[c1].anim = OBJ_ANIM_YEL_BUTFLY_LEFT;
2266 objects[c1].frame = 0;
2267 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2268 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2269 } else if (objects[c1].x_add > 0 && objects[c1].anim != OBJ_ANIM_YEL_BUTFLY_RIGHT) {
2270 objects[c1].anim = OBJ_ANIM_YEL_BUTFLY_RIGHT;
2271 objects[c1].frame = 0;
2272 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2273 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2276 if (objects[c1].x_add < 0 && objects[c1].anim != OBJ_ANIM_PINK_BUTFLY_LEFT) {
2277 objects[c1].anim = OBJ_ANIM_PINK_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_PINK_BUTFLY_RIGHT) {
2282 objects[c1].anim = OBJ_ANIM_PINK_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 objects[c1].ticks--;
2289 if (objects[c1].ticks <= 0) {
2290 objects[c1].frame++;
2291 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2292 objects[c1].frame = object_anims[objects[c1].anim].restart_frame;
2294 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2295 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2298 if (objects[c1].used == 1)
2299 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2303 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 0);
2304 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 0) {
2305 objects[c1].y_add += 3072;
2306 if (objects[c1].y_add > 196608L)
2307 objects[c1].y_add = 196608L;
2308 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 2) {
2309 if (objects[c1].x_add < 0) {
2310 if (objects[c1].x_add < -65536L)
2311 objects[c1].x_add = -65536L;
2312 objects[c1].x_add += 1024;
2313 if (objects[c1].x_add > 0)
2314 objects[c1].x_add = 0;
2316 if (objects[c1].x_add > 65536L)
2317 objects[c1].x_add = 65536L;
2318 objects[c1].x_add -= 1024;
2319 if (objects[c1].x_add < 0)
2320 objects[c1].x_add = 0;
2322 objects[c1].y_add += 1024;
2323 if (objects[c1].y_add < -65536L)
2324 objects[c1].y_add = -65536L;
2325 if (objects[c1].y_add > 65536L)
2326 objects[c1].y_add = 65536L;
2328 objects[c1].x += objects[c1].x_add;
2329 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)) {
2330 if (objects[c1].x_add < 0) {
2331 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2332 objects[c1].x_add = -objects[c1].x_add >> 2;
2334 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2335 objects[c1].x_add = -objects[c1].x_add >> 2;
2338 objects[c1].y += objects[c1].y_add;
2339 if ((objects[c1].x >> 16) < -5 || (objects[c1].x >> 16) > 405 || (objects[c1].y >> 16) > 260)
2340 objects[c1].used = 0;
2341 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0)) {
2342 if (objects[c1].y_add < 0) {
2343 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 2) {
2344 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2345 objects[c1].x_add >>= 2;
2346 objects[c1].y_add = -objects[c1].y_add >> 2;
2349 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1) {
2350 if (objects[c1].y_add > 131072L) {
2351 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2352 objects[c1].x_add >>= 2;
2353 objects[c1].y_add = -objects[c1].y_add >> 2;
2355 objects[c1].used = 0;
2356 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3) {
2357 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2358 if (objects[c1].y_add > 131072L)
2359 objects[c1].y_add = -objects[c1].y_add >> 2;
2361 objects[c1].y_add = 0;
2365 if (objects[c1].x_add < 0 && objects[c1].x_add > -16384)
2366 objects[c1].x_add = -16384;
2367 if (objects[c1].x_add > 0 && objects[c1].x_add < 16384)
2368 objects[c1].x_add = 16384;
2369 if (objects[c1].used == 1) {
2370 s1 = (int)(atan2(objects[c1].y_add, objects[c1].x_add) * 4 / M_PI);
2377 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].frame + s1, &object_gobs);
2381 if (rnd(100) < 30) {
2382 if (objects[c1].frame == 76)
2383 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 1);
2384 else if (objects[c1].frame == 77)
2385 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 2);
2386 else if (objects[c1].frame == 78)
2387 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 3);
2389 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 0) {
2390 objects[c1].y_add += 3072;
2391 if (objects[c1].y_add > 196608L)
2392 objects[c1].y_add = 196608L;
2393 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 2) {
2394 if (objects[c1].x_add < 0) {
2395 if (objects[c1].x_add < -65536L)
2396 objects[c1].x_add = -65536L;
2397 objects[c1].x_add += 1024;
2398 if (objects[c1].x_add > 0)
2399 objects[c1].x_add = 0;
2401 if (objects[c1].x_add > 65536L)
2402 objects[c1].x_add = 65536L;
2403 objects[c1].x_add -= 1024;
2404 if (objects[c1].x_add < 0)
2405 objects[c1].x_add = 0;
2407 objects[c1].y_add += 1024;
2408 if (objects[c1].y_add < -65536L)
2409 objects[c1].y_add = -65536L;
2410 if (objects[c1].y_add > 65536L)
2411 objects[c1].y_add = 65536L;
2413 objects[c1].x += objects[c1].x_add;
2414 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)) {
2415 if (objects[c1].x_add < 0) {
2416 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2417 objects[c1].x_add = -objects[c1].x_add >> 2;
2419 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2420 objects[c1].x_add = -objects[c1].x_add >> 2;
2423 objects[c1].y += objects[c1].y_add;
2424 if ((objects[c1].x >> 16) < -5 || (objects[c1].x >> 16) > 405 || (objects[c1].y >> 16) > 260)
2425 objects[c1].used = 0;
2426 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0)) {
2427 if (objects[c1].y_add < 0) {
2428 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 2) {
2429 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2430 objects[c1].x_add >>= 2;
2431 objects[c1].y_add = -objects[c1].y_add >> 2;
2434 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1) {
2435 if (objects[c1].y_add > 131072L) {
2436 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2437 objects[c1].x_add >>= 2;
2438 objects[c1].y_add = -objects[c1].y_add >> 2;
2440 if (rnd(100) < 10) {
2442 add_leftovers(0, objects[c1].x >> 16, (objects[c1].y >> 16) + s1, objects[c1].frame, &object_gobs);
2443 add_leftovers(1, objects[c1].x >> 16, (objects[c1].y >> 16) + s1, objects[c1].frame, &object_gobs);
2445 objects[c1].used = 0;
2447 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3) {
2448 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2449 if (objects[c1].y_add > 131072L)
2450 objects[c1].y_add = -objects[c1].y_add >> 2;
2452 objects[c1].y_add = 0;
2456 if (objects[c1].x_add < 0 && objects[c1].x_add > -16384)
2457 objects[c1].x_add = -16384;
2458 if (objects[c1].x_add > 0 && objects[c1].x_add < 16384)
2459 objects[c1].x_add = 16384;
2460 if (objects[c1].used == 1)
2461 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].frame, &object_gobs);
2463 case OBJ_FLESH_TRACE:
2464 objects[c1].ticks--;
2465 if (objects[c1].ticks <= 0) {
2466 objects[c1].frame++;
2467 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2468 objects[c1].used = 0;
2470 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2471 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2474 if (objects[c1].used == 1)
2475 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2484 int add_pob(int page, int x, int y, int image, gob_t *pob_data)
2487 if (main_info.page_info[page].num_pobs >= NUM_POBS)
2490 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].x = x;
2491 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].y = y;
2492 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].image = image;
2493 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].pob_data = pob_data;
2494 main_info.page_info[page].num_pobs++;
2501 void draw_flies(int page)
2505 for (c2 = 0; c2 < NUM_FLIES; c2++) {
2506 flies[c2].back[main_info.draw_page] = get_pixel(main_info.draw_page, flies[c2].x, flies[c2].y);
2507 flies[c2].back_defined[main_info.draw_page] = 1;
2508 if (mask_pic[(flies[c2].y * JNB_WIDTH) + flies[c2].x] == 0)
2509 set_pixel(main_info.draw_page, flies[c2].x, flies[c2].y, 0);
2513 void draw_pobs(int page)
2520 for (c1 = main_info.page_info[page].num_pobs - 1; c1 >= 0; c1--) {
2521 main_info.page_info[page].pobs[c1].back_buf_ofs = back_buf_ofs;
2522 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);
2524 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;
2526 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;
2527 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);
2533 void redraw_flies_background(int page)
2537 for (c2 = NUM_FLIES - 1; c2 >= 0; c2--) {
2538 if (flies[c2].back_defined[page] == 1)
2539 set_pixel(page, flies[c2].old_draw_x, flies[c2].old_draw_y, flies[c2].back[page]);
2540 flies[c2].old_draw_x = flies[c2].x;
2541 flies[c2].old_draw_y = flies[c2].y;
2546 void redraw_pob_backgrounds(int page)
2550 for (c1 = 0; c1 < main_info.page_info[page].num_pobs; c1++)
2551 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);
2556 int add_leftovers(int page, int x, int y, int image, gob_t *pob_data)
2559 if (leftovers.page[page].num_pobs >= NUM_LEFTOVERS)
2562 leftovers.page[page].pobs[leftovers.page[page].num_pobs].x = x;
2563 leftovers.page[page].pobs[leftovers.page[page].num_pobs].y = y;
2564 leftovers.page[page].pobs[leftovers.page[page].num_pobs].image = image;
2565 leftovers.page[page].pobs[leftovers.page[page].num_pobs].pob_data = pob_data;
2566 leftovers.page[page].num_pobs++;
2573 void draw_leftovers(int page)
2577 for (c1 = leftovers.page[page].num_pobs - 1; c1 >= 0; c1--)
2578 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);
2580 leftovers.page[page].num_pobs = 0;
2585 int init_level(int level, char *pal)
2587 unsigned char *handle;
2591 if ((handle = dat_open("level.pcx", datfile_name, "rb")) == 0) {
2592 strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n");
2595 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
2596 strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n");
2600 flip_pixels(background_pic);
2601 if ((handle = dat_open("mask.pcx", datfile_name, "rb")) == 0) {
2602 strcpy(main_info.error_str, "Error loading 'mask.pcx', aborting...\n");
2605 if (read_pcx(handle, mask_pic, JNB_WIDTH*JNB_HEIGHT, 0) != 0) {
2606 strcpy(main_info.error_str, "Error loading 'mask.pcx', aborting...\n");
2610 flip_pixels(mask_pic);
2611 register_mask(mask_pic);
2613 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
2614 if (player[c1].enabled == 1) {
2615 player[c1].bumps = 0;
2616 for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++)
2617 player[c1].bumped[c2] = 0;
2618 position_player(c1);
2622 for (c1 = 0; c1 < NUM_OBJECTS; c1++)
2623 objects[c1].used = 0;
2625 for (c1 = 0; c1 < 16; c1++) {
2626 for (c2 = 0; c2 < 22; c2++) {
2627 if (ban_map[c1][c2] == BAN_SPRING)
2628 add_object(OBJ_SPRING, c2 << 4, c1 << 4, 0, 0, OBJ_ANIM_SPRING, 5);
2635 if (ban_map[s2][s1] == BAN_VOID) {
2636 add_object(OBJ_YEL_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2643 if (ban_map[s2][s1] == BAN_VOID) {
2644 add_object(OBJ_YEL_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2651 if (ban_map[s2][s1] == BAN_VOID) {
2652 add_object(OBJ_PINK_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2659 if (ban_map[s2][s1] == BAN_VOID) {
2660 add_object(OBJ_PINK_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2670 void deinit_level(void)
2678 #define PATH_MAX 1024
2681 unsigned char *datafile_buffer = NULL;
2683 static void preread_datafile(const char *fname)
2689 char *gzfilename = alloca(strlen(fname) + 4);
2694 strcpy(gzfilename, fname);
2695 strcat(gzfilename, ".gz");
2697 gzf = gzopen(gzfilename, "rb");
2702 if (bufpos >= bufsize) {
2703 bufsize += 1024 * 1024;
2704 datafile_buffer = (unsigned char *) realloc(datafile_buffer, bufsize);
2705 if (datafile_buffer == NULL) {
2706 perror("realloc()");
2711 br = gzread(gzf, datafile_buffer + bufpos, bufsize - bufpos);
2713 fprintf(stderr, "gzread failed.\n");
2718 } while (!gzeof(gzf));
2720 /* try to shrink buffer... */
2721 ptr = (unsigned char *) realloc(datafile_buffer, bufpos);
2723 datafile_buffer = ptr;
2729 /* drop through and try for an uncompressed datafile... */
2732 fd = open(fname, O_RDONLY | O_BINARY);
2734 fprintf(stderr, "can't open %s: %s\n", fname, strerror(errno));
2738 len = filelength(fd);
2739 datafile_buffer = (unsigned char *) malloc(len);
2740 if (datafile_buffer == NULL) {
2746 if (read(fd, datafile_buffer, len) != len) {
2756 int init_program(int argc, char *argv[], char *pal)
2758 char *netarg = NULL;
2759 unsigned char *handle = (unsigned char *) NULL;
2764 int player_anim_data[] = {
2765 1, 0, 0, 0x7fff, 0, 0, 0, 0, 0, 0,
2766 4, 0, 0, 4, 1, 4, 2, 4, 3, 4,
2767 1, 0, 4, 0x7fff, 0, 0, 0, 0, 0, 0,
2768 4, 2, 5, 8, 6, 10, 7, 3, 6, 3,
2769 1, 0, 6, 0x7fff, 0, 0, 0, 0, 0, 0,
2770 2, 1, 5, 8, 4, 0x7fff, 0, 0, 0, 0,
2771 1, 0, 8, 5, 0, 0, 0, 0, 0, 0
2775 memset(&net_info, 0, sizeof(net_info));
2779 if (__djgpp_nearptr_enable() == 0)
2785 if (hook_keyb_handler() != 0)
2788 memset(&main_info, 0, sizeof(main_info));
2790 strcpy(datfile_name, DATA_PATH);
2792 force2 = force3 = 0;
2795 for (c1 = 1; c1 < argc; c1++) {
2796 if (stricmp(argv[c1], "-nosound") == 0)
2797 main_info.no_sound = 1;
2798 else if (stricmp(argv[c1], "-musicnosound") == 0)
2799 main_info.music_no_sound = 1;
2800 else if (stricmp(argv[c1], "-nogore") == 0)
2801 main_info.no_gore = 1;
2802 else if (stricmp(argv[c1], "-noflies") == 0)
2804 else if (stricmp(argv[c1], "-nojoy") == 0)
2805 main_info.joy_enabled = 0;
2806 else if (stricmp(argv[c1], "-fireworks") == 0)
2807 main_info.fireworks = 1;
2809 else if (stricmp(argv[c1], "-fullscreen") == 0)
2812 else if (stricmp(argv[c1], "-scaleup") == 0)
2814 else if (stricmp(argv[c1], "-mirror") == 0)
2816 else if (stricmp(argv[c1], "-dat") == 0) {
2817 if (c1 < (argc - 1)) {
2820 if ((f = fopen(argv[c1 + 1], "rb")) != NULL) {
2822 strcpy(datfile_name, argv[c1 + 1]);
2825 } else if (stricmp(argv[c1], "-player") == 0) {
2826 if (c1 < (argc - 1)) {
2827 if (client_player_num < 0)
2828 client_player_num = atoi(argv[c1 + 1]);
2830 } else if (stricmp(argv[c1], "-server") == 0) {
2831 if (c1 < (argc - 1)) {
2834 netarg = argv[c1 + 1];
2836 } else if (stricmp(argv[c1], "-connect") == 0) {
2837 if (c1 < (argc - 1)) {
2840 netarg = argv[c1 + 1];
2842 } else if (stricmp(argv[c1], "-mouse") == 0) {
2843 if (c1 < (argc - 1)) {
2844 if (stricmp(argv[c1 + 1], "2") == 0)
2846 if (stricmp(argv[c1 + 1], "3") == 0)
2850 else if (strstr(argv[1],"-v")) {
2851 printf("jumpnbump %s compiled %s at %s with",JNB_VERSION,__DATE__,__TIME__);
2855 printf(" network support.\n");
2858 else if (strstr(argv[1],"-h")) {
2859 printf("Usage: jumpnbump [OPTION]...\n");
2861 printf(" -h this help\n");
2862 printf(" -v print version\n");
2863 printf(" -dat level.dat play a different level\n");
2864 printf(" -port port define listen port\n");
2865 printf(" -net player host rport define network players\n");
2866 printf(" -fireworks screensaver mode\n");
2867 printf(" -fullscreen run in fullscreen mode\n");
2868 printf(" -nosound play without sound\n");
2869 printf(" -nogore play without blood\n");
2870 printf(" -noflies disable flies\n");
2871 printf(" -mirror play with mirrored level\n");
2872 printf(" -scaleup play with doubled resolution (800x512)\n");
2873 printf(" -musicnosound play with music but without sound\n");
2880 preread_datafile(datfile_name);
2883 if (client_player_num < 0)
2884 client_player_num = 0;
2885 player[client_player_num].enabled = 1;
2888 main_info.pob_backbuf[0] = malloc(screen_pitch*screen_height*bytes_per_pixel);
2889 main_info.pob_backbuf[1] = malloc(screen_pitch*screen_height*bytes_per_pixel);
2891 for (c1 = 0; c1 < 7; c1++) {
2892 player_anims[c1].num_frames = player_anim_data[c1 * 10];
2893 player_anims[c1].restart_frame = player_anim_data[c1 * 10 + 1];
2894 for (c2 = 0; c2 < 4; c2++) {
2895 player_anims[c1].frame[c2].image = player_anim_data[c1 * 10 + c2 * 2 + 2];
2896 player_anims[c1].frame[c2].ticks = player_anim_data[c1 * 10 + c2 * 2 + 3];
2900 if ((handle = dat_open("menu.pcx", datfile_name, "rb")) == 0) {
2901 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
2904 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
2905 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
2909 if ((handle = dat_open("rabbit.gob", datfile_name, "rb")) == 0) {
2910 strcpy(main_info.error_str, "Error loading 'rabbit.gob', aborting...\n");
2913 if (register_gob(handle, &rabbit_gobs, dat_filelen("rabbit.gob", datfile_name))) {
2918 if ((handle = dat_open("objects.gob", datfile_name, "rb")) == 0) {
2919 strcpy(main_info.error_str, "Error loading 'objects.gob', aborting...\n");
2922 if (register_gob(handle, &object_gobs, dat_filelen("objects.gob", datfile_name))) {
2927 if ((handle = dat_open("font.gob", datfile_name, "rb")) == 0) {
2928 strcpy(main_info.error_str, "Error loading 'font.gob', aborting...\n");
2931 if (register_gob(handle, &font_gobs, dat_filelen("font.gob", datfile_name))) {
2936 if ((handle = dat_open("numbers.gob", datfile_name, "rb")) == 0) {
2937 strcpy(main_info.error_str, "Error loading 'numbers.gob', aborting...\n");
2940 if (register_gob(handle, &number_gobs, dat_filelen("numbers.gob", datfile_name))) {
2945 if (read_level() != 0) {
2946 strcpy(main_info.error_str, "Error loading 'levelmap.txt', aborting...\n");
2952 if (main_info.no_sound == 0) {
2954 dj_set_mixing_freq(20000);
2958 dj_set_num_sfx_channels(5);
2959 dj_set_sfx_volume(64);
2963 if ((handle = dat_open("jump.mod", datfile_name, "rb")) == 0) {
2964 strcpy(main_info.error_str, "Error loading 'jump.mod', aborting...\n");
2967 if (dj_load_mod(handle, 0, MOD_MENU) != 0) {
2968 strcpy(main_info.error_str, "Error loading 'jump.mod', aborting...\n");
2972 if ((handle = dat_open("bump.mod", datfile_name, "rb")) == 0) {
2973 strcpy(main_info.error_str, "Error loading 'bump.mod', aborting...\n");
2976 if (dj_load_mod(handle, 0, MOD_GAME) != 0) {
2977 strcpy(main_info.error_str, "Error loading 'bump.mod', aborting...\n");
2981 if ((handle = dat_open("scores.mod", datfile_name, "rb")) == 0) {
2982 strcpy(main_info.error_str, "Error loading 'scores.mod', aborting...\n");
2985 if (dj_load_mod(handle, 0, MOD_SCORES) != 0) {
2986 strcpy(main_info.error_str, "Error loading 'scores.mod', aborting...\n");
2990 if ((handle = dat_open("jump.smp", datfile_name, "rb")) == 0) {
2991 strcpy(main_info.error_str, "Error loading 'jump.smp', aborting...\n");
2994 if (dj_load_sfx(handle, 0, dat_filelen("jump.smp", datfile_name), DJ_SFX_TYPE_SMP, SFX_JUMP) != 0) {
2995 strcpy(main_info.error_str, "Error loading 'jump.smp', aborting...\n");
2999 if ((handle = dat_open("death.smp", datfile_name, "rb")) == 0) {
3000 strcpy(main_info.error_str, "Error loading 'death.smp', aborting...\n");
3003 if (dj_load_sfx(handle, 0, dat_filelen("death.smp", datfile_name), DJ_SFX_TYPE_SMP, SFX_DEATH) != 0) {
3004 strcpy(main_info.error_str, "Error loading 'death.smp', aborting...\n");
3008 if ((handle = dat_open("spring.smp", datfile_name, "rb")) == 0) {
3009 strcpy(main_info.error_str, "Error loading 'spring.smp', aborting...\n");
3012 if (dj_load_sfx(handle, 0, dat_filelen("spring.smp", datfile_name), DJ_SFX_TYPE_SMP, SFX_SPRING) != 0) {
3013 strcpy(main_info.error_str, "Error loading 'spring.smp', aborting...\n");
3017 if ((handle = dat_open("splash.smp", datfile_name, "rb")) == 0) {
3018 strcpy(main_info.error_str, "Error loading 'splash.smp', aborting...\n");
3021 if (dj_load_sfx(handle, 0, dat_filelen("splash.smp", datfile_name), DJ_SFX_TYPE_SMP, SFX_SPLASH) != 0) {
3022 strcpy(main_info.error_str, "Error loading 'splash.smp', aborting...\n");
3026 if ((handle = dat_open("fly.smp", datfile_name, "rb")) == 0) {
3027 strcpy(main_info.error_str, "Error loading 'fly.smp', aborting...\n");
3030 if (dj_load_sfx(handle, 0, dat_filelen("fly.smp", datfile_name), DJ_SFX_TYPE_SMP, SFX_FLY) != 0) {
3031 strcpy(main_info.error_str, "Error loading 'fly.smp', aborting...\n");
3035 dj_get_sfx_settings(SFX_FLY, &fly);
3037 fly.default_freq = SFX_FLY_FREQ;
3040 fly.loop_length = fly.length;
3041 dj_set_sfx_settings(SFX_FLY, &fly);
3044 if ((background_pic = malloc(JNB_WIDTH*JNB_HEIGHT)) == NULL)
3046 if ((mask_pic = malloc(JNB_WIDTH*JNB_HEIGHT)) == NULL)
3048 memset(mask_pic, 0, JNB_WIDTH*JNB_HEIGHT);
3049 register_mask(mask_pic);
3051 for (c1 = 0; c1 < 16; c1++) { // fix dark font
3052 pal[(240 + c1) * 3 + 0] = c1 << 2;
3053 pal[(240 + c1) * 3 + 1] = c1 << 2;
3054 pal[(240 + c1) * 3 + 2] = c1 << 2;
3057 setpalette(0, 256, pal);
3061 recalculate_gob(&font_gobs, pal);
3063 if (main_info.joy_enabled == 1 && main_info.fireworks == 0) {
3065 put_text(0, 200, 40, "JOYSTICK CALIBRATION", 2);
3066 put_text(0, 200, 100, "Move the joystick to the", 2);
3067 put_text(0, 200, 115, "UPPER LEFT", 2);
3068 put_text(0, 200, 130, "and press button A", 2);
3069 put_text(0, 200, 200, "Or press ESC to use", 2);
3070 put_text(0, 200, 215, "previous settings", 2);
3071 if (calib_joy(0) != 0)
3074 register_background(NULL, NULL);
3076 main_info.view_page = 1;
3081 put_text(1, 200, 40, "JOYSTICK CALIBRATION", 2);
3082 put_text(1, 200, 100, "Move the joystick to the", 2);
3083 put_text(1, 200, 115, "LOWER RIGHT", 2);
3084 put_text(1, 200, 130, "and press button A", 2);
3085 put_text(1, 200, 200, "Or press ESC to use", 2);
3086 put_text(1, 200, 215, "previous settings", 2);
3087 if (calib_joy(1) != 0)
3090 register_background(NULL, NULL);
3095 put_text(0, 200, 40, "JOYSTICK CALIBRATION", 2);
3096 put_text(0, 200, 100, "Move the joystick to the", 2);
3097 put_text(0, 200, 115, "CENTER", 2);
3098 put_text(0, 200, 130, "and press button A", 2);
3099 put_text(0, 200, 200, "Or press ESC to use", 2);
3100 put_text(0, 200, 215, "previous settings", 2);
3101 if (calib_joy(2) != 0)
3104 if (joy.calib_data.x1 == joy.calib_data.x2)
3105 joy.calib_data.x1 -= 10;
3106 if (joy.calib_data.x3 == joy.calib_data.x2)
3107 joy.calib_data.x3 += 10;
3108 if (joy.calib_data.y1 == joy.calib_data.y2)
3109 joy.calib_data.y1 -= 10;
3110 if (joy.calib_data.y3 == joy.calib_data.y2)
3111 joy.calib_data.y3 += 10;
3116 if (load_flag == 1) {
3117 if ((handle = dat_open("calib.dat", datfile_name, "rb")) == 0) {
3118 strcpy(main_info.error_str, "Error loading 'calib.dat', aborting...\n");
3121 joy.calib_data.x1 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3122 joy.calib_data.x2 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3123 joy.calib_data.x3 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3124 joy.calib_data.y1 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3125 joy.calib_data.y2 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3126 joy.calib_data.y3 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3132 init_server(netarg);
3134 connect_to_server(netarg);
3142 void deinit_program(void)
3149 dj_free_mod(MOD_MENU);
3150 dj_free_mod(MOD_GAME);
3151 dj_free_sfx(SFX_DEATH);
3152 dj_free_sfx(SFX_SPRING);
3153 dj_free_sfx(SFX_SPLASH);
3156 if (background_pic != 0)
3157 free(background_pic);
3161 remove_keyb_handler();
3165 __dpmi_int(0x10, ®s);
3168 if (main_info.error_str[0] != 0) {
3169 printf(main_info.error_str);
3171 MessageBox(0, main_info.error_str, "Jump'n'Bump", 0);
3180 unsigned short rnd(unsigned short max)
3182 return (rand() % max);
3186 int read_level(void)
3188 unsigned char *handle;
3192 if ((handle = dat_open("levelmap.txt", datfile_name, "rb")) == 0) {
3193 strcpy(main_info.error_str, "Error loading 'levelmap.txt', aborting...\n");
3197 for (c1 = 0; c1 < 16; c1++) {
3198 for (c2 = 0; c2 < 22; c2++) {
3200 chr = (int) *(handle++);
3201 if (chr >= '0' && chr <= '4')
3205 ban_map[c1][21-c2] = chr - '0';
3207 ban_map[c1][c2] = chr - '0';
3211 for (c2 = 0; c2 < 22; c2++)
3212 ban_map[16][c2] = BAN_SOLID;
3219 unsigned char *dat_open(char *file_name, char *dat_name, char *mode)
3227 if (datafile_buffer == NULL)
3230 memset(name, 0, sizeof(name));
3232 num = ( (datafile_buffer[0] << 0) +
3233 (datafile_buffer[1] << 8) +
3234 (datafile_buffer[2] << 16) +
3235 (datafile_buffer[3] << 24) );
3237 ptr = datafile_buffer + 4;
3239 for (c1 = 0; c1 < num; c1++) {
3241 memcpy(name, ptr, 12);
3244 if (strnicmp(name, file_name, strlen(file_name)) == 0) {
3245 ofs = ( (ptr[0] << 0) +
3250 return (datafile_buffer + ofs);
3259 int dat_filelen(char *file_name, char *dat_name)
3267 memset(name, 0, sizeof(name));
3269 num = ( (datafile_buffer[0] << 0) +
3270 (datafile_buffer[1] << 8) +
3271 (datafile_buffer[2] << 16) +
3272 (datafile_buffer[3] << 24) );
3274 ptr = datafile_buffer + 4;
3276 for (c1 = 0; c1 < num; c1++) {
3278 memcpy(name, ptr, 12);
3281 if (strnicmp(name, file_name, strlen(file_name)) == 0) {
3284 len = ( (ptr[0] << 0) +
3298 void write_calib_data(void)
3306 if ((handle = fopen(datfile_name, "rb")) == NULL)
3308 len = filelength(fileno(handle));
3309 if ((mem = malloc(len)) == NULL)
3311 fread(mem, 1, len, handle);
3315 num = *(int *) (&mem[0]);
3316 for (c1 = 0; c1 < num; c1++) {
3317 if (strnicmp(&mem[ofs], "calib.dat", strlen("calib.dat")) == 0) {
3318 ofs = *(int *) (&mem[ofs + 12]);
3324 mem[ofs] = joy.calib_data.x1 & 0xff;
3325 mem[ofs + 1] = (joy.calib_data.x1 >> 8) & 0xff;
3326 mem[ofs + 2] = (joy.calib_data.x1 >> 16) & 0xff;
3327 mem[ofs + 3] = (joy.calib_data.x1 >> 24) & 0xff;
3328 mem[ofs + 4] = joy.calib_data.x2 & 0xff;
3329 mem[ofs + 5] = (joy.calib_data.x2 >> 8) & 0xff;
3330 mem[ofs + 6] = (joy.calib_data.x2 >> 16) & 0xff;
3331 mem[ofs + 7] = (joy.calib_data.x2 >> 24) & 0xff;
3332 mem[ofs + 8] = joy.calib_data.x3 & 0xff;
3333 mem[ofs + 9] = (joy.calib_data.x3 >> 8) & 0xff;
3334 mem[ofs + 10] = (joy.calib_data.x3 >> 16) & 0xff;
3335 mem[ofs + 11] = (joy.calib_data.x3 >> 24) & 0xff;
3336 mem[ofs + 12] = joy.calib_data.y1 & 0xff;
3337 mem[ofs + 13] = (joy.calib_data.y1 >> 8) & 0xff;
3338 mem[ofs + 14] = (joy.calib_data.y1 >> 16) & 0xff;
3339 mem[ofs + 15] = (joy.calib_data.y1 >> 24) & 0xff;
3340 mem[ofs + 16] = joy.calib_data.y2 & 0xff;
3341 mem[ofs + 17] = (joy.calib_data.y2 >> 8) & 0xff;
3342 mem[ofs + 18] = (joy.calib_data.y2 >> 16) & 0xff;
3343 mem[ofs + 19] = (joy.calib_data.y2 >> 24) & 0xff;
3344 mem[ofs + 20] = joy.calib_data.y3 & 0xff;
3345 mem[ofs + 21] = (joy.calib_data.y3 >> 8) & 0xff;
3346 mem[ofs + 22] = (joy.calib_data.y3 >> 16) & 0xff;
3347 mem[ofs + 23] = (joy.calib_data.y3 >> 24) & 0xff;
3349 if ((handle = fopen(datfile_name, "wb")) == NULL)
3351 fwrite(mem, 1, len, handle);