cdvd: Fix end-of-disc issues (#3051)

* cdvd: Fix off-by-one end of file checks

* cdvd: Fix loading for games that attempt to read non-existent sectors

Some games will hang when attempting to read non-existent sectors.
Just do nothing when it occurs instead of erroring out.

* cdvdgigaherz: Fix loading for games that attempt to read non-existent sectors

Some games will hang when attempting to read non-existent sectors.
Just do nothing when it occurs instead of erroring out.

* cdvd: Don't write non-existent sectors to blockdump
This commit is contained in:
Jonathan Li 2019-08-25 15:09:28 +01:00 committed by Robert Neumann
parent 014753894a
commit 92aa43fe91
8 changed files with 41 additions and 32 deletions

View File

@ -56,7 +56,7 @@ static int diskTypeCached = -1;
// used to bridge the gap between the old getBuffer api and the new getBuffer2 api.
int lastReadSize;
int lastLSN; // needed for block dumping
u32 lastLSN; // needed for block dumping
// Records last read block length for block dumping
//static int plsn = 0;
@ -490,6 +490,12 @@ s32 DoCDVDgetBuffer(u8* buffer)
if (ret == 0 && blockDumpFile.IsOpened())
{
cdvdTD td;
CDVD->getTD(0, &td);
if (lastLSN >= td.lsn)
return 0;
if (blockDumpFile.GetBlockSize() == CD_FRAMESIZE_RAW && lastReadSize != 2352)
{
u8 blockDumpBuffer[CD_FRAMESIZE_RAW];

View File

@ -315,7 +315,7 @@ s32 CALLBACK ISOreadSector(u8* tempbuffer, u32 lsn, int mode)
int _lsn = lsn;
if (_lsn < 0) lsn = iso.GetBlockCount() + _lsn;
if (lsn > iso.GetBlockCount()) return -1;
if (lsn >= iso.GetBlockCount()) return -1;
if(mode == CDVD_MODE_2352)
{
@ -362,7 +362,6 @@ s32 CALLBACK ISOreadTrack(u32 lsn, int mode)
int _lsn = lsn;
if (_lsn < 0) lsn = iso.GetBlockCount() + _lsn;
if (lsn > iso.GetBlockCount()) return -1;
iso.BeginRead2(lsn);

View File

@ -35,10 +35,10 @@ static const char* nameFromType(int type)
int InputIsoFile::ReadSync(u8* dst, uint lsn)
{
if (lsn > m_blocks)
if (lsn >= m_blocks)
{
FastFormatUnicode msg;
msg.Write("isoFile error: Block index is past the end of file! (%u > %u).", lsn, m_blocks);
msg.Write("isoFile error: Block index is past the end of file! (%u >= %u).", lsn, m_blocks);
pxAssertDev(false, msg);
Console.Error(msg.c_str());
@ -50,24 +50,16 @@ int InputIsoFile::ReadSync(u8* dst, uint lsn)
void InputIsoFile::BeginRead2(uint lsn)
{
if (lsn > m_blocks)
m_current_lsn = lsn;
if (lsn >= m_blocks)
{
FastFormatUnicode msg;
msg.Write("isoFile error: Block index is past the end of file! (%u > %u).", lsn, m_blocks);
pxAssertDev(false, msg);
Console.Error(msg.c_str());
// [TODO] : Throw exception?
// Typically an error like this is bad; indicating an invalid dump or corrupted
// iso file.
m_current_lsn = -1;
// While this usually indicates that the ISO is corrupted, some games do attempt
// to read past the end of the disc, so don't error here.
DevCon.Warning("isoFile error: Block index is past the end of file! (%u >= %u).", lsn, m_blocks);
return;
}
m_current_lsn = lsn;
if(lsn >= m_read_lsn && lsn < (m_read_lsn+m_read_count))
{
// Already buffered
@ -90,13 +82,17 @@ void InputIsoFile::BeginRead2(uint lsn)
int InputIsoFile::FinishRead3(u8* dst, uint mode)
{
// Do nothing for out of bounds disc sector reads. It prevents some games
// from hanging (All-Star Baseball 2005, Hello Kitty: Roller Rescue,
// Hot Wheels: Beat That! (NTSC), Ratchet & Clank 3 (PAL),
// Test Drive: Eve of Destruction, etc.).
if (m_current_lsn >= m_blocks)
return 0;
int _offset = 0;
int length = 0;
int ret = 0;
if(m_current_lsn < 0)
return -1;
if(m_read_inprogress)
{
ret = m_reader->FinishRead();

View File

@ -48,7 +48,7 @@ protected:
wxString m_filename;
AsyncFileReader* m_reader;
s32 m_current_lsn;
u32 m_current_lsn;
isoType m_type;
u32 m_flags;

View File

@ -452,7 +452,8 @@ static const LegacyApi_OptMethod s_MethMessOpt_PAD[] =
// ----------------------------------------------------------------------------
void CALLBACK CDVD_newDiskCB(void (*callback)()) {}
extern int lastReadSize, lastLSN;
extern int lastReadSize;
extern u32 lastLSN;
static s32 CALLBACK CDVD_getBuffer2(u8* buffer)
{
// TEMP: until I fix all the plugins to use this function style

View File

@ -40,7 +40,7 @@ track tracks[100];
int curDiskType;
int curTrayStatus;
int csector;
static u32 csector;
int cmode;
///////////////////////////////////////////////////////////////////////////////
@ -252,7 +252,9 @@ EXPORT s32 CALLBACK CDVDreadTrack(u32 lsn, int mode)
return ret;
}
return lsn < src->GetSectorCount() ? cdvdRequestSector(lsn, mode) : -1;
cdvdRequestSector(lsn, mode);
return 0;
}
// return can be NULL (for async modes)
@ -269,6 +271,13 @@ EXPORT u8 *CALLBACK CDVDgetBuffer()
// return can be NULL (for async modes)
EXPORT int CALLBACK CDVDgetBuffer2(u8 *dest)
{
// Do nothing for out of bounds disc sector reads. It prevents some games
// from hanging (All-Star Baseball 2005, Hello Kitty: Roller Rescue,
// Hot Wheels: Beat That! (NTSC), Ratchet & Clank 3 (PAL),
// Test Drive: Eve of Destruction, etc.).
if (csector >= src->GetSectorCount())
return 0;
int csize = 2352;
switch (cmode) {
case CDVD_MODE_2048:

View File

@ -113,7 +113,7 @@ extern void (*newDiscCB)();
bool cdvdStartThread();
void cdvdStopThread();
s32 cdvdRequestSector(u32 sector, s32 mode);
void cdvdRequestSector(u32 sector, s32 mode);
u8 *cdvdGetSector(u32 sector, s32 mode);
s32 cdvdDirectReadSector(u32 sector, s32 mode, u8 *buffer);
s32 cdvdGetMediaType();

View File

@ -257,16 +257,16 @@ void cdvdStopThread()
s_thread.join();
}
s32 cdvdRequestSector(u32 sector, s32 mode)
void cdvdRequestSector(u32 sector, s32 mode)
{
if (sector >= src->GetSectorCount())
return -1;
return;
// Align to cache block
sector &= ~(sectors_per_read - 1);
if (cdvdCacheCheck(sector))
return 0;
return;
{
std::lock_guard<std::mutex> guard(s_request_lock);
@ -274,8 +274,6 @@ s32 cdvdRequestSector(u32 sector, s32 mode)
}
s_notify_cv.notify_one();
return 0;
}
u8 *cdvdGetSector(u32 sector, s32 mode)