Skip to content

Commit

Permalink
Basic Configuration System (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
Xphalnos authored Jan 19, 2025
2 parents 9434a16 + 3bc2ff7 commit 6fc8d53
Show file tree
Hide file tree
Showing 11 changed files with 234 additions and 17 deletions.
6 changes: 5 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
[submodule "third_party/SDL3"]
path = third_party/SDL3
url = https://github.com/libsdl-org/SDL.git
shallow = true
shallow = true
[submodule "third_party/toml11"]
path = third_party/toml11
url = https://github.com/ToruNiina/toml11.git
shallow = true
7 changes: 6 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,16 @@ function(create_target_directory_groups target_name)
endfunction()

find_package(SDL3 3.1.10 CONFIG)
find_package(toml11 4.3.0 CONFIG)

add_subdirectory(third_party)
include_directories(Xenon)

set(Base
Xenon/Base/Config.cpp
Xenon/Base/Config.h
Xenon/Base/Path_util.cpp
Xenon/Base/Path_util.h
Xenon/Base/SystemDevice.h
Xenon/Base/Types.h
Xenon/Base/Version.h
Expand Down Expand Up @@ -134,7 +139,7 @@ add_executable(Xenon
create_target_directory_groups(Xenon)

target_include_directories(Xenon PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(Xenon PRIVATE SDL3::SDL3)
target_link_libraries(Xenon PRIVATE SDL3::SDL3 toml11::toml11)

if (WIN32)
target_sources(Xenon PRIVATE Xenon/Xenon.rc)
Expand Down
114 changes: 114 additions & 0 deletions Xenon/Base/Config.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright 2025 Xenon Emulator Project

#include <iostream>
#include <toml.hpp>

#include <fstream>
#include <string>

#include "Config.h"
#include "Path_util.h"

namespace toml {
template <typename TC, typename K>
std::filesystem::path find_fs_path_or(const basic_value<TC>& v, const K& ky,
std::filesystem::path opt) {
try {
auto str = find<std::string>(v, ky);
if (str.empty()) {
return opt;
}
std::u8string u8str{(char8_t*)&str.front(), (char8_t*)&str.back() + 1};
return std::filesystem::path{u8str};
} catch (...) {
return opt;
}
}
} // namespace toml

namespace Config {

static bool isFullscreen = false;

static s32 screenWidth = 1280;
static s32 screenHeight = 720;
// static s32 gpuId = -1; // Vulkan physical device index. Set to negative for auto select


bool getIsFullscreen() {
return isFullscreen;
}

s32 getScreenWidth() {
return screenWidth;
}

s32 getScreenHeight() {
return screenHeight;
}

// s32 getGpuId() {
// return gpuId;
// }

void load(const std::filesystem::path& path) {
// If the configuration file does not exist, create it and return
std::error_code error;
if (!std::filesystem::exists(path, error)) {
save(path);
return;
}

toml::value data;

try {
data = toml::parse(path);
} catch (std::exception& ex) {
std::cout << "Got exception trying to load config file. Exception: " << ex.what() << std::endl;
return;
}
if (data.contains("General")) {
const toml::value& general = data.at("General");

isFullscreen = toml::find_or<bool>(general, "Fullscreen", false);
}

if (data.contains("GPU")) {
const toml::value& gpu = data.at("GPU");

screenWidth = toml::find_or<int>(gpu, "screenWidth", screenWidth);
screenHeight = toml::find_or<int>(gpu, "screenHeight", screenHeight);
// gpuId = toml::find_or<int>(gpu, "gpuId", -1);
}
}

void save(const std::filesystem::path& path) {
toml::value data;

std::error_code error;
if (std::filesystem::exists(path, error)) {
try {
data = toml::parse(path);
} catch (const std::exception& ex) {
std::cout << "Exception trying to parse config file. Exception: " << ex.what() << std::endl;
return;
}
} else {
if (error) {
std::cout << "Filesystem error: " << error.message() << std::endl;
}
std::cout << "Saving new configuration file " << path.string() << std::endl;
}

data["General"]["Fullscreen"] = isFullscreen;

data["GPU"]["screenWidth"] = screenWidth;
data["GPU"]["screenHeight"] = screenHeight;
// data["GPU"]["gpuId"] = gpuId;

std::ofstream file(path, std::ios::binary);
file << data;
file.close();
}

} // namespace Config
21 changes: 21 additions & 0 deletions Xenon/Base/Config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2025 Xenon Emulator Project

#pragma once

#include <filesystem>
#include <vector>
#include "Types.h"

namespace Config {

void load(const std::filesystem::path& path);
void save(const std::filesystem::path& path);

bool getIsFullscreen();

s32 getScreenWidth();
s32 getScreenHeight();

// s32 getGpuId();

}; // namespace Config
41 changes: 41 additions & 0 deletions Xenon/Base/Path_util.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2025 Xenon Emulator Project

#include <unordered_map>
#include "Path_util.h"

namespace Base::FS {

namespace fs = std::filesystem;

static auto UserPaths = [] {

auto user_dir = std::filesystem::current_path() / PORTABLE_DIR;

std::unordered_map<PathType, fs::path> paths;

const auto create_path = [&](PathType xenon_path, const fs::path& new_path) {
std::filesystem::create_directory(new_path);
paths.insert_or_assign(xenon_path, new_path);
};

create_path(PathType::UserDir, user_dir);
return paths;
}();

std::string PathToUTF8String(const std::filesystem::path& path) {
const auto u8_string = path.u8string();
return std::string{u8_string.begin(), u8_string.end()};
}

const fs::path& GetUserPath(PathType xenon_path) {
return UserPaths.at(xenon_path);
}

std::string GetUserPathString(PathType xenon_path) {
return PathToUTF8String(GetUserPath(xenon_path));
}

void SetUserPath(PathType xenon_path, const fs::path& new_path) {
UserPaths.insert_or_assign(xenon_path, new_path);
}
}
24 changes: 24 additions & 0 deletions Xenon/Base/Path_util.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2025 Xenon Emulator Project

#pragma once

#include <filesystem>
#include <vector>

namespace Base::FS {

enum class PathType {
UserDir
};

constexpr auto PORTABLE_DIR = "Xenon";

[[nodiscard]] std::string PathToUTF8String(const std::filesystem::path& path);

[[nodiscard]] const std::filesystem::path& GetUserPath(PathType user_path);

[[nodiscard]] std::string GetUserPathString(PathType user_path);

void SetUserPath(PathType user_path, const std::filesystem::path& new_path);

}
12 changes: 6 additions & 6 deletions Xenon/Core/XGPU/XGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "XenosRegisters.h"
#include "XGPUConfig.h"

#include "Base/Config.h"
#include "Base/Version.h"

Xe::Xenos::XGPU::XGPU(RAM* ram)
Expand Down Expand Up @@ -120,7 +121,7 @@ bool Xe::Xenos::XGPU::isAddressMappedInBAR(u32 address)
return false;
}

static inline int xeFbConvert(int winWidth, int addr)
static inline int xeFbConvert(const int winWidth, const int addr)
{
const int y = addr / (winWidth * 4);
const int x = addr % (winWidth * 4) / 4;
Expand All @@ -136,8 +137,8 @@ void Xe::Xenos::XGPU::XenosThread()
// TODO(bitsh1ft3r):
// Change resolution/window size according to current AVPACK, that is according to corresponding registers inside Xenos.

winWidth = 1280;
winHeight = 720;
const s32 winWidth = Config::getScreenWidth();
const s32 winHeight = Config::getScreenHeight();

if (!SDL_Init(SDL_INIT_VIDEO))
{
Expand All @@ -161,8 +162,6 @@ void Xe::Xenos::XGPU::XenosThread()

// Rendering Mode.
bool rendering = true;
// Fullscreen Mode.
bool fullscreenMode = false;
// VSYNC Mode.
bool VSYNC = true;

Expand All @@ -184,8 +183,9 @@ void Xe::Xenos::XGPU::XenosThread()
}
if (windowEvent.key.key == SDLK_F11)
{
SDL_WindowFlags flag = SDL_GetWindowFlags(mainWindow);
bool fullscreenMode = flag & SDL_WINDOW_FULLSCREEN;
SDL_SetWindowFullscreen(mainWindow, !fullscreenMode);
fullscreenMode = !fullscreenMode;
}
break;
default:
Expand Down
1 change: 0 additions & 1 deletion Xenon/Core/XGPU/XGPU.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ namespace Xe
SDL_Renderer* renderer = nullptr;
SDL_Event windowEvent;
SDL_Texture* texture;
s32 winWidth, winHeight;
};
}
}
11 changes: 9 additions & 2 deletions Xenon/Xe_Main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// Copyright 2025 Xenon Emulator Project

#include "Base/Config.h"
#include "Base/Path_util.h"

#include "Core/RootBus/RootBus.h"
#include "Core/RAM/RAM.h"
#include "Core/NAND/NAND.h"
Expand All @@ -19,8 +22,12 @@
#include "Core/RootBus/HostBridge/PCIBridge/EHCI0/EHCI0.h"
#include "Core/RootBus/HostBridge/PCIBridge/EHCI1/EHCI1.h"

int main(int argc, char* argv[])
{
int main(int argc, char* argv[]) {

// Load configurations
const auto user_dir = Base::FS::GetUserPath(Base::FS::PathType::UserDir);
Config::load(user_dir / "Xenon.toml");

/*********Jasper motherboard CPU fuses*********/
eFuses jasperCpuFuses;
jasperCpuFuses.fuseLine00 = 0xc0ffffffffffffff;
Expand Down
13 changes: 7 additions & 6 deletions third_party/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
# SPDX-FileCopyrightText: Copyright 2025 Xenon Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2025 Xenon Emulator Project

set(BUILD_SHARED_LIBS OFF)
set(BUILD_TESTING OFF)
set_directory_properties(PROPERTIES
EXCLUDE_FROM_ALL ON
SYSTEM ON
)
set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON SYSTEM ON)

# Set CMP0069 policy to "NEW" in order to ensure consistent behavior when building external targets with LTO enabled
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
Expand All @@ -15,4 +11,9 @@ set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
if (NOT TARGET SDL3::SDL3)
set(SDL_PIPEWIRE OFF)
add_subdirectory(SDL3)
endif()

# Toml11
if (NOT TARGET toml11::toml11)
add_subdirectory(toml11)
endif()
1 change: 1 addition & 0 deletions third_party/toml11
Submodule toml11 added at 499be3

0 comments on commit 6fc8d53

Please sign in to comment.