Procházet zdrojové kódy

core: Consolidate top-level system state into a singleton.

bunnei před 9 roky
rodič
revize
198b6c9bdd

+ 14 - 21
src/citra/citra.cpp

@@ -64,7 +64,7 @@ int main(int argc, char** argv) {
         return -1;
     }
 #endif
-    std::string boot_filename;
+    std::string filepath;
 
     static struct option long_options[] = {
         {"gdbport", required_argument, 0, 'g'},
@@ -97,9 +97,9 @@ int main(int argc, char** argv) {
             }
         } else {
 #ifdef _WIN32
-            boot_filename = Common::UTF16ToUTF8(argv_w[optind]);
+            filepath = Common::UTF16ToUTF8(argv_w[optind]);
 #else
-            boot_filename = argv[optind];
+            filepath = argv[optind];
 #endif
             optind++;
         }
@@ -115,7 +115,7 @@ int main(int argc, char** argv) {
     MicroProfileOnThreadCreate("EmuThread");
     SCOPE_EXIT({ MicroProfileShutdown(); });
 
-    if (boot_filename.empty()) {
+    if (filepath.empty()) {
         LOG_CRITICAL(Frontend, "Failed to load ROM: No ROM specified");
         return -1;
     }
@@ -127,27 +127,20 @@ int main(int argc, char** argv) {
     Settings::values.use_gdbstub = use_gdbstub;
     Settings::Apply();
 
-    std::unique_ptr<EmuWindow_SDL2> emu_window = std::make_unique<EmuWindow_SDL2>();
+    std::unique_ptr<EmuWindow_SDL2> emu_window{ std::make_unique<EmuWindow_SDL2>() };
 
-    std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(boot_filename);
-    if (!loader) {
-        LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", boot_filename.c_str());
-        return -1;
-    }
-
-    boost::optional<u32> system_mode = loader->LoadKernelSystemMode();
+    Core::System& system{ Core::System::GetInstance() };
 
-    if (!system_mode) {
-        LOG_CRITICAL(Frontend, "Failed to load ROM (Could not determine system mode)!");
-        return -1;
-    }
+    SCOPE_EXIT({ system.Shutdown(); });
 
-    System::Init(emu_window.get(), system_mode.get());
-    SCOPE_EXIT({ System::Shutdown(); });
+    const Core::System::ResultStatus load_result{ system.Load(emu_window.get(), filepath) };
 
-    Loader::ResultStatus load_result = loader->Load();
-    if (Loader::ResultStatus::Success != load_result) {
-        LOG_CRITICAL(Frontend, "Failed to load ROM (Error %i)!", load_result);
+    switch (load_result) {
+    case Core::System::ResultStatus::ErrorGetLoader:
+        LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filepath.c_str());
+        return -1;
+    case Core::System::ResultStatus::ErrorLoader:
+        LOG_CRITICAL(Frontend, "Failed to load ROM!");
         return -1;
     }
 

+ 1 - 1
src/citra_qt/bootmanager.cpp

@@ -60,7 +60,7 @@ void EmuThread::run() {
     }
 
     // Shutdown the core emulation
-    System::Shutdown();
+    Core::System::GetInstance().Shutdown();
 
 #if MICROPROFILE_ENABLED
     MicroProfileOnThreadExit();

+ 1 - 1
src/citra_qt/configure_general.cpp

@@ -14,7 +14,7 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent)
     ui->setupUi(this);
     this->setConfiguration();
 
-    ui->toggle_cpu_jit->setEnabled(!System::IsPoweredOn());
+    ui->toggle_cpu_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn());
 }
 
 ConfigureGeneral::~ConfigureGeneral() {}

+ 1 - 1
src/citra_qt/configure_graphics.cpp

@@ -13,7 +13,7 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent)
     ui->setupUi(this);
     this->setConfiguration();
 
-    ui->toggle_vsync->setEnabled(!System::IsPoweredOn());
+    ui->toggle_vsync->setEnabled(!Core::System::GetInstance().IsPoweredOn());
 }
 
 ConfigureGraphics::~ConfigureGraphics() {}

+ 1 - 1
src/citra_qt/configure_system.cpp

@@ -24,7 +24,7 @@ ConfigureSystem::ConfigureSystem(QWidget* parent) : QWidget(parent), ui(new Ui::
 ConfigureSystem::~ConfigureSystem() {}
 
 void ConfigureSystem::setConfiguration() {
-    enabled = !System::IsPoweredOn();
+    enabled = !Core::System::GetInstance().IsPoweredOn();
 
     if (!enabled) {
         ReadSystemSettings();

+ 26 - 55
src/citra_qt/main.cpp

@@ -274,7 +274,7 @@ void GMainWindow::OnDisplayTitleBars(bool show) {
     }
 }
 
-bool GMainWindow::InitializeSystem(u32 system_mode) {
+bool GMainWindow::LoadROM(const std::string& filename) {
     // Shutdown previous session if the emu thread is still active...
     if (emu_thread != nullptr)
         ShutdownGame();
@@ -284,79 +284,50 @@ bool GMainWindow::InitializeSystem(u32 system_mode) {
 
     if (!gladLoadGL()) {
         QMessageBox::critical(this, tr("Error while starting Citra!"),
-                              tr("Failed to initialize the video core!\n\n"
-                                 "Please ensure that your GPU supports OpenGL 3.3 and that you "
-                                 "have the latest graphics driver."));
+            tr("Failed to initialize the video core!\n\n"
+                "Please ensure that your GPU supports OpenGL 3.3 and that you "
+                "have the latest graphics driver."));
         return false;
     }
 
-    // Initialize the core emulation
-    System::Result system_result = System::Init(render_window, system_mode);
-    if (System::Result::Success != system_result) {
-        switch (system_result) {
-        case System::Result::ErrorInitVideoCore:
-            QMessageBox::critical(this, tr("Error while starting Citra!"),
-                                  tr("Failed to initialize the video core!\n\n"
-                                     "Please ensure that your GPU supports OpenGL 3.3 and that you "
-                                     "have the latest graphics driver."));
-            break;
+    Core::System& system{ Core::System::GetInstance() };
 
-        default:
-            QMessageBox::critical(this, tr("Error while starting Citra!"),
-                                  tr("Unknown error (please check the log)!"));
-            break;
-        }
-        return false;
-    }
-    return true;
-}
+    const Core::System::ResultStatus result{ system.Load(render_window, filename) };
 
-bool GMainWindow::LoadROM(const std::string& filename) {
-    std::unique_ptr<Loader::AppLoader> app_loader = Loader::GetLoader(filename);
-    if (!app_loader) {
-        LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filename.c_str());
-        QMessageBox::critical(this, tr("Error while loading ROM!"),
-                              tr("The ROM format is not supported."));
-        return false;
-    }
-
-    boost::optional<u32> system_mode = app_loader->LoadKernelSystemMode();
-    if (!system_mode) {
-        LOG_CRITICAL(Frontend, "Failed to load ROM!");
-        QMessageBox::critical(this, tr("Error while loading ROM!"),
-                              tr("Could not determine the system mode."));
-        return false;
-    }
-
-    if (!InitializeSystem(system_mode.get()))
-        return false;
+    if (result != Core::System::ResultStatus::Success) {
+        switch (result) {
+        case Core::System::ResultStatus::ErrorGetLoader:
+            LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filename.c_str());
+            QMessageBox::critical(this, tr("Error while loading ROM!"),
+                tr("The ROM format is not supported."));
+            break;
 
-    Loader::ResultStatus result = app_loader->Load();
-    if (Loader::ResultStatus::Success != result) {
-        System::Shutdown();
-        LOG_CRITICAL(Frontend, "Failed to load ROM!");
+        case Core::System::ResultStatus::ErrorSystemMode:
+            LOG_CRITICAL(Frontend, "Failed to load ROM!");
+            QMessageBox::critical(this, tr("Error while loading ROM!"),
+                tr("Could not determine the system mode."));
+            break;
 
-        switch (result) {
-        case Loader::ResultStatus::ErrorEncrypted: {
+        case Core::System::ResultStatus::ErrorLoader_ErrorEncrypted:
+        {
             // Build the MessageBox ourselves to have clickable link
             QMessageBox popup_error;
             popup_error.setTextFormat(Qt::RichText);
             popup_error.setWindowTitle(tr("Error while loading ROM!"));
             popup_error.setText(
                 tr("The game that you are trying to load must be decrypted before being used with "
-                   "Citra.<br/><br/>"
-                   "For more information on dumping and decrypting games, please see: <a "
-                   "href='https://citra-emu.org/wiki/Dumping-Game-Cartridges'>https://"
-                   "citra-emu.org/wiki/Dumping-Game-Cartridges</a>"));
+                    "Citra.<br/><br/>"
+                    "For more information on dumping and decrypting games, please see: <a "
+                    "href='https://citra-emu.org/wiki/Dumping-Game-Cartridges'>https://"
+                    "citra-emu.org/wiki/Dumping-Game-Cartridges</a>"));
             popup_error.setIcon(QMessageBox::Critical);
             popup_error.exec();
             break;
         }
-        case Loader::ResultStatus::ErrorInvalidFormat:
+        case Core::System::ResultStatus::ErrorLoader_ErrorInvalidFormat:
             QMessageBox::critical(this, tr("Error while loading ROM!"),
-                                  tr("The ROM format is not supported."));
+                tr("The ROM format is not supported."));
             break;
-        case Loader::ResultStatus::Error:
 
         default:
             QMessageBox::critical(this, tr("Error while loading ROM!"), tr("Unknown error!"));

+ 48 - 13
src/core/system.cpp

@@ -13,33 +13,30 @@
 #include "core/system.h"
 #include "video_core/video_core.h"
 
-namespace System {
+namespace Core {
 
-static bool is_powered_on{false};
+/*static*/ System System::s_instance;
 
-Result Init(EmuWindow* emu_window, u32 system_mode) {
+System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
     Core::Init();
     CoreTiming::Init();
     Memory::Init();
     HW::Init();
     Kernel::Init(system_mode);
     HLE::Init();
-    if (!VideoCore::Init(emu_window)) {
-        return Result::ErrorInitVideoCore;
-    }
     AudioCore::Init();
     GDBStub::Init();
 
-    is_powered_on = true;
+    if (!VideoCore::Init(emu_window)) {
+        return ResultStatus::ErrorVideoCore;
+    }
 
-    return Result::Success;
-}
+    is_powered_on = true;
 
-bool IsPoweredOn() {
-    return is_powered_on;
+    return ResultStatus::Success;
 }
 
-void Shutdown() {
+void System::Shutdown() {
     GDBStub::Shutdown();
     AudioCore::Shutdown();
     VideoCore::Shutdown();
@@ -52,4 +49,42 @@ void Shutdown() {
     is_powered_on = false;
 }
 
-} // namespace
+System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& filepath) {
+    state.app_loader = Loader::GetLoader(filepath);
+
+    if (!state.app_loader) {
+        LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filepath.c_str());
+        return ResultStatus::ErrorGetLoader;
+    }
+
+    boost::optional<u32> system_mode{ state.app_loader->LoadKernelSystemMode() };
+    if (!system_mode) {
+        LOG_CRITICAL(Frontend, "Failed to determine system mode!");
+        return ResultStatus::ErrorSystemMode;
+    }
+
+    ResultStatus init_result{ Init(emu_window, system_mode.get()) };
+    if (init_result != ResultStatus::Success) {
+        LOG_CRITICAL(Frontend, "Failed to initialize system (Error %i)!", init_result);
+        System::Shutdown();
+        return init_result;
+    }
+
+    const Loader::ResultStatus load_result{ state.app_loader->Load() };
+    if (Loader::ResultStatus::Success != load_result) {
+        LOG_CRITICAL(Frontend, "Failed to load ROM (Error %i)!", load_result);
+        System::Shutdown();
+
+        switch (load_result) {
+        case Loader::ResultStatus::ErrorEncrypted:
+            return ResultStatus::ErrorLoader_ErrorEncrypted;
+        case Loader::ResultStatus::ErrorInvalidFormat:
+            return ResultStatus::ErrorLoader_ErrorInvalidFormat;
+        default:
+            return ResultStatus::ErrorLoader;
+        }
+    }
+    return ResultStatus::Success;
+}
+
+} // namespace Core

+ 72 - 10
src/core/system.h

@@ -4,18 +4,80 @@
 
 #pragma once
 
+#include <string>
+
+#include "core/loader/loader.h"
+
 class EmuWindow;
 
-namespace System {
+namespace Core {
+
+class System {
+public:
+    struct State {
+        std::unique_ptr<Loader::AppLoader> app_loader;
+    };
+
+    /**
+     * Gets the instance of the System singleton class.
+     * @returns Reference to the instance of the System singleton class.
+     */
+    static System& GetInstance() {
+        return s_instance;
+    }
+
+    /// Enumeration representing the return values of the System Initialize and Load process.
+    enum class ResultStatus : u32 {
+        Success, ///< Succeeded
+        ErrorGetLoader, ///< Error finding the correct application loader
+        ErrorSystemMode, ///< Error determining the system mode
+        ErrorLoader, ///< Error loading the specified application
+        ErrorLoader_ErrorEncrypted, ///< Error loading the specified application due to encryption
+        ErrorLoader_ErrorInvalidFormat, ///< Error loading the specified application due to an invalid format
+        ErrorVideoCore, ///< Error in the video core
+    };
+
+    /**
+     * Initialize the emulated system.
+     * @param emu_window Pointer to the host-system window used for video output and keyboard input.
+     * @param system_mode The system mode.
+     * @returns ResultStatus code, indicating if the operation succeeded.
+     */
+    ResultStatus Init(EmuWindow* emu_window, u32 system_mode);
+
+    /// Shutdown the emulated system.
+    void Shutdown();
+
+    /**
+     * Load an executable application.
+     * @param emu_window Pointer to the host-system window used for video output and keyboard input.
+     * @param filepath String path to the executable application to load on the host file system.
+     * @returns ResultStatus code, indicating if the operation succeeded.
+     */
+    ResultStatus Load(EmuWindow* emu_window, const std::string& filepath);
+
+    /**
+     * Indicates if the emulated system is powered on (all subsystems initialized and able to run an
+     * application).
+     * @returns True if the emulated system is powered on, otherwise false.
+     */
+    bool IsPoweredOn() const {
+        return is_powered_on;
+    }
+
+    /**
+     * Gets the internal state of the emulated system.
+     * @returns The internal state of the emulated system
+     */
+    State& GetState() {
+        return state;
+    }
+
+private:
+    bool is_powered_on{};
+    State state;
 
-enum class Result {
-    Success,            ///< Everything is fine
-    Error,              ///< Something went wrong (no module specified)
-    ErrorInitCore,      ///< Something went wrong during core init
-    ErrorInitVideoCore, ///< Something went wrong during video core init
+    static System s_instance;
 };
 
-Result Init(EmuWindow* emu_window, u32 system_mode);
-bool IsPoweredOn();
-void Shutdown();
-}
+} // namespace Core