Merge branch 'feature/handle-quit-event'
[jumpnbump.git] / sdl / interrpt.c
blobd6ab688b6528a9cc689f383eb16f6837f87ec9c5
1 /*
2 * interrpt.c
3 * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/
4 *
5 * Copyright (C) 2001 Chuck Mason <cemason@users.sourceforge.net>
7 * Copyright (C) 2002 Florian Schulze <crow@icculus.org>
9 * This file is part of Jump'n'Bump.
11 * Jump'n'Bump is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * Jump'n'Bump is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <time.h>
29 #ifndef _MSC_VER
30 #include <unistd.h>
31 #endif
32 #include "globals.h"
34 #ifdef USE_KAILLERA
35 #include "SDL_thread.h"
36 #include "SDL_mutex.h"
37 #include <kailleraclient.h>
39 char local_keyb[256];
40 #endif /* USE_KAILLERA */
42 char keyb[256];
43 char last_keys[50];
45 #ifdef USE_KAILLERA
47 /* information about the party in this session */
48 static int my_player = -1;
49 static int my_numplayers = -1;
51 /* semaphore for controlling kaillera thread */
52 static SDL_sem *game_start_sem = NULL;
54 /* keys supported on my end */
55 static int my_player_up = -1;
56 static int my_player_left = -1;
57 static int my_player_right = 1;
59 /* values for the kaillera client interface */
60 static char kaillera_app_name[] = "Jump 'n Bump";
61 static char kaillera_game_name[] = "Jump 'n Bump\0\0";
63 static int player_keys[4][3] = {
65 KEY_PL1_LEFT,
66 KEY_PL1_RIGHT,
67 KEY_PL1_JUMP
68 },
70 KEY_PL2_LEFT,
71 KEY_PL2_RIGHT,
72 KEY_PL2_JUMP
75 KEY_PL3_LEFT,
76 KEY_PL3_RIGHT,
77 KEY_PL3_JUMP
80 KEY_PL4_LEFT,
81 KEY_PL4_RIGHT,
82 KEY_PL4_JUMP
86 static int WINAPI kaillera_game_callback(char *game, int player, int numplayers)
88 int length;
89 int urand;
90 unsigned char random[8];
92 if (strcmp(game, kaillera_game_name) != 0) {
93 printf("unknown game selected: %s\n", game);
95 my_player = -1;
96 goto release;
99 printf("start network game with %d players\n", numplayers);
100 printf("I am player %d\n", player);
102 my_player = player;
103 my_numplayers = numplayers;
105 my_player_up = player_keys[player-1][0] & 0xff;
106 my_player_left = player_keys[player-1][1] & 0xff;
107 my_player_right = player_keys[player-1][2] & 0xff;
109 /* initialize randomizer agreed by all players */
110 random[0] = time(0) & 0xff;
111 random[1] = random[2] = random[3] = 0x00;
112 length = kailleraModifyPlayValues(&random, sizeof(random[0]));
113 if (length < 0) {
114 goto release;
117 urand = random[3] << 24 | random[2] << 16 | random[1] << 8 | random[0];
118 srand(urand);
120 release:
122 SDL_SemPost(game_start_sem);
123 return 0;
126 static kailleraInfos kaillera_data = {
127 kaillera_app_name,
128 kaillera_game_name,
129 kaillera_game_callback,
130 NULL,
131 NULL,
132 NULL
135 static void print_version()
137 char version[16];
139 kailleraGetVersion(version);
140 printf("using kaillera version %s\n", version);
143 static int kaillera_thread(void *arg)
145 kailleraInit();
147 /* print_version(); */
149 kailleraSetInfos(&kaillera_data);
151 kailleraSelectServerDialog(0);
152 if (SDL_SemValue(game_start_sem) == 0) {
153 /* server dialog returned and game didnt start */
155 /* release blocking thread */
156 my_player = -1;
157 SDL_SemPost(game_start_sem);
160 return 0;
163 static int start_kaillera_thread(void)
165 SDL_Thread *thread;
167 game_start_sem = SDL_CreateSemaphore(0);
169 thread = SDL_CreateThread(kaillera_thread, NULL);
170 if (!thread) {
171 printf("SDL_CreateThread failed\n");
172 return -1;
175 return 0;
178 int addkey(unsigned int key)
180 /* it doesnt matter if a player presses keys
181 * that control other bunnies. whatever is sent
182 * is packed by pack_keys()
184 if (!(key & 0x8000)) {
185 local_keyb[key & 0x7fff] = 1;
186 } else
187 local_keyb[key & 0x7fff] = 0;
188 return 0;
191 void remove_keyb_handler(void)
193 kailleraShutdown();
196 int pack_keys(void)
198 int rv;
200 rv = local_keyb[my_player_up];
201 rv |= local_keyb[my_player_left] << 1;
202 rv |= local_keyb[my_player_right] << 2;
203 rv |= local_keyb[1] << 3;
204 return rv;
207 void unpack_keys(int player, char value)
209 keyb[player_keys[player][0] & 0xff] = (value >> 0) & 1;
210 keyb[player_keys[player][1] & 0xff] = (value >> 1) & 1;
211 keyb[player_keys[player][2] & 0xff] = (value >> 2) & 1;
213 /* escape key is shared among all users */
214 keyb[1] |= (value >> 3) & 1;
217 int update_kaillera_keys(void)
219 char keys[8];
220 int length;
221 int player;
223 keys[0] = pack_keys();
224 length = kailleraModifyPlayValues(&keys, sizeof(keys[0]));
226 if (length < 0) {
227 /* terminate session */
228 printf("** LOST CONNECTION **\n");
229 kailleraEndGame();
230 my_player = -1;
231 return -1;
234 for (player=0; player<length; player++) {
235 unpack_keys(player, keys[player]);
238 return 0;
241 int hook_keyb_handler(void)
243 SDL_EnableUNICODE(1);
244 memset((void *) last_keys, 0, sizeof(last_keys));
246 start_kaillera_thread();
247 SDL_SemWait(game_start_sem);
248 if (my_player < 0) {
249 printf("GAME ABORTED!\n");
250 return -1;
253 printf("GAME STARTS!\n");
254 return 0;
257 int key_pressed(int key)
259 if (key == 1 && my_player < 0) {
260 /* if game completed or aborted, post ESC */
261 return 1;
264 return keyb[(unsigned char) key];
267 #else /* USE_KAILLERA */
269 int addkey(unsigned int key)
271 int c1;
273 if (!(key & 0x8000)) {
274 keyb[key & 0x7fff] = 1;
275 for (c1 = 48; c1 > 0; c1--)
276 last_keys[c1] = last_keys[c1 - 1];
277 last_keys[0] = key & 0x7fff;
278 } else
279 keyb[key & 0x7fff] = 0;
280 return 0;
283 void remove_keyb_handler(void)
287 int hook_keyb_handler(void)
289 SDL_EnableUNICODE(1);
290 memset((void *) last_keys, 0, sizeof(last_keys));
292 return 0;
295 int key_pressed(int key)
297 return keyb[(unsigned char) key];
301 #endif /* USE_KAILLERA */
303 int intr_sysupdate()
305 SDL_Event e;
306 int i = 0;
307 static int last_time = 0;
308 int now, time_diff;
310 while (SDL_PollEvent(&e)) {
311 switch (e.type) {
312 case SDL_MOUSEBUTTONDOWN:
313 case SDL_MOUSEBUTTONUP:
314 if(e.button.state == SDL_PRESSED &&
315 ((key_pressed(KEY_PL3_LEFT) && e.button.button == SDL_BUTTON_RIGHT) ||
316 (key_pressed(KEY_PL3_RIGHT) && e.button.button == SDL_BUTTON_LEFT) ||
317 (e.button.button == SDL_BUTTON_LEFT && e.button.button == SDL_BUTTON_RIGHT) ||
318 e.button.button == SDL_BUTTON_MIDDLE))
320 addkey(KEY_PL3_JUMP & 0x7f);
322 else if(e.button.state == SDL_RELEASED &&
323 ((key_pressed(KEY_PL3_LEFT) && e.button.button == SDL_BUTTON_RIGHT) ||
324 (key_pressed(KEY_PL3_RIGHT) && e.button.button == SDL_BUTTON_LEFT) ||
325 e.button.button == SDL_BUTTON_MIDDLE))
327 addkey((KEY_PL3_JUMP & 0x7f) | 0x8000);
330 if(e.button.button == SDL_BUTTON_LEFT)
332 SDLKey sym = KEY_PL3_LEFT;
333 sym &= 0x7f;
334 if(e.button.state == SDL_RELEASED)
336 if(key_pressed(KEY_PL3_JUMP) && (SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(SDL_BUTTON_RIGHT)))
337 addkey(KEY_PL3_RIGHT & 0x7f);
338 else
339 sym |= 0x8000;
341 addkey(sym);
343 else if(e.button.button == SDL_BUTTON_RIGHT)
345 SDLKey sym = KEY_PL3_RIGHT;
346 sym &= 0x7f;
347 if (e.button.state == SDL_RELEASED)
349 if(key_pressed(KEY_PL3_JUMP) && (SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(SDL_BUTTON_LEFT)))
350 addkey(KEY_PL3_LEFT & 0x7f);
351 else
352 sym |= 0x8000;
354 addkey(sym);
356 break;
357 case SDL_KEYDOWN:
358 case SDL_KEYUP:
359 switch (e.key.keysym.sym) {
360 case SDLK_F12:
361 if (e.type == SDL_KEYDOWN) {
362 SDL_Quit();
363 exit(1);
365 break;
366 case SDLK_F10:
367 if (e.type == SDL_KEYDOWN) {
368 fs_toggle();
370 break;
371 case SDLK_1:
372 if (e.type == SDL_KEYUP)
373 ai[0] = !ai[0];
375 /* Release keys, otherwise it will continue moving that way */
376 addkey((KEY_PL1_LEFT & 0x7f) | 0x8000);
377 addkey((KEY_PL1_RIGHT & 0x7f) | 0x8000);
378 addkey((KEY_PL1_JUMP & 0x7f) | 0x8000);
379 break;
380 case SDLK_2:
381 if (e.type == SDL_KEYUP)
382 ai[1] = !ai[1];
384 /* Release keys, otherwise it will continue moving that way */
385 addkey((KEY_PL2_LEFT & 0x7f) | 0x8000);
386 addkey((KEY_PL2_RIGHT & 0x7f) | 0x8000);
387 addkey((KEY_PL2_JUMP & 0x7f) | 0x8000);
388 break;
389 case SDLK_3:
390 if (e.type == SDL_KEYUP)
391 ai[2] = !ai[2];
393 /* Release keys, otherwise it will continue moving that way */
394 addkey((KEY_PL3_LEFT & 0x7f) | 0x8000);
395 addkey((KEY_PL3_RIGHT & 0x7f) | 0x8000);
396 addkey((KEY_PL3_JUMP & 0x7f) | 0x8000);
397 break;
398 case SDLK_4:
399 if (e.type == SDL_KEYUP)
400 ai[3] = !ai[3];
402 /* Release keys, otherwise it will continue moving that way */
403 addkey((KEY_PL4_LEFT & 0x7f) | 0x8000);
404 addkey((KEY_PL4_RIGHT & 0x7f) | 0x8000);
405 addkey((KEY_PL4_JUMP & 0x7f) | 0x8000);
406 break;
407 case SDLK_ESCAPE:
408 if (e.type == SDL_KEYUP)
409 addkey(1 | 0x8000);
410 else
411 addkey(1 & 0x7f);
412 break;
413 default:
414 e.key.keysym.sym &= 0x7f;
415 if (e.type == SDL_KEYUP)
416 e.key.keysym.sym |= 0x8000;
417 addkey(e.key.keysym.sym);
419 break;
421 break;
422 case SDL_QUIT:
423 deinit_program();
424 break;
425 default:
426 break;
428 i++;
431 SDL_Delay(1);
432 now = SDL_GetTicks();
433 time_diff = now - last_time;
434 if (time_diff>0) {
435 i = time_diff / (1000 / 60);
436 if (i) {
437 last_time = now;
438 } else {
439 int tmp;
441 tmp = (1000/60) - i - 10;
442 if (tmp>0)
443 SDL_Delay(tmp);
447 if (!then)
448 SDL_Delay(1);
449 else {
450 then = (1000 / 60) - (now - then);
451 if (then > 0 && then < 1000)
452 SDL_Delay(then);
454 then = now;
457 #ifdef USE_KAILLERA
458 if (my_player >= 0) {
459 update_kaillera_keys();
460 i=1;
462 #endif /* USE_KAILLERA */
464 return i;