rev |
line source |
nuclear@5
|
1 /* This file implements all calls made to dos-specific code using SDL */
|
nuclear@5
|
2 #include <stdlib.h>
|
nuclear@5
|
3 #include <assert.h>
|
nuclear@5
|
4 #include <SDL/SDL.h>
|
nuclear@5
|
5 #ifdef DOSEMU_CAPTURE
|
nuclear@5
|
6 #include <imago2.h>
|
nuclear@5
|
7 #endif
|
nuclear@5
|
8 #include "gfx.h"
|
nuclear@5
|
9 #include "mouse.h"
|
nuclear@5
|
10 #include "keyb.h"
|
nuclear@5
|
11 #include "timer.h"
|
nuclear@5
|
12
|
nuclear@9
|
13 static void cleanup(void);
|
nuclear@5
|
14 static void proc_events(void);
|
nuclear@5
|
15 static void capture_frame(unsigned char *frame);
|
nuclear@5
|
16
|
nuclear@9
|
17 static void init_sdl(void)
|
nuclear@5
|
18 {
|
nuclear@5
|
19 const SDL_version *ver;
|
nuclear@5
|
20
|
nuclear@5
|
21 if(!SDL_WasInit(SDL_INIT_EVERYTHING)) {
|
nuclear@5
|
22 SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
nuclear@5
|
23
|
nuclear@5
|
24 if((ver = SDL_Linked_Version())) {
|
nuclear@5
|
25 printf("SDL %d.%d.%d initialized\n", ver->major, ver->minor, ver->patch);
|
nuclear@5
|
26 }
|
nuclear@9
|
27 atexit(cleanup);
|
nuclear@5
|
28 }
|
nuclear@5
|
29 }
|
nuclear@5
|
30
|
nuclear@9
|
31 static void cleanup(void)
|
nuclear@9
|
32 {
|
nuclear@9
|
33 SDL_Quit();
|
nuclear@9
|
34 }
|
nuclear@9
|
35
|
nuclear@5
|
36 /* ----- graphics (gfx.c (vbe) implementation) ----- */
|
nuclear@5
|
37 static SDL_Surface *fbsurf;
|
nuclear@5
|
38 static int scale = 1;
|
nuclear@5
|
39 static int frames_to_capture;
|
nuclear@5
|
40
|
nuclear@5
|
41 static struct {
|
nuclear@5
|
42 unsigned char r, g, b;
|
nuclear@5
|
43 } palette[256];
|
nuclear@5
|
44
|
nuclear@5
|
45
|
nuclear@5
|
46 void *set_video_mode(int xsz, int ysz, int bpp)
|
nuclear@5
|
47 {
|
nuclear@5
|
48 unsigned int sdl_flags = bpp <= 8 ? SDL_HWPALETTE : 0;
|
nuclear@5
|
49 char *env;
|
nuclear@5
|
50
|
nuclear@5
|
51 if(getenv("DOSEMU_DOUBLESIZE")) {
|
nuclear@5
|
52 scale = 2;
|
nuclear@5
|
53 }
|
nuclear@5
|
54
|
nuclear@5
|
55 if((env = getenv("DOSEMU_SCALE"))) {
|
nuclear@5
|
56 int n = atoi(env);
|
nuclear@5
|
57 if(n > 0) {
|
nuclear@5
|
58 scale = n;
|
nuclear@5
|
59 }
|
nuclear@5
|
60 }
|
nuclear@5
|
61 xsz *= scale;
|
nuclear@5
|
62 ysz *= scale;
|
nuclear@5
|
63
|
nuclear@5
|
64 if(getenv("DOSEMU_FULLSCREEN")) {
|
nuclear@5
|
65 sdl_flags |= SDL_FULLSCREEN;
|
nuclear@5
|
66 }
|
nuclear@5
|
67
|
nuclear@5
|
68 init_sdl();
|
nuclear@5
|
69
|
nuclear@5
|
70 if(!(fbsurf = SDL_SetVideoMode(xsz, ysz, bpp, sdl_flags))) {
|
nuclear@5
|
71 fprintf(stderr, "failed to set video mode\n");
|
nuclear@5
|
72 abort();
|
nuclear@5
|
73 }
|
nuclear@5
|
74 SDL_WM_SetCaption("Rayzor", 0);
|
nuclear@5
|
75 /*SDL_ShowCursor(0);*/
|
nuclear@5
|
76
|
nuclear@5
|
77 return fbsurf->pixels;
|
nuclear@5
|
78 }
|
nuclear@5
|
79
|
nuclear@5
|
80 int set_text_mode(void)
|
nuclear@5
|
81 {
|
nuclear@5
|
82 SDL_ShowCursor(1);
|
nuclear@5
|
83 SDL_EnableKeyRepeat(0, 0);
|
nuclear@5
|
84 return 0;
|
nuclear@5
|
85 }
|
nuclear@5
|
86
|
nuclear@5
|
87 int get_color_depth(void)
|
nuclear@5
|
88 {
|
nuclear@5
|
89 return fbsurf->format->BitsPerPixel;
|
nuclear@5
|
90 }
|
nuclear@5
|
91
|
nuclear@5
|
92 static int count_bits(unsigned int x)
|
nuclear@5
|
93 {
|
nuclear@5
|
94 int i, count = 0;
|
nuclear@5
|
95 for(i=0; i<32; i++) {
|
nuclear@5
|
96 if(x & 1) {
|
nuclear@5
|
97 count++;
|
nuclear@5
|
98 }
|
nuclear@5
|
99 x >>= 1;
|
nuclear@5
|
100 }
|
nuclear@5
|
101 return count;
|
nuclear@5
|
102 }
|
nuclear@5
|
103
|
nuclear@5
|
104 int get_color_bits(int *rbits, int *gbits, int *bbits)
|
nuclear@5
|
105 {
|
nuclear@5
|
106 *rbits = count_bits(fbsurf->format->Rmask);
|
nuclear@5
|
107 *gbits = count_bits(fbsurf->format->Gmask);
|
nuclear@5
|
108 *bbits = count_bits(fbsurf->format->Bmask);
|
nuclear@5
|
109 return *rbits + *gbits + *bbits;
|
nuclear@5
|
110 }
|
nuclear@5
|
111
|
nuclear@5
|
112 int get_color_shift(int *rshift, int *gshift, int *bshift)
|
nuclear@5
|
113 {
|
nuclear@5
|
114 *rshift = fbsurf->format->Rshift;
|
nuclear@5
|
115 *gshift = fbsurf->format->Gshift;
|
nuclear@5
|
116 *bshift = fbsurf->format->Bshift;
|
nuclear@5
|
117 return 0;
|
nuclear@5
|
118 }
|
nuclear@5
|
119
|
nuclear@5
|
120 int get_color_mask(unsigned int *rmask, unsigned int *gmask, unsigned int *bmask)
|
nuclear@5
|
121 {
|
nuclear@5
|
122 *rmask = fbsurf->format->Rmask;
|
nuclear@5
|
123 *gmask = fbsurf->format->Gmask;
|
nuclear@5
|
124 *bmask = fbsurf->format->Bmask;
|
nuclear@5
|
125 return 0;
|
nuclear@5
|
126 }
|
nuclear@5
|
127
|
nuclear@5
|
128
|
nuclear@5
|
129 void set_palette(int idx, int r, int g, int b)
|
nuclear@5
|
130 {
|
nuclear@5
|
131 SDL_Color col;
|
nuclear@5
|
132 col.r = r;
|
nuclear@5
|
133 col.g = g;
|
nuclear@5
|
134 col.b = b;
|
nuclear@5
|
135
|
nuclear@5
|
136 if(SDL_SetPalette(fbsurf, SDL_LOGPAL | SDL_PHYSPAL, &col, idx, 1) != 1) {
|
nuclear@5
|
137 fprintf(stderr, "set_palette failed to set the required color\n");
|
nuclear@5
|
138 }
|
nuclear@5
|
139
|
nuclear@5
|
140 palette[idx].r = r;
|
nuclear@5
|
141 palette[idx].g = g;
|
nuclear@5
|
142 palette[idx].b = b;
|
nuclear@5
|
143 }
|
nuclear@5
|
144
|
nuclear@5
|
145 static int copy_frame_called;
|
nuclear@5
|
146
|
nuclear@5
|
147 void copy_frame(void *pixels)
|
nuclear@5
|
148 {
|
nuclear@5
|
149 unsigned char *frame = (unsigned char*)pixels;
|
nuclear@5
|
150 copy_frame_called = 1;
|
nuclear@5
|
151
|
nuclear@5
|
152 if(SDL_MUSTLOCK(fbsurf)) {
|
nuclear@5
|
153 SDL_LockSurface(fbsurf);
|
nuclear@5
|
154 }
|
nuclear@5
|
155
|
nuclear@5
|
156 if(pixels) {
|
nuclear@5
|
157 if(scale > 1) {
|
nuclear@5
|
158 int i, j, xsz, ysz;
|
nuclear@5
|
159 unsigned char *dest = fbsurf->pixels;
|
nuclear@5
|
160
|
nuclear@5
|
161 xsz = fbsurf->w * scale;
|
nuclear@5
|
162 ysz = fbsurf->h * scale;
|
nuclear@5
|
163
|
nuclear@5
|
164 for(i=0; i<ysz; i++) {
|
nuclear@5
|
165 for(j=0; j<xsz; j++) {
|
nuclear@5
|
166 *dest++ = frame[(i / scale) * fbsurf->w + (j / scale)];
|
nuclear@5
|
167 }
|
nuclear@5
|
168 }
|
nuclear@5
|
169 } else {
|
nuclear@5
|
170 int num_pixels = fbsurf->w * fbsurf->h;
|
nuclear@5
|
171 memcpy(fbsurf->pixels, frame, num_pixels * fbsurf->format->BytesPerPixel);
|
nuclear@5
|
172 }
|
nuclear@5
|
173 }
|
nuclear@5
|
174
|
nuclear@5
|
175 if(SDL_MUSTLOCK(fbsurf)) {
|
nuclear@5
|
176 SDL_UnlockSurface(fbsurf);
|
nuclear@5
|
177 }
|
nuclear@5
|
178
|
nuclear@5
|
179 SDL_Flip(fbsurf);
|
nuclear@5
|
180
|
nuclear@5
|
181 if(frames_to_capture > 0) {
|
nuclear@5
|
182 capture_frame(pixels);
|
nuclear@5
|
183 --frames_to_capture;
|
nuclear@5
|
184 }
|
nuclear@5
|
185
|
nuclear@5
|
186 /* also print fps every second ... */
|
nuclear@9
|
187 /*{
|
nuclear@5
|
188 static long prev_fps, num_frames;
|
nuclear@5
|
189 long msec, dt;
|
nuclear@5
|
190
|
nuclear@5
|
191 msec = get_msec();
|
nuclear@5
|
192 dt = msec - prev_fps;
|
nuclear@5
|
193 if(dt >= 1000) {
|
nuclear@5
|
194 float fps = (float)num_frames / ((float)dt / 1000.0f);
|
nuclear@5
|
195 printf("framerate: %.1f \r", fps);
|
nuclear@5
|
196 fflush(stdout);
|
nuclear@5
|
197 num_frames = 0;
|
nuclear@5
|
198 prev_fps = msec;
|
nuclear@5
|
199 } else {
|
nuclear@5
|
200 num_frames++;
|
nuclear@5
|
201 }
|
nuclear@9
|
202 }*/
|
nuclear@5
|
203 }
|
nuclear@5
|
204
|
nuclear@5
|
205 #define spin_delay(ms) \
|
nuclear@5
|
206 do { \
|
nuclear@5
|
207 unsigned int end = SDL_GetTicks() + ms; \
|
nuclear@5
|
208 while((prev_msec = SDL_GetTicks()) < end); \
|
nuclear@5
|
209 } while(0)
|
nuclear@5
|
210
|
nuclear@5
|
211 #define FRAME_INTERVAL (1000/70)
|
nuclear@5
|
212
|
nuclear@5
|
213 void wait_vsync(void)
|
nuclear@5
|
214 {
|
nuclear@9
|
215 /*static int prev_msec;
|
nuclear@9
|
216 int msec, dt, tleft;*/
|
nuclear@5
|
217
|
nuclear@5
|
218 if(!copy_frame_called) {
|
nuclear@5
|
219 copy_frame(0);
|
nuclear@5
|
220 copy_frame_called = 0;
|
nuclear@5
|
221 }
|
nuclear@5
|
222
|
nuclear@9
|
223 /*
|
nuclear@5
|
224 msec = SDL_GetTicks();
|
nuclear@5
|
225
|
nuclear@5
|
226 dt = msec - prev_msec;
|
nuclear@5
|
227
|
nuclear@5
|
228 tleft = FRAME_INTERVAL - dt;
|
nuclear@5
|
229 if(tleft > 0) {
|
nuclear@5
|
230 int coarse = tleft & 0xfffffff8;
|
nuclear@5
|
231 tleft = tleft & 7;
|
nuclear@5
|
232
|
nuclear@5
|
233 if(coarse) {
|
nuclear@5
|
234 SDL_Delay(coarse);
|
nuclear@5
|
235 }
|
nuclear@5
|
236 if(tleft) {
|
nuclear@5
|
237 spin_delay(tleft);
|
nuclear@5
|
238 } else {
|
nuclear@5
|
239 prev_msec = SDL_GetTicks();
|
nuclear@5
|
240 }
|
nuclear@5
|
241 } else {
|
nuclear@5
|
242 prev_msec = msec;
|
nuclear@5
|
243 }
|
nuclear@9
|
244 */
|
nuclear@5
|
245 }
|
nuclear@5
|
246
|
nuclear@5
|
247 static int cap_count = 0;
|
nuclear@5
|
248 void begin_capture(int frames)
|
nuclear@5
|
249 {
|
nuclear@5
|
250 frames_to_capture = frames;
|
nuclear@5
|
251 }
|
nuclear@5
|
252
|
nuclear@5
|
253 void end_capture(void)
|
nuclear@5
|
254 {
|
nuclear@5
|
255 cap_count = 0;
|
nuclear@5
|
256 frames_to_capture = 0;
|
nuclear@5
|
257 }
|
nuclear@5
|
258
|
nuclear@5
|
259 #define NUMPIX (fbsurf->w * fbsurf->h)
|
nuclear@5
|
260 static void capture_frame(unsigned char *frame)
|
nuclear@5
|
261 {
|
nuclear@5
|
262 #ifdef DOSEMU_CAPTURE
|
nuclear@5
|
263 static unsigned char rgbpix[NUMPIX * 4];
|
nuclear@5
|
264 char fname[32];
|
nuclear@5
|
265 int i;
|
nuclear@5
|
266 unsigned char *src, *dest;
|
nuclear@5
|
267
|
nuclear@5
|
268 sprintf(fname, "frame%04d.png", cap_count++);
|
nuclear@5
|
269
|
nuclear@5
|
270 src = frame;
|
nuclear@5
|
271 dest = rgbpix;
|
nuclear@5
|
272
|
nuclear@5
|
273 for(i=0; i<NUMPIX; i++) {
|
nuclear@5
|
274 unsigned char c = *src++;
|
nuclear@5
|
275 *dest++ = palette[c].r;
|
nuclear@5
|
276 *dest++ = palette[c].g;
|
nuclear@5
|
277 *dest++ = palette[c].b;
|
nuclear@5
|
278 *dest++ = 255;
|
nuclear@5
|
279 }
|
nuclear@5
|
280
|
nuclear@5
|
281 img_save_pixels(fname, rgbpix, fbsurf->w, fbsurf->h, IMG_FMT_RGBA32);
|
nuclear@5
|
282 #endif
|
nuclear@5
|
283 }
|
nuclear@5
|
284
|
nuclear@5
|
285
|
nuclear@5
|
286 /* ----- event handling (conio.h) ----- */
|
nuclear@5
|
287 static SDL_Event *keybev;
|
nuclear@5
|
288 static int mousex, mousey, bnmask;
|
nuclear@5
|
289
|
nuclear@5
|
290 static int keystate[256];
|
nuclear@5
|
291 static int num_pressed;
|
nuclear@5
|
292
|
nuclear@5
|
293 int kbhit(void)
|
nuclear@5
|
294 {
|
nuclear@5
|
295 if(!keybev) {
|
nuclear@5
|
296 proc_events();
|
nuclear@5
|
297 }
|
nuclear@5
|
298 return keybev != 0;
|
nuclear@5
|
299 }
|
nuclear@5
|
300
|
nuclear@5
|
301 int getch(void)
|
nuclear@5
|
302 {
|
nuclear@5
|
303 int res;
|
nuclear@5
|
304
|
nuclear@5
|
305 while(!keybev) {
|
nuclear@5
|
306 SDL_Event ev;
|
nuclear@5
|
307 SDL_WaitEvent(&ev);
|
nuclear@5
|
308 SDL_PushEvent(&ev);
|
nuclear@5
|
309 proc_events();
|
nuclear@5
|
310 }
|
nuclear@5
|
311 res = keybev->key.keysym.sym;
|
nuclear@5
|
312 keybev = 0;
|
nuclear@5
|
313 return res;
|
nuclear@5
|
314 }
|
nuclear@5
|
315
|
nuclear@5
|
316 /* ----- improved event handling (keyb.h) ---- */
|
nuclear@5
|
317
|
nuclear@5
|
318 int kb_init(int bufsz)
|
nuclear@5
|
319 {
|
nuclear@5
|
320 init_sdl();
|
nuclear@5
|
321
|
nuclear@5
|
322 return 0;
|
nuclear@5
|
323 }
|
nuclear@5
|
324
|
nuclear@5
|
325 void kb_shutdown(void)
|
nuclear@5
|
326 {
|
nuclear@5
|
327 }
|
nuclear@5
|
328
|
nuclear@5
|
329 int kb_getkey(void)
|
nuclear@5
|
330 {
|
nuclear@5
|
331 int res = -1;
|
nuclear@5
|
332
|
nuclear@5
|
333 proc_events();
|
nuclear@5
|
334 if(keybev) {
|
nuclear@5
|
335 res = keybev->key.keysym.sym;
|
nuclear@5
|
336 keybev = 0;
|
nuclear@5
|
337 }
|
nuclear@5
|
338 return res;
|
nuclear@5
|
339 }
|
nuclear@5
|
340
|
nuclear@5
|
341 int kb_isdown(int key)
|
nuclear@5
|
342 {
|
nuclear@5
|
343 if(key == KB_ANY) {
|
nuclear@5
|
344 return num_pressed;
|
nuclear@5
|
345 }
|
nuclear@5
|
346 return keystate[key];
|
nuclear@5
|
347 }
|
nuclear@5
|
348
|
nuclear@5
|
349 /* mouse handling (mouse.c implementation) */
|
nuclear@5
|
350 static unsigned long last_mouse_hide_time;
|
nuclear@5
|
351
|
nuclear@5
|
352 int have_mouse(void)
|
nuclear@5
|
353 {
|
nuclear@5
|
354 return 1;
|
nuclear@5
|
355 }
|
nuclear@5
|
356
|
nuclear@8
|
357 void set_mouse_limits(int xmin, int ymin, int xmax, int ymax)
|
nuclear@8
|
358 {
|
nuclear@8
|
359 }
|
nuclear@8
|
360
|
nuclear@5
|
361 void set_mouse(int x, int y)
|
nuclear@5
|
362 {
|
nuclear@5
|
363 SDL_ShowCursor(0);
|
nuclear@5
|
364 last_mouse_hide_time = get_msec();
|
nuclear@5
|
365
|
nuclear@5
|
366 SDL_WarpMouse(x * scale, y * scale);
|
nuclear@5
|
367 mousex = x;
|
nuclear@5
|
368 mousey = y;
|
nuclear@5
|
369 }
|
nuclear@5
|
370
|
nuclear@5
|
371 int read_mouse(int *xp, int *yp)
|
nuclear@5
|
372 {
|
nuclear@5
|
373 if(xp) *xp = mousex;
|
nuclear@5
|
374 if(yp) *yp = mousey;
|
nuclear@5
|
375 return bnmask;
|
nuclear@5
|
376 }
|
nuclear@5
|
377
|
nuclear@5
|
378 static void proc_events(void)
|
nuclear@5
|
379 {
|
nuclear@5
|
380 static SDL_Event ev;
|
nuclear@5
|
381
|
nuclear@5
|
382 if(last_mouse_hide_time > 0 && get_msec() - last_mouse_hide_time > 3000) {
|
nuclear@5
|
383 last_mouse_hide_time = 0;
|
nuclear@5
|
384 SDL_ShowCursor(1);
|
nuclear@5
|
385 }
|
nuclear@5
|
386
|
nuclear@5
|
387 while(SDL_PollEvent(&ev)) {
|
nuclear@5
|
388 switch(ev.type) {
|
nuclear@5
|
389 case SDL_KEYDOWN:
|
nuclear@5
|
390 {
|
nuclear@5
|
391 int key = ev.key.keysym.sym;
|
nuclear@5
|
392
|
nuclear@5
|
393 if(!keybev) {
|
nuclear@5
|
394 keybev = &ev;
|
nuclear@5
|
395 }
|
nuclear@5
|
396
|
nuclear@5
|
397 if(!keystate[key]) {
|
nuclear@5
|
398 keystate[key] = 1;
|
nuclear@5
|
399 num_pressed++;
|
nuclear@5
|
400 }
|
nuclear@5
|
401 }
|
nuclear@5
|
402 break;
|
nuclear@5
|
403
|
nuclear@5
|
404 case SDL_KEYUP:
|
nuclear@5
|
405 {
|
nuclear@5
|
406 int key = ev.key.keysym.sym;
|
nuclear@5
|
407
|
nuclear@5
|
408 if(keystate[key]) {
|
nuclear@5
|
409 keystate[key] = 0;
|
nuclear@5
|
410 if(--num_pressed < 0) {
|
nuclear@5
|
411 num_pressed = 0;
|
nuclear@5
|
412 }
|
nuclear@5
|
413 }
|
nuclear@5
|
414 }
|
nuclear@5
|
415 break;
|
nuclear@5
|
416
|
nuclear@5
|
417 case SDL_MOUSEMOTION:
|
nuclear@5
|
418 mousex = ev.motion.x / scale;
|
nuclear@5
|
419 mousey = ev.motion.y / scale;
|
nuclear@5
|
420 break;
|
nuclear@5
|
421
|
nuclear@5
|
422 case SDL_MOUSEBUTTONDOWN:
|
nuclear@5
|
423 case SDL_MOUSEBUTTONUP:
|
nuclear@5
|
424 {
|
nuclear@5
|
425 int mask = 0;
|
nuclear@5
|
426 switch(ev.button.button) {
|
nuclear@5
|
427 case SDL_BUTTON_LEFT:
|
nuclear@5
|
428 mask = MOUSE_LEFT;
|
nuclear@5
|
429 break;
|
nuclear@5
|
430 case SDL_BUTTON_MIDDLE:
|
nuclear@5
|
431 mask = MOUSE_MIDDLE;
|
nuclear@5
|
432 break;
|
nuclear@5
|
433 case SDL_BUTTON_RIGHT:
|
nuclear@5
|
434 mask = MOUSE_RIGHT;
|
nuclear@5
|
435 default:
|
nuclear@5
|
436 break;
|
nuclear@5
|
437 }
|
nuclear@5
|
438 if(!mask) {
|
nuclear@5
|
439 break;
|
nuclear@5
|
440 }
|
nuclear@5
|
441
|
nuclear@5
|
442 if(ev.button.state == SDL_PRESSED) {
|
nuclear@5
|
443 bnmask |= mask;
|
nuclear@5
|
444 } else {
|
nuclear@5
|
445 bnmask &= ~mask;
|
nuclear@5
|
446 }
|
nuclear@5
|
447 }
|
nuclear@5
|
448 break;
|
nuclear@5
|
449
|
nuclear@5
|
450 default:
|
nuclear@5
|
451 break;
|
nuclear@5
|
452 }
|
nuclear@5
|
453 }
|
nuclear@5
|
454 }
|
nuclear@5
|
455
|
nuclear@5
|
456 /* ---- timer.c implementation ---- */
|
nuclear@5
|
457 static Uint32 start_time;
|
nuclear@5
|
458
|
nuclear@5
|
459 void init_timer(int res_hz)
|
nuclear@5
|
460 {
|
nuclear@5
|
461 init_sdl();
|
nuclear@5
|
462 reset_timer();
|
nuclear@5
|
463 }
|
nuclear@5
|
464
|
nuclear@5
|
465 void reset_timer(void)
|
nuclear@5
|
466 {
|
nuclear@5
|
467 start_time = SDL_GetTicks();
|
nuclear@5
|
468 printf("resetting timer: %u, %lu\n", start_time, get_msec());
|
nuclear@5
|
469 }
|
nuclear@5
|
470
|
nuclear@5
|
471 unsigned long get_msec(void)
|
nuclear@5
|
472 {
|
nuclear@5
|
473 Uint32 ticks = SDL_GetTicks();
|
nuclear@5
|
474 return (unsigned long)(ticks - start_time);
|
nuclear@5
|
475 }
|