mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-14 15:00:30 +02:00
System_AudioPushSamples converts straight into the output buffer: the block loop never advanced the source pointer and copied numSamples*2 int16s out of a 2048-sample stack buffer, a stack OOB read for any push over 1024 frames. Realloc failure drops samples instead of crashing and log_cb is NULL-checked. retro_serialize refuses to write a state larger than the frontend's buffer, retro_get_memory_data/size return nothing until PSP memory is mapped, deferred unserialize no longer leaks the previous buffer, and the cheat entry points stop leaking a CWCheatEngine per call. The emu thread acknowledges a pause with a CAS so it cannot clobber a concurrent quit request. EmuThreadStop stops and joins from any live state, so unloading while paused no longer leaves a thread running over freed state. EmuThreadPause pumps queued frames until the thread parks, via a new non-blocking GLRenderManager::HasQueuedThreadWork() check, instead of draining one frame, which deadlocked when the thread was blocked on a readback sync in the next frame. retro_run resumes a paused thread and pauses it before check_variables() rewrites g_Config, retro_reset stops it before PSP_Shutdown(), and the sleep_ms(4) after resume is gone.
116 lines
3.0 KiB
C++
116 lines
3.0 KiB
C++
#pragma once
|
|
#include <atomic>
|
|
|
|
#include <libretro.h>
|
|
#include "Common/GPU/GraphicsContext.h"
|
|
#include "Common/GPU/thin3d_create.h"
|
|
|
|
#include "Common/CommonTypes.h"
|
|
#include "Core/Config.h"
|
|
#include "Core/System.h"
|
|
#include "GPU/GPUState.h"
|
|
#include "GPU/Software/SoftGpu.h"
|
|
#include "headless/Compare.h"
|
|
#include "Common/Data/Convert/ColorConv.h"
|
|
|
|
#define NATIVEWIDTH 480
|
|
#define NATIVEHEIGHT 272
|
|
#define SOFT_BMP_SIZE NATIVEWIDTH * NATIVEHEIGHT * 4
|
|
|
|
class LibretroGraphicsContext : public GraphicsContext {
|
|
public:
|
|
LibretroGraphicsContext() {}
|
|
~LibretroGraphicsContext() override { ShutdownAPI(); }
|
|
|
|
virtual void SetRenderTarget() {}
|
|
virtual GPUCore GetGPUCore() = 0;
|
|
virtual const char *Ident() = 0;
|
|
|
|
void ShutdownAPI() override {
|
|
DestroyDrawContext();
|
|
}
|
|
virtual void SwapBuffers() = 0;
|
|
void Resize() override {}
|
|
// True if ThreadFrame() has queued work to run (emu thread backends only).
|
|
virtual bool ThreadFramePending() { return false; }
|
|
|
|
virtual void GotBackbuffer();
|
|
virtual void LostBackbuffer();
|
|
|
|
virtual void CreateDrawContext() {}
|
|
virtual void DestroyDrawContext() {
|
|
if (!draw_) {
|
|
return;
|
|
}
|
|
delete draw_;
|
|
draw_ = nullptr;
|
|
}
|
|
Draw::DrawContext *GetDrawContext() override { return draw_; }
|
|
|
|
static LibretroGraphicsContext *CreateGraphicsContext();
|
|
|
|
static retro_video_refresh_t video_cb;
|
|
|
|
protected:
|
|
Draw::DrawContext *draw_ = nullptr;
|
|
};
|
|
|
|
class LibretroHWRenderContext : public LibretroGraphicsContext {
|
|
public:
|
|
LibretroHWRenderContext(retro_hw_context_type context_type, unsigned version_major = 0, unsigned version_minor = 0);
|
|
bool InitHW(bool cache_context);
|
|
void SetRenderTarget() override {}
|
|
void SwapBuffers() override {
|
|
video_cb(RETRO_HW_FRAME_BUFFER_VALID, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight, 0);
|
|
}
|
|
virtual void ContextReset();
|
|
virtual void ContextDestroy();
|
|
|
|
protected:
|
|
retro_hw_render_callback hw_render_ = {};
|
|
};
|
|
|
|
std::vector<u32> ConvertFramebufferForLibretro(const GPUDebugBuffer *buffer, u32 stride, u32 h);
|
|
|
|
class LibretroSoftwareContext : public LibretroGraphicsContext {
|
|
public:
|
|
LibretroSoftwareContext() {}
|
|
void SwapBuffers() override {
|
|
GPUDebugBuffer buf;
|
|
u16 w = NATIVEWIDTH;
|
|
u16 h = NATIVEHEIGHT;
|
|
if (gpu) {
|
|
gpu->GetOutputFramebuffer(buf);
|
|
const std::vector<u32> pixels = ConvertFramebufferForLibretro(&buf, w, h);
|
|
memcpy(soft_bmp, pixels.data(), SOFT_BMP_SIZE);
|
|
}
|
|
u32 offset = g_Config.bDisplayCropTo16x9 ? w << 1 : 0;
|
|
h -= g_Config.bDisplayCropTo16x9 ? 2 : 0;
|
|
video_cb(soft_bmp + offset, w, h, w << 2);
|
|
}
|
|
GPUCore GetGPUCore() override { return GPUCORE_SOFTWARE; }
|
|
const char *Ident() override { return "Software"; }
|
|
|
|
u16 soft_bmp[SOFT_BMP_SIZE] = {0};
|
|
};
|
|
|
|
namespace Libretro {
|
|
extern LibretroGraphicsContext *ctx;
|
|
extern retro_environment_t environ_cb;
|
|
extern retro_hw_context_type backend;
|
|
|
|
enum class EmuThreadState {
|
|
DISABLED,
|
|
RUNNING,
|
|
PAUSE_REQUESTED,
|
|
PAUSED,
|
|
QUIT_REQUESTED,
|
|
STOPPED,
|
|
};
|
|
extern bool useEmuThread;
|
|
extern std::atomic<EmuThreadState> emuThreadState;
|
|
void EmuThreadStart();
|
|
void EmuThreadStop();
|
|
void EmuThreadPause();
|
|
} // namespace Libretro
|