diff --git a/src/core/hle/service/ldr_ro.cpp b/src/core/hle/service/ldr_ro.cpp index 1c0dd88c6..7a8c03652 100644 --- a/src/core/hle/service/ldr_ro.cpp +++ b/src/core/hle/service/ldr_ro.cpp @@ -896,6 +896,42 @@ class CROHelper final { return RESULT_SUCCESS; } + /** + * Clears all external patches to zero. + * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. + */ + ResultCode ClearExternalPatches() { + u32 external_patch_num = GetField(ExternalPatchNum); + ExternalPatchEntry patch; + + bool batch_begin = true; + for (u32 i = 0; i < external_patch_num; ++i) { + GetEntry(i, patch); + VAddr patch_target = SegmentTagToAddress(patch.target_position); + + if (patch_target == 0) { + return CROFormatError(0x12); + } + + ResultCode result = ClearPatch(patch_target, patch.type); + if (result.IsError()) { + LOG_ERROR(Service_LDR, "Error clearing patch %08X", result.raw); + return result; + } + + if (batch_begin) { + // resets to unresolved state + patch.is_batch_resolved = 0; + SetEntry(i, patch); + } + + // if current is an end, then the next is a beginning + batch_begin = patch.is_batch_end != 0; + } + + return RESULT_SUCCESS; + } + /** * Applies all static anonymous symbol to the static module. * @param crs_address the virtual address of the static module @@ -1309,6 +1345,25 @@ public: UnrebaseHeader(); } + /** + * Clears all patches to zero. + * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. + */ + ResultCode ClearPatches() { + ResultCode result = ClearExternalPatches(); + if (result.IsError()) { + LOG_ERROR(Service_LDR, "Error clearing external patches %08X", result.raw); + return result; + } + + result = ClearInternalPatches(); + if (result.IsError()) { + LOG_ERROR(Service_LDR, "Error clearing internal patches %08X", result.raw); + return result; + } + return RESULT_SUCCESS; + } + void InitCRS() { SetNext(0); SetPrevious(0);