summaryrefslogtreecommitdiffstats
path: root/docs/release/src/osd/winui/properties.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'docs/release/src/osd/winui/properties.cpp')
-rw-r--r--docs/release/src/osd/winui/properties.cpp3695
1 files changed, 3695 insertions, 0 deletions
diff --git a/docs/release/src/osd/winui/properties.cpp b/docs/release/src/osd/winui/properties.cpp
new file mode 100644
index 00000000000..d01f23732f3
--- /dev/null
+++ b/docs/release/src/osd/winui/properties.cpp
@@ -0,0 +1,3695 @@
+// For licensing and usage information, read docs/winui_license.txt
+// MASTER
+//****************************************************************************
+
+/***************************************************************************
+
+ Properties.cpp
+
+ Properties Popup and Misc UI support routines.
+
+ Created 8/29/98 by Mike Haaland (mhaaland@hypertech.com)
+
+***************************************************************************/
+
+/***************************************************************************
+
+MSH - 20070809
+--
+Notes on properties and ini files, reset and reset to default.
+----------------------------------------------------------------------------
+Each ini contains a complete option set.
+
+Priority order for option sets (Lowest to Highest):
+
+built-in defaults
+program ini (executable root filename ini)
+debug ini (if running a debug build)
+driver ini (source code root filename in which this driver is found)
+game ini (where game is the driver name for this game)
+
+To determine which option set to use, start at the top level (lowest
+priority), and overlay all higher priority ini's until the desired level
+is reached.
+
+The 'default' option set is the next priority higher up the list from
+the desired level. For the default (program.ini) level, it is also the
+default.
+
+When MAME is run, the desired level is game ini.
+
+Expected Code behavior:
+----------------------------------------------------------------------------
+This approach requires 3 option sets, 'current', 'original' and 'default'.
+
+'current': used to populate the property pages, and to initialize the
+'original' set.
+
+'original': used to evaluate if the 'Reset' button is enabled.
+If 'current' matches 'original', the 'Reset' button is disabled,
+otherwise it is enabled.
+
+'default': used to evaluate if the 'Restore to Defaults' button is enabled.
+If 'current' matches 'default', the 'Restore to Defaults' button is disabled,
+otherwise it is enabled.
+
+When editing any option set, the desired level is set to the one being
+edited, the default set for that level, is the next lower priority set found.
+
+Upon entering the properties dialog:
+a) 'current' is initialized
+b) 'original' is initialized by 'current'
+c) 'default' is initialized
+d) Populate Property pages with 'current'
+e) 'Reset' and 'Restore to Defaults' buttons are evaluated.
+
+After any change:
+a) 'current' is updated
+b) 'Reset' and 'Restore to Defaults' buttons are re-evaluated.
+
+Reset:
+a) 'current' is reinitialized to 'original'
+b) Re-populate Property pages with 'current'
+c) 'Reset' and 'Restore to Defaults' buttons are re-evaluated.
+
+Restore to Defaults:
+a) 'current' is reinitialized to 'default'
+b) Re-populate Property pages with 'current'
+b) 'Reset' and 'Restore to Defaults' buttons are re-evaluated.
+
+Apply:
+a) 'original' is reinitialized to 'current'
+b) 'Reset' and 'Restore to defaults' are re-evaluated.
+c) If they 'current' matches 'default', remove the ini from disk.
+ Otherwise, write the ini to disk.
+
+Cancel:
+a) Exit the dialog.
+
+OK:
+a) If they 'current' matches 'default', remove the ini from disk.
+ Otherwise, write the ini to disk.
+b) Exit the dialog.
+
+
+***************************************************************************/
+
+// standard windows headers
+#include <windows.h>
+#include <windowsx.h>
+
+// standard C headers
+#include <tchar.h>
+#include <sys/stat.h> // for S_IFDIR
+
+// MAME/MAMEUI headers
+#include "emu.h"
+#include "screen.h"
+#include "mui_audit.h"
+#include "mui_opts.h"
+#include "resource.h"
+#include "dijoystick.h" /* For DIJoystick availability. */
+#include "mui_util.h"
+#include "datamap.h"
+#include "help.h"
+#include "winui.h"
+#include "strconv.h"
+#include "winutf8.h"
+#include "directories.h"
+#include "sound/samples.h"
+
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#endif
+
+#include "newuires.h"
+#ifdef UI_DIRECTDRAW
+#include "directdraw.h" /* has to be after samples.h */
+#endif
+#include "properties.h"
+#include "drivenum.h"
+#include "machine/ram.h"
+#include <shlwapi.h>
+
+
+#if defined(__GNUC__)
+/* fix warning: cast does not match function type */
+#undef PropSheet_GetTabControl
+#define PropSheet_GetTabControl(d) (HWND)(LRESULT)(int)SendMessage((d),PSM_GETTABCONTROL,0,0)
+#endif /* defined(__GNUC__) */
+
+/* Enable this if MAME supports multiple versions of D3D */
+//#define D3DVERSION
+
+/***************************************************************
+ * Imported function prototypes
+ ***************************************************************/
+
+/**************************************************************
+ * Local function prototypes
+ **************************************************************/
+
+static void SetSamplesEnabled(HWND hWnd, int nIndex, BOOL bSoundEnabled);
+static void InitializeOptions(HWND hDlg);
+static void InitializeMisc(HWND hDlg);
+static void OptOnHScroll(HWND hWnd, HWND hwndCtl, UINT code, int pos);
+static void NumScreensSelectionChange(HWND hwnd);
+static void RefreshSelectionChange(HWND hWnd, HWND hWndCtrl);
+static void InitializeSoundUI(HWND hwnd);
+static void InitializeSkippingUI(HWND hwnd);
+static void InitializeRotateUI(HWND hwnd);
+static void UpdateSelectScreenUI(HWND hwnd);
+static void InitializeSelectScreenUI(HWND hwnd);
+#ifdef D3DVERSION
+static void InitializeD3DVersionUI(HWND hwnd);
+#endif
+static void InitializeVideoUI(HWND hwnd);
+static void InitializeBIOSUI(HWND hwnd);
+static void InitializeControllerMappingUI(HWND hwnd);
+static void InitializeLanguageUI(HWND hWnd);
+static void InitializePluginsUI(HWND hWnd);
+//static void InitializeGLSLFilterUI(HWND hWnd);
+static void UpdateOptions(HWND hDlg, datamap *map, windows_options &opts);
+static void UpdateProperties(HWND hDlg, datamap *map, windows_options &opts);
+static void PropToOptions(HWND hWnd, windows_options &o);
+static void OptionsToProp(HWND hWnd, windows_options &o);
+static void SetPropEnabledControls(HWND hWnd);
+static bool SelectLUAScript(HWND hWnd);
+static bool ResetLUAScript(HWND hWnd);
+static bool SelectPlugins(HWND hWnd);
+static bool ResetPlugins(HWND hWnd);
+//static bool SelectBGFXChains(HWND hWnd);
+//static bool ResetBGFXChains(HWND hWnd);
+static BOOL SelectEffect(HWND hWnd);
+static BOOL ResetEffect(HWND hWnd);
+static BOOL SelectJoystickMap(HWND hWnd);
+static BOOL ResetJoystickMap(HWND hWnd);
+static BOOL SelectDebugscript(HWND hWnd);
+static BOOL ResetDebugscript(HWND hWnd);
+
+static void BuildDataMap(void);
+static void ResetDataMap(HWND hWnd);
+
+static void UpdateBackgroundBrush(HWND hwndTab);
+static HBRUSH hBkBrush;
+
+#ifdef MESS
+static BOOL DirListReadControl(datamap *map, HWND dialog, HWND control, windows_options *opts, const char *option_name);
+static BOOL DirListPopulateControl(datamap *map, HWND dialog, HWND control, windows_options *opts, const char *option_name);
+static BOOL RamPopulateControl(datamap *map, HWND dialog, HWND control, windows_options *opts, const char *option_name);
+extern BOOL BrowseForDirectory(HWND hwnd, LPCTSTR pStartDir, TCHAR* pResult);
+//static BOOL g_bModifiedSoftwarePaths = false;
+#endif
+
+/**************************************************************
+ * Local private variables
+ **************************************************************/
+
+/* No longer used by the core, but we need it to predefine configurable screens for all games. */
+#ifndef MAX_SCREENS
+/* maximum number of screens for one game */
+#define MAX_SCREENS 4
+#endif
+
+static windows_options pOrigOpts, pDefaultOpts, pCurrentOpts;
+static datamap *properties_datamap;
+
+static int g_nGame = 0;
+static int g_nFolder = 0;
+static int g_nFolderGame = 0;
+static OPTIONS_TYPE g_nPropertyMode = OPTIONS_GAME;
+static BOOL g_bAutoAspect[MAX_SCREENS] = {false, false, false, false};
+static BOOL g_bAutoSnapSize = false;
+static HICON g_hIcon = NULL;
+std::vector<string> plugin_names(32);
+
+/* Property sheets */
+
+#define HIGHLIGHT_COLOR RGB(0,196,0)
+static HBRUSH highlight_brush = NULL;
+static HBRUSH background_brush = NULL;
+
+#define ORIENTATION_COLOR RGB( 190, 128, 0) //LIGHT BROWN
+#define VECTOR_COLOR RGB( 190, 0, 0) //DARK RED
+#define FOLDER_COLOR RGB( 0, 128, 0 ) // DARK GREEN
+#define PARENT_COLOR RGB( 190, 128, 192 ) // PURPLE
+#define GAME_COLOR RGB( 0, 128, 192 ) // DARK BLUE
+
+
+BOOL PropSheetFilter_Vector(const machine_config *drv, const game_driver *gamedrv)
+{
+ return isDriverVector(drv);
+}
+
+/* Help IDs - moved to auto-generated helpids.c */
+extern const DWORD dwHelpIDs[];
+
+typedef struct
+{
+ const TCHAR* m_pText;
+ const char* m_pData;
+}
+DUALCOMBOSTR;
+
+typedef struct
+{
+ const TCHAR* m_pText;
+ const int m_pData;
+}
+DUALCOMBOINT;
+
+const DUALCOMBOSTR g_ComboBoxVideo[] =
+{
+ { TEXT("Auto"), "auto" },
+ { TEXT("GDI"), "gdi" },
+#ifdef UI_DIRECTDRAW
+ { TEXT("DirectDraw"), "ddraw" }, // removed 20160217
+#endif
+ { TEXT("Direct3D"), "d3d" },
+ { TEXT("BGFX"), "bgfx" },
+ { TEXT("OpenGL"), "opengl" },
+};
+#define NUMVIDEO (sizeof(g_ComboBoxVideo) / sizeof(g_ComboBoxVideo[0]))
+
+const DUALCOMBOSTR g_ComboBoxSound[] =
+{
+ { TEXT("None"), "none" },
+ { TEXT("Auto"), "auto" },
+ { TEXT("DirectSound"), "dsound" },
+ { TEXT("PortAudio"), "portaudio" },
+// { TEXT("XAudio2"), "xaudio2" }, // invalid option
+};
+#define NUMSOUND (sizeof(g_ComboBoxSound) / sizeof(g_ComboBoxSound[0]))
+#ifdef D3DVERSION
+const DUALCOMBOINT g_ComboBoxD3DVersion[] =
+{
+ { TEXT("Version 9"), 9 },
+// { TEXT("Version 8"), 8 },
+};
+
+#define NUMD3DVERSIONS (sizeof(g_ComboBoxD3DVersion) / sizeof(g_ComboBoxD3DVersion[0]))
+#define WINOPTION_D3DVERSION "9"
+#endif
+const DUALCOMBOINT g_ComboBoxSelectScreen[] =
+{
+ { TEXT("Screen 0"), 0 },
+ { TEXT("Screen 1"), 1 },
+ { TEXT("Screen 2"), 2 },
+ { TEXT("Screen 3"), 3 },
+};
+#define NUMSELECTSCREEN (sizeof(g_ComboBoxSelectScreen) / sizeof(g_ComboBoxSelectScreen[0]))
+
+const DUALCOMBOSTR g_ComboBoxView[] =
+{
+ { TEXT("Auto"), "auto" },
+ { TEXT("Standard"), "standard" },
+ { TEXT("Pixel Aspect"), "pixel" },
+ { TEXT("Cocktail"), "cocktail" },
+};
+#define NUMVIEW (sizeof(g_ComboBoxView) / sizeof(g_ComboBoxView[0]))
+
+
+
+const DUALCOMBOSTR g_ComboBoxDevice[] =
+{
+ { TEXT("None"), "none" },
+ { TEXT("Keyboard"), "keyboard" },
+ { TEXT("Mouse"), "mouse" },
+ { TEXT("Joystick"), "joystick" },
+ { TEXT("Lightgun"), "lightgun" },
+};
+
+#define NUMDEVICES (sizeof(g_ComboBoxDevice) / sizeof(g_ComboBoxDevice[0]))
+
+const DUALCOMBOSTR g_ComboBoxSnapView[] =
+{
+ { TEXT("Internal"), "internal" },
+ { TEXT("Auto"), "auto" },
+ { TEXT("Standard"), "standard" },
+ { TEXT("Pixel Aspect"), "pixel" },
+ { TEXT("Cocktail"), "cocktail" },
+};
+#define NUMSNAPVIEW (sizeof(g_ComboBoxSnapView) / sizeof(g_ComboBoxSnapView[0]))
+
+
+/***************************************************************
+ * Public functions
+ ***************************************************************/
+
+
+int PropertiesCurrentGame(HWND hDlg)
+{
+ return g_nGame;
+}
+
+DWORD_PTR GetHelpIDs(void)
+{
+ return (DWORD_PTR)dwHelpIDs;
+}
+
+static int GetSelectedScreen(HWND hWnd)
+{
+ int nSelectedScreen = 0;
+ HWND hCtrl = GetDlgItem(hWnd, IDC_SCREENSELECT);
+ if (hCtrl)
+ nSelectedScreen = ComboBox_GetCurSel(hCtrl);
+ if ((nSelectedScreen < 0) || (nSelectedScreen >= NUMSELECTSCREEN))
+ nSelectedScreen = 0;
+ return nSelectedScreen;
+
+}
+
+static PROPSHEETPAGE *CreatePropSheetPages(HINSTANCE hInst, BOOL bOnlyDefault,
+// const game_driver *gamedrv, UINT *pnMaxPropSheets, BOOL isGame )
+ int nGame, UINT *pnMaxPropSheets, BOOL isGame )
+{
+ PROPSHEETPAGE *pspages;
+ int maxPropSheets = 0;
+ int possiblePropSheets;
+ int i = ( isGame ) ? 0 : 2;
+
+ for (; g_propSheets[i].pfnDlgProc; i++)
+ ;
+
+ possiblePropSheets = (isGame) ? i + 1 : i - 1;
+
+ pspages = (PROPSHEETPAGE *)malloc(sizeof(PROPSHEETPAGE) * possiblePropSheets);
+ if (!pspages)
+ return NULL;
+
+ memset(pspages, 0, sizeof(PROPSHEETPAGE) * possiblePropSheets);
+
+ i = ( isGame ) ? 0 : 2;
+
+ for (; g_propSheets[i].pfnDlgProc; i++)
+ {
+ if (nGame < 0)
+ {
+ if (g_propSheets[i].bOnDefaultPage)
+ {
+ pspages[maxPropSheets].dwSize = sizeof(PROPSHEETPAGE);
+ pspages[maxPropSheets].dwFlags = 0;
+ pspages[maxPropSheets].hInstance = hInst;
+ pspages[maxPropSheets].pszTemplate = MAKEINTRESOURCE(g_propSheets[i].dwDlgID);
+ pspages[maxPropSheets].pfnCallback = NULL;
+ pspages[maxPropSheets].lParam = 0;
+ pspages[maxPropSheets].pfnDlgProc = g_propSheets[i].pfnDlgProc;
+ maxPropSheets++;
+ }
+ }
+ else
+ if ((nGame >= 0) || g_propSheets[i].bOnDefaultPage)
+ {
+ //machine_config config(*gamedrv,pCurrentOpts);
+
+// if (!gamedrv || !g_propSheets[i].pfnFilterProc || g_propSheets[i].pfnFilterProc(&config, gamedrv))
+ if (nGame < 0 || !g_propSheets[i].pfnFilterProc || g_propSheets[i].pfnFilterProc(nGame))
+ {
+ pspages[maxPropSheets].dwSize = sizeof(PROPSHEETPAGE);
+ pspages[maxPropSheets].dwFlags = 0;
+ pspages[maxPropSheets].hInstance = hInst;
+ pspages[maxPropSheets].pszTemplate = MAKEINTRESOURCE(g_propSheets[i].dwDlgID);
+ pspages[maxPropSheets].pfnCallback = NULL;
+ pspages[maxPropSheets].lParam = 0;
+ pspages[maxPropSheets].pfnDlgProc = g_propSheets[i].pfnDlgProc;
+ maxPropSheets++;
+ }
+ }
+ }
+
+ if (pnMaxPropSheets)
+ *pnMaxPropSheets = maxPropSheets;
+
+ return pspages;
+}
+
+// This is for the DEFAULT property-page options only
+void InitDefaultPropertyPage(HINSTANCE hInst, HWND hWnd)
+{
+ // clear globals
+ g_nGame = GLOBAL_OPTIONS;
+ windows_options dummy;
+ OptionsCopy(dummy,pDefaultOpts);
+ OptionsCopy(dummy,pOrigOpts);
+ OptionsCopy(dummy,pCurrentOpts);
+
+ /* Get default options to populate property sheets */
+ load_options(pCurrentOpts, OPTIONS_GLOBAL, g_nGame, 0);
+ load_options(pOrigOpts, OPTIONS_GLOBAL, g_nGame, 0);
+ load_options(pDefaultOpts, OPTIONS_GLOBAL, -2, 0);
+
+ g_nPropertyMode = OPTIONS_GLOBAL;
+ BuildDataMap();
+
+ PROPSHEETHEADER pshead;
+ ZeroMemory(&pshead, sizeof(pshead));
+
+ PROPSHEETPAGE *pspage;
+ pspage = CreatePropSheetPages(hInst, true, -1, &pshead.nPages, false);
+ if (!pspage)
+ return;
+
+ /* Fill in the property sheet header */
+ pshead.hwndParent = hWnd;
+ pshead.dwSize = sizeof(PROPSHEETHEADER);
+ pshead.dwFlags = PSH_PROPSHEETPAGE | PSH_USEICONID | PSH_PROPTITLE;
+ pshead.hInstance = hInst;
+ pshead.pszCaption = TEXT("Default Game");
+ pshead.nStartPage = 0;
+ pshead.pszIcon = MAKEINTRESOURCE(IDI_MAMEUI_ICON);
+ pshead.ppsp = pspage;
+
+ /* Create the Property sheet and display it */
+ if (PropertySheet(&pshead) == -1)
+ {
+ char temp[100];
+ DWORD dwError = GetLastError();
+ sprintf(temp, "Property Sheet Error %d %X", (int)dwError, (int)dwError);
+ win_message_box_utf8(0, temp, "Error", IDOK);
+ }
+
+ free(pspage);
+}
+
+/* Initialize the property pages for anything but the Default option set */
+void InitPropertyPage(HINSTANCE hInst, HWND hWnd, HICON hIcon, OPTIONS_TYPE opt_type, int folder_id, int game_num)
+{
+ InitPropertyPageToPage(hInst, hWnd, hIcon, opt_type, folder_id, game_num, PROPERTIES_PAGE);
+}
+
+void InitPropertyPageToPage(HINSTANCE hInst, HWND hWnd, HICON hIcon, OPTIONS_TYPE opt_type, int folder_id, int game_num, int start_page )
+{
+ if (highlight_brush == NULL)
+ highlight_brush = CreateSolidBrush(HIGHLIGHT_COLOR);
+
+ if (background_brush == NULL)
+ background_brush = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
+
+ // Initialize the options
+ windows_options dummy;
+ OptionsCopy(dummy,pDefaultOpts);
+ OptionsCopy(dummy,pOrigOpts);
+ OptionsCopy(dummy,pCurrentOpts);
+
+ load_options(pCurrentOpts, opt_type, game_num, 1);
+ load_options(pOrigOpts, opt_type, game_num, 1);
+ if (game_num == GLOBAL_OPTIONS)
+ load_options(pDefaultOpts, OPTIONS_GLOBAL, -2, 0); // base opts is the backup for global
+ else
+ load_options(pDefaultOpts, OPTIONS_GLOBAL, -1, 0); // global is the backup for games
+
+ // Copy icon to use for the property pages
+ g_hIcon = CopyIcon(hIcon);
+
+ // These MUST be valid, they are used as indicies
+ g_nGame = game_num;
+ g_nFolder = folder_id;
+
+ // Keep track of OPTIONS_TYPE that was passed in.
+ g_nPropertyMode = opt_type;
+
+ BuildDataMap();
+
+ PROPSHEETHEADER pshead;
+ ZeroMemory(&pshead, sizeof(PROPSHEETHEADER));
+
+ // Set the game to audit to this game
+
+ // Create the property sheets
+ PROPSHEETPAGE *pspage;
+ if( OPTIONS_GAME == opt_type )
+ {
+ InitGameAudit(game_num);
+ pspage = CreatePropSheetPages(hInst, false, game_num, &pshead.nPages, true);
+ }
+ else
+ pspage = CreatePropSheetPages(hInst, false, -1, &pshead.nPages, false);
+
+ if (!pspage)
+ return;
+
+ // Get the description use as the dialog caption.
+ TCHAR* t_description = 0;
+ switch( opt_type )
+ {
+ case OPTIONS_GAME:
+ t_description = ui_wstring_from_utf8(ModifyThe(driver_list::driver(g_nGame).type.fullname()));
+ break;
+ case OPTIONS_SOURCE:
+ t_description = ui_wstring_from_utf8(GetDriverFilename(g_nGame));
+ break;
+ case OPTIONS_GLOBAL:
+ t_description = ui_wstring_from_utf8("Default Settings");
+ break;
+ default:
+ return;
+ }
+ // If we have no description, return.
+ if( !t_description )
+ return;
+
+ /* Fill in the property sheet header */
+ pshead.pszCaption = t_description;
+ pshead.hwndParent = hWnd;
+ pshead.dwSize = sizeof(PROPSHEETHEADER);
+ pshead.dwFlags = PSH_PROPSHEETPAGE | PSH_USEICONID | PSH_PROPTITLE;
+ pshead.hInstance = hInst;
+ pshead.nStartPage = start_page;
+ pshead.pszIcon = MAKEINTRESOURCE(IDI_MAMEUI_ICON);
+ pshead.ppsp = pspage;
+
+ /* Create the Property sheet and display it */
+ if (PropertySheet(&pshead) == -1)
+ {
+ char temp[100];
+ DWORD dwError = GetLastError();
+ sprintf(temp, "Property Sheet Error %d %X", (int)dwError, (int)dwError);
+ win_message_box_utf8(0, temp, "Error", IDOK);
+ }
+
+ free(t_description);
+ free(pspage);
+}
+
+
+/*********************************************************************
+ * Local Functions
+ *********************************************************************/
+#define WINUI_ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
+
+/* Build CPU info string */
+static char *GameInfoCPU(int nIndex)
+{
+ machine_config config(driver_list::driver(nIndex), MameUIGlobal());
+ execute_interface_iterator cpuiter(config.root_device());
+ std::unordered_set<std::string> exectags;
+ static char buffer[1024];
+
+ memset(&buffer, 0, sizeof(buffer));
+
+ for (device_execute_interface &exec : cpuiter)
+ {
+ if (!exectags.insert(exec.device().tag()).second)
+ continue;
+
+ char temp[300];
+ int count = 1;
+ int clock = exec.device().clock();
+ const char *name = exec.device().name();
+
+ for (device_execute_interface &scan : cpuiter)
+ {
+ if (exec.device().type() == scan.device().type() && strcmp(name, scan.device().name()) == 0 && clock == scan.device().clock())
+ if (exectags.insert(scan.device().tag()).second)
+ count++;
+ }
+
+ if (count > 1)
+ {
+ snprintf(temp, WINUI_ARRAY_LENGTH(temp), "%d x ", count);
+ strcat(buffer, temp);
+ }
+
+ if (clock >= 1000000)
+ snprintf(temp, WINUI_ARRAY_LENGTH(temp), "%s %d.%06d MHz\r\n", name, clock / 1000000, clock % 1000000);
+ else
+ snprintf(temp, WINUI_ARRAY_LENGTH(temp), "%s %d.%03d kHz\r\n", name, clock / 1000, clock % 1000);
+
+ strcat(buffer, temp);
+ }
+
+ return buffer;
+}
+
+/* Build Sound system info string */
+static char *GameInfoSound(int nIndex)
+{
+ machine_config config(driver_list::driver(nIndex), MameUIGlobal());
+ sound_interface_iterator sounditer(config.root_device());
+ std::unordered_set<std::string> soundtags;
+ static char buffer[1024];
+
+ memset(&buffer, 0, sizeof(buffer));
+
+ for (device_sound_interface &sound : sounditer)
+ {
+ if (!soundtags.insert(sound.device().tag()).second)
+ continue;
+
+ char temp[300];
+ int count = 1;
+ int clock = sound.device().clock();
+ const char *name = sound.device().name();
+
+ for (device_sound_interface &scan : sounditer)
+ {
+ if (sound.device().type() == scan.device().type() && strcmp(name, scan.device().name()) == 0 && clock == scan.device().clock())
+ if (soundtags.insert(scan.device().tag()).second)
+ count++;
+ }
+
+ if (count > 1)
+ {
+ snprintf(temp, WINUI_ARRAY_LENGTH(temp), "%d x ", count);
+ strcat(buffer, temp);
+ }
+
+ strcat(buffer, name);
+
+ if (clock)
+ {
+ if (clock >= 1000000)
+ snprintf(temp, WINUI_ARRAY_LENGTH(temp), " %d.%06d MHz", clock / 1000000, clock % 1000000);
+ else
+ snprintf(temp, WINUI_ARRAY_LENGTH(temp), " %d.%03d kHz", clock / 1000, clock % 1000);
+
+ strcat(buffer, temp);
+ }
+
+ strcat(buffer, "\r\n");
+ }
+
+ return buffer;
+}
+
+/* Build Display info string */
+static char *GameInfoScreen(UINT nIndex)
+{
+ static char buf[2048];
+ machine_config config(driver_list::driver(nIndex),pCurrentOpts);
+ memset(buf, '\0', 2048);
+
+ if (isDriverVector(&config))
+ strcpy(buf, "Vector Game");
+ else
+ {
+ screen_device_iterator iter(config.root_device());
+ const screen_device *screen = iter.first();
+ if (screen == NULL)
+ strcpy(buf, "Screenless Game");
+ else
+ {
+ for (screen_device &screen : screen_device_iterator(config.root_device()))
+ {
+ char tmpbuf[2048];
+ const rectangle &visarea = screen.visible_area();
+
+ if (BIT(GetDriverCacheLower(nIndex), 2)) //ORIENTATION_SWAP_XY
+ {
+ sprintf(tmpbuf,"%d x %d (V) %f Hz\n",
+ visarea.max_y - visarea.min_y + 1,
+ visarea.max_x - visarea.min_x + 1,
+ ATTOSECONDS_TO_HZ(screen.refresh_attoseconds()));
+ }
+ else
+ {
+ sprintf(tmpbuf,"%d x %d (H) %f Hz\n",
+ visarea.max_x - visarea.min_x + 1,
+ visarea.max_y - visarea.min_y + 1,
+ ATTOSECONDS_TO_HZ(screen.refresh_attoseconds()));
+ }
+ strcat(buf, tmpbuf);
+ }
+ }
+ }
+ return buf;
+}
+
+
+/* Build game status string */
+const char *GameInfoStatus(int driver_index, BOOL bRomStatus)
+{
+ static char buffer[2048];
+ memset(buffer,0,sizeof(char)*2048);
+ if (driver_index < 0)
+ return buffer;
+
+ int audit_result = GetRomAuditResults(driver_index);
+ uint32_t cache = GetDriverCacheLower(driver_index);
+ if ( bRomStatus )
+ {
+ if (IsAuditResultKnown(audit_result) == false)
+ strcpy(buffer, "Unknown");
+ else
+ if (IsAuditResultYes(audit_result))
+ {
+ if (DriverIsBroken(driver_index))
+ {
+ strcpy(buffer, "Not working");
+
+ if (BIT(cache, 22))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Game protection isn't fully emulated");
+ }
+ if (BIT(cache, 21))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Colors are completely wrong");
+ }
+ if (BIT(cache, 20))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Colors aren't 100% accurate");
+ }
+ if (BIT(cache, 18))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Video emulation isn't 100% accurate");
+ }
+ if (BIT(cache, 17))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Game lacks sound");
+ }
+ if (BIT(cache, 16))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Sound emulation isn't 100% accurate");
+ }
+ if (BIT(cache, 8))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Screen flipping is not supported");
+ }
+ if (BIT(cache, 10))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Game requires artwork");
+ }
+ }
+ else
+ {
+ strcpy(buffer, "Working");
+
+ if (BIT(cache, 22))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Game protection isn't fully emulated");
+ }
+ if (BIT(cache, 21))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Colors are completely wrong");
+ }
+ if (BIT(cache, 20))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Colors aren't 100% accurate");
+ }
+ if (BIT(cache, 18))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Video emulation isn't 100% accurate");
+ }
+ if (BIT(cache, 17))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Game lacks sound");
+ }
+ if (BIT(cache, 16))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Sound emulation isn't 100% accurate");
+ }
+ if (BIT(cache, 8))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Screen flipping is not supported");
+ }
+ if (BIT(cache, 10))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Game requires artwork");
+ }
+ }
+ }
+ else
+ // audit result is no
+ strcpy(buffer, "BIOS missing");
+ }
+ else
+ {
+ //Just show the emulation flags
+ if (DriverIsBroken(driver_index))
+ strcpy(buffer, "Not working");
+ else
+ strcpy(buffer, "Working");
+
+ if (BIT(cache, 22))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Game protection isn't fully emulated");
+ }
+ if (BIT(cache, 21))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Colors are completely wrong");
+ }
+ if (BIT(cache, 20))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Colors aren't 100% accurate");
+ }
+ if (BIT(cache, 18))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Video emulation isn't 100% accurate");
+ }
+ if (BIT(cache, 17))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Game lacks sound");
+ }
+ if (BIT(cache, 16))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Sound emulation isn't 100% accurate");
+ }
+ if (BIT(cache, 8))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Screen flipping is not supported");
+ }
+ if (BIT(cache, 10))
+ {
+ if (*buffer != '\0')
+ strcat(buffer, "\r\n");
+ strcat(buffer, "Game requires artwork");
+ }
+ }
+ return buffer;
+}
+
+/* Build game manufacturer string */
+static char *GameInfoManufactured(UINT nIndex)
+{
+ static char buffer[1024];
+
+ snprintf(buffer,sizeof(buffer),"%s %s",driver_list::driver(nIndex).year,driver_list::driver(nIndex).manufacturer);
+ return buffer;
+}
+
+/* Build Game title string */
+char *GameInfoTitle(OPTIONS_TYPE opt_type, UINT nIndex)
+{
+ static char buf[1024];
+
+ if (OPTIONS_GLOBAL == opt_type)
+ strcpy(buf, "Global game options\nDefault options used by all games");
+ else
+ if (OPTIONS_SOURCE == opt_type)
+ strcpy(buf, "Options used by all games in the source");
+ else
+ if (OPTIONS_VECTOR == opt_type)
+ strcpy(buf, "Global vector options");
+ else
+ if (OPTIONS_GAME == opt_type)
+ sprintf(buf, "%s\n\"%s\"", ModifyThe(driver_list::driver(nIndex).type.fullname()), driver_list::driver(nIndex).name);
+ return buf;
+}
+
+/* Build game clone information string */
+static char *GameInfoCloneOf(UINT nIndex)
+{
+ static char buf[1024];
+ int nParentIndex= -1;
+
+ buf[0] = '\0';
+
+ if (DriverIsClone(nIndex))
+ {
+ nParentIndex = GetParentIndex(&driver_list::driver(nIndex));
+ sprintf(buf, "%s - \"%s\"",
+ ConvertAmpersandString(ModifyThe(driver_list::driver(nParentIndex).type.fullname())),
+ driver_list::driver(nParentIndex).name);
+ }
+
+ return buf;
+}
+
+static const char * GameInfoSource(UINT nIndex)
+{
+ return GetDriverFilename(nIndex);
+}
+
+/* Handle the information property page */
+INT_PTR CALLBACK GamePropertiesDialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+HWND hWnd;
+ switch (Msg)
+ {
+ case WM_INITDIALOG:
+ if (g_hIcon)
+ SendDlgItemMessage(hDlg, IDC_GAME_ICON, STM_SETICON, (WPARAM) g_hIcon, 0);
+#if defined(USE_SINGLELINE_TABCONTROL)
+ {
+ HWND hWnd = PropSheet_GetTabControl(GetParent(hDlg));
+ DWORD tabStyle = (GetWindowLong(hWnd,GWL_STYLE) & ~TCS_MULTILINE);
+ SetWindowLong(hWnd,GWL_STYLE,tabStyle | TCS_SINGLELINE);
+ }
+#endif
+
+ win_set_window_text_utf8(GetDlgItem(hDlg, IDC_PROP_TITLE), GameInfoTitle(g_nPropertyMode, g_nGame));
+ win_set_window_text_utf8(GetDlgItem(hDlg, IDC_PROP_MANUFACTURED), GameInfoManufactured(g_nGame));
+ win_set_window_text_utf8(GetDlgItem(hDlg, IDC_PROP_STATUS), GameInfoStatus(g_nGame, false));
+ win_set_window_text_utf8(GetDlgItem(hDlg, IDC_PROP_CPU), GameInfoCPU(g_nGame));
+ win_set_window_text_utf8(GetDlgItem(hDlg, IDC_PROP_SOUND), GameInfoSound(g_nGame));
+ win_set_window_text_utf8(GetDlgItem(hDlg, IDC_PROP_SCREEN), GameInfoScreen(g_nGame));
+ win_set_window_text_utf8(GetDlgItem(hDlg, IDC_PROP_CLONEOF), GameInfoCloneOf(g_nGame));
+ win_set_window_text_utf8(GetDlgItem(hDlg, IDC_PROP_SOURCE), GameInfoSource(g_nGame));
+
+ if (DriverIsClone(g_nGame))
+ ShowWindow(GetDlgItem(hDlg, IDC_PROP_CLONEOF_TEXT), SW_SHOW);
+ else
+ ShowWindow(GetDlgItem(hDlg, IDC_PROP_CLONEOF_TEXT), SW_HIDE);
+
+ hWnd = PropSheet_GetTabControl(GetParent(hDlg));
+ UpdateBackgroundBrush(hWnd);
+ ShowWindow(hDlg, SW_SHOW);
+ return 1;
+ }
+ return 0;
+}
+
+/* Handle all options property pages */
+INT_PTR CALLBACK GameOptionsProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+ BOOL g_bUseDefaults = false, g_bReset = false;
+
+ switch (Msg)
+ {
+ case WM_INITDIALOG:
+ /* Fill in the Game info at the top of the sheet */
+ win_set_window_text_utf8(GetDlgItem(hDlg, IDC_PROP_TITLE), GameInfoTitle(g_nPropertyMode, g_nGame));
+ InitializeOptions(hDlg);
+ InitializeMisc(hDlg);
+
+ UpdateProperties(hDlg, properties_datamap, pCurrentOpts);
+
+ g_bUseDefaults = AreOptionsEqual(pCurrentOpts, pDefaultOpts) ? false : true;
+ g_bReset = AreOptionsEqual(pCurrentOpts, pOrigOpts) ? false : true;
+
+ // Default button doesn't exist on Default settings
+// if (g_nGame == GLOBAL_OPTIONS)
+// ShowWindow(GetDlgItem(hDlg, IDC_USE_DEFAULT), SW_HIDE);
+// else
+ EnableWindow(GetDlgItem(hDlg, IDC_USE_DEFAULT), g_bUseDefaults);
+
+ // Setup Reset button
+ EnableWindow(GetDlgItem(hDlg, IDC_PROP_RESET), g_bReset);
+ ShowWindow(hDlg, SW_SHOW);
+ return 1;
+
+ case WM_HSCROLL:
+ /* slider changed */
+ HANDLE_WM_HSCROLL(hDlg, wParam, lParam, OptOnHScroll);
+ EnableWindow(GetDlgItem(hDlg, IDC_USE_DEFAULT), true);
+
+ // Enable Apply button
+ PropSheet_Changed(GetParent(hDlg), hDlg);
+
+ // make sure everything's copied over, to determine what's changed
+ UpdateOptions(hDlg, properties_datamap, pCurrentOpts);
+
+ // redraw it, it might be a new color now
+ InvalidateRect((HWND)lParam,NULL,true);
+
+ break;
+
+ case WM_COMMAND:
+ {
+ /* Below, 'changed' is used to signify the 'Apply' button should be enabled. */
+ WORD wID = GET_WM_COMMAND_ID(wParam, lParam);
+ HWND hWndCtrl = GET_WM_COMMAND_HWND(wParam, lParam);
+ WORD wNotifyCode = GET_WM_COMMAND_CMD(wParam, lParam);
+ BOOL changed = false;
+ int nCurSelection = 0;
+ TCHAR szClass[256];
+
+ switch (wID)
+ {
+ case IDC_REFRESH:
+ if (wNotifyCode == LBN_SELCHANGE)
+ {
+ RefreshSelectionChange(hDlg, hWndCtrl);
+ changed = true;
+ }
+ break;
+
+ case IDC_ASPECT:
+ nCurSelection = Button_GetCheck( GetDlgItem(hDlg, IDC_ASPECT));
+ if( g_bAutoAspect[GetSelectedScreen(hDlg)] != nCurSelection )
+ {
+ changed = true;
+ g_bAutoAspect[GetSelectedScreen(hDlg)] = nCurSelection;
+ }
+ break;
+
+ case IDC_SNAPSIZE:
+ nCurSelection = Button_GetCheck( GetDlgItem(hDlg, IDC_SNAPSIZE));
+ if( g_bAutoSnapSize != nCurSelection )
+ {
+ changed = true;
+ g_bAutoSnapSize = nCurSelection;
+ }
+ break;
+
+ case IDC_SELECT_EFFECT:
+ changed = SelectEffect(hDlg);
+ break;
+
+ case IDC_RESET_EFFECT:
+ changed = ResetEffect(hDlg);
+ break;
+
+ case IDC_SELECT_JOYSTICKMAP:
+ changed = SelectJoystickMap(hDlg);
+ break;
+
+ case IDC_RESET_JOYSTICKMAP:
+ changed = ResetJoystickMap(hDlg);
+ break;
+
+ case IDC_SELECT_DEBUGSCRIPT:
+ changed = SelectDebugscript(hDlg);
+ break;
+
+ case IDC_RESET_DEBUGSCRIPT:
+ changed = ResetDebugscript(hDlg);
+ break;
+
+ case IDC_SELECT_LUASCRIPT:
+ changed = SelectLUAScript(hDlg);
+ break;
+
+ case IDC_RESET_LUASCRIPT:
+ changed = ResetLUAScript(hDlg);
+ break;
+
+ case IDC_SELECT_PLUGIN:
+ changed = SelectPlugins(hDlg);
+ break;
+
+ case IDC_RESET_PLUGIN:
+ changed = ResetPlugins(hDlg);
+ break;
+
+ case IDC_PROP_RESET:
+ // RESET Button - Only do it if mouse-clicked
+ if (wNotifyCode != BN_CLICKED)
+ break;
+
+ // Change settings in property sheets back to original
+ UpdateProperties(hDlg, properties_datamap, pOrigOpts);
+ // The original options become the current options.
+ UpdateOptions(hDlg, properties_datamap, pCurrentOpts);
+
+ g_bUseDefaults = AreOptionsEqual(pCurrentOpts, pDefaultOpts) ? false : true;
+ g_bReset = AreOptionsEqual(pCurrentOpts, pOrigOpts) ? false : true;
+ // Turn off Apply
+ PropSheet_UnChanged(GetParent(hDlg), hDlg);
+ EnableWindow(GetDlgItem(hDlg, IDC_USE_DEFAULT), g_bUseDefaults);
+ EnableWindow(GetDlgItem(hDlg, IDC_PROP_RESET), g_bReset);
+ break;
+
+ case IDC_USE_DEFAULT:
+ // DEFAULT Button - Only do it if mouse-clicked
+ if (wNotifyCode != BN_CLICKED)
+ break;
+
+ // Change settings to be the same as mame.ini
+ UpdateProperties(hDlg, properties_datamap, pDefaultOpts);
+ // The original options become the current options.
+ UpdateOptions(hDlg, properties_datamap, pCurrentOpts);
+
+ g_bUseDefaults = AreOptionsEqual(pCurrentOpts, pDefaultOpts) ? false : true;
+ g_bReset = AreOptionsEqual(pCurrentOpts, pOrigOpts) ? false : true;
+ // Enable/Disable the Reset to Defaults button
+ EnableWindow(GetDlgItem(hDlg, IDC_USE_DEFAULT), g_bUseDefaults);
+ EnableWindow(GetDlgItem(hDlg, IDC_PROP_RESET), g_bReset);
+ // Tell the dialog to enable/disable the apply button.
+ if (g_nGame != GLOBAL_OPTIONS)
+ {
+ if (g_bReset)
+ PropSheet_Changed(GetParent(hDlg), hDlg);
+ else
+ PropSheet_UnChanged(GetParent(hDlg), hDlg);
+ }
+ break;
+
+ // MSH 20070813 - Update all related controls
+ case IDC_SCREENSELECT:
+ case IDC_SCREEN:
+ // NPW 3-Apr-2007: Ugh I'm only perpetuating the vile hacks in this code
+ if ((wNotifyCode == CBN_SELCHANGE) || (wNotifyCode == CBN_SELENDOK))
+ {
+ changed = datamap_read_control(properties_datamap, hDlg, pCurrentOpts, wID);
+ datamap_populate_control(properties_datamap, hDlg, pCurrentOpts, IDC_SIZES);
+ //MSH 20070814 - Hate to do this, but its either this, or update each individual
+ // control on the SCREEN tab.
+ UpdateProperties(hDlg, properties_datamap, pCurrentOpts);
+ changed = true;
+ /* NOT USED *************
+ datamap_populate_control(properties_datamap, hDlg, pCurrentOpts, IDC_SCREENSELECT);
+ datamap_populate_control(properties_datamap, hDlg, pCurrentOpts, IDC_SCREEN);
+ datamap_populate_control(properties_datamap, hDlg, pCurrentOpts, IDC_REFRESH);
+ datamap_populate_control(properties_datamap, hDlg, pCurrentOpts, IDC_SIZES);
+ datamap_populate_control(properties_datamap, hDlg, pCurrentOpts, IDC_VIEW);
+ datamap_populate_control(properties_datamap, hDlg, pCurrentOpts, IDC_SWITCHRES);
+
+ if (strcmp(options_get_string(pCurrentOpts, "screen0"), options_get_string(pOrigOpts, "screen0")!=0) ||
+ strcmp(options_get_string(pCurrentOpts, "screen1"), options_get_string(pOrigOpts, "screen1")!=0) ||
+ strcmp(options_get_string(pCurrentOpts, "screen2"), options_get_string(pOrigOpts, "screen2")!=0) ||
+ strcmp(options_get_string(pCurrentOpts, "screen3"), options_get_string(pOrigOpts, "screen3")!=0))
+ changed = true;
+ ************************************* */
+ }
+ break;
+ default:
+#ifdef MESS
+ if (MessPropertiesCommand(hDlg, wNotifyCode, wID, &changed))
+ // To Do: add a hook to MessReadMountedSoftware(drvindex); so the software will update itself when the folder is configured
+ break;
+#endif
+
+ // use default behavior; try to get the result out of the datamap if
+ // appropriate
+ GetClassName(hWndCtrl, szClass, ARRAY_LENGTH(szClass));
+ if (!_tcscmp(szClass, WC_COMBOBOX))
+ {
+ // combo box
+ if ((wNotifyCode == CBN_SELCHANGE) || (wNotifyCode == CBN_SELENDOK))
+ changed = datamap_read_control(properties_datamap, hDlg, pCurrentOpts, wID);
+ }
+ else if (!_tcscmp(szClass, WC_BUTTON) && (GetWindowLong(hWndCtrl, GWL_STYLE) & BS_CHECKBOX))
+ {
+ // check box
+ changed = datamap_read_control(properties_datamap, hDlg, pCurrentOpts, wID);
+ }
+ break;
+ }
+
+ if (changed == true)
+ {
+ // make sure everything's copied over, to determine what's changed
+ UpdateOptions(hDlg, properties_datamap, pCurrentOpts);
+ // enable the apply button
+ PropSheet_Changed(GetParent(hDlg), hDlg);
+ g_bUseDefaults = AreOptionsEqual(pCurrentOpts, pDefaultOpts) ? false : true;
+ g_bReset = AreOptionsEqual(pCurrentOpts, pOrigOpts) ? false : true;
+ EnableWindow(GetDlgItem(hDlg, IDC_USE_DEFAULT), g_bUseDefaults);
+ EnableWindow(GetDlgItem(hDlg, IDC_PROP_RESET), g_bReset);
+ }
+ }
+ break;
+
+ case WM_NOTIFY:
+ {
+ // Set to true if we are exiting the properties dialog
+ //BOOL bClosing = ((LPPSHNOTIFY) lParam)->lParam; // indicates OK was clicked rather than APPLY
+
+ switch (((NMHDR *) lParam)->code)
+ {
+ //We'll need to use a CheckState Table
+ //Because this one gets called for all kinds of other things too, and not only if a check is set
+ case PSN_SETACTIVE:
+ /* Initialize the controls. */
+ UpdateProperties(hDlg, properties_datamap, pCurrentOpts);
+ g_bUseDefaults = AreOptionsEqual(pCurrentOpts, pDefaultOpts) ? false : true;
+ g_bReset = AreOptionsEqual(pCurrentOpts, pOrigOpts) ? false : true;
+ EnableWindow(GetDlgItem(hDlg, IDC_USE_DEFAULT), g_bUseDefaults);
+ EnableWindow(GetDlgItem(hDlg, IDC_PROP_RESET), g_bReset);
+ break;
+
+ case PSN_APPLY:
+ // Handle more than one PSN_APPLY, since this proc handles more than one
+ // property sheet and can be called multiple times when it's time to exit,
+ // and we may have already freed the windows_options.
+ //if (bClosing)
+ //{
+ //if (NULL == pCurrentOpts)
+ //return true;
+ //}
+
+ // Read the datamap
+ UpdateOptions(hDlg, properties_datamap, pCurrentOpts);
+ // The current options become the original options.
+ UpdateOptions(hDlg, properties_datamap, pOrigOpts);
+
+ // Repopulate the controls? WTF? We just read them, they should be fine.
+ UpdateProperties(hDlg, properties_datamap, pCurrentOpts);
+
+ g_bUseDefaults = AreOptionsEqual(pCurrentOpts, pDefaultOpts) ? false : true;
+ g_bReset = AreOptionsEqual(pCurrentOpts, pOrigOpts) ? false : true;
+ EnableWindow(GetDlgItem(hDlg, IDC_USE_DEFAULT), g_bUseDefaults);
+ EnableWindow(GetDlgItem(hDlg, IDC_PROP_RESET), g_bReset);
+
+ // Save the current options
+ save_options(pCurrentOpts, g_nPropertyMode, g_nGame);
+
+ // Disable apply button
+ PropSheet_UnChanged(GetParent(hDlg), hDlg);
+ SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
+
+ return true;
+
+ case PSN_KILLACTIVE:
+ /* Save Changes to the options here. */
+ UpdateOptions(hDlg, properties_datamap, pCurrentOpts);
+ // Determine button states.
+ g_bUseDefaults = AreOptionsEqual(pCurrentOpts, pDefaultOpts) ? false : true;
+ g_bReset = AreOptionsEqual(pCurrentOpts, pOrigOpts) ? false : true;
+ EnableWindow(GetDlgItem(hDlg, IDC_USE_DEFAULT), g_bUseDefaults);
+ EnableWindow(GetDlgItem(hDlg, IDC_PROP_RESET), g_bReset);
+
+ ResetDataMap(hDlg);
+ SetWindowLongPtr(hDlg, DWLP_MSGRESULT, false);
+ return 1;
+
+ case PSN_RESET:
+ // Reset to the original values. Disregard changes
+ //pCurrentOpts = pOrigOpts;
+ g_bUseDefaults = AreOptionsEqual(pCurrentOpts, pDefaultOpts) ? false : true;
+ g_bReset = AreOptionsEqual(pCurrentOpts, pOrigOpts) ? false : true;
+ EnableWindow(GetDlgItem(hDlg, IDC_USE_DEFAULT), g_bUseDefaults);
+ EnableWindow(GetDlgItem(hDlg, IDC_PROP_RESET), g_bReset);
+ SetWindowLongPtr(hDlg, DWLP_MSGRESULT, false);
+ break;
+
+ case PSN_HELP:
+ // User wants help for this property page
+ break;
+ }
+ }
+ break;
+
+ case WM_HELP:
+ /* User clicked the ? from the upper right on a control */
+ HelpFunction((HWND)((LPHELPINFO)lParam)->hItemHandle, MAMEUICONTEXTHELP, HH_TP_HELP_WM_HELP, GetHelpIDs());
+ break;
+
+ case WM_CONTEXTMENU:
+ HelpFunction((HWND)wParam, MAMEUICONTEXTHELP, HH_TP_HELP_CONTEXTMENU, GetHelpIDs());
+ break;
+
+ }
+
+ return 0;
+}
+
+/* Read controls that are not handled in the DataMap */
+static void PropToOptions(HWND hWnd, windows_options &o)
+{
+ HWND hCtrl;
+ HWND hCtrl2;
+ HWND hCtrl3;
+
+ /* aspect ratio */
+ hCtrl = GetDlgItem(hWnd, IDC_ASPECTRATION);
+ hCtrl2 = GetDlgItem(hWnd, IDC_ASPECTRATIOD);
+ hCtrl3 = GetDlgItem(hWnd, IDC_ASPECT);
+ if (hCtrl && hCtrl2 && hCtrl3)
+ {
+ char aspect_option[32];
+ snprintf(aspect_option, ARRAY_LENGTH(aspect_option), "aspect%d", GetSelectedScreen(hWnd));
+
+ if (Button_GetCheck(hCtrl3))
+ {
+ o.set_value(aspect_option, "auto", OPTION_PRIORITY_CMDLINE);
+ }
+ else
+ {
+ int n = 0;
+ int d = 0;
+ TCHAR buffer[200];
+ char buffer2[200];
+
+ Edit_GetText(hCtrl, buffer, ARRAY_LENGTH(buffer));
+ _stscanf(buffer,TEXT("%d"),&n);
+
+ Edit_GetText(hCtrl2, buffer, ARRAY_LENGTH(buffer));
+ _stscanf(buffer,TEXT("%d"),&d);
+
+ if (n == 0 || d == 0)
+ {
+ n = 4;
+ d = 3;
+ }
+
+ snprintf(buffer2, sizeof(buffer2), "%d:%d", n, d);
+ o.set_value(aspect_option, buffer2, OPTION_PRIORITY_CMDLINE);
+ }
+ }
+ /* aspect ratio */
+ hCtrl = GetDlgItem(hWnd, IDC_SNAPSIZEWIDTH);
+ hCtrl2 = GetDlgItem(hWnd, IDC_SNAPSIZEHEIGHT);
+ hCtrl3 = GetDlgItem(hWnd, IDC_SNAPSIZE);
+ if (hCtrl && hCtrl2 && hCtrl3)
+ {
+ if (Button_GetCheck(hCtrl3))
+ {
+ o.set_value(OPTION_SNAPSIZE, "auto", OPTION_PRIORITY_CMDLINE);
+ }
+ else
+ {
+ int width = 0;
+ int height = 0;
+ TCHAR buffer[200];
+ char buffer2[200];
+
+ Edit_GetText(hCtrl, buffer, ARRAY_LENGTH(buffer));
+ _stscanf(buffer, TEXT("%d"), &width);
+
+ Edit_GetText(hCtrl2, buffer, ARRAY_LENGTH(buffer));
+ _stscanf(buffer, TEXT("%d"), &height);
+
+ if (width == 0 || height == 0)
+ {
+ width = 640;
+ height = 480;
+ }
+
+ snprintf(buffer2, sizeof(buffer2), "%dx%d", width, height);
+ o.set_value(OPTION_SNAPSIZE, buffer2, OPTION_PRIORITY_CMDLINE);
+ }
+ }
+}
+
+/* Update options from the dialog */
+static void UpdateOptions(HWND hDlg, datamap *map, windows_options &opts)
+{
+ /* These are always called together, so make one convenient function. */
+ datamap_read_all_controls(map, hDlg, opts);
+ PropToOptions(hDlg, opts);
+}
+
+/* Update the dialog from the options */
+static void UpdateProperties(HWND hDlg, datamap *map, windows_options &opts)
+{
+ /* These are always called together, so make one convenient function. */
+ datamap_populate_all_controls(map, hDlg, opts);
+ OptionsToProp(hDlg, opts);
+ SetPropEnabledControls(hDlg);
+}
+
+/* Populate controls that are not handled in the DataMap */
+static void OptionsToProp(HWND hWnd, windows_options& o)
+{
+ HWND hCtrl2;
+ TCHAR buf[1024];
+ int n = 0;
+ int d = 0;
+ int width = 0;
+ int height = 0;
+ int res = 0;
+
+ /* video */
+
+ /* Setup refresh list based on depth. */
+ datamap_update_control(properties_datamap, hWnd, pCurrentOpts, IDC_REFRESH);
+ /* Setup Select screen*/
+ UpdateSelectScreenUI(hWnd );
+
+ HWND hCtrl = GetDlgItem(hWnd, IDC_ASPECT);
+ if (hCtrl)
+ Button_SetCheck(hCtrl, g_bAutoAspect[GetSelectedScreen(hWnd)] );
+
+ hCtrl = GetDlgItem(hWnd, IDC_SNAPSIZE);
+ if (hCtrl)
+ Button_SetCheck(hCtrl, g_bAutoSnapSize );
+
+ /* Bios select list */
+ hCtrl = GetDlgItem(hWnd, IDC_BIOS);
+ if (hCtrl)
+ {
+ const char* cBuffer;
+ for( uint8_t i = 0; i < ComboBox_GetCount( hCtrl ); i++ )
+ {
+ cBuffer = (const char*)ComboBox_GetItemData( hCtrl, i );
+ if (strcmp(cBuffer, pCurrentOpts.value(OPTION_BIOS) ) == 0)
+ {
+ res = ComboBox_SetCurSel(hCtrl, i);
+ break;
+ }
+
+ }
+ }
+
+
+ hCtrl = GetDlgItem(hWnd, IDC_ASPECT);
+ if (hCtrl)
+ {
+ char aspect_option[32];
+ snprintf(aspect_option, ARRAY_LENGTH(aspect_option), "aspect%d", GetSelectedScreen(hWnd));
+ if( strcmp(o.value(aspect_option), "auto") == 0)
+ {
+ Button_SetCheck(hCtrl, true);
+ g_bAutoAspect[GetSelectedScreen(hWnd)] = true;
+ }
+ else
+ {
+ Button_SetCheck(hCtrl, false);
+ g_bAutoAspect[GetSelectedScreen(hWnd)] = false;
+ }
+ }
+
+ /* aspect ratio */
+ hCtrl = GetDlgItem(hWnd, IDC_ASPECTRATION);
+ hCtrl2 = GetDlgItem(hWnd, IDC_ASPECTRATIOD);
+ if (hCtrl && hCtrl2)
+ {
+ char aspect_option[32];
+ snprintf(aspect_option, ARRAY_LENGTH(aspect_option), "aspect%d", GetSelectedScreen(hWnd));
+
+ n = 0;
+ d = 0;
+ if (o.value(aspect_option))
+ {
+ if (sscanf(o.value(aspect_option), "%d:%d", &n, &d) == 2 && n != 0 && d != 0)
+ {
+ _stprintf(buf, TEXT("%d"), n);
+ Edit_SetText(hCtrl, buf);
+ _stprintf(buf, TEXT("%d"), d);
+ Edit_SetText(hCtrl2, buf);
+ }
+ else
+ {
+ Edit_SetText(hCtrl, TEXT("4"));
+ Edit_SetText(hCtrl2, TEXT("3"));
+ }
+ }
+ else
+ {
+ Edit_SetText(hCtrl, TEXT("4"));
+ Edit_SetText(hCtrl2, TEXT("3"));
+ }
+ }
+
+ hCtrl = GetDlgItem(hWnd, IDC_EFFECT);
+ if (hCtrl) {
+ const char* effect = o.value(OPTION_EFFECT);
+ if (effect == NULL) {
+ effect = "none";
+ o.set_value(OPTION_EFFECT, effect, OPTION_PRIORITY_CMDLINE);
+ }
+ win_set_window_text_utf8(hCtrl, effect);
+ }
+
+ hCtrl = GetDlgItem(hWnd, IDC_SNAPSIZE);
+ if (hCtrl)
+ {
+ if( strcmp(o.value(OPTION_SNAPSIZE), "auto") == 0)
+ {
+ Button_SetCheck(hCtrl, true);
+ g_bAutoSnapSize = true;
+ }
+ else
+ {
+ Button_SetCheck(hCtrl, false);
+ g_bAutoSnapSize = false;
+ }
+ }
+#if 0
+ for (int i = 0; i < 5; i++)
+ {
+ UpdateMameShader(hWnd, i, opts);
+ UpdateScreenShader(hWnd, i, opts);
+ }
+
+ hCtrl = GetDlgItem(hWnd, IDC_CHEATFILE);
+
+ if (hCtrl)
+ {
+ const char* cheatfile = opts.value(OPTION_CHEATPATH);
+
+ if (strcmp(cheatfile, "cheat") == 0)
+ winui_set_window_text_utf8(hCtrl, "Default");
+ else
+ {
+ char *cheatname = strrchr(cheatfile, '\\');
+
+ if (cheatname != NULL)
+ {
+ strcpy(buffer, cheatname + 1);
+ winui_set_window_text_utf8(hCtrl, buffer);
+ }
+ else
+ winui_set_window_text_utf8(hCtrl, cheatfile);
+ }
+ }
+#endif
+ hCtrl = GetDlgItem(hWnd, IDC_JOYSTICKMAP);
+
+ if (hCtrl)
+ {
+ const char* joymap = o.value(OPTION_JOYSTICK_MAP);
+
+ win_set_window_text_utf8(hCtrl, joymap);
+ }
+
+ hCtrl = GetDlgItem(hWnd, IDC_LUASCRIPT);
+
+ if (hCtrl)
+ {
+ const char* script = o.value(OPTION_AUTOBOOT_SCRIPT);
+
+ if (strcmp(script, "") == 0)
+ win_set_window_text_utf8(hCtrl, "None");
+ else
+ {
+ char buffer[260];
+ wchar_t *t_filename = ui_wstring_from_utf8(script);
+ wchar_t *tempname = PathFindFileName(t_filename);
+ PathRemoveExtension(tempname);
+ char *optname = ui_utf8_from_wstring(tempname);
+ strcpy(buffer, optname);
+ free(t_filename);
+ free(optname);
+ win_set_window_text_utf8(hCtrl, buffer);
+ }
+ }
+
+ hCtrl = GetDlgItem(hWnd, IDC_PLUGIN);
+
+ if (hCtrl)
+ {
+ string t1 = GetPlugins();
+ const char* plugin = t1.c_str();
+
+ if (strlen(plugin) == 0)
+ //if (strcmp(plugin, "") == 0)
+ win_set_window_text_utf8(hCtrl, "None");
+ else
+ win_set_window_text_utf8(hCtrl, plugin);
+ }
+#if 0
+ hCtrl = GetDlgItem(hWnd, IDC_BGFX_CHAINS);
+
+ if (hCtrl)
+ {
+ const char* chains = o.value(OSDOPTION_BGFX_SCREEN_CHAINS);
+
+ if (strcmp(chains, "default") == 0)
+ winui_set_window_text_utf8(hCtrl, "Default");
+ else
+ winui_set_window_text_utf8(hCtrl, chains);
+ }
+#endif
+ /* snapshot size */
+ hCtrl = GetDlgItem(hWnd, IDC_SNAPSIZEWIDTH);
+ hCtrl2 = GetDlgItem(hWnd, IDC_SNAPSIZEHEIGHT);
+ if (hCtrl && hCtrl2)
+ {
+ n = 0;
+ d = 0;
+ if (o.value(OPTION_SNAPSIZE))
+ {
+ if (sscanf(o.value(OPTION_SNAPSIZE), "%dx%d", &width, &height) == 2 && width && height)
+ {
+ _stprintf(buf, TEXT("%d"), width);
+ Edit_SetText(hCtrl, buf);
+ _stprintf(buf, TEXT("%d"), height);
+ Edit_SetText(hCtrl2, buf);
+ }
+ else
+ {
+ Edit_SetText(hCtrl, TEXT("640"));
+ Edit_SetText(hCtrl2, TEXT("480"));
+ }
+ }
+ else
+ {
+ Edit_SetText(hCtrl, TEXT("640"));
+ Edit_SetText(hCtrl2, TEXT("480"));
+ }
+ }
+ res++;
+}
+
+/* Adjust controls - tune them to the currently selected game */
+static void SetPropEnabledControls(HWND hWnd)
+{
+ bool useart = true;
+ BOOL joystick_attached = false;
+ bool in_window = false;
+ int nIndex = g_nGame;
+
+ // auto is a reserved word
+ bool autov = (core_stricmp(pCurrentOpts.value(OSDOPTION_VIDEO), "auto")==0);
+ bool d3d = (core_stricmp(pCurrentOpts.value(OSDOPTION_VIDEO), "d3d")==0) | autov;
+#ifdef UI_DIRECTDRAW
+ bool ddraw = (core_stricmp(pCurrentOpts.value(OSDOPTION_VIDEO), "ddraw")==0) | autov;
+#else
+ bool ddraw = false;
+#endif
+
+ in_window = pCurrentOpts.bool_value(OSDOPTION_WINDOW);
+ Button_SetCheck(GetDlgItem(hWnd, IDC_ASPECT), g_bAutoAspect[GetSelectedScreen(hWnd)] );
+
+ EnableWindow(GetDlgItem(hWnd, IDC_WAITVSYNC), d3d|ddraw);
+ EnableWindow(GetDlgItem(hWnd, IDC_TRIPLE_BUFFER), d3d|ddraw);
+ EnableWindow(GetDlgItem(hWnd, IDC_PRESCALE), d3d|ddraw);
+ EnableWindow(GetDlgItem(hWnd, IDC_PRESCALEDISP), d3d|ddraw);
+ EnableWindow(GetDlgItem(hWnd, IDC_PRESCALETEXT), d3d|ddraw);
+#ifdef UI_DIRECTDRAW
+ EnableWindow(GetDlgItem(hWnd, IDC_HWSTRETCH), ddraw && DirectDraw_HasHWStretch());
+#else
+ EnableWindow(GetDlgItem(hWnd, IDC_HWSTRETCH), false);
+#endif
+ EnableWindow(GetDlgItem(hWnd, IDC_SWITCHRES), true);
+ EnableWindow(GetDlgItem(hWnd, IDC_SYNCREFRESH), true);
+ EnableWindow(GetDlgItem(hWnd, IDC_REFRESH), !in_window);
+ EnableWindow(GetDlgItem(hWnd, IDC_REFRESHTEXT), !in_window);
+ EnableWindow(GetDlgItem(hWnd, IDC_FSGAMMA), !in_window);
+ EnableWindow(GetDlgItem(hWnd, IDC_FSGAMMATEXT), !in_window);
+ EnableWindow(GetDlgItem(hWnd, IDC_FSGAMMADISP), !in_window);
+ EnableWindow(GetDlgItem(hWnd, IDC_FSBRIGHTNESS), !in_window);
+ EnableWindow(GetDlgItem(hWnd, IDC_FSBRIGHTNESSTEXT), !in_window);
+ EnableWindow(GetDlgItem(hWnd, IDC_FSBRIGHTNESSDISP), !in_window);
+ EnableWindow(GetDlgItem(hWnd, IDC_FSCONTRAST), !in_window);
+ EnableWindow(GetDlgItem(hWnd, IDC_FSCONTRASTTEXT), !in_window);
+ EnableWindow(GetDlgItem(hWnd, IDC_FSCONTRASTDISP), !in_window);
+
+ EnableWindow(GetDlgItem(hWnd, IDC_ASPECTRATIOTEXT), !g_bAutoAspect[GetSelectedScreen(hWnd)]);
+ EnableWindow(GetDlgItem(hWnd, IDC_ASPECTRATION), !g_bAutoAspect[GetSelectedScreen(hWnd)]);
+ EnableWindow(GetDlgItem(hWnd, IDC_ASPECTRATIOD), !g_bAutoAspect[GetSelectedScreen(hWnd)]);
+
+ EnableWindow(GetDlgItem(hWnd, IDC_SNAPSIZETEXT), !g_bAutoSnapSize);
+ EnableWindow(GetDlgItem(hWnd, IDC_SNAPSIZEHEIGHT), !g_bAutoSnapSize);
+ EnableWindow(GetDlgItem(hWnd, IDC_SNAPSIZEWIDTH), !g_bAutoSnapSize);
+ EnableWindow(GetDlgItem(hWnd, IDC_SNAPSIZEX), !g_bAutoSnapSize);
+
+ EnableWindow(GetDlgItem(hWnd, IDC_D3D_FILTER),d3d);
+#ifdef D3DVERSION
+ EnableWindow(GetDlgItem(hWnd, IDC_D3D_VERSION),(NUMD3DVERSIONS>1) & d3d);
+#endif
+
+ //Switchres and D3D or ddraw enable the per screen parameters
+ EnableWindow(GetDlgItem(hWnd, IDC_NUMSCREENS), ddraw | d3d);
+ EnableWindow(GetDlgItem(hWnd, IDC_NUMSCREENSDISP), ddraw | d3d);
+ EnableWindow(GetDlgItem(hWnd, IDC_SCREENSELECT), ddraw | d3d);
+ EnableWindow(GetDlgItem(hWnd, IDC_SCREENSELECTTEXT), ddraw | d3d);
+
+ EnableWindow(GetDlgItem(hWnd, IDC_ARTWORK_CROP), useart);
+ EnableWindow(GetDlgItem(hWnd, IDC_BACKDROPS), useart);
+ EnableWindow(GetDlgItem(hWnd, IDC_BEZELS), useart);
+ EnableWindow(GetDlgItem(hWnd, IDC_OVERLAYS), useart);
+ EnableWindow(GetDlgItem(hWnd, IDC_CPANELS), useart);
+ EnableWindow(GetDlgItem(hWnd, IDC_MARQUEES), useart);
+ EnableWindow(GetDlgItem(hWnd, IDC_ARTMISCTEXT), useart);
+
+ /* Joystick options */
+ joystick_attached = DIJoystick.Available();
+
+ Button_Enable(GetDlgItem(hWnd,IDC_JOYSTICK), joystick_attached);
+ EnableWindow(GetDlgItem(hWnd, IDC_JDZTEXT), joystick_attached);
+ EnableWindow(GetDlgItem(hWnd, IDC_JDZDISP), joystick_attached);
+ EnableWindow(GetDlgItem(hWnd, IDC_JDZ), joystick_attached);
+ EnableWindow(GetDlgItem(hWnd, IDC_JSATTEXT), joystick_attached);
+ EnableWindow(GetDlgItem(hWnd, IDC_JSATDISP), joystick_attached);
+ EnableWindow(GetDlgItem(hWnd, IDC_JSAT), joystick_attached);
+ /* Trackball / Mouse options */
+ if (nIndex <= -1 || DriverUsesTrackball(nIndex) || DriverUsesLightGun(nIndex))
+ Button_Enable(GetDlgItem(hWnd,IDC_USE_MOUSE),true);
+ else
+ Button_Enable(GetDlgItem(hWnd,IDC_USE_MOUSE),false);
+
+ if (!in_window && (nIndex <= -1 || DriverUsesLightGun(nIndex)))
+ {
+ // on WinXP the Lightgun and Dual Lightgun switches are no longer supported use mouse instead
+ OSVERSIONINFOEX osvi;
+ BOOL bOsVersionInfoEx;
+ // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
+ // If that fails, try using the OSVERSIONINFO structure.
+
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+
+ if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
+ {
+ osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
+ bOsVersionInfoEx = GetVersionEx ( (OSVERSIONINFO *) &osvi);
+ }
+
+// if( bOsVersionInfoEx && (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osvi.dwMajorVersion >= 5) )
+// {
+ BOOL use_lightgun;
+ //XP and above...
+ Button_Enable(GetDlgItem(hWnd,IDC_LIGHTGUN),false);
+ use_lightgun = Button_GetCheck(GetDlgItem(hWnd,IDC_USE_MOUSE));
+ Button_Enable(GetDlgItem(hWnd,IDC_DUAL_LIGHTGUN),false);
+ Button_Enable(GetDlgItem(hWnd,IDC_RELOAD),use_lightgun);
+// }
+// else
+// {
+// BOOL use_lightgun;
+ // Older than XP
+// Button_Enable(GetDlgItem(hWnd,IDC_LIGHTGUN),true);
+// use_lightgun = Button_GetCheck(GetDlgItem(hWnd,IDC_LIGHTGUN));
+// Button_Enable(GetDlgItem(hWnd,IDC_DUAL_LIGHTGUN),use_lightgun);
+// Button_Enable(GetDlgItem(hWnd,IDC_RELOAD),use_lightgun);
+// }
+ }
+ else
+ {
+ Button_Enable(GetDlgItem(hWnd,IDC_LIGHTGUN),false);
+ Button_Enable(GetDlgItem(hWnd,IDC_DUAL_LIGHTGUN),false);
+ Button_Enable(GetDlgItem(hWnd,IDC_RELOAD),false);
+ }
+
+
+ /* Sound options */
+ bool sound = (core_stricmp(pCurrentOpts.value(OSDOPTION_SOUND), "none")!=0);
+ ComboBox_Enable(GetDlgItem(hWnd, IDC_SAMPLERATE), sound);
+ EnableWindow(GetDlgItem(hWnd,IDC_VOLUME),sound);
+ EnableWindow(GetDlgItem(hWnd,IDC_RATETEXT),sound);
+ EnableWindow(GetDlgItem(hWnd,IDC_VOLUMEDISP),sound);
+ EnableWindow(GetDlgItem(hWnd,IDC_VOLUMETEXT),sound);
+ EnableWindow(GetDlgItem(hWnd,IDC_AUDIO_LATENCY),sound);
+ EnableWindow(GetDlgItem(hWnd,IDC_AUDIO_LATENCY_DISP),sound);
+ EnableWindow(GetDlgItem(hWnd,IDC_AUDIO_LATENCY_TEXT),sound);
+ SetSamplesEnabled(hWnd, nIndex, sound);
+
+ if (Button_GetCheck(GetDlgItem(hWnd, IDC_AUTOFRAMESKIP)))
+ EnableWindow(GetDlgItem(hWnd, IDC_FRAMESKIP), false);
+ else
+ EnableWindow(GetDlgItem(hWnd, IDC_FRAMESKIP), 1);
+
+ if (nIndex <= -1 || DriverHasOptionalBIOS(nIndex))
+ EnableWindow(GetDlgItem(hWnd,IDC_BIOS),true);
+ else
+ EnableWindow(GetDlgItem(hWnd,IDC_BIOS),false);
+
+}
+
+//============================================================
+// CONTROL HELPER FUNCTIONS FOR DATA EXCHANGE
+//============================================================
+
+static BOOL RotateReadControl(datamap *map, HWND dialog, HWND control, windows_options *opts, const char *option_name)
+{
+ int selected_index = ComboBox_GetCurSel(control);
+ int original_selection = 0;
+
+ // Figure out what the original selection value is
+ if (opts->bool_value(OPTION_ROR) && !opts->bool_value(OPTION_ROL))
+ original_selection = 1;
+ else if (!opts->bool_value(OPTION_ROR) && opts->bool_value(OPTION_ROL))
+ original_selection = 2;
+ else if (!opts->bool_value(OPTION_ROTATE))
+ original_selection = 3;
+ else if (opts->bool_value(OPTION_AUTOROR))
+ original_selection = 4;
+ else if (opts->bool_value(OPTION_AUTOROL))
+ original_selection = 5;
+
+ // Any work to do? If so, make the changes and return true.
+ if (selected_index != original_selection)
+ {
+ // Set the options based on the new selection.
+ opts->set_value(OPTION_ROR, selected_index == 1, OPTION_PRIORITY_CMDLINE);
+ opts->set_value(OPTION_ROL, selected_index == 2, OPTION_PRIORITY_CMDLINE);
+ opts->set_value(OPTION_ROTATE, selected_index != 3, OPTION_PRIORITY_CMDLINE);
+ opts->set_value(OPTION_AUTOROR, selected_index == 4, OPTION_PRIORITY_CMDLINE);
+ opts->set_value(OPTION_AUTOROL, selected_index == 5, OPTION_PRIORITY_CMDLINE);
+ return true;
+ }
+
+ // No changes
+ return false;
+}
+
+
+
+static BOOL RotatePopulateControl(datamap *map, HWND dialog, HWND control, windows_options *opts, const char *option_name)
+{
+ int res, selected_index = 0;
+ if (opts->bool_value(OPTION_ROR) && !opts->bool_value(OPTION_ROL))
+ selected_index = 1;
+ else if (!opts->bool_value(OPTION_ROR) && opts->bool_value(OPTION_ROL))
+ selected_index = 2;
+ else if (!opts->bool_value(OPTION_ROTATE))
+ selected_index = 3;
+ else if (opts->bool_value(OPTION_AUTOROR))
+ selected_index = 4;
+ else if (opts->bool_value(OPTION_AUTOROL))
+ selected_index = 5;
+
+ res = ComboBox_SetCurSel(control, selected_index);
+ res++;
+ return false;
+}
+
+
+
+static BOOL ScreenReadControl(datamap *map, HWND dialog, HWND control, windows_options *opts, const char *option_name)
+{
+ char screen_option_name[32];
+ int selected_screen = GetSelectedScreen(dialog);
+ int screen_option_index = ComboBox_GetCurSel(control);
+ TCHAR *screen_option_value = (TCHAR*) ComboBox_GetItemData(control, screen_option_index);
+ snprintf(screen_option_name, ARRAY_LENGTH(screen_option_name), "screen%d", selected_screen);
+ char *op_val = ui_utf8_from_wstring(screen_option_value);
+ opts->set_value(screen_option_name, op_val, OPTION_PRIORITY_CMDLINE);
+ free(op_val);
+ return false;
+}
+
+
+
+static BOOL ScreenPopulateControl(datamap *map, HWND dialog, HWND control, windows_options *opts, const char *option_name)
+{
+ //int iMonitors;
+ DISPLAY_DEVICE dd;
+ int res, i = 0;
+ int nSelection = 0;
+ TCHAR* t_option = 0;
+
+ /* Remove all items in the list. */
+ res = ComboBox_ResetContent(control);
+ res = ComboBox_InsertString(control, 0, TEXT("Auto"));
+ res = ComboBox_SetItemData(control, 0, (void*)ui_wstring_from_utf8("auto"));
+
+ //Dynamically populate it, by enumerating the Monitors
+ //iMonitors = GetSystemMetrics(SM_CMONITORS); // this gets the count of monitors attached
+ ZeroMemory(&dd, sizeof(dd));
+ dd.cb = sizeof(dd);
+ for(i=0; EnumDisplayDevices(NULL, i, &dd, 0); i++)
+ {
+ if( !(dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) )
+ {
+ char screen_option[32];
+
+ //we have to add 1 to account for the "auto" entry
+ res = ComboBox_InsertString(control, i+1, win_tstring_strdup(dd.DeviceName));
+ res = ComboBox_SetItemData(control, i+1, (void*)win_tstring_strdup(dd.DeviceName));
+
+ snprintf(screen_option, ARRAY_LENGTH(screen_option), "screen%d", GetSelectedScreen(dialog));
+ t_option = ui_wstring_from_utf8(opts->value(screen_option));
+ if( !t_option )
+ return false;
+ if (_tcscmp(t_option, dd.DeviceName) == 0)
+ nSelection = i+1;
+ free(t_option);
+ }
+ }
+ res = ComboBox_SetCurSel(control, nSelection);
+ res++;
+ return false;
+}
+
+
+
+static void ViewSetOptionName(datamap *map, HWND dialog, HWND control, char *buffer, size_t buffer_size)
+{
+ snprintf(buffer, buffer_size, "view%d", GetSelectedScreen(dialog));
+}
+
+static BOOL ViewPopulateControl(datamap *map, HWND dialog, HWND control, windows_options *opts, const char *option_name)
+{
+ int selected_index = 0;
+ char view_option[32];
+
+ // determine the view option value
+ snprintf(view_option, ARRAY_LENGTH(view_option), "view%d", GetSelectedScreen(dialog));
+ const char *view = opts->value(view_option);
+
+ int res = ComboBox_ResetContent(control);
+ for (int i = 0; i < NUMVIEW; i++)
+ {
+ res = ComboBox_InsertString(control, i, g_ComboBoxView[i].m_pText);
+ res = ComboBox_SetItemData(control, i, g_ComboBoxView[i].m_pData);
+
+ if (strcmp(view, g_ComboBoxView[i].m_pData)==0)
+ selected_index = i;
+ }
+ res = ComboBox_SetCurSel(control, selected_index);
+ res++;
+ return false;
+}
+
+static BOOL SnapViewPopulateControl(datamap *map, HWND dialog, HWND control, windows_options *opts, const char *option_name)
+{
+ int selected_index = 0;
+
+ // determine the snapview option value
+ const char *snapview = opts->value(OPTION_SNAPVIEW);
+
+ int res = ComboBox_ResetContent(control);
+ for (int i = 0; i < NUMSNAPVIEW; i++)
+ {
+ res = ComboBox_InsertString(control, i, g_ComboBoxSnapView[i].m_pText);
+ res = ComboBox_SetItemData(control, i, g_ComboBoxSnapView[i].m_pData);
+
+ if (strcmp(snapview, g_ComboBoxSnapView[i].m_pData)==0)
+ selected_index = i;
+ }
+ res = ComboBox_SetCurSel(control, selected_index);
+ res++;
+ return false;
+}
+
+static BOOL DefaultInputReadControl(datamap *map, HWND dialog, HWND control, windows_options *opts, const char *option_name)
+{
+ int input_option_index = ComboBox_GetCurSel(control);
+ TCHAR *input_option_value = (TCHAR*) ComboBox_GetItemData(control, input_option_index);
+ char *op_val = ui_utf8_from_wstring(input_option_value);
+ opts->set_value(OPTION_CTRLR, input_option_index ? op_val : "", OPTION_PRIORITY_CMDLINE);
+ free(op_val);
+ return false;
+}
+
+wchar_t *win_wstring_from_utf8(const char *utf8string)
+{
+ // convert MAME string (UTF-8) to UTF-16
+ int char_count = MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, nullptr, 0);
+ wchar_t *result = (wchar_t *)malloc(char_count * sizeof(*result));
+
+ if (result != nullptr)
+ MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, result, char_count);
+
+ return result;
+}
+
+char *win_utf8_from_wstring(const wchar_t *wstring)
+{
+ // convert UTF-16 to MAME string (UTF-8)
+ int char_count = WideCharToMultiByte(CP_UTF8, 0, wstring, -1, nullptr, 0, nullptr, nullptr);
+ char *result = (char *)malloc(char_count * sizeof(*result));
+
+ if (result != nullptr)
+ WideCharToMultiByte(CP_UTF8, 0, wstring, -1, result, char_count, nullptr, nullptr);
+
+ return result;
+}
+
+HANDLE winui_find_first_file_utf8(const char* filename, WIN32_FIND_DATA *findfiledata)
+{
+ wchar_t *t_filename = win_wstring_from_utf8(filename);
+
+ if (!t_filename)
+ return NULL;
+
+ HANDLE result = FindFirstFile(t_filename, findfiledata);
+ free(t_filename);
+ return result;
+}
+
+static BOOL DefaultInputPopulateControl(datamap *map, HWND dialog, HWND control, windows_options *opts, const char *option_name)
+{
+ WIN32_FIND_DATA FindFileData;
+ char path[MAX_PATH];
+ int selected = 0;
+ int index = 0;
+
+ // determine the ctrlr option
+ const char *ctrlr_option = opts->value(OPTION_CTRLR);
+
+ // reset the controllers dropdown
+ (void)ComboBox_ResetContent(control);
+ (void)ComboBox_InsertString(control, index, TEXT("Default"));
+ (void)ComboBox_SetItemData(control, index, "");
+ index++;
+ snprintf(path, WINUI_ARRAY_LENGTH(path), "%s\\*.*", GetCtrlrDir().c_str());
+ HANDLE hFind = winui_find_first_file_utf8(path, &FindFileData);
+
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ while (FindNextFile (hFind, &FindFileData) != 0)
+ {
+ // copy the filename
+ const char *root = win_utf8_from_wstring(FindFileData.cFileName);
+ // find the extension
+ char *ext = strrchr(root, '.');
+
+ if (ext)
+ {
+ // check if it's a cfg file
+ if (strcmp (ext, ".cfg") == 0)
+ {
+ // and strip off the extension
+ *ext = 0;
+
+ // set the option?
+ if (!strcmp(root, ctrlr_option))
+ selected = index;
+
+ // add it as an option
+ wchar_t *t_root = win_wstring_from_utf8(root);
+ (void)ComboBox_InsertString(control, index, t_root);
+ (void)ComboBox_SetItemData(control, index, root);
+ free(t_root);
+ root = NULL;
+ index++;
+ }
+ }
+ }
+
+ FindClose (hFind);
+ }
+
+ (void)ComboBox_SetCurSel(control, selected);
+
+ return false;
+}
+
+
+
+static void ResolutionSetOptionName(datamap *map, HWND dialog, HWND control, char *buffer, size_t buffer_size)
+{
+ snprintf(buffer, buffer_size, "resolution%d", GetSelectedScreen(dialog));
+}
+
+
+static BOOL ResolutionReadControl(datamap *map, HWND dialog, HWND control, windows_options *opts, const char *option_name)
+{
+ HWND refresh_control = GetDlgItem(dialog, IDC_REFRESH);
+ HWND sizes_control = GetDlgItem(dialog, IDC_SIZES);
+ int res = 0, width = 0, height = 0;
+ char option_value[256];
+
+ if (refresh_control && sizes_control)
+ {
+ TCHAR buffer[256];
+ res = ComboBox_GetText(sizes_control, buffer, ARRAY_LENGTH(buffer) - 1);
+ if (_stscanf(buffer, TEXT("%d x %d"), &width, &height) == 2)
+ {
+ int refresh_index = ComboBox_GetCurSel(refresh_control);
+ int refresh_value = ComboBox_GetItemData(refresh_control, refresh_index);
+ snprintf(option_value, ARRAY_LENGTH(option_value), "%dx%d@%d", width, height, refresh_value);
+ }
+ else
+ snprintf(option_value, ARRAY_LENGTH(option_value), "auto");
+
+ opts->set_value(option_name, option_value, OPTION_PRIORITY_CMDLINE);
+ }
+ res++;
+ return false;
+}
+
+
+
+static BOOL ResolutionPopulateControl(datamap *map, HWND dialog, HWND control_, windows_options *opts, const char *option_name)
+{
+ HWND sizes_control = GetDlgItem(dialog, IDC_SIZES);
+ HWND refresh_control = GetDlgItem(dialog, IDC_REFRESH);
+ int width, height, refresh;
+ const char *option_value;
+ int sizes_index = 0;
+ int refresh_index = 0;
+ int sizes_selection = 0;
+ int refresh_selection = 0;
+ char screen_option[32];
+ const char *screen;
+ LPTSTR t_screen;
+ TCHAR buf[16];
+ int res = 0, i;
+ DEVMODE devmode;
+
+ if (sizes_control && refresh_control)
+ {
+ // determine the resolution
+ option_value = opts->value(option_name);
+ if (sscanf(option_value, "%dx%d@%d", &width, &height, &refresh) != 3)
+ {
+ width = 0;
+ height = 0;
+ refresh = 0;
+ }
+
+ // reset sizes control
+ res = ComboBox_ResetContent(sizes_control);
+ res = ComboBox_InsertString(sizes_control, sizes_index, TEXT("Auto"));
+ res = ComboBox_SetItemData(sizes_control, sizes_index, 0);
+ sizes_index++;
+
+ // reset refresh control
+ res = ComboBox_ResetContent(refresh_control);
+ res = ComboBox_InsertString(refresh_control, refresh_index, TEXT("Auto"));
+ res = ComboBox_SetItemData(refresh_control, refresh_index, 0);
+ refresh_index++;
+
+ // determine which screen we're using
+ snprintf(screen_option, ARRAY_LENGTH(screen_option), "screen%d", GetSelectedScreen(dialog));
+ screen = opts->value(screen_option);
+ t_screen = ui_wstring_from_utf8(screen);
+
+ // retrieve screen information
+ devmode.dmSize = sizeof(devmode);
+ for (i = 0; EnumDisplaySettings(t_screen, i, &devmode); i++)
+ {
+ if ((devmode.dmBitsPerPel == 32 ) // Only 32 bit depth supported by core
+ &&(devmode.dmDisplayFrequency == refresh || refresh == 0))
+ {
+ _sntprintf(buf, ARRAY_LENGTH(buf), TEXT("%li x %li"),
+ devmode.dmPelsWidth, devmode.dmPelsHeight);
+
+ if (ComboBox_FindString(sizes_control, 0, buf) == CB_ERR)
+ {
+ res = ComboBox_InsertString(sizes_control, sizes_index, buf);
+
+ if ((width == devmode.dmPelsWidth) && (height == devmode.dmPelsHeight))
+ sizes_selection = sizes_index;
+ sizes_index++;
+
+ }
+ }
+ if (devmode.dmDisplayFrequency >= 10 )
+ {
+ // I have some devmode "vga" which specifes 1 Hz, which is probably bogus, so we filter it out
+
+ _sntprintf(buf, ARRAY_LENGTH(buf), TEXT("%li Hz"), devmode.dmDisplayFrequency);
+
+ if (ComboBox_FindString(refresh_control, 0, buf) == CB_ERR)
+ {
+ res = ComboBox_InsertString(refresh_control, refresh_index, buf);
+ res = ComboBox_SetItemData(refresh_control, refresh_index, devmode.dmDisplayFrequency);
+
+ if (refresh == devmode.dmDisplayFrequency)
+ refresh_selection = refresh_index;
+
+ refresh_index++;
+ }
+ }
+ }
+ free(t_screen);
+
+ res = ComboBox_SetCurSel(sizes_control, sizes_selection);
+ res = ComboBox_SetCurSel(refresh_control, refresh_selection);
+ }
+ res++;
+ return false;
+}
+
+
+/************************************************************
+ * DataMap initializers
+ ************************************************************/
+
+/* Initialize local helper variables */
+static void ResetDataMap(HWND hWnd)
+{
+ char screen_option[32];
+
+ snprintf(screen_option, ARRAY_LENGTH(screen_option), "screen%d", GetSelectedScreen(hWnd));
+
+ if (pCurrentOpts.value(screen_option) == NULL
+ || (core_stricmp(pCurrentOpts.value(screen_option), "") == 0 )
+ || (core_stricmp(pCurrentOpts.value(screen_option), "auto") == 0 ) )
+ {
+ pCurrentOpts.set_value(screen_option, "auto", OPTION_PRIORITY_CMDLINE);
+ }
+}
+
+
+/* Build the control mapping by adding all needed information to the DataMap */
+static void BuildDataMap(void)
+{
+ properties_datamap = datamap_create();
+
+ // core state options
+ datamap_add(properties_datamap, IDC_ENABLE_AUTOSAVE, DM_BOOL, OPTION_AUTOSAVE);
+ datamap_add(properties_datamap, IDC_SNAPVIEW, DM_STRING, OPTION_SNAPVIEW);
+ datamap_add(properties_datamap, IDC_SNAPSIZEWIDTH, DM_STRING, NULL);
+ datamap_add(properties_datamap, IDC_SNAPSIZEHEIGHT, DM_STRING, NULL);
+
+ // core performance options
+ datamap_add(properties_datamap, IDC_AUTOFRAMESKIP, DM_BOOL, OPTION_AUTOFRAMESKIP);
+ datamap_add(properties_datamap, IDC_FRAMESKIP, DM_INT, OPTION_FRAMESKIP);
+ datamap_add(properties_datamap, IDC_SECONDSTORUN, DM_INT, OPTION_SECONDS_TO_RUN);
+ datamap_add(properties_datamap, IDC_SECONDSTORUNDISP, DM_INT, OPTION_SECONDS_TO_RUN);
+ datamap_add(properties_datamap, IDC_THROTTLE, DM_BOOL, OPTION_THROTTLE);
+ datamap_add(properties_datamap, IDC_SLEEP, DM_BOOL, OPTION_SLEEP);
+ datamap_add(properties_datamap, IDC_SPEED, DM_FLOAT, OPTION_SPEED);
+ datamap_add(properties_datamap, IDC_SPEEDDISP, DM_FLOAT, OPTION_SPEED);
+ datamap_add(properties_datamap, IDC_REFRESHSPEED, DM_BOOL, OPTION_REFRESHSPEED);
+
+ // core retation options
+ datamap_add(properties_datamap, IDC_ROTATE, DM_INT, NULL);
+ // ror, rol, autoror, autorol handled by callback
+ datamap_add(properties_datamap, IDC_FLIPX, DM_BOOL, OPTION_FLIPX);
+ datamap_add(properties_datamap, IDC_FLIPY, DM_BOOL, OPTION_FLIPY);
+
+ // core artwork options
+ datamap_add(properties_datamap, IDC_ARTWORK_CROP, DM_BOOL, OPTION_ARTWORK_CROP);
+ datamap_add(properties_datamap, IDC_BACKDROPS, DM_BOOL, OPTION_USE_BACKDROPS);
+ datamap_add(properties_datamap, IDC_OVERLAYS, DM_BOOL, OPTION_USE_OVERLAYS);
+ datamap_add(properties_datamap, IDC_BEZELS, DM_BOOL, OPTION_USE_BEZELS);
+ datamap_add(properties_datamap, IDC_CPANELS, DM_BOOL, OPTION_USE_CPANELS);
+ datamap_add(properties_datamap, IDC_MARQUEES, DM_BOOL, OPTION_USE_MARQUEES);
+
+ // core screen options
+ datamap_add(properties_datamap, IDC_BRIGHTCORRECT, DM_FLOAT, OPTION_BRIGHTNESS);
+ datamap_add(properties_datamap, IDC_BRIGHTCORRECTDISP, DM_FLOAT, OPTION_BRIGHTNESS);
+ datamap_add(properties_datamap, IDC_CONTRAST, DM_FLOAT, OPTION_CONTRAST);
+ datamap_add(properties_datamap, IDC_CONTRASTDISP, DM_FLOAT, OPTION_CONTRAST);
+ datamap_add(properties_datamap, IDC_GAMMA, DM_FLOAT, OPTION_GAMMA);
+ datamap_add(properties_datamap, IDC_GAMMADISP, DM_FLOAT, OPTION_GAMMA);
+ datamap_add(properties_datamap, IDC_PAUSEBRIGHT, DM_FLOAT, OPTION_PAUSE_BRIGHTNESS);
+ datamap_add(properties_datamap, IDC_PAUSEBRIGHTDISP, DM_FLOAT, OPTION_PAUSE_BRIGHTNESS);
+ datamap_add(properties_datamap, IDC_BURNIN, DM_BOOL, OPTION_BURNIN);
+ datamap_add(properties_datamap, IDC_SNAPBILINEAR, DM_BOOL, OPTION_SNAPBILINEAR);
+
+ // core vector options
+ datamap_add(properties_datamap, IDC_BEAM_MIN, DM_FLOAT, OPTION_BEAM_WIDTH_MIN);
+ datamap_add(properties_datamap, IDC_BEAM_MINDISP, DM_FLOAT, OPTION_BEAM_WIDTH_MIN);
+ datamap_add(properties_datamap, IDC_BEAM_MAX, DM_FLOAT, OPTION_BEAM_WIDTH_MAX);
+ datamap_add(properties_datamap, IDC_BEAM_MAXDISP, DM_FLOAT, OPTION_BEAM_WIDTH_MAX);
+ datamap_add(properties_datamap, IDC_BEAM_INTEN, DM_FLOAT, OPTION_BEAM_INTENSITY_WEIGHT);
+ datamap_add(properties_datamap, IDC_BEAM_INTENDISP, DM_FLOAT, OPTION_BEAM_INTENSITY_WEIGHT);
+ datamap_add(properties_datamap, IDC_FLICKER, DM_FLOAT, OPTION_FLICKER);
+ datamap_add(properties_datamap, IDC_FLICKERDISP, DM_FLOAT, OPTION_FLICKER);
+
+ // core sound options
+ datamap_add(properties_datamap, IDC_SAMPLERATE, DM_INT, OPTION_SAMPLERATE);
+ datamap_add(properties_datamap, IDC_SAMPLES, DM_BOOL, OPTION_SAMPLES);
+ datamap_add(properties_datamap, IDC_SOUND_MODE, DM_STRING, OSDOPTION_SOUND);
+ datamap_add(properties_datamap, IDC_VOLUME, DM_INT, OPTION_VOLUME);
+ datamap_add(properties_datamap, IDC_VOLUMEDISP, DM_INT, OPTION_VOLUME);
+
+ // core input options
+ datamap_add(properties_datamap, IDC_COINLOCKOUT, DM_BOOL, OPTION_COIN_LOCKOUT);
+ datamap_add(properties_datamap, IDC_DEFAULT_INPUT, DM_STRING, OPTION_CTRLR);
+ datamap_add(properties_datamap, IDC_USE_MOUSE, DM_BOOL, OPTION_MOUSE);
+ datamap_add(properties_datamap, IDC_JOYSTICK, DM_BOOL, OPTION_JOYSTICK);
+ datamap_add(properties_datamap, IDC_LIGHTGUN, DM_BOOL, OPTION_LIGHTGUN);
+ datamap_add(properties_datamap, IDC_STEADYKEY, DM_BOOL, OPTION_STEADYKEY);
+ datamap_add(properties_datamap, IDC_MULTIKEYBOARD, DM_BOOL, OPTION_MULTIKEYBOARD);
+ datamap_add(properties_datamap, IDC_MULTIMOUSE, DM_BOOL, OPTION_MULTIMOUSE);
+ datamap_add(properties_datamap, IDC_RELOAD, DM_BOOL, OPTION_OFFSCREEN_RELOAD);
+
+ datamap_add(properties_datamap, IDC_JDZ, DM_FLOAT, OPTION_JOYSTICK_DEADZONE);
+ datamap_add(properties_datamap, IDC_JDZDISP, DM_FLOAT, OPTION_JOYSTICK_DEADZONE);
+ datamap_add(properties_datamap, IDC_JSAT, DM_FLOAT, OPTION_JOYSTICK_SATURATION);
+ datamap_add(properties_datamap, IDC_JSATDISP, DM_FLOAT, OPTION_JOYSTICK_SATURATION);
+ datamap_add(properties_datamap, IDC_JOYSTICKMAP, DM_STRING, OPTION_JOYSTICK_MAP);
+
+ // core input automatic enable options
+ datamap_add(properties_datamap, IDC_PADDLE, DM_STRING, OPTION_PADDLE_DEVICE);
+ datamap_add(properties_datamap, IDC_ADSTICK, DM_STRING, OPTION_ADSTICK_DEVICE);
+ datamap_add(properties_datamap, IDC_PEDAL, DM_STRING, OPTION_PEDAL_DEVICE);
+ datamap_add(properties_datamap, IDC_DIAL, DM_STRING, OPTION_DIAL_DEVICE);
+ datamap_add(properties_datamap, IDC_TRACKBALL, DM_STRING, OPTION_TRACKBALL_DEVICE);
+ datamap_add(properties_datamap, IDC_LIGHTGUNDEVICE, DM_STRING, OPTION_LIGHTGUN_DEVICE);
+ datamap_add(properties_datamap, IDC_POSITIONAL, DM_STRING, OPTION_POSITIONAL_DEVICE);
+ datamap_add(properties_datamap, IDC_MOUSE, DM_STRING, OPTION_MOUSE_DEVICE);
+
+ // core debugging options
+ datamap_add(properties_datamap, IDC_LOG, DM_BOOL, OPTION_LOG);
+ datamap_add(properties_datamap, IDC_DEBUG, DM_BOOL, OPTION_DEBUG);
+ datamap_add(properties_datamap, IDC_VERBOSE, DM_BOOL, OPTION_VERBOSE);
+ datamap_add(properties_datamap, IDC_UPDATEINPAUSE, DM_BOOL, OPTION_UPDATEINPAUSE);
+ datamap_add(properties_datamap, IDC_DEBUGSCRIPT, DM_STRING, OPTION_DEBUGSCRIPT);
+
+ // core misc options
+ datamap_add(properties_datamap, IDC_BIOS, DM_STRING, OPTION_BIOS);
+ datamap_add(properties_datamap, IDC_CHEAT, DM_BOOL, OPTION_CHEAT);
+ datamap_add(properties_datamap, IDC_SKIP_GAME_INFO, DM_BOOL, OPTION_SKIP_GAMEINFO);
+
+ datamap_add(properties_datamap, IDC_LANGUAGE, DM_STRING, OPTION_LANGUAGE);
+ datamap_add(properties_datamap, IDC_LUASCRIPT, DM_STRING, OPTION_AUTOBOOT_SCRIPT);
+ datamap_add(properties_datamap, IDC_BOOTDELAY, DM_INT, OPTION_AUTOBOOT_DELAY);
+ datamap_add(properties_datamap, IDC_BOOTDELAYDISP, DM_INT, OPTION_AUTOBOOT_DELAY);
+ datamap_add(properties_datamap, IDC_PLUGINS, DM_BOOL, OPTION_PLUGINS);
+ datamap_add(properties_datamap, IDC_PLUGIN, DM_STRING, OPTION_PLUGIN);
+ datamap_add(properties_datamap, IDC_NVRAM_SAVE, DM_BOOL, OPTION_NVRAM_SAVE);
+ datamap_add(properties_datamap, IDC_REWIND, DM_BOOL, OPTION_REWIND);
+
+ // windows debugging options
+ datamap_add(properties_datamap, IDC_OSLOG, DM_BOOL, OPTION_OSLOG);
+
+ // windows performance options
+ datamap_add(properties_datamap, IDC_HIGH_PRIORITY, DM_INT, WINOPTION_PRIORITY);
+ datamap_add(properties_datamap, IDC_HIGH_PRIORITYTXT, DM_INT, WINOPTION_PRIORITY);
+
+ // windows video options
+ datamap_add(properties_datamap, IDC_VIDEO_MODE, DM_STRING, OSDOPTION_VIDEO);
+ datamap_add(properties_datamap, IDC_NUMSCREENS, DM_INT, OSDOPTION_NUMSCREENS);
+ datamap_add(properties_datamap, IDC_NUMSCREENSDISP, DM_INT, OSDOPTION_NUMSCREENS);
+ datamap_add(properties_datamap, IDC_WINDOWED, DM_BOOL, OSDOPTION_WINDOW);
+ datamap_add(properties_datamap, IDC_MAXIMIZE, DM_BOOL, OSDOPTION_MAXIMIZE);
+ datamap_add(properties_datamap, IDC_KEEPASPECT, DM_BOOL, OPTION_KEEPASPECT);
+ datamap_add(properties_datamap, IDC_PRESCALE, DM_INT, OSDOPTION_PRESCALE);
+ datamap_add(properties_datamap, IDC_PRESCALEDISP, DM_INT, OSDOPTION_PRESCALE);
+ datamap_add(properties_datamap, IDC_EFFECT, DM_STRING, OPTION_EFFECT);
+ datamap_add(properties_datamap, IDC_WAITVSYNC, DM_BOOL, OSDOPTION_WAITVSYNC);
+ datamap_add(properties_datamap, IDC_SYNCREFRESH, DM_BOOL, OSDOPTION_SYNCREFRESH);
+
+ // Direct3D specific options
+#ifdef D3DVERSION
+ datamap_add(properties_datamap, IDC_D3D_VERSION, DM_INT, WINOPTION_D3DVERSION);
+#endif
+ datamap_add(properties_datamap, IDC_D3D_FILTER, DM_BOOL, OSDOPTION_FILTER);
+
+ // per window video options
+ datamap_add(properties_datamap, IDC_SCREEN, DM_STRING, NULL);
+ datamap_add(properties_datamap, IDC_SCREENSELECT, DM_STRING, NULL);
+ datamap_add(properties_datamap, IDC_VIEW, DM_STRING, NULL);
+ datamap_add(properties_datamap, IDC_ASPECTRATIOD, DM_STRING, NULL);
+ datamap_add(properties_datamap, IDC_ASPECTRATION, DM_STRING, NULL);
+ datamap_add(properties_datamap, IDC_REFRESH, DM_STRING, NULL);
+ datamap_add(properties_datamap, IDC_SIZES, DM_STRING, NULL);
+
+ // full screen options
+ datamap_add(properties_datamap, IDC_TRIPLE_BUFFER, DM_BOOL, WINOPTION_TRIPLEBUFFER);
+ datamap_add(properties_datamap, IDC_SWITCHRES, DM_BOOL, OSDOPTION_SWITCHRES);
+ datamap_add(properties_datamap, IDC_FSBRIGHTNESS, DM_FLOAT, WINOPTION_FULLSCREENBRIGHTNESS);
+ datamap_add(properties_datamap, IDC_FSBRIGHTNESSDISP, DM_FLOAT, WINOPTION_FULLSCREENBRIGHTNESS);
+ datamap_add(properties_datamap, IDC_FSCONTRAST, DM_FLOAT, WINOPTION_FULLSCREENCONTRAST);
+ datamap_add(properties_datamap, IDC_FSCONTRASTDISP, DM_FLOAT, WINOPTION_FULLSCREENCONTRAST);
+ datamap_add(properties_datamap, IDC_FSGAMMA, DM_FLOAT, WINOPTION_FULLSCREENGAMMA);
+ datamap_add(properties_datamap, IDC_FSGAMMADISP, DM_FLOAT, WINOPTION_FULLSCREENGAMMA);
+
+ // windows sound options
+ datamap_add(properties_datamap, IDC_AUDIO_LATENCY, DM_INT, OSDOPTION_AUDIO_LATENCY);
+ datamap_add(properties_datamap, IDC_AUDIO_LATENCY_DISP, DM_INT, OSDOPTION_AUDIO_LATENCY);
+
+ // input device options
+ datamap_add(properties_datamap, IDC_DUAL_LIGHTGUN, DM_BOOL, WINOPTION_DUAL_LIGHTGUN);
+
+ // show menu
+ datamap_add(properties_datamap, IDC_SHOW_MENU, DM_BOOL, WINOPTION_MENU);
+
+ // set up callbacks
+ datamap_set_callback(properties_datamap, IDC_ROTATE, DCT_READ_CONTROL, RotateReadControl);
+ datamap_set_callback(properties_datamap, IDC_ROTATE, DCT_POPULATE_CONTROL, RotatePopulateControl);
+ datamap_set_callback(properties_datamap, IDC_SCREEN, DCT_READ_CONTROL, ScreenReadControl);
+ datamap_set_callback(properties_datamap, IDC_SCREEN, DCT_POPULATE_CONTROL, ScreenPopulateControl);
+ datamap_set_callback(properties_datamap, IDC_VIEW, DCT_POPULATE_CONTROL, ViewPopulateControl);
+ datamap_set_callback(properties_datamap, IDC_REFRESH, DCT_READ_CONTROL, ResolutionReadControl);
+ datamap_set_callback(properties_datamap, IDC_REFRESH, DCT_POPULATE_CONTROL, ResolutionPopulateControl);
+ datamap_set_callback(properties_datamap, IDC_SIZES, DCT_READ_CONTROL, ResolutionReadControl);
+ datamap_set_callback(properties_datamap, IDC_SIZES, DCT_POPULATE_CONTROL, ResolutionPopulateControl);
+ datamap_set_callback(properties_datamap, IDC_DEFAULT_INPUT, DCT_READ_CONTROL, DefaultInputReadControl);
+ datamap_set_callback(properties_datamap, IDC_DEFAULT_INPUT, DCT_POPULATE_CONTROL, DefaultInputPopulateControl);
+ datamap_set_callback(properties_datamap, IDC_SNAPVIEW, DCT_POPULATE_CONTROL, SnapViewPopulateControl);
+
+ datamap_set_option_name_callback(properties_datamap, IDC_VIEW, ViewSetOptionName);
+ //missing population of views with per game defined additional views
+ datamap_set_option_name_callback(properties_datamap, IDC_REFRESH, ResolutionSetOptionName);
+ datamap_set_option_name_callback(properties_datamap, IDC_SIZES, ResolutionSetOptionName);
+
+
+ // formats
+ datamap_set_int_format(properties_datamap, IDC_VOLUMEDISP, "%ddB");
+ datamap_set_int_format(properties_datamap, IDC_AUDIO_LATENCY_DISP, "%d/5");
+ datamap_set_float_format(properties_datamap, IDC_BEAM_MINDISP, "%3.2f");
+ datamap_set_float_format(properties_datamap, IDC_BEAM_MAXDISP, "%3.2f");
+ datamap_set_float_format(properties_datamap, IDC_BEAM_INTENDISP, "%3.2f");
+ datamap_set_float_format(properties_datamap, IDC_FLICKERDISP, "%3.2f");
+ datamap_set_float_format(properties_datamap, IDC_GAMMADISP, "%03.2f");
+ datamap_set_float_format(properties_datamap, IDC_BRIGHTCORRECTDISP, "%03.2f");
+ datamap_set_float_format(properties_datamap, IDC_CONTRASTDISP, "%03.2f");
+ datamap_set_float_format(properties_datamap, IDC_PAUSEBRIGHTDISP, "%03.2f");
+ datamap_set_float_format(properties_datamap, IDC_FSGAMMADISP, "%03.2f");
+ datamap_set_float_format(properties_datamap, IDC_FSBRIGHTNESSDISP, "%03.2f");
+ datamap_set_float_format(properties_datamap, IDC_FSCONTRASTDISP, "%03.2f");
+ datamap_set_float_format(properties_datamap, IDC_JDZDISP, "%03.2f");
+ datamap_set_float_format(properties_datamap, IDC_JSATDISP, "%03.2f");
+ datamap_set_float_format(properties_datamap, IDC_SPEEDDISP, "%03.2f");
+
+ // trackbar ranges - slider-name,start,end,step
+ datamap_set_trackbar_range(properties_datamap, IDC_JDZ, 0.00, 1.00, (float)0.05);
+ datamap_set_trackbar_range(properties_datamap, IDC_JSAT, 0.00, 1.00, (float)0.05);
+ datamap_set_trackbar_range(properties_datamap, IDC_SPEED, 0.00, 3.00, (float)0.01);
+ datamap_set_trackbar_range(properties_datamap, IDC_BEAM_MIN, 0.00, 1.00, (float)0.01);
+ datamap_set_trackbar_range(properties_datamap, IDC_BEAM_MAX, 1.00, 10.00, (float)0.01);
+ datamap_set_trackbar_range(properties_datamap, IDC_BEAM_INTEN, -10.00, 10.00, (float)0.01);
+ datamap_set_trackbar_range(properties_datamap, IDC_FLICKER, 0.00, 1.00, (float)0.01);
+ datamap_set_trackbar_range(properties_datamap, IDC_AUDIO_LATENCY, 1, 5, 1);
+ datamap_set_trackbar_range(properties_datamap, IDC_VOLUME, -32, 0, 1);
+ datamap_set_trackbar_range(properties_datamap, IDC_SECONDSTORUN, 0, 60, 1);
+ datamap_set_trackbar_range(properties_datamap, IDC_NUMSCREENS, 1, 4, 1);
+ datamap_set_trackbar_range(properties_datamap, IDC_PRESCALE, 1, 3, 1);
+ datamap_set_trackbar_range(properties_datamap, IDC_FSGAMMA, 0.0, 3.0, (float)0.1);
+ datamap_set_trackbar_range(properties_datamap, IDC_FSBRIGHTNESS, 0.00, 2.0, (float)0.1);
+ datamap_set_trackbar_range(properties_datamap, IDC_FSCONTRAST, 0.0, 2.0, (float)0.1);
+ datamap_set_trackbar_range(properties_datamap, IDC_GAMMA, 0.0, 3.0, (float)0.1);
+ datamap_set_trackbar_range(properties_datamap, IDC_BRIGHTCORRECT, 0.00, 2.0, (float)0.1);
+ datamap_set_trackbar_range(properties_datamap, IDC_CONTRAST, 0.0, 2.0, (float)0.1);
+ datamap_set_trackbar_range(properties_datamap, IDC_PAUSEBRIGHT, 0.00, 1.00, (float)0.05);
+ datamap_set_trackbar_range(properties_datamap, IDC_BOOTDELAY, 0, 5, 1);
+
+#ifdef MESS
+ // MESS specific stuff
+ datamap_add(properties_datamap, IDC_DIR_LIST, DM_STRING, NULL);
+ datamap_add(properties_datamap, IDC_RAM_COMBOBOX, DM_INT, OPTION_RAMSIZE);
+
+ // set up callbacks
+ datamap_set_callback(properties_datamap, IDC_DIR_LIST, DCT_READ_CONTROL, DirListReadControl);
+ datamap_set_callback(properties_datamap, IDC_DIR_LIST, DCT_POPULATE_CONTROL, DirListPopulateControl);
+ datamap_set_callback(properties_datamap, IDC_RAM_COMBOBOX, DCT_POPULATE_CONTROL, RamPopulateControl);
+#endif
+}
+
+
+static void SetSamplesEnabled(HWND hWnd, int nIndex, BOOL bSoundEnabled)
+{
+ BOOL enabled = false;
+ HWND hCtrl = GetDlgItem(hWnd, IDC_SAMPLES);
+
+
+ if (hCtrl)
+ {
+ if ( nIndex > -1 )
+ {
+ machine_config config(driver_list::driver(nIndex),pCurrentOpts);
+
+ for (device_sound_interface &sound : sound_interface_iterator(config.root_device()))
+ if (sound.device().type() == SAMPLES)
+ enabled = true;
+ }
+ enabled = enabled && bSoundEnabled;
+ EnableWindow(hCtrl, enabled);
+ }
+}
+
+/* Moved here cause it's called in a few places */
+static void InitializeOptions(HWND hDlg)
+{
+// from FX
+// InitializeSampleRateUI(hDlg);
+ InitializeSoundUI(hDlg);
+// InitializeSoundModeUI(hDlg);
+ InitializeSkippingUI(hDlg);
+ InitializeRotateUI(hDlg);
+ InitializeSelectScreenUI(hDlg);
+ InitializeBIOSUI(hDlg);
+ InitializeControllerMappingUI(hDlg);
+ InitializeVideoUI(hDlg);
+// InitializeSnapViewUI(hDlg);
+// InitializeSnapNameUI(hDlg);
+ InitializeLanguageUI(hDlg);
+ InitializePluginsUI(hDlg);
+// InitializeGLSLFilterUI(hDlg);
+#ifdef D3DVERSION
+ InitializeD3DVersionUI(hDlg);
+#endif
+}
+
+/* Moved here because it is called in several places */
+static void InitializeMisc(HWND hDlg)
+{
+ Button_Enable(GetDlgItem(hDlg, IDC_JOYSTICK), DIJoystick.Available());
+}
+
+static void OptOnHScroll(HWND hwnd, HWND hwndCtl, UINT code, int pos)
+{
+ if (hwndCtl == GetDlgItem(hwnd, IDC_NUMSCREENS))
+ NumScreensSelectionChange(hwnd);
+}
+
+/* Handle changes to the Numscreens slider */
+static void NumScreensSelectionChange(HWND hwnd)
+{
+ //Also Update the ScreenSelect Combo with the new number of screens
+ UpdateSelectScreenUI(hwnd );
+}
+
+/* Handle changes to the Refresh drop down */
+static void RefreshSelectionChange(HWND hWnd, HWND hWndCtrl)
+{
+ int nCurSelection = ComboBox_GetCurSel(hWndCtrl);
+
+ if (nCurSelection != CB_ERR)
+ {
+ datamap_read_control(properties_datamap, hWnd, pCurrentOpts, IDC_SIZES);
+ datamap_populate_control(properties_datamap, hWnd, pCurrentOpts, IDC_SIZES);
+ }
+}
+
+/* Initialize the sound options */
+static void InitializeSoundUI(HWND hwnd)
+{
+ int res = 0, i;
+
+ HWND hCtrl = GetDlgItem(hwnd, IDC_SOUND_MODE);
+ if (hCtrl)
+ {
+ for (i = 0; i < NUMSOUND; i++)
+ {
+ res = ComboBox_InsertString(hCtrl, i, g_ComboBoxSound[i].m_pText);
+ res = ComboBox_SetItemData( hCtrl, i, g_ComboBoxSound[i].m_pData);
+ }
+ }
+
+ i = 0;
+
+ hCtrl = GetDlgItem(hwnd, IDC_SAMPLERATE);
+ if (hCtrl)
+ {
+ res = ComboBox_AddString(hCtrl, TEXT("11025"));
+ res = ComboBox_SetItemData(hCtrl, i++, 11025);
+ res = ComboBox_AddString(hCtrl, TEXT("22050"));
+ res = ComboBox_SetItemData(hCtrl, i++, 22050);
+ res = ComboBox_AddString(hCtrl, TEXT("44100"));
+ res = ComboBox_SetItemData(hCtrl, i++, 44100);
+ res = ComboBox_AddString(hCtrl, TEXT("48000"));
+ res = ComboBox_SetItemData(hCtrl, i++, 48000);
+ res = ComboBox_SetCurSel(hCtrl, 1);
+ }
+ res++;
+}
+
+/* Populate the Frame Skipping drop down */
+static void InitializeSkippingUI(HWND hwnd)
+{
+ HWND hCtrl = GetDlgItem(hwnd, IDC_FRAMESKIP);
+ int res = 0, i = 0;
+
+ if (hCtrl)
+ {
+ res = ComboBox_AddString(hCtrl, TEXT("Draw every frame"));
+ res = ComboBox_SetItemData(hCtrl, i++, 0);
+ res = ComboBox_AddString(hCtrl, TEXT("Skip 1 frame"));
+ res = ComboBox_SetItemData(hCtrl, i++, 1);
+ res = ComboBox_AddString(hCtrl, TEXT("Skip 2 frames"));
+ res = ComboBox_SetItemData(hCtrl, i++, 2);
+ res = ComboBox_AddString(hCtrl, TEXT("Skip 3 frames"));
+ res = ComboBox_SetItemData(hCtrl, i++, 3);
+ res = ComboBox_AddString(hCtrl, TEXT("Skip 4 frames"));
+ res = ComboBox_SetItemData(hCtrl, i++, 4);
+ res = ComboBox_AddString(hCtrl, TEXT("Skip 5 frames"));
+ res = ComboBox_SetItemData(hCtrl, i++, 5);
+ res = ComboBox_AddString(hCtrl, TEXT("Skip 6 frames"));
+ res = ComboBox_SetItemData(hCtrl, i++, 6);
+ res = ComboBox_AddString(hCtrl, TEXT("Skip 7 frames"));
+ res = ComboBox_SetItemData(hCtrl, i++, 7);
+ res = ComboBox_AddString(hCtrl, TEXT("Skip 8 frames"));
+ res = ComboBox_SetItemData(hCtrl, i++, 8);
+ res = ComboBox_AddString(hCtrl, TEXT("Skip 9 frames"));
+ res = ComboBox_SetItemData(hCtrl, i++, 9);
+ res = ComboBox_AddString(hCtrl, TEXT("Skip 10 frames"));
+ res = ComboBox_SetItemData(hCtrl, i++, 10);
+ }
+ res++;
+}
+
+/* Populate the Rotate drop down */
+static void InitializeRotateUI(HWND hwnd)
+{
+ HWND hCtrl = GetDlgItem(hwnd, IDC_ROTATE);
+ int res = 0;
+
+ if (hCtrl)
+ {
+ res = ComboBox_AddString(hCtrl, TEXT("Default")); // 0
+ res = ComboBox_AddString(hCtrl, TEXT("Clockwise")); // 1
+ res = ComboBox_AddString(hCtrl, TEXT("Anti-clockwise")); // 2
+ res = ComboBox_AddString(hCtrl, TEXT("None")); // 3
+ res = ComboBox_AddString(hCtrl, TEXT("Auto clockwise")); // 4
+ res = ComboBox_AddString(hCtrl, TEXT("Auto anti-clockwise")); // 5
+ }
+ res++;
+}
+
+/* Populate the Video Mode drop down */
+static void InitializeVideoUI(HWND hwnd)
+{
+ int res = 0;
+
+ HWND hCtrl = GetDlgItem(hwnd, IDC_VIDEO_MODE);
+ if (hCtrl)
+ {
+ for (int i = 0; i < NUMVIDEO; i++)
+ {
+ res = ComboBox_InsertString(hCtrl, i, g_ComboBoxVideo[i].m_pText);
+ res = ComboBox_SetItemData( hCtrl, i, g_ComboBoxVideo[i].m_pData);
+ }
+ }
+ res++;
+}
+
+#ifdef D3DVERSION
+/* Populate the D3D Version drop down */
+static void InitializeD3DVersionUI(HWND hwnd)
+{
+ HWND hCtrl = GetDlgItem(hwnd, IDC_D3D_VERSION);
+ int res = 0;
+ if (hCtrl)
+ {
+ for (int i = 0; i < NUMD3DVERSIONS; i++)
+ {
+ res = ComboBox_InsertString(hCtrl, i, g_ComboBoxD3DVersion[i].m_pText);
+ res = ComboBox_SetItemData( hCtrl, i, g_ComboBoxD3DVersion[i].m_pData);
+ }
+ }
+ res++;
+}
+#endif
+static void UpdateSelectScreenUI(HWND hwnd)
+{
+ int res = 0, i, curSel;
+ HWND hCtrl = GetDlgItem(hwnd, IDC_SCREENSELECT);
+ if (hCtrl)
+ {
+ curSel = ComboBox_GetCurSel(hCtrl);
+ if ((curSel < 0) || (curSel >= NUMSELECTSCREEN))
+ curSel = 0;
+ res = ComboBox_ResetContent(hCtrl);
+ for (i = 0; i < NUMSELECTSCREEN && i < pCurrentOpts.int_value(OSDOPTION_NUMSCREENS) ; i++)
+ {
+ res = ComboBox_InsertString(hCtrl, i, g_ComboBoxSelectScreen[i].m_pText);
+ res = ComboBox_SetItemData( hCtrl, i, g_ComboBoxSelectScreen[i].m_pData);
+ }
+ // Smaller Amount of screens was selected, so use 0
+ if( i < curSel )
+ res = ComboBox_SetCurSel(hCtrl, 0);
+ else
+ res = ComboBox_SetCurSel(hCtrl, curSel);
+ }
+ res++;
+}
+
+/* Populate the Select Screen drop down */
+static void InitializeSelectScreenUI(HWND hwnd)
+{
+ UpdateSelectScreenUI(hwnd);
+}
+
+static void InitializeControllerMappingUI(HWND hwnd)
+{
+ int res = 0;
+ HWND hCtrl = GetDlgItem(hwnd,IDC_PADDLE);
+ HWND hCtrl1 = GetDlgItem(hwnd,IDC_ADSTICK);
+ HWND hCtrl2 = GetDlgItem(hwnd,IDC_PEDAL);
+ HWND hCtrl3 = GetDlgItem(hwnd,IDC_MOUSE);
+ HWND hCtrl4 = GetDlgItem(hwnd,IDC_DIAL);
+ HWND hCtrl5 = GetDlgItem(hwnd,IDC_TRACKBALL);
+ HWND hCtrl6 = GetDlgItem(hwnd,IDC_LIGHTGUNDEVICE);
+ HWND hCtrl7 = GetDlgItem(hwnd,IDC_POSITIONAL);
+
+ for (int i = 0; i < NUMDEVICES; i++)
+ {
+ if (hCtrl)
+ {
+ res = ComboBox_InsertString(hCtrl, i, g_ComboBoxDevice[i].m_pText);
+ res = ComboBox_SetItemData( hCtrl, i, g_ComboBoxDevice[i].m_pData);
+ }
+
+ if (hCtrl1)
+ {
+ res = ComboBox_InsertString(hCtrl1, i, g_ComboBoxDevice[i].m_pText);
+ res = ComboBox_SetItemData( hCtrl1, i, g_ComboBoxDevice[i].m_pData);
+ }
+
+ if (hCtrl2)
+ {
+ res = ComboBox_InsertString(hCtrl2, i, g_ComboBoxDevice[i].m_pText);
+ res = ComboBox_SetItemData( hCtrl2, i, g_ComboBoxDevice[i].m_pData);
+ }
+
+ if (hCtrl3)
+ {
+ res = ComboBox_InsertString(hCtrl3, i, g_ComboBoxDevice[i].m_pText);
+ res = ComboBox_SetItemData( hCtrl3, i, g_ComboBoxDevice[i].m_pData);
+ }
+
+ if (hCtrl4)
+ {
+ res = ComboBox_InsertString(hCtrl4, i, g_ComboBoxDevice[i].m_pText);
+ res = ComboBox_SetItemData( hCtrl4, i, g_ComboBoxDevice[i].m_pData);
+ }
+
+ if (hCtrl5)
+ {
+ res = ComboBox_InsertString(hCtrl5, i, g_ComboBoxDevice[i].m_pText);
+ res = ComboBox_SetItemData( hCtrl5, i, g_ComboBoxDevice[i].m_pData);
+ }
+
+ if (hCtrl6)
+ {
+ res = ComboBox_InsertString(hCtrl6, i, g_ComboBoxDevice[i].m_pText);
+ res = ComboBox_SetItemData( hCtrl6, i, g_ComboBoxDevice[i].m_pData);
+ }
+
+ if (hCtrl7)
+ {
+ res = ComboBox_InsertString(hCtrl7, i, g_ComboBoxDevice[i].m_pText);
+ res = ComboBox_SetItemData( hCtrl7, i, g_ComboBoxDevice[i].m_pData);
+ }
+ }
+ res++;
+}
+
+
+static void InitializeBIOSUI(HWND hwnd)
+{
+ HWND hCtrl = GetDlgItem(hwnd,IDC_BIOS);
+ int res = 0, i = 0;
+ TCHAR* t_s;
+ if (hCtrl)
+ {
+ const game_driver *gamedrv = &driver_list::driver(g_nGame);
+ const rom_entry *rom;
+
+ if (g_nGame == GLOBAL_OPTIONS)
+ {
+ res = ComboBox_InsertString(hCtrl, i, TEXT("None"));
+ res = ComboBox_SetItemData( hCtrl, i++, "");
+ return;
+ }
+ if (g_nGame == LOCAL_OPTIONS) //Folder Options: This is the only place that LOCAL_OPTIONS is used, is this code ever executed?
+ {
+ gamedrv = &driver_list::driver(g_nFolderGame);
+ if (DriverHasOptionalBIOS(g_nFolderGame) == false)
+ {
+ res = ComboBox_InsertString(hCtrl, i, TEXT("None"));
+ res = ComboBox_SetItemData( hCtrl, i++, "");
+ return;
+ }
+ res = ComboBox_InsertString(hCtrl, i, TEXT("Default"));
+ res = ComboBox_SetItemData( hCtrl, i++, "");
+
+ if (gamedrv->rom)
+ {
+ auto rom_entries = rom_build_entries(gamedrv->rom);
+ for (rom = rom_entries.data(); !ROMENTRY_ISEND(rom); rom++)
+ {
+ if (ROMENTRY_ISSYSTEM_BIOS(rom))
+ {
+ const char *name = ROM_GETHASHDATA(rom);
+ const char *biosname = ROM_GETNAME(rom);
+ t_s = ui_wstring_from_utf8(name);
+ if( !t_s )
+ return;
+ res = ComboBox_InsertString(hCtrl, i, win_tstring_strdup(t_s));
+ res = ComboBox_SetItemData( hCtrl, i++, biosname);
+ free(t_s);
+ }
+ }
+ }
+ return;
+ }
+
+ if (DriverHasOptionalBIOS(g_nGame) == false)
+ {
+ res = ComboBox_InsertString(hCtrl, i, TEXT("None"));
+ res = ComboBox_SetItemData( hCtrl, i++, "");
+ return;
+ }
+ res = ComboBox_InsertString(hCtrl, i, TEXT("Default"));
+ res = ComboBox_SetItemData( hCtrl, i++, "");
+
+ if (gamedrv->rom)
+ {
+ auto rom_entries = rom_build_entries(gamedrv->rom);
+ for (rom = rom_entries.data(); !ROMENTRY_ISEND(rom); rom++)
+ {
+ if (ROMENTRY_ISSYSTEM_BIOS(rom))
+ {
+ const char *name = ROM_GETHASHDATA(rom);
+ const char *biosname = ROM_GETNAME(rom);
+ t_s = ui_wstring_from_utf8(name);
+ if( !t_s )
+ return;
+ res = ComboBox_InsertString(hCtrl, i, win_tstring_strdup(t_s));
+ res = ComboBox_SetItemData( hCtrl, i++, biosname);
+ free(t_s);
+ }
+ }
+ }
+ }
+ res++;
+}
+
+static void InitializeLanguageUI(HWND hWnd)
+{
+ HWND hCtrl = GetDlgItem(hWnd, IDC_LANGUAGE);
+
+ if (hCtrl)
+ {
+ int count = 0;
+ string t1 = GetLangDir();
+ const char* t2 = t1.c_str();
+ osd::directory::ptr directory = osd::directory::open(t2);
+
+ if (directory == nullptr)
+ return;
+
+ for (const osd::directory::entry *entry = directory->read(); entry; entry = directory->read())
+ {
+ if (entry->type == osd::directory::entry::entry_type::DIR)
+ {
+ string name = entry->name;
+
+ if (!(name == "." || name == ".."))
+ {
+ char *value = strdup(entry->name);
+ wchar_t *text = ui_wstring_from_utf8(entry->name);
+ (void)ComboBox_InsertString(hCtrl, count, text);
+ (void)ComboBox_SetItemData(hCtrl, count, value);
+ count++;
+ free(text);
+ free(value);
+ }
+ }
+ }
+
+ directory.reset();
+ }
+}
+
+static void InitializePluginsUI(HWND hWnd)
+{
+ HWND hCtrl = GetDlgItem(hWnd, IDC_SELECT_PLUGIN);
+
+ if (hCtrl)
+ {
+ string t1 = GetPluginsDir();
+ const char* t2 = t1.c_str();
+ osd::directory::ptr directory = osd::directory::open(t2);
+
+ if (directory == nullptr)
+ return;
+
+ TCHAR* t_s;
+ int count = 0;
+
+ for (const osd::directory::entry *entry = directory->read(); entry; entry = directory->read())
+ {
+ if (entry->type == osd::directory::entry::entry_type::DIR)
+ {
+ string name = entry->name;
+
+ if (!(name == "." || name == ".." || name == "json"))
+ {
+ plugin_names[count] = name;
+ const char* label = name.c_str();
+ t_s = ui_wstring_from_utf8(label);
+ label = 0;
+ if( !t_s )
+ return;
+ if (ComboBox_InsertString(hCtrl, count++, win_tstring_strdup(t_s)) == CB_ERR)
+ return;
+ free(t_s);
+ }
+ }
+ }
+ directory.reset();
+ }
+
+ (void)ComboBox_SetCurSel(hCtrl, -1);
+ (void)ComboBox_SetCueBannerText(hCtrl, TEXT("Select a plugin"));
+}
+#if 0
+static void InitializeGLSLFilterUI(HWND hWnd)
+{
+ HWND hCtrl = GetDlgItem(hWnd, IDC_GLSLFILTER);
+
+ if (hCtrl)
+ {
+ for (int i = 0; i < NUMGLSLFILTER; i++)
+ {
+ (void)ComboBox_InsertString(hCtrl, i, g_ComboBoxGLSLFilter[i].m_pText);
+ (void)ComboBox_SetItemData(hCtrl, i, g_ComboBoxGLSLFilter[i].m_pData);
+ }
+ }
+}
+#endif
+static BOOL SelectEffect(HWND hWnd)
+{
+ char filename[MAX_PATH];
+ BOOL changed = false;
+
+ *filename = 0;
+ if (CommonFileDialog(GetOpenFileName, filename, FILETYPE_EFFECT_FILES))
+ {
+ //strip Path and extension
+ char buff[MAX_PATH];
+ int i, j = 0, k = 0, l = 0;
+ for(i=0; i<strlen(filename); i++ )
+ {
+ if( filename[i] == '\\' )
+ j = i;
+ if( filename[i] == '.' )
+ k = i;
+ }
+ for(i=j+1; i<k; i++)
+ buff[l++] = filename[i];
+
+ buff[l] = '\0';
+
+ if (strcmp(buff, pCurrentOpts.value(OPTION_EFFECT))!=0)
+ {
+ HWND control = GetDlgItem(hWnd, IDC_EFFECT);
+ pCurrentOpts.set_value(OPTION_EFFECT, buff, OPTION_PRIORITY_CMDLINE);
+ win_set_window_text_utf8(control, buff);
+ // datamap_populate_control(properties_datamap, hWnd, pCurrentOpts, IDC_EFFECT);
+ changed = true;
+ }
+ }
+ return changed;
+}
+
+static BOOL ResetEffect(HWND hWnd)
+{
+ BOOL changed = false;
+ const char *new_value = "none";
+
+ if (strcmp(new_value, pCurrentOpts.value(OPTION_EFFECT))!=0)
+ {
+ HWND control = GetDlgItem(hWnd, IDC_EFFECT);
+ pCurrentOpts.set_value(OPTION_EFFECT, new_value, OPTION_PRIORITY_CMDLINE);
+ win_set_window_text_utf8(control, new_value);
+ // datamap_populate_control(properties_datamap, hWnd, pCurrentOpts, IDC_EFFECT);
+ changed = true;
+ }
+ return changed;
+}
+
+static BOOL SelectJoystickMap(HWND hWnd)
+{
+ char filename[MAX_PATH];
+ BOOL changed = false;
+
+ *filename = 0;
+ if (CommonFileDialog(GetOpenFileName, filename, FILETYPE_JOYMAP_FILES))
+ {
+ if (strcmp(filename, pCurrentOpts.value(OPTION_JOYSTICK_MAP))!=0)
+ {
+ HWND control = GetDlgItem(hWnd, IDC_JOYSTICKMAP);
+ pCurrentOpts.set_value(OPTION_JOYSTICK_MAP, filename, OPTION_PRIORITY_CMDLINE);
+ win_set_window_text_utf8(control, filename);
+ changed = true;
+ }
+ }
+ return changed;
+}
+
+static BOOL ResetJoystickMap(HWND hWnd)
+{
+ BOOL changed = false;
+ const char *new_value = "auto";
+
+ if (strcmp(new_value, pCurrentOpts.value(OPTION_JOYSTICK_MAP))!=0)
+ {
+ HWND control = GetDlgItem(hWnd, IDC_JOYSTICKMAP);
+ pCurrentOpts.set_value(OPTION_JOYSTICK_MAP, new_value, OPTION_PRIORITY_CMDLINE);
+ win_set_window_text_utf8(control, new_value);
+ changed = true;
+ }
+ return changed;
+}
+
+static bool SelectLUAScript(HWND hWnd)
+{
+ char filename[MAX_PATH];
+ bool changed = false;
+
+ *filename = 0;
+
+ if (CommonFileDialog(GetOpenFileName, filename, FILETYPE_LUASCRIPT_FILES))
+ {
+ char option[MAX_PATH];
+ char script[MAX_PATH];
+ wchar_t *t_filename = ui_wstring_from_utf8(filename);
+ wchar_t *tempname = PathFindFileName(t_filename);
+ char *optvalue = ui_utf8_from_wstring(tempname);
+ strcpy(script, optvalue);
+ PathRemoveExtension(tempname);
+ char *optname = ui_utf8_from_wstring(tempname);
+ strcpy(option, optname);
+ free(t_filename);
+ free(optname);
+ free(optvalue);
+
+ if (strcmp(script, pCurrentOpts.value(OPTION_AUTOBOOT_SCRIPT)))
+ {
+ pCurrentOpts.set_value(OPTION_AUTOBOOT_SCRIPT, script, OPTION_PRIORITY_CMDLINE);
+ win_set_window_text_utf8(GetDlgItem(hWnd, IDC_LUASCRIPT), option);
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+
+static bool ResetLUAScript(HWND hWnd)
+{
+ bool changed = false;
+ const char *new_value = "";
+
+ if (strcmp(new_value, pCurrentOpts.value(OPTION_AUTOBOOT_SCRIPT)))
+ {
+ pCurrentOpts.set_value(OPTION_AUTOBOOT_SCRIPT, new_value, OPTION_PRIORITY_CMDLINE);
+ win_set_window_text_utf8(GetDlgItem(hWnd, IDC_LUASCRIPT), "None");
+ changed = true;
+ }
+
+ return changed;
+}
+
+static bool SelectPlugins(HWND hWnd)
+{
+ bool changed = false;
+ bool already_enabled = false;
+ HWND hcontrol = GetDlgItem(hWnd, IDC_SELECT_PLUGIN);
+ if (!hcontrol)
+ return changed;
+
+ int index = ComboBox_GetCurSel(hcontrol);
+ if (index == CB_ERR)
+ return changed;
+
+ const char *new_value = plugin_names[index].c_str();
+ string t1 = GetPlugins();
+ const char* value = t1.c_str();
+
+ char *token = NULL;
+ char buffer[990]; // hold all plugins
+ char plugins[24][32]; // number of possible plugins, max length of name
+ int num_plugins = 0;
+
+ strcpy(buffer, value);
+ token = strtok(buffer, ",");
+
+ if (token == NULL)
+ {
+ strcpy(plugins[num_plugins], buffer);
+ }
+ else
+ {
+ while (token != NULL)
+ {
+ strcpy(plugins[num_plugins], token);
+ num_plugins++;
+ token = strtok(NULL, ",");
+ }
+ }
+
+ if (strcmp(value, "") == 0)
+ {
+ pCurrentOpts.set_value(OPTION_PLUGIN, new_value, OPTION_PRIORITY_CMDLINE);
+ win_set_window_text_utf8(GetDlgItem(hWnd, IDC_PLUGIN), new_value);
+ changed = true;
+ (void)ComboBox_SetCurSel(GetDlgItem(hWnd, IDC_SELECT_PLUGIN), -1);
+ return changed;
+ }
+
+ for (int i = 0; i < num_plugins; i++)
+ {
+ if (strcmp(new_value, plugins[i]) == 0)
+ {
+ already_enabled = true;
+ break;
+ }
+ }
+
+ if (!already_enabled)
+ {
+ char new_option[256];
+ snprintf(new_option, WINUI_ARRAY_LENGTH(new_option), "%s,%s", value, new_value);
+ pCurrentOpts.set_value(OPTION_PLUGIN, new_option, OPTION_PRIORITY_CMDLINE);
+ win_set_window_text_utf8(GetDlgItem(hWnd, IDC_PLUGIN), new_option);
+ changed = true;
+ }
+
+ (void)ComboBox_SetCurSel(GetDlgItem(hWnd, IDC_SELECT_PLUGIN), -1);
+ return changed;
+}
+
+static bool ResetPlugins(HWND hWnd)
+{
+ bool changed = false;
+ pCurrentOpts.set_value(OPTION_PLUGIN, "", OPTION_PRIORITY_CMDLINE);
+ win_set_window_text_utf8(GetDlgItem(hWnd, IDC_PLUGIN), "None");
+ changed = true;
+ (void)ComboBox_SetCurSel(GetDlgItem(hWnd, IDC_SELECT_PLUGIN), -1);
+ return changed;
+}
+
+static BOOL SelectDebugscript(HWND hWnd)
+{
+ char filename[MAX_PATH];
+ BOOL changed = false;
+
+ *filename = 0;
+ if (CommonFileDialog(GetOpenFileName, filename, FILETYPE_DEBUGSCRIPT_FILES))
+ {
+ if (strcmp(filename, pCurrentOpts.value(OPTION_DEBUGSCRIPT))!=0)
+ {
+ HWND control = GetDlgItem(hWnd, IDC_DEBUGSCRIPT);
+ pCurrentOpts.set_value(OPTION_DEBUGSCRIPT, filename, OPTION_PRIORITY_CMDLINE);
+ win_set_window_text_utf8(control, filename);
+ changed = true;
+ }
+ }
+ return changed;
+}
+
+static BOOL ResetDebugscript(HWND hWnd)
+{
+ BOOL changed = false;
+ const char *new_value = "";
+
+ if (strcmp(new_value, pCurrentOpts.value(OPTION_DEBUGSCRIPT))!=0)
+ {
+ HWND control = GetDlgItem(hWnd, IDC_DEBUGSCRIPT);
+ pCurrentOpts.set_value(OPTION_DEBUGSCRIPT, new_value, OPTION_PRIORITY_CMDLINE);
+ win_set_window_text_utf8(control, new_value);
+ changed = true;
+ }
+ return changed;
+}
+
+void UpdateBackgroundBrush(HWND hwndTab)
+{
+ // Destroy old brush
+ if (hBkBrush)
+ DeleteBrush(hBkBrush);
+
+ hBkBrush = NULL;
+
+ // Only do this if the theme is active
+ if (SafeIsAppThemed())
+ {
+ // Get tab control dimensions
+ RECT rc;
+ GetWindowRect( hwndTab, &rc);
+
+ // Get the tab control DC
+ HDC hDC = GetDC(hwndTab);
+
+ // Create a compatible DC
+ HDC hDCMem = CreateCompatibleDC(hDC);
+ HBITMAP hBmp = CreateCompatibleBitmap(hDC, rc.right - rc.left, rc.bottom - rc.top);
+ HBITMAP hBmpOld = (HBITMAP)(SelectObject(hDCMem, hBmp));
+
+ // Tell the tab control to paint in our DC
+ SendMessage(hwndTab, WM_PRINTCLIENT, (WPARAM)(hDCMem), (LPARAM)(PRF_ERASEBKGND | PRF_CLIENT | PRF_NONCLIENT));
+
+ // Create a pattern brush from the bitmap selected in our DC
+ hBkBrush = CreatePatternBrush(hBmp);
+
+ // Restore the bitmap
+ SelectObject(hDCMem, hBmpOld);
+
+ // Cleanup
+ DeleteBitmap(hBmp);
+ DeleteDC(hDCMem);
+ ReleaseDC(hwndTab, hDC);
+ }
+}
+
+
+// from propertiesms.cpp (MESSUI)
+
+
+//============================================================
+#ifdef MESS
+//============================================================
+// DATAMAP HANDLERS FOR MESS
+//============================================================
+
+static void AppendList(HWND hList, LPCTSTR lpItem, int nItem)
+{
+ LV_ITEM Item;
+ memset(&Item, 0, sizeof(LV_ITEM));
+ Item.mask = LVIF_TEXT;
+ Item.pszText = (LPTSTR) lpItem;
+ Item.iItem = nItem;
+ HRESULT res = ListView_InsertItem(hList, &Item);
+ res++;
+}
+
+static BOOL DirListReadControl(datamap *map, HWND dialog, HWND control, windows_options *opts, const char *option_name)
+{
+ int directory_count;
+ LV_ITEM lvi;
+ TCHAR buffer[2048];
+ int pos = 0;
+ BOOL res;
+
+ // determine the directory count; note that one item is the "< >" entry
+ directory_count = ListView_GetItemCount(control);
+ if (directory_count > 0)
+ directory_count--;
+
+ buffer[0] = '\0';
+
+ for (int i = 0; i < directory_count; i++)
+ {
+ // append a semicolon, if we're past the first entry
+ if (i > 0)
+ pos += _sntprintf(&buffer[pos], ARRAY_LENGTH(buffer) - pos, TEXT(";"));
+
+ // retrieve the next entry
+ memset(&lvi, '\0', sizeof(lvi));
+ lvi.mask = LVIF_TEXT;
+ lvi.iItem = i;
+ lvi.pszText = &buffer[pos];
+ lvi.cchTextMax = ARRAY_LENGTH(buffer) - pos;
+ res = ListView_GetItem(control, &lvi);
+
+ // advance the position
+ pos += _tcslen(&buffer[pos]);
+ }
+
+ char* paths = ui_utf8_from_wstring(buffer);
+ if ((buffer[1] == 0x3A) || (buffer[0] == 0)) // must be a folder or null
+ pCurrentOpts.set_value(OPTION_SWPATH, paths, OPTION_PRIORITY_CMDLINE);
+
+ free (paths);
+ res++;
+ return true;
+}
+
+
+static BOOL DirListPopulateControl(datamap *map, HWND dialog, HWND control, windows_options *opts, const char *option_name)
+{
+ int new_pos = 0;
+
+ // access the directory list, and convert to TCHARs
+ int driver_index = PropertiesCurrentGame(dialog);
+ windows_options o;
+ load_options(o, OPTIONS_GAME, driver_index, 0);
+ const char* paths = o.value(OPTION_SWPATH);
+ TCHAR* t_dir_list = ui_wstring_from_utf8(paths);
+ paths = 0;
+ if (!t_dir_list)
+ return false;
+
+ // delete all items in the list control
+ BOOL b_res = ListView_DeleteAllItems(control);
+
+ // add the column
+ RECT r;
+ GetClientRect(control, &r);
+ LV_COLUMN lvc;
+ memset(&lvc, 0, sizeof(LVCOLUMN));
+ lvc.mask = LVCF_WIDTH;
+ lvc.cx = r.right - r.left - GetSystemMetrics(SM_CXHSCROLL);
+ HRESULT res = ListView_InsertColumn(control, 0, &lvc);
+
+ // add each of the directories
+ int pos = 0;
+ int current_item = 0;
+ while(t_dir_list[pos] != '\0')
+ {
+ // parse off this item
+ TCHAR *s = _tcschr(&t_dir_list[pos], ';');
+ if (s)
+ {
+ *s = '\0';
+ new_pos = s - t_dir_list + 1;
+ }
+ else
+ new_pos = pos + _tcslen(&t_dir_list[pos]);
+
+ // append this item
+ AppendList(control, &t_dir_list[pos], current_item);
+
+ // advance to next item
+ pos = new_pos;
+ current_item++;
+ }
+
+ // finish up
+ AppendList(control, TEXT(DIRLIST_NEWENTRYTEXT), current_item);
+ ListView_SetItemState(control, 0, LVIS_SELECTED, LVIS_SELECTED);
+ free(t_dir_list);
+ res++;
+ b_res++;
+ return true;
+}
+
+
+
+static const char *messram_string(char *buffer, UINT32 ram)
+{
+ const char *suffix;
+
+ if ((ram % (1024*1024)) == 0)
+ {
+ ram /= 1024*1024;
+ suffix = "MB";
+ }
+ else if ((ram % 1024) == 0)
+ {
+ ram /= 1024;
+ suffix = "KB";
+ }
+ else
+ suffix = "";
+
+ sprintf(buffer, "%u%s", ram, suffix);
+ return buffer;
+}
+
+//-------------------------------------------------
+// parse_string - convert a ram string to an
+// integer value
+//-------------------------------------------------
+
+static uint32_t parse_string(const char *s)
+{
+ static const struct
+ {
+ const char *suffix;
+ unsigned multiple;
+ } s_suffixes[] =
+ {
+ { "", 1 },
+ { "k", 1024 },
+ { "kb", 1024 },
+ { "kib", 1024 },
+ { "m", 1024 * 1024 },
+ { "mb", 1024 * 1024 },
+ { "mib", 1024 * 1024 }
+ };
+
+ // parse the string
+ unsigned ram = 0;
+ char suffix[8] = { 0, };
+ sscanf(s, "%u%7s", &ram, suffix);
+
+ // perform the lookup
+ auto iter = std::find_if(std::begin(s_suffixes), std::end(s_suffixes), [&suffix](const auto &potential_suffix)
+ { return !core_stricmp(suffix, potential_suffix.suffix); } );
+
+ // identify the multiplier (or 0 if not recognized, signalling a parse failure)
+ unsigned multiple = iter != std::end(s_suffixes) ? iter->multiple : 0;
+
+ // return the result
+ return ram * multiple;
+}
+
+static BOOL RamPopulateControl(datamap *map, HWND dialog, HWND control, windows_options *opts, const char *option_name)
+{
+ int i = 0, current_index = 0;
+
+ // identify the driver
+ int driver_index = PropertiesCurrentGame(dialog);
+ const game_driver *gamedrv = &driver_list::driver(driver_index);
+
+ // clear out the combo box
+ int res = ComboBox_ResetContent(control);
+
+ // allocate the machine config
+ machine_config cfg(*gamedrv,*opts);
+
+ // identify how many options that we have
+ ram_device_iterator iter(cfg.root_device());
+ ram_device *device = iter.first();
+
+ EnableWindow(control, (device != NULL));
+
+ // we can only do something meaningful if there is more than one option
+ if (device)
+ {
+ const ram_device *ramdev = dynamic_cast<const ram_device *>(device);
+
+ // identify the current amount of RAM
+ const char *this_ram_string = opts->value(OPTION_RAMSIZE);
+ uint32_t current_ram = (this_ram_string) ? parse_string(this_ram_string) : 0;
+ uint32_t ram = ramdev->default_size();
+ if (current_ram == 0)
+ current_ram = ram;
+
+ char ramtext[20];
+ messram_string(ramtext, ram);
+ TCHAR *t_ramstring = ui_wstring_from_utf8(ramtext);
+ if( !t_ramstring )
+ return false;
+
+ res = ComboBox_InsertString(control, i, win_tstring_strdup(t_ramstring));
+ res = ComboBox_SetItemData(control, i, ram);
+
+ if (!ramdev->extra_options().empty())
+ {
+ /* try to parse each option */
+ for (ram_device::extra_option const &option : ramdev->extra_options())
+ {
+ // identify this option
+ t_ramstring = ui_wstring_from_utf8(option.first.c_str());
+ if( t_ramstring )
+ {
+ i++;
+ // add this option to the combo box
+ res = ComboBox_InsertString(control, i, win_tstring_strdup(t_ramstring));
+ res = ComboBox_SetItemData(control, i, option.second);
+
+ // is this the current option? record the index if so
+ if (option.second == current_ram)
+ current_index = i;
+ }
+ }
+ }
+ if (t_ramstring)
+ free (t_ramstring);
+ // set the combo box
+ res = ComboBox_SetCurSel(control, current_index);
+ }
+ res++;
+ return true;
+}
+
+
+static void MarkChanged(HWND hDlg)
+{
+ /* fake a CBN_SELCHANGE event from IDC_SIZES to force it to be changed */
+ HWND hCtrl = GetDlgItem(hDlg, IDC_SIZES);
+ PostMessage(hDlg, WM_COMMAND, (CBN_SELCHANGE << 16) | IDC_SIZES, (LPARAM) hCtrl);
+}
+
+
+static BOOL SoftwareDirectories_OnInsertBrowse(HWND hDlg, BOOL bBrowse, LPCTSTR lpItem)
+{
+ TCHAR inbuf[MAX_PATH];
+ TCHAR outbuf[MAX_PATH];
+ LPTSTR lpIn;
+ BOOL res = false;
+
+ g_bModifiedSoftwarePaths = true;
+
+ HWND hList = GetDlgItem(hDlg, IDC_DIR_LIST);
+ int nItem = ListView_GetNextItem(hList, -1, LVNI_SELECTED);
+
+ if (nItem == -1)
+ return false;
+
+ /* Last item is placeholder for append */
+ if (nItem == ListView_GetItemCount(hList) - 1)
+ bBrowse = false;
+
+ if (!lpItem)
+ {
+ if (bBrowse)
+ {
+ ListView_GetItemText(hList, nItem, 0, inbuf, ARRAY_LENGTH(inbuf));
+ lpIn = inbuf;
+ }
+ else
+ lpIn = NULL;
+
+ if (!BrowseForDirectory(hDlg, lpIn, outbuf))
+ return false;
+
+ lpItem = outbuf;
+ }
+
+ AppendList(hList, lpItem, nItem);
+ if (bBrowse)
+ res = ListView_DeleteItem(hList, nItem+1);
+ MarkChanged(hDlg);
+ res++;
+ return true;
+}
+
+
+
+static BOOL SoftwareDirectories_OnDelete(HWND hDlg)
+{
+ int nSelect = 0;
+ HWND hList = GetDlgItem(hDlg, IDC_DIR_LIST);
+
+ g_bModifiedSoftwarePaths = true;
+
+ int nItem = ListView_GetNextItem(hList, -1, LVNI_SELECTED | LVNI_ALL);
+
+ if (nItem == -1)
+ return false;
+
+ /* Don't delete "Append" placeholder. */
+ if (nItem == ListView_GetItemCount(hList) - 1)
+ return false;
+
+ BOOL res = ListView_DeleteItem(hList, nItem);
+
+ int nCount = ListView_GetItemCount(hList);
+ if (nCount <= 1)
+ return false;
+
+ /* If the last item was removed, select the item above. */
+ if (nItem == nCount - 1)
+ nSelect = nCount - 2;
+ else
+ nSelect = nItem;
+
+ ListView_SetItemState(hList, nSelect, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
+ MarkChanged(hDlg);
+ res++;
+ return true;
+}
+
+
+
+static BOOL SoftwareDirectories_OnBeginLabelEdit(HWND hDlg, NMHDR* pNMHDR)
+{
+ BOOL bResult = false;
+ NMLVDISPINFO* pDispInfo = (NMLVDISPINFO*)pNMHDR;
+ LVITEM* pItem = &pDispInfo->item;
+ HWND hList = GetDlgItem(hDlg, IDC_DIR_LIST);
+
+ /* Last item is placeholder for append */
+ if (pItem->iItem == ListView_GetItemCount(hList) - 1)
+ {
+ HWND hEdit = (HWND) (uintptr_t) SendMessage(hList, LVM_GETEDITCONTROL, 0, 0);
+ win_set_window_text_utf8(hEdit, "");
+ }
+
+ return bResult;
+}
+
+
+
+static BOOL SoftwareDirectories_OnEndLabelEdit(HWND hDlg, NMHDR* pNMHDR)
+{
+ BOOL bResult = false;
+ NMLVDISPINFO* pDispInfo = (NMLVDISPINFO*)pNMHDR;
+ LVITEM* pItem = &pDispInfo->item;
+
+ if (pItem->pszText)
+ {
+ struct _stat file_stat;
+
+ /* Don't allow empty entries. */
+ if (!_tcscmp(pItem->pszText, TEXT("")))
+ return false;
+
+ /* Check validity of edited directory. */
+ if ((_tstat(pItem->pszText, &file_stat) == 0) && (file_stat.st_mode & S_IFDIR))
+ bResult = true;
+ else
+ if (win_message_box_utf8(NULL, "Folder does not exist, continue anyway?", MAMEUINAME, MB_OKCANCEL) == IDOK)
+ bResult = true;
+ }
+
+ if (bResult == true)
+ SoftwareDirectories_OnInsertBrowse(hDlg, true, pItem->pszText);
+
+ return bResult;
+}
+
+
+static BOOL DriverHasDevice(const game_driver *gamedrv, iodevice_t type)
+{
+ BOOL b = false;
+
+ // allocate the machine config
+ machine_config config(*gamedrv,MameUIGlobal());
+
+ for (device_image_interface &dev : image_interface_iterator(config.root_device()))
+ {
+ if (!dev.user_loadable())
+ continue;
+ if (dev.image_type() == type)
+ {
+ b = true;
+ break;
+ }
+ }
+ return b;
+}
+
+BOOL PropSheetFilter_Config(const machine_config *drv, const game_driver *gamedrv)
+{
+ ram_device_iterator iter(drv->root_device());
+ return (iter.first()) || DriverHasDevice(gamedrv, IO_PRINTER);
+}
+
+INT_PTR CALLBACK GameMessOptionsProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+ INT_PTR rc = 0;
+ BOOL bHandled = false;
+
+ switch (Msg)
+ {
+ case WM_NOTIFY:
+ switch (((NMHDR *) lParam)->code)
+ {
+ case LVN_ENDLABELEDIT:
+ rc = SoftwareDirectories_OnEndLabelEdit(hDlg, (NMHDR *) lParam);
+ bHandled = true;
+ break;
+
+ case LVN_BEGINLABELEDIT:
+ rc = SoftwareDirectories_OnBeginLabelEdit(hDlg, (NMHDR *) lParam);
+ bHandled = true;
+ break;
+ }
+ }
+
+ if (!bHandled)
+ rc = GameOptionsProc(hDlg, Msg, wParam, lParam);
+
+ return rc;
+}
+
+
+
+BOOL MessPropertiesCommand(HWND hWnd, WORD wNotifyCode, WORD wID, BOOL *changed)
+{
+ BOOL handled = true;
+
+ switch(wID)
+ {
+ case IDC_DIR_BROWSE:
+ if (wNotifyCode == BN_CLICKED)
+ *changed = SoftwareDirectories_OnInsertBrowse(hWnd, true, NULL);
+ break;
+
+ case IDC_DIR_INSERT:
+ if (wNotifyCode == BN_CLICKED)
+ *changed = SoftwareDirectories_OnInsertBrowse(hWnd, false, NULL);
+ break;
+
+ case IDC_DIR_DELETE:
+ if (wNotifyCode == BN_CLICKED)
+ *changed = SoftwareDirectories_OnDelete(hWnd);
+ break;
+
+ default:
+ handled = false;
+ break;
+ }
+ return handled;
+}
+
+#endif
+