All MODE SENSE and MODE SELECT commands now support the block descriptor when a CD-ROM drive is set to SCSI;

Fixed MODE SELECT behavior with ATAPI;
Removed excess PIIX logging;
Fixed and improved the CD Audio buffer code in sound.c.
This commit is contained in:
OBattler
2017-01-27 23:03:20 +01:00
parent 661b409621
commit 10503674eb
7 changed files with 371 additions and 179 deletions

View File

@@ -304,6 +304,7 @@ static int ioctl_medium_changed(uint8_t id)
if (!cdrom_ioctl[id].tocvalid || (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive))
{
cdrom_ioctl[id].cd_state = CD_STOPPED;
cdrom_ioctl_log("Setting TOC...\n");
cdrom_ioctl_windows[id].toc = ltoc;
cdrom_ioctl[id].tocvalid = 1;
if (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive)
@@ -318,6 +319,7 @@ static int ioctl_medium_changed(uint8_t id)
(ltoc.TrackData[ltoc.LastTrack].Address[3] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[3]))
{
cdrom_ioctl[id].cd_state = CD_STOPPED;
cdrom_ioctl_log("Setting TOC...\n");
cdrom_ioctl_windows[id].toc = ltoc;
cdrom_ioctl[id].cdrom_capacity = ioctl_get_last_block(id, 0, 0, 4096, 0);
return 1; /* TOC mismatches. */
@@ -345,69 +347,77 @@ static uint8_t ioctl_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf)
int track = get_track_nr(id, cdpos);
uint32_t track_address = cdrom_ioctl_windows[id].toc.TrackData[track].Address[3] + (cdrom_ioctl_windows[id].toc.TrackData[track].Address[2] * 75) + (cdrom_ioctl_windows[id].toc.TrackData[track].Address[1] * 75 * 60);
b[pos++] = sub.CurrentPosition.Control;
b[pos++] = track + 1;
b[pos++] = sub.CurrentPosition.IndexNumber;
cdrom_ioctl_log("cdpos = %i, track = %i, track_address = %i\n", cdpos, track, track_address);
b[pos++] = sub.CurrentPosition.Control;
b[pos++] = track + 1;
b[pos++] = sub.CurrentPosition.IndexNumber;
if (msf)
{
uint32_t dat = cdpos;
b[pos + 3] = (uint8_t)(dat % 75); dat /= 75;
b[pos + 2] = (uint8_t)(dat % 60); dat /= 60;
b[pos + 1] = (uint8_t)dat;
b[pos] = 0;
pos += 4;
dat = cdpos - track_address;
b[pos + 3] = (uint8_t)(dat % 75); dat /= 75;
b[pos + 2] = (uint8_t)(dat % 60); dat /= 60;
b[pos + 1] = (uint8_t)dat;
b[pos] = 0;
pos += 4;
}
else
{
b[pos++] = (cdpos >> 24) & 0xff;
b[pos++] = (cdpos >> 16) & 0xff;
b[pos++] = (cdpos >> 8) & 0xff;
b[pos++] = cdpos & 0xff;
cdpos -= track_address;
b[pos++] = (cdpos >> 24) & 0xff;
b[pos++] = (cdpos >> 16) & 0xff;
b[pos++] = (cdpos >> 8) & 0xff;
b[pos++] = cdpos & 0xff;
}
if (msf)
{
uint32_t dat = cdpos;
b[pos + 3] = (uint8_t)(dat % 75); dat /= 75;
b[pos + 2] = (uint8_t)(dat % 60); dat /= 60;
b[pos + 1] = (uint8_t)dat;
b[pos] = 0;
pos += 4;
dat = cdpos - track_address;
b[pos + 3] = (uint8_t)(dat % 75); dat /= 75;
b[pos + 2] = (uint8_t)(dat % 60); dat /= 60;
b[pos + 1] = (uint8_t)dat;
b[pos] = 0;
pos += 4;
}
else
{
b[pos++] = (cdpos >> 24) & 0xff;
b[pos++] = (cdpos >> 16) & 0xff;
b[pos++] = (cdpos >> 8) & 0xff;
b[pos++] = cdpos & 0xff;
cdpos -= track_address;
b[pos++] = (cdpos >> 24) & 0xff;
b[pos++] = (cdpos >> 16) & 0xff;
b[pos++] = (cdpos >> 8) & 0xff;
b[pos++] = cdpos & 0xff;
}
if (cdrom_ioctl[id].cd_state == CD_PLAYING) return 0x11;
return 0x12;
}
if (cdrom_ioctl[id].cd_state == CD_PLAYING) return 0x11;
return 0x12;
}
b[pos++]=sub.CurrentPosition.Control;
b[pos++]=sub.CurrentPosition.TrackNumber;
b[pos++]=sub.CurrentPosition.IndexNumber;
b[pos++]=sub.CurrentPosition.Control;
b[pos++]=sub.CurrentPosition.TrackNumber;
b[pos++]=sub.CurrentPosition.IndexNumber;
cdrom_ioctl_log("cdpos = %i, track_address = %i\n", MSFtoLBA(sub.CurrentPosition.AbsoluteAddress[1], sub.CurrentPosition.AbsoluteAddress[2], sub.CurrentPosition.AbsoluteAddress[3]), MSFtoLBA(sub.CurrentPosition.TrackRelativeAddress[1], sub.CurrentPosition.TrackRelativeAddress[2], sub.CurrentPosition.TrackRelativeAddress[3]));
if (msf)
{
int c;
for (c = 0; c < 4; c++)
b[pos++] = sub.CurrentPosition.AbsoluteAddress[c];
for (c = 0; c < 4; c++)
b[pos++] = sub.CurrentPosition.TrackRelativeAddress[c];
}
else
{
uint32_t temp = MSFtoLBA(sub.CurrentPosition.AbsoluteAddress[1], sub.CurrentPosition.AbsoluteAddress[2], sub.CurrentPosition.AbsoluteAddress[3]);
b[pos++] = temp >> 24;
b[pos++] = temp >> 16;
b[pos++] = temp >> 8;
b[pos++] = temp;
temp = MSFtoLBA(sub.CurrentPosition.TrackRelativeAddress[1], sub.CurrentPosition.TrackRelativeAddress[2], sub.CurrentPosition.TrackRelativeAddress[3]);
b[pos++] = temp >> 24;
b[pos++] = temp >> 16;
b[pos++] = temp >> 8;
b[pos++] = temp;
}
if (msf)
{
int c;
for (c = 0; c < 4; c++)
{
b[pos++] = sub.CurrentPosition.AbsoluteAddress[c];
}
for (c = 0; c < 4; c++)
{
b[pos++] = sub.CurrentPosition.TrackRelativeAddress[c];
}
}
else
{
uint32_t temp = MSFtoLBA(sub.CurrentPosition.AbsoluteAddress[1], sub.CurrentPosition.AbsoluteAddress[2], sub.CurrentPosition.AbsoluteAddress[3]);
b[pos++] = temp >> 24;
b[pos++] = temp >> 16;
b[pos++] = temp >> 8;
b[pos++] = temp;
temp = MSFtoLBA(sub.CurrentPosition.TrackRelativeAddress[1], sub.CurrentPosition.TrackRelativeAddress[2], sub.CurrentPosition.TrackRelativeAddress[3]);
b[pos++] = temp >> 24;
b[pos++] = temp >> 16;
b[pos++] = temp >> 8;
b[pos++] = temp;
}
return 0x13;
return 0x13;
}
static void ioctl_eject(uint8_t id)
@@ -664,6 +674,43 @@ static void ioctl_read_capacity(uint8_t id, uint8_t *b)
ioctl_close(id);
}
static int ioctl_media_type_id(uint8_t id)
{
uint8_t old_sense[3] = { 0, 0, 0 };
UCHAR msbuf[28];
int len = 0;
int sense = 0;
const UCHAR cdb[] = { 0x5A, 0x00, 0x2A, 0, 0, 0, 0, 0, 28, 0, 0, 0 };
old_sense[0] = cdrom_sense_key;
old_sense[1] = cdrom_asc;
old_sense[2] = cdrom_asc;
ioctl_open(id, 0);
SCSICommand(id, cdb, msbuf, &len, 1);
pclog("Returned length: %i, media type: %i\n", len, msbuf[2]);
ioctl_close(id);
sense = cdrom_sense_key;
cdrom_sense_key = old_sense[0];
cdrom_asc = old_sense[1];
cdrom_asc = old_sense[2];
if (sense == 0)
{
return msbuf[2];
}
else
{
return 3;
}
}
static uint32_t msf_to_lba32(int lba)
{
int m = (lba >> 16) & 0xff;
@@ -754,6 +801,7 @@ static void ioctl_validate_toc(uint8_t id)
}
cdrom_ioctl[id].cd_state = CD_STOPPED;
ioctl_open(id, 0);
cdrom_ioctl_log("Validating TOC...\n");
DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&cdrom_ioctl_windows[id].toc,sizeof(cdrom_ioctl_windows[id].toc),&size,NULL);
ioctl_close(id);
cdrom_ioctl[id].tocvalid=1;
@@ -781,7 +829,7 @@ static int ioctl_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t
int temp_len = 0;
int chunk = 0;
if (cdb[0] == 0x43)
if (in_cdb[0] == 0x43)
{
/* This is a read TOC, so we have to validate the TOC to make the rest of the emulator happy. */
ioctl_validate_toc(id);
@@ -950,6 +998,7 @@ static CDROM ioctl_cdrom=
{
ioctl_ready,
ioctl_medium_changed,
ioctl_media_type_id,
ioctl_audio_callback,
ioctl_audio_stop,
NULL,

View File

@@ -589,10 +589,23 @@ static int iso_is_track_audio(uint8_t id, uint32_t pos, int ismsf)
return 0;
}
static int iso_media_type_id(uint8_t id)
{
if (iso_size(id) <= 405000)
{
return 1; /* Data CD. */
}
else
{
return 65; /* DVD. */
}
}
static CDROM iso_cdrom =
{
iso_ready,
iso_medium_changed,
iso_media_type_id,
NULL,
NULL,
iso_readtoc,

View File

@@ -100,10 +100,16 @@ static int null_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t *
return 0;
}
static int null_media_type_id(uint8_t id)
{
return 0x70;
}
static CDROM null_cdrom =
{
null_ready,
null_medium_changed,
null_media_type_id,
NULL,
NULL,
null_readtoc,

View File

@@ -27,8 +27,9 @@
#define MODE_SELECT_PHASE_IDLE 0
#define MODE_SELECT_PHASE_HEADER 1
#define MODE_SELECT_PHASE_PAGE_HEADER 2
#define MODE_SELECT_PHASE_PAGE 3
#define MODE_SELECT_PHASE_BLOCK_DESC 2
#define MODE_SELECT_PHASE_PAGE_HEADER 3
#define MODE_SELECT_PHASE_PAGE 4
cdrom_t cdrom[CDROM_NUM];
cdrom_drive_t cdrom_drives[CDROM_NUM];
@@ -170,19 +171,19 @@ uint8_t cdrom_mode_sense_pages_changeable[CDROM_NUM][0x40][0x40] =
{
{ [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 0, 0, 0, 0, 0 },
[GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 0, 0, 0, 0, 0 },
[GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 },
[GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0xFF, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 },
[GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
{ [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 0, 0, 0, 0, 0 },
[GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 0, 0, 0, 0, 0 },
[GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 },
[GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0xFF, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 },
[GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
{ [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 0, 0, 0, 0, 0 },
[GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 0, 0, 0, 0, 0 },
[GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 },
[GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0xFF, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 },
[GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
{ [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 0, 0, 0, 0, 0 },
[GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 0, 0, 0, 0, 0 },
[GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 },
[GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0xFF, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 },
[GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
};
@@ -535,7 +536,7 @@ int cdrom_mode_select_terminate(uint8_t id, int force)
{
cdrom_mode_sense_save(id);
}
cdrom[id].current_page_pos = cdrom[id].current_page_len = 0;
cdrom[id].current_page_pos = cdrom[id].current_page_len = cdrom[id].block_descriptor_len = 0;
cdrom[id].total_length = cdrom[id].written_length = 0;
cdrom[id].mode_select_phase = MODE_SELECT_PHASE_IDLE;
if (force)
@@ -550,10 +551,51 @@ int cdrom_mode_select_terminate(uint8_t id, int force)
}
}
int cdrom_mode_select_header(uint8_t id)
int cdrom_mode_select_header(uint8_t id, uint8_t val)
{
if (cdrom[id].current_page_pos == 0)
{
cdrom[id].block_descriptor_len = 0;
}
else if (cdrom[id].current_page_pos == (cdrom[id].current_page_len - 2))
{
if (cdrom_drives[id].bus_type && (cdrom[id].current_page_len == 8))
{
cdrom[id].block_descriptor_len |= ((uint16_t) val) << 8;
cdrom_log("CD-ROM %i: Position: %02X, value: %02X, block descriptor length: %02X\n", id, cdrom[id].current_page_pos, val, cdrom[id].block_descriptor_len);
}
}
else if (cdrom[id].current_page_pos == (cdrom[id].current_page_len - 1))
{
if (cdrom_drives[id].bus_type)
{
cdrom[id].block_descriptor_len |= (uint16_t) val;
cdrom_log("CD-ROM %i: Position: %02X, value: %02X, block descriptor length: %02X\n", id, cdrom[id].current_page_pos, val, cdrom[id].block_descriptor_len);
}
}
cdrom[id].current_page_pos++;
if (cdrom[id].current_page_pos >= cdrom[id].current_page_len)
{
cdrom[id].current_page_pos = 0;
if (cdrom[id].block_descriptor_len)
{
cdrom[id].mode_select_phase = MODE_SELECT_PHASE_BLOCK_DESC;
}
else
{
cdrom[id].mode_select_phase = MODE_SELECT_PHASE_PAGE_HEADER;
}
}
return 1;
}
int cdrom_mode_select_block_desc(uint8_t id)
{
cdrom[id].current_page_pos++;
if (cdrom[id].current_page_pos >= cdrom[id].current_page_len)
if (cdrom[id].current_page_pos >= 8)
{
cdrom[id].current_page_pos = 0;
cdrom[id].mode_select_phase = MODE_SELECT_PHASE_PAGE_HEADER;
@@ -652,7 +694,11 @@ int cdrom_mode_select_write(uint8_t id, uint8_t val)
break;
case MODE_SELECT_PHASE_HEADER:
cdrom_log("CD-ROM %i: MODE SELECT header (%02X)\n", id, val);
ret = cdrom_mode_select_header(id);
ret = cdrom_mode_select_header(id, val);
break;
case MODE_SELECT_PHASE_BLOCK_DESC:
cdrom_log("CD-ROM %i: MODE SELECT block descriptor (%02X)\n", id, val);
ret = cdrom_mode_select_block_desc(id);
break;
case MODE_SELECT_PHASE_PAGE_HEADER:
cdrom_log("CD-ROM %i: MODE SELECT page header (%02X)\n", id, val);
@@ -682,6 +728,41 @@ int cdrom_mode_select_write(uint8_t id, uint8_t val)
return ret;
}
uint8_t cdrom_read_capacity_cdb[12] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static int cdrom_pass_through(uint8_t id, int *len, uint8_t *cdb, uint8_t *buffer);
int cdrom_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, int *len)
{
int ret = 0;
int size = 0;
if (cdrom_drives[id].handler->pass_through)
{
ret = cdrom_pass_through(id, len, cdb, buffer);
if (!ret)
{
return 0;
}
if (*len == 65534)
{
*len = 8;
}
}
else
{
size = cdrom_drives[id].handler->size(id) - 1; /* IMPORTANT: What's returned is the last LBA block. */
memset(buffer, 0, 8);
buffer[0] = (size >> 24) & 0xff;
buffer[1] = (size >> 16) & 0xff;
buffer[2] = (size >> 8) & 0xff;
buffer[3] = size & 0xff;
buffer[6] = 8; /* 2048 = 0x0800 */
*len = 8;
}
return 1;
}
/*SCSI Mode Sense 6/10*/
uint8_t cdrom_mode_sense_read(uint8_t id, uint8_t page_control, uint8_t page, uint8_t pos)
{
@@ -700,7 +781,7 @@ uint8_t cdrom_mode_sense_read(uint8_t id, uint8_t page_control, uint8_t page, ui
}
}
uint32_t cdrom_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type)
uint32_t cdrom_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len)
{
uint8_t page_control = (type >> 6) & 3;
@@ -711,6 +792,20 @@ uint32_t cdrom_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type)
type &= 0x3f;
int len = 0;
if (block_descriptor_len)
{
buf[pos++] = 1; /* Density code. */
buf[pos++] = 0; /* Number of blocks (0 = all). */
buf[pos++] = 0;
buf[pos++] = 0;
buf[pos++] = 0; /* Reserved. */
buf[pos++] = 0; /* Block length (0x800 = 2048 bytes). */
buf[pos++] = 8;
buf[pos++] = 0;
}
for (i = 0; i < 0x40; i++)
{
if ((type == GPMODE_ALL_PAGES) || (type == i))
@@ -1018,13 +1113,15 @@ static void cdrom_data_phase_error(uint8_t id)
cdrom_cmd_error(id);
}
static int cdrom_pass_through(uint8_t id, int *len)
static int cdrom_pass_through(uint8_t id, int *len, uint8_t *cdb, uint8_t *buffer)
{
int ret = 0;
uint8_t *cdbufferb = (uint8_t *) cdrom[id].buffer;
// uint8_t *cdbufferb = (uint8_t *) cdrom[id].buffer;
ret = cdrom_drives[id].handler->pass_through(id, cdrom[id].current_cdb, cdbufferb + cdrom[id].data_pos, len);
cdrom_log("CD-ROM %i: Data from pass through: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, cdbufferb[cdrom[id].data_pos + 0], cdbufferb[cdrom[id].data_pos + 1], cdbufferb[cdrom[id].data_pos + 2], cdbufferb[cdrom[id].data_pos + 3], cdbufferb[cdrom[id].data_pos + 4], cdbufferb[cdrom[id].data_pos + 5], cdbufferb[cdrom[id].data_pos + 6], cdbufferb[cdrom[id].data_pos + 7]);
// ret = cdrom_drives[id].handler->pass_through(id, cdrom[id].current_cdb, cdbufferb + cdrom[id].data_pos, len);
ret = cdrom_drives[id].handler->pass_through(id, cdb, buffer, len);
// cdrom_log("CD-ROM %i: Data from pass through: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, cdbufferb[cdrom[id].data_pos + 0], cdbufferb[cdrom[id].data_pos + 1], cdbufferb[cdrom[id].data_pos + 2], cdbufferb[cdrom[id].data_pos + 3], cdbufferb[cdrom[id].data_pos + 4], cdbufferb[cdrom[id].data_pos + 5], cdbufferb[cdrom[id].data_pos + 6], cdbufferb[cdrom[id].data_pos + 7]);
cdrom_log("CD-ROM %i: Data from pass through: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]);
cdrom_log("CD-ROM %i: Returned value: %i\n", id, ret);
if (!ret)
@@ -1124,7 +1221,7 @@ int cdrom_read_data(uint8_t id, int msf, int type, int flags, int *len)
{
cdsize = cdrom_drives[id].handler->size(id);
ret = cdrom_pass_through(id, len);
ret = cdrom_pass_through(id, len, cdrom[id].current_cdb, cdbufferb + cdrom[id].data_pos);
cdrom[id].data_pos += *len;
if (!ret)
@@ -1656,6 +1753,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
int alloc_length;
int completed;
uint8_t index = 0;
int block_desc = 0;
int media;
int format;
int ret;
@@ -1688,16 +1786,19 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
memcpy(cdrom[id].current_cdb, cdb, cdrom[id].cdb_len);
cdrom_log("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, %i, Unit attention: %i\n", id, cdb[0], cdrom_sense_key, cdrom_asc, cdrom_ascq, ins, cdrom[id].unit_attention);
cdrom_log("CD-ROM %i: Request length: %04X\n", id, cdrom[id].request_length);
#if 0
int CdbLength;
for (CdbLength = 1; CdbLength < cdrom[id].cdb_len; CdbLength++)
if (cdb[0] != 0)
{
cdrom_log("CD-ROM %i: CDB[%d] = 0x%02X\n", id, CdbLength, cdb[CdbLength]);
}
cdrom_log("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, %i, Unit attention: %i\n", id, cdb[0], cdrom_sense_key, cdrom_asc, cdrom_ascq, ins, cdrom[id].unit_attention);
cdrom_log("CD-ROM %i: Request length: %04X\n", id, cdrom[id].request_length);
#if 0
int CdbLength;
for (CdbLength = 1; CdbLength < cdrom[id].cdb_len; CdbLength++)
{
cdrom_log("CD-ROM %i: CDB[%d] = 0x%02X\n", id, CdbLength, cdb[CdbLength]);
}
#endif
}
msf = cdb[1] & 2;
cdrom[id].sector_len = 0;
@@ -1754,7 +1855,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
if (cdrom_drives[id].handler->pass_through)
{
ret = cdrom_pass_through(id, &len);
ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb);
if (!ret)
{
return;
@@ -1894,7 +1995,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
case GPCMD_READ_HEADER:
if (cdrom_drives[id].handler->pass_through)
{
ret = cdrom_pass_through(id, &len);
ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb);
if (!ret)
{
return;
@@ -1927,6 +2028,15 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
case GPCMD_MODE_SENSE_6:
case GPCMD_MODE_SENSE_10:
if (cdrom_drives[id].bus_type)
{
block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1;
}
else
{
block_desc = 0;
}
if (cdb[0] == GPCMD_MODE_SENSE_6)
{
len = cdb[4];
@@ -1947,30 +2057,44 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
if (cdb[0] == GPCMD_MODE_SENSE_6)
{
len = cdrom_mode_sense(id, cdbufferb, 4, cdb[2]);
cdbufferb[0] = len - 1;
cdbufferb[1] = 3; /*120mm data CD-ROM*/
len = cdrom_mode_sense(id, cdbufferb, 4, cdb[2], block_desc);
if (len > alloc_length)
{
len = alloc_length;
}
cdbufferb[0] = len - 1;
cdbufferb[1] = cdrom_drives[id].handler->media_type_id(id);
if (block_desc)
{
cdbufferb[3] = 8;
}
}
else
{
len = cdrom_mode_sense(id, cdbufferb, 8, cdb[2]);
len = cdrom_mode_sense(id, cdbufferb, 8, cdb[2], block_desc);
if (len > alloc_length)
{
len = alloc_length;
}
cdbufferb[0]=(len - 2) >> 8;
cdbufferb[1]=(len - 2) & 255;
cdbufferb[2] = 3; /*120mm data CD-ROM*/
if (len > alloc_length)
cdbufferb[2] = cdrom_drives[id].handler->media_type_id(id);
if (block_desc)
{
len = alloc_length;
cdbufferb[6] = 0;
cdbufferb[7] = 8;
}
}
if (len > alloc_length)
{
len = alloc_length;
}
else if (len < alloc_length)
{
alloc_length = len;
}
cdrom_log("CD-ROM %i: Reading mode page: %02X...\n", id, cdb[2]);
cdrom_data_command_finish(id, len, len, alloc_length, 0);
@@ -2105,7 +2229,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
if (cdrom_drives[id].handler->pass_through)
{
ret = cdrom_pass_through(id, &len);
ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb);
if (!ret)
{
return;
@@ -2145,7 +2269,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
if (cdrom_drives[id].handler->pass_through)
{
ret = cdrom_pass_through(id, &len);
ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb);
if (!ret)
{
return;
@@ -2246,11 +2370,12 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
max_len = cdb[7];
max_len <<= 8;
max_len |= cdb[8];
msf = (cdb[1] >> 1) & 1;
cdrom_log("CD-ROM %i: Getting page %i\n", id, cdb[3]);
if ((cdrom_drives[id].handler->pass_through) && (cdb[3] != 1))
{
ret = cdrom_pass_through(id, &len);
ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb);
if (!ret)
{
return;
@@ -2264,15 +2389,11 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
case CD_STATUS_PAUSED:
cdbufferb[1] = 0x12;
break;
case CD_STATUS_DATA_ONLY:
cdbufferb[1] = 0x15;
break;
default:
if (completed)
{
cdbufferb[1] = 0x13;
}
else
{
cdbufferb[1] = 0x15;
}
cdbufferb[1] = 0x13;
break;
}
if (len == 65534)
@@ -2322,9 +2443,20 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
if (cdb[3] == 1)
{
cdbufferb[1] = cdrom_drives[id].handler->getcurrentsubchannel(id, &cdbufferb[5], msf);
if (((cdbufferb[1] == 0x13) && !completed) || (cdrom[id].cd_status == CD_STATUS_DATA_ONLY))
switch(cdrom[id].cd_status)
{
cdbufferb[1] = 0x15;
case CD_STATUS_PLAYING:
cdbufferb[1] = 0x11;
break;
case CD_STATUS_PAUSED:
cdbufferb[1] = 0x12;
break;
case CD_STATUS_DATA_ONLY:
cdbufferb[1] = 0x15;
break;
default:
cdbufferb[1] = 0x13;
break;
}
}
if (!(cdb[2] & 0x40) || (cdb[3] == 0))
@@ -2343,7 +2475,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
case GPCMD_READ_DVD_STRUCTURE:
if (cdrom_drives[id].handler->pass_through)
{
ret = cdrom_pass_through(id, &len);
ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb);
if (!ret)
{
return;
@@ -2559,28 +2691,9 @@ atapi_out:
break;
case GPCMD_READ_CDROM_CAPACITY:
if (cdrom_drives[id].handler->pass_through)
if (cdrom_read_capacity(id, cdrom[id].current_cdb, cdbufferb, &len) == 0)
{
ret = cdrom_pass_through(id, &len);
if (!ret)
{
return;
}
if (len == 65534)
{
len = 8;
}
}
else
{
size = cdrom_drives[id].handler->size(id) - 1; /* IMPORTANT: What's returned is the last LBA block. */
memset(cdbufferb, 0, 8);
cdbufferb[0] = (size >> 24) & 0xff;
cdbufferb[1] = (size >> 16) & 0xff;
cdbufferb[2] = (size >> 8) & 0xff;
cdbufferb[3] = size & 0xff;
cdbufferb[6] = 8; /* 2048 = 0x0800 */
len = 8;
return;
}
cdrom_data_command_finish(id, len, len, len, 0);
@@ -3037,6 +3150,8 @@ void cdrom_write(uint8_t channel, uint32_t val, int length)
uint16_t *cdbufferw;
uint32_t *cdbufferl;
uint8_t old_pos = 0;
uint8_t id = atapi_cdrom_drives[channel];
int ret = 0;
@@ -3050,6 +3165,8 @@ void cdrom_write(uint8_t channel, uint32_t val, int length)
cdbufferw = cdrom[id].buffer;
cdbufferl = (uint32_t *) cdrom[id].buffer;
old_pos = cdrom[id].pos;
switch(length)
{
case 1:
@@ -3072,7 +3189,7 @@ void cdrom_write(uint8_t channel, uint32_t val, int length)
{
for (i = 0; i < length; i++)
{
ret = cdrom_mode_select_write(id, val);
ret = cdrom_mode_select_write(id, cdbufferb[old_pos + i]);
cdrom_mode_select_return(id, ret);
}
return;

View File

@@ -24,6 +24,7 @@ typedef struct CDROM
{
int (*ready)(uint8_t id);
int (*medium_changed)(uint8_t id);
int (*media_type_id)(uint8_t id);
void (*audio_callback)(uint8_t id, int16_t *output, int len);
void (*audio_stop)(uint8_t id);
int (*readtoc)(uint8_t id, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single);
@@ -110,6 +111,7 @@ typedef struct __attribute__((__packed__))
int all_blocks_total;
int old_len;
int block_descriptor_len;
} cdrom_t;
extern cdrom_t cdrom[CDROM_NUM];

View File

@@ -85,7 +85,6 @@ void piix_write(int func, int addr, uint8_t val, void *priv)
{
uint16_t base = (card_piix_ide[0x20] & 0xf0) | (card_piix_ide[0x21] << 8);
io_removehandler(old_base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL);
pclog("Setting PIIX IDE bus master to new base address: %04X\n", base);
if (card_piix_ide[0x04] & 1)
{
io_sethandler(base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL);

View File

@@ -109,15 +109,15 @@ static void sound_cd_thread(void *param)
{
int i = 0;
while (1)
{
int c, has_audio;
thread_wait_event(sound_cd_event, -1);
while (1)
{
int c, has_audio;
thread_wait_event(sound_cd_event, -1);
for (c = 0; c < CD_BUFLEN*2; c += 2)
{
cd_out_buffer[c] = 0;
cd_out_buffer[c+1] = 0;
cd_out_buffer[c] = 0.0;
cd_out_buffer[c+1] = 0.0;
}
for (i = 0; i < CDROM_NUM; i++)
{
@@ -127,57 +127,63 @@ static void sound_cd_thread(void *param)
cdrom_drives[i].handler->audio_callback(i, cd_buffer[i], CD_BUFLEN*2);
has_audio = cdrom_drives[i].sound_on;
}
if (soundon && has_audio)
{
int32_t audio_vol_l = cdrom_mode_sense_get_volume(i, 0);
int32_t audio_vol_r = cdrom_mode_sense_get_volume(i, 1);
int channel_select[2];
channel_select[0] = cdrom_mode_sense_get_channel(i, 0);
channel_select[1] = cdrom_mode_sense_get_channel(i, 1);
for (c = 0; c < CD_BUFLEN*2; c += 2)
{
int32_t cd_buffer_temp[2] = {0, 0};
if (soundon && has_audio)
{
int32_t audio_vol_l = cdrom_mode_sense_get_volume(i, 0);
int32_t audio_vol_r = cdrom_mode_sense_get_volume(i, 1);
int channel_select[2];
/*First, adjust input from drive according to ATAPI/SCSI volume.*/
cd_buffer[i][c] = ((int32_t)cd_buffer[i][c] * audio_vol_l) / 255;
cd_buffer[i][c+1] = ((int32_t)cd_buffer[i][c+1] * audio_vol_r) / 255;
channel_select[0] = cdrom_mode_sense_get_channel(i, 0);
channel_select[1] = cdrom_mode_sense_get_channel(i, 1);
/*Apply ATAPI channel select*/
if (channel_select[0] & 1)
cd_buffer_temp[0] += cd_buffer[i][c];
if (channel_select[0] & 2)
cd_buffer_temp[1] += cd_buffer[i][c];
if (channel_select[1] & 1)
cd_buffer_temp[0] += cd_buffer[i][c+1];
if (channel_select[1] & 2)
cd_buffer_temp[1] += cd_buffer[i][c+1];
/*Apply sound card CD volume*/
cd_buffer_temp[0] = (cd_buffer_temp[0] * (int)cd_vol_l) / 65535;
cd_buffer_temp[1] = (cd_buffer_temp[1] * (int)cd_vol_r) / 65535;
for (c = 0; c < CD_BUFLEN*2; c += 2)
{
float cd_buffer_temp[2] = {0.0, 0.0};
float cd_buffer_temp2[2] = {0.0, 0.0};
if (cd_buffer_temp[0] > 32767)
cd_buffer_temp[0] = 32767;
if (cd_buffer_temp[0] < -32768)
cd_buffer_temp[0] = -32768;
if (cd_buffer_temp[1] > 32767)
cd_buffer_temp[1] = 32767;
if (cd_buffer_temp[1] < -32768)
cd_buffer_temp[1] = -32768;
/* First, transfer the CD audio data to the temporary buffer. */
cd_buffer_temp[0] = (float) cd_buffer[i][c];
cd_buffer_temp[1] = (float) cd_buffer[i][c+1];
/* Then, adjust input from drive according to ATAPI/SCSI volume. */
cd_buffer_temp[0] *= (float) audio_vol_l;
cd_buffer_temp[0] /= 255.0;
cd_buffer_temp[1] *= (float) audio_vol_r;
cd_buffer_temp[1] /= 255.0;
cd_buffer[i][c] = cd_buffer_temp[0];
cd_buffer[i][c+1] = cd_buffer_temp[1];
/*Apply ATAPI channel select*/
cd_buffer_temp2[0] = cd_buffer_temp2[1] = 0.0;
if (channel_select[0] & 1)
{
cd_buffer_temp2[0] += cd_buffer_temp[0];
}
if (channel_select[0] & 2)
{
cd_buffer_temp2[1] += cd_buffer_temp[0];
}
if (channel_select[1] & 1)
{
cd_buffer_temp2[0] += cd_buffer_temp[1];
}
if (channel_select[1] & 2)
{
cd_buffer_temp2[1] += cd_buffer_temp[1];
}
cd_out_buffer[c] += ((float) cd_buffer[i][c]) / 32768.0;
cd_out_buffer[c+1] += ((float) cd_buffer[i][c+1]) / 32768.0;
}
/*Apply sound card CD volume*/
cd_buffer_temp2[0] *= (float) cd_vol_l;
cd_buffer_temp2[0] /= 65535.0;
}
cd_buffer_temp2[1] *= (float) cd_vol_r;
cd_buffer_temp2[1] /= 65535.0;
cd_out_buffer[c] += (cd_buffer_temp2[0] / 32768.0);
cd_out_buffer[c+1] += (cd_buffer_temp2[1] / 32768.0);
}
}
}
givealbuffer_cd(cd_out_buffer);
}
}
}
static int32_t *outbuffer;