From 23483a80c7f604f4111d36ffe13d354973174234 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 20 Jan 2025 22:54:26 +0100 Subject: [PATCH] cellGem: Fix camera image when loading savestates --- rpcs3/Emu/Cell/Modules/cellCamera.cpp | 15 +++++++++++++++ rpcs3/Emu/Cell/Modules/cellCamera.h | 7 +++++++ rpcs3/Emu/Cell/Modules/cellGem.cpp | 27 +++++++++++++++++++++++++-- rpcs3/Emu/savestate_utils.cpp | 4 ++-- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellCamera.cpp b/rpcs3/Emu/Cell/Modules/cellCamera.cpp index e8a6b656d7..4d6bb038d0 100644 --- a/rpcs3/Emu/Cell/Modules/cellCamera.cpp +++ b/rpcs3/Emu/Cell/Modules/cellCamera.cpp @@ -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); + } +} diff --git a/rpcs3/Emu/Cell/Modules/cellCamera.h b/rpcs3/Emu/Cell/Modules/cellCamera.h index ae4786cdcc..a6ce62d334 100644 --- a/rpcs3/Emu/Cell/Modules/cellCamera.h +++ b/rpcs3/Emu/Cell/Modules/cellCamera.h @@ -471,6 +471,13 @@ using camera_thread = named_thread; /// 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 frame_timestamp_us{}; // latest read timestamp from cellCamera (cellCameraRead(Ex)) atomic_t width{640}; atomic_t height{480}; diff --git a/rpcs3/Emu/Cell/Modules/cellGem.cpp b/rpcs3/Emu/Cell/Modules/cellGem.cpp index c66c79577f..5c32a299b3 100644 --- a/rpcs3/Emu/Cell/Modules/cellGem.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGem.cpp @@ -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 gem_imag if (g_cfg.io.move != move_handler::null) { - auto& shared_data = g_fxo->get(); + const auto& shared_data = g_fxo->get(); auto& controller = gem.controllers[gem_num]; gem_image_state->frame_timestamp = shared_data.frame_timestamp_us.load(); diff --git a/rpcs3/Emu/savestate_utils.cpp b/rpcs3/Emu/savestate_utils.cpp index a40cda95c3..bb3e440564 100644 --- a/rpcs3/Emu/savestate_utils.cpp +++ b/rpcs3/Emu/savestate_utils.cpp @@ -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)