From 18e21107392ab927d7dc362c826c5859dc7ca069 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 11 May 2017 06:34:25 +0200 Subject: [PATCH] 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. --- src/cdrom-ioctl.c | 62 +++++++++++++++++++++++++++++--------- src/cdrom.c | 6 +++- src/cdrom.h | 7 +++++ src/scsi_aha154x.c | 6 ++++ src/scsi_buslogic.c | 6 ++++ src/win.c | 73 ++++++++++++++++++++++++++++++--------------- 6 files changed, 121 insertions(+), 39 deletions(-) diff --git a/src/cdrom-ioctl.c b/src/cdrom-ioctl.c index 3534dd2e2..98c7cc538 100644 --- a/src/cdrom-ioctl.c +++ b/src/cdrom-ioctl.c @@ -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; } diff --git a/src/cdrom.c b/src/cdrom.c index bb286451f..74968157d 100644 --- a/src/cdrom.c +++ b/src/cdrom.c @@ -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; } diff --git a/src/cdrom.h b/src/cdrom.h index 678b64086..a3a3a69a9 100644 --- a/src/cdrom.h +++ b/src/cdrom.h @@ -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); diff --git a/src/scsi_aha154x.c b/src/scsi_aha154x.c index 316679ab8..615bd8675 100644 --- a/src/scsi_aha154x.c +++ b/src/scsi_aha154x.c @@ -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); diff --git a/src/scsi_buslogic.c b/src/scsi_buslogic.c index c5155d4ea..11a4d3d27 100644 --- a/src/scsi_buslogic.c +++ b/src/scsi_buslogic.c @@ -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); diff --git a/src/win.c b/src/win.c index 049b0cbc0..4d7bc0631 100644 --- a/src/win.c +++ b/src/win.c @@ -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;