CD-ROM emulation now reads multiple sectors at once.

This commit is contained in:
SarahW 2018-03-04 13:59:39 +00:00
commit bab6695b2c
7 changed files with 59 additions and 50 deletions

View file

@ -284,10 +284,10 @@ static void image_load(void)
{ {
} }
static int image_readsector(uint8_t *b, int sector) static int image_readsector(uint8_t *b, int sector, int count)
{ {
if (!cdrom) return -1; if (!cdrom) return -1;
return !cdrom->ReadSector(b, false, sector); return !cdrom->ReadSectors((PhysPt)b, false, sector, count);
} }
static void image_readsector_raw(uint8_t *b, int sector) static void image_readsector_raw(uint8_t *b, int sector)

View file

@ -409,13 +409,13 @@ static void ioctl_load(void)
cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0); cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0);
} }
static int ioctl_readsector(uint8_t *b, int sector) static int ioctl_readsector(uint8_t *b, int sector, int count)
{ {
if (ioctl_fd <= 0) if (ioctl_fd <= 0)
return -1; return -1;
lseek(ioctl_fd, sector*2048, SEEK_SET); lseek(ioctl_fd, sector*2048, SEEK_SET);
read(ioctl_fd, b, 2048); read(ioctl_fd, b, count*2048);
return 0; return 0;
} }

View file

@ -86,7 +86,7 @@ static void ioctl_load(void)
{ {
} }
static int ioctl_readsector(uint8_t *b, int sector) static int ioctl_readsector(uint8_t *b, int sector, int count)
{ {
return 0; return 0;
} }

View file

@ -432,11 +432,11 @@ typedef struct _SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER {
UCHAR SenseBuf[32]; UCHAR SenseBuf[32];
} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER; } SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
static int ioctl_readsector(uint8_t *b, int sector) static int ioctl_readsector(uint8_t *b, int sector, int count)
{ {
LARGE_INTEGER pos; LARGE_INTEGER pos;
BOOL status; BOOL status;
long size; long size = 0;
if (!cdrom_drive) if (!cdrom_drive)
return -1; return -1;
@ -448,16 +448,18 @@ static int ioctl_readsector(uint8_t *b, int sector)
pos.QuadPart=sector*2048; pos.QuadPart=sector*2048;
ioctl_open(0); ioctl_open(0);
SetFilePointer(hIOCTL,pos.LowPart,&pos.HighPart,FILE_BEGIN); SetFilePointer(hIOCTL,pos.LowPart,&pos.HighPart,FILE_BEGIN);
status = ReadFile(hIOCTL,b,2048,(LPDWORD)&size,NULL); status = ReadFile(hIOCTL, b, count*2048, (LPDWORD)&size, NULL);
ioctl_close(); ioctl_close();
/*If the read failed, try again using SPTI*/ /*If the read failed, try again using SPTI*/
if (!status || size != 2048) if (!status || size != count*2048)
{ {
uint8_t cmd[12] = { 0xbe, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }; uint8_t cmd[12] = { 0xbe, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 };
SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb; SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb;
DWORD returned; DWORD returned;
uint8_t data_buffer[IOCTL_DATA_BUFFER]; uint8_t *data_buffer;//[IOCTL_DATA_BUFFER];
data_buffer = malloc(count * IOCTL_DATA_BUFFER);
ioctl_open(0); ioctl_open(0);
@ -466,6 +468,9 @@ static int ioctl_readsector(uint8_t *b, int sector)
cmd[3] = (uint8_t)(sector >> 16); cmd[3] = (uint8_t)(sector >> 16);
cmd[4] = (uint8_t)(sector >> 8); cmd[4] = (uint8_t)(sector >> 8);
cmd[5] = (uint8_t)(sector >> 0); cmd[5] = (uint8_t)(sector >> 0);
cmd[6] = (uint8_t)(count >> 16);
cmd[7] = (uint8_t)(count >> 8);
cmd[8] = (uint8_t)(count >> 0);
memset(&swb, 0, sizeof (swb)); memset(&swb, 0, sizeof (swb));
memcpy(swb.spt.Cdb, cmd, 12); memcpy(swb.spt.Cdb, cmd, 12);
@ -473,9 +478,9 @@ static int ioctl_readsector(uint8_t *b, int sector)
swb.spt.Length = sizeof (SCSI_PASS_THROUGH); swb.spt.Length = sizeof (SCSI_PASS_THROUGH);
swb.spt.CdbLength = 12; swb.spt.CdbLength = 12;
swb.spt.DataIn = SCSI_IOCTL_DATA_IN; swb.spt.DataIn = SCSI_IOCTL_DATA_IN;
swb.spt.DataTransferLength = IOCTL_DATA_BUFFER; swb.spt.DataTransferLength = count*IOCTL_DATA_BUFFER;
swb.spt.DataBuffer = data_buffer; swb.spt.DataBuffer = data_buffer;
memset(data_buffer, 0, IOCTL_DATA_BUFFER); memset(data_buffer, 0, count*IOCTL_DATA_BUFFER);
swb.spt.TimeOutValue = 80 * 60; swb.spt.TimeOutValue = 80 * 60;
swb.spt.SenseInfoOffset = (uintptr_t)&swb.SenseBuf - (uintptr_t)&swb;//offsetof(swb, SenseBuf); swb.spt.SenseInfoOffset = (uintptr_t)&swb.SenseBuf - (uintptr_t)&swb;//offsetof(swb, SenseBuf);
swb.spt.SenseInfoLength = 32; swb.spt.SenseInfoLength = 32;
@ -484,9 +489,16 @@ static int ioctl_readsector(uint8_t *b, int sector)
&swb, sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), &swb, sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER),
&swb, sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), &swb, sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER),
&returned, NULL)) &returned, NULL))
memcpy(b, data_buffer, 2048); {
memcpy(b, data_buffer, count*2048);
status = 1;
}
else
status = 0;
ioctl_close(); ioctl_close();
free(data_buffer);
} }
return !status; return !status;

View file

@ -59,7 +59,7 @@ static void null_load(void)
{ {
} }
static int null_readsector(uint8_t *b, int sector) static int null_readsector(uint8_t *b, int sector, int count)
{ {
return 0; return 0;
} }

View file

@ -12,7 +12,7 @@ typedef struct ATAPI
int (*readtoc_session)(uint8_t *b, int msf, int maxlen); int (*readtoc_session)(uint8_t *b, int msf, int maxlen);
int (*readtoc_raw)(uint8_t *b, int maxlen); int (*readtoc_raw)(uint8_t *b, int maxlen);
uint8_t (*getcurrentsubchannel)(uint8_t *b, int msf); uint8_t (*getcurrentsubchannel)(uint8_t *b, int msf);
int (*readsector)(uint8_t *b, int sector); int (*readsector)(uint8_t *b, int sector, int count);
void (*readsector_raw)(uint8_t *b, int sector); void (*readsector_raw)(uint8_t *b, int sector);
void (*playaudio)(uint32_t pos, uint32_t len, int ismsf); void (*playaudio)(uint32_t pos, uint32_t len, int ismsf);
void (*seek)(uint32_t pos); void (*seek)(uint32_t pos);

View file

@ -12,7 +12,7 @@
#define BUFFER_SIZE (256*1024) #define BUFFER_SIZE (256*1024)
#define MAX_NR_SECTORS 2 #define MAX_NR_SECTORS 16
enum enum
{ {
@ -638,28 +638,32 @@ static int scsi_cd_command(uint8_t *cdb, void *p)
return SCSI_PHASE_STATUS; return SCSI_PHASE_STATUS;
} }
for (c = 0; c < MAX_NR_SECTORS; c++) if (rcdmode == 0x10)
{ {
if (rcdmode == 0x10) c = MIN(data->cdlen, MAX_NR_SECTORS);
{ if (atapi->readsector(data->data_in, data->cdpos, c))
if (atapi->readsector(&data->data_in[c*2048], data->cdpos))
{
// pclog("Read sector failed\n");
atapi_cmd_error(data, SENSE_ILLEGAL_REQUEST, ASC_LBA_OUT_OF_RANGE, 0);
data->cmd_pos = CMD_POS_IDLE;
return SCSI_PHASE_STATUS;
}
}
else
{
atapi->readsector_raw(&data->data_in[c*2352], data->cdpos);
}
data->cdpos++;
data->cdlen--;
if (!data->cdlen)
{ {
c++; // pclog("Read sector failed\n");
break; atapi_cmd_error(data, SENSE_ILLEGAL_REQUEST, ASC_LBA_OUT_OF_RANGE, 0);
data->cmd_pos = CMD_POS_IDLE;
return SCSI_PHASE_STATUS;
}
data->cdpos += c;
data->cdlen -= c;
}
else
{
for (c = 0; c < MAX_NR_SECTORS; c++)
{
atapi->readsector_raw(&data->data_in[c*2352], data->cdpos);
data->cdpos++;
data->cdlen--;
if (!data->cdlen)
{
c++;
break;
}
} }
} }
readflash_set(READFLASH_HDC, data->id); readflash_set(READFLASH_HDC, data->id);
@ -704,23 +708,16 @@ static int scsi_cd_command(uint8_t *cdb, void *p)
return SCSI_PHASE_STATUS; return SCSI_PHASE_STATUS;
} }
readflash_set(READFLASH_HDC, data->id); readflash_set(READFLASH_HDC, data->id);
for (c = 0; c < MAX_NR_SECTORS; c++) c = MIN(data->cdlen, MAX_NR_SECTORS);
if (atapi->readsector(data->data_in, data->cdpos, c))
{ {
if (atapi->readsector(&data->data_in[c*2048], data->cdpos)) // pclog("Read sector failed\n");
{ atapi_cmd_error(data, SENSE_ILLEGAL_REQUEST, ASC_LBA_OUT_OF_RANGE, 0);
pclog("Read sector failed\n"); data->cmd_pos = CMD_POS_IDLE;
atapi_cmd_error(data, SENSE_ILLEGAL_REQUEST, ASC_LBA_OUT_OF_RANGE, 0); return SCSI_PHASE_STATUS;
data->cmd_pos = CMD_POS_IDLE;
return SCSI_PHASE_STATUS;
}
data->cdpos++;
data->cdlen--;
if (!data->cdlen)
{
c++;
break;
}
} }
data->cdpos += c;
data->cdlen -= c;
data->data_pos_read = 0; data->data_pos_read = 0;
data->data_pos_write = c * 2048; data->data_pos_write = c * 2048;