rayzor

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