mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-26 23:55:40 +00:00
System: Simplify save state booting
Fixes memory card warning messages on load state.
This commit is contained in:
parent
d2c7639dd8
commit
b17a5832e5
|
@ -82,13 +82,13 @@ void HostInterface::CreateAudioStream()
|
|||
|
||||
bool HostInterface::BootSystem(const SystemBootParameters& parameters)
|
||||
{
|
||||
if (parameters.filename.empty())
|
||||
Log_InfoPrintf("Boot Filename: <BIOS/Shell>");
|
||||
else
|
||||
Log_InfoPrintf("Boot Filename: %s", parameters.filename.c_str());
|
||||
|
||||
if (!parameters.state_filename.empty())
|
||||
Log_InfoPrintf("Save State Filename: %s", parameters.filename.c_str());
|
||||
if (!parameters.state_stream)
|
||||
{
|
||||
if (parameters.filename.empty())
|
||||
Log_InfoPrintf("Boot Filename: <BIOS/Shell>");
|
||||
else
|
||||
Log_InfoPrintf("Boot Filename: %s", parameters.filename.c_str());
|
||||
}
|
||||
|
||||
if (!AcquireHostDisplay())
|
||||
{
|
||||
|
@ -111,9 +111,6 @@ bool HostInterface::BootSystem(const SystemBootParameters& parameters)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!parameters.state_filename.empty())
|
||||
LoadState(parameters.state_filename.c_str());
|
||||
|
||||
OnSystemCreated();
|
||||
|
||||
m_paused = m_settings.start_paused;
|
||||
|
@ -475,18 +472,9 @@ bool HostInterface::LoadState(const char* filename)
|
|||
else
|
||||
{
|
||||
SystemBootParameters boot_params;
|
||||
boot_params.state_stream = std::move(stream);
|
||||
if (!BootSystem(boot_params))
|
||||
{
|
||||
ReportFormattedError("Failed to boot system to load state from '%s'.", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_system->LoadState(stream.get()))
|
||||
{
|
||||
ReportFormattedError("Failed to load state. The log may contain more information. Shutting down system.");
|
||||
DestroySystem();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_system->ResetPerformanceCounters();
|
||||
|
@ -1219,19 +1207,13 @@ void HostInterface::RecreateSystem()
|
|||
DestroySystem();
|
||||
|
||||
SystemBootParameters boot_params;
|
||||
boot_params.state_stream = std::move(stream);
|
||||
if (!BootSystem(boot_params))
|
||||
{
|
||||
ReportError("Failed to boot system after recreation.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_system->LoadState(stream.get()))
|
||||
{
|
||||
ReportError("Failed to load state after system recreation. Shutting down.");
|
||||
DestroySystem();
|
||||
return;
|
||||
}
|
||||
|
||||
m_system->ResetPerformanceCounters();
|
||||
PauseSystem(was_paused);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "types.h"
|
||||
|
||||
static constexpr u32 SAVE_STATE_MAGIC = 0x43435544;
|
||||
static constexpr u32 SAVE_STATE_VERSION = 35;
|
||||
static constexpr u32 SAVE_STATE_VERSION = 36;
|
||||
|
||||
#pragma pack(push, 4)
|
||||
struct SAVE_STATE_HEADER
|
||||
|
@ -17,6 +17,9 @@ struct SAVE_STATE_HEADER
|
|||
u32 version;
|
||||
char title[MAX_TITLE_LENGTH];
|
||||
char game_code[MAX_GAME_CODE_LENGTH];
|
||||
|
||||
u32 media_filename_length;
|
||||
u32 offset_to_media_filename;
|
||||
|
||||
u32 screenshot_width;
|
||||
u32 screenshot_height;
|
||||
|
|
|
@ -37,6 +37,13 @@ SystemBootParameters::SystemBootParameters() = default;
|
|||
|
||||
SystemBootParameters::SystemBootParameters(std::string filename_) : filename(filename_) {}
|
||||
|
||||
SystemBootParameters::SystemBootParameters(const SystemBootParameters& copy)
|
||||
: filename(copy.filename), override_fast_boot(copy.override_fast_boot), override_fullscreen(copy.override_fullscreen)
|
||||
{
|
||||
// only exists for qt, we can't copy the state stream
|
||||
Assert(!copy.state_stream);
|
||||
}
|
||||
|
||||
SystemBootParameters::~SystemBootParameters() = default;
|
||||
|
||||
System::System(HostInterface* host_interface) : m_host_interface(host_interface)
|
||||
|
@ -130,6 +137,9 @@ void System::SetCPUExecutionMode(CPUExecutionMode mode)
|
|||
|
||||
bool System::Boot(const SystemBootParameters& params)
|
||||
{
|
||||
if (params.state_stream)
|
||||
return DoLoadState(params.state_stream.get(), true);
|
||||
|
||||
// Load CD image up and detect region.
|
||||
std::unique_ptr<CDImage> media;
|
||||
bool exe_boot = false;
|
||||
|
@ -318,34 +328,6 @@ bool System::DoState(StateWrapper& sw)
|
|||
sw.Do(&m_internal_frame_number);
|
||||
sw.Do(&m_global_tick_counter);
|
||||
|
||||
std::string media_filename = m_cdrom->GetMediaFileName();
|
||||
sw.Do(&media_filename);
|
||||
|
||||
bool media_is_bad = false;
|
||||
if (sw.IsReading())
|
||||
{
|
||||
std::unique_ptr<CDImage> media;
|
||||
if (!media_filename.empty())
|
||||
{
|
||||
media = CDImage::Open(media_filename.c_str());
|
||||
if (!media)
|
||||
{
|
||||
Log_ErrorPrintf("Failed to open CD image from save state: '%s'. Disc will be removed.", media_filename.c_str());
|
||||
media_is_bad = true;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateRunningGame(media_filename.c_str(), media.get());
|
||||
if (GetSettings().HasAnyPerGameMemoryCards())
|
||||
UpdateMemoryCards();
|
||||
|
||||
m_cdrom->Reset();
|
||||
if (media)
|
||||
m_cdrom->InsertMedia(std::move(media));
|
||||
else
|
||||
m_cdrom->RemoveMedia();
|
||||
}
|
||||
|
||||
if (!sw.DoMarker("CPU") || !m_cpu->DoState(sw))
|
||||
return false;
|
||||
|
||||
|
@ -385,9 +367,6 @@ bool System::DoState(StateWrapper& sw)
|
|||
if (!sw.DoMarker("Events") || !DoEventsState(sw))
|
||||
return false;
|
||||
|
||||
if (media_is_bad)
|
||||
m_cdrom->RemoveMedia(true);
|
||||
|
||||
return !sw.HasError();
|
||||
}
|
||||
|
||||
|
@ -413,6 +392,11 @@ void System::Reset()
|
|||
}
|
||||
|
||||
bool System::LoadState(ByteStream* state)
|
||||
{
|
||||
return DoLoadState(state, false);
|
||||
}
|
||||
|
||||
bool System::DoLoadState(ByteStream* state, bool init_components)
|
||||
{
|
||||
SAVE_STATE_HEADER header;
|
||||
if (!state->Read2(&header, sizeof(header)))
|
||||
|
@ -428,6 +412,49 @@ bool System::LoadState(ByteStream* state)
|
|||
return false;
|
||||
}
|
||||
|
||||
std::string media_filename;
|
||||
std::unique_ptr<CDImage> media;
|
||||
if (header.media_filename_length > 0)
|
||||
{
|
||||
media_filename.resize(header.media_filename_length);
|
||||
if (!state->SeekAbsolute(header.offset_to_media_filename) ||
|
||||
!state->Read2(media_filename.data(), header.media_filename_length))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
media = CDImage::Open(media_filename.c_str());
|
||||
if (!media)
|
||||
{
|
||||
m_host_interface->ReportFormattedError("Failed to open CD image from save state: '%s'.", media_filename.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateRunningGame(media_filename.c_str(), media.get());
|
||||
|
||||
if (init_components)
|
||||
{
|
||||
InitializeComponents();
|
||||
UpdateControllers();
|
||||
UpdateMemoryCards();
|
||||
|
||||
if (media)
|
||||
m_cdrom->InsertMedia(std::move(media));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cdrom->Reset();
|
||||
if (media)
|
||||
m_cdrom->InsertMedia(std::move(media));
|
||||
else
|
||||
m_cdrom->RemoveMedia();
|
||||
|
||||
// ensure the correct card is loaded
|
||||
if (GetSettings().HasAnyPerGameMemoryCards())
|
||||
UpdateMemoryCards();
|
||||
}
|
||||
|
||||
if (header.data_compression_type != 0)
|
||||
{
|
||||
m_host_interface->ReportFormattedError("Unknown save state compression type %u", header.data_compression_type);
|
||||
|
@ -455,6 +482,12 @@ bool System::SaveState(ByteStream* state)
|
|||
StringUtil::Strlcpy(header.title, m_running_game_title.c_str(), sizeof(header.title));
|
||||
StringUtil::Strlcpy(header.game_code, m_running_game_code.c_str(), sizeof(header.game_code));
|
||||
|
||||
std::string media_filename = m_cdrom->GetMediaFileName();
|
||||
header.offset_to_media_filename = static_cast<u32>(state->GetPosition());
|
||||
header.media_filename_length = static_cast<u32>(media_filename.length());
|
||||
if (!media_filename.empty() && !state->Write2(media_filename.data(), header.media_filename_length))
|
||||
return false;
|
||||
|
||||
// save screenshot
|
||||
{
|
||||
const u32 screenshot_width = 128;
|
||||
|
|
|
@ -32,12 +32,13 @@ struct SystemBootParameters
|
|||
{
|
||||
SystemBootParameters();
|
||||
SystemBootParameters(std::string filename_);
|
||||
SystemBootParameters(const SystemBootParameters& copy);
|
||||
~SystemBootParameters();
|
||||
|
||||
std::string filename;
|
||||
std::string state_filename;
|
||||
std::optional<bool> override_fast_boot;
|
||||
std::optional<bool> override_fullscreen;
|
||||
std::unique_ptr<ByteStream> state_stream;
|
||||
};
|
||||
|
||||
class System
|
||||
|
@ -143,6 +144,7 @@ public:
|
|||
private:
|
||||
System(HostInterface* host_interface);
|
||||
|
||||
bool DoLoadState(ByteStream* stream, bool init_components);
|
||||
bool DoState(StateWrapper& sw);
|
||||
bool CreateGPU(GPURenderer renderer);
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "common_host_interface.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/audio_stream.h"
|
||||
#include "common/byte_stream.h"
|
||||
#include "common/file_system.h"
|
||||
#include "common/log.h"
|
||||
#include "common/string_util.h"
|
||||
|
@ -289,9 +290,22 @@ bool CommonHostInterface::ParseCommandLineParameters(int argc, char* argv[],
|
|||
|
||||
std::unique_ptr<SystemBootParameters> boot_params = std::make_unique<SystemBootParameters>();
|
||||
boot_params->filename = std::move(boot_filename);
|
||||
boot_params->state_filename = std::move(state_filename);
|
||||
boot_params->override_fast_boot = std::move(force_fast_boot);
|
||||
boot_params->override_fullscreen = std::move(force_fullscreen);
|
||||
|
||||
if (!state_filename.empty())
|
||||
{
|
||||
std::unique_ptr<ByteStream> state_stream =
|
||||
FileSystem::OpenFile(state_filename.c_str(), BYTESTREAM_OPEN_READ | BYTESTREAM_OPEN_STREAMED);
|
||||
if (!state_stream)
|
||||
{
|
||||
Log_ErrorPrintf("Failed to open save state file '%s'", state_filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
boot_params->state_stream = std::move(state_stream);
|
||||
}
|
||||
|
||||
*out_boot_params = std::move(boot_params);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue