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.
// Returns -2 if the asynchronous read is still pending.
// Returns -1 if the asyncronous read failed.
// 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* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq);

View File

@ -714,36 +714,49 @@ __forceinline void cdvdReadInterrupt()
}
else
{
// Read Error -1 is only returned by readTrack, so handle it first here.
// If readTrack failed it means we don't have any valid data to fetch.
if (cdvd.RErr == -1)
if( cdvd.RErr == 0 )
{
cdvd.RetryCntP++;
Console::Error("CDVD READ ERROR, sector=%d", params cdvd.Sector);
if (cdvd.RetryCntP <= cdvd.RetryCnt)
while( (cdvd.RErr = DoCDVDgetBuffer(cdr.Transfer)), cdvd.RErr == -2 )
{
cdvd.RErr = DoCDVDreadTrack(cdvd.Sector, cdvd.ReadMode);
CDVDREAD_INT(cdvd.ReadTime);
return;
// not finished yet ... block on the read until it finishes.
Threading::Sleep( 0 );
Threading::SpinWait();
}
}
cdvd.RErr = DoCDVDgetBuffer(cdr.Transfer);
if(cdvd.RErr == -2)
if (cdvd.RErr == -1)
{
// not finished yet ... give it a bit more time
CDVDREAD_INT(cdvd.ReadTime/4);
cdvd.RetryCntP++;
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;
}
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)
{
// 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 );
CDVDREAD_INT(cdvd.ReadTime);
CDVDREAD_INT(cdvd.ReadTime/4);
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.
int lastReadSize;
int lastLSN; // needed for block dumping
// Records last read block length for block dumping
static int plsn = 0;
@ -56,11 +57,9 @@ static void CheckNullCDVD()
DevAssert( CDVD != NULL, "Invalid CDVD object state (null pointer exception)" );
}
/////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////
// Disk Type detection stuff (from cdvdGigaherz)
//
int CheckDiskTypeFS(int baseType)
{
int f;
@ -118,7 +117,7 @@ static int FindDiskType(int mType)
}
else if (mType < 0)
{
static u8 bleh[2352];
static u8 bleh[CD_FRAMESIZE_RAW];
cdvdTD td;
CDVD->getTD(0,&td);
@ -322,26 +321,25 @@ s32 DoCDVDopen(const char* pTitleFilename)
cdvdTD td;
CDVD->getTD(0, &td);
int blockofs = 0, blocksize = 0, blocks = td.lsn;
switch(cdtype)
blockDumpFile = isoCreate(Path::Combine( Path::GetWorkingDirectory(), fname ).c_str(), ISOFLAGS_BLOCKDUMP_V3);
if (blockDumpFile)
{
case CDVD_TYPE_PS2DVD:
case CDVD_TYPE_DVDV:
case CDVD_TYPE_DETCTDVDS:
case CDVD_TYPE_DETCTDVDD:
blockofs = 24;
blocksize = 2048;
break;
default:
blockofs = 0;
blocksize= 2352;
break;
}
int blockofs = 0, blocksize = CD_FRAMESIZE_RAW, blocks = td.lsn;
blockDumpFile = isoCreate(fname.c_str(), ISOFLAGS_BLOCKDUMP);
if (blockDumpFile) isoSetFormat(blockDumpFile, blockofs, blocksize, blocks);
// hack: Because of limitations of the current cdvd design, we can't query the blocksize
// 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
{
@ -396,7 +394,7 @@ s32 DoCDVDreadTrack(u32 lsn, int mode)
}
//DevCon::Notice("CDVD readTrack(lsn=%d,mode=%d)",params lsn, lastReadSize);
lastLSN = lsn;
return CDVD->readTrack(lsn,mode);
}
@ -407,7 +405,7 @@ s32 DoCDVDgetBuffer(u8* buffer)
if (ret == 0 && blockDumpFile != NULL)
{
isoWriteBlock(blockDumpFile, buffer, lastReadSize);
isoWriteBlock(blockDumpFile, buffer, lastLSN);
}
return ret;

View File

@ -295,9 +295,10 @@ s32 CALLBACK ISOreadSector(u8* tempbuffer, u32 lsn, int mode)
return 0;
}
isoReadBlock(iso, cdbuffer + iso->blockofs, lsn);
isoReadBlock(iso, cdbuffer, lsn);
pbuffer = cdbuffer;
switch (mode)
{
case CDVD_MODE_2352:
@ -317,6 +318,11 @@ s32 CALLBACK ISOreadSector(u8* tempbuffer, u32 lsn, int mode)
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);
return 0;
@ -329,9 +335,9 @@ s32 CALLBACK ISOreadTrack(u32 lsn, int mode)
if (_lsn < 0) lsn = iso->blocks + _lsn;
if (lsn > iso->blocks) return -1;
isoReadBlock(iso, cdbuffer + iso->blockofs, lsn);
isoReadBlock(iso, cdbuffer, lsn);
pbuffer = cdbuffer;
switch (mode)
{
case CDVD_MODE_2352:
@ -351,6 +357,11 @@ s32 CALLBACK ISOreadTrack(u32 lsn, int mode)
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;
}

View File

@ -497,28 +497,27 @@ void cdrReadInterrupt() {
cdr.StatP|= 0x22;
cdr.Result[0] = cdr.StatP;
// Read Error -1 is only returned by readTrack, so handle it first here.
// If readTrack failed it means we don't have any valid data to fetch.
if( cdr.RErr == 0 )
{
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)
{
CDR_LOG(" err\n");
memzero_obj(cdr.Transfer);
cdr.Stat = DiskError;
cdr.Result[0]|= 0x01;
cdr.Result[0] |= 0x01;
ReadTrack();
CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime);
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_LOG(" %x:%x:%x", cdr.Transfer[0], cdr.Transfer[1], cdr.Transfer[2]);

View File

@ -29,12 +29,12 @@
int detect(isoFile *iso)
{
u8 buf[2448];
struct cdVolDesc *volDesc;
cdVolDesc *volDesc;
if (isoReadBlock(iso, buf + iso->blockofs, 16) == -1) return -1;
volDesc = (struct cdVolDesc *)(buf + 24);
if (isoReadBlock(iso, buf, 16) == -1) return -1;
volDesc = (cdVolDesc *) (( iso->flags & ISOFLAGS_BLOCKDUMP_V3 ) ? buf : (buf + 24));
if (strncmp((char*)volDesc->volID, "CD001", 5)) return 0;
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)
{
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->blocks, 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
iso->offset = 0;
iso->blocksize = 2352;
iso->blocksize = CD_FRAMESIZE_RAW;
iso->blockofs = 0;
iso->type = ISOTYPE_AUDIO;
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("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, &blocksize, 4) < 4) return -1;
if (_writefile(iso->handle, &blocks, 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;
}
@ -275,7 +290,7 @@ int _isoReadBlock(isoFile *iso, u8 *dst, int lsn)
memset(dst, 0, iso->blockofs);
_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)
{
@ -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);
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;
_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;
return 0;
@ -330,7 +345,7 @@ int _isoReadBlockM(isoFile *iso, u8 *dst, int lsn)
memset(dst, 0, iso->blockofs);
_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)
{
@ -351,7 +366,9 @@ int isoReadBlock(isoFile *iso, u8 *dst, int lsn)
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);
else if (iso->flags & ISOFLAGS_MULTI)
ret = _isoReadBlockM(iso, dst, lsn);
@ -362,13 +379,8 @@ int isoReadBlock(isoFile *iso, u8 *dst, int lsn)
if (iso->type == ISOTYPE_CD)
{
// This is weird voodoo mess that does some kind of time adjustment on the
// block headers of CD-Rom images. hackfixed it to work with 24 byte block
// 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;
LSNtoMSF(dst + 12, lsn);
dst[15] = 2;
}
return 0;
@ -381,7 +393,7 @@ int _isoWriteBlock(isoFile *iso, u8 *src, int lsn)
u64 ofs = (u64)lsn * iso->blocksize + iso->offset;
_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;
return 0;
@ -395,7 +407,7 @@ int _isoWriteBlockD(isoFile *iso, u8 *src, int lsn)
ret = _writefile(iso->handle, &lsn, 4);
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);
@ -406,15 +418,10 @@ int _isoWriteBlockD(isoFile *iso, u8 *src, int lsn)
int isoWriteBlock(isoFile *iso, u8 *src, int lsn)
{
int ret;
if (iso->flags & ISOFLAGS_BLOCKDUMP)
ret = _isoWriteBlockD(iso, src, lsn);
if (iso->flags & ISOFLAGS_BLOCKDUMP_V3)
return _isoWriteBlockD(iso, src, lsn);
else
ret = _isoWriteBlock(iso, src, lsn);
if (ret == -1) return -1;
return 0;
return _isoWriteBlock(iso, src, lsn);
}
void isoClose(isoFile *iso)

View File

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

View File

@ -485,7 +485,7 @@ static void CALLBACK CDVD_about() {}
static s32 CALLBACK CDVD_test() { return 0; }
static void CALLBACK CDVD_newDiskCB(void (*callback)()) {}
extern int lastReadSize;
extern int lastReadSize, lastLSN;
static s32 CALLBACK CDVD_getBuffer2(u8* buffer)
{
// 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;
break;
}
lastLSN = lsn;
return CDVD->getBuffer2(buffer);
}