[Libretro] Implement SET_SYSTEM_AV_INFO and SET_GEOMETRY

This commit is contained in:
CasualPokePlayer 2022-07-06 14:52:28 -07:00
parent 799dc4a2f0
commit 0d3c7b7e0c
7 changed files with 116 additions and 13 deletions

Binary file not shown.

Binary file not shown.

View File

@ -17,6 +17,10 @@ public:
: supportsNoGame(false)
, retroMessageString()
, retroMessageTime(0)
, geoInfoDirty(false)
, geoInfo()
, timingInfoDirty(false)
, timingInfo()
, variablesDirty(false)
, variableCount(0)
, variableKeys()
@ -238,8 +242,15 @@ public:
*static_cast<const char**>(data) = saveDirectory.c_str();
return true;
case RETRO_ENVIRONMENT::SET_SYSTEM_AV_INFO:
RetroLog(RETRO_LOG::WARN, "NEED RETRO_ENVIRONMENT::SET_SYSTEM_AV_INFO");
return false;
{
const retro_system_av_info* av = static_cast<const retro_system_av_info*>(data);
std::memcpy(&geoInfo, &av->geometry, sizeof (retro_game_geometry));
SetVideoSize(geoInfo.max_width * geoInfo.max_height);
geoInfoDirty = true;
std::memcpy(&timingInfo, &av->timing, sizeof (retro_system_timing));
timingInfoDirty = true;
return true;
}
case RETRO_ENVIRONMENT::SET_PROC_ADDRESS_CALLBACK:
//this is some way to get symbols for API extensions
//of which none exist
@ -252,9 +263,13 @@ public:
//TODO medium priority probably
return false;
case RETRO_ENVIRONMENT::SET_GEOMETRY:
//TODO medium priority probably
//this is essentially just set system av info, except only for video
return false;
{
const retro_game_geometry* geo = static_cast<const retro_game_geometry*>(data);
std::memcpy(&geoInfo, geo, sizeof (retro_game_geometry));
SetVideoSize(geoInfo.max_width * geoInfo.max_height);
geoInfoDirty = true;
return true;
}
case RETRO_ENVIRONMENT::GET_USERNAME:
//we definitely want to return false here so the core will do something deterministic
return false;
@ -461,6 +476,26 @@ public:
}
}
bool GetRetroGeometryInfo(retro_game_geometry* geo) {
if (!geoInfoDirty) {
return false;
}
std::memcpy(geo, &geoInfo, sizeof (retro_game_geometry));
geoInfoDirty = false;
return true;
}
bool GetRetroTimingInfo(retro_system_timing* timing) {
if (!timingInfoDirty) {
return false;
}
std::memcpy(timing, &timingInfo, sizeof (retro_system_timing));
timingInfoDirty = false;
return true;
}
// need some way to communicate with retro variables later
void SetDirectories(const char* systemDirectory, const char* saveDirectory, const char* coreDirectory, const char* coreAssetsDirectory) {
@ -528,6 +563,12 @@ private:
std::string retroMessageString;
u32 retroMessageTime;
bool geoInfoDirty;
retro_game_geometry geoInfo;
bool timingInfoDirty;
retro_system_timing timingInfo;
bool variablesDirty;
u32 variableCount;
std::unique_ptr<std::string[]> variableKeys;
@ -593,6 +634,20 @@ EXPORT void LibretroBridge_GetRetroMessage(CallbackHandler* cbHandler, retro_mes
cbHandler->GetRetroMessage(m);
}
// get current retro_game_geometry set by the core
// returns false if no changes are needed for geometry info
// geo is only valid if true is returned
EXPORT bool LibretroBridge_GetRetroGeometryInfo(CallbackHandler* cbHandler, retro_game_geometry* geo) {
return cbHandler->GetRetroGeometryInfo(geo);
}
// get current retro_system_timing set by the core
// returns false if no changes are needed for timing info
// timing is only valid if true is returned
EXPORT bool LibretroBridge_GetRetroTimingInfo(CallbackHandler* cbHandler, retro_system_timing* timing) {
return cbHandler->GetRetroTimingInfo(timing);
}
// set directories for the core
EXPORT void LibretroBridge_SetDirectories(CallbackHandler* cbHandler, const char* systemDirectory, const char* saveDirectory, const char* coreDirectory, const char* coreAssetsDirectory) {
cbHandler->SetDirectories(systemDirectory, saveDirectory, coreDirectory, coreAssetsDirectory);

View File

@ -11,6 +11,9 @@ typedef std::uint16_t u16;
typedef std::uint32_t u32;
typedef std::uint64_t u64;
typedef float f32;
typedef double f64;
typedef u8 boolean;
#define EXPORT extern "C" __attribute__((visibility("default")))
@ -355,6 +358,24 @@ enum class RETRO_LOG {
DUMMY = INT_MAX,
};
struct retro_game_geometry {
u32 base_width;
u32 base_height;
u32 max_width;
u32 max_height;
f32 aspect_ratio;
};
struct retro_system_timing {
f64 fps;
f64 sample_rate;
};
struct retro_system_av_info {
retro_game_geometry geometry;
retro_system_timing timing;
};
struct retro_variable {
const char* key;
const char* value;

View File

@ -326,20 +326,29 @@ namespace BizHawk.Emulation.Cores.Libretro
}
[StructLayout(LayoutKind.Sequential)]
public struct retro_system_av_info
public struct retro_game_geometry
{
// struct retro_game_geometry
public uint base_width;
public uint base_height;
public uint max_width;
public uint max_height;
public float aspect_ratio;
}
// struct retro_system_timing
[StructLayout(LayoutKind.Sequential)]
public struct retro_system_timing
{
public double fps;
public double sample_rate;
}
[StructLayout(LayoutKind.Sequential)]
public struct retro_system_av_info
{
public retro_game_geometry geometry;
public retro_system_timing timing;
}
[BizImport(cc)]
public abstract void retro_init();
@ -432,6 +441,12 @@ namespace BizHawk.Emulation.Cores.Libretro
[BizImport(cc)]
public abstract bool LibretroBridge_GetSupportsNoGame(IntPtr cbHandler);
[BizImport(cc)]
public abstract bool LibretroBridge_GetRetroGeometryInfo(IntPtr cbHandler, ref LibretroApi.retro_game_geometry g);
[BizImport(cc)]
public abstract bool LibretroBridge_GetRetroTimingInfo(IntPtr cbHandler, ref LibretroApi.retro_system_timing t);
[BizImport(cc)]
public abstract void LibretroBridge_GetRetroMessage(IntPtr cbHandler, ref LibretroApi.retro_message m);

View File

@ -210,13 +210,13 @@ namespace BizHawk.Emulation.Cores.Libretro
//this stuff can only happen after the game is loaded
//allocate a video buffer which will definitely be large enough
InitVideoBuffer((int)av.base_width, (int)av.base_height, (int)(av.max_width * av.max_height));
InitVideoBuffer((int)av.geometry.base_width, (int)av.geometry.base_height, (int)(av.geometry.max_width * av.geometry.max_height));
// TODO: more precise
VsyncNumerator = (int)(10000000 * av.fps);
VsyncNumerator = (int)(10000000 * av.timing.fps);
VsyncDenominator = 10000000;
SetupResampler(av.fps, av.sample_rate);
SetupResampler(av.timing.fps, av.timing.sample_rate);
InitMemoryDomains(); // im going to assume this should happen when a game is loaded
@ -236,6 +236,18 @@ namespace BizHawk.Emulation.Cores.Libretro
private void FrameAdvancePost(bool render, bool renderSound)
{
if (bridge.LibretroBridge_GetRetroGeometryInfo(cbHandler, ref av_info.geometry))
{
vidBuffer = new int[av_info.geometry.max_width * av_info.geometry.max_height];
}
if (bridge.LibretroBridge_GetRetroTimingInfo(cbHandler, ref av_info.timing))
{
VsyncNumerator = (int)(10000000 * av_info.timing.fps);
_blipL.SetRates(av_info.timing.sample_rate, 44100);
_blipR.SetRates(av_info.timing.sample_rate, 44100);
}
if (render)
{
UpdateVideoBuffer();

View File

@ -27,7 +27,7 @@ namespace BizHawk.Emulation.Cores.Libretro
{
get
{
var dar = av_info.aspect_ratio;
var dar = av_info.geometry.aspect_ratio;
if (dar <= 0)
{
return vidWidth;
@ -44,7 +44,7 @@ namespace BizHawk.Emulation.Cores.Libretro
{
get
{
var dar = av_info.aspect_ratio;
var dar = av_info.geometry.aspect_ratio;
if (dar <= 0)
{
return vidHeight;