Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add m3u support #6

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 96 additions & 18 deletions libretro/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ static const IConsoleWriter ConsoleWriter_Libretro =
0, // instance-level indentation (should always be 0)
};

static std::vector<const char*> disk_images;
static wxVector<wxString> disk_images;
static int image_index = 0;
static bool eject_state;
static bool RETRO_CALLCONV set_eject_state(bool ejected)
Expand Down Expand Up @@ -282,7 +282,7 @@ static bool RETRO_CALLCONV replace_image_index(unsigned index, const struct retr

static bool RETRO_CALLCONV add_image_index(void)
{
disk_images.push_back(nullptr);
disk_images.push_back("");
return true;
}

Expand All @@ -301,21 +301,21 @@ static bool RETRO_CALLCONV get_image_path(unsigned index, char* path, size_t len
if (index >= disk_images.size())
return false;

if (!disk_images[index])
if (disk_images[index].empty())
return false;

strncpy(path, disk_images[index], len);
strncpy(path, disk_images[index].c_str(), len);
return true;
}
static bool RETRO_CALLCONV get_image_label(unsigned index, char* label, size_t len)
{
if (index >= disk_images.size())
return false;

if (!disk_images[index])
if (disk_images[index].empty())
return false;

strncpy(label, disk_images[index], len);
strncpy(label, disk_images[index].c_str(), len);
return true;
}

Expand Down Expand Up @@ -427,7 +427,7 @@ void retro_get_system_info(retro_system_info* info)
#endif

info->library_name = "pcsx2";
info->valid_extensions = "elf|iso|ciso|cue|bin|gz";
info->valid_extensions = "elf|iso|ciso|cue|bin|gz|m3u";
info->need_fullpath = true;
info->block_extract = true;
}
Expand Down Expand Up @@ -523,6 +523,59 @@ static bool set_hw_render(retro_hw_context_type type)
return environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render);
}

static wxVector<wxString>
read_m3u_file(const wxFileName& m3u_file)
{
log_cb(RETRO_LOG_DEBUG, "Reading M3U file");

wxVector<wxString> result;
wxVector<wxString> nonexistent;

wxTextFile m3u_data;
if (!m3u_data.Open(m3u_file.GetFullPath()))
{
log_cb(RETRO_LOG_ERROR, "M3U file \"%s\" cannot be read", m3u_file.GetFullPath().c_str());
return result;
}

wxString base_path = m3u_file.GetPath();

// This is the UTF-8 representation of U+FEFF.
const wxString utf8_bom = "\xEF\xBB\xBF";

wxString line = m3u_data.GetFirstLine();
if (line.StartsWith(utf8_bom))
{
log_cb(RETRO_LOG_WARN, "M3U file \"%s\" contains UTF-8 BOM", m3u_file.GetFullPath().c_str());
line.erase(0, utf8_bom.length());
}

for (line; !m3u_data.Eof(); line = m3u_data.GetNextLine())
{
if (!line.StartsWith('#')) // Comments start with #
{
wxFileName discFile(base_path, line);
discFile.Normalize();
if (discFile.Exists())
{
log_cb(RETRO_LOG_DEBUG, "Found disc image in M3U file, %s", discFile.GetFullPath());
result.push_back(discFile.GetFullPath());
}
else
{
wxString full_path = discFile.GetFullPath();
nonexistent.push_back(full_path);
log_cb(RETRO_LOG_WARN, "File specified in the M3U file \"%s\" was not found:\n%s", m3u_file.GetFullPath().c_str(), full_path.c_str());
}
}
}

if (result.empty())
log_cb(RETRO_LOG_ERROR, "No paths found in the M3U file \"%s\"", m3u_file.GetFullPath().c_str());

return result;
}

bool retro_load_game(const struct retro_game_info* game)
{
if (Options::bios.empty())
Expand All @@ -546,31 +599,56 @@ bool retro_load_game(const struct retro_game_info* game)

Options::renderer.UpdateAndLock(); // disallow changes to Options::renderer outside of retro_load_game.

u32 magic = 0;
if (game)
{
FILE* fp = fopen(game->path, "rb");
wxVector<wxString> game_paths;

wxFileName file_name(game->path);
if (file_name.GetExt() == "m3u")
{
game_paths = read_m3u_file(file_name);
log_cb(RETRO_LOG_DEBUG, "Found %u game images in M3U file.", game_paths.size());
}
else
{
game_paths.push_back(game->path);
}

disk_images.assign(game_paths.begin(), game_paths.end());

u32 magic = 0;
FILE* fp = fopen(game_paths[0], "rb");
if (!fp)
{
log_cb(RETRO_LOG_ERROR, "Could not open File: %s\n", game->path);
log_cb(RETRO_LOG_ERROR, "Could not open File: %s\n", game_paths[0]);
return false;
}

fread(&magic, 4, 1, fp);
fclose(fp);
}

if (magic == 0x464C457F) // elf
{
// g_Conf->CurrentIRX = "";
g_Conf->EmuOptions.UseBOOT2Injection = true;
pcsx2->SysExecute(CDVD_SourceType::NoDisc, game->path);
if (magic == 0x464C457F) // elf
{
log_cb(RETRO_LOG_DEBUG, "Loading image as ELF.");
// g_Conf->CurrentIRX = "";
g_Conf->EmuOptions.UseBOOT2Injection = true;
pcsx2->SysExecute(CDVD_SourceType::NoDisc, game_paths[0]);
}
else
{
log_cb(RETRO_LOG_DEBUG, "Loading image as disc.");
g_Conf->EmuOptions.UseBOOT2Injection = Options::fast_boot;
g_Conf->CdvdSource = CDVD_SourceType::Iso;
g_Conf->CurrentIso = game_paths[0];
pcsx2->SysExecute(g_Conf->CdvdSource);
}
}
else
{
log_cb(RETRO_LOG_DEBUG, "Loading without image.");
g_Conf->EmuOptions.UseBOOT2Injection = Options::fast_boot;
g_Conf->CdvdSource = game ? CDVD_SourceType::Iso : CDVD_SourceType::NoDisc;
g_Conf->CurrentIso = game ? game->path : "";
g_Conf->CdvdSource = CDVD_SourceType::NoDisc;
g_Conf->CurrentIso = "";
pcsx2->SysExecute(g_Conf->CdvdSource);
}

Expand Down