rayzor

view src/dosemu/dosemu.c @ 10:235c8b764c0b

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