Skip to content

Commit 49d36c0

Browse files
authored
Merge pull request #453 from replicacoil/master
Subsystem implementation for the Game Boy Player.
2 parents a0671be + d8892d3 commit 49d36c0

4 files changed

Lines changed: 143 additions & 4 deletions

File tree

Source/Core/Core/HW/GBACore.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,8 +758,14 @@ bool Core::GetRomInfo(const char* rom_path, std::array<u8, 20>& hash, std::strin
758758

759759
std::string Core::GetSavePath(std::string_view rom_path, int device_number)
760760
{
761+
// This is done to make the save file compatible with the save from the mGBA core in RA as it
762+
// saves in *.srm format.
763+
#ifdef __LIBRETRO__
764+
std::string save_path = fmt::format("{}.srm", rom_path.substr(0, rom_path.find_last_of('.')));
765+
#else
761766
std::string save_path =
762767
fmt::format("{}-{}.sav", rom_path.substr(0, rom_path.find_last_of('.')), device_number + 1);
768+
#endif
763769

764770
if (!Config::Get(Config::MAIN_GBA_SAVES_IN_ROM_PATH))
765771
{

Source/Core/DolphinLibretro/Boot.cpp

Lines changed: 112 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "Common/CommonPaths.h"
99
#include "Core/CommonTitles.h"
1010
#include "Common/FileUtil.h"
11+
#include "Common/StringUtil.h"
1112
#include "Common/Version.h"
1213
#include "Core/Boot/Boot.h"
1314
#include "Core/BootManager.h"
@@ -19,6 +20,7 @@
1920
#include "Core/GeckoCodeConfig.h"
2021
#include "Core/HW/DVD/DVDInterface.h"
2122
#include "Core/HW/EXI/EXI_Device.h"
23+
#include "Core/HW/HSP/HSP_Device.h"
2224
#include "Core/HW/VideoInterface.h"
2325
#include "Core/HW/WiimoteReal/WiimoteReal.h"
2426
#include "Core/PowerPC/PowerPC.h"
@@ -53,6 +55,10 @@ static unsigned disk_index = 0;
5355
static bool eject_state;
5456
static std::vector<std::string> disk_paths;
5557

58+
// GBPlayer
59+
static std::string GBPlayer_rom_path;
60+
static bool GBPlayer_active;
61+
5662
// silence forward declaration warnings
5763
void reload_cheats_from_ini();
5864
void generate_cht_from_ini(std::string fileName);
@@ -168,12 +174,64 @@ void generate_cht_from_ini(std::string fileName)
168174
bool retro_load_game(const struct retro_game_info* game)
169175
{
170176
const char* save_dir = NULL;
177+
const char* gba_save_dir = NULL;
171178
const char* system_dir = NULL;
172179
const char* core_assets_dir = NULL;
180+
std::string rebuild_save_dir;
173181
std::string user_dir;
174182
std::string sys_dir;
175183

176-
Libretro::environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &save_dir);
184+
/*
185+
* If the GBPlayer is active, we try to reconstruct the GC save dir location
186+
* with regards to content sorting and core sorting. If we do not do this,
187+
* there will be a User directory with GC saves in the GB/GBC/GBA rom save path
188+
* when a user has content/core sorting enabled. Since the user is trying to avoid
189+
* said behavior actively if those sorting options are enabled,
190+
* we should seperate them accordingly.
191+
*/
192+
if (Libretro::GBPlayer_active)
193+
{
194+
std::filesystem::path gba_content_dir = std::filesystem::path("");
195+
if (!Libretro::GBPlayer_rom_path.empty())
196+
gba_content_dir = std::filesystem::path(Libretro::GBPlayer_rom_path).parent_path().filename().string();
197+
198+
Libretro::environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &gba_save_dir);
199+
std::filesystem::path base = std::filesystem::path(gba_save_dir);
200+
201+
bool core_sort = false;
202+
retro_system_info sys_info{};
203+
retro_get_system_info(&sys_info);
204+
const std::string library_name = sys_info.library_name;
205+
206+
if (!base.empty() && !library_name.empty())
207+
core_sort = Common::CaseInsensitiveEquals(base.filename().string(), library_name);
208+
if (core_sort)
209+
base = base.parent_path();
210+
211+
bool content_sort = false;
212+
std::string gc_content_dir;
213+
if (!gba_content_dir.empty() && !base.empty())
214+
content_sort = Common::CaseInsensitiveEquals(base.filename().string(), gba_content_dir.string());
215+
if (content_sort)
216+
{
217+
gc_content_dir = std::filesystem::path(game->path).parent_path().filename().string();
218+
base = base.parent_path();
219+
}
220+
221+
rebuild_save_dir = base.string();
222+
if (content_sort)
223+
rebuild_save_dir = rebuild_save_dir + DIR_SEP + gc_content_dir;
224+
if (core_sort)
225+
rebuild_save_dir = rebuild_save_dir + DIR_SEP + library_name;
226+
227+
save_dir = rebuild_save_dir.c_str();
228+
INFO_LOG_FMT(BOOT, "GBPlayer: GC save dir reconstructed to: '{}'", save_dir);
229+
}
230+
else
231+
{
232+
Libretro::environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &save_dir);
233+
}
234+
177235
Libretro::environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &system_dir);
178236
Libretro::environ_cb(RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY, &core_assets_dir);
179237
Libretro::InitDiskControlInterface();
@@ -212,6 +270,22 @@ bool retro_load_game(const struct retro_game_info* game)
212270
UICommon::CreateDirectories();
213271
UICommon::Init();
214272
Libretro::Log::Init();
273+
274+
if (Libretro::GBPlayer_active)
275+
{
276+
Config::SetBase(Config::MAIN_GBA_ROM_PATHS[Config::GBPLAYER_GBA_INDEX], Libretro::GBPlayer_rom_path);
277+
INFO_LOG_FMT(BOOT, "GBPlayer: GBA ROM path applied from subsystem: '{}'", Libretro::GBPlayer_rom_path);
278+
Config::SetBase(Config::MAIN_GBA_SAVES_PATH, std::string(gba_save_dir));
279+
INFO_LOG_FMT(BOOT, "GBPlayer: ROM save set to: '{}'", gba_save_dir);
280+
// In order to prevent confusion for the settings of the save location between RA and the
281+
// emulator we just turn this off
282+
Config::SetBase(Config::MAIN_GBA_SAVES_IN_ROM_PATH, false);
283+
}
284+
else
285+
{
286+
Config::SetBase(Config::MAIN_GBA_ROM_PATHS[Config::GBPLAYER_GBA_INDEX], std::string{});
287+
}
288+
215289
Discord::SetDiscordPresenceEnabled(false);
216290
Common::SetEnableAlert(false);
217291
Common::SetAbortOnPanicAlert(false);
@@ -633,10 +707,44 @@ bool retro_load_game(const struct retro_game_info* game)
633707
return true;
634708
}
635709

636-
bool retro_load_game_special(unsigned game_type, const struct retro_game_info* info,
637-
size_t num_info)
710+
bool retro_load_game_special(unsigned game_type, const struct retro_game_info* info, size_t num_info)
638711
{
639-
return false;
712+
if (game_type != Libretro::g_gbplayer_subsystem_id)
713+
{
714+
ERROR_LOG_FMT(BOOT, "retro_load_game_special: unknown game_type {}", game_type);
715+
return false;
716+
}
717+
if (num_info < 1 || !info)
718+
{
719+
ERROR_LOG_FMT(BOOT, "retro_load_game_special: no content info");
720+
return false;
721+
}
722+
723+
const retro_game_info* gba_slot = (num_info >= 2 && info[0].path && *info[0].path) ? &info[0] : nullptr;
724+
725+
const retro_game_info* gc_slot = (info[1].path && *info[1].path) ? &info[1] : nullptr;
726+
727+
if (!gc_slot)
728+
{
729+
ERROR_LOG_FMT(BOOT, "GBPlayer: no GC disc path provided in slot 0");
730+
return false;
731+
}
732+
733+
INFO_LOG_FMT(BOOT, "GBPlayer: GC disc = '{}'", gc_slot->path);
734+
if (gba_slot)
735+
{
736+
Libretro::GBPlayer_rom_path = gba_slot->path;
737+
INFO_LOG_FMT(BOOT, "GBPlayer: ROM = '{}'", gba_slot->path);
738+
}
739+
else
740+
{
741+
Libretro::GBPlayer_rom_path.clear();
742+
INFO_LOG_FMT(BOOT, "GBPlayer: no ROM");
743+
}
744+
745+
Libretro::GBPlayer_active = true;
746+
747+
return retro_load_game(gc_slot);
640748
}
641749

642750
void retro_unload_game(void)

Source/Core/DolphinLibretro/Common/Globals.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ extern retro_environment_t environ_cb;
1313
extern bool g_emuthread_launched;
1414
extern std::vector<Gecko::GeckoCode> g_gecko_codes;
1515
extern std::vector<ActionReplay::ARCode> g_ar_codes;
16+
inline constexpr unsigned g_gbplayer_subsystem_id = 0x101;
1617

1718
namespace Input
1819
{

Source/Core/DolphinLibretro/Main.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,30 @@ void retro_set_environment(retro_environment_t cb)
8989
#ifdef PERF_TEST
9090
environ_cb(RETRO_ENVIRONMENT_GET_PERF_INTERFACE, &perf_cb);
9191
#endif
92+
static const struct retro_subsystem_memory_info gbp_gba_memory[] = {
93+
{"srm", RETRO_MEMORY_SAVE_RAM},
94+
};
95+
static const struct retro_subsystem_rom_info gbp_roms[] = {
96+
{"GBA ROM", "gba|gbc|gb|zip|7z",
97+
true,
98+
true,
99+
false,
100+
gbp_gba_memory, 1},
101+
{"GameCube Disc", "rvz|gcm|iso|ciso|wbfs|gcz|tgc|m3u",
102+
true,
103+
false,
104+
true,
105+
nullptr, 0},
106+
};
107+
static const struct retro_subsystem_info subsystems[] = {
108+
{
109+
"Game Boy Player",
110+
"GBP",
111+
gbp_roms, 2,
112+
Libretro::g_gbplayer_subsystem_id
113+
},
114+
{nullptr, nullptr, nullptr, 0, 0}};
115+
cb(RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO, (void*)subsystems);
92116
}
93117

94118
void retro_init(void)

0 commit comments

Comments
 (0)