Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Common/UI/Notice.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class NoticeView : public UI::InertView {
void SetWrapText(bool wrapText) {
wrapText_ = wrapText;
}
void SetDetailsText(std::string_view detailsText) {
detailsText_ = detailsText;
}

void GetContentDimensionsBySpec(const UIContext &dc, UI::MeasureSpec horiz, UI::MeasureSpec vert, float &w, float &h) const override;
void Draw(UIContext &dc) override;
Expand Down
38 changes: 23 additions & 15 deletions Common/UI/PopupScreens.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -833,25 +833,28 @@ std::string PopupTextInputChoice::ValueText(bool *shadow) const {
}
}

ViewGroup *CreateSoftKeyboard(TextEdit *edit, bool *upperCase) {
ViewGroup *CreateSoftKeyboard(TextEdit *edit, SoftKeyboardState *state) {
ScrollView *scrollView = new ScrollView(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));

LinearLayout *keyboard = scrollView->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)));
// TODO: Make something a bit more international... Although we don't need that for domain names.
static struct {
std::string_view v; const char *tag;
} kbRows[] = {
{"1234567890-=", "A"},
{"qwertyuiop'[]", "L"},
{"asdfghjkl()", "L"},
{"1234567890-_", "A"},
{"qwertyuiop", "L"},
{"asdfghjkl", "L"},
{"zxcvbnm,.", "L"},
{"QWERTYUIOP'[]", "U"},
{"ASDFGHJKL()", "U"},
{"QWERTYUIOP", "U"},
{"ASDFGHJKL", "U"},
{"ZXCVBNM,.", "U"},
{"@#$_&()/-+_", "S"},
{"*\"':;!?[]", "S"},
{"={}~<>|", "S"},
{"", "A"},
};
static const float space[] = {
0.0f, 10.0f, 20.0f, 30.0f, 10.0f, 20.0f, 30.0f, 30.0f,
0.0f, 10.0f, 20.0f, 30.0f, 10.0f, 20.0f, 30.0f, 10.0f, 20.0f, 30.0f, 30.0f,
};

static_assert(ARRAY_SIZE(kbRows) == ARRAY_SIZE(space));
Expand All @@ -871,8 +874,9 @@ ViewGroup *CreateSoftKeyboard(TextEdit *edit, bool *upperCase) {

bool visible = false;
switch (kbRows[i].tag[0]) {
case 'L': visible = !(*upperCase); break;
case 'U': visible = *upperCase; break;
case 'L': visible = (*state == SoftKeyboardState::Lower); break;
case 'U': visible = (*state == SoftKeyboardState::Upper); break;
case 'S': visible = (*state == SoftKeyboardState::Symbols); break;
case 'A': visible = true; break;
default: visible = false; break;
}
Expand All @@ -885,16 +889,20 @@ ViewGroup *CreateSoftKeyboard(TextEdit *edit, bool *upperCase) {
edit->Backspace();
});
break;
case 7:
case 10:
// Special keys.
row->Add(new Button("Aa", new LinearLayoutParams(80.0f, 50.0f)))->OnClick.Add([keyboard, upperCase](EventParams &) {
*upperCase = !(*upperCase);
row->Add(new Button("Aa", new LinearLayoutParams(80.0f, 50.0f)))->OnClick.Add([keyboard, state](EventParams &) {
*state = (SoftKeyboardState)((int)*state + 1);
if (*state == SoftKeyboardState::MAX) {
*state = SoftKeyboardState::Upper;
}
// Work through visibility.
for (int i = 0; i < keyboard->GetNumSubviews(); i++) {
LinearLayout *row = (LinearLayout *)keyboard->GetViewByIndex(i);
switch (row->Tag()[0]) {
case 'L': row->SetVisibility(*upperCase ? V_GONE : V_VISIBLE); break;
case 'U': row->SetVisibility(*upperCase ? V_VISIBLE : V_GONE); break;
case 'L': row->SetVisibility((*state == SoftKeyboardState::Lower) ? V_VISIBLE : V_GONE); break;
case 'U': row->SetVisibility((*state == SoftKeyboardState::Upper) ? V_VISIBLE : V_GONE); break;
case 'S': row->SetVisibility((*state == SoftKeyboardState::Symbols) ? V_VISIBLE : V_GONE); break;
case 'A': row->SetVisibility(V_VISIBLE); break;
default: row->SetVisibility(V_GONE); break;
}
Expand Down Expand Up @@ -930,7 +938,7 @@ void TextEditPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {

parent->Add(new Spacer(8.0f));

keyboard_ = parent->Add(CreateSoftKeyboard(edit_, &upperCase_));
keyboard_ = parent->Add(CreateSoftKeyboard(edit_, &kbState_));
if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) {
keyboard_->SetVisibility(V_GONE);
lin->Add(new Spacer(5.0f));
Expand Down
11 changes: 9 additions & 2 deletions Common/UI/PopupScreens.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,14 @@ class SliderFloatPopupScreen : public PopupScreen {
bool liveUpdate_;
};

ViewGroup *CreateSoftKeyboard(TextEdit *edit, bool *upperCase);
enum class SoftKeyboardState {
Upper = 0,
Lower,
Symbols,
MAX,
};

ViewGroup *CreateSoftKeyboard(TextEdit *edit, SoftKeyboardState *state);

class TextEditPopupScreen : public PopupScreen {
public:
Expand All @@ -249,7 +256,7 @@ class TextEditPopupScreen : public PopupScreen {
std::string textEditValue_;
std::string placeholder_;
int maxLen_;
bool upperCase_ = false;
SoftKeyboardState kbState_{};
bool passwordMasking_ = false;
};

Expand Down
6 changes: 6 additions & 0 deletions Core/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,12 @@ static const ConfigSetting controlSettings[] = {

ConfigSetting("SystemControls", SETTING(g_Config, bSystemControls), true, CfgFlag::DEFAULT),
ConfigSetting("RapidFileInterval", SETTING(g_Config, iRapidFireInterval), 5, CfgFlag::DEFAULT),

#if PPSSPP_PLATFORM(WINDOWS)
ConfigSetting("AllowHIDInput", SETTING(g_Config, bAllowHIDInput), true, CfgFlag::DEFAULT),
ConfigSetting("AllowXInput", SETTING(g_Config, bAllowXInput), true, CfgFlag::DEFAULT),
ConfigSetting("AllowDInput", SETTING(g_Config, bAllowDInput), true, CfgFlag::DEFAULT),
#endif
};

static const std::vector<std::string_view> emptyList;
Expand Down
5 changes: 5 additions & 0 deletions Core/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,11 @@ struct Config : public ConfigBlock {
float fMouseSmoothing;
int iMouseWheelUpDelayMs;

// Crude Windows controller filter.
bool bAllowHIDInput;
bool bAllowXInput;
bool bAllowDInput;

bool bSystemControls;
int iRapidFireInterval;

Expand Down
81 changes: 57 additions & 24 deletions UI/CwCheatScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,8 @@ void CwCheatScreen::CreateSettingsViews(UI::ViewGroup *leftColumn) {

std::string title = StringFromFormat(cw->T_cstr("Import from %s"), "PSP/Cheats/cheat.db");

leftColumn->Add(new Choice(title.c_str()))->OnClick.Handle(this, &CwCheatScreen::OnImportCheat);
leftColumn->Add(new Choice(title))->OnClick.Handle(this, &CwCheatScreen::OnImportCheat);
leftColumn->Add(new Choice(mm->T("Browse"), ImageID("I_FOLDER_OPEN")))->OnClick.Handle(this, &CwCheatScreen::OnImportBrowse);
errorMessageView_ = leftColumn->Add(new TextView(di->T("LoadingFailed")));
errorMessageView_->SetVisibility(V_GONE);

leftColumn->Add(new ItemHeader(di->T("Options")));
#if !defined(MOBILE_DEVICE)
Expand All @@ -127,7 +125,14 @@ void CwCheatScreen::CreateContentViews(UI::ViewGroup *parent) {
LinearLayout *rightColumn = new LinearLayoutList(ORIENT_VERTICAL, new LinearLayoutParams(200, FILL_PARENT));
rightColumn->SetSpacing(0.0f);
rightScroll->Add(rightColumn);

if (!errorMessage_.empty()) {
rightColumn->Add(new NoticeView(errorLevel_, errorMessage_, errorDetails_));
rightColumn->Add(new Spacer(8.0f));
}

rightColumn->Add(new ItemHeader(cw->T("Cheats")));

bool prevIsTitle = false;
for (size_t i = 0; i < fileInfo_.size(); ++i) {
std::string_view text;
Expand Down Expand Up @@ -231,50 +236,76 @@ static char *GetLineNoNewline(char *temp, int sz, FILE *fp) {
return line;
}

void CwCheatScreen::ImportAndReport(const Path &cheatFile) {
int cheatCount = 0;
if (!ImportCheats(cheatFile, &cheatCount)) {
// Show an error message?
if (File::Exists(cheatFile)) {
auto er = GetI18NCategory(I18NCat::ERRORS);
errorMessage_ = ApplySafeSubstitutions(er->T("File not found: %1"), "");
errorLevel_ = NoticeLevel::WARN;
} else {
auto di = GetI18NCategory(I18NCat::DIALOG);
errorMessage_ = di->T("LoadingFailed");
errorLevel_ = NoticeLevel::ERROR;
}
errorDetails_ = GetFriendlyPath(cheatFile);
} else if (cheatCount == 0) {
auto cw = GetI18NCategory(I18NCat::CWCHEATS);
// Show an error message?
errorLevel_ = NoticeLevel::INFO;
errorMessage_ = cw->T("No cheats found for this game");
errorDetails_.clear();
} else {
auto cw = GetI18NCategory(I18NCat::CWCHEATS);
// Show a success message?
errorLevel_ = NoticeLevel::SUCCESS;
errorMessage_ = ApplySafeSubstitutions(cw->T("Added %1 cheats for this game"), cheatCount);
errorDetails_ = GetFriendlyPath(cheatFile);
}
g_Config.bReloadCheats = true;
RecreateViews();
}

void CwCheatScreen::OnImportBrowse(UI::EventParams &params) {
System_BrowseForFile(GetRequesterToken(), "Open cheat DB file", BrowseFileType::DB, [&](const std::string &value, int) {
if (value.empty()) {
return;
}
Path path(value);
INFO_LOG(Log::System, "Attempting to load cheats from: '%s'", path.ToVisualString().c_str());
if (ImportCheats(path)) {
g_Config.bReloadCheats = true;
} else {
// Show an error message?
}
RecreateViews();
int cheatsFound = 0;
ImportAndReport(path);
});
}

void CwCheatScreen::OnImportCheat(UI::EventParams &params) {
if (!ImportCheats(GetGlobalCheatFilePath())) {
// Show an error message?
errorMessageView_->SetVisibility(UI::V_VISIBLE);
}

g_Config.bReloadCheats = true;
RecreateViews();
const Path importPath = GetGlobalCheatFilePath();
ImportAndReport(importPath);
}

bool CwCheatScreen::ImportCheats(const Path & cheatFile) {
bool CwCheatScreen::ImportCheats(const Path &cheatFile, int *cheatsFound) {
FILE *in = File::OpenCFile(cheatFile, "rt");
if (!in) {
WARN_LOG(Log::Common, "Unable to open %s\n", cheatFile.c_str());
return false;
}

if (gameID_.length() != 9 || !engine_) {
WARN_LOG(Log::Common, "CWCHEAT: Incorrect ID(%s) - can't import cheats.", gameID_.c_str());
return false;
}

std::string gameID = StringFromFormat("_S %s-%s", gameID_.substr(0, 4).c_str(), gameID_.substr(4).c_str());

FILE *in = File::OpenCFile(cheatFile, "rt");
if (!in) {
WARN_LOG(Log::Common, "Unable to open %s\n", cheatFile.c_str());
return false;
}

std::vector<std::string> title;
std::vector<std::string> newList;

char linebuf[2048]{};
bool parseGameEntry = false;
bool parseCheatEntry = false;

(*cheatsFound) = 0;
while (in && !feof(in)) {
char *line = GetLineNoNewline(linebuf, sizeof(linebuf), in);

Expand Down Expand Up @@ -304,6 +335,7 @@ bool CwCheatScreen::ImportCheats(const Path & cheatFile) {
title.push_back(line);
} else if (parseCheatEntry && ((line[0] == '_' && (line[1] == 'C' || line[1] == 'L')) || line[0] == '/' || line[0] == '#')) {
newList.push_back(line);
(*cheatsFound)++;
}
}
fclose(in);
Expand All @@ -320,8 +352,9 @@ bool CwCheatScreen::ImportCheats(const Path & cheatFile) {
}

FILE *append = File::OpenCFile(engine_->CheatFilename(), "at");
if (!append)
if (!append) {
return false;
}

if (title2.size() == 0 || title2[0] != '_' || title2[1] != 'S') {
for (int i = (int)title.size(); i > 0; i--) {
Expand Down
11 changes: 8 additions & 3 deletions UI/CwCheatScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

struct CheatFileInfo;
class CWCheatEngine;
class NoticeView;

class CwCheatScreen : public UITwoPaneBaseDialogScreen {
public:
Expand Down Expand Up @@ -55,17 +56,21 @@ class CwCheatScreen : public UITwoPaneBaseDialogScreen {

private:
void OnCheckBox(int index);
bool ImportCheats(const Path &cheatFile);
bool ImportCheats(const Path &cheatFile, int *cheatsFound);

void ImportAndReport(const Path &cheatFile);

enum { INDEX_ALL = -1 };
bool HasCheatWithName(const std::string &name);
bool RebuildCheatFile(int index);

UI::TextView *errorMessageView_ = nullptr;

CWCheatEngine *engine_ = nullptr;
std::vector<CheatFileInfo> fileInfo_;
std::string gameID_;
int fileCheckCounter_ = 0;
uint64_t fileCheckHash_ = 0;

std::string errorMessage_;
NoticeLevel errorLevel_ = NoticeLevel::ERROR;
std::string errorDetails_;
};
7 changes: 7 additions & 0 deletions UI/GameSettingsScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,13 @@ void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings)
disableDiags->SetEnabledPtr(&g_Config.bShowTouchControls);
}

#if PPSSPP_PLATFORM(WINDOWS)
controlsSettings->Add(new ItemHeader(co->T("Control input sources")));
controlsSettings->Add(new CheckBox(&g_Config.bAllowHIDInput, co->T("HID input")));
controlsSettings->Add(new CheckBox(&g_Config.bAllowXInput, co->T("XInput")));
controlsSettings->Add(new CheckBox(&g_Config.bAllowDInput, co->T("DirectInput")));
#endif

if (deviceType != DEVICE_TYPE_VR) {
controlsSettings->Add(new ItemHeader(co->T("Keyboard", "Keyboard Control Settings")));
#if defined(USING_WIN_UI)
Expand Down
1 change: 1 addition & 0 deletions UI/UIAtlas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ static const ImageMeta g_uiImageIDs[] = {
{"I_FOLDER_UPLOAD", false},
{"I_FILE", false},
{"I_FILE_COPY", false},
{"I_FILE_PASTE", false},
{"I_WEB_BROWSER", false},
{"I_WIFI", false},
{"I_LOGO_X", false},
Expand Down
Loading
Loading