pureikyubu/SRC/UI/UserSettings.cpp
2020-04-27 02:58:35 +03:00

584 lines
18 KiB
C++

// Dolwin settings dialog (to configure user variables)
#include "pch.h"
// all user variables (except memory cards vars) are placed in UserConfig.h
// parent window and instance
static HWND hParentWnd, hChildDlg[4];
static HINSTANCE hParentInst;
static BOOL settingsLoaded[4];
static BOOL needSelUpdate;
static const TCHAR * tabs[] =
{
_T("Emulator"),
_T("GUI/Selector"),
_T("GCN Hardware"),
_T("GCN HLE")
};
static struct ConsoleVersion
{
uint32_t ver;
const TCHAR* info;
} consoleVersion[] = {
{ 0x00000001, _T("0x00000001: Retail 1") },
{ 0x00000002, _T("0x00000002: HW2 production board") },
{ 0x00000003, _T("0x00000003: The latest production board") },
{ 0x10000004, _T("0x10000004: 1st Devkit HW") },
{ 0x10000005, _T("0x10000005: 2nd Devkit HW") },
{ 0x10000006, _T("0x10000006: The latest Devkit HW") },
{ 0xffffffff, _T("0x%08X: User defined") }
};
static char * int2str(int i)
{
static char str[16];
sprintf_s (str, sizeof(str), "%i", i);
return str;
}
// ---------------------------------------------------------------------------
static void LoadSettings(int n) // dialogs created
{
HWND hDlg = hChildDlg[n];
// Emulator
if(n == 0)
{
CheckDlgButton(hDlg, IDC_ENSURE_WINDALL, BST_UNCHECKED);
EnableWindow(GetDlgItem(hDlg, IDC_WINDALL), 0);
settingsLoaded[0] = TRUE;
}
// GUI/Selector
if(n == 1)
{
for (auto it = usel.paths.begin(); it != usel.paths.end(); ++it)
{
TCHAR* path = *it;
SendDlgItemMessage(hDlg, IDC_PATHLIST, LB_ADDSTRING, 0, (LPARAM)path);
}
needSelUpdate = FALSE;
settingsLoaded[1] = TRUE;
}
// GCN Hardware
if(n == 2)
{
uint32_t ver = GetConfigInt(USER_CONSOLE, USER_HW);
int i=0, selected = sizeof(consoleVersion) / 8 - 1;
while(consoleVersion[i].ver != 0xffffffff)
{
if(consoleVersion[i].ver == ver)
{
selected = i;
break;
}
i++;
}
if(consoleVersion[i].ver == 0xffffffff) selected = sizeof(consoleVersion)/8 - 1;
i=0;
SendDlgItemMessage(hDlg, IDC_CONSOLE_VER, CB_RESETCONTENT, 0, 0);
do
{
SendDlgItemMessage(hDlg, IDC_CONSOLE_VER, CB_INSERTSTRING, -1, (LPARAM)consoleVersion[i].info);
} while(consoleVersion[++i].ver != 0xffffffff);
if(selected == sizeof(consoleVersion)/8 - 1)
{
TCHAR buf[100];
_stprintf_s(buf, _countof(buf) - 1, consoleVersion[selected].info, ver);
SendDlgItemMessage(hDlg, IDC_CONSOLE_VER, CB_INSERTSTRING, -1, (LPARAM)buf);
}
SendDlgItemMessage(hDlg, IDC_CONSOLE_VER, CB_SETCURSEL, selected, 0);
SetDlgItemText(hDlg, IDC_BOOTROM_FILE, GetConfigString(USER_BOOTROM, USER_HW));
SetDlgItemText(hDlg, IDC_DSPDROM_FILE, GetConfigString(USER_DSP_DROM, USER_HW));
SetDlgItemText(hDlg, IDC_DSPIROM_FILE, GetConfigString(USER_DSP_IROM, USER_HW));
settingsLoaded[2] = TRUE;
}
// GCN High Level
if(n == 3)
{
CheckDlgButton(hDlg, IDC_MTXHLE, BST_UNCHECKED);
CheckDlgButton(hDlg, IDC_DSP_FAKE, BST_UNCHECKED);
BOOL flag = GetConfigBool(USER_HLE_MTX, USER_HLE);
if(flag) CheckDlgButton(hDlg, IDC_MTXHLE, BST_CHECKED);
settingsLoaded[3] = TRUE;
}
}
static void SaveSettings() // OK pressed
{
int i;
TCHAR buf[0x1000] = { 0, };
// Emulator
if(settingsLoaded[0])
{
}
// GUI/Selector
if(settingsLoaded[1])
{
HWND hDlg = hChildDlg[1];
TCHAR text[0x1000] = { 0, };
int max = (int)SendDlgItemMessage(hDlg, IDC_PATHLIST, LB_GETCOUNT, 0, 0);
// delete all dirs
usel.paths.clear();
SetConfigString(USER_PATH, (TCHAR *)_T(""), USER_UI);
// add dirs again
for(i=0; i<max; i++)
{
SendDlgItemMessage(hDlg, IDC_PATHLIST, LB_GETTEXT, i, (LPARAM)text);
AddSelectorPath(text);
}
// update selector layout, if PATH has changed
if(needSelUpdate)
{
UpdateSelector();
needSelUpdate = FALSE;
}
}
// GCN Hardwre
if(settingsLoaded[2])
{
HWND hDlg = hChildDlg[2];
int selected = (int)SendDlgItemMessage(hDlg, IDC_CONSOLE_VER, CB_GETCURSEL, 0, 0);
if(selected == sizeof(consoleVersion)/8 - 1)
{
SendDlgItemMessage(hDlg, IDC_CONSOLE_VER, CB_GETLBTEXT, selected, (LPARAM)buf);
uint32_t ver = _tcstoul(buf, NULL, 0);
SetConfigInt(USER_CONSOLE, ver, USER_HW);
}
else SetConfigInt(USER_CONSOLE, consoleVersion[selected].ver, USER_HW);
GetDlgItemText(hDlg, IDC_BOOTROM_FILE, buf, sizeof(buf));
SetConfigString(USER_BOOTROM, buf, USER_HW);
GetDlgItemText(hDlg, IDC_DSPDROM_FILE, buf, sizeof(buf));
SetConfigString(USER_DSP_DROM, buf, USER_HW);
GetDlgItemText(hDlg, IDC_DSPIROM_FILE, buf, sizeof(buf));
SetConfigString(USER_DSP_IROM, buf, USER_HW);
}
// GCN High Level
if(settingsLoaded[3])
{
HWND hDlg = hChildDlg[3];
BOOL flag = IsDlgButtonChecked(hDlg, IDC_MTXHLE);
SetConfigBool(USER_HLE_MTX, flag, USER_HLE);
}
}
void ResetAllSettings()
{
// Danger zone
}
// make sure path have ending '\\'
static void fix_path(TCHAR *path)
{
size_t n = _tcslen(path);
if(path[n-1] != _T('\\'))
{
path[n] = _T('\\');
path[n+1] = 0;
}
}
// ---------------------------------------------------------------------------
// Emulator
static INT_PTR CALLBACK EmulatorSettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
HWND propSheet;
switch(message)
{
case WM_INITDIALOG:
// seems propsheet callback is shit :)
// this trick do the same job
propSheet = GetParent(hDlg);
CenterChildWindow(hParentWnd, propSheet);
hChildDlg[0] = hDlg;
LoadSettings(0);
return TRUE;
case WM_COMMAND:
switch(wParam)
{
case IDC_WINDALL:
{
ResetAllSettings();
UI::DolwinReport(
_T("All Settings have been deleted.\n")
_T("Default values will be restored after first run.")
);
for(int i=0; i<4; i++) LoadSettings(i);
}
break;
case IDC_ENSURE_WINDALL:
{
if(IsDlgButtonChecked(hDlg, IDC_ENSURE_WINDALL))
EnableWindow(GetDlgItem(hDlg, IDC_WINDALL), 1);
else
EnableWindow(GetDlgItem(hDlg, IDC_WINDALL), 0);
}
break;
}
break;
case WM_NOTIFY:
if(((NMHDR FAR *)lParam)->code == PSN_APPLY) SaveSettings();
break;
}
return FALSE;
}
// ---------------------------------------------------------------------------
// UserMenu
static INT_PTR CALLBACK UserMenuSettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
int i;
int curSel, max;
TCHAR * path, text[1024];
switch(message)
{
case WM_INITDIALOG:
hChildDlg[1] = hDlg;
LoadSettings(1);
return TRUE;
case WM_COMMAND:
switch(wParam)
{
case IDC_FILEFILTER:
EditFileFilter(hDlg);
break;
case IDC_ADDPATH:
if((path = UI::FileOpen(hDlg, UI::FileType::Directory)) != nullptr)
{
fix_path(path);
// check if already present
max = (int)SendDlgItemMessage(hDlg, IDC_PATHLIST, LB_GETCOUNT, 0, 0);
for(i=0; i<max; i++)
{
SendDlgItemMessage(hDlg, IDC_PATHLIST, LB_GETTEXT, i, (LPARAM)text);
if(!_tcsicmp(path, text)) break;
}
// add new path
if(i == max)
{
SendDlgItemMessage( hDlg, IDC_PATHLIST, LB_ADDSTRING,
0, (LPARAM)path );
needSelUpdate = TRUE;
}
}
break;
case IDC_KILLPATH:
curSel = (int)SendDlgItemMessage(hDlg, IDC_PATHLIST, LB_GETCURSEL, 0, 0);
SendDlgItemMessage(hDlg, IDC_PATHLIST, LB_DELETESTRING, (WPARAM)curSel, 0);
needSelUpdate = TRUE;
break;
}
break;
case WM_NOTIFY:
if(((NMHDR FAR *)lParam)->code == PSN_APPLY) SaveSettings();
break;
}
return FALSE;
}
// ---------------------------------------------------------------------------
// GCN Hardware
static INT_PTR CALLBACK HardwareSettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
TCHAR * file = nullptr;
switch(message)
{
case WM_INITDIALOG:
hChildDlg[2] = hDlg;
LoadSettings(2);
return TRUE;
case WM_NOTIFY:
if(((NMHDR FAR *)lParam)->code == PSN_APPLY) SaveSettings();
break;
case WM_COMMAND:
switch (wParam)
{
case IDC_CHOOSE_BOOTROM:
file = UI::FileOpen(wnd.hMainWindow, UI::FileType::All);
if (file != nullptr)
{
SetDlgItemText(hDlg, IDC_BOOTROM_FILE, file);
}
else
{
SetDlgItemText(hDlg, IDC_BOOTROM_FILE, _T(""));
}
break;
case IDC_CHOOSE_DSPDROM:
file = UI::FileOpen(wnd.hMainWindow, UI::FileType::All);
if (file != nullptr)
{
SetDlgItemText(hDlg, IDC_DSPDROM_FILE, file);
}
else
{
SetDlgItemText(hDlg, IDC_DSPDROM_FILE, _T(""));
}
break;
case IDC_CHOOSE_DSPIROM:
file = UI::FileOpen(wnd.hMainWindow, UI::FileType::All);
if (file != nullptr)
{
SetDlgItemText(hDlg, IDC_DSPIROM_FILE, file);
}
else
{
SetDlgItemText(hDlg, IDC_DSPIROM_FILE, _T(""));
}
break;
}
break;
}
return FALSE;
}
// ---------------------------------------------------------------------------
// GCN High Level
static INT_PTR CALLBACK HighLevelSettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
hChildDlg[3] = hDlg;
LoadSettings(3);
return TRUE;
case WM_NOTIFY:
if(((NMHDR FAR *)lParam)->code == PSN_APPLY) SaveSettings();
break;
}
return FALSE;
}
// ---------------------------------------------------------------------------
void OpenSettingsDialog(HWND hParent, HINSTANCE hInst)
{
hParentWnd = hParent;
hParentInst = hInst;
PROPSHEETPAGE psp[4] = { 0 };
PROPSHEETHEADER psh = { 0 };
// Emulator page
psp[0].dwSize = sizeof(PROPSHEETPAGE);
psp[0].dwFlags = PSP_USETITLE;
psp[0].hInstance = hParentInst;
psp[0].pszTemplate = MAKEINTRESOURCE(IDD_SETTINGS_EMU);
psp[0].pfnDlgProc = EmulatorSettingsProc;
psp[0].pszTitle = tabs[0];
psp[0].lParam = 0;
psp[0].pfnCallback = NULL;
// UserMenu page
psp[1].dwSize = sizeof(PROPSHEETPAGE);
psp[1].dwFlags = PSP_USETITLE;
psp[1].hInstance = hParentInst;
psp[1].pszTemplate = MAKEINTRESOURCE(IDD_SETTINGS_GUI);
psp[1].pfnDlgProc = UserMenuSettingsProc;
psp[1].pszTitle = tabs[1];
psp[1].lParam = 0;
psp[1].pfnCallback = NULL;
settingsLoaded[0] = FALSE;
// Hardware page
psp[2].dwSize = sizeof(PROPSHEETPAGE);
psp[2].dwFlags = PSP_USETITLE;
psp[2].hInstance = hParentInst;
psp[2].pszTemplate = MAKEINTRESOURCE(IDD_SETTINGS_HW);
psp[2].pfnDlgProc = HardwareSettingsProc;
psp[2].pszTitle = tabs[2];
psp[2].lParam = 0;
psp[2].pfnCallback = NULL;
settingsLoaded[1] = FALSE;
// High Level page
psp[3].dwSize = sizeof(PROPSHEETPAGE);
psp[3].dwFlags = PSP_USETITLE;
psp[3].hInstance = hParentInst;
psp[3].pszTemplate = MAKEINTRESOURCE(IDD_SETTINGS_HLE);
psp[3].pfnDlgProc = HighLevelSettingsProc;
psp[3].pszTitle = tabs[3];
psp[3].lParam = 0;
psp[3].pfnCallback = NULL;
settingsLoaded[2] = FALSE;
// property sheet
psh.dwSize = sizeof(PROPSHEETHEADER);
psh.dwFlags = PSH_USEHICON | /*PSH_PROPTITLE |*/ PSH_NOAPPLYNOW | PSH_PROPSHEETPAGE;
psh.hwndParent = hParentWnd;
psh.hInstance = hParentInst;
psh.hIcon = LoadIcon(hParentInst, MAKEINTRESOURCE(IDI_DOLWIN_ICON));
psh.pszCaption = _T("Configure ") APPNAME;
psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
psh.nStartPage = 0;
psh.ppsp = (LPCPROPSHEETPAGE)&psp;
psh.pfnCallback = NULL;
settingsLoaded[3] = FALSE;
PropertySheet(&psh); // blocking call
}
/* ---------------------------------------------------------------------------
Misc config section.
--------------------------------------------------------------------------- */
// ---------------------------------------------------------------------------
// file filter dialog
static void filter_string(HWND hDlg, uint32_t filter)
{
TCHAR buf[64] = { 0 }, * ptr = buf;
const TCHAR * mask[] = { _T("*.dol"), _T("*.elf"), _T("*.gcm"), _T("*.iso") };
filter = _byteswap_ulong(filter);
for(int i=0; i<4; i++)
{
if(filter & 0xff) ptr += _stprintf_s(ptr, _countof(buf) - (ptr - buf), _T("%s;"), mask[i]);
filter >>= 8;
}
SetDlgItemText(hDlg, IDC_FILE_FILTER, buf);
}
static void check_filter(HWND hDlg, uint32_t filter)
{
// DOL
if(filter & 0xff000000) CheckDlgButton(hDlg, IDC_DOL_FILTER, BST_CHECKED);
else CheckDlgButton(hDlg, IDC_DOL_FILTER, BST_UNCHECKED);
// ELF
if(filter & 0x00ff0000) CheckDlgButton(hDlg, IDC_ELF_FILTER, BST_CHECKED);
else CheckDlgButton(hDlg, IDC_ELF_FILTER, BST_UNCHECKED);
// GCM
if(filter & 0x0000ff00) CheckDlgButton(hDlg, IDC_GCM_FILTER, BST_CHECKED);
else CheckDlgButton(hDlg, IDC_GCM_FILTER, BST_UNCHECKED);
// ISO
if(filter & 0x000000ff) CheckDlgButton(hDlg, IDC_GMP_FILTER, BST_CHECKED);
else CheckDlgButton(hDlg, IDC_GMP_FILTER, BST_UNCHECKED);
}
// dialog procedure
static INT_PTR CALLBACK FileFilterProc(
HWND hwndDlg, // handle to dialog box
UINT uMsg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
switch(uMsg)
{
// prepare dialog
case WM_INITDIALOG:
{
CenterChildWindow(GetParent(hwndDlg), hwndDlg);
// set dialog appearance
ShowWindow(hwndDlg, SW_NORMAL);
SendMessage(hwndDlg, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_DOLWIN_ICON)));
// fill by default info
usel.filter = GetConfigInt(USER_FILTER, USER_UI);
filter_string(hwndDlg, usel.filter);
check_filter(hwndDlg, usel.filter);
return TRUE;
}
// close button
case WM_CLOSE:
{
EndDialog(hwndDlg, 0);
return TRUE;
}
// dialog controls
case WM_COMMAND:
{
if(wParam == IDOK)
{
EndDialog(hwndDlg, 0);
// save information and update selector (if filter was changed)
if((uint32_t)GetConfigInt(USER_FILTER, USER_UI) != usel.filter)
{
SetConfigInt(USER_FILTER, usel.filter, USER_UI);
UpdateSelector();
}
return TRUE;
}
switch(LOWORD(wParam))
{
case IDC_DOL_FILTER: // DOL
usel.filter ^= 0xff000000;
filter_string(hwndDlg, usel.filter);
check_filter(hwndDlg, usel.filter);
return TRUE;
case IDC_ELF_FILTER: // ELF
usel.filter ^= 0x00ff0000;
filter_string(hwndDlg, usel.filter);
check_filter(hwndDlg, usel.filter);
return TRUE;
case IDC_GCM_FILTER: // GCM
usel.filter ^= 0x0000ff00;
filter_string(hwndDlg, usel.filter);
check_filter(hwndDlg, usel.filter);
return TRUE;
case IDC_GMP_FILTER: // ISO
usel.filter ^= 0x000000ff;
filter_string(hwndDlg, usel.filter);
check_filter(hwndDlg, usel.filter);
return TRUE;
}
}
}
return FALSE;
}
void EditFileFilter(HWND hwnd)
{
DialogBox(
GetModuleHandle(NULL),
MAKEINTRESOURCE(IDD_FILE_FILTER),
hwnd,
FileFilterProc);
}