rayzor
diff src/dosemu/dosemu.c @ 5:5fcf72837b69
fixed the dosemu bit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 06 Apr 2014 02:43:24 +0300 |
parents | |
children | fcd06a15dfdd |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/dosemu/dosemu.c Sun Apr 06 02:43:24 2014 +0300 1.3 @@ -0,0 +1,463 @@ 1.4 +/* This file implements all calls made to dos-specific code using SDL */ 1.5 +#include <stdlib.h> 1.6 +#include <assert.h> 1.7 +#include <SDL/SDL.h> 1.8 +#ifdef DOSEMU_CAPTURE 1.9 +#include <imago2.h> 1.10 +#endif 1.11 +#include "gfx.h" 1.12 +#include "mouse.h" 1.13 +#include "keyb.h" 1.14 +#include "timer.h" 1.15 + 1.16 +static void proc_events(void); 1.17 +static void capture_frame(unsigned char *frame); 1.18 + 1.19 +static void init_sdl() 1.20 +{ 1.21 + const SDL_version *ver; 1.22 + 1.23 + if(!SDL_WasInit(SDL_INIT_EVERYTHING)) { 1.24 + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER); 1.25 + 1.26 + if((ver = SDL_Linked_Version())) { 1.27 + printf("SDL %d.%d.%d initialized\n", ver->major, ver->minor, ver->patch); 1.28 + } 1.29 + } 1.30 +} 1.31 + 1.32 +/* ----- graphics (gfx.c (vbe) implementation) ----- */ 1.33 +static SDL_Surface *fbsurf; 1.34 +static int scale = 1; 1.35 +static int frames_to_capture; 1.36 + 1.37 +static struct { 1.38 + unsigned char r, g, b; 1.39 +} palette[256]; 1.40 + 1.41 + 1.42 +void *set_video_mode(int xsz, int ysz, int bpp) 1.43 +{ 1.44 + unsigned int sdl_flags = bpp <= 8 ? SDL_HWPALETTE : 0; 1.45 + char *env; 1.46 + 1.47 + if(getenv("DOSEMU_DOUBLESIZE")) { 1.48 + scale = 2; 1.49 + } 1.50 + 1.51 + if((env = getenv("DOSEMU_SCALE"))) { 1.52 + int n = atoi(env); 1.53 + if(n > 0) { 1.54 + scale = n; 1.55 + } 1.56 + } 1.57 + xsz *= scale; 1.58 + ysz *= scale; 1.59 + 1.60 + if(getenv("DOSEMU_FULLSCREEN")) { 1.61 + sdl_flags |= SDL_FULLSCREEN; 1.62 + } 1.63 + 1.64 + init_sdl(); 1.65 + 1.66 + if(!(fbsurf = SDL_SetVideoMode(xsz, ysz, bpp, sdl_flags))) { 1.67 + fprintf(stderr, "failed to set video mode\n"); 1.68 + abort(); 1.69 + } 1.70 + SDL_WM_SetCaption("Rayzor", 0); 1.71 + /*SDL_ShowCursor(0);*/ 1.72 + 1.73 + return fbsurf->pixels; 1.74 +} 1.75 + 1.76 +int set_text_mode(void) 1.77 +{ 1.78 + SDL_ShowCursor(1); 1.79 + SDL_EnableKeyRepeat(0, 0); 1.80 + SDL_Quit(); 1.81 + return 0; 1.82 +} 1.83 + 1.84 +int get_color_depth(void) 1.85 +{ 1.86 + return fbsurf->format->BitsPerPixel; 1.87 +} 1.88 + 1.89 +static int count_bits(unsigned int x) 1.90 +{ 1.91 + int i, count = 0; 1.92 + for(i=0; i<32; i++) { 1.93 + if(x & 1) { 1.94 + count++; 1.95 + } 1.96 + x >>= 1; 1.97 + } 1.98 + return count; 1.99 +} 1.100 + 1.101 +int get_color_bits(int *rbits, int *gbits, int *bbits) 1.102 +{ 1.103 + *rbits = count_bits(fbsurf->format->Rmask); 1.104 + *gbits = count_bits(fbsurf->format->Gmask); 1.105 + *bbits = count_bits(fbsurf->format->Bmask); 1.106 + return *rbits + *gbits + *bbits; 1.107 +} 1.108 + 1.109 +int get_color_shift(int *rshift, int *gshift, int *bshift) 1.110 +{ 1.111 + *rshift = fbsurf->format->Rshift; 1.112 + *gshift = fbsurf->format->Gshift; 1.113 + *bshift = fbsurf->format->Bshift; 1.114 + return 0; 1.115 +} 1.116 + 1.117 +int get_color_mask(unsigned int *rmask, unsigned int *gmask, unsigned int *bmask) 1.118 +{ 1.119 + *rmask = fbsurf->format->Rmask; 1.120 + *gmask = fbsurf->format->Gmask; 1.121 + *bmask = fbsurf->format->Bmask; 1.122 + return 0; 1.123 +} 1.124 + 1.125 + 1.126 +void set_palette(int idx, int r, int g, int b) 1.127 +{ 1.128 + SDL_Color col; 1.129 + col.r = r; 1.130 + col.g = g; 1.131 + col.b = b; 1.132 + 1.133 + if(SDL_SetPalette(fbsurf, SDL_LOGPAL | SDL_PHYSPAL, &col, idx, 1) != 1) { 1.134 + fprintf(stderr, "set_palette failed to set the required color\n"); 1.135 + } 1.136 + 1.137 + palette[idx].r = r; 1.138 + palette[idx].g = g; 1.139 + palette[idx].b = b; 1.140 +} 1.141 + 1.142 +static int copy_frame_called; 1.143 + 1.144 +void copy_frame(void *pixels) 1.145 +{ 1.146 + unsigned char *frame = (unsigned char*)pixels; 1.147 + copy_frame_called = 1; 1.148 + 1.149 + if(SDL_MUSTLOCK(fbsurf)) { 1.150 + SDL_LockSurface(fbsurf); 1.151 + } 1.152 + 1.153 + if(pixels) { 1.154 + if(scale > 1) { 1.155 + int i, j, xsz, ysz; 1.156 + unsigned char *dest = fbsurf->pixels; 1.157 + 1.158 + xsz = fbsurf->w * scale; 1.159 + ysz = fbsurf->h * scale; 1.160 + 1.161 + for(i=0; i<ysz; i++) { 1.162 + for(j=0; j<xsz; j++) { 1.163 + *dest++ = frame[(i / scale) * fbsurf->w + (j / scale)]; 1.164 + } 1.165 + } 1.166 + } else { 1.167 + int num_pixels = fbsurf->w * fbsurf->h; 1.168 + memcpy(fbsurf->pixels, frame, num_pixels * fbsurf->format->BytesPerPixel); 1.169 + } 1.170 + } 1.171 + 1.172 + if(SDL_MUSTLOCK(fbsurf)) { 1.173 + SDL_UnlockSurface(fbsurf); 1.174 + } 1.175 + 1.176 + SDL_Flip(fbsurf); 1.177 + 1.178 + if(frames_to_capture > 0) { 1.179 + capture_frame(pixels); 1.180 + --frames_to_capture; 1.181 + } 1.182 + 1.183 + /* also print fps every second ... */ 1.184 + { 1.185 + static long prev_fps, num_frames; 1.186 + long msec, dt; 1.187 + 1.188 + msec = get_msec(); 1.189 + dt = msec - prev_fps; 1.190 + if(dt >= 1000) { 1.191 + float fps = (float)num_frames / ((float)dt / 1000.0f); 1.192 + printf("framerate: %.1f \r", fps); 1.193 + fflush(stdout); 1.194 + num_frames = 0; 1.195 + prev_fps = msec; 1.196 + } else { 1.197 + num_frames++; 1.198 + } 1.199 + } 1.200 +} 1.201 + 1.202 +#define spin_delay(ms) \ 1.203 + do { \ 1.204 + unsigned int end = SDL_GetTicks() + ms; \ 1.205 + while((prev_msec = SDL_GetTicks()) < end); \ 1.206 + } while(0) 1.207 + 1.208 +#define FRAME_INTERVAL (1000/70) 1.209 + 1.210 +void wait_vsync(void) 1.211 +{ 1.212 + static int prev_msec; 1.213 + int msec, dt, tleft; 1.214 + 1.215 + if(!copy_frame_called) { 1.216 + copy_frame(0); 1.217 + copy_frame_called = 0; 1.218 + } 1.219 + 1.220 + msec = SDL_GetTicks(); 1.221 + 1.222 + dt = msec - prev_msec; 1.223 + 1.224 + tleft = FRAME_INTERVAL - dt; 1.225 + if(tleft > 0) { 1.226 + int coarse = tleft & 0xfffffff8; 1.227 + tleft = tleft & 7; 1.228 + 1.229 + if(coarse) { 1.230 + SDL_Delay(coarse); 1.231 + } 1.232 + if(tleft) { 1.233 + spin_delay(tleft); 1.234 + } else { 1.235 + prev_msec = SDL_GetTicks(); 1.236 + } 1.237 + } else { 1.238 + prev_msec = msec; 1.239 + } 1.240 +} 1.241 + 1.242 +static int cap_count = 0; 1.243 +void begin_capture(int frames) 1.244 +{ 1.245 + frames_to_capture = frames; 1.246 +} 1.247 + 1.248 +void end_capture(void) 1.249 +{ 1.250 + cap_count = 0; 1.251 + frames_to_capture = 0; 1.252 +} 1.253 + 1.254 +#define NUMPIX (fbsurf->w * fbsurf->h) 1.255 +static void capture_frame(unsigned char *frame) 1.256 +{ 1.257 +#ifdef DOSEMU_CAPTURE 1.258 + static unsigned char rgbpix[NUMPIX * 4]; 1.259 + char fname[32]; 1.260 + int i; 1.261 + unsigned char *src, *dest; 1.262 + 1.263 + sprintf(fname, "frame%04d.png", cap_count++); 1.264 + 1.265 + src = frame; 1.266 + dest = rgbpix; 1.267 + 1.268 + for(i=0; i<NUMPIX; i++) { 1.269 + unsigned char c = *src++; 1.270 + *dest++ = palette[c].r; 1.271 + *dest++ = palette[c].g; 1.272 + *dest++ = palette[c].b; 1.273 + *dest++ = 255; 1.274 + } 1.275 + 1.276 + img_save_pixels(fname, rgbpix, fbsurf->w, fbsurf->h, IMG_FMT_RGBA32); 1.277 +#endif 1.278 +} 1.279 + 1.280 + 1.281 +/* ----- event handling (conio.h) ----- */ 1.282 +static SDL_Event *keybev; 1.283 +static int mousex, mousey, bnmask; 1.284 + 1.285 +static int keystate[256]; 1.286 +static int num_pressed; 1.287 + 1.288 +int kbhit(void) 1.289 +{ 1.290 + if(!keybev) { 1.291 + proc_events(); 1.292 + } 1.293 + return keybev != 0; 1.294 +} 1.295 + 1.296 +int getch(void) 1.297 +{ 1.298 + int res; 1.299 + 1.300 + while(!keybev) { 1.301 + SDL_Event ev; 1.302 + SDL_WaitEvent(&ev); 1.303 + SDL_PushEvent(&ev); 1.304 + proc_events(); 1.305 + } 1.306 + res = keybev->key.keysym.sym; 1.307 + keybev = 0; 1.308 + return res; 1.309 +} 1.310 + 1.311 +/* ----- improved event handling (keyb.h) ---- */ 1.312 + 1.313 +int kb_init(int bufsz) 1.314 +{ 1.315 + init_sdl(); 1.316 + 1.317 + return 0; 1.318 +} 1.319 + 1.320 +void kb_shutdown(void) 1.321 +{ 1.322 +} 1.323 + 1.324 +int kb_getkey(void) 1.325 +{ 1.326 + int res = -1; 1.327 + 1.328 + proc_events(); 1.329 + if(keybev) { 1.330 + res = keybev->key.keysym.sym; 1.331 + keybev = 0; 1.332 + } 1.333 + return res; 1.334 +} 1.335 + 1.336 +int kb_isdown(int key) 1.337 +{ 1.338 + if(key == KB_ANY) { 1.339 + return num_pressed; 1.340 + } 1.341 + return keystate[key]; 1.342 +} 1.343 + 1.344 +/* mouse handling (mouse.c implementation) */ 1.345 +static unsigned long last_mouse_hide_time; 1.346 + 1.347 +int have_mouse(void) 1.348 +{ 1.349 + return 1; 1.350 +} 1.351 + 1.352 +void set_mouse(int x, int y) 1.353 +{ 1.354 + SDL_ShowCursor(0); 1.355 + last_mouse_hide_time = get_msec(); 1.356 + 1.357 + SDL_WarpMouse(x * scale, y * scale); 1.358 + mousex = x; 1.359 + mousey = y; 1.360 +} 1.361 + 1.362 +int read_mouse(int *xp, int *yp) 1.363 +{ 1.364 + if(xp) *xp = mousex; 1.365 + if(yp) *yp = mousey; 1.366 + return bnmask; 1.367 +} 1.368 + 1.369 +static void proc_events(void) 1.370 +{ 1.371 + static SDL_Event ev; 1.372 + 1.373 + if(last_mouse_hide_time > 0 && get_msec() - last_mouse_hide_time > 3000) { 1.374 + last_mouse_hide_time = 0; 1.375 + SDL_ShowCursor(1); 1.376 + } 1.377 + 1.378 + while(SDL_PollEvent(&ev)) { 1.379 + switch(ev.type) { 1.380 + case SDL_KEYDOWN: 1.381 + { 1.382 + int key = ev.key.keysym.sym; 1.383 + 1.384 + if(!keybev) { 1.385 + keybev = &ev; 1.386 + } 1.387 + 1.388 + if(!keystate[key]) { 1.389 + keystate[key] = 1; 1.390 + num_pressed++; 1.391 + } 1.392 + } 1.393 + break; 1.394 + 1.395 + case SDL_KEYUP: 1.396 + { 1.397 + int key = ev.key.keysym.sym; 1.398 + 1.399 + if(keystate[key]) { 1.400 + keystate[key] = 0; 1.401 + if(--num_pressed < 0) { 1.402 + num_pressed = 0; 1.403 + } 1.404 + } 1.405 + } 1.406 + break; 1.407 + 1.408 + case SDL_MOUSEMOTION: 1.409 + mousex = ev.motion.x / scale; 1.410 + mousey = ev.motion.y / scale; 1.411 + break; 1.412 + 1.413 + case SDL_MOUSEBUTTONDOWN: 1.414 + case SDL_MOUSEBUTTONUP: 1.415 + { 1.416 + int mask = 0; 1.417 + switch(ev.button.button) { 1.418 + case SDL_BUTTON_LEFT: 1.419 + mask = MOUSE_LEFT; 1.420 + break; 1.421 + case SDL_BUTTON_MIDDLE: 1.422 + mask = MOUSE_MIDDLE; 1.423 + break; 1.424 + case SDL_BUTTON_RIGHT: 1.425 + mask = MOUSE_RIGHT; 1.426 + default: 1.427 + break; 1.428 + } 1.429 + if(!mask) { 1.430 + break; 1.431 + } 1.432 + 1.433 + if(ev.button.state == SDL_PRESSED) { 1.434 + bnmask |= mask; 1.435 + } else { 1.436 + bnmask &= ~mask; 1.437 + } 1.438 + } 1.439 + break; 1.440 + 1.441 + default: 1.442 + break; 1.443 + } 1.444 + } 1.445 +} 1.446 + 1.447 +/* ---- timer.c implementation ---- */ 1.448 +static Uint32 start_time; 1.449 + 1.450 +void init_timer(int res_hz) 1.451 +{ 1.452 + init_sdl(); 1.453 + reset_timer(); 1.454 +} 1.455 + 1.456 +void reset_timer(void) 1.457 +{ 1.458 + start_time = SDL_GetTicks(); 1.459 + printf("resetting timer: %u, %lu\n", start_time, get_msec()); 1.460 +} 1.461 + 1.462 +unsigned long get_msec(void) 1.463 +{ 1.464 + Uint32 ticks = SDL_GetTicks(); 1.465 + return (unsigned long)(ticks - start_time); 1.466 +}