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 <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <wchar.h>
#define HAVE_STDARG_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
plat_cdrom_get_sector_size(UNUSED(uint32_t sector))
plat_cdrom_get_sector_size(uint32_t sector)
{
long size;
DISK_GEOMETRY dgCDROM;
/* Sector size returned by Windows is always a power of two, which is pointless. */
return 2352;
}
plat_cdrom_open();
DeviceIoControl(handle, IOCTL_CDROM_GET_DRIVE_GEOMETRY, NULL, 0, &dgCDROM, sizeof(dgCDROM), (LPDWORD)&size, NULL);
plat_cdrom_close();
/* Used EXCLUSIVELY to read raw sectors, not to detect tracks. */
static int
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);
return dgCDROM.BytesPerSector;
SCSI_PASS_THROUGH_DIRECT_BUF req;
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
@@ -351,13 +390,18 @@ plat_cdrom_read_sector(uint8_t *buffer, int raw, uint32_t sector)
if (raw) {
win_cdrom_ioctl_log("Raw\n");
/* Raw */
RAW_READ_INFO in;
in.DiskOffset.LowPart = sector * COOKED_SECTOR_SIZE;
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);
status = plat_cdrom_read_scsi_direct(sector, buffer);
if (status) {
return 1;
} else {
RAW_READ_INFO in;
in.DiskOffset.LowPart = sector * COOKED_SECTOR_SIZE;
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 {
win_cdrom_ioctl_log("Cooked\n");
/* Cooked */