//============================================================ // switchres_modeline_setup // //============================================================ bool switchres_modeline_setup(running_machine &machine) { ModeLine *bestMode; char modeline[1024]= {'\x00'}; bool success = false; int got_res = 0; mame_printf_verbose("SwitchRes: Entering switchres_modeline_setup (%d)\n", machine.switchRes.resolution.count); bestMode = &machine.switchRes.bestMode; windows_options &options = downcast<windows_options &>(machine.options()); astring error_string; if (!machine.switchRes.resolution.count) { strcpy(machine.switchRes.gameInfo.resolution, options.resolution()); machine.switchRes.cs.monitorcount = options.numscreens(); machine.switchRes.cs.doublescan = 0; if (!strcmp(options.video(), "d3d")) { machine.switchRes.cs.cleanstretch = 1; options.set_value(OPTION_CLEANSTRETCH, true, OPTION_PRIORITY_MAXIMUM, error_string); mame_printf_verbose("SwitchRes: Setting Option -cleanstretch\n"); } } // Save old modeline first if it exists if (machine.switchRes.resolution.count > 0) { memcpy(&machine.switchRes.lastMode, bestMode, sizeof(ModeLine)); mame_printf_verbose("SwitchRes: Copy lastMode name %s\n", machine.switchRes.lastMode.name); } // Generate modeline switchres_calc_modeline(machine); if (!machine.switchRes.modeLine) { mame_printf_error("SwitchRes: Modeline was NULL!!!\n"); return false; } // Initially get the registry modelines if (machine.switchRes.modecount == 0) { int custom_count = 0; machine.switchRes.modecount = GetAvailableVideoModes(machine.switchRes.videoModes); custom_count = GetCustomVideoModes(&machine.switchRes.cs, machine.switchRes.videoModes); mame_printf_verbose("SwitchRes: Found %d custom of %d active modelines\n", custom_count, machine.switchRes.modecount); } // If we got any, check for the best modeline if (machine.switchRes.modecount > 0) { int orientation = 0; if (machine.switchRes.gameInfo.orientation && !strcmp(machine.switchRes.cs.morientation, "horizontal")) orientation = 1; got_res = findBestMode(orientation, machine.switchRes.modeLine, machine.switchRes.videoModes, bestMode); mame_printf_verbose("SwitchRes: Index %d/%d modeline %s score %.02f %s\n", got_res, machine.switchRes.modecount, bestMode->label, bestMode->score, (got_res >= 0)?"matches":"has no match"); } else { got_res = -1; machine.switchRes.modecount = -1; mame_printf_error("SwitchRes: Didn't get any system or custom modelines %d\n", got_res); } // If we got a best mode, setup for use if (got_res != -1) { int use_ini = strcmp(machine.switchRes.gameInfo.resolution, "auto")?1:0; bool virtualize = false; // Got a registry modeline to change refresh rate of mame_printf_verbose("SwitchRes: Got %s modeline %s - %s:\n\t%s\n", bestMode->custom?"Custom":"System", bestMode->resolution, bestMode->label, PrintModeline(bestMode, modeline)); // Tweak modeline if height/width changed if (machine.switchRes.modeLine->hactive != bestMode->a_width || machine.switchRes.modeLine->vactive != bestMode->a_height) { int minwidth = machine.switchRes.modeLine->hactive; // Turn off .ini file support, since we can't do that use_ini = 0; // Use values from registry machine.switchRes.gameInfo.width = bestMode->a_width; machine.switchRes.gameInfo.height = bestMode->a_height; mame_printf_verbose("SwitchRes: Trying to recalculate modeline %d x %d != %d x %d\n", machine.switchRes.modeLine->hactive, machine.switchRes.modeLine->vactive, bestMode->a_width, bestMode->a_height); // Generate new modeline ModelineCreate(&machine.switchRes.cs, &machine.switchRes.gameInfo, machine.switchRes.monitorMode, machine.switchRes.modeLine); machine.switchRes.modeLine->weight = ModelineResult(machine.switchRes.modeLine, &machine.switchRes.cs); // Double check the height/width, recalculate if necessary if (machine.switchRes.modeLine->hactive != bestMode->a_width || machine.switchRes.modeLine->vactive != bestMode->a_height) { mame_printf_verbose("SwitchRes: Trying again to recalculate modeline %d x %d != %d x %d\n", machine.switchRes.modeLine->hactive, machine.switchRes.modeLine->vactive, bestMode->a_width, bestMode->a_height); if (machine.switchRes.modecount > 0) { int orientation = 0; int idx = 0; if (machine.switchRes.gameInfo.orientation && !strcmp(machine.switchRes.cs.morientation, "horizontal")) orientation = 1; idx = findBestMode(orientation, machine.switchRes.modeLine, machine.switchRes.videoModes, bestMode); mame_printf_verbose("SwitchRes: Recalculated index %d/%d modeline %s score %.02f %s\n", idx, machine.switchRes.modecount, bestMode->label, bestMode->score, (got_res >= 0)?"matches":"has no match"); if (idx) { if (bestMode->custom) { mame_printf_verbose("SwitchRes: Got %s modeline %s - %s:\n\t%s\n", bestMode->custom?"Custom":"System", bestMode->resolution, bestMode->label, PrintModeline(bestMode, modeline)); } else { mame_printf_verbose("SwitchRes: Got %s modeline %s\n", bestMode->custom?"Custom":"System", bestMode->label); } machine.switchRes.gameInfo.width = bestMode->a_width; machine.switchRes.gameInfo.height = bestMode->a_height; } else virtualize = true; } else virtualize = true; if (virtualize) mame_printf_error("SwitchRes: Failed at finding a good modeline!!!\n"); } // Check if aspect ratio needs to be fixed if (bestMode->a_width > minwidth) { mame_printf_verbose("SwitchRes: Setting Option -keepaspect\n"); options.set_value(WINOPTION_KEEPASPECT, true, OPTION_PRIORITY_MAXIMUM, error_string); } PrintModeline(machine.switchRes.modeLine, modeline); mame_printf_verbose("SwitchRes: New Modeline: \tModeLine %s\n", modeline); } // Set new resolution settings and reload it into the system if (!bestMode->custom || virtualize) { machine.switchRes.modeLine->result |= RESULT_VFREQ_CHANGE; success = true; } else if (!SetCustomVideoModes(&machine.switchRes.cs, bestMode, machine.switchRes.modeLine, 0)) { ResetVideoModes(); success = true; } else { machine.switchRes.modeLine->result |= RESULT_VIRTUALIZE; mame_printf_error("SwitchRes: Failed setting modeline!!!\n"); success = false; } // Calculate flags to set options CalculateMameOptions(machine); // If not virtualizing, do 1:1 scaling from original for height/width if (!(machine.switchRes.modeLine->result & RESULT_VIRTUALIZE)) { if ((machine.switchRes.modeLine->result & (RESULT_RES_INC|RESULT_RES_DEC))) virtualize = true; } else virtualize = true; if (virtualize) { // Adjust settings if stretched resolution mame_printf_verbose("SwitchRes: Setting Option -hwstretch\n"); options.set_value(WINOPTION_HWSTRETCH, true, OPTION_PRIORITY_MAXIMUM, error_string); mame_printf_verbose("SwitchRes: Setting Option -keepaspect\n"); options.set_value(WINOPTION_KEEPASPECT, true, OPTION_PRIORITY_MAXIMUM, error_string); // Aspect ratio specified if ((machine.switchRes.gameInfo.orientation && !strcmp(machine.switchRes.cs.morientation, "horizontal")) || (!machine.switchRes.gameInfo.orientation && !strcmp(machine.switchRes.cs.morientation, "vertical"))) { mame_printf_verbose("SwitchRes: Setting Option -screen_aspect %s\n", machine.switchRes.cs.aspect); options.set_value(WINOPTION_ASPECT, machine.switchRes.cs.aspect, OPTION_PRIORITY_MAXIMUM, error_string); } } // If interlacing, we need the filter on if (bestMode->interlace) { mame_printf_verbose("SwitchRes: Setting Option -filter\n"); options.set_value(WINOPTION_FILTER, true, OPTION_PRIORITY_MAXIMUM, error_string); } // Only use soundsync if set by user and also vsync doesn't match, else turn it off if (machine.switchRes.modeLine->result & RESULT_VFREQ_CHANGE) { if (machine.options().soundsync()) { mame_printf_verbose("SwitchRes: Setting Option -soundsync\n"); machine.switchRes.cs.soundsync = 1; } } else { mame_printf_verbose("SwitchRes: Setting Option -nosoundsync\n"); machine.switchRes.cs.soundsync = 0; } if ((machine.switchRes.modeLine->result & RESULT_VFREQ_CHANGE && !options.sync_refresh()) || options.triple_buffer()) { // Resolution doesn't match refresh rate mame_printf_verbose("SwitchRes: Disabling VSYNC\n"); mame_printf_verbose("SwitchRes: Setting Option -throttle\n"); options.set_value(OPTION_THROTTLE, true, OPTION_PRIORITY_MAXIMUM, error_string); mame_printf_verbose("SwitchRes: Setting Option -nowaitvsync\n"); options.set_value(WINOPTION_WAITVSYNC, false, OPTION_PRIORITY_MAXIMUM, error_string); } else { // Resolution matches refresh rate mame_printf_verbose("SwitchRes: Enabling VSYNC\n"); mame_printf_verbose("SwitchRes: Setting Option -nothrottle\n"); options.set_value(OPTION_THROTTLE, false, OPTION_PRIORITY_MAXIMUM, error_string); mame_printf_verbose("SwitchRes: Setting Option -waitvsync\n"); options.set_value(WINOPTION_WAITVSYNC, true, OPTION_PRIORITY_MAXIMUM, error_string); } // Force resolution if (!use_ini) { sprintf(machine.switchRes.bestMode.resolution, "%dx%d@%d", machine.switchRes.bestMode.hactive, machine.switchRes.bestMode.vactive, (int)machine.switchRes.bestMode.vfreq); mame_printf_verbose("SwitchRes: Setting Option -resolution %s\n", machine.switchRes.bestMode.resolution); options.set_value(WINOPTION_RESOLUTION, machine.switchRes.bestMode.resolution, OPTION_PRIORITY_MAXIMUM, error_string); // Setup video config resolution parameters screen 1 video_config.window[0].refresh = (int)machine.switchRes.bestMode.vfreq; video_config.window[0].width = machine.switchRes.bestMode.a_height; video_config.window[0].height = machine.switchRes.bestMode.a_width; } else mame_printf_verbose("SwitchRes: INI File resolution: %dx%d@%d\n", video_config.window[0].width, video_config.window[0].height, video_config.window[0].refresh); machine.switchRes.cs.cleanstretch = machine.options().cleanstretch(); machine.switchRes.resolution.count++; } else { mame_printf_error("SwitchRes: Couldn't find a working resolution for %dx%d@%d\n", machine.switchRes.modeLine->hactive, machine.switchRes.modeLine->vactive, (int)machine.switchRes.gameInfo.refresh); } return success; }
int main (int argc, char *argv[]) { DisplayModeRec *Mode; int HDisplay = 0, VDisplay = 0; float VRefresh = 0.0; Bool Reduced = FALSE, Verbose = FALSE, IsCVT; Bool Interlaced = FALSE; int n; if ((argc < 3) || (argc > 7)) { PrintUsage(argv[0]); return 1; } /* This doesn't filter out bad flags properly. Bad flags get passed down * to atoi/atof, which then return 0, so that these variables can get * filled next time round. So this is just a cosmetic problem. */ for (n = 1; n < argc; n++) { if (!strcmp(argv[n], "-r") || !strcmp(argv[n], "--reduced")) Reduced = TRUE; else if (!strcmp(argv[n], "-i") || !strcmp(argv[n], "--interlaced")) Interlaced = TRUE; else if (!strcmp(argv[n], "-v") || !strcmp(argv[n], "--verbose")) Verbose = TRUE; else if (!strcmp(argv[n], "-h") || !strcmp(argv[n], "--help")) { PrintUsage(argv[0]); return 0; } else if (!HDisplay) { HDisplay = atoi(argv[n]); if (!HDisplay) { PrintUsage(argv[0]); return 1; } } else if (!VDisplay) { VDisplay = atoi(argv[n]); if (!VDisplay) { PrintUsage(argv[0]); return 1; } } else if (!VRefresh) { VRefresh = atof(argv[n]); if (!VRefresh) { PrintUsage(argv[0]); return 1; } } else { PrintUsage(argv[0]); return 1; } } if (!HDisplay || !VDisplay) { PrintUsage(argv[0]); return 0; } /* Default to 60.0Hz */ if (!VRefresh) VRefresh = 60.0; /* Horizontal timing is always a multiple of 8: round up. */ if (HDisplay & 0x07) { HDisplay &= ~0x07; HDisplay += 8; } if (Reduced) { if ((VRefresh / 60.0) != floor(VRefresh / 60.0)) { fprintf(stderr, "\nERROR: Multiple of 60Hz refresh rate required for " " reduced blanking.\n"); PrintUsage(argv[0]); return 0; } } IsCVT = CVTCheckStandard(HDisplay, VDisplay, VRefresh, Reduced, Verbose); Mode = xf86CVTMode(HDisplay, VDisplay, VRefresh, Reduced, Interlaced); PrintComment(Mode, IsCVT, Reduced); PrintModeline(Mode, HDisplay, VDisplay, VRefresh, Reduced); return 0; }