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); printf(" * CDVD: Opening drive '%s'...\n", csrc);
// open device file // open device file
src = new IOCtlSrc(csrc); try {
src = new IOCtlSrc(csrc);
if (!src->IsOK()) { } catch (std::runtime_error &ex) {
printf(" * CDVD: Error opening source.\n"); fputs(ex.what(), stdout);
return -1; return -1;
} }

View File

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

View File

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

View File

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