cellGem: Fix camera image when loading savestates

This commit is contained in:
Megamouse 2025-01-20 22:54:26 +01:00
parent ade2698bb4
commit 23483a80c7
4 changed files with 49 additions and 4 deletions

View File

@ -1961,3 +1961,18 @@ bool camera_context::on_handler_state(camera_handler_base::camera_handler_state
return true;
}
gem_camera_shared::gem_camera_shared(utils::serial& ar)
{
save(ar);
}
void gem_camera_shared::save(utils::serial& ar)
{
const s32 version = GET_OR_USE_SERIALIZATION_VERSION(ar.is_writing(), cellCamera);
if (ar.is_writing() || version >= 2)
{
ar(frame_timestamp_us, width, height, size, format);
}
}

View File

@ -471,6 +471,13 @@ using camera_thread = named_thread<camera_context>;
/// Shared data between cellGem and cellCamera
struct gem_camera_shared
{
gem_camera_shared() {}
gem_camera_shared(utils::serial& ar);
void save(utils::serial& ar);
SAVESTATE_INIT_POS(7);
atomic_t<u64> frame_timestamp_us{}; // latest read timestamp from cellCamera (cellCameraRead(Ex))
atomic_t<s32> width{640};
atomic_t<s32> height{480};

View File

@ -292,6 +292,12 @@ public:
bool wait_for_result(ppu_thread& ppu)
{
// Notify gem thread that the initial state after loading a savestate can be updated.
if (m_done.compare_and_swap_test(2, 0))
{
m_done.notify_one();
}
while (!m_done && !ppu.is_stopped())
{
thread_ctrl::wait_on(m_done, 0);
@ -540,7 +546,7 @@ public:
load_configs();
};
SAVESTATE_INIT_POS(15);
SAVESTATE_INIT_POS(16.1); // Depends on cellCamera
void save(utils::serial& ar)
{
@ -581,6 +587,11 @@ public:
}
ar(connected_controllers, updating, camera_frame, memory_ptr, start_timestamp_us);
if (ar.is_writing() || version >= 3)
{
ar(video_conversion_in_progress, video_data_out_size);
}
}
gem_config_data(utils::serial& ar)
@ -1253,6 +1264,18 @@ void gem_config_data::operator()()
u64 last_update_us = 0;
// Handle initial state after loading a savestate
if (state && video_conversion_in_progress)
{
// Wait for cellGemConvertVideoFinish. The initial savestate loading may take a while.
m_done = 2; // Use special value 2 for this case
thread_ctrl::wait_on(m_done, 2, 5'000'000);
// Just mark this conversion as complete (there's no real downside to this, except for a black image)
video_conversion_in_progress = false;
done();
}
while (thread_ctrl::state() != thread_state::aborting && !Emu.IsStopped())
{
u64 timeout = umax;
@ -2646,7 +2669,7 @@ error_code cellGemGetImageState(u32 gem_num, vm::ptr<CellGemImageState> gem_imag
if (g_cfg.io.move != move_handler::null)
{
auto& shared_data = g_fxo->get<gem_camera_shared>();
const auto& shared_data = g_fxo->get<gem_camera_shared>();
auto& controller = gem.controllers[gem_num];
gem_image_state->frame_timestamp = shared_data.frame_timestamp_us.load();

View File

@ -71,8 +71,8 @@ SERIALIZATION_VER(sceNp, 11)
SERIALIZATION_VER(cellVdec, 12, 1)
SERIALIZATION_VER(cellAudio, 13, 1)
SERIALIZATION_VER(cellCamera, 14, 1)
SERIALIZATION_VER(cellGem, 15, 1, 2/*calibration_status_flags*/)
SERIALIZATION_VER(cellCamera, 14, 1, 2/*gem_camera_shared*/)
SERIALIZATION_VER(cellGem, 15, 1, 2/*calibration_status_flags*/, 3/*video_conversion*/)
SERIALIZATION_VER(sceNpTrophy, 16, 1)
SERIALIZATION_VER(cellMusic, 17, 1)
SERIALIZATION_VER(cellVoice, 18, 1)