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

View File

@ -193,7 +193,30 @@ bool SDLInterface::CreateAudioStream()
return true; 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>(); std::unique_ptr<SDLInterface> intf = std::make_unique<SDLInterface>();
if (!intf->CreateSDLWindow() || !intf->CreateGLContext() || !intf->CreateImGuiContext() || if (!intf->CreateSDLWindow() || !intf->CreateGLContext() || !intf->CreateImGuiContext() ||
@ -202,6 +225,16 @@ std::unique_ptr<SDLInterface> SDLInterface::Create()
return nullptr; 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; return intf;
} }
@ -561,7 +594,7 @@ void SDLInterface::DrawMainMenuBar()
if (ImGui::BeginMenu("Save State")) 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())) if (ImGui::MenuItem(TinyString::FromFormat("State %u", i).GetCharArray()))
DoSaveState(i); DoSaveState(i);
@ -842,12 +875,7 @@ void SDLInterface::DoStartDisc()
AddOSDMessage(SmallString::FromFormat("Starting disc from '%s'...", path)); AddOSDMessage(SmallString::FromFormat("Starting disc from '%s'...", path));
if (!InitializeSystem(path, nullptr)) if (!InitializeSystem(path, nullptr))
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", "System initialization failed.", m_window);
return; return;
}
ConnectDevices();
} }
void SDLInterface::DoStartBIOS() void SDLInterface::DoStartBIOS()
@ -856,16 +884,14 @@ void SDLInterface::DoStartBIOS()
AddOSDMessage("Starting BIOS..."); AddOSDMessage("Starting BIOS...");
if (!InitializeSystem(nullptr, nullptr)) if (!InitializeSystem(nullptr, nullptr))
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", "System initialization failed.", m_window);
return; return;
}
ConnectDevices();
} }
void SDLInterface::DoLoadState(u32 index) void SDLInterface::DoLoadState(u32 index)
{ {
if (!HasSystem() && !InitializeSystem(nullptr, nullptr))
return;
LoadState(GetSaveStateFilename(index)); LoadState(GetSaveStateFilename(index));
m_last_frame_number = m_system->GetFrameNumber(); m_last_frame_number = m_system->GetFrameNumber();
m_last_internal_frame_number = m_system->GetInternalFrameNumber(); m_last_internal_frame_number = m_system->GetInternalFrameNumber();
@ -875,18 +901,10 @@ void SDLInterface::DoLoadState(u32 index)
void SDLInterface::DoSaveState(u32 index) void SDLInterface::DoSaveState(u32 index)
{ {
Assert(m_system);
SaveState(GetSaveStateFilename(index)); 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() void SDLInterface::Run()
{ {
m_audio_stream->PauseOutput(false); m_audio_stream->PauseOutput(false);

View File

@ -7,8 +7,8 @@
#include <SDL.h> #include <SDL.h>
#include <array> #include <array>
#include <deque> #include <deque>
#include <mutex>
#include <memory> #include <memory>
#include <mutex>
class System; class System;
class DigitalController; class DigitalController;
@ -21,22 +21,24 @@ public:
SDLInterface(); SDLInterface();
~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); 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; void ReportMessage(const char* message) override;
// Adds OSD messages, duration is in seconds. // Adds OSD messages, duration is in seconds.
void AddOSDMessage(const char* message, float duration = 2.0f) override; void AddOSDMessage(const char* message, float duration = 2.0f) override;
void ConnectDevices();
void Run(); void Run();
private: private:
static constexpr u32 NUM_QUICK_SAVE_STATES = 10;
struct OSDMessage struct OSDMessage
{ {
String text; String text;
@ -44,12 +46,17 @@ private:
float duration; float duration;
}; };
bool HasSystem() const { return static_cast<bool>(m_system); }
bool CreateSDLWindow(); bool CreateSDLWindow();
bool CreateGLContext(); bool CreateGLContext();
bool CreateImGuiContext(); bool CreateImGuiContext();
bool CreateGLResources(); bool CreateGLResources();
bool CreateAudioStream(); 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 // We only pass mouse input through if it's grabbed
bool IsWindowFullscreen() const; bool IsWindowFullscreen() const;
void DrawImGui(); void DrawImGui();