rayzor

view src/dosemu/dosemu.c @ 20:6b11a3f8706e

foo
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 15 Apr 2014 01:36:03 +0300
parents d94a69933a71
children
line source
1 /* This file implements all calls made to dos-specific code using SDL */
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <SDL/SDL.h>
5 #ifdef DOSEMU_CAPTURE
6 #include <imago2.h>
7 #endif
8 #include "gfx.h"
9 #include "mouse.h"
10 #include "keyb.h"
11 #include "timer.h"
13 static void cleanup(void);
14 static void proc_events(void);
15 static int translate_sdlkey(int sym);
16 static void update_modkeys(void);
17 static void capture_frame(unsigned char *frame);
19 static void init_sdl(void)
20 {
21 const SDL_version *ver;
23 if(!SDL_WasInit(SDL_INIT_EVERYTHING)) {
24 SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
26 if((ver = SDL_Linked_Version())) {
27 printf("SDL %d.%d.%d initialized\n", ver->major, ver->minor, ver->patch);
28 }
29 atexit(cleanup);
30 }
31 }
33 static void cleanup(void)
34 {
35 SDL_Quit();
36 }
38 /* ----- graphics (gfx.c (vbe) implementation) ----- */
39 static SDL_Surface *fbsurf;
40 static int scale = 1;
41 static int frames_to_capture;
43 static struct {
44 unsigned char r, g, b;
45 } palette[256];
48 void *set_video_mode(int xsz, int ysz, int bpp)
49 {
50 unsigned int sdl_flags = bpp <= 8 ? SDL_HWPALETTE : 0;
51 char *env;
53 if(getenv("DOSEMU_DOUBLESIZE")) {
54 scale = 2;
55 }
57 if((env = getenv("DOSEMU_SCALE"))) {
58 int n = atoi(env);
59 if(n > 0) {
60 scale = n;
61 }
62 }
63 xsz *= scale;
64 ysz *= scale;
66 if(getenv("DOSEMU_FULLSCREEN")) {
67 sdl_flags |= SDL_FULLSCREEN;
68 }
70 init_sdl();
72 if(!(fbsurf = SDL_SetVideoMode(xsz, ysz, bpp, sdl_flags))) {
73 fprintf(stderr, "failed to set video mode\n");
74 abort();
75 }
76 SDL_WM_SetCaption("Rayzor", 0);
77 /*SDL_ShowCursor(0);*/
79 return fbsurf->pixels;
80 }
82 int set_text_mode(void)
83 {
84 SDL_ShowCursor(1);
85 SDL_EnableKeyRepeat(0, 0);
86 return 0;
87 }
89 int get_color_depth(void)
90 {
91 return fbsurf->format->BitsPerPixel;
92 }
94 static int count_bits(unsigned int x)
95 {
96 int i, count = 0;
97 for(i=0; i<32; i++) {
98 if(x & 1) {
99 count++;
100 }
101 x >>= 1;
102 }
103 return count;
104 }
106 int get_color_bits(int *rbits, int *gbits, int *bbits)
107 {
108 *rbits = count_bits(fbsurf->format->Rmask);
109 *gbits = count_bits(fbsurf->format->Gmask);
110 *bbits = count_bits(fbsurf->format->Bmask);
111 return *rbits + *gbits + *bbits;
112 }
114 int get_color_shift(int *rshift, int *gshift, int *bshift)
115 {
116 *rshift = fbsurf->format->Rshift;
117 *gshift = fbsurf->format->Gshift;
118 *bshift = fbsurf->format->Bshift;
119 return 0;
120 }
122 int get_color_mask(unsigned int *rmask, unsigned int *gmask, unsigned int *bmask)
123 {
124 *rmask = fbsurf->format->Rmask;
125 *gmask = fbsurf->format->Gmask;
126 *bmask = fbsurf->format->Bmask;
127 return 0;
128 }
131 void set_palette(int idx, int r, int g, int b)
132 {
133 SDL_Color col;
134 col.r = r;
135 col.g = g;
136 col.b = b;
138 if(SDL_SetPalette(fbsurf, SDL_LOGPAL | SDL_PHYSPAL, &col, idx, 1) != 1) {
139 fprintf(stderr, "set_palette failed to set the required color\n");
140 }
142 palette[idx].r = r;
143 palette[idx].g = g;
144 palette[idx].b = b;
145 }
147 static int copy_frame_called;
149 void copy_frame(void *pixels)
150 {
151 unsigned char *frame = (unsigned char*)pixels;
152 copy_frame_called = 1;
154 if(SDL_MUSTLOCK(fbsurf)) {
155 SDL_LockSurface(fbsurf);
156 }
158 if(pixels) {
159 if(scale > 1) {
160 int i, j, xsz, ysz;
161 unsigned char *dest = fbsurf->pixels;
163 xsz = fbsurf->w * scale;
164 ysz = fbsurf->h * scale;
166 for(i=0; i<ysz; i++) {
167 for(j=0; j<xsz; j++) {
168 *dest++ = frame[(i / scale) * fbsurf->w + (j / scale)];
169 }
170 }
171 } else {
172 int num_pixels = fbsurf->w * fbsurf->h;
173 memcpy(fbsurf->pixels, frame, num_pixels * fbsurf->format->BytesPerPixel);
174 }
175 }
177 if(SDL_MUSTLOCK(fbsurf)) {
178 SDL_UnlockSurface(fbsurf);
179 }
181 SDL_Flip(fbsurf);
183 if(frames_to_capture > 0) {
184 capture_frame(pixels);
185 --frames_to_capture;
186 }
188 /* also print fps every second ... */
189 /*{
190 static long prev_fps, num_frames;
191 long msec, dt;
193 msec = get_msec();
194 dt = msec - prev_fps;
195 if(dt >= 1000) {
196 float fps = (float)num_frames / ((float)dt / 1000.0f);
197 printf("framerate: %.1f \r", fps);
198 fflush(stdout);
199 num_frames = 0;
200 prev_fps = msec;
201 } else {
202 num_frames++;
203 }
204 }*/
205 }
207 #define spin_delay(ms) \
208 do { \
209 unsigned int end = SDL_GetTicks() + ms; \
210 while((prev_msec = SDL_GetTicks()) < end); \
211 } while(0)
213 #define FRAME_INTERVAL (1000/70)
215 void wait_vsync(void)
216 {
217 /*static int prev_msec;
218 int msec, dt, tleft;*/
220 if(!copy_frame_called) {
221 copy_frame(0);
222 copy_frame_called = 0;
223 }
225 /*
226 msec = SDL_GetTicks();
228 dt = msec - prev_msec;
230 tleft = FRAME_INTERVAL - dt;
231 if(tleft > 0) {
232 int coarse = tleft & 0xfffffff8;
233 tleft = tleft & 7;
235 if(coarse) {
236 SDL_Delay(coarse);
237 }
238 if(tleft) {
239 spin_delay(tleft);
240 } else {
241 prev_msec = SDL_GetTicks();
242 }
243 } else {
244 prev_msec = msec;
245 }
246 */
247 }
249 static int cap_count = 0;
250 void begin_capture(int frames)
251 {
252 frames_to_capture = frames;
253 }
255 void end_capture(void)
256 {
257 cap_count = 0;
258 frames_to_capture = 0;
259 }
261 #define NUMPIX (fbsurf->w * fbsurf->h)
262 static void capture_frame(unsigned char *frame)
263 {
264 #ifdef DOSEMU_CAPTURE
265 static unsigned char rgbpix[NUMPIX * 4];
266 char fname[32];
267 int i;
268 unsigned char *src, *dest;
270 sprintf(fname, "frame%04d.png", cap_count++);
272 src = frame;
273 dest = rgbpix;
275 for(i=0; i<NUMPIX; i++) {
276 unsigned char c = *src++;
277 *dest++ = palette[c].r;
278 *dest++ = palette[c].g;
279 *dest++ = palette[c].b;
280 *dest++ = 255;
281 }
283 img_save_pixels(fname, rgbpix, fbsurf->w, fbsurf->h, IMG_FMT_RGBA32);
284 #endif
285 }
288 /* ----- event handling (conio.h) ----- */
289 static SDL_Event *keybev;
290 static int mousex, mousey, bnmask;
292 static int keystate[256];
293 static int num_pressed;
295 int kbhit(void)
296 {
297 if(!keybev) {
298 proc_events();
299 }
300 return keybev != 0;
301 }
303 int getch(void)
304 {
305 int res;
307 while(!keybev) {
308 SDL_Event ev;
309 SDL_WaitEvent(&ev);
310 SDL_PushEvent(&ev);
311 proc_events();
312 }
313 res = keybev->key.keysym.sym;
314 keybev = 0;
315 return res;
316 }
318 /* ----- improved event handling (keyb.h) ---- */
319 static char sdlkey_tbl[SDLK_LAST];
321 int kb_init(int bufsz)
322 {
323 int i;
324 init_sdl();
326 /* construct the SDL key translation table */
327 for(i=0; i<256; i++) {
328 sdlkey_tbl[i] = i; /* start from an identity mapping for the first 256 */
329 }
330 /* then change the special keys */
331 sdlkey_tbl[SDLK_LALT] = KB_LALT;
332 sdlkey_tbl[SDLK_RALT] = KB_RALT;
333 sdlkey_tbl[SDLK_LCTRL] = KB_LCTRL;
334 sdlkey_tbl[SDLK_RCTRL] = KB_RCTRL;
335 sdlkey_tbl[SDLK_LSHIFT] = KB_LSHIFT;
336 for(i=0; i<12; i++) {
337 sdlkey_tbl[SDLK_F1 + i] = KB_F1 + i;
338 }
339 sdlkey_tbl[SDLK_CAPSLOCK] = KB_CAPSLK;
340 sdlkey_tbl[SDLK_NUMLOCK] = KB_NUMLK;
341 sdlkey_tbl[SDLK_SCROLLOCK] = KB_SCRLK;
342 sdlkey_tbl[SDLK_SYSREQ] = KB_SYSRQ;
343 sdlkey_tbl[SDLK_ESCAPE] = KB_ESC;
344 sdlkey_tbl[SDLK_INSERT] = KB_INSERT;
345 sdlkey_tbl[SDLK_DELETE] = KB_DEL;
346 sdlkey_tbl[SDLK_HOME] = KB_HOME;
347 sdlkey_tbl[SDLK_END] = KB_END;
348 sdlkey_tbl[SDLK_PAGEUP] = KB_PGUP;
349 sdlkey_tbl[SDLK_PAGEDOWN] = KB_PGDN;
350 sdlkey_tbl[SDLK_LEFT] = KB_LEFT;
351 sdlkey_tbl[SDLK_RIGHT] = KB_RIGHT;
352 sdlkey_tbl[SDLK_UP] = KB_UP;
353 sdlkey_tbl[SDLK_DOWN] = KB_DOWN;
354 sdlkey_tbl[SDLK_KP_PERIOD] = KB_NUM_DOT;
355 sdlkey_tbl[SDLK_KP_ENTER] = KB_NUM_ENTER;
356 sdlkey_tbl[SDLK_KP_PLUS] = KB_NUM_PLUS;
357 sdlkey_tbl[SDLK_KP_MINUS] = KB_NUM_MINUS;
358 sdlkey_tbl[SDLK_KP_MULTIPLY] = KB_NUM_MUL;
359 sdlkey_tbl[SDLK_KP_DIVIDE] = KB_NUM_DIV;
360 /* TODO missing numeric keypad numbers */
361 sdlkey_tbl[SDLK_BACKSPACE] = KB_BACKSP;
364 return 0;
365 }
367 void kb_shutdown(void)
368 {
369 }
371 int kb_getkey(void)
372 {
373 int res = -1;
375 proc_events();
376 if(keybev) {
377 res = translate_sdlkey(keybev->key.keysym.sym);
378 keybev = 0;
379 }
380 return res;
381 }
383 int kb_isdown(int key)
384 {
385 switch(key) {
386 case KB_ANY:
387 return num_pressed;
389 case KB_ALT:
390 return keystate[KB_LALT] + keystate[KB_RALT];
392 case KB_CTRL:
393 return keystate[KB_LCTRL] + keystate[KB_RCTRL];
394 }
395 return keystate[key];
396 }
398 /* mouse handling (mouse.c implementation) */
399 static unsigned long last_mouse_hide_time;
401 int have_mouse(void)
402 {
403 return 1;
404 }
406 void set_mouse_limits(int xmin, int ymin, int xmax, int ymax)
407 {
408 }
410 void set_mouse(int x, int y)
411 {
412 SDL_ShowCursor(0);
413 last_mouse_hide_time = get_msec();
415 SDL_WarpMouse(x * scale, y * scale);
416 mousex = x;
417 mousey = y;
418 }
420 int read_mouse(int *xp, int *yp)
421 {
422 if(xp) *xp = mousex;
423 if(yp) *yp = mousey;
424 return bnmask;
425 }
427 static void proc_events(void)
428 {
429 static SDL_Event ev;
431 if(last_mouse_hide_time > 0 && get_msec() - last_mouse_hide_time > 3000) {
432 last_mouse_hide_time = 0;
433 SDL_ShowCursor(1);
434 }
436 while(SDL_PollEvent(&ev)) {
437 switch(ev.type) {
438 case SDL_KEYDOWN:
439 {
440 int key = translate_sdlkey(ev.key.keysym.sym);
442 if(!keybev) {
443 keybev = &ev;
444 }
446 if(!keystate[key]) {
447 keystate[key] = 1;
448 num_pressed++;
449 }
451 update_modkeys();
452 }
453 break;
455 case SDL_KEYUP:
456 {
457 int key = translate_sdlkey(ev.key.keysym.sym);
459 if(keystate[key]) {
460 keystate[key] = 0;
461 if(--num_pressed < 0) {
462 num_pressed = 0;
463 }
464 }
466 update_modkeys();
467 }
468 break;
470 case SDL_MOUSEMOTION:
471 mousex = ev.motion.x / scale;
472 mousey = ev.motion.y / scale;
473 break;
475 case SDL_MOUSEBUTTONDOWN:
476 case SDL_MOUSEBUTTONUP:
477 {
478 int mask = 0;
479 switch(ev.button.button) {
480 case SDL_BUTTON_LEFT:
481 mask = MOUSE_LEFT;
482 break;
483 case SDL_BUTTON_MIDDLE:
484 mask = MOUSE_MIDDLE;
485 break;
486 case SDL_BUTTON_RIGHT:
487 mask = MOUSE_RIGHT;
488 default:
489 break;
490 }
491 if(!mask) {
492 break;
493 }
495 if(ev.button.state == SDL_PRESSED) {
496 bnmask |= mask;
497 } else {
498 bnmask &= ~mask;
499 }
500 }
501 break;
503 default:
504 break;
505 }
506 }
507 }
509 static int translate_sdlkey(int sym)
510 {
511 return sdlkey_tbl[sym];
512 }
514 static void update_modkeys(void)
515 {
516 unsigned int mod = SDL_GetModState();
518 keystate[KB_LALT] = mod & KMOD_LALT;
519 keystate[KB_RALT] = mod & KMOD_RALT;
520 keystate[KB_LCTRL] = mod & KMOD_LCTRL;
521 keystate[KB_RCTRL] = mod & KMOD_RCTRL;
522 keystate[KB_LSHIFT] = mod & KMOD_LSHIFT;
523 keystate[KB_RSHIFT] = mod & KMOD_RSHIFT;
524 }
526 /* ---- timer.c implementation ---- */
527 static Uint32 start_time;
529 void init_timer(int res_hz)
530 {
531 init_sdl();
532 reset_timer();
533 }
535 void reset_timer(void)
536 {
537 start_time = SDL_GetTicks();
538 printf("resetting timer: %u, %lu\n", start_time, get_msec());
539 }
541 unsigned long get_msec(void)
542 {
543 Uint32 ticks = SDL_GetTicks();
544 return (unsigned long)(ticks - start_time);
545 }