|
13 | 13 | #include <libretro.h> |
14 | 14 | #include <string> |
15 | 15 | #include <thread> |
| 16 | +#include <fstream> |
16 | 17 |
|
17 | 18 | #include "options.h" |
18 | 19 |
|
@@ -358,11 +359,60 @@ void retro_get_system_info(retro_system_info* info) |
358 | 359 | #endif |
359 | 360 |
|
360 | 361 | info->library_name = "pcsx2"; |
361 | | - info->valid_extensions = "elf|iso|ciso|cue|bin|gz"; |
| 362 | + info->valid_extensions = "elf|iso|ciso|cue|bin|gz|m3u"; |
362 | 363 | info->need_fullpath = true; |
363 | 364 | info->block_extract = true; |
364 | 365 | } |
365 | 366 |
|
| 367 | + |
| 368 | +static std::vector<std::string> |
| 369 | + read_m3u_file(const std::string& m3u_file) |
| 370 | +{ |
| 371 | + log_cb(RETRO_LOG_DEBUG, "Reading M3U file"); |
| 372 | + std::vector<std::string> result; |
| 373 | + std::ifstream m3u_data(m3u_file); |
| 374 | + if (!m3u_data.is_open()) |
| 375 | + { |
| 376 | + log_cb(RETRO_LOG_ERROR, "M3U file \"%s\" cannot be read", m3u_file.c_str()); |
| 377 | + return result; |
| 378 | + } |
| 379 | + // This is the UTF-8 representation of U+FEFF. |
| 380 | + const std::string utf8_bom = "\xEF\xBB\xBF"; |
| 381 | + std::string line; |
| 382 | + getline(m3u_data, line); |
| 383 | + if (line.rfind(utf8_bom,0) == 0) |
| 384 | + { |
| 385 | + log_cb(RETRO_LOG_WARN, "M3U file \"%s\" contains UTF-8 BOM", m3u_file.c_str()); |
| 386 | + line.erase(0, utf8_bom.length()); |
| 387 | + } |
| 388 | + std::string m3u_parent = Path::Canonicalize(Path::GetDirectory(m3u_file)); |
| 389 | + for (line; !m3u_data.eof(); getline(m3u_data, line)) |
| 390 | + { |
| 391 | + if (!line.rfind('#', 0) == 0) // Comments start with # |
| 392 | + { |
| 393 | + std::string m3u_path = line; |
| 394 | + if (!Path::IsAbsolute(line)) |
| 395 | + { |
| 396 | + m3u_path = Path::Combine(m3u_parent, line); |
| 397 | + } |
| 398 | + std::ifstream discFile(m3u_path); |
| 399 | + if (discFile.is_open()) |
| 400 | + { |
| 401 | + log_cb(RETRO_LOG_DEBUG, "Found disc image in M3U file, %s", m3u_path.c_str()); |
| 402 | + result.push_back(m3u_path); |
| 403 | + } |
| 404 | + else |
| 405 | + { |
| 406 | + log_cb(RETRO_LOG_WARN, "File specified in the M3U file \"%s\" was not found", m3u_path.c_str()); |
| 407 | + } |
| 408 | + } |
| 409 | + } |
| 410 | + if (result.empty()) |
| 411 | + log_cb(RETRO_LOG_ERROR, "No paths found in the M3U file \"%s\"", m3u_file.c_str()); |
| 412 | + |
| 413 | + return result; |
| 414 | +} |
| 415 | + |
366 | 416 | void retro_get_system_av_info(retro_system_av_info* info) |
367 | 417 | { |
368 | 418 | if (Options::renderer == "Software" || Options::renderer == "Null") |
@@ -718,8 +768,18 @@ bool retro_load_game(const struct retro_game_info* game) |
718 | 768 | VMBootParameters boot_params; |
719 | 769 | if(game && game->path) |
720 | 770 | { |
721 | | - disk_images.push_back(game->path); |
722 | | - boot_params.filename = game->path; |
| 771 | + std::vector<std::string> game_paths; |
| 772 | + if (Path::GetExtension(game->path) == "m3u") |
| 773 | + { |
| 774 | + game_paths = read_m3u_file(game->path); |
| 775 | + log_cb(RETRO_LOG_DEBUG, "Found %u game images in M3U file.", game_paths.size()); |
| 776 | + } |
| 777 | + else |
| 778 | + { |
| 779 | + game_paths.push_back(game->path); |
| 780 | + } |
| 781 | + disk_images.assign(game_paths.begin(), game_paths.end()); |
| 782 | + boot_params.filename = disk_images[0]; |
723 | 783 | } |
724 | 784 |
|
725 | 785 | cpu_thread = std::thread(cpu_thread_entry, boot_params); |
|
0 commit comments