static int hotkey_function(int key_code, int key_mod) { //write_log("hotkey: %d mod %d\n", key_code, key_mod); switch (key_code) { case FS_ML_KEY_R: fs_emu_log("hot key: soft reset\n"); fs_emu_warning(_("Soft Reset")); fs_emu_queue_action(INPUTEVENT_SPC_SOFTRESET, 1); return 0; case FS_ML_KEY_T: fs_emu_log("hot key: hard reset\n"); fs_emu_warning(_("Hard Reset")); fs_emu_queue_action(INPUTEVENT_SPC_HARDRESET, 1); return 0; case FS_ML_KEY_A: fs_emu_log("hot key: freeze button\n"); fs_emu_queue_action(INPUTEVENT_SPC_FREEZEBUTTON, 1); return 0; case FS_ML_KEY_D: fs_emu_log("hot key: enter debugger\n"); if (fs_config_get_boolean("console_debugger") == 1) { fs_emu_warning(_("Activated debugger")); fs_emu_queue_action(INPUTEVENT_SPC_ENTERDEBUGGER, 1); } else { fs_emu_warning(_("Option \"%s\" is not enabled"), "console_debugger"); } return 0; } return 0; }
static void configure_memory(amiga_config *c) { int chip_memory = fs_config_get_int("chip_memory"); if (chip_memory != FS_CONFIG_NONE) { if (chip_memory % 512 == 0) { amiga_set_int_option("chipmem_size", chip_memory / 512); } else { fs_emu_warning("chip_memory must be a multiple of 512"); chip_memory = 0; } } else { chip_memory = 0; } int slow_memory = fs_config_get_int("slow_memory"); if (slow_memory != FS_CONFIG_NONE) { if (slow_memory % 256 == 0) { amiga_set_int_option("bogomem_size", slow_memory / 256); } else { fs_emu_warning("slow_memory must be a multiple of 256"); slow_memory = 0; } } else { slow_memory = 0; } int fast_memory = fs_config_get_int("fast_memory"); if (fast_memory != FS_CONFIG_NONE) { if (fast_memory % 1024 == 0) { amiga_set_int_option("fastmem_size", fast_memory / 1024); } else { fs_emu_warning("fast_memory must be a multiple of 1024"); fast_memory = 0; } } else { fast_memory = 0; } int z3_memory = fs_config_get_int("zorro_iii_memory"); if (z3_memory != FS_CONFIG_NONE) { if (z3_memory && !c->allow_z3_memory) { fs_emu_warning("Zorro III fast memory needs a processor " "with 32-bit addressing"); z3_memory = 0; } else if (z3_memory % 1024 == 0) { amiga_set_int_option("z3mem_size", z3_memory / 1024); } else { fs_emu_warning("zorro_iii_memory must be a multiple of 1024"); z3_memory = 0; } } else { z3_memory = 0; } }
void fs_emu_load_shader(fs_emu_shader *shader) { parse_data *data = g_new0(parse_data, 1); data->shader = shader; data->buffer = malloc(MAX_TEXT_SIZE); GMarkupParseContext *context = g_markup_parse_context_new( &counter_subparser, G_MARKUP_TREAT_CDATA_AS_TEXT, data, NULL); FILE *f = g_fopen(data->shader->path, "rb"); if (f == NULL) { fs_log("could not open shader file\n"); return; } char *buffer = malloc(8192); int read = fread(buffer, 1, 8192, f); while (read > 0) { g_markup_parse_context_parse(context, buffer, read, NULL); read = fread(buffer, 1, 8192, f); } fclose(f); free(buffer); // If the list of shader passes is empty, this shader file is invalid. // Abort this algorithm, do not continue trying to load the file. Host // applications should alert the user that there was a problem loading // the file. if (data->shader->passes == NULL) { fs_emu_warning("no shader passes loaded"); data->shader->ok = 0; } else if (data->error) { fs_emu_warning("error occured while loading shader"); data->shader->ok = 0; } else { fs_log("shader ok\n"); data->shader->ok = 1; } free(data->buffer); free(data); g_markup_parse_context_free(context); CHECK_GL_ERROR(); fs_log("done loading shader\n"); //exit(1); }
static fs_image *load_font_from_file(const char *path) { if (path == NULL) { fs_emu_warning(_("Could not find font: %s"), path); return NULL; } fs_emu_log("loading image \"%s\"\n", path); fs_image *image = fs_image_new_from_file(path); if (image == NULL) { fs_emu_warning(_("Error loading font: %s"), path); return NULL; } convert_to_premultiplied_alpha(image); return image; }
void fs_ml_toggle_fullscreen() { fs_log("fs_ml_toggle_fullscreen\n"); #ifdef USE_SDL2 if (g_fs_emu_video_fullscreen_mode == FULLSCREEN_WINDOW) { fs_emu_warning("Cannot toggle fullscreen with fullscreen-mode=window"); return; } int display_index = 0; SDL_DisplayMode mode; memset(&mode, 0, sizeof(SDL_DisplayMode)); if (SDL_GetDesktopDisplayMode(display_index, &mode) == 0) { SDL_SetWindowDisplayMode(g_fs_ml_window, &mode); } g_fs_emu_video_fullscreen = !g_fs_emu_video_fullscreen; int flags = 0; if (g_fs_emu_video_fullscreen) { if (g_fs_emu_video_fullscreen_mode == FULLSCREEN_DESKTOP) { flags = SDL_WINDOW_FULLSCREEN_DESKTOP; } else { flags = SDL_WINDOW_FULLSCREEN; } } SDL_SetWindowFullscreen(g_fs_ml_window, flags); #else g_fs_emu_video_fullscreen = !g_fs_emu_video_fullscreen; destroy_opengl_state(); set_video_mode(); recreate_opengl_state(); #endif }
static void init_window_overrides() { const char *s = fs_config_get_const_string("viewport"); if (s == NULL) { return; } int pos = 0; while (1) { int result = read_window_override(s, &pos); if (!result) { fs_log("error parsing wiewport transformation\n"); } while(s[pos] == ' ') { ++(pos); } int c = s[(pos)++]; if (c == ';') { continue; } else if (c == ',') { continue; } else if (c == '\0') { break; } else { fs_emu_warning("Unexpected byte (%d) while parsing " "viewport option\n", c); return; } } }
const char* fs_uae_base_dir(void) { static const char* path; if (path) { return path; } path = fs_config_get_const_string("base_dir"); if (path) { fs_log("base specified via base_dir option\n"); path = fs_uae_expand_path(path); } if (path == NULL) { // FIXME: deprecated const char *env_path = getenv("FS_UAE_BASE_DIR"); if (env_path && env_path[0]) { path = env_path; fs_log("base specified via FS_UAE_BASE_DIR\n"); fs_emu_deprecated("FS_UAE_BASE_DIR is deprecated"); } } if (path == NULL) { // check for portable dir char buffer[MAX_PATH]; fs_get_application_exe_dir(buffer, MAX_PATH); char *next = g_strdup(buffer); char *orig = g_strdup(":INVALID;"); while (strcmp(orig, next) != 0) { char *test = g_build_filename(next, "Portable.ini", NULL); fs_log("checking %s\n", test); if (fs_path_exists(test)) { path = next; fs_log("using portable base dir %s\n", path); g_free(orig); break; } g_free(test); g_free(orig); orig = next; next = g_path_get_dirname(next); } } if (path == NULL) { path = read_custom_path("base-dir"); } if (path == NULL) { fs_log("- using base dir $DOCUMENTS/FS-UAE\n"); path = g_build_filename(fs_uae_documents_dir(), "FS-UAE", NULL); } int result = g_mkdir_with_parents(path, 0755); if (result == -1) { fs_emu_warning("Could not create base directory " "at %s", path); path = fs_uae_documents_dir(); } fs_log("- using base ($BASE / $FSUAE) directory \"%s\"\n", path); return path; }
void fse_init_theme() { fs_log("THEME: Init\n"); fs_emu_theme_overlay* o = g_fs_emu_theme.overlays; o[FS_EMU_TOP_LEFT_OVERLAY].name = g_strdup("top_left_overlay"); o[FS_EMU_TOP_RIGHT_OVERLAY].name = g_strdup("top_right_overlay"); o[FS_EMU_TOP_RIGHT_OVERLAY].anchor = FS_EMU_ANCHOR_TOP_RIGHT; o[FS_EMU_BOTTOM_RIGHT_OVERLAY].name = g_strdup("bottom_right_overlay"); o[FS_EMU_BOTTOM_RIGHT_OVERLAY].anchor = FS_EMU_ANCHOR_BOTTOM_RIGHT; o[FS_EMU_BOTTOM_LEFT_OVERLAY].name = g_strdup("bottom_left_overlay"); o[FS_EMU_BOTTOM_LEFT_OVERLAY].anchor = FS_EMU_ANCHOR_BOTTOM_LEFT; o[FS_EMU_AUDIO_LED_OVERLAY].name = g_strdup("audio_led"); o[FS_EMU_FPS_LED_OVERLAY].name = g_strdup("fps_led"); o[FS_EMU_VSYNC_LED_OVERLAY].name = g_strdup("vsync_led"); o[FS_EMU_FPS_D0_OVERLAY].name = g_strdup("fps_d0"); o[FS_EMU_FPS_D1_OVERLAY].name = g_strdup("fps_d1"); const char *theme = fs_config_get_const_string("theme"); if (theme) { g_fs_emu_theme.name = g_strdup(theme); // first try to find the theme in the user's theme dir const char *themes_dir = fs_config_get_const_string("themes_dir"); if (themes_dir) { g_fs_emu_theme.path = g_build_filename(themes_dir, g_fs_emu_theme.name, NULL); if (!fs_path_exists(g_fs_emu_theme.path)) { free(g_fs_emu_theme.path); g_fs_emu_theme.path = NULL; } } // or by direct path lookup if (!g_fs_emu_theme.path) { if (fs_path_exists(theme)) { g_fs_emu_theme.path = g_strdup(theme); } } // then try to find a bundled / installed theme if (!g_fs_emu_theme.path) { g_fs_emu_theme.path = fs_get_program_data_file( g_fs_emu_theme.name); } if (g_fs_emu_theme.path) { fs_log("theme found at %s\n", g_fs_emu_theme.path); } else { fs_emu_warning(_("Theme not found: %s"), g_fs_emu_theme.name); free(g_fs_emu_theme.name); // resources will not be found, but path should not be NULL... g_fs_emu_theme.path = g_strdup(""); } } else { g_fs_emu_theme.name = g_strdup(""); g_fs_emu_theme.path = g_strdup(""); } load_defaults(); load_theme(); }
static void init_freetype(void) { int error = FT_Init_FreeType(&library); if (error) { fs_emu_warning("Could not initialize freetype"); } else { fs_emu_log("freetype initialized\n"); } }
static fs_image *load_font_from_data(char *data, int size) { fs_image *image = fs_image_new_from_data(data, size); if (image == NULL) { fs_emu_warning(_("Error loading font from data")); return NULL; } convert_to_premultiplied_alpha(image); return image; }
void fs_uae_configure_sound_card(amiga_config *c) { const char *card = fs_config_get_const_string(OPTION_SOUND_CARD); if (card != NULL) { if (fs_uae_values_matches(card, "toccata")) { amiga_set_option("toccata", "true"); } else { fs_emu_warning("Unrecognized sound card"); } } }
const char *fs_uae_kickstarts_cache_dir() { static const char *path = NULL; if (path == NULL) { path = g_build_filename(fs_uae_cache_dir(), "Kickstarts", NULL); int result = g_mkdir_with_parents(path, 0755); if (result == -1) { fs_emu_warning("Could not create kickstarts cache directory"); path = fs_uae_base_dir(); } } return path; }
static void select_port_0_device(int data) { printf("--> device index %d\n", data); int port = 0; if (data == 9) { // 9 is currently a hack to indicate the local mouse g_fs_uae_input_ports[port].mode = AMIGA_JOYPORT_MOUSE; g_fs_uae_input_ports[port].new_mode = AMIGA_JOYPORT_MOUSE; strcpy(g_fs_uae_input_ports[port].device, "MOUSE"); amiga_set_joystick_port_mode(port, AMIGA_JOYPORT_MOUSE); // FIXME: not a warning, rather a notification fs_emu_warning(_("Port 0: %s"), _("Mouse")); } else { int count = 0; int new_mode = AMIGA_JOYPORT_DJOY; if (g_fs_uae_amiga_model == MODEL_CD32) { new_mode = AMIGA_JOYPORT_CD32JOY; } fs_emu_input_device *devices = fs_emu_get_input_devices(&count); if (data < count) { g_fs_uae_input_ports[port].mode = new_mode; g_fs_uae_input_ports[port].new_mode = new_mode; uae_strlcpy(g_fs_uae_input_ports[port].device, devices[data].name, sizeof(g_fs_uae_input_ports[port].device)); amiga_set_joystick_port_mode(port, new_mode); // FIXME: not a warning, rather a notification fs_emu_warning(_("Port 0: %s"), devices[data].name); } } fs_uae_reconfigure_input_ports_host(); fs_emu_menu_update_current(); //fs_emu_get_input_devices() //g_fs_uae_input_ports[port].mode = mode; //amiga_set_joystick_port_mode(port, mode); //g_fs_uae_input_ports[port].new_mode = mode; //fs_uae_reconfigure_input_ports_host(); //fs_emu_menu_update_current(); }
fs_image *load_font_from_file(const char *name) { char *full_name = g_strconcat(name, ".png", NULL); //char *path = g_build_filename(fs_emu_get_share_dir(), full_name, NULL); char *path = fs_get_program_data_file(full_name); if (path == NULL) { fs_emu_warning("Could not find font %s", full_name); return NULL; } fs_emu_log("loading image \"%s\"\n", path); fs_image *image = fs_image_new_from_file(path); g_free(path); if (image == NULL) { fs_emu_warning("Error loading font from %s", full_name); g_free(full_name); return NULL; } g_free(full_name); // convert to premultiplied alpha if (image->format == FS_IMAGE_FORMAT_RGBA) { int num_pixels = image->width * image->height; unsigned char *pixels = image->data; for (int i = 0; i < num_pixels; i++) { unsigned char alpha = pixels[3]; // should really divide by 255, but 256 is faster... //pixels[0] = ((int) pixels[0]) * alpha / 256; //pixels[1] = ((int) pixels[1]) * alpha / 256; //pixels[2] = ((int) pixels[2]) * alpha / 256; pixels[0] = ((int) pixels[0]) * alpha / 255; pixels[1] = ((int) pixels[1]) * alpha / 255; pixels[2] = ((int) pixels[2]) * alpha / 255; //pixels[0] = (unsigned char) ((pixels[0] * alpha + 0.5) / 255.0); //pixels[1] = (unsigned char) ((pixels[1] * alpha + 0.5) / 255.0); //pixels[2] = (unsigned char) ((pixels[2] * alpha + 0.5) / 255.0); pixels += 4; } } return image; }
void fs_emu_theme_init_lua(void) { fs_log("fs_emu_theme_init_lua\n"); char *path = fs_path_join(g_fs_emu_theme.path, "theme.lua", NULL); if (fs_path_exists(path)) { int result = luaL_dofile(fs_emu_lua_state, path); if (result != 0) { fs_emu_warning("Error loading/running theme.lua"); fs_emu_lua_log_error("Error loading/running theme.lua"); } } free(path); }
static void fs_emu_load_default_shader() { const char *name = fs_config_get_const_string("shader"); if (!name) { return; } char *path = find_shader(name); if (!path) { fs_emu_warning(_("Shader not found: %s"), name); return; } fs_emu_shader *shader= g_new0(fs_emu_shader, 1); shader->path = path; fs_emu_load_shader(shader); fs_gl_add_context_notification(context_notification_handler, shader); g_active_shader = shader; }
static const char* fs_uae_documents_dir() { static const char* path = NULL; if (path == NULL) { path = fs_get_documents_dir(); if (path == NULL) { fs_log("WARNING: did not find documents directory\n"); path = fs_uae_home_dir(); } int result = g_mkdir_with_parents(path, 0755); if (result == -1) { fs_emu_warning("Documents directory does not " "exist: %s", path); path = fs_uae_home_dir(); } fs_log("- using documents directory \"%s\"\n", path); } return path; }
static void log_opengl_information(void) { static int written = 0; if (written) { return; } written = 1; char *software_renderer = NULL; const char *str; str = (const char*) glGetString(GL_VENDOR); if (str) { fs_log("opengl vendor: %s\n", str); } str = (const char*) glGetString(GL_RENDERER); if (str) { fs_log("opengl renderer: %s\n", str); if (strstr(str, "GDI Generic") != NULL) { software_renderer = g_strdup(str); } else if (strstr(str, "llvmpipe") != NULL) { software_renderer = g_strdup(str); } } str = (const char*) glGetString(GL_VERSION); if (str) { fs_log("opengl version: %s\n", str); } str = (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION); if (str) { fs_log("opengl shading language version: %s\n", str); } str = (const char*) glGetString(GL_EXTENSIONS); if (str) { fs_log("opengl extensions: %s\n", str); } glGetIntegerv(GL_MAX_TEXTURE_SIZE, &g_max_texture_size); fs_log("opengl max texture size (estimate): %dx%d\n", g_max_texture_size, g_max_texture_size); if (software_renderer) { fs_emu_warning("No HW OpenGL driver: %s", software_renderer); g_free(software_renderer); } }
const char *fs_uae_state_dir() { static const char *path = NULL; if (path == NULL) { path = fs_uae_state_dir_path(); if (!path || !path[0]) { path = fs_uae_base_dir(); fs_log("reverting state dir to: %s\n", path); } fs_log("- using state dir %s\n", path); int result = g_mkdir_with_parents(path, 0755); if (result == -1) { fs_emu_warning("Could not create state directory"); path = fs_uae_base_dir(); } fs_log("final state dir path: %s\n", path); } return path; }
void fs_ml_set_fullscreen(bool fullscreen) { if (!is_video_thread()) { if (fullscreen) { fs_log("Posting enable fullscreen event\n"); post_video_event(FS_ML_VIDEO_EVENT_ENABLE_FULLSCREEN); } else { fs_log("Posting disable fullscreen event\n"); post_video_event(FS_ML_VIDEO_EVENT_DISABLE_FULLSCREEN); } return; } if (fullscreen == g_fs_emu_video_fullscreen) return; if (g_fs_emu_video_fullscreen_mode == FULLSCREEN_WINDOW) { fs_emu_warning("Cannot toggle fullscreen with fullscreen-mode=window"); return; } int display_index = 0; SDL_DisplayMode mode; memset(&mode, 0, sizeof(SDL_DisplayMode)); if (SDL_GetDesktopDisplayMode(display_index, &mode) == 0) { SDL_SetWindowDisplayMode(g_fs_ml_window, &mode); } int flags = 0; if (fullscreen) { if (g_fs_emu_video_fullscreen_mode == FULLSCREEN_DESKTOP) flags = SDL_WINDOW_FULLSCREEN_DESKTOP; else flags = SDL_WINDOW_FULLSCREEN; } SDL_SetWindowFullscreen(g_fs_ml_window, flags); g_fs_emu_video_fullscreen = fullscreen; }
static char *get_or_create_default_dir(const char *name, const char *key1, const char *key2, const char *dashed_key, int create, int cache) { char *path = NULL; if (path == NULL && key1 != NULL) { path = fs_config_get_string(key1); } if (path == NULL && key2 != NULL) { path = fs_config_get_string(key2); } if (path == NULL && dashed_key != NULL) { path = read_custom_path(dashed_key); } if (path == NULL) { if (cache) { path = g_build_filename(fs_uae_cache_dir(), name, NULL); } else { path = g_build_filename(fs_uae_base_dir(), name, NULL); } } char *expanded_path = fs_uae_expand_path_and_free(path); path = fs_uae_resolve_path(expanded_path, FS_UAE_DIR_PATHS); free(expanded_path); if (create) { int result = g_mkdir_with_parents(path, 0755); if (result == -1) { fs_emu_warning("Could not create %s directory", name); free(path); path = g_strdup(fs_uae_base_dir()); } } fs_log("- using \"%s\" directory \"%s\"\n", name, path); return path; }
int fs_ml_video_create_window(const char *title) { fs_log("fs_ml_video_create_window\n"); g_window_title = g_strdup(title); g_fs_ml_keyboard_input_grab = fs_config_get_boolean( "keyboard_input_grab"); if (g_fs_ml_automatic_input_grab == FS_CONFIG_NONE) { g_fs_ml_keyboard_input_grab = 1; } fs_log("keyboard input grab: %d\n", g_fs_ml_keyboard_input_grab); static int initialized = 0; #ifdef USE_SDL2 SDL_SetHint(SDL_HINT_GRAB_KEYBOARD, g_fs_ml_keyboard_input_grab ? "1" : "0"); #endif SDL_Init(SDL_INIT_VIDEO); SDL_version version; SDL_VERSION(&version); fs_log("FS-UAE was compiled for SDL %d.%d.%d\n", version.major, version.minor, version.patch); if (!initialized) { #ifdef USE_SDL2 int display_index = 0; SDL_DisplayMode mode; int should_be_zero = SDL_GetCurrentDisplayMode(display_index, &mode); if(should_be_zero != 0) { fs_log("SDL_GetCurrentDisplayMode failed\n"); SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR, "Display Error", "SDL_GetCurrentDisplayMode failed.", NULL); exit(1); } #else const SDL_VideoInfo* info = SDL_GetVideoInfo(); #endif g_fullscreen_width = fs_config_get_int("fullscreen_width"); if (g_fullscreen_width == FS_CONFIG_NONE) { #ifdef USE_SDL2 g_fullscreen_width = mode.w; #else g_fullscreen_width = info->current_w; #endif } g_fullscreen_height = fs_config_get_int("fullscreen_height"); if (g_fullscreen_height == FS_CONFIG_NONE) { #ifdef USE_SDL2 g_fullscreen_height = mode.h; #else g_fullscreen_height = info->current_h; #endif } if (g_fs_emu_video_fullscreen_mode_string == NULL) { g_fs_emu_video_fullscreen_mode = -1; } else if (g_ascii_strcasecmp(g_fs_emu_video_fullscreen_mode_string, "window") == 0) { g_fs_emu_video_fullscreen_mode = FULLSCREEN_WINDOW; } else if (g_ascii_strcasecmp(g_fs_emu_video_fullscreen_mode_string, "fullscreen") == 0) { g_fs_emu_video_fullscreen_mode = FULLSCREEN_FULLSCREEN; } #ifdef USE_SDL2 else if (g_ascii_strcasecmp(g_fs_emu_video_fullscreen_mode_string, "desktop") == 0) { g_fs_emu_video_fullscreen_mode = FULLSCREEN_DESKTOP; } #endif if (g_fs_emu_video_fullscreen_mode == -1) { #ifdef MACOSX g_fs_emu_video_fullscreen_mode = FULLSCREEN_FULLSCREEN; #else g_fs_emu_video_fullscreen_mode = FULLSCREEN_FULLSCREEN; #endif #ifdef USE_SDL2 fs_log("defaulting to fullscreen_mode = desktop for SDL2\n"); g_fs_emu_video_fullscreen_mode = FULLSCREEN_DESKTOP; #endif } initialized = 1; } if (g_fs_ml_video_sync) { g_fs_ml_vblank_sync = 1; } SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); #ifdef USE_SDL2 // setting swap interval after creating OpenGL context #else if (g_fs_ml_vblank_sync) { fs_emu_log("*** Setting swap interval to 1 ***\n"); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); } else { fs_emu_log("*** Setting swap interval to 0 ***\n"); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 0); } #endif if (g_fsaa) { fs_log("setting FSAA samples to %d\n", g_fsaa); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, g_fsaa); } g_window_width = fs_config_get_int("window_width"); if (g_window_width == FS_CONFIG_NONE) { g_window_width = 1920 / 2; } g_window_height = fs_config_get_int("window_height"); if (g_window_height == FS_CONFIG_NONE) { g_window_height = 1080/ 2; } #ifdef USE_SDL2 g_window_x = fs_config_get_int("window_x"); if (g_window_x == FS_CONFIG_NONE) { g_window_x = SDL_WINDOWPOS_CENTERED; } g_window_y = fs_config_get_int("window_y"); if (g_window_y == FS_CONFIG_NONE) { g_window_y = SDL_WINDOWPOS_CENTERED; } #endif g_window_resizable = fs_config_get_boolean("window_resizable"); if (g_window_resizable == FS_CONFIG_NONE) { g_window_resizable = 1; } g_fs_ml_automatic_input_grab = fs_config_get_boolean( "automatic_input_grab"); if (g_fs_ml_automatic_input_grab == FS_CONFIG_NONE) { if (fs_ml_mouse_integration()) { g_fs_ml_automatic_input_grab = 0; } else { g_fs_ml_automatic_input_grab = 1; } } fs_log("automatic input grab: %d\n", g_fs_ml_automatic_input_grab); g_initial_input_grab = g_fs_ml_automatic_input_grab; if (fs_config_get_boolean("initial_input_grab") == 1) { g_initial_input_grab = 1; } else if (fs_config_get_boolean("initial_input_grab") == 0 || // deprecated names: fs_config_get_boolean("input_grab") == 0 || fs_config_get_boolean("grab_input") == 0) { g_initial_input_grab = 0; } set_video_mode(); #ifdef USE_SDL2 if (g_fs_ml_vblank_sync) { fs_emu_log("*** Setting swap interval to 1 ***\n"); if (SDL_GL_SetSwapInterval(1) != 0) { fs_emu_warning("SDL_GL_SetSwapInterval(1) failed"); } } else { fs_emu_log("*** Setting swap interval to 0 ***\n"); SDL_GL_SetSwapInterval(0); } #endif // we display a black frame as soon as possible (to reduce flickering on // startup) glClear(GL_COLOR_BUFFER_BIT); #ifdef USE_SDL2 SDL_GL_SwapWindow(g_fs_ml_window); #else SDL_GL_SwapBuffers(); #endif fs_gl_finish(); #ifdef USE_SDL2 // set in SDL_CreateWindow instead #else SDL_WM_SetCaption(g_window_title, fs_get_application_name()); #endif fs_log("initial input grab: %d\n", g_initial_input_grab); if (g_initial_input_grab && !g_has_input_grab) { fs_ml_grab_input(1, 1); } fs_ml_show_cursor(0, 1); // this function must be called from the video thread fs_log("init_opengl\n"); fs_emu_video_init_opengl(); #ifdef WINDOWS #ifdef USE_SDL2 // we use only SDL functions with SDL2 #else fs_ml_init_raw_input(); #endif #else #ifdef USE_SDL2 SDL_StartTextInput(); #else // enable keysym to unicode char translation SDL_EnableUNICODE(1); #endif #endif fs_log("create windows is done\n"); return 1; }
void fs_emu_audio_openal_init(void) { fs_log("fs_emu_audio_openal_init\n"); register_functions(); // select the "preferred device" g_device = alcOpenDevice(NULL); if (g_device) { fs_log("[OPENAL] Opened device: %s\n", alcGetString(g_device, ALC_DEVICE_SPECIFIER)); } else { fs_log("[OPENAL] NULL from alcOpenDevice\n"); ALenum error_code = alGetError(); fs_log("[OPENAL] Error code %d\n", error_code); if (alGetString(error_code)) { fs_log("[OPENAL] %s\n", alGetString(error_code)); } fs_emu_warning("OPENAL: Could not open audio device"); } if (!g_device) { return; } log_openal_info(); log_openal_devices(); int frequencies[] = { 48000, 44100, 0 }; if (fs_config_get_int("audio_frequency") != FS_CONFIG_NONE) { frequencies[0] = fs_config_get_int("audio_frequency"); } for (int i = 0; frequencies[i]; i++) { int frequency = frequencies[i]; fs_log("OPENAL: trying frequency %d\n", frequency); ALCint attributes[] = { ALC_MONO_SOURCES, 0, ALC_STEREO_SOURCES, 2, ALC_FREQUENCY, frequency, 0 }; g_context = alcCreateContext(g_device, attributes); if (g_context) { g_audio_out_frequency = frequency; break; } } if (g_context) { fs_log("OPENAL: created context\n"); alcMakeContextCurrent(g_context); check_al_error("alcMakeContextCurrent"); fs_log("OPENAL: made context current\n"); } else { fs_emu_warning("OpenAL: no context created\n"); //check_al_error("alcCreateContext"); } int stereo_sources; alcGetIntegerv(g_device, ALC_STEREO_SOURCES, 1, &stereo_sources); fs_log("openal: number of stereo sources is %d\n", stereo_sources); // FIXME: configure elsewhere int abt = fs_config_get_int_clamped("audio_buffer_target_size", 1, 100); if (abt == FS_CONFIG_NONE) { if (fs_config_get_int("audio_buffer_target_bytes") != FS_CONFIG_NONE) { fs_emu_warning("Use audio_buffer_target_size instead\n"); } abt = 40; #if 0 if (abt == FS_CONFIG_NONE) { abt = 40; } else { abt = (int) (abt / 1000.0 * (options->frequency * 2 * 2)); } #endif } fs_log("AUDIO: Buffer target size (ms) = %d\n", abt); //abt = (int) (abt / 1000.0 * (options->frequency * 2 * 2)); // fs_log("AUDIO: Buffer target size (bytes) = %d\n", abt); /* Specifying fill target in microseconds */ g_default_fill_target = abt * 1000; }
void fs_emu_video_init_options(void) { //int auto_sync_mode = 1; //int sync_to_vblank = 1; //int sync_with_emu = 0; char *sync_mode_str = NULL; int fsaa = fs_config_get_int_clamped("fsaa", 0, 4); if (fsaa != FS_CONFIG_NONE) { fs_log("setting full-scene anti-aliasing (FSAA) to %dx%d\n", fsaa, fsaa); fs_ml_set_video_fsaa(fsaa); } else { fs_log("full-scene anti-aliasing is not requested\n"); } fs_ml_video_mode mode; memset(&mode, 0, sizeof(fs_ml_video_mode)); if (fs_ml_video_mode_get_current(&mode) == 0) { fs_log("current display mode is %dx%d @ %d Hz\n", mode.width, mode.height, mode.fps); int assume_refresh_rate = fs_config_get_int("assume_refresh_rate"); if (assume_refresh_rate != FS_CONFIG_NONE) { fs_log("assuming host refresh rate: %d Hz (from config)\n", assume_refresh_rate); g_fs_emu_video_frame_rate_host = assume_refresh_rate; } else { g_fs_emu_video_frame_rate_host = mode.fps; } } else { fs_log("could not get display mode\n"); } fs_log("checking video sync mode\n"); sync_mode_str = fs_config_get_string("video_sync"); if (!sync_mode_str) { // compatibility key, FIXME: remove when FS-UAE translates compat // option names when loading config. sync_mode_str = fs_config_get_string("sync"); } if (sync_mode_str) { if (g_ascii_strcasecmp(sync_mode_str, "auto") == 0) { g_fs_emu_video_sync_to_vblank = 1; g_fs_emu_video_allow_full_sync = 1; } else if (g_ascii_strcasecmp(sync_mode_str, "1") == 0) { // shortcut option, nice from command line (e.g. --video-sync) g_fs_emu_video_sync_to_vblank = 1; g_fs_emu_video_allow_full_sync = 1; } else if (g_ascii_strcasecmp(sync_mode_str, "full") == 0) { // old compatibility option g_fs_emu_video_sync_to_vblank = 1; g_fs_emu_video_allow_full_sync = 1; } else if (g_ascii_strcasecmp(sync_mode_str, "0") == 0) { // shortcut option, nice from command line (e.g. --no-video-sync) g_fs_emu_video_sync_to_vblank = 0; g_fs_emu_video_allow_full_sync = 0; } else if (g_ascii_strcasecmp(sync_mode_str, "off") == 0) { //g_fs_emu_video_sync_to_vblank = 0; //g_fs_emu_video_allow_full_sync = 0; } else if (g_ascii_strcasecmp(sync_mode_str, "vblank") == 0) { g_fs_emu_video_sync_to_vblank = 1; } else { fs_log("WARNING: invalid value for video-sync: %s\n", sync_mode_str); } free(sync_mode_str); } else { //fs_log("not specified: using automatic video sync mode\n"); fs_log("not specified: no video sync\n"); //g_fs_emu_video_sync_to_vblank = 0; //g_fs_emu_video_allow_full_sync = 0; } /* if (auto_sync_mode) { fs_log("auto sync mode is enabled\n"); if (frame_rate && frame_rate == mode.fps) { fs_log("frame rate (%d) equals screen refresh (%d)\n", frame_rate, mode.fps); sync_to_vblank = 1; sync_with_emu = 1; } else { fs_log("frame rate (%d) does not equal screen refresh (%d)\n", frame_rate, mode.fps); sync_to_vblank = 1; } } */ if (fs_emu_netplay_enabled()) { fs_log("netplay is enabled, disabling full video/emulator sync\n"); g_fs_emu_video_allow_full_sync = 0; //sync_with_emu = 0; //sync_to_vblank = 0; } if (fs_config_get_boolean("benchmark") != FS_CONFIG_NONE) { fs_log("benchmarking enable, disabling video sync\n"); g_fs_emu_video_sync_to_vblank = 0; //sync_with_emu = 0; g_fs_emu_benchmarking = 1; g_fs_ml_benchmarking = 1; g_fs_emu_video_allow_full_sync = 0; } //if (sync_with_emu && !g_fs_emu_full_sync_allowed) { // FIXME: check where g_fs_emu_full_sync_allowed is used if (!g_fs_emu_full_sync_allowed) { fs_log("full video/emu sync is not allowed in this mode\n"); //sync_with_emu = 0; g_fs_emu_video_allow_full_sync = 0; } /* if (sync_with_emu) { fs_log("will sync emulation and video with vblank\n"); fs_ml_video_sync_enable(); if (frame_rate && mode.fps) { double pitch = (1.0 * mode.fps) / frame_rate; fs_log("changing audio pitch to %0.2f based on frame rates\n", pitch); fs_emu_audio_set_default_pitch(pitch); } } else if (sync_to_vblank) { fs_log("will sync video output only to vblank (no tearing)\n"); fs_ml_vblank_sync_enable(); } else { fs_log("no video sync\n"); } */ if (g_fs_emu_video_sync_to_vblank) { fs_log("will sync video updates to vblank\n"); fs_ml_vblank_sync_enable(); } else { fs_log("no video sync (using timers only)\n"); } if (fs_config_get_boolean("disable_aspect_correction") == 1) { g_fs_emu_disable_aspect_correction = 1; } else if (fs_config_get_boolean("keep_aspect") == 1) { fs_emu_video_set_aspect_correction(1); } // the default texture format is RGB, set here because some video // formats implicitly changes the default texture format g_fs_emu_texture_format = FS_EMU_TEXTURE_FORMAT_RGB; const char *s = fs_config_get_const_string("video_format"); if (s) { if (g_ascii_strcasecmp(s, "bgra") == 0) { fs_log("using video format BGRA\n"); g_fs_emu_video_format = FS_EMU_VIDEO_FORMAT_BGRA; g_fs_emu_video_bpp = 4; } else if (g_ascii_strcasecmp(s, "rgba") == 0) { fs_log("using video format RGBA\n"); g_fs_emu_video_format = FS_EMU_VIDEO_FORMAT_RGBA; g_fs_emu_video_bpp = 4; } else if (g_ascii_strcasecmp(s, "rgb") == 0) { fs_log("using video format RGB\n"); g_fs_emu_video_format = FS_EMU_VIDEO_FORMAT_RGB; g_fs_emu_video_bpp = 3; } else if (g_ascii_strcasecmp(s, "rgb565") == 0) { fs_log("using video format RGB565\n"); g_fs_emu_video_format = FS_EMU_VIDEO_FORMAT_R5G6B5; g_fs_emu_video_bpp = 2; g_fs_emu_texture_format = FS_EMU_TEXTURE_FORMAT_RGB5; } else if (g_ascii_strcasecmp(s, "rgba5551") == 0) { fs_log("using video format RGBA5551\n"); g_fs_emu_video_format = FS_EMU_VIDEO_FORMAT_R5G5B5A1; g_fs_emu_video_bpp = 2; g_fs_emu_texture_format = FS_EMU_TEXTURE_FORMAT_RGB5_A1; } else { fs_emu_warning("Unknown video format"); } } if (!g_fs_emu_video_format) { fs_log("using default video format BGRA\n"); g_fs_emu_video_format = FS_EMU_VIDEO_FORMAT_BGRA; g_fs_emu_video_bpp = 4; } s = fs_config_get_const_string("texture_format"); if (s) { if (g_ascii_strcasecmp(s, "rgb") == 0) { fs_log("using texture format RGB\n"); g_fs_emu_texture_format = FS_EMU_TEXTURE_FORMAT_RGB; } else if (g_ascii_strcasecmp(s, "rgb8") == 0) { fs_log("using texture format RGB8\n"); g_fs_emu_texture_format = FS_EMU_TEXTURE_FORMAT_RGB8; } else if (g_ascii_strcasecmp(s, "rgba") == 0) { fs_log("using texture format RGBA\n"); g_fs_emu_texture_format = FS_EMU_TEXTURE_FORMAT_RGBA; } else if (g_ascii_strcasecmp(s, "rgba8") == 0) { fs_log("using texture format RGBA8\n"); g_fs_emu_texture_format = FS_EMU_TEXTURE_FORMAT_RGBA8; } else if (g_ascii_strcasecmp(s, "rgb5") == 0) { fs_log("using texture format RGB5\n"); g_fs_emu_texture_format = FS_EMU_TEXTURE_FORMAT_RGB5; } else if (g_ascii_strcasecmp(s, "rgb5_a1") == 0) { fs_log("using texture format RGB5_A1\n"); g_fs_emu_texture_format = FS_EMU_TEXTURE_FORMAT_RGB5_A1; } else { fs_emu_warning("Unknown texture format (using default)"); } } else { fs_log("using default texture format\n"); } double dval; if (fs_config_get_boolean("scanlines") == 1) { g_fs_emu_scanlines = 1; } dval = fs_config_get_double_clamped("scanlines_light", 0, 100); if (dval != FS_CONFIG_NONE) { g_fs_emu_scanlines_light = 255.0 * dval / 100.0; } dval = fs_config_get_double_clamped("scanlines_dark", 0, 100); if (dval != FS_CONFIG_NONE) { g_fs_emu_scanlines_dark = 255.0 * dval / 100.0; } }
int main(int argc, char *argv[]) { fs_uae_argc = argc; fs_uae_argv = argv; fs_set_argv(argc, argv); #ifdef WITH_CEF cef_init(argc, argv); #endif char **arg; arg = argv + 1; while (arg && *arg) { if (strcmp(*arg, "--list-joysticks") == 0) { list_joysticks(); exit(0); } else if (strcmp(*arg, "--list-devices") == 0) { list_joysticks(); exit(0); } else if (strcmp(*arg, "--version") == 0) { printf("%s\n", PACKAGE_VERSION); exit(0); } else if (strcmp(*arg, "--help") == 0) { printf(COPYRIGHT_NOTICE, PACKAGE_VERSION, OS_NAME_2, ARCH_NAME_2); printf(EXTRA_HELP_TEXT); exit(0); } arg++; } fs_init(); int error = fs_data_init("fs-uae", "fs-uae.dat"); if (error) { printf("WARNING: error (%d) loading fs-uae.dat\n", error); } fs_set_prgname("fs-uae"); fs_set_application_name("Amiga Emulator"); amiga_set_log_function(log_to_libfsemu); //result = parse_options(argc, argv); printf(COPYRIGHT_NOTICE, PACKAGE_VERSION, OS_NAME_2, ARCH_NAME_2); fs_log(COPYRIGHT_NOTICE, PACKAGE_VERSION, OS_NAME_2, ARCH_NAME_2); char *current_dir = g_get_current_dir(); fs_log("current directory is %s\n", current_dir); g_free(current_dir); amiga_init(); #if 0 // FIXME: disabling fullscreen spaces must be done before // SDL_INIT_VIDEO, but we need to check config to see if this should // be done, and we initialize SDL early to check for config file // (catch 22)... // FIXME: check fullscreen_spaces option SDL_SetHint(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, "0"); #endif #ifdef MACOSX SDL_Init(SDL_INIT_EVERYTHING); SDL_PumpEvents(); SDL_Event event; fs_log("OS X: Check for pending SDL_DROPFILE event\n"); while (SDL_PollEvent(&event)) { fs_log("Got SDL event 0x%x\n", event.type); if (event.type == SDL_DROPFILE) { if (event.drop.file != NULL) { g_fs_uae_config_file_path = strdup(event.drop.file); } SDL_free(event.drop.file); } } #endif // skip first entry arg = argv + 1; if (g_fs_uae_config_file_path == NULL) { while (arg && *arg) { const gchar *test_path = *arg; if (test_path && fs_path_exists(test_path)) { if (check_extension(test_path, ".fs-uae")) { g_fs_uae_config_file_path = g_strdup(test_path); } else if (check_extension(test_path, ".conf")) { g_fs_uae_config_file_path = g_strdup(test_path); } else if (check_extension(test_path, ".adf")) { g_fs_uae_disk_file_path = g_strdup(test_path); } else if (check_extension(test_path, ".ipf")) { g_fs_uae_disk_file_path = g_strdup(test_path); } else if (check_extension(test_path, ".dms")) { g_fs_uae_disk_file_path = g_strdup(test_path); } } arg++; } } /* Parse options first, in case base_dir, logging options etc is * specified on the command line. */ fs_config_parse_options(argc - 1, argv + 1); fs_log("\n"); fs_log(LOG_LINE); fs_log("libfsemu init\n"); fs_log(LOG_LINE); fs_log("\n"); fs_emu_path_set_expand_function(fs_uae_expand_path); fs_emu_init_overlays(overlay_names); fs_emu_init(); // then load the config file load_config_file(); init_i18n(); if (g_fs_uae_disk_file_path) { fs_config_set_string(OPTION_FLOPPY_DRIVE_0, g_fs_uae_disk_file_path); g_warn_about_missing_config_file = 0; } if (g_warn_about_missing_config_file) { fs_emu_warning(_("No configuration file was found")); } fs_log("\n"); fs_log(LOG_LINE); fs_log("fs-uae init\n"); fs_log(LOG_LINE); fs_log("\n"); configure_logging(fs_config_get_const_string("log")); fs_emu_set_state_check_function(amiga_get_state_checksum); fs_emu_set_rand_check_function(amiga_get_rand_checksum); // force creation of some recommended default directories fs_uae_kickstarts_dir(); fs_uae_configurations_dir(); fs_uae_init_path_resolver(); fs_uae_plugins_init(); // must be called early, before fs_emu_init -affects video output fs_uae_configure_amiga_model(); // force creation of state directories //fs_uae_flash_memory_dir(); //fs_uae_save_states_dir(); //fs_uae_floppy_overlays_dir(); fs_uae_state_dir(); const char *controllers_dir = fs_uae_controllers_dir(); if (controllers_dir) { fs_emu_set_controllers_dir(controllers_dir); } const char *logs_dir = fs_uae_logs_dir(); if (logs_dir) { char *log_file; log_file = g_build_filename(logs_dir, "FS-UAE.log", NULL); if (fs_path_exists(log_file)) { g_unlink(log_file); } g_free(log_file); log_file = g_build_filename(logs_dir, "FS-UAE.log.txt", NULL); if (fs_path_exists(log_file)) { g_unlink(log_file); } g_free(log_file); log_file = g_build_filename(logs_dir, "Emulator.log.txt", NULL); if (fs_path_exists(log_file)) { g_unlink(log_file); } g_free(log_file); log_file = g_build_filename(logs_dir, "fs-uae.log.txt", NULL); fs_config_set_log_file(log_file); g_free(log_file); } fs_config_set_string_if_unset("themes_dir", fs_uae_themes_dir()); fs_emu_set_pause_function(pause_function); //fs_uae_init_input(); fs_emu_init_2(FS_EMU_INIT_EVERYTHING); // we initialize the recording module either it is used or not, so it // can delete state-specific recordings (if necessary) when states are // saved fs_uae_init_recording(); int deterministic_mode = 0; const char* record_file = fs_config_get_const_string("record"); if (record_file) { fs_log("record file specified: %s, forcing deterministic mode\n", record_file); deterministic_mode = 1; fs_uae_enable_recording(record_file); } else { fs_log("not running in record mode\n"); } if (fs_emu_netplay_enabled() || fs_config_get_boolean(OPTION_DETERMINISTIC) == 1) { deterministic_mode = 1; } if (deterministic_mode) { amiga_set_deterministic_mode(); } if (logs_dir) { if (fs_emu_netplay_enabled()) { char *sync_log_file = g_build_filename(logs_dir, "Synchronization.log", NULL); amiga_set_synchronization_log_file(sync_log_file); free(sync_log_file); } } #ifdef FS_EMU_DRIVERS fs_emu_audio_stream_options **options = fs_emu_audio_alloc_stream_options(2); options[0]->frequency = fs_emu_audio_output_frequency(); /* 12 * 2352 is CDDA_BUFFERS * 2352 (blkdev_cdimage.cpp) */ options[1]->buffer_size = 12 * 2352; // begin playing with only one buffer queued options[1]->min_buffers = 1; fs_emu_audio_configure(options); amiga_set_audio_buffer_size(options[0]->buffer_size); fs_emu_audio_free_stream_options(options); #else // this stream is for paula output and drive clicks // FIXME: could mix drive clicks in its own stream instead, -might // give higher quality mixing fs_emu_audio_stream_options options; options.struct_size = sizeof(fs_emu_audio_stream_options); fs_emu_init_audio_stream_options(&options); options.frequency = fs_emu_audio_output_frequency(); fs_emu_init_audio_stream(0, &options); amiga_set_audio_buffer_size(options.buffer_size); // this stream is for CD audio output (CDTV/CD32) fs_emu_init_audio_stream_options(&options); // 12 * 2352 is CDDA_BUFFERS * 2352 (blkdev_cdimage.cpp) options.buffer_size = 12 * 2352; // begin playing with only one buffer queued options.min_buffers = 1; fs_emu_init_audio_stream(1, &options); #endif amiga_set_audio_callback(audio_callback_function); amiga_set_cd_audio_callback(audio_callback_function); amiga_set_event_function(event_handler); amiga_set_led_function(led_function); amiga_on_update_leds(on_update_leds); amiga_set_media_function(media_function); amiga_set_init_function(on_init); if (fs_config_get_boolean(OPTION_JIT_COMPILER) == 1) { amiga_init_jit_compiler(); } #ifdef WITH_LUA amiga_init_lua(fs_emu_acquire_lua, fs_emu_release_lua); amiga_init_lua_state(fs_emu_get_lua_state()); fs_uae_init_lua_state(fs_emu_get_lua_state()); #endif if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_RGBA) { amiga_set_video_format(AMIGA_VIDEO_FORMAT_RGBA); } else if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_BGRA) { amiga_set_video_format(AMIGA_VIDEO_FORMAT_BGRA); } else if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_R5G6B5) { amiga_set_video_format(AMIGA_VIDEO_FORMAT_R5G6B5); } else if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_R5G5B5A1) { amiga_set_video_format(AMIGA_VIDEO_FORMAT_R5G5B5A1); } else { fs_emu_warning("Unsupported video format requested"); } amiga_add_rtg_resolution(672, 540); amiga_add_rtg_resolution(960, 540); amiga_add_rtg_resolution(672 * 2, 540 * 2); amiga_add_rtg_resolution(fs_emu_get_windowed_width(), fs_emu_get_windowed_height()); amiga_add_rtg_resolution(fs_emu_get_fullscreen_width(), fs_emu_get_fullscreen_height()); fs_uae_init_video(); //fs_uae_init_keyboard(); fs_uae_init_mouse(); fs_uae_configure_menu(); fs_emu_run(main_function); fs_log("fs-uae shutting down, fs_emu_run returned\n"); if (g_rmdir(fs_uae_state_dir()) == 0) { fs_log("state dir %s was removed because it was empty\n", fs_uae_state_dir()); } else { fs_log("state dir %s was not removed (non-empty)\n", fs_uae_state_dir()); } fs_log("end of main function\n"); cleanup_old_files(); #ifdef WITH_CEF cef_destroy(); #endif return 0; }
static void on_gui_message(const char* message) { printf("MESSAGE: %s\n", message); fs_emu_warning("%s", message); }
void fs_uae_process_input_event(int line, int action, int state, int playback) { static int first_time = 1; if (first_time == 1) { first_time = 0; int load_state_number = fs_config_get_int("load_state"); if (load_state_number >= 1 && load_state_number <= 9) { // FIXME: improvement, check if state file exists and show // GUI warning if not... fs_log("trying to load state number: %d\n", load_state_number); amiga_send_input_event( INPUTEVENT_SPC_STATERESTORE1 - 1 + load_state_number, 1); } } #if 0 g_fs_uae_last_input_event = input_event; g_fs_uae_last_input_event_state = state; fs_emu_lua_run_handler("on_fs_uae_input_event"); // handler can modify input event amiga_send_input_event(g_fs_uae_last_input_event, g_fs_uae_last_input_event_state); #endif #if 0 if (action == INPUTEVENT_KEY_RETURN) { printf("FIXME: ignoring RETURN event for now\n"); return; } #endif if (action >= INPUTEVENT_AMIGA_JOYPORT_MODE_0_NONE && action < INPUTEVENT_AMIGA_JOYPORT_MODE_3_LAST) { change_port_device_mode( action - INPUTEVENT_AMIGA_JOYPORT_MODE_0_NONE); return; } if (action >= INPUTEVENT_AMIGA_JOYPORT_0_DEVICE_0 && action < INPUTEVENT_AMIGA_JOYPORT_0_DEVICE_LAST) { select_port_0_device(action - INPUTEVENT_AMIGA_JOYPORT_0_DEVICE_0); return; } if (state && action >= INPUTEVENT_AMIGA_JOYPORT_0_AUTOFIRE && action <= INPUTEVENT_AMIGA_JOYPORT_3_AUTOFIRE) { int port = action - INPUTEVENT_AMIGA_JOYPORT_0_AUTOFIRE; if (g_fs_uae_input_ports[port].autofire_mode) { g_fs_uae_input_ports[port].autofire_mode = 0; amiga_set_joystick_port_autofire(port, 0); fs_emu_warning(_("Auto-fire disabled for port %d"), port); } else { g_fs_uae_input_ports[port].autofire_mode = 1; amiga_set_joystick_port_autofire(port, 1); fs_emu_warning(_("Auto-fire enabled for port %d"), port); } fs_emu_menu_update_current(); // this event must be passed on to the Amiga core } int record_event = 1; if (playback) { record_event = 0; } int load_state = 0; int save_state = 0; if (action >= INPUTEVENT_SPC_STATESAVE1 && action <= INPUTEVENT_SPC_STATESAVE9) { save_state = action - INPUTEVENT_SPC_STATESAVE1 + 1; g_fs_uae_state_number = save_state; } if (action >= INPUTEVENT_SPC_STATERESTORE1 && action <= INPUTEVENT_SPC_STATERESTORE9) { load_state = action - INPUTEVENT_SPC_STATERESTORE1 + 1; g_fs_uae_state_number = load_state; } if (load_state) { #ifdef WITH_LUA fs_log("run handler on_fs_uae_load_state\n"); fs_emu_lua_run_handler("on_fs_uae_load_state"); #endif record_event = 0; } else if (save_state) { #ifdef WITH_LUA fs_log("run handler on_fs_uae_save_state\n"); fs_emu_lua_run_handler("on_fs_uae_save_state"); #endif record_event = 0; } if (record_event) { fs_uae_record_input_event(line, action, state); } amiga_send_input_event(action, state); if (load_state) { #ifdef WITH_LUA fs_log("run handler on_fs_uae_load_state_done\n"); fs_emu_lua_run_handler("on_fs_uae_load_state_done"); #endif } else if (save_state) { #ifdef WITH_LUA fs_log("run handler on_fs_uae_save_state_done\n"); fs_emu_lua_run_handler("on_fs_uae_save_state_done"); #endif } }
static void load_atlas_texture(fs_image *atlas_image, int texture_id, const char *name) { char *path = fs_emu_theme_get_resource(name); if (!path) { fs_emu_warning("Could not find resource %s\n", name); return; } fs_image *image = fs_image_new_from_file(path); if (!image) { fs_emu_warning("error loading texture \"%s\"\n", name); return; } fs_emu_log("loaded sub-texture from \"%s\"\n", path); // find needed number of cells int cw = (image->width + 7) / 8; int ch = (image->height + 7) / 8; // adding 1 to get some spacing between cells if (cw < 128) { cw++; } if (ch < 128) { ch++; } // try to find space for it in the texture atlas using a simple // brute-force search int cx = 0; int cy = 0; int ok = 0; for (cy = 0; cy <= 128 - ch; cy++) { for (cx = 0; cx <= 128 - cw; cx++) { if (check_placement(cx, cy, cw, ch)) { ok = 1; break; } } if (ok) { break; } } if (!ok) { fs_emu_warning("could not find space for \"%s\"\n", name); //printf("%d %d %d %d\n", cx * 8, cy * 8, cw * 8, ch * 8); return; } // mark cells as used for (int y = cy; y < cy + ch; y++) { for (int x = cx; x < cx + cw; x++) { g_cells[y][x] = 1; } } //printf("%d %d %d %d\n", cx * 8, cy * 8, cw * 8, ch * 8); // copy sub-texture into texture, also converting to pre-multiplied // alpha, and BGRA if needed. Also copy border pixels to pixels outside // border to fix unwanted bilinear filtering effects int dx = cx * 8; int dy = cy * 8; int ds = atlas_image->width * 4; // stride unsigned char *dst = atlas_image->data + \ (dy * atlas_image->width + dx) * 4; unsigned char *sp = image->data; for (int y = 0; y < image->height; y++) { #if 1 if (y == 0 && dy > 0) { // repeat first line unsigned char *dp = dst - ds; for (int x = 0; x < image->width; x++) { copy_pixel(&dp, &sp); } sp -= image->width * 4; } #endif unsigned char *dp = dst; for (int x = 0; x < image->width; x++) { copy_pixel(&dp, &sp); } dst += 1024 * 4; // stride #if 1 if (y == image->height - 1 && dy + y - 1 < atlas_image->height - 1) { // repeat last line sp -= image->width * 4; unsigned char *dp = dst; for (int x = 0; x < image->width; x++) { copy_pixel(&dp, &sp); } } #endif } // repeat left and right borders uint32_t *idata = (uint32_t *) atlas_image->data; int iwidth = atlas_image->width; int y1 = dy; int y2 = dy + image->height - 1; if (y1 > 0) { y1 -= 1; } if (y2 < atlas_image->height - 1) { y2 += 1; } if (dx > 0) { for (int y = y1; y <= y2; y++) { idata[y * iwidth + dx - 1] = idata[y * iwidth + dx]; } } if (dx + image->width - 1 < atlas_image->width - 1) { for (int y = y1; y <= y2; y++) { idata[y * iwidth + dx + image->width - 1 + 1] = \ idata[y * iwidth + dx + image->width - 1]; } } // register texture coordinates g_entries[texture_id].x = cx * 8; g_entries[texture_id].y = cy * 8; g_entries[texture_id].w = image->width; g_entries[texture_id].h = image->height; // and finally free the sub-texture image fs_unref(image); }
fs_emu_texture *fs_emu_texture_new_from_file(const char *name) { char *full_name; char *path; if (fs_path_exists(name)) { full_name = fs_strdup(name); path = fs_strdup(name); } else { full_name = fs_strconcat(name, ".png", NULL); path = fs_get_program_data_file(full_name); if (path == NULL) { fs_emu_warning("Could not find texture %s\n", full_name); return NULL; } } fs_image *image = fs_image_new_from_file(path); fs_emu_log("loading texture \"%s\"\n", path); free(path); if (image == NULL) { fs_emu_warning("Could not load texture from %s\n", full_name); free(full_name); return NULL; } free(full_name); if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_BGRA) { // convert to premultiplied alpha if (image->format == FS_IMAGE_FORMAT_RGBA) { int num_pixels = image->width * image->height; unsigned char *pixels = image->data; for (int i = 0; i < num_pixels; i++) { unsigned char alpha = pixels[3]; unsigned char temp = pixels[2]; pixels[2] = ((int) pixels[0]) * alpha / 255; pixels[1] = ((int) pixels[1]) * alpha / 255; pixels[0] = ((int) temp) * alpha / 255; pixels += 4; } } else { // FIXME: should swap R and B here... } } else { // convert to premultiplied alpha if (image->format == FS_IMAGE_FORMAT_RGBA) { int num_pixels = image->width * image->height; unsigned char *pixels = image->data; for (int i = 0; i < num_pixels; i++) { unsigned char alpha = pixels[3]; // should really divide by 255, but 256 is faster... //pixels[0] = ((int) pixels[0]) * alpha / 256; //pixels[1] = ((int) pixels[1]) * alpha / 256; //pixels[2] = ((int) pixels[2]) * alpha / 256; pixels[0] = ((int) pixels[0]) * alpha / 255; pixels[1] = ((int) pixels[1]) * alpha / 255; pixels[2] = ((int) pixels[2]) * alpha / 255; //pixels[0] = (unsigned char) ((pixels[0] * alpha + 0.5) / 255.0); //pixels[1] = (unsigned char) ((pixels[1] * alpha + 0.5) / 255.0); //pixels[2] = (unsigned char) ((pixels[2] * alpha + 0.5) / 255.0); pixels += 4; } } } fs_emu_texture *texture = fs_new(fs_emu_texture, 1); texture->width = image->width; texture->height = image->height; texture->image = image; load_texture(texture); fs_emu_set_texture(texture); fs_gl_add_context_notification(context_notification_handler, texture); return texture; }
void fs_uae_configure_graphics_card(amiga_config *c) { const char *card = NULL; int memory = 0; bool found = false; if (fs_config_get_const_string(OPTION_GRAPHICS_CARD)) { card = fs_config_get_const_string(OPTION_GRAPHICS_CARD); } else { int uaegfx_card = fs_config_get_boolean(OPTION_UAEGFX_CARD); if (uaegfx_card != FS_CONFIG_NONE) { fs_log("DEPRECATED: uaegfx_card is deprecated, use graphics_card " "instead\n"); if (uaegfx_card == 1) { if (!c->allow_z3_memory) { fs_emu_warning(_("Option uaegfx.card needs a CPU with " "32-bit addressing")); } else { card = "ZorroIII"; memory = 32; found = true; } } } } if (card == NULL) { /* For example A4000/OS4 defaults to picasso-iv-z3 */ card = cfg->default_graphics_card; } CHECK_CARD("none", NULL, 0, NULL, 0) CHECK_CARD("uaegfx", "ZorroII", 8, "ZorroIII", 512) CHECK_CARD("picasso-ii", "PicassoII", 2, NULL, 0) CHECK_CARD("picasso-ii+", "PicassoII+", 2, NULL, 0) CHECK_CARD("picasso-iv", "PicassoIV_Z2", 4, "PicassoIV_Z3", 4) if (card && !found) { fs_emu_warning("Unsupported graphics card: %s\n", card); } if (fs_config_get_const_string(OPTION_GRAPHICS_CARD_MEMORY)) { memory = fs_uae_read_memory_option(OPTION_GRAPHICS_CARD_MEMORY); memory /= 1024; fs_log("CONFIG: Overriding graphics card memory: %d MB\n", memory); } if (card != NULL) { if (memory != 0) { amiga_set_option("gfxcard_type", card); amiga_set_int_option("gfxcard_size", memory); } } char *path = fs_config_get_string(OPTION_GRAPHICS_CARD_ROM); if (path) { path = fs_uae_expand_path_and_free(path); path = fs_uae_resolve_path_and_free(path, FS_UAE_ROM_PATHS); amiga_set_option("picassoiv_rom_file", path); g_free(path); } }