Frontend: Support loading state while powered off

This commit is contained in:
Connor McLaughlin 2019-10-21 00:38:04 +10:00
parent 1b8b730f85
commit 6c73dc6efb
3 changed files with 58 additions and 49 deletions

View file

@ -30,15 +30,6 @@ static int Run(int argc, char* argv[])
return -1;
}
// create display and host interface
std::unique_ptr<SDLInterface> host_interface = SDLInterface::Create();
if (!host_interface)
{
Panic("Failed to create host interface");
SDL_Quit();
return -1;
}
// parameters
const char* filename = nullptr;
const char* exp1_filename = nullptr;
@ -59,23 +50,16 @@ static int Run(int argc, char* argv[])
#undef CHECK_ARG_PARAM
}
// create system
const bool boot = (filename != nullptr || exp1_filename != nullptr || !state_filename.IsEmpty());
if (boot)
// create display and host interface
std::unique_ptr<SDLInterface> host_interface =
SDLInterface::Create(filename, exp1_filename, state_filename.IsEmpty() ? nullptr : state_filename.GetCharArray());
if (!host_interface)
{
if (!host_interface->InitializeSystem(filename, exp1_filename))
{
host_interface.reset();
Panic("Failed to create host interface");
SDL_Quit();
return -1;
}
host_interface->ConnectDevices();
if (!state_filename.IsEmpty())
host_interface->LoadState(state_filename);
}
// run
host_interface->Run();

View file

@ -193,7 +193,30 @@ bool SDLInterface::CreateAudioStream()
return true;
}
std::unique_ptr<SDLInterface> SDLInterface::Create()
bool SDLInterface::InitializeSystem(const char* filename, const char* exp1_filename)
{
if (!HostInterface::InitializeSystem(filename, exp1_filename))
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", "System initialization failed.", m_window);
return false;
}
ConnectDevices();
return true;
}
void SDLInterface::ConnectDevices()
{
m_controller = DigitalController::Create();
m_system->SetController(0, m_controller);
m_memory_card = MemoryCard::Create();
m_system->SetMemoryCard(0, m_memory_card);
}
std::unique_ptr<SDLInterface> SDLInterface::Create(const char* filename /* = nullptr */,
const char* exp1_filename /* = nullptr */,
const char* save_state_filename /* = nullptr */)
{
std::unique_ptr<SDLInterface> intf = std::make_unique<SDLInterface>();
if (!intf->CreateSDLWindow() || !intf->CreateGLContext() || !intf->CreateImGuiContext() ||
@ -202,6 +225,16 @@ std::unique_ptr<SDLInterface> SDLInterface::Create()
return nullptr;
}
const bool boot = (filename != nullptr || exp1_filename != nullptr || save_state_filename != nullptr);
if (boot)
{
if (!intf->InitializeSystem(filename, exp1_filename))
return nullptr;
if (save_state_filename)
intf->LoadState(save_state_filename);
}
return intf;
}
@ -561,7 +594,7 @@ void SDLInterface::DrawMainMenuBar()
if (ImGui::BeginMenu("Save State"))
{
for (u32 i = 1; i <= 8; i++)
for (u32 i = 1; i <= NUM_QUICK_SAVE_STATES; i++)
{
if (ImGui::MenuItem(TinyString::FromFormat("State %u", i).GetCharArray()))
DoSaveState(i);
@ -842,30 +875,23 @@ void SDLInterface::DoStartDisc()
AddOSDMessage(SmallString::FromFormat("Starting disc from '%s'...", path));
if (!InitializeSystem(path, nullptr))
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", "System initialization failed.", m_window);
return;
}
ConnectDevices();
}
void SDLInterface::DoStartBIOS()
{
Assert(!m_system);
AddOSDMessage("Starting BIOS...");
if (!InitializeSystem(nullptr, nullptr))
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", "System initialization failed.", m_window);
return;
}
ConnectDevices();
}
void SDLInterface::DoLoadState(u32 index)
{
if (!HasSystem() && !InitializeSystem(nullptr, nullptr))
return;
LoadState(GetSaveStateFilename(index));
m_last_frame_number = m_system->GetFrameNumber();
m_last_internal_frame_number = m_system->GetInternalFrameNumber();
@ -875,18 +901,10 @@ void SDLInterface::DoLoadState(u32 index)
void SDLInterface::DoSaveState(u32 index)
{
Assert(m_system);
SaveState(GetSaveStateFilename(index));
}
void SDLInterface::ConnectDevices()
{
m_controller = DigitalController::Create();
m_system->SetController(0, m_controller);
m_memory_card = MemoryCard::Create();
m_system->SetMemoryCard(0, m_memory_card);
}
void SDLInterface::Run()
{
m_audio_stream->PauseOutput(false);

View file

@ -7,8 +7,8 @@
#include <SDL.h>
#include <array>
#include <deque>
#include <mutex>
#include <memory>
#include <mutex>
class System;
class DigitalController;
@ -21,22 +21,24 @@ public:
SDLInterface();
~SDLInterface();
static std::unique_ptr<SDLInterface> Create();
static std::unique_ptr<SDLInterface> Create(const char* filename = nullptr, const char* exp1_filename = nullptr,
const char* save_state_filename = nullptr);
static TinyString GetSaveStateFilename(u32 index);
void SetDisplayTexture(GL::Texture* texture, u32 offset_x, u32 offset_y, u32 width, u32 height, float aspect_ratio) override;
void SetDisplayTexture(GL::Texture* texture, u32 offset_x, u32 offset_y, u32 width, u32 height,
float aspect_ratio) override;
void ReportMessage(const char* message) override;
// Adds OSD messages, duration is in seconds.
void AddOSDMessage(const char* message, float duration = 2.0f) override;
void ConnectDevices();
void Run();
private:
static constexpr u32 NUM_QUICK_SAVE_STATES = 10;
struct OSDMessage
{
String text;
@ -44,12 +46,17 @@ private:
float duration;
};
bool HasSystem() const { return static_cast<bool>(m_system); }
bool CreateSDLWindow();
bool CreateGLContext();
bool CreateImGuiContext();
bool CreateGLResources();
bool CreateAudioStream();
bool InitializeSystem(const char* filename = nullptr, const char* exp1_filename = nullptr);
void ConnectDevices();
// We only pass mouse input through if it's grabbed
bool IsWindowFullscreen() const;
void DrawImGui();