libretro: Implement disk control interface
This commit is contained in:
parent
8e1c0a4fe4
commit
f3df4f91a2
|
@ -1,6 +1,6 @@
|
|||
#include "string_util.h"
|
||||
#include <cstdio>
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
|
||||
namespace StringUtil {
|
||||
|
||||
|
@ -137,7 +137,23 @@ std::size_t Strlcpy(char* dst, const char* src, std::size_t size)
|
|||
else
|
||||
{
|
||||
std::memcpy(dst, src, size - 1);
|
||||
dst[size] = '\0';
|
||||
dst[size - 1] = '\0';
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
std::size_t Strlcpy(char* dst, const std::string_view& src, std::size_t size)
|
||||
{
|
||||
std::size_t len = src.length();
|
||||
if (len < size)
|
||||
{
|
||||
std::memcpy(dst, src.data(), len);
|
||||
dst[len] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memcpy(dst, src.data(), size - 1);
|
||||
dst[size - 1] = '\0';
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <cstring>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#if defined(__has_include) && __has_include(<charconv>)
|
||||
#include <charconv>
|
||||
|
@ -27,6 +28,9 @@ bool WildcardMatch(const char* subject, const char* mask, bool case_sensitive =
|
|||
/// Safe version of strlcpy.
|
||||
std::size_t Strlcpy(char* dst, const char* src, std::size_t size);
|
||||
|
||||
/// Strlcpy from string_view.
|
||||
std::size_t Strlcpy(char* dst, const std::string_view& src, std::size_t size);
|
||||
|
||||
/// Platform-independent strcasecmp
|
||||
static inline int Strcasecmp(const char* s1, const char* s2)
|
||||
{
|
||||
|
|
|
@ -27,6 +27,7 @@ Log_SetChannel(LibretroHostInterface);
|
|||
#endif
|
||||
|
||||
LibretroHostInterface g_libretro_host_interface;
|
||||
#define P_THIS (&g_libretro_host_interface)
|
||||
|
||||
retro_environment_t g_retro_environment_callback;
|
||||
retro_video_refresh_t g_retro_video_refresh_callback;
|
||||
|
@ -232,6 +233,7 @@ bool LibretroHostInterface::retro_load_game(const struct retro_game_info* game)
|
|||
{
|
||||
SystemBootParameters bp;
|
||||
bp.filename = game->path;
|
||||
bp.media_playlist_index = m_next_disc_index.value_or(0);
|
||||
bp.force_software_renderer = !m_hw_render_callback_valid;
|
||||
|
||||
if (!BootSystem(bp))
|
||||
|
@ -907,3 +909,180 @@ void LibretroHostInterface::SwitchToSoftwareRenderer()
|
|||
m_display = std::make_unique<LibretroHostDisplay>();
|
||||
m_system->RecreateGPU(GPURenderer::Software);
|
||||
}
|
||||
|
||||
bool LibretroHostInterface::DiskControlSetEjectState(bool ejected)
|
||||
{
|
||||
System* system = P_THIS->GetSystem();
|
||||
if (!system)
|
||||
{
|
||||
Log_ErrorPrintf("DiskControlSetEjectState() - no system");
|
||||
return false;
|
||||
}
|
||||
|
||||
Log_DevPrintf("DiskControlSetEjectState(%u)", static_cast<unsigned>(ejected));
|
||||
|
||||
if (ejected)
|
||||
{
|
||||
if (!system->HasMedia())
|
||||
return false;
|
||||
|
||||
system->RemoveMedia();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
const u32 image_to_insert = P_THIS->m_next_disc_index.value_or(0);
|
||||
Log_DevPrintf("Inserting image %u", image_to_insert);
|
||||
return system->SwitchMediaFromPlaylist(image_to_insert);
|
||||
}
|
||||
}
|
||||
|
||||
bool LibretroHostInterface::DiskControlGetEjectState()
|
||||
{
|
||||
System* system = P_THIS->GetSystem();
|
||||
if (!system)
|
||||
{
|
||||
Log_ErrorPrintf("DiskControlGetEjectState() - no system");
|
||||
return false;
|
||||
}
|
||||
|
||||
Log_DevPrintf("DiskControlGetEjectState() -> %u", static_cast<unsigned>(system->HasMedia()));
|
||||
return system->HasMedia();
|
||||
}
|
||||
|
||||
unsigned LibretroHostInterface::DiskControlGetImageIndex()
|
||||
{
|
||||
System* system = P_THIS->GetSystem();
|
||||
if (!system)
|
||||
{
|
||||
Log_ErrorPrintf("DiskControlGetImageIndex() - no system");
|
||||
return false;
|
||||
}
|
||||
|
||||
const u32 index = P_THIS->m_next_disc_index.value_or(system->GetMediaPlaylistIndex());
|
||||
Log_DevPrintf("DiskControlGetImageIndex() -> %u", index);
|
||||
return index;
|
||||
}
|
||||
|
||||
bool LibretroHostInterface::DiskControlSetImageIndex(unsigned index)
|
||||
{
|
||||
System* system = P_THIS->GetSystem();
|
||||
if (!system)
|
||||
{
|
||||
Log_ErrorPrintf("DiskControlSetImageIndex() - no system");
|
||||
return false;
|
||||
}
|
||||
|
||||
Log_DevPrintf("DiskControlSetImageIndex(%u)", index);
|
||||
|
||||
if (index >= system->GetMediaPlaylistCount())
|
||||
return false;
|
||||
|
||||
P_THIS->m_next_disc_index = index;
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned LibretroHostInterface::DiskControlGetNumImages()
|
||||
{
|
||||
System* system = P_THIS->GetSystem();
|
||||
if (!system)
|
||||
{
|
||||
Log_ErrorPrintf("DiskControlGetNumImages() - no system");
|
||||
return false;
|
||||
}
|
||||
|
||||
Log_DevPrintf("DiskControlGetNumImages() -> %u", system->GetMediaPlaylistCount());
|
||||
return static_cast<unsigned>(system->GetMediaPlaylistCount());
|
||||
}
|
||||
|
||||
bool LibretroHostInterface::DiskControlReplaceImageIndex(unsigned index, const retro_game_info* info)
|
||||
{
|
||||
System* system = P_THIS->GetSystem();
|
||||
if (!system)
|
||||
{
|
||||
Log_ErrorPrintf("DiskControlReplaceImageIndex() - no system");
|
||||
return false;
|
||||
}
|
||||
|
||||
Log_DevPrintf("DiskControlReplaceImageIndex(%u, %s)", index, info ? info->path : "null");
|
||||
if (info && info->path)
|
||||
return system->ReplaceMediaPathFromPlaylist(index, info->path);
|
||||
else
|
||||
return system->RemoveMediaPathFromPlaylist(index);
|
||||
}
|
||||
|
||||
bool LibretroHostInterface::DiskControlAddImageIndex()
|
||||
{
|
||||
System* system = P_THIS->GetSystem();
|
||||
if (!system)
|
||||
{
|
||||
Log_ErrorPrintf("DiskControlAddImageIndex() - no system");
|
||||
return false;
|
||||
}
|
||||
|
||||
Log_DevPrintf("DiskControlAddImageIndex() -> %zu", system->GetMediaPlaylistCount());
|
||||
system->AddMediaPathToPlaylist({});
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LibretroHostInterface::DiskControlSetInitialImage(unsigned index, const char* path)
|
||||
{
|
||||
Log_DevPrintf("DiskControlSetInitialImage(%u, %s)", index, path);
|
||||
P_THIS->m_next_disc_index = index;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LibretroHostInterface::DiskControlGetImagePath(unsigned index, char* path, size_t len)
|
||||
{
|
||||
System* system = P_THIS->GetSystem();
|
||||
if (!system || index >= system->GetMediaPlaylistCount())
|
||||
return false;
|
||||
|
||||
const std::string& image_path = system->GetMediaPlaylistPath(index);
|
||||
Log_DevPrintf("DiskControlGetImagePath(%u) -> %s", index, image_path.c_str());
|
||||
if (image_path.empty())
|
||||
return false;
|
||||
|
||||
StringUtil::Strlcpy(path, image_path.c_str(), len);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LibretroHostInterface::DiskControlGetImageLabel(unsigned index, char* label, size_t len)
|
||||
{
|
||||
System* system = P_THIS->GetSystem();
|
||||
if (!system || index >= system->GetMediaPlaylistCount())
|
||||
return false;
|
||||
|
||||
const std::string& image_path = system->GetMediaPlaylistPath(index);
|
||||
if (image_path.empty())
|
||||
return false;
|
||||
|
||||
const std::string_view title = GameList::GetTitleForPath(label);
|
||||
StringUtil::Strlcpy(label, title, len);
|
||||
Log_DevPrintf("DiskControlGetImagePath(%u) -> %s", index, label);
|
||||
return true;
|
||||
}
|
||||
|
||||
void LibretroHostInterface::InitDiskControlInterface()
|
||||
{
|
||||
unsigned version = 0;
|
||||
if (g_retro_environment_callback(RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION, &version) && version >= 1)
|
||||
{
|
||||
retro_disk_control_ext_callback ext_cb = {
|
||||
&LibretroHostInterface::DiskControlSetEjectState, &LibretroHostInterface::DiskControlGetEjectState,
|
||||
&LibretroHostInterface::DiskControlGetImageIndex, &LibretroHostInterface::DiskControlSetImageIndex,
|
||||
&LibretroHostInterface::DiskControlGetNumImages, &LibretroHostInterface::DiskControlReplaceImageIndex,
|
||||
&LibretroHostInterface::DiskControlAddImageIndex, &LibretroHostInterface::DiskControlSetInitialImage,
|
||||
&LibretroHostInterface::DiskControlGetImagePath, &LibretroHostInterface::DiskControlGetImageLabel};
|
||||
if (g_retro_environment_callback(RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE, &ext_cb))
|
||||
return;
|
||||
}
|
||||
|
||||
retro_disk_control_callback cb = {
|
||||
&LibretroHostInterface::DiskControlSetEjectState, &LibretroHostInterface::DiskControlGetEjectState,
|
||||
&LibretroHostInterface::DiskControlGetImageIndex, &LibretroHostInterface::DiskControlSetImageIndex,
|
||||
&LibretroHostInterface::DiskControlGetNumImages, &LibretroHostInterface::DiskControlReplaceImageIndex,
|
||||
&LibretroHostInterface::DiskControlAddImageIndex};
|
||||
if (!g_retro_environment_callback(RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE, &cb))
|
||||
Log_WarningPrint("Failed to set disk control interface");
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include "core/host_interface.h"
|
||||
#include "core/system.h"
|
||||
#include "libretro.h"
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
|
||||
class LibretroHostInterface : public HostInterface
|
||||
{
|
||||
|
@ -12,6 +14,7 @@ public:
|
|||
static void InitLogging();
|
||||
static bool SetCoreOptions();
|
||||
static bool HasCoreVariablesChanged();
|
||||
static void InitDiskControlInterface();
|
||||
|
||||
ALWAYS_INLINE u32 GetResolutionScale() const { return m_settings.gpu_resolution_scale; }
|
||||
|
||||
|
@ -66,10 +69,23 @@ private:
|
|||
static void HardwareRendererContextReset();
|
||||
static void HardwareRendererContextDestroy();
|
||||
|
||||
// Disk control callbacks
|
||||
static bool RETRO_CALLCONV DiskControlSetEjectState(bool ejected);
|
||||
static bool RETRO_CALLCONV DiskControlGetEjectState();
|
||||
static unsigned RETRO_CALLCONV DiskControlGetImageIndex();
|
||||
static bool RETRO_CALLCONV DiskControlSetImageIndex(unsigned index);
|
||||
static unsigned RETRO_CALLCONV DiskControlGetNumImages();
|
||||
static bool RETRO_CALLCONV DiskControlReplaceImageIndex(unsigned index, const retro_game_info* info);
|
||||
static bool RETRO_CALLCONV DiskControlAddImageIndex();
|
||||
static bool RETRO_CALLCONV DiskControlSetInitialImage(unsigned index, const char* path);
|
||||
static bool RETRO_CALLCONV DiskControlGetImagePath(unsigned index, char* path, size_t len);
|
||||
static bool RETRO_CALLCONV DiskControlGetImageLabel(unsigned index, char* label, size_t len);
|
||||
|
||||
retro_hw_render_callback m_hw_render_callback = {};
|
||||
std::unique_ptr<HostDisplay> m_hw_render_display;
|
||||
bool m_hw_render_callback_valid = false;
|
||||
bool m_using_hardware_renderer = false;
|
||||
std::optional<u32> m_next_disc_index;
|
||||
};
|
||||
|
||||
extern LibretroHostInterface g_libretro_host_interface;
|
||||
|
|
|
@ -127,6 +127,7 @@ RETRO_API void retro_set_environment(retro_environment_t f)
|
|||
Log_WarningPrintf("Failed to set core options, settings will not be changeable.");
|
||||
|
||||
g_libretro_host_interface.InitLogging();
|
||||
g_libretro_host_interface.InitDiskControlInterface();
|
||||
}
|
||||
|
||||
RETRO_API void retro_set_video_refresh(retro_video_refresh_t f)
|
||||
|
|
Loading…
Reference in New Issue