More CDVD fixes. I *think* this revision might provide some noticeable speedups when running games directly from cd drives. Also built-in CDVD blockdumps work now (DVD images only, legacy CdRom games still don't blockdump right unless you use the cdvdiso plugin).

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1701 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-08-28 21:23:32 +00:00
parent 8393f828dd
commit b4b292d219
9 changed files with 130 additions and 99 deletions

View File

@ -629,8 +629,8 @@ typedef u8* (CALLBACK* _CDVDgetBuffer)();
// Copies loaded data to the target buffer. // Copies loaded data to the target buffer.
// Returns -2 if the asynchronous read is still pending. // Returns -2 if the asynchronous read is still pending.
// Returns -1 if the asyncronous read failed.
// Returns 0 on success. // Returns 0 on success.
// This function is not allowed to return -1 (reserved for use by readTrack)
typedef s32 (CALLBACK* _CDVDgetBuffer2)(u8* buffer); typedef s32 (CALLBACK* _CDVDgetBuffer2)(u8* buffer);
typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq);

View File

@ -714,36 +714,49 @@ __forceinline void cdvdReadInterrupt()
} }
else else
{ {
// Read Error -1 is only returned by readTrack, so handle it first here. if( cdvd.RErr == 0 )
// If readTrack failed it means we don't have any valid data to fetch.
if (cdvd.RErr == -1)
{ {
cdvd.RetryCntP++; while( (cdvd.RErr = DoCDVDgetBuffer(cdr.Transfer)), cdvd.RErr == -2 )
Console::Error("CDVD READ ERROR, sector=%d", params cdvd.Sector);
if (cdvd.RetryCntP <= cdvd.RetryCnt)
{ {
cdvd.RErr = DoCDVDreadTrack(cdvd.Sector, cdvd.ReadMode); // not finished yet ... block on the read until it finishes.
CDVDREAD_INT(cdvd.ReadTime); Threading::Sleep( 0 );
return; Threading::SpinWait();
} }
} }
cdvd.RErr = DoCDVDgetBuffer(cdr.Transfer); if (cdvd.RErr == -1)
if(cdvd.RErr == -2)
{ {
// not finished yet ... give it a bit more time cdvd.RetryCntP++;
CDVDREAD_INT(cdvd.ReadTime/4);
if (cdvd.RetryCntP <= cdvd.RetryCnt)
{
CDVD_LOG( "CDVD read err, retrying... (attempt %d of %d)", cdvd.RetryCntP, cdvd.RetryCnt );
cdvd.RErr = DoCDVDreadTrack(cdvd.Sector, cdvd.ReadMode);
CDVDREAD_INT(cdvd.ReadTime);
}
else
Console::Error("CDVD READ ERROR, sector = 0x%08x", params cdvd.Sector);
return; return;
} }
cdvd.Reading = false; cdvd.Reading = false;
// Any other value besides 0 should be considered invalid here (wtf is that wacky
// plugin trying to do?)
jASSUME( cdvd.RErr == 0 );
} }
if (cdvdReadSector() == -1) if (cdvdReadSector() == -1)
{ {
// This means that the BCR/DMA hasn't finished yet, and rather than fire off the
// sector-finished notice too early (which might overwrite game data) we delay a
// bit and try to read the sector again later.
// An arbitrary delay of some number of cycles probably makes more sense here,
// but for now it's based on the cdvd.ReadTime value. -- air
assert((int)cdvd.ReadTime > 0 ); assert((int)cdvd.ReadTime > 0 );
CDVDREAD_INT(cdvd.ReadTime); CDVDREAD_INT(cdvd.ReadTime/4);
return; return;
} }

View File

@ -44,6 +44,7 @@ static int diskTypeCached = -1;
// used to bridge the gap between the old getBuffer api and the new getBuffer2 api. // used to bridge the gap between the old getBuffer api and the new getBuffer2 api.
int lastReadSize; int lastReadSize;
int lastLSN; // needed for block dumping
// Records last read block length for block dumping // Records last read block length for block dumping
static int plsn = 0; static int plsn = 0;
@ -56,11 +57,9 @@ static void CheckNullCDVD()
DevAssert( CDVD != NULL, "Invalid CDVD object state (null pointer exception)" ); DevAssert( CDVD != NULL, "Invalid CDVD object state (null pointer exception)" );
} }
///////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
//
// Disk Type detection stuff (from cdvdGigaherz) // Disk Type detection stuff (from cdvdGigaherz)
// //
int CheckDiskTypeFS(int baseType) int CheckDiskTypeFS(int baseType)
{ {
int f; int f;
@ -118,7 +117,7 @@ static int FindDiskType(int mType)
} }
else if (mType < 0) else if (mType < 0)
{ {
static u8 bleh[2352]; static u8 bleh[CD_FRAMESIZE_RAW];
cdvdTD td; cdvdTD td;
CDVD->getTD(0,&td); CDVD->getTD(0,&td);
@ -322,26 +321,25 @@ s32 DoCDVDopen(const char* pTitleFilename)
cdvdTD td; cdvdTD td;
CDVD->getTD(0, &td); CDVD->getTD(0, &td);
int blockofs = 0, blocksize = 0, blocks = td.lsn; blockDumpFile = isoCreate(Path::Combine( Path::GetWorkingDirectory(), fname ).c_str(), ISOFLAGS_BLOCKDUMP_V3);
if (blockDumpFile)
switch(cdtype)
{ {
case CDVD_TYPE_PS2DVD: int blockofs = 0, blocksize = CD_FRAMESIZE_RAW, blocks = td.lsn;
case CDVD_TYPE_DVDV:
case CDVD_TYPE_DETCTDVDS:
case CDVD_TYPE_DETCTDVDD:
blockofs = 24;
blocksize = 2048;
break;
default:
blockofs = 0;
blocksize= 2352;
break;
}
blockDumpFile = isoCreate(fname.c_str(), ISOFLAGS_BLOCKDUMP); // hack: Because of limitations of the current cdvd design, we can't query the blocksize
if (blockDumpFile) isoSetFormat(blockDumpFile, blockofs, blocksize, blocks); // of the underlying media. So lets make a best guess:
switch(cdtype)
{
case CDVD_TYPE_PS2DVD:
case CDVD_TYPE_DVDV:
case CDVD_TYPE_DETCTDVDS:
case CDVD_TYPE_DETCTDVDD:
blocksize = 2048;
break;
}
isoSetFormat(blockDumpFile, blockofs, blocksize, blocks);
}
} }
else else
{ {
@ -396,7 +394,7 @@ s32 DoCDVDreadTrack(u32 lsn, int mode)
} }
//DevCon::Notice("CDVD readTrack(lsn=%d,mode=%d)",params lsn, lastReadSize); //DevCon::Notice("CDVD readTrack(lsn=%d,mode=%d)",params lsn, lastReadSize);
lastLSN = lsn;
return CDVD->readTrack(lsn,mode); return CDVD->readTrack(lsn,mode);
} }
@ -407,7 +405,7 @@ s32 DoCDVDgetBuffer(u8* buffer)
if (ret == 0 && blockDumpFile != NULL) if (ret == 0 && blockDumpFile != NULL)
{ {
isoWriteBlock(blockDumpFile, buffer, lastReadSize); isoWriteBlock(blockDumpFile, buffer, lastLSN);
} }
return ret; return ret;

View File

@ -295,9 +295,10 @@ s32 CALLBACK ISOreadSector(u8* tempbuffer, u32 lsn, int mode)
return 0; return 0;
} }
isoReadBlock(iso, cdbuffer + iso->blockofs, lsn); isoReadBlock(iso, cdbuffer, lsn);
pbuffer = cdbuffer; pbuffer = cdbuffer;
switch (mode) switch (mode)
{ {
case CDVD_MODE_2352: case CDVD_MODE_2352:
@ -317,6 +318,11 @@ s32 CALLBACK ISOreadSector(u8* tempbuffer, u32 lsn, int mode)
break; break;
} }
// version 3 blockdumps have no pbuffer header, so lets reset back to the
// original pointer. :)
if( iso->flags & ISOFLAGS_BLOCKDUMP_V3 )
pbuffer = cdbuffer;
memcpy_fast(tempbuffer,pbuffer,psize); memcpy_fast(tempbuffer,pbuffer,psize);
return 0; return 0;
@ -329,9 +335,9 @@ s32 CALLBACK ISOreadTrack(u32 lsn, int mode)
if (_lsn < 0) lsn = iso->blocks + _lsn; if (_lsn < 0) lsn = iso->blocks + _lsn;
if (lsn > iso->blocks) return -1; if (lsn > iso->blocks) return -1;
isoReadBlock(iso, cdbuffer + iso->blockofs, lsn); isoReadBlock(iso, cdbuffer, lsn);
pbuffer = cdbuffer; pbuffer = cdbuffer;
switch (mode) switch (mode)
{ {
case CDVD_MODE_2352: case CDVD_MODE_2352:
@ -351,6 +357,11 @@ s32 CALLBACK ISOreadTrack(u32 lsn, int mode)
break; break;
} }
// version 3 blockdumps have no pbuffer header, so lets reset back to the
// original pointer. :)
if( iso->flags & ISOFLAGS_BLOCKDUMP_V3 )
pbuffer = cdbuffer;
return 0; return 0;
} }

View File

@ -497,28 +497,27 @@ void cdrReadInterrupt() {
cdr.StatP|= 0x22; cdr.StatP|= 0x22;
cdr.Result[0] = cdr.StatP; cdr.Result[0] = cdr.StatP;
// Read Error -1 is only returned by readTrack, so handle it first here. if( cdr.RErr == 0 )
// If readTrack failed it means we don't have any valid data to fetch. {
while( (cdr.RErr = DoCDVDgetBuffer(cdr.Transfer)), cdr.RErr == -2 )
{
// not finished yet ... block on the read until it finishes.
Threading::Sleep( 0 );
Threading::SpinWait();
}
}
if (cdr.RErr == -1) if (cdr.RErr == -1)
{ {
CDR_LOG(" err\n"); CDR_LOG(" err\n");
memzero_obj(cdr.Transfer); memzero_obj(cdr.Transfer);
cdr.Stat = DiskError; cdr.Stat = DiskError;
cdr.Result[0]|= 0x01; cdr.Result[0] |= 0x01;
ReadTrack(); ReadTrack();
CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime);
return; return;
} }
cdr.RErr = DoCDVDgetBuffer(cdr.Transfer);
if(cdr.RErr == -2)
{
// async mode is not finished yet ... give it a bit more time
CDREAD_INT(cdReadTime / 4);
return;
}
cdr.Stat = DataReady; cdr.Stat = DataReady;
CDR_LOG(" %x:%x:%x", cdr.Transfer[0], cdr.Transfer[1], cdr.Transfer[2]); CDR_LOG(" %x:%x:%x", cdr.Transfer[0], cdr.Transfer[1], cdr.Transfer[2]);

View File

@ -29,12 +29,12 @@
int detect(isoFile *iso) int detect(isoFile *iso)
{ {
u8 buf[2448]; u8 buf[2448];
struct cdVolDesc *volDesc; cdVolDesc *volDesc;
if (isoReadBlock(iso, buf + iso->blockofs, 16) == -1) return -1; if (isoReadBlock(iso, buf, 16) == -1) return -1;
volDesc = (struct cdVolDesc *)(buf + 24);
volDesc = (cdVolDesc *) (( iso->flags & ISOFLAGS_BLOCKDUMP_V3 ) ? buf : (buf + 24));
if (strncmp((char*)volDesc->volID, "CD001", 5)) return 0; if (strncmp((char*)volDesc->volID, "CD001", 5)) return 0;
if (volDesc->rootToc.tocSize == 2048) if (volDesc->rootToc.tocSize == 2048)
@ -87,7 +87,16 @@ int isoDetect(isoFile *iso) // based on florin's CDVDbin detection code :)
if (strncmp(buf, "BDV2", 4) == 0) if (strncmp(buf, "BDV2", 4) == 0)
{ {
iso->flags = ISOFLAGS_BLOCKDUMP; iso->flags = ISOFLAGS_BLOCKDUMP_V2;
_readfile(iso->handle, &iso->blocksize, 4);
_readfile(iso->handle, &iso->blocks, 4);
_readfile(iso->handle, &iso->blockofs, 4);
_isoReadDtable(iso);
return (detect(iso) == 1) ? 0 : -1;
}
else if (strncmp(buf, "BDV3", 4) == 0)
{
iso->flags = ISOFLAGS_BLOCKDUMP_V3;
_readfile(iso->handle, &iso->blocksize, 4); _readfile(iso->handle, &iso->blocksize, 4);
_readfile(iso->handle, &iso->blocks, 4); _readfile(iso->handle, &iso->blocks, 4);
_readfile(iso->handle, &iso->blockofs, 4); _readfile(iso->handle, &iso->blockofs, 4);
@ -111,7 +120,7 @@ int isoDetect(isoFile *iso) // based on florin's CDVDbin detection code :)
if (tryIsoType(iso, 2448, -8, 0)) return 0; // RAWQ 2448 if (tryIsoType(iso, 2448, -8, 0)) return 0; // RAWQ 2448
iso->offset = 0; iso->offset = 0;
iso->blocksize = 2352; iso->blocksize = CD_FRAMESIZE_RAW;
iso->blockofs = 0; iso->blockofs = 0;
iso->type = ISOTYPE_AUDIO; iso->type = ISOTYPE_AUDIO;
return 0; return 0;
@ -232,13 +241,19 @@ int isoSetFormat(isoFile *iso, int blockofs, int blocksize, int blocks)
Console::WriteLn("blocksize = %d", params iso->blocksize); Console::WriteLn("blocksize = %d", params iso->blocksize);
Console::WriteLn("blocks = %d", params iso->blocks); Console::WriteLn("blocks = %d", params iso->blocks);
if (iso->flags & ISOFLAGS_BLOCKDUMP) if (iso->flags & ISOFLAGS_BLOCKDUMP_V2)
{ {
if (_writefile(iso->handle, "BDV2", 4) < 4) return -1; if (_writefile(iso->handle, "BDV2", 4) < 4) return -1;
if (_writefile(iso->handle, &blocksize, 4) < 4) return -1; if (_writefile(iso->handle, &blocksize, 4) < 4) return -1;
if (_writefile(iso->handle, &blocks, 4) < 4) return -1; if (_writefile(iso->handle, &blocks, 4) < 4) return -1;
if (_writefile(iso->handle, &blockofs, 4) < 4) return -1; if (_writefile(iso->handle, &blockofs, 4) < 4) return -1;
} }
else if (iso->flags & ISOFLAGS_BLOCKDUMP_V3)
{
if (_writefile(iso->handle, "BDV3", 4) < 4) return -1;
if (_writefile(iso->handle, &blocksize, 4) < 4) return -1;
if (_writefile(iso->handle, &blocks, 4) < 4) return -1;
}
return 0; return 0;
} }
@ -275,7 +290,7 @@ int _isoReadBlock(isoFile *iso, u8 *dst, int lsn)
memset(dst, 0, iso->blockofs); memset(dst, 0, iso->blockofs);
_seekfile(iso->handle, ofs, SEEK_SET); _seekfile(iso->handle, ofs, SEEK_SET);
ret = _readfile(iso->handle, dst, iso->blocksize); ret = _readfile(iso->handle, dst + iso->blockofs, iso->blocksize);
if (ret < iso->blocksize) if (ret < iso->blocksize)
{ {
@ -293,13 +308,13 @@ int _isoReadBlockD(isoFile *iso, u8 *dst, int lsn)
// Console::WriteLn("_isoReadBlockD %d, blocksize=%d, blockofs=%d\n", params lsn, iso->blocksize, iso->blockofs); // Console::WriteLn("_isoReadBlockD %d, blocksize=%d, blockofs=%d\n", params lsn, iso->blocksize, iso->blockofs);
memset(dst, 0, iso->blockofs); memset(dst, 0, iso->blockofs);
for (int i = 0; i < iso->dtablesize;i++) for (int i = 0; i < iso->dtablesize; i++)
{ {
if (iso->dtable[i] != lsn) continue; if (iso->dtable[i] != lsn) continue;
_seekfile(iso->handle, 16 + i * (iso->blocksize + 4) + 4, SEEK_SET); _seekfile(iso->handle, 16 + i * (iso->blocksize + 4) + 4, SEEK_SET);
ret = _readfile(iso->handle, dst, iso->blocksize); ret = _readfile(iso->handle, dst + iso->blockofs, iso->blocksize);
if (ret < iso->blocksize) return -1; if (ret < iso->blocksize) return -1;
return 0; return 0;
@ -330,7 +345,7 @@ int _isoReadBlockM(isoFile *iso, u8 *dst, int lsn)
memset(dst, 0, iso->blockofs); memset(dst, 0, iso->blockofs);
_seekfile(iso->multih[i].handle, ofs, SEEK_SET); _seekfile(iso->multih[i].handle, ofs, SEEK_SET);
ret = _readfile(iso->multih[i].handle, dst, iso->blocksize); ret = _readfile(iso->multih[i].handle, dst + iso->blockofs, iso->blocksize);
if (ret < iso->blocksize) if (ret < iso->blocksize)
{ {
@ -351,7 +366,9 @@ int isoReadBlock(isoFile *iso, u8 *dst, int lsn)
return -1; return -1;
} }
if (iso->flags & ISOFLAGS_BLOCKDUMP) if (iso->flags & ISOFLAGS_BLOCKDUMP_V2)
ret = _isoReadBlockD(iso, dst, lsn);
else if( iso->flags & ISOFLAGS_BLOCKDUMP_V3 )
ret = _isoReadBlockD(iso, dst, lsn); ret = _isoReadBlockD(iso, dst, lsn);
else if (iso->flags & ISOFLAGS_MULTI) else if (iso->flags & ISOFLAGS_MULTI)
ret = _isoReadBlockM(iso, dst, lsn); ret = _isoReadBlockM(iso, dst, lsn);
@ -362,13 +379,8 @@ int isoReadBlock(isoFile *iso, u8 *dst, int lsn)
if (iso->type == ISOTYPE_CD) if (iso->type == ISOTYPE_CD)
{ {
// This is weird voodoo mess that does some kind of time adjustment on the LSNtoMSF(dst + 12, lsn);
// block headers of CD-Rom images. hackfixed it to work with 24 byte block dst[15] = 2;
// offsets... no idea if it'll work with others.
DevAssert( iso->blockofs == 24, "Undocumented CD-Rom checkpoint." );
LSNtoMSF(dst - iso->blockofs + 12, lsn);
dst[15-iso->blockofs] = 2;
} }
return 0; return 0;
@ -381,7 +393,7 @@ int _isoWriteBlock(isoFile *iso, u8 *src, int lsn)
u64 ofs = (u64)lsn * iso->blocksize + iso->offset; u64 ofs = (u64)lsn * iso->blocksize + iso->offset;
_seekfile(iso->handle, ofs, SEEK_SET); _seekfile(iso->handle, ofs, SEEK_SET);
ret = _writefile(iso->handle, src, iso->blocksize); ret = _writefile(iso->handle, src + iso->blockofs, iso->blocksize);
if (ret < iso->blocksize) return -1; if (ret < iso->blocksize) return -1;
return 0; return 0;
@ -395,7 +407,7 @@ int _isoWriteBlockD(isoFile *iso, u8 *src, int lsn)
ret = _writefile(iso->handle, &lsn, 4); ret = _writefile(iso->handle, &lsn, 4);
if (ret < 4) return -1; if (ret < 4) return -1;
ret = _writefile(iso->handle, src, iso->blocksize); ret = _writefile(iso->handle, src + iso->blockofs, iso->blocksize);
// Console::WriteLn("_isoWriteBlock %d", params ret); // Console::WriteLn("_isoWriteBlock %d", params ret);
@ -406,15 +418,10 @@ int _isoWriteBlockD(isoFile *iso, u8 *src, int lsn)
int isoWriteBlock(isoFile *iso, u8 *src, int lsn) int isoWriteBlock(isoFile *iso, u8 *src, int lsn)
{ {
int ret; if (iso->flags & ISOFLAGS_BLOCKDUMP_V3)
return _isoWriteBlockD(iso, src, lsn);
if (iso->flags & ISOFLAGS_BLOCKDUMP)
ret = _isoWriteBlockD(iso, src, lsn);
else else
ret = _isoWriteBlock(iso, src, lsn); return _isoWriteBlock(iso, src, lsn);
if (ret == -1) return -1;
return 0;
} }
void isoClose(isoFile *iso) void isoClose(isoFile *iso)

View File

@ -35,13 +35,14 @@ enum isoFlags
{ {
ISOFLAGS_Z = 0x0001, ISOFLAGS_Z = 0x0001,
ISOFLAGS_Z2 = 0x0002, ISOFLAGS_Z2 = 0x0002,
ISOFLAGS_BLOCKDUMP = 0x0004, ISOFLAGS_BLOCKDUMP_V2 = 0x0004,
ISOFLAGS_MULTI = 0x0008, ISOFLAGS_MULTI = 0x0008,
ISOFLAGS_BZ2 = 0x0010 ISOFLAGS_BZ2 = 0x0010,
ISOFLAGS_BLOCKDUMP_V3 = 0x0020
}; };
#define CD_FRAMESIZE_RAW 2352 static const int CD_FRAMESIZE_RAW = 2352;
#define DATA_SIZE (CD_FRAMESIZE_RAW-12) static const int CD_DATA_SIZE = CD_FRAMESIZE_RAW - 12;
//#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ //#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */
//#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ //#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */
@ -73,12 +74,12 @@ struct isoFile
}; };
isoFile *isoOpen(const char *filename); extern isoFile *isoOpen(const char *filename);
isoFile *isoCreate(const char *filename, int mode); extern isoFile *isoCreate(const char *filename, int mode);
int isoSetFormat(isoFile *iso, int blockofs, int blocksize, int blocks); extern int isoSetFormat(isoFile *iso, int blockofs, int blocksize, int blocks);
int isoDetect(isoFile *iso); extern int isoDetect(isoFile *iso);
int isoReadBlock(isoFile *iso, u8 *dst, int lsn); extern int isoReadBlock(isoFile *iso, u8 *dst, int lsn);
int isoWriteBlock(isoFile *iso, u8 *src, int lsn); extern int isoWriteBlock(isoFile *iso, u8 *src, int lsn);
void isoClose(isoFile *iso); extern void isoClose(isoFile *iso);
#endif /* __LIBISO_H__ */ #endif /* __LIBISO_H__ */

View File

@ -38,7 +38,7 @@ void *_openfile(const char *filename, int flags)
handle = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); handle = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
} }
return handle == INVALID_HANDLE_VALUE ? NULL : handle; return (handle == INVALID_HANDLE_VALUE) ? NULL : handle;
} }
u64 _tellfile(void *handle) u64 _tellfile(void *handle)

View File

@ -485,7 +485,7 @@ static void CALLBACK CDVD_about() {}
static s32 CALLBACK CDVD_test() { return 0; } static s32 CALLBACK CDVD_test() { return 0; }
static void CALLBACK CDVD_newDiskCB(void (*callback)()) {} static void CALLBACK CDVD_newDiskCB(void (*callback)()) {}
extern int lastReadSize; extern int lastReadSize, lastLSN;
static s32 CALLBACK CDVD_getBuffer2(u8* buffer) static s32 CALLBACK CDVD_getBuffer2(u8* buffer)
{ {
// TEMP: until I fix all the plugins to use this function style // TEMP: until I fix all the plugins to use this function style
@ -517,6 +517,8 @@ static s32 CALLBACK CDVD_readSector(u8* buffer, u32 lsn, int mode)
lastReadSize = 2048; lastReadSize = 2048;
break; break;
} }
lastLSN = lsn;
return CDVD->getBuffer2(buffer); return CDVD->getBuffer2(buffer);
} }