CD-ROM IOCTL: Raw sector read fix.

This commit is contained in:
OBattler
2024-07-15 15:38:36 +02:00
parent f57a07b8e8
commit fba01a9b39

View File

@@ -30,6 +30,7 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h>
#include <wchar.h> #include <wchar.h>
#define HAVE_STDARG_H #define HAVE_STDARG_H
#include <86box/86box.h> #include <86box/86box.h>
@@ -326,17 +327,55 @@ plat_cdrom_get_audio_sub(UNUSED(uint32_t sector), uint8_t *attr, uint8_t *track,
} }
int int
plat_cdrom_get_sector_size(UNUSED(uint32_t sector)) plat_cdrom_get_sector_size(uint32_t sector)
{ {
long size; /* Sector size returned by Windows is always a power of two, which is pointless. */
DISK_GEOMETRY dgCDROM; return 2352;
}
plat_cdrom_open(); /* Used EXCLUSIVELY to read raw sectors, not to detect tracks. */
DeviceIoControl(handle, IOCTL_CDROM_GET_DRIVE_GEOMETRY, NULL, 0, &dgCDROM, sizeof(dgCDROM), (LPDWORD)&size, NULL); static int
plat_cdrom_close(); plat_cdrom_read_scsi_direct(uint32_t sector, uint8_t *buffer)
{
DWORD unused;
int ret;
typedef struct SCSI_PASS_THROUGH_DIRECT_BUF {
SCSI_PASS_THROUGH_DIRECT spt;
ULONG Filler;
UCHAR SenseBuf[32];
} SCSI_PASS_THROUGH_DIRECT_BUF;
win_cdrom_ioctl_log("BytesPerSector=%d\n", dgCDROM.BytesPerSector); SCSI_PASS_THROUGH_DIRECT_BUF req;
return dgCDROM.BytesPerSector;
memset(&req, 0, sizeof(req));
req.Filler = 0;
req.spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
req.spt.CdbLength = 12;
req.spt.DataIn = SCSI_IOCTL_DATA_IN;
req.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_BUF, SenseBuf);
req.spt.SenseInfoLength = sizeof(req.SenseBuf);
req.spt.TimeOutValue = 6;
req.spt.DataTransferLength = 2352;
req.spt.DataBuffer = buffer;
/* Fill in the CDB. */
req.spt.Cdb[0] = 0xBE; /* READ CD */
req.spt.Cdb[1] = 0x00; /* DAP = 0, Any Sector Type. */
req.spt.Cdb[2] = (sector & 0xFF000000) >> 24;
req.spt.Cdb[3] = (sector & 0xFF0000) >> 16;
req.spt.Cdb[4] = (sector & 0xFF00) >> 8;
req.spt.Cdb[5] = (sector & 0xFF); /* Starting Logical Block Address. */
req.spt.Cdb[6] = 0;
req.spt.Cdb[7] = 0;
req.spt.Cdb[8] = 1; /* Transfer Length. */
req.spt.Cdb[9] = 0xF8; /* 2352 bytes of data (non-subchannel). */
req.spt.Cdb[10] = 0; /* No subchannel data. */
req.spt.Cdb[11] = 0;
ret = DeviceIoControl(handle, IOCTL_SCSI_PASS_THROUGH_DIRECT, &req, sizeof(req), &req, sizeof(req), &unused, NULL) && req.spt.DataTransferLength == 2352;
win_cdrom_ioctl_log("plat_cdrom_read_scsi_direct: ret = %d, req.spt.DataTransferLength = %lu\n", ret, req.spt.DataTransferLength);
return ret;
} }
int int
@@ -351,13 +390,18 @@ plat_cdrom_read_sector(uint8_t *buffer, int raw, uint32_t sector)
if (raw) { if (raw) {
win_cdrom_ioctl_log("Raw\n"); win_cdrom_ioctl_log("Raw\n");
/* Raw */ /* Raw */
RAW_READ_INFO in; status = plat_cdrom_read_scsi_direct(sector, buffer);
in.DiskOffset.LowPart = sector * COOKED_SECTOR_SIZE; if (status) {
in.DiskOffset.HighPart = 0; return 1;
in.SectorCount = 1; } else {
in.TrackMode = CDDA; RAW_READ_INFO in;
status = DeviceIoControl(handle, IOCTL_CDROM_RAW_READ, &in, sizeof(in), in.DiskOffset.LowPart = sector * COOKED_SECTOR_SIZE;
buffer, buflen, (LPDWORD)&size, NULL); in.DiskOffset.HighPart = 0;
in.SectorCount = 1;
in.TrackMode = CDDA;
status = DeviceIoControl(handle, IOCTL_CDROM_RAW_READ, &in, sizeof(in),
buffer, buflen, (LPDWORD)&size, NULL);
}
} else { } else {
win_cdrom_ioctl_log("Cooked\n"); win_cdrom_ioctl_log("Cooked\n");
/* Cooked */ /* Cooked */