[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) : supportsNoGame(false)
, retroMessageString() , retroMessageString()
, retroMessageTime(0) , retroMessageTime(0)
, geoInfoDirty(false)
, geoInfo()
, timingInfoDirty(false)
, timingInfo()
, variablesDirty(false) , variablesDirty(false)
, variableCount(0) , variableCount(0)
, variableKeys() , variableKeys()
@ -238,8 +242,15 @@ public:
*static_cast<const char**>(data) = saveDirectory.c_str(); *static_cast<const char**>(data) = saveDirectory.c_str();
return true; return true;
case RETRO_ENVIRONMENT::SET_SYSTEM_AV_INFO: 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: case RETRO_ENVIRONMENT::SET_PROC_ADDRESS_CALLBACK:
//this is some way to get symbols for API extensions //this is some way to get symbols for API extensions
//of which none exist //of which none exist
@ -252,9 +263,13 @@ public:
//TODO medium priority probably //TODO medium priority probably
return false; return false;
case RETRO_ENVIRONMENT::SET_GEOMETRY: case RETRO_ENVIRONMENT::SET_GEOMETRY:
//TODO medium priority probably {
//this is essentially just set system av info, except only for video const retro_game_geometry* geo = static_cast<const retro_game_geometry*>(data);
return false; std::memcpy(&geoInfo, geo, sizeof (retro_game_geometry));
SetVideoSize(geoInfo.max_width * geoInfo.max_height);
geoInfoDirty = true;
return true;
}
case RETRO_ENVIRONMENT::GET_USERNAME: case RETRO_ENVIRONMENT::GET_USERNAME:
//we definitely want to return false here so the core will do something deterministic //we definitely want to return false here so the core will do something deterministic
return false; 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 // need some way to communicate with retro variables later
void SetDirectories(const char* systemDirectory, const char* saveDirectory, const char* coreDirectory, const char* coreAssetsDirectory) { void SetDirectories(const char* systemDirectory, const char* saveDirectory, const char* coreDirectory, const char* coreAssetsDirectory) {
@ -528,6 +563,12 @@ private:
std::string retroMessageString; std::string retroMessageString;
u32 retroMessageTime; u32 retroMessageTime;
bool geoInfoDirty;
retro_game_geometry geoInfo;
bool timingInfoDirty;
retro_system_timing timingInfo;
bool variablesDirty; bool variablesDirty;
u32 variableCount; u32 variableCount;
std::unique_ptr<std::string[]> variableKeys; std::unique_ptr<std::string[]> variableKeys;
@ -593,6 +634,20 @@ EXPORT void LibretroBridge_GetRetroMessage(CallbackHandler* cbHandler, retro_mes
cbHandler->GetRetroMessage(m); 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 // set directories for the core
EXPORT void LibretroBridge_SetDirectories(CallbackHandler* cbHandler, const char* systemDirectory, const char* saveDirectory, const char* coreDirectory, const char* coreAssetsDirectory) { EXPORT void LibretroBridge_SetDirectories(CallbackHandler* cbHandler, const char* systemDirectory, const char* saveDirectory, const char* coreDirectory, const char* coreAssetsDirectory) {
cbHandler->SetDirectories(systemDirectory, saveDirectory, coreDirectory, 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::uint32_t u32;
typedef std::uint64_t u64; typedef std::uint64_t u64;
typedef float f32;
typedef double f64;
typedef u8 boolean; typedef u8 boolean;
#define EXPORT extern "C" __attribute__((visibility("default"))) #define EXPORT extern "C" __attribute__((visibility("default")))
@ -355,6 +358,24 @@ enum class RETRO_LOG {
DUMMY = INT_MAX, 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 { struct retro_variable {
const char* key; const char* key;
const char* value; const char* value;

View File

@ -326,20 +326,29 @@ namespace BizHawk.Emulation.Cores.Libretro
} }
[StructLayout(LayoutKind.Sequential)] [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_width;
public uint base_height; public uint base_height;
public uint max_width; public uint max_width;
public uint max_height; public uint max_height;
public float aspect_ratio; public float aspect_ratio;
}
// struct retro_system_timing [StructLayout(LayoutKind.Sequential)]
public struct retro_system_timing
{
public double fps; public double fps;
public double sample_rate; 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)] [BizImport(cc)]
public abstract void retro_init(); public abstract void retro_init();
@ -432,6 +441,12 @@ namespace BizHawk.Emulation.Cores.Libretro
[BizImport(cc)] [BizImport(cc)]
public abstract bool LibretroBridge_GetSupportsNoGame(IntPtr cbHandler); 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)] [BizImport(cc)]
public abstract void LibretroBridge_GetRetroMessage(IntPtr cbHandler, ref LibretroApi.retro_message m); 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 //this stuff can only happen after the game is loaded
//allocate a video buffer which will definitely be large enough //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 // TODO: more precise
VsyncNumerator = (int)(10000000 * av.fps); VsyncNumerator = (int)(10000000 * av.timing.fps);
VsyncDenominator = 10000000; 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 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) 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) if (render)
{ {
UpdateVideoBuffer(); UpdateVideoBuffer();

View File

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