Skip to content

Commit

Permalink
Merge pull request #11424 from unknownbrackets/disc-error
Browse files Browse the repository at this point in the history
Core: Report disc read errors to the user
  • Loading branch information
hrydgard committed Sep 29, 2018
2 parents 2e8e28f + ce6cb7e commit bb5b981
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 17 deletions.
53 changes: 36 additions & 17 deletions Core/FileSystems/BlockDevices.cpp
Expand Up @@ -15,14 +15,15 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.


#include <cstdio>
#include <cstring>
#include <algorithm>
#include "i18n/i18n.h"
#include "Common/FileUtil.h"
#include "Common/Swap.h"
#include "Core/Loaders.h"
#include "Core/Host.h"
#include "Core/FileSystems/BlockDevices.h"
#include <cstdio>
#include <cstring>
#include <algorithm>

extern "C"
{
Expand Down Expand Up @@ -62,6 +63,13 @@ u32 BlockDevice::CalculateCRC() {
return crc;
}

void BlockDevice::NotifyReadError() {
I18NCategory *err = GetI18NCategory("Error");
if (!reportedError_) {
host->NotifyUserMessage(err->T("Game disc read error - ISO corrupt"), 6.0f);
reportedError_ = true;
}
}

FileBlockDevice::FileBlockDevice(FileLoader *fileLoader)
: fileLoader_(fileLoader) {
Expand Down Expand Up @@ -169,24 +177,33 @@ CISOFileBlockDevice::CISOFileBlockDevice(FileLoader *fileLoader)

#if COMMON_LITTLE_ENDIAN
index = new u32[indexSize];
if (fileLoader->ReadAt(sizeof(hdr), sizeof(u32), indexSize, index) != indexSize)
if (fileLoader->ReadAt(sizeof(hdr), sizeof(u32), indexSize, index) != indexSize) {
NotifyReadError();
memset(index, 0, indexSize * sizeof(u32));
}
#else
index = new u32[indexSize];
u32_le *indexTemp = new u32_le[indexSize];

if (fileLoader->ReadAt(sizeof(hdr), sizeof(u32), indexSize, indexTemp) != indexSize)
{
if (fileLoader->ReadAt(sizeof(hdr), sizeof(u32), indexSize, indexTemp) != indexSize) {
NotifyReadError();
memset(indexTemp, 0, indexSize * sizeof(u32_le));
}

for (u32 i = 0; i < indexSize; i++)
{
index[i] = indexTemp[i];
}

delete[] indexTemp;
#endif

// Double check that the CSO is not truncated. In most cases, this will be the exact size.
u64 fileSize = fileLoader->FileSize();
u64 lastIndexPos = index[indexSize - 1] & 0x7FFFFFFF;
u64 expectedFileSize = lastIndexPos << indexShift;
if (expectedFileSize > fileSize) {
ERROR_LOG(LOADER, "Expected CSO to at least be %lld bytes, but file is %lld bytes", expectedFileSize, fileSize);
NotifyReadError();
}
}

CISOFileBlockDevice::~CISOFileBlockDevice()
Expand Down Expand Up @@ -235,9 +252,9 @@ bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr, bool uncached)
z.zalloc = Z_NULL;
z.zfree = Z_NULL;
z.opaque = Z_NULL;
if(inflateInit2(&z, -15) != Z_OK)
{
if (inflateInit2(&z, -15) != Z_OK) {
ERROR_LOG(LOADER, "GetBlockSize() ERROR: %s\n", (z.msg) ? z.msg : "?");
NotifyReadError();
return false;
}
z.avail_in = readSize;
Expand All @@ -246,24 +263,23 @@ bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr, bool uncached)
z.next_in = readBuffer;

int status = inflate(&z, Z_FINISH);
if (status != Z_STREAM_END)
{
if (status != Z_STREAM_END) {
ERROR_LOG(LOADER, "block %d: inflate : %s[%d]\n", blockNumber, (z.msg) ? z.msg : "error", status);
NotifyReadError();
inflateEnd(&z);
memset(outPtr, 0, GetBlockSize());
return false;
}
if (z.total_out != frameSize)
{
if (z.total_out != frameSize) {
ERROR_LOG(LOADER, "block %d: block size error %d != %d\n", blockNumber, (u32)z.total_out, frameSize);
NotifyReadError();
inflateEnd(&z);
memset(outPtr, 0, GetBlockSize());
return false;
}
inflateEnd(&z);

if (frameSize != (u32)GetBlockSize())
{
if (frameSize != (u32)GetBlockSize()) {
zlibBufferFrame = frameNumber;
memcpy(outPtr, zlibBuffer + compressedOffset, GetBlockSize());
}
Expand Down Expand Up @@ -341,9 +357,11 @@ bool CISOFileBlockDevice::ReadBlocks(u32 minBlock, int count, u8 *outPtr) {
int status = inflate(&z, Z_FINISH);
if (status != Z_STREAM_END) {
ERROR_LOG(LOADER, "Inflate frame %d: failed - %s[%d]\n", frame, (z.msg) ? z.msg : "error", status);
NotifyReadError();
memset(outPtr, 0, frameBlocks * GetBlockSize());
} else if (z.total_out != frameSize) {
ERROR_LOG(LOADER, "Inflate frame %d: block size error %d != %d\n", frame, (u32)z.total_out, frameSize);
NotifyReadError();
memset(outPtr, 0, frameBlocks * GetBlockSize());
} else if (frameBlocks != blocksPerFrame) {
memcpy(outPtr, zlibBuffer + frameBlockOffset * GetBlockSize(), frameBlocks * GetBlockSize());
Expand Down Expand Up @@ -492,6 +510,7 @@ bool NPDRMDemoBlockDevice::ReadBlock(int blockNumber, u8 *outPtr, bool uncached)
lzsize = lzrc_decompress(blockBuf, 0x00100000, readBuf, table[block].size);
if(lzsize!=blockSize){
ERROR_LOG(LOADER, "LZRC decompress error! lzsize=%d\n", lzsize);
NotifyReadError();
return false;
}
}
Expand Down
4 changes: 4 additions & 0 deletions Core/FileSystems/BlockDevices.h
Expand Up @@ -47,6 +47,10 @@ class BlockDevice {
virtual u32 GetNumBlocks() = 0;

u32 CalculateCRC();
void NotifyReadError();

protected:
bool reportedError_ = false;
};

class CISOFileBlockDevice : public BlockDevice {
Expand Down
3 changes: 3 additions & 0 deletions Core/FileSystems/ISOFileSystem.cpp
Expand Up @@ -204,6 +204,7 @@ void ISOFileSystem::ReadDirectory(TreeEntry *root) {
for (u32 secnum = root->startsector, endsector = root->startsector + (root->dirsize + 2047) / 2048; secnum < endsector; ++secnum) {
u8 theSector[2048];
if (!blockDevice->ReadBlock(secnum, theSector)) {
blockDevice->NotifyReadError();
ERROR_LOG(FILESYS, "Error reading block for directory %s - skipping", root->name.c_str());
root->valid = true; // Prevents re-reading
return;
Expand All @@ -220,6 +221,7 @@ void ISOFileSystem::ReadDirectory(TreeEntry *root) {

const int IDENTIFIER_OFFSET = 33;
if (offset + IDENTIFIER_OFFSET + dir.identifierLength > 2048) {
blockDevice->NotifyReadError();
ERROR_LOG(FILESYS, "Directory entry crosses sectors, corrupt iso?");
return;
}
Expand Down Expand Up @@ -254,6 +256,7 @@ void ISOFileSystem::ReadDirectory(TreeEntry *root) {

if (entry->isDirectory && !relative) {
if (entry->startsector == root->startsector) {
blockDevice->NotifyReadError();
ERROR_LOG(FILESYS, "WARNING: Appear to have a recursive file system, breaking recursion. Probably corrupt ISO.");
}
}
Expand Down

0 comments on commit bb5b981

Please sign in to comment.