Both SCSI controllers now set the next callback to be issued after 1000 * TIMER_USEC instead of 50 * TIMER_USEC if the device is CD-ROM and the command is 0x42 (READ SUBCHANNEL);

A few CD-ROM IOCTL commands are cached now;
CD Audio over IOCTL works again;
The status bar icons are now only loaded once at emulator start, and subsequently just used on demand.
This commit is contained in:
OBattler
2017-05-11 06:34:25 +02:00
parent 08cf490f3f
commit 18e2110739
6 changed files with 121 additions and 39 deletions

View File

@@ -107,6 +107,11 @@ static int get_track_nr(uint8_t id, uint32_t pos)
return 0;
}
if (cdrom_ioctl[id].last_track_pos == pos)
{
return cdrom_ioctl[id].last_track_nr;
}
for (c = cdrom_ioctl_windows[id].toc.FirstTrack; c < cdrom_ioctl_windows[id].toc.LastTrack; c++)
{
uint32_t track_address = cdrom_ioctl_windows[id].toc.TrackData[c].Address[3] +
@@ -118,6 +123,9 @@ static int get_track_nr(uint8_t id, uint32_t pos)
track = c;
}
}
cdrom_ioctl[id].last_track_pos = pos;
cdrom_ioctl[id].last_track_nr = track;
return track;
}
@@ -349,19 +357,35 @@ static uint8_t ioctl_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf)
CDROM_SUB_Q_DATA_FORMAT insub;
SUB_Q_CHANNEL_DATA sub;
unsigned long size;
int pos=0;
int pos = 0, track;
uint32_t cdpos, track_address, dat;
if (!cdrom_drives[id].host_drive) return 0;
insub.Format = IOCTL_CDROM_CURRENT_POSITION;
ioctl_open(id, 0);
DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL,&insub,sizeof(insub),&sub,sizeof(sub),&size,NULL);
ioctl_close(id);
cdpos = cdrom[id].seek_pos;
if (cdrom_ioctl[id].last_subchannel_pos == cdpos)
{
memcpy(&insub, cdrom_ioctl[id].sub_q_data_format, sizeof(insub));
memcpy(&sub, cdrom_ioctl[id].sub_q_channel_data, sizeof(sub));
}
else
{
insub.Format = IOCTL_CDROM_CURRENT_POSITION;
ioctl_open(id, 0);
DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL,&insub,sizeof(insub),&sub,sizeof(sub),&size,NULL);
ioctl_close(id);
memset(cdrom_ioctl[id].sub_q_data_format, 0, 16);
memcpy(cdrom_ioctl[id].sub_q_data_format, &insub, sizeof(insub));
memset(cdrom_ioctl[id].sub_q_channel_data, 0, 256);
memcpy(cdrom_ioctl[id].sub_q_channel_data, &sub, sizeof(sub));
cdrom_ioctl[id].last_subchannel_pos = cdpos;
}
if (cdrom_ioctl[id].cd_state == CD_PLAYING || cdrom_ioctl[id].cd_state == CD_PAUSED)
{
uint32_t cdpos = cdrom[id].seek_pos;
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);
track = get_track_nr(id, cdpos);
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);
cdrom_ioctl_log("cdpos = %i, track = %i, track_address = %i\n", cdpos, track, track_address);
@@ -371,7 +395,7 @@ static uint8_t ioctl_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf)
if (msf)
{
uint32_t dat = cdpos;
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;
@@ -709,11 +733,19 @@ static void ioctl_read_capacity(uint8_t id, uint8_t *b)
const UCHAR cdb[] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
UCHAR buf[16];
ioctl_open(id, 0);
if (!cdrom_ioctl[id].capacity_read)
{
ioctl_open(id, 0);
SCSICommand(id, cdb, buf, &len, 1);
SCSICommand(id, cdb, buf, &len, 1);
memcpy(b, buf, len);
memcpy(cdrom_ioctl[id].rcbuf, buf, len);
cdrom_ioctl[id].capacity_read = 1;
}
else
{
memcpy(b, cdrom_ioctl[id].rcbuf, 16);
}
ioctl_close(id);
}
@@ -1016,10 +1048,12 @@ int ioctl_open(uint8_t id, char d)
if (!cdrom_ioctl[id].ioctl_inited)
{
cdrom_ioctl[id].ioctl_inited=1;
cdrom_ioctl[id].capacity_read=0; /* With this two lines, we read the READ CAPACITY command output from the host drive into our cache buffer. */
ioctl_read_capacity(id, NULL);
CloseHandle(cdrom_ioctl_windows[id].hIOCTL);
cdrom_ioctl_windows[id].hIOCTL = NULL;
update_status_bar_icon_state(0x10 | id, 0);
}
update_status_bar_icon_state(0x10 | id, 0);
return 0;
}

View File

@@ -2953,7 +2953,11 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
alloc_length = 24;
break;
}
if (alloc_length < len)
if (!(cdb[2] & 0x40) || (cdb[3] == 0))
{
len = 4;
}
else
{
len = alloc_length;
}

View File

@@ -199,6 +199,13 @@ typedef struct
int16_t cd_buffer[BUF_SIZE];
int cd_buflen;
int actual_requested_blocks;
int last_track_pos;
int last_track_nr;
int capacity_read;
uint8_t rcbuf[16];
uint8_t sub_q_data_format[16];
uint8_t sub_q_channel_data[256];
int last_subchannel_pos;
} cdrom_ioctl_t;
void ioctl_close(uint8_t id);

View File

@@ -2156,6 +2156,12 @@ aha_cmd_cb(void *priv)
} else if (AHA_InOperation == 1) {
pclog("BusLogic Callback: Process CD-ROM request\n");
aha_cdrom_cmd(dev);
if (dev->Req.CmdBlock.common.Cdb[0] == 0x42)
{
/* This is needed since CD Audio inevitably means READ SUBCHANNEL spam. */
AHA_Callback += 1000 * SCSI_TIME;
return;
}
} else if (AHA_InOperation == 2) {
pclog("BusLogic Callback: Send incoming mailbox\n");
aha_mbi(dev);

View File

@@ -1970,6 +1970,12 @@ BuslogicCommandCallback(void *p)
} else if (BuslogicInOperation == 1) {
pclog("BusLogic Callback: Process CD-ROM request\n");
BuslogicCDROMCommand(bl);
if (bl->Req.CmdBlock.common.Cdb[0] == 0x42)
{
/* This is needed since CD Audio inevitably means READ SUBCHANNEL spam. */
BuslogicCallback += 1000 * SCSI_TIME;
return;
}
} else if (BuslogicInOperation == 2) {
pclog("BusLogic Callback: Send incoming mailbox\n");
BuslogicMailboxIn(bl);

View File

@@ -617,7 +617,7 @@ HANDLE hinstAcc;
HICON LoadIconEx(PCTSTR pszIconName)
{
return (HICON) LoadImage(hinstance, pszIconName, IMAGE_ICON, 16, 16, 0);
return (HICON) LoadImage(hinstance, pszIconName, IMAGE_ICON, 16, 16, LR_SHARED);
}
HICON LoadIconBig(PCTSTR pszIconName)
@@ -722,9 +722,7 @@ void update_status_bar_icon(int tag, int active)
sb_part_icons[found] &= ~257;
sb_part_icons[found] |= sb_icon_flags[found];
DestroyIcon(hIcon[found]);
hIcon[found] = LoadIconEx((PCTSTR) sb_part_icons[found]);
SendMessage(hwndStatus, SB_SETICON, found, (LPARAM) hIcon[found]);
SendMessage(hwndStatus, SB_SETICON, found, (LPARAM) hIcon[sb_part_icons[found]]);
}
}
}
@@ -751,29 +749,13 @@ void update_status_bar_icon_state(int tag, int state)
if (found != -1)
{
if (state)
{
switch(tag & 0xf0)
{
case 0x00:
default:
discfns[tag & 0x0f][0] = L'\0';
break;
case 0x10:
cdrom_image[tag & 0x0f].image_path[0] = L'\0';
break;
}
}
sb_icon_flags[found] &= ~256;
sb_icon_flags[found] |= state ? 256 : 0;
sb_part_icons[found] &= ~257;
sb_part_icons[found] |= sb_icon_flags[found];
DestroyIcon(hIcon[found]);
hIcon[found] = LoadIconEx((PCTSTR) sb_part_icons[found]);
SendMessage(hwndStatus, SB_SETICON, found, (LPARAM) hIcon[found]);
SendMessage(hwndStatus, SB_SETICON, found, (LPARAM) hIcon[sb_part_icons[found]]);
}
}
@@ -1052,9 +1034,7 @@ void update_status_bar_panes(HWND hwnds)
if (sb_part_icons[i] != -1)
{
SendMessage(hwnds, SB_SETTEXT, i | SBT_NOBORDERS, (LPARAM) "");
DestroyIcon(hIcon[i]);
hIcon[i] = LoadIconEx((PCTSTR) sb_part_icons[i]);
SendMessage(hwnds, SB_SETICON, i, (LPARAM) hIcon[i]);
SendMessage(hwnds, SB_SETICON, i, (LPARAM) hIcon[sb_part_icons[i]]);
SendMessage(hwnds, SB_SETTIPTEXT, i, (LPARAM) sbTips[i]);
/* pclog("Status bar part found: %02X (%i)\n", sb_part_meanings[i], sb_part_icons[i]); */
}
@@ -1072,6 +1052,51 @@ HWND EmulatorStatusBar(HWND hwndParent, int idStatus, HINSTANCE hinst)
RECT rectDialog;
int dw, dh;
for (i = 128; i < 136; i++)
{
hIcon[i] = LoadIconEx((PCTSTR) i);
}
for (i = 144; i < 148; i++)
{
hIcon[i] = LoadIconEx((PCTSTR) i);
}
for (i = 150; i < 154; i++)
{
hIcon[i] = LoadIconEx((PCTSTR) i);
}
for (i = 160; i < 166; i++)
{
hIcon[i] = LoadIconEx((PCTSTR) i);
}
for (i = 176; i < 184; i++)
{
hIcon[i] = LoadIconEx((PCTSTR) i);
}
for (i = 384; i < 392; i++)
{
hIcon[i] = LoadIconEx((PCTSTR) i);
}
for (i = 400; i < 404; i++)
{
hIcon[i] = LoadIconEx((PCTSTR) i);
}
for (i = 406; i < 410; i++)
{
hIcon[i] = LoadIconEx((PCTSTR) i);
}
for (i = 416; i < 422; i++)
{
hIcon[i] = LoadIconEx((PCTSTR) i);
}
GetWindowRect(hwndParent, &rectDialog);
dw = rectDialog.right - rectDialog.left;
dh = rectDialog.bottom - rectDialog.top;