mirror of https://github.com/PCSX2/pcsx2.git
Merge pull request #1545 from turtleli/cdvd-spti
cdvdgigaherz: Use SPTI to read raw CD sectors
This commit is contained in:
commit
4d10eda308
|
@ -90,7 +90,7 @@ class IOCtlSrc: public Source
|
||||||
IOCtlSrc(IOCtlSrc&);
|
IOCtlSrc(IOCtlSrc&);
|
||||||
|
|
||||||
HANDLE device;
|
HANDLE device;
|
||||||
|
bool m_can_use_spti;
|
||||||
bool OpenOK;
|
bool OpenOK;
|
||||||
|
|
||||||
s32 last_read_mode;
|
s32 last_read_mode;
|
||||||
|
|
|
@ -18,6 +18,12 @@
|
||||||
#include <winioctl.h>
|
#include <winioctl.h>
|
||||||
#include <ntddcdvd.h>
|
#include <ntddcdvd.h>
|
||||||
#include <ntddcdrm.h>
|
#include <ntddcdrm.h>
|
||||||
|
// "typedef ignored" warning will disappear once we move to the Windows 10 SDK.
|
||||||
|
#pragma warning (push)
|
||||||
|
#pragma warning (disable: 4091)
|
||||||
|
#include <ntddscsi.h>
|
||||||
|
#pragma warning (pop)
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
@ -284,13 +290,15 @@ s32 IOCtlSrc::Reopen()
|
||||||
DWORD size;
|
DWORD size;
|
||||||
|
|
||||||
OpenOK = false;
|
OpenOK = false;
|
||||||
|
// SPTI only works if the device is opened with GENERIC_WRITE access.
|
||||||
|
m_can_use_spti = true;
|
||||||
device = CreateFile(fName, GENERIC_READ|GENERIC_WRITE|FILE_READ_ATTRIBUTES, share, NULL, OPEN_EXISTING, flags, 0);
|
device = CreateFile(fName, GENERIC_READ|GENERIC_WRITE|FILE_READ_ATTRIBUTES, share, NULL, OPEN_EXISTING, flags, 0);
|
||||||
if(device==INVALID_HANDLE_VALUE)
|
if(device==INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
device = CreateFile(fName, GENERIC_READ|FILE_READ_ATTRIBUTES, share, NULL, OPEN_EXISTING, flags, 0);
|
device = CreateFile(fName, GENERIC_READ|FILE_READ_ATTRIBUTES, share, NULL, OPEN_EXISTING, flags, 0);
|
||||||
if(device==INVALID_HANDLE_VALUE)
|
if(device==INVALID_HANDLE_VALUE)
|
||||||
return -1;
|
return -1;
|
||||||
|
m_can_use_spti = false;
|
||||||
}
|
}
|
||||||
// Dual layer DVDs cannot read from layer 1 without this ioctl
|
// Dual layer DVDs cannot read from layer 1 without this ioctl
|
||||||
DeviceIoControl(device, FSCTL_ALLOW_EXTENDED_DASD_IO, nullptr, 0, nullptr, 0, &size, nullptr);
|
DeviceIoControl(device, FSCTL_ALLOW_EXTENDED_DASD_IO, nullptr, 0, nullptr, 0, &size, nullptr);
|
||||||
|
@ -624,6 +632,8 @@ s32 IOCtlSrc::ReadSectors2048(u32 sector, u32 count, char *buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FIXME: Probably doesn't work if the sectors to be read are from two tracks
|
||||||
|
// of different types.
|
||||||
s32 IOCtlSrc::ReadSectors2352(u32 sector, u32 count, char *buffer)
|
s32 IOCtlSrc::ReadSectors2352(u32 sector, u32 count, char *buffer)
|
||||||
{
|
{
|
||||||
RAW_READ_INFO rri;
|
RAW_READ_INFO rri;
|
||||||
|
@ -632,6 +642,48 @@ s32 IOCtlSrc::ReadSectors2352(u32 sector, u32 count, char *buffer)
|
||||||
|
|
||||||
if(!OpenOK) return -1;
|
if(!OpenOK) return -1;
|
||||||
|
|
||||||
|
if (m_can_use_spti)
|
||||||
|
{
|
||||||
|
struct sptdinfo
|
||||||
|
{
|
||||||
|
SCSI_PASS_THROUGH_DIRECT info;
|
||||||
|
char sense_buffer[20];
|
||||||
|
} sptd = {};
|
||||||
|
|
||||||
|
// READ CD command
|
||||||
|
sptd.info.Cdb[0] = 0xBE;
|
||||||
|
// Don't care about sector type.
|
||||||
|
sptd.info.Cdb[1] = 0;
|
||||||
|
sptd.info.Cdb[2] = (sector >> 24) & 0xFF;
|
||||||
|
sptd.info.Cdb[3] = (sector >> 16) & 0xFF;
|
||||||
|
sptd.info.Cdb[4] = (sector >> 8) & 0xFF;
|
||||||
|
sptd.info.Cdb[5] = sector & 0xFF;
|
||||||
|
sptd.info.Cdb[6] = (count >> 16) & 0xFF;
|
||||||
|
sptd.info.Cdb[7] = (count >> 8) & 0xFF;
|
||||||
|
sptd.info.Cdb[8] = count & 0xFF;
|
||||||
|
// Sync + all headers + user data + EDC/ECC. Excludes C2 + subchannel
|
||||||
|
sptd.info.Cdb[9] = 0xF8;
|
||||||
|
sptd.info.Cdb[10] = 0;
|
||||||
|
sptd.info.Cdb[11] = 0;
|
||||||
|
|
||||||
|
sptd.info.CdbLength = 12;
|
||||||
|
sptd.info.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
|
||||||
|
sptd.info.DataIn = SCSI_IOCTL_DATA_IN;
|
||||||
|
sptd.info.DataTransferLength = 2352 * count;
|
||||||
|
sptd.info.DataBuffer = buffer;
|
||||||
|
sptd.info.SenseInfoLength = sizeof(sptd.sense_buffer);
|
||||||
|
sptd.info.SenseInfoOffset = offsetof(sptdinfo, sense_buffer);
|
||||||
|
sptd.info.TimeOutValue = 5;
|
||||||
|
|
||||||
|
if (DeviceIoControl(device, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd,
|
||||||
|
sizeof(sptd), &sptd, sizeof(sptd), &size, nullptr))
|
||||||
|
{
|
||||||
|
if (sptd.info.DataTransferLength == 2352 * count)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
printf(" * CDVD: SPTI failed reading sectors %u-%u\n", sector, sector + count - 1);
|
||||||
|
}
|
||||||
|
|
||||||
rri.DiskOffset.QuadPart=sector*(u64)2048;
|
rri.DiskOffset.QuadPart=sector*(u64)2048;
|
||||||
rri.SectorCount=count;
|
rri.SectorCount=count;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue