Kaillera support by Gil Megidish.
[crow/jumpnbump.git] / sdl / interrpt.c
1 /*
2  * interrpt.c
3  * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/
4  * 
5  * Copyright (C) 2001 Chuck Mason <cemason@users.sourceforge.net>
6  *
7  * Copyright (C) 2002 Florian Schulze <crow@icculus.org>
8  *
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.
12  *
13  * This file is part of Jump'n'Bump.
14  *
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.
19  *
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.
24  *
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
28  */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <time.h>
33 #ifndef _MSC_VER
34 #include <unistd.h>
35 #endif
36 #include "globals.h"
37
38 #ifdef USE_KAILLERA
39 #include <SDL_thread.h>
40 #include <SDL_mutex.h>
41 #include <kailleraclient.h>
42
43 char local_keyb[256];
44 #endif // USE_KAILLERA
45
46 char keyb[256];
47 char last_keys[50];
48
49 #ifdef USE_KAILLERA
50
51 /* information about the party in this session */
52 static int my_player = -1;
53 static int my_numplayers = -1;
54
55 /* semaphore for controlling kaillera thread */
56 static SDL_sem *game_start_sem = NULL;
57
58 /* keys supported on my end */
59 static int my_player_up = -1;
60 static int my_player_left = -1;
61 static int my_player_right = 1;
62
63 /* values for the kaillera client interface */
64 static char kaillera_app_name[] = "Jump 'n Bump";
65 static char kaillera_game_name[] = "Jump 'n Bump\0\0";
66
67 static int player_keys[4][3] = {
68         {
69                 KEY_PL1_LEFT,
70                 KEY_PL1_RIGHT,
71                 KEY_PL1_JUMP
72         },                        
73         {
74                 KEY_PL2_LEFT,
75                 KEY_PL2_RIGHT,
76                 KEY_PL2_JUMP
77         },
78         {
79                 KEY_PL3_LEFT,
80                 KEY_PL3_RIGHT,
81                 KEY_PL3_JUMP
82         },
83         {
84                 KEY_PL4_LEFT,
85                 KEY_PL4_RIGHT,
86                 KEY_PL4_JUMP
87         }
88 };
89
90 static int WINAPI kaillera_game_callback(char *game, int player, int numplayers)
91 {
92         int length;
93         int urand;
94         unsigned char random[8];
95
96         if (strcmp(game, kaillera_game_name) != 0) {
97                 printf("unknown game selected: %s\n", game);
98
99                 my_player = -1;
100                 goto release;
101         }
102
103         printf("start network game with %d players\n", numplayers);
104         printf("I am player %d\n", player);
105
106         my_player = player;
107         my_numplayers = numplayers;
108
109         my_player_up = player_keys[player-1][0] & 0xff;
110         my_player_left = player_keys[player-1][1] & 0xff;
111         my_player_right = player_keys[player-1][2] & 0xff;
112
113         /* initialize randomizer agreed by all players */
114         random[0] = time(0) & 0xff;
115         random[1] = random[2] = random[3] = 0x00;
116         length = kailleraModifyPlayValues(&random, sizeof(random[0]));
117         if (length < 0) {
118                 goto release;
119         }
120
121         urand = random[3] << 24 | random[2] << 16 | random[1] << 8 | random[0];
122         srand(urand);
123
124 release:
125
126         SDL_SemPost(game_start_sem);
127         return 0;
128 }
129
130 static kailleraInfos kaillera_data = {
131         kaillera_app_name,
132         kaillera_game_name,
133         kaillera_game_callback,
134         NULL,
135         NULL,
136         NULL
137 };
138
139 static void print_version()
140 {
141         char version[16];
142
143         kailleraGetVersion(version);
144         printf("using kaillera version %s\n", version);
145 }
146
147 static int kaillera_thread(void *arg)
148 {
149         kailleraInit();
150         
151         /* print_version(); */
152
153         kailleraSetInfos(&kaillera_data);
154
155         kailleraSelectServerDialog(0);
156         if (SDL_SemValue(game_start_sem) == 0) {
157                 /* server dialog returned and game didnt start */
158                 
159                 /* release blocking thread */
160                 my_player = -1;
161                 SDL_SemPost(game_start_sem);
162         }
163
164         return 0;
165 }
166
167 static int start_kaillera_thread(void)
168 {
169         SDL_Thread *thread;
170
171         game_start_sem = SDL_CreateSemaphore(0);
172
173         thread = SDL_CreateThread(kaillera_thread, NULL);
174         if (!thread) {
175                 printf("SDL_CreateThread failed\n");
176                 return -1;
177         }
178         
179         return 0;
180 }       
181
182 int addkey(unsigned int key)
183 {
184         /* it doesnt matter if a player presses keys
185          * that control other bunnies. whatever is sent 
186          * is packed by pack_keys()
187          */
188         if (!(key & 0x8000)) {
189                 local_keyb[key & 0x7fff] = 1;
190         } else
191                 local_keyb[key & 0x7fff] = 0;
192         return 0;
193 }
194
195 void remove_keyb_handler(void)
196 {
197         kailleraShutdown();
198 }
199
200 int pack_keys(void)
201 {
202         int rv;
203
204         rv = local_keyb[my_player_up];
205         rv |= local_keyb[my_player_left] << 1;
206         rv |= local_keyb[my_player_right] << 2;
207         rv |= local_keyb[1] << 3;
208         return rv;
209 }
210
211 void unpack_keys(int player, char value)
212 {
213         keyb[player_keys[player][0] & 0xff] = (value >> 0) & 1;
214         keyb[player_keys[player][1] & 0xff] = (value >> 1) & 1;
215         keyb[player_keys[player][2] & 0xff] = (value >> 2) & 1;
216
217         /* escape key is shared among all users */
218         keyb[1] |= (value >> 3) & 1;
219 }
220
221 int update_kaillera_keys(void)
222 {
223         char keys[8];
224         int length;
225         int player;
226
227         keys[0] = pack_keys();
228         length = kailleraModifyPlayValues(&keys, sizeof(keys[0]));
229
230         if (length < 0) {
231                 /* terminate session */
232                 printf("** LOST CONNECTION **\n");
233                 kailleraEndGame();
234                 my_player = -1;
235                 return -1;
236         }
237
238         for (player=0; player<length; player++) {
239                 unpack_keys(player, keys[player]);
240         }
241
242         return 0;
243 }
244
245 int hook_keyb_handler(void)
246 {
247         SDL_EnableUNICODE(1);
248         memset((void *) last_keys, 0, sizeof(last_keys));
249
250         start_kaillera_thread();
251         SDL_SemWait(game_start_sem);
252         if (my_player < 0) {
253                 printf("GAME ABORTED!\n");
254                 return -1;
255         }
256
257         printf("GAME STARTS!\n");
258         return 0;
259 }
260
261 int key_pressed(int key)
262 {
263         if (key == 1 && my_player < 0) {
264                 /* if game completed or aborted, post ESC */
265                 return 1;
266         }
267
268         return keyb[(unsigned char) key];
269 }
270
271 #else // USE_KAILLERA
272
273 int addkey(unsigned int key)
274 {
275         int c1;
276
277         if (!(key & 0x8000)) {
278                 keyb[key & 0x7fff] = 1;
279                 for (c1 = 48; c1 > 0; c1--)
280                         last_keys[c1] = last_keys[c1 - 1];
281                 last_keys[0] = key & 0x7fff;
282         } else
283                 keyb[key & 0x7fff] = 0;
284         return 0;
285 }
286
287 void remove_keyb_handler(void)
288 {
289 }
290
291 int hook_keyb_handler(void)
292 {
293         SDL_EnableUNICODE(1);
294         memset((void *) last_keys, 0, sizeof(last_keys));
295
296         return 0;
297 }
298
299 int key_pressed(int key)
300 {
301         return keyb[(unsigned char) key];
302 }
303
304
305 #endif // USE_KAILLERA
306
307 int intr_sysupdate()
308 {
309         SDL_Event e;
310         int i = 0;
311         static int last_time = 0;
312         int now, time_diff;
313
314         while (SDL_PollEvent(&e)) {
315                 switch (e.type) {
316                 case SDL_MOUSEBUTTONDOWN:
317                         break;
318                 case SDL_KEYDOWN:
319                 case SDL_KEYUP:
320                         switch (e.key.keysym.sym) {
321                         case SDLK_F12:
322                                 if (e.type == SDL_KEYDOWN) {
323                                         SDL_Quit();
324                                         exit(1);
325                                 }
326                                 break;
327                         case SDLK_F10:
328                                 if (e.type == SDL_KEYDOWN) {
329                                         fs_toggle();
330                                 }
331                                 break;
332                         case SDLK_ESCAPE:
333                                 if (e.type == SDL_KEYUP)
334                                         addkey(1 | 0x8000);
335                                 else
336                                         addkey(1 & 0x7f);
337                                 break;
338                         default:
339                                 e.key.keysym.sym &= 0x7f;
340                                 if (e.type == SDL_KEYUP)
341                                         e.key.keysym.sym |= 0x8000;
342                                 addkey(e.key.keysym.sym);
343
344                                 break;
345                         }
346                         break;
347                 default:
348                         break;
349                 }
350                 i++;
351         }
352
353         SDL_Delay(1);
354         now = SDL_GetTicks();
355         time_diff = now - last_time;
356         if (time_diff>0) {
357                 i = time_diff / (1000 / 60);
358                 if (i) {
359                         last_time = now;
360                 } else {
361                         int tmp;
362
363                         tmp = (1000/60) - i - 10;
364                         if (tmp>0)
365                                 SDL_Delay(tmp);
366                 }
367         }
368 /*
369         if (!then)
370                 SDL_Delay(1);
371         else {
372                 then = (1000 / 60) - (now - then);
373                 if (then > 0 && then < 1000)
374                         SDL_Delay(then);
375         }
376         then = now;
377 */
378
379 #ifdef USE_KAILLERA
380         if (my_player >= 0) {
381                 update_kaillera_keys();
382                 i=1;
383         }
384 #endif // USE_KAILLERA
385
386         return i;
387 }