Skip to content

Commit

Permalink
erreula: Rework implementation and fix bugs
Browse files Browse the repository at this point in the history
There is more work to do but this is already a big improvement. Fixes the issue where the error dialog would softlock in some games.
  • Loading branch information
Exzap committed Nov 10, 2024
1 parent 99e46d9 commit 641ef0f
Show file tree
Hide file tree
Showing 5 changed files with 307 additions and 176 deletions.
42 changes: 21 additions & 21 deletions src/Cafe/CafeSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -637,40 +637,40 @@ namespace CafeSystem
fsc_unmount("/cemuBossStorage/", FSC_PRIORITY_BASE);
}

STATUS_CODE LoadAndMountForegroundTitle(TitleId titleId)
PREPARE_STATUS_CODE LoadAndMountForegroundTitle(TitleId titleId)
{
cemuLog_log(LogType::Force, "Mounting title {:016x}", (uint64)titleId);
sGameInfo_ForegroundTitle = CafeTitleList::GetGameInfo(titleId);
if (!sGameInfo_ForegroundTitle.IsValid())
{
cemuLog_log(LogType::Force, "Mounting failed: Game meta information is either missing, inaccessible or not valid (missing or invalid .xml files in code and meta folder)");
return STATUS_CODE::UNABLE_TO_MOUNT;
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT;
}
// check base
TitleInfo& titleBase = sGameInfo_ForegroundTitle.GetBase();
if (!titleBase.IsValid())
return STATUS_CODE::UNABLE_TO_MOUNT;
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT;
if(!titleBase.ParseXmlInfo())
return STATUS_CODE::UNABLE_TO_MOUNT;
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT;
cemuLog_log(LogType::Force, "Base: {}", titleBase.GetPrintPath());
// mount base
if (!titleBase.Mount("/vol/content", "content", FSC_PRIORITY_BASE) || !titleBase.Mount(GetInternalVirtualCodeFolder(), "code", FSC_PRIORITY_BASE))
{
cemuLog_log(LogType::Force, "Mounting failed");
return STATUS_CODE::UNABLE_TO_MOUNT;
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT;
}
// check update
TitleInfo& titleUpdate = sGameInfo_ForegroundTitle.GetUpdate();
if (titleUpdate.IsValid())
{
if (!titleUpdate.ParseXmlInfo())
return STATUS_CODE::UNABLE_TO_MOUNT;
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT;
cemuLog_log(LogType::Force, "Update: {}", titleUpdate.GetPrintPath());
// mount update
if (!titleUpdate.Mount("/vol/content", "content", FSC_PRIORITY_PATCH) || !titleUpdate.Mount(GetInternalVirtualCodeFolder(), "code", FSC_PRIORITY_PATCH))
{
cemuLog_log(LogType::Force, "Mounting failed");
return STATUS_CODE::UNABLE_TO_MOUNT;
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT;
}
}
else
Expand All @@ -682,20 +682,20 @@ namespace CafeSystem
// todo - support for multi-title AOC
TitleInfo& titleAOC = aocList[0];
if (!titleAOC.ParseXmlInfo())
return STATUS_CODE::UNABLE_TO_MOUNT;
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT;
cemu_assert_debug(titleAOC.IsValid());
cemuLog_log(LogType::Force, "DLC: {}", titleAOC.GetPrintPath());
// mount AOC
if (!titleAOC.Mount(fmt::format("/vol/aoc{:016x}", titleAOC.GetAppTitleId()), "content", FSC_PRIORITY_PATCH))
{
cemuLog_log(LogType::Force, "Mounting failed");
return STATUS_CODE::UNABLE_TO_MOUNT;
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT;
}
}
else
cemuLog_log(LogType::Force, "DLC: Not present");
sForegroundTitleId = titleId;
return STATUS_CODE::SUCCESS;
return PREPARE_STATUS_CODE::SUCCESS;
}

void UnmountForegroundTitle()
Expand Down Expand Up @@ -723,7 +723,7 @@ namespace CafeSystem
}
}

STATUS_CODE SetupExecutable()
PREPARE_STATUS_CODE SetupExecutable()
{
// set rpx path from cos.xml if available
_pathToBaseExecutable = _pathToExecutable;
Expand Down Expand Up @@ -755,7 +755,7 @@ namespace CafeSystem
}
}
LoadMainExecutable();
return STATUS_CODE::SUCCESS;
return PREPARE_STATUS_CODE::SUCCESS;
}

void SetupMemorySpace()
Expand All @@ -769,7 +769,7 @@ namespace CafeSystem
memory_unmapForCurrentTitle();
}

STATUS_CODE PrepareForegroundTitle(TitleId titleId)
PREPARE_STATUS_CODE PrepareForegroundTitle(TitleId titleId)
{
CafeTitleList::WaitForMandatoryScan();
sLaunchModeIsStandalone = false;
Expand All @@ -780,21 +780,21 @@ namespace CafeSystem
// mount mlc storage
MountBaseDirectories();
// mount title folders
STATUS_CODE r = LoadAndMountForegroundTitle(titleId);
if (r != STATUS_CODE::SUCCESS)
PREPARE_STATUS_CODE r = LoadAndMountForegroundTitle(titleId);
if (r != PREPARE_STATUS_CODE::SUCCESS)
return r;
gameProfile_load();
// setup memory space and PPC recompiler
SetupMemorySpace();
PPCRecompiler_init();
r = SetupExecutable(); // load RPX
if (r != STATUS_CODE::SUCCESS)
if (r != PREPARE_STATUS_CODE::SUCCESS)
return r;
InitVirtualMlcStorage();
return STATUS_CODE::SUCCESS;
return PREPARE_STATUS_CODE::SUCCESS;
}

STATUS_CODE PrepareForegroundTitleFromStandaloneRPX(const fs::path& path)
PREPARE_STATUS_CODE PrepareForegroundTitleFromStandaloneRPX(const fs::path& path)
{
sLaunchModeIsStandalone = true;
cemuLog_log(LogType::Force, "Launching executable in standalone mode due to incorrect layout or missing meta files");
Expand All @@ -812,7 +812,7 @@ namespace CafeSystem
if (!r)
{
cemuLog_log(LogType::Force, "Failed to mount {}", _pathToUtf8(contentPath));
return STATUS_CODE::UNABLE_TO_MOUNT;
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT;
}
}
}
Expand All @@ -824,7 +824,7 @@ namespace CafeSystem
// since a lot of systems (including save folder location) rely on a TitleId, we derive a placeholder id from the executable hash
auto execData = fsc_extractFile(_pathToExecutable.c_str());
if (!execData)
return STATUS_CODE::INVALID_RPX;
return PREPARE_STATUS_CODE::INVALID_RPX;
uint32 h = generateHashFromRawRPXData(execData->data(), execData->size());
sForegroundTitleId = 0xFFFFFFFF00000000ULL | (uint64)h;
cemuLog_log(LogType::Force, "Generated placeholder TitleId: {:016x}", sForegroundTitleId);
Expand All @@ -834,7 +834,7 @@ namespace CafeSystem
// load executable
SetupExecutable();
InitVirtualMlcStorage();
return STATUS_CODE::SUCCESS;
return PREPARE_STATUS_CODE::SUCCESS;
}

void _LaunchTitleThread()
Expand Down
7 changes: 3 additions & 4 deletions src/Cafe/CafeSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,19 @@ namespace CafeSystem
virtual void CafeRecreateCanvas() = 0;
};

enum class STATUS_CODE
enum class PREPARE_STATUS_CODE
{
SUCCESS,
INVALID_RPX,
UNABLE_TO_MOUNT, // failed to mount through TitleInfo (most likely caused by an invalid or outdated path)
//BAD_META_DATA, - the title list only stores titles with valid meta, so this error code is impossible
};

void Initialize();
void SetImplementation(SystemImplementation* impl);
void Shutdown();

STATUS_CODE PrepareForegroundTitle(TitleId titleId);
STATUS_CODE PrepareForegroundTitleFromStandaloneRPX(const fs::path& path);
PREPARE_STATUS_CODE PrepareForegroundTitle(TitleId titleId);
PREPARE_STATUS_CODE PrepareForegroundTitleFromStandaloneRPX(const fs::path& path);
void LaunchForegroundTitle();
bool IsTitleRunning();

Expand Down
7 changes: 6 additions & 1 deletion src/Cafe/OS/libs/coreinit/coreinit_Time.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ namespace coreinit

inline TimerTicks ConvertNsToTimerTicks(uint64 ns)
{
return ((GetTimerClock() / 31250LL) * ((ns)) / 32000LL);
return ((GetTimerClock() / 31250LL) * ((TimerTicks)ns) / 32000LL);
}

inline TimerTicks ConvertMsToTimerTicks(uint64 ms)
{
return (TimerTicks)ms * GetTimerClock() / 1000LL;
}
};

Expand Down
Loading

0 comments on commit 641ef0f

Please sign in to comment.