vita3k: implement Pause/resume app.

This commit is contained in:
Zangetsu38 2023-05-05 14:00:53 +02:00 committed by Zangetsu
parent a0e45675c1
commit 39bfd76424
14 changed files with 62 additions and 2 deletions

View File

@ -41,6 +41,7 @@ enum class AppRunType {
bool init(EmuEnvState &state, Config &cfg, const Root &root_paths);
void destroy(EmuEnvState &emuenv, ImGui_State *imgui);
void update_viewport(EmuEnvState &state);
void switch_state(EmuEnvState &emuenv, const bool pause);
void error_dialog(const std::string &message, SDL_Window *window = nullptr);
void set_window_title(EmuEnvState &emuenv);

View File

@ -247,4 +247,13 @@ void destroy(EmuEnvState &emuenv, ImGui_State *imgui) {
config::serialize_config(emuenv.cfg, emuenv.cfg.config_path);
}
void switch_state(EmuEnvState &emuenv, const bool pause) {
if (pause)
emuenv.kernel.pause_threads();
else
emuenv.kernel.resume_threads();
emuenv.audio.switch_state(pause);
}
} // namespace app

View File

@ -55,4 +55,5 @@ public:
AudioOutPortPtr open_port(int nb_channels, int freq, int nb_sample) override;
void audio_output(ThreadState &thread, AudioOutPort &out_port, const void *buffer) override;
void set_volume(AudioOutPort &out_port, float volume) override;
void switch_state(const bool pause) override;
};

View File

@ -28,4 +28,5 @@ public:
~SDLAudioAdapter();
bool init() override;
void switch_state(const bool pause) override;
};

View File

@ -93,6 +93,7 @@ public:
virtual AudioOutPortPtr open_port(int nb_channels, int freq, int nb_sample) { return nullptr; }
virtual void audio_output(ThreadState &thread, AudioOutPort &out_port, const void *buffer) {}
virtual void set_volume(AudioOutPort &out_port, float volume) {}
virtual void switch_state(const bool pause) {}
friend struct AudioState;
};
@ -113,4 +114,5 @@ struct AudioState {
AudioOutPortPtr open_port(int nb_channels, int freq, int nb_sample);
void audio_output(ThreadState &thread, AudioOutPort &out_port, const void *buffer);
void set_volume(AudioOutPort &out_port, float volume);
void switch_state(const bool pause);
};

View File

@ -171,3 +171,7 @@ void AudioState::set_volume(AudioOutPort &out_port, float volume) {
adapter->set_volume(out_port, volume);
}
void AudioState::switch_state(const bool pause) {
adapter->switch_state(pause);
}

View File

@ -155,3 +155,13 @@ void CubebAudioAdapter::set_volume(AudioOutPort &out_port, float volume) {
CubebAudioOutPort &port = static_cast<CubebAudioOutPort &>(out_port);
cubeb_stream_set_volume(port.out_stream, volume);
}
void CubebAudioAdapter::switch_state(const bool pause) {
for (auto [_, out_port] : state.out_ports) {
CubebAudioOutPort &port = static_cast<CubebAudioOutPort &>(*out_port);
if (pause)
cubeb_stream_stop(port.out_stream);
else
cubeb_stream_start(port.out_stream);
}
}

View File

@ -67,3 +67,7 @@ bool SDLAudioAdapter::init() {
return true;
}
void SDLAudioAdapter::switch_state(const bool pause) {
SDL_PauseAudioDevice(device_id, pause);
}

View File

@ -48,7 +48,7 @@ static void vblank_sync_thread(EmuEnvState &emuenv) {
display.has_next_frame = false;
// in this case, even though no new game frames are being rendered, we still need to update the screen
if (emuenv.common_dialog.status == SCE_COMMON_DIALOG_STATUS_RUNNING)
if (emuenv.kernel.is_threads_paused() || (emuenv.common_dialog.status == SCE_COMMON_DIALOG_STATUS_RUNNING))
emuenv.renderer->should_display = true;
}

View File

@ -17,6 +17,7 @@
#include "private.h"
#include <app/functions.h>
#include <config/functions.h>
#include <compat/functions.h>
@ -158,6 +159,7 @@ void pre_run_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path
gui.vita_area.home_screen = false;
gui.vita_area.live_area_screen = false;
gui.vita_area.information_bar = false;
app::switch_state(emuenv, false);
}
} else {
gui.vita_area.home_screen = false;

View File

@ -609,6 +609,8 @@ bool handle_events(EmuEnvState &emuenv, GuiState &gui) {
gui.vita_area.information_bar = !gui.vita_area.information_bar;
gui.vita_area.live_area_screen = !gui.vita_area.live_area_screen;
}
app::switch_state(emuenv, !emuenv.kernel.is_threads_paused());
}
}
if (event.key.keysym.scancode == emuenv.cfg.keyboard_gui_toggle_touch && !gui.is_key_capture_dropped && !ImGui::GetIO().WantTextInput)

View File

@ -143,6 +143,7 @@ struct KernelState {
MsgPipePtrs msgpipes;
CallbackPtrs callbacks;
std::map<SceUID, ThreadStatus> paused_threads_status;
ThreadStatePtrs threads;
SceKernelModuleInfoPtrs loaded_modules;
@ -178,7 +179,11 @@ struct KernelState {
ThreadStatePtr get_thread(SceUID thread_id);
Ptr<Ptr<void>> get_thread_tls_addr(MemState &mem, SceUID thread_id, int key);
void exit_delete_all_threads();
bool is_threads_paused() { return !paused_threads_status.empty(); };
void pause_threads();
void resume_threads();
void set_memory_watch(bool enabled);
void invalidate_jit_cache(Address start, size_t length);

View File

@ -174,6 +174,24 @@ void KernelState::exit_delete_all_threads() {
}
}
void KernelState::pause_threads() {
const std::lock_guard<std::mutex> lock(mutex);
for (auto [_, thread] : threads) {
paused_threads_status[thread->id] = thread->status;
if (thread->status == ThreadStatus::run)
thread->suspend();
}
}
void KernelState::resume_threads() {
const std::lock_guard<std::mutex> lock(mutex);
for (auto [_, thread] : threads) {
if (paused_threads_status[thread->id] == ThreadStatus::run)
thread->resume();
}
paused_threads_status.clear();
}
std::shared_ptr<SceKernelModuleInfo> KernelState::find_module_by_addr(Address address) {
const auto lock = std::lock_guard(mutex);
for (auto [_, mod] : loaded_modules) {

View File

@ -421,7 +421,8 @@ int main(int argc, char *argv[]) {
gui::set_shaders_compiled_display(gui, emuenv);
gui::draw_begin(gui, emuenv);
gui::draw_common_dialog(gui, emuenv);
if (!gui.vita_area.live_area_screen)
gui::draw_common_dialog(gui, emuenv);
gui::draw_vita_area(gui, emuenv);
if (emuenv.cfg.performance_overlay && !gui.vita_area.home_screen && !gui.vita_area.live_area_screen && !gui.vita_area.start_screen && gui::get_sys_apps_state(gui))