Skip to content

Commit

Permalink
config: moved json parser to platform/windows package
Browse files Browse the repository at this point in the history
  • Loading branch information
JaCzekanski committed Mar 31, 2020
1 parent 939889d commit 8cdaa01
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 107 deletions.
85 changes: 6 additions & 79 deletions src/config.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
#include "config.h"
#include <fmt/core.h>
#include <nlohmann/json.hpp>
#include "device/controller/controller_type.h"
#include "device/gpu/rendering_mode.h"
#include "utils/file.h"
// TODO: json enums!

const char* CONFIG_NAME = "config.json";

namespace DefaultKeyBindings {
// clang-format off
avocado_config_t::KeyBindings none() {
KeyBindings none() {
return {
{"dpad_up", ""},
{"dpad_right", ""},
Expand Down Expand Up @@ -40,7 +33,7 @@ avocado_config_t::KeyBindings none() {
};
}

avocado_config_t::KeyBindings keyboard_wadx() {
KeyBindings keyboard_wadx() {
return {
{"dpad_up", "keyboard|Up"},
{"dpad_right", "keyboard|Right"},
Expand Down Expand Up @@ -69,7 +62,7 @@ avocado_config_t::KeyBindings keyboard_wadx() {
{"r_left", ""},
};
}
avocado_config_t::KeyBindings keyboard_numpad() {
KeyBindings keyboard_numpad() {
return {
{"dpad_up", "keyboard|Up"},
{"dpad_right", "keyboard|Right"},
Expand Down Expand Up @@ -99,7 +92,7 @@ avocado_config_t::KeyBindings keyboard_numpad() {
};
}

avocado_config_t::KeyBindings controller(int n) {
KeyBindings controller(int n) {
auto C = [n](const char* key) {
return fmt::format("controller{}|{}", n, key);
};
Expand Down Expand Up @@ -132,7 +125,7 @@ avocado_config_t::KeyBindings controller(int n) {
};
}

avocado_config_t::KeyBindings mouse() {
KeyBindings mouse() {
return {
{"dpad_up", ""},
{"dpad_right", ""},
Expand Down Expand Up @@ -164,71 +157,5 @@ avocado_config_t::KeyBindings mouse() {
// clang-format on
} // namespace DefaultKeyBindings

const avocado_config_t defaultConfig {
.bios = "",
.extension = "",
.iso = "",
.controller = {
{
.type = ControllerType::analog,
.keys = DefaultKeyBindings::keyboard_numpad(),
},
{
.type = ControllerType::none,
.keys = DefaultKeyBindings::none(),
},
},
.memoryCard = {
{
.path = "data/memory/card1.mcr"
},
{
.path = ""
},
},
};

const avocado_config_t defaultConfig;
avocado_config_t config = defaultConfig;

using json = nlohmann::json;
json fixObject(json oldconfig, json newconfig) {
for (auto oldField = oldconfig.begin(); oldField != oldconfig.end(); ++oldField) {
auto newField = newconfig.find(oldField.key());

// Add nonexisting fields
if (newField == newconfig.end()) {
newconfig.emplace(oldField.key(), oldField.value());
continue;
}

// Repair these with invalid types
if (newField.value().type() != oldField.value().type()) {
newconfig[oldField.key()] = oldField.value();
continue;
}

// If field is an object or an array - fix it recursively
if (newField.value().is_object() || newField.value().is_array()) {
newconfig[oldField.key()] = fixObject(oldField.value(), newField.value());
}
}
return newconfig;
}

void saveConfigFile(const char* configName) {
// putFileContents(configName, config.dump(4));
}

void loadConfigFile(const char* configName) {
auto file = getFileContents(configName);
if (file.empty()) {
saveConfigFile(configName);
return;
}
nlohmann::json newconfig = json::parse(file.begin(), file.end());

// Add missing and repair invalid fields
// config = fixObject(config, newconfig);
}

bool isEmulatorConfigured() { return !config.bios.empty(); }
60 changes: 33 additions & 27 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,34 @@
#define printf(...) __android_log_print(ANDROID_LOG_DEBUG, "AVOCADO", __VA_ARGS__);
#endif

struct avocado_config_t {
using string = std::string;
using KeyBindings = std::unordered_map<std::string, std::string>;
using KeyBindings = std::unordered_map<std::string, std::string>;

namespace DefaultKeyBindings {
KeyBindings none();
KeyBindings keyboard_wadx();
KeyBindings keyboard_numpad();
KeyBindings mouse();
KeyBindings controller(int n);
} // namespace DefaultKeyBindings

string bios = "";
string extension = "";
string iso = "";
struct avocado_config_t {
std::string bios = "";
std::string extension = "";
std::string iso = "";

struct {
ControllerType type;
KeyBindings keys;
} controller[2];
} controller[2]{
{
.type = ControllerType::analog,
.keys = DefaultKeyBindings::keyboard_numpad(),
},
{
.type = ControllerType::none,
.keys = DefaultKeyBindings::none(),
},
};

struct {
struct {
Expand All @@ -42,7 +58,7 @@ struct avocado_config_t {

struct {
bool preserveState = true;
bool timeTravel = false; // Change it?
bool timeTravel = false;
} emulator;

} options;
Expand All @@ -63,28 +79,18 @@ struct avocado_config_t {
} debug;

struct {
string path;
} memoryCard[2];
std::string path;
} memoryCard[2]{
{.path = "data/memory/card1.mcr"}, //
{.path = ""}, //
};

struct {
string lastPath = "";
std::string lastPath = "";
} gui;

// Methods
bool isEmulatorConfigured() const { return !bios.empty(); }
};

extern avocado_config_t config;

namespace DefaultKeyBindings {
avocado_config_t::KeyBindings none();
avocado_config_t::KeyBindings keyboard_wadx();
avocado_config_t::KeyBindings keyboard_numpad();
avocado_config_t::KeyBindings mouse();
avocado_config_t::KeyBindings controller(int n);
} // namespace DefaultKeyBindings

extern const char* CONFIG_NAME;
extern const avocado_config_t defaultConfig;
// extern nlohmann::json config;
void saveConfigFile(const char* configName);
void loadConfigFile(const char* configName);

bool isEmulatorConfigured();
150 changes: 150 additions & 0 deletions src/platform/windows/config_parser.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
#include "config_parser.h"
#include <nlohmann/json.hpp>
#include <fmt/core.h>
#include "config.h"
#include "device/controller/controller_type.h"
#include "device/gpu/rendering_mode.h"
#include "utils/file.h"
#include "utils/json_enum.h"

// For now .json format is used for config serialization.
// Might switch to .toml some day

const char* CONFIG_NAME = "config.json";
void saveConfigFile(const char* configName);
void loadConfigFile(const char* configName);

JSON_ENUM(ControllerType);
JSON_ENUM(RenderingMode);

void saveConfigFile(const char* configName) {
nlohmann::json json;
json["bios"] = config.bios;
json["extension"] = config.extension;
json["iso"] = config.iso;

for (int i = 0; i < 2; i++) {
json["controller"][std::to_string(i + 1)] = {
{"type", config.controller[i].type},
{"keys", config.controller[i].keys},
};
}

auto g = config.options.graphics;
json["options"]["graphics"] = {
{"renderingMode", g.renderingMode},
{"widescreen", g.widescreen},
{"forceWidescreen", g.forceWidescreen},
{
"resolution",
{
{"width", g.resolution.width},
{"height", g.resolution.height},
},
},
{"vsync", g.vsync},
{"forceNtsc", g.forceNtsc},
};

json["options"]["sound"] = {
{"enabled", config.options.sound.enabled},
};

json["options"]["emulator"] = {
{"preserveState", config.options.emulator.preserveState},
{"timeTravel", config.options.emulator.timeTravel},
};

auto l = config.debug.log;
json["debug"]["log"] = {
{"bios", l.bios}, //
{"cdrom", l.cdrom}, //
{"controller", l.controller}, //
{"dma", l.dma}, //
{"gpu", l.gpu}, //
{"gte", l.gte}, //
{"mdec", l.mdec}, //
{"memoryCard", l.memoryCard}, //
{"spu", l.spu}, //
{"system", l.system}, //
};

for (int i = 0; i < 2; i++) {
json["memoryCard"][std::to_string(i + 1)] = config.memoryCard[i].path;
}

json["gui"] = {
{"lastPath", config.gui.lastPath},
};

putFileContents(configName, json.dump(4));
}

void loadConfigFile(const char* configName) {
auto file = getFileContents(configName);
if (file.empty()) {
saveConfigFile(configName);
return;
}
nlohmann::json json = nlohmann::json::parse(file.begin(), file.end());

try {
config.bios = json["bios"];
config.extension = json["extension"];
config.iso = json["iso"];

for (int i = 0; i < 2; i++) {
auto ctrl = json["controller"][std::to_string(i + 1)];
if (ctrl.is_null()) continue;

config.controller[i].type = ctrl["type"];
config.controller[i].keys = ctrl["keys"].get<KeyBindings>();
}

if (auto g = json["options"]["graphics"]; !g.is_null()) {
config.options.graphics.renderingMode = g["renderingMode"];
config.options.graphics.widescreen = g["widescreen"];
config.options.graphics.forceWidescreen = g["forceWidescreen"];
config.options.graphics.resolution.width = g["resolution"]["width"];
config.options.graphics.resolution.height = g["resolution"]["height"];
config.options.graphics.vsync = g["vsync"];
config.options.graphics.forceNtsc = g["forceNtsc"];
}

if (auto s = json["options"]["sound"]; !s.is_null()) {
config.options.sound.enabled = s["enabled"];
}

if (auto e = json["options"]["emulator"]; !e.is_null()) {
config.options.emulator.preserveState = e["preserveState"];
config.options.emulator.timeTravel = e["timeTravel"];
}

if (auto l = json["debug"]["log"]; !l.is_null()) {
config.debug.log.bios = l["bios"];
config.debug.log.cdrom = l["cdrom"];
config.debug.log.controller = l["controller"];
config.debug.log.dma = l["dma"];
config.debug.log.gpu = l["gpu"];
config.debug.log.gte = l["gte"];
config.debug.log.mdec = l["mdec"];
config.debug.log.memoryCard = l["memoryCard"];
config.debug.log.spu = l["spu"];
config.debug.log.system = l["system"];
}

for (int i = 0; i < 2; i++) {
auto card = json["memoryCard"][std::to_string(i + 1)];
if (card.is_null()) continue;

config.memoryCard[i].path = card;
}

if (auto g = json["gui"]; !g.is_null()) {
config.gui.lastPath = g["lastPath"];
}

} catch (nlohmann::json::exception& e) {
fmt::print("[ERROR] Cannot load {} - {}\n", configName, e.what());
}
}
5 changes: 5 additions & 0 deletions src/platform/windows/config_parser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

extern const char* CONFIG_NAME;
void saveConfigFile(const char* configName);
void loadConfigFile(const char* configName);
2 changes: 1 addition & 1 deletion src/platform/windows/gui/gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ void GUI::render(System* sys) {
aboutHelp.displayWindows();
}

if (!isEmulatorConfigured() && !notInitializedWindowShown) {
if (!config.isEmulatorConfigured() && !notInitializedWindowShown) {
notInitializedWindowShown = true;
ImGui::OpenPopup("Avocado");
}
Expand Down
1 change: 1 addition & 0 deletions src/platform/windows/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <cstdio>
#include <string>
#include "config.h"
#include "config_parser.h"
#include "gui/gui.h"
#include "input/sdl_input_manager.h"
#include "renderer/opengl/opengl.h"
Expand Down

0 comments on commit 8cdaa01

Please sign in to comment.