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