void sdl_put(unsigned char *image, int width, int height) { SDL_Event event; if (screen && overlay) { SDL_Rect rect; float aspect_ratio = (float)width / height; int pic_width, pic_height; if (width != cur_width || height != cur_height) sdl_video_open(width, height); if (SDL_MUSTLOCK(screen)) if (SDL_LockSurface(screen) < 0) return; SDL_LockYUVOverlay(overlay); memcpy(overlay->pixels[0], image, width * height); memcpy(overlay->pixels[2], image + (width * height), (width * height / 4)); memcpy(overlay->pixels[1], image + (width * height * 5 / 4), (width * height / 4)); SDL_UnlockYUVOverlay(overlay); if (SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen); pic_height = screen->h; pic_width = pic_height * aspect_ratio; if (pic_width > screen->w) { pic_width = screen->w; pic_height = pic_width / aspect_ratio; } rect.x = (screen->w - pic_width) / 2; rect.y = (screen->h - pic_height) / 2; rect.w = pic_width; rect.h = pic_height; if (SDL_DisplayYUVOverlay(overlay, &rect)) MOTION_LOG(ERR, TYPE_ALL, SHOW_ERRNO, "%s: SDL_DisplayYUVOverlay: %s", SDL_GetError()); if (SDL_PollEvent(&event)) { if ((event.type == SDL_QUIT || (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE))) sdl_stop(); else if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_f) { is_full_screen = !is_full_screen; sdl_video_open(width, height); } else if (event.type == SDL_VIDEORESIZE) screen = SDL_SetVideoMode(event.resize.w, event.resize.h, screen->format->BitsPerPixel, screen->flags); } } }
static int sdl_video_open(int width, int height) { int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL; int w,h; if (is_full_screen) flags |= SDL_FULLSCREEN; else flags |= SDL_RESIZABLE; if (is_full_screen && fs_screen_width) { w = fs_screen_width; h = fs_screen_height; } else if (width > fs_screen_width || height > fs_screen_height) { w = fs_screen_width; h = fs_screen_height; } else { w = width; h = height; } /* 32 because framebuffer is usually initalized to 8 and you have to use fbset with -depth to make it working */ screen = SDL_SetVideoMode(w, h, 32, flags); if (!screen) { MOTION_LOG(ERR, TYPE_ALL, SHOW_ERRNO,"%s: Unable to set video mode: %s", SDL_GetError()); return -1; } MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, "%s: SDL dimension %d x %d fullscreen %d BytesPerPixel %d", screen->w, screen->h, is_full_screen, screen->format->BytesPerPixel); SDL_WM_SetCaption("motion", "motion"); SDL_ShowCursor(SDL_DISABLE); if (cur_width != width || cur_height != height) { cur_width = width; cur_height = height; if (overlay) SDL_FreeYUVOverlay(overlay); overlay = SDL_CreateYUVOverlay(cur_width, cur_height, SDL_YV12_OVERLAY, screen); if (!overlay) { MOTION_LOG(ERR, TYPE_ALL, SHOW_ERRNO, "%s: Could not create overlay: %s", SDL_GetError()); sdl_stop(); } else MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, "%s: SDL created %dx%dx%d %s overlay", overlay->w,overlay->h,overlay->planes, overlay->hw_overlay?"hardware":"software"); } return overlay == NULL; }
int main(int argc, char** argv) { int opt; //int verbose_flag = 0; char *bios_path = NULL; char *rom_path = NULL; Uint32 start_time, time, frame; uint32_t delta, elapsed; pause_emu = 0; scale = 2; while ((opt = getopt(argc, argv, "vdb:")) != -1) { switch (opt) { case 'b': bios_path = optarg; break; case 'v': //verbose_flag = 1; break; case 'd': debug_flag = 1; debug_pause = 1; break; default: usage(argv[0]); } } if (optind == argc) { usage(argv[0]); } rom_path = argv[optind]; dmg_init(); dmg_load_bios(bios_path); dmg_load_rom(rom_path); sdl_init(scale); time = 0; frame = 1; start_time = SDL_GetTicks(); for (;;) { delta = ((frame * 1000) / SCREEN_FPS) - time; if ((elapsed = main_loop(delta)) == -1) { break; } time += elapsed; if (elapsed > 0) { sdl_render(screen_get_fb()); } // Sync to maximum fps if (SDL_GetTicks() - start_time < time) { SDL_Delay(time - (SDL_GetTicks() - start_time)); } else { time = 0; frame = 1; start_time = SDL_GetTicks(); } frame++; // When Uint32 overflows, restart. This is unlikely to happen: // Uint32 will overflow after 828 days at 60 fps if (frame == 0) { start_time = SDL_GetTicks(); } } sdl_stop(); return 0; }