summaryrefslogblamecommitdiffstats
path: root/src/core/core.h
blob: f81cbfb3ccfc390447146552896d8267fea0b1d0 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                        
                                            
                                          
 
            
 
                 
                 
                                
                                   
                                      
                               
                        
                            
                                   
                                               
                           
 
                
                    
 



                       

                

              

              









                                                                                             




                                                                                         
                                                                                                  

                                                                                              

                                                                          
                                                                    
                                                                                   
                                                            


       
                            




                                                                                                    
                                                        
                                                                                
       
                                                 


                                   
                                                                                



















                                                                                                    
                                   

     







                                                                               


                                                   

                                              
       

                                                
       

                          

     



                         



                                    



                                                          
                         
                               
 
                                                                            
                            


                                     

     
                                                 
                              

     



                                             


                                                              







                                                                           
        










                                                                                                    


                                                                
                                            
                                                 

                                         

                                                       

                                                       


                                                          


                                                                 


                                                              
                             
 

                                                
  
 
                             
                                       
 
 



                                                    



                                                             
                   
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

#pragma once

#include <memory>
#include <string>
#include "common/common_types.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/scheduler.h"
#include "core/loader/loader.h"
#include "core/memory.h"
#include "core/perf_stats.h"
#include "core/telemetry_session.h"
#include "video_core/debug_utils/debug_utils.h"
#include "video_core/gpu.h"

class EmuWindow;
class ARM_Interface;

namespace Service::SM {
class ServiceManager;
}

namespace Core {

class System {
public:
    ~System();

    /**
     * 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
        ErrorNotInitialized,        ///< Error trying to use core prior to initialization
        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
        ErrorSystemFiles,               ///< Error in finding system files
        ErrorSharedFont,                ///< Error in finding shared font
        ErrorVideoCore,                 ///< Error in the video core
        ErrorUnsupportedArch,           ///< Unsupported Architecture (32-Bit ROMs)
        ErrorUnknown                    ///< Any other error
    };

    /**
     * Run the core CPU loop
     * This function runs the core for the specified number of CPU instructions before trying to
     * update hardware. This is much faster than SingleStep (and should be equivalent), as the CPU
     * is not required to do a full dispatch with each instruction. NOTE: the number of instructions
     * requested is not guaranteed to run, as this will be interrupted preemptively if a hardware
     * update is requested (e.g. on a thread switch).
     * @param tight_loop If false, the CPU single-steps.
     * @return Result status, indicating whether or not the operation succeeded.
     */
    ResultStatus RunLoop(bool tight_loop = true);

    /**
     * Step the CPU one instruction
     * @return Result status, indicating whether or not the operation succeeded.
     */
    ResultStatus SingleStep();

    /// 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 cpu_core != nullptr;
    }

    /**
     * Returns a reference to the telemetry session for this emulation session.
     * @returns Reference to the telemetry session.
     */
    Core::TelemetrySession& TelemetrySession() const {
        return *telemetry_session;
    }

    /// Prepare the core emulation for a reschedule
    void PrepareReschedule();

    PerfStats::Results GetAndResetPerfStats();

    /**
     * Gets a reference to the emulated CPU.
     * @returns A reference to the emulated CPU.
     */
    ARM_Interface& CPU() {
        return *cpu_core;
    }

    Tegra::GPU& GPU() {
        return *gpu_core;
    }

    Kernel::Scheduler& Scheduler() {
        return *scheduler;
    }

    Kernel::SharedPtr<Kernel::Process>& CurrentProcess() {
        return current_process;
    }

    PerfStats perf_stats;
    FrameLimiter frame_limiter;

    void SetStatus(ResultStatus new_status, const char* details = nullptr) {
        status = new_status;
        if (details) {
            status_details = details;
        }
    }

    const std::string& GetStatusDetails() const {
        return status_details;
    }

    Loader::AppLoader& GetAppLoader() const {
        return *app_loader;
    }

    Service::SM::ServiceManager& ServiceManager();
    const Service::SM::ServiceManager& ServiceManager() const;

    void SetGPUDebugContext(std::shared_ptr<Tegra::DebugContext> context) {
        debug_context = std::move(context);
    }

    std::shared_ptr<Tegra::DebugContext> GetGPUDebugContext() const {
        return debug_context;
    }

private:
    /**
     * 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.
     * @return ResultStatus code, indicating if the operation succeeded.
     */
    ResultStatus Init(EmuWindow* emu_window, u32 system_mode);

    /// Reschedule the core emulation
    void Reschedule();

    /// AppLoader used to load the current executing application
    std::unique_ptr<Loader::AppLoader> app_loader;

    std::shared_ptr<ARM_Interface> cpu_core;
    std::unique_ptr<Kernel::Scheduler> scheduler;
    std::unique_ptr<Tegra::GPU> gpu_core;

    std::shared_ptr<Tegra::DebugContext> debug_context;

    Kernel::SharedPtr<Kernel::Process> current_process;

    /// When true, signals that a reschedule should happen
    bool reschedule_pending{};

    /// Service manager
    std::shared_ptr<Service::SM::ServiceManager> service_manager;

    /// Telemetry session for this emulation session
    std::unique_ptr<Core::TelemetrySession> telemetry_session;

    static System s_instance;

    ResultStatus status = ResultStatus::Success;
    std::string status_details = "";
};

inline ARM_Interface& CPU() {
    return System::GetInstance().CPU();
}

inline TelemetrySession& Telemetry() {
    return System::GetInstance().TelemetrySession();
}

inline Kernel::SharedPtr<Kernel::Process>& CurrentProcess() {
    return System::GetInstance().CurrentProcess();
}

} // namespace Core