Unverified Commit 0a4c18e1 authored by Libretro-Admin's avatar Libretro-Admin Committed by GitHub
Browse files

Merge pull request #26 from jdgleaver/content-data-api

Add support for RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE API extension - enables soft patching of non-CD content
parents 4ef73108 59382a5d
Pipeline #46058 passed with stages
in 19 minutes and 12 seconds
This diff is collapsed.
......@@ -28,7 +28,7 @@
#define MEDNAFEN_CORE_NAME_MODULE "pce"
#define MEDNAFEN_CORE_NAME "Beetle PCE"
#define MEDNAFEN_CORE_VERSION "v0.9.48"
#define MEDNAFEN_CORE_EXTENSIONS "pce|cue|ccd|chd|sgx"
#define MEDNAFEN_CORE_EXTENSIONS "pce|sgx|cue|ccd|chd|toc|m3u"
#define MEDNAFEN_CORE_TIMING_FPS 7159090.90909090 / 455.0 / 263.0
#define MEDNAFEN_CORE_GEOMETRY_BASE_W 256
#define MEDNAFEN_CORE_GEOMETRY_BASE_H 224
......@@ -621,16 +621,23 @@ end:
static std::vector<CDIF *> CDInterfaces; // FIXME: Cleanup on error out.
// TODO: LoadCommon()
static bool MDFNI_LoadCD(const char *devicename)
static bool MDFNI_LoadCD(const char *path, const char *ext)
{
bool ret = false;
log_cb(RETRO_LOG_INFO, "Loading %s...\n\n", devicename);
if(devicename && strlen(devicename) > 4 && !strcasecmp(devicename + strlen(devicename) - 4, ".m3u"))
if (!path || !ext)
{
log_cb(RETRO_LOG_ERROR, "Error opening CD - invalid path\n");
return false;
}
log_cb(RETRO_LOG_INFO, "Loading %s...\n\n", path);
if (!strcasecmp(ext, "m3u"))
{
std::vector<std::string> file_list;
ReadM3U(file_list, devicename);
ReadM3U(file_list, path);
for(unsigned i = 0; i < file_list.size(); i++)
{
......@@ -640,7 +647,7 @@ static bool MDFNI_LoadCD(const char *devicename)
}
else
{
CDIF *cdif = CDIF_Open(devicename, cdimagecache);
CDIF *cdif = CDIF_Open(path, cdimagecache);
if (cdif)
{
......@@ -701,40 +708,63 @@ static bool MDFNI_LoadCD(const char *devicename)
return true;
}
static bool MDFNI_LoadGame(const char *name)
static bool MDFNI_LoadGame(const char *path, const char *ext,
const uint8_t *data, size_t size)
{
MDFNFILE *GameFile = NULL;
MDFNGameInfo = &EmulatedPCE;
MDFNFILE *GameFile = NULL;
MDFNGameInfo = &EmulatedPCE;
const uint8_t *content_data = NULL;
size_t content_size = 0;
if(strlen(name) > 4 && (!strcasecmp(name + strlen(name) - 4, ".cue") || !strcasecmp(name + strlen(name) - 4, ".ccd") || !strcasecmp(name + strlen(name) - 4, ".chd") || !strcasecmp(name + strlen(name) - 4, ".toc") || !strcasecmp(name + strlen(name) - 4, ".m3u")))
return MDFNI_LoadCD(name);
if(ext &&
(!strcasecmp(ext, "cue") ||
!strcasecmp(ext, "ccd") ||
!strcasecmp(ext, "chd") ||
!strcasecmp(ext, "toc") ||
!strcasecmp(ext, "m3u")))
return MDFNI_LoadCD(path, ext);
MDFN_printf("Loading %s...\n",name);
MDFN_printf("Loading %s...\n", path ? path : "content");
MDFN_indent(1);
// Construct a NULL-delimited list of known file extensions for MDFN_fopen()
GameFile = file_open(name);
/* Check whether we already have a valid
* data buffer */
if (data)
{
content_data = data;
content_size = size;
}
else
{
if (!path)
{
log_cb(RETRO_LOG_ERROR, "Error loading content - invalid path\n");
goto error;
}
/* Load content from file */
GameFile = file_open(path);
if(!GameFile)
goto error;
if(!GameFile)
goto error;
content_data = GameFile->data;
content_size = GameFile->size;
}
MDFN_printf("Using module: pce.\n\n");
MDFN_indent(1);
//
// Load per-game settings
//
// Maybe we should make a "pgcfg" subdir, and automatically load all files in it?
// End load per-game settings
//
if(PCE_Load(GameFile) <= 0)
if(PCE_Load(content_data, content_size, ext) <= 0)
goto error;
MDFN_LoadGameCheats(NULL);
MDFNMP_InstallReadPatches();
if (GameFile)
file_close(GameFile);
MDFN_indent(-2);
return true;
......@@ -1336,14 +1366,57 @@ bool retro_load_game(const struct retro_game_info *info)
{ 0 },
};
if (!info || failed_init)
const struct retro_game_info_ext *info_ext = NULL;
const uint8_t *content_data = NULL;
size_t content_size = 0;
const char *content_path = NULL;
char content_ext[8];
content_ext[0] = '\0';
if (failed_init)
return false;
/* Attempt to fetch extended game info */
if (environ_cb(RETRO_ENVIRONMENT_GET_GAME_INFO_EXT, &info_ext))
{
content_data = (const uint8_t *)info_ext->data;
content_size = info_ext->size;
/* Content path information is only required
* if we do not have a valid data buffer */
if (!content_data)
{
content_path = info_ext->full_path;
strncpy(content_ext, info_ext->ext, sizeof(content_ext));
content_ext[sizeof(content_ext) - 1] = '\0';
}
}
else
{
const char *ext = NULL;
if (!info || !info->path)
return false;
content_data = NULL;
content_size = 0;
content_path = info->path;
if ((ext = strrchr(info->path, '.')))
{
strncpy(content_ext, ext + 1, sizeof(content_ext));
content_ext[sizeof(content_ext) - 1] = '\0';
}
}
environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc);
check_variables(false);
if (!MDFNI_LoadGame(info->path))
if (!MDFNI_LoadGame(content_path, content_ext,
content_data, content_size))
return false;
surf = (MDFN_Surface*)calloc(1, sizeof(*surf));
......@@ -1827,8 +1900,18 @@ void retro_set_environment(retro_environment_t cb)
{ 0 },
};
static const struct retro_system_content_info_override content_overrides[] = {
{
"pce|sgx", /* extensions */
false, /* need_fullpath */
false /* persistent_data */
},
{ NULL, false, false }
};
libretro_set_core_options(environ_cb);
environ_cb(RETRO_ENVIRONMENT_SET_CONTROLLER_INFO, (void*)ports);
environ_cb(RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE, (void*)content_overrides);
vfs_iface_info.required_interface_version = 1;
vfs_iface_info.iface = NULL;
......
......@@ -203,7 +203,7 @@ static void LoadSaveMemory(const std::string& path, uint8* const data, const uin
#endif
}
uint32 HuC_Load(MDFNFILE* fp, bool DisableBRAM, SysCardType syscard)
uint32 HuC_Load(const uint8_t *data, size_t size, bool DisableBRAM, SysCardType syscard)
{
uint32 crc = 0;
const uint32 sf2_threshold = 2048 * 1024;
......@@ -213,24 +213,23 @@ uint32 HuC_Load(MDFNFILE* fp, bool DisableBRAM, SysCardType syscard)
uint64 len, m_len;
len = fp->size;
len = size;
if(len & 512) // Skip copier header.
{
len &= ~512;
file_seek(fp, 512, SEEK_SET);
data += 512;
size -= 512;
}
m_len = (len + 8191) &~ 8191;
if(len >= 8192)
if(size >= 8192)
{
uint8 buf[8192];
file_read(fp, buf, 8192, 1);
memcpy(buf, data, 8192);
if(!memcmp(buf + 0x1FD0, "MCGENJIN", 8))
mcg_mapper = true;
file_seek(fp, -8192, SEEK_CUR); // Seek backwards so we don't undo skip copier header.
}
if(!syscard && m_len >= sf2_threshold && !mcg_mapper)
......@@ -273,7 +272,7 @@ uint32 HuC_Load(MDFNFILE* fp, bool DisableBRAM, SysCardType syscard)
if(mcg_mapper)
{
mcg = new MCGenjin(fp);
mcg = new MCGenjin(data, size);
for(unsigned i = 0; i < 128; i++)
{
......@@ -303,7 +302,7 @@ uint32 HuC_Load(MDFNFILE* fp, bool DisableBRAM, SysCardType syscard)
HuCROM = new uint8[m_len];
memset(HuCROM, 0xFF, m_len);
file_read(fp, HuCROM, min_T<uint64>(m_len, len), 1);
memcpy(HuCROM, data, min_T<uint64>(m_len, size));
crc = encoding_crc32(0, HuCROM, min_T<uint64>(m_len, len));
if(syscard == SYSCARD_NONE)
......
#ifndef __MDFN_PCE_HUC_H
#define __MDFN_PCE_HUC_H
#include <stddef.h>
typedef enum
{
SYSCARD_NONE = 0,
......@@ -10,7 +12,7 @@ typedef enum
SYSCARD_ARCADE // 3.0 + extras
} SysCardType;
uint32 HuC_Load(MDFNFILE* fp, bool DisableBRAM = false, SysCardType syscard = SYSCARD_NONE) MDFN_COLD;
uint32 HuC_Load(const uint8_t *data, size_t size, bool DisableBRAM = false, SysCardType syscard = SYSCARD_NONE) MDFN_COLD;
void HuC_SaveNV(void);
void HuC_Kill(void) MDFN_COLD;
......
......@@ -193,9 +193,9 @@ void MCGenjin::WriteNV(const unsigned di, const uint8 *buffer, uint32 offset, ui
cs[di]->WriteNV(buffer, offset, count);
}
MCGenjin::MCGenjin(MDFNFILE* fp)
MCGenjin::MCGenjin(const uint8_t *data, size_t size)
{
const uint64 rr_size = fp->size;
const uint64 rr_size = size;
uint8 revision, num256_pages, region, cs_di[2];
if(rr_size > 1024 * 1024 * 128)
......@@ -211,7 +211,7 @@ MCGenjin::MCGenjin(MDFNFILE* fp)
}
rom.resize(round_up_pow2(rr_size));
file_read(fp, &rom[0], rr_size, 1);
memcpy(&rom[0], data, rr_size);
if(memcmp(&rom[0x1FD0], "MCGENJIN", 8))
{
......
......@@ -18,6 +18,8 @@
#ifndef __MDFN_PCE_MCGENJIN_H
#define __MDFN_PCE_MCGENJIN_H
#include <stddef.h>
class MCGenjin_CS_Device
{
public:
......@@ -43,7 +45,7 @@ class MCGenjin
{
public:
MCGenjin(MDFNFILE* fp);
MCGenjin(const uint8_t *data, size_t size);
~MCGenjin();
void Power(void);
......
......@@ -295,7 +295,7 @@ static const struct
{ 0, "" }
};
MDFN_COLD int PCE_Load(MDFNFILE *fp)
MDFN_COLD int PCE_Load(const uint8_t *data, size_t size, const char *ext)
{
IsSGX = false;
......@@ -303,9 +303,9 @@ MDFN_COLD int PCE_Load(MDFNFILE *fp)
uint32 crc;
crc = HuC_Load(fp, MDFN_GetSettingB("pce.disable_bram_hucard"));
crc = HuC_Load(data, size, MDFN_GetSettingB("pce.disable_bram_hucard"));
if(!strcmp(fp->ext, "sgx"))
if(!strcmp(ext, "sgx"))
IsSGX = true;
else
{
......@@ -499,7 +499,7 @@ MDFN_COLD int PCE_LoadCD(std::vector<CDIF *> *CDInterfaces)
if(disable_bram_cd)
MDFN_printf("Warning: BRAM is disabled per pcfx.disable_bram_cd setting. This is simulating a malfunction.\n");
HuC_Load(fp, disable_bram_cd, PCE_ACEnabled ? SYSCARD_ARCADE : SYSCARD_3);
HuC_Load(fp->data, fp->size, disable_bram_cd, PCE_ACEnabled ? SYSCARD_ARCADE : SYSCARD_3);
file_close(fp);
ADPCMBuf = new RavenBuffer();
......
......@@ -2,6 +2,7 @@
#define __MDFN_PCE_PCE_H
#include <vector>
#include <stddef.h>
#include <mednafen/mednafen.h>
#include <mednafen/state.h>
......@@ -21,7 +22,7 @@ extern MDFNGI EmulatedPCE;
extern bool PCE_ACEnabled; // Arcade Card emulation enabled?
extern void PCE_Power(void);
extern MDFN_COLD int PCE_Load(MDFNFILE *fp);
extern MDFN_COLD int PCE_Load(const uint8_t *data, size_t size, const char *ext);
extern MDFN_COLD int PCE_LoadCD(std::vector<CDIF *> *CDInterfaces);
extern MDFN_COLD void PCE_CloseGame(void);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment