cdvdGigaherz: Some improvements to smooth out the "experience" when playing from CDs. A keepalive thread polls the drive every 30 seconds to prevent it from spinning down. When the plugin starts, it now tries to limit the spindle speed so it is less noisy and doesn't wear out as much (32x speed for CD games, 8x speed for DVD games).

Version bump to 0.9.
This commit is contained in:
ramapcsx2 2014-05-26 14:28:56 +02:00
parent 71ebb2493e
commit 53e2824937
5 changed files with 146 additions and 8 deletions

View File

@ -25,6 +25,10 @@
void (*newDiscCB)();
HANDLE hThread_keepAlive = INVALID_HANDLE_VALUE;
HANDLE hNotify_keepAlive = INVALID_HANDLE_VALUE;
DWORD pidThreadKeepAlive = 0;
#define STRFY(x) #x
#define TOSTR(x) STRFY(x)
@ -59,7 +63,7 @@ char *LibName = "cdvdGigaherz "
const unsigned char version = PS2E_CDVD_VERSION;
const unsigned char revision = 0;
const unsigned char build = 8;
const unsigned char build = 9;
HINSTANCE hinst;
@ -129,6 +133,7 @@ void __inline lba_to_msf(s32 lba, u8* m, u8* s, u8* f) {
char csrc[20];
BOOL cdvd_is_open=FALSE;
BOOL cdvdKeepAlive_is_open = false;
Source *src;
@ -137,6 +142,65 @@ s32 disc_has_changed=0;
int weAreInNewDiskCB=0;
char bfr[2352];
char throwaway[2352];
extern s32 prefetch_last_lba;
extern s32 prefetch_last_mode;
///////////////////////////////////////////////////////////////////////////////
// keepAliveThread throws a read event regularly to prevent drive spin down //
DWORD CALLBACK keepAliveThread(PVOID param)
{
printf(" * CDVD: KeepAlive thread started...\n");
while (cdvdKeepAlive_is_open)
{
// Sleep 30 seconds with thread abort check
if (WaitForSingleObject(hNotify_keepAlive, 30000) != WAIT_TIMEOUT) break;
if (!cdvdKeepAlive_is_open) {
break;
}
//printf(" * keepAliveThread: polling drive.\n");
//if (prefetch_last_mode == CDVD_MODE_2048)
src->ReadSectors2048(prefetch_last_lba, 1, throwaway);
//else
// src->ReadSectors2352(prefetch_last_lba, 1, throwaway);
}
printf(" * CDVD: KeepAlive thread finished.\n");
return 0;
}
s32 StartKeepAliveThread()
{
hNotify_keepAlive = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hNotify_keepAlive == INVALID_HANDLE_VALUE)
return -1;
cdvdKeepAlive_is_open = true;
hThread_keepAlive = CreateThread(NULL, 0, keepAliveThread, NULL, 0, &pidThreadKeepAlive);
if (hThread_keepAlive == INVALID_HANDLE_VALUE) {
cdvdKeepAlive_is_open = false;
return -1;
}
SetThreadPriority(hThread_keepAlive, THREAD_PRIORITY_NORMAL);
return 0;
}
void StopKeepAliveThread()
{
cdvdKeepAlive_is_open = false;
PulseEvent(hNotify_keepAlive);
if (WaitForSingleObject(hThread_keepAlive, 5000) == WAIT_TIMEOUT)
{
TerminateThread(hThread_keepAlive, 0);
}
CloseHandle(hThread_keepAlive);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
@ -204,14 +268,15 @@ s32 CALLBACK CDVDopen(const char* pTitleFilename)
//setup threading manager
cdvdStartThread();
StartKeepAliveThread();
return cdvdRefreshData();
}
void CALLBACK CDVDclose()
{
StopKeepAliveThread();
cdvdStopThread();
//close device
delete src;
src=NULL;

View File

@ -128,6 +128,7 @@ public:
virtual s32 GetLayerBreakAddress();
virtual s32 GetMediaType();
virtual void SetSpindleSpeed(bool restore_defaults);
virtual s32 IsOK();
virtual s32 Reopen();
@ -160,6 +161,7 @@ void CfgSetSettingsDir( const char* dir );
extern char csrc[];
extern BOOL cdvd_is_open;
extern BOOL cdvdKeepAlive_is_open;
extern int weAreInNewDiskCB;
extern void (*newDiscCB)();

View File

@ -43,8 +43,8 @@ typedef struct
char data[2352*16]; //we will read in blocks of 16 sectors
} SectorInfo;
//bits: 8 would use 1<<8 entries, or 256*16 sectors
#define CACHE_SIZE 10
//bits: 12 would use 1<<12 entries, or 4096*16 sectors ~ 128MB
#define CACHE_SIZE 12
const s32 CacheSize=(1<<CACHE_SIZE);
SectorInfo Cache[CacheSize];
@ -92,7 +92,7 @@ bool cdvdCacheFetch(int lsn, int mode, char* data)
LeaveCriticalSection( &CacheMutex );
return true;
}
//printf("NOT IN CACHE\n");
LeaveCriticalSection( &CacheMutex );
return false;
}

View File

@ -316,12 +316,14 @@ IOCtlSrc::IOCtlSrc(const char* fileName)
strcpy_s(fName,256,fileName);
Reopen();
SetSpindleSpeed(false);
}
IOCtlSrc::~IOCtlSrc()
{
if(OpenOK)
{
SetSpindleSpeed( true );
DWORD size;
DeviceIoControl(device,IOCTL_DVD_END_SESSION,&sessID,sizeof(DVD_SESSION_ID),NULL,0,&size, NULL);
@ -485,6 +487,51 @@ s32 IOCtlSrc::GetLayerBreakAddress()
return 0;
}
void IOCtlSrc::SetSpindleSpeed(bool restore_defaults) {
DWORD dontcare;
int speed = 0;
if (GetMediaType() < 0 ) speed = 4800; // CD-ROM to ~32x (PS2 has 24x (3600 KB/s))
else speed = 11080; // DVD-ROM to ~8x (PS2 has 4x (5540 KB/s))
if (!restore_defaults) {
CDROM_SET_SPEED s;
s.RequestType = CdromSetSpeed;
s.RotationControl = CdromDefaultRotation;
s.ReadSpeed = speed;
s.WriteSpeed = speed;
if (DeviceIoControl(device,
IOCTL_CDROM_SET_SPEED, //operation to perform
&s, sizeof(s), //no input buffer
NULL, 0, //output buffer
&dontcare, //#bytes returned
(LPOVERLAPPED)NULL)) //synchronous I/O == 0)
{
printf(" * CDVD: setSpindleSpeed success (%dKB/s)\n", speed);
}
else
{
printf(" * CDVD: setSpindleSpeed failed! \n");
}
}
else {
CDROM_SET_SPEED s;
s.RequestType = CdromSetSpeed;
s.RotationControl = CdromDefaultRotation;
s.ReadSpeed = 0xffff; // maximum ?
s.WriteSpeed = 0xffff;
DeviceIoControl(device,
IOCTL_CDROM_SET_SPEED, //operation to perform
&s, sizeof(s), //no input buffer
NULL, 0, //output buffer
&dontcare, //#bytes returned
(LPOVERLAPPED)NULL); //synchronous I/O == 0)
}
}
s32 IOCtlSrc::GetMediaType()
{
DWORD size;
@ -626,15 +673,20 @@ s32 IOCtlSrc::ReadSectors2352(u32 sector, u32 count, char *buffer)
rri.TrackMode=(TRACK_MODE_TYPE)last_read_mode;
if(DeviceIoControl(device,IOCTL_CDROM_RAW_READ,&rri,sizeof(rri),buffer, 2352*count, &size, NULL)==0)
{
rri.TrackMode=YellowMode2;
rri.TrackMode = XAForm2;
printf(" * CDVD: CD-ROM read mode change\n");
printf(" * CDVD: Trying XAForm2\n");
if(DeviceIoControl(device,IOCTL_CDROM_RAW_READ,&rri,sizeof(rri),buffer, 2352*count, &size, NULL)==0)
{
rri.TrackMode=XAForm2;
rri.TrackMode = YellowMode2;
printf(" * CDVD: Trying YellowMode2\n");
if(DeviceIoControl(device,IOCTL_CDROM_RAW_READ,&rri,sizeof(rri),buffer, 2352*count, &size, NULL)==0)
{
rri.TrackMode=CDDA;
rri.TrackMode = CDDA;
printf(" * CDVD: Trying CDDA\n");
if(DeviceIoControl(device,IOCTL_CDROM_RAW_READ,&rri,sizeof(rri),buffer, 2352*count, &size, NULL)==0)
{
printf(" * CDVD: Failed to read this CD-ROM with error code: %d\n", GetLastError());
return -1;
}
}

View File

@ -342,6 +342,25 @@ typedef struct __RAW_READ_INFO {
TRACK_MODE_TYPE TrackMode;
} RAW_READ_INFO, *PRAW_READ_INFO;
typedef enum _CDROM_SPEED_REQUEST {
CdromSetSpeed,
CdromSetStreaming
} CDROM_SPEED_REQUEST, *PCDROM_SPEED_REQUEST;
typedef enum _WRITE_ROTATION {
CdromDefaultRotation,
CdromCAVRotation
} WRITE_ROTATION, *PWRITE_ROTATION;
typedef struct _CDROM_SET_SPEED {
CDROM_SPEED_REQUEST RequestType;
USHORT ReadSpeed;
USHORT WriteSpeed;
WRITE_ROTATION RotationControl;
} CDROM_SET_SPEED, *PCDROM_SET_SPEED;
#define IOCTL_CDROM_SET_SPEED CTL_CODE(IOCTL_CDROM_BASE, 0x0018, METHOD_BUFFERED, FILE_READ_ACCESS)
#ifdef __cplusplus
}
#endif