cdvdgigaherz: Get disc info when disc is first ready

Also set the disc speed at the correct time - CDROM SET SPEED only stays
in effect till the disc is removed.

Also fix a memleak in CDVDopen when the drive cannot be accessed.
This commit is contained in:
Jonathan Li 2016-10-23 00:53:41 +01:00
parent 95b98c5a38
commit 1834b7d0f9
4 changed files with 46 additions and 112 deletions

View File

@ -225,10 +225,10 @@ s32 CALLBACK CDVDopen(const char *pTitleFilename)
printf(" * CDVD: Opening drive '%s'...\n", csrc);
// open device file
src = new IOCtlSrc(csrc);
if (!src->IsOK()) {
printf(" * CDVD: Error opening source.\n");
try {
src = new IOCtlSrc(csrc);
} catch (std::runtime_error &ex) {
fputs(ex.what(), stdout);
return -1;
}

View File

@ -56,9 +56,7 @@ class IOCtlSrc
HANDLE m_device = INVALID_HANDLE_VALUE;
std::string m_filename;
bool OpenOK;
bool m_disc_ready = false;
s32 m_media_type = 0;
u32 m_sectors = 0;
u32 m_layer_break = 0;
@ -66,25 +64,20 @@ class IOCtlSrc
bool ReadDVDInfo();
bool ReadCDInfo();
bool RefreshDiscInfo();
bool Reopen();
public:
IOCtlSrc(const char *filename);
~IOCtlSrc();
u32 GetSectorCount();
const std::vector<toc_entry> &ReadTOC();
u32 GetSectorCount() const;
const std::vector<toc_entry> &ReadTOC() const;
s32 ReadSectors2048(u32 sector, u32 count, char *buffer);
s32 ReadSectors2352(u32 sector, u32 count, char *buffer);
u32 GetLayerBreakAddress();
s32 GetMediaType();
void SetSpindleSpeed(bool restore_defaults);
s32 IsOK();
s32 Reopen();
s32 DiscChanged();
u32 GetLayerBreakAddress() const;
s32 GetMediaType() const;
void SetSpindleSpeed(bool restore_defaults) const;
bool DiscReady();
};
extern IOCtlSrc *src;

View File

@ -107,22 +107,9 @@ void cdvdCallNewDiscCB()
bool cdvdUpdateDiscStatus()
{
int change = src->DiscChanged();
bool ready = src->DiscReady();
if (change == -1) { //error getting status (no disc in drive?)
//try to recreate the device
src->Reopen();
if (src->IsOK()) {
change = 1;
} else {
curDiskType = CDVD_TYPE_NODISC;
curTrayStatus = CDVD_TRAY_OPEN;
return true;
}
}
if (change == 1) {
if (!ready) {
if (!disc_has_changed) {
disc_has_changed = true;
curDiskType = CDVD_TYPE_NODISC;
@ -134,15 +121,12 @@ bool cdvdUpdateDiscStatus()
curDiskType = CDVD_TYPE_NODISC;
curTrayStatus = CDVD_TRAY_CLOSE;
// just a test
src->Reopen();
disc_has_changed = false;
cdvdRefreshData();
cdvdCallNewDiscCB();
}
}
return (change != 0);
return !ready;
}
DWORD CALLBACK cdvdThread(PVOID param)
@ -150,9 +134,6 @@ DWORD CALLBACK cdvdThread(PVOID param)
printf(" * CDVD: IO thread started...\n");
while (cdvd_is_open) {
if (!src)
break;
if (cdvdUpdateDiscStatus()) {
// Need to sleep some to avoid an aggressive spin that sucks the cpu dry.
Sleep(10);

View File

@ -28,46 +28,49 @@
#include <cstddef>
#include <cstdlib>
#include <array>
#include <stdexcept>
IOCtlSrc::IOCtlSrc(const char *filename)
: m_filename(filename)
{
Reopen();
SetSpindleSpeed(false);
if (!Reopen())
throw std::runtime_error(" * CDVD: Error opening source.\n");
}
IOCtlSrc::~IOCtlSrc()
{
if (OpenOK) {
if (m_device != INVALID_HANDLE_VALUE) {
SetSpindleSpeed(true);
CloseHandle(m_device);
}
}
s32 IOCtlSrc::Reopen()
// If a new disc is inserted, ReadFile will fail unless the device is closed
// and reopened.
bool IOCtlSrc::Reopen()
{
if (m_device != INVALID_HANDLE_VALUE)
CloseHandle(m_device);
DWORD size;
OpenOK = false;
// SPTI only works if the device is opened with GENERIC_WRITE access.
m_device = CreateFile(m_filename.c_str(), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, nullptr, OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN, nullptr);
if (m_device == INVALID_HANDLE_VALUE)
return -1;
return false;
DWORD unused;
// Required to read from layer 1 of Dual layer DVDs
DeviceIoControl(m_device, FSCTL_ALLOW_EXTENDED_DASD_IO, nullptr, 0, nullptr, 0, &size, nullptr);
DeviceIoControl(m_device, FSCTL_ALLOW_EXTENDED_DASD_IO, nullptr, 0, nullptr,
0, &unused, nullptr);
m_disc_ready = false;
OpenOK = true;
return 0;
if (ReadDVDInfo() || ReadCDInfo())
SetSpindleSpeed(false);
return true;
}
void IOCtlSrc::SetSpindleSpeed(bool restore_defaults)
void IOCtlSrc::SetSpindleSpeed(bool restore_defaults) const
{
DWORD dontcare;
@ -112,38 +115,23 @@ void IOCtlSrc::SetSpindleSpeed(bool restore_defaults)
}
}
u32 IOCtlSrc::GetSectorCount()
u32 IOCtlSrc::GetSectorCount() const
{
if (!m_disc_ready)
RefreshDiscInfo();
return m_sectors;
}
u32 IOCtlSrc::GetLayerBreakAddress()
u32 IOCtlSrc::GetLayerBreakAddress() const
{
if (!m_disc_ready)
RefreshDiscInfo();
if (GetMediaType() < 0)
return 0;
return m_layer_break;
}
s32 IOCtlSrc::GetMediaType()
s32 IOCtlSrc::GetMediaType() const
{
if (!m_disc_ready)
RefreshDiscInfo();
return m_media_type;
}
const std::vector<toc_entry> &IOCtlSrc::ReadTOC()
const std::vector<toc_entry> &IOCtlSrc::ReadTOC() const
{
if (!m_disc_ready)
RefreshDiscInfo();
return m_toc;
}
@ -153,9 +141,6 @@ s32 IOCtlSrc::ReadSectors2048(u32 sector, u32 count, char *buffer)
DWORD size = 0;
if (!OpenOK)
return -1;
rri.DiskOffset.QuadPart = sector * (u64)2048;
rri.SectorCount = count;
@ -179,9 +164,6 @@ s32 IOCtlSrc::ReadSectors2048(u32 sector, u32 count, char *buffer)
s32 IOCtlSrc::ReadSectors2352(u32 sector, u32 count, char *buffer)
{
if (!OpenOK)
return -1;
struct sptdinfo
{
SCSI_PASS_THROUGH_DIRECT info;
@ -332,43 +314,21 @@ bool IOCtlSrc::ReadCDInfo()
return true;
}
bool IOCtlSrc::RefreshDiscInfo()
bool IOCtlSrc::DiscReady()
{
if (m_disc_ready)
return true;
m_media_type = 0;
m_layer_break = 0;
m_sectors = 0;
if (!OpenOK)
if (m_device == INVALID_HANDLE_VALUE)
return false;
if (ReadDVDInfo() || ReadCDInfo())
m_disc_ready = true;
return m_disc_ready;
}
s32 IOCtlSrc::DiscChanged()
{
DWORD size = 0;
if (!OpenOK)
return -1;
int ret = DeviceIoControl(m_device, IOCTL_STORAGE_CHECK_VERIFY, NULL, 0, NULL, 0, &size, NULL);
if (ret == 0) {
m_disc_ready = false;
return 1;
DWORD unused;
if (DeviceIoControl(m_device, IOCTL_STORAGE_CHECK_VERIFY, nullptr, 0,
nullptr, 0, &unused, nullptr)) {
if (!m_sectors)
Reopen();
} else {
m_sectors = 0;
m_layer_break = 0;
m_media_type = 0;
}
return 0;
}
s32 IOCtlSrc::IsOK()
{
return OpenOK;
return !!m_sectors;
}