1
0
forked from metin2/client
client/src/Config/MainDialog.cpp

492 lines
13 KiB
C++

#include "MainDialog.h"
#include <d3d9.h>
#include <algorithm>
#include <math.h>
#define APP_NAME _T("Metin2 Config")
#define FILENAME_CONFIG "metin2.cfg"
#define LOCALE_CONFIG "locale.cfg"
static const unsigned int kVisibilityNames[CMainDialog::VISIBILITY_MAX_NUM] = {
IDS_FOG_NEAR, IDS_FOG_MID, IDS_FOG_FAR
};
static const unsigned int kTilingNames[CMainDialog::TILING_MAX_NUM] = {
IDS_TILE_AUTO, IDS_TILE_CPU, IDS_TILE_GPU
};
static const unsigned int kShadowNames[CMainDialog::SHADOW_MAX_NUM] = {
IDS_SHADOW_NONE, IDS_SHADOW_LV1, IDS_SHADOW_LV2, IDS_SHADOW_ALL
};
enum Language
{
kLanguageCzech,
kLanguageDanish,
kLanguageDutch,
kLanguageEnglish,
kLanguageFrench,
kLanguageGerman,
kLanguageGreek,
kLanguageHungarian,
kLanguageItalian,
kLanguagePolish,
kLanguagePortuguese,
kLanguageRomanian,
kLanguageRussian,
kLanguageSpanish,
kLanguageTurkish,
kLanguageMax
};
struct LanguageConfig
{
int stringId;
int charset;
const char* name;
} kLanguageConfig[] = {
{IDS_LANGUAGE_CZECH, 1250, "cz"},
{IDS_LANGUAGE_DANISH, 1252, "dk"},
{IDS_LANGUAGE_DUTCH, 1252, "nl"},
{IDS_LANGUAGE_ENGLISH, 1252, "en"},
{IDS_LANGUAGE_FRENCH, 1252, "fr"},
{IDS_LANGUAGE_GERMAN, 1252, "de"},
{IDS_LANGUAGE_GREEK, 1253, "gr"},
{IDS_LANGUAGE_HUNGARIAN, 1250, "hu"},
{IDS_LANGUAGE_ITALIAN, 1252, "it"},
{IDS_LANGUAGE_POLISH, 1250, "pl"},
{IDS_LANGUAGE_PORTUGUESE, 1252, "pt"},
{IDS_LANGUAGE_ROMANIAN, 1250, "ro"},
{IDS_LANGUAGE_RUSSIAN, 1251, "ru"},
{IDS_LANGUAGE_SPANISH, 1252, "es"},
{IDS_LANGUAGE_TURKISH, 1254, "tr"},
};
CMainDialog::CMainDialog()
{
InitDefaultConfig();
}
BOOL CMainDialog::OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
{
CenterWindow();
HICON hIcon = AtlLoadIconImage(IDR_MAINFRAME, LR_DEFAULTCOLOR,
::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON));
SetIcon(hIcon, TRUE);
HICON hIconSmall = AtlLoadIconImage(IDR_MAINFRAME, LR_DEFAULTCOLOR, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON));
SetIcon(hIconSmall, FALSE);
GetResolutionList();
LoadConfig();
DoDataExchange(FALSE);
// Screen Resolution
ATL::CString strResolutionName;
for (int i=0; i < m_nResolutionCount; i++) {
strResolutionName.Format(_T("%dx%d %dbpp"), m_ResolutionList[i].width, m_ResolutionList[i].height, m_ResolutionList[i].bpp);
m_comboResolution.InsertString( i, strResolutionName );
}
// Resolution Selection
strResolutionName.Format(_T("%dx%d %dbpp"), m_stConfig.width, m_stConfig.height, m_stConfig.bpp);
int iResolutionSel = m_comboResolution.FindString(0, strResolutionName);
if (iResolutionSel < 0)
m_comboResolution.SetCurSel(0);
else
m_comboResolution.SetCurSel(iResolutionSel);
// Frequency
UpdateFrequencyComboBox();
ATL::CString strFrequency;
strFrequency.Format(_T("%d"), m_stConfig.frequency);
int iFrequencySel = m_comboFrequency.FindString(0, strFrequency);
if (iFrequencySel < 0)
m_comboFrequency.SetCurSel(0);
else
m_comboFrequency.SetCurSel(iFrequencySel);
// Gamma
ATL::CString strGammaName;
for (int i=0; i < GAMMA_MAX_NUM; i++) {
strGammaName.Format(_T("%d"), i + 1);
m_comboGamma.InsertString(i, strGammaName);
}
// Gamma Selection
if (m_stConfig.gamma > 0 && m_stConfig.gamma <= GAMMA_MAX_NUM)
m_comboGamma.SetCurSel(m_stConfig.gamma - 1);
else
m_comboGamma.SetCurSel(0);
// Visibility
ATL::CString strVisibility;
for (int i = 0; i < VISIBILITY_MAX_NUM; i++) {
strVisibility.LoadString(kVisibilityNames[i]);
m_comboVisibility.InsertString(i, strVisibility);
}
if (m_stConfig.iDistance > 0 && m_stConfig.iDistance <= VISIBILITY_MAX_NUM)
m_comboVisibility.SetCurSel(m_stConfig.iDistance - 1);
else
m_comboVisibility.SetCurSel(0);
// Tiling
ATL::CString strTiling;
for (int i=0; i < TILING_MAX_NUM; i++) {
strTiling.LoadString(kTilingNames[i]);
m_comboTiling.InsertString(i, strTiling);
}
m_stConfig.iTiling = std::max<int>(m_stConfig.iTiling, 0);
m_stConfig.iTiling = std::min<int>(m_stConfig.iTiling, TILING_MAX_NUM - 1);
m_comboTiling.SetCurSel(m_stConfig.iTiling);
// Shadow
ATL::CString strShadow;
for (int i=0; i < SHADOW_MAX_NUM; i++) {
strShadow.LoadString(kShadowNames[i]);
m_comboShadow.InsertString(i, strShadow);
}
m_stConfig.iShadowLevel = std::max<int>(m_stConfig.iShadowLevel, 0);
m_stConfig.iShadowLevel = std::min<int>(m_stConfig.iShadowLevel, SHADOW_MAX_NUM-1);
m_comboShadow.SetCurSel(m_stConfig.iShadowLevel);
// Language
ATL::CString language;
for (int i = 0; i < kLanguageMax; ++i) {
language.LoadString(kLanguageConfig[i].stringId);
m_comboLanguage.InsertString(i, language);
}
m_stConfig.language = std::clamp((int) m_stConfig.language, 0, kLanguageMax - 1);
m_comboLanguage.SetCurSel(m_stConfig.language);
// Sound
m_sliderBGMVolume.SetRange(0, 1000, true);
m_sliderSoundVolume.SetRange(0, 1000, true);
if (m_stConfig.music_volume >= 0.0f &&
m_stConfig.music_volume <= MUSIC_VOLUME_MAX_NUM)
m_sliderBGMVolume.SetPos(int(m_stConfig.music_volume * 1000.0f));
if (m_stConfig.voice_volume >= 0 &&
m_stConfig.voice_volume <= SOUND_VOLUME_MAX_NUM)
m_sliderSoundVolume.SetPos(m_stConfig.voice_volume * 200);
return TRUE;
}
void CMainDialog::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl)
{
if (DoDataExchange(TRUE) == FALSE) {
//MessageBox();
}
ApplyConfig();
SaveConfig();
EndDialog(nID);
}
void CMainDialog::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl)
{
EndDialog(nID);
}
// Utility functions
void CMainDialog::InitDefaultConfig()
{
memset(&m_stConfig, 0, sizeof(m_stConfig));
m_stConfig.width = 800;
m_stConfig.height = 600;
m_stConfig.frequency = 60;
m_stConfig.bpp = 16;
m_stConfig.bUseSoftwareCursor = false;
m_stConfig.iDistance = 3;
m_stConfig.iTiling = 0;
m_stConfig.iShadowLevel = 3;
m_stConfig.gamma = 3;
m_stConfig.music_volume = 1.0f;
m_stConfig.voice_volume = 5;
m_stConfig.bFullscreen = true;
auto lang = PRIMARYLANGID(LANGIDFROMLCID(GetUserDefaultLCID()));
switch (lang) {
case LANG_GERMAN:
m_stConfig.language = kLanguageGerman;
break;
default:
m_stConfig.language = kLanguageEnglish;
break;
}
}
void CMainDialog::LoadConfig()
{
char buf[256];
char command[256];
char value[256];
FILE * fp = fopen(FILENAME_CONFIG, "rt");
if (fp == NULL)
return;
while (fgets(buf, 256, fp)) {
if (sscanf(buf, " %s %s \n", command, value) == EOF)
break;
if (!_stricmp(command, "WIDTH"))
m_stConfig.width = atoi(value);
else if (!_stricmp(command, "HEIGHT"))
m_stConfig.height = atoi(value);
else if (!_stricmp(command, "BPP"))
m_stConfig.bpp = atoi(value);
else if (!_stricmp(command, "FREQUENCY"))
m_stConfig.frequency = atoi(value);
else if (!_stricmp(command, "SOFTWARE_CURSOR"))
m_stConfig.bUseSoftwareCursor = atoi(value) ? true : false;
else if (!_stricmp(command, "VISIBILITY"))
m_stConfig.iDistance = atoi(value);
else if (!_stricmp(command, "SOFTWARE_TILING"))
m_stConfig.iTiling = atoi(value);
else if (!_stricmp(command, "SHADOW_LEVEL"))
m_stConfig.iShadowLevel = atoi(value);
else if (!_stricmp(command, "MUSIC_VOLUME"))
m_stConfig.music_volume = (float) atof(value);
else if (!_stricmp(command, "VOICE_VOLUME"))
m_stConfig.voice_volume = (char) atoi(value);
else if (!_stricmp(command, "GAMMA"))
m_stConfig.gamma = std::max<int>(1, std::min<int>(GAMMA_MAX_NUM, atoi(value)));
else if (!_stricmp(command, "WINDOWED"))
m_stConfig.bFullscreen = atoi(value) == 1 ? false : true;
}
fclose(fp);
int charset;
char lang[256];
fp = fopen(LOCALE_CONFIG, "rt");
if (!fp)
return;
fgets(buf, 256, fp);
sscanf(buf, "%d %s", &charset, lang);
for (int i = 0; i < kLanguageMax; ++i) {
const auto& cfg = kLanguageConfig[i];
if (0 == std::strcmp(lang, cfg.name))
m_stConfig.language = i;
}
fclose(fp);
}
void CMainDialog::SaveConfig()
{
FILE* fp = fopen(FILENAME_CONFIG, "wt");
if (fp == NULL)
return;
fprintf(fp, "WIDTH %d\n", m_stConfig.width);
fprintf(fp, "HEIGHT %d\n", m_stConfig.height);
fprintf(fp, "BPP %d\n", m_stConfig.bpp);
fprintf(fp, "FREQUENCY %d\n", m_stConfig.frequency);
fprintf(fp, "SOFTWARE_CURSOR %d\n", m_stConfig.bUseSoftwareCursor);
fprintf(fp, "VISIBILITY %d\n", m_stConfig.iDistance);
fprintf(fp, "SOFTWARE_TILING %d\n", m_stConfig.iTiling);
fprintf(fp, "SHADOW_LEVEL %d\n", m_stConfig.iShadowLevel);
fprintf(fp, "MUSIC_VOLUME %.3f\n", m_stConfig.music_volume);
fprintf(fp, "VOICE_VOLUME %d\n", m_stConfig.voice_volume);
fprintf(fp, "GAMMA %d\n", m_stConfig.gamma);
fprintf(fp, "WINDOWED %d\n", !m_stConfig.bFullscreen);
fprintf(fp, "\n");
fclose(fp);
fp = fopen(LOCALE_CONFIG, "wt");
if (!fp)
return;
fprintf(fp, "%d %s", kLanguageConfig[m_stConfig.language].charset, kLanguageConfig[m_stConfig.language].name);
fclose(fp);
}
void CMainDialog::UpdateFrequencyComboBox()
{
int iScreenCurrentSelection = m_comboResolution.GetCurSel();
m_comboFrequency.ResetContent();
ATL::CString strFrequencyName;
for (int i=0; i < m_ResolutionList[iScreenCurrentSelection].frequency_count; i++) {
strFrequencyName.Format(_T("%d"), m_ResolutionList[iScreenCurrentSelection].frequency[i]);
m_comboFrequency.InsertString(i, strFrequencyName);
}
m_comboFrequency.SetCurSel(m_ResolutionList[iScreenCurrentSelection].frequency_count - 1);
}
void CMainDialog::GetResolutionList()
{
m_nResolutionCount = 0;
auto lpd3d = Direct3DCreate9(D3D_SDK_VERSION);
if (!lpd3d) {
m_ResolutionList[m_nResolutionCount].width = 800;
m_ResolutionList[m_nResolutionCount].height = 600;
m_ResolutionList[m_nResolutionCount].bpp = 16;
m_ResolutionList[m_nResolutionCount].frequency[0] = 60;
m_ResolutionList[m_nResolutionCount].frequency_count = 1;
++m_nResolutionCount;
return;
}
const D3DFORMAT allowedFormats[] = {
D3DFMT_X8R8G8B8,
D3DFMT_R5G6B5,
};
for (int i = 0; i < sizeof(allowedFormats) / sizeof(D3DFORMAT); ++i) {
// 이 어뎁터가 가지고 있는 디스플래이 모드갯수를 나열한다..
DWORD dwNumAdapterModes = lpd3d->GetAdapterModeCount(0, allowedFormats[i]);
if (dwNumAdapterModes == 0) {
m_ResolutionList[m_nResolutionCount].width = 800;
m_ResolutionList[m_nResolutionCount].height = 600;
m_ResolutionList[m_nResolutionCount].bpp = 16;
m_ResolutionList[m_nResolutionCount].frequency[0] = 60;
m_ResolutionList[m_nResolutionCount].frequency_count = 1;
++m_nResolutionCount;
lpd3d->Release();
return;
}
for (UINT iMode = 0; iMode < dwNumAdapterModes; iMode++) {
D3DDISPLAYMODE displayMode;
lpd3d->EnumAdapterModes(0, allowedFormats[i], iMode, &displayMode);
if (displayMode.Width < 800 || displayMode.Height < 600)
continue;
int bpp = 0;
if (allowedFormats[i] == D3DFMT_R5G6B5)
bpp = 16;
else if (allowedFormats[i] == D3DFMT_X8R8G8B8)
bpp = 32;
int check_res = false;
for (int i = 0; !check_res && i < m_nResolutionCount; ++i) {
if (m_ResolutionList[i].bpp != bpp ||
m_ResolutionList[i].width != displayMode.Width ||
m_ResolutionList[i].height != displayMode.Height)
continue;
int check_fre = false;
for (int j = 0; j < m_ResolutionList[i].frequency_count; ++j) {
if (m_ResolutionList[i].frequency[j] == displayMode.RefreshRate) {
check_fre = true;
break;
}
}
if (!check_fre )
if (m_ResolutionList[i].frequency_count < FREQUENCY_MAX_NUM)
m_ResolutionList[i].frequency[m_ResolutionList[i].frequency_count++] = displayMode.RefreshRate;
check_res = true;
}
if (!check_res) {
if (m_nResolutionCount < RESOLUTION_MAX_NUM) {
m_ResolutionList[m_nResolutionCount].width = displayMode.Width;
m_ResolutionList[m_nResolutionCount].height = displayMode.Height;
m_ResolutionList[m_nResolutionCount].bpp = bpp;
m_ResolutionList[m_nResolutionCount].frequency[0] = displayMode.RefreshRate;
m_ResolutionList[m_nResolutionCount].frequency_count = 1;
++m_nResolutionCount;
}
}
}
}
lpd3d->Release();
}
void CMainDialog::ApplyConfig()
{
int iResolutionSel = m_comboResolution.GetCurSel();
if ((iResolutionSel >= 0) && (iResolutionSel < m_nResolutionCount)) {
m_stConfig.width = m_ResolutionList[iResolutionSel].width;
m_stConfig.height = m_ResolutionList[iResolutionSel].height;
m_stConfig.bpp = m_ResolutionList[iResolutionSel].bpp;
int iFrequencySel = m_comboFrequency.GetCurSel();
if ((iFrequencySel >= 0) && (iFrequencySel < m_ResolutionList[iResolutionSel].frequency_count))
m_stConfig.frequency = m_ResolutionList[iResolutionSel].frequency[iFrequencySel];
else
m_stConfig.frequency = 60;
} else {
m_stConfig.width = 800;
m_stConfig.height = 600;
m_stConfig.bpp = 16;
m_stConfig.frequency = 60;
}
m_stConfig.gamma = m_comboGamma.GetCurSel() + 1;
m_stConfig.music_volume = float(m_sliderBGMVolume.GetPos()) / 1000.0f;
m_stConfig.voice_volume = m_sliderSoundVolume.GetPos() / 200;
m_stConfig.iDistance = m_comboVisibility.GetCurSel() + 1;
m_stConfig.iTiling = m_comboTiling.GetCurSel();
m_stConfig.iShadowLevel = m_comboShadow.GetCurSel();
m_stConfig.language = m_comboLanguage.GetCurSel();
}
void CMainDialog::OnResolutionSelChange(UINT uNotifyCode, int nID, CWindow wndCtl)
{
UpdateFrequencyComboBox();
}
void CMainDialog::OnTilingSelChange(UINT uNotifyCode, int nID, CWindow wndCtl)
{
switch (m_comboTiling.GetCurSel()) {
case 0:
break;
case 1: {
ATL::CString strCaption((LPCTSTR) IDS_NOTIFY);
ATL::CString strDescription((LPCTSTR) IDS_TILING_CPU);
MessageBox(strDescription, strCaption);
break;
}
case 2: {
ATL::CString strCaption((LPCTSTR) IDS_NOTIFY);
ATL::CString strDescription((LPCTSTR) IDS_TILING_GPU);
MessageBox(strDescription, strCaption);
break;
}
}
}