diff --git a/Common/Data/Format/IniFile.cpp b/Common/Data/Format/IniFile.cpp index 06ee1acd60..0900e28499 100644 --- a/Common/Data/Format/IniFile.cpp +++ b/Common/Data/Format/IniFile.cpp @@ -170,6 +170,10 @@ void Section::Set(const char* key, uint32_t newValue) { Set(key, StringFromFormat("0x%08x", newValue).c_str()); } +void Section::Set(const char* key, uint64_t newValue) { + Set(key, StringFromFormat("0x%016lx", newValue).c_str()); +} + void Section::Set(const char* key, float newValue) { Set(key, StringFromFormat("%f", newValue).c_str()); } @@ -311,6 +315,16 @@ bool Section::Get(const char* key, uint32_t* value, uint32_t defaultValue) return false; } +bool Section::Get(const char* key, uint64_t* value, uint64_t defaultValue) +{ + std::string temp; + bool retval = Get(key, &temp, 0); + if (retval && TryParse(temp, value)) + return true; + *value = defaultValue; + return false; +} + bool Section::Get(const char* key, bool* value, bool defaultValue) { std::string temp; @@ -659,6 +673,17 @@ bool IniFile::Get(const char* sectionName, const char* key, uint32_t* value, uin } } +bool IniFile::Get(const char* sectionName, const char* key, uint64_t* value, uint64_t defaultValue) +{ + Section *section = GetSection(sectionName); + if (!section) { + *value = defaultValue; + return false; + } else { + return section->Get(key, value, defaultValue); + } +} + bool IniFile::Get(const char* sectionName, const char* key, bool* value, bool defaultValue) { Section *section = GetSection(sectionName); diff --git a/Common/Data/Format/IniFile.h b/Common/Data/Format/IniFile.h index 6499562edb..87bd1d1830 100644 --- a/Common/Data/Format/IniFile.h +++ b/Common/Data/Format/IniFile.h @@ -35,6 +35,7 @@ public: bool Get(const char* key, std::string* value, const char* defaultValue); void Set(const char* key, uint32_t newValue); + void Set(const char* key, uint64_t newValue); void Set(const char* key, float newValue); void Set(const char* key, const float newValue, const float defaultValue); void Set(const char* key, double newValue); @@ -58,6 +59,7 @@ public: bool Get(const char* key, int* value, int defaultValue = 0); bool Get(const char* key, uint32_t* value, uint32_t defaultValue = 0); + bool Get(const char* key, uint64_t* value, uint64_t defaultValue = 0); bool Get(const char* key, bool* value, bool defaultValue = false); bool Get(const char* key, float* value, float defaultValue = false); bool Get(const char* key, double* value, double defaultValue = false); @@ -103,6 +105,9 @@ public: void Set(const char* sectionName, const char* key, uint32_t newValue) { GetOrCreateSection(sectionName)->Set(key, newValue); } + void Set(const char* sectionName, const char* key, uint64_t newValue) { + GetOrCreateSection(sectionName)->Set(key, newValue); + } void Set(const char* sectionName, const char* key, bool newValue) { GetOrCreateSection(sectionName)->Set(key, newValue); } @@ -114,6 +119,7 @@ public: bool Get(const char* sectionName, const char* key, std::string* value, const char* defaultValue = ""); bool Get(const char* sectionName, const char* key, int* value, int defaultValue = 0); bool Get(const char* sectionName, const char* key, uint32_t* value, uint32_t defaultValue = 0); + bool Get(const char* sectionName, const char* key, uint64_t* value, uint64_t defaultValue = 0); bool Get(const char* sectionName, const char* key, bool* value, bool defaultValue = false); bool Get(const char* sectionName, const char* key, std::vector& values); diff --git a/Common/Data/Text/Parsers.cpp b/Common/Data/Text/Parsers.cpp index ab7c057339..5342b6fbcd 100644 --- a/Common/Data/Text/Parsers.cpp +++ b/Common/Data/Text/Parsers.cpp @@ -71,6 +71,26 @@ bool TryParse(const std::string &str, uint32_t *const output) { return true; } +bool TryParse(const std::string &str, uint64_t *const output) { + char *endptr = NULL; + + // Holy crap this is ugly. + + // Reset errno to a value other than ERANGE + errno = 0; + + uint64_t value = strtoul(str.c_str(), &endptr, 0); + + if (!endptr || *endptr) + return false; + + if (errno == ERANGE) + return false; + + *output = value; + return true; +} + bool TryParse(const std::string &str, bool *const output) { if ("1" == str || !strcasecmp("true", str.c_str())) *output = true; diff --git a/Common/Data/Text/Parsers.h b/Common/Data/Text/Parsers.h index 909e667178..bfa111774c 100644 --- a/Common/Data/Text/Parsers.h +++ b/Common/Data/Text/Parsers.h @@ -57,6 +57,7 @@ bool ParseMacAddress(std::string str, uint8_t macAddr[6]); bool TryParse(const std::string &str, bool *const output); bool TryParse(const std::string &str, uint32_t *const output); +bool TryParse(const std::string &str, uint64_t *const output); template static bool TryParse(const std::string &str, N *const output) { diff --git a/Core/Config.cpp b/Core/Config.cpp index 3b24ee691a..d97e2509cd 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -68,46 +68,56 @@ struct ConfigSetting { TYPE_BOOL, TYPE_INT, TYPE_UINT32, + TYPE_UINT64, TYPE_FLOAT, TYPE_STRING, TYPE_TOUCH_POS, TYPE_PATH, + TYPE_CUSTOM_BUTTON }; union DefaultValue { bool b; int i; uint32_t u; + uint64_t lu; float f; const char *s; const char *p; // not sure how much point.. ConfigTouchPos touchPos; + ConfigCustomButton customButton; }; union SettingPtr { bool *b; int *i; uint32_t *u; + uint64_t *lu; float *f; std::string *s; Path *p; ConfigTouchPos *touchPos; + ConfigCustomButton *customButton; }; typedef bool (*BoolDefaultCallback)(); typedef int (*IntDefaultCallback)(); typedef uint32_t (*Uint32DefaultCallback)(); + typedef uint64_t (*Uint64DefaultCallback)(); typedef float (*FloatDefaultCallback)(); typedef const char *(*StringDefaultCallback)(); typedef ConfigTouchPos(*TouchPosDefaultCallback)(); typedef const char *(*PathDefaultCallback)(); + typedef ConfigCustomButton (*CustomButtonDefaultCallback)(); union Callback { BoolDefaultCallback b; IntDefaultCallback i; Uint32DefaultCallback u; + Uint64DefaultCallback lu; FloatDefaultCallback f; StringDefaultCallback s; PathDefaultCallback p; TouchPosDefaultCallback touchPos; + CustomButtonDefaultCallback customButton; }; ConfigSetting(bool v) @@ -144,6 +154,13 @@ struct ConfigSetting { default_.u = def; } + ConfigSetting(const char *ini, uint64_t *v, uint64_t def, bool save = true, bool perGame = false) + : iniKey_(ini), type_(TYPE_UINT64), report_(false), save_(save), perGame_(perGame) { + ptr_.lu = v; + cb_.lu = nullptr; + default_.lu = def; + } + ConfigSetting(const char *ini, float *v, float def, bool save = true, bool perGame = false) : iniKey_(ini), type_(TYPE_FLOAT), report_(false), save_(save), perGame_(perGame) { ptr_.f = v; @@ -172,6 +189,13 @@ struct ConfigSetting { default_.touchPos = def; } + ConfigSetting(const char *iniKey, const char *iniImage, const char *iniShape, const char *iniToggle, ConfigCustomButton *v, ConfigCustomButton def, bool save = true, bool perGame = false) + : iniKey_(iniKey), ini2_(iniImage), ini3_(iniShape), ini4_(iniToggle), type_(TYPE_CUSTOM_BUTTON), report_(false), save_(save), perGame_(perGame) { + ptr_.customButton = v; + cb_.customButton = nullptr; + default_.customButton = def; + } + ConfigSetting(const char *ini, bool *v, BoolDefaultCallback def, bool save = true, bool perGame = false) : iniKey_(ini), type_(TYPE_BOOL), report_(false), save_(save), perGame_(perGame) { ptr_.b = v; @@ -242,6 +266,11 @@ struct ConfigSetting { default_.u = cb_.u(); } return section->Get(iniKey_, ptr_.u, default_.u); + case TYPE_UINT64: + if (cb_.lu) { + default_.lu = cb_.lu(); + } + return section->Get(iniKey_, ptr_.lu, default_.lu); case TYPE_FLOAT: if (cb_.f) { default_.f = cb_.f(); @@ -277,6 +306,15 @@ struct ConfigSetting { } return result; } + case TYPE_CUSTOM_BUTTON: + if (cb_.customButton) { + default_.customButton = cb_.customButton(); + } + section->Get(iniKey_, &ptr_.customButton->key, default_.customButton.key); + section->Get(ini2_, &ptr_.customButton->image, default_.customButton.image); + section->Get(ini3_, &ptr_.customButton->shape, default_.customButton.shape); + section->Get(ini4_, &ptr_.customButton->toggle, default_.customButton.toggle); + return true; default: _dbg_assert_msg_(false, "Unexpected ini setting type"); return false; @@ -298,6 +336,8 @@ struct ConfigSetting { return section->Set(iniKey_, *ptr_.i); case TYPE_UINT32: return section->Set(iniKey_, *ptr_.u); + case TYPE_UINT64: + return section->Set(iniKey_, *ptr_.lu); case TYPE_FLOAT: return section->Set(iniKey_, *ptr_.f); case TYPE_STRING: @@ -312,6 +352,12 @@ struct ConfigSetting { section->Set(ini4_, ptr_.touchPos->show); } return; + case TYPE_CUSTOM_BUTTON: + section->Set(iniKey_, ptr_.customButton->key); + section->Set(ini2_, ptr_.customButton->image); + section->Set(ini3_, ptr_.customButton->shape); + section->Set(ini4_, ptr_.customButton->toggle); + return; default: _dbg_assert_msg_(false, "Unexpected ini setting type"); return; @@ -329,6 +375,8 @@ struct ConfigSetting { return data.Add(prefix + iniKey_, *ptr_.i); case TYPE_UINT32: return data.Add(prefix + iniKey_, *ptr_.u); + case TYPE_UINT64: + return data.Add(prefix + iniKey_, *ptr_.lu); case TYPE_FLOAT: return data.Add(prefix + iniKey_, *ptr_.f); case TYPE_STRING: @@ -338,6 +386,9 @@ struct ConfigSetting { case TYPE_TOUCH_POS: // Doesn't report. return; + case TYPE_CUSTOM_BUTTON: + // Doesn't report. + return; default: _dbg_assert_msg_(false, "Unexpected ini setting type"); return; @@ -490,7 +541,6 @@ static ConfigSetting generalSettings[] = { ConfigSetting("GridView1", &g_Config.bGridView1, true), ConfigSetting("GridView2", &g_Config.bGridView2, true), ConfigSetting("GridView3", &g_Config.bGridView3, false), - ConfigSetting("ComboMode", &g_Config.iComboMode, 0), ConfigSetting("RightAnalogUp", &g_Config.iRightAnalogUp, 0, true, true), ConfigSetting("RightAnalogDown", &g_Config.iRightAnalogDown, 0, true, true), ConfigSetting("RightAnalogLeft", &g_Config.iRightAnalogLeft, 0, true, true), @@ -887,17 +937,16 @@ static ConfigSetting controlSettings[] = { ConfigSetting("ShowTouchSquare", &g_Config.bShowTouchSquare, true, true, true), ConfigSetting("ShowTouchTriangle", &g_Config.bShowTouchTriangle, true, true, true), - ConfigSetting("ComboKey0Mapping", &g_Config.iCombokey0, 0, true, true), - ConfigSetting("ComboKey1Mapping", &g_Config.iCombokey1, 0, true, true), - ConfigSetting("ComboKey2Mapping", &g_Config.iCombokey2, 0, true, true), - ConfigSetting("ComboKey3Mapping", &g_Config.iCombokey3, 0, true, true), - ConfigSetting("ComboKey4Mapping", &g_Config.iCombokey4, 0, true, true), - - ConfigSetting("ComboKey0Toggle", &g_Config.bComboToggle0, false, true, true), - ConfigSetting("ComboKey1Toggle", &g_Config.bComboToggle1, false, true, true), - ConfigSetting("ComboKey2Toggle", &g_Config.bComboToggle2, false, true, true), - ConfigSetting("ComboKey3Toggle", &g_Config.bComboToggle3, false, true, true), - ConfigSetting("ComboKey4Toggle", &g_Config.bComboToggle4, false, true, true), + ConfigSetting("Custom0Mapping", "Custom0Image", "Custom0Shape", "Custom0Toggle", &g_Config.CustomKey0, {0, 0, 0, false}, true, true), + ConfigSetting("Custom1Mapping", "Custom1Image", "Custom1Shape", "Custom1Toggle", &g_Config.CustomKey1, {0, 1, 0, false}, true, true), + ConfigSetting("Custom2Mapping", "Custom2Image", "Custom2Shape", "Custom2Toggle", &g_Config.CustomKey2, {0, 2, 0, false}, true, true), + ConfigSetting("Custom3Mapping", "Custom3Image", "Custom3Shape", "Custom3Toggle", &g_Config.CustomKey3, {0, 3, 0, false}, true, true), + ConfigSetting("Custom4Mapping", "Custom4Image", "Custom4Shape", "Custom4Toggle", &g_Config.CustomKey4, {0, 4, 0, false}, true, true), + ConfigSetting("Custom5Mapping", "Custom5Image", "Custom5Shape", "Custom5Toggle", &g_Config.CustomKey5, {0, 0, 1, false}, true, true), + ConfigSetting("Custom6Mapping", "Custom6Image", "Custom6Shape", "Custom6Toggle", &g_Config.CustomKey6, {0, 1, 1, false}, true, true), + ConfigSetting("Custom7Mapping", "Custom7Image", "Custom7Shape", "Custom7Toggle", &g_Config.CustomKey7, {0, 2, 1, false}, true, true), + ConfigSetting("Custom8Mapping", "Custom8Image", "Custom8Shape", "Custom8Toggle", &g_Config.CustomKey8, {0, 3, 1, false}, true, true), + ConfigSetting("Custom9Mapping", "Custom9Image", "Custom9Shape", "Custom9Toggle", &g_Config.CustomKey9, {0, 4, 1, false}, true, true), #if defined(_WIN32) // A win32 user seeing touch controls is likely using PPSSPP on a tablet. There it makes @@ -956,11 +1005,11 @@ static ConfigSetting controlSettings[] = { ConfigSetting("fcombo2X", "fcombo2Y", "comboKeyScale2", "ShowComboKey2", &g_Config.touchCombo2, defaultTouchPosHide, true, true), ConfigSetting("fcombo3X", "fcombo3Y", "comboKeyScale3", "ShowComboKey3", &g_Config.touchCombo3, defaultTouchPosHide, true, true), ConfigSetting("fcombo4X", "fcombo4Y", "comboKeyScale4", "ShowComboKey4", &g_Config.touchCombo4, defaultTouchPosHide, true, true), - ConfigSetting("Speed1KeyX", "Speed1KeyY", "Speed1KeyScale", "ShowSpeed1Key", &g_Config.touchSpeed1Key, defaultTouchPosHide, true, true), - ConfigSetting("Speed2KeyX", "Speed2KeyY", "Speed2KeyScale", "ShowSpeed2Key", &g_Config.touchSpeed2Key, defaultTouchPosHide, true, true), - ConfigSetting("RapidFireKeyX", "RapidFireKeyY", "RapidFireKeyScale", "ShowRapidFireKey", &g_Config.touchRapidFireKey, defaultTouchPosHide, true, true), - ConfigSetting("AnalogRotationCWKeyX", "AnalogRotationKeyCWY", "AnalogRotationKeyCWScale", "ShowAnalogRotationCWKey", &g_Config.touchAnalogRotationCWKey, defaultTouchPosHide, true, true), - ConfigSetting("AnalogRotationCCWKeyX", "AnalogRotationKeyCCWY", "AnalogRotationKeyCCWScale", "ShowAnalogRotationCCWKey", &g_Config.touchAnalogRotationCCWKey, defaultTouchPosHide, true, true), + ConfigSetting("fcombo5X", "fcombo5Y", "comboKeyScale5", "ShowComboKey5", &g_Config.touchCombo5, defaultTouchPosHide, true, true), + ConfigSetting("fcombo6X", "fcombo6Y", "comboKeyScale6", "ShowComboKey6", &g_Config.touchCombo6, defaultTouchPosHide, true, true), + ConfigSetting("fcombo7X", "fcombo7Y", "comboKeyScale7", "ShowComboKey7", &g_Config.touchCombo7, defaultTouchPosHide, true, true), + ConfigSetting("fcombo8X", "fcombo8Y", "comboKeyScale8", "ShowComboKey8", &g_Config.touchCombo8, defaultTouchPosHide, true, true), + ConfigSetting("fcombo9X", "fcombo9Y", "comboKeyScale9", "ShowComboKey9", &g_Config.touchCombo9, defaultTouchPosHide, true, true), ConfigSetting("AnalogDeadzone", &g_Config.fAnalogDeadzone, 0.15f, true, true), ConfigSetting("AnalogInverseDeadzone", &g_Config.fAnalogInverseDeadzone, 0.0f, true, true), @@ -1788,11 +1837,11 @@ void Config::ResetControlLayout() { reset(g_Config.touchCombo2); reset(g_Config.touchCombo3); reset(g_Config.touchCombo4); - reset(g_Config.touchSpeed1Key); - reset(g_Config.touchSpeed2Key); - reset(g_Config.touchRapidFireKey); - reset(g_Config.touchAnalogRotationCWKey); - reset(g_Config.touchAnalogRotationCCWKey); + reset(g_Config.touchCombo5); + reset(g_Config.touchCombo6); + reset(g_Config.touchCombo7); + reset(g_Config.touchCombo8); + reset(g_Config.touchCombo9); } void Config::GetReportingInfo(UrlEncoder &data) { diff --git a/Core/Config.h b/Core/Config.h index ba6dfb2db4..a07a6182d8 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -55,6 +55,13 @@ struct ConfigTouchPos { bool show; }; +struct ConfigCustomButton { + uint64_t key; + int image; + int shape; + bool toggle; +}; + struct Config { public: Config(); @@ -299,8 +306,6 @@ public: bool bGridView1; bool bGridView2; bool bGridView3; - //Combo key screen flag - int iComboMode; // Right analog binding int iRightAnalogUp; @@ -349,11 +354,11 @@ public: ConfigTouchPos touchCombo2; ConfigTouchPos touchCombo3; ConfigTouchPos touchCombo4; - ConfigTouchPos touchSpeed1Key; - ConfigTouchPos touchSpeed2Key; - ConfigTouchPos touchRapidFireKey; - ConfigTouchPos touchAnalogRotationCWKey; - ConfigTouchPos touchAnalogRotationCCWKey; + ConfigTouchPos touchCombo5; + ConfigTouchPos touchCombo6; + ConfigTouchPos touchCombo7; + ConfigTouchPos touchCombo8; + ConfigTouchPos touchCombo9; // Controls Visibility bool bShowTouchControls; @@ -363,18 +368,16 @@ public: bool bShowTouchTriangle; bool bShowTouchSquare; - // Combo_key mapping. These are bitfields. - int iCombokey0; - int iCombokey1; - int iCombokey2; - int iCombokey3; - int iCombokey4; - - bool bComboToggle0; - bool bComboToggle1; - bool bComboToggle2; - bool bComboToggle3; - bool bComboToggle4; + ConfigCustomButton CustomKey0; + ConfigCustomButton CustomKey1; + ConfigCustomButton CustomKey2; + ConfigCustomButton CustomKey3; + ConfigCustomButton CustomKey4; + ConfigCustomButton CustomKey5; + ConfigCustomButton CustomKey6; + ConfigCustomButton CustomKey7; + ConfigCustomButton CustomKey8; + ConfigCustomButton CustomKey9; // Ignored on iOS and other platforms that lack pause. bool bShowTouchPause; diff --git a/Core/ControlMapper.h b/Core/ControlMapper.h index 9676be212b..cb363c7ebc 100644 --- a/Core/ControlMapper.h +++ b/Core/ControlMapper.h @@ -16,6 +16,7 @@ public: void Update(); bool Key(const KeyInput &key, bool *pauseTrigger); + void pspKey(int pspKeyCode, int flags); bool Axis(const AxisInput &axis); // Required callbacks @@ -29,7 +30,6 @@ public: private: void processAxis(const AxisInput &axis, int direction); - void pspKey(int pspKeyCode, int flags); void setVKeyAnalog(char axis, int stick, int virtualKeyMin, int virtualKeyMax, bool setZero = true); void SetPSPAxis(char axis, float value, int stick); diff --git a/UI/ComboKeyMappingScreen.cpp b/UI/ComboKeyMappingScreen.cpp index f1582ef9aa..3fd324e845 100644 --- a/UI/ComboKeyMappingScreen.cpp +++ b/UI/ComboKeyMappingScreen.cpp @@ -30,117 +30,167 @@ #include "Common/StringUtils.h" #include "Core/Config.h" -#include "TouchControlVisibilityScreen.h" #include "UI/ComboKeyMappingScreen.h" +class ButtonPreview : public UI::View { +public: + ButtonPreview(ImageID bgImg, ImageID img, float rotationIcon, bool flipShape, float rotationShape, int x, int y) + : View(new UI::AnchorLayoutParams(x, y, UI::NONE, UI::NONE, true)), bgImg_(bgImg), img_(img), rotI_(rotationIcon), + flipS_(flipShape), rotS_(rotationShape), x_(x), y_(y) {} + + void Draw(UIContext &dc) override { + float opacity = g_Config.iTouchButtonOpacity / 100.0f; + + uint32_t colorBg = colorAlpha(g_Config.iTouchButtonStyle != 0 ? 0xFFFFFF : 0xc0b080, opacity); + uint32_t color = colorAlpha(0xFFFFFF, opacity); + + dc.Draw()->DrawImageRotated(bgImg_, x_, y_, 1.0f, rotS_*PI/180, colorBg, flipS_); + dc.Draw()->DrawImageRotated(img_, x_, y_, 1.0f, rotI_*PI/180, color, false); + } +private: + int x_; + int y_; + float rotI_; + float rotS_; + bool flipS_; + ImageID bgImg_; + ImageID img_; +}; + void ComboKeyScreen::CreateViews() { using namespace UI; + using namespace CustomKey; auto co = GetI18NCategory("Controls"); + auto mc = GetI18NCategory("MappableControls"); root_ = new LinearLayout(ORIENT_VERTICAL); - root_->Add(new ItemHeader(co->T("Combo Key Setting"))); + root_->Add(new ItemHeader(co->T("Custom Key Setting"))); LinearLayout *root__ = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(1.0)); root_->Add(root__); LinearLayout *leftColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(120, FILL_PARENT)); auto di = GetI18NCategory("Dialog"); - static const ImageID comboKeyImages[5] = { - ImageID("I_1"), ImageID("I_2"), ImageID("I_3"), ImageID("I_4"), ImageID("I_5"), - }; - - comboselect = new ChoiceStrip(ORIENT_VERTICAL, new AnchorLayoutParams(10, 10, NONE, NONE)); - comboselect->SetSpacing(10); - for (int i = 0; i < 5; i++) { - comboselect->AddChoice(comboKeyImages[i]); - } - comboselect->SetSelection(*mode, false); - comboselect->OnChoice.Handle(this, &ComboKeyScreen::onCombo); - leftColumn->Add(comboselect); - root__->Add(leftColumn); - rightScroll_ = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0f)); - leftColumn->Add(new Spacer(new LinearLayoutParams(1.0f))); - leftColumn->Add(new Choice(di->T("Back")))->OnClick.Handle(this, &UIScreen::OnBack); - root__->Add(rightScroll_); - - const int cellSize = 400; - - UI::GridLayoutSettings gridsettings(cellSize, 64, 5); - gridsettings.fillCells = true; - GridLayout *grid = rightScroll_->Add(new GridLayout(gridsettings, new LayoutParams(FILL_PARENT, WRAP_CONTENT))); - - bool *toggle = nullptr; + ConfigCustomButton* cfg = nullptr; + bool* show = nullptr; memset(array, 0, sizeof(array)); - switch (*mode) { + switch (id_) { case 0: - toggle = &g_Config.bComboToggle0; - for (int i = 0; i < 16; i++) - array[i] = (0x01 == ((g_Config.iCombokey0 >> i) & 0x01)); + cfg = &g_Config.CustomKey0; + show = &g_Config.touchCombo0.show; + for (int i = 0; i < ARRAY_SIZE(comboKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomKey0.key >> i) & 0x01)); break; case 1: - toggle = &g_Config.bComboToggle1; - for (int i = 0; i < 16; i++) - array[i] = (0x01 == ((g_Config.iCombokey1 >> i) & 0x01)); + cfg = &g_Config.CustomKey1; + show = &g_Config.touchCombo1.show; + for (int i = 0; i < ARRAY_SIZE(comboKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomKey1.key >> i) & 0x01)); break; case 2: - toggle = &g_Config.bComboToggle2; - for (int i = 0; i < 16; i++) - array[i] = (0x01 == ((g_Config.iCombokey2 >> i) & 0x01)); + cfg = &g_Config.CustomKey2; + show = &g_Config.touchCombo2.show; + for (int i = 0; i < ARRAY_SIZE(comboKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomKey2.key >> i) & 0x01)); break; case 3: - toggle = &g_Config.bComboToggle3; - for (int i = 0; i < 16; i++) - array[i] = (0x01 == ((g_Config.iCombokey3 >> i) & 0x01)); + cfg = &g_Config.CustomKey3; + show = &g_Config.touchCombo3.show; + for (int i = 0; i < ARRAY_SIZE(comboKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomKey3.key >> i) & 0x01)); break; case 4: - toggle = &g_Config.bComboToggle4; - for (int i = 0; i < 16; i++) - array[i] = (0x01 == ((g_Config.iCombokey4 >> i) & 0x01)); + cfg = &g_Config.CustomKey4; + show = &g_Config.touchCombo4.show; + for (int i = 0; i < ARRAY_SIZE(comboKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomKey4.key >> i) & 0x01)); + break; + case 5: + cfg = &g_Config.CustomKey5; + show = &g_Config.touchCombo5.show; + for (int i = 0; i < ARRAY_SIZE(comboKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomKey5.key >> i) & 0x01)); + break; + case 6: + cfg = &g_Config.CustomKey6; + show = &g_Config.touchCombo6.show; + for (int i = 0; i < ARRAY_SIZE(comboKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomKey6.key >> i) & 0x01)); + break; + case 7: + cfg = &g_Config.CustomKey7; + show = &g_Config.touchCombo7.show; + for (int i = 0; i < ARRAY_SIZE(comboKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomKey7.key >> i) & 0x01)); + break; + case 8: + cfg = &g_Config.CustomKey8; + show = &g_Config.touchCombo8.show; + for (int i = 0; i < ARRAY_SIZE(comboKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomKey8.key >> i) & 0x01)); + break; + case 9: + cfg = &g_Config.CustomKey9; + show = &g_Config.touchCombo9.show; + for (int i = 0; i < ARRAY_SIZE(comboKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomKey9.key >> i) & 0x01)); break; default: // This shouldn't happen, let's just not crash. - toggle = &g_Config.bComboToggle0; + cfg = &g_Config.CustomKey0; + show = &g_Config.touchCombo0.show; break; } - std::map keyImages; - keyImages["Circle"] = ImageID("I_CIRCLE"); - keyImages["Cross"] = ImageID("I_CROSS"); - keyImages["Square"] = ImageID("I_SQUARE"); - keyImages["Triangle"] = ImageID("I_TRIANGLE"); - keyImages["L"] = ImageID("I_L"); - keyImages["R"] = ImageID("I_R"); - keyImages["Start"] = ImageID("I_START"); - keyImages["Select"] = ImageID("I_SELECT"); - keyToggles["Circle"] = &array[13]; - keyToggles["Cross"] = &array[14]; - keyToggles["Square"] = &array[15]; - keyToggles["Triangle"] = &array[12]; - keyToggles["L"] = &array[8]; - keyToggles["R"] = &array[9]; - keyToggles["Left"] = &array[7]; - keyToggles["Up"] = &array[4]; - keyToggles["Right"] = &array[5]; - keyToggles["Down"] = &array[6]; - keyToggles["Start"] = &array[3]; - keyToggles["Select"] = &array[0]; + leftColumn->Add(new ButtonPreview(g_Config.iTouchButtonStyle == 0 ? comboKeyShapes[cfg->shape].i : comboKeyShapes[cfg->shape].l, + comboKeyImages[cfg->image].i, comboKeyImages[cfg->image].r, comboKeyShapes[cfg->shape].f, comboKeyShapes[cfg->shape].r, 62, 82)); - std::map::iterator imageFinder; + root__->Add(leftColumn); + rightScroll_ = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT, 1.0f)); + leftColumn->Add(new Spacer(new LinearLayoutParams(1.0f))); + leftColumn->Add(new Choice(di->T("Back")))->OnClick.Handle(this, &UIScreen::OnBack); + root__->Add(rightScroll_); - auto mc = GetI18NCategory("MappableControls"); + LinearLayout *vertLayout = new LinearLayout(ORIENT_VERTICAL); + rightScroll_->Add(vertLayout); + + vertLayout->Add(new ItemHeader(co->T("Button Style"))); + vertLayout->Add(new CheckBox(show, co->T("Visible"))); - for (auto i = keyToggles.begin(); i != keyToggles.end(); ++i) { + // All icon and name are defined in GamepadEmu.h + static const char *imageNames[ARRAY_SIZE(comboKeyImages)]; + for (int i = 0; i < ARRAY_SIZE(imageNames); ++i) { + imageNames[i] = comboKeyImages[i].n; + } + PopupMultiChoice *icon = vertLayout->Add(new PopupMultiChoice(&(cfg->image), co->T("Icon"), imageNames, 0, ARRAY_SIZE(imageNames), mc->GetName(), screenManager())); + icon->OnChoice.Handle(this, &ComboKeyScreen::onCombo); + + // All shape and name are defined in GamepadEmu.h + static const char *shapeNames[ARRAY_SIZE(comboKeyShapes)]; + for (int i = 0; i < ARRAY_SIZE(shapeNames); ++i) { + shapeNames[i] = comboKeyShapes[i].n; + } + vertLayout->Add(new PopupMultiChoice(&(cfg->shape), co->T("Shape"), shapeNames, 0, ARRAY_SIZE(shapeNames), mc->GetName(), screenManager()))->OnChoice.Handle(this, &ComboKeyScreen::onCombo); + + vertLayout->Add(new ItemHeader(co->T("Button Binding"))); + vertLayout->Add(new CheckBox(&(cfg->toggle), co->T("Toggle mode"))); + + const int cellSize = 400; + UI::GridLayoutSettings gridsettings(cellSize, 64, 5); + gridsettings.fillCells = true; + GridLayout *grid = vertLayout->Add(new GridLayout(gridsettings, new LayoutParams(FILL_PARENT, WRAP_CONTENT))); + + // Button name, image and action are defined in GamepadEmu.h + for (int i = 0; i < ARRAY_SIZE(comboKeyList); ++i) { LinearLayout *row = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); row->SetSpacing(0); - CheckBox *checkbox = new CheckBox(i->second, "", "", new LinearLayoutParams(50, WRAP_CONTENT)); + CheckBox *checkbox = new CheckBox(&array[i], "", "", new LinearLayoutParams(50, WRAP_CONTENT)); row->Add(checkbox); - imageFinder = keyImages.find(i->first); Choice *choice; - if (imageFinder != keyImages.end()) { - choice = new Choice(keyImages[imageFinder->first], new LinearLayoutParams(1.0f)); - } - else { - choice = new Choice(mc->T(i->first.c_str()), new LinearLayoutParams(1.0f)); + if (comboKeyList[i].i.isValid()) { + choice = new Choice(comboKeyList[i].i, new LinearLayoutParams(1.0f)); + } else { + choice = new Choice(mc->T(comboKeyList[i].n), new LinearLayoutParams(1.0f)); } ChoiceEventHandler *choiceEventHandler = new ChoiceEventHandler(checkbox); @@ -150,76 +200,67 @@ void ComboKeyScreen::CreateViews() { row->Add(choice); grid->Add(row); - } - - LinearLayout *row = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); - row->SetSpacing(0); - - CheckBox *checkbox = new CheckBox(toggle, "", "", new LinearLayoutParams(50, WRAP_CONTENT)); - row->Add(checkbox); - - Choice *choice = new Choice(mc->T("Toggle mode"), new LinearLayoutParams(1.0f)); - ChoiceEventHandler *choiceEventHandler = new ChoiceEventHandler(checkbox); - choice->OnClick.Handle(choiceEventHandler, &ChoiceEventHandler::onChoiceClick); - choice->SetCentered(true); - - row->Add(choice); - grid->Add(row); } -static int arrayToInt(bool ary[16]) { - int value = 0; - for (int i = 15; i >= 0; i--) { +static uint64_t arrayToInt(bool ary[ARRAY_SIZE(CustomKey::comboKeyList)]) { + uint64_t value = 0; + for (int i = ARRAY_SIZE(CustomKey::comboKeyList)-1; i >= 0; i--) { value |= ary[i] ? 1 : 0; - value = value << 1; + if (i > 0) { + value = value << 1; + } + } + return value; +} + +void ComboKeyScreen::saveArray() { + switch (id_) { + case 0: + g_Config.CustomKey0.key = arrayToInt(array); + break; + case 1: + g_Config.CustomKey1.key = arrayToInt(array); + break; + case 2: + g_Config.CustomKey2.key = arrayToInt(array); + break; + case 3: + g_Config.CustomKey3.key = arrayToInt(array); + break; + case 4: + g_Config.CustomKey4.key = arrayToInt(array); + break; + case 5: + g_Config.CustomKey5.key = arrayToInt(array); + break; + case 6: + g_Config.CustomKey6.key = arrayToInt(array); + break; + case 7: + g_Config.CustomKey7.key = arrayToInt(array); + break; + case 8: + g_Config.CustomKey8.key = arrayToInt(array); + break; + case 9: + g_Config.CustomKey9.key = arrayToInt(array); + break; } - return value >> 1; } void ComboKeyScreen::onFinish(DialogResult result) { - switch (*mode) { - case 0: - g_Config.iCombokey0 = arrayToInt(array); - break; - case 1: - g_Config.iCombokey1 = arrayToInt(array); - break; - case 2: - g_Config.iCombokey2 = arrayToInt(array); - break; - case 3: - g_Config.iCombokey3 = arrayToInt(array); - break; - case 4: - g_Config.iCombokey4 = arrayToInt(array); - break; - } - g_Config.Save("ComboKeyScreen::onFInish"); + saveArray(); + g_Config.Save("ComboKeyScreen::onFinish"); } UI::EventReturn ComboKeyScreen::ChoiceEventHandler::onChoiceClick(UI::EventParams &e){ checkbox_->Toggle(); - - return UI::EVENT_DONE; }; UI::EventReturn ComboKeyScreen::onCombo(UI::EventParams &e) { - switch (*mode){ - case 0:g_Config.iCombokey0 = arrayToInt(array); - break; - case 1:g_Config.iCombokey1 = arrayToInt(array); - break; - case 2:g_Config.iCombokey2 = arrayToInt(array); - break; - case 3:g_Config.iCombokey3 = arrayToInt(array); - break; - case 4:g_Config.iCombokey4 = arrayToInt(array); - } - *mode = comboselect->GetSelection(); + saveArray(); CreateViews(); return UI::EVENT_DONE; } - - diff --git a/UI/ComboKeyMappingScreen.h b/UI/ComboKeyMappingScreen.h index bafc3a974b..aa4fd71a06 100644 --- a/UI/ComboKeyMappingScreen.h +++ b/UI/ComboKeyMappingScreen.h @@ -18,6 +18,7 @@ #pragma once #include "MiscScreens.h" +#include "UI/GamepadEmu.h" #include @@ -27,15 +28,16 @@ namespace UI { class ComboKeyScreen : public UIDialogScreenWithBackground { public: - ComboKeyScreen(int *key): mode(key) {} + ComboKeyScreen(int id): id_(id) {} void CreateViews() override; void onFinish(DialogResult result) override; UI::EventReturn onCombo(UI::EventParams &e); private: - std::map keyToggles; - bool array[16]; - int *mode; + void saveArray(); + + bool array[ARRAY_SIZE(CustomKey::comboKeyList)]; + int id_; UI::ChoiceStrip *comboselect; UI::ScrollView *rightScroll_; class ChoiceEventHandler{ diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index d323aadb71..13ed2e5d18 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -775,7 +775,7 @@ void EmuScreen::CreateViews() { const Bounds &bounds = screenManager()->getUIContext()->GetLayoutBounds(); InitPadLayout(bounds.w, bounds.h); - root_ = CreatePadLayout(bounds.w, bounds.h, &pauseTrigger_); + root_ = CreatePadLayout(bounds.w, bounds.h, &pauseTrigger_, &controlMapper_); if (g_Config.bShowDeveloperMenu) { root_->Add(new Button(dev->T("DevMenu")))->OnClick.Handle(this, &EmuScreen::OnDevTools); } diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index b1cf9bcb0b..ba5851c96d 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -49,7 +49,6 @@ #include "UI/TouchControlVisibilityScreen.h" #include "UI/TiltAnalogSettingsScreen.h" #include "UI/TiltEventProcessor.h" -#include "UI/ComboKeyMappingScreen.h" #include "UI/GPUDriverTestScreen.h" #include "UI/MemStickScreen.h" @@ -688,7 +687,7 @@ void GameSettingsScreen::CreateViews() { if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) != DEVICE_TYPE_TV) { controlsSettings->Add(new ItemHeader(co->T("OnScreen", "On-Screen Touch Controls"))); controlsSettings->Add(new CheckBox(&g_Config.bShowTouchControls, co->T("OnScreen", "On-Screen Touch Controls"))); - layoutEditorChoice_ = controlsSettings->Add(new Choice(co->T("Custom layout..."))); + layoutEditorChoice_ = controlsSettings->Add(new Choice(co->T("Customize Touch Controls"))); layoutEditorChoice_->OnClick.Handle(this, &GameSettingsScreen::OnTouchControlLayout); layoutEditorChoice_->SetEnabledPtr(&g_Config.bShowTouchControls); @@ -696,11 +695,6 @@ void GameSettingsScreen::CreateViews() { CheckBox *floatingAnalog = controlsSettings->Add(new CheckBox(&g_Config.bAutoCenterTouchAnalog, co->T("Auto-centering analog stick"))); floatingAnalog->SetEnabledPtr(&g_Config.bShowTouchControls); - // Combo key setup - Choice *comboKey = controlsSettings->Add(new Choice(co->T("Combo Key Setup"))); - comboKey->OnClick.Handle(this, &GameSettingsScreen::OnComboKey); - comboKey->SetEnabledPtr(&g_Config.bShowTouchControls); - // On non iOS systems, offer to let the user see this button. // Some Windows touch devices don't have a back button or other button to call up the menu. if (System_GetPropertyBool(SYSPROP_HAS_BACK_BUTTON)) { @@ -1472,11 +1466,6 @@ UI::EventReturn GameSettingsScreen::OnChangeMacAddress(UI::EventParams &e) { return UI::EVENT_DONE; } -UI::EventReturn GameSettingsScreen::OnComboKey(UI::EventParams &e) { - screenManager()->push(new ComboKeyScreen(&g_Config.iComboMode)); - return UI::EVENT_DONE; -} - UI::EventReturn GameSettingsScreen::OnLanguage(UI::EventParams &e) { auto dev = GetI18NCategory("Developer"); auto langScreen = new NewLanguageScreen(dev->T("Language")); diff --git a/UI/GameSettingsScreen.h b/UI/GameSettingsScreen.h index b5d3c9e3e9..ebc5d59f88 100644 --- a/UI/GameSettingsScreen.h +++ b/UI/GameSettingsScreen.h @@ -74,7 +74,6 @@ private: UI::EventReturn OnDumpNextFrameToLog(UI::EventParams &e); UI::EventReturn OnTiltTypeChange(UI::EventParams &e); UI::EventReturn OnTiltCustomize(UI::EventParams &e); - UI::EventReturn OnComboKey(UI::EventParams &e); // Global settings handlers UI::EventReturn OnLanguage(UI::EventParams &e); diff --git a/UI/GamepadEmu.cpp b/UI/GamepadEmu.cpp index 69359e1432..8394a3faa2 100644 --- a/UI/GamepadEmu.cpp +++ b/UI/GamepadEmu.cpp @@ -31,6 +31,7 @@ #include "Core/Core.h" #include "Core/System.h" #include "Core/HLE/sceCtrl.h" +#include "Core/ControlMapper.h" #include "UI/GamepadEmu.h" static u32 GetButtonColor() { @@ -158,68 +159,6 @@ void BoolButton::Touch(const TouchInput &input) { } } -void FPSLimitButton::Touch(const TouchInput &input) { - bool lastDown = pointerDownMask_ != 0; - MultiTouchButton::Touch(input); - bool down = pointerDownMask_ != 0; - - if (!down && lastDown && IsDown()) { - PSP_CoreParameter().fpsLimit = FPSLimit::NORMAL; - } else if (down && !lastDown && PSP_CoreParameter().fpsLimit == FPSLimit::NORMAL) { - int limit = limit_ == FPSLimit::CUSTOM1 ? g_Config.iFpsLimit1 : g_Config.iFpsLimit2; - // Validate it actually has a setting (may this should override visible?) - if (limit >= 0) { - PSP_CoreParameter().fpsLimit = limit_; - } - } -} - -bool FPSLimitButton::IsDown() { - return PSP_CoreParameter().fpsLimit == limit_; -} - -void RapidFireButton::Touch(const TouchInput &input) { - bool lastDown = pointerDownMask_ != 0; - MultiTouchButton::Touch(input); - bool down = pointerDownMask_ != 0; - if (down && !lastDown) { - __CtrlSetRapidFire(!__CtrlGetRapidFire()); - } -} - -bool RapidFireButton::IsDown() { - return __CtrlGetRapidFire(); -} - -void AnalogRotationButton::Touch(const TouchInput &input) { - bool lastDown = pointerDownMask_ != 0; - MultiTouchButton::Touch(input); - bool down = pointerDownMask_ != 0; - if (down && !lastDown) { - autoRotating_ = true; - } else if (lastDown && !down) { - autoRotating_ = false; - __CtrlSetAnalogXY(0, 0.0f, 0.0f); - } -} - -void AnalogRotationButton::Update() { - const float now = time_now_d(); - float delta = now - lastFrameTime_; - if (delta > 0) { - secondsWithoutTouch_ += delta; - } - lastFrameTime_ = now; - - if (autoRotating_) { - float speed = clockWise_ ? -g_Config.fAnalogAutoRotSpeed : g_Config.fAnalogAutoRotSpeed; - // Clamp to a square - __CtrlSetAnalogXY(0, - std::min(1.0f, std::max(-1.0f, 1.42f*cosf(now*speed))), - std::min(1.0f, std::max(-1.0f, 1.42f*sinf(now*speed)))); - } -} - void PSPButton::Touch(const TouchInput &input) { bool lastDown = pointerDownMask_ != 0; MultiTouchButton::Touch(input); @@ -234,31 +173,30 @@ void PSPButton::Touch(const TouchInput &input) { } } +bool ComboKey::IsDown() { + return (toggle_ && on_) || (!toggle_ && pointerDownMask_ != 0); +} + void ComboKey::Touch(const TouchInput &input) { + using namespace CustomKey; bool lastDown = pointerDownMask_ != 0; MultiTouchButton::Touch(input); bool down = pointerDownMask_ != 0; - static const int combo[16] = {CTRL_SQUARE ,CTRL_TRIANGLE ,CTRL_CIRCLE ,CTRL_CROSS ,CTRL_UP ,CTRL_DOWN ,CTRL_LEFT ,CTRL_RIGHT ,CTRL_START ,CTRL_SELECT ,CTRL_LTRIGGER ,CTRL_RTRIGGER }; - if (down || lastDown) { - for (int i = 0; i < 16; i++) { - if (pspButtonBit_ & combo[i]) - { - if (down && !lastDown) { - if (g_Config.bHapticFeedback) { - Vibrate(HAPTIC_VIRTUAL_KEY); - } - if (!toggle_) { - __CtrlButtonDown(combo[i]); - } else { - if (__CtrlPeekButtons() & combo[i]) - __CtrlButtonUp(combo[i]); - else - __CtrlButtonDown(combo[i]); - } - } - else if (lastDown && !down && !toggle_) { - __CtrlButtonUp(combo[i]); - } + + if (down && !lastDown) { + if (g_Config.bHapticFeedback) + Vibrate(HAPTIC_VIRTUAL_KEY); + for (int i = 0; i < ARRAY_SIZE(comboKeyList); i++) { + if (pspButtonBit_ & (1UL << i)) { + controllMapper_->pspKey(comboKeyList[i].c, (on_ && toggle_) ? KEY_UP : KEY_DOWN); + } + } + if (toggle_) + on_ = !on_; + } else if (!toggle_ && lastDown && !down) { + for (int i = 0; i < ARRAY_SIZE(comboKeyList); i++) { + if (pspButtonBit_ & (1UL << i)) { + controllMapper_->pspKey(comboKeyList[i].c, KEY_UP); } } } @@ -697,12 +635,6 @@ void InitPadLayout(float xres, float yres, float globalScale) { int unthrottle_key_Y = yres - 60 * scale; initTouchPos(g_Config.touchUnthrottleKey, unthrottle_key_X, unthrottle_key_Y); - initTouchPos(g_Config.touchSpeed1Key, unthrottle_key_X, unthrottle_key_Y - 60 * scale); - initTouchPos(g_Config.touchSpeed2Key, unthrottle_key_X + bottom_key_spacing * scale, unthrottle_key_Y - 60 * scale); - initTouchPos(g_Config.touchRapidFireKey, unthrottle_key_X + 2*bottom_key_spacing * scale, unthrottle_key_Y - 60 * scale); - initTouchPos(g_Config.touchAnalogRotationCCWKey, unthrottle_key_X, unthrottle_key_Y - 120 * scale); - initTouchPos(g_Config.touchAnalogRotationCWKey, unthrottle_key_X + bottom_key_spacing * scale, unthrottle_key_Y - 120 * scale); - // L and R------------------------------------------------------------ // Put them above the analog stick / above the buttons to the right. // The corners were very hard to reach.. @@ -735,9 +667,29 @@ void InitPadLayout(float xres, float yres, float globalScale) { int combo4_key_X = halfW + bottom_key_spacing * scale * 2.2f; int combo4_key_Y = yres / 3; initTouchPos(g_Config.touchCombo4, combo4_key_X, combo4_key_Y); + + int combo5_key_X = halfW - bottom_key_spacing * scale * 1.2f; + int combo5_key_Y = yres / 2; + initTouchPos(g_Config.touchCombo5, combo5_key_X, combo5_key_Y); + + int combo6_key_X = halfW - bottom_key_spacing * scale * 2.2f; + int combo6_key_Y = yres / 2; + initTouchPos(g_Config.touchCombo6, combo6_key_X, combo6_key_Y); + + int combo7_key_X = halfW - bottom_key_spacing * scale * 3.2f; + int combo7_key_Y = yres / 2; + initTouchPos(g_Config.touchCombo7, combo7_key_X, combo7_key_Y); + + int combo8_key_X = halfW - bottom_key_spacing * scale * 1.2f; + int combo8_key_Y = yres / 3; + initTouchPos(g_Config.touchCombo8, combo8_key_X, combo8_key_Y); + + int combo9_key_X = halfW - bottom_key_spacing * scale * 2.2f; + int combo9_key_Y = yres / 3; + initTouchPos(g_Config.touchCombo9, combo9_key_X, combo9_key_Y); } -UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause) { +UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause, ControlMapper* controllMapper) { using namespace UI; AnchorLayout *root = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT)); @@ -764,13 +716,11 @@ UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause) { const int halfW = xres / 2; const ImageID roundImage = g_Config.iTouchButtonStyle ? ImageID("I_ROUND_LINE") : ImageID("I_ROUND"); - const ImageID rectImage = g_Config.iTouchButtonStyle ? ImageID("I_RECT_LINE") : ImageID("I_RECT"); const ImageID shoulderImage = g_Config.iTouchButtonStyle ? ImageID("I_SHOULDER_LINE") : ImageID("I_SHOULDER"); const ImageID dirImage = g_Config.iTouchButtonStyle ? ImageID("I_DIR_LINE") : ImageID("I_DIR"); const ImageID stickImage = g_Config.iTouchButtonStyle ? ImageID("I_STICK_LINE") : ImageID("I_STICK"); const ImageID stickBg = g_Config.iTouchButtonStyle ? ImageID("I_STICK_BG_LINE") : ImageID("I_STICK_BG"); - static const ImageID comboKeyImages[5] = { ImageID("I_1"), ImageID("I_2"), ImageID("I_3"), ImageID("I_4"), ImageID("I_5") }; auto addPSPButton = [=](int buttonBit, const char *key, ImageID bgImg, ImageID bgDownImg, ImageID img, const ConfigTouchPos &touch, ButtonOffset off = { 0, 0 }) -> PSPButton * { if (touch.show) { @@ -778,21 +728,21 @@ UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause) { } return nullptr; }; - auto addComboKey = [=](int buttonBit, const char *key, bool toggle, ImageID bgImg, ImageID bgDownImg, ImageID img, const ConfigTouchPos &touch) -> ComboKey * { - if (touch.show) { - return root->Add(new ComboKey(buttonBit, key, toggle, bgImg, bgDownImg, img, touch.scale, buttonLayoutParams(touch))); - } - return nullptr; - }; auto addBoolButton = [=](bool *value, const char *key, ImageID bgImg, ImageID bgDownImg, ImageID img, const ConfigTouchPos &touch) -> BoolButton * { if (touch.show) { return root->Add(new BoolButton(value, key, bgImg, bgDownImg, img, touch.scale, buttonLayoutParams(touch))); } return nullptr; }; - auto addFPSLimitButton = [=](FPSLimit value, const char *key, ImageID bgImg, ImageID bgDownImg, ImageID img, const ConfigTouchPos &touch) -> FPSLimitButton * { + auto addComboKey = [=](const ConfigCustomButton& cfg, const char *key, const ConfigTouchPos &touch) -> ComboKey * { + using namespace CustomKey; if (touch.show) { - return root->Add(new FPSLimitButton(value, key, bgImg, bgDownImg, img, touch.scale, buttonLayoutParams(touch))); + auto aux = root->Add(new ComboKey(cfg.key, key, cfg.toggle, controllMapper, + g_Config.iTouchButtonStyle == 0 ? comboKeyShapes[cfg.shape].i : comboKeyShapes[cfg.shape].l, comboKeyShapes[cfg.shape].i, + comboKeyImages[cfg.image].i, touch.scale, buttonLayoutParams(touch))); + aux->SetAngle(comboKeyImages[cfg.image].r, comboKeyShapes[cfg.shape].r); + aux->FlipImageH(comboKeyShapes[cfg.shape].f); + return aux; } return nullptr; }; @@ -825,28 +775,6 @@ UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause) { }); } - if (g_Config.touchRapidFireKey.show) { - auto rapidFire = root->Add(new RapidFireButton("Rapid fire button", rectImage, ImageID("I_RECT"), ImageID("I_ARROW"), g_Config.touchRapidFireKey.scale, buttonLayoutParams(g_Config.touchRapidFireKey))); - rapidFire->SetAngle(90.0f, 180.0f); - } - - if (g_Config.touchAnalogRotationCWKey.show) { - auto analogRotationCC = root->Add(new AnalogRotationButton(true, "Analog clockwise rotation button", rectImage, ImageID("I_RECT"), ImageID("I_ARROW"), g_Config.touchAnalogRotationCWKey.scale, buttonLayoutParams(g_Config.touchAnalogRotationCWKey))); - analogRotationCC->SetAngle(190.0f, 180.0f); - } - - if (g_Config.touchAnalogRotationCCWKey.show) { - auto analogRotationCCW = root->Add(new AnalogRotationButton(false, "Analog counter clockwise rotation button", rectImage, ImageID("I_RECT"), ImageID("I_ARROW"), g_Config.touchAnalogRotationCCWKey.scale, buttonLayoutParams(g_Config.touchAnalogRotationCCWKey))); - analogRotationCCW->SetAngle(350.0f, 180.0f); - } - - FPSLimitButton *speed1 = addFPSLimitButton(FPSLimit::CUSTOM1, "Alternate speed 1 button", rectImage, ImageID("I_RECT"), ImageID("I_ARROW"), g_Config.touchSpeed1Key); - if (speed1) - speed1->SetAngle(170.0f, 180.0f); - FPSLimitButton *speed2 = addFPSLimitButton(FPSLimit::CUSTOM2, "Alternate speed 2 button", rectImage, ImageID("I_RECT"), ImageID("I_ARROW"), g_Config.touchSpeed2Key); - if (speed2) - speed2->SetAngle(190.0f, 180.0f); - addPSPButton(CTRL_LTRIGGER, "Left shoulder button", shoulderImage, ImageID("I_SHOULDER"), ImageID("I_L"), g_Config.touchLKey); PSPButton *rTrigger = addPSPButton(CTRL_RTRIGGER, "Right shoulder button", shoulderImage, ImageID("I_SHOULDER"), ImageID("I_R"), g_Config.touchRKey); if (rTrigger) @@ -865,11 +793,16 @@ UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause) { root->Add(new PSPStick(stickBg, "Right analog stick", stickImage, ImageID("I_STICK"), 1, g_Config.touchRightAnalogStick.scale, buttonLayoutParams(g_Config.touchRightAnalogStick))); } - addComboKey(g_Config.iCombokey0, "Combo 1 button", g_Config.bComboToggle0, roundImage, ImageID("I_ROUND"), comboKeyImages[0], g_Config.touchCombo0); - addComboKey(g_Config.iCombokey1, "Combo 2 button", g_Config.bComboToggle1, roundImage, ImageID("I_ROUND"), comboKeyImages[1], g_Config.touchCombo1); - addComboKey(g_Config.iCombokey2, "Combo 3 button", g_Config.bComboToggle2, roundImage, ImageID("I_ROUND"), comboKeyImages[2], g_Config.touchCombo2); - addComboKey(g_Config.iCombokey3, "Combo 4 button", g_Config.bComboToggle3, roundImage, ImageID("I_ROUND"), comboKeyImages[3], g_Config.touchCombo3); - addComboKey(g_Config.iCombokey4, "Combo 5 button", g_Config.bComboToggle4, roundImage, ImageID("I_ROUND"), comboKeyImages[4], g_Config.touchCombo4); + addComboKey(g_Config.CustomKey0, "Custom 1 button", g_Config.touchCombo0); + addComboKey(g_Config.CustomKey1, "Custom 2 button", g_Config.touchCombo1); + addComboKey(g_Config.CustomKey2, "Custom 3 button", g_Config.touchCombo2); + addComboKey(g_Config.CustomKey3, "Custom 4 button", g_Config.touchCombo3); + addComboKey(g_Config.CustomKey4, "Custom 5 button", g_Config.touchCombo4); + addComboKey(g_Config.CustomKey5, "Custom 6 button", g_Config.touchCombo5); + addComboKey(g_Config.CustomKey6, "Custom 7 button", g_Config.touchCombo6); + addComboKey(g_Config.CustomKey7, "Custom 8 button", g_Config.touchCombo7); + addComboKey(g_Config.CustomKey8, "Custom 9 button", g_Config.touchCombo8); + addComboKey(g_Config.CustomKey9, "Custom 10 button", g_Config.touchCombo9); return root; } diff --git a/UI/GamepadEmu.h b/UI/GamepadEmu.h index d6fc612a8e..20c1a72a2d 100644 --- a/UI/GamepadEmu.h +++ b/UI/GamepadEmu.h @@ -23,6 +23,7 @@ #include "Common/UI/View.h" #include "Common/UI/ViewGroup.h" #include "Core/CoreParameter.h" +#include "UI/EmuScreen.h" class GamepadView : public UI::View { public: @@ -86,41 +87,6 @@ private: bool *value_; }; -class FPSLimitButton : public MultiTouchButton { -public: - FPSLimitButton(FPSLimit limit, const char *key, ImageID bgImg, ImageID bgDownImg, ImageID img, float scale, UI::LayoutParams *layoutParams) - : MultiTouchButton(key, bgImg, bgDownImg, img, scale, layoutParams), limit_(limit) { - - } - void Touch(const TouchInput &input) override; - bool IsDown() override; - -private: - FPSLimit limit_; -}; - -class RapidFireButton : public MultiTouchButton { -public: - RapidFireButton(const char *key, ImageID bgImg, ImageID bgDownImg, ImageID img, float scale, UI::LayoutParams *layoutParams) - : MultiTouchButton(key, bgImg, bgDownImg, img, scale, layoutParams) { - } - void Touch(const TouchInput &input) override; - bool IsDown() override; -}; - -class AnalogRotationButton : public MultiTouchButton { -public: - AnalogRotationButton(bool clockWise, const char *key, ImageID bgImg, ImageID bgDownImg, ImageID img, float scale, UI::LayoutParams *layoutParams) - : MultiTouchButton(key, bgImg, bgDownImg, img, scale, layoutParams), clockWise_(clockWise) { - } - void Touch(const TouchInput &input) override; - void Update() override; - -private: - bool autoRotating_ = false; - bool clockWise_; -}; - class PSPButton : public MultiTouchButton { public: PSPButton(int pspButtonBit, const char *key, ImageID bgImg, ImageID bgDownImg, ImageID img, float scale, UI::LayoutParams *layoutParams) @@ -196,18 +162,125 @@ private: //initializes the layout from Config. if a default layout does not exist, //it sets up default values void InitPadLayout(float xres, float yres, float globalScale = 1.15f); -UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause); +UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause, ControlMapper* controllMapper); const int D_pad_Radius = 50; const int baseActionButtonSpacing = 60; class ComboKey : public MultiTouchButton { public: - ComboKey(int pspButtonBit, const char *key, bool toggle, ImageID bgImg, ImageID bgDownImg, ImageID img, float scale, UI::LayoutParams *layoutParams) - : MultiTouchButton(key, bgImg, bgDownImg, img, scale, layoutParams), pspButtonBit_(pspButtonBit), toggle_(toggle) { + ComboKey(uint64_t pspButtonBit, const char *key, bool toggle, ControlMapper* controllMapper, ImageID bgImg, ImageID bgDownImg, ImageID img, float scale, UI::LayoutParams *layoutParams) + : MultiTouchButton(key, bgImg, bgDownImg, img, scale, layoutParams), pspButtonBit_(pspButtonBit), toggle_(toggle), controllMapper_(controllMapper), on_(false) { } void Touch(const TouchInput &input) override; + bool IsDown() override; private: - int pspButtonBit_; + uint64_t pspButtonBit_; bool toggle_; + ControlMapper* controllMapper_; + bool on_; +}; + +// Just edit this to add new image, shape or button function +namespace CustomKey { + // Image list + struct keyImage { + const char* n; // UI name + ImageID i; // ImageID + float r; // Rotation angle in degree + }; + static const keyImage comboKeyImages[] = { + { "1", ImageID("I_1"), 0.0f }, + { "2", ImageID("I_2"), 0.0f }, + { "3", ImageID("I_3"), 0.0f }, + { "4", ImageID("I_4"), 0.0f }, + { "5", ImageID("I_5"), 0.0f }, + { "6", ImageID("I_6"), 0.0f }, + { "A", ImageID("I_A"), 0.0f }, + { "B", ImageID("I_B"), 0.0f }, + { "C", ImageID("I_C"), 0.0f }, + { "D", ImageID("I_D"), 0.0f }, + { "E", ImageID("I_E"), 0.0f }, + { "F", ImageID("I_F"), 0.0f }, + { "Circle", ImageID("I_CIRCLE"), 0.0f }, + { "Cross", ImageID("I_CROSS"), 0.0f }, + { "Square", ImageID("I_SQUARE"), 0.0f }, + { "Triangle", ImageID("I_TRIANGLE"), 0.0f }, + { "L", ImageID("I_L"), 0.0f }, + { "R", ImageID("I_R"), 0.0f }, + { "Start", ImageID("I_START"), 0.0f }, + { "Select", ImageID("I_SELECT"), 0.0f }, + { "Plus", ImageID("I_CROSS"), 45.0f }, + { "Rhombus", ImageID("I_SQUARE"), 45.0f }, + { "Down Triangle", ImageID("I_TRIANGLE"), 180.0f }, + { "Arrow up", ImageID("I_ARROW"), 90.0f}, + { "Arrow down", ImageID("I_ARROW"), 270.0f}, + { "Arrow left", ImageID("I_ARROW"), 0.0f}, + { "Arrow right", ImageID("I_ARROW"), 180.0f}, + { "Gear", ImageID("I_GEAR"), 0.0f}, + }; + + // Shape list + struct keyShape { + const char* n; // UI name + ImageID i; // ImageID + ImageID l; // ImageID line version + float r; // Rotation angle in dregree + bool f; // Flip Horizontally + }; + static const keyShape comboKeyShapes[] = { + { "Circle", ImageID("I_ROUND"), ImageID("I_ROUND_LINE"), 0.0f, false }, + { "Rectangle", ImageID("I_RECT"), ImageID("I_RECT_LINE"), 0.0f, false }, + { "Vertical Rectangle", ImageID("I_RECT"), ImageID("I_RECT_LINE"), 90.0f, false }, + { "L button", ImageID("I_SHOULDER"), ImageID("I_SHOULDER_LINE"), 0.0f, false }, + { "R button", ImageID("I_SHOULDER"), ImageID("I_SHOULDER_LINE"), 0.0f, true }, + { "Arrow up", ImageID("I_DIR"), ImageID("I_DIR_LINE"), 270.0f, false }, + { "Arrow down", ImageID("I_DIR"), ImageID("I_DIR_LINE"), 90.0f, false }, + { "Arrow left", ImageID("I_DIR"), ImageID("I_DIR_LINE"), 180.0f, false }, + { "Arrow right", ImageID("I_DIR"), ImageID("I_DIR_LINE"), 0.0f, false }, + }; + + // Button list + struct keyList { + const char* n; // UI name + ImageID i; // UI ImageID + uint32_t c; // Key code + }; + static const keyList comboKeyList[] = { + { "Square", ImageID("I_SQUARE"), CTRL_SQUARE }, + { "Triangle", ImageID("I_TRIANGLE"), CTRL_TRIANGLE }, + { "Circle", ImageID("I_CIRCLE"), CTRL_CIRCLE }, + { "Cross", ImageID("I_CROSS"), CTRL_CROSS }, + { "Up", ImageID::invalid(), CTRL_UP }, + { "Down", ImageID::invalid(), CTRL_DOWN }, + { "Left", ImageID::invalid(), CTRL_LEFT }, + { "Right", ImageID::invalid(), CTRL_RIGHT }, + { "Start", ImageID("I_START"), CTRL_START }, + { "Select", ImageID("I_SELECT"), CTRL_SELECT }, + { "L", ImageID("I_L"), CTRL_LTRIGGER }, + { "R", ImageID("I_R"), CTRL_RTRIGGER }, + { "RapidFire", ImageID::invalid(), VIRTKEY_RAPID_FIRE }, + { "Unthrottle", ImageID::invalid(), VIRTKEY_UNTHROTTLE }, + { "SpeedToggle", ImageID::invalid(), VIRTKEY_SPEED_TOGGLE }, + { "Rewind", ImageID::invalid(), VIRTKEY_REWIND }, + { "Save State", ImageID::invalid(), VIRTKEY_SAVE_STATE }, + { "Load State", ImageID::invalid(), VIRTKEY_LOAD_STATE }, + { "Next Slot", ImageID::invalid(), VIRTKEY_NEXT_SLOT }, + { "Toggle Fullscreen", ImageID::invalid(), VIRTKEY_TOGGLE_FULLSCREEN }, + { "Alt speed 1", ImageID::invalid(), VIRTKEY_SPEED_CUSTOM1 }, + { "Alt speed 2", ImageID::invalid(), VIRTKEY_SPEED_CUSTOM2 }, + { "Texture Dumping", ImageID::invalid(), VIRTKEY_TEXTURE_DUMP }, + { "Texture Replacement", ImageID::invalid(), VIRTKEY_TEXTURE_REPLACE }, + { "Screenshot", ImageID::invalid(), VIRTKEY_SCREENSHOT }, + { "Mute toggle", ImageID::invalid(), VIRTKEY_MUTE_TOGGLE }, + { "OpenChat", ImageID::invalid(), VIRTKEY_OPENCHAT }, + { "Auto Analog Rotation (CW)", ImageID::invalid(), VIRTKEY_ANALOG_ROTATE_CW }, + { "Auto Analog Rotation (CCW)", ImageID::invalid(), VIRTKEY_ANALOG_ROTATE_CCW }, + { "Pause", ImageID::invalid(), VIRTKEY_PAUSE }, + { "DevMenu", ImageID::invalid(), VIRTKEY_DEVMENU }, +#ifndef MOBILE_DEVICE + { "Record", ImageID::invalid(), VIRTKEY_RECORD }, +#endif + }; + static_assert(ARRAY_SIZE(comboKeyList) <= 64, "Too many key for a uint64_t bit mask"); }; diff --git a/UI/TouchControlLayoutScreen.cpp b/UI/TouchControlLayoutScreen.cpp index 25a5a07df0..3f040f5ae3 100644 --- a/UI/TouchControlLayoutScreen.cpp +++ b/UI/TouchControlLayoutScreen.cpp @@ -333,6 +333,7 @@ void ControlLayoutView::Touch(const TouchInput &touch) { } void ControlLayoutView::CreateViews() { + using namespace CustomKey; const Bounds &bounds = GetBounds(); if (bounds.w == 0.0f || bounds.h == 0.0f) { // Layout hasn't happened yet, return. @@ -356,8 +357,6 @@ void ControlLayoutView::CreateViews() { ImageID stickBg = g_Config.iTouchButtonStyle ? ImageID("I_STICK_BG_LINE") : ImageID("I_STICK_BG"); ImageID roundImage = g_Config.iTouchButtonStyle ? ImageID("I_ROUND_LINE") : ImageID("I_ROUND"); - const ImageID comboKeyImages[5] = { ImageID("I_1"), ImageID("I_2"), ImageID("I_3"), ImageID("I_4"), ImageID("I_5") }; - auto addDragDropButton = [&](ConfigTouchPos &pos, const char *key, ImageID bgImg, ImageID img) { DragDropButton *b = nullptr; if (pos.show) { @@ -377,22 +376,6 @@ void ControlLayoutView::CreateViews() { if (auto *unthrottle = addDragDropButton(g_Config.touchUnthrottleKey, "Unthrottle button", rectImage, ImageID("I_ARROW"))) { unthrottle->SetAngle(180.0f); } - if (auto *speed1 = addDragDropButton(g_Config.touchSpeed1Key, "Alternate speed 1 button", rectImage, ImageID("I_ARROW"))) { - speed1->SetAngle(170.0f, 180.0f); - } - if (auto *speed2 = addDragDropButton(g_Config.touchSpeed2Key, "Alternate speed 2 button", rectImage, ImageID("I_ARROW"))) { - speed2->SetAngle(190.0f, 180.0f); - } - if (auto *rapidFire = addDragDropButton(g_Config.touchRapidFireKey, "Rapid fire button", rectImage, ImageID("I_ARROW"))) { - rapidFire->SetAngle(90.0f, 180.0f); - } - if (auto *analogRotationCW = addDragDropButton(g_Config.touchAnalogRotationCWKey, "Analog clockwise rotation button", rectImage, ImageID("I_ARROW"))) { - analogRotationCW->SetAngle(190.0f, 180.0f); - } - if (auto *analogRotationCCW = addDragDropButton(g_Config.touchAnalogRotationCCWKey, "Analog counter clockwise rotation button", rectImage, ImageID("I_ARROW"))) { - analogRotationCCW->SetAngle(350.0f, 180.0f); - } - addDragDropButton(g_Config.touchLKey, "Left shoulder button", shoulderImage, ImageID("I_L")); if (auto *rbutton = addDragDropButton(g_Config.touchRKey, "Right shoulder button", shoulderImage, ImageID("I_R"))) { rbutton->FlipImageH(true); @@ -400,11 +383,27 @@ void ControlLayoutView::CreateViews() { addDragDropButton(g_Config.touchAnalogStick, "Left analog stick", stickBg, stickImage); addDragDropButton(g_Config.touchRightAnalogStick, "Right analog stick", stickBg, stickImage); - addDragDropButton(g_Config.touchCombo0, "Combo 1 button", roundImage, comboKeyImages[0]); - addDragDropButton(g_Config.touchCombo1, "Combo 2 button", roundImage, comboKeyImages[1]); - addDragDropButton(g_Config.touchCombo2, "Combo 3 button", roundImage, comboKeyImages[2]); - addDragDropButton(g_Config.touchCombo3, "Combo 4 button", roundImage, comboKeyImages[3]); - addDragDropButton(g_Config.touchCombo4, "Combo 5 button", roundImage, comboKeyImages[4]); + + auto addDragComboKey = [&](ConfigTouchPos &pos, const char *key, const ConfigCustomButton& cfg) { + DragDropButton *b = nullptr; + if (pos.show) { + b = new DragDropButton(pos, key, g_Config.iTouchButtonStyle == 0 ? comboKeyShapes[cfg.shape].i : comboKeyShapes[cfg.shape].l, comboKeyImages[cfg.image].i, bounds); + b->FlipImageH(comboKeyShapes[cfg.shape].f); + b->SetAngle(comboKeyImages[cfg.image].r, comboKeyShapes[cfg.shape].r); + controls_.push_back(b); + } + return b; + }; + addDragComboKey(g_Config.touchCombo0, "Custom 1 button", g_Config.CustomKey0); + addDragComboKey(g_Config.touchCombo1, "Custom 2 button", g_Config.CustomKey1); + addDragComboKey(g_Config.touchCombo2, "Custom 3 button", g_Config.CustomKey2); + addDragComboKey(g_Config.touchCombo3, "Custom 4 button", g_Config.CustomKey3); + addDragComboKey(g_Config.touchCombo4, "Custom 5 button", g_Config.CustomKey4); + addDragComboKey(g_Config.touchCombo5, "Custom 6 button", g_Config.CustomKey5); + addDragComboKey(g_Config.touchCombo6, "Custom 7 button", g_Config.CustomKey6); + addDragComboKey(g_Config.touchCombo7, "Custom 8 button", g_Config.CustomKey7); + addDragComboKey(g_Config.touchCombo8, "Custom 9 button", g_Config.CustomKey8); + addDragComboKey(g_Config.touchCombo9, "Custom 10 button", g_Config.CustomKey9); for (size_t i = 0; i < controls_.size(); i++) { Add(controls_[i]); @@ -500,7 +499,7 @@ void TouchControlLayoutScreen::CreateViews() { Choice *reset = new Choice(di->T("Reset"), "", false, new AnchorLayoutParams(leftColumnWidth, WRAP_CONTENT, 10, NONE, NONE, 84)); Choice *back = new Choice(di->T("Back"), "", false, new AnchorLayoutParams(leftColumnWidth, WRAP_CONTENT, 10, NONE, NONE, 10)); - Choice *visibility = new Choice(co->T("Visibility"), "", false, new AnchorLayoutParams(leftColumnWidth, WRAP_CONTENT, 10, NONE, NONE, 298)); + Choice *visibility = new Choice(co->T("Customize"), "", false, new AnchorLayoutParams(leftColumnWidth, WRAP_CONTENT, 10, NONE, NONE, 298)); // controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fButtonScale, 0.80, 2.0, co->T("Button Scaling"), screenManager())) // ->OnChange.Handle(this, &GameSettingsScreen::OnChangeControlScaling); diff --git a/UI/TouchControlVisibilityScreen.cpp b/UI/TouchControlVisibilityScreen.cpp index 9a6bf19a49..af88eb93e3 100644 --- a/UI/TouchControlVisibilityScreen.cpp +++ b/UI/TouchControlVisibilityScreen.cpp @@ -20,6 +20,7 @@ #include "TouchControlVisibilityScreen.h" #include "Core/Config.h" #include "Common/Data/Text/I18n.h" +#include "ComboKeyMappingScreen.h" static const int leftColumnWidth = 140; @@ -42,6 +43,7 @@ private: void TouchControlVisibilityScreen::CreateViews() { using namespace UI; + using namespace CustomKey; auto di = GetI18NCategory("Dialog"); auto co = GetI18NCategory("Controls"); @@ -70,30 +72,62 @@ void TouchControlVisibilityScreen::CreateViews() { gridsettings.fillCells = true; GridLayout *grid = vert->Add(new GridLayoutList(gridsettings, new LayoutParams(FILL_PARENT, WRAP_CONTENT))); - static const char* rightAnalogKey = "Right Analog Stick (tap to customize)"; toggles_.clear(); - toggles_.push_back({ "Circle", &g_Config.bShowTouchCircle, ImageID("I_CIRCLE") }); - toggles_.push_back({ "Cross", &g_Config.bShowTouchCross, ImageID("I_CROSS") }); - toggles_.push_back({ "Square", &g_Config.bShowTouchSquare, ImageID("I_SQUARE") }); - toggles_.push_back({ "Triangle", &g_Config.bShowTouchTriangle, ImageID("I_TRIANGLE") }); - toggles_.push_back({ "L", &g_Config.touchLKey.show, ImageID("I_L") }); - toggles_.push_back({ "R", &g_Config.touchRKey.show, ImageID("I_R") }); - toggles_.push_back({ "Start", &g_Config.touchStartKey.show, ImageID("I_START") }); - toggles_.push_back({ "Select", &g_Config.touchSelectKey.show, ImageID("I_SELECT") }); - toggles_.push_back({ "Dpad", &g_Config.touchDpad.show, ImageID::invalid() }); - toggles_.push_back({ "Analog Stick", &g_Config.touchAnalogStick.show, ImageID::invalid() }); - toggles_.push_back({ rightAnalogKey, &g_Config.touchRightAnalogStick.show, ImageID::invalid() }); - toggles_.push_back({ "Unthrottle", &g_Config.touchUnthrottleKey.show, ImageID::invalid() }); - toggles_.push_back({ "Combo0", &g_Config.touchCombo0.show, ImageID("I_1") }); - toggles_.push_back({ "Combo1", &g_Config.touchCombo1.show, ImageID("I_2") }); - toggles_.push_back({ "Combo2", &g_Config.touchCombo2.show, ImageID("I_3") }); - toggles_.push_back({ "Combo3", &g_Config.touchCombo3.show, ImageID("I_4") }); - toggles_.push_back({ "Combo4", &g_Config.touchCombo4.show, ImageID("I_5") }); - toggles_.push_back({ "Alt speed 1", &g_Config.touchSpeed1Key.show, ImageID::invalid() }); - toggles_.push_back({ "Alt speed 2", &g_Config.touchSpeed2Key.show, ImageID::invalid() }); - toggles_.push_back({ "RapidFire", &g_Config.touchRapidFireKey.show, ImageID::invalid() }); - toggles_.push_back({ "Auto Analog Rotation (CW)", &g_Config.touchAnalogRotationCWKey.show, ImageID::invalid() }); - toggles_.push_back({ "Auto Analog Rotation (CCW)", &g_Config.touchAnalogRotationCCWKey.show, ImageID::invalid() }); + toggles_.push_back({ "Circle", &g_Config.bShowTouchCircle, ImageID("I_CIRCLE"), nullptr }); + toggles_.push_back({ "Cross", &g_Config.bShowTouchCross, ImageID("I_CROSS"), nullptr }); + toggles_.push_back({ "Square", &g_Config.bShowTouchSquare, ImageID("I_SQUARE"), nullptr }); + toggles_.push_back({ "Triangle", &g_Config.bShowTouchTriangle, ImageID("I_TRIANGLE"), nullptr }); + toggles_.push_back({ "L", &g_Config.touchLKey.show, ImageID("I_L"), nullptr }); + toggles_.push_back({ "R", &g_Config.touchRKey.show, ImageID("I_R"), nullptr }); + toggles_.push_back({ "Start", &g_Config.touchStartKey.show, ImageID("I_START"), nullptr }); + toggles_.push_back({ "Select", &g_Config.touchSelectKey.show, ImageID("I_SELECT"), nullptr }); + toggles_.push_back({ "Dpad", &g_Config.touchDpad.show, ImageID::invalid(), nullptr }); + toggles_.push_back({ "Analog Stick", &g_Config.touchAnalogStick.show, ImageID::invalid(), nullptr }); + toggles_.push_back({ "Right Analog Stick", &g_Config.touchRightAnalogStick.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new RightAnalogMappingScreen()); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Unthrottle", &g_Config.touchUnthrottleKey.show, ImageID::invalid(), nullptr }); + toggles_.push_back({ "Custom 1", &g_Config.touchCombo0.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new ComboKeyScreen(0)); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Custom 2", &g_Config.touchCombo1.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new ComboKeyScreen(1)); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Custom 3", &g_Config.touchCombo2.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new ComboKeyScreen(2)); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Custom 4", &g_Config.touchCombo3.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new ComboKeyScreen(3)); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Custom 5", &g_Config.touchCombo4.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new ComboKeyScreen(4)); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Custom 6", &g_Config.touchCombo5.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new ComboKeyScreen(5)); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Custom 7", &g_Config.touchCombo6.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new ComboKeyScreen(6)); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Custom 8", &g_Config.touchCombo7.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new ComboKeyScreen(7)); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Custom 9", &g_Config.touchCombo8.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new ComboKeyScreen(8)); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Custom 10", &g_Config.touchCombo9.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new ComboKeyScreen(9)); + return UI::EVENT_DONE; + }}); auto mc = GetI18NCategory("MappableControls"); for (auto toggle : toggles_) { @@ -102,21 +136,17 @@ void TouchControlVisibilityScreen::CreateViews() { CheckBox *checkbox = new CheckBox(toggle.show, "", "", new LinearLayoutParams(50, WRAP_CONTENT)); row->Add(checkbox); - - if (toggle.key == rightAnalogKey) { - Choice *rightAnalog = new Choice(mc->T(rightAnalogKey), "", false, new LinearLayoutParams(1.0f)); - rightAnalog->SetCentered(true); - row->Add(rightAnalog)->OnClick.Handle(this, &TouchControlVisibilityScreen::RightAnalogBindScreen); + Choice *choice; + if (toggle.handle) { + choice = new Choice(std::string(mc->T(toggle.key))+mc->T(" (tap to customize)"), "", false, new LinearLayoutParams(1.0f)); + choice->OnClick.Add(toggle.handle); + } else if (toggle.img.isValid()) { + choice = new CheckBoxChoice(toggle.img, checkbox, new LinearLayoutParams(1.0f)); } else { - Choice *choice; - if (toggle.img.isValid()) { - choice = new CheckBoxChoice(toggle.img, checkbox, new LinearLayoutParams(1.0f)); - } else { - choice = new CheckBoxChoice(mc->T(toggle.key), checkbox, new LinearLayoutParams(1.0f)); - } - choice->SetCentered(true); - row->Add(choice); + choice = new CheckBoxChoice(mc->T(toggle.key), checkbox, new LinearLayoutParams(1.0f)); } + choice->SetCentered(true); + row->Add(choice); grid->Add(row); } } @@ -143,14 +173,14 @@ void RightAnalogMappingScreen::CreateViews() { vert->SetSpacing(0); static const char *rightAnalogButton[] = {"None", "L", "R", "Square", "Triangle", "Circle", "Cross", "D-pad up", "D-pad down", "D-pad left", "D-pad right", "Start", "Select"}; - + + vert->Add(new CheckBox(&g_Config.touchRightAnalogStick.show, co->T("Visible"))); vert->Add(new CheckBox(&g_Config.bRightAnalogCustom, co->T("Use custom right analog"))); PopupMultiChoice *rightAnalogUp = vert->Add(new PopupMultiChoice(&g_Config.iRightAnalogUp, mc->T("RightAn.Up"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton), mc->GetName(), screenManager())); PopupMultiChoice *rightAnalogDown = vert->Add(new PopupMultiChoice(&g_Config.iRightAnalogDown, mc->T("RightAn.Down"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton), mc->GetName(), screenManager())); PopupMultiChoice *rightAnalogLeft = vert->Add(new PopupMultiChoice(&g_Config.iRightAnalogLeft, mc->T("RightAn.Left"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton), mc->GetName(), screenManager())); PopupMultiChoice *rightAnalogRight = vert->Add(new PopupMultiChoice(&g_Config.iRightAnalogRight, mc->T("RightAn.Right"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton), mc->GetName(), screenManager())); PopupMultiChoice *rightAnalogPress = vert->Add(new PopupMultiChoice(&g_Config.iRightAnalogPress, co->T("Keep this button pressed when right analog is pressed"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton), mc->GetName(), screenManager())); - vert->Add(new CheckBox(&g_Config.touchRightAnalogStick.show, co->T("Show right analog"))); rightAnalogUp->SetEnabledPtr(&g_Config.bRightAnalogCustom); rightAnalogDown->SetEnabledPtr(&g_Config.bRightAnalogCustom); rightAnalogLeft->SetEnabledPtr(&g_Config.bRightAnalogCustom); diff --git a/UI/TouchControlVisibilityScreen.h b/UI/TouchControlVisibilityScreen.h index 04be4a1872..c3a7df1613 100644 --- a/UI/TouchControlVisibilityScreen.h +++ b/UI/TouchControlVisibilityScreen.h @@ -28,6 +28,7 @@ struct TouchButtonToggle { const char *key; bool *show; ImageID img; + std::function handle; }; class TouchControlVisibilityScreen : public UIDialogScreenWithBackground { diff --git a/android/assets/ui_atlas.meta b/android/assets/ui_atlas.meta index fcb370adba..d5adf2b26c 100644 Binary files a/android/assets/ui_atlas.meta and b/android/assets/ui_atlas.meta differ diff --git a/android/assets/ui_atlas.zim b/android/assets/ui_atlas.zim index 5fa4ef3878..890802642d 100644 Binary files a/android/assets/ui_atlas.zim and b/android/assets/ui_atlas.zim differ diff --git a/assets/ui_atlas.meta b/assets/ui_atlas.meta index fcb370adba..d5adf2b26c 100644 Binary files a/assets/ui_atlas.meta and b/assets/ui_atlas.meta differ diff --git a/assets/ui_atlas.zim b/assets/ui_atlas.zim index 5fa4ef3878..890802642d 100644 Binary files a/assets/ui_atlas.zim and b/assets/ui_atlas.zim differ diff --git a/atlasscript.txt b/atlasscript.txt index 3aa700a8b2..96aef83457 100644 --- a/atlasscript.txt +++ b/atlasscript.txt @@ -51,4 +51,10 @@ image I_FLAG_KO source_assets/image/flag_ko.png copy image I_FULLSCREEN source_assets/image/fullscreen.png copy image I_RESTORE source_assets/image/restore.png copy image I_SDCARD source_assets/image/sdcard.png copy -image I_HOME source_assets/image/home.png copy \ No newline at end of file +image I_HOME source_assets/image/home.png copy +image I_A source_assets/image/a.png copy +image I_B source_assets/image/b.png copy +image I_C source_assets/image/c.png copy +image I_D source_assets/image/d.png copy +image I_E source_assets/image/e.png copy +image I_F source_assets/image/f.png copy diff --git a/korean.txt b/korean.txt index d225e670a5..e48b5a7c0c 100644 --- a/korean.txt +++ b/korean.txt @@ -739,3 +739,1077 @@ ko_KR = "KOREAN" th_TH = "THAI" zh_TW = "CHINESE_TRADITIONAL" zh_CN = "CHINESE_SIMPLIFIED" +[Audio] +Alternate speed volume = 대체 속도 볼륨 +Audio backend = 오디오 처리자 (재시작 필요) +AudioBufferingForBluetooth = 블루투스 친화적 버퍼링 (느림) +Auto = 자동 +Device = 장치 +DSound (compatible) = DSound (호환됨) +Enable Sound = 사운드 활성화 +Global volume = 전역 볼륨 +Microphone = Microphone +Microphone Device = Microphone device +Mute = 음소거 +Switch on new audio device = 새로운 오디오 장치로 전환 +Use global volume = 전역 볼륨 사용 +WASAPI (fast) = WASAPI (빠름) + +[Controls] +Analog auto-rotation speed = 아날로그 자동 회전 속도 +Analog Axis Sensitivity = 아날로그 축 민감도 +Analog Limiter = 아날로그 제한 +Analog Mapper High End = 아날로그 매퍼 high-end (축 감도) +Analog Mapper Low End = 아날로그 매퍼 low-end (데드존 반전) +Analog Mapper Mode = 아날로그 매퍼 모드 +Analog Stick = 아날로그 스틱 +AnalogLimiter Tip = 아날로그 제한 버튼이 눌러졌을 때 아날로그를 제한합니다. +Auto = 자동 +Auto-centering analog stick = 아날로그 스틱 자동으로 중앙 고정 +Auto-hide buttons after seconds = 버튼 자동 숨김 +Binds = Binds +Button Opacity = 버튼 투명도 +Button style = 버튼 스타일 +Calibrate D-Pad = 십자 패드 보정 +Calibration = 보정 +Classic = 클래식 +Combo Key Setting = 콤보 키 설정 +Combo Key Setup = 콤보 키 설정하기 +Confine Mouse = 창/화면 안에 커서를 가두기 +Control Mapping = 컨트롤 맵핑 +Custom layout... = 터치 컨트롤 레이아웃 편집... +Customize tilt = 기울기 사용자화... +D-PAD = 십자 패드 +Deadzone Radius = 데드존 범위 +DInput Analog Settings = DInput 아날로그 설정 (다이렉트 인풋) +Disable D-Pad diagonals (4-way touch) = 십자 패드 대각선 비활성 (4방향 터치) +Glowing borders = 빛나는 테두리 +HapticFeedback = 햅틱 피드백 (진동) +Ignore gamepads when not focused = 창이 활성화 되지 않았을 때 게임패드 무시 +Ignore Windows Key = 윈도우 키 무시 +Invert Axes = 축 반전 +Invert Tilt along X axis = X축 기울기 반전 +Invert Tilt along Y axis = Y축 기울기 반전 +Keep this button pressed when right analog is pressed = 오른쪽 아날로그가 눌렸을 때 이 버튼을 눌리게끔 유지 +Keyboard = 키보드 조작 설정 +L/R Trigger Buttons = L/R 트리거 버튼 +Landscape = 가로 +Landscape Auto = 가로 자동 +Landscape Reversed = 가로 반전 +Mouse = 마우스 설정 +Mouse sensitivity = 마우스 민감도 +Mouse smoothing = 마우스 가속도(Smoothing) +MouseControl Tip = 'M' 아이콘을 눌러 조작 매핑 화면에 들어가 마우스를 매핑할 수 있습니다. +None (Disabled) = 없음 (비활성) +Off = 끄기 +OnScreen = 화면 터치 컨트롤 +Portrait = 세로 +Portrait Reversed = 세로 반전 +PSP Action Buttons = PSP 액션 버튼 +Screen Rotation = 화면 회전 +seconds, 0 : off = 초 단위, 0 : 끄기 +Sensitivity = 민감도 +Show right analog = 오른쪽 아날로그 보기 +Show Touch Pause Menu Button = 일시 정지 메뉴 버튼 표시 +Thin borders = 얇은 테두리 +Tilt Base Radius = Tilt base radius +Tilt Input Type = 기울기 입력 방식 +Tilt Sensitivity along X axis = X축 기울기 민감도 +Tilt Sensitivity along Y axis = Y축 기울기 민감도 +To Calibrate = 보정하려면, 기기를 평평한 곳에 놓고 "보정"을 눌러주십시오. +Touch Control Visibility = 터치 컨트롤 표시 +Use custom right analog = 사용자 정의 오른쪽 아날로그 사용 +Use Mouse Control = 마우스 사용하기 +Visibility = 표시 +X = X +X + Y = X + Y +XInput Analog Settings = XInput 아날로그 설정 (Xbox 계열 컨트롤러) +Y = Y + +[CwCheats] +Cheats = 치트 +Edit Cheat File = 치트 파일 편집 +Enable/Disable All = 모든 치트 활성화/비활성화 +Import Cheats = 치트 가져오기 (cheat.db에서) +Options = 옵션 +Refresh Rate = 재생률 + +[DesktopUI] +# If your language does not show well with the default font, you can use Font to specify a different one. +# Just add it to your language's ini file and uncomment it (remove the # by Font). +Font = NanumGothic +About PPSSPP... = PPSSPP 정보(&A)... +Auto = 자동(&A) +Backend = 렌더링 처리자(&B) (PPSSPP 재시작) +Bicubic = 쌍입방(&B) +Break = 중단 +Break on Load = 불러올 때 중단 +Buffered Rendering = 버퍼링된 렌더링(&B) +Buy Gold = 골드 버전 구매(&G) +Control Mapping... = 컨트롤 맵핑(&O)... +Debugging = 디버그(&D) +Deposterize = 색조 융합(&D) +Direct3D9 = Direct3D 9(&D) +Direct3D11 = Direct3D &11 +Disassembly = 역어셈블리(&D)... +Discord = Discord +Display Layout Editor = 화면 레이아웃 편집기... +Display Rotation = 화면 회전 +Dump Next Frame to Log = 로그에 다음 프레임 덤프(&U) +Emulation = 에뮬레이션(&E) +Enable Chat = 대화 활성화 +Enable Cheats = 치트 활성화(&C) +Enable Sound = 사운드 활성화(&O) +Exit = 종료(&X) +Extract File... = 파일 추출(&X)... +File = 파일(&F) +Frame Skipping = 프레임 생략(&F) +Frame Skipping Type = 프레임 생략 유형 +Fullscreen = 전체 화면(&L) +Game Settings = 게임 설정(&G) +GE Debugger... = GE 디버거(&R)... +GitHub = Git&Hub +Hardware Transform = 하드웨어 변환(&H) +Help = 도움말(&H) +Hybrid = 혼합(&H) +Hybrid + Bicubic = 혼합 + 쌍입방(&Y) +Ignore Illegal Reads/Writes = 잘못된 읽기/쓰기 무시(&I) +Ignore Windows Key = 윈도우 키 무시 +Keep PPSSPP On Top = PPSSPP 항상 위에 표시(&K) +Landscape = 가로 +Landscape reversed = 가로 반전 +Language... = 언어(&N)... +Linear = 선형 필터링(&L) +Load = 불러오기(&L)... +Load .sym File... = sym 파일 불러오기(&A)... +Load Map File... = 맵 파일 불러오기(&M)... +Load State = 상태 불러오기(&O) +Load State File... = 상태 파일 불러오기(&L)... +Log Console = 콘솔 로그(&L) +Memory View... = 메모리 뷰(&V)... +More Settings... = 기타 설정(&M)... +Nearest = 근접 필터링(&N) +Non-Buffered Rendering = 버퍼 없는 렌더링(&S) +Off = 끄기(&O) +Open Directory... = 디렉터리 열기(&D)... +Open from MS:/PSP/GAME... = MS:/PSP/GAME에서 열기(&P)... +Open Memory Stick = 메모리 스틱 열기(&M) +Open New Instance = Open new instance +OpenGL = OpenGL(&O) +Pause = 일시 정지(&P) +Pause When Not Focused = 포커싱되지 않았을 때 일시 정지(&P) +Portrait = 세로 +Portrait reversed = 세로 반전 +Postprocessing Shader = 후처리 셰이더(&G) +PPSSPP Forums = PPSSPP 포럼(&F) +Record = 기록(&R) +Record Audio = 소리 녹음(&A) +Record Display = 영상 녹화(&D) +Rendering Mode = 렌더링 방식(&O) +Rendering Resolution = 렌더링 해상도(&R) +Reset = 리셋(&E) +Reset Symbol Table = 심볼 테이블 리셋(&Y) +Run = 실행(&R) +Save .sym File... = sym 파일 저장하기(&E)... +Save Map File... = 맵 파일 저장하기(&S)... +Save State = 상태 저장하기(&A) +Save State File... = 상태 파일 저장하기(&S)... +Savestate Slot = 상태 저장 슬롯(&T) +Screen Scaling Filter = 화면 크기 조절 필터(&E) +Show Debug Statistics = 디버그 통계 표시(&G) +Show FPS Counter = FPS 카운터 표시(&F) +Skip Number of Frames = 프레임 수 생략 +Skip Percent of FPS = FPS 비율 생략 +Stop = 정지(&S) +Switch UMD = UMD 교체 +Take Screenshot = 스크린샷 찍기(&T) +Texture Filtering = 텍스처 필터링(&X) +Texture Scaling = 텍스처 크기 조절(&T) +Use Lossless Video Codec (FFV1) = 무손실 비디오 코덱 사용 (FFV1)(&U) +Use output buffer for video = 비디오에 출력 버퍼 사용 +Vertex Cache = 버텍스 캐시(&V) +VSync = 수직 동기(&Y) +Vulkan = 벌칸(Vulkan) +Window Size = 창 크기(&W) +www.ppsspp.org = www.ppsspp.org 방문(&P) +xBRZ = xBRZ(&X) + +[Developer] +Allocator Viewer = 할당기(Allocator) 뷰어 (Vulkan) +Allow remote debugger = 원격 디버거 허용 +Backspace = 백스페이스 +Block address = 주소를 차단 +By Address = 주소로 +Copy savestates to memstick root = Copy save states to Memory Stick root +Create/Open textures.ini file for current game = 현재 게임의 textures.ini 파일 생성 및 열기 +Current = 현재 +Dev Tools = 개발자 도구 +DevMenu = 개발 메뉴 +Disabled JIT functionality = 비활성화 된 JIT 기능 +Draw Frametimes Graph = 프레임 레이트 그래프 그리기 +Dump Decrypted Eboot = 게임 부팅 시 복호화된 EBOOT.BIN 덤프 (암호화 되어 있는 경우) +Dump Frame GPU Commands = 프레임 GPU 명령어를 덤프 +Enable driver bug workarounds = Enable driver bug workarounds +Enable Logging = 디버그 로깅 활성화 +Enter address = 주소 입력 +FPU = FPU +Framedump tests = Framedump tests +Frame Profiler = 프레임 프로파일러 +GPU Driver Test = GPU 드라이버 테스트 +GPU Profile = GPU 프로파일 +Jit Compare = JIT 비교 +JIT debug tools = JIT 디버그 툴 +Language = 언어 +Load language ini = 언어 ini 불러오기 +Log Dropped Frame Statistics = 프레임 저하 통계 기록하기 +Log Level = 로그 깊이 +Log View = 로그 보기 +Logging Channels = 로깅 채널 +Next = 다음 +No block = 블록 없음 +Prev = 이전 +Random = 랜덤 +Replace textures = 텍스처 덮어쓰기 +Reset limited logging = Reset limited logging +RestoreDefaultSettings = 모든 설정을 다시 기본으로 복원 하시겠습니까?\n컨트롤 맵핑 설정은 변경되지 않습니다.\n\n\n이 작업은 되돌릴 수 없습니다.\n변경 사항을 적용하기 위해 PPSSPP를 재시작해 주십시오. +RestoreGameDefaultSettings = 게임 지정 설정을 다시\nPPSSPP 기본 설정으로 복원하시겠습니까? +Resume = Resume +Run CPU Tests = CPU 테스트 실행 +Save language ini = 언어 ini 저장하기 +Save new textures = 새로운 텍스처 저장 +Shader Viewer = 셰이더 뷰어 +Show Developer Menu = 개발자 메뉴 표시 +Show on-screen messages = Show on-screen messages +Stats = 상태 +System Information = 시스템 정보 +Texture Replacement = 텍스처 교체하기 +Toggle Audio Debug = 오디오 디버그 토글 +Toggle Freeze = 토글 프리징 +Touchscreen Test = 터치 스크린 테스트 +VFPU = VFPU + +[Dialog] +* PSP res = * PSP 리소스 +Active = 활성화 +Back = 뒤로 +Cancel = 취소 +Center = 중앙 +ChangingGPUBackends = GPU 처리자를 변경하기 위해서는 PPSSPP를 재시작해야 합니다. 재시작할까요? +ChangingInflightFrames = 그래픽 커멘드 버퍼링을 변경하기 위해서는 PPSSPP를 재시작해야 합니다. 재시작할까요? +Channel: = Channel: +Choose PPSSPP save folder = PPSSPP 저장 폴더 선택 +Confirm Overwrite = 데이터를 덮어쓰시겠습니까? +Confirm Save = 이 데이터를 저장하시겠습니까? +ConfirmLoad = 이 데이터를 불러오시겠습니까? +ConnectingAP = Connecting to the access point.\nPlease wait... +ConnectingPleaseWait = Connecting.\nPlease wait... +ConnectionName = Connection name +Corrupted Data = Corrupted data +Delete = 삭제 +Delete all = 전체 삭제 +Delete completed = 삭제를 완료했습니다. +DeleteConfirm = 이 데이터는 삭제됩니다.\n계속하시겠습니까? +DeleteConfirmAll = 이 게임에 대한 모든 저장 데이터를\n삭제하시겠습니까? +DeleteConfirmGame = 이 게임을 정말로 당신의 장치에서\n삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다. +DeleteConfirmGameConfig = 이 게임의 설정을 정말로 삭제하시겠습니까? +DeleteFailed = 삭제할 수 없습니다. +Deleting = 삭제 중입니다.\n잠시 기다려 주세요... +Disable All = 모두 비활성화 +Edit = Edit +Enable All = 모두 활성화 +Enter = 결정 +Finish = 완료 +Grid = 격자 +Inactive = 비활성화 +InternalError = An internal error has occurred. +Load = 불러오기 +Load completed = 불러오기를 완료했습니다. +Loading = 불러오는 중입니다.\n잠시 기다려 주세요... +LoadingFailed = 불러올 수 없습니다. +Move = 이동 +Network Connection = 네트워크 연결 +NEW DATA = 새로운 데이터 +No = 아니오 +ObtainingIP = Obtaining IP address.\nPlease wait... +OK = 확인 +Old savedata detected = 구 버전 저장 데이터 감지됨 +Options = 옵션 +Reset = 리셋 +Resize = 크기 조정 +Retry = 다시 시도 +Save = 저장하기 +Save completed = 저장을 완료했습니다. +Saving = 저장 중입니다.\n잠시 기다려 주세요... +SavingFailed = 저장할 수 없습니다. +Select = 선택 +Shift = 전환 +Snap = Snap +Space = 스페이스 +SSID = SSID +Submit = 전송 +Supported = 지원 +There is no data = 데이터가 없습니다. +Toggle All = 전체 선택 +Toggle List = Toggle list +Unsupported = 지원되지 않음 +When you save, it will load on a PSP, but not an older PPSSPP = 저장할 경우 PSP에서는 불러올 수 있지만 구 버전의 PPSSPP에서는 불러올 수 없습니다. +When you save, it will not work on outdated PSP Firmware anymore = 저장할 경우 더 이상 구 버전의 PSP 펌웨어에서는 작동하지 않을 것입니다. +Yes = 네 +Zoom = 확대 + +[Error] +7z file detected (Require 7-Zip) = 파일이 7z 형식으로 압축되어 있습니다.\n먼저 압축을 해제해 주십시오. (7-Zip 또는 WinRAR) +A PSP game couldn't be found on the disc. = 디스크에서 PSP 게임을 찾을 수 없습니다. +Cannot boot ELF located outside mountRoot. = 삽입된 Root 이외의 경로에 위치한 ELF는 부팅할 수 없습니다. +Could not save screenshot file = 스크린샷 파일을 저장할 수 없습니다. +D3D9or11 = Direct3D 9를 사용할까요? ("아니오"를 선택할 경우 Direct3D 11를 사용합니다.) +D3D11CompilerMissing = D3DCompiler_47.dll 을 찾을 수 없었습니다. 설치한 후 재시도하거나 대신 예 버튼을 눌러 Direct3D 9 를 사용할 수 있습니다. +D3D11InitializationError = Direct3D 11 초기화 오류 +D3D11Missing = 현재 사용중인 OS가 D3D11을 포함하지 않고 있습니다. 업데이트를 진행해 보십시오.\n\n예를 눌러 Direct3D 9를 대신 사용합니다. +D3D11NotSupported = 현재 사용중인 GPU가 Direct3D 11을 지원하지 않습니다.\n\n예를 눌러 Direct3D 9를 대신 사용할 수 있습니다. +Disk full while writing data = 데이터를 쓰는 도중 디스크가 가득 찼습니다. +ELF file truncated - can't load = ELF 파일이 불완전합니다 - 불러올 수 없습니다. +Error loading file = 파일 불러오는 중 오류 : +Error reading file = 파일을 읽는 동안 오류가 발생했습니다. +Failed initializing CPU/Memory = Failed initializing CPU or memory +Failed to identify file = 파일을 식별하는데 실패했습니다. +Failed to load executable: = 실행 파일을 불러오는데 실패했습니다: +File corrupt = 파일이 손상되었습니다. +Game disc read error - ISO corrupt = 게임 디스크 읽기 오류: ISO 파일이 손상되었습니다. +GenericAllStartupError = PPSSPP failed to start up with any graphics backend. Try upgrading your graphics and other drivers. +GenericBackendSwitchCrash = PPSSPP crashed while starting.\n\nThis usually means a graphics driver problem. Try upgrading your graphics drivers.\n\nGraphics backend has been switched: +GenericDirect3D9Error = Direct 3D 9 그래픽 초기화에 실패했습니다. 그래픽 드라이버와 DirectX 9 런타임을 업데이트해 보십시오.\n\nOpenGL으로 전환해 보시겠습니까?\n\오류 메시지: +GenericGraphicsError = 그래픽 오류 +GenericOpenGLError = OpenGL 그래픽 초기화에 실패했습니다. 그래픽 드라이버를 업데이트해 보십시오.\n\nDirectX 9로 전환해 보시겠습니까?\n\n오류 메시지: +GenericVulkanError = Vulkan 그래픽 초기화에 실패했습니다. 그래픽 드라이버를 업데이트해 보십시오.\n\nOpenGL으로 전환해 보시겠습니까?\n\n오류 메시지: +InsufficientOpenGLDriver = OpenGL 드라이버 지원 부족 감지!\n\n현재 PPSSPP를 실행하는데 필요한 OpenGL 2.0을 지원하지 않는 것 같습니다.\n\n당신의 GPU가 OpenGL 2.0과 호환되는지 확인해 주십시오. 호환되는 경우, 당신의 GPU 공급업체의 웹사이트에서 새로운 그래픽 드라이버를 찾아서 설치해야 합니다.\n\n자세한 내용은 https://forums.ppsspp.org 포럼을 방문하십시오. +Just a directory. = 디렉토리 입니다. +Missing key = 키가 누락되었습니다. +MsgErrorCode = Error code: +MsgErrorSavedataDataBroken = Save data was corrupt. +MsgErrorSavedataMSFull = Memory Stick full. Check your storage space. +MsgErrorSavedataNoData = Warning: no save data was found. +MsgErrorSavedataNoMS = Memory Stick not inserted. +No EBOOT.PBP, misidentified game = EBOOT.PBP가 없으면, 게임을 식별할 수 없습니다. +Not a valid disc image. = 유효한 디스크 이미지가 아닙니다. +OpenGLDriverError = OpenGL 드라이버 오류 +PPSSPP doesn't support UMD Music. = PPSSPP는 UMD 음악을 지원하지 않습니다. +PPSSPP doesn't support UMD Video. = PPSSPP는 UMD 비디오를 지원하지 않습니다. +PPSSPP plays PSP games, not PlayStation 1 or 2 games. = PPSSPP plays PSP games, not PlayStation 1 or 2 games. +PPSSPPDoesNotSupportInternet = PPSSPP는 현재 DLC, PSN, 게임 업데이트에 대한 인터넷 연결을 지원하지 않습니다. +PS1 EBOOTs are not supported by PPSSPP. = PS1 EBOOTs는 PPSSPP에서 지원되지 않습니다. +PSX game image detected. = MODE2 이미지 파일입니다. PPSSPP는 PS1 게임을 지원하지 않습니다. +RAR file detected (Require UnRAR) = 파일이 RAR 형식으로 압축되어 있습니다.\n먼저 압축을 해제해 주십시오. (UnRAR로 시도) +RAR file detected (Require WINRAR) = 파일이 RAR 형식으로 압축되어 있습니다.\n먼저 압축을 해제해 주십시오. (WinRAR로 시도) +Running slow: try frameskip, sound is choppy when slow = 느리게 작동 중입니다: 게임 소리가 제대로 재생되지 않을 경우 프레임 스킵을 시도해 보십시오. +Running slow: Try turning off Software Rendering = 느리게 작동 중입니다: 소프트웨어 렌더링 모드를 해제해 보십시오. +Save encryption failed. This save won't work on real PSP = 저장 파일 암호화에 실패했습니다. 이 저장 파일은 실제 PSP상에서 동작하지 않을 것입니다. +textures.ini filenames may not be cross-platform = 다른 운영체제의 "textures.ini" 파일을 사용할 수 없습니다. +This is a saved state, not a game. = 게임이 아닌 상태 저장 파일입니다. 게임 파일을 선택해 주십시오. +This is save data, not a game. = 게임이 아닌 저장 파일입니다. 게임 파일을 선택해 주십시오. +Unable to create cheat file, disk may be full = 치트 파일을 생성할 수 없습니다. 디스크 용량이 꽉 찼을 수도 있습니다. +Unable to initialize rendering engine. = 렌더링 엔진을 초기화할 수 없습니다. +Unable to write savedata, disk may be full = 저장 파일을 작성할 수 없습니다. 디스크 용량이 꽉 찼을 수도 있습니다. +Warning: Video memory FULL, reducing upscaling and switching to slow caching mode = 경고: 비디오 메모리가 꽉 찼습니다. 업스케일링을 줄이고 느린 캐시 모드로 전환합니다. +Warning: Video memory FULL, switching to slow caching mode = 경고: 비디오 메모리가 꽉 찼습니다. 느린 캐시 모드로 전환합니다. +ZIP file detected (Require UnRAR) = 파일이 ZIP 형식으로 압축되어 있습니다.\n먼저 압축을 해제해 주십시오. (UnRAR로 시도) +ZIP file detected (Require WINRAR) = 파일이 ZIP 형식으로 압축되어 있습니다.\n먼저 압축을 해제해 주십시오. (WinRAR로 시도) + +[Game] +Asia = 아시아 +ConfirmDelete = 삭제 +Create Game Config = 게임 설정파일 만들기 +Create Shortcut = 바로가기 만들기 +Delete Game = 게임 삭제 +Delete Game Config = 게임 설정파일 삭제 +Delete Save Data = 저장 데이터 삭제 +Europe = 유럽 +Game = 게임 +Game Settings = 게임 설정 +Homebrew = 홈브류 +Hong Kong = 홍콩 +InstallData = 데이터 설치 +Japan = 일본 +Korea = 대한민국 +MB = MB +One moment please... = 잠시만 기다려 주세요... +Play = 재생 +Remove From Recent = 최근 기록 제거 +SaveData = 저장 데이터 +Setting Background = 배경화면 설정 +Show In Folder = 폴더에 표시 +USA = 북미 +Use UI background = UI 배경화면 사용 + +[Graphics] +% of the void = 무효 영역의 백분율 +% of viewport = 뷰포트의 백분율 +%, 0:unlimited = %, 0 = 무제한 +(supersampling) = (슈퍼 샘플링) +(upscaling) = (업스케일링) +1x PSP = PSP 1배 +2x = 2배 +2x PSP = PSP 2배 +3x = 3배 +3x PSP = PSP 3배 +4x = 4배 +4x PSP = PSP 4배 +5x = 5배 +5x PSP = PSP 5배 +6x PSP = PSP 6배 +7x PSP = PSP 7배 +8x = 8배 +8x PSP = PSP 8배 +9x PSP = PSP 9배 +10x PSP = PSP 10배 +16x = 16배 +Aggressive = 급격한 +Alternative Speed = 대체 속도 +Alternative Speed 2 = 대체 속도 2 (단위 퍼센트, 0 = 무제한) +Anisotropic Filtering = 비등방성 필터링 +Auto = 자동 +Auto (1:1) = 자동 (1:1) +Auto (same as Rendering) = 자동 (렌더링 해상도와 같음) +Auto FrameSkip = 자동 프레임 생략 +Auto Scaling = 자동 스케일링 +Backend = 처리자 +Balanced = 평형 +Bicubic = 쌍입방 +BlockTransfer Tip = 몇몇 게임들의 그래픽 오류를 고치기 위해 이 설정이 필요합니다. +BlockTransferRequired = 주의 - 이 설정을 키기 위해 이 게임은 "블럭단위 전송 효과 시뮬레이트"를 사용해야 합니다. +Both = 모두 표시 +Buffer graphics commands (faster, input lag) = 버퍼 그래픽 커맨드 (빠름, 입력 렉 발생) +Buffered Rendering = 버퍼링된 렌더링 +BufferedRenderingRequired = 주의 - 이 게임은 "렌더링 모드"가 "버퍼됨" 이어야 합니다. +Camera = 카메라 +Camera Device = 카메라 장치 +Cardboard Screen Size = 화면 크기 (뷰포트의 백분율) +Cardboard Screen X Shift = X축 이동 (여백의 백분율) +Cardboard Screen Y Shift = Y축 이동 (여백의 백분율) +Cardboard VR Settings = 구글 카드보드 설정 +Cheats = 치트 +Clear Speedhack = Clear framebuffers on first use (speed hack) +ClearSpeedhack Tip = Sometimes faster (mostly on mobile devices), may cause glitches +CPU Core = CPU 코어 +Debugging = 디버깅 +DefaultCPUClockRequired = 주의 - 이 게임은 CPU 클럭이 기본 설정이어야 합니다. +Deposterize = 색조 융합 +Deposterize Tip = 업스케일링된 텍스처의 왜곡 현상 고치기 +Device = 장치 +Direct3D 9 = Direct3D 9 +Direct3D 11 = Direct3D 11 +Disable slower effects (speedup) = 느림 효과를 비활성화 (속도 상승) +Disabled = 비활성화 +Display layout editor = 화면 레이아웃 편집기 +Display Resolution (HW scaler) = 화면 해상도 (하드웨어 스케일러) +Dump next frame to log = 로그에 다음 프레임 덤프 +Enable Cardboard VR = 구글 카드보드 활성화 +FPS = FPS +Frame Rate Control = 프레임 비율 제어 +Frame Skipping = 프레임 생략 +Frame Skipping Type = 프레임 생략 유형 +FullScreen = 전체 화면 +Hack Settings = 핵 설정 (이것은 오류의 원인이 됩니다) +Hardware Tessellation = 하드웨어 테셀레이션 +Hardware Transform = 하드웨어 변환 +hardware transform error - falling back to software = 하드웨어 변환 오류 - 소프트웨어로 전환 +HardwareTessellation Tip = 하드웨어가 곡선을 그리게 하여 언제나 고정된 품질을 사용합니다. +High = 높음 +Hybrid = 혼합 +Hybrid + Bicubic = 혼합 + 쌍입방 +Ignore camera notch when centering = Ignore camera notch when centering +Internal Resolution = 내부 해상도 +Lazy texture caching = 텍스처 캐싱을 줄임 (속도 상승) +Linear = 선형 필터링 +Low = 낮음 +LowCurves = 낮은 품질의 스플라인 및 베지어 곡선 (속도 상승) +LowCurves Tip = 몇몇 게임에만 사용됩니다. 곡선의 부드러움의 정도를 조정합니다. +Lower resolution for effects (reduces artifacts) = 효과 해상도 저하 (질감 감소) +Manual Scaling = 수동 스케일링 +Medium = 중간 +Mode = 방식 +Must Restart = 이 설정을 적용하기 위해서는 PPSSPP를 재시작해 주십시오. +Native device resolution = 기본 장치 해상도 +Nearest = 근접 필터링 +No buffer = 버퍼 없음 +Non-Buffered Rendering = 버퍼 없는 렌더링 (속도 상승) +None = 없음 +Number of Frames = 프레임 수 +Off = 끄기 +OpenGL = OpenGL +Overlay Information = 오버레이 정보 +Partial Stretch = 부분 늘이기 +Percent of FPS = FPS 비율 +Performance = 성능 +Postprocessing effect = Postprocessing effects +Postprocessing Shader = 후처리 셰이더 +Recreate Activity = Recreate activity +Render duplicate frames to 60hz = 중복된 프레임을 60Hz로 렌더링 +RenderDuplicateFrames Tip = 낮은 프레임 레이트에서 동작하는 게임을 부드럽게 해 줍니다. +Rendering Mode = 렌더링 방식 +Rendering Resolution = 렌더링 해상도 +RenderingMode NonBuffered Tip = 빠르지만 몇몇 게임에서는 작동하지 않을 수 있습니다. +Retain changed textures = 변경된 텍스처를 보유 (속도 감소) +RetainChangedTextures Tip = 많은 게임들이 이 설정을 적용하면 대부분 느려지지만 몇몇 게임은 더 빨라질 수 있습니다. +Rotation = 회전 +Safe = 안전 +Screen layout = Screen layout +Screen Scaling Filter = 화면 크기 조절 필터 +Show Debug Statistics = 디버그 통계 표시 +Show FPS Counter = FPS 카운터 표시 +Simulate Block Transfer = 블록 전송 효과를 시뮬레이션 +SoftGPU Tip = 현재 매우 느림 +Software Rendering = 소프트웨어 렌더링 (실험적) +Software Skinning = 소프트웨어 스키닝 +SoftwareSkinning Tip = 스키닝 된 모델을 합쳐 CPU에 그립니다. 대부분에 게임이 빨라집니다. +Speed = 속도 +Stretching = 늘이기 +Texture Filter = 텍스처 필터링 +Texture Filtering = 텍스처 필터링 +Texture Scaling = 텍스처 크기 조절 +Texture Shader = Texture shader +Turn off Hardware Tessellation - unsupported = "하드웨어 테셀레이션" 끄기: 지원하지 않음 +Unlimited = 무제한 +Up to 1 = 최대 1까지 +Up to 2 = 최대 2까지 +Upscale Level = 확대 수준 +Upscale Type = 확대 종류 +UpscaleLevel Tip = CPU가 할 일이 많아집니다 - 또한 끊김 현상을 줄이기 위해 스케일링이 늦어질 수 있습니다. +Use all displays = 모든 디스플레이 사용하기 +Vertex Cache = 버텍스 캐시 +VertexCache Tip = 빠르지만 잠시동안 화면이 깜빡거릴 수 있습니다. +VSync = 수직 동기 +Vulkan = 벌칸(Vulkan) +Window Size = 창 크기 +xBRZ = xBRZ + +[InstallZip] +Delete ZIP file = ZIP 파일 삭제 +Install = 설치 +Install game from ZIP file? = ZIP 파일로부터 게임을 설치하시겠습니까? +Install textures from ZIP file? = ZIP 파일로부터 텍스처팩을 설치하시겠습니까? +Installed! = 설치되었습니다! +Texture pack doesn't support install = 이 텍스처팩의 설치는 지원하지 않습니다. +Zip archive corrupt = ZIP 파일이 손상되었습니다. +Zip file does not contain PSP software = ZIP 파일에 PSP 소프트웨어가 들어있지 않습니다. + +[KeyMapping] +Autoconfigure = 자동 설정 +Autoconfigure for device = 디바이스에 맞게 자동 설정 +Clear All = 모두 지우기 +Default All = 기본값 복원 +Map a new key for = 새로운 키 입력 +Map Key = 키 매핑 +Map Mouse = 마우스 매핑 +Test Analogs = 아날로그 테스트 +You can press ESC to cancel. = 취소하려면 ESC를 눌러주십시오. + +[MainMenu] +Browse = 찾아보기... +Buy PPSSPP Gold = PPSSPP Gold 구매 +Choose folder = 폴더 선택하기 +Credits = 만든이 +DownloadFromStore = PPSSPP 홈브류 스토어에서 다운로드하십시오. +Exit = 종료 +Game Settings = 게임 설정 +Games = 게임 +Give PPSSPP permission to access storage = 저장공간에 접근하기 위해 PPSSPP에 권한이 필요합니다. +Homebrew & Demos = 홈브류 및 데모 +How to get games = 어떻게 게임을 구할 수 있나요? +How to get homebrew & demos = 어떻게 홈브류 및 데모를 구할 수 있나요? +Load = 불러오기... +Loading... = 불러오는 중... +PinPath = 경로 고정 +PPSSPP can't load games or save right now = 현재 PPSSPP에서 게임을 불러오거나 저장할 수 없습니다 +Recent = 최근 게임 +SavesAreTemporary = 임시 저장장치에 저장하는 중 +SavesAreTemporaryGuidance = 영구적으로 사용하기 위해 PPSSPP를 기억장치에 복사해 주십시오. +SavesAreTemporaryIgnore = 무시하기 +UnpinPath = 고정 해제 +www.ppsspp.org = www.ppsspp.org + +[MainSettings] +Audio = 오디오 +Controls = 조작 +Graphics = 그래픽 +Networking = 네트워킹 +System = 시스템 +Tools = 도구 + +[MappableControls] +Alt speed 1 = 대체 속도 1 +Alt speed 2 = 대체 속도 2 +An.Down = 아날로그.하 +An.Left = 아날로그.좌 +An.Right = 아날로그.우 +An.Up = 아날로그.상 +Analog limiter = 아날로그 제한자 +Analog Stick = 아날로그 스틱 +Audio/Video Recording = 소리/영상 녹화 +Auto Analog Rotation (CCW) = 자동 아날로그 회전 (CCW) +Auto Analog Rotation (CW) = 자동 아날로그 회전 (CW) +AxisSwap = 축 스왑 +Circle = 동그라미 +Cross = 십자 +D-pad down = 방향 패드.하 +D-pad left = 방향 패드.좌 +D-pad right = 방향 패드.우 +D-pad up = 방향 패드.상 +DevMenu = 개발 메뉴 +Down = 방향 패드.하 +Dpad = 방향 패드 +Frame Advance = 프레임 건너뛰기 +Hold = 잠금 +Home = 홈 +L = L +Left = 방향 패드.좌 +Load State = 상태 불러오기 +Mute toggle = 음소거 전환 +Next Slot = 다음 슬롯 +None = 없음 +Note = 참고 +OpenChat = 대화 열기 +Pause = 일시 정지 +R = R +RapidFire = 연사 +Remote hold = 리모트 잠금 +Rewind = 되감기 +Right = 방향 패드.우 +Right Analog Stick (tap to customize) = 오른쪽 아날로그 스틱 (탭해서 사용자화) +RightAn.Down = 우측An.하 +RightAn.Left = 우측An.좌 +RightAn.Right = 우측An.우 +RightAn.Up = 우측An.상 +Rotate Analog (CCW) = 아날로그 회전 (CCW) +Rotate Analog (CW) = 아날로그 회전 (CW) +Save State = 상태 저장하기 +Screen = 화면 +Screenshot = 스크린샷 +Select = 선택 +SpeedToggle = 속도 전환 +Square = 네모 +Start = 시작 +Texture Dumping = 텍스처 덤프 +Texture Replacement = 텍스처 교체 +Toggle Fullscreen = 전체화면 고정 +Toggle mode = 토글 모드 +Triangle = 세모 +Unthrottle = 터보 +Up = 방향 패드.상 +Vol + = 볼륨 + +Vol - = 볼륨 - +Wlan = 무선랜 + +[Networking] +Adhoc Multiplayer forum = 애드혹 멀티플레이어 포럼 방문 +AdHoc Server = Ad hoc server +AdhocServer Failed to Bind Port = Ad hoc server failed to bind port +Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right +Change Mac Address = Mac 주소 변경 +Change proAdhocServer Address = PRO 애드혹 서버 IP 주소 변경 (localhost = multiple instances) +Chat = 대화 +Chat Button Position = 대화 버튼 위치 +Chat Here = 여기에 입력 +Chat Screen Position = 대화 화면 위치 +Disconnected from AdhocServer = Disconnected from ad hoc server +DNS Error Resolving = DNS error resolving +Enable built-in PRO Adhoc Server = 내장된 PRO 애드혹 서버 활성화 +Enable network chat = 네트워크 대화 활성화 +Enable networking = 네트워킹/무선 랜 활성화 (베타, 게임 작동을 방해할 수 있음) +Enable UPnP = Enable UPnP (need a few seconds to detect) +EnableQuickChat = 빠른 대화 활성화 +Enter a new PSP nickname = 새로운 PSP 별명 입력 +Enter Quick Chat 1 = 빠른 대화 1 참가 +Enter Quick Chat 2 = 빠른 대화 2 참가 +Enter Quick Chat 3 = 빠른 대화 3 참가 +Enter Quick Chat 4 = 빠른 대화 4 참가 +Enter Quick Chat 5 = 빠른 대화 5 참가 +Error = Error +Failed to Bind Localhost IP = Failed to bind localhost IP +Failed to Bind Port = Failed to bind port +Failed to connect to Adhoc Server = Failed to connect to ad hoc server +Forced First Connect = Forced first connect (faster connect) +Invalid IP or hostname = 올바르지 않은 IP 또는 호스트 이름 +Minimum Timeout = Minimum timeout (override in ms, 0 = default) +Misc = Miscellaneous (default = PSP compatibility) +Network Initialized = 네트워크 초기화됨 +Please change your Port Offset = Please change your port offset +Port offset = 포트 오프셋(0 = PSP 호환) +proAdhocServer Address: = Ad hoc server address: +Quick Chat 1 = 빠른 대화 1 +Quick Chat 2 = 빠른 대화 2 +Quick Chat 3 = 빠른 대화 3 +Quick Chat 4 = 빠른 대화 4 +Quick Chat 5 = 빠른 대화 5 +QuickChat = 빠른 대화 +Send = 보내기 +Send Discord Presence information = Discord 프로필에 PPSSPP 표시 +TCP No Delay = TCP No Delay (faster TCP) +Top Center = Top center +Top Left = Top left +Top Right = Top right +Unable to find UPnP device = Unable to find UPnP device +UPnP (port-forwarding) = UPnP (port forwarding) +UPnP need to be reinitialized = UPnP need to be reinitialized +UPnP use original port = UPnP use original port (enabled = PSP compatibility) +Validating address... = 주소 검증하는 중... +WLAN Channel = WLAN channel +You're in Offline Mode, go to lobby or online hall = 현재 오프라인 모드입니다. 로비나 온라인 홀로 돌아갑니다. + +[Pause] +Cheats = 치트 +Continue = 계속 +Create Game Config = 게임 설정파일 생성 +Delete Game Config = 게임 설정파일 제거 +Exit to menu = 종료 후 메뉴로 +Game Settings = 게임 설정 +Load State = 상태 불러오기 +Rewind = 되감기 +Save State = 상태 저장하기 +Settings = 설정 +Switch UMD = UMD 교체 + +[PostShaders] +(duplicated setting, previous slider will be used) = (duplicated setting, previous slider will be used) +4xHqGLSL = 4배 HQ GLSL (OpenGL 셰이딩 언어) +5xBR = 5xBR +5xBR-lv2 = 5xBR-lv2 +AAColor = AA 색상 +Amount = Amount +Black border = 검정 테두리 +Bloom = 블룸 +Brightness = 밝기 +Cartoon = 카툰 +ColorCorrection = 색상 교정 +Contrast = 명암 +CRT = CRT 스캔라인 +FXAA = FXAA (Fast Approximate Anti-Aliasing) +Gamma = 감마 +Grayscale = 그레이스케일 +Intensity = 강도 +InverseColors = 색 반전 +Natural = 자연 색상 +NaturalA = 자연 색상 (블러 없음) +Off = 끄기 +Power = Power +PSPColor = PSP color +Saturation = 채도 +Scanlines = 스캔라인 (CRT) +Sharpen = 선명하게 +SSAA(Gauss) = 슈퍼샘플링 AA (가우스) +Tex4xBRZ = 4xBRZ +UpscaleSpline36 = 스플라인36 확대 +VideoSmoothingAA = VideoSmoothingAA +Vignette = 비네트 + +[PSPCredits] +all the forum mods = 모든 포럼 모드 +build server = 빌드 서버 +Buy Gold = 골드 버전 구매 +check = 최고의 Wii/GC 에뮬 Dolphin 또한 확인하십시오. +CheckOutPPSSPP = 멋진 PSP 에뮬레이터 PPSSPP를 확인해 보십시오: https://www.ppsspp.org/ +contributors = 도움을 주신 분들: +created = 만든이: +Discord = Discord +info1 = PPSSPP는 교육적인 목적으로만 사용할 수 있습니다. +info2 = 설치한 게임의 소유 권리가 분명한지를 확인해 주십시오. +info3 = 해당 게임의 UMD를 소유하거나 디지털로 구매하여 플레이하십시오. +info4 = 해당 게임을 실제 PSP에 존재하는 PSN Store에서 구매해 주십시오. +info5 = PSP는 주식회사 소니의 등록 상표입니다. +iOS builds = iOS 빌드 +license = GPL 2.0+ 라이선스를 따르는 무료 소프트웨어 +list = 호환 목록, 포럼 및 개발 정보 +PPSSPP Forums = PPSSPP 포럼 +Privacy Policy = 개인 정보 정책 +Share PPSSPP = PPSSPP 공유 +specialthanks = 특별히 감사드립니다: +specialthanksKeithGalocy = - NVIDIA 로부터 (하드웨어, 지도) +specialthanksMaxim = - 놀라운 Atrac3+ 디코더 지원 +testing = 테스트 +this translation by = 번역: +title = 빠르고 휴대성이 높은 PSP 에뮬레이터 +tools = 사용된 무료 도구들: +# Add translators or contributors who translated PPSSPP into your language here. +# Add translators1-6 for up to 6 lines of translator credits. +# Leave extra lines blank. 4 contributors per line seems to look best. +# It is character-set for keyboard(atlas) +# ㄱㄲㄳㄴㄵㄶㄷㄸㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅃㅄㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎㅏㅐㅑㅒㅓㅔㅕㅖㅗㅛㅜㅠㅡㅣ +translators1 = mgaver Hisman_Yosika 오원식 MrGiKILL +translators2 = DDinghoya +translators3 = +translators4 = +translators5 = +translators6 = +Twitter @PPSSPP_emu = Twitter @PPSSPP_emu +website = 웹 사이트에서 확인하세요: +written = 속도와 이식성을 보장하기 위해 C++로 작성되었습니다. + +[RemoteISO] +Browse Games = 게임 찾아보기 +Local Server Port = 로컬 서버 포트 +Manual Mode Client = 수동 모드 클라이언트 +Remote disc streaming = 원격 디스크 스트리밍 +Remote Port = 원격 포트 +Remote Server = 원격 서버 +Remote Subdirectory = 공유할 하위 폴더 +RemoteISODesc = 최근 게임 목록에 있는 게임들이 공유됩니다. +RemoteISOLoading = 접속 완료, 게임 목록 불러오는 중... +RemoteISOScanning = 검색 중... 서버 장치의 "게임 공유하기" 버튼을 눌러주십시오. +RemoteISOScanningTimeout = 검색 중... 방화벽 설정을 확인하십시오. +RemoteISOWifi = 팁: 같은 Wi-Fi 네트워크 상에서 서로 접속할 수 있습니다. +RemoteISOWinFirewall = 경고: Windows 방화벽이 공유를 차단하고 있습니다. +Settings = 설정 +Share Games (Server) = 게임 공유하기 (서버) +Share on PPSSPP startup = PPSSPP 시작시 자동으로 공유하기 +Stop Sharing = 공유 끝내기 +Stopping.. = 중지하는 중... + +[Reporting] +Bad = 나쁨 +FeedbackDelayInfo = 피드백 데이터를 전송 중입니다. +FeedbackDesc = 게임이 어땠나요? 저희에게 알려주십시오! +FeedbackDisabled = 서버에 호환성 문제 보고를 체크해 주십시오. +FeedbackIncludeCRC = 참고: 디스크 CRC를 위해 배터리가 사용될 수 있습니다. +FeedbackIncludeScreen = 스크린샷 포함하기 +FeedbackSubmitDone = 피드백 데이터가 전송되었습니다. +FeedbackSubmitFail = 서버에 피드백을 전송할 수 없었습니다. PPSSPP를 업데이트해 보십시오. +FeedbackThanks = 피드백 고맙습니다! +Gameplay = 게임 플레이 +Graphics = 그래픽 +Great = 좋음 +In-game = 게임 내 +In-game Description = 게임이 실행되었지만 제대로 작동하지 않았습니다 +Menu/Intro = 메뉴/인트로 +Menu/Intro Description = 게임 내에 진입할 수 없었습니다 +Nothing = 전부 +Nothing Description = 전혀 동작하지 않았습니다 +OK = 괜찮음 +Open Browser = 브라우저 열기 +Overall = 평가 +Perfect = 완벽함 +Perfect Description = 게임 전체가 흠 없이 매끄럽게 작동했습니다 - 대박! +Plays = 플레이 중 +Plays Description = 게임을 즐길 수는 있지만 문제가 있을 수 있습니다 +ReportButton = 피드백 남기기 +Speed = 속도 +Submit Feedback = 피드백 전송 +SuggestionConfig = 적합한 설정을 위해 웹사이트에 올라온 보고서들을 확인해 보십시오. +SuggestionCPUSpeed0 = 잠긴 CPU 설정을 비활성화해 주십시오. +SuggestionDowngrade = 구 버전의 PPSSPP로 내려보십시오. (그리고 이 버그를 신고해 주십시오). +SuggestionsFound = 다른 유저들이 더 나은 결과를 보고했습니다. 피드백 보기를 눌러 확인해 주십시오. +SuggestionsNone = 다른 유저들도 이 게임이 제대로 작동하지 않았습니다. +SuggestionsWaiting = 전송 및 다른 유저의 보고서 확인 중... +SuggestionUpgrade = 새로운 PPSSPP 버전으로 업데이트 하십시오. +SuggestionVerifyDisc = ISO 파일이 제대로 디스크로부터 복사되었는지 확인해 보십시오. +Unselected Overall Description = 이 게임이 얼마만큼 잘 작동했나요? +View Feedback = 모든 피드백 보기 + +[Savedata] +Date = 날짜 +Filename = 파일 이름 +No screenshot = 스크린샷 없음 +None yet. Things will appear here after you save. = 아직 없음. 저장하면 나타납니다. +Save Data = 저장 데이터 +Save States = 상태 저장 +Savedata Manager = 저장 데이터 관리자 +Size = 크기 + +[Screen] +Cardboard VR OFF = 구글 카드보드 끄기 +Chainfire3DWarning = 경고: 체인파이어 3D가 검출되었습니다. 문제가 발생할 수 있습니다. +Failed to load state = 상태 불러오기에 실패했습니다 +Failed to save state = 상태 저장에 실패했습니다 +fixed = 속도: 고정 +GLToolsWarning = 경고: GLTools가 감지되었습니다. 문제가 발생할 수 있습니다. +In menu = 메뉴 +Load savestate failed = 상태 불러오기 실패 +Loaded State = 상태 불러옴 +Loaded. Save in game, restart, and load for less bugs. = 불러왔습니다. 게임을 저장한 다음 재시작하면 적은 버그로 로드됩니다. +LoadStateDoesntExist = 상태를 불러오지 못했습니다: 상태 저장이 존재하지 않습니다! +LoadStateWrongVersion = 상태를 불러오지 못했습니다: 구 버전의 상태 저장입니다! +norewind = 되감기 저장 상태가 없습니다. +Playing = 실행 +PressESC = ESC를 누르면 중지 메뉴가 열립니다. +replaceTextures_false = 텍스처가 더 이상 대체되지 않습니다. +replaceTextures_true = 텍스처 교체가 활성화되었습니다. +Save State Failed = 상태를 저장하지 못했습니다! +Saved State = 상태 저장됨 +saveNewTextures_false = 텍스처 저장이 비활성화되었습니다. +saveNewTextures_true = 텍스처가 이제 저장 공간에 저장됩니다. +SpeedCustom2 = 속도: 고정 속도 2 +standard = 속도: 표준 +Untitled PSP game = 이름 없는 PSP 게임 + +[Store] +Already Installed = 이미 설치되어 있습니다 +Connection Error = 연결 오류 +Install = 설치 +Launch Game = 게임 실행 +Loading... = 불러오는 중... +MB = MB +Size = 크기 +Uninstall = 제거 + +[SysInfo] +%d (%d per core, %d cores) = %d (코어 당 %d, 코어 %d개) +%d bytes = %d 바이트 +(none detected) = (감지되지 않음) +3D API = 3D API +ABI = ABI +API Version = API 버전 +Audio Information = 오디오 정보 +Board = Board +Build Config = 빌드 설정 +Build Configuration = 빌드 설정 +Built by = 빌드 실행자 +Core Context = 코어 컨텍스트 +Cores = 코어 +CPU Extensions = CPU 확장 +CPU Information = CPU 정보 +CPU Name = 이름 +D3DCompiler Version = D3DCompiler 버전 +Debug = 디버그 +Debugger Present = 디버거 표시 +Device Info = 장치 정보 +Display Information = 디스플레이 정보 +Driver Version = 드라이버 버전 +EGL Extensions = EGL 확장 +Frames per buffer = 버퍼당 프레임 +GPU Information = GPU 정보 +High precision float range = High precision float range +High precision int range = 정밀한 정수 범위 +Lang/Region = 언어/지역 +Memory Page Size = 메모리 페이지 크기 +Native Resolution = 기본 해상도 +OGL Extensions = OGL 확장 +OpenGL ES 2.0 Extensions = OpenGL ES 2.0 확장 +OpenGL ES 3.0 Extensions = OpenGL ES 3.0 확장 +OpenGL Extensions = OpenGL 확장 +Optimal frames per buffer = 버퍼당 최적 프레임 +Optimal sample rate = 최적 샘플 속도 +OS Information = OS 정보 +PPSSPP build = PPSSPP 빌드 +Refresh rate = 주사율 +Release = 출시 +RW/RX exclusive = RW/RX 독점 +Sample rate = 샘플 속도 +Shading Language = 셰이딩 언어 +Sustained perf mode = 지속 성능 모드 +System Information = 시스템 정보 +System Name = 시스템 이름 +System Version = 시스템 버전 +Threads = 스레드 +Vendor = 공급 업체 +Vendor (detected) = 공급 업체 (감지됨) +Version Information = 버전 정보 +Vulkan Extensions = 벌칸 확장 +Vulkan Features = 벌칸 기능 + +[System] +(broken) = (이용 불가) +12HR = 12시간 +24HR = 24시간 +Auto = 자동 +Auto Load Savestate = 상태 저장 자동 불러오기 +AVI Dump started. = AVI 덤프 시작됨 +AVI Dump stopped. = AVI 덤프 정지됨 +Cache ISO in RAM = ISO 전체를 램에 캐싱 +Change CPU Clock = CPU 클럭 변경 (불안정) +Change Memory Stick folder = 메모리 스틱 폴더 변경 +Change Memory Stick Size = Change Memory Stick size (GB) +Change Nickname = 별명 변경 +ChangingMemstickPath = 게임 저장, 상태 저장, 기타 데이터는 이 폴더에 복사되지 않습니다.\n\n메모리 스틱 폴더를 변경하시겠습니까? +ChangingMemstickPathInvalid = 이 경로는 메모리 스틱 파일을 저장하는데 사용할 수 없습니다. +ChangingMemstickPathNotExists = 해당 폴더는 아직 존재하지 않습니다.\n\n게임 저장, 상태 저장, 기타 데이터는 이 폴더에 복사되지 않습니다.\n\n새 메모리 스틱 폴더를 만드시겠습니까? +Cheats = 치트 (실험적, 포럼 참조) +Clear Recent = "최근" 지우기 +Clear Recent Games List = 최근 게임 목록 지우기 +Clear UI background = UI 배경화면 초기화 +Confirmation Button = 확인 버튼 +Date Format = 날짜 표시 방식 +Day Light Saving = 서머 타임 +DDMMYYYY = DDMMYYYY +Decrease size = 크기 줄이기 +Developer Tools = 개발자 도구 +Display Extra Info = 추가 정보 표시 +Display Games on a grid = 그리드에 "게임 탭" 표시 +Display Homebrew on a grid = 그리드에 "홈브류 및 데모 탭" 표시 +Display Recent on a grid = 그리드에 "최근 탭" 표시 +Dynarec (JIT) = 동적 재컴파일 (JIT) +Emulation = 에뮬레이션 +Enable Cheats = 치트 활성화 +Enable Compatibility Server Reports = 서버에 호환성 문제를 보고 +Failed to load state. Error in the file system. = 상태 저장을 불러올 수 없었습니다. 파일 시스템에 오류가 있습니다. +Failed to save state. Error in the file system. = 상태 저장을 저장할 수 없었습니다. 파일 시스템에 오류가 있습니다. +Fast (lag on slow storage) = 빠름 (느린 저장 장치에서 지연 발생) +Fast Memory = 빠른 메모리 (불안정) +Force real clock sync (slower, less lag) = 강제 실제 클럭 동기화 (느림, 약간의 지연) +frames, 0:off = 프레임, 0 = 끄기 +Games list settings = 게임 목록 설정 +General = 일반 +Grid icon size = 그리드 아이콘 크기 +Help the PPSSPP team = PPSSPP 팀 돕기 +Host (bugs, less lag) = 호스트 (버그, 약간의 지연) +I/O on thread (experimental) = I/O on thread (experimental) +Ignore bad memory accesses = Ignore bad memory accesses +Increase size = 크기 늘리기 +Interpreter = 해석기 +IO timing method = I/O 타이밍 방법 +IR Interpreter = IR 인터프리터 +Memory Stick Folder = 메모리 스틱 폴더 +Memory Stick inserted = 메모리 스틱 삽입됨 +MHz, 0:default = MHz, 0 = 기본 값 +MMDDYYYY = MMDDYYYY +Newest Save = 제일 새로운 저장 +Not a PSP game = PSP 게임이 아님 +Off = 끄기 +Oldest Save = 제일 오래된 저장 +PSP Model = PSP 기종 +PSP Settings = PSP 설정 +PSP-1000 = PSP-1000 +PSP-2000/3000 = PSP-2000/3000 +Record Audio = 소리 녹음하기 +Record Display = 영상 녹화하기 +Reset Recording on Save/Load State = 저장/불러올 때 기록된 것을 재설정하기 +Restore Default Settings = PPSSPP의 설정을 기본으로 복원 +Rewind Snapshot Frequency = 스냅샷 주기 되감기 (mem hog) +Save path in installed.txt = 경로를 installed.txt에 저장 +Save path in My Documents = 경로를 내 문서에 저장 +Savestate Slot = 상태 저장 슬롯 +Savestate slot backups = 상태 저장 백업 +Screenshots as PNG = PNG 형식으로 스크린샷 저장 +Set UI background... = UI 배경화면 지정하기... +Show ID = ID 보기 +Show region flag = 지역코드 플래그 보기 +Simulate UMD delays = UMD 지연 시뮬레이션 +Slot 1 = 슬롯 1 +Slot 2 = 슬롯 2 +Slot 3 = 슬롯 3 +Slot 4 = 슬롯 4 +Slot 5 = 슬롯 5 +Storage full = 저장 공간 가득참 +Sustained performance mode = 지속 성능 모드 +Time Format = 시간 표시 방식 +UI = 사용자 인터페이스 +UI Sound = UI sound +undo %c = %c 백업 +Use Lossless Video Codec (FFV1) = 무손실 비디오 코덱 사용 (FFV1) +Use O to confirm = 확인 버튼으로 O 사용 +Use output buffer (with overlay) for recording = 기록에 출력 버퍼(오버레이 포함) 사용 +Use system native keyboard = 시스템 기본 키보드 사용 +Use X to confirm = 확인 버튼으로 X 사용 +VersionCheck = PPSSPP의 새로운 버전을 확인 +WARNING: Android battery save mode is on = 주의: 안드로이드 배터리 절약 모드가 켜짐 +WARNING: Battery save mode is on = 주의: 배터리 절약 모드가 켜짐 +YYYYMMDD = YYYYMMDD + +[Upgrade] +Details = Details +Dismiss = 거절 +Download = 다운로드 +New version of PPSSPP available = 새로운 버전의 PPSSPP를 이용할 수 있습니다. diff --git a/source_assets/image/a.png b/source_assets/image/a.png new file mode 100644 index 0000000000..524904f292 Binary files /dev/null and b/source_assets/image/a.png differ diff --git a/source_assets/image/b.png b/source_assets/image/b.png new file mode 100644 index 0000000000..48b1c2ab39 Binary files /dev/null and b/source_assets/image/b.png differ diff --git a/source_assets/image/buttons.svg b/source_assets/image/buttons.svg index 61aa452258..644c2bc86b 100644 --- a/source_assets/image/buttons.svg +++ b/source_assets/image/buttons.svg @@ -12,7 +12,7 @@ height="1052.3622047" id="svg2" version="1.1" - inkscape:version="1.0beta2 (5ba348d, 2020-03-28)" + inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)" sodipodi:docname="buttons.svg"> @@ -1388,6 +1388,198 @@ in2="offset" id="feComposite5130-3" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A + B + C + D + F + E diff --git a/source_assets/image/c.png b/source_assets/image/c.png new file mode 100644 index 0000000000..bcb7f503d5 Binary files /dev/null and b/source_assets/image/c.png differ diff --git a/source_assets/image/d.png b/source_assets/image/d.png new file mode 100644 index 0000000000..9ff0eb4a7d Binary files /dev/null and b/source_assets/image/d.png differ diff --git a/source_assets/image/e.png b/source_assets/image/e.png new file mode 100644 index 0000000000..0d53463ba6 Binary files /dev/null and b/source_assets/image/e.png differ diff --git a/source_assets/image/f.png b/source_assets/image/f.png new file mode 100644 index 0000000000..22e16b31e4 Binary files /dev/null and b/source_assets/image/f.png differ