aboutsummaryrefslogtreecommitdiffstats
path: root/testing/mame/groovymame.patch
diff options
context:
space:
mode:
Diffstat (limited to 'testing/mame/groovymame.patch')
-rw-r--r--testing/mame/groovymame.patch7810
1 files changed, 0 insertions, 7810 deletions
diff --git a/testing/mame/groovymame.patch b/testing/mame/groovymame.patch
deleted file mode 100644
index e16837b107d..00000000000
--- a/testing/mame/groovymame.patch
+++ /dev/null
@@ -1,7810 +0,0 @@
-diff --git a/scripts/src/emu.lua b/scripts/src/emu.lua
-index b7736fb4c27..2be746a8b5f 100644
---- a/scripts/src/emu.lua
-+++ b/scripts/src/emu.lua
-@@ -259,6 +259,11 @@ files {
- MAME_DIR .. "src/emu/video/rgbsse.h",
- MAME_DIR .. "src/emu/video/rgbvmx.cpp",
- MAME_DIR .. "src/emu/video/rgbvmx.h",
-+ MAME_DIR .. "src/emu/switchres/modeline.cpp",
-+ MAME_DIR .. "src/emu/switchres/monitor.cpp",
-+ MAME_DIR .. "src/emu/switchres/util.cpp",
-+ MAME_DIR .. "src/emu/switchres/switchres.cpp",
-+ MAME_DIR .. "src/emu/switchres/switchres.h",
- }
-
- pchsource(MAME_DIR .. "src/emu/main.cpp")
-diff --git a/scripts/src/osd/sdl.lua b/scripts/src/osd/sdl.lua
-index 10aa9940c52..0a87568a2aa 100644
---- a/scripts/src/osd/sdl.lua
-+++ b/scripts/src/osd/sdl.lua
-@@ -47,12 +47,19 @@ function maintargetosdoptions(_target,_subtarget)
- if BASE_TARGETOS=="unix" and _OPTIONS["targetos"]~="macosx" and _OPTIONS["targetos"]~="android" and _OPTIONS["targetos"]~="asmjs" then
- links {
- "SDL2_ttf",
-+ "Xrandr",
- }
- local str = backtick(pkgconfigcmd() .. " --libs fontconfig")
- addlibfromstring(str)
- addoptionsfromstring(str)
- end
-
-+ if BASE_TARGETOS=="unix" and _OPTIONS["targetos"]=="linux" then
-+ local str = backtick("pkg-config --libs libdrm")
-+ addlibfromstring(str)
-+ addoptionsfromstring(str)
-+ end
-+
- if _OPTIONS["targetos"]=="windows" then
- if _OPTIONS["with-bundled-sdl2"]~=nil then
- configuration { "mingw*"}
-@@ -435,6 +442,7 @@ project ("osd_" .. _OPTIONS["osd"])
- MAME_DIR .. "src/osd/sdl/video.cpp",
- MAME_DIR .. "src/osd/sdl/window.cpp",
- MAME_DIR .. "src/osd/sdl/window.h",
-+ MAME_DIR .. "src/osd/sdl/switchres_sdl.cpp",
- MAME_DIR .. "src/osd/modules/osdwindow.cpp",
- MAME_DIR .. "src/osd/modules/osdwindow.h",
- MAME_DIR .. "src/osd/modules/render/drawsdl.cpp",
-diff --git a/scripts/src/osd/sdl_cfg.lua b/scripts/src/osd/sdl_cfg.lua
-index e942e50fdde..c9b37d07c70 100644
---- a/scripts/src/osd/sdl_cfg.lua
-+++ b/scripts/src/osd/sdl_cfg.lua
-@@ -134,6 +134,9 @@ if _OPTIONS["targetos"]=="windows" then
- configuration { }
-
- elseif _OPTIONS["targetos"]=="linux" then
-+ buildoptions {
-+ backtick("pkg-config --cflags libdrm"),
-+ }
- if _OPTIONS["QT_HOME"]~=nil then
- buildoptions {
- "-I" .. backtick(_OPTIONS["QT_HOME"] .. "/bin/qmake -query QT_INSTALL_HEADERS"),
-diff --git a/scripts/src/osd/windows.lua b/scripts/src/osd/windows.lua
-index 963980b22ca..91344edea4a 100644
---- a/scripts/src/osd/windows.lua
-+++ b/scripts/src/osd/windows.lua
-@@ -45,6 +45,7 @@ function maintargetosdoptions(_target,_subtarget)
- "psapi",
- "ole32",
- "shlwapi",
-+ "dwmapi",
- }
- end
-
-@@ -170,6 +171,16 @@ project ("osd_" .. _OPTIONS["osd"])
- MAME_DIR .. "src/osd/windows/winmenu.cpp",
- MAME_DIR .. "src/osd/windows/winmain.cpp",
- MAME_DIR .. "src/osd/windows/winmain.h",
-+ MAME_DIR .. "src/osd/windows/switchres_windows.cpp",
-+ MAME_DIR .. "src/osd/windows/custom_video.cpp",
-+ MAME_DIR .. "src/osd/windows/custom_video.h",
-+ MAME_DIR .. "src/osd/windows/custom_video_ati.cpp",
-+ MAME_DIR .. "src/osd/windows/custom_video_ati.h",
-+ MAME_DIR .. "src/osd/windows/custom_video_adl.cpp",
-+ MAME_DIR .. "src/osd/windows/custom_video_adl.h",
-+ MAME_DIR .. "src/osd/windows/custom_video_ati_family.cpp",
-+ MAME_DIR .. "src/osd/windows/custom_video_pstrip.cpp",
-+ MAME_DIR .. "src/osd/windows/custom_video_pstrip.h",
- MAME_DIR .. "src/osd/osdepend.h",
- MAME_DIR .. "src/osd/modules/debugger/win/consolewininfo.cpp",
- MAME_DIR .. "src/osd/modules/debugger/win/consolewininfo.h",
-diff --git a/src/emu/drivenum.cpp b/src/emu/drivenum.cpp
-index 5a29dcabd9a..34f5a912cb0 100644
---- a/src/emu/drivenum.cpp
-+++ b/src/emu/drivenum.cpp
-@@ -238,7 +238,7 @@ void driver_enumerator::find_approximate_matches(std::string const &string, std:
- if (m_included[index])
- templist[arrayindex++] = index;
- assert(arrayindex == m_filtered_count);
--
-+/*
- // shuffle
- for (int shufnum = 0; shufnum < (4 * s_driver_count); shufnum++)
- {
-@@ -248,7 +248,7 @@ void driver_enumerator::find_approximate_matches(std::string const &string, std:
- templist[item1] = templist[item2];
- templist[item2] = temp;
- }
--
-+*/
- // copy out the first few entries
- for (int matchnum = 0; matchnum < count; matchnum++)
- results[matchnum] = templist[matchnum % m_filtered_count];
-diff --git a/src/emu/drivers/empty.cpp b/src/emu/drivers/empty.cpp
-index faa17f60158..47744719cb9 100644
---- a/src/emu/drivers/empty.cpp
-+++ b/src/emu/drivers/empty.cpp
-@@ -52,7 +52,7 @@ void empty_state::___empty(machine_config &config)
- screen.set_screen_update(FUNC(empty_state::screen_update));
- screen.set_size(640, 480);
- screen.set_visarea(0, 639, 0, 479);
-- screen.set_refresh_hz(30);
-+ screen.set_refresh_hz(61);
- }
-
-
-diff --git a/src/emu/emu.h b/src/emu/emu.h
-index 35a5d6a3f60..ee75aa354ba 100644
---- a/src/emu/emu.h
-+++ b/src/emu/emu.h
-@@ -84,6 +84,9 @@
- #include "gamedrv.h"
- #include "parameters.h"
-
-+// Switchres
-+#include "switchres/switchres.h"
-+
- // the running machine
- #include "main.h"
- #include "machine.h"
-@@ -108,4 +111,7 @@
- // member templates that don't like incomplete types
- #include "device.ipp"
-
-+// Switchres prototypes
-+#include "switchres/switchres_proto.h"
-+
- #endif // __EMU_H__
-diff --git a/src/emu/emuopts.cpp b/src/emu/emuopts.cpp
-index a48a4f80811..5a60c9338ea 100644
---- a/src/emu/emuopts.cpp
-+++ b/src/emu/emuopts.cpp
-@@ -85,10 +85,12 @@ const options_entry emu_options::s_option_entries[] =
- { OPTION_FRAMESKIP ";fs(0-10)", "0", OPTION_INTEGER, "set frameskip to fixed value, 0-10 (autoframeskip must be disabled)" },
- { OPTION_SECONDS_TO_RUN ";str", "0", OPTION_INTEGER, "number of emulated seconds to run before automatically exiting" },
- { OPTION_THROTTLE, "1", OPTION_BOOLEAN, "throttle emulation to keep system running in sync with real time" },
-+ { OPTION_SYNCREFRESH ";srf", "0", OPTION_BOOLEAN, "enable using the start of VBLANK for throttling instead of the game time" },
-+ { OPTION_AUTOSYNC ";as", "1", OPTION_BOOLEAN, "automatically enable syncrefresh if refresh difference is below syncrefresh_tolerance" },
- { OPTION_SLEEP, "1", OPTION_BOOLEAN, "enable sleeping, which gives time back to other applications when idle" },
- { OPTION_SPEED "(0.01-100)", "1.0", OPTION_FLOAT, "controls the speed of gameplay, relative to realtime; smaller numbers are slower" },
- { OPTION_REFRESHSPEED ";rs", "0", OPTION_BOOLEAN, "automatically adjust emulation speed to keep the emulated refresh rate slower than the host screen" },
-- { OPTION_LOWLATENCY ";lolat", "0", OPTION_BOOLEAN, "draws new frame before throttling to reduce input latency" },
-+ { OPTION_LOWLATENCY ";lolat", "1", OPTION_BOOLEAN, "draws new frame before throttling to reduce input latency" },
-
- // render options
- { nullptr, nullptr, OPTION_HEADER, "CORE RENDER OPTIONS" },
-@@ -113,7 +115,7 @@ const options_entry emu_options::s_option_entries[] =
-
- // artwork options
- { nullptr, nullptr, OPTION_HEADER, "CORE ARTWORK OPTIONS" },
-- { OPTION_ARTWORK_CROP ";artcrop", "0", OPTION_BOOLEAN, "crop artwork so emulated screen image fills output screen/window in one axis" },
-+ { OPTION_ARTWORK_CROP ";artcrop", "1", OPTION_BOOLEAN, "crop artwork so emulated screen image fills output screen/window in one axis" },
- { OPTION_FALLBACK_ARTWORK, nullptr, OPTION_STRING, "fallback artwork if no external artwork or internal driver layout defined" },
- { OPTION_OVERRIDE_ARTWORK, nullptr, OPTION_STRING, "override artwork for external artwork and internal driver layout" },
-
-@@ -216,6 +218,38 @@ const options_entry emu_options::s_option_entries[] =
- { OPTION_HTTP_PORT, "8080", OPTION_INTEGER, "HTTP server port" },
- { OPTION_HTTP_ROOT, "web", OPTION_STRING, "HTTP server document root" },
-
-+ // Switchres options
-+ { nullptr, nullptr, OPTION_HEADER, "CORE SWITCHRES OPTIONS" },
-+ { OPTION_MODELINE_GENERATION ";ml", "1", OPTION_BOOLEAN, "Automatic generation of modelines based on the specified monitor type" },
-+ { OPTION_MONITOR ";m", "generic_15",OPTION_STRING, "Monitor type, e.g.: generic_15, arcade_15, lcd, custom, etc." },
-+ { OPTION_ORIENTATION ";or", "horizontal",OPTION_STRING, "Monitor orientation (horizontal|vertical|rotate|rotate_r|rotate_l)" },
-+ { OPTION_CONNECTOR ";cn", "auto", OPTION_STRING, "[Linux] video card output (VGA-0|VGA-1|DVI-0|DVI-1)" },
-+ { OPTION_INTERLACE ";in", "1", OPTION_BOOLEAN, "Enable interlaced scanning when necessary" },
-+ { OPTION_DOUBLESCAN ";ds", "1", OPTION_BOOLEAN, "Enable double scanning when necessary (unsupported under Windows)" },
-+ { OPTION_SUPER_WIDTH ";cs", "2560", OPTION_INTEGER, "Automatically apply -unevenstretchx if resolution width is equal or greater than this value" },
-+ { OPTION_CHANGERES ";cr", "1", OPTION_BOOLEAN, "Enable dynamic in-game video mode switching" },
-+ { OPTION_POWERSTRIP ";ps", "0", OPTION_BOOLEAN, "Use Powerstrip API for dynamic setting of custom video timings" },
-+ { OPTION_LOCK_SYSTEM_MODES ";lsm", "1", OPTION_BOOLEAN, "Lock system (non-custom) video modes, only use modes created by us" },
-+ { OPTION_LOCK_UNSUPPORTED_MODES ";lum", "1", OPTION_BOOLEAN, "Lock video modes reported as unsupported by your monitor's EDID" },
-+ { OPTION_REFRESH_DONT_CARE ";rdc", "0", OPTION_BOOLEAN, "Ignore video mode's refresh reported by OS when checking ranges" },
-+ { OPTION_DOTCLOCK_MIN ";dcm", "0", OPTION_STRING, "Lowest pixel clock supported by video card, in MHz, default is 0" },
-+ { OPTION_SYNC_REFRESH_TOLERANCE ";srt", "2.0", OPTION_STRING, "Maximum refresh difference, in Hz, allowed in order to synchronize" },
-+ { OPTION_FRAME_DELAY ";fd", "0", OPTION_INTEGER, "Delays the start of each frame to minimize input lag (0-9)"},
-+ { OPTION_VSYNC_OFFSET, "0", OPTION_INTEGER, "Offset vsync position by this many lines to prevent tearing with frame_delay and high-resolution displays" },
-+ { OPTION_BLACK_FRAME_INSERTION ";bfi", "0", OPTION_BOOLEAN, "Inserts a black frame after each normal frame, intended to reduce motion blur on 120 Hz monitors" },
-+ { OPTION_MODELINE ";mode", "auto", OPTION_STRING, "Use custom defined modeline" },
-+ { OPTION_PS_TIMING ";pst", "auto", OPTION_STRING, "Use custom Powertrip timing string" },
-+ { OPTION_LCD_RANGE ";lcd", "auto", OPTION_STRING, "Add custom LCD range, VfreqMin-VfreqMax, in Hz, e.g.: 55.50-61.00" },
-+ { OPTION_CRT_RANGE0 ";crt0", "auto", OPTION_STRING, "Add custom CRT range, see documentation for details." },
-+ { OPTION_CRT_RANGE1 ";crt1", "auto", OPTION_STRING, "Add custom CRT range" },
-+ { OPTION_CRT_RANGE2 ";crt2", "auto", OPTION_STRING, "Add custom CRT range" },
-+ { OPTION_CRT_RANGE3 ";crt3", "auto", OPTION_STRING, "Add custom CRT range" },
-+ { OPTION_CRT_RANGE4 ";crt4", "auto", OPTION_STRING, "Add custom CRT range" },
-+ { OPTION_CRT_RANGE5 ";crt5", "auto", OPTION_STRING, "Add custom CRT range" },
-+ { OPTION_CRT_RANGE6 ";crt6", "auto", OPTION_STRING, "Add custom CRT range" },
-+ { OPTION_CRT_RANGE7 ";crt7", "auto", OPTION_STRING, "Add custom CRT range" },
-+ { OPTION_CRT_RANGE8 ";crt8", "auto", OPTION_STRING, "Add custom CRT range" },
-+ { OPTION_CRT_RANGE9 ";crt9", "auto", OPTION_STRING, "Add custom CRT range" },
- { nullptr }
- };
-
-diff --git a/src/emu/emuopts.h b/src/emu/emuopts.h
-index a1a23e77a2b..1a12f23d99b 100644
---- a/src/emu/emuopts.h
-+++ b/src/emu/emuopts.h
-@@ -72,6 +72,8 @@
- #define OPTION_FRAMESKIP "frameskip"
- #define OPTION_SECONDS_TO_RUN "seconds_to_run"
- #define OPTION_THROTTLE "throttle"
-+#define OPTION_SYNCREFRESH "syncrefresh"
-+#define OPTION_AUTOSYNC "autosync"
- #define OPTION_SLEEP "sleep"
- #define OPTION_SPEED "speed"
- #define OPTION_REFRESHSPEED "refreshspeed"
-@@ -193,6 +195,38 @@
- #define OPTION_HTTP_PORT "http_port"
- #define OPTION_HTTP_ROOT "http_root"
-
-+/* Switchres Options */
-+#define OPTION_MODELINE_GENERATION "modeline_generation"
-+#define OPTION_MONITOR "monitor"
-+#define OPTION_CONNECTOR "connector"
-+#define OPTION_ORIENTATION "orientation"
-+#define OPTION_INTERLACE "interlace"
-+#define OPTION_DOUBLESCAN "doublescan"
-+#define OPTION_SUPER_WIDTH "super_width"
-+#define OPTION_CHANGERES "changeres"
-+#define OPTION_POWERSTRIP "powerstrip"
-+#define OPTION_LOCK_SYSTEM_MODES "lock_system_modes"
-+#define OPTION_LOCK_UNSUPPORTED_MODES "lock_unsupported_modes"
-+#define OPTION_REFRESH_DONT_CARE "refresh_dont_care"
-+#define OPTION_DOTCLOCK_MIN "dotclock_min"
-+#define OPTION_SYNC_REFRESH_TOLERANCE "sync_refresh_tolerance"
-+#define OPTION_FRAME_DELAY "frame_delay"
-+#define OPTION_VSYNC_OFFSET "vsync_offset"
-+#define OPTION_BLACK_FRAME_INSERTION "black_frame_insertion"
-+#define OPTION_MODELINE "modeline"
-+#define OPTION_PS_TIMING "ps_timing"
-+#define OPTION_LCD_RANGE "lcd_range"
-+#define OPTION_CRT_RANGE0 "crt_range0"
-+#define OPTION_CRT_RANGE1 "crt_range1"
-+#define OPTION_CRT_RANGE2 "crt_range2"
-+#define OPTION_CRT_RANGE3 "crt_range3"
-+#define OPTION_CRT_RANGE4 "crt_range4"
-+#define OPTION_CRT_RANGE5 "crt_range5"
-+#define OPTION_CRT_RANGE6 "crt_range6"
-+#define OPTION_CRT_RANGE7 "crt_range7"
-+#define OPTION_CRT_RANGE8 "crt_range8"
-+#define OPTION_CRT_RANGE9 "crt_range9"
-+
- //**************************************************************************
- // TYPE DEFINITIONS
- //**************************************************************************
-@@ -350,6 +384,8 @@ public:
- int frameskip() const { return int_value(OPTION_FRAMESKIP); }
- int seconds_to_run() const { return int_value(OPTION_SECONDS_TO_RUN); }
- bool throttle() const { return bool_value(OPTION_THROTTLE); }
-+ bool sync_refresh() const { return bool_value(OPTION_SYNCREFRESH); }
-+ bool autosync() const { return bool_value(OPTION_AUTOSYNC); }
- bool sleep() const { return m_sleep; }
- float speed() const { return float_value(OPTION_SPEED); }
- bool refresh_speed() const { return m_refresh_speed; }
-@@ -444,6 +480,38 @@ public:
- const char *ram_size() const { return value(OPTION_RAMSIZE); }
- bool nvram_save() const { return bool_value(OPTION_NVRAM_SAVE); }
-
-+ // Switchres options
-+ bool modeline_generation() const { return bool_value(OPTION_MODELINE_GENERATION); }
-+ const char *monitor() const { return value(OPTION_MONITOR); }
-+ const char *connector() const { return value(OPTION_CONNECTOR); }
-+ const char *orientation() const { return value(OPTION_ORIENTATION); }
-+ bool doublescan() const { return bool_value(OPTION_DOUBLESCAN); }
-+ bool interlace() const { return bool_value(OPTION_INTERLACE); }
-+ int super_width() const { return int_value(OPTION_SUPER_WIDTH); }
-+ int changeres() const { return int_value(OPTION_CHANGERES); }
-+ bool powerstrip() const { return bool_value(OPTION_POWERSTRIP); }
-+ bool lock_system_modes() const { return bool_value(OPTION_LOCK_SYSTEM_MODES); }
-+ bool lock_unsupported_modes() const { return bool_value(OPTION_LOCK_UNSUPPORTED_MODES); }
-+ bool refresh_dont_care() const { return bool_value(OPTION_REFRESH_DONT_CARE); }
-+ const char *dotclock_min() const { return value(OPTION_DOTCLOCK_MIN); }
-+ const char *sync_refresh_tolerance() const { return value(OPTION_SYNC_REFRESH_TOLERANCE); }
-+ int frame_delay() const { return int_value(OPTION_FRAME_DELAY); }
-+ int vsync_offset() const { return int_value(OPTION_VSYNC_OFFSET); }
-+ bool black_frame_insertion() const { return bool_value(OPTION_BLACK_FRAME_INSERTION); }
-+ const char *modeline() const { return value(OPTION_MODELINE); }
-+ const char *ps_timing() const { return value(OPTION_PS_TIMING); }
-+ const char *lcd_range() const { return value(OPTION_LCD_RANGE); }
-+ const char *crt_range0() const { return value(OPTION_CRT_RANGE0); }
-+ const char *crt_range1() const { return value(OPTION_CRT_RANGE1); }
-+ const char *crt_range2() const { return value(OPTION_CRT_RANGE2); }
-+ const char *crt_range3() const { return value(OPTION_CRT_RANGE3); }
-+ const char *crt_range4() const { return value(OPTION_CRT_RANGE4); }
-+ const char *crt_range5() const { return value(OPTION_CRT_RANGE5); }
-+ const char *crt_range6() const { return value(OPTION_CRT_RANGE6); }
-+ const char *crt_range7() const { return value(OPTION_CRT_RANGE7); }
-+ const char *crt_range8() const { return value(OPTION_CRT_RANGE8); }
-+ const char *crt_range9() const { return value(OPTION_CRT_RANGE9); }
-+
- // core comm options
- const char *comm_localhost() const { return value(OPTION_COMM_LOCAL_HOST); }
- const char *comm_localport() const { return value(OPTION_COMM_LOCAL_PORT); }
-diff --git a/src/emu/machine.cpp b/src/emu/machine.cpp
-index 7b86af34925..0b93346b0d3 100644
---- a/src/emu/machine.cpp
-+++ b/src/emu/machine.cpp
-@@ -135,6 +135,7 @@ running_machine::running_machine(const machine_config &_config, machine_manager
- m_dummy_space(_config, "dummy_space", &root_device(), 0)
- {
- memset(&m_base_time, 0, sizeof(m_base_time));
-+ memset(&switchres, 0, sizeof(switchres));
-
- m_dummy_space.set_machine(*this);
- m_dummy_space.config_complete();
-diff --git a/src/emu/machine.h b/src/emu/machine.h
-index 205988fbbe6..5d641a1cb7e 100644
---- a/src/emu/machine.h
-+++ b/src/emu/machine.h
-@@ -257,6 +257,9 @@ public:
- std::string compose_saveload_filename(std::string &&base_filename, const char **searchpath = nullptr);
- std::string get_statename(const char *statename_opt) const;
-
-+ // SwitchRes manager
-+ switchres_manager switchres; // SwitchRes data
-+
- private:
- // side effect disable counter
- u32 m_side_effects_disabled;
-diff --git a/src/emu/sound.cpp b/src/emu/sound.cpp
-index c876431c41b..15fd0116787 100644
---- a/src/emu/sound.cpp
-+++ b/src/emu/sound.cpp
-@@ -866,16 +866,13 @@ sound_manager::sound_manager(running_machine &machine)
- machine.add_notifier(MACHINE_NOTIFY_RESUME, machine_notify_delegate(&sound_manager::resume, this));
- machine.add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(&sound_manager::reset, this));
- machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&sound_manager::stop_recording, this));
-+ machine.add_notifier(MACHINE_NOTIFY_FRAME, machine_notify_delegate(&sound_manager::update, this));
-
- // register global states
- machine.save().save_item(NAME(m_last_update));
-
- // set the starting attenuation
- set_attenuation(machine.options().volume());
--
-- // start the periodic update flushing timer
-- m_update_timer = machine.scheduler().timer_alloc(timer_expired_delegate(FUNC(sound_manager::update), this));
-- m_update_timer->adjust(STREAMS_UPDATE_ATTOTIME, 0, STREAMS_UPDATE_ATTOTIME);
- }
-
-
-@@ -1077,7 +1074,7 @@ void sound_manager::config_save(config_type cfg_type, util::xml::data_node *pare
- // and send it to the OSD layer
- //-------------------------------------------------
-
--void sound_manager::update(void *ptr, int param)
-+void sound_manager::update()
- {
- VPRINTF(("sound_update\n"));
-
-@@ -1089,13 +1086,13 @@ void sound_manager::update(void *ptr, int param)
- speaker.mix(&m_leftmix[0], &m_rightmix[0], m_samples_this_update, (m_muted & MUTE_REASON_SYSTEM));
-
- // now downmix the final result
-- u32 finalmix_step = machine().video().speed_factor();
-+ u32 finalmix_step = machine().video().speed_factor() * 100;
- u32 finalmix_offset = 0;
- s16 *finalmix = &m_finalmix[0];
- int sample;
-- for (sample = m_finalmix_leftover; sample < m_samples_this_update * 1000; sample += finalmix_step)
-+ for (sample = m_finalmix_leftover; sample < m_samples_this_update * 100000; sample += finalmix_step)
- {
-- int sampindex = sample / 1000;
-+ int sampindex = sample / 100000;
-
- // clamp the left side
- s32 samp = m_leftmix[sampindex];
-@@ -1113,7 +1110,7 @@ void sound_manager::update(void *ptr, int param)
- samp = 32767;
- finalmix[finalmix_offset++] = samp;
- }
-- m_finalmix_leftover = sample - m_samples_this_update * 1000;
-+ m_finalmix_leftover = sample - m_samples_this_update * 100000;
-
- // play the result
- if (finalmix_offset > 0)
-diff --git a/src/emu/sound.h b/src/emu/sound.h
-index 7301a4d69ba..91fd6b0de4a 100644
---- a/src/emu/sound.h
-+++ b/src/emu/sound.h
-@@ -225,7 +225,7 @@ private:
- void config_load(config_type cfg_type, util::xml::data_node const *parentnode);
- void config_save(config_type cfg_type, util::xml::data_node *parentnode);
-
-- void update(void *ptr = nullptr, s32 param = 0);
-+ void update();
-
- // internal state
- running_machine & m_machine; // reference to our machine
-diff --git a/src/emu/switchres/modeline.cpp b/src/emu/switchres/modeline.cpp
-new file mode 100644
-index 00000000000..8eddd2b4e2a
---- /dev/null
-+++ b/src/emu/switchres/modeline.cpp
-@@ -0,0 +1,690 @@
-+/**************************************************************
-+
-+ modeline.cpp - Modeline generation and scoring routines
-+
-+ ---------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2016 - Chris Kennedy, Antonio Giner
-+
-+ **************************************************************/
-+
-+#include "emu.h"
-+
-+#define max(a,b)({ __typeof__ (a) _a = (a);__typeof__ (b) _b = (b);_a > _b ? _a : _b; })
-+#define min(a,b)({ __typeof__ (a) _a = (a);__typeof__ (b) _b = (b);_a < _b ? _a : _b; })
-+
-+//============================================================
-+// PROTOTYPES
-+//============================================================
-+
-+int get_line_params(modeline *mode, monitor_range *range);
-+int scale_into_range (int value, int lower_limit, int higher_limit);
-+int scale_into_range (float value, float lower_limit, float higher_limit);
-+int scale_into_aspect (int source_res, int tot_res, float original_monitor_aspect, float users_monitor_aspect, float *best_diff);
-+int stretch_into_range(float vfreq, monitor_range *range, bool interlace_allowed, float *interlace);
-+int total_lines_for_yres(int yres, float vfreq, monitor_range *range, float interlace);
-+float max_vfreq_for_yres (int yres, monitor_range *range, float interlace);
-+int round_near (double number);
-+
-+//============================================================
-+// modeline_create
-+//============================================================
-+
-+int modeline_create(modeline *s_mode, modeline *t_mode, monitor_range *range, config_settings *cs)
-+{
-+ float vfreq = 0;
-+ float vfreq_real = 0;
-+ int xres = 0;
-+ int yres = 0;
-+ float interlace = 1;
-+ float doublescan = 1;
-+ float scan_factor = 1;
-+ int x_scale = 0;
-+ int y_scale = 0;
-+ int v_scale = 0;
-+ float x_diff = 0;
-+ float y_diff = 0;
-+ float v_diff = 0;
-+ float y_ratio = 0;
-+ float x_ratio = 0;
-+
-+ // init all editable fields with source or user values
-+ if (t_mode->type & X_RES_EDITABLE)
-+ xres = cs->width? cs->width : s_mode->hactive;
-+ else
-+ xres = t_mode->hactive;
-+ if (t_mode->type & Y_RES_EDITABLE)
-+ yres = cs->height? cs->height : s_mode->vactive;
-+ else
-+ yres = t_mode->vactive;
-+ if (t_mode->type & V_FREQ_EDITABLE)
-+ vfreq = s_mode->vfreq;
-+ else
-+ vfreq = t_mode->vfreq;
-+
-+ // lock resolution fields if required
-+ if (cs->width) t_mode->type &= ~X_RES_EDITABLE;
-+ if (cs->height) t_mode->type &= ~Y_RES_EDITABLE;
-+
-+ // ··· Vertical refresh ···
-+ // try to fit vertical frequency into current range
-+ v_scale = scale_into_range(vfreq, range->vfreq_min, range->vfreq_max);
-+
-+ if (!v_scale && (t_mode->type & V_FREQ_EDITABLE))
-+ {
-+ vfreq = vfreq < range->vfreq_min? range->vfreq_min : range->vfreq_max;
-+ v_scale = 1;
-+ }
-+ else if (v_scale != 1 && !(t_mode->type & V_FREQ_EDITABLE))
-+ {
-+ t_mode->result.weight |= R_OUT_OF_RANGE;
-+ return -1;
-+ }
-+
-+ // ··· Vertical resolution ···
-+ // try to fit active lines in the progressive range first
-+ if (range->progressive_lines_min && (!t_mode->interlace || (t_mode->type & V_FREQ_EDITABLE)))
-+ y_scale = scale_into_range(yres, range->progressive_lines_min, range->progressive_lines_max);
-+
-+ // if not possible, try to fit in the interlaced range, if any
-+ if (!y_scale && range->interlaced_lines_min && cs->interlace && (t_mode->interlace || (t_mode->type & V_FREQ_EDITABLE)))
-+ {
-+ y_scale = scale_into_range(yres, range->interlaced_lines_min, range->interlaced_lines_max);
-+ interlace = 2;
-+ }
-+
-+ // if we succeeded, let's see if we can apply integer scaling
-+ if (y_scale == 1 || (y_scale > 1 && (t_mode->type & Y_RES_EDITABLE)))
-+ {
-+ // check if we should apply doublescan
-+ if (cs->doublescan && y_scale % 2 == 0)
-+ {
-+ y_scale /= 2;
-+ doublescan = 0.5;
-+ }
-+ scan_factor = interlace * doublescan;
-+
-+ // calculate expected achievable refresh for this height
-+ vfreq_real = min(vfreq * v_scale, max_vfreq_for_yres(yres * y_scale, range, scan_factor));
-+ if (vfreq_real != vfreq * v_scale && !(t_mode->type & V_FREQ_EDITABLE))
-+ {
-+ t_mode->result.weight |= R_OUT_OF_RANGE;
-+ return -1;
-+ }
-+
-+ // calculate the ratio that our scaled yres represents with respect to the original height
-+ y_ratio = float(yres) * y_scale / s_mode->vactive;
-+ int y_source_scaled = s_mode->vactive * floor(y_ratio);
-+
-+ // if our original height doesn't fit the target height, we're forced to stretch
-+ if (!y_source_scaled)
-+ t_mode->result.weight |= R_RES_STRETCH;
-+
-+ // otherwise we try to perform integer scaling
-+ else
-+ {
-+ if (t_mode->type & V_FREQ_EDITABLE)
-+ {
-+ // calculate y borders considering physical lines (instead of logical resolution)
-+ int tot_yres = total_lines_for_yres(yres * y_scale, vfreq_real, range, scan_factor);
-+ int tot_source = total_lines_for_yres(y_source_scaled, vfreq * v_scale, range, scan_factor);
-+ y_diff = tot_yres > tot_source?float(tot_yres % tot_source) / tot_yres * 100:0;
-+
-+ // we penalize for the logical lines we need to add in order to meet the user's lower active lines limit
-+ int y_min = interlace == 2?range->interlaced_lines_min:range->progressive_lines_min;
-+ int tot_rest = (y_min >= y_source_scaled)? y_min % y_source_scaled:0;
-+ y_diff += float(tot_rest) / tot_yres * 100;
-+ }
-+ else
-+ y_diff = float((yres * y_scale) % y_source_scaled) / (yres * y_scale) * 100;
-+
-+ // we save the integer ratio between source and target resolutions, this will be used for prescaling
-+ y_scale = floor(y_ratio);
-+
-+ // now if the borders obtained are low enough (< 10%) we'll finally apply integer scaling
-+ // otherwise we'll stretch the original resolution over the target one
-+ if (!(y_ratio >= 1.0 && y_ratio < 16.0 && y_diff < 10.0))
-+ t_mode->result.weight |= R_RES_STRETCH;
-+ }
-+ }
-+
-+ // otherwise, check if we're allowed to apply fractional scaling
-+ else if (t_mode->type & Y_RES_EDITABLE)
-+ t_mode->result.weight |= R_RES_STRETCH;
-+
-+ // if there's nothing we can do, we're out of range
-+ else
-+ {
-+ t_mode->result.weight |= R_OUT_OF_RANGE;
-+ return -1;
-+ }
-+
-+ // ··· Horizontal resolution ···
-+ // make the best possible adjustment of xres depending on what happened in the previous steps
-+ // let's start with the SCALED case
-+ if (!(t_mode->result.weight & R_RES_STRETCH))
-+ {
-+ // if we can, let's apply the same scaling to both directions
-+ if (t_mode->type & X_RES_EDITABLE)
-+ {
-+ if (t_mode->type & Y_RES_EDITABLE) yres *= y_scale;
-+ x_scale = y_scale;
-+ xres = normalize(float(xres) * float(x_scale) * cs->monitor_aspect / (cs->effective_orientation? (1.0/(STANDARD_CRT_ASPECT)) : (STANDARD_CRT_ASPECT)), 8);
-+ }
-+
-+ // otherwise, try to get the best out of our current xres
-+ else
-+ {
-+ x_scale = xres / s_mode->hactive;
-+ // if the source width fits our xres, try applying integer scaling
-+ if (x_scale)
-+ {
-+ x_scale = scale_into_aspect(s_mode->hactive, xres, cs->effective_orientation?1.0/(STANDARD_CRT_ASPECT):STANDARD_CRT_ASPECT, cs->monitor_aspect, &x_diff);
-+ if (x_diff > 15.0 && t_mode->width < cs->super_width)
-+ t_mode->result.weight |= R_RES_STRETCH;
-+ }
-+ // otherwise apply fractional scaling
-+ else
-+ t_mode->result.weight |= R_RES_STRETCH;
-+ }
-+ }
-+
-+ // if the result was fractional scaling in any of the previous steps, deal with it
-+ if (t_mode->result.weight & R_RES_STRETCH)
-+ {
-+ if (t_mode->type & Y_RES_EDITABLE)
-+ {
-+ // always try to use the interlaced range first if it exists, for better resolution
-+ yres = stretch_into_range(vfreq, range, cs->interlace, &interlace);
-+
-+ // check in case we couldn't achieve the desired refresh
-+ vfreq_real = min(vfreq, max_vfreq_for_yres(yres, range, interlace));
-+ }
-+
-+ // check if we can create a normal aspect resolution
-+ if (t_mode->type & X_RES_EDITABLE)
-+ xres = max(xres, normalize(STANDARD_CRT_ASPECT * yres, 8));
-+
-+ // calculate integer scale for prescaling
-+ x_scale = max(1, scale_into_aspect(s_mode->hactive, xres, cs->effective_orientation?1.0/(STANDARD_CRT_ASPECT):STANDARD_CRT_ASPECT, cs->monitor_aspect, &x_diff));
-+ y_scale = max(1, floor(float(yres) / s_mode->vactive));
-+
-+ scan_factor = interlace;
-+ doublescan = 1;
-+ }
-+
-+ x_ratio = float(xres) / s_mode->hactive;
-+ y_ratio = float(yres) / s_mode->vactive;
-+ v_scale = max(round_near(vfreq_real / s_mode->vfreq), 1);
-+ v_diff = (vfreq_real / v_scale) - s_mode->vfreq;
-+ if (fabs(v_diff) > cs->sync_refresh_tolerance)
-+ t_mode->result.weight |= R_V_FREQ_OFF;
-+
-+ // ··· Modeline generation ···
-+ // compute new modeline if we are allowed to
-+ if (cs->modeline_generation && (t_mode->type & V_FREQ_EDITABLE))
-+ {
-+ float margin = 0;
-+ float vblank_lines = 0;
-+ float vvt_ini = 0;
-+
-+ // Get games basic resolution
-+ t_mode->hactive = xres;
-+ t_mode->vactive = yres;
-+ t_mode->vfreq = vfreq_real;
-+
-+ // Get total vertical lines
-+ vvt_ini = total_lines_for_yres(t_mode->vactive, t_mode->vfreq, range, scan_factor) + (interlace == 2?0.5:0);
-+
-+ // Calculate horizontal frequency
-+ t_mode->hfreq = t_mode->vfreq * vvt_ini;
-+
-+ horizontal_values:
-+
-+ // Fill horizontal part of modeline
-+ get_line_params(t_mode, range);
-+
-+ // Calculate pixel clock
-+ t_mode->pclock = t_mode->htotal * t_mode->hfreq;
-+ if (t_mode->pclock <= cs->pclock_min)
-+ {
-+ if (t_mode->type & X_RES_EDITABLE)
-+ {
-+ x_scale *= 2;
-+ t_mode->hactive *= 2;
-+ goto horizontal_values;
-+ }
-+ else
-+ {
-+ t_mode->result.weight |= R_OUT_OF_RANGE;
-+ return -1;
-+ }
-+ }
-+
-+ // Vertical blanking
-+ t_mode->vtotal = vvt_ini * scan_factor;
-+ vblank_lines = int(t_mode->hfreq * range->vertical_blank) + (interlace == 2?0.5:0);
-+ margin = (t_mode->vtotal - t_mode->vactive - vblank_lines * scan_factor) / 2;
-+ t_mode->vbegin = t_mode->vactive + max(round_near(t_mode->hfreq * range->vfront_porch * scan_factor + margin), 1);
-+ t_mode->vend = t_mode->vbegin + max(round_near(t_mode->hfreq * range->vsync_pulse * scan_factor), 1);
-+
-+ // Recalculate final vfreq
-+ t_mode->vfreq = (t_mode->hfreq / t_mode->vtotal) * scan_factor;
-+
-+ t_mode->hsync = range->hsync_polarity;
-+ t_mode->vsync = range->vsync_polarity;
-+ t_mode->interlace = interlace == 2?1:0;
-+ t_mode->doublescan = doublescan == 1?0:1;
-+ }
-+
-+ // finally, store result
-+ t_mode->result.x_scale = x_scale;
-+ t_mode->result.y_scale = y_scale;
-+ t_mode->result.v_scale = v_scale;
-+ t_mode->result.x_diff = x_diff;
-+ t_mode->result.y_diff = y_diff;
-+ t_mode->result.v_diff = v_diff;
-+ t_mode->result.x_ratio = x_ratio;
-+ t_mode->result.y_ratio = y_ratio;
-+ t_mode->result.v_ratio = 0;
-+ t_mode->result.rotated = cs->effective_orientation;
-+
-+ return 0;
-+}
-+
-+//============================================================
-+// get_line_params
-+//============================================================
-+
-+int get_line_params(modeline *mode, monitor_range *range)
-+{
-+ int hhi, hhf, hht;
-+ int hh, hs, he, ht;
-+ float line_time, char_time, new_char_time;
-+ float hfront_porch_min, hsync_pulse_min, hback_porch_min;
-+
-+ hfront_porch_min = range->hfront_porch * .90;
-+ hsync_pulse_min = range->hsync_pulse * .90;
-+ hback_porch_min = range->hback_porch * .90;
-+
-+ line_time = 1 / mode->hfreq * 1000000;
-+
-+ hh = round(mode->hactive / 8);
-+ hs = he = ht = 1;
-+
-+ do {
-+ char_time = line_time / (hh + hs + he + ht);
-+ if (hs * char_time < hfront_porch_min ||
-+ fabs((hs + 1) * char_time - range->hfront_porch) < fabs(hs * char_time - range->hfront_porch))
-+ hs++;
-+
-+ if (he * char_time < hsync_pulse_min ||
-+ fabs((he + 1) * char_time - range->hsync_pulse) < fabs(he * char_time - range->hsync_pulse))
-+ he++;
-+
-+ if (ht * char_time < hback_porch_min ||
-+ fabs((ht + 1) * char_time - range->hback_porch) < fabs(ht * char_time - range->hback_porch))
-+ ht++;
-+
-+ new_char_time = line_time / (hh + hs + he + ht);
-+ } while (new_char_time != char_time);
-+
-+ hhi = (hh + hs) * 8;
-+ hhf = (hh + hs + he) * 8;
-+ hht = (hh + hs + he + ht) * 8;
-+
-+ mode->hbegin = hhi;
-+ mode->hend = hhf;
-+ mode->htotal = hht;
-+
-+ return 0;
-+}
-+
-+//============================================================
-+// scale_into_range
-+//============================================================
-+
-+int scale_into_range (int value, int lower_limit, int higher_limit)
-+{
-+ int scale = 1;
-+ while (value * scale < lower_limit) scale ++;
-+ if (value * scale <= higher_limit)
-+ return scale;
-+ else
-+ return 0;
-+}
-+
-+//============================================================
-+// scale_into_range
-+//============================================================
-+
-+int scale_into_range (float value, float lower_limit, float higher_limit)
-+{
-+ int scale = 1;
-+ while (value * scale < lower_limit) scale ++;
-+ if (value * scale <= higher_limit)
-+ return scale;
-+ else
-+ return 0;
-+}
-+
-+//============================================================
-+// scale_into_aspect
-+//============================================================
-+
-+int scale_into_aspect (int source_res, int tot_res, float original_monitor_aspect, float users_monitor_aspect, float *best_diff)
-+{
-+ int scale = 1, best_scale = 1;
-+ float diff = 0;
-+ *best_diff = 0;
-+
-+ while (source_res * scale <= tot_res)
-+ {
-+ diff = fabs(1.0 - (users_monitor_aspect / (float(tot_res) / float(source_res * scale) * original_monitor_aspect))) * 100.0;
-+ if (diff < *best_diff || *best_diff == 0)
-+ {
-+ *best_diff = diff;
-+ best_scale = scale;
-+ }
-+ scale ++;
-+ }
-+ return best_scale;
-+}
-+
-+//============================================================
-+// stretch_into_range
-+//============================================================
-+
-+int stretch_into_range(float vfreq, monitor_range *range, bool interlace_allowed, float *interlace)
-+{
-+ int yres, lower_limit;
-+
-+ if (range->interlaced_lines_min && interlace_allowed)
-+ {
-+ yres = range->interlaced_lines_max;
-+ lower_limit = range->interlaced_lines_min;
-+ *interlace = 2;
-+ }
-+ else
-+ {
-+ yres = range->progressive_lines_max;
-+ lower_limit = range->progressive_lines_min;
-+ }
-+
-+ while (yres > lower_limit && max_vfreq_for_yres(yres, range, *interlace) < vfreq)
-+ yres -= 8;
-+
-+ return yres;
-+}
-+
-+
-+//============================================================
-+// total_lines_for_yres
-+//============================================================
-+
-+int total_lines_for_yres(int yres, float vfreq, monitor_range *range, float interlace)
-+{
-+ int vvt = max(yres / interlace + round_near(vfreq * yres / (interlace * (1.0 - vfreq * range->vertical_blank)) * range->vertical_blank), 1);
-+ while ((vfreq * vvt < range->hfreq_min) && (vfreq * (vvt + 1) < range->hfreq_max)) vvt++;
-+ return vvt;
-+}
-+
-+//============================================================
-+// max_vfreq_for_yres
-+//============================================================
-+
-+float max_vfreq_for_yres (int yres, monitor_range *range, float interlace)
-+{
-+ return range->hfreq_max / (yres / interlace + round_near(range->hfreq_max * range->vertical_blank));
-+}
-+
-+//============================================================
-+// modeline_print
-+//============================================================
-+
-+char * modeline_print(modeline *mode, char *modeline, int flags)
-+{
-+ char label[48]={'\x00'};
-+ char params[192]={'\x00'};
-+
-+ if (flags & MS_LABEL)
-+ sprintf(label, "\"%dx%d_%d %.6fKHz %.6fHz\"", mode->hactive, mode->vactive, mode->refresh, mode->hfreq/1000, mode->vfreq);
-+
-+ if (flags & MS_LABEL_SDL)
-+ sprintf(label, "\"%dx%d_%.6f\"", mode->hactive, mode->vactive, mode->vfreq);
-+
-+ if (flags & MS_PARAMS)
-+ sprintf(params, " %.6f %d %d %d %d %d %d %d %d %s %s %s %s", float(mode->pclock)/1000000.0, mode->hactive, mode->hbegin, mode->hend, mode->htotal, mode->vactive, mode->vbegin, mode->vend, mode->vtotal,
-+ mode->interlace?"interlace":"", mode->doublescan?"doublescan":"", mode->hsync?"+hsync":"-hsync", mode->vsync?"+vsync":"-vsync");
-+
-+ sprintf(modeline, "%s%s", label, params);
-+
-+ return modeline;
-+}
-+
-+//============================================================
-+// modeline_result
-+//============================================================
-+
-+char * modeline_result(modeline *mode, char *result)
-+{
-+ osd_printf_verbose(" rng(%d): ", mode->range);
-+
-+ if (mode->result.weight & R_OUT_OF_RANGE)
-+ sprintf(result, " out of range");
-+
-+ else
-+ sprintf(result, "%4d x%4d_%3.6f%s%s %3.6f [%s] scale(%d, %d, %d) diff(%.2f, %.2f, %.4f) ratio(%.3f, %.3f)",
-+ mode->hactive, mode->vactive, mode->vfreq, mode->interlace?"i":"p", mode->doublescan?"d":"", mode->hfreq/1000, mode->result.weight & R_RES_STRETCH?"fract":"integ",
-+ mode->result.x_scale, mode->result.y_scale, mode->result.v_scale, mode->result.x_diff, mode->result.y_diff, mode->result.v_diff, mode->result.x_ratio, mode->result.y_ratio);
-+ return result;
-+}
-+
-+//============================================================
-+// modeline_compare
-+//============================================================
-+
-+int modeline_compare(modeline *t, modeline *best)
-+{
-+ bool vector = (t->hactive == (int)t->result.x_ratio);
-+
-+ if (t->result.weight < best->result.weight)
-+ return 1;
-+
-+ else if (t->result.weight <= best->result.weight)
-+ {
-+ float t_v_diff = fabs(t->result.v_diff);
-+ float b_v_diff = fabs(best->result.v_diff);
-+
-+ if (t->result.weight & R_RES_STRETCH || vector)
-+ {
-+ float t_y_score = t->result.y_ratio * (t->interlace?(2.0/3.0):1.0);
-+ float b_y_score = best->result.y_ratio * (best->interlace?(2.0/3.0):1.0);
-+
-+ if ((t_v_diff < b_v_diff) ||
-+ ((t_v_diff == b_v_diff) && (t_y_score > b_y_score)) ||
-+ ((t_v_diff == b_v_diff) && (t_y_score == b_y_score) && (t->result.x_ratio > best->result.x_ratio)))
-+ return 1;
-+ }
-+ else
-+ {
-+ int t_y_score = t->result.y_scale + t->interlace + t->doublescan;
-+ int b_y_score = best->result.y_scale + best->interlace + best->doublescan;
-+ float xy_diff = roundf((t->result.x_diff + t->result.y_diff) * 100) / 100;
-+ float best_xy_diff = roundf((best->result.x_diff + best->result.y_diff) * 100) / 100;
-+
-+ if ((t_y_score < b_y_score) ||
-+ ((t_y_score == b_y_score) && (xy_diff < best_xy_diff)) ||
-+ ((t_y_score == b_y_score) && (xy_diff == best_xy_diff) && (t->result.x_scale < best->result.x_scale)) ||
-+ ((t_y_score == b_y_score) && (xy_diff == best_xy_diff) && (t->result.x_scale == best->result.x_scale) && (t_v_diff < b_v_diff)))
-+ return 1;
-+ }
-+ }
-+ return 0;
-+}
-+
-+//============================================================
-+// modeline_vesa_gtf
-+// Based on the VESA GTF spreadsheet by Andy Morrish 1/5/97
-+//============================================================
-+
-+int modeline_vesa_gtf(modeline *m)
-+{
-+ int C, M;
-+ int v_sync_lines, v_porch_lines_min, v_front_porch_lines, v_back_porch_lines, v_sync_v_back_porch_lines, v_total_lines;
-+ int h_sync_width_percent, h_sync_width_pixels, h_blanking_pixels, h_front_porch_pixels, h_total_pixels;
-+ float v_freq, v_freq_est, v_freq_real, v_sync_v_back_porch;
-+ float h_freq, h_period, h_period_real, h_ideal_blanking;
-+ float pixel_freq, interlace;
-+
-+ // Check if there's a value defined for vfreq. We're assuming input vfreq is the total field vfreq regardless interlace
-+ v_freq = m->vfreq? m->vfreq:float(m->refresh);
-+
-+ // These values are GTF defined defaults
-+ v_sync_lines = 3;
-+ v_porch_lines_min = 1;
-+ v_front_porch_lines = v_porch_lines_min;
-+ v_sync_v_back_porch = 550;
-+ h_sync_width_percent = 8;
-+ M = 128.0 / 256 * 600;
-+ C = ((40 - 20) * 128.0 / 256) + 20;
-+
-+ // GTF calculation
-+ interlace = m->interlace?0.5:0;
-+ h_period = ((1.0 / v_freq) - (v_sync_v_back_porch / 1000000)) / ((float)m->height + v_front_porch_lines + interlace) * 1000000;
-+ v_sync_v_back_porch_lines = round_near(v_sync_v_back_porch / h_period);
-+ v_back_porch_lines = v_sync_v_back_porch_lines - v_sync_lines;
-+ v_total_lines = m->height + v_front_porch_lines + v_sync_lines + v_back_porch_lines;
-+ v_freq_est = (1.0 / h_period) / v_total_lines * 1000000;
-+ h_period_real = h_period / (v_freq / v_freq_est);
-+ v_freq_real = (1.0 / h_period_real) / v_total_lines * 1000000;
-+ h_ideal_blanking = float(C - (M * h_period_real / 1000));
-+ h_blanking_pixels = round_near(m->width * h_ideal_blanking /(100 - h_ideal_blanking) / (2 * 8)) * (2 * 8);
-+ h_total_pixels = m->width + h_blanking_pixels;
-+ pixel_freq = h_total_pixels / h_period_real * 1000000;
-+ h_freq = 1000000 / h_period_real;
-+ h_sync_width_pixels = round_near(h_sync_width_percent * h_total_pixels / 100 / 8) * 8;
-+ h_front_porch_pixels = (h_blanking_pixels / 2) - h_sync_width_pixels;
-+
-+ // Results
-+ m->hactive = m->width;
-+ m->hbegin = m->hactive + h_front_porch_pixels;
-+ m->hend = m->hbegin + h_sync_width_pixels;
-+ m->htotal = h_total_pixels;
-+ m->vactive = m->height;
-+ m->vbegin = m->vactive + v_front_porch_lines;
-+ m->vend = m->vbegin + v_sync_lines;
-+ m->vtotal = v_total_lines;
-+ m->hfreq = h_freq;
-+ m->vfreq = v_freq_real;
-+ m->pclock = pixel_freq;
-+ m->hsync = 0;
-+ m->vsync = 1;
-+
-+ return true;
-+}
-+
-+//============================================================
-+// modeline_parse
-+//============================================================
-+
-+int modeline_parse(const char *user_modeline, modeline *mode)
-+{
-+ char modeline_txt[256]={'\x00'};
-+
-+ if (strcmp(user_modeline, "auto"))
-+ {
-+ // Remove quotes
-+ char *quote_start, *quote_end;
-+ quote_start = strstr((char*)user_modeline, "\"");
-+ if (quote_start)
-+ {
-+ quote_start++;
-+ quote_end = strstr(quote_start, "\"");
-+ if (!quote_end || *quote_end++ == 0)
-+ return false;
-+ user_modeline = quote_end;
-+ }
-+
-+ // Get timing flags
-+ mode->interlace = strstr(user_modeline, "interlace")?1:0;
-+ mode->doublescan = strstr(user_modeline, "doublescan")?1:0;
-+ mode->hsync = strstr(user_modeline, "+hsync")?1:0;
-+ mode->vsync = strstr(user_modeline, "+vsync")?1:0;
-+
-+ // Get timing values
-+ float pclock;
-+ int e = sscanf(user_modeline, " %f %d %d %d %d %d %d %d %d",
-+ &pclock,
-+ &mode->hactive, &mode->hbegin, &mode->hend, &mode->htotal,
-+ &mode->vactive, &mode->vbegin, &mode->vend, &mode->vtotal);
-+
-+ if (e != 9)
-+ {
-+ osd_printf_error("SwitchRes: missing parameter in user modeline\n %s\n", user_modeline);
-+ memset(mode, 0, sizeof(struct modeline));
-+ return false;
-+ }
-+
-+ // Calculate timings
-+ mode->pclock = pclock * 1000000.0;
-+ mode->hfreq = mode->pclock / mode->htotal;
-+ mode->vfreq = mode->hfreq / mode->vtotal * (mode->interlace?2:1);
-+ mode->refresh = mode->vfreq;
-+ osd_printf_verbose("SwitchRes: user modeline %s\n", modeline_print(mode, modeline_txt, MS_FULL));
-+ }
-+ return true;
-+}
-+
-+//============================================================
-+// modeline_to_monitor_range
-+//============================================================
-+
-+int modeline_to_monitor_range(monitor_range *range, modeline *mode)
-+{
-+ if (range->vfreq_min == 0)
-+ {
-+ range->vfreq_min = mode->vfreq - 0.2;
-+ range->vfreq_max = mode->vfreq + 0.2;
-+ }
-+
-+ float line_time = 1 / mode->hfreq;
-+ float pixel_time = line_time / mode->htotal * 1000000;
-+
-+ range->hfront_porch = pixel_time * (mode->hbegin - mode->hactive);
-+ range->hsync_pulse = pixel_time * (mode->hend - mode->hbegin);
-+ range->hback_porch = pixel_time * (mode->htotal - mode->hend);
-+
-+ range->vfront_porch = line_time * (mode->vbegin - mode->vactive);
-+ range->vsync_pulse = line_time * (mode->vend - mode->vbegin);
-+ range->vback_porch = line_time * (mode->vtotal - mode->vend);
-+ range->vertical_blank = range->vfront_porch + range->vsync_pulse + range->vback_porch;
-+
-+ range->hsync_polarity = mode->hsync;
-+ range->vsync_polarity = mode->vsync;
-+
-+ range->progressive_lines_min = mode->interlace?0:mode->vactive;
-+ range->progressive_lines_max = mode->interlace?0:mode->vactive;
-+ range->interlaced_lines_min = mode->interlace?mode->vactive:0;
-+ range->interlaced_lines_max= mode->interlace?mode->vactive:0;
-+
-+ range->hfreq_min = range->vfreq_min * mode->vtotal;
-+ range->hfreq_max = range->vfreq_max * mode->vtotal;
-+
-+ return 1;
-+}
-+
-+//============================================================
-+// round_near
-+//============================================================
-+
-+int round_near(double number)
-+{
-+ return number < 0.0 ? ceil(number - 0.5) : floor(number + 0.5);
-+}
-diff --git a/src/emu/switchres/modeline.h b/src/emu/switchres/modeline.h
-new file mode 100644
-index 00000000000..ef59b98cd4a
---- /dev/null
-+++ b/src/emu/switchres/modeline.h
-@@ -0,0 +1,118 @@
-+/**************************************************************
-+
-+ modeline.h - Modeline generation header
-+
-+ ---------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2016 - Chris Kennedy, Antonio Giner
-+
-+ **************************************************************/
-+
-+#ifndef __MODELINE_H__
-+#define __MODELINE_H__
-+
-+#include "monitor.h"
-+
-+//============================================================
-+// CONSTANTS
-+//============================================================
-+
-+// Modeline print flags
-+#define MS_LABEL 0x00000001
-+#define MS_LABEL_SDL 0x00000002
-+#define MS_PARAMS 0x00000004
-+#define MS_FULL MS_LABEL | MS_PARAMS
-+
-+// Modeline result
-+#define R_V_FREQ_OFF 0x00000001
-+#define R_RES_STRETCH 0x00000002
-+#define R_OUT_OF_RANGE 0x00000004
-+
-+// Modeline commands
-+#define MODELINE_DELETE 0x001
-+#define MODELINE_CREATE 0x002
-+#define MODELINE_UPDATE 0x004
-+#define MODELINE_UPDATE_LIST 0x008
-+
-+// Mode types
-+#define MODE_OK 0x00000000
-+#define MODE_DESKTOP 0x10000000
-+#define MODE_ROTATED 0x20000000
-+#define MODE_DISABLED 0x40000000
-+#define MODE_USER_DEF 0x80000000
-+#define V_FREQ_EDITABLE 0x00000001
-+#define X_RES_EDITABLE 0x00000002
-+#define Y_RES_EDITABLE 0x00000004
-+#define XYV_EDITABLE (X_RES_EDITABLE | Y_RES_EDITABLE | V_FREQ_EDITABLE )
-+
-+#define DUMMY_WIDTH 1234
-+#define MAX_MODELINES 256
-+
-+//============================================================
-+// TYPE DEFINITIONS
-+//============================================================
-+
-+typedef struct mode_result
-+{
-+ int weight;
-+ int x_scale;
-+ int y_scale;
-+ int v_scale;
-+ float x_diff;
-+ float y_diff;
-+ float v_diff;
-+ float x_ratio;
-+ float y_ratio;
-+ float v_ratio;
-+ bool rotated;
-+} mode_result;
-+
-+typedef struct modeline
-+{
-+ uint64_t pclock;
-+ int hactive;
-+ int hbegin;
-+ int hend;
-+ int htotal;
-+ int vactive;
-+ int vbegin;
-+ int vend;
-+ int vtotal;
-+ int interlace;
-+ int doublescan;
-+ int hsync;
-+ int vsync;
-+ //
-+ double vfreq;
-+ double hfreq;
-+ //
-+ int width;
-+ int height;
-+ int refresh;
-+ int refresh_label;
-+ //
-+ int type;
-+ int range;
-+ //
-+ mode_result result;
-+} modeline;
-+
-+//============================================================
-+// PROTOTYPES
-+//============================================================
-+
-+int modeline_create(modeline *s_mode, modeline *t_mode, monitor_range *range, config_settings *cs);
-+int modeline_compare(modeline *t_mode, modeline *best_mode);
-+char * modeline_print(modeline *mode, char *modeline, int flags);
-+char * modeline_result(modeline *mode, char *result);
-+int modeline_vesa_gtf(modeline *m);
-+int modeline_parse(const char *user_modeline, modeline *mode);
-+int modeline_to_monitor_range(monitor_range *range, modeline *mode);
-+
-+#endif
-diff --git a/src/emu/switchres/monitor.cpp b/src/emu/switchres/monitor.cpp
-new file mode 100644
-index 00000000000..4a83d1802eb
---- /dev/null
-+++ b/src/emu/switchres/monitor.cpp
-@@ -0,0 +1,481 @@
-+/**************************************************************
-+
-+ monitor.cpp - Monitor presets and custom monitor definition
-+
-+ ---------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2016 - Chris Kennedy, Antonio Giner
-+
-+ **************************************************************/
-+
-+#include "emu.h"
-+
-+//============================================================
-+// CONSTANTS
-+//============================================================
-+
-+#define HFREQ_MIN 14000
-+#define HFREQ_MAX 540672 // 8192 * 1.1 * 60
-+#define VFREQ_MIN 40
-+#define VFREQ_MAX 200
-+#define PROGRESSIVE_LINES_MIN 128
-+
-+//============================================================
-+// monitor_fill_range
-+//============================================================
-+
-+int monitor_fill_range(monitor_range *range, const char *specs_line)
-+{
-+ monitor_range new_range;
-+
-+ if (strcmp(specs_line, "auto")) {
-+ int e = sscanf(specs_line, "%lf-%lf,%lf-%lf,%lf,%lf,%lf,%lf,%lf,%lf,%d,%d,%d,%d,%d,%d",
-+ &new_range.hfreq_min, &new_range.hfreq_max,
-+ &new_range.vfreq_min, &new_range.vfreq_max,
-+ &new_range.hfront_porch, &new_range.hsync_pulse, &new_range.hback_porch,
-+ &new_range.vfront_porch, &new_range.vsync_pulse, &new_range.vback_porch,
-+ &new_range.hsync_polarity, &new_range.vsync_polarity,
-+ &new_range.progressive_lines_min, &new_range.progressive_lines_max,
-+ &new_range.interlaced_lines_min, &new_range.interlaced_lines_max);
-+
-+ if (e != 16) {
-+ osd_printf_error("SwitchRes: Error trying to fill monitor range with\n %s\n", specs_line);
-+ return -1;
-+ }
-+
-+ new_range.vfront_porch /= 1000;
-+ new_range.vsync_pulse /= 1000;
-+ new_range.vback_porch /= 1000;
-+ new_range.vertical_blank = (new_range.vfront_porch + new_range.vsync_pulse + new_range.vback_porch);
-+
-+ if (monitor_evaluate_range(&new_range))
-+ {
-+ osd_printf_error("SwitchRes: Error in monitor range (ignoring): %s\n", specs_line);
-+ return -1;
-+ }
-+ else
-+ {
-+ memcpy(range, &new_range, sizeof(struct monitor_range));
-+ monitor_show_range(range);
-+ }
-+ }
-+ return 0;
-+}
-+
-+//============================================================
-+// monitor_fill_lcd_range
-+//============================================================
-+
-+int monitor_fill_lcd_range(monitor_range *range, const char *specs_line)
-+{
-+ if (strcmp(specs_line, "auto"))
-+ {
-+ if (sscanf(specs_line, "%lf-%lf", &range->vfreq_min, &range->vfreq_max) == 2)
-+ {
-+ osd_printf_verbose("SwitchRes: LCD vfreq range set by user as %f-%f\n", range->vfreq_min, range->vfreq_max);
-+ return true;
-+ }
-+ else
-+ osd_printf_error("SwitchRes: Error trying to fill LCD range with\n %s\n", specs_line);
-+ }
-+ // Use default values
-+ range->vfreq_min = 59;
-+ range->vfreq_max = 61;
-+ osd_printf_verbose("SwitchRes: Using default vfreq range for LCD %f-%f\n", range->vfreq_min, range->vfreq_max);
-+
-+ return 0;
-+}
-+
-+//============================================================
-+// monitor_fill_vesa_gtf
-+//============================================================
-+
-+int monitor_fill_vesa_gtf(monitor_range *range, const char *max_lines)
-+{
-+ int lines = 0;
-+ sscanf(max_lines, "vesa_%d", &lines);
-+
-+ if (!lines)
-+ return 0;
-+
-+ int i = 0;
-+ if (lines >= 480)
-+ i += monitor_fill_vesa_range(&range[i], 384, 480);
-+ if (lines >= 600)
-+ i += monitor_fill_vesa_range(&range[i], 480, 600);
-+ if (lines >= 768)
-+ i += monitor_fill_vesa_range(&range[i], 600, 768);
-+ if (lines >= 1024)
-+ i += monitor_fill_vesa_range(&range[i], 768, 1024);
-+
-+ return i;
-+}
-+
-+//============================================================
-+// monitor_fill_vesa_range
-+//============================================================
-+
-+int monitor_fill_vesa_range(monitor_range *range, int lines_min, int lines_max)
-+{
-+ modeline mode;
-+ memset(&mode, 0, sizeof(modeline));
-+
-+ mode.width = real_res(STANDARD_CRT_ASPECT * lines_max);
-+ mode.height = lines_max;
-+ mode.refresh = 60;
-+ range->vfreq_min = 50;
-+ range->vfreq_max = 65;
-+
-+ modeline_vesa_gtf(&mode);
-+ modeline_to_monitor_range(range, &mode);
-+
-+ range->progressive_lines_min = lines_min;
-+ range->hfreq_min = mode.hfreq - 500;
-+ range->hfreq_max = mode.hfreq + 500;
-+ monitor_show_range(range);
-+
-+ return 1;
-+}
-+
-+//============================================================
-+// monitor_show_range
-+//============================================================
-+
-+int monitor_show_range(monitor_range *range)
-+{
-+ osd_printf_verbose("SwitchRes: Monitor range %.2f-%.2f,%.2f-%.2f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%d,%d,%d,%d,%d,%d\n",
-+ range->hfreq_min, range->hfreq_max,
-+ range->vfreq_min, range->vfreq_max,
-+ range->hfront_porch, range->hsync_pulse, range->hback_porch,
-+ range->vfront_porch * 1000, range->vsync_pulse * 1000, range->vback_porch * 1000,
-+ range->hsync_polarity, range->vsync_polarity,
-+ range->progressive_lines_min, range->progressive_lines_max,
-+ range->interlaced_lines_min, range->interlaced_lines_max);
-+
-+ return 0;
-+}
-+
-+//============================================================
-+// monitor_set_preset
-+//============================================================
-+
-+int monitor_set_preset(char *type, monitor_range *range)
-+{
-+ // PAL TV - 50 Hz/625
-+ if (!strcmp(type, "pal"))
-+ {
-+ monitor_fill_range(&range[0], "15625.00-15625.00, 50.00-50.00, 1.500, 4.700, 5.800, 0.064, 0.160, 1.056, 0, 0, 192, 288, 448, 576");
-+ return 1;
-+ }
-+ // NTSC TV - 60 Hz/525
-+ else if (!strcmp(type, "ntsc"))
-+ {
-+ monitor_fill_range(&range[0], "15734.26-15734.26, 59.94-59.94, 1.500, 4.700, 4.700, 0.191, 0.191, 0.953, 0, 0, 192, 240, 448, 480");
-+ return 1;
-+ }
-+ // Generic 15.7 kHz
-+ else if (!strcmp(type, "generic_15"))
-+ {
-+ monitor_fill_range(&range[0], "15625-15750, 49.50-65.00, 2.000, 4.700, 8.000, 0.064, 0.192, 1.024, 0, 0, 192, 288, 448, 576");
-+ return 1;
-+ }
-+ // Arcade 15.7 kHz - standard resolution
-+ else if (!strcmp(type, "arcade_15"))
-+ {
-+ monitor_fill_range(&range[0], "15625-16200, 49.50-65.00, 2.000, 4.700, 8.000, 0.064, 0.192, 1.024, 0, 0, 192, 288, 448, 576");
-+ return 1;
-+ }
-+ // Arcade 15.7-16.5 kHz - extended resolution
-+ else if (!strcmp(type, "arcade_15ex"))
-+ {
-+ monitor_fill_range(&range[0], "15625-16500, 49.50-65.00, 2.000, 4.700, 8.000, 0.064, 0.192, 1.024, 0, 0, 192, 288, 448, 576");
-+ return 1;
-+ }
-+ // Arcade 25.0 kHz - medium resolution
-+ else if (!strcmp(type, "arcade_25"))
-+ {
-+ monitor_fill_range(&range[0], "24960-24960, 49.50-65.00, 0.800, 4.000, 3.200, 0.080, 0.200, 1.000, 0, 0, 384, 400, 768, 800");
-+ return 1;
-+ }
-+ // Arcade 31.5 kHz - medium resolution
-+ else if (!strcmp(type, "arcade_31"))
-+ {
-+ monitor_fill_range(&range[0], "31400-31500, 49.50-65.00, 0.940, 3.770, 1.890, 0.349, 0.064, 1.017, 0, 0, 400, 512, 0, 0");
-+ return 1;
-+ }
-+ // Arcade 15.7/25.0 kHz - dual-sync
-+ else if (!strcmp(type, "arcade_15_25"))
-+ {
-+ monitor_fill_range(&range[0], "15625-16200, 49.50-65.00, 2.000, 4.700, 8.000, 0.064, 0.192, 1.024, 0, 0, 192, 288, 448, 576");
-+ monitor_fill_range(&range[1], "24960-24960, 49.50-65.00, 0.800, 4.000, 3.200, 0.080, 0.200, 1.000, 0, 0, 384, 400, 768, 800");
-+ return 2;
-+ }
-+ // Arcade 15.7/31.5 kHz - dual-sync
-+ else if (!strcmp(type, "arcade_15_31"))
-+ {
-+ monitor_fill_range(&range[0], "15625-16200, 49.50-65.00, 2.000, 4.700, 8.000, 0.064, 0.192, 1.024, 0, 0, 192, 288, 448, 576");
-+ monitor_fill_range(&range[1], "31400-31500, 49.50-65.00, 0.940, 3.770, 1.890, 0.349, 0.064, 1.017, 0, 0, 400, 512, 0, 0");
-+ return 2;
-+ }
-+ // Arcade 15.7/25.0/31.5 kHz - tri-sync
-+ else if (!strcmp(type, "arcade_15_25_31"))
-+ {
-+ monitor_fill_range(&range[0], "15625-16200, 49.50-65.00, 2.000, 4.700, 8.000, 0.064, 0.192, 1.024, 0, 0, 192, 288, 448, 576");
-+ monitor_fill_range(&range[1], "24960-24960, 49.50-65.00, 0.800, 4.000, 3.200, 0.080, 0.200, 1.000, 0, 0, 384, 400, 768, 800");
-+ monitor_fill_range(&range[2], "31400-31500, 49.50-65.00, 0.940, 3.770, 1.890, 0.349, 0.064, 1.017, 0, 0, 400, 512, 0, 0");
-+ return 3;
-+ }
-+ // Makvision 2929D
-+ else if (!strcmp(type, "m2929"))
-+ {
-+ monitor_fill_range(&range[0], "30000-40000, 47.00-90.00, 0.600, 2.500, 2.800, 0.032, 0.096, 0.448, 0, 0, 384, 640, 0, 0");
-+ return 1;
-+ }
-+ // Wells Gardner D9800, D9400
-+ else if (!strcmp(type, "d9800") || !strcmp(type, "d9400"))
-+ {
-+ monitor_fill_range(&range[0], "15250-18000, 40-80, 2.187, 4.688, 6.719, 0.190, 0.191, 1.018, 0, 0, 224, 288, 448, 576");
-+ monitor_fill_range(&range[1], "18001-19000, 40-80, 2.187, 4.688, 6.719, 0.140, 0.191, 0.950, 0, 0, 288, 320, 0, 0");
-+ monitor_fill_range(&range[2], "20501-29000, 40-80, 2.910, 3.000, 4.440, 0.451, 0.164, 1.048, 0, 0, 320, 384, 0, 0");
-+ monitor_fill_range(&range[3], "29001-32000, 40-80, 0.636, 3.813, 1.906, 0.318, 0.064, 1.048, 0, 0, 384, 480, 0, 0");
-+ monitor_fill_range(&range[4], "32001-34000, 40-80, 0.636, 3.813, 1.906, 0.020, 0.106, 0.607, 0, 0, 480, 576, 0, 0");
-+ monitor_fill_range(&range[5], "34001-38000, 40-80, 1.000, 3.200, 2.200, 0.020, 0.106, 0.607, 0, 0, 576, 600, 0, 0");
-+ return 6;
-+ }
-+ // Wells Gardner D9200
-+ else if (!strcmp(type, "d9200"))
-+ {
-+ monitor_fill_range(&range[0], "15250-16500, 40-80, 2.187, 4.688, 6.719, 0.190, 0.191, 1.018, 0, 0, 224, 288, 448, 576");
-+ monitor_fill_range(&range[1], "23900-24420, 40-80, 2.910, 3.000, 4.440, 0.451, 0.164, 1.148, 0, 0, 384, 400, 0, 0");
-+ monitor_fill_range(&range[2], "31000-32000, 40-80, 0.636, 3.813, 1.906, 0.318, 0.064, 1.048, 0, 0, 400, 512, 0, 0");
-+ monitor_fill_range(&range[3], "37000-38000, 40-80, 1.000, 3.200, 2.200, 0.020, 0.106, 0.607, 0, 0, 512, 600, 0, 0");
-+ return 4;
-+ }
-+ // Wells Gardner K7000
-+ else if (!strcmp(type, "k7000"))
-+ {
-+ monitor_fill_range(&range[0], "15625-15800, 49.50-63.00, 2.000, 4.700, 8.000, 0.064, 0.160, 1.056, 0, 0, 192, 288, 448, 576");
-+ return 1;
-+ }
-+ // Wells Gardner 25K7131
-+ else if (!strcmp(type, "k7131"))
-+ {
-+ monitor_fill_range(&range[0], "15625-16670, 49.5-65, 2.000, 4.700, 8.000, 0.064, 0.160, 1.056, 0, 0, 192, 288, 448, 576");
-+ return 1;
-+ }
-+ // Wei-Ya M3129
-+ else if (!strcmp(type, "m3129"))
-+ {
-+ monitor_fill_range(&range[0], "15250-16500, 40-80, 2.187, 4.688, 6.719, 0.190, 0.191, 1.018, 1, 1, 192, 288, 448, 576");
-+ monitor_fill_range(&range[1], "23900-24420, 40-80, 2.910, 3.000, 4.440, 0.451, 0.164, 1.048, 1, 1, 384, 400, 0, 0");
-+ monitor_fill_range(&range[2], "31000-32000, 40-80, 0.636, 3.813, 1.906, 0.318, 0.064, 1.048, 1, 1, 400, 512, 0, 0");
-+ return 3;
-+ }
-+ // Hantarex MTC 9110
-+ else if (!strcmp(type, "h9110") || !strcmp(type, "polo"))
-+ {
-+ monitor_fill_range(&range[0], "15625-16670, 49.5-65, 2.000, 4.700, 8.000, 0.064, 0.160, 1.056, 0, 0, 192, 288, 448, 576");
-+ return 1;
-+ }
-+ // Hantarex Polostar 25
-+ else if (!strcmp(type, "pstar"))
-+ {
-+ monitor_fill_range(&range[0], "15700-15800, 50-65, 1.800, 0.400, 7.400, 0.064, 0.160, 1.056, 0, 0, 192, 256, 0, 0");
-+ monitor_fill_range(&range[1], "16200-16300, 50-65, 0.200, 0.400, 8.000, 0.040, 0.040, 0.640, 0, 0, 256, 264, 512, 528");
-+ monitor_fill_range(&range[2], "25300-25400, 50-65, 0.200, 0.400, 8.000, 0.040, 0.040, 0.640, 0, 0, 384, 400, 768, 800");
-+ monitor_fill_range(&range[3], "31500-31600, 50-65, 0.170, 0.350, 5.500, 0.040, 0.040, 0.640, 0, 0, 400, 512, 0, 0");
-+ return 4;
-+ }
-+ // Nanao MS-2930, MS-2931
-+ else if (!strcmp(type, "ms2930"))
-+ {
-+ monitor_fill_range(&range[0], "15450-16050, 50-65, 3.190, 4.750, 6.450, 0.191, 0.191, 1.164, 0, 0, 192, 288, 448, 576");
-+ monitor_fill_range(&range[1], "23900-24900, 50-65, 2.870, 3.000, 4.440, 0.451, 0.164, 1.148, 0, 0, 384, 400, 0, 0");
-+ monitor_fill_range(&range[2], "31000-32000, 50-65, 0.330, 3.580, 1.750, 0.316, 0.063, 1.137, 0, 0, 480, 512, 0, 0");
-+ return 3;
-+ }
-+ // Nanao MS9-29
-+ else if (!strcmp(type, "ms929"))
-+ {
-+ monitor_fill_range(&range[0], "15450-16050, 50-65, 3.910, 4.700, 6.850, 0.190, 0.191, 1.018, 0, 0, 192, 288, 448, 576");
-+ monitor_fill_range(&range[1], "23900-24900, 50-65, 2.910, 3.000, 4.440, 0.451, 0.164, 1.048, 0, 0, 384, 400, 0, 0");
-+ return 2;
-+ }
-+ // Rodotron 666B-29
-+ else if (!strcmp(type, "r666b"))
-+ {
-+ monitor_fill_range(&range[0], "15450-16050, 50-65, 3.190, 4.750, 6.450, 0.191, 0.191, 1.164, 0, 0, 192, 288, 448, 576");
-+ monitor_fill_range(&range[1], "23900-24900, 50-65, 2.870, 3.000, 4.440, 0.451, 0.164, 1.148, 0, 0, 384, 400, 0, 0");
-+ monitor_fill_range(&range[2], "31000-32500, 50-65, 0.330, 3.580, 1.750, 0.316, 0.063, 1.137, 0, 0, 400, 512, 0, 0");
-+ return 3;
-+ }
-+ // PC CRT 70kHz/120Hz
-+ else if (!strcmp(type, "pc_31_120"))
-+ {
-+ monitor_fill_range(&range[0], "31400-31600, 100-130, 0.671, 2.683, 3.353, 0.034, 0.101, 0.436, 0, 0, 200, 256, 0, 0");
-+ monitor_fill_range(&range[1], "31400-31600, 50-65, 0.671, 2.683, 3.353, 0.034, 0.101, 0.436, 0, 0, 400, 512, 0, 0");
-+ return 2;
-+ }
-+ // PC CRT 70kHz/120Hz
-+ else if (!strcmp(type, "pc_70_120"))
-+ {
-+ monitor_fill_range(&range[0], "30000-70000, 100-130, 2.201, 0.275, 4.678, 0.063, 0.032, 0.633, 0, 0, 192, 320, 0, 0");
-+ monitor_fill_range(&range[1], "30000-70000, 50-65, 2.201, 0.275, 4.678, 0.063, 0.032, 0.633, 0, 0, 400, 1024, 0, 0");
-+ return 2;
-+ }
-+ // VESA GTF
-+ else if (!strcmp(type, "vesa_480") || !strcmp(type, "vesa_600") || !strcmp(type, "vesa_768") || !strcmp(type, "vesa_1024"))
-+ {
-+ return monitor_fill_vesa_gtf(&range[0], type);
-+ }
-+
-+ osd_printf_error("SwitchRes: Monitor type unknown: %s\n", type);
-+ return 0;
-+}
-+
-+//============================================================
-+// monitor_evaluate_range
-+//============================================================
-+
-+int monitor_evaluate_range(monitor_range *range)
-+{
-+ // First we check that all frequency ranges are reasonable
-+ if (range->hfreq_min < HFREQ_MIN || range->hfreq_min > HFREQ_MAX)
-+ {
-+ osd_printf_error("SwitchRes: hfreq_min %.2f out of range\n", range->hfreq_min);
-+ return 1;
-+ }
-+ if (range->hfreq_max < HFREQ_MIN || range->hfreq_max < range->hfreq_min || range->hfreq_max > HFREQ_MAX)
-+ {
-+ osd_printf_error("SwitchRes: hfreq_max %.2f out of range\n", range->hfreq_max);
-+ return 1;
-+ }
-+ if (range->vfreq_min < VFREQ_MIN || range->vfreq_min > VFREQ_MAX)
-+ {
-+ osd_printf_error("SwitchRes: vfreq_min %.2f out of range\n", range->vfreq_min);
-+ return 1;
-+ }
-+ if (range->vfreq_max < VFREQ_MIN || range->vfreq_max < range->vfreq_min || range->vfreq_max > VFREQ_MAX)
-+ {
-+ osd_printf_error("SwitchRes: vfreq_max %.2f out of range\n", range->vfreq_max);
-+ return 1;
-+ }
-+
-+ // line_time in µs. We check that no horizontal value is longer than a whole line
-+ double line_time = 1 / range->hfreq_max * 1000000;
-+
-+ if (range->hfront_porch <= 0 || range->hfront_porch > line_time)
-+ {
-+ osd_printf_error("SwitchRes: hfront_porch %.3f out of range\n", range->hfront_porch);
-+ return 1;
-+ }
-+ if (range->hsync_pulse <= 0 || range->hsync_pulse > line_time)
-+ {
-+ osd_printf_error("SwitchRes: hsync_pulse %.3f out of range\n", range->hsync_pulse);
-+ return 1;
-+ }
-+ if (range->hback_porch <= 0 || range->hback_porch > line_time)
-+ {
-+ osd_printf_error("SwitchRes: hback_porch %.3f out of range\n", range->hback_porch);
-+ return 1;
-+ }
-+
-+ // frame_time in ms. We check that no vertical value is longer than a whole frame
-+ double frame_time = 1 / range->vfreq_max * 1000;
-+
-+ if (range->vfront_porch <= 0 || range->vfront_porch > frame_time)
-+ {
-+ osd_printf_error("SwitchRes: vfront_porch %.3f out of range\n", range->vfront_porch);
-+ return 1;
-+ }
-+ if (range->vsync_pulse <= 0 || range->vsync_pulse > frame_time)
-+ {
-+ osd_printf_error("SwitchRes: vsync_pulse %.3f out of range\n", range->vsync_pulse);
-+ return 1;
-+ }
-+ if (range->vback_porch <= 0 || range->vback_porch > frame_time)
-+ {
-+ osd_printf_error("SwitchRes: vback_porch %.3f out of range\n", range->vback_porch);
-+ return 1;
-+ }
-+
-+ // Now we check sync polarities
-+ if (range->hsync_polarity != 0 && range->hsync_polarity != 1)
-+ {
-+ osd_printf_error("SwitchRes: Hsync polarity can be only 0 or 1\n");
-+ return 1;
-+ }
-+ if (range->vsync_polarity != 0 && range->vsync_polarity != 1)
-+ {
-+ osd_printf_error("SwitchRes: Vsync polarity can be only 0 or 1\n");
-+ return 1;
-+ }
-+
-+ // Finally we check that the line limiters are reasonable
-+ // Progressive range:
-+ if (range->progressive_lines_min > 0 && range->progressive_lines_min < PROGRESSIVE_LINES_MIN)
-+ {
-+ osd_printf_error("SwitchRes: progressive_lines_min must be greater than %d\n", PROGRESSIVE_LINES_MIN);
-+ return 1;
-+ }
-+ if ((range->progressive_lines_min + range->hfreq_max * range->vertical_blank) * range->vfreq_min > range->hfreq_max)
-+ {
-+ osd_printf_error("SwitchRes: progressive_lines_min %d out of range\n", range->progressive_lines_min);
-+ return 1;
-+ }
-+ if (range->progressive_lines_max < range->progressive_lines_min)
-+ {
-+ osd_printf_error("SwitchRes: progressive_lines_max must greater than progressive_lines_min\n");
-+ return 1;
-+ }
-+ if ((range->progressive_lines_max + range->hfreq_max * range->vertical_blank) * range->vfreq_min > range->hfreq_max)
-+ {
-+ osd_printf_error("SwitchRes: progressive_lines_max %d out of range\n", range->progressive_lines_max);
-+ return 1;
-+ }
-+
-+ // Interlaced range:
-+ if (range->interlaced_lines_min != 0)
-+ {
-+ if (range->interlaced_lines_min < range->progressive_lines_max)
-+ {
-+ osd_printf_error("SwitchRes: interlaced_lines_min must greater than progressive_lines_max\n");
-+ return 1;
-+ }
-+ if (range->interlaced_lines_min < PROGRESSIVE_LINES_MIN * 2)
-+ {
-+ osd_printf_error("SwitchRes: interlaced_lines_min must be greater than %d\n", PROGRESSIVE_LINES_MIN * 2);
-+ return 1;
-+ }
-+ if ((range->interlaced_lines_min / 2 + range->hfreq_max * range->vertical_blank) * range->vfreq_min > range->hfreq_max)
-+ {
-+ osd_printf_error("SwitchRes: interlaced_lines_min %d out of range\n", range->interlaced_lines_min);
-+ return 1;
-+ }
-+ if (range->interlaced_lines_max < range->interlaced_lines_min)
-+ {
-+ osd_printf_error("SwitchRes: interlaced_lines_max must greater than interlaced_lines_min\n");
-+ return 1;
-+ }
-+ if ((range->interlaced_lines_max / 2 + range->hfreq_max * range->vertical_blank) * range->vfreq_min > range->hfreq_max)
-+ {
-+ osd_printf_error("SwitchRes: interlaced_lines_max %d out of range\n", range->interlaced_lines_max);
-+ return 1;
-+ }
-+ }
-+ else
-+ {
-+ if (range->interlaced_lines_max != 0)
-+ {
-+ osd_printf_error("SwitchRes: interlaced_lines_max must be zero if interlaced_lines_min is not defined\n");
-+ return 1;
-+ }
-+ }
-+ return 0;
-+}
-diff --git a/src/emu/switchres/monitor.h b/src/emu/switchres/monitor.h
-new file mode 100644
-index 00000000000..49aecf20b3d
---- /dev/null
-+++ b/src/emu/switchres/monitor.h
-@@ -0,0 +1,66 @@
-+/**************************************************************
-+
-+ monitor.h - Monitor presets header
-+
-+ ---------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2016 - Chris Kennedy, Antonio Giner
-+
-+ **************************************************************/
-+
-+#ifndef __MONITOR_H__
-+#define __MONITOR_H__
-+
-+//============================================================
-+// CONSTANTS
-+//============================================================
-+
-+#define MAX_RANGES 10
-+#define MONITOR_CRT 0
-+#define MONITOR_LCD 1
-+#define STANDARD_CRT_ASPECT 4.0/3.0
-+
-+//============================================================
-+// TYPE DEFINITIONS
-+//============================================================
-+
-+typedef struct monitor_range
-+{
-+ double hfreq_min;
-+ double hfreq_max;
-+ double vfreq_min;
-+ double vfreq_max;
-+ double hfront_porch;
-+ double hsync_pulse;
-+ double hback_porch;
-+ double vfront_porch;
-+ double vsync_pulse;
-+ double vback_porch;
-+ int hsync_polarity;
-+ int vsync_polarity;
-+ int progressive_lines_min;
-+ int progressive_lines_max;
-+ int interlaced_lines_min;
-+ int interlaced_lines_max;
-+ double vertical_blank;
-+} monitor_range;
-+
-+//============================================================
-+// PROTOTYPES
-+//============================================================
-+
-+int monitor_fill_range(monitor_range *range, const char *specs_line);
-+int monitor_show_range(monitor_range *range);
-+int monitor_set_preset(char *type, monitor_range *range);
-+int monitor_fill_lcd_range(monitor_range *range, const char *specs_line);
-+int monitor_fill_vesa_gtf(monitor_range *range, const char *max_lines);
-+int monitor_fill_vesa_range(monitor_range *range, int lines_min, int lines_max);
-+int monitor_evaluate_range(monitor_range *range);
-+
-+#endif
-diff --git a/src/emu/switchres/switchres.cpp b/src/emu/switchres/switchres.cpp
-new file mode 100644
-index 00000000000..6b406a33651
---- /dev/null
-+++ b/src/emu/switchres/switchres.cpp
-@@ -0,0 +1,386 @@
-+/**************************************************************
-+
-+ switchres.cpp - SwichRes core routines
-+
-+ ---------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2016 - Chris Kennedy, Antonio Giner
-+
-+ **************************************************************/
-+
-+#include "emu.h"
-+#include "emuopts.h"
-+#include "../frontend/mame/mameopts.h"
-+#include "config.h"
-+#include "rendutil.h"
-+
-+#define CUSTOM_VIDEO_TIMING_SYSTEM 0x00000010
-+
-+//============================================================
-+// PROTOTYPES
-+//============================================================
-+
-+void set_option(running_machine &machine, const char *option_ID, bool state);
-+
-+//============================================================
-+// switchres_get_video_mode
-+//============================================================
-+
-+bool switchres_get_video_mode(running_machine &machine)
-+{
-+ switchres_manager *switchres = &machine.switchres;
-+ config_settings *cs = &switchres->cs;
-+ game_info *game = &switchres->game;
-+ monitor_range *range = switchres->range;
-+ modeline *mode;
-+ modeline *mode_table = switchres->video_modes;
-+ modeline *best_mode = &switchres->best_mode;
-+ modeline *user_mode = &switchres->user_mode;
-+ modeline source_mode, *s_mode = &source_mode;
-+ modeline target_mode, *t_mode = &target_mode;
-+ char modeline[256]={'\x00'};
-+ char result[256]={'\x00'};
-+ int i = 0, j = 0, table_size = 0;
-+
-+ cs->effective_orientation = effective_orientation(machine);
-+
-+ osd_printf_verbose("SwitchRes: v%s:[%s] Calculating best video mode for %dx%d@%.6f orientation: %s\n",
-+ SWITCHRES_VERSION, game->name, game->width, game->height, game->refresh,
-+ cs->effective_orientation?"rotated":"normal");
-+
-+ memset(best_mode, 0, sizeof(struct modeline));
-+ best_mode->result.weight |= R_OUT_OF_RANGE;
-+ s_mode->hactive = game->vector?1:normalize(game->width, 8);
-+ s_mode->vactive = game->vector?1:game->height;
-+ s_mode->vfreq = game->refresh;
-+
-+ if (user_mode->hactive)
-+ {
-+ table_size = 1;
-+ mode = user_mode;
-+ }
-+ else
-+ {
-+ i = 1;
-+ table_size = MAX_MODELINES;
-+ mode = &mode_table[i];
-+ }
-+
-+ while (mode->width && i < table_size)
-+ {
-+ // apply options to mode type
-+ if (!cs->modeline_generation)
-+ mode->type &= ~XYV_EDITABLE;
-+
-+ if (cs->refresh_dont_care)
-+ mode->type |= V_FREQ_EDITABLE;
-+
-+ if (cs->lock_system_modes && (mode->type & CUSTOM_VIDEO_TIMING_SYSTEM) && !(mode->type & MODE_DESKTOP) && !(mode->type & MODE_USER_DEF))
-+ mode->type |= MODE_DISABLED;
-+
-+ osd_printf_verbose("\nSwitchRes: %s%4d%sx%s%4d%s_%s%d=%.6fHz%s%s\n",
-+ mode->type & X_RES_EDITABLE?"(":"[", mode->width, mode->type & X_RES_EDITABLE?")":"]",
-+ mode->type & Y_RES_EDITABLE?"(":"[", mode->height, mode->type & Y_RES_EDITABLE?")":"]",
-+ mode->type & V_FREQ_EDITABLE?"(":"[", mode->refresh, mode->vfreq, mode->type & V_FREQ_EDITABLE?")":"]",
-+ mode->type & MODE_DISABLED?" - locked":"");
-+
-+ // now get the mode if allowed
-+ if (!(mode->type & MODE_DISABLED))
-+ {
-+ for (j = 0 ; j < MAX_RANGES ; j++)
-+ {
-+ if (range[j].hfreq_min)
-+ {
-+ memcpy(t_mode, mode, sizeof(struct modeline));
-+ modeline_create(s_mode, t_mode, &range[j], cs);
-+ t_mode->range = j;
-+
-+ osd_printf_verbose("%s\n", modeline_result(t_mode, result));
-+
-+ if (modeline_compare(t_mode, best_mode))
-+ memcpy(best_mode, t_mode, sizeof(struct modeline));
-+ }
-+ }
-+ }
-+ mode++;
-+ i++;
-+ }
-+
-+ if (best_mode->result.weight & R_OUT_OF_RANGE)
-+ {
-+ osd_printf_error("SwitchRes: could not find a video mode that meets your specs\n");
-+ return false;
-+ }
-+
-+ osd_printf_info("\nSwitchRes: [%s] (%d) %s (%dx%d@%.6f)->(%dx%d@%.6f)\n", game->name, game->screens, game->orientation?"vertical":"horizontal",
-+ game->width, game->height, game->refresh, best_mode->hactive, best_mode->vactive, best_mode->vfreq);
-+
-+ osd_printf_verbose("%s\n", modeline_result(best_mode, result));
-+ if (cs->modeline_generation)
-+ osd_printf_verbose("SwitchRes: Modeline %s\n", modeline_print(best_mode, modeline, MS_FULL));
-+
-+ return true;
-+}
-+
-+//============================================================
-+// switchres_get_monitor_specs
-+//============================================================
-+
-+int switchres_get_monitor_specs(running_machine &machine)
-+{
-+ switchres_manager *switchres = &machine.switchres;
-+ char default_monitor[] = "generic_15";
-+
-+ memset(&switchres->range[0], 0, sizeof(struct monitor_range) * MAX_RANGES);
-+
-+ if (!strcmp(switchres->cs.monitor, "custom"))
-+ {
-+ monitor_fill_range(&switchres->range[0],machine.options().crt_range0());
-+ monitor_fill_range(&switchres->range[1],machine.options().crt_range1());
-+ monitor_fill_range(&switchres->range[2],machine.options().crt_range2());
-+ monitor_fill_range(&switchres->range[3],machine.options().crt_range3());
-+ monitor_fill_range(&switchres->range[4],machine.options().crt_range4());
-+ monitor_fill_range(&switchres->range[5],machine.options().crt_range5());
-+ monitor_fill_range(&switchres->range[6],machine.options().crt_range6());
-+ monitor_fill_range(&switchres->range[7],machine.options().crt_range7());
-+ monitor_fill_range(&switchres->range[8],machine.options().crt_range8());
-+ monitor_fill_range(&switchres->range[9],machine.options().crt_range9());
-+ }
-+ else if (!strcmp(switchres->cs.monitor, "lcd"))
-+ monitor_fill_lcd_range(&switchres->range[0],machine.options().lcd_range());
-+
-+ else if (monitor_set_preset(switchres->cs.monitor, switchres->range) == 0)
-+ monitor_set_preset(default_monitor, switchres->range);
-+
-+ return 0;
-+}
-+
-+//============================================================
-+// switchres_init
-+//============================================================
-+
-+void switchres_init(running_machine &machine)
-+{
-+ emu_options &options = machine.options();
-+ config_settings *cs = &machine.switchres.cs;
-+ modeline *user_mode = &machine.switchres.user_mode;
-+
-+ osd_printf_verbose("SwitchRes: v%s, Monitor: %s, Orientation: %s, Modeline generation: %s\n",
-+ SWITCHRES_VERSION, options.monitor(), options.orientation(), options.modeline_generation()?"enabled":"disabled");
-+
-+ // Get user defined modeline
-+ if (options.modeline_generation())
-+ {
-+ modeline_parse(options.modeline(), user_mode);
-+ user_mode->type |= MODE_USER_DEF;
-+ }
-+
-+ // Get monitor specs
-+ sprintf(cs->monitor, "%s", options.monitor());
-+ sprintf(cs->connector, "%s", options.connector());
-+ for (int i = 0; cs->monitor[i]; i++) cs->monitor[i] = tolower(cs->monitor[i]);
-+ if (user_mode->hactive)
-+ {
-+ modeline_to_monitor_range(machine.switchres.range, user_mode);
-+ monitor_show_range(machine.switchres.range);
-+ }
-+ else
-+ switchres_get_monitor_specs(machine);
-+
-+ // Get rest of config options
-+ cs->modeline_generation = options.modeline_generation();
-+ cs->doublescan = options.doublescan();
-+ cs->interlace = options.interlace();
-+ cs->lock_system_modes = options.lock_system_modes();
-+ cs->lock_unsupported_modes = options.lock_unsupported_modes();
-+ cs->refresh_dont_care = options.refresh_dont_care();
-+ cs->super_width = options.super_width();
-+ sscanf(options.sync_refresh_tolerance(), "%f", &cs->sync_refresh_tolerance);
-+ float pclock_min;
-+ sscanf(options.dotclock_min(), "%f", &pclock_min);
-+ cs->pclock_min = pclock_min * 1000000;
-+}
-+
-+//============================================================
-+// switchres_get_game_info
-+//============================================================
-+
-+void switchres_get_game_info(running_machine &machine)
-+{
-+ emu_options &options = machine.options();
-+ game_info *game = &machine.switchres.game;
-+ const game_driver *game_drv = &machine.system();
-+ const screen_device *screen;
-+
-+ // Get game information
-+ sprintf(game->name, "%s", options.system_name());
-+ if (game->name[0] == 0) sprintf(game->name, "empty");
-+
-+ machine_config config(*game_drv, options);
-+ screen = screen_device_iterator(config.root_device()).first();
-+
-+ // Fill in current video mode settings
-+ game->orientation = effective_orientation(machine);
-+
-+ if (screen->screen_type() == SCREEN_TYPE_VECTOR)
-+ {
-+ game->vector = 1;
-+ game->width = 640;
-+ game->height = 480;
-+ }
-+
-+ // Output width and height only for games that are not vector
-+ else
-+ {
-+ const rectangle &visarea = screen->visible_area();
-+ int w = visarea.max_x - visarea.min_x + 1;
-+ int h = visarea.max_y - visarea.min_y + 1;
-+ game->width = game->orientation?h:w;
-+ game->height = game->orientation?w:h;
-+ }
-+
-+ game->refresh = ATTOSECONDS_TO_HZ(screen->refresh_attoseconds());
-+
-+ // Check for multiple screens
-+ screen_device_iterator iter(config.root_device());
-+ game->screens = iter.count();
-+}
-+
-+//============================================================
-+// effective_orientation
-+//============================================================
-+
-+bool effective_orientation(running_machine &machine)
-+{
-+ config_settings *cs = &machine.switchres.cs;
-+ const game_driver *game = &machine.system();
-+ emu_options &options = machine.options();
-+ render_target *target = machine.render().first_target();
-+ bool game_orientation = ((game->flags & machine_flags::MASK_ORIENTATION) & ORIENTATION_SWAP_XY);
-+
-+ if (target)
-+ cs->monitor_orientation = ((target->orientation() & machine_flags::MASK_ORIENTATION) & ORIENTATION_SWAP_XY? 1:0) ^ cs->desktop_rotated;
-+ else if (!strcmp(options.orientation(), "horizontal"))
-+ cs->monitor_orientation = 0;
-+ else if (!strcmp(options.orientation(), "vertical"))
-+ cs->monitor_orientation = 1;
-+ else if (!strcmp(options.orientation(), "rotate") || !strcmp(options.orientation(), "rotate_r"))
-+ {
-+ cs->monitor_orientation = game_orientation;
-+ cs->monitor_rotates_cw = 0;
-+ }
-+ else if (!strcmp(options.orientation(), "rotate_l"))
-+ {
-+ cs->monitor_orientation = game_orientation;
-+ cs->monitor_rotates_cw = 1;
-+ }
-+
-+ return game_orientation ^ cs->monitor_orientation;
-+}
-+
-+//============================================================
-+// switchres_check_resolution_change
-+//============================================================
-+
-+bool switchres_check_resolution_change(running_machine &machine)
-+{
-+ game_info *game = &machine.switchres.game;
-+ config_settings *cs = &machine.switchres.cs;
-+
-+ int new_width = game->width;
-+ int new_height = game->height;
-+ float new_vfreq = game->refresh;
-+ bool new_orientation = effective_orientation(machine);
-+
-+ screen_device_iterator scriter(machine.root_device());
-+ if (scriter.count())
-+ {
-+ screen_device *screen = scriter.first();
-+ if (screen->frame_number())
-+ {
-+ const rectangle &visarea = screen->visible_area();
-+ new_width = new_orientation? visarea.height() : visarea.width();
-+ new_height = new_orientation? visarea.width() : visarea.height();
-+ new_vfreq = ATTOSECONDS_TO_HZ(screen->frame_period().m_attoseconds);
-+ }
-+ }
-+
-+ if (game->width != new_width || game->height != new_height || new_vfreq != game->refresh || cs->effective_orientation != new_orientation)
-+ {
-+ osd_printf_verbose("SwitchRes: Resolution change from %dx%d@%f %s to %dx%d@%f %s\n",
-+ game->width, game->height, game->refresh, cs->effective_orientation?"rotated":"normal", new_width, new_height, new_vfreq, new_orientation?"rotated":"normal");
-+
-+ game->width = new_width;
-+ game->height = new_height;
-+ game->refresh = new_vfreq;
-+
-+ return true;
-+ }
-+ return false;
-+}
-+
-+//============================================================
-+// switchres_set_options
-+//============================================================
-+
-+void switchres_set_options(running_machine &machine)
-+{
-+ config_settings *cs = &machine.switchres.cs;
-+ bool native_orientation = ((machine.system().flags & machine_flags::MASK_ORIENTATION) & ORIENTATION_SWAP_XY);
-+ bool must_rotate = effective_orientation(machine) ^ cs->desktop_rotated;
-+ modeline *best_mode = &machine.switchres.best_mode;
-+
-+ // Set rotation options
-+ set_option(machine, OPTION_ROTATE, true);
-+ if (cs->monitor_rotates_cw)
-+ {
-+ set_option(machine, OPTION_ROL, (!native_orientation & must_rotate));
-+ set_option(machine, OPTION_AUTOROL, !must_rotate);
-+ set_option(machine, OPTION_ROR, false);
-+ set_option(machine, OPTION_AUTOROR, false);
-+ }
-+ else
-+ {
-+ set_option(machine, OPTION_ROR, (!native_orientation & must_rotate));
-+ set_option(machine, OPTION_AUTOROR, !must_rotate);
-+ set_option(machine, OPTION_ROL, false);
-+ set_option(machine, OPTION_AUTOROL, false);
-+ }
-+
-+ // Set scaling/stretching options
-+ set_option(machine, OPTION_KEEPASPECT, true);
-+ set_option(machine, OPTION_UNEVENSTRETCH, best_mode->result.weight & R_RES_STRETCH);
-+ set_option(machine, OPTION_UNEVENSTRETCHX, (!(best_mode->result.weight & R_RES_STRETCH) && (best_mode->width >= machine.options().super_width())));
-+
-+ // Update target if it's already initialized
-+ render_target *target = machine.render().first_target();
-+ if (target)
-+ {
-+ if (machine.options().uneven_stretch())
-+ target->set_scale_mode(SCALE_FRACTIONAL);
-+ else if(machine.options().uneven_stretch_x())
-+ target->set_scale_mode(SCALE_FRACTIONAL_X);
-+ else if(machine.options().uneven_stretch_y())
-+ target->set_scale_mode(SCALE_FRACTIONAL_Y);
-+ else
-+ target->set_scale_mode(SCALE_INTEGER);
-+ }
-+}
-+
-+//============================================================
-+// set_option - option setting wrapper
-+//============================================================
-+
-+void set_option(running_machine &machine, const char *option_ID, bool state)
-+{
-+ emu_options &options = machine.options();
-+
-+ options.set_value(option_ID, state, OPTION_PRIORITY_SWITCHRES);
-+ osd_printf_verbose("SwitchRes: Setting option -%s%s\n", machine.options().bool_value(option_ID)?"":"no", option_ID);
-+}
-diff --git a/src/emu/switchres/switchres.h b/src/emu/switchres/switchres.h
-new file mode 100644
-index 00000000000..b162ed70125
---- /dev/null
-+++ b/src/emu/switchres/switchres.h
-@@ -0,0 +1,80 @@
-+/**************************************************************
-+
-+ switchres.h - SwichRes general header
-+
-+ ---------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2016 - Chris Kennedy, Antonio Giner
-+
-+ **************************************************************/
-+
-+#ifndef __SWITCHRES_H__
-+#define __SWITCHRES_H__
-+
-+//============================================================
-+// CONSTANTS
-+//============================================================
-+
-+#define SWITCHRES_VERSION "0.017p"
-+
-+//============================================================
-+// TYPE DEFINITIONS
-+//============================================================
-+
-+typedef struct game_info
-+{
-+ char name[32];
-+ int width;
-+ int height;
-+ float refresh;
-+ bool orientation;
-+ bool vector;
-+ bool changeres;
-+ int screens;
-+} game_info;
-+
-+typedef struct config_settings
-+{
-+ char connector[32];
-+ char monitor[32];
-+ bool modeline_generation;
-+ bool monitor_orientation;
-+ bool effective_orientation;
-+ bool desktop_rotated;
-+ bool monitor_rotates_cw;
-+ float monitor_aspect;
-+ int monitor_count;
-+ int pclock_min;
-+ int pclock_align;
-+ int interlace;
-+ int doublescan;
-+ int width;
-+ int height;
-+ int refresh;
-+ int super_width;
-+ bool lock_unsupported_modes;
-+ bool lock_system_modes;
-+ bool refresh_dont_care;
-+ float sync_refresh_tolerance;
-+} config_settings;
-+
-+#include "monitor.h"
-+#include "modeline.h"
-+
-+typedef struct switchres_manager
-+{
-+ struct config_settings cs;
-+ struct game_info game;
-+ struct modeline best_mode;
-+ struct modeline user_mode;
-+ struct monitor_range range[MAX_RANGES];
-+ struct modeline video_modes[MAX_MODELINES];
-+} switchres;
-+
-+#endif
-diff --git a/src/emu/switchres/switchres_proto.h b/src/emu/switchres/switchres_proto.h
-new file mode 100644
-index 00000000000..de9185e6810
---- /dev/null
-+++ b/src/emu/switchres/switchres_proto.h
-@@ -0,0 +1,42 @@
-+/**************************************************************
-+
-+ switchres_proto.h - SwichRes prototypes header
-+
-+ ---------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2016 - Chris Kennedy, Antonio Giner
-+
-+ **************************************************************/
-+
-+#ifndef __SWITCHRES_H_PROTO__
-+#define __SWITCHRES_H_PROTO__
-+
-+//============================================================
-+// PROTOTYPES
-+//============================================================
-+
-+// util.cpp
-+int normalize(int a, int b);
-+int real_res(int x);
-+
-+// switchres.cpp
-+bool switchres_get_video_mode(running_machine &machine);
-+int switchres_get_monitor_specs(running_machine &machine);
-+void switchres_init(running_machine &machine);
-+void switchres_get_game_info(running_machine &machine);
-+bool switchres_check_resolution_change(running_machine &machine);
-+void switchres_set_options(running_machine &machine);
-+bool effective_orientation(running_machine &machine);
-+
-+// OSD - switchres.cpp
-+bool switchres_init_osd(running_machine &machine);
-+bool switchres_modeline_setup(running_machine &machine);
-+bool switchres_modeline_remove(running_machine &machine);
-+
-+#endif
-diff --git a/src/emu/switchres/util.cpp b/src/emu/switchres/util.cpp
-new file mode 100644
-index 00000000000..c0def9124d0
---- /dev/null
-+++ b/src/emu/switchres/util.cpp
-@@ -0,0 +1,34 @@
-+/**************************************************************
-+
-+ util.cpp - Utility functions
-+
-+ ---------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2016 - Chris Kennedy, Antonio Giner
-+
-+ **************************************************************/
-+
-+//============================================================
-+// normalize
-+//============================================================
-+
-+int normalize(int a, int b)
-+{
-+ int c, d;
-+ c = a % b;
-+ d = a / b;
-+ if (c) d++;
-+ return d * b;
-+}
-+
-+//============================================================
-+// real_res
-+//============================================================
-+
-+int real_res(int x) {return (int) (x / 8) * 8;}
-diff --git a/src/emu/video.cpp b/src/emu/video.cpp
-index 8da14f03b85..5deeb91d39f 100644
---- a/src/emu/video.cpp
-+++ b/src/emu/video.cpp
-@@ -51,7 +51,7 @@ const bool video_manager::s_skiptable[FRAMESKIP_LEVELS][FRAMESKIP_LEVELS] =
- { false, true , true , true , true , true , true , true , true , true , true , true }
- };
-
--
-+int video_manager::s_fd_speeds[FD_BINS] = { 0,0,0,0,0,0,0,0,0,0 };
-
- //**************************************************************************
- // VIDEO MANAGER
-@@ -86,6 +86,8 @@ video_manager::video_manager(running_machine &machine)
- , m_overall_valid_counter(0)
- , m_throttled(machine.options().throttle())
- , m_throttle_rate(1.0f)
-+ , m_syncrefresh(machine.options().sync_refresh())
-+ , m_framedelay(machine.options().frame_delay())
- , m_fastforward(false)
- , m_seconds_to_run(machine.options().seconds_to_run())
- , m_auto_frameskip(machine.options().auto_frameskip())
-@@ -237,6 +239,14 @@ void video_manager::frame_update(bool from_debugger)
- machine().osd().update(!from_debugger && skipped_it);
- g_profiler.stop();
-
-+ // manage black frame insertion
-+ if (machine().options().black_frame_insertion() && machine().options().sync_refresh())
-+ {
-+ render_container *container = &machine().render().ui_container();
-+ container->add_rect(0, 0, 1, 1, 0xff000000, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
-+ machine().osd().update(!from_debugger && skipped_it);
-+ }
-+
- // we synchronize after rendering instead of before, if low latency mode is enabled
- if (!from_debugger && !skipped_it && m_low_latency && effective_throttle())
- update_throttle(current_time);
-@@ -523,6 +533,23 @@ void video_manager::exit()
- osd_ticks_t tps = osd_ticks_per_second();
- double final_real_time = (double)m_overall_real_seconds + (double)m_overall_real_ticks / (double)tps;
- double final_emu_time = m_overall_emutime.as_double();
-+
-+ if (!m_throttled)
-+ {
-+ int i;
-+ float sum = 0;
-+
-+ osd_printf_info("Frame delay/percentage:");
-+
-+ for (i = 0; i < FD_BINS; i++)
-+ sum += s_fd_speeds[i];
-+
-+ for (i = 0; i < FD_BINS; i++)
-+ if (s_fd_speeds[i])
-+ osd_printf_info(" %d/%.2f%%", i, (float) s_fd_speeds[i] / sum * 100.f);
-+ osd_printf_info("\n");
-+ }
-+
- osd_printf_info("Average speed: %.2f%% (%d seconds)\n", 100 * final_emu_time / final_real_time, (m_overall_emutime + attotime(0, ATTOSECONDS_PER_SECOND / 2)).seconds());
- }
- }
-@@ -728,6 +755,20 @@ void video_manager::update_throttle(attotime emutime)
- 3,4,4,5,4,5,5,6, 4,5,5,6,5,6,6,7, 4,5,5,6,5,6,6,7, 5,6,6,7,6,7,7,8
- };
-
-+ // if we're only syncing to the refresh, bail now
-+ if (m_syncrefresh)
-+ {
-+ modeline *mode = &machine().switchres.best_mode;
-+ if (m_framedelay == 0 || m_framedelay > 9 || mode->hactive == 0)
-+ return;
-+
-+ osd_ticks_t now = osd_ticks();
-+ osd_ticks_t ticks_per_second = osd_ticks_per_second();
-+ attoseconds_t attoseconds_per_tick = ATTOSECONDS_PER_SECOND / ticks_per_second * m_throttle_rate;
-+ throttle_until_ticks(now + HZ_TO_ATTOSECONDS(mode->vfreq / mode->result.v_scale) / attoseconds_per_tick * m_framedelay / 10);
-+ return;
-+ }
-+
- // outer scope so we can break out in case of a resync
- while (1)
- {
-@@ -999,6 +1040,21 @@ void video_manager::recompute_speed(const attotime &emutime)
- osd_ticks_t tps = osd_ticks_per_second();
- m_speed_percent = delta_emutime.as_double() * (double)tps / (double)delta_realtime;
-
-+ // adjust speed for audio resampling
-+ if (m_syncrefresh && m_throttled)
-+ {
-+ if (m_speed_percent >= 0.8 && m_speed_percent <= 1.2)
-+ m_speed = m_speed_percent * 1000;
-+ }
-+
-+ // log speed for frame delay statistic
-+ if (!m_throttled)
-+ {
-+ int bin = (float) FD_BINS - 10.f/m_speed_percent;
-+ bin = bin > (FD_BINS - 1) ? (FD_BINS - 1) : bin < 0 ? 0 : bin;
-+ s_fd_speeds[bin]++;
-+ }
-+
- // remember the last times
- m_speed_last_realtime = realtime;
- m_speed_last_emutime = emutime;
-diff --git a/src/emu/video.h b/src/emu/video.h
-index 2fe7786afb5..f205fa7fa62 100644
---- a/src/emu/video.h
-+++ b/src/emu/video.h
-@@ -28,6 +28,7 @@
- constexpr int FRAMESKIP_LEVELS = 12;
- constexpr int MAX_FRAMESKIP = FRAMESKIP_LEVELS - 2;
-
-+constexpr int FD_BINS = 10;
-
- //**************************************************************************
- // TYPE DEFINITIONS
-@@ -50,6 +51,8 @@ public:
- int frameskip() const { return m_auto_frameskip ? -1 : m_frameskip_level; }
- bool throttled() const { return m_throttled; }
- float throttle_rate() const { return m_throttle_rate; }
-+ bool sync_refresh() const { return m_syncrefresh; }
-+ int32_t framedelay() const { return m_framedelay; }
- bool fastforward() const { return m_fastforward; }
- bool is_recording() const;
-
-@@ -59,6 +62,7 @@ public:
- void set_throttle_rate(float throttle_rate) { m_throttle_rate = throttle_rate; }
- void set_fastforward(bool ffwd = true) { m_fastforward = ffwd; }
- void set_output_changed() { m_output_changed = true; }
-+ void set_framedelay(int framedelay) { m_framedelay = framedelay; }
-
- // misc
- void toggle_throttle();
-@@ -148,6 +152,8 @@ private:
- // configuration
- bool m_throttled; // flag: true if we're currently throttled
- float m_throttle_rate; // target rate for throttling
-+ bool m_syncrefresh; // flag: TRUE if we're currently refresh-synced
-+ int32_t m_framedelay; // tenths of frame to delay emulation start
- bool m_fastforward; // flag: true if we're currently fast-forwarding
- u32 m_seconds_to_run; // number of seconds to run before quitting
- bool m_auto_frameskip; // flag: true if we're automatically frameskipping
-@@ -172,6 +178,9 @@ private:
- // movie recordings
- std::vector<movie_recording::ptr> m_movie_recordings;
-
-+ // frame delay statistics
-+ static int s_fd_speeds[FD_BINS];
-+
- static const bool s_skiptable[FRAMESKIP_LEVELS][FRAMESKIP_LEVELS];
-
- static const attoseconds_t ATTOSECONDS_PER_SPEED_UPDATE = ATTOSECONDS_PER_SECOND / 4;
-diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp
-index aa5ec7606b8..f93231fa84b 100644
---- a/src/frontend/mame/clifront.cpp
-+++ b/src/frontend/mame/clifront.cpp
-@@ -1732,6 +1732,7 @@
- osd_printf_info(
- "%3$s v%2$s\n"
- "%5$s\n"
-+ "GroovyMAME - SwitchRes version %6$s\n"
- "\n"
- "This software reproduces, more or less faithfully, the behaviour of a wide range\n"
- "of machines. But hardware is useless without software, so images of the ROMs and\n"
-@@ -1749,5 +1750,6 @@
- build_version,
- emulator_info::get_appname(),
- emulator_info::get_configname(),
-- emulator_info::get_copyright_info());
-+ emulator_info::get_copyright_info(),
-+ SWITCHRES_VERSION);
- }
-diff --git a/src/frontend/mame/mameopts.h b/src/frontend/mame/mameopts.h
-index 2b178fb2ead..502d20f76d0 100644
---- a/src/frontend/mame/mameopts.h
-+++ b/src/frontend/mame/mameopts.h
-@@ -29,6 +29,7 @@ enum
-
- // INI-based options are NORMAL priority, in increasing order:
- OPTION_PRIORITY_MAME_INI = OPTION_PRIORITY_NORMAL + 1,
-+ OPTION_PRIORITY_SWITCHRES,
- OPTION_PRIORITY_DEBUG_INI,
- OPTION_PRIORITY_ORIENTATION_INI,
- OPTION_PRIORITY_SYSTYPE_INI,
-diff --git a/src/frontend/mame/ui/info.cpp b/src/frontend/mame/ui/info.cpp
-index 76b2f012731..dc6bf8532a6 100644
---- a/src/frontend/mame/ui/info.cpp
-+++ b/src/frontend/mame/ui/info.cpp
-@@ -420,6 +420,15 @@ std::string machine_info::game_info_string() const
- }
- }
-
-+ // display SwitchRes information
-+ modeline *mode = &m_machine.switchres.best_mode;
-+ if (mode->hactive)
-+ {
-+ buf << _("\nSwitchres:\n");
-+ util::stream_format(buf, "%d " UTF8_MULTIPLY " %d%s%s %2.3f Hz %2.3f kHz\n",
-+ mode->hactive, mode->vactive, mode->interlace?"i":"p", mode->doublescan?"d":"", mode->vfreq, mode->hfreq/1000);
-+ }
-+
- return buf.str();
- }
-
-diff --git a/src/frontend/mame/ui/submenu.cpp b/src/frontend/mame/ui/submenu.cpp
-index 207ac56d057..efee8fc4047 100644
---- a/src/frontend/mame/ui/submenu.cpp
-+++ b/src/frontend/mame/ui/submenu.cpp
-@@ -107,7 +107,7 @@ std::vector<submenu::option> const submenu::video_options = {
- { submenu::option_type::OSD, __("Window Mode"), OSDOPTION_WINDOW },
- { submenu::option_type::EMU, __("Enforce Aspect Ratio"), OPTION_KEEPASPECT },
- { submenu::option_type::OSD, __("Start Out Maximized"), OSDOPTION_MAXIMIZE },
-- { submenu::option_type::OSD, __("Synchronized Refresh"), OSDOPTION_SYNCREFRESH },
-+ { submenu::option_type::OSD, __("Synchronized Refresh"), OPTION_SYNCREFRESH },
- { submenu::option_type::OSD, __("Wait Vertical Sync"), OSDOPTION_WAITVSYNC }
- };
-
-diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp
-index bfcfd10bd97..885e8a825a0 100644
---- a/src/frontend/mame/ui/ui.cpp
-+++ b/src/frontend/mame/ui/ui.cpp
-@@ -31,6 +31,7 @@
- #include "ui/viewgfx.h"
- #include "imagedev/cassette.h"
- #include "../osd/modules/lib/osdobj_common.h"
-+#include "config.h"
-
-
- /***************************************************************************
-@@ -193,6 +194,9 @@ void mame_ui_manager::init()
- // request a callback upon exiting
- machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&mame_ui_manager::exit, this));
-
-+ // register callbacks
-+ machine().configuration().config_register("sliders", config_load_delegate(&mame_ui_manager::config_load, this), config_save_delegate(&mame_ui_manager::config_save, this));
-+
- // create mouse bitmap
- uint32_t *dst = &m_mouse_bitmap.pix32(0);
- memcpy(dst,mouse_bitmap,32*32*sizeof(uint32_t));
-@@ -1351,6 +1355,9 @@ std::vector<ui::menu_item> mame_ui_manager::slider_init(running_machine &machine
- // add overall volume
- m_sliders.push_back(slider_alloc(SLIDER_ID_VOLUME, _("Master Volume"), -32, 0, 0, 1, nullptr));
-
-+ // add frame delay
-+ m_sliders.push_back(slider_alloc(SLIDER_ID_FRAMEDELAY, _("Frame Delay"), 0, machine.options().frame_delay(), 9, 1, nullptr));
-+
- // add per-channel volume
- mixer_input info;
- for (int item = 0; machine.sound().indexed_mixer_input(item, info); item++)
-@@ -1495,6 +1502,8 @@ std::vector<ui::menu_item> mame_ui_manager::slider_init(running_machine &machine
- }
- #endif
-
-+ config_apply();
-+
- std::vector<ui::menu_item> items;
- for (auto &slider : m_sliders)
- {
-@@ -1518,6 +1527,8 @@ int32_t mame_ui_manager::slider_changed(running_machine &machine, void *arg, int
- {
- if (id == SLIDER_ID_VOLUME)
- return slider_volume(machine, arg, id, str, newval);
-+ else if (id == SLIDER_ID_FRAMEDELAY)
-+ return slider_framedelay(machine, arg, id, str, newval);
- else if (id >= SLIDER_ID_MIXERVOL && id <= SLIDER_ID_MIXERVOL_LAST)
- return slider_mixervol(machine, arg, id, str, newval);
- else if (id >= SLIDER_ID_ADJUSTER && id <= SLIDER_ID_ADJUSTER_LAST)
-@@ -1581,6 +1592,21 @@ int32_t mame_ui_manager::slider_volume(running_machine &machine, void *arg, int
- }
-
-
-+//-------------------------------------------------
-+// slider_framedelay - global frame delay slider
-+// callback
-+//-------------------------------------------------
-+
-+int32_t mame_ui_manager::slider_framedelay(running_machine &machine, void *arg, int id, std::string *str, int32_t newval)
-+{
-+ if (newval != SLIDER_NOCHANGE)
-+ machine.video().set_framedelay(newval);
-+ if (str)
-+ *str = string_format(_("%1$3d"), machine.video().framedelay());
-+ return machine.video().framedelay();
-+}
-+
-+
- //-------------------------------------------------
- // slider_mixervol - single channel volume
- // slider callback
-@@ -2198,3 +2224,83 @@ void ui_colors::refresh(const ui_options &options)
- m_dipsw_color = options.dipsw_color();
- m_slider_color = options.slider_color();
- }
-+
-+//-------------------------------------------------
-+// config_load - read data from the
-+// configuration file
-+//-------------------------------------------------
-+
-+void mame_ui_manager::config_load(config_type cfg_type, util::xml::data_node const *parentnode)
-+{
-+ // we only care about game files
-+ if (cfg_type != config_type::GAME)
-+ return;
-+
-+ // might not have any data
-+ if (parentnode == nullptr)
-+ return;
-+
-+ // iterate over slider nodes
-+ for (util::xml::data_node const *slider_node = parentnode->get_child("slider"); slider_node; slider_node = slider_node->get_next_sibling("slider"))
-+ {
-+ const char *desc = slider_node->get_attribute_string("desc", "");
-+ int32_t saved_val = slider_node->get_attribute_int("value", 0);
-+
-+ // create a dummy slider to store the saved value
-+ m_sliders_saved.push_back(slider_alloc(0, desc, 0, saved_val, 0, 0, 0));
-+ }
-+}
-+
-+
-+//-------------------------------------------------
-+// config_appy - apply data from the conf. file
-+// This currently needs to be done on a separate
-+// step because sliders are not created yet when
-+// configuration file is loaded
-+//-------------------------------------------------
-+
-+void mame_ui_manager::config_apply(void)
-+{
-+ // iterate over sliders and restore saved values
-+ for (auto &slider : m_sliders)
-+ {
-+ for (auto &slider_saved : m_sliders_saved)
-+ {
-+ if (!strcmp(slider->description.c_str(), slider_saved->description.c_str()))
-+ {
-+ std::string tempstring;
-+ slider->update(machine(), slider->arg, slider->id, &tempstring, slider_saved->defval);
-+ break;
-+
-+ }
-+ }
-+ }
-+}
-+
-+
-+//-------------------------------------------------
-+// config_save - save data to the configuration
-+// file
-+//-------------------------------------------------
-+
-+void mame_ui_manager::config_save(config_type cfg_type, util::xml::data_node *parentnode)
-+{
-+ // we only care about game files
-+ if (cfg_type != config_type::GAME)
-+ return;
-+
-+ std::string tempstring;
-+ util::xml::data_node *slider_node;
-+
-+ // save UI sliders
-+ for (auto &slider : m_sliders)
-+ {
-+ int32_t curval = slider->update(machine(), slider->arg, slider->id, &tempstring, SLIDER_NOCHANGE);
-+ if (curval != slider->defval)
-+ {
-+ slider_node = parentnode->add_child("slider", nullptr);
-+ slider_node->set_attribute("desc", slider->description.c_str());
-+ slider_node->set_attribute_int("value", curval);
-+ }
-+ }
-+}
-\ No newline at end of file
-diff --git a/src/frontend/mame/ui/ui.h b/src/frontend/mame/ui/ui.h
-index 71f6a5ab8b8..f4ae6e2c962 100644
---- a/src/frontend/mame/ui/ui.h
-+++ b/src/frontend/mame/ui/ui.h
-@@ -53,6 +53,7 @@ class machine_info;
- enum
- {
- SLIDER_ID_VOLUME = 0,
-+ SLIDER_ID_FRAMEDELAY,
- SLIDER_ID_MIXERVOL,
- SLIDER_ID_MIXERVOL_LAST = SLIDER_ID_MIXERVOL + SLIDER_DEVICE_SPACING,
- SLIDER_ID_ADJUSTER,
-@@ -234,6 +235,11 @@ public:
- void start_save_state();
- void start_load_state();
-
-+ // config callbacks
-+ void config_load(config_type cfg_type, util::xml::data_node const *parentnode);
-+ void config_save(config_type cfg_type, util::xml::data_node *parentnode);
-+ void config_apply(void);
-+
- // slider controls
- std::vector<ui::menu_item>& get_slider_list(void);
-
-@@ -300,6 +306,7 @@ private:
- virtual int32_t slider_changed(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) override;
-
- int32_t slider_volume(running_machine &machine, void *arg, int id, std::string *str, int32_t newval);
-+ int32_t slider_framedelay(running_machine &machine, void *arg, int id, std::string *str, int32_t newval);
- int32_t slider_mixervol(running_machine &machine, void *arg, int id, std::string *str, int32_t newval);
- int32_t slider_adjuster(running_machine &machine, void *arg, int id, std::string *str, int32_t newval);
- int32_t slider_overclock(running_machine &machine, void *arg, int id, std::string *str, int32_t newval);
-@@ -326,6 +333,7 @@ private:
- #endif
-
- std::vector<std::unique_ptr<slider_state>> m_sliders;
-+ std::vector<std::unique_ptr<slider_state>> m_sliders_saved;
- };
-
-
-diff --git a/src/osd/modules/lib/osdobj_common.cpp b/src/osd/modules/lib/osdobj_common.cpp
-index 25d4b979e87..6f7c512dcc3 100644
---- a/src/osd/modules/lib/osdobj_common.cpp
-+++ b/src/osd/modules/lib/osdobj_common.cpp
-@@ -59,7 +59,6 @@ const options_entry osd_options::s_option_entries[] =
- { OSDOPTION_WINDOW ";w", "0", OPTION_BOOLEAN, "enable window mode; otherwise, full screen mode is assumed" },
- { OSDOPTION_MAXIMIZE ";max", "1", OPTION_BOOLEAN, "default to maximized windows" },
- { OSDOPTION_WAITVSYNC ";vs", "0", OPTION_BOOLEAN, "enable waiting for the start of VBLANK before flipping screens (reduces tearing effects)" },
-- { OSDOPTION_SYNCREFRESH ";srf", "0", OPTION_BOOLEAN, "enable using the start of VBLANK for throttling instead of the game time" },
- { OSD_MONITOR_PROVIDER, OSDOPTVAL_AUTO, OPTION_STRING, "monitor discovery method: " },
-
- // per-window options
-@@ -91,10 +90,10 @@ const options_entry osd_options::s_option_entries[] =
-
- // full screen options
- { nullptr, nullptr, OPTION_HEADER, "OSD FULL SCREEN OPTIONS" },
-- { OSDOPTION_SWITCHRES, "0", OPTION_BOOLEAN, "enable resolution switching" },
-+ { OSDOPTION_SWITCHRES, "1", OPTION_BOOLEAN, "enable resolution switching" },
-
- { nullptr, nullptr, OPTION_HEADER, "OSD ACCELERATED VIDEO OPTIONS" },
-- { OSDOPTION_FILTER ";glfilter;flt", "1", OPTION_BOOLEAN, "use bilinear filtering when scaling emulated video" },
-+ { OSDOPTION_FILTER ";glfilter;flt", "0", OPTION_BOOLEAN, "use bilinear filtering when scaling emulated video" },
- { OSDOPTION_PRESCALE "(1-8)", "1", OPTION_INTEGER, "scale emulated video by this factor before applying filters/shaders" },
-
- #if USE_OPENGL
-@@ -129,7 +128,7 @@ const options_entry osd_options::s_option_entries[] =
-
- { nullptr, nullptr, OPTION_HEADER, "OSD SOUND OPTIONS" },
- { OSDOPTION_SOUND, OSDOPTVAL_AUTO, OPTION_STRING, "sound output method: " },
-- { OSDOPTION_AUDIO_LATENCY "(1-5)", "2", OPTION_INTEGER, "set audio latency (increase to reduce glitches, decrease for responsiveness)" },
-+ { OSDOPTION_AUDIO_LATENCY "(0.1-5.0)", "2.0", OPTION_FLOAT, "set audio latency (increase to reduce glitches, decrease for responsiveness)" },
-
- #ifndef NO_USE_PORTAUDIO
- { nullptr, nullptr, OPTION_HEADER, "PORTAUDIO OPTIONS" },
-diff --git a/src/osd/modules/lib/osdobj_common.h b/src/osd/modules/lib/osdobj_common.h
-index 9fb1b1eef6b..756b15f1b0a 100644
---- a/src/osd/modules/lib/osdobj_common.h
-+++ b/src/osd/modules/lib/osdobj_common.h
-@@ -50,7 +50,6 @@
- #define OSDOPTION_WINDOW "window"
- #define OSDOPTION_MAXIMIZE "maximize"
- #define OSDOPTION_WAITVSYNC "waitvsync"
--#define OSDOPTION_SYNCREFRESH "syncrefresh"
-
- #define OSDOPTION_SCREEN "screen"
- #define OSDOPTION_ASPECT "aspect"
-@@ -122,7 +121,6 @@ public:
- bool window() const { return bool_value(OSDOPTION_WINDOW); }
- bool maximize() const { return bool_value(OSDOPTION_MAXIMIZE); }
- bool wait_vsync() const { return bool_value(OSDOPTION_WAITVSYNC); }
-- bool sync_refresh() const { return bool_value(OSDOPTION_SYNCREFRESH); }
-
- // per-window options
- const char *screen() const { return value(OSDOPTION_SCREEN); }
-@@ -153,7 +151,7 @@ public:
-
- // sound options
- const char *sound() const { return value(OSDOPTION_SOUND); }
-- int audio_latency() const { return int_value(OSDOPTION_AUDIO_LATENCY); }
-+ float audio_latency() const { return float_value(OSDOPTION_AUDIO_LATENCY); }
-
- // CoreAudio specific options
- const char *audio_output() const { return value(OSDOPTION_AUDIO_OUTPUT); }
-diff --git a/src/osd/modules/osdwindow.h b/src/osd/modules/osdwindow.h
-index 3fe020c56fe..6479d544e43 100644
---- a/src/osd/modules/osdwindow.h
-+++ b/src/osd/modules/osdwindow.h
-@@ -215,9 +215,13 @@ public:
- virtual void record() { };
- virtual void toggle_fsfx() { };
- virtual bool sliders_dirty() { return m_sliders_dirty; }
-+ virtual int restart() { return 0; }
-
- static std::unique_ptr<osd_renderer> make_for_type(int mode, std::shared_ptr<osd_window> window, int extra_flags = FLAG_NONE);
-
-+ // SwitchRes mode
-+ modeline * m_switchres_mode;
-+
- protected:
- virtual void build_slider_list() { }
-
-@@ -262,6 +266,7 @@ struct osd_video_config
- int waitvsync; // spin until vsync
- int syncrefresh; // sync only to refresh rate
- int switchres; // switch resolutions
-+ int framedelay; // frame delay
-
- // d3d, accel, opengl
- int filter; // enable filtering
-diff --git a/src/osd/modules/render/d3d/d3dhlsl.h b/src/osd/modules/render/d3d/d3dhlsl.h
-index 7f7dacc4538..e700a36f36f 100644
---- a/src/osd/modules/render/d3d/d3dhlsl.h
-+++ b/src/osd/modules/render/d3d/d3dhlsl.h
-@@ -302,7 +302,7 @@ public:
-
- bool init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *renderer);
-
-- bool enabled() { return post_fx_enable && d3dintf->post_fx_available; }
-+ bool enabled() { return (this != nullptr) && post_fx_enable && d3dintf->post_fx_available; }
- void toggle() { post_fx_enable = initialized && !post_fx_enable; }
-
- void begin_draw();
-diff --git a/src/osd/modules/render/drawd3d.cpp b/src/osd/modules/render/drawd3d.cpp
-index 56c905636a4..2d503662083 100644
---- a/src/osd/modules/render/drawd3d.cpp
-+++ b/src/osd/modules/render/drawd3d.cpp
-@@ -45,7 +45,7 @@ enum
- // INLINES
- //============================================================
-
--static inline BOOL GetClientRectExceptMenu(HWND hWnd, PRECT pRect, BOOL fullscreen)
-+inline BOOL renderer_d3d9::GetClientRectExceptMenu(HWND hWnd, PRECT pRect, BOOL fullscreen)
- {
- static HMENU last_menu;
- static RECT last_rect;
-@@ -53,6 +53,12 @@ static inline BOOL GetClientRectExceptMenu(HWND hWnd, PRECT pRect, BOOL fullscre
- HMENU menu = GetMenu(hWnd);
- BOOL result = GetClientRect(hWnd, pRect);
-
-+ if (m_switchres_mode && m_switchres_mode->hactive)
-+ {
-+ pRect->right = m_switchres_mode->type & MODE_ROTATED? m_switchres_mode->vactive : m_switchres_mode->hactive;
-+ pRect->bottom = m_switchres_mode->type & MODE_ROTATED? m_switchres_mode->hactive : m_switchres_mode->vactive;
-+ }
-+
- if (!fullscreen || !menu)
- return result;
-
-@@ -184,7 +190,14 @@ render_primitive_list *renderer_d3d9::get_primitives()
- GetClientRectExceptMenu(hWnd, &client, win->fullscreen());
- if (rect_width(&client) > 0 && rect_height(&client) > 0)
- {
-- win->target()->set_bounds(rect_width(&client), rect_height(&client), win->pixel_aspect());
-+ // handle aspect correction for magic resolutions
-+ float aspect_corrector = 1.0f;
-+ if (m_switchres_mode && m_switchres_mode->hactive)
-+ {
-+ aspect_corrector = ((float)m_switchres_mode->width / (float)m_switchres_mode->height) / ((float)m_switchres_mode->hactive / (float)m_switchres_mode->vactive);
-+ if (m_switchres_mode->type & MODE_ROTATED) aspect_corrector = 1.0 / aspect_corrector;
-+ }
-+ win->target()->set_bounds(rect_width(&client), rect_height(&client), win->pixel_aspect() * aspect_corrector);
- win->target()->set_max_update_rate((get_refresh() == 0) ? get_origmode().RefreshRate : get_refresh());
- }
- if (m_shaders != nullptr)
-@@ -733,12 +746,111 @@ void renderer_d3d9::end_frame()
- if (FAILED(result))
- osd_printf_verbose("Direct3D: Error %08lX during device end_scene call\n", result);
-
-+ if (m_frame_delay != video_config.framedelay)
-+ {
-+ m_frame_delay = video_config.framedelay;
-+ update_break_scanlines();
-+ }
-+
-+ D3DRASTER_STATUS raster_status;
-+ memset (&raster_status, 0, sizeof(D3DRASTER_STATUS));
-+
-+ // sync to VBLANK-BEGIN
-+ if (video_config.framedelay && video_config.syncrefresh)
-+ {
-+ // check if retrace has been missed
-+ if (m_device->GetRasterStatus(0, &raster_status) == D3D_OK)
-+ {
-+ if (raster_status.ScanLine < m_delay_scanline && !raster_status.InVBlank)
-+ {
-+ static const double tps = (double)osd_ticks_per_second();
-+ static const double time_start = (double)osd_ticks() / tps;
-+ osd_printf_verbose("renderer::end_frame(), probably missed retrace, entered at scanline %d, should break at %d, realtime is %f.\n", raster_status.ScanLine, m_break_scanline, (double)osd_ticks() / tps - time_start);
-+ }
-+ }
-+
-+ do
-+ {
-+ if (m_device->GetRasterStatus(0, &raster_status) != D3D_OK)
-+ break;
-+ } while (!raster_status.InVBlank && raster_status.ScanLine < m_break_scanline);
-+ }
-+
- // present the current buffers
- result = m_device->Present(nullptr, nullptr, nullptr, nullptr);
- if (FAILED(result))
- osd_printf_verbose("Direct3D: Error %08lX during device present call\n", result);
-+
-+ // sync to VBLANK-END
-+ if (video_config.framedelay && video_config.syncrefresh)
-+ {
-+ do
-+ {
-+ if (m_device->GetRasterStatus(0, &raster_status) != D3D_OK)
-+ break;
-+ } while (!raster_status.InVBlank);
-+ }
-+}
-+
-+void renderer_d3d9::device_flush()
-+{
-+ HRESULT result;
-+
-+ if(m_device)
-+ {
-+ if(m_query != nullptr)
-+ {
-+ m_query->Issue(D3DISSUE_END);
-+ do
-+ {
-+ result = m_query->GetData(NULL, 0, D3DGETDATA_FLUSH);
-+ if (result == D3DERR_DEVICELOST)
-+ return;
-+ } while(result == S_FALSE);
-+ }
-+ }
-+}
-+
-+void renderer_d3d9::update_break_scanlines()
-+{
-+ switch (m_vendor_id)
-+ {
-+ case 0x1002: // ATI
-+ m_first_scanline = m_switchres_mode && m_switchres_mode->vtotal ?
-+ (m_switchres_mode->vtotal - m_switchres_mode->vbegin) / (m_switchres_mode->interlace ? 2 : 1) :
-+ 1;
-+
-+ m_last_scanline = m_switchres_mode && m_switchres_mode->vtotal ?
-+ m_switchres_mode->vactive + (m_switchres_mode->vtotal - m_switchres_mode->vbegin) / (m_switchres_mode->interlace ? 2 : 1) :
-+ m_height;
-+ break;
-+
-+ case 0x8086: // Intel
-+ m_first_scanline = 1;
-+
-+ m_last_scanline = m_switchres_mode && m_switchres_mode->vtotal ?
-+ m_switchres_mode->vactive / (m_switchres_mode->interlace ? 2 : 1) :
-+ m_height;
-+ break;
-+
-+ default: // NVIDIA (0x10DE) + others (?)
-+ m_first_scanline = 0;
-+
-+ m_last_scanline = m_switchres_mode && m_switchres_mode->vtotal ?
-+ (m_switchres_mode->vactive - 1) / (m_switchres_mode->interlace ? 2 : 1) :
-+ m_height - 1;
-+ break;
-+ }
-+
-+ auto win = assert_window();
-+ m_break_scanline = m_last_scanline - win->machine().options().vsync_offset();
-+ m_break_scanline = m_break_scanline > m_first_scanline ? m_break_scanline : m_last_scanline;
-+ m_delay_scanline = m_first_scanline + m_height * (float)video_config.framedelay / 10;
-+
-+ osd_printf_verbose("Direct3D: Frame delay: %d, First scanline: %d, Last scanline: %d, Break scanline: %d, Delay scanline: %d\n", video_config.framedelay, m_first_scanline, m_last_scanline, m_break_scanline, m_delay_scanline);
- }
-
-+
- void renderer_d3d9::update_presentation_parameters()
- {
- auto win = assert_window();
-@@ -747,7 +859,7 @@ void renderer_d3d9::update_presentation_parameters()
- m_presentation.BackBufferWidth = m_width;
- m_presentation.BackBufferHeight = m_height;
- m_presentation.BackBufferFormat = m_pixformat;
-- m_presentation.BackBufferCount = video_config.triplebuf ? 2 : 1;
-+ m_presentation.BackBufferCount = 1;
- m_presentation.MultiSampleType = D3DMULTISAMPLE_NONE;
- m_presentation.SwapEffect = D3DSWAPEFFECT_DISCARD;
- m_presentation.hDeviceWindow = std::static_pointer_cast<win_window_info>(win)->platform_window();
-@@ -756,10 +868,10 @@ void renderer_d3d9::update_presentation_parameters()
- m_presentation.AutoDepthStencilFormat = D3DFMT_D16;
- m_presentation.Flags = 0;
- m_presentation.FullScreen_RefreshRateInHz = m_refresh;
-- m_presentation.PresentationInterval = (
-- (video_config.triplebuf && win->fullscreen())
-+ m_presentation.PresentationInterval = (video_config.framedelay == 0 &&
-+ ((video_config.triplebuf && win->fullscreen())
- || video_config.waitvsync
-- || video_config.syncrefresh)
-+ || video_config.syncrefresh))
- ? D3DPRESENT_INTERVAL_ONE
- : D3DPRESENT_INTERVAL_IMMEDIATE;
- }
-@@ -1184,6 +1296,34 @@ int renderer_d3d9::device_test_cooperative()
- }
-
-
-+//============================================================
-+// restart
-+//============================================================
-+
-+int renderer_d3d9::restart()
-+{
-+ // free all existing resources
-+ device_delete_resources();
-+
-+ // configure new video mode
-+ pick_best_mode();
-+ update_presentation_parameters();
-+
-+ // reset the device
-+ HRESULT result = m_device->Reset(&m_presentation);
-+ if (FAILED(result))
-+ {
-+ osd_printf_error("Unable to reset, result %08lX\n", result);
-+ return 1;
-+ }
-+
-+ // create the resources again
-+ device_create_resources();
-+
-+ return 0;
-+}
-+
-+
- //============================================================
- // config_adapter_mode
- //============================================================
-@@ -1203,6 +1343,9 @@ int renderer_d3d9::config_adapter_mode()
- }
-
- osd_printf_verbose("Direct3D: Configuring adapter #%d = %s\n", m_adapter, id.Description);
-+ osd_printf_verbose("Direct3D: Adapter has Vendor ID: %lX and Device ID: %lX\n", id.VendorId, id.DeviceId);
-+
-+ m_vendor_id = id.VendorId;
-
- // get the current display mode
- result = d3dintf->d3dobj->GetAdapterDisplayMode(m_adapter, &m_origmode);
-@@ -1219,6 +1362,9 @@ int renderer_d3d9::config_adapter_mode()
- {
- RECT client;
-
-+ // Disable SwitchRes
-+ m_switchres_mode = 0;
-+
- // bounds are from the window client rect
- GetClientRectExceptMenu(std::static_pointer_cast<win_window_info>(win)->platform_window(), &client, win->fullscreen());
- m_width = client.right - client.left;
-@@ -1302,6 +1448,20 @@ void renderer_d3d9::pick_best_mode()
-
- auto win = assert_window();
-
-+ // only link window #0 to SwitchRes
-+ if (win->m_index == 0)
-+ {
-+ m_switchres_mode = &win->machine().switchres.best_mode;
-+ if (m_switchres_mode)
-+ {
-+ m_width = m_switchres_mode->type & MODE_ROTATED? m_switchres_mode->height : m_switchres_mode->width;
-+ m_height = m_switchres_mode->type & MODE_ROTATED? m_switchres_mode->width : m_switchres_mode->height;
-+ m_refresh = (int)m_switchres_mode->refresh;
-+ m_interlace = m_switchres_mode->interlace;
-+ return;
-+ }
-+ }
-+
- // determine the refresh rate of the primary screen
- const screen_device *primary_screen = screen_device_iterator(win->machine().root_device()).first();
- if (primary_screen != nullptr)
-@@ -1343,10 +1503,6 @@ void renderer_d3d9::pick_best_mode()
- if (mode.Width < minwidth || mode.Height < minheight)
- size_score *= 0.01f;
-
-- // if mode is smaller than we'd like, it only scores up to 0.1
-- if (mode.Width < target_width || mode.Height < target_height)
-- size_score *= 0.1f;
--
- // if we're looking for a particular mode, that's a winner
- if (mode.Width == win->m_win_config.width && mode.Height == win->m_win_config.height)
- size_score = 2.0f;
-@@ -1354,10 +1510,6 @@ void renderer_d3d9::pick_best_mode()
- // compute refresh score
- float refresh_score = 1.0f / (1.0f + fabs((double)mode.RefreshRate - target_refresh));
-
-- // if refresh is smaller than we'd like, it only scores up to 0.1
-- if ((double)mode.RefreshRate < target_refresh)
-- refresh_score *= 0.1f;
--
- // if we're looking for a particular refresh, make sure it matches
- if (mode.RefreshRate == win->m_win_config.refresh)
- refresh_score = 2.0f;
-diff --git a/src/osd/modules/render/drawd3d.h b/src/osd/modules/render/drawd3d.h
-index 03527d7374e..5f0637698d0 100644
---- a/src/osd/modules/render/drawd3d.h
-+++ b/src/osd/modules/render/drawd3d.h
-@@ -67,6 +67,8 @@ public:
- virtual void add_audio_to_recording(const int16_t *buffer, int samples_this_frame) override;
- virtual std::vector<ui::menu_item> get_slider_list() override;
- virtual void set_sliders_dirty() override;
-+ virtual int restart() override;
-+ inline BOOL GetClientRectExceptMenu(HWND hWnd, PRECT pRect, BOOL fullscreen);
-
- int initialize();
-
-@@ -74,6 +76,8 @@ public:
- int device_create_resources();
- void device_delete();
- void device_delete_resources();
-+ void device_flush();
-+ void update_break_scanlines();
- void update_presentation_parameters();
- void update_gamma_ramp();
-
-@@ -134,9 +138,16 @@ public:
-
- private:
- int m_adapter; // ordinal adapter number
-+ int m_vendor_id; // adapter vendor id
- int m_width; // current width
- int m_height; // current height
- int m_refresh; // current refresh rate
-+ bool m_interlace; // current interlace
-+ int m_frame_delay; // current frame delay value
-+ int m_first_scanline; // first scanline number (visible)
-+ int m_last_scanline; // last scanline number (visible)
-+ int m_delay_scanline; // scanline number supposed to be after frame delay
-+ int m_break_scanline; // break scanline number, for vsync offset
- int m_create_error_count; // number of consecutive create errors
-
- IDirect3DDevice9 * m_device; // pointer to the Direct3DDevice object
-@@ -144,6 +155,7 @@ private:
- D3DPRESENT_PARAMETERS m_presentation; // set of presentation parameters
- D3DDISPLAYMODE m_origmode; // original display mode for the adapter
- D3DFORMAT m_pixformat; // pixel format we are using
-+ IDirect3DQuery9 * m_query;
-
- IDirect3DVertexBuffer9 *m_vertexbuf; // pointer to the vertex buffer object
- vertex * m_lockedbuf; // pointer to the locked vertex buffer
-diff --git a/src/osd/modules/render/drawogl.cpp b/src/osd/modules/render/drawogl.cpp
-index ae030224e74..02934712fea 100644
---- a/src/osd/modules/render/drawogl.cpp
-+++ b/src/osd/modules/render/drawogl.cpp
-@@ -40,6 +40,13 @@
- #include "modules/opengl/gl_shader_tool.h"
- #include "modules/opengl/gl_shader_mgr.h"
-
-+#ifdef SDLMAME_X11
-+// DRM
-+#include <xf86drm.h>
-+#include <xf86drmMode.h>
-+#include <fcntl.h>
-+#endif
-+
- #if defined(SDLMAME_MACOSX) || defined(OSD_MAC)
- #include <cstring>
- #include <cstdio>
-@@ -245,6 +252,10 @@ void renderer_ogl::set_blendmode(int blendmode)
- // STATIC VARIABLES
- //============================================================
-
-+#ifdef SDLMAME_X11
-+static int drawogl_drm_open(void);
-+#endif
-+
- // OGL 1.3
- #if defined(GL_ARB_multitexture) && !defined(OSD_MAC)
- static PFNGLACTIVETEXTUREARBPROC pfn_glActiveTexture = nullptr;
-@@ -578,7 +589,11 @@ int renderer_ogl::create()
- osd_printf_error("%s\n", m_gl_context->LastErrorMsg());
- return 1;
- }
-- m_gl_context->SetSwapInterval(video_config.waitvsync ? 1 : 0);
-+#ifdef SDLMAME_X11
-+ // Try to open DRM device
-+ m_fd = drawogl_drm_open();
-+#endif
-+ m_gl_context->SetSwapInterval((video_config.waitvsync && m_fd == 0) ? 1 : 0);
-
-
- m_blittimer = 0;
-@@ -605,6 +620,26 @@ int renderer_ogl::create()
- return 0;
- }
-
-+#ifdef SDLMAME_X11
-+//============================================================
-+// drawogl_drm_open
-+//============================================================
-+
-+static int drawogl_drm_open(void)
-+{
-+ int fd = 0;
-+ const char *node = {"/dev/dri/card0"};
-+
-+ fd = open(node, O_RDWR | O_CLOEXEC);
-+ if (fd < 0)
-+ {
-+ fprintf(stderr, "cannot open %s\n", node);
-+ return 0;
-+ }
-+ osd_printf_verbose("%s successfully opened\n", node);
-+ return fd;
-+}
-+#endif
-
- //============================================================
- // drawsdl_xy_to_render_target
-@@ -1419,6 +1454,19 @@ int renderer_ogl::draw(const int update)
- win->m_primlist->release_lock();
- m_init_context = 0;
-
-+#ifdef SDLMAME_X11
-+ // wait for vertical retrace
-+ if (video_config.waitvsync && m_fd)
-+ {
-+ drmVBlank vbl;
-+ memset(&vbl, 0, sizeof(vbl));
-+ vbl.request.type = DRM_VBLANK_RELATIVE;
-+ vbl.request.sequence = 1;
-+ if (drmWaitVBlank(m_fd, &vbl) != 0)
-+ osd_printf_verbose("drmWaitVBlank failed\n");
-+ }
-+#endif
-+
- m_gl_context->SwapBuffer();
-
- return 0;
-@@ -1645,6 +1693,7 @@ void renderer_ogl::texture_compute_size_type(const render_texinfo *texsource, og
- texture->rawheight_create = finalheight_create;
- }
-
-+
- //============================================================
- // texture_create
- //============================================================
-diff --git a/src/osd/modules/render/drawogl.h b/src/osd/modules/render/drawogl.h
-index 525ba0c3ffa..165703f9c67 100644
---- a/src/osd/modules/render/drawogl.h
-+++ b/src/osd/modules/render/drawogl.h
-@@ -125,6 +125,7 @@ public:
- , m_last_vofs(0.0f)
- , m_surf_w(0)
- , m_surf_h(0)
-+ , m_fd(0)
- {
- for (int i=0; i < HASH_SIZE + OVERFLOW_SIZE; i++)
- m_texhash[i] = nullptr;
-@@ -237,6 +238,8 @@ private:
-
- static bool s_shown_video_info;
- static bool s_dll_loaded;
-+ // DRM file handle
-+ int m_fd;
- };
-
- #endif // __DRAWOGL__
-diff --git a/src/osd/modules/sound/direct_sound.cpp b/src/osd/modules/sound/direct_sound.cpp
-index 05333674541..1ef1a76ad51 100644
---- a/src/osd/modules/sound/direct_sound.cpp
-+++ b/src/osd/modules/sound/direct_sound.cpp
-@@ -432,6 +432,7 @@ HRESULT sound_direct_sound::dsound_init()
- stream_buffer_size = std::max(DWORD(1024), (stream_buffer_size / 1024) * 1024);
-
- LOG(("stream_buffer_size = %u\n", (unsigned)stream_buffer_size));
-+ osd_printf_verbose("stream_buffer_size = %u\n", (unsigned)stream_buffer_size);
-
- // create the buffers
- m_bytes_per_sample = stream_format.nBlockAlign;
-diff --git a/src/osd/modules/sound/sdl_sound.cpp b/src/osd/modules/sound/sdl_sound.cpp
-index 5ff8f2e6821..8c8d80cdf94 100644
---- a/src/osd/modules/sound/sdl_sound.cpp
-+++ b/src/osd/modules/sound/sdl_sound.cpp
-@@ -333,7 +333,7 @@ void sound_sdl::sdl_callback(void *userdata, Uint8 *stream, int len)
- int sound_sdl::init(const osd_options &options)
- {
- int n_channels = 2;
-- int audio_latency;
-+ float audio_latency;
- SDL_AudioSpec aspec, obtained;
- char audio_driver[16] = "";
-
-diff --git a/src/osd/osdcore.cpp b/src/osd/osdcore.cpp
-index fd696706e6b..fee08261a4f 100644
---- a/src/osd/osdcore.cpp
-+++ b/src/osd/osdcore.cpp
-@@ -133,13 +133,20 @@ void osd_vprintf_debug(util::format_argument_pack<std::ostream> const &args)
- }
-
-
-+#ifdef OSD_WINDOWS
-+ typedef std::chrono::steady_clock s_clock;
-+#else
-+ typedef std::chrono::high_resolution_clock s_clock;
-+#endif
-+
-+
- //============================================================
- // osd_ticks
- //============================================================
-
- osd_ticks_t osd_ticks()
- {
-- return std::chrono::high_resolution_clock::now().time_since_epoch().count();
-+ return s_clock::now().time_since_epoch().count();
- }
-
-
-@@ -149,7 +156,7 @@ osd_ticks_t osd_ticks()
-
- osd_ticks_t osd_ticks_per_second()
- {
-- return std::chrono::high_resolution_clock::period::den / std::chrono::high_resolution_clock::period::num;
-+ return s_clock::period::den / s_clock::period::num;
- }
-
- //============================================================
-@@ -162,7 +169,7 @@ void osd_sleep(osd_ticks_t duration)
- // sleep_for appears to oversleep on Windows with gcc 8
- Sleep(duration / (osd_ticks_per_second() / 1000));
- #else
-- std::this_thread::sleep_for(std::chrono::high_resolution_clock::duration(duration));
-+ std::this_thread::sleep_for(s_clock::duration(duration));
- #endif
- }
-
-diff --git a/src/osd/sdl/osdsdl.h b/src/osd/sdl/osdsdl.h
-index 4cbec2d9d14..48788a90aae 100644
---- a/src/osd/sdl/osdsdl.h
-+++ b/src/osd/sdl/osdsdl.h
-@@ -22,7 +22,6 @@
- #define SDLOPTION_SCALEMODE "scalemode"
-
- #define SDLOPTION_WAITVSYNC "waitvsync"
--#define SDLOPTION_SYNCREFRESH "syncrefresh"
- #define SDLOPTION_KEYMAP "keymap"
- #define SDLOPTION_KEYMAP_FILE "keymap_file"
-
-@@ -143,6 +142,8 @@ public:
- bool should_hide_mouse();
- void process_events_buf();
-
-+ void extract_video_config();
-+
- virtual sdl_options &options() override { return m_options; }
-
- protected:
-@@ -152,7 +153,6 @@ protected:
- private:
- virtual void osd_exit() override;
-
-- void extract_video_config();
- void output_oslog(const char *buffer);
-
- sdl_options &m_options;
-diff --git a/src/osd/sdl/sdlmain.cpp b/src/osd/sdl/sdlmain.cpp
-index 37d1434a2e8..0ac77667cdc 100644
---- a/src/osd/sdl/sdlmain.cpp
-+++ b/src/osd/sdl/sdlmain.cpp
-@@ -62,6 +62,10 @@
- #endif // INI_PATH
-
-
-+extern bool switchres_modeline_setup(running_machine &machine);
-+extern bool switchres_modeline_reset(running_machine &machine);
-+extern bool switchres_modeline_remove(running_machine &machine);
-+
- //============================================================
- // Global variables
- //============================================================
-@@ -257,6 +261,10 @@ void sdl_osd_interface::osd_exit()
- osd_common_t::osd_exit();
-
- SDL_QuitSubSystem(SDL_INIT_VIDEO);
-+
-+ // SwitchRes modeline removal
-+ switchres_modeline_reset(machine());
-+ switchres_modeline_remove(machine());
- }
-
- //============================================================
-@@ -415,6 +423,10 @@ void sdl_osd_interface::init(running_machine &machine)
-
- const char *stemp;
-
-+ // Switchres
-+ switchres_init_osd(machine);
-+ switchres_modeline_setup(machine);
-+
- // determine if we are benchmarking, and adjust options appropriately
- int bench = options().bench();
- if (bench > 0)
-diff --git a/src/osd/sdl/switchres_sdl.cpp b/src/osd/sdl/switchres_sdl.cpp
-new file mode 100644
-index 00000000000..19e0582d131
---- /dev/null
-+++ b/src/osd/sdl/switchres_sdl.cpp
-@@ -0,0 +1,606 @@
-+/**************************************************************
-+
-+ switchres_sdl.cpp - SDL OSD SwitchRes core routines
-+
-+ ---------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2017 - Chris Kennedy, Antonio Giner, Alexandre W
-+
-+ **************************************************************/
-+
-+// SDL headers
-+#include "SDL_syswm.h"
-+
-+// MAME headers
-+#include "osdepend.h"
-+#include "emu.h"
-+#include "emuopts.h"
-+#include "../../frontend/mame/mameopts.h"
-+
-+// MAMEOS headers
-+#include "video.h"
-+#include "input.h"
-+#include "output.h"
-+#include "osdsdl.h"
-+#include "window.h"
-+
-+// X11 Xrandr headers
-+#include <X11/extensions/Xrandr.h>
-+
-+#define XRANDR_ARGS ""
-+#define min(a,b)({ __typeof__ (a) _a = (a);__typeof__ (b) _b = (b);_a < _b ? _a : _b; })
-+
-+#define XRANDR_TIMING 0x00000020
-+extern int fd;
-+
-+//============================================================
-+// PROTOTYPES
-+//============================================================
-+
-+bool switchres_init_osd(running_machine &machine);
-+bool switchres_modeline_setup(running_machine &machine);
-+bool switchres_modeline_remove(running_machine &machine);
-+bool switchres_modeline_reset(running_machine &machine);
-+bool switchres_resolution_change(sdl_window_info *window);
-+static bool add_custom_video_mode(modeline *mode, char *connector);
-+static bool set_custom_video_mode(modeline *mode, char *connector);
-+static int del_custom_video_mode(modeline *mode, char *connector);
-+static void set_option_osd(running_machine &machine, const char *option_ID, bool state);
-+
-+//============================================================
-+// LOCAL VARIABLES
-+//============================================================
-+
-+int mode_count = 1;
-+
-+//============================================================
-+// XRANDR
-+//============================================================
-+
-+static Display *dpy;
-+static Window root;
-+
-+static short original_rate;
-+static Rotation original_rotation;
-+static SizeID original_size_id;
-+static int width = 0;
-+static int height = 0;
-+
-+static int gmoutput_primary = 0;
-+static int gmoutput_mode = 0;
-+
-+static int (*old_error_handler)(Display *, XErrorEvent *);
-+
-+static int xerrors = 0;
-+
-+static int error_handler (Display *dpy, XErrorEvent *err)
-+{
-+ xerrors++;
-+ return 0;
-+} /* xorg_error_handler() */
-+
-+//============================================================
-+// switchres_init_osd
-+//============================================================
-+
-+bool switchres_init_osd(running_machine &machine)
-+{
-+ config_settings *cs = &machine.switchres.cs;
-+ game_info *game = &machine.switchres.game;
-+ modeline *mode_table = machine.switchres.video_modes;
-+ modeline *user_mode = &machine.switchres.user_mode;
-+ monitor_range *range = machine.switchres.range;
-+ const char * aspect;
-+ char *connector = machine.switchres.cs.connector;
-+ char resolution[32]={'\x00'};
-+
-+ sdl_options &options = downcast<sdl_options &>(machine.options());
-+
-+ // Initialize structures and config settings
-+ memset(cs, 0, sizeof(struct config_settings));
-+ memset(game, 0, sizeof(struct game_info));
-+
-+ // Init Switchres common info
-+ switchres_init(machine);
-+
-+ // Complete config settings
-+ strcpy(resolution, options.resolution());
-+ cs->monitor_count = options.numscreens();
-+
-+ // Get current resolution
-+ int screen = -1;
-+
-+ // dpy is global to reduce open/close calls, resource is freed when modeline is reset
-+ dpy = XOpenDisplay(NULL);
-+ int major_version, minor_version;
-+ XRRQueryVersion(dpy, &major_version, &minor_version);
-+ osd_printf_verbose("SwitchRes: xrandr version %d.%d\n",major_version,minor_version);
-+
-+ // select current display and root window
-+ // root is global to reduce open/close calls, resource is freed when modeline is reset
-+ screen = DefaultScreen(dpy); // multiple screen ScreenCount (dpy)
-+ root = RootWindow(dpy, screen);
-+ XRRScreenResources *res = XRRGetScreenResourcesCurrent(dpy, root);
-+
-+ // get screen size, rate and rotation from screen configuration
-+ XRRScreenConfiguration *sc = XRRGetScreenInfo(dpy, root);
-+ original_rate = XRRConfigCurrentRate(sc);
-+ original_size_id = XRRConfigCurrentConfiguration(sc, &original_rotation);
-+ XRRFreeScreenConfigInfo(sc);
-+
-+ Rotation current_rotation = 0;
-+ for (int o = 0; o < res->noutput && !gmoutput_mode; o++)
-+ {
-+ XRROutputInfo *output_info = XRRGetOutputInfo (dpy, res, res->outputs[o]);
-+ if (!output_info)
-+ osd_printf_error("SwitchRes: error could not get output 0x%x information\n", (uint) res->outputs[o]);
-+
-+ // first connected output
-+ if (output_info->connection == RR_Connected)
-+ {
-+ for (int j = 0; j < output_info->nmode && !gmoutput_mode; j++)
-+ {
-+ if ( output_info->crtc )
-+ {
-+ XRRCrtcInfo *crtc_info = XRRGetCrtcInfo(dpy, res, output_info->crtc);
-+ current_rotation = crtc_info->rotation;
-+ if (!strcmp(cs->connector, "auto") || !strcmp(cs->connector,output_info->name))
-+ {
-+ // connector name is kept but not necessary due to global gmoutput_primary varial, optimization can happen here
-+ sprintf(connector,"%s", output_info->name);
-+ osd_printf_verbose("SwitchRes: Found output connector '%s'\n", connector);
-+ gmoutput_primary = o;
-+ }
-+ for (int m = 0; m < res->nmode && !gmoutput_mode; m++)
-+ {
-+ XRRModeInfo *mode = &res->modes[m];
-+ // get screen mode
-+ if (crtc_info->mode == mode->id)
-+ {
-+ gmoutput_mode = mode->id;
-+ width = crtc_info->x + crtc_info->width;
-+ height = crtc_info->y + crtc_info->height;
-+ }
-+ }
-+ }
-+ if (current_rotation & 0xe) // screen rotation is left or right
-+ {
-+ osd_printf_verbose("Switchres: desktop rotation is %s\n",(current_rotation & 0x2)?"left":((current_rotation & 0x8)?"right":"inverted"));
-+ cs->desktop_rotated = 1;
-+ }
-+ }
-+ }
-+ XRRFreeOutputInfo(output_info);
-+ }
-+ XRRFreeScreenResources(res);
-+
-+ // Get per window resolution
-+ strcpy(resolution, strcmp(options.resolution(0), "auto")? options.resolution(0) : options.resolution());
-+
-+ // Get monitor aspect
-+ aspect = strcmp(options.aspect(0), "auto")? options.aspect(0) : options.aspect();
-+ if (strcmp(aspect, "auto"))
-+ {
-+ float num, den;
-+ sscanf(aspect, "%f:%f", &num, &den);
-+ cs->monitor_aspect = cs->desktop_rotated? den/num : num/den;
-+ }
-+ else
-+ cs->monitor_aspect = STANDARD_CRT_ASPECT;
-+
-+ // Create dummy mode table
-+ mode_table[1].width = mode_table[1].height = 1;
-+ mode_table[1].refresh = 60;
-+ mode_table[1].vfreq = mode_table[1].refresh;
-+ mode_table[1].hactive = mode_table[1].vactive = 1;
-+ mode_table[1].type = XYV_EDITABLE | XRANDR_TIMING | (cs->desktop_rotated? MODE_ROTATED : MODE_OK);
-+
-+ if (user_mode->hactive)
-+ {
-+ user_mode->width = user_mode->hactive;
-+ user_mode->height = user_mode->vactive;
-+ user_mode->refresh = int(user_mode->refresh);
-+ user_mode->type = XRANDR_TIMING | MODE_USER_DEF | (cs->desktop_rotated? MODE_ROTATED : MODE_OK);
-+ }
-+
-+ // Create automatic specs and force resolution for LCD monitors
-+ if (!strcmp(cs->monitor, "lcd"))
-+ {
-+ modeline current;
-+ memset(&current, 0, sizeof(struct modeline));
-+
-+ osd_printf_verbose("SwitchRes: Creating automatic specs for LCD based on VESA GTF\n");
-+ current.width = width;
-+ current.height = height;
-+ current.refresh = 60;
-+ modeline_vesa_gtf(&current);
-+ modeline_to_monitor_range(range, &current);
-+ monitor_show_range(range);
-+
-+ sprintf(resolution, "%dx%d@%d", current.width, current.height, current.refresh);
-+ }
-+ // Otherwise (non-LCD), convert the user defined modeline into a -resolution option
-+ else if (user_mode->hactive)
-+ sprintf(resolution, "%dx%d", user_mode->hactive, user_mode->vactive);
-+
-+ // Get resolution from ini
-+ if (strcmp(resolution, "auto"))
-+ {
-+ osd_printf_verbose("SwitchRes: -resolution was set at command line or in .ini file as %s\n", resolution);
-+
-+ if ((sscanf(resolution, "%dx%d@%d", &cs->width, &cs->height, &cs->refresh) < 3) &&
-+ ((!strstr(resolution, "x") || (sscanf(resolution, "%dx%d", &cs->width, &cs->height) != 2))))
-+ osd_printf_info("SwitchRes: illegal -resolution value: %s\n", resolution);
-+ else
-+ {
-+ // Add the user's resolution to our table
-+ if (!user_mode->hactive)
-+ {
-+ mode_table[1].width = mode_table[1].hactive = cs->width? cs->width : 1;
-+ mode_table[1].height = mode_table[1].vactive = cs->height? cs->height : 1;
-+ mode_table[1].refresh = cs->refresh? int(cs->refresh) : 60;
-+ mode_table[1].vfreq = mode_table[1].refresh;
-+ mode_table[1].type |= MODE_USER_DEF;
-+ if (cs->width) mode_table[1].type &= ~X_RES_EDITABLE;
-+ if (cs->height) mode_table[1].type &= ~Y_RES_EDITABLE;
-+ }
-+ }
-+ }
-+ // Get game info
-+ switchres_get_game_info(machine);
-+
-+ return true;
-+}
-+
-+//============================================================
-+// switchres_modeline_setup
-+//============================================================
-+
-+bool switchres_modeline_setup(running_machine &machine)
-+{
-+ modeline *best_mode = &machine.switchres.best_mode;
-+ modeline *mode_table = machine.switchres.video_modes;
-+ char *connector = machine.switchres.cs.connector;
-+ sdl_options &options = downcast<sdl_options &>(machine.options());
-+ sdl_osd_interface &osd = downcast<sdl_osd_interface &>(machine.osd());
-+ std::string error_string;
-+
-+ osd_printf_verbose("\nSwitchRes: Entering switchres_modeline_setup\n");
-+
-+ // Find most suitable video mode and generate a modeline for it if we're allowed
-+ if (!switchres_get_video_mode(machine))
-+ {
-+ set_option_osd(machine, OSDOPTION_SWITCHRES, false);
-+ return false;
-+ }
-+
-+ // Make the new modeline available to the system
-+ if (machine.options().modeline_generation())
-+ {
-+ // Lock mode before adding it to mode table
-+ best_mode->type |= MODE_DISABLED;
-+
-+ // Check if the same mode had been created already
-+ int i;
-+ bool found = false;
-+ for (i = 2; i <= mode_count; i++)
-+ if (!memcmp(&mode_table[i], best_mode, sizeof(modeline) - sizeof(mode_result)))
-+ found = true;
-+
-+ // Create the new mode and store it in our table
-+ if (!found)
-+ {
-+ mode_count++;
-+ memcpy(&mode_table[mode_count], best_mode, sizeof(modeline));
-+ add_custom_video_mode(best_mode, connector);
-+ }
-+
-+ // Switch to the new mode
-+ set_custom_video_mode(best_mode, connector);
-+ }
-+
-+ // Set MAME common options
-+ switchres_set_options(machine);
-+
-+ // Black frame insertion / multithreading
-+ bool black_frame_insertion = options.black_frame_insertion() && best_mode->result.v_scale > 1 && best_mode->vfreq > 100;
-+ set_option_osd(machine, OPTION_BLACK_FRAME_INSERTION, black_frame_insertion);
-+
-+ // Set MAME OSD specific options
-+
-+ // Vertical synchronization management (autosync)
-+ // Disable -syncrefresh if our vfreq is scaled or out of syncrefresh_tolerance
-+ bool sync_refresh_effective = black_frame_insertion || !((best_mode->result.weight & R_V_FREQ_OFF) || best_mode->result.v_scale > 1);
-+ set_option_osd(machine, OPTION_SYNCREFRESH, options.autosync()? sync_refresh_effective : options.sync_refresh());
-+ set_option_osd(machine, OSDOPTION_WAITVSYNC, options.sync_refresh()? options.sync_refresh() : options.wait_vsync());
-+
-+ // Set filter options
-+ set_option_osd(machine, OSDOPTION_FILTER, ((best_mode->result.weight & R_RES_STRETCH || best_mode->interlace)));
-+
-+ // Refresh video options
-+ osd.extract_video_config();
-+
-+ return true;
-+}
-+
-+//============================================================
-+// switchres_modeline_remove
-+//============================================================
-+
-+bool switchres_modeline_remove(running_machine &machine)
-+{
-+ return true;
-+}
-+
-+//============================================================
-+// switchres_modeline_reset
-+//============================================================
-+
-+bool switchres_modeline_reset(running_machine &machine)
-+{
-+ config_settings *cs = &machine.switchres.cs;
-+ modeline *mode_table = machine.switchres.video_modes;
-+
-+ // Restore desktop resolution
-+ XRRScreenResources *res = XRRGetScreenResourcesCurrent(dpy, root);
-+ XRRScreenConfiguration *sc = XRRGetScreenInfo(dpy, root);
-+
-+ XRRSetScreenConfigAndRate(dpy, sc, root, original_size_id, original_rotation, original_rate, CurrentTime);
-+ XRRFreeScreenConfigInfo(sc);
-+ XRRFreeScreenResources(res);
-+
-+ osd_printf_verbose("SwitchRes: xrandr original video mode restored.\n");
-+
-+ // Remove modelines
-+ while (mode_count > 1)
-+ {
-+ del_custom_video_mode(&mode_table[mode_count], cs->connector);
-+ mode_count--;
-+ }
-+
-+ XCloseDisplay(dpy);
-+ return true;
-+}
-+
-+//============================================================
-+// switchres_resolution_change
-+//============================================================
-+
-+bool switchres_resolution_change(sdl_window_info *window)
-+{
-+ running_machine &machine = window->machine();
-+ modeline *best_mode = &machine.switchres.best_mode;
-+ modeline previous_mode;
-+
-+ // If there's no pending change, just exit
-+ if (!switchres_check_resolution_change(machine))
-+ return false;
-+
-+ // Get the new resolution
-+ previous_mode = *best_mode;
-+ switchres_modeline_setup(machine);
-+
-+ // Only change resolution if the new one is actually different
-+ if (memcmp(&previous_mode, best_mode, offsetof(modeline, result)))
-+ return true;
-+
-+ return false;
-+}
-+
-+//============================================================
-+// add_custom_video_mode
-+//============================================================
-+
-+static bool add_custom_video_mode(modeline *mode, char *connector)
-+{
-+ if (!mode)
-+ return false;
-+
-+ // Add modeline to interface
-+ char name[48];
-+ sprintf(name,"GM-%dx%d_%.6f",mode->hactive, mode->vactive, mode->vfreq); // add ID
-+
-+ // Setup the xrandr mode structure
-+ XRRModeInfo xmode;
-+ xmode.name = name;
-+ xmode.nameLength = strlen(name);
-+ xmode.dotClock = float(mode->pclock);
-+ xmode.width = mode->hactive;
-+ xmode.hSyncStart = mode->hbegin;
-+ xmode.hSyncEnd = mode->hend;
-+ xmode.hTotal = mode->htotal;
-+ xmode.height = mode->vactive;
-+ xmode.vSyncStart = mode->vbegin;
-+ xmode.vSyncEnd = mode->vend;
-+ xmode.vTotal = mode->vtotal;
-+ xmode.modeFlags = (mode->interlace?RR_Interlace:0) | (mode->doublescan?RR_DoubleScan:0) | (mode->hsync?RR_HSyncPositive:RR_HSyncNegative) | (mode->vsync?RR_VSyncPositive:RR_VSyncNegative);
-+
-+ // Create the modeline
-+ XSync(dpy, False);
-+ xerrors = 0;
-+ old_error_handler = XSetErrorHandler(error_handler);
-+ RRMode gmid = XRRCreateMode(dpy, root, &xmode);
-+ XSync(dpy, False);
-+ XSetErrorHandler(old_error_handler);
-+ if (xerrors)
-+ osd_printf_error("Switchres: xrandr error in %s\n","XRRCreateMode");
-+
-+ // Add new modeline to primary output
-+ XRRScreenResources *res = XRRGetScreenResourcesCurrent(dpy, root);
-+
-+ XSync(dpy, False);
-+ xerrors = 0;
-+ old_error_handler = XSetErrorHandler(error_handler);
-+ XRRAddOutputMode(dpy, res->outputs[gmoutput_primary], gmid);
-+ XSync(dpy, False);
-+ XSetErrorHandler(old_error_handler);
-+ if (xerrors)
-+ osd_printf_error("Switchres: xrandr error in %s\n","XRRAddOutputMode");
-+
-+ XRRFreeScreenResources(res);
-+ return true;
-+}
-+
-+//============================================================
-+// set_custom_video_mode
-+//============================================================
-+
-+static bool set_custom_video_mode(modeline *mode, char *connector)
-+{
-+ // Use xrandr to switch to new mode. SDL_SetVideoMode doesn't work when (new_width, new_height)==(old_width, old_height)
-+ char name[48];
-+ sprintf(name,"GM-%dx%d_%.6f",mode->hactive, mode->vactive, mode->vfreq); // add ID
-+
-+ XRRScreenResources *res = XRRGetScreenResourcesCurrent(dpy, root);
-+ XRROutputInfo *output_info = XRRGetOutputInfo(dpy, res, res->outputs[gmoutput_primary]);
-+ XRRCrtcInfo *crtc_info = XRRGetCrtcInfo(dpy, res, output_info->crtc);
-+
-+ // Select corresponding mode from modeline, can be enhanced by saving mode index to modeline structure
-+ XRRModeInfo *xmode=0;
-+ for (int m = 0; m < res->nmode; m++)
-+ {
-+ XRRModeInfo *tmp_mode = &res->modes[m];
-+ if (!strcmp(name, tmp_mode->name))
-+ {
-+ xmode = &res->modes[m];
-+ }
-+ }
-+
-+ // Grab X server to prevent unwanted interaction from the window manager
-+ XGrabServer(dpy);
-+
-+ // Disable all CRTCs
-+ for (int i = 0; i < output_info->ncrtc; i++)
-+ {
-+ if (XRRSetCrtcConfig(dpy, res, output_info->crtcs[i], CurrentTime, 0, 0, None, RR_Rotate_0, NULL, 0) != RRSetConfigSuccess)
-+ osd_printf_error("Switchres: xrandr error when disabling CRTC.\n");
-+ }
-+ osd_printf_verbose("Switchres: CRTC %d: mode %#lx, %ux%u+%d+%d.\n", 0, crtc_info->mode,crtc_info->width, crtc_info->height, crtc_info->x, crtc_info->y);
-+
-+ // Check if framebuffer size is correct
-+ int change_resolution = 0;
-+ if (width < crtc_info->x + mode->hactive)
-+ {
-+ width = crtc_info->x + mode->hactive;
-+ change_resolution = 1;
-+ }
-+ if (height < crtc_info->y + mode->vactive)
-+ {
-+ height = crtc_info->y + mode->vactive;
-+ change_resolution = 1;
-+ }
-+
-+ // Enlarge the screen size for the new mode
-+ if (change_resolution)
-+ {
-+ osd_printf_verbose("Switchres: xrandr change screen size.\n");
-+ XSync(dpy, False);
-+ xerrors = 0;
-+ old_error_handler = XSetErrorHandler(error_handler);
-+ XRRSetScreenSize(dpy, root, width, height, (25.4 * width) / 96.0, (25.4 * height) / 96.0);
-+ XSync(dpy, False);
-+ XSetErrorHandler(old_error_handler);
-+ if (xerrors)
-+ osd_printf_error("Switchres: xrandr error in %s\n","XRRSetScreenSize");
-+ }
-+
-+ // Switch to new modeline
-+ XSync(dpy, False);
-+ xerrors = 0;
-+ old_error_handler = XSetErrorHandler(error_handler);
-+ XRRSetCrtcConfig(dpy, res, output_info->crtc, CurrentTime , crtc_info->x, crtc_info->y, xmode->id, original_rotation, crtc_info->outputs, crtc_info->noutput);
-+ XSync(dpy, False);
-+ XSetErrorHandler(old_error_handler);
-+
-+ XRRFreeCrtcInfo(crtc_info);
-+
-+ if (xerrors)
-+ osd_printf_error("Switchres: xrandr error in %s\n","XRRSetCrtcConfig");
-+
-+ // Release X server, events can be processed now
-+ XUngrabServer(dpy);
-+
-+ crtc_info = XRRGetCrtcInfo(dpy, res, output_info->crtc); // recall crtc to settle parameters
-+
-+ // If the crtc config modeline change fails, revert to original mode (prevents ending with black screen due to all crtc disabled)
-+ if (crtc_info->mode == 0)
-+ {
-+ osd_printf_error("Switchres: xrandr resolution switch error, original mode restored\n");
-+ XRRScreenConfiguration *sc = XRRGetScreenInfo(dpy, root);
-+ XRRSetScreenConfigAndRate(dpy, sc, root, original_size_id, original_rotation, original_rate, CurrentTime);
-+ XRRFreeScreenConfigInfo(sc);
-+ }
-+
-+ // check, verify current active mode
-+ for (int m = 0; m < res->nmode; m++)
-+ {
-+ XRRModeInfo *mode = &res->modes[m];
-+ if (mode->id == crtc_info->mode)
-+ osd_printf_verbose("Switchres: xrandr mode (%s) (0x%x) %6.6fMHz\n", mode->name, (int)mode->id,(double)mode->dotClock / 1000000.0);
-+ }
-+
-+ XRRFreeCrtcInfo(crtc_info);
-+ XRRFreeOutputInfo(output_info);
-+ XRRFreeScreenResources(res);
-+
-+ return true;
-+}
-+
-+//============================================================
-+// del_custom_video_mode
-+//============================================================
-+
-+static int del_custom_video_mode(modeline *mode, char *connector)
-+{
-+ if (!mode)
-+ return false;
-+
-+ char name[48];
-+ sprintf(name,"GM-%dx%d_%.6f",mode->hactive, mode->vactive, mode->vfreq); // add ID
-+
-+ XRRScreenResources *res = XRRGetScreenResourcesCurrent (dpy, root);
-+
-+ // Delete modeline
-+ for (int m = 0; m < res->nmode; m++)
-+ {
-+ XRRModeInfo *xmode = &res->modes[m];
-+ if (!strcmp(name, xmode->name))
-+ {
-+ XSync(dpy, False);
-+ xerrors = 0;
-+ old_error_handler = XSetErrorHandler(error_handler);
-+ XRRDeleteOutputMode (dpy, res->outputs[gmoutput_primary], xmode->id);
-+ if (xerrors)
-+ osd_printf_error("Switchres: xrandr error in %s\n","XRRDeleteOutputMode");
-+
-+ xerrors = 0;
-+ XRRDestroyMode (dpy, xmode->id);
-+ XSync(dpy, False);
-+ XSetErrorHandler(old_error_handler);
-+ if (xerrors)
-+ osd_printf_error("Switchres: xrandr error in %s\n","XRRDestroyMode");
-+ }
-+ }
-+
-+ XRRFreeScreenResources(res);
-+
-+ return true;
-+}
-+
-+//============================================================
-+// set_option_osd - option setting wrapper
-+//============================================================
-+
-+static void set_option_osd(running_machine &machine, const char *option_ID, bool state)
-+{
-+ sdl_options &options = downcast<sdl_options &>(machine.options());
-+
-+ options.set_value(option_ID, state, OPTION_PRIORITY_SWITCHRES);
-+ osd_printf_verbose("SwitchRes: Setting option -%s%s\n", machine.options().bool_value(option_ID)?"":"no", option_ID);
-+}
-diff --git a/src/osd/sdl/video.cpp b/src/osd/sdl/video.cpp
-index e7af55e56ba..8d1eeb1eaa8 100644
---- a/src/osd/sdl/video.cpp
-+++ b/src/osd/sdl/video.cpp
-@@ -247,12 +247,7 @@ void sdl_osd_interface::extract_video_config()
- video_config.centerh = options().centerh();
- video_config.centerv = options().centerv();
- video_config.waitvsync = options().wait_vsync();
-- video_config.syncrefresh = options().sync_refresh();
-- if (!video_config.waitvsync && video_config.syncrefresh)
-- {
-- osd_printf_warning("-syncrefresh specified without -waitvsync. Reverting to -nosyncrefresh\n");
-- video_config.syncrefresh = 0;
-- }
-+ video_config.syncrefresh = machine().options().sync_refresh();
-
- if (video_config.prescale < 1 || video_config.prescale > 8)
- {
-diff --git a/src/osd/sdl/window.cpp b/src/osd/sdl/window.cpp
-index 70886d76a73..83f6c5f035d 100644
---- a/src/osd/sdl/window.cpp
-+++ b/src/osd/sdl/window.cpp
-@@ -80,6 +80,7 @@ public:
- // PROTOTYPES
- //============================================================
-
-+extern bool switchres_resolution_change(sdl_window_info *window);
-
- //============================================================
- // window_init
-@@ -352,6 +353,23 @@ void sdl_window_info::modify_prescale(int dir)
- }
- }
-
-+void sdl_window_info::reset_fullscreen_renderer()
-+{
-+#if (SDLMAME_SDL2)
-+ if (this->fullscreen() && video_config.switchres)
-+ {
-+ complete_destroy();
-+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
-+ SDL_InitSubSystem(SDL_INIT_VIDEO);
-+ complete_create();
-+ }
-+#else
-+ if (this->fullscreen() && video_config.switchres)
-+ this->window_resize(window->minwidth, window->minheight);
-+#endif
-+}
-+
-+
- //============================================================
- // sdlwindow_update_cursor_state
- // (main or window thread)
-@@ -491,6 +509,14 @@ osd_dim sdl_window_info::pick_best_mode()
- float size_score, best_score = 0.0f;
- osd_dim ret(0,0);
-
-+ // check if we already have a best mode
-+ modeline *mode = &this->machine().switchres.best_mode;
-+ if (mode->hactive)
-+ {
-+ ret = osd_dim(mode->type & MODE_ROTATED? mode->vactive : mode->hactive, mode->type & MODE_ROTATED? mode->hactive : mode->vactive);
-+ return ret;
-+ }
-+
- // determine the minimum width/height for the selected target
- m_target->compute_minimum_size(minimum_width, minimum_height);
-
-@@ -584,8 +610,15 @@ void sdl_window_info::update()
- }
- else if (video_config.switchres)
- {
-- osd_dim tmp = this->pick_best_mode();
-- resize(tmp.width(), tmp.height());
-+ // check resolution change
-+ if (renderer().m_switchres_mode != nullptr && video_config.switchres && machine().options().changeres())
-+ {
-+ if (switchres_resolution_change(this))
-+ {
-+ reset_fullscreen_renderer();
-+ return;
-+ }
-+ }
- }
- }
-
-diff --git a/src/osd/sdl/window.h b/src/osd/sdl/window.h
-index d6010e91ed2..9b2ef28371b 100644
---- a/src/osd/sdl/window.h
-+++ b/src/osd/sdl/window.h
-@@ -73,7 +73,6 @@ public:
- // Pointer to next window
- sdl_window_info * m_next;
-
--private:
- // window handle and info
- char m_title[256];
- int m_startmaximized;
-@@ -105,6 +104,7 @@ private:
- void update_cursor_state();
- osd_dim pick_best_mode();
- void set_fullscreen(int afullscreen) { m_fullscreen = afullscreen; }
-+ void reset_fullscreen_renderer();
-
- // Pointer to machine
- running_machine & m_machine;
-diff --git a/src/osd/windows/custom_video.cpp b/src/osd/windows/custom_video.cpp
-new file mode 100644
-index 00000000000..a07fb6dc95c
---- /dev/null
-+++ b/src/osd/windows/custom_video.cpp
-@@ -0,0 +1,359 @@
-+/**************************************************************
-+
-+ custom_video.cpp - Custom video library
-+
-+ ---------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2016 - Chris Kennedy, Antonio Giner
-+
-+ **************************************************************/
-+
-+// standard windows headers
-+#include <windows.h>
-+
-+#include "emu.h"
-+#include "custom_video.h"
-+#include "custom_video_ati.h"
-+#include "custom_video_adl.h"
-+#include "custom_video_pstrip.h"
-+
-+extern bool ati_is_legacy(int vendor, int device);
-+
-+//============================================================
-+// LOCAL VARIABLES
-+//============================================================
-+
-+static int custom_method;
-+static modeline m_user_mode;
-+static modeline m_backup_mode;
-+static modeline *m_mode_table;
-+static char m_device_name[32];
-+static char m_device_key[128];
-+static char ps_timing[256];
-+
-+//============================================================
-+// custom_video_init
-+//============================================================
-+
-+bool custom_video_init(char *device_name, char *device_id, modeline *desktop_mode, modeline *user_mode, modeline *mode_table, int method, char *s_param)
-+{
-+ memset(&m_backup_mode, 0, sizeof(modeline));
-+ memcpy(&m_user_mode, user_mode, sizeof(modeline));
-+ memcpy(m_device_name, device_name, sizeof(m_device_name));
-+ m_mode_table = mode_table;
-+
-+ if ((method == CUSTOM_VIDEO_TIMING_POWERSTRIP) && ps_init(ps_monitor_index(m_device_name), &m_backup_mode))
-+ {
-+ custom_method = CUSTOM_VIDEO_TIMING_POWERSTRIP;
-+ m_backup_mode.type |= CUSTOM_VIDEO_TIMING_POWERSTRIP;
-+
-+ // If we have a -ps_timing string defined, use it as user defined modeline
-+ memcpy(ps_timing, s_param, sizeof(ps_timing));
-+ if (strcmp(ps_timing, "auto"))
-+ {
-+ MonitorTiming timing;
-+ if (ps_read_timing_string(ps_timing, &timing))
-+ {
-+ ps_pstiming_to_modeline(&timing, &m_user_mode);
-+ m_user_mode.type |= CUSTOM_VIDEO_TIMING_POWERSTRIP;
-+ memcpy(user_mode, &m_user_mode, sizeof(modeline));
-+
-+ char modeline_txt[256]={'\x00'};
-+ osd_printf_verbose("SwitchRes: ps_string: %s (%s)\n", ps_timing, modeline_print(&m_user_mode, modeline_txt, MS_PARAMS));
-+ }
-+ else osd_printf_verbose("Switchres: ps_timing string with invalid format\n");
-+ }
-+ return true;
-+ }
-+ else
-+ {
-+ int vendor, device;
-+ custom_video_parse_pci_id(device_id, &vendor, &device);
-+
-+ if (vendor == 0x1002) // ATI/AMD
-+ {
-+ if (ati_is_legacy(vendor, device))
-+ {
-+ memcpy(m_device_key, s_param, sizeof(m_device_key));
-+ if (ati_init(m_device_name, m_device_key, device_id))
-+ {
-+ custom_method = CUSTOM_VIDEO_TIMING_ATI_LEGACY;
-+ return true;
-+ }
-+ }
-+ else
-+ {
-+ memcpy(m_device_key, s_param, sizeof(m_device_key));
-+ if (adl_init(m_device_name, m_device_key, device_id))
-+ {
-+ custom_method = CUSTOM_VIDEO_TIMING_ATI_ADL;
-+ return true;
-+ }
-+ }
-+ }
-+ else
-+ osd_printf_info("Video chipset is not compatible.\n");
-+ }
-+
-+ return false;
-+}
-+
-+//============================================================
-+// custom_video_close
-+//============================================================
-+
-+void custom_video_close()
-+{
-+ switch (custom_method)
-+ {
-+ case CUSTOM_VIDEO_TIMING_ATI_LEGACY:
-+ break;
-+
-+ case CUSTOM_VIDEO_TIMING_ATI_ADL:
-+ adl_close();
-+ break;
-+
-+ case CUSTOM_VIDEO_TIMING_POWERSTRIP:
-+ break;
-+ }
-+}
-+
-+//============================================================
-+// custom_video_get_timing
-+//============================================================
-+
-+bool custom_video_get_timing(modeline *mode)
-+{
-+ char modeline_txt[256]={'\x00'};
-+
-+ switch (custom_method)
-+ {
-+ case CUSTOM_VIDEO_TIMING_ATI_LEGACY:
-+ if (ati_get_modeline(mode))
-+ {
-+ osd_printf_verbose("ATI legacy timing %s\n", modeline_print(mode, modeline_txt, MS_FULL));
-+ mode->type |= CUSTOM_VIDEO_TIMING_ATI_LEGACY | (!(mode->type & MODE_DESKTOP)? V_FREQ_EDITABLE | (mode->width == DUMMY_WIDTH? X_RES_EDITABLE:0):0);
-+ return true;
-+ }
-+ break;
-+
-+ case CUSTOM_VIDEO_TIMING_ATI_ADL:
-+ if (adl_get_modeline(m_device_name, mode))
-+ {
-+ osd_printf_verbose("ATI ADL timing %s\n", modeline_print(mode, modeline_txt, MS_FULL));
-+ mode->type |= CUSTOM_VIDEO_TIMING_ATI_ADL | (!(mode->type & MODE_DESKTOP)? V_FREQ_EDITABLE :0);
-+ return true;
-+ }
-+ break;
-+
-+ case CUSTOM_VIDEO_TIMING_POWERSTRIP:
-+ if ((mode->type & MODE_DESKTOP) && ps_get_modeline(ps_monitor_index(m_device_name), mode))
-+ osd_printf_verbose("Powerstrip timing %s\n", modeline_print(mode, modeline_txt, MS_FULL));
-+ else
-+ osd_printf_verbose("Not current mode\n");
-+
-+ mode->type |= CUSTOM_VIDEO_TIMING_POWERSTRIP | V_FREQ_EDITABLE;
-+ return true;
-+ }
-+
-+ osd_printf_verbose("system mode\n");
-+ mode->type |= CUSTOM_VIDEO_TIMING_SYSTEM;
-+ return false;
-+}
-+
-+//============================================================
-+// custom_video_set_timing
-+//============================================================
-+
-+bool custom_video_set_timing(modeline *mode)
-+{
-+ char modeline_txt[256]={'\x00'};
-+
-+ switch (custom_method)
-+ {
-+ case CUSTOM_VIDEO_TIMING_ATI_LEGACY:
-+ if (ati_set_modeline(mode))
-+ {
-+ osd_printf_verbose("ATI legacy timing %s\n", modeline_print(mode, modeline_txt, MS_FULL));
-+ return true;
-+ }
-+ break;
-+
-+ case CUSTOM_VIDEO_TIMING_ATI_ADL:
-+ if (adl_set_modeline(m_device_name, mode, mode->interlace != m_backup_mode.interlace? MODELINE_UPDATE_LIST : MODELINE_UPDATE))
-+ {
-+ osd_printf_verbose("ATI ADL timing %s\n", modeline_print(mode, modeline_txt, MS_FULL));
-+ return true;
-+ }
-+ break;
-+
-+ case CUSTOM_VIDEO_TIMING_POWERSTRIP:
-+ // In case -ps_timing is provided, pass it as raw string
-+ if (m_user_mode.type & CUSTOM_VIDEO_TIMING_POWERSTRIP)
-+ ps_set_monitor_timing_string(ps_monitor_index(m_device_name), (char*)ps_timing);
-+ // Otherwise pass it as modeline
-+ else
-+ ps_set_modeline(ps_monitor_index(m_device_name), mode);
-+
-+ osd_printf_verbose("Powerstrip timing %s\n", modeline_print(mode, modeline_txt, MS_FULL));
-+ Sleep(100);
-+ return true;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+ return false;
-+}
-+
-+//============================================================
-+// custom_video_restore_timing
-+//============================================================
-+
-+bool custom_video_restore_timing()
-+{
-+ if (!m_backup_mode.hactive)
-+ return false;
-+
-+ // Restore backup mode
-+ return custom_video_update_timing(0);
-+}
-+
-+//============================================================
-+// custom_video_refresh_timing
-+//============================================================
-+
-+void custom_video_refresh_timing()
-+{
-+ switch (custom_method)
-+ {
-+ case CUSTOM_VIDEO_TIMING_ATI_LEGACY:
-+ ati_refresh_timings();
-+ break;
-+
-+ case CUSTOM_VIDEO_TIMING_ATI_ADL:
-+ break;
-+
-+ case CUSTOM_VIDEO_TIMING_POWERSTRIP:
-+ break;
-+ }
-+}
-+
-+//============================================================
-+// custom_video_update_timing
-+//============================================================
-+
-+bool custom_video_update_timing(modeline *mode)
-+{
-+ switch (custom_method)
-+ {
-+ case CUSTOM_VIDEO_TIMING_ATI_LEGACY:
-+ case CUSTOM_VIDEO_TIMING_ATI_ADL:
-+
-+ // Restore old video timing
-+ if (m_backup_mode.hactive)
-+ {
-+ osd_printf_verbose("Switchres: restoring ");
-+ custom_video_set_timing(&m_backup_mode);
-+ }
-+
-+ // Update with new video timing
-+ if (mode)
-+ {
-+ // Backup current timing
-+ int found = 0;
-+ for (int i = 0; i <= MAX_MODELINES; i++)
-+ {
-+ if (m_mode_table[i].width == mode->width && m_mode_table[i].height == mode->height && m_mode_table[i].refresh == mode->refresh)
-+ {
-+ memcpy(&m_backup_mode, &m_mode_table[i], sizeof(modeline));
-+ found = 1;
-+ break;
-+ }
-+ }
-+ if (!found)
-+ {
-+ osd_printf_verbose("Switchres: mode not found in mode_table\n");
-+ return false;
-+ }
-+ osd_printf_verbose("Switchres: saving ");
-+ custom_video_get_timing(&m_backup_mode);
-+
-+ // Apply new timing now
-+ osd_printf_verbose("Switchres: updating ");
-+ if (!custom_video_set_timing(mode)) goto error;
-+ }
-+ custom_video_refresh_timing();
-+ break;
-+
-+ case CUSTOM_VIDEO_TIMING_POWERSTRIP:
-+ // We only backup/restore the desktop mode with Powerstrip
-+ if (!mode)
-+ ps_reset(ps_monitor_index(m_device_name));
-+ else
-+ {
-+ osd_printf_verbose("Switchres: updating ");
-+ custom_video_set_timing(mode);
-+ }
-+ break;
-+ }
-+ return true;
-+
-+error:
-+ osd_printf_verbose(": error updating video timings\n");
-+ return false;
-+}
-+
-+//============================================================
-+// custom_video_parse_timing
-+//============================================================
-+
-+bool custom_video_parse_timing(char *timing_string, modeline *user_mode)
-+{
-+ char modeline_txt[256]={'\x00'};
-+
-+ if (!strcmp(timing_string, "auto"))
-+ return false;
-+
-+ if (strstr(timing_string, "="))
-+ {
-+ // Powerstrip timing string
-+ MonitorTiming timing;
-+ ps_read_timing_string(timing_string, &timing);
-+ ps_pstiming_to_modeline(&timing, user_mode);
-+ user_mode->type |= CUSTOM_VIDEO_TIMING_POWERSTRIP;
-+ osd_printf_verbose("SwitchRes: ps_string: %s (%s)\n", timing_string, modeline_print(user_mode, modeline_txt, MS_PARAMS));
-+ }
-+ else
-+ {
-+ // Normal modeline
-+ modeline_parse(timing_string, user_mode);
-+ osd_printf_verbose("SwitchRes: modeline: %s \n", modeline_print(user_mode, modeline_txt, MS_PARAMS));
-+ }
-+
-+ return true;
-+}
-+
-+//============================================================
-+// custom_video_parse_pci_id
-+//============================================================
-+
-+int custom_video_parse_pci_id(char *device_id, int *vendor, int *device)
-+{
-+ return sscanf(device_id, "PCI\\VEN_%x&DEV_%x", vendor, device);
-+}
-+
-+//============================================================
-+// custom_get_backup_mode
-+//============================================================
-+
-+modeline *custom_video_get_backup_mode()
-+{
-+ return &m_backup_mode;
-+}
-diff --git a/src/osd/windows/custom_video.h b/src/osd/windows/custom_video.h
-new file mode 100644
-index 00000000000..4e0fe242d75
---- /dev/null
-+++ b/src/osd/windows/custom_video.h
-@@ -0,0 +1,31 @@
-+/**************************************************************
-+
-+ custom_video.h - Custom video library header
-+
-+ ---------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2016 - Chris Kennedy, Antonio Giner
-+
-+ **************************************************************/
-+
-+#define CUSTOM_VIDEO_TIMING_MASK 0x00000ff0
-+#define CUSTOM_VIDEO_TIMING_SYSTEM 0x00000010
-+#define CUSTOM_VIDEO_TIMING_XRANDR 0x00000020
-+#define CUSTOM_VIDEO_TIMING_POWERSTRIP 0x00000040
-+#define CUSTOM_VIDEO_TIMING_ATI_LEGACY 0x00000080
-+#define CUSTOM_VIDEO_TIMING_ATI_ADL 0x00000100
-+
-+bool custom_video_init(char *device_name, char *device_id, modeline *desktop_mode, modeline *user_mode, modeline *mode_table, int method, char *s_param);
-+void custom_video_close();
-+bool custom_video_get_timing(modeline *mode);
-+bool custom_video_set_timing(modeline *mode);
-+bool custom_video_restore_timing();
-+bool custom_video_update_timing(modeline *mode);
-+int custom_video_parse_pci_id(char *device_id, int *vendor, int *device);
-+modeline *custom_video_get_backup_mode();
-diff --git a/src/osd/windows/custom_video_adl.cpp b/src/osd/windows/custom_video_adl.cpp
-new file mode 100644
-index 00000000000..5d90fc127b1
---- /dev/null
-+++ b/src/osd/windows/custom_video_adl.cpp
-@@ -0,0 +1,376 @@
-+/**************************************************************
-+
-+ custom_video_adl.cpp - ATI/AMD ADL library
-+
-+ ---------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2016 - Chris Kennedy, Antonio Giner
-+
-+ **************************************************************/
-+
-+// Constants and structures ported from AMD ADL SDK files
-+
-+#include <windows.h>
-+#include "emu.h"
-+#include "custom_video_adl.h"
-+
-+bool enum_displays(HINSTANCE h_dll);
-+
-+typedef void* (__stdcall *ADL_MAIN_MALLOC_CALLBACK)(int);
-+typedef int (*ADL_MAIN_CONTROL_CREATE)(ADL_MAIN_MALLOC_CALLBACK, int);
-+typedef int (*ADL_MAIN_CONTROL_DESTROY)();
-+typedef int (*ADL_ADAPTER_NUMBEROFADAPTERS_GET) (int*);
-+typedef int (*ADL_ADAPTER_ADAPTERINFO_GET) (LPAdapterInfo, int);
-+typedef int (*ADL_DISPLAY_DISPLAYINFO_GET) (int, int *, ADLDisplayInfo **, int);
-+typedef int (*ADL_DISPLAY_MODETIMINGOVERRIDE_GET) (int iAdapterIndex, int iDisplayIndex, ADLDisplayMode *lpModeIn, ADLDisplayModeInfo *lpModeInfoOut);
-+typedef int (*ADL_DISPLAY_MODETIMINGOVERRIDE_SET) (int iAdapterIndex, int iDisplayIndex, ADLDisplayModeInfo *lpMode, int iForceUpdate);
-+typedef int (*ADL_DISPLAY_MODETIMINGOVERRIDELIST_GET) (int iAdapterIndex, int iDisplayIndex, int iMaxNumOfOverrides, ADLDisplayModeInfo *lpModeInfoList, int *lpNumOfOverrides);
-+
-+ADL_ADAPTER_NUMBEROFADAPTERS_GET ADL_Adapter_NumberOfAdapters_Get;
-+ADL_ADAPTER_ADAPTERINFO_GET ADL_Adapter_AdapterInfo_Get;
-+ADL_DISPLAY_DISPLAYINFO_GET ADL_Display_DisplayInfo_Get;
-+ADL_DISPLAY_MODETIMINGOVERRIDE_GET ADL_Display_ModeTimingOverride_Get;
-+ADL_DISPLAY_MODETIMINGOVERRIDE_SET ADL_Display_ModeTimingOverride_Set;
-+ADL_DISPLAY_MODETIMINGOVERRIDELIST_GET ADL_Display_ModeTimingOverrideList_Get;
-+
-+HINSTANCE hDLL;
-+LPAdapterInfo lpAdapterInfo = NULL;
-+LPAdapterList lpAdapter;
-+int iNumberAdapters;
-+int cat_version, sub_version;
-+
-+int invert_pol(bool on_read) { return ((cat_version <= 12) || (cat_version >= 15 && on_read)); }
-+int interlace_factor(bool interlace, bool on_read) { return interlace && ((cat_version <= 12) || (cat_version >= 15 && on_read))? 2 : 1; }
-+
-+
-+//============================================================
-+// memory allocation callbacks
-+//============================================================
-+
-+void* __stdcall ADL_Main_Memory_Alloc(int iSize)
-+{
-+ void* lpBuffer = malloc(iSize);
-+ return lpBuffer;
-+}
-+
-+void __stdcall ADL_Main_Memory_Free(void** lpBuffer)
-+{
-+ if (NULL != *lpBuffer)
-+ {
-+ free(*lpBuffer);
-+ *lpBuffer = NULL;
-+ }
-+}
-+
-+//============================================================
-+// adl_get_driver_version
-+//============================================================
-+
-+bool adl_get_driver_version(char *device_key)
-+{
-+ HKEY hkey;
-+ bool found = false;
-+
-+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, device_key, 0, KEY_READ , &hkey) == ERROR_SUCCESS)
-+ {
-+ BYTE cat_ver[32];
-+ DWORD length = sizeof(cat_ver);
-+ if ((RegQueryValueExA(hkey, "Catalyst_Version", NULL, NULL, cat_ver, &length) == ERROR_SUCCESS) ||
-+ (RegQueryValueExA(hkey, "RadeonSoftwareVersion", NULL, NULL, cat_ver, &length) == ERROR_SUCCESS))
-+ {
-+ found = true;
-+ sscanf((char *)cat_ver, "%d.%d", &cat_version, &sub_version);
-+ osd_printf_verbose("AMD driver version %d.%d\n", cat_version, sub_version);
-+ }
-+ RegCloseKey(hkey);
-+ }
-+ return found;
-+}
-+
-+//============================================================
-+// adl_open
-+//============================================================
-+
-+int adl_open()
-+{
-+ ADL_MAIN_CONTROL_CREATE ADL_Main_Control_Create;
-+ int ADL_Err = ADL_ERR;
-+
-+ hDLL = LoadLibraryA("atiadlxx.dll");
-+ if (hDLL == NULL) hDLL = LoadLibraryA("atiadlxy.dll");
-+
-+ if (hDLL != NULL)
-+ {
-+ ADL_Main_Control_Create = (ADL_MAIN_CONTROL_CREATE)GetProcAddress(hDLL, "ADL_Main_Control_Create");
-+ if (ADL_Main_Control_Create != NULL)
-+ ADL_Err = ADL_Main_Control_Create(ADL_Main_Memory_Alloc, 1);
-+ }
-+ else
-+ {
-+ osd_printf_verbose("ADL Library not found!\n");
-+ }
-+
-+ return ADL_Err;
-+}
-+
-+//============================================================
-+// adl_close
-+//============================================================
-+
-+void adl_close()
-+{
-+ ADL_MAIN_CONTROL_DESTROY ADL_Main_Control_Destroy;
-+
-+ osd_printf_verbose("ATI/AMD ADL close\n");
-+
-+ for (int i = 0; i <= iNumberAdapters - 1; i++)
-+ ADL_Main_Memory_Free((void **)&lpAdapter[i].m_display_list);
-+
-+ ADL_Main_Memory_Free((void **)&lpAdapterInfo);
-+ ADL_Main_Memory_Free((void **)&lpAdapter);
-+
-+ ADL_Main_Control_Destroy = (ADL_MAIN_CONTROL_DESTROY)GetProcAddress(hDLL, "ADL_Main_Control_Destroy");
-+ if (ADL_Main_Control_Destroy != NULL)
-+ ADL_Main_Control_Destroy();
-+
-+ FreeLibrary(hDLL);
-+}
-+
-+//============================================================
-+// adl_init
-+//============================================================
-+
-+bool adl_init(char *device_name, char *device_key, char *device_id)
-+{
-+ int ADL_Err = ADL_ERR;
-+
-+ osd_printf_verbose("ATI/AMD ADL init\n");
-+
-+ ADL_Err = adl_open();
-+ if (ADL_Err != ADL_OK)
-+ {
-+ osd_printf_verbose("ERROR: ADL Initialization error!\n");
-+ return false;
-+ }
-+
-+ ADL_Adapter_NumberOfAdapters_Get = (ADL_ADAPTER_NUMBEROFADAPTERS_GET)GetProcAddress(hDLL,"ADL_Adapter_NumberOfAdapters_Get");
-+ if (ADL_Adapter_NumberOfAdapters_Get == NULL)
-+ {
-+ osd_printf_verbose("ERROR: ADL_Adapter_NumberOfAdapters_Get not available!");
-+ return false;
-+ }
-+ ADL_Adapter_AdapterInfo_Get = (ADL_ADAPTER_ADAPTERINFO_GET)GetProcAddress(hDLL,"ADL_Adapter_AdapterInfo_Get");
-+ if (ADL_Adapter_AdapterInfo_Get == NULL)
-+ {
-+ osd_printf_verbose("ERROR: ADL_Adapter_AdapterInfo_Get not available!");
-+ return false;
-+ }
-+ ADL_Display_DisplayInfo_Get = (ADL_DISPLAY_DISPLAYINFO_GET)GetProcAddress(hDLL,"ADL_Display_DisplayInfo_Get");
-+ if (ADL_Display_DisplayInfo_Get == NULL)
-+ {
-+ osd_printf_verbose("ERROR: ADL_Display_DisplayInfo_Get not available!");
-+ return false;
-+ }
-+ ADL_Display_ModeTimingOverride_Get = (ADL_DISPLAY_MODETIMINGOVERRIDE_GET)GetProcAddress(hDLL,"ADL_Display_ModeTimingOverride_Get");
-+ if (ADL_Display_ModeTimingOverride_Get == NULL)
-+ {
-+ osd_printf_verbose("ERROR: ADL_Display_ModeTimingOverride_Get not available!");
-+ return false;
-+ }
-+ ADL_Display_ModeTimingOverride_Set = (ADL_DISPLAY_MODETIMINGOVERRIDE_SET)GetProcAddress(hDLL,"ADL_Display_ModeTimingOverride_Set");
-+ if (ADL_Display_ModeTimingOverride_Set == NULL)
-+ {
-+ osd_printf_verbose("ERROR: ADL_Display_ModeTimingOverride_Set not available!");
-+ return false;
-+ }
-+ ADL_Display_ModeTimingOverrideList_Get = (ADL_DISPLAY_MODETIMINGOVERRIDELIST_GET)GetProcAddress(hDLL,"ADL_Display_ModeTimingOverrideList_Get");
-+ if (ADL_Display_ModeTimingOverrideList_Get == NULL)
-+ {
-+ osd_printf_verbose("ERROR: ADL_Display_ModeTimingOverrideList_Get not available!");
-+ return false;
-+ }
-+
-+ if (!enum_displays(hDLL))
-+ {
-+ osd_printf_error("ADL error enumerating displays.\n");
-+ return false;
-+ }
-+
-+ adl_get_driver_version(device_key);
-+
-+ osd_printf_verbose("ADL functions retrieved successfully.\n");
-+ return true;
-+}
-+
-+//============================================================
-+// enum_displays
-+//============================================================
-+
-+bool enum_displays(HINSTANCE h_dll)
-+{
-+ ADL_Adapter_NumberOfAdapters_Get(&iNumberAdapters);
-+
-+ lpAdapterInfo = (LPAdapterInfo)malloc(sizeof(AdapterInfo) * iNumberAdapters);
-+ memset(lpAdapterInfo, '\0', sizeof(AdapterInfo) * iNumberAdapters);
-+ ADL_Adapter_AdapterInfo_Get(lpAdapterInfo, sizeof(AdapterInfo) * iNumberAdapters);
-+
-+ lpAdapter = (LPAdapterList)malloc(sizeof(AdapterList) * iNumberAdapters);
-+ for (int i = 0; i <= iNumberAdapters - 1; i++)
-+ {
-+ lpAdapter[i].m_index = lpAdapterInfo[i].iAdapterIndex;
-+ lpAdapter[i].m_bus = lpAdapterInfo[i].iBusNumber;
-+ memcpy(&lpAdapter[i].m_name, &lpAdapterInfo[i].strAdapterName, ADL_MAX_PATH);
-+ memcpy(&lpAdapter[i].m_display_name, &lpAdapterInfo[i].strDisplayName, ADL_MAX_PATH);
-+ lpAdapter[i].m_num_of_displays = 0;
-+ lpAdapter[i].m_display_list = 0;
-+ ADL_Display_DisplayInfo_Get(lpAdapter[i].m_index, &lpAdapter[i].m_num_of_displays, &lpAdapter[i].m_display_list, 1);
-+ }
-+ return true;
-+}
-+
-+//============================================================
-+// get_device_mapping_from_display_name
-+//============================================================
-+
-+bool get_device_mapping_from_display_name(char *target_display, int *adapter_index, int *display_index)
-+{
-+ for (int i = 0; i <= iNumberAdapters -1; i++)
-+ {
-+ if (!strcmp(target_display, lpAdapter[i].m_display_name))
-+ {
-+ ADLDisplayInfo *display_list;
-+ display_list = lpAdapter[i].m_display_list;
-+
-+ for (int j = 0; j <= lpAdapter[i].m_num_of_displays - 1; j++)
-+ {
-+ if (lpAdapter[i].m_index == display_list[j].displayID.iDisplayLogicalAdapterIndex)
-+ {
-+ *adapter_index = lpAdapter[i].m_index;
-+ *display_index = display_list[j].displayID.iDisplayLogicalIndex;
-+ return true;
-+ }
-+ }
-+ }
-+ }
-+ return false;
-+}
-+
-+//============================================================
-+// ADL_display_mode_info_to_modeline
-+//============================================================
-+
-+bool adl_display_mode_info_to_modeline(ADLDisplayModeInfo *dmi, modeline *m)
-+{
-+ if (dmi->sDetailedTiming.sHTotal == 0) return false;
-+
-+ ADLDetailedTiming dt;
-+ memcpy(&dt, &dmi->sDetailedTiming, sizeof(ADLDetailedTiming));
-+
-+ if (dt.sHTotal == 0) return false;
-+
-+ m->htotal = dt.sHTotal;
-+ m->hactive = dt.sHDisplay;
-+ m->hbegin = dt.sHSyncStart;
-+ m->hend = dt.sHSyncWidth + m->hbegin;
-+ m->vtotal = dt.sVTotal;
-+ m->vactive = dt.sVDisplay;
-+ m->vbegin = dt.sVSyncStart;
-+ m->vend = dt.sVSyncWidth + m->vbegin;
-+ m->interlace = (dt.sTimingFlags & ADL_DL_TIMINGFLAG_INTERLACED)? 1 : 0;
-+ m->hsync = ((dt.sTimingFlags & ADL_DL_TIMINGFLAG_H_SYNC_POLARITY)? 1 : 0) ^ invert_pol(1);
-+ m->vsync = ((dt.sTimingFlags & ADL_DL_TIMINGFLAG_V_SYNC_POLARITY)? 1 : 0) ^ invert_pol(1) ;
-+ m->pclock = dt.sPixelClock * 10000;
-+
-+ m->height = m->height? m->height : dmi->iPelsHeight;
-+ m->width = m->width? m->width : dmi->iPelsWidth;
-+ m->refresh = m->refresh? m->refresh : dmi->iRefreshRate / interlace_factor(m->interlace, 1);;
-+ m->hfreq = float(m->pclock / m->htotal);
-+ m->vfreq = float(m->hfreq / m->vtotal) * (m->interlace? 2 : 1);
-+
-+ return true;
-+}
-+
-+//============================================================
-+// ADL_get_modeline
-+//============================================================
-+
-+bool adl_get_modeline(char *target_display, modeline *m)
-+{
-+ int adapter_index = 0;
-+ int display_index = 0;
-+ ADLDisplayMode mode_in;
-+ ADLDisplayModeInfo mode_info_out;
-+ modeline m_temp = *m;
-+
-+ //modeline to ADLDisplayMode
-+ mode_in.iPelsHeight = m->height;
-+ mode_in.iPelsWidth = m->width;
-+ mode_in.iBitsPerPel = 32;
-+ mode_in.iDisplayFrequency = m->refresh * interlace_factor(m->interlace, 1);
-+
-+ if (!get_device_mapping_from_display_name(target_display, &adapter_index, &display_index)) return false;
-+ if (ADL_Display_ModeTimingOverride_Get(adapter_index, display_index, &mode_in, &mode_info_out) != ADL_OK) return false;
-+ if (adl_display_mode_info_to_modeline(&mode_info_out, &m_temp))
-+ {
-+ if (m_temp.interlace == m->interlace)
-+ {
-+ memcpy(m, &m_temp, sizeof(modeline));
-+ return true;
-+ }
-+ }
-+ return false;
-+}
-+
-+//============================================================
-+// ADL_set_modeline
-+//============================================================
-+
-+bool adl_set_modeline(char *target_display, modeline *m, int update_mode)
-+{
-+ int adapter_index = 0;
-+ int display_index = 0;
-+ ADLDisplayModeInfo mode_info;
-+ ADLDetailedTiming *dt;
-+ modeline m_temp;
-+
-+ //modeline to ADLDisplayModeInfo
-+ mode_info.iTimingStandard = (update_mode & MODELINE_DELETE)? ADL_DL_MODETIMING_STANDARD_DRIVER_DEFAULT : ADL_DL_MODETIMING_STANDARD_CUSTOM;
-+ mode_info.iPossibleStandard = 0;
-+ mode_info.iRefreshRate = m->refresh * interlace_factor(m->interlace, 0);
-+ mode_info.iPelsWidth = m->width;
-+ mode_info.iPelsHeight = m->height;
-+
-+ //modeline to ADLDetailedTiming
-+ dt = &mode_info.sDetailedTiming;
-+ dt->sTimingFlags = (m->interlace? ADL_DL_TIMINGFLAG_INTERLACED : 0) |
-+ (m->hsync ^ invert_pol(0)? ADL_DL_TIMINGFLAG_H_SYNC_POLARITY : 0) |
-+ (m->vsync ^ invert_pol(0)? ADL_DL_TIMINGFLAG_V_SYNC_POLARITY : 0);
-+ dt->sHTotal = m->htotal;
-+ dt->sHDisplay = m->hactive;
-+ dt->sHSyncStart = m->hbegin;
-+ dt->sHSyncWidth = m->hend - m->hbegin;
-+ dt->sVTotal = m->vtotal;
-+ dt->sVDisplay = m->vactive;
-+ dt->sVSyncStart = m->vbegin;
-+ dt->sVSyncWidth = m->vend - m->vbegin;
-+ dt->sPixelClock = m->pclock / 10000;
-+ dt->sHOverscanRight = 0;
-+ dt->sHOverscanLeft = 0;
-+ dt->sVOverscanBottom = 0;
-+ dt->sVOverscanTop = 0;
-+
-+ if (!get_device_mapping_from_display_name(target_display, &adapter_index, &display_index)) return false;
-+ if (ADL_Display_ModeTimingOverride_Set(adapter_index, display_index, &mode_info, (update_mode & MODELINE_UPDATE_LIST)? 1 : 0) != ADL_OK) return false;
-+
-+ // read modeline to trigger timing refresh on modded drivers
-+ memcpy(&m_temp, m, sizeof(modeline));
-+ if (update_mode & MODELINE_UPDATE) adl_get_modeline(target_display, &m_temp);
-+
-+ return true;
-+}
-diff --git a/src/osd/windows/custom_video_adl.h b/src/osd/windows/custom_video_adl.h
-new file mode 100644
-index 00000000000..390041aa8c6
---- /dev/null
-+++ b/src/osd/windows/custom_video_adl.h
-@@ -0,0 +1,130 @@
-+/**************************************************************
-+
-+ custom_video_adl.h - ATI/AMD ADL library header
-+
-+ ---------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2016 - Chris Kennedy, Antonio Giner
-+
-+ **************************************************************/
-+
-+// Constants and structures ported from AMD ADL SDK files
-+
-+#define ADL_MAX_PATH 256
-+#define ADL_OK 0
-+#define ADL_ERR -1
-+
-+//ADL_DETAILED_TIMING.sTimingFlags
-+#define ADL_DL_TIMINGFLAG_DOUBLE_SCAN 0x0001
-+#define ADL_DL_TIMINGFLAG_INTERLACED 0x0002
-+#define ADL_DL_TIMINGFLAG_H_SYNC_POLARITY 0x0004
-+#define ADL_DL_TIMINGFLAG_V_SYNC_POLARITY 0x0008
-+
-+//ADL_DISPLAY_MODE_INFO.iTimingStandard
-+#define ADL_DL_MODETIMING_STANDARD_CVT 0x00000001 // CVT Standard
-+#define ADL_DL_MODETIMING_STANDARD_GTF 0x00000002 // GFT Standard
-+#define ADL_DL_MODETIMING_STANDARD_DMT 0x00000004 // DMT Standard
-+#define ADL_DL_MODETIMING_STANDARD_CUSTOM 0x00000008 // User-defined standard
-+#define ADL_DL_MODETIMING_STANDARD_DRIVER_DEFAULT 0x00000010 // Remove Mode from overriden list
-+#define ADL_DL_MODETIMING_STANDARD_CVT_RB 0x00000020 // CVT-RB Standard
-+
-+typedef struct AdapterInfo
-+{
-+ int iSize;
-+ int iAdapterIndex;
-+ char strUDID[ADL_MAX_PATH];
-+ int iBusNumber;
-+ int iDeviceNumber;
-+ int iFunctionNumber;
-+ int iVendorID;
-+ char strAdapterName[ADL_MAX_PATH];
-+ char strDisplayName[ADL_MAX_PATH];
-+ int iPresent;
-+ int iExist;
-+ char strDriverPath[ADL_MAX_PATH];
-+ char strDriverPathExt[ADL_MAX_PATH];
-+ char strPNPString[ADL_MAX_PATH];
-+ int iOSDisplayIndex;
-+} AdapterInfo, *LPAdapterInfo;
-+
-+typedef struct ADLDisplayID
-+{
-+ int iDisplayLogicalIndex;
-+ int iDisplayPhysicalIndex;
-+ int iDisplayLogicalAdapterIndex;
-+ int iDisplayPhysicalAdapterIndex;
-+} ADLDisplayID, *LPADLDisplayID;
-+
-+
-+typedef struct ADLDisplayInfo
-+{
-+ ADLDisplayID displayID;
-+ int iDisplayControllerIndex;
-+ char strDisplayName[ADL_MAX_PATH];
-+ char strDisplayManufacturerName[ADL_MAX_PATH];
-+ int iDisplayType;
-+ int iDisplayOutputType;
-+ int iDisplayConnector;
-+ int iDisplayInfoMask;
-+ int iDisplayInfoValue;
-+} ADLDisplayInfo, *LPADLDisplayInfo;
-+
-+typedef struct ADLDisplayMode
-+{
-+ int iPelsHeight;
-+ int iPelsWidth;
-+ int iBitsPerPel;
-+ int iDisplayFrequency;
-+} ADLDisplayMode;
-+
-+typedef struct ADLDetailedTiming
-+{
-+ int iSize;
-+ short sTimingFlags;
-+ short sHTotal;
-+ short sHDisplay;
-+ short sHSyncStart;
-+ short sHSyncWidth;
-+ short sVTotal;
-+ short sVDisplay;
-+ short sVSyncStart;
-+ short sVSyncWidth;
-+ unsigned short sPixelClock;
-+ short sHOverscanRight;
-+ short sHOverscanLeft;
-+ short sVOverscanBottom;
-+ short sVOverscanTop;
-+ short sOverscan8B;
-+ short sOverscanGR;
-+} ADLDetailedTiming;
-+
-+typedef struct ADLDisplayModeInfo
-+{
-+ int iTimingStandard;
-+ int iPossibleStandard;
-+ int iRefreshRate;
-+ int iPelsWidth;
-+ int iPelsHeight;
-+ ADLDetailedTiming sDetailedTiming;
-+} ADLDisplayModeInfo;
-+
-+typedef struct AdapterList
-+{
-+ int m_index;
-+ int m_bus;
-+ char m_name[ADL_MAX_PATH];
-+ char m_display_name[ADL_MAX_PATH];
-+ int m_num_of_displays;
-+ ADLDisplayInfo *m_display_list;
-+} AdapterList, *LPAdapterList;
-+
-+bool adl_init(char *device_name, char *device_key, char *device_id);
-+void adl_close();
-+bool adl_get_modeline(char *target_display, modeline *m);
-+bool adl_set_modeline(char *target_display, modeline *m, int update_mode);
-diff --git a/src/osd/windows/custom_video_ati.cpp b/src/osd/windows/custom_video_ati.cpp
-new file mode 100644
-index 00000000000..3bf863afd0a
---- /dev/null
-+++ b/src/osd/windows/custom_video_ati.cpp
-@@ -0,0 +1,309 @@
-+/**************************************************************
-+
-+ custom_video_ati.cpp - ATI legacy library
-+ ---------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2016 - Chris Kennedy, Antonio Giner
-+
-+ **************************************************************/
-+
-+#include <windows.h>
-+
-+#include "emu.h"
-+#include "custom_video_ati.h"
-+
-+#define CRTC_DOUBLE_SCAN 0x0001
-+#define CRTC_INTERLACED 0x0002
-+#define CRTC_H_SYNC_POLARITY 0x0004
-+#define CRTC_V_SYNC_POLARITY 0x0008
-+
-+static int get_DWORD(int i, char *lp_data);
-+static int get_DWORD_BCD(int i, char *lp_data);
-+static void set_DWORD(char *data_string, UINT32 data_word, int offset);
-+static void set_DWORD_BCD(char *data_string, UINT32 data_word, int offset);
-+static int os_version(void);
-+static bool is_elevated();
-+static int win_interlace_factor(modeline *mode);
-+
-+char m_device_name[32];
-+char m_device_key[256];
-+int win_version;
-+
-+//============================================================
-+// ati_custom_video_init
-+//============================================================
-+
-+bool ati_init(char *device_name, char *device_key, char *device_id)
-+{
-+ osd_printf_verbose("ATI legacy init\n");
-+
-+ // Get Windows version
-+ win_version = os_version();
-+
-+ if (win_version > 5 && !is_elevated())
-+ {
-+ osd_printf_error("ATI legacy error: the program needs administrator rights.\n");
-+ return false;
-+ }
-+
-+ memcpy(m_device_name, device_name, sizeof(m_device_name));
-+ memcpy(m_device_key, device_key, sizeof(m_device_key));
-+
-+ return true;
-+}
-+
-+//============================================================
-+// ati_get_modeline
-+//============================================================
-+
-+bool ati_get_modeline(modeline *mode)
-+{
-+ HKEY hKey;
-+ char lp_name[1024];
-+ char lp_data[68];
-+ DWORD length;
-+ bool found = false;
-+ int refresh_label = mode->refresh_label? mode->refresh_label : mode->refresh * win_interlace_factor(mode);
-+ int vfreq_incr = 0;
-+
-+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, m_device_key, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
-+ {
-+ sprintf(lp_name, "DALDTMCRTBCD%dx%dx0x%d", mode->width, mode->height, refresh_label);
-+ length = sizeof(lp_data);
-+
-+ if (RegQueryValueExA(hKey, lp_name, NULL, NULL, (LPBYTE)lp_data, &length) == ERROR_SUCCESS && length == sizeof(lp_data))
-+ found = true;
-+ else if (win_version > 5 && mode->interlace)
-+ {
-+ vfreq_incr = 1;
-+ sprintf(lp_name, "DALDTMCRTBCD%dx%dx0x%d", mode->width, mode->height, refresh_label + vfreq_incr);
-+ if (RegQueryValueExA(hKey, lp_name, NULL, NULL, (LPBYTE)lp_data, &length) == ERROR_SUCCESS && length == sizeof(lp_data))
-+ found = true;
-+ }
-+ if (found)
-+ {
-+ mode->pclock = get_DWORD_BCD(36, lp_data) * 10000;
-+ mode->hactive = get_DWORD_BCD(8, lp_data);
-+ mode->hbegin = get_DWORD_BCD(12, lp_data);
-+ mode->hend = get_DWORD_BCD(16, lp_data) + mode->hbegin;
-+ mode->htotal = get_DWORD_BCD(4, lp_data);
-+ mode->vactive = get_DWORD_BCD(24, lp_data);
-+ mode->vbegin = get_DWORD_BCD(28, lp_data);
-+ mode->vend = get_DWORD_BCD(32, lp_data) + mode->vbegin;
-+ mode->vtotal = get_DWORD_BCD(20, lp_data);
-+ mode->interlace = (get_DWORD(0, lp_data) & CRTC_INTERLACED)?1:0;
-+ mode->hsync = (get_DWORD(0, lp_data) & CRTC_H_SYNC_POLARITY)?0:1;
-+ mode->vsync = (get_DWORD(0, lp_data) & CRTC_V_SYNC_POLARITY)?0:1;
-+ mode->hfreq = mode->pclock / mode->htotal;
-+ mode->vfreq = mode->hfreq / mode->vtotal * (mode->interlace?2:1);
-+ mode->refresh_label = refresh_label;
-+
-+ int checksum = 65535 - get_DWORD(0, lp_data) - mode->htotal - mode->hactive - mode->hend
-+ - mode->vtotal - mode->vactive - mode->vend - mode->pclock/10000;
-+ if (checksum != get_DWORD(64, lp_data))
-+ osd_printf_verbose("bad checksum! ");
-+ }
-+ RegCloseKey(hKey);
-+ return (found);
-+ }
-+ osd_printf_info("Failed opening registry entry for mode.\n");
-+ return false;
-+}
-+
-+//============================================================
-+// ati_set_modeline
-+//============================================================
-+
-+bool ati_set_modeline(modeline *mode)
-+{
-+ HKEY hKey;
-+ char lp_name[1024];
-+ char lp_data[68];
-+ long checksum;
-+ bool found = false;
-+ int refresh_label = mode->refresh_label? mode->refresh_label : mode->refresh * win_interlace_factor(mode);
-+ int vfreq_incr = 0;
-+
-+ memset(lp_data, 0, sizeof(lp_data));
-+ set_DWORD_BCD(lp_data, (int)mode->pclock/10000, 36);
-+ set_DWORD_BCD(lp_data, mode->hactive, 8);
-+ set_DWORD_BCD(lp_data, mode->hbegin, 12);
-+ set_DWORD_BCD(lp_data, mode->hend - mode->hbegin, 16);
-+ set_DWORD_BCD(lp_data, mode->htotal, 4);
-+ set_DWORD_BCD(lp_data, mode->vactive, 24);
-+ set_DWORD_BCD(lp_data, mode->vbegin, 28);
-+ set_DWORD_BCD(lp_data, mode->vend - mode->vbegin, 32);
-+ set_DWORD_BCD(lp_data, mode->vtotal, 20);
-+ set_DWORD(lp_data, (mode->interlace?CRTC_INTERLACED:0) | (mode->hsync?0:CRTC_H_SYNC_POLARITY) | (mode->vsync?0:CRTC_V_SYNC_POLARITY), 0);
-+
-+ checksum = 65535 - get_DWORD(0, lp_data) - mode->htotal - mode->hactive - mode->hend
-+ - mode->vtotal - mode->vactive - mode->vend - mode->pclock/10000;
-+ set_DWORD(lp_data, checksum, 64);
-+
-+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, m_device_key, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
-+ {
-+ sprintf (lp_name, "DALDTMCRTBCD%dx%dx0x%d", mode->width, mode->height, refresh_label);
-+
-+ if (RegQueryValueExA(hKey, lp_name, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
-+ found = true;
-+ else if (win_version > 5 && mode->interlace)
-+ {
-+ vfreq_incr = 1;
-+ sprintf(lp_name, "DALDTMCRTBCD%dx%dx0x%d", mode->width, mode->height, refresh_label + vfreq_incr);
-+ if (RegQueryValueExA(hKey, lp_name, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
-+ found = true;
-+ }
-+
-+ if (!(found && RegSetValueExA(hKey, lp_name, 0, REG_BINARY, (LPBYTE)lp_data, 68) == ERROR_SUCCESS))
-+ osd_printf_info("Failed saving registry entry %s\n", lp_name);
-+
-+ RegCloseKey(hKey);
-+ return (found);
-+ }
-+
-+ osd_printf_info("Failed updating registry entry for mode.\n");
-+ return 0;
-+}
-+
-+//============================================================
-+// ati_refresh_timings
-+//============================================================
-+
-+void ati_refresh_timings(void)
-+{
-+ int iModeNum = 0;
-+ DEVMODEA lpDevMode;
-+
-+ memset(&lpDevMode, 0, sizeof(DEVMODEA));
-+ lpDevMode.dmSize = sizeof(DEVMODEA);
-+
-+ while (EnumDisplaySettingsExA(m_device_name, iModeNum, &lpDevMode, 0) != 0)
-+ iModeNum++;
-+}
-+
-+//============================================================
-+// get_DWORD
-+//============================================================
-+
-+static int get_DWORD(int i, char *lp_data)
-+{
-+ char out[32] = "";
-+ UINT32 x;
-+
-+ sprintf(out, "%02X%02X%02X%02X", lp_data[i]&0xFF, lp_data[i+1]&0xFF, lp_data[i+2]&0xFF, lp_data[i+3]&0xFF);
-+ sscanf(out, "%08X", &x);
-+ return x;
-+}
-+
-+//============================================================
-+// get_DWORD_BCD
-+//============================================================
-+
-+static int get_DWORD_BCD(int i, char *lp_data)
-+{
-+ char out[32] = "";
-+ UINT32 x;
-+
-+ sprintf(out, "%02X%02X%02X%02X", lp_data[i]&0xFF, lp_data[i+1]&0xFF, lp_data[i+2]&0xFF, lp_data[i+3]&0xFF);
-+ sscanf(out, "%d", &x);
-+ return x;
-+}
-+
-+//============================================================
-+// set_DWORD
-+//============================================================
-+
-+static void set_DWORD(char *data_string, UINT32 data_dword, int offset)
-+{
-+ char *p_dword = (char*)&data_dword;
-+
-+ data_string[offset] = p_dword[3]&0xFF;
-+ data_string[offset+1] = p_dword[2]&0xFF;
-+ data_string[offset+2] = p_dword[1]&0xFF;
-+ data_string[offset+3] = p_dword[0]&0xFF;
-+}
-+
-+//============================================================
-+// set_DWORD_BCD
-+//============================================================
-+
-+static void set_DWORD_BCD(char *data_string, UINT32 data_dword, int offset)
-+{
-+ if (data_dword < 100000000)
-+ {
-+ int low_word, high_word;
-+ int a, b, c, d;
-+ char out[32] = "";
-+
-+ low_word = data_dword % 10000;
-+ high_word = data_dword / 10000;
-+
-+ sprintf(out, "%d %d %d %d", high_word / 100, high_word % 100 , low_word / 100, low_word % 100);
-+ sscanf(out, "%02X %02X %02X %02X", &a, &b, &c, &d);
-+
-+ data_string[offset] = a;
-+ data_string[offset+1] = b;
-+ data_string[offset+2] = c;
-+ data_string[offset+3] = d;
-+ }
-+}
-+
-+//============================================================
-+// os_version
-+//============================================================
-+
-+static int os_version(void)
-+{
-+ OSVERSIONINFOA lpVersionInfo;
-+
-+ memset(&lpVersionInfo, 0, sizeof(OSVERSIONINFOA));
-+ lpVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
-+ GetVersionExA (&lpVersionInfo);
-+
-+ return lpVersionInfo.dwMajorVersion;
-+}
-+
-+//============================================================
-+// is_elevated
-+//============================================================
-+
-+static bool is_elevated()
-+{
-+ HANDLE htoken;
-+ bool result = false;
-+
-+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &htoken))
-+ return false;
-+
-+ TOKEN_ELEVATION te = {0};
-+ DWORD dw_return_length;
-+
-+ if (GetTokenInformation(htoken, TokenElevation, &te, sizeof(te), &dw_return_length))
-+ {
-+ if (te.TokenIsElevated)
-+ {
-+ result = true;
-+ }
-+ }
-+
-+ CloseHandle(htoken);
-+ return (result);
-+}
-+
-+//============================================================
-+// win_interlace_factor
-+//============================================================
-+
-+static int win_interlace_factor(modeline *mode)
-+{
-+ if (win_version > 5 && mode->interlace)
-+ return 2;
-+
-+ return 1;
-+}
-diff --git a/src/osd/windows/custom_video_ati.h b/src/osd/windows/custom_video_ati.h
-new file mode 100644
-index 00000000000..25061d53340
---- /dev/null
-+++ b/src/osd/windows/custom_video_ati.h
-@@ -0,0 +1,20 @@
-+/**************************************************************
-+
-+ custom_video_ati.h - ATI legacy library header
-+
-+ ---------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2016 - Chris Kennedy, Antonio Giner
-+
-+ **************************************************************/
-+
-+bool ati_init(char *device_name, char *device_key, char *device_id);
-+bool ati_get_modeline(modeline *mode);
-+bool ati_set_modeline(modeline *mode);
-+void ati_refresh_timings(void);
-diff --git a/src/osd/windows/custom_video_ati_family.cpp b/src/osd/windows/custom_video_ati_family.cpp
-new file mode 100644
-index 00000000000..0e0ac8c706a
---- /dev/null
-+++ b/src/osd/windows/custom_video_ati_family.cpp
-@@ -0,0 +1,850 @@
-+/**************************************************************
-+
-+ custom_video_ati_family.cpp - ATI/AMD Radeon family
-+ ---------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2016 - Chris Kennedy, Antonio Giner
-+
-+ **************************************************************/
-+
-+/* Constants and structures ported from Linux open source drivers:
-+ drivers\gpu\drm\radeon\radeon.h
-+ drivers\gpu\drm\radeon\radeon_family.h
-+ include\drm\drm_pciids.h
-+*/
-+
-+#ifndef RADEON_FAMILY_H
-+#define RADEON_FAMILY_H
-+
-+struct pci_device_id
-+{
-+ int vendor, device;
-+ int subvendor, subdevice;
-+ int _class, _class_mask;
-+ int driver_data;
-+};
-+
-+enum radeon_family
-+{
-+ CHIP_R100 = 0,
-+ CHIP_RV100,
-+ CHIP_RS100,
-+ CHIP_RV200,
-+ CHIP_RS200,
-+ CHIP_R200,
-+ CHIP_RV250,
-+ CHIP_RS300,
-+ CHIP_RV280,
-+ CHIP_R300,
-+ CHIP_R350,
-+ CHIP_RV350,
-+ CHIP_RV380,
-+ CHIP_R420,
-+ CHIP_R423,
-+ CHIP_RV410,
-+ CHIP_RS400,
-+ CHIP_RS480,
-+ CHIP_RS600,
-+ CHIP_RS690,
-+ CHIP_RS740,
-+ CHIP_RV515,
-+ CHIP_R520,
-+ CHIP_RV530,
-+ CHIP_RV560,
-+ CHIP_RV570,
-+ CHIP_R580,
-+ CHIP_R600,
-+ CHIP_RV610,
-+ CHIP_RV630,
-+ CHIP_RV670,
-+ CHIP_RV620,
-+ CHIP_RV635,
-+ CHIP_RS780,
-+ CHIP_RS880,
-+ CHIP_RV770,
-+ CHIP_RV730,
-+ CHIP_RV710,
-+ CHIP_RV740,
-+ CHIP_CEDAR,
-+ CHIP_REDWOOD,
-+ CHIP_JUNIPER,
-+ CHIP_CYPRESS,
-+ CHIP_HEMLOCK,
-+ CHIP_PALM,
-+ CHIP_SUMO,
-+ CHIP_SUMO2,
-+ CHIP_BARTS,
-+ CHIP_TURKS,
-+ CHIP_CAICOS,
-+ CHIP_CAYMAN,
-+ CHIP_ARUBA,
-+ CHIP_TAHITI,
-+ CHIP_PITCAIRN,
-+ CHIP_VERDE,
-+ CHIP_OLAND,
-+ CHIP_HAINAN,
-+ CHIP_BONAIRE,
-+ CHIP_KAVERI,
-+ CHIP_KABINI,
-+ CHIP_HAWAII,
-+ CHIP_MULLINS,
-+ CHIP_LAST,
-+};
-+
-+enum radeon_chip_flags
-+{
-+ RADEON_FAMILY_MASK = 0x0000ffffUL,
-+ RADEON_FLAGS_MASK = 0xffff0000UL,
-+ RADEON_IS_MOBILITY = 0x00010000UL,
-+ RADEON_IS_IGP = 0x00020000UL,
-+ RADEON_SINGLE_CRTC = 0x00040000UL,
-+ RADEON_IS_AGP = 0x00080000UL,
-+ RADEON_HAS_HIERZ = 0x00100000UL,
-+ RADEON_IS_PCIE = 0x00200000UL,
-+ RADEON_NEW_MEMMAP = 0x00400000UL,
-+ RADEON_IS_PCI = 0x00800000UL,
-+ RADEON_IS_IGPGART = 0x01000000UL,
-+ RADEON_IS_PX = 0x02000000UL,
-+};
-+
-+#define PCI_ANY_ID (~0)
-+
-+#define radeon_PCI_IDS \
-+ {0x1002, 0x1304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x1305, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x1306, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x1307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x1309, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x130A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x130B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x130C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x130D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x130E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x130F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x1310, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x1311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x1312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x1313, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x1315, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x1316, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x1317, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x1318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x131B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x131C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x131D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x3151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x3155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x3E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x3E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|RADEON_IS_IGP}, \
-+ {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP}, \
-+ {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
-+ {0x1002, 0x4145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
-+ {0x1002, 0x4146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
-+ {0x1002, 0x4147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
-+ {0x1002, 0x4148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-+ {0x1002, 0x4149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-+ {0x1002, 0x414A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-+ {0x1002, 0x414B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-+ {0x1002, 0x4150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
-+ {0x1002, 0x4151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
-+ {0x1002, 0x4152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
-+ {0x1002, 0x4153, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
-+ {0x1002, 0x4154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
-+ {0x1002, 0x4155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
-+ {0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
-+ {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP}, \
-+ {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-+ {0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \
-+ {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \
-+ {0x1002, 0x4A48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x4A4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x4A4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x4A4D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x4A4E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x4A4F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x4A50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x4A54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x4B48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x4B49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x4B4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x4B4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x4B4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x4C5A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x4C6E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
-+ {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
-+ {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
-+ {0x1002, 0x4E47, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
-+ {0x1002, 0x4E48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-+ {0x1002, 0x4E49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-+ {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-+ {0x1002, 0x4E4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-+ {0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x4E52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x4E53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x4E56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
-+ {0x1002, 0x5145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
-+ {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
-+ {0x1002, 0x5147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
-+ {0x1002, 0x5148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-+ {0x1002, 0x514C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-+ {0x1002, 0x514D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-+ {0x1002, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \
-+ {0x1002, 0x5158, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \
-+ {0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
-+ {0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
-+ {0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|RADEON_SINGLE_CRTC}, \
-+ {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x554B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x554C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x554D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x554E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5551, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5554, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x564A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x564B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5657, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \
-+ {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x5954, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
-+ {0x1002, 0x5955, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
-+ {0x1002, 0x5974, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
-+ {0x1002, 0x5975, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
-+ {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
-+ {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
-+ {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
-+ {0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
-+ {0x1002, 0x5965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
-+ {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|RADEON_SINGLE_CRTC}, \
-+ {0x1002, 0x5a41, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_IGPGART}, \
-+ {0x1002, 0x5a42, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
-+ {0x1002, 0x5a61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_IGPGART}, \
-+ {0x1002, 0x5a62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
-+ {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5b62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5b63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5b64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5b65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \
-+ {0x1002, 0x5d48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5d49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5d4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5d4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5d4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5d50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5d52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5d57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5e48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5e4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6600, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6601, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6602, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6603, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6604, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6605, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6606, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6607, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6608, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6610, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6611, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6613, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6620, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6621, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6623, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6631, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6658, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x665c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x665d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6663, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6664, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6665, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6667, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x666F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6701, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6702, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6703, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6704, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6705, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6706, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6707, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6708, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6709, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6718, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6719, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x671c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x671d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x671f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6720, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6721, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6722, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6723, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6724, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6725, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6726, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6727, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6728, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6729, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6738, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6739, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x673e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6740, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6741, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6742, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6743, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6744, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6745, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6746, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6747, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6748, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6749, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x674A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6758, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6759, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x675B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x675D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x675F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6760, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6761, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6762, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6763, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6764, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6765, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6766, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6767, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6768, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6770, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6771, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6778, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6779, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x677B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6784, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6788, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x678A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6790, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6791, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6792, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x679B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x679E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x679F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x67A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x67A1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x67A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x67A8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x67A9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x67AA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x67B0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x67B1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x67B8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x67B9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x67BA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x67BE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6801, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6802, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6806, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6811, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6819, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6821, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6822, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6823, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6824, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6826, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6827, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6829, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x682A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x682B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x682C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x682D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x682F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6830, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6831, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6838, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6839, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x683B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x683D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x683F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6840, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6841, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6842, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6843, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6849, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x684C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6858, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6859, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6880, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6888, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6889, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x688A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x688C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x688D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6898, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x6899, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x689b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x689c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HEMLOCK|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x689d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HEMLOCK|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x689e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68a0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68a1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68a8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68a9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68b8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68b9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68ba, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68be, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68bf, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68c1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68c7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68c8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68c9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68d9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68da, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68de, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68e0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68e1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68e4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68e5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68e8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68e9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68f1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68f2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68f8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68f9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68fa, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x68fe, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x710A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x710B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x710C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x710E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x710F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7140, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7141, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7142, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7143, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x714A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x714B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x714C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x714D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x714E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x714F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7153, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x715E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x715F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7181, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7183, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7186, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7187, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7188, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x718A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x718B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x718C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x718D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x718F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7193, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7196, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x719B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x719F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x71C0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x71C1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x71C2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x71C3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x71C4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x71C5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x71C6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x71C7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x71CD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x71CE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x71D2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x71D4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x71D5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x71D6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x71DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x71DE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7244, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7245, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7246, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7247, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7248, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7249, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x724A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x724B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x724C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x724D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x724E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x724F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7280, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV570|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7281, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7283, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7284, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7287, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV570|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7289, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV570|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x728B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV570|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x728C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV570|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7290, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7291, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7293, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7297, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x791e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
-+ {0x1002, 0x791f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
-+ {0x1002, 0x793f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS600|RADEON_IS_IGP|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7941, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS600|RADEON_IS_IGP|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x7942, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS600|RADEON_IS_IGP|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x796c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS740|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
-+ {0x1002, 0x796d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS740|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
-+ {0x1002, 0x796e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS740|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
-+ {0x1002, 0x796f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS740|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
-+ {0x1002, 0x9400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9402, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9403, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9405, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x940A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x940B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x940F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94A1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94A3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94B1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94B3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94B4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94B5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94B9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9441, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9442, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9444, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x944A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x944B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x944C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x944E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9450, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9452, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9456, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x945A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x945B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x945E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x946A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x946B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x947A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x947B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9480, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9487, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9488, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9489, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x948A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x948F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9490, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9491, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9495, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9498, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x949C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x949E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x949F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94C0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV610|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94C1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV610|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94C3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV610|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94C4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV610|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94C5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV610|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94C6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV610|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94C7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV610|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94C8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV610|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94C9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV610|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94CB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV610|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94CC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV610|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x94CD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV610|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV670|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9501, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV670|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9504, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV670|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9505, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV670|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9506, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV670|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9507, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV670|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9508, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV670|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9509, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV670|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x950F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV670|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV670|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9515, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV670|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9517, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV670|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9519, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV670|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9540, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9541, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9542, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x954E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x954F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9553, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9555, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9557, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x955f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9580, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9581, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9583, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9586, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9587, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9588, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9589, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x958A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x958B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x958C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x958D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x958E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x958F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9590, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV635|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9591, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV635|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9593, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV635|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9595, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV635|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9596, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV635|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9597, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV635|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9598, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV635|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9599, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV635|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x959B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV635|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x95C0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x95C2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x95C4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x95C5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x95C6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x95C7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x95C9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x95CC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x95CD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x95CE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x95CF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
-+ {0x1002, 0x9610, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9611, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9612, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9613, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9614, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9615, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9616, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9642, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9643, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9644, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
-+ {0x1002, 0x9648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
-+ {0x1002, 0x9649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
-+ {0x1002, 0x964a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x964b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x964c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x964e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
-+ {0x1002, 0x964f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
-+ {0x1002, 0x9710, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9711, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9713, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9714, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9715, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9802, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9804, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9805, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9806, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9807, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x980A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9830, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9831, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9832, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9833, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9836, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9838, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9839, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x983a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x983b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x983c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x983d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x983e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x983f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9851, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9852, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9853, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9854, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9855, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9856, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9857, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9858, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9859, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x985A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x985B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x985C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x985D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x985E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x985F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9904, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9905, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9906, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9908, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9909, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x990A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x990B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x990C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x990D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x990E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x990F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9910, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9913, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9917, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9918, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9919, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9990, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9991, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9993, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9994, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9995, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9996, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9997, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9998, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x9999, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x999A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x999B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x999C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x999D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x99A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x99A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0x1002, 0x99A4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-+ {0, 0, 0}
-+
-+static struct pci_device_id pciidlist[] = {radeon_PCI_IDS};
-+
-+//============================================================
-+// ati_family
-+//============================================================
-+
-+int ati_family(int vendor, int device)
-+{
-+ int i = 0;
-+ while (pciidlist[i].vendor)
-+ {
-+ if (pciidlist[i].vendor == vendor && pciidlist[i].device == device)
-+ return (pciidlist[i].driver_data & RADEON_FAMILY_MASK);
-+ i++;
-+ }
-+ // Not found, must be newer
-+ if (vendor == 0x1002)
-+ return CHIP_LAST;
-+
-+ return 0;
-+}
-+
-+//============================================================
-+// ati_is_legacy
-+//============================================================
-+
-+bool ati_is_legacy(int vendor, int device)
-+{
-+ return (ati_family(vendor, device) < CHIP_CEDAR);
-+}
-+
-+#endif
-\ No newline at end of file
-diff --git a/src/osd/windows/custom_video_pstrip.cpp b/src/osd/windows/custom_video_pstrip.cpp
-new file mode 100644
-index 00000000000..151b6daf63a
---- /dev/null
-+++ b/src/osd/windows/custom_video_pstrip.cpp
-@@ -0,0 +1,529 @@
-+/**************************************************************
-+
-+ custom_video_pstrip.cpp - PowerStrip interface routines
-+
-+ ---------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2016 - Chris Kennedy, Antonio Giner
-+
-+ **************************************************************/
-+
-+/* http://forums.entechtaiwan.com/index.php?topic=5534.msg20902;topicseen#msg20902
-+
-+ UM_SETCUSTOMTIMING = WM_USER+200;
-+ wparam = monitor number, zero-based
-+ lparam = atom for string pointer
-+ lresult = -1 for failure else current pixel clock (integer in Hz)
-+ Note: pass full PowerStrip timing string*
-+
-+ UM_SETREFRESHRATE = WM_USER+201;
-+ wparam = monitor number, zero-based
-+ lparam = refresh rate (integer in Hz), or 0 for read-only
-+ lresult = -1 for failure else current refresh rate (integer in Hz)
-+
-+ UM_SETPOLARITY = WM_USER+202;
-+ wparam = monitor number, zero-based
-+ lparam = polarity bits
-+ lresult = -1 for failure else current polarity bits+1
-+
-+ UM_REMOTECONTROL = WM_USER+210;
-+ wparam = 99
-+ lparam =
-+ 0 to hide tray icon
-+ 1 to show tray icon,
-+ 2 to get build number
-+ 10 to show Performance profiles
-+ 11 to show Color profiles
-+ 12 to show Display profiles
-+ 13 to show Application profiles
-+ 14 to show Adapter information
-+ 15 to show Monitor information
-+ 16 to show Hotkey manager
-+ 17 to show Resource manager
-+ 18 to show Preferences
-+ 19 to show Online services
-+ 20 to show About screen
-+ 21 to show Tip-of-the-day
-+ 22 to show Setup wizard
-+ 23 to show Screen fonts
-+ 24 to show Advanced timing options
-+ 25 to show Custom resolutions
-+ 99 to close PS
-+ lresult = -1 for failure else lparam+1 for success or build number (e.g., 335)
-+ if lparam was 2
-+
-+ UM_SETGAMMARAMP = WM_USER+203;
-+ wparam = monitor number, zero-based
-+ lparam = atom for string pointer
-+ lresult = -1 for failure, 1 for success
-+
-+ UM_CREATERESOLUTION = WM_USER+204;
-+ wparam = monitor number, zero-based
-+ lparam = atom for string pointer
-+ lresult = -1 for failure, 1 for success
-+ Note: pass full PowerStrip timing string*; reboot is usually necessary to see if
-+ the resolution is accepted by the display driver
-+
-+ UM_GETTIMING = WM_USER+205;
-+ wparam = monitor number, zero-based
-+ lresult = -1 for failure else GlobalAtom number identifiying the timing string*
-+ Note: be sure to call GlobalDeleteAtom after reading the string associated with
-+ the atom
-+
-+ UM_GETSETCLOCKS = WM_USER+206;
-+ wparam = monitor number, zero-based
-+ lparam = atom for string pointer
-+ lresult = -1 for failure else GlobalAtom number identifiying the performance
-+ string**
-+ Note: pass full PowerStrip performance string** to set the clocks, and ull to
-+ get clocks; be sure to call GlobalDeleteAtom after reading the string associated
-+ with the atom
-+
-+ NegativeHorizontalPolarity = 0x02;
-+ NegativeVerticalPolarity = 0x04;
-+
-+ *Timing string parameter definition:
-+ 1 = horizontal active pixels
-+ 2 = horizontal front porch
-+ 3 = horizontal sync width
-+ 4 = horizontal back porch
-+ 5 = vertical active pixels
-+ 6 = vertical front porch
-+ 7 = vertical sync width
-+ 8 = vertical back porch
-+ 9 = pixel clock in hertz
-+ 10 = timing flags, where bit:
-+ 1 = negative horizontal porlarity
-+ 2 = negative vertical polarity
-+ 3 = interlaced
-+ 5 = composite sync
-+ 7 = sync-on-green
-+ all other bits reserved
-+
-+ **Performance string parameter definition:
-+ 1 = memory clock in hertz
-+ 2 = engine clock in hertz
-+ 3 = reserved
-+ 4 = reserved
-+ 5 = reserved
-+ 6 = reserved
-+ 7 = reserved
-+ 8 = reserved
-+ 9 = 2D memory clock in hertz (if different from 3D)
-+ 10 = 2D engine clock in hertz (if different from 3D) */
-+
-+// standard windows headers
-+#include <windows.h>
-+#include <stdio.h>
-+
-+// MAME headers
-+#include "emu.h"
-+
-+// PowerStrip header
-+#include "custom_video_pstrip.h"
-+
-+//============================================================
-+// GLOBALS
-+//============================================================
-+
-+static HWND hPSWnd;
-+static MonitorTiming timing_backup;
-+
-+//============================================================
-+// CONSTANTS
-+//============================================================
-+
-+#define UM_SETCUSTOMTIMING (WM_USER+200)
-+#define UM_SETREFRESHRATE (WM_USER+201)
-+#define UM_SETPOLARITY (WM_USER+202)
-+#define UM_REMOTECONTROL (WM_USER+210)
-+#define UM_SETGAMMARAMP (WM_USER+203)
-+#define UM_CREATERESOLUTION (WM_USER+204)
-+#define UM_GETTIMING (WM_USER+205)
-+#define UM_GETSETCLOCKS (WM_USER+206)
-+#define UM_SETCUSTOMTIMINGFAST (WM_USER+211) // glitches vertical sync with PS 3.65 build 568
-+
-+#define NegativeHorizontalPolarity 0x02
-+#define NegativeVerticalPolarity 0x04
-+#define Interlace 0x08
-+
-+#define HideTrayIcon 0x00
-+#define ShowTrayIcon 0x01
-+#define ClosePowerStrip 0x63
-+
-+//============================================================
-+// ps_init
-+//============================================================
-+
-+int ps_init(int monitor_index, modeline *modeline)
-+{
-+ hPSWnd = FindWindowA("TPShidden", NULL);
-+
-+ if (hPSWnd)
-+ {
-+ osd_printf_verbose("PStrip: PowerStrip found!\n");
-+ if (ps_get_monitor_timing(monitor_index, &timing_backup) && modeline)
-+ {
-+ ps_pstiming_to_modeline(&timing_backup, modeline);
-+ return 1;
-+ }
-+ }
-+ else
-+ osd_printf_verbose("PStrip: Could not get PowerStrip API interface\n");
-+
-+ return 0;
-+}
-+
-+//============================================================
-+// ps_reset
-+//============================================================
-+
-+int ps_reset(int monitor_index)
-+{
-+ return ps_set_monitor_timing(monitor_index, &timing_backup);
-+}
-+
-+//============================================================
-+// ps_get_modeline
-+//============================================================
-+
-+int ps_get_modeline(int monitor_index, modeline *modeline)
-+{
-+ MonitorTiming timing = {0};
-+
-+ if (ps_get_monitor_timing(monitor_index, &timing))
-+ {
-+ ps_pstiming_to_modeline(&timing, modeline);
-+ return 1;
-+ }
-+ else return 0;
-+}
-+
-+//============================================================
-+// ps_set_modeline
-+//============================================================
-+
-+int ps_set_modeline(int monitor_index, modeline *modeline)
-+{
-+ MonitorTiming timing = {0};
-+
-+ ps_modeline_to_pstiming(modeline, &timing);
-+
-+ timing.PixelClockInKiloHertz = ps_best_pclock(monitor_index, &timing, timing.PixelClockInKiloHertz);
-+
-+ if (ps_set_monitor_timing(monitor_index, &timing))
-+ return 1;
-+ else
-+ return 0;
-+}
-+
-+//============================================================
-+// ps_get_monitor_timing
-+//============================================================
-+
-+int ps_get_monitor_timing(int monitor_index, MonitorTiming *timing)
-+{
-+ LRESULT lresult;
-+ char in[256];
-+
-+ if (!hPSWnd) return 0;
-+
-+ lresult = SendMessage(hPSWnd, UM_GETTIMING, monitor_index, 0);
-+
-+ if (lresult == -1)
-+ {
-+ osd_printf_verbose("PStrip: Could not get PowerStrip timing string\n");
-+ return 0;
-+ }
-+
-+ if (!GlobalGetAtomNameA(lresult, in, sizeof(in)))
-+ {
-+ osd_printf_verbose("PStrip: GlobalGetAtomName failed\n");
-+ return 0;
-+ }
-+
-+ osd_printf_verbose("PStrip: ps_get_monitor_timing(%d): %s\n", monitor_index, in);
-+
-+ ps_read_timing_string(in, timing);
-+
-+ GlobalDeleteAtom(lresult); // delete atom created by PowerStrip
-+
-+ return 1;
-+}
-+
-+//============================================================
-+// ps_set_monitor_timing
-+//============================================================
-+
-+int ps_set_monitor_timing(int monitor_index, MonitorTiming *timing)
-+{
-+ LRESULT lresult;
-+ ATOM atom;
-+ char out[256];
-+
-+ if (!hPSWnd) return 0;
-+
-+ ps_fill_timing_string(out, timing);
-+ atom = GlobalAddAtomA(out);
-+
-+ if (atom)
-+ {
-+ lresult = SendMessage(hPSWnd, UM_SETCUSTOMTIMING, monitor_index, atom);
-+
-+ if (lresult < 0)
-+ {
-+ osd_printf_verbose("PStrip: SendMessage failed\n");
-+ GlobalDeleteAtom(atom);
-+ }
-+ else
-+ {
-+ osd_printf_verbose("PStrip: ps_set_monitor_timing(%d): %s\n", monitor_index, out);
-+ return 1;
-+ }
-+ }
-+ else osd_printf_verbose("PStrip: ps_set_monitor_timing atom creation failed\n");
-+
-+ return 0;
-+}
-+
-+//============================================================
-+// ps_set_monitor_timing_string
-+//============================================================
-+
-+int ps_set_monitor_timing_string(int monitor_index, char *in)
-+{
-+ MonitorTiming timing;
-+
-+ ps_read_timing_string(in, &timing);
-+ return ps_set_monitor_timing(monitor_index, &timing);
-+}
-+
-+//============================================================
-+// ps_set_refresh
-+//============================================================
-+
-+int ps_set_refresh(int monitor_index, double vfreq)
-+{
-+ MonitorTiming timing = {0};
-+ int hht, vvt, new_vvt;
-+ int desired_pClock;
-+ int best_pClock;
-+
-+ memcpy(&timing, &timing_backup, sizeof(MonitorTiming));
-+
-+ hht = timing.HorizontalActivePixels
-+ + timing.HorizontalFrontPorch
-+ + timing.HorizontalSyncWidth
-+ + timing.HorizontalBackPorch;
-+
-+ vvt = timing.VerticalActivePixels
-+ + timing.VerticalFrontPorch
-+ + timing.VerticalSyncWidth
-+ + timing.VerticalBackPorch;
-+
-+ desired_pClock = hht * vvt * vfreq / 1000;
-+ best_pClock = ps_best_pclock(monitor_index, &timing, desired_pClock);
-+
-+ new_vvt = best_pClock * 1000 / (vfreq * hht);
-+
-+ timing.VerticalBackPorch += (new_vvt - vvt);
-+ timing.PixelClockInKiloHertz = best_pClock;
-+
-+ ps_set_monitor_timing(monitor_index, &timing);
-+ ps_get_monitor_timing(monitor_index, &timing);
-+
-+ return 1;
-+}
-+
-+//============================================================
-+// ps_best_pclock
-+//============================================================
-+
-+int ps_best_pclock(int monitor_index, MonitorTiming *timing, int desired_pclock)
-+{
-+ MonitorTiming timing_read;
-+ int best_pclock = 0;
-+
-+ osd_printf_verbose("PStrip: ps_best_pclock(%d), getting stable dotclocks for %d...\n", monitor_index, desired_pclock);
-+
-+ for (int i = -50; i <= 50; i += 25)
-+ {
-+ timing->PixelClockInKiloHertz = desired_pclock + i;
-+
-+ ps_set_monitor_timing(monitor_index, timing);
-+ ps_get_monitor_timing(monitor_index, &timing_read);
-+
-+ if (abs(timing_read.PixelClockInKiloHertz - desired_pclock) < abs(desired_pclock - best_pclock))
-+ best_pclock = timing_read.PixelClockInKiloHertz;
-+ }
-+
-+ osd_printf_verbose("PStrip: ps_best_pclock(%d), new dotclock: %d\n", monitor_index, best_pclock);
-+
-+ return best_pclock;
-+}
-+
-+//============================================================
-+// ps_create_resolution
-+//============================================================
-+
-+int ps_create_resolution(int monitor_index, modeline *modeline)
-+{
-+ LRESULT lresult;
-+ ATOM atom;
-+ char out[256];
-+ MonitorTiming timing = {0};
-+
-+ if (!hPSWnd) return 0;
-+
-+ ps_modeline_to_pstiming(modeline, &timing);
-+
-+ ps_fill_timing_string(out, &timing);
-+ atom = GlobalAddAtomA(out);
-+
-+ if (atom)
-+ {
-+ lresult = SendMessage(hPSWnd, UM_CREATERESOLUTION, monitor_index, atom);
-+
-+ if (lresult < 0)
-+ {
-+ osd_printf_verbose("PStrip: SendMessage failed\n");
-+ GlobalDeleteAtom(atom);
-+ }
-+ else
-+ {
-+ osd_printf_verbose("PStrip: ps_create_resolution(%d): %dx%d succeded \n",
-+ modeline->width, modeline->height, monitor_index);
-+ return 1;
-+ }
-+ }
-+ else osd_printf_verbose("PStrip: ps_create_resolution atom creation failed\n");
-+
-+ return 0;
-+}
-+
-+//============================================================
-+// ps_read_timing_string
-+//============================================================
-+
-+bool ps_read_timing_string(char *in, MonitorTiming *timing)
-+{
-+ if (sscanf(in,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
-+ &timing->HorizontalActivePixels,
-+ &timing->HorizontalFrontPorch,
-+ &timing->HorizontalSyncWidth,
-+ &timing->HorizontalBackPorch,
-+ &timing->VerticalActivePixels,
-+ &timing->VerticalFrontPorch,
-+ &timing->VerticalSyncWidth,
-+ &timing->VerticalBackPorch,
-+ &timing->PixelClockInKiloHertz,
-+ &timing->TimingFlags.w) == 10) return true;
-+
-+ return false;
-+}
-+
-+//============================================================
-+// ps_fill_timing_string
-+//============================================================
-+
-+void ps_fill_timing_string(char *out, MonitorTiming *timing)
-+{
-+ sprintf(out, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
-+ timing->HorizontalActivePixels,
-+ timing->HorizontalFrontPorch,
-+ timing->HorizontalSyncWidth,
-+ timing->HorizontalBackPorch,
-+ timing->VerticalActivePixels,
-+ timing->VerticalFrontPorch,
-+ timing->VerticalSyncWidth,
-+ timing->VerticalBackPorch,
-+ timing->PixelClockInKiloHertz,
-+ timing->TimingFlags.w);
-+}
-+
-+//============================================================
-+// ps_modeline_to_pstiming
-+//============================================================
-+
-+int ps_modeline_to_pstiming(modeline *modeline, MonitorTiming *timing)
-+{
-+ timing->HorizontalActivePixels = modeline->hactive;
-+ timing->HorizontalFrontPorch = modeline->hbegin - modeline->hactive;
-+ timing->HorizontalSyncWidth = modeline->hend - modeline->hbegin;
-+ timing->HorizontalBackPorch = modeline->htotal - modeline->hend;
-+
-+ timing->VerticalActivePixels = modeline->vactive;
-+ timing->VerticalFrontPorch = modeline->vbegin - modeline->vactive;
-+ timing->VerticalSyncWidth = modeline->vend - modeline->vbegin;
-+ timing->VerticalBackPorch = modeline->vtotal - modeline->vend;
-+
-+ timing->PixelClockInKiloHertz = modeline->pclock / 1000;
-+
-+ if (modeline->hsync == 0)
-+ timing->TimingFlags.w |= NegativeHorizontalPolarity;
-+ if (modeline->vsync == 0)
-+ timing->TimingFlags.w |= NegativeVerticalPolarity;
-+ if (modeline->interlace)
-+ timing->TimingFlags.w |= Interlace;
-+
-+ return 0;
-+}
-+
-+//============================================================
-+// ps_pstiming_to_modeline
-+//============================================================
-+
-+int ps_pstiming_to_modeline(MonitorTiming *timing, modeline *modeline)
-+{
-+ modeline->hactive = timing->HorizontalActivePixels;
-+ modeline->hbegin = modeline->hactive + timing->HorizontalFrontPorch;
-+ modeline->hend = modeline->hbegin + timing->HorizontalSyncWidth;
-+ modeline->htotal = modeline->hend + timing->HorizontalBackPorch;
-+
-+ modeline->vactive = timing->VerticalActivePixels;
-+ modeline->vbegin = modeline->vactive + timing->VerticalFrontPorch;
-+ modeline->vend = modeline->vbegin + timing->VerticalSyncWidth;
-+ modeline->vtotal = modeline->vend + timing->VerticalBackPorch;
-+
-+ modeline->width = modeline->hactive;
-+ modeline->height = modeline->vactive;
-+
-+ modeline->pclock = timing->PixelClockInKiloHertz * 1000;
-+
-+ if (!(timing->TimingFlags.w & NegativeHorizontalPolarity))
-+ modeline->hsync = 1;
-+
-+ if (!(timing->TimingFlags.w & NegativeVerticalPolarity))
-+ modeline->vsync = 1;
-+
-+ if ((timing->TimingFlags.w & Interlace))
-+ modeline->interlace = 1;
-+
-+ modeline->hfreq = modeline->pclock / modeline->htotal;
-+ modeline->vfreq = modeline->hfreq / modeline->vtotal * (modeline->interlace?2:1);
-+
-+ return 0;
-+}
-+
-+//============================================================
-+// ps_monitor_index
-+//============================================================
-+
-+int ps_monitor_index (const char *display_name)
-+{
-+ int monitor_index = 0;
-+ char sub_index[2];
-+
-+ sub_index[0] = display_name[strlen(display_name)-1];
-+ sub_index[1] = 0;
-+ if (sscanf(sub_index,"%d", &monitor_index) == 1)
-+ monitor_index --;
-+
-+ return monitor_index;
-+}
-diff --git a/src/osd/windows/custom_video_pstrip.h b/src/osd/windows/custom_video_pstrip.h
-new file mode 100644
-index 00000000000..b73deb98eca
---- /dev/null
-+++ b/src/osd/windows/custom_video_pstrip.h
-@@ -0,0 +1,63 @@
-+/**************************************************************
-+
-+ custom_video_powerstrip.h - PowerStrip interface routines
-+
-+ ---------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2016 - Chris Kennedy, Antonio Giner
-+
-+ **************************************************************/
-+
-+//============================================================
-+// TYPE DEFINITIONS
-+//============================================================
-+
-+typedef struct
-+{
-+ int HorizontalActivePixels;
-+ int HorizontalFrontPorch;
-+ int HorizontalSyncWidth;
-+ int HorizontalBackPorch;
-+ int VerticalActivePixels;
-+ int VerticalFrontPorch;
-+ int VerticalSyncWidth;
-+ int VerticalBackPorch;
-+ int PixelClockInKiloHertz;
-+ union
-+ {
-+ int w;
-+ struct
-+ {
-+ unsigned :1;
-+ unsigned HorizontalPolarityNegative:1;
-+ unsigned VerticalPolarityNegative:1;
-+ unsigned :29;
-+ } b;
-+ } TimingFlags;
-+} MonitorTiming;
-+
-+//============================================================
-+// PROTOTYPES
-+//============================================================
-+
-+int ps_init(int monitor_index, modeline *modeline);
-+int ps_reset(int monitor_index);
-+int ps_get_modeline(int monitor_index, modeline *modeline);
-+int ps_set_modeline(int monitor_index, modeline *modeline);
-+int ps_get_monitor_timing(int monitor_index, MonitorTiming *timing);
-+int ps_set_monitor_timing(int monitor_index, MonitorTiming *timing);
-+int ps_set_monitor_timing_string(int monitor_index, char *in);
-+int ps_set_refresh(int monitor_index, double vfreq);
-+int ps_best_pclock(int monitor_index, MonitorTiming *timing, int desired_pclock);
-+int ps_create_resolution(int monitor_index, modeline *modeline);
-+bool ps_read_timing_string(char *in, MonitorTiming *timing);
-+void ps_fill_timing_string(char *out, MonitorTiming *timing);
-+int ps_modeline_to_pstiming(modeline *modeline, MonitorTiming *timing);
-+int ps_pstiming_to_modeline(MonitorTiming *timing, modeline *modeline);
-+int ps_monitor_index (const char *display_name);
-diff --git a/src/osd/windows/switchres_windows.cpp b/src/osd/windows/switchres_windows.cpp
-new file mode 100644
-index 00000000000..5a0c052f49a
---- /dev/null
-+++ b/src/osd/windows/switchres_windows.cpp
-@@ -0,0 +1,516 @@
-+/**************************************************************
-+
-+ switchres_windows.cpp - Windows OSD SwitchRes core routines
-+
-+ -----------------------------------------------------------
-+
-+ SwitchRes Modeline generation engine for emulation
-+
-+ GroovyMAME Integration of SwitchRes into the MAME project
-+ Some reworked patches from SailorSat's CabMAME
-+
-+ License GPL-2.0+
-+ Copyright 2010-2016 - Chris Kennedy, Antonio Giner
-+
-+ **************************************************************/
-+
-+// standard windows headers
-+#include <windows.h>
-+
-+// MAME headers
-+#include "emu.h"
-+#include "emuopts.h"
-+#include "../../frontend/mame/mameopts.h"
-+
-+// MAMEOS headers
-+#include "winmain.h"
-+#include "window.h"
-+
-+// Custom video headers
-+#include "custom_video.h"
-+
-+#ifdef _MSC_VER
-+#define min(a, b) ((a) < (b) ? (a) : (b))
-+#else
-+#define min(a,b)({ __typeof__ (a) _a = (a);__typeof__ (b) _b = (b);_a < _b ? _a : _b; })
-+#endif
-+
-+//============================================================
-+// PROTOTYPES
-+//============================================================
-+
-+int display_get_device_info(const char *screen_option, char *device_name, char *device_id, char *device_key);
-+int display_get_available_video_modes(const char *device_name, modeline *mode, modeline *current, config_settings *cs);
-+int display_get_desktop_mode(const char *device_name, modeline *current);
-+int display_set_desktop_mode(modeline *mode, int flags);
-+int display_restore_desktop_mode(int flags);
-+
-+static void set_option_osd(running_machine &machine, const char *option_ID, bool state);
-+static int copy_to_clipboard(char *txt);
-+
-+//============================================================
-+// PARAMETERS
-+//============================================================
-+
-+// display modes
-+#define DM_INTERLACED 0x00000002
-+#define DISPLAY_MAX 16
-+
-+//============================================================
-+// LOCAL VARIABLES
-+//============================================================
-+
-+static char m_device_name[32];
-+static char m_device_id[128];
-+static char m_device_key[128];
-+static DEVMODEA desktop_devmode;
-+
-+//============================================================
-+// switchres_init_osd
-+//============================================================
-+
-+bool switchres_init_osd(running_machine &machine)
-+{
-+ config_settings *cs = &machine.switchres.cs;
-+ game_info *game = &machine.switchres.game;
-+ modeline *mode_table = machine.switchres.video_modes;
-+ modeline *user_mode = &machine.switchres.user_mode;
-+ monitor_range *range = machine.switchres.range;
-+ const char * screen, * aspect;
-+ char resolution[32]={'\x00'};
-+ modeline desktop_mode;
-+
-+ windows_options &options = downcast<windows_options &>(machine.options());
-+
-+ // Initialize structures and config settings
-+ memset(&desktop_mode, 0, sizeof(struct modeline));
-+ memset(cs, 0, sizeof(struct config_settings));
-+ memset(game, 0, sizeof(struct game_info));
-+
-+ // Init Switchres common info
-+ switchres_init(machine);
-+
-+ // Complete config settings
-+ cs->monitor_count = options.numscreens();
-+ cs->doublescan = 0;
-+
-+ // Get device info
-+ screen = strcmp(options.screen(0), "auto")? options.screen(0) : options.screen();
-+ display_get_device_info(screen, m_device_name, m_device_id, m_device_key);
-+
-+ // Get current desktop resolution
-+ display_get_desktop_mode(m_device_name, &desktop_mode);
-+
-+ // Initialize custom video
-+ custom_video_init(m_device_name, m_device_id, &desktop_mode, user_mode, mode_table,
-+ options.powerstrip()? CUSTOM_VIDEO_TIMING_POWERSTRIP : 0,
-+ options.powerstrip()? (char *)options.ps_timing() : m_device_key);
-+
-+ // Get per window resolution
-+ strcpy(resolution, strcmp(options.resolution(0), "auto")? options.resolution(0) : options.resolution());
-+
-+ // Get list of available video modes
-+ if (!display_get_available_video_modes(m_device_name, mode_table, &desktop_mode, cs))
-+ {
-+ set_option_osd(machine, OSDOPTION_SWITCHRES, false);
-+ return false;
-+ }
-+
-+ // Get per window aspect
-+ aspect = strcmp(options.aspect(0), "auto")? options.aspect(0) : options.aspect();
-+ if (strcmp(aspect, "auto"))
-+ {
-+ float num, den;
-+ sscanf(aspect, "%f:%f", &num, &den);
-+ cs->monitor_aspect = cs->desktop_rotated? den/num : num/den;
-+ }
-+ else
-+ cs->monitor_aspect = STANDARD_CRT_ASPECT;
-+
-+ // If monitor is LCD, create automatic specs and force resolution
-+ if (!strcmp(cs->monitor, "lcd"))
-+ {
-+ osd_printf_verbose("SwitchRes: Creating automatic specs for LCD based on %s\n", desktop_mode.hactive? "current timings" : "VESA GTF");
-+ if (!desktop_mode.hactive) modeline_vesa_gtf(&desktop_mode);
-+ modeline_to_monitor_range(range, &desktop_mode);
-+ monitor_show_range(range);
-+ sprintf(resolution, "%dx%d@%d", desktop_mode.width, desktop_mode.height, desktop_mode.refresh);
-+ }
-+ // Otherwise (non-LCD), convert the user defined modeline into a -resolution option
-+ else if (user_mode->hactive)
-+ sprintf(resolution, "%dx%d", user_mode->hactive, user_mode->vactive);
-+
-+ // Filter the mode table according the -resolution option
-+ if (strcmp(resolution, "auto"))
-+ {
-+ int i = 1;
-+ bool found = false;
-+ osd_printf_verbose("SwitchRes: -resolution was forced as %s\n", resolution);
-+
-+ if ((sscanf(resolution, "%dx%d@%d", &cs->width, &cs->height, &cs->refresh) < 3) &&
-+ ((!strstr(resolution, "x") || (sscanf(resolution, "%dx%d", &cs->width, &cs->height) != 2))))
-+ osd_printf_info("SwitchRes: illegal -resolution value: %s\n", resolution);
-+
-+ else while (mode_table[i].width && i < MAX_MODELINES)
-+ {
-+ // Lock all modes that don't match the user's -resolution rules
-+ if (!( (mode_table[i].width == cs->width || (mode_table[i].type & X_RES_EDITABLE && cs->width <= DUMMY_WIDTH) || cs->width == 0)
-+ && (mode_table[i].height == cs->height || cs->height == 0)
-+ && (mode_table[i].refresh == cs->refresh || cs->refresh == 0) ))
-+ mode_table[i].type |= MODE_DISABLED;
-+
-+ else
-+ {
-+ // If we have an user defined modeline, link its label to current item in mode table
-+ if (user_mode->hactive && !found)
-+ {
-+ user_mode->width = mode_table[i].width;
-+ user_mode->height = mode_table[i].height;
-+ user_mode->refresh = mode_table[i].refresh;
-+ user_mode->type = mode_table[i].type & ~V_FREQ_EDITABLE & ~X_RES_EDITABLE;
-+ }
-+ mode_table[i].type &= ~MODE_DISABLED;
-+ mode_table[i].type |= MODE_USER_DEF;
-+ found = true;
-+ }
-+ i++;
-+ }
-+ if (!found)
-+ osd_printf_info("SwitchRes: -resolution value not available: %s\n", resolution);
-+ }
-+
-+ // Get game info
-+ switchres_get_game_info(machine);
-+
-+ return true;
-+}
-+
-+//============================================================
-+// switchres_modeline_setup
-+//============================================================
-+
-+bool switchres_modeline_setup(running_machine &machine)
-+{
-+ modeline *best_mode = &machine.switchres.best_mode;
-+ windows_options &options = downcast<windows_options &>(machine.options());
-+ windows_osd_interface &osd = downcast<windows_osd_interface &>(machine.osd());
-+ char modeline_txt[256]={'\x00'};
-+
-+ osd_printf_verbose("\nSwitchRes: Entering switchres_modeline_setup\n");
-+
-+ // Find most suitable video mode and generate a modeline for it if we're allowed
-+ if (!switchres_get_video_mode(machine))
-+ {
-+ set_option_osd(machine, OSDOPTION_SWITCHRES, false);
-+ return false;
-+ }
-+
-+ // Make the new video timings available to the system
-+ if (options.modeline_generation())
-+ {
-+ if(!custom_video_update_timing(best_mode))
-+ {
-+ set_option_osd(machine, OSDOPTION_SWITCHRES, false);
-+ return false;
-+ }
-+
-+ if (options.verbose())
-+ {
-+ modeline_print(best_mode, modeline_txt, MS_FULL);
-+ copy_to_clipboard(modeline_txt);
-+ }
-+ }
-+
-+ // Set MAME common options
-+ switchres_set_options(machine);
-+
-+ // Set MAME OSD specific options
-+
-+ // Set fullscreen resolution for the OpenGL case
-+ if (options.switch_res() && (!strcmp(options.video(), "opengl"))) display_set_desktop_mode(best_mode, CDS_FULLSCREEN);
-+
-+ // Black frame insertion / multithreading
-+ bool black_frame_insertion = options.black_frame_insertion() && best_mode->result.v_scale > 1 && best_mode->vfreq > 100;
-+ set_option_osd(machine, OPTION_BLACK_FRAME_INSERTION, black_frame_insertion);
-+
-+ // Vertical synchronization management (autosync)
-+ // Disable -syncrefresh if our vfreq is scaled or out of syncrefresh_tolerance (-triplebuffer will be used instead)
-+ // Forcing -syncrefresh will override the -triplebuffer setting
-+ bool sync_refresh_effective = black_frame_insertion || !((best_mode->result.weight & R_V_FREQ_OFF) || best_mode->result.v_scale > 1);
-+ set_option_osd(machine, OPTION_SYNCREFRESH, options.autosync()? sync_refresh_effective : options.sync_refresh());
-+ set_option_osd(machine, WINOPTION_TRIPLEBUFFER, options.autosync()? !sync_refresh_effective : (options.triple_buffer() && !options.sync_refresh()));
-+ set_option_osd(machine, OSDOPTION_WAITVSYNC, options.sync_refresh() || options.triple_buffer());
-+
-+ // Set filter options
-+ set_option_osd(machine, OSDOPTION_FILTER, ((best_mode->result.weight & R_RES_STRETCH || best_mode->interlace) && (!strcmp(options.video(), "auto") || !strcmp(options.video(), "d3d"))));
-+
-+ // Refresh video options
-+ osd.extract_video_config();
-+
-+ return true;
-+}
-+
-+//============================================================
-+// switchres_modeline_remove
-+//============================================================
-+
-+bool switchres_modeline_remove(running_machine &machine)
-+{
-+ windows_options &options = downcast<windows_options &>(machine.options());
-+
-+ // Restore original video timings
-+ if (options.modeline_generation()) custom_video_restore_timing();
-+
-+ // Set destop resolution for the OpenGL case
-+ if (options.switch_res() && !strcmp(options.video(), "opengl")) display_restore_desktop_mode(0);
-+
-+ // Free custom video api
-+ custom_video_close();
-+
-+ return true;
-+}
-+
-+//============================================================
-+// switchres_resolution_change
-+//============================================================
-+
-+bool switchres_resolution_change(win_window_info *window)
-+{
-+ running_machine &machine = window->machine();
-+ modeline *best_mode = &machine.switchres.best_mode;
-+ modeline previous_mode;
-+
-+ // If there's no pending change, just exit
-+ if (!switchres_check_resolution_change(machine))
-+ return false;
-+
-+ // Get the new resolution
-+ previous_mode = *best_mode;
-+ switchres_modeline_setup(machine);
-+
-+ // Only change resolution if the new one is actually different
-+ if (memcmp(&previous_mode, best_mode, offsetof(modeline, result)))
-+ {
-+ window->m_win_config.width = best_mode->width;
-+ window->m_win_config.height = best_mode->height;
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+//============================================================
-+// display_get_desktop_mode
-+//============================================================
-+
-+int display_get_desktop_mode(const char *device_name, modeline *current)
-+{
-+ memset(&desktop_devmode, 0, sizeof(DEVMODEA));
-+ desktop_devmode.dmSize = sizeof(DEVMODEA);
-+
-+ if (EnumDisplaySettingsExA(!strcmp(device_name, "auto")?NULL:device_name, ENUM_CURRENT_SETTINGS, &desktop_devmode, 0))
-+ {
-+ if (current)
-+ {
-+ current->width = desktop_devmode.dmDisplayOrientation == DMDO_DEFAULT || desktop_devmode.dmDisplayOrientation == DMDO_180? desktop_devmode.dmPelsWidth:desktop_devmode.dmPelsHeight;
-+ current->height = desktop_devmode.dmDisplayOrientation == DMDO_DEFAULT || desktop_devmode.dmDisplayOrientation == DMDO_180? desktop_devmode.dmPelsHeight:desktop_devmode.dmPelsWidth;
-+ current->refresh = desktop_devmode.dmDisplayFrequency;
-+ current->interlace = (desktop_devmode.dmDisplayFlags & DM_INTERLACED)?1:0;
-+ }
-+ return true;
-+ }
-+ return false;
-+}
-+
-+//============================================================
-+// display_restore_desktop_mode
-+//============================================================
-+
-+int display_restore_desktop_mode(int flags)
-+{
-+ if (ChangeDisplaySettingsExA(m_device_name, &desktop_devmode, NULL, 0, 0) == DISP_CHANGE_SUCCESSFUL)
-+ return true;
-+
-+ return false;
-+}
-+
-+//============================================================
-+// display_set_desktop_mode
-+//============================================================
-+
-+int display_set_desktop_mode(modeline *mode, int flags)
-+{
-+ modeline *backup_mode = custom_video_get_backup_mode();
-+ modeline *mode_to_check_interlace = backup_mode->hactive? backup_mode : mode;
-+ DEVMODEA lpDevMode;
-+
-+ display_get_desktop_mode(m_device_name, NULL);
-+
-+ if (mode)
-+ {
-+ memset(&lpDevMode, 0, sizeof(DEVMODEA));
-+ lpDevMode.dmSize = sizeof(DEVMODEA);
-+ lpDevMode.dmPelsWidth = mode->type & MODE_ROTATED? mode->height : mode->width;
-+ lpDevMode.dmPelsHeight = mode->type & MODE_ROTATED? mode->width : mode->height;
-+ lpDevMode.dmDisplayFrequency = (int)mode->refresh;
-+ lpDevMode.dmDisplayFlags = mode_to_check_interlace->interlace?DM_INTERLACED:0;
-+ lpDevMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS;
-+
-+ if (ChangeDisplaySettingsExA(m_device_name, &lpDevMode, NULL, flags, 0) == DISP_CHANGE_SUCCESSFUL)
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+//============================================================
-+// display_get_available_video_modes
-+//============================================================
-+
-+int display_get_available_video_modes(const char *device_name, modeline *mode, modeline *current, config_settings *cs)
-+{
-+ int iModeNum = 0, i = 0, j = 0, k = 1;
-+ DEVMODEA lpDevMode;
-+
-+ if (!strcmp(device_name, "auto"))
-+ device_name = NULL;
-+
-+
-+ memset(&lpDevMode, 0, sizeof(DEVMODEA));
-+ lpDevMode.dmSize = sizeof(DEVMODEA);
-+
-+ osd_printf_verbose("Switchres: Searching for custom video modes...\n");
-+
-+ while (EnumDisplaySettingsExA(device_name, iModeNum, &lpDevMode, cs->lock_unsupported_modes?0:EDS_RAWMODE) != 0)
-+ {
-+ if (k == MAX_MODELINES)
-+ {
-+ osd_printf_verbose("SwitchRes: Warning, too many active modelines for storage %d\n", k);
-+ break;
-+ }
-+ else if (lpDevMode.dmBitsPerPel == 32 && lpDevMode.dmDisplayFixedOutput == DMDFO_DEFAULT)
-+ {
-+ modeline *m = &mode[k];
-+ memset(m, 0, sizeof(struct modeline));
-+ m->interlace = (lpDevMode.dmDisplayFlags & DM_INTERLACED)?1:0;
-+ m->width = lpDevMode.dmDisplayOrientation == DMDO_DEFAULT || lpDevMode.dmDisplayOrientation == DMDO_180? lpDevMode.dmPelsWidth:lpDevMode.dmPelsHeight;
-+ m->height = lpDevMode.dmDisplayOrientation == DMDO_DEFAULT || lpDevMode.dmDisplayOrientation == DMDO_180? lpDevMode.dmPelsHeight:lpDevMode.dmPelsWidth;
-+ m->refresh = lpDevMode.dmDisplayFrequency;
-+ m->hactive = m->width;
-+ m->vactive = m->height;
-+ m->vfreq = m->refresh;
-+ m->type |= lpDevMode.dmDisplayOrientation == DMDO_90 || lpDevMode.dmDisplayOrientation == DMDO_270? MODE_ROTATED : MODE_OK;
-+
-+ for (i = 0; i < k; i++) if (mode[i].width == m->width && mode[i].height == m->height && mode[i].refresh == m->refresh) goto found;
-+
-+ if (current && m->width == current->width && m->height == current->height && m->refresh == current->refresh)
-+ {
-+ m->type |= MODE_DESKTOP;
-+ if (m->type & MODE_ROTATED) cs->desktop_rotated = true;
-+ }
-+
-+ osd_printf_verbose("Switchres: [%3d] %4dx%4d @%3d%s %s: ", k, m->width, m->height, m->refresh, m->type & MODE_DESKTOP?"*":"", m->type & MODE_ROTATED?"rot":"");
-+
-+ if (custom_video_get_timing(m))
-+ {
-+ j++;
-+ if (m->type & MODE_DESKTOP) memcpy(current, m, sizeof(modeline));
-+ }
-+ k++;
-+ }
-+ found:
-+ iModeNum++;
-+ }
-+ k--;
-+ osd_printf_verbose("SwitchRes: Found %d custom of %d active video modes\n", j, k);
-+ return k;
-+}
-+
-+//============================================================
-+// display_get_device_info
-+//============================================================
-+
-+int display_get_device_info(const char *screen_option, char *device_name, char *device_id, char *device_key)
-+{
-+ DISPLAY_DEVICEA lpDisplayDevice[DISPLAY_MAX];
-+ int idev = 0;
-+ int found = -1;
-+
-+ while (idev < DISPLAY_MAX)
-+ {
-+ memset(&lpDisplayDevice[idev], 0, sizeof(DISPLAY_DEVICEA));
-+ lpDisplayDevice[idev].cb = sizeof(DISPLAY_DEVICEA);
-+
-+ if (EnumDisplayDevicesA(NULL, idev, &lpDisplayDevice[idev], 0) == FALSE)
-+ break;
-+
-+ if ((!strcmp(screen_option, "auto") && (lpDisplayDevice[idev].StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE))
-+ || !strcmp(screen_option, lpDisplayDevice[idev].DeviceName))
-+ found = idev;
-+
-+ idev++;
-+ }
-+ if (found != -1)
-+ {
-+ strncpy(device_name, lpDisplayDevice[found].DeviceName, sizeof(m_device_name));
-+ strncpy(device_id, lpDisplayDevice[found].DeviceID, sizeof(m_device_id));
-+ osd_printf_verbose("SwitchRes: %s: %s (%s)\n", device_name, lpDisplayDevice[found].DeviceString, device_id);
-+
-+ char *pch;
-+ int i;
-+ for (i = 0; i < idev; i++)
-+ {
-+ pch = strstr(lpDisplayDevice[i].DeviceString, lpDisplayDevice[found].DeviceString);
-+ if (pch)
-+ {
-+ found = i;
-+ break;
-+ }
-+ }
-+
-+ char *chsrc, *chdst;
-+ chdst = device_key;
-+
-+ for (chsrc = lpDisplayDevice[i].DeviceKey + 18; *chsrc != 0; chsrc++)
-+ *chdst++ = *chsrc;
-+
-+ *chdst = 0;
-+ }
-+ else
-+ {
-+ osd_printf_verbose("SwitchRes: Failed obtaining default video registry key\n");
-+ return -1;
-+ }
-+
-+ osd_printf_verbose("SwitchRes: Device key: %s\n", device_key);
-+ return 0;
-+}
-+
-+//============================================================
-+// set_option_osd - option setting wrapper
-+//============================================================
-+
-+static void set_option_osd(running_machine &machine, const char *option_ID, bool state)
-+{
-+ windows_options &options = downcast<windows_options &>(machine.options());
-+
-+ options.set_value(option_ID, state, OPTION_PRIORITY_SWITCHRES);
-+ osd_printf_verbose("SwitchRes: Setting option -%s%s\n", machine.options().bool_value(option_ID)?"":"no", option_ID);
-+}
-+
-+//============================================================
-+// copy_to_clipboard
-+//============================================================
-+
-+static int copy_to_clipboard(char *txt)
-+{
-+ HGLOBAL hglb;
-+ hglb = GlobalAlloc(GMEM_MOVEABLE, 256);
-+ memcpy(GlobalLock(hglb), txt, strlen(txt) + 1);
-+ GlobalUnlock(hglb);
-+ OpenClipboard(NULL);
-+ EmptyClipboard();
-+ SetClipboardData(CF_TEXT, hglb);
-+ CloseClipboard();
-+ return 1;
-+}
-diff --git a/src/osd/windows/video.cpp b/src/osd/windows/video.cpp
-index c6f4d3a0a89..5f5dbd64971 100644
---- a/src/osd/windows/video.cpp
-+++ b/src/osd/windows/video.cpp
-@@ -190,9 +190,10 @@ void windows_osd_interface::extract_video_config()
- video_config.mode = VIDEO_MODE_GDI;
- }
- video_config.waitvsync = options().wait_vsync();
-- video_config.syncrefresh = options().sync_refresh();
-+ video_config.syncrefresh = machine().options().sync_refresh();
- video_config.triplebuf = options().triple_buffer();
- video_config.switchres = options().switch_res();
-+ video_config.framedelay = options().frame_delay();
-
- if (video_config.prescale < 1 || video_config.prescale > 8)
- {
-diff --git a/src/osd/windows/window.cpp b/src/osd/windows/window.cpp
-index 8e723ea6246..16f0ba16a23 100644
---- a/src/osd/windows/window.cpp
-+++ b/src/osd/windows/window.cpp
-@@ -55,6 +55,8 @@ using namespace Windows::UI::Core;
- #define MAKE_DI_SCAN(scan, isextended) (scan & 0x7f) | (isextended ? 0x80 : 0x00)
- #define WINOSD(machine) downcast<windows_osd_interface*>(&machine.osd())
-
-+extern bool switchres_resolution_change(win_window_info *window);
-+
- //============================================================
- // PARAMETERS
- //============================================================
-@@ -88,7 +90,7 @@ using namespace Windows::UI::Core;
-
- static DWORD main_threadid;
-
--
-+static BOOL multithreading_enabled = FALSE;
-
- //============================================================
- // LOCAL VARIABLES
-@@ -804,6 +806,11 @@ void win_window_info::create(running_machine &machine, int index, std::shared_pt
- // handle error conditions
- if (window->m_init_state == -1)
- fatalerror("Unable to complete window creation\n");
-+
-+ // create blitting thread
-+ multithreading_enabled = options.triple_buffer();
-+ if (multithreading_enabled)
-+ window->blit_loop_create();
- }
-
- std::shared_ptr<osd_monitor_info> win_window_info::monitor_from_rect(const osd_rect* proposed) const
-@@ -838,6 +845,10 @@ void win_window_info::destroy()
- {
- assert(GetCurrentThreadId() == main_threadid);
-
-+ // destroy blitting thread
-+ if (multithreading_enabled)
-+ blit_loop_destroy();
-+
- // remove us from the list
- osd_common_t::s_window_list.remove(shared_from_this());
-
-@@ -851,6 +862,97 @@ void win_window_info::destroy()
-
-
-
-+//============================================================
-+// blit_loop_create
-+// (blitting thread)
-+//============================================================
-+
-+void win_window_info::blit_loop_create()
-+{
-+ // set loop as active and lock it until ready
-+ m_blitting_active = TRUE;
-+ m_blit_lock = TRUE;
-+
-+ // create blitting events
-+ m_blit_pending = CreateEvent(NULL, FALSE, FALSE, NULL);
-+ m_blit_done = CreateEvent(NULL, FALSE, FALSE, NULL);
-+
-+ // create blitting thread
-+ CreateThread (NULL, 0, blit_loop, (LPVOID)this, 0, &m_blit_threadid);
-+ osd_printf_verbose("Blitting thread created\n");
-+}
-+
-+//============================================================
-+// blit_loop_destroy
-+// (blitting thread)
-+//============================================================
-+
-+void win_window_info::blit_loop_destroy()
-+{
-+ // turn off blitting flag and wait until thread ends
-+ m_blitting_active = FALSE;
-+ WaitForSingleObject(m_blit_done, 100);
-+
-+ // close blitting events
-+ if (m_blit_done) CloseHandle(m_blit_done);
-+ if (m_blit_pending) CloseHandle(m_blit_pending);
-+
-+ osd_printf_verbose("Blitting thread destroyed\n");
-+}
-+
-+//============================================================
-+// blit_loop
-+// (blitting thread)
-+//============================================================
-+
-+DWORD WINAPI win_window_info::blit_loop(LPVOID lpParameter)
-+{
-+ return ((win_window_info *)lpParameter)->blit_loop_wt();
-+}
-+
-+DWORD win_window_info::blit_loop_wt()
-+{
-+ bool m_throttled;
-+ osd_printf_verbose("Blitting thread started\n");
-+
-+ do {
-+ WaitForSingleObject(m_blit_pending, INFINITE);
-+ m_throttled = machine().video().throttled();
-+ if (!m_blit_lock && has_renderer()) draw_video_contents(NULL, FALSE);
-+ if (m_throttled) SetEvent(m_blit_done);
-+ } while (m_blitting_active);
-+
-+ osd_printf_verbose("Blitting thread ended\n");
-+
-+ return -1;
-+}
-+
-+//============================================================
-+// blit_lock_set
-+// (window thread)
-+//============================================================
-+
-+void win_window_info::blit_lock_set()
-+{
-+ m_blit_lock = TRUE;
-+ osd_printf_verbose("blit_lock = TRUE\n");
-+ Sleep(20);
-+}
-+
-+//============================================================
-+// blit_lock_release
-+// (window thread)
-+//============================================================
-+
-+void win_window_info::blit_lock_release()
-+{
-+ Sleep(20);
-+ m_blit_lock = FALSE;
-+ osd_printf_verbose("blit_lock = FALSE\n");
-+}
-+
-+
-+
- //============================================================
- // winwindow_video_window_update
- // (main thread)
-@@ -860,6 +962,7 @@ void win_window_info::update()
- {
- int targetview, targetorient;
- render_layer_config targetlayerconfig;
-+ static int frame_count = 0;
-
- assert(GetCurrentThreadId() == main_threadid);
-
-@@ -888,11 +991,7 @@ void win_window_info::update()
- {
- bool got_lock = true;
-
-- // only block if we're throttled
-- if (machine().video().throttled() || timeGetTime() - last_update_time > 250)
-- m_render_lock.lock();
-- else
-- got_lock = m_render_lock.try_lock();
-+ got_lock = m_render_lock.try_lock();
-
- // only render if we were able to get the lock
- if (got_lock)
-@@ -902,6 +1001,33 @@ void win_window_info::update()
- // don't hold the lock; we just used it to see if rendering was still happening
- m_render_lock.unlock();
-
-+ // check if frame delay has changed
-+ static int frame_delay = 0;
-+ int new_frame_delay = machine().video().framedelay();
-+ if (new_frame_delay != frame_delay)
-+ {
-+ video_config.framedelay = new_frame_delay;
-+
-+ bool reset_required = ((bool)frame_delay != (bool)new_frame_delay);
-+ frame_delay = new_frame_delay;
-+
-+ if (reset_required)
-+ {
-+ reset_fullscreen_renderer();
-+ return;
-+ }
-+ }
-+
-+ // check resolution change
-+ if (renderer().m_switchres_mode != nullptr && video_config.switchres && machine().options().changeres())
-+ {
-+ if (switchres_resolution_change(this))
-+ {
-+ reset_fullscreen_renderer();
-+ return;
-+ }
-+ }
-+
- // ensure the target bounds are up-to-date, and then get the primitives
- primlist = renderer().get_primitives();
-
-@@ -919,7 +1045,20 @@ void win_window_info::update()
- }
- else
- {
-- SendMessage(platform_window(), WM_USER_REDRAW, 0, (LPARAM)primlist);
-+ if (multithreading_enabled && !m_blit_lock && video_config.mode != VIDEO_MODE_GDI)
-+ {
-+ m_primlist = primlist;
-+ SetEvent(m_blit_pending);
-+ if ((video_config.syncrefresh && machine().video().throttled()))
-+ WaitForSingleObject(m_blit_done, 1000);
-+ frame_count = 0;
-+ }
-+ else
-+ {
-+ m_primlist = primlist;
-+ draw_video_contents(NULL, FALSE);
-+ if (multithreading_enabled && frame_count++ > 5) blit_lock_release();
-+ }
- }
- }
- }
-@@ -1196,8 +1335,7 @@ LRESULT CALLBACK win_window_info::video_window_proc(HWND wnd, UINT message, WPAR
- case WM_PAINT:
- {
- PAINTSTRUCT pstruct;
-- HDC hdc = BeginPaint(wnd, &pstruct);
-- window->draw_video_contents(hdc, true);
-+ BeginPaint(wnd, &pstruct);
- if (window->win_has_menu())
- DrawMenuBar(window->platform_window());
- EndPaint(wnd, &pstruct);
-@@ -1340,6 +1478,11 @@ LRESULT CALLBACK win_window_info::video_window_proc(HWND wnd, UINT message, WPAR
- return DefWindowProc(wnd, message, wparam, lparam);
- }
-
-+ case WM_ACTIVATE:
-+ if (window->has_renderer() && window->fullscreen() && (LOWORD(wparam) == WA_INACTIVE) && !is_mame_window(HWND(lparam)))
-+ if (osd_common_t::s_window_list.size()) winwindow_toggle_full_screen();
-+ break;
-+
- // close: cause MAME to exit
- case WM_CLOSE:
- window->machine().schedule_exit();
-@@ -1797,6 +1940,7 @@ void win_window_info::adjust_window_position_after_major_change()
- }
-
-
-+
- //============================================================
- // set_fullscreen
- // (window thread)
-@@ -1815,6 +1959,10 @@ void win_window_info::set_fullscreen(int fullscreen)
- // FIXME: this cause crash if called when running_machine.m_ui not yet initialised. e.g. when trying to show error/warning messagebox at startup (during auto-switch from full screen to windowed mode).
- machine().ui().menu_reset();
-
-+ // pause blitting thread;
-+ if (multithreading_enabled)
-+ blit_lock_set();
-+
- // kill off the drawers
- renderer_reset();
-
-@@ -1883,6 +2031,49 @@ void win_window_info::set_fullscreen(int fullscreen)
- }
-
-
-+//============================================================
-+// reset_fullscreen_renderer
-+//============================================================
-+
-+void win_window_info::reset_fullscreen_renderer()
-+{
-+ // if we're in the right state, punt
-+ if (!m_fullscreen)
-+ return;
-+
-+ // pause blitting thread;
-+ if (multithreading_enabled)
-+ blit_lock_set();
-+
-+ if (video_config.mode == VIDEO_MODE_D3D)
-+ {
-+ renderer().restart();
-+ return;
-+ }
-+
-+ // kill off the drawers
-+ renderer_reset();
-+
-+ // hide ourself
-+ ShowWindow(platform_window(), SW_HIDE);
-+
-+ // adjust the style
-+ SetWindowLong(platform_window(), GWL_STYLE, WINDOW_STYLE);
-+ SetWindowLong(platform_window(), GWL_EXSTYLE, WINDOW_STYLE_EX);
-+ SetWindowPos(platform_window(), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
-+
-+ SetWindowLong(platform_window(), GWL_STYLE, FULLSCREEN_STYLE);
-+ SetWindowLong(platform_window(), GWL_EXSTYLE, FULLSCREEN_STYLE_EX);
-+ SetWindowPos(platform_window(), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
-+
-+ ShowWindow(platform_window(), SW_SHOW);
-+
-+ set_renderer(osd_renderer::make_for_type(video_config.mode, shared_from_this()));
-+ if (renderer().create())
-+ exit(1);
-+}
-+
-+
- //============================================================
- // focus
- // (main or window thread)
-diff --git a/src/osd/windows/window.h b/src/osd/windows/window.h
-index b04e35aa110..455522781a0 100644
---- a/src/osd/windows/window.h
-+++ b/src/osd/windows/window.h
-@@ -96,6 +96,7 @@ public:
- // static
-
- static void create(running_machine &machine, int index, std::shared_ptr<osd_monitor_info> monitor, const osd_window_config *config);
-+ static DWORD WINAPI blit_loop(LPVOID lpParameter);
-
- // static callbacks
-
-@@ -131,6 +132,13 @@ public:
- int m_lastclickx;
- int m_lastclicky;
-
-+ // blitting thread
-+ HANDLE m_blit_pending;
-+ HANDLE m_blit_done;
-+ DWORD m_blit_threadid;
-+ BOOL m_blitting_active;
-+ BOOL m_blit_lock;
-+
- private:
- void draw_video_contents(HDC dc, bool update);
- int complete_create();
-@@ -146,6 +154,12 @@ private:
- void adjust_window_position_after_major_change();
- void set_fullscreen(int fullscreen);
- std::shared_ptr<osd_monitor_info> monitor_from_rect(const osd_rect* proposed) const;
-+ void reset_fullscreen_renderer();
-+ void blit_loop_create();
-+ void blit_loop_destroy();
-+ DWORD blit_loop_wt();
-+ void blit_lock_set();
-+ void blit_lock_release();
-
- static POINT s_saved_cursor_pos;
-
-diff --git a/src/osd/windows/winmain.cpp b/src/osd/windows/winmain.cpp
-index 05888769c0d..3eab0ca4867 100644
---- a/src/osd/windows/winmain.cpp
-+++ b/src/osd/windows/winmain.cpp
-@@ -43,6 +43,9 @@ using namespace Windows::UI::Popups;
-
- #define DEBUG_SLOW_LOCKS 0
-
-+extern bool switchres_modeline_setup(running_machine &machine);
-+extern bool switchres_modeline_remove(running_machine &machine);
-+
- //**************************************************************************
- // MACROS
- //**************************************************************************
-@@ -525,6 +528,10 @@ void windows_osd_interface::init(running_machine &machine)
- const char *stemp;
- auto &options = downcast<windows_options &>(machine.options());
-
-+ // Switchres
-+ switchres_init_osd(machine);
-+ switchres_modeline_setup(machine);
-+
- // determine if we are benchmarking, and adjust options appropriately
- int bench = options.bench();
- if (bench > 0)
-@@ -603,6 +610,9 @@ void windows_osd_interface::init(running_machine &machine)
-
- void windows_osd_interface::osd_exit()
- {
-+ // Remove Switchres
-+ switchres_modeline_remove(machine());
-+
- // no longer have a machine
- g_current_machine = nullptr;
-