summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorTilka <tilkax@gmail.com>2020-01-14 17:51:21 +0000
committerGitHub <noreply@github.com>2020-01-14 17:51:21 +0000
commit31d7b56c19e44df568a979ffca43fd18fcd8e658 (patch)
treeccde50758ed4b208ea8e2a1c548395dd41947063 /Source
parenta2f2536a77253dbf64c5db60701fd801203f4a0a (diff)
parent21c152f51f91baec8e5187ead264db9e1c748da9 (diff)
Merge pull request #8561 from JosJuice/di-wii-oob-2
Fix Error #001 (alternative solution)
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/HW/DVD/DVDInterface.cpp20
-rw-r--r--Source/Core/Core/HW/DVD/DVDThread.cpp13
2 files changed, 22 insertions, 11 deletions
diff --git a/Source/Core/Core/HW/DVD/DVDInterface.cpp b/Source/Core/Core/HW/DVD/DVDInterface.cpp
index 5050cd906e..9ecb58dc03 100644
--- a/Source/Core/Core/HW/DVD/DVDInterface.cpp
+++ b/Source/Core/Core/HW/DVD/DVDInterface.cpp
@@ -748,6 +748,26 @@ bool ExecuteReadCommand(u64 dvd_offset, u32 output_address, u32 dvd_length, u32
dvd_length = output_length;
}
+ // Many Wii games intentionally try to read from an offset which is just past the end of a regular
+ // DVD but just before the end of a DVD-R, displaying "Error #001" and failing to boot if the read
+ // succeeds (see https://wiibrew.org/wiki//dev/di#0x8D_DVDLowUnencryptedRead for more details).
+ // It would be nice if we simply could rely on DiscIO for letting us know whether a read is out
+ // of bounds, but this unfortunately doesn't work when using a disc image format that doesn't
+ // store the original size of the disc, most notably WBFS. Instead, we have a little hack here:
+ // reject all non-partition reads that come from IOS that go past the offset 0x50000. IOS only
+ // allows non-partition reads if they are before 0x50000 or if they are in one of the two small
+ // areas 0x118240000-0x118240020 and 0x1FB4E0000-0x1FB4E0020 (both of which only are used for
+ // Error #001 checks), so the only thing we disallow with this hack that actually should be
+ // allowed is non-partition reads in the 0x118240000-0x118240020 area on dual-layer discs.
+ // In practice, dual-layer games don't attempt to do non-partition reads in that area.
+ if (reply_type == ReplyType::IOS && partition == DiscIO::PARTITION_NONE &&
+ dvd_offset + dvd_length > 0x50000)
+ {
+ SetHighError(DVDInterface::ERROR_BLOCK_OOB);
+ *interrupt_type = DIInterruptType::DEINT;
+ return false;
+ }
+
ScheduleReads(dvd_offset, dvd_length, partition, output_address, reply_type);
return true;
}
diff --git a/Source/Core/Core/HW/DVD/DVDThread.cpp b/Source/Core/Core/HW/DVD/DVDThread.cpp
index 5f28518a91..00279c5df4 100644
--- a/Source/Core/Core/HW/DVD/DVDThread.cpp
+++ b/Source/Core/Core/HW/DVD/DVDThread.cpp
@@ -345,17 +345,8 @@ static void FinishRead(u64 id, s64 cycles_late)
DVDInterface::DIInterruptType interrupt;
if (buffer.size() != request.length)
{
- if (request.dvd_offset != 0x118280000 && request.dvd_offset != 0x1FB500000)
- {
- PanicAlertT("The disc could not be read (at 0x%" PRIx64 " - 0x%" PRIx64 ").",
- request.dvd_offset, request.dvd_offset + request.length);
- }
- else
- {
- // Part of the error 001 check.
- INFO_LOG(DVDINTERFACE, "Ignoring out of bounds test read (at 0x%" PRIx64 " - 0x%" PRIx64 ")",
- request.dvd_offset, request.dvd_offset + request.length);
- }
+ PanicAlertT("The disc could not be read (at 0x%" PRIx64 " - 0x%" PRIx64 ").",
+ request.dvd_offset, request.dvd_offset + request.length);
DVDInterface::SetHighError(DVDInterface::ERROR_BLOCK_OOB);
interrupt = DVDInterface::DIInterruptType::DEINT;