Fixes for FEXConfig

Fixes the formatting. Everything was using the incorrect formatting.

Changes the saved msg popup to a generic popup handler.

If a file couldn't be opened, open a popup claiming the error.
Makes it nicer to realize when trying to open main and nothing happens
when the file doesn't exit
This commit is contained in:
Ryan Houdek 2020-12-13 22:39:10 -08:00
parent 00a2560905
commit 92c8303798

View File

@ -13,136 +13,162 @@
#include "imgui_impl_opengl3.h"
namespace {
static double GlobalTime{};
static double GlobalTime{};
static bool ConfigOpen{};
static bool ConfigChanged{};
static int EnvironmentVariableSelected{};
static bool ConfigOpen{};
static bool ConfigChanged{};
static int EnvironmentVariableSelected{};
static std::string ConfigFilename{};
static std::unique_ptr<FEXCore::Config::Layer> LoadedConfig{};
static std::string ConfigFilename{};
static std::unique_ptr<FEXCore::Config::Layer> LoadedConfig{};
static const char EnvironmentPopupName[] = "#New Environment Variable";
static bool OpenSavedPopup{};
static const char EnvironmentPopupName[] = "#New Environment Variable";
static const char SavedPopupAppName[] = "#SavedApp";
static const char SavedPopupName[] = "#Saved";
static const char SavedPopupAppName[] = "#SavedApp";
static bool OpenMsgPopup{};
static std::string MsgMessage{};
static const char MsgPopupName[] = "#Msg";
static std::chrono::high_resolution_clock::time_point MsgTimerStart{};
static bool SelectedOpenFile{};
static bool SelectedSaveFileAs{};
static ImGuiFs::Dialog DialogSaveAs{};
static ImGuiFs::Dialog DialogOpen{};
static bool SelectedOpenFile{};
static bool SelectedSaveFileAs{};
static ImGuiFs::Dialog DialogSaveAs{};
static ImGuiFs::Dialog DialogOpen{};
static std::chrono::high_resolution_clock::time_point SavedTimerStart{};
void OpenFile(std::string Filename) {
if (!std::filesystem::exists(Filename)) {
return;
}
ConfigOpen = true;
ConfigFilename = Filename;
LoadedConfig = std::make_unique<FEX::Config::MainLoader>(Filename);
LoadedConfig->Load();
}
void LoadDefaultSettings() {
ConfigOpen = true;
ConfigFilename = {};
LoadedConfig = std::make_unique<FEX::Config::EmptyMapper>();
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_DEFAULTCORE, "1");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_MAXBLOCKINST, "1");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_SINGLESTEP, "0");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_MULTIBLOCK, "0");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_GDBSERVER, "0");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_EMULATED_CPU_CORES, "1");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_ROOTFSPATH, "");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_THUNKLIBSPATH, "");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_SILENTLOGS, "0");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT, "GALLIUM_THREAD=1");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT, "GALLIUM_HUD=fps");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT, "TERM=xterm");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_OUTPUTLOG, "");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_DUMPIR, "no"),
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_TSO_ENABLED, "1");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_SMC_CHECKS, "0");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_ABI_LOCAL_FLAGS, "0");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_ABI_NO_PF, "0");
}
void SaveFile(std::string Filename) {
if (!ConfigOpen) {
return;
void OpenMsgMessagePopup(std::string Message) {
OpenMsgPopup = true;
MsgMessage = Message;
MsgTimerStart = std::chrono::high_resolution_clock::now();
}
FEX::Config::SaveLayerToJSON(Filename, LoadedConfig.get());
ConfigChanged = false;
ConfigFilename = Filename;
OpenSavedPopup = true;
SavedTimerStart = std::chrono::high_resolution_clock::now();
// Output in terminal as well
printf("Config Saved to: '%s'\n", ConfigFilename.c_str());
}
void CloseConfig() {
ConfigOpen = false;
ConfigFilename = {};
ConfigChanged = false;
LoadedConfig.reset();
}
void FillCPUConfig() {
char BlockSize[32]{};
char EmulatedCPUCores[32]{};
if (ImGui::BeginTabItem("CPU")) {
ImGui::Text("Core:");
auto Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_DEFAULTCORE);
ImGui::SameLine();
if (ImGui::RadioButton("Int", Value.has_value() && **Value == "0")) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_DEFAULTCORE, "0");
ConfigChanged = true;
void OpenFile(std::string Filename) {
if (!std::filesystem::exists(Filename)) {
OpenMsgMessagePopup("Couldn't open: " + Filename);
return;
}
ImGui::SameLine();
if (ImGui::RadioButton("JIT", Value.has_value() && **Value == "1")) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_DEFAULTCORE, "1");
ConfigChanged = true;
}
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_MAXBLOCKINST);
if (Value.has_value() && !(*Value)->empty()) {
strncpy(BlockSize, &(*Value)->at(0), 32);
}
if (ImGui::InputText("Block Size:", BlockSize, 32, ImGuiInputTextFlags_EnterReturnsTrue)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_MAXBLOCKINST, BlockSize);
ConfigChanged = true;
}
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_MULTIBLOCK);
bool Multiblock = Value.has_value() && **Value == "1";
if (ImGui::Checkbox("Multiblock", &Multiblock)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_MULTIBLOCK, Multiblock ? "1" : "0");
ConfigChanged = true;
}
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_EMULATED_CPU_CORES);
if (Value.has_value() && !(*Value)->empty()) {
strncpy(EmulatedCPUCores, &(*Value)->at(0), 32);
}
if (ImGui::InputText("Emulated CPU cores:", EmulatedCPUCores, 32, ImGuiInputTextFlags_EnterReturnsTrue)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_EMULATED_CPU_CORES, EmulatedCPUCores);
ConfigChanged = true;
}
ImGui::EndTabItem();
ConfigOpen = true;
ConfigFilename = Filename;
LoadedConfig = std::make_unique<FEX::Config::MainLoader>(Filename);
LoadedConfig->Load();
}
}
bool EnvironmentVariableFiller(void *data, int idx, const char** out_text) {
static char TmpString[256];
auto Value = LoadedConfig->All(FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT);
if (Value.has_value()) {
void LoadDefaultSettings() {
ConfigOpen = true;
ConfigFilename = {};
LoadedConfig = std::make_unique<FEX::Config::EmptyMapper>();
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_DEFAULTCORE, "1");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_MAXBLOCKINST, "1");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_SINGLESTEP, "0");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_MULTIBLOCK, "0");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_GDBSERVER, "0");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_EMULATED_CPU_CORES, "1");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_ROOTFSPATH, "");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_THUNKLIBSPATH, "");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_SILENTLOGS, "0");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT, "GALLIUM_THREAD=1");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT, "GALLIUM_HUD=fps");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT, "TERM=xterm");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_OUTPUTLOG, "");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_DUMPIR, "no"),
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_TSO_ENABLED, "1");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_SMC_CHECKS, "0");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_ABI_LOCAL_FLAGS, "0");
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_ABI_NO_PF, "0");
}
void SaveFile(std::string Filename) {
if (!ConfigOpen) {
OpenMsgMessagePopup("Can't save file when config isn't open");
return;
}
FEX::Config::SaveLayerToJSON(Filename, LoadedConfig.get());
ConfigChanged = false;
ConfigFilename = Filename;
OpenMsgMessagePopup("Config Saved to: '" + Filename + "'");
// Output in terminal as well
printf("Config Saved to: '%s'\n", ConfigFilename.c_str());
}
void CloseConfig() {
ConfigOpen = false;
ConfigFilename = {};
ConfigChanged = false;
LoadedConfig.reset();
}
void FillCPUConfig() {
char BlockSize[32]{};
char EmulatedCPUCores[32]{};
if (ImGui::BeginTabItem("CPU")) {
ImGui::Text("Core:");
auto Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_DEFAULTCORE);
ImGui::SameLine();
if (ImGui::RadioButton("Int", Value.has_value() && **Value == "0")) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_DEFAULTCORE, "0");
ConfigChanged = true;
}
ImGui::SameLine();
if (ImGui::RadioButton("JIT", Value.has_value() && **Value == "1")) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_DEFAULTCORE, "1");
ConfigChanged = true;
}
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_MAXBLOCKINST);
if (Value.has_value() && !(*Value)->empty()) {
strncpy(BlockSize, &(*Value)->at(0), 32);
}
if (ImGui::InputText("Block Size:", BlockSize, 32, ImGuiInputTextFlags_EnterReturnsTrue)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_MAXBLOCKINST, BlockSize);
ConfigChanged = true;
}
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_MULTIBLOCK);
bool Multiblock = Value.has_value() && **Value == "1";
if (ImGui::Checkbox("Multiblock", &Multiblock)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_MULTIBLOCK, Multiblock ? "1" : "0");
ConfigChanged = true;
}
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_EMULATED_CPU_CORES);
if (Value.has_value() && !(*Value)->empty()) {
strncpy(EmulatedCPUCores, &(*Value)->at(0), 32);
}
if (ImGui::InputText("Emulated CPU cores:", EmulatedCPUCores, 32, ImGuiInputTextFlags_EnterReturnsTrue)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_EMULATED_CPU_CORES, EmulatedCPUCores);
ConfigChanged = true;
}
ImGui::EndTabItem();
}
}
bool EnvironmentVariableFiller(void *data, int idx, const char** out_text) {
static char TmpString[256];
auto Value = LoadedConfig->All(FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT);
if (Value.has_value()) {
auto List = (*Value);
auto it = List->begin();
// Since this is a list, we don't have a linear allocator that we can just jump to an element
// Just do a quick spin
for (int i = 0; i < idx; ++i)
++it;
snprintf(TmpString, 256, "%s", it->c_str());
*out_text = TmpString;
return true;
}
return false;
}
void DeleteEnvironmentVariable(int idx) {
auto Value = LoadedConfig->All(FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT);
auto List = (*Value);
auto it = List->begin();
@ -151,348 +177,329 @@ bool EnvironmentVariableFiller(void *data, int idx, const char** out_text) {
for (int i = 0; i < idx; ++i)
++it;
snprintf(TmpString, 256, "%s", it->c_str());
*out_text = TmpString;
return true;
List->erase(it);
ConfigChanged = true;
}
return false;
}
void AddNewEnvironmentVariable() {
char Environment[256]{};
void DeleteEnvironmentVariable(int idx) {
auto Value = LoadedConfig->All(FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT);
auto List = (*Value);
auto it = List->begin();
// Since this is a list, we don't have a linear allocator that we can just jump to an element
// Just do a quick spin
for (int i = 0; i < idx; ++i)
++it;
List->erase(it);
ConfigChanged = true;
}
void AddNewEnvironmentVariable() {
char Environment[256]{};
if (ImGui::BeginPopup(EnvironmentPopupName)) {
if (ImGui::InputText("New Environment", Environment, 256, ImGuiInputTextFlags_EnterReturnsTrue)) {
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT, Environment);
ImGui::CloseCurrentPopup();
ConfigChanged = true;
}
ImGui::EndPopup();
}
}
void FillEmulationConfig() {
char RootFS[256]{};
char ThunkPath[256]{};
int NumEnvironmentVariables{};
if (ImGui::BeginTabItem("Emulation")) {
auto Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_ROOTFSPATH);
if (Value.has_value() && !(*Value)->empty()) {
strncpy(RootFS, &(*Value)->at(0), 256);
}
if (ImGui::InputText("RootFS:", RootFS, 256, ImGuiInputTextFlags_EnterReturnsTrue)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_ROOTFSPATH, RootFS);
ConfigChanged = true;
}
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_THUNKLIBSPATH);
if (Value.has_value() && !(*Value)->empty()) {
strncpy(ThunkPath, &(*Value)->at(0), 256);
}
if (ImGui::InputText("Thunk library folder:", ThunkPath, 256, ImGuiInputTextFlags_EnterReturnsTrue)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_THUNKLIBSPATH, ThunkPath);
ConfigChanged = true;
}
auto ValueList = LoadedConfig->All(FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT);
if (ValueList.has_value()) {
NumEnvironmentVariables = (*ValueList)->size();
}
ImGui::Text("Number of environment variables: %d", NumEnvironmentVariables);
ImGui::ListBox("Environment variables", &EnvironmentVariableSelected, EnvironmentVariableFiller, nullptr, NumEnvironmentVariables);
if (ImGui::SmallButton("+")) {
ImGui::OpenPopup(EnvironmentPopupName);
}
// Only draws if popup is open
AddNewEnvironmentVariable();
if (NumEnvironmentVariables) {
ImGui::SameLine();
if (ImGui::SmallButton("-")) {
DeleteEnvironmentVariable(EnvironmentVariableSelected);
EnvironmentVariableSelected = std::max(0, EnvironmentVariableSelected - 1);
if (ImGui::BeginPopup(EnvironmentPopupName)) {
if (ImGui::InputText("New Environment", Environment, 256, ImGuiInputTextFlags_EnterReturnsTrue)) {
LoadedConfig->Set(FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT, Environment);
ImGui::CloseCurrentPopup();
ConfigChanged = true;
}
}
ImGui::EndTabItem();
ImGui::EndPopup();
}
}
}
void FillLoggingConfig() {
char LogFile[256]{};
char IRDump[256]{};
void FillEmulationConfig() {
char RootFS[256]{};
char ThunkPath[256]{};
if (ImGui::BeginTabItem("Logging")) {
auto Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_SILENTLOGS);
bool SilentLog = Value.has_value() && **Value == "1";
if (ImGui::Checkbox("Silent Logging", &SilentLog)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_SILENTLOGS, SilentLog ? "1" : "0");
ConfigChanged = true;
}
int NumEnvironmentVariables{};
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_OUTPUTLOG);
if (Value.has_value() && !(*Value)->empty()) {
strncpy(LogFile, &(*Value)->at(0), 256);
}
if (ImGui::InputText("Output log file:", LogFile, 256, ImGuiInputTextFlags_EnterReturnsTrue)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_OUTPUTLOG, LogFile);
ConfigChanged = true;
}
if (ImGui::BeginTabItem("Emulation")) {
auto Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_ROOTFSPATH);
if (Value.has_value() && !(*Value)->empty()) {
strncpy(RootFS, &(*Value)->at(0), 256);
}
if (ImGui::InputText("RootFS:", RootFS, 256, ImGuiInputTextFlags_EnterReturnsTrue)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_ROOTFSPATH, RootFS);
ConfigChanged = true;
}
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_DUMPIR);
if (Value.has_value() && !(*Value)->empty()) {
strncpy(IRDump, &(*Value)->at(0), 256);
}
if (ImGui::InputText("IR Dump location:", IRDump, 256, ImGuiInputTextFlags_EnterReturnsTrue)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_DUMPIR, IRDump);
ConfigChanged = true;
}
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_THUNKLIBSPATH);
if (Value.has_value() && !(*Value)->empty()) {
strncpy(ThunkPath, &(*Value)->at(0), 256);
}
if (ImGui::InputText("Thunk library folder:", ThunkPath, 256, ImGuiInputTextFlags_EnterReturnsTrue)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_THUNKLIBSPATH, ThunkPath);
ConfigChanged = true;
}
ImGui::EndTabItem();
auto ValueList = LoadedConfig->All(FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT);
if (ValueList.has_value()) {
NumEnvironmentVariables = (*ValueList)->size();
}
ImGui::Text("Number of environment variables: %d", NumEnvironmentVariables);
ImGui::ListBox("Environment variables", &EnvironmentVariableSelected, EnvironmentVariableFiller, nullptr, NumEnvironmentVariables);
if (ImGui::SmallButton("+")) {
ImGui::OpenPopup(EnvironmentPopupName);
}
// Only draws if popup is open
AddNewEnvironmentVariable();
if (NumEnvironmentVariables) {
ImGui::SameLine();
if (ImGui::SmallButton("-")) {
DeleteEnvironmentVariable(EnvironmentVariableSelected);
EnvironmentVariableSelected = std::max(0, EnvironmentVariableSelected - 1);
}
}
ImGui::EndTabItem();
}
}
}
void FillHackConfig() {
if (ImGui::BeginTabItem("Hacks")) {
auto Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_TSO_ENABLED);
bool TSOEnabled = Value.has_value() && **Value == "1";
if (ImGui::Checkbox("TSO Enabled", &TSOEnabled)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_TSO_ENABLED, TSOEnabled ? "1" : "0");
ConfigChanged = true;
void FillLoggingConfig() {
char LogFile[256]{};
char IRDump[256]{};
if (ImGui::BeginTabItem("Logging")) {
auto Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_SILENTLOGS);
bool SilentLog = Value.has_value() && **Value == "1";
if (ImGui::Checkbox("Silent Logging", &SilentLog)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_SILENTLOGS, SilentLog ? "1" : "0");
ConfigChanged = true;
}
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_OUTPUTLOG);
if (Value.has_value() && !(*Value)->empty()) {
strncpy(LogFile, &(*Value)->at(0), 256);
}
if (ImGui::InputText("Output log file:", LogFile, 256, ImGuiInputTextFlags_EnterReturnsTrue)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_OUTPUTLOG, LogFile);
ConfigChanged = true;
}
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_DUMPIR);
if (Value.has_value() && !(*Value)->empty()) {
strncpy(IRDump, &(*Value)->at(0), 256);
}
if (ImGui::InputText("IR Dump location:", IRDump, 256, ImGuiInputTextFlags_EnterReturnsTrue)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_DUMPIR, IRDump);
ConfigChanged = true;
}
ImGui::EndTabItem();
}
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_SMC_CHECKS);
bool SMCChecks = Value.has_value() && **Value == "1";
if (ImGui::Checkbox("SMC Checks", &SMCChecks)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_SMC_CHECKS, SMCChecks ? "1" : "0");
ConfigChanged = true;
}
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_ABI_LOCAL_FLAGS);
bool UnsafeLocalFlags = Value.has_value() && **Value == "1";
if (ImGui::Checkbox("Unsafe local flags optimization", &UnsafeLocalFlags)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_ABI_LOCAL_FLAGS, UnsafeLocalFlags ? "1" : "0");
ConfigChanged = true;
}
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_ABI_NO_PF);
bool NoPFCalculation = Value.has_value() && **Value == "1";
if (ImGui::Checkbox("Disable PF calculation", &NoPFCalculation)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_ABI_NO_PF, NoPFCalculation ? "1" : "0");
ConfigChanged = true;
}
ImGui::EndTabItem();
}
}
void FillConfigWindow() {
ImGui::BeginTabBar("Config");
FillCPUConfig();
FillEmulationConfig();
FillLoggingConfig();
FillHackConfig();
ImGui::EndTabBar();
}
void FillHackConfig() {
if (ImGui::BeginTabItem("Hacks")) {
auto Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_TSO_ENABLED);
bool TSOEnabled = Value.has_value() && **Value == "1";
if (ImGui::Checkbox("TSO Enabled", &TSOEnabled)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_TSO_ENABLED, TSOEnabled ? "1" : "0");
ConfigChanged = true;
}
void DrawUI(GLContext::Context *Context) {
ImGuiIO& io = ImGui::GetIO();
double current_time = glfwGetTime();
io.DeltaTime = GlobalTime > 0.0 ? static_cast<float>(current_time - GlobalTime) : static_cast<float>(1.0f/60.0f);
GlobalTime = current_time;
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_SMC_CHECKS);
bool SMCChecks = Value.has_value() && **Value == "1";
if (ImGui::Checkbox("SMC Checks", &SMCChecks)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_SMC_CHECKS, SMCChecks ? "1" : "0");
ConfigChanged = true;
}
ImGui::NewFrame();
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_ABI_LOCAL_FLAGS);
bool UnsafeLocalFlags = Value.has_value() && **Value == "1";
if (ImGui::Checkbox("Unsafe local flags optimization", &UnsafeLocalFlags)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_ABI_LOCAL_FLAGS, UnsafeLocalFlags ? "1" : "0");
ConfigChanged = true;
}
// We are using the ImGuiWindowFlags_NoDocking flag to make the parent window not dockable into,
// because it would be confusing to have two docking targets within each others.
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->Pos);
ImGui::SetNextWindowSize(viewport->Size);
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_ABI_NO_PF);
bool NoPFCalculation = Value.has_value() && **Value == "1";
if (ImGui::Checkbox("Disable PF calculation", &NoPFCalculation)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_ABI_NO_PF, NoPFCalculation ? "1" : "0");
ConfigChanged = true;
}
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("DockSpace", nullptr, window_flags);
ImGui::PopStyleVar(3);
ImGui::DockSpace(ImGui::GetID("DockSpace"));
struct {
bool Open{};
bool OpenDefault{};
bool LoadDefault{};
bool Save{};
bool SaveAs{};
bool SaveDefault{};
bool Close{};
} Selected;
char AppName[256]{};
if (ImGui::BeginMenuBar()) {
if (ImGui::BeginMenu("File")) {
ImGui::MenuItem("Open", "CTRL+O", &Selected.Open, true);
ImGui::MenuItem("Open Default", "CTRL+SHIFT+O", &Selected.OpenDefault, true);
ImGui::MenuItem("Load Default Options", "CTRL+SHIFT+D", &Selected.LoadDefault, true);
ImGui::MenuItem("Save", "CTRL+S", &Selected.Save, true);
ImGui::MenuItem("Save As", "CTRL+SHIFT+S", &Selected.SaveAs, true);
ImGui::MenuItem("Save As App profile", "CTRL+E", nullptr, true);
ImGui::MenuItem("Save Default", "CTRL+SHIFT+P", &Selected.SaveDefault, true);
ImGui::MenuItem("Close", "CTRL+W", &Selected.Close, true);
ImGui::EndMenu();
ImGui::EndTabItem();
}
}
ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::GetFrameHeight());
void FillConfigWindow() {
ImGui::BeginTabBar("Config");
FillCPUConfig();
FillEmulationConfig();
FillLoggingConfig();
FillHackConfig();
ImGui::EndTabBar();
}
if (ConfigOpen) {
if (ConfigChanged) {
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(1.0, 1.0, 0.0, 1.0));
ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(1.0, 1.0, 0.0, 1.0));
void DrawUI(GLContext::Context *Context) {
ImGuiIO& io = ImGui::GetIO();
double current_time = glfwGetTime();
io.DeltaTime = GlobalTime > 0.0 ? static_cast<float>(current_time - GlobalTime) : static_cast<float>(1.0f/60.0f);
GlobalTime = current_time;
ImGui::NewFrame();
// We are using the ImGuiWindowFlags_NoDocking flag to make the parent window not dockable into,
// because it would be confusing to have two docking targets within each others.
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->Pos);
ImGui::SetNextWindowSize(viewport->Size);
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("DockSpace", nullptr, window_flags);
ImGui::PopStyleVar(3);
ImGui::DockSpace(ImGui::GetID("DockSpace"));
struct {
bool Open{};
bool OpenDefault{};
bool LoadDefault{};
bool Save{};
bool SaveAs{};
bool SaveDefault{};
bool Close{};
} Selected;
char AppName[256]{};
if (ImGui::BeginMenuBar()) {
if (ImGui::BeginMenu("File")) {
ImGui::MenuItem("Open", "CTRL+O", &Selected.Open, true);
ImGui::MenuItem("Open Default", "CTRL+SHIFT+O", &Selected.OpenDefault, true);
ImGui::MenuItem("Load Default Options", "CTRL+SHIFT+D", &Selected.LoadDefault, true);
ImGui::MenuItem("Save", "CTRL+S", &Selected.Save, true);
ImGui::MenuItem("Save As", "CTRL+SHIFT+S", &Selected.SaveAs, true);
ImGui::MenuItem("Save As App profile", "CTRL+E", nullptr, true);
ImGui::MenuItem("Save Default", "CTRL+SHIFT+P", &Selected.SaveDefault, true);
ImGui::MenuItem("Close", "CTRL+W", &Selected.Close, true);
ImGui::EndMenu();
}
ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::GetFrameHeight());
if (ConfigOpen) {
if (ConfigChanged) {
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(1.0, 1.0, 0.0, 1.0));
ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(1.0, 1.0, 0.0, 1.0));
}
else {
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0, 1.0, 0.0, 1.0));
ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(0.0, 1.0, 0.0, 1.0));
}
}
else {
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0, 1.0, 0.0, 1.0));
ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(0.0, 1.0, 0.0, 1.0));
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(1.0, 0.0, 0.0, 1.0));
ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(1.0, 0.0, 0.0, 1.0));
}
}
else {
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(1.0, 0.0, 0.0, 1.0));
ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(1.0, 0.0, 0.0, 1.0));
ImGui::RadioButton("", true);
ImGui::PopStyleColor(2);
ImGui::EndMenuBar();
}
ImGui::RadioButton("", true);
ImGui::PopStyleColor(2);
if (ConfigOpen) {
if (ImGui::Begin("#Config")) {
FillConfigWindow();
}
ImGui::EndMenuBar();
if (ImGui::IsKeyPressed(GLFW_KEY_E) && io.KeyCtrl) {
ImGui::OpenPopup(SavedPopupAppName);
}
ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x + viewport->Size.x / 2, viewport->Pos.y + viewport->Size.y / 2), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
if (ImGui::BeginPopupModal(SavedPopupAppName)) {
if (ImGui::InputText("App name", AppName, 256, ImGuiInputTextFlags_EnterReturnsTrue)) {
std::string AppNameString = AppName;
std::string Filename = FEX::Config::GetApplicationConfig(AppNameString, false);
SaveFile(Filename);
ImGui::CloseCurrentPopup();
}
if (ImGui::IsKeyPressed(GLFW_KEY_ESCAPE)) {
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
// Need this frame delay loop since ImGui doesn't allow us to enable a popup near the end of the frame
if (OpenMsgPopup) {
ImGui::OpenPopup(MsgPopupName);
OpenMsgPopup = false;
}
// Center the saved popup in the center of the window
ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x + viewport->Size.x / 2, viewport->Pos.y + viewport->Size.y / 2), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
if (ImGui::BeginPopup(MsgPopupName)) {
ImGui::Text("%s", MsgMessage.c_str());
if ((std::chrono::high_resolution_clock::now() - MsgTimerStart) >= std::chrono::seconds(2)) {
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
ImGui::End();
}
if (Selected.Open ||
(ImGui::IsKeyPressed(GLFW_KEY_O) && io.KeyCtrl && !io.KeyShift)) {
SelectedOpenFile = true;
}
if (Selected.OpenDefault ||
(ImGui::IsKeyPressed(GLFW_KEY_O) && io.KeyCtrl && io.KeyShift)) {
OpenFile(FEX::Config::GetConfigFileLocation());
}
if (Selected.LoadDefault ||
(ImGui::IsKeyPressed(GLFW_KEY_D) && io.KeyCtrl && io.KeyShift)) {
LoadDefaultSettings();
}
if (Selected.Save ||
(ImGui::IsKeyPressed(GLFW_KEY_S) && io.KeyCtrl && !io.KeyShift)) {
SaveFile(ConfigFilename);
}
if (Selected.SaveAs ||
(ImGui::IsKeyPressed(GLFW_KEY_S) && io.KeyCtrl && io.KeyShift)) {
SelectedSaveFileAs = true;
}
if (Selected.SaveDefault ||
(ImGui::IsKeyPressed(GLFW_KEY_P) && io.KeyCtrl && io.KeyShift)) {
SaveFile(FEX::Config::GetConfigFileLocation());
}
if (Selected.Close ||
(ImGui::IsKeyPressed(GLFW_KEY_W) && io.KeyCtrl && !io.KeyShift)) {
CloseConfig();
}
ImGui::End(); // End dockspace
char const *InitialPath;
char const *File;
InitialPath = DialogOpen.chooseFileDialog(SelectedOpenFile, "./", ".json", "#Chose a config to load");
File = DialogOpen.getChosenPath();
if (strlen(InitialPath) > 0 && strlen(File) > 0) {
OpenFile(File);
}
InitialPath = DialogSaveAs.saveFileDialog(SelectedSaveFileAs, "./", "Config.json", ".json", "#Choose where to save a config");
File = DialogSaveAs.getChosenPath();
if (strlen(InitialPath) > 0 && strlen(File) > 0) {
SaveFile(File);
}
SelectedOpenFile = false;
SelectedSaveFileAs = false;
ImGui::Render();
}
if (ConfigOpen) {
if (ImGui::Begin("#Config")) {
FillConfigWindow();
}
// Need this frame delay loop since ImGui doesn't allow us to enable a popup near the end of the frame
if (OpenSavedPopup) {
ImGui::OpenPopup(SavedPopupName);
OpenSavedPopup = false;
}
// Center the saved popup in the center of the window
ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x + viewport->Size.x / 2, viewport->Pos.y + viewport->Size.y / 2), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
if (ImGui::BeginPopup(SavedPopupName)) {
ImGui::Text("Config Saved to: '%s'", ConfigFilename.c_str());
if ((std::chrono::high_resolution_clock::now() - SavedTimerStart) >= std::chrono::seconds(2)) {
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
if (ImGui::IsKeyPressed(GLFW_KEY_E) && io.KeyCtrl) {
ImGui::OpenPopup(SavedPopupAppName);
}
ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x + viewport->Size.x / 2, viewport->Pos.y + viewport->Size.y / 2), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
if (ImGui::BeginPopupModal(SavedPopupAppName)) {
if (ImGui::InputText("App name", AppName, 256, ImGuiInputTextFlags_EnterReturnsTrue)) {
std::string AppNameString = AppName;
std::string Filename = FEX::Config::GetApplicationConfig(AppNameString, false);
SaveFile(Filename);
ImGui::CloseCurrentPopup();
}
if (ImGui::IsKeyPressed(GLFW_KEY_ESCAPE)) {
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
ImGui::End();
}
if (Selected.Open ||
(ImGui::IsKeyPressed(GLFW_KEY_O) && io.KeyCtrl && !io.KeyShift)) {
SelectedOpenFile = true;
}
if (Selected.OpenDefault ||
(ImGui::IsKeyPressed(GLFW_KEY_O) && io.KeyCtrl && io.KeyShift)) {
OpenFile(FEX::Config::GetConfigFileLocation());
}
if (Selected.LoadDefault ||
(ImGui::IsKeyPressed(GLFW_KEY_D) && io.KeyCtrl && io.KeyShift)) {
LoadDefaultSettings();
}
if (Selected.Save ||
(ImGui::IsKeyPressed(GLFW_KEY_S) && io.KeyCtrl && !io.KeyShift)) {
SaveFile(ConfigFilename);
}
if (Selected.SaveAs ||
(ImGui::IsKeyPressed(GLFW_KEY_S) && io.KeyCtrl && io.KeyShift)) {
SelectedSaveFileAs = true;
}
if (Selected.SaveDefault ||
(ImGui::IsKeyPressed(GLFW_KEY_P) && io.KeyCtrl && io.KeyShift)) {
SaveFile(FEX::Config::GetConfigFileLocation());
}
if (Selected.Close ||
(ImGui::IsKeyPressed(GLFW_KEY_W) && io.KeyCtrl && !io.KeyShift)) {
CloseConfig();
}
ImGui::End(); // End dockspace
char const *InitialPath;
char const *File;
InitialPath = DialogOpen.chooseFileDialog(SelectedOpenFile, "./", ".json", "#Chose a config to load");
File = DialogOpen.getChosenPath();
if (strlen(InitialPath) > 0 && strlen(File) > 0) {
OpenFile(File);
}
InitialPath = DialogSaveAs.saveFileDialog(SelectedSaveFileAs, "./", "Config.json", ".json", "#Choose where to save a config");
File = DialogSaveAs.getChosenPath();
if (strlen(InitialPath) > 0 && strlen(File) > 0) {
SaveFile(File);
}
SelectedOpenFile = false;
SelectedSaveFileAs = false;
ImGui::Render();
}
}
int main() {
@ -529,10 +536,10 @@ int main() {
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
GLFWwindow* backup_current_context = glfwGetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
glfwMakeContextCurrent(backup_current_context);
GLFWwindow* backup_current_context = glfwGetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
glfwMakeContextCurrent(backup_current_context);
}
Context->Swap();