From: Toni Wilen Date: Sun, 18 Jul 2010 15:19:39 +0000 (+0300) Subject: 2210b4 X-Git-Tag: 2300~21 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=7ad2c4c4250d89fa465e434f5a1d312ba1604043;p=francis%2Fwinuae.git 2210b4 --- diff --git a/a2091.cpp b/a2091.cpp index fe1b4816..2a07e7af 100644 --- a/a2091.cpp +++ b/a2091.cpp @@ -1225,23 +1225,23 @@ static void freenativescsi (void) static void addnativescsi (void) { int i, j; - int devices[MAX_TOTAL_DEVICES]; - int types[MAX_TOTAL_DEVICES]; - struct device_info dis[MAX_TOTAL_DEVICES]; + int devices[MAX_TOTAL_SCSI_DEVICES]; + int types[MAX_TOTAL_SCSI_DEVICES]; + struct device_info dis[MAX_TOTAL_SCSI_DEVICES]; freenativescsi (); i = 0; - while (i < MAX_TOTAL_DEVICES) { + while (i < MAX_TOTAL_SCSI_DEVICES) { types[i] = -1; devices[i] = -1; - if (sys_command_open (DF_SCSI, i)) { - if (sys_command_info (DF_SCSI, i, &dis[i], 0)) { + if (sys_command_open (i)) { + if (sys_command_info (i, &dis[i], 0)) { devices[i] = i; types[i] = 100 - i; if (dis[i].type == INQ_ROMD) types[i] = 1000 - i; } - sys_command_close (DF_SCSI, i); + sys_command_close (i); } i++; } diff --git a/akiko.cpp b/akiko.cpp index c3a7396d..22f75292 100644 --- a/akiko.cpp +++ b/akiko.cpp @@ -454,9 +454,9 @@ static void cdaudiostop_do (void) cdrom_paused = 0; if (unitnum < 0) return; - sys_command_cd_pause (DF_IOCTL, unitnum, 0); - sys_command_cd_stop (DF_IOCTL, unitnum); - sys_command_cd_pause (DF_IOCTL, unitnum, 1); + sys_command_cd_pause (unitnum, 0); + sys_command_cd_stop (unitnum); + sys_command_cd_pause (unitnum, 1); } static void cdaudiostop (void) @@ -512,7 +512,8 @@ static void cdaudioplay_do (void) qcode_valid = 0; if (unitnum < 0) return; - sys_command_cd_play (DF_IOCTL, unitnum, startlsn, endlsn, scan, subfunc); + sys_command_cd_pause (unitnum, 0); + sys_command_cd_play (unitnum, startlsn, endlsn, scan, subfunc); } static bool isaudiotrack (int startlsn) @@ -623,17 +624,14 @@ static int get_cdrom_toc (void) { int j; int datatrack = 0, secondtrack = 0; - struct cd_toc_head *th; cdrom_toc_counter = -1; - th = sys_command_cd_toc (DF_IOCTL, unitnum); - if (!th) + if (!sys_command_cd_toc (unitnum, &cdrom_toc_cd_buffer)) return 1; - memcpy (&cdrom_toc_cd_buffer, th, sizeof cdrom_toc_cd_buffer); memset (cdrom_toc_buffer, 0, MAX_TOC_ENTRIES * 13); cdrom_data_end = -1; - for (j = 0; j < th->points; j++) { - struct cd_toc *s = &th->toc[j]; + for (j = 0; j < cdrom_toc_cd_buffer.points; j++) { + struct cd_toc *s = &cdrom_toc_cd_buffer.toc[j]; uae_u8 *d = &cdrom_toc_buffer[j * 13]; int addr = s->paddress; int msf = lsn2msf (addr); @@ -666,32 +664,34 @@ static int sys_cddev_open (void) struct device_info di1, *di2; int cd32unit = -1; int audiounit = -1; - int opened[MAX_TOTAL_DEVICES]; + int opened[MAX_TOTAL_SCSI_DEVICES]; int i; - for (unitnum = 0; unitnum < MAX_TOTAL_DEVICES; unitnum++) { + for (unitnum = 0; unitnum < MAX_TOTAL_SCSI_DEVICES; unitnum++) { opened[unitnum] = 0; - if (sys_command_open (DF_IOCTL, unitnum)) { + if (sys_command_open (unitnum)) { opened[unitnum] = 1; - di2 = sys_command_info (DF_IOCTL, unitnum, &di1, 0); + di2 = sys_command_info (unitnum, &di1, 0); if (di2 && di2->type == INQ_ROMD) { write_log (L"%s: ", di2->label); if (first < 0) first = unitnum; if (!get_cdrom_toc ()) { if (cdrom_data_end > 0) { - uae_u8 *p = sys_command_cd_read (DF_IOCTL, unitnum, NULL, 16, 1); - if (p) { + uae_u8 buffer[2048]; + if (sys_command_cd_read (unitnum, buffer, 16, 1)) { + uae_u8 *p = buffer; if (!memcmp (p + 8, "CDTV", 4) || !memcmp (p + 8, "CD32", 4)) { uae_u32 crc; write_log (L"CD32 or CDTV"); if (cd32unit < 0) cd32unit = unitnum; - p = sys_command_cd_read (DF_IOCTL, unitnum, NULL, 21, 1); - crc = get_crc32 (p, 2048); - if (crc == 0xe56c340f) - write_log (L" [CD32.TM]"); - write_log (L"\n"); + if (sys_command_cd_read (unitnum, buffer, 21, 1)) { + crc = get_crc32 (buffer, 2048); + if (crc == 0xe56c340f) + write_log (L" [CD32.TM]"); + write_log (L"\n"); + } } else { write_log (L"non CD32/CDTV data CD\n"); } @@ -716,19 +716,19 @@ static int sys_cddev_open (void) unitnum = first; if (unitnum >= 0) opened[unitnum] = 0; - for (i = 0; i < MAX_TOTAL_DEVICES; i++) { + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { if (opened[i]) - sys_command_close (DF_IOCTL, i); + sys_command_close (i); } if (unitnum < 0) return 1; - di2 = sys_command_info (DF_IOCTL, unitnum, &di1, 0); + di2 = sys_command_info (unitnum, &di1, 0); if (!di2) { write_log (L"unit %d info failed\n", unitnum); - sys_command_close (DF_IOCTL, unitnum); + sys_command_close (unitnum); return 1; } - if (sys_command_ismedia (DF_IOCTL, unitnum, 0) <= 0) + if (sys_command_ismedia (unitnum, 0) <= 0) cd_hunt = 1; write_log (L"using drive %s (unit %d, media %d)\n", di2->label, unitnum, di2->media_inserted); /* make sure CD audio is not playing */ @@ -740,7 +740,7 @@ static int sys_cddev_open (void) static void sys_cddev_close (void) { cdaudiostop_do (); - sys_command_close (DF_IOCTL, unitnum); + sys_command_close (unitnum); } static int command_lengths[] = { 1,2,1,1,12,2,1,1,4,1,-1,-1,-1,-1,-1,-1 }; @@ -806,7 +806,7 @@ static int cdrom_command_media_status (void) if (cd_hunt) { cdrom_result_buffer[1] = 0x80; } else { - cdrom_result_buffer[1] = sys_command_ismedia (DF_IOCTL, unitnum, 0) > 0 ? 0x83: 0x80; + cdrom_result_buffer[1] = sys_command_ismedia (unitnum, 0) > 0 ? 0x83: 0x80; } return 2; } @@ -1189,28 +1189,28 @@ static void akiko_internal (void) static void do_hunt (void) { int i; - for (i = 0; i < MAX_TOTAL_DEVICES; i++) { - if (sys_command_ismedia (DF_IOCTL, i, 1) > 0) + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + if (sys_command_ismedia (i, 1) > 0) break; } - if (i == MAX_TOTAL_DEVICES) { - if (unitnum >= 0 && sys_command_ismedia (DF_IOCTL, unitnum, 1) >= 0) + if (i == MAX_TOTAL_SCSI_DEVICES) { + if (unitnum >= 0 && sys_command_ismedia (unitnum, 1) >= 0) return; - for (i = 0; i < MAX_TOTAL_DEVICES; i++) { - if (sys_command_ismedia (DF_IOCTL, i, 1) >= 0) + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + if (sys_command_ismedia (i, 1) >= 0) break; } - if (i == MAX_TOTAL_DEVICES) + if (i == MAX_TOTAL_SCSI_DEVICES) return; } if (unitnum >= 0) { int ou = unitnum; unitnum = -1; - sys_command_close (DF_IOCTL, ou); + sys_command_close (ou); } - if (sys_command_open (DF_IOCTL, i) > 0) { + if (sys_command_open (i) > 0) { struct device_info di = { 0 }; - sys_command_info (DF_IOCTL, i, &di, 0); + sys_command_info (i, &di, 0); unitnum = i; cd_hunt = 0; lastmediastate = -1; @@ -1225,7 +1225,7 @@ void AKIKO_hsync_handler (void) if (cd_hunt) { static int huntcnt; - if (huntcnt <= 0 && !mediachanged) { + if (huntcnt <= 0 && (!mediachanged || unitnum < 0)) { do_hunt (); huntcnt = 312 * 50 * 2; } @@ -1296,7 +1296,6 @@ static void *akiko_thread (void *null) uae_u8 *tmp1; uae_u8 *tmp2; int tmp3; - uae_u8 *p; int offset; int sector; @@ -1307,19 +1306,19 @@ static void *akiko_thread (void *null) switch (b) { case 0x0102: // pause - sys_command_cd_pause (DF_IOCTL, unitnum, 1); + sys_command_cd_pause (unitnum, 1); break; case 0x0103: // unpause - sys_command_cd_pause (DF_IOCTL, unitnum, 0); + sys_command_cd_pause (unitnum, 0); break; case 0x0104: // stop cdaudiostop_do (); break; case 0x0105: // mute change - sys_command_cd_volume (DF_IOCTL, unitnum, cdrom_muted ? 0 : 0xffff); + sys_command_cd_volume (unitnum, cdrom_muted ? 0 : 0x7fff, cdrom_muted ? 0 : 0x7fff); break; case 0x0110: // do_play! - sys_command_cd_volume (DF_IOCTL, unitnum, cdrom_muted ? 0 : 0xffff); + sys_command_cd_volume (unitnum, cdrom_muted ? 0 : 0x7fff, cdrom_muted ? 0 : 0x7fff); cdaudioplay_do (); break; } @@ -1327,7 +1326,7 @@ static void *akiko_thread (void *null) if (frame2counter <= 0) { frame2counter = 312 * 50 / 2; - if (sys_command_cd_qcode (DF_IOCTL, unitnum, qcode_buf)) { + if (unitnum >= 0 && sys_command_cd_qcode (unitnum, qcode_buf)) { uae_u8 as = qcode_buf[1]; qcode_valid = 1; if (as == AUDIO_STATUS_IN_PROGRESS) { @@ -1343,14 +1342,14 @@ static void *akiko_thread (void *null) if (mediacheckcounter <= 0) { mediacheckcounter = 312 * 50 * 2; - int media = sys_command_ismedia (DF_IOCTL, unitnum, 1); + int media = sys_command_ismedia (unitnum, 1); if (media < 0) { if (!cd_hunt) { - cd_hunt = 1; write_log (L"CD32: device unit %d lost\n", unitnum); media = lastmediastate = cdrom_disk = 0; mediachanged = 1; cdaudiostop_do (); + cd_hunt = 1; } } else if (media != lastmediastate) { write_log (L"CD32: media changed = %d (hunt=%d)\n", media, cd_hunt); @@ -1375,12 +1374,10 @@ static void *akiko_thread (void *null) sector_buffer_sector_2 = sector; offset = 0; while (offset < SECTOR_BUFFER_SIZE) { - p = 0; + int ok = 0; if (sector < cdrom_data_end) - p = sys_command_cd_read (DF_IOCTL, unitnum, NULL, sector, 1); - if (p) - memcpy (sector_buffer_2 + offset * 2048, p, 2048); - sector_buffer_info_2[offset] = p ? 3 : 0; + ok = sys_command_cd_read (unitnum, sector_buffer_2 + offset * 2048, sector, 1); + sector_buffer_info_2[offset] = ok ? 3 : 0; offset++; sector++; } @@ -1767,7 +1764,7 @@ int akiko_init (void) { if (currprefs.cs_cd32cd && cdromok == 0) { unitnum = -1; - if (!device_func_init (DEVICE_TYPE_IOCTL)) { + if (!device_func_init (0)) { write_log (L"no CDROM support\n"); return 0; } diff --git a/blkdev.cpp b/blkdev.cpp index 5369750e..1b34842e 100644 --- a/blkdev.cpp +++ b/blkdev.cpp @@ -13,13 +13,14 @@ #include "blkdev.h" #include "scsidev.h" #include "savestate.h" +#ifdef RETROPLATFORM +#include "rp.h" +#endif -static int scsiemu; +static int scsiemu[MAX_TOTAL_SCSI_DEVICES]; -static struct device_functions *device_func[2]; -static int have_ioctl; -static int openlist[MAX_TOTAL_DEVICES]; -static int forcedunit = -1; +static struct device_functions *device_func[MAX_TOTAL_SCSI_DEVICES]; +static int openlist[MAX_TOTAL_SCSI_DEVICES]; /* convert minutes, seconds and frames -> logical sector number */ int msf2lsn (int msf) @@ -59,6 +60,34 @@ void tolongbcd (uae_u8 *p, int v) p[2] = tobcd ((v >> 0) & 0xff); } +static struct cd_toc *gettoc (struct cd_toc_head *th, int block) +{ + for (int i = th->first_track_offset; i < th->last_track_offset; i++) { + struct cd_toc *t = &th->toc[i]; + if (block < t->paddress) { + if (i == th->first_track_offset) + return t; + else + return t - 1; + } + } + return &th->toc[th->last_track_offset]; +} + +int isaudiotrack (struct cd_toc_head *th, int block) +{ + struct cd_toc *t = gettoc (th, block); + if (!t) + return 0; + return (t->control & 0x0c) != 4; +} +int isdatatrack (struct cd_toc_head *th, int block) +{ + return !isaudiotrack (th, block); +} + +static int cdscsidevicetype[MAX_TOTAL_SCSI_DEVICES]; + #ifdef _WIN32 #include "od-win32/win32.h" @@ -68,173 +97,290 @@ extern struct device_functions devicefunc_win32_spti; extern struct device_functions devicefunc_win32_ioctl; extern struct device_functions devicefunc_cdimage; +static struct device_functions *devicetable[] = { + NULL, + &devicefunc_cdimage, + &devicefunc_win32_ioctl, + &devicefunc_win32_spti, + &devicefunc_win32_aspi, + NULL +}; +static int driver_installed[6]; + static void install_driver (int flags) { - scsiemu = 0; - device_func[DF_IOCTL] = NULL; - device_func[DF_SCSI] = NULL; - if (devicefunc_cdimage.checkbus (flags | DEVICE_TYPE_CHECKAVAIL)) { - device_func[DF_IOCTL] = &devicefunc_cdimage; - device_func[DF_SCSI] = &devicefunc_cdimage; - scsiemu = 1; - return; + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + scsiemu[i] = false; + device_func[i] = NULL; + switch (cdscsidevicetype[i]) + { + case SCSI_UNIT_IMAGE: + device_func[i] = devicetable[SCSI_UNIT_IMAGE]; + scsiemu[i] = true; + break; + case SCSI_UNIT_IOCTL: + device_func[i] = devicetable[SCSI_UNIT_IOCTL]; + scsiemu[i] = true; + break; + case SCSI_UNIT_SPTI: + if (currprefs.win32_uaescsimode == UAESCSI_CDEMU) { + device_func[i] = devicetable[SCSI_UNIT_IOCTL]; + scsiemu[i] = true; + } else { + device_func[i] = devicetable[SCSI_UNIT_SPTI]; + } + break; + case SCSI_UNIT_ASPI: + device_func[i] = devicetable[SCSI_UNIT_ASPI]; + break; + } } -#ifdef WINDDK - if (!device_func[DF_IOCTL]) - device_func[DF_IOCTL] = &devicefunc_win32_ioctl; - if (currprefs.win32_uaescsimode == UAESCSI_CDEMU) { - device_func[DF_SCSI] = &devicefunc_win32_ioctl; - scsiemu = 1; - } else if (flags != DEVICE_TYPE_IOCTL) { - device_func[DF_SCSI] = &devicefunc_win32_spti; - if (currprefs.win32_uaescsimode == UAESCSI_ADAPTECASPI || - currprefs.win32_uaescsimode == UAESCSI_NEROASPI || - currprefs.win32_uaescsimode == UAESCSI_FROGASPI) { - device_func[DF_SCSI] = &devicefunc_win32_aspi; - device_func[DF_IOCTL] = 0; + + for (int j = 1; devicetable[j]; j++) { + if (!driver_installed[j]) { + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + if (device_func[i] == devicetable[j]) { + int ok = device_func[i]->openbus (0); + driver_installed[j] = 1; + write_log (L"%s driver installed, ok=%d\n", device_func[i]->name, ok); + break; + } + } } } -#endif - if (device_func[DF_SCSI]) - device_func[DF_SCSI]->checkbus (DEVICE_TYPE_CHECKAVAIL); - if (device_func[DF_IOCTL]) - device_func[DF_IOCTL]->checkbus (DEVICE_TYPE_CHECKAVAIL); + } #endif -int sys_command_isopen (int unitnum) +void blkdev_default_prefs (struct uae_prefs *p) { - return openlist[unitnum]; + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + p->cdimagefile[i][0] = 0; + p->cdimagefileuse[i] = false; + p->cdscsidevicetype[i] = SCSI_UNIT_NONE; + cdscsidevicetype[i] = SCSI_UNIT_NONE; + } } -void sys_command_setunit (int unitnum) +void blkdev_fix_prefs (struct uae_prefs *p) { - forcedunit = unitnum; -} + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) + cdscsidevicetype[i] = p->cdscsidevicetype[i]; -int sys_command_open (int mode, int unitnum) -{ - int ret = 0; + // blkdev_win32_aspi.cpp does not support multi units + if (currprefs.win32_uaescsimode >= UAESCSI_ASPI_FIRST) { + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) + cdscsidevicetype[i] = SCSI_UNIT_ASPI; + return; + } - if (forcedunit >= 0) { - if (unitnum != forcedunit) - return 0; + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + if (cdscsidevicetype[i] != SCSI_UNIT_NONE) + continue; + if (p->cdimagefileuse[i] || p->cdimagefile[i][0]) { + TCHAR *name = p->cdimagefile[i]; + if (_tcslen (name) == 3 && name[1] == ':' && name[2] == '\\') { + if (currprefs.scsi && (currprefs.win32_uaescsimode == UAESCSI_SPTI || currprefs.win32_uaescsimode == UAESCSI_SPTISCAN)) + cdscsidevicetype[i] = SCSI_UNIT_SPTI; + else + cdscsidevicetype[i] = SCSI_UNIT_IOCTL; + } else { + cdscsidevicetype[i] = SCSI_UNIT_IMAGE; + } + } else if (currprefs.scsi) { + if (currprefs.win32_uaescsimode == UAESCSI_CDEMU) + cdscsidevicetype[i] = SCSI_UNIT_IOCTL; + else if (currprefs.win32_uaescsimode >= UAESCSI_ASPI_FIRST) + cdscsidevicetype[i] = SCSI_UNIT_ASPI; + else + cdscsidevicetype[i] = SCSI_UNIT_SPTI; + } else { + cdscsidevicetype[i] = SCSI_UNIT_IOCTL; + } } - if (mode == DF_SCSI || !have_ioctl) { - if (device_func[DF_SCSI] != NULL) - ret = device_func[DF_SCSI]->opendev (unitnum); - } else { - ret = device_func[DF_IOCTL]->opendev (unitnum); +} + + +int sys_command_isopen (int unitnum) +{ + return openlist[unitnum]; +} + +int sys_command_open (int unitnum) +{ + int ret = 0; + if (openlist[unitnum]) + write_log (L"BUG unit %d open: opencnt=%d!\n", unitnum, openlist[unitnum]); + if (device_func[unitnum]) { + ret = device_func[unitnum]->opendev (unitnum, currprefs.cdimagefile[unitnum][0] ? currprefs.cdimagefile[unitnum] : NULL); + if (ret) + openlist[unitnum]++; } - if (ret) - openlist[unitnum]++; return ret; } -void sys_command_close (int mode, int unitnum) +void sys_command_close (int unitnum) { - if (mode == DF_SCSI || !have_ioctl) { - if (device_func[DF_SCSI] != NULL) - device_func[DF_SCSI]->closedev (unitnum); - } else { - device_func[DF_IOCTL]->closedev (unitnum); + if (openlist[unitnum] <= 0) + write_log (L"BUG unit %d close: opencnt=%d!\n", unitnum, openlist[unitnum]); + if (device_func[unitnum]) { + device_func[unitnum]->closedev (unitnum); + if (openlist[unitnum] > 0) + openlist[unitnum]--; } - if (openlist[unitnum] > 0) - openlist[unitnum]--; } void device_func_reset (void) { - have_ioctl = 0; } int device_func_init (int flags) { - static int old_flags = -1; - int support_scsi = 0, support_ioctl = 0; - int oflags; - - if (flags & DEVICE_TYPE_USE_OLD) { - if (old_flags >= 0) - flags = old_flags; - else - flags &= ~DEVICE_TYPE_USE_OLD; + device_func_reset (); + blkdev_fix_prefs (&currprefs); + install_driver (flags); + return 1; +} + +static TCHAR newimagefiles[MAX_TOTAL_SCSI_DEVICES][256]; +static int imagechangetime[MAX_TOTAL_SCSI_DEVICES]; +static bool cdimagefileinuse[MAX_TOTAL_SCSI_DEVICES], wasopen[MAX_TOTAL_SCSI_DEVICES]; + +static void check_changes (int unitnum) +{ + bool changed = false; + + if (_tcscmp (changed_prefs.cdimagefile[unitnum], currprefs.cdimagefile[unitnum]) != 0) + changed = true; + if (!changed && changed_prefs.cdimagefile[unitnum][0] == 0 && changed_prefs.cdimagefileuse[unitnum] != currprefs.cdimagefileuse[unitnum]) + changed = true; + + if (changed) { + cdimagefileinuse[unitnum] = changed_prefs.cdimagefileuse[unitnum]; + _tcscpy (newimagefiles[unitnum], changed_prefs.cdimagefile[unitnum]); + changed_prefs.cdimagefile[unitnum][0] = currprefs.cdimagefile[unitnum][0] = 0; + currprefs.cdimagefileuse[unitnum] = changed_prefs.cdimagefileuse[unitnum]; + int pollmode = 0; + imagechangetime[unitnum] = 3 * 50; + struct device_info di; + device_func[unitnum]->info (unitnum, &di, 0); + wasopen[unitnum] = di.open; + if (wasopen[unitnum]) { + device_func[unitnum]->closedev (unitnum); + if (currprefs.scsi) { + scsi_do_disk_change (unitnum, 0, &pollmode); + if (pollmode) + imagechangetime[unitnum] = 8 * 50; + } + } + write_log (L"CD: eject (%s)\n", pollmode ? L"slow" : L"fast"); +#ifdef RETROPLATFORM + rp_cd_image_change (unitnum, NULL); +#endif + } + if (imagechangetime[unitnum] == 0) + return; + imagechangetime[unitnum]--; + if (imagechangetime[unitnum] > 0) + return; + _tcscpy (currprefs.cdimagefile[unitnum], newimagefiles[unitnum]); + _tcscpy (changed_prefs.cdimagefile[unitnum], newimagefiles[unitnum]); + currprefs.cdimagefileuse[unitnum] = changed_prefs.cdimagefileuse[unitnum] = cdimagefileinuse[unitnum]; + newimagefiles[unitnum][0] = 0; + write_log (L"CD: delayed insert '%s'\n", currprefs.cdimagefile[unitnum][0] ? currprefs.cdimagefile[unitnum] : L""); + device_func_init (0); + if (wasopen[unitnum]) { + if (!device_func[unitnum]->opendev (unitnum, currprefs.cdimagefile[unitnum])) { + write_log (L"-> device open failed\n"); + } + } + wasopen[unitnum] = 0; + if (currprefs.scsi) { + struct device_info di; + device_func[unitnum]->info (unitnum, &di, 0); + int pollmode; + scsi_do_disk_change (unitnum, 1, &pollmode); } +#ifdef RETROPLATFORM + rp_cd_image_change (unitnum, currprefs.cdimagefile[unitnum]); +#endif + config_changed = 1; - old_flags = flags; +} - oflags = (flags & DEVICE_TYPE_SCSI) ? 0 : (1 << INQ_ROMD); +void blkdev_vsync (void) +{ + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) + check_changes (i); +} - forcedunit = -1; - install_driver (flags); - if (device_func[DF_IOCTL]) - have_ioctl = 1; - else - have_ioctl = 0; - if (flags & DEVICE_TYPE_ALLOWEMU) - oflags |= DEVICE_TYPE_ALLOWEMU; - if (device_func[DF_SCSI]) { - if (device_func[DF_SCSI] != device_func[DF_IOCTL]) - support_scsi = device_func[DF_SCSI]->openbus (oflags) ? 1 : 0; - else - support_scsi = 1; - } - oflags |= 1 << INQ_ROMD; - if (have_ioctl) - support_ioctl = device_func[DF_IOCTL]->openbus (oflags) ? 1 : 0; - write_log (L"support_scsi = %d support_ioctl = %d\n", support_scsi, support_ioctl); - return (support_scsi ? (1 << DF_SCSI) : 0) | (support_ioctl ? (1 << DF_IOCTL) : 0); +static int do_scsi (int unitnum, uae_u8 *cmd, int cmdlen) +{ + return 0; +} +static int do_scsi (int unitnum, uae_u8 *cmd, int cmdlen, uae_u8 *out, int outsize) +{ + return 0; +} + +static int failunit (int unitnum) +{ + if (unitnum < 0 || unitnum >= MAX_TOTAL_SCSI_DEVICES) + return 1; + if (device_func[unitnum] == NULL) + return 1; + return 0; } static int audiostatus (int unitnum) { uae_u8 cmd[10] = {0x42,2,0x40,1,0,0,0,(uae_u8)(DEVICE_SCSI_BUFSIZE>>8),(uae_u8)(DEVICE_SCSI_BUFSIZE&0xff),0}; - uae_u8 *p = device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof (cmd), 0); + uae_u8 *p = device_func[unitnum]->exec_in (unitnum, cmd, sizeof (cmd), 0); if (!p) return 0; return p[1]; } /* pause/unpause CD audio */ -void sys_command_cd_pause (int mode, int unitnum, int paused) +int sys_command_cd_pause (int unitnum, int paused) { - if (mode == DF_SCSI || !have_ioctl) { + if (failunit (unitnum)) + return -1; + if (device_func[unitnum]->pause == NULL) { int as = audiostatus (unitnum); - if ((paused && as == 0x11) && (!paused && as == 0x12)) { - uae_u8 cmd[10] = {0x4b,0,0,0,0,0,0,0,paused?0:1,0}; - device_func[DF_SCSI]->exec_out (unitnum, cmd, sizeof (cmd)); - } - return; + uae_u8 cmd[10] = {0x4b,0,0,0,0,0,0,0,paused?0:1,0}; + do_scsi (unitnum, cmd, sizeof cmd); + return as == AUDIO_STATUS_PAUSED; } - device_func[DF_IOCTL]->pause (unitnum, paused); + return device_func[unitnum]->pause (unitnum, paused); } /* stop CD audio */ -void sys_command_cd_stop (int mode, int unitnum) +void sys_command_cd_stop (int unitnum) { - if (mode == DF_SCSI || !have_ioctl) { + if (failunit (unitnum)) + return; + if (device_func[unitnum]->stop == NULL) { int as = audiostatus (unitnum); - if (as == 0x11) { - uae_u8 cmd[6] = {0x4e,0,0,0,0,0}; - device_func[DF_SCSI]->exec_out (unitnum, cmd, sizeof (cmd)); - } + uae_u8 cmd[6] = {0x4e,0,0,0,0,0}; + do_scsi (unitnum, cmd, sizeof cmd); return; } - device_func[DF_IOCTL]->stop (unitnum); + device_func[unitnum]->stop (unitnum); } #if 0 static int adjustplaypos (int unitnum, int startlsn) { uae_u8 q[SUBQ_SIZE]; - if (!device_func[DF_IOCTL]->qcode (unitnum, q, startlsn - 1)) + if (!device_func[unitnum]->qcode (unitnum, q, startlsn - 1)) return startlsn; int otrack = frombcd (q[4 + 1]); int lsn = startlsn; int max = 150; while (max-- > 0 && startlsn > 0) { - if (!device_func[DF_IOCTL]->qcode (unitnum, q, startlsn - 1)) + if (!device_func[unitnum]->qcode (unitnum, q, startlsn - 1)) break; int track = frombcd (q[4 + 1]); int idx = frombcd (q[4 + 2]); @@ -253,179 +399,154 @@ static int adjustplaypos (int unitnum, int startlsn) #endif /* play CD audio */ -int sys_command_cd_play (int mode, int unitnum, int startlsn, int endlsn, int scan) +int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan) { - if (mode == DF_SCSI || !have_ioctl) { + if (failunit (unitnum)) + return 0; + if (device_func[unitnum]->play == NULL) { uae_u8 cmd[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; -#if 0 - if (scan) { - cmd[0] = 0xba; - cmd[1] = scan < 0 ? 0x10 : 0x0; - cmd[3] = (uae_u8)(startmsf >> 16); - cmd[4] = (uae_u8)(startmsf >> 8); - cmd[5] = (uae_u8)(startmsf >> 0); - cmd[9] = 0x40; - } else { -#endif - int startmsf = lsn2msf (startlsn); - int endmsf = lsn2msf (endlsn); - cmd[0] = 0x47; - cmd[3] = (uae_u8)(startmsf >> 16); - cmd[4] = (uae_u8)(startmsf >> 8); - cmd[5] = (uae_u8)(startmsf >> 0); - cmd[6] = (uae_u8)(endmsf >> 16); - cmd[7] = (uae_u8)(endmsf >> 8); - cmd[8] = (uae_u8)(endmsf >> 0); -#if 0 - } -#endif - return device_func[DF_SCSI]->exec_out (unitnum, cmd, sizeof (cmd)) == 0 ? 0 : 1; + int startmsf = lsn2msf (startlsn); + int endmsf = lsn2msf (endlsn); + cmd[0] = 0x47; + cmd[3] = (uae_u8)(startmsf >> 16); + cmd[4] = (uae_u8)(startmsf >> 8); + cmd[5] = (uae_u8)(startmsf >> 0); + cmd[6] = (uae_u8)(endmsf >> 16); + cmd[7] = (uae_u8)(endmsf >> 8); + cmd[8] = (uae_u8)(endmsf >> 0); + return do_scsi (unitnum, cmd, sizeof cmd) ? 0 : 1; } //startlsn = adjustplaypos (unitnum, startlsn); - return device_func[DF_IOCTL]->play (unitnum, startlsn, endlsn, scan, NULL); + return device_func[unitnum]->play (unitnum, startlsn, endlsn, scan, NULL); } /* play CD audio with subchannels */ -int sys_command_cd_play (int mode, int unitnum, int startlsn, int endlsn, int scan, play_subchannel_callback subfunc) +int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan, play_subchannel_callback subfunc) { - if (mode == DF_SCSI || !have_ioctl) + if (failunit (unitnum)) return 0; + if (device_func[unitnum]->play == NULL) + return sys_command_cd_play (unitnum, startlsn, endlsn, scan); //startlsn = adjustplaypos (unitnum, startlsn); - return device_func[DF_IOCTL]->play (unitnum, startlsn, endlsn, scan, subfunc); + return device_func[unitnum]->play (unitnum, startlsn, endlsn, scan, subfunc); } /* set CD audio volume */ -void sys_command_cd_volume (int mode, int unitnum, uae_u16 volume) +uae_u32 sys_command_cd_volume (int unitnum, uae_u16 volume_left, uae_u16 volume_right) { - if (mode == DF_SCSI || !have_ioctl) - return; - device_func[DF_IOCTL]->volume (unitnum, volume); + if (failunit (unitnum)) + return 0; + if (device_func[unitnum]->volume == NULL) + return -1; + return device_func[unitnum]->volume (unitnum, volume_left, volume_right); } /* read qcode */ -int sys_command_cd_qcode (int mode, int unitnum, uae_u8 *buf) +int sys_command_cd_qcode (int unitnum, uae_u8 *buf) { - if (mode == DF_SCSI || !have_ioctl) { - uae_u8 cmd[10] = {0x42,2,0x40,1,0,0,0,(uae_u8)(DEVICE_SCSI_BUFSIZE>>8),(uae_u8)(DEVICE_SCSI_BUFSIZE&0xff),0}; - uae_u8 *p = device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof (cmd), 0); - if (p) { - memcpy (buf, p, SUBQ_SIZE); - return 1; - } - return 0; + if (failunit (unitnum)) + return 0; + if (device_func[unitnum]->qcode == NULL) { + uae_u8 cmd[10] = {0x42,2,0x40,1,0,0,0,(uae_u8)(SUBQ_SIZE>>8),(uae_u8)(SUBQ_SIZE&0xff),0}; + return do_scsi (unitnum, cmd, sizeof cmd, buf, SUBQ_SIZE); } - return device_func[DF_IOCTL]->qcode (unitnum, buf, -1); + return device_func[unitnum]->qcode (unitnum, buf, -1); }; /* read table of contents */ -struct cd_toc_head *sys_command_cd_toc (int mode, int unitnum) +int sys_command_cd_toc (int unitnum, struct cd_toc_head *toc) { - if (mode == DF_SCSI || !have_ioctl) { - uae_u8 cmd [10] = { 0x43,0,2,0,0,0,1,(uae_u8)(DEVICE_SCSI_BUFSIZE>>8),(uae_u8)(DEVICE_SCSI_BUFSIZE&0xff),0}; - return NULL; -// return device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof(cmd), 0); + if (failunit (unitnum)) + return 0; + if (device_func[unitnum]->toc == NULL) { + uae_u8 buf[4 + 8 * 103]; + int size = sizeof buf; + uae_u8 cmd [10] = { 0x43,0,2,0,0,0,0,(uae_u8)(size>>8),(uae_u8)(size&0xff),0}; + if (do_scsi (unitnum, cmd, sizeof cmd, buf, size)) { + // toc parse to do + return 0; + } + return 0; } - return device_func[DF_IOCTL]->toc (unitnum); + return device_func[unitnum]->toc (unitnum, toc); } /* read one cd sector */ -uae_u8 *sys_command_cd_read (int mode, int unitnum, uae_u8 *data, int block, int size) +int sys_command_cd_read (int unitnum, uae_u8 *data, int block, int size) { - if (mode == DF_SCSI || !have_ioctl) { - uae_u8 cmd[12] = { 0xbe, 0, 0, 0, 0, 0, 0, 0, 1, 0x10, 0, 0 }; - cmd[3] = (uae_u8)(block >> 16); - cmd[4] = (uae_u8)(block >> 8); - cmd[5] = (uae_u8)(block >> 0); - uae_u8 *p = device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof (cmd), 0); - if (p && data) - memcpy (data, p, size); - return p; + if (failunit (unitnum)) + return 0; + if (device_func[unitnum]->read == NULL) { + uae_u8 cmd[12] = { 0xbe, 0, block >> 24, block >> 16, block >> 8, block >> 0, size >> 16, size >> 8, size >> 0, 0x10, 0, 0 }; + cmd[1] = 2 << 3; // 2048 + if (!do_scsi (unitnum, cmd, sizeof cmd, data, size * 2048)) + cmd[1] = 4 << 3; // 2048 mode2 + return do_scsi (unitnum, cmd, sizeof cmd, data, size * 2048); } - return device_func[DF_IOCTL]->read (unitnum, data, block, size); + return device_func[unitnum]->read (unitnum, data, block, size); } -uae_u8 *sys_command_cd_rawread (int mode, int unitnum, uae_u8 *data, int sector, int size, int sectorsize) +int sys_command_cd_rawread (int unitnum, uae_u8 *data, int block, int size, int sectorsize) { - if (mode == DF_SCSI || !have_ioctl) { - uae_u8 cmd[12] = { 0xbe, 0, 0, 0, 0, 0, 0, 0, size, 0x10, 0, 0 }; - cmd[3] = (uae_u8)(sector >> 16); - cmd[4] = (uae_u8)(sector >> 8); - cmd[5] = (uae_u8)(sector >> 0); - uae_u8 *p = device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof (cmd), 0); - if (p && data) - memcpy (data, p, size); - return p; + if (failunit (unitnum)) + return -1; + if (device_func[unitnum]->rawread == NULL) { + uae_u8 cmd[12] = { 0xbe, 0, block >> 24, block >> 16, block >> 8, block >> 0, size >> 16, size >> 8, size >> 0, 0x10, 0, 0 }; + return do_scsi (unitnum, cmd, sizeof cmd, data, size * sectorsize); } - return device_func[DF_IOCTL]->rawread (unitnum, data, sector, size, sectorsize); + return device_func[unitnum]->rawread (unitnum, data, block, size, sectorsize, 0xffff); +} +int sys_command_cd_rawread (int unitnum, uae_u8 *data, int block, int size, int sectorsize, uae_u8 scsicmd9, uae_u8 subs) +{ + if (failunit (unitnum)) + return -1; + if (device_func[unitnum]->rawread == NULL) { + uae_u8 cmd[12] = { 0xbe, 0, block >> 24, block >> 16, block >> 8, block >> 0, size >> 16, size >> 8, size >> 0, 0x10, 0, 0 }; + return do_scsi (unitnum, cmd, sizeof cmd, data, size * sectorsize); + } + return device_func[unitnum]->rawread (unitnum, data, block, size, sectorsize, (scsicmd9 << 8) | subs); } /* read block */ -uae_u8 *sys_command_read (int mode, int unitnum, uae_u8 *data, int block, int size) +int sys_command_read (int unitnum, uae_u8 *data, int block, int size) { - if (mode == DF_SCSI || !have_ioctl) { - uae_u8 cmd[10] = { 0x28, 0, 0, 0, 0, 0, 0, 0, 1, 0 }; + if (failunit (unitnum)) + return 0; + if (device_func[unitnum]->read == NULL) { + uae_u8 cmd[12] = { 0xa8, 0, 0, 0, 0, 0, size >> 24, size >> 16, size >> 8, size >> 0, 0, 0 }; cmd[2] = (uae_u8)(block >> 24); cmd[3] = (uae_u8)(block >> 16); cmd[4] = (uae_u8)(block >> 8); cmd[5] = (uae_u8)(block >> 0); - uae_u8 *p = device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof (cmd), 0); - if (p && data) - memcpy (data, p, size); - return p; + return do_scsi (unitnum, cmd, sizeof cmd, data, size * 2048); } - return device_func[DF_IOCTL]->read (unitnum, data, block, size); + return device_func[unitnum]->read (unitnum, data, block, size); } /* write block */ -int sys_command_write (int mode, int unitnum, uae_u8 *data, int offset, int size) +int sys_command_write (int unitnum, uae_u8 *data, int offset, int size) { - if (mode == DF_SCSI || !have_ioctl) { - uae_u8 cmd[10] = { 0x2a, 0, 0, 0, 0, 0, 0, 0, size, 0 }; - cmd[2] = (uae_u8)(offset >> 24); - cmd[3] = (uae_u8)(offset >> 16); - cmd[4] = (uae_u8)(offset >> 8); - cmd[5] = (uae_u8)(offset >> 0); - if (device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof (cmd), 0)) - return -1; + if (failunit (unitnum)) return 0; - } - return device_func[DF_IOCTL]->write (unitnum, data, offset, size); + if (device_func[unitnum]->write == NULL) + return 0; + return device_func[unitnum]->write (unitnum, data, offset, size); } -int sys_command_ismedia (int mode, int unitnum, int quick) +int sys_command_ismedia (int unitnum, int quick) { - struct device_info di; - - if (forcedunit >= 0) { - if (unitnum != forcedunit) - return -1; - } - - if (mode == DF_SCSI || !have_ioctl || !device_func[DF_IOCTL]->ismedia) { - if (quick) - return -1; - memset(&di, 0, sizeof di); - if (device_func[DF_SCSI]->info (unitnum, &di, quick) == NULL, quick) - return -1; - return di.media_inserted; + if (failunit (unitnum)) + return -1; + if (device_func[unitnum] == NULL) { + uae_u8 cmd[6] = { 0, 0, 0, 0, 0, 0 }; + return do_scsi (unitnum, cmd, sizeof cmd); } else { - return device_func[DF_IOCTL]->ismedia (unitnum, quick); + return device_func[unitnum]->ismedia (unitnum, quick); } } -struct device_info *sys_command_info (int mode, int unitnum, struct device_info *di, int quick) -{ - if (mode == DF_SCSI || !have_ioctl) - return device_func[DF_SCSI]->info (unitnum, di, quick); - else - return device_func[DF_IOCTL]->info (unitnum, di, quick); -} - -struct device_scsi_info *sys_command_scsi_info (int mode, int unitnum, struct device_scsi_info *dsi) +struct device_info *sys_command_info (int unitnum, struct device_info *di, int quick) { - if (mode == DF_SCSI || !have_ioctl) - return device_func[DF_SCSI]->scsiinfo (unitnum, dsi); - else - return device_func[DF_IOCTL]->scsiinfo (unitnum, dsi); + return device_func[unitnum]->info (unitnum, di, quick); } #define MODE_SELECT_6 0x15 @@ -561,7 +682,10 @@ uae_u8 *save_cd (int num, int *len) dstbak = dst = xmalloc (uae_u8, 4 + 256); save_u32 (4); - save_string (currprefs.cdimagefile); + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + save_string (currprefs.cdimagefile[i]); + save_u32 (currprefs.cdscsidevicetype[i]); + } *len = dst - dstbak; return dstbak; } @@ -574,8 +698,8 @@ uae_u8 *restore_cd (int unit, uae_u8 *src) flags = restore_u32 (); s = restore_string (); if ((flags & 4) && unit == 0) { - _tcscpy (changed_prefs.cdimagefile, s); - _tcscpy (currprefs.cdimagefile, s); + _tcscpy (changed_prefs.cdimagefile[0], s); + _tcscpy (currprefs.cdimagefile[0], s); } return src; } @@ -586,7 +710,7 @@ static bool nodisk (struct device_info *di) } static uae_u64 cmd_readx (int unitnum, uae_u8 *dataptr, int offset, int len) { - if (device_func[DF_IOCTL]->read (unitnum, dataptr, offset, len)) + if (device_func[unitnum]->read (unitnum, dataptr, offset, len)) return len; else return 0; @@ -608,18 +732,66 @@ static int rl (uae_u8 *p) { return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); } +static int rw (uae_u8 *p) +{ + return (p[0] << 8) | (p[1]); +} -static struct cd_toc *gettoc (struct device_info *di, int block) +static void stopplay (int unitnum) { - for (int i = di->toc.first_track_offset; i < di->toc.last_track_offset; i++) { - struct cd_toc *t = &di->toc.toc[i]; - if (t->paddress > block) { - if (t->point == 1) - return t; - return t - 1; + sys_command_cd_stop (unitnum); +} + +static int addtocentry (uae_u8 **dstp, int *len, int point, int newpoint, int msf, uae_u8 *head, struct cd_toc_head *th) +{ + uae_u8 *dst = *dstp; + + for (int i = 0; i < th->points; i++) { + struct cd_toc *t = &th->toc[i]; + if (t->point == point) { + if (*len < 8) + return 0; + int addr = t->paddress; + if (msf) + addr = lsn2msf (addr); + dst[0] = 0; + dst[1] = (t->adr << 4) | t->control; + dst[2] = newpoint >= 0 ? newpoint : point; + dst[3] = 0; + dst[4] = addr >> 24; + dst[5] = addr >> 16; + dst[6] = addr >> 8; + dst[7] = addr >> 0; + + if (point >= 1 && point <= 99) { + if (head[2] == 0) + head[2] = point; + head[3] = point; + } + + *len -= 8; + *dstp = dst + 8; + return 1; } } - return &di->toc.toc[di->toc.last_track_offset]; + return -1; +} + +static int scsi_read_cd (int unitnum, uae_u8 *cmd, uae_u8 *data, struct device_info *di) +{ + int msf = cmd[0] == 0xb9; + int start = msf ? msf2lsn (rl (cmd + 2) & 0x00ffffff) : rl (cmd + 2); + int len = rl (cmd + 5) & 0x00ffffff; + if (msf) { + int end = msf2lsn (len); + len = end - start; + if (len < 0) + return -1; + } + int subs = cmd[10] & 7; + if (len == 0) + return 0; + return sys_command_cd_rawread (unitnum, data, start, len, 0, cmd[9], subs); } static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, @@ -629,15 +801,13 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, int lr = 0, ls = 0; int scsi_len = -1; int status = 0; - int i; - char *ss; struct device_info di; *reply_len = *sense_len = 0; memset (r, 0, 256); memset (s, 0, 256); - sys_command_info (DF_IOCTL, unitnum, &di, 1); + sys_command_info (unitnum, &di, 1); if (cmdbuf[0] == 0) { /* TEST UNIT READY */ if (nodisk (&di)) @@ -645,10 +815,14 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, scsi_len = 0; goto end; } - + write_log (L"SCSIEMU %d: %02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X CMDLEN=%d DATA=%08X LEN=%d\n", unitnum, + cmdbuf[0], cmdbuf[1], cmdbuf[2], cmdbuf[3], cmdbuf[4], cmdbuf[5], cmdbuf[6], + cmdbuf[7], cmdbuf[8], cmdbuf[9], cmdbuf[10], cmdbuf[11], + scsi_cmd_len, scsi_data, *data_len); switch (cmdbuf[0]) { case 0x12: /* INQUIRY */ + { if ((cmdbuf[1] & 1) || cmdbuf[2] != 0) goto err; len = cmdbuf[4]; @@ -663,98 +837,135 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, scsi_len = lr = len < 36 ? (uae_u32)len : 36; r[2] = 2; r[3] = 2; - ss = "UAE"; - i = 0; /* vendor id */ - while (i < 8 && ss[i]) { - r[8 + i] = ss[i]; - i++; - } - while (i < 8) { - r[8 + i] = 32; - i++; - } - char tmp[256]; - sprintf (tmp, "SCSI CD%d EMU", unitnum); - ss = tmp; - i = 0; /* product id */ - while (i < 16 && ss[i]) { - r[16 + i] = ss[i]; - i++; - } - while (i < 16) { - r[16 + i] = 32; - i++; - } - ss = "0.1"; - i = 0; /* product revision */ - while (i < 4 && ss[i]) { - r[32 + i] = ss[i]; - i++; - } - while (i < 4) { - r[32 + i] = 32; - i++; + char *s = ua (di.vendorid); + memcpy (r + 8, s, strlen (s)); + xfree (s); + s = ua (di.productid); + memcpy (r + 16, s, strlen (s)); + xfree (s); + s = ua (di.revision); + memcpy (r + 32, s, strlen (s)); + xfree (s); + for (int i = 8; i < 36; i++) { + if (r[i] == 0) + r[i] = 32; } + } + break; + case 0xbe: // READ CD + case 0xb9: // READ CD MSF + if (nodisk (&di)) + goto nodisk; + scsi_len = scsi_read_cd (unitnum, cmdbuf, scsi_data, &di); + if (scsi_len == -2) + goto notdatatrack; + if (scsi_len == -1) + goto errreq; break; + case 0x55: // MODE SELECT(10) + case 0x15: // MODE SELECT(6) + { + uae_u8 *p; + p = scsi_data + 4; + if (cmdbuf[0] == 0x55) + p += 4; + int pcode = p[0] & 0x3f; + if (pcode == 14) { // CD audio control + uae_u16 vol_left = (p[9] << 7) | (p[9] >> 1); + uae_u16 vol_right = (p[11] << 7) | (p[11] >> 1); + sys_command_cd_volume (unitnum, vol_left, vol_right); + scsi_len = 0; + } else { + goto errreq; + } + } + break; + case 0x5a: // MODE SENSE(10) case 0x1a: /* MODE SENSE(6) */ - { - uae_u8 *p; - int pc = cmdbuf[2] >> 6; - int pcode = cmdbuf[2] & 0x3f; - int dbd = cmdbuf[1] & 8; - int cyl, cylsec, head, tracksec; - if (nodisk (&di)) - goto nodisk; - cyl = di.cylinders; - head = 1; - cylsec = tracksec = di.trackspercylinder; - //write_log (L"MODE SENSE PC=%d CODE=%d DBD=%d\n", pc, pcode, dbd); - p = r; + { + uae_u8 *p; + int pc = cmdbuf[2] >> 6; + int pcode = cmdbuf[2] & 0x3f; + int dbd = cmdbuf[1] & 8; + if (cmdbuf[0] == 0x5a) + dbd = 1; + write_log (L"MODE SENSE PC=%d CODE=%d DBD=%d\n", pc, pcode, dbd); + p = r; + if (cmdbuf[0] == 0x5a) { + p[0] = 8 - 1; + p[1] = 0; + p[2] = 0; + p[3] = 0; + p[4] = 0; + p[5] = 0; + p[6] = 0; + p[7] = 0; + p += 8; + } else { p[0] = 4 - 1; p[1] = 0; p[2] = 0; p[3] = 0; p += 4; - if (!dbd) { - uae_u32 blocks = di.sectorspertrack * di.cylinders * di.trackspercylinder; - p[-1] = 8; - wl(p + 0, blocks); - wl(p + 4, di.bytespersector); - p += 8; - } - if (pcode == 0) { - p[0] = 0; - p[1] = 0; - p[2] = 0x20; - p[3] = 0; - r[0] += 4; - } else if (pcode == 3) { - p[0] = 3; - p[1] = 24; - p[3] = 1; - p[10] = tracksec >> 8; - p[11] = tracksec; - p[12] = di.bytespersector >> 8; - p[13] = di.bytespersector; - p[15] = 1; // interleave - p[20] = 0x80; - r[0] += p[1]; - } else if (pcode == 4) { - p[0] = 4; - wl(p + 1, cyl); - p[1] = 24; - p[5] = head; - wl(p + 13, cyl); - ww(p + 20, 0); - r[0] += p[1]; - } else { - goto err; - } - r[0] += r[3]; - scsi_len = lr = r[0] + 1; - break; } - break; + if (!dbd) { + if (nodisk (&di)) + goto nodisk; + uae_u32 blocks = di.sectorspertrack * di.cylinders * di.trackspercylinder; + p[-1] = 8; + wl(p + 0, blocks); + wl(p + 4, di.bytespersector); + p += 8; + } + if (pcode == 0) { + p[0] = 0; + p[1] = 0; + p[2] = 0x20; + p[3] = 0; + r[0] += 4; + } else if (pcode == 3) { + if (nodisk (&di)) + goto nodisk; + p[0] = 3; + p[1] = 24; + p[3] = 1; + p[10] = di.trackspercylinder >> 8; + p[11] = di.trackspercylinder; + p[12] = di.bytespersector >> 8; + p[13] = di.bytespersector; + p[15] = 1; // interleave + p[20] = 0x80; + r[0] += p[1]; + } else if (pcode == 4) { + if (nodisk (&di)) + goto nodisk; + p[0] = 4; + wl(p + 1, di.cylinders); + p[1] = 24; + p[5] = 1; + wl(p + 13, di.cylinders); + ww(p + 20, 0); + r[0] += p[1]; + } else if (pcode == 14) { // CD audio control + uae_u32 vol = sys_command_cd_volume (unitnum, 0xffff, 0xffff); + p[0] = 0x0e; + p[1] = 0x0e; + p[2] = 1; + p[3] = 4; + p[6] = 0; + p[7] = 75; + p[8] = 1; + p[9] = pc == 0 ? (vol >> 7) & 0xff : 0xff; + p[10] = 2; + p[11] = pc == 0 ? (vol >> (16 + 7)) & 0xff : 0xff; + r[0] += p[1]; + } else { + goto err; + } + r[0] += r[3]; + scsi_len = lr = r[0] + 1; + } + break; case 0x1d: /* SEND DIAGNOSTICS */ scsi_len = 0; break; @@ -788,8 +999,9 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, { if (nodisk (&di)) goto nodisk; + stopplay (unitnum); offset = ((cmdbuf[1] & 31) << 16) | (cmdbuf[2] << 8) | cmdbuf[3]; - struct cd_toc *t = gettoc (&di, offset); + struct cd_toc *t = gettoc (&di.toc, offset); if ((t->control & 0x0c) == 0x04) { len = cmdbuf[4]; if (!len) @@ -806,8 +1018,9 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, { if (nodisk (&di)) goto nodisk; + stopplay (unitnum); offset = rl (cmdbuf + 2); - struct cd_toc *t = gettoc (&di, offset); + struct cd_toc *t = gettoc (&di.toc, offset); if ((t->control & 0x0c) == 0x04) { len = rl (cmdbuf + 7 - 2) & 0xffff; scsi_len = cmd_readx (unitnum, scsi_data, offset, len) * di.bytespersector; @@ -822,8 +1035,9 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, { if (nodisk (&di)) goto nodisk; + stopplay (unitnum); offset = rl (cmdbuf + 2); - struct cd_toc *t = gettoc (&di, offset); + struct cd_toc *t = gettoc (&di.toc, offset); if ((t->control & 0x0c) == 0x04) { len = rl (cmdbuf + 6); scsi_len = (uae_u32)cmd_readx (unitnum, scsi_data, offset, len) * di.bytespersector;; @@ -836,57 +1050,231 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, goto readprot; case 0x43: // READ TOC { + if (nodisk (&di)) + goto nodisk; uae_u8 *p = scsi_data; int strack = cmdbuf[6]; int msf = cmdbuf[1] & 2; + int format = cmdbuf[2] & 7; + if (format >= 3) + goto errreq; int maxlen = (cmdbuf[7] << 8) | cmdbuf[8]; - struct cd_toc_head *toc = sys_command_cd_toc (DF_IOCTL, unitnum); - if (!toc) + struct cd_toc_head ttoc; + if (!sys_command_cd_toc (unitnum, &ttoc)) goto readerr; + struct cd_toc_head *toc = &ttoc; if (maxlen < 4) goto errreq; - if (strack == 0) - strack = toc->first_track; - if (strack >= 100 && strack != 0xaa) - goto errreq; - if (strack == 0xaa) - strack = 0xa2; - uae_u8 *p2 = p + 4; - p[2] = 0; - p[3] = 0; - for (int i = 0; i < toc->points; i++) { - if (strack == toc->toc[i].point) { - int trk = strack >= 100 ? 0xaa : strack; - if (p[2] == 0) - p[2] = trk; - p[3] = trk; - int addr = toc->toc[i].paddress; - if (msf) - addr = lsn2msf (addr); - if (p2 - p + 8 > maxlen) + if (format == 1) { + p[0] = 0; + p[1] = 8; + p[2] = 1; + p[3] = 1; + p[4] = 0; + p[5] = (toc->toc[0].adr << 4) | toc->toc[0].control; + p[6] = toc->first_track; + p[7] = 0; + if (msf) + wl (p + 8, lsn2msf (toc->toc[0].address)); + else + wl (p + 8 , toc->toc[0].address); + scsi_len = 12; + } else if (format == 2 || format == 0) { + if (format == 2 && !msf) + goto errreq; + if (strack == 0) + strack = toc->first_track; + if (format == 0 && strack >= 100 && strack != 0xaa) + goto errreq; + uae_u8 *p2 = p + 4; + p[2] = 0; + p[3] = 0; + maxlen -= 4; + if (format == 2) { + if (!addtocentry (&p2, &maxlen, 0xa0, -1, msf, p, toc)) + goto errreq; + if (!addtocentry (&p2, &maxlen, 0xa1, -1, msf, p, toc)) + goto errreq; + if (!addtocentry (&p2, &maxlen, 0xa2, -1, msf, p, toc)) + goto errreq; + } + while (strack < 100) { + if (!addtocentry (&p2, &maxlen, strack, -1, msf, p, toc)) goto errreq; - p2[0] = 0; - p2[1] = (toc->toc[i].adr << 4) | toc->toc[i].control; - p2[2] = trk; - p2[3] = 0; - p2[4] = addr >> 24; - p2[5] = addr >> 16; - p2[6] = addr >> 8; - p2[7] = addr >> 0; - p2 += 8; strack++; } - if (i == toc->points - 1) { - if (strack >= 0xa2) - break; - i = 0; - strack = 0xa2; + if (!addtocentry (&p2, &maxlen, 0xa2, 0xaa, msf, p, toc)) + goto errreq; + int tlen = p2 - (p + 4); + p[0] = tlen >> 8; + p[1] = tlen >> 0; + scsi_len = tlen + 4; + } + } + break; + case 0x42: // READ SUB-CHANNEL + { + int msf = cmdbuf[1] & 2; + int subq = cmdbuf[2] & 0x40; + int format = cmdbuf[3]; + int track = cmdbuf[6]; + int len = rw (cmdbuf + 7); + uae_u8 buf[SUBQ_SIZE] = { 0 }; + + if (nodisk (&di)) + goto nodisk; + sys_command_cd_qcode (unitnum, buf); + if (len < 4) + goto errreq; + scsi_len = 4; + scsi_data[0] = 0; + scsi_data[1] = buf[1]; + if (subq && format == 1) { + if (len < 4 + 12) + goto errreq; + scsi_data[2] = 0; + scsi_data[3] = 12; + scsi_len += 12; + scsi_data[4] = 1; + scsi_data[5] = (buf[4 + 0] << 4) | (buf[4 + 0] >> 4); + scsi_data[6] = frombcd (buf[4 + 1]); // track + scsi_data[7] = frombcd (buf[4 + 2]); // index + int reladdr = fromlongbcd (&buf[4 + 3]); + int absaddr = fromlongbcd (&buf[4 + 7]); + if (!msf) { + reladdr = msf2lsn (reladdr); + absaddr = msf2lsn (absaddr); + } + wl (scsi_data + 8, absaddr); + wl (scsi_data + 12, reladdr); + } else { + scsi_data[2] = 0; + scsi_data[3] = 0; + } + } + break; + case 0x1b: // START/STOP + sys_command_cd_stop (unitnum); + scsi_len = 0; + break; + case 0x4e: // STOP PLAY/SCAN + if (nodisk (&di)) + goto nodisk; + sys_command_cd_stop (unitnum); + scsi_len = 0; + break; + case 0xba: // SCAN + { + if (nodisk (&di)) + goto nodisk; + struct cd_toc_head ttoc; + if (!sys_command_cd_toc (unitnum, &ttoc)) + goto readerr; + struct cd_toc_head *toc = &ttoc; + int scan = (cmdbuf[1] & 0x10) ? -1 : 1; + int start = rl (cmdbuf + 1) & 0x00ffffff; + int end = scan > 0 ? toc->lastaddress : toc->toc[toc->first_track_offset].paddress; + int type = cmdbuf[9] >> 6; + if (type == 1) + start = lsn2msf (start); + if (type == 3) + goto errreq; + if (type == 2) { + if (toc->first_track_offset + start >= toc->last_track_offset) + goto errreq; + start = toc->toc[toc->first_track_offset + start].paddress; + } + sys_command_cd_play (unitnum, start, end, scan, NULL); + scsi_len = 0; + } + break; + case 0x48: // PLAY AUDIO TRACK/INDEX + { + if (nodisk (&di)) + goto nodisk; + int strack = cmdbuf[4]; + int etrack = cmdbuf[7]; + struct cd_toc_head ttoc; + if (!sys_command_cd_toc (unitnum, &ttoc)) + goto readerr; + struct cd_toc_head *toc = &ttoc; + if (strack < toc->first_track || strack > toc->last_track || + etrack < toc->first_track || etrack > toc->last_track || + strack > etrack) + goto errreq; + int start = toc->toc[toc->first_track_offset + strack - 1].paddress; + int end = etrack == toc->last_track ? toc->lastaddress : toc->toc[toc->first_track_offset + etrack - 1 + 1].paddress; + if (!sys_command_cd_play (unitnum, start, end, 0, NULL)) + goto notdatatrack; + scsi_len = 0; + } + break; + case 0x47: // PLAY AUDIO MSF + { + if (nodisk (&di)) + goto nodisk; + int start = rl (cmdbuf + 2) & 0x00ffffff; + if (start == 0x00ffffff) { + uae_u8 buf[SUBQ_SIZE] = { 0 }; + sys_command_cd_qcode (unitnum, buf); + start = fromlongbcd (buf + 4 + 7); + } + int end = msf2lsn (rl (cmdbuf + 5) & 0x00ffffff); + start = msf2lsn (start); + if (start > end) + goto errreq; + if (start < end) + sys_command_cd_play (unitnum, start, end, 0, NULL); + scsi_len = 0; + } + break; + case 0x45: // PLAY AUDIO + { + if (nodisk (&di)) + goto nodisk; + int start = rl (cmdbuf + 2); + int len = rw (cmdbuf + 7); + if (len > 0) { + if (start == -1) { + uae_u8 buf[SUBQ_SIZE] = { 0 }; + sys_command_cd_qcode (unitnum, buf); + start = msf2lsn (fromlongbcd (buf + 4 + 7)); } + sys_command_cd_play (unitnum, start, start + len, 0, NULL); + } + scsi_len = 0; + } + break; + case 0xbc: // PLAY CD + { + if (nodisk (&di)) + goto nodisk; + int start = -1; + int end = -1; + if (cmdbuf[1] & 2) { + start = msf2lsn (rl (cmdbuf + 2) & 0x00ffffff); + end = msf2lsn (rl (cmdbuf + 5) & 0x00ffffff); + } else { + start = rl (cmdbuf + 2); + end = start + rl (cmdbuf + 6); } - int tlen = p2 - (p + 4); - p[0] = tlen >> 8; - p[1] = tlen >> 0; - scsi_len = tlen + 4; + if (start > end) + goto errreq; + if (start < end) + sys_command_cd_play (unitnum, start, end, 0, NULL); + } + break; + case 0x4b: // PAUSE/RESUME + { + if (nodisk (&di)) + goto nodisk; + uae_u8 buf[SUBQ_SIZE] = { 0 }; + int resume = cmdbuf[8] & 1; + sys_command_cd_qcode (unitnum, buf); + if (buf[1] != AUDIO_STATUS_IN_PROGRESS && buf[1] != AUDIO_STATUS_PAUSED) + goto errreq; + sys_command_cd_pause (unitnum, resume ? 0 : 1); + scsi_len = 0; } break; readprot: @@ -934,6 +1322,8 @@ end: *data_len = scsi_len; *reply_len = lr; *sense_len = ls; + if (cmdbuf[0]) + write_log (L"-> DATAOUT=%d ST=%d SENSELEN=%d\n", scsi_len, status, ls); return status; } @@ -943,7 +1333,7 @@ static int execscsicmd_direct (int unitnum, struct amigascsi *as) int io_error = 0; uae_u8 *scsi_datap, *scsi_datap_org; uae_u32 scsi_cmd_len_orig = as->cmd_len; - uae_u8 cmd[16]; + uae_u8 cmd[16] = { 0 }; uae_u8 replydata[256]; int datalen = as->len; int senselen = as->sense_len; @@ -987,14 +1377,14 @@ static int execscsicmd_direct (int unitnum, struct amigascsi *as) int sys_command_scsi_direct_native (int unitnum, struct amigascsi *as) { - if (scsiemu) { + if (scsiemu[unitnum]) { return execscsicmd_direct (unitnum, as); } else { - if (!device_func[DF_SCSI] || !device_func[DF_SCSI]->exec_direct) + if (!device_func[unitnum]->exec_direct) return -1; } - int ret = device_func[DF_SCSI]->exec_direct (unitnum, as); - if (!ret && device_func[DF_SCSI]->isatapi(unitnum)) + int ret = device_func[unitnum]->exec_direct (unitnum, as); + if (!ret && device_func[unitnum]->isatapi(unitnum)) scsi_atapi_fixup_inquiry (as); return ret; } @@ -1018,6 +1408,8 @@ int sys_command_scsi_direct (int unitnum, uaecptr acmd) as.cmd_len = get_word (acmd + 16); for (i = 0; i < as.cmd_len; i++) as.cmd[i] = get_byte (ap++); + while (i < sizeof as.cmd) + as.cmd[i++] = 0; as.flags = get_byte (acmd + 20); as.sense_len = get_word (acmd + 26); diff --git a/blkdev_cdimage.cpp b/blkdev_cdimage.cpp index 1d0396a0..8679a044 100644 --- a/blkdev_cdimage.cpp +++ b/blkdev_cdimage.cpp @@ -56,6 +56,7 @@ struct cdtoc struct cdunit { bool enabled; + bool open; uae_u8 buffer[2352]; struct cdtoc toc[102]; int tracks; @@ -65,8 +66,8 @@ struct cdunit { int cdda_play_finished; int cdda_play; int cdda_paused; - int cdda_volume; - int cdda_volume_main; + int cdda_volume[2]; + int cdda_scan; int cd_last_pos; int cdda_start, cdda_end; play_subchannel_callback cdda_subfunc; @@ -75,9 +76,19 @@ struct cdunit { int donotmountme; TCHAR newfile[MAX_DPATH]; uae_sem_t sub_sem; + struct device_info di; }; -static struct cdunit cdunits[MAX_TOTAL_DEVICES]; +static struct cdunit cdunits[MAX_TOTAL_SCSI_DEVICES]; +static int bus_open; + +static struct cdunit *unitisopen (int unitnum) +{ + struct cdunit *cdu = &cdunits[unitnum]; + if (cdu->open) + return cdu; + return NULL; +} static struct cdtoc *findtoc (struct cdunit *cdu, int *sectorp) { @@ -164,9 +175,36 @@ static int getsub (uae_u8 *dst, struct cdunit *cdu, struct cdtoc *t, int sector) return ret; } +static void sub_to_interleaved (const uae_u8 *s, uae_u8 *d) +{ + for (int i = 0; i < 8 * 12; i ++) { + int dmask = 0x80; + int smask = 1 << (7 - (i & 7)); + (*d) = 0; + for (int j = 0; j < 8; j++) { + (*d) |= (s[(i / 8) + j * 12] & smask) ? dmask : 0; + dmask >>= 1; + } + d++; + } +} +static void sub_to_deinterleaved (const uae_u8 *s, uae_u8 *d) +{ + for (int i = 0; i < 8 * 12; i ++) { + int dmask = 0x80; + int smask = 1 << (7 - (i / 12)); + (*d) = 0; + for (int j = 0; j < 8; j++) { + (*d) |= (s[(i % 12) * 8 + j] & smask) ? dmask : 0; + dmask >>= 1; + } + d++; + } +} + static void dosub (struct cdunit *cdu, struct cdtoc *t, int sector) { - uae_u8 *s, *d; + uae_u8 *d; uae_u8 subbuf[SUB_CHANNEL_SIZE]; uae_u8 subbuf2[SUB_CHANNEL_SIZE]; @@ -181,36 +219,8 @@ static void dosub (struct cdunit *cdu, struct cdtoc *t, int sector) memset (subbuf, 0, SUB_CHANNEL_SIZE); int mode = getsub (subbuf, cdu, t, sector); if (mode == 2) { // deinterleaved -> interleaved - s = subbuf; - d = subbuf2; - for (int i = 0; i < 8 * 12; i ++) { - int dmask = 0x80; - int smask = 1 << (7 - (i & 7)); - (*d) = 0; - for (int j = 0; j < 8; j++) { - (*d) |= (s[(i / 8) + j * 12] & smask) ? dmask : 0; - dmask >>= 1; - } - d++; - } -#if 0 - uae_u8 subbuf3[SUB_CHANNEL_SIZE]; - s = subbuf2; - d = subbuf3; - for (int i = 0; i < 8 * 12; i ++) { - int dmask = 0x80; - int smask = 1 << (7 - (i / 12)); - (*d) = 0; - for (int j = 0; j < 8; j++) { - (*d) |= (s[(i % 12) * 8 + j] & smask) ? dmask : 0; - dmask >>= 1; - } - d++; - } -#endif + sub_to_interleaved (subbuf, subbuf2); d = subbuf2; - - } else { d = subbuf; } @@ -229,10 +239,10 @@ static void *cdda_play_func (void *v) int i; WAVEHDR whdr[2]; MMRESULT mmr; - int volume, volume_main; + int volume[2], volume_main; int oldplay; mp3decoder *mp3dec = NULL; - struct cdunit *cdu = &cdunits[0]; + struct cdunit *cdu = (struct cdunit*)v; int firstloops; for (i = 0; i < 2; i++) { @@ -250,7 +260,7 @@ static void *cdda_play_func (void *v) bufon[0] = bufon[1] = 0; bufnum = 0; buffered = 0; - volume = -1; + volume[0] = volume[1] = -1; volume_main = -1; if (cdda_openwav ()) { @@ -294,6 +304,8 @@ static void *cdda_play_func (void *v) } } firstloops = 25; + while (cdu->cdda_paused && cdu->cdda_play > 0) + Sleep (10); } while (!(whdr[bufnum].dwFlags & WHDR_DONE)) { @@ -303,6 +315,9 @@ static void *cdda_play_func (void *v) } bufon[bufnum] = 0; + if (!isaudiotrack (&cdu->di.toc, cdda_pos)) + goto end; // data track? + if ((cdda_pos < cdu->cdda_end || cdu->cdda_end == 0xffffffff) && !cdu->cdda_paused && cdu->cdda_play > 0) { struct cdtoc *t; int sector, cnt; @@ -321,7 +336,13 @@ static void *cdda_play_func (void *v) for (cnt = 0; cnt < num_sectors; cnt++) { sector = cdda_pos; - cdda_pos++; + if (cdu->cdda_scan) { + cdda_pos += cdu->cdda_scan; + if (cdda_pos < 0) + cdda_pos = 0; + } else { + cdda_pos++; + } if (cdda_pos - num_sectors < cdu->cdda_end && cdda_pos >= cdu->cdda_end) dofinish = 1; @@ -344,20 +365,22 @@ static void *cdda_play_func (void *v) } - volume = cdu->cdda_volume; volume_main = currprefs.sound_volume; - int vol_mult = (100 - volume_main) * volume / 100; - if (vol_mult) - vol_mult++; - if (vol_mult >= 65536) - vol_mult = 65536; + int vol_mult[2]; + for (int j = 0; j < 2; j++) { + volume[j] = cdu->cdda_volume[j]; + vol_mult[j] = (100 - volume_main) * volume[j] / 100; + if (vol_mult[j]) + vol_mult[j]++; + if (vol_mult[j] >= 32768) + vol_mult[j] = 32768; + } uae_s16 *p = (uae_s16*)(px[bufnum]); for (i = 0; i < num_sectors * 2352 / 4; i++) { - p[i * 2 + 0] = p[i * 2 + 0] * vol_mult / 65536; - p[i * 2 + 1] = p[i * 2 + 1] * vol_mult / 65536; + p[i * 2 + 0] = p[i * 2 + 0] * vol_mult[0] / 32768; + p[i * 2 + 1] = p[i * 2 + 1] * vol_mult[1] / 32768; } - bufon[bufnum] = 1; mmr = waveOutWrite (cdda_wavehandle, &whdr[bufnum], sizeof (WAVEHDR)); if (mmr != MMSYSERR_NOERROR) { @@ -419,17 +442,18 @@ static void cdda_stop (struct cdunit *cdu) static int command_pause (int unitnum, int paused) { - struct cdunit *cdu = &cdunits[unitnum]; - if (unitnum) - return 0; + struct cdunit *cdu = unitisopen (unitnum); + if (!cdu) + return -1; + int old = cdu->cdda_paused; cdu->cdda_paused = paused; - return 1; + return old; } static int command_stop (int unitnum) { - struct cdunit *cdu = &cdunits[unitnum]; - if (unitnum) + struct cdunit *cdu = unitisopen (unitnum); + if (!cdu) return 0; cdda_stop (cdu); return 1; @@ -437,34 +461,35 @@ static int command_stop (int unitnum) static int command_play (int unitnum, int startlsn, int endlsn, int scan, play_subchannel_callback subfunc) { - struct cdunit *cdu = &cdunits[unitnum]; - if (unitnum) + struct cdunit *cdu = unitisopen (unitnum); + if (!cdu) + return 0; + if (!isaudiotrack (&cdu->di.toc, startlsn)) return 0; - - cdu->cdda_paused = 0; cdu->cdda_play_finished = 0; cdu->cd_last_pos = startlsn; cdu->cdda_start = startlsn; cdu->cdda_end = endlsn; cdu->cdda_subfunc = subfunc; + cdu->cdda_scan = scan > 0 ? 10 : (scan < 0 ? 10 : 0); if (!cdu->cdda_play) - uae_start_thread (L"cdda_play", cdda_play_func, NULL, NULL); + uae_start_thread (L"cdda_play", cdda_play_func, cdu, NULL); cdu->cdda_play++; return 1; } static int command_qcode (int unitnum, uae_u8 *buf, int sector) { - struct cdunit *cdu = &cdunits[unitnum]; + struct cdunit *cdu = unitisopen (unitnum); + if (!cdu) + return 0; + uae_u8 subbuf[SUB_CHANNEL_SIZE]; uae_u8 *p; int trk; int pos; int status; - if (unitnum) - return NULL; - memset (buf, 0, SUBQ_SIZE); p = buf; @@ -506,46 +531,89 @@ static int command_qcode (int unitnum, uae_u8 *buf, int sector) return 1; } -static void command_volume (int unitnum, uae_u16 volume) +static uae_u32 command_volume (int unitnum, uae_u16 volume_left, uae_u16 volume_right) { - struct cdunit *cdu = &cdunits[unitnum]; - cdu->cdda_volume = volume; + struct cdunit *cdu = unitisopen (unitnum); + if (!cdu) + return -1; + uae_u32 old = (cdu->cdda_volume[1] << 16) | (cdu->cdda_volume[0] << 0); + cdu->cdda_volume[0] = volume_left; + cdu->cdda_volume[1] = volume_right; + return old; } -uae_u8 *command_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize) +static int command_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize, uae_u16 extra) { - struct cdunit *cdu = &cdunits[unitnum]; + int ret = 0; + struct cdunit *cdu = unitisopen (unitnum); + if (!cdu) + return 0; struct cdtoc *t = findtoc (cdu, §or); int offset; - if (unitnum) - return NULL; if (!t || t->handle == NULL) - return NULL; - + return 0; cdda_stop (cdu); - if (sectorsize > t->size) - return NULL; - offset = 0; - if (sectorsize == 2336 && t->size == 2352) - offset = 16; - zfile_fseek (t->handle, t->offset + sector * t->size + offset, SEEK_SET); - if (data) + if (sectorsize > 0) { + if (sectorsize > t->size) + return 0; + offset = 0; + if (sectorsize == 2336 && t->size == 2352) + offset = 16; + zfile_fseek (t->handle, t->offset + sector * t->size + offset, SEEK_SET); zfile_fread (data, sectorsize, size, t->handle); - else - zfile_fread (cdu->buffer, sectorsize, 1, t->handle); - cdu->cd_last_pos = sector; - return cdu->buffer; + cdu->cd_last_pos = sector; + ret = sectorsize * size; + } else { + uae_u8 cmd9 = extra >> 8; + int sync = (cmd9 >> 7) & 1; + int headercodes = (cmd9 >> 5) & 3; + int userdata = (cmd9 >> 4) & 1; + int edcecc = (cmd9 >> 3) & 1; + int errorfield = (cmd9 >> 1) & 3; + uae_u8 subs = extra & 7; + if (subs != 0 && subs != 1 && subs != 2 && subs != 4) + return -1; + + if (isaudiotrack (&cdu->di.toc, sector)) { + if (t->size != 2352) + return -2; + for (int i = 0; i < size; i++) { + zfile_fseek (t->handle, t->offset + sector * t->size, SEEK_SET); + zfile_fread (data, t->size, 1, t->handle); + uae_u8 *p = data + t->size; + if (subs) { + uae_u8 subdata[SUB_CHANNEL_SIZE]; + getsub (subdata, cdu, t, sector); + if (subs == 4) { // all, de-interleaved + memcpy (p, subdata, SUB_CHANNEL_SIZE); + p += SUB_CHANNEL_SIZE; + } else if (subs == 2) { // q-only + memcpy (p, subdata + SUB_ENTRY_SIZE, SUB_ENTRY_SIZE); + p += SUB_ENTRY_SIZE; + } else if (subs == 1) { // all, interleaved + sub_to_interleaved (subdata, p); + p += SUB_CHANNEL_SIZE; + } + } + ret += p - data; + data = p; + sector++; + } + } + } + return ret; } -static uae_u8 *command_read (int unitnum, uae_u8 *data, int sector, int size) +static int command_read (int unitnum, uae_u8 *data, int sector, int size) { - struct cdunit *cdu = &cdunits[unitnum]; + struct cdunit *cdu = unitisopen (unitnum); + if (!cdu) + return 0; + struct cdtoc *t = findtoc (cdu, §or); int offset; - if (unitnum) - return NULL; if (!t || t->handle == NULL) return NULL; cdda_stop (cdu); @@ -553,40 +621,37 @@ static uae_u8 *command_read (int unitnum, uae_u8 *data, int sector, int size) if (t->size > 2048) offset = 16; zfile_fseek (t->handle, t->offset + sector * t->size + offset, SEEK_SET); - if (data) - zfile_fread (data, size, 2048, t->handle); - else - zfile_fread (cdu->buffer, 2048, 1, t->handle); + zfile_fread (data, size, 2048, t->handle); cdu->cd_last_pos = sector; - return cdu->buffer; + return 1; } -static struct cd_toc_head *command_toc (int unitnum) +static int command_toc (int unitnum, struct cd_toc_head *th) { - struct cdunit *cdu = &cdunits[unitnum]; - static struct cd_toc_head statictoc; - struct cd_toc *toc = &statictoc.toc[0]; + struct cdunit *cdu = unitisopen (unitnum); + if (!cdu) + return 0; + int i; - if (unitnum) - return NULL; - cdda_stop (cdu); + memset (&cdu->di.toc, 0, sizeof (struct cd_toc_head)); if (!cdu->tracks) - return NULL; + return 0; - memset (&statictoc, 0, sizeof statictoc); - statictoc.first_track = 1; - statictoc.last_track = cdu->tracks; - statictoc.points = cdu->tracks + 3; - statictoc.tracks = cdu->tracks; - statictoc.lastaddress = cdu->toc[cdu->tracks].address; + memset (th, 0, sizeof (struct cd_toc_head)); + struct cd_toc *toc = &th->toc[0]; + th->first_track = 1; + th->last_track = cdu->tracks; + th->points = cdu->tracks + 3; + th->tracks = cdu->tracks; + th->lastaddress = cdu->toc[cdu->tracks].address; toc->adr = 1; toc->point = 0xa0; - toc->track = statictoc.first_track; + toc->track = th->first_track; toc++; - statictoc.first_track_offset = 1; + th->first_track_offset = 1; for (i = 0; i < cdu->tracks; i++) { toc->adr = cdu->toc[i].adr; toc->control = cdu->toc[i].ctrl; @@ -596,19 +661,20 @@ static struct cd_toc_head *command_toc (int unitnum) toc++; } - statictoc.last_track_offset = cdu->tracks; + th->last_track_offset = cdu->tracks; toc->adr = 1; toc->point = 0xa1; - toc->track = statictoc.last_track; + toc->track = th->last_track; toc++; toc->adr = 1; toc->point = 0xa2; - toc->paddress = statictoc.lastaddress; + toc->paddress = th->lastaddress; toc++; + memcpy (&cdu->di.toc, th, sizeof (struct cd_toc_head)); gui_flicker_led (LED_CD, unitnum, 1); - return &statictoc; + return 1; } static void skipspace (TCHAR **s) @@ -653,7 +719,7 @@ static int readval (const TCHAR *s) return _tcstol (s, &endptr, base); } -static int parseccd (struct cdunit *cdu, struct zfile *zcue, TCHAR *img) +static int parseccd (struct cdunit *cdu, struct zfile *zcue, const TCHAR *img) { int mode; int num, tracknum, trackmode; @@ -782,7 +848,7 @@ static int parseccd (struct cdunit *cdu, struct zfile *zcue, TCHAR *img) return cdu->tracks; } -static int parsecue (struct cdunit *cdu, struct zfile *zcue, TCHAR *img) +static int parsecue (struct cdunit *cdu, struct zfile *zcue, const TCHAR *img) { int tracknum, index0, pregap; int offset, secoffset, newfile; @@ -1002,12 +1068,11 @@ static int parsecue (struct cdunit *cdu, struct zfile *zcue, TCHAR *img) return cdu->tracks; } -static int parse_image (struct cdunit *cdu) +static int parse_image (struct cdunit *cdu, const TCHAR *img) { struct zfile *zcue; int i; - TCHAR *img = currprefs.cdimagefile; - TCHAR *ext; + const TCHAR *ext; int secoffset; secoffset = 0; @@ -1104,105 +1169,39 @@ static void unload_image (struct cdunit *cdu) } -static int open_device (int unitnum) +static int open_device (int unitnum, const TCHAR *ident) { struct cdunit *cdu = &cdunits[unitnum]; - if (!cdu->enabled) + + if (cdu->open) return 0; uae_sem_init (&cdu->sub_sem, 0, 1); - if (!cdu->tracks) - parse_image (cdu); + parse_image (cdu, ident); + cdu->open = true; + cdu->enabled = true; + cdu->cdda_volume[0] = 0x7fff; + cdu->cdda_volume[1] = 0x7fff; +#ifdef RETROPLATFORM + rp_cd_change (unitnum, 0); + rp_cd_image_change (unitnum, currprefs.cdimagefile[unitnum]); +#endif return 1; } static void close_device (int unitnum) { struct cdunit *cdu = &cdunits[unitnum]; + if (cdu->open == false) + return; + cdda_stop (cdu); unload_image (cdu); uae_sem_destroy (&cdu->sub_sem); -} - -static int mountme (struct cdunit *cdu, bool checkparse) -{ - sys_command_setunit (-1); - - bool sel = false; - cdu->donotmountme = 1; - device_func_init (DEVICE_TYPE_ANY | DEVICE_TYPE_USE_OLD); - for (int i = 0; i < MAX_TOTAL_DEVICES && !sel; i++) { - int opened = sys_command_isopen (i); - struct device_info *discsi, discsi2; - discsi = 0; - if (sys_command_open (DF_IOCTL, i)) { - discsi = sys_command_info (DF_IOCTL, i, &discsi2, 0); - if (discsi && discsi->type == INQ_ROMD) { - if (!_tcsicmp (currprefs.cdimagefile, discsi->label)) { - sys_command_setunit (i); - write_log (L"Drive '%s' (unit=%d) selected (media=%d)\n", discsi->label, i, discsi->media_inserted); - cdu->donotmountme = false; - return -1; - } - } - } - } - cdu->donotmountme = -1; - device_func_init (DEVICE_TYPE_ANY | DEVICE_TYPE_USE_OLD); // activate us again - cdu->donotmountme = 0; - if (checkparse) { - sys_command_setunit (0); - parse_image (cdu); - int media = cdu->tracks > 0; - write_log (L"CDEMU (%s) selected (media=%d)\n", currprefs.cdimagefile, media); - return 1; - } - return 0; -} - -void cdimage_vsync (void) -{ - struct cdunit *cdu = &cdunits[0]; - - if (_tcscmp (changed_prefs.cdimagefile, currprefs.cdimagefile)) { - _tcscpy (cdu->newfile, changed_prefs.cdimagefile); - changed_prefs.cdimagefile[0] = currprefs.cdimagefile[0] = 0; - cdu->imagechange = 3 * 50; - unload_image (cdu); - int pollmode = 0; - scsi_do_disk_change (-1, 0, &pollmode); - if (pollmode) - cdu->imagechange = 8 * 50; - write_log (L"CD: eject (%s)\n", pollmode ? L"slow" : L"fast"); -#ifdef RETROPLATFORM - rp_cd_image_change (0, NULL); -#endif - } - if (cdu->imagechange == 0) - return; - cdu->imagechange--; - if (cdu->imagechange > 0) - return; - _tcscpy (currprefs.cdimagefile, cdu->newfile); - _tcscpy (changed_prefs.cdimagefile, cdu->newfile); - cdu->newfile[0] = 0; - write_log (L"CD: delayed insert '%s'\n", currprefs.cdimagefile[0] ? currprefs.cdimagefile : L""); - if (currprefs.scsi) { - cdu->donotmountme = 1; - int un = scsi_do_disk_device_change (); - cdu->donotmountme = 0; - if (un < 0) { - cdu->donotmountme = -1; - device_func_init (DEVICE_TYPE_ANY); // activate us again - cdu->donotmountme = 0; - parse_image (cdu); - scsi_do_disk_change (255, 1, NULL); - } - } else { - mountme (cdu, true); - } + cdu->open = false; + cdu->enabled = false; #ifdef RETROPLATFORM - rp_cd_image_change (0, currprefs.cdimagefile); + rp_cd_change (unitnum, 1); + rp_cd_image_change (unitnum, currprefs.cdimagefile[unitnum]); #endif - config_changed = 1; } static int ismedia (int unitnum, int quick) @@ -1216,8 +1215,10 @@ static int ismedia (int unitnum, int quick) static struct device_info *info_device (int unitnum, struct device_info *di, int quick) { struct cdunit *cdu = &cdunits[unitnum]; + memset (di, 0, sizeof (struct device_info)); if (!cdu->enabled) return 0; + di->open = cdu->open; di->removable = 1; di->bus = unitnum; di->target = 0; @@ -1230,71 +1231,43 @@ static struct device_info *info_device (int unitnum, struct device_info *di, int di->sectorspertrack = cdu->cdsize / di->bytespersector; if (ismedia (unitnum, 1)) { di->media_inserted = 1; - _tcscpy (di->mediapath, currprefs.cdimagefile); + _tcscpy (di->mediapath, currprefs.cdimagefile[0]); } memset (&di->toc, 0, sizeof (struct cd_toc_head)); - struct cd_toc_head *th = command_toc (unitnum); - if (th) - memcpy (&di->toc, th, sizeof (struct cd_toc_head)); + command_toc (unitnum, &di->toc); di->write_protected = 1; di->type = INQ_ROMD; - di->id = 255; + di->unitnum = unitnum + 1; _tcscpy (di->label, L"CDEMU"); return di; } -static int check_bus (int flags) +static void close_bus (void) { - struct cdunit *cdu = &cdunits[0]; - cdu->enabled = true; - if (!(flags & DEVICE_TYPE_CHECKAVAIL)) - return 1; - if (cdu->donotmountme < 0 || (flags & DEVICE_TYPE_ALLOWEMU)) - return 1; - if (cdu->donotmountme > 0) - return 0; - if (cdu->imagechange) - return 1; - int v = currprefs.cdimagefile[0] ? 1 : 0; - if (v) { - if (mountme (cdu, false) < 0) // is it supported \? - return 0; - } - if (currprefs.cdimagefileuse) { - v = 1; + if (!bus_open) { + write_log (L"IMAGE close_bus() when already closed!\n"); + return; } - return v; + bus_open = 0; + write_log (L"IMAGE driver closed.\n"); } static int open_bus (int flags) { - struct cdunit *cdu = &cdunits[0]; - if (!(flags & DEVICE_TYPE_CHECKAVAIL)) + if (bus_open) { + write_log (L"IOCTL open_bus() more than once!\n"); return 1; - if (cdu->donotmountme < 0 || (flags & DEVICE_TYPE_ALLOWEMU)) - return 1; - if (cdu->donotmountme > 0) - return 0; - - mountme (cdu, true); -#ifdef RETROPLATFORM - rp_cd_change (0, 0); - rp_cd_image_change (0, currprefs.cdimagefile); -#endif + } + bus_open = 1; + write_log (L"Image driver open.\n"); return 1; } -static void close_bus (void) -{ -#ifdef RETROPLATFORM - rp_cd_change (0, 1); -#endif -} - struct device_functions devicefunc_cdimage = { - check_bus, open_bus, close_bus, open_device, close_device, info_device, + L"IMAGE", + open_bus, close_bus, open_device, close_device, info_device, 0, 0, 0, command_pause, command_stop, command_play, command_volume, command_qcode, command_toc, command_read, command_rawread, 0, - 0, 0, ismedia + 0, ismedia }; diff --git a/cdtv.cpp b/cdtv.cpp index eda5756f..100153d8 100644 --- a/cdtv.cpp +++ b/cdtv.cpp @@ -83,7 +83,6 @@ static uae_u32 last_play_pos, last_play_end; static volatile int cdtv_hsync, dma_finished, cdtv_sectorsize; static volatile uae_u64 dma_wait; -static int first; static int cd_volume, cd_volume_stored; static int cd_led; static int frontpanel; @@ -133,10 +132,8 @@ static void subreset (void) static int get_toc (void) { datatrack = 0; - struct cd_toc_head *t = sys_command_cd_toc (DF_IOCTL, unitnum); - if (!t) + if (!sys_command_cd_toc (unitnum, &toc)) return 0; - memcpy (&toc, t, sizeof toc); last_cd_position = toc.lastaddress; if (toc.first_track == 1 && (toc.toc[toc.first_track_offset].control & 0x0c) == 0x04) datatrack = 1; @@ -154,7 +151,7 @@ static void finished_cdplay (void) static int get_qcode (void) { - if (!sys_command_cd_qcode (DF_IOCTL, unitnum, cdrom_qcode)) + if (!sys_command_cd_qcode (unitnum, cdrom_qcode)) return 0; if (cd_playing) { if (cdrom_qcode[1] == AUDIO_STATUS_IN_PROGRESS) { @@ -182,8 +179,8 @@ static void cdaudiostop (void) cd_motor = 0; if (unitnum < 0) return; - sys_command_cd_pause (DF_IOCTL, unitnum, 0); - sys_command_cd_stop (DF_IOCTL, unitnum); + sys_command_cd_pause (unitnum, 0); + sys_command_cd_stop (unitnum); } static void cdaudiostopfp (void) { @@ -194,7 +191,7 @@ static void cdaudiostopfp (void) static int pause_audio (int pause) { - sys_command_cd_pause (DF_IOCTL, unitnum, pause); + sys_command_cd_pause (unitnum, pause); if (!cd_playing) { cd_paused = 0; cd_audio_status = AUDIO_STATUS_NO_STATUS; @@ -226,7 +223,7 @@ static int ismedia (void) { if (unitnum < 0) return 0; - return sys_command_ismedia (DF_IOCTL, unitnum, 0); + return sys_command_ismedia (unitnum, 0); } static int issub (void) @@ -284,10 +281,10 @@ static void do_play (void) uae_u32 end = read_comm_pipe_u32_blocking (&requests); uae_u32 scan = read_comm_pipe_u32_blocking (&requests); subreset (); - sys_command_cd_pause (DF_IOCTL, unitnum, 0); + sys_command_cd_pause (unitnum, 0); cd_audio_status = AUDIO_STATUS_PLAY_ERROR; - sys_command_cd_volume (DF_IOCTL, unitnum, (cd_volume_stored << 6) | (cd_volume_stored >> 4)); - if (sys_command_cd_play (DF_IOCTL, unitnum, start, end, 0, subfunc)) { + sys_command_cd_volume (unitnum, (cd_volume_stored << 5) | (cd_volume_stored >> 5), (cd_volume_stored << 5) | (cd_volume_stored >> 5)); + if (sys_command_cd_play (unitnum, start, end, 0, subfunc)) { cd_audio_status = AUDIO_STATUS_IN_PROGRESS; cd_playing = 1; } else { @@ -358,8 +355,8 @@ static int play_cd (uae_u8 *p) cd_paused = 0; cd_motor = 0; cd_audio_status = AUDIO_STATUS_PLAY_COMPLETE; - sys_command_cd_pause (DF_IOCTL, unitnum, 0); - sys_command_cd_stop (DF_IOCTL, unitnum); + sys_command_cd_pause (unitnum, 0); + sys_command_cd_stop (unitnum); cd_isready = 50; cd_error = 1; return 0; @@ -553,8 +550,6 @@ static void cdrom_command_thread (uae_u8 b) cdrom_command_output[0] = flag; cdrom_command_accepted (1, s, &cdrom_command_cnt_in); cd_finished = 0; - if (first == -1) - first = 100; } break; case 0x82: @@ -616,18 +611,16 @@ static void cdrom_command_thread (uae_u8 b) } } -static uae_u8 *read_raw (int sector, int size) +static int read_raw (int sector, uae_u8 *dst, int blocksize) { int osector = sector - 150; static struct zfile *f; static int track; int trackcnt; TCHAR fname[MAX_DPATH]; - static uae_u8 buf[4096]; uae_u32 prevlsn = 0; struct cd_toc *t = &toc.toc[0]; - memset (buf, 0, sizeof buf); trackcnt = 0; for (;;) { int lsn = t->paddress; @@ -651,18 +644,18 @@ static uae_u8 *read_raw (int sector, int size) track = trackcnt; } if (f) { - write_log (L"CDTV fakeraw: %dx%d=%d\n", sector, size, sector * size); - zfile_fseek (f, sector * size, SEEK_SET); - zfile_fread (buf, size, 1, f); - return buf; + write_log (L"CDTV fakeraw: %dx%d=%d\n", sector, blocksize, sector * blocksize); + zfile_fseek (f, sector * blocksize, SEEK_SET); + zfile_fread (dst, blocksize, 1, f); + return 1; } - return sys_command_cd_rawread (DF_IOCTL, unitnum, NULL, osector, size, 1); + return sys_command_cd_rawread (unitnum, dst, osector, blocksize, 1); } static void dma_do_thread (void) { static int readsector; - uae_u8 *p = NULL; + int didread = 0; int cnt; while (dma_finished) @@ -677,13 +670,14 @@ static void dma_do_thread (void) #endif dma_wait += cnt * (uae_u64)312 * 50 / 75 + 1; while (cnt > 0 && dmac_dma) { - if (!p || readsector != (cdrom_offset / cdtv_sectorsize)) { + uae_u8 buffer[2352]; + if (!didread || readsector != (cdrom_offset / cdtv_sectorsize)) { readsector = cdrom_offset / cdtv_sectorsize; if (cdtv_sectorsize == 2336) - p = read_raw (readsector, cdtv_sectorsize); + didread = read_raw (readsector, buffer, cdtv_sectorsize); else - p = sys_command_cd_read (DF_IOCTL, unitnum, NULL, readsector, 1); - if (!p) { + didread = sys_command_cd_read (unitnum, buffer, readsector, 1); + if (!didread) { cd_error = 1; activate_stch = 1; write_log (L"CDTV: CD read error!\n"); @@ -691,8 +685,8 @@ static void dma_do_thread (void) } } - put_byte (dmac_acr, p[(cdrom_offset % cdtv_sectorsize) + 0]); - put_byte (dmac_acr + 1, p[(cdrom_offset % cdtv_sectorsize) + 1]); + put_byte (dmac_acr, buffer[(cdrom_offset % cdtv_sectorsize) + 0]); + put_byte (dmac_acr + 1, buffer[(cdrom_offset % cdtv_sectorsize) + 1]); cnt--; dmac_acr += 2; cdrom_length -= 2; @@ -747,10 +741,10 @@ static void *dev_thread (void *p) } break; case 0x0102: // pause - sys_command_cd_pause (DF_IOCTL, unitnum, 1); + sys_command_cd_pause (unitnum, 1); break; case 0x0103: // unpause - sys_command_cd_pause (DF_IOCTL, unitnum, 0); + sys_command_cd_pause (unitnum, 0); break; case 0x0104: // stop cdaudiostop (); @@ -787,8 +781,8 @@ static void init_play (int start, int end) last_play_pos = start; last_play_end = end; #ifdef CDTV_DEBUG - write_log (L"PLAY CD AUDIO from %d-%d, %06X (%d) to %06X (%d)\n", - track_start, track_end, lsn2msf (start), start, lsn2msf (end), end); + write_log (L"PLAY CD AUDIO from %06X (%d) to %06X (%d)\n", + lsn2msf (start), start, lsn2msf (end), end); #endif play_state = 1; subreset (); @@ -950,7 +944,7 @@ static void tp_bput (int addr, uae_u8 v) if (cd_volume > 1023) cd_volume = 1023; if (unitnum >= 0) - sys_command_cd_volume (DF_IOCTL, unitnum, (cd_volume << 6) | (cd_volume >> 4)); + sys_command_cd_volume (unitnum, (cd_volume << 5) | (cd_volume >> 5), (cd_volume << 5) | (cd_volume >> 5)); cd_volume_stored = cd_volume; cd_volume = 0; volstrobe2 = 1; @@ -1059,29 +1053,29 @@ void cdtv_getdmadata (uae_u32 *acr) static void do_hunt (void) { int i; - for (i = 0; i < MAX_TOTAL_DEVICES; i++) { - if (sys_command_ismedia (DF_IOCTL, i, 1) > 0) + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + if (sys_command_ismedia (i, 1) > 0) break; } - if (i == MAX_TOTAL_DEVICES) { - if (unitnum >= 0 && sys_command_ismedia (DF_IOCTL, unitnum, 1) >= 0) + if (i == MAX_TOTAL_SCSI_DEVICES) { + if (unitnum >= 0 && sys_command_ismedia (unitnum, 1) >= 0) return; - for (i = 0; i < MAX_TOTAL_DEVICES; i++) { - if (sys_command_ismedia (DF_IOCTL, i, 1) >= 0) + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + if (sys_command_ismedia (i, 1) >= 0) break; } - if (i == MAX_TOTAL_DEVICES) + if (i == MAX_TOTAL_SCSI_DEVICES) return; } if (unitnum >= 0) { cdaudiostop (); int ou = unitnum; unitnum = -1; - sys_command_close (DF_IOCTL, ou); + sys_command_close (ou); } - if (sys_command_open (DF_IOCTL, i) > 0) { + if (sys_command_open (i) > 0) { struct device_info di = { 0 }; - sys_command_info (DF_IOCTL, i, &di, 0); + sys_command_info (i, &di, 0); unitnum = i; cd_hunt = 0; write_log (L"CDTV: autodetected unit %d ('%s')\n", unitnum, di.label); @@ -1285,7 +1279,6 @@ static void cdtv_reset (void) cd_finished = 0; cd_led = 0; stch = 1; - first = -1; } static uae_u32 dmac_bget2 (uaecptr addr) @@ -1568,31 +1561,31 @@ static void open_unit (void) struct device_info di1, *di2; int first = -1; int cdtvunit = -1, audiounit = -1; - int opened[MAX_TOTAL_DEVICES]; + int opened[MAX_TOTAL_SCSI_DEVICES]; int i; if (unitnum >= 0) - sys_command_close (DF_IOCTL, unitnum); + sys_command_close (unitnum); unitnum = -1; cdtv_reset (); - if (!device_func_init (DEVICE_TYPE_IOCTL)) { + if (!device_func_init (0)) { write_log (L"no CDROM support\n"); return; } - for (unitnum = 0; unitnum < MAX_TOTAL_DEVICES; unitnum++) { + for (unitnum = 0; unitnum < MAX_TOTAL_SCSI_DEVICES; unitnum++) { opened[unitnum] = 0; - if (sys_command_open (DF_IOCTL, unitnum)) { + if (sys_command_open (unitnum)) { opened[unitnum] = 1; - di2 = sys_command_info (DF_IOCTL, unitnum, &di1, 0); + di2 = sys_command_info (unitnum, &di1, 0); if (di2 && di2->type == INQ_ROMD) { write_log (L"%s: ", di2->label); if (first < 0) first = unitnum; if (get_toc () > 0) { if (datatrack) { - uae_u8 *p = sys_command_cd_read (DF_IOCTL, unitnum, NULL, 16, 1); - if (p) { - if (!memcmp (p + 8, "CDTV", 4)) { + uae_u8 buffer[2048]; + if (sys_command_cd_read (unitnum, buffer, 16, 1)) { + if (!memcmp (buffer + 8, "CDTV", 4)) { write_log (L"CDTV\n"); if (cdtvunit < 0) cdtvunit = unitnum; @@ -1616,9 +1609,9 @@ static void open_unit (void) unitnum = first; if (unitnum >= 0) opened[unitnum] = 0; - for (i = 0; i < MAX_TOTAL_DEVICES; i++) { + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { if (opened[i]) - sys_command_close (DF_IOCTL, i); + sys_command_close (i); } cd_media = 0; if (unitnum >= 0) { @@ -1780,7 +1773,7 @@ void cdtv_free (void) thread_alive = 0; cdaudiostop (); if (unitnum >= 0) - sys_command_close (DF_IOCTL, unitnum); + sys_command_close (unitnum); unitnum = -1; configured = 0; } diff --git a/cfgfile.cpp b/cfgfile.cpp index 5267e70f..4d6ac581 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -29,6 +29,7 @@ #include "filesys.h" #include "fsdb.h" #include "disk.h" +#include "blkdev.h" #include "statusline.h" static int config_newfilesystem; @@ -178,6 +179,7 @@ static const TCHAR *dongles[] = L"rugby coach", L"cricket captain", L"leviathan", NULL }; +static const TCHAR *cdmodes[] = { L"", L"image", L"ioctl", L"spti", L"aspi", 0 }; static const TCHAR *obsolete[] = { L"accuracy", L"gfx_opengl", L"gfx_32bit_blits", L"32bit_blits", @@ -554,8 +556,18 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) } } - if (p->cdimagefile[0] || p->cdimagefileuse) - cfgfile_write_str (f, L"cdimage0", p->cdimagefile); + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + if (p->cdimagefile[i][0] || p->cdimagefileuse[i]) { + TCHAR tmp2[MAX_DPATH]; + _stprintf (tmp, L"cdimage%d", i); + _tcscpy (tmp2, p->cdimagefile[i]); + if (p->cdscsidevicetype[i] != 0 || _tcschr (p->cdimagefile[i], ',')) { + _tcscat (tmp2, L","); + _tcscat (tmp2, cdmodes[p->cdscsidevicetype[i]]); + } + cfgfile_write_str (f, tmp, tmp2); + } + } if (p->quitstatefile[0]) cfgfile_write_str (f, L"statefile_quit", p->quitstatefile); @@ -1127,9 +1139,23 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value) } } - if (cfgfile_path (option, value, L"cdimage0", p->cdimagefile, sizeof p->cdimagefile / sizeof (TCHAR))) { - p->cdimagefileuse = true; - return 1; + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + TCHAR tmp[20]; + _stprintf (tmp, L"cdimage%d", i); + if (!_tcsicmp (option, tmp)) { + TCHAR *next = _tcsrchr (value, ','); + if (next) { + *next = 0; + TCHAR *next2 = _tcschr (next + 1, ':'); + if (next2) + *next2 = 0; + cfgfile_intval (option, next + 1, tmp, &p->cdscsidevicetype[i], 1); + } + _tcsncpy (p->cdimagefile[i], value, sizeof p->cdimagefile[i]); + p->cdimagefile[i][sizeof p->cdimagefile[i] - 1] = 0; + p->cdimagefileuse[i] = true; + return 1; + } } if (cfgfile_intval (option, value, L"sound_frequency", &p->sound_freq, 1)) { @@ -3607,6 +3633,8 @@ void default_prefs (struct uae_prefs *p, int type) inputdevice_default_prefs (p); + blkdev_default_prefs (p); + zfile_fclose (default_file); default_file = NULL; f = zfile_fopen_empty (NULL, L"configstore", 100000); diff --git a/custom.cpp b/custom.cpp index 35f6effb..f8211b88 100644 --- a/custom.cpp +++ b/custom.cpp @@ -174,8 +174,7 @@ int maxhpos = MAXHPOS_PAL; int maxhpos_short = MAXHPOS_PAL; int maxvpos = MAXVPOS_PAL; int maxvpos_nom = MAXVPOS_PAL; // nominal value (same as maxvpos but "faked" maxvpos in fake 60hz modes) -static int hsyncstartpos; -int hsyncstartposnative; +int hsyncstartpos; static int maxvpos_total = 511; int minfirstline = VBLANK_ENDLINE_PAL; int equ_vblank_endline = EQU_ENDLINE_PAL; @@ -2807,7 +2806,6 @@ void init_hz (void) } else { hsyncstartpos = maxhpos_short + 13; } - hsyncstartposnative = coord_hw_to_window_x (hsyncstartpos * 2); eventtab[ev_hsync].oldcycles = get_cycles (); eventtab[ev_hsync].evtime = get_cycles () + HSYNCTIME; events_schedule (); @@ -5083,7 +5081,7 @@ static void vsync_handler (void) picasso_handle_vsync (); #endif audio_vsync (); - cdimage_vsync (); + blkdev_vsync (); if (quit_program > 0) { /* prevent possible infinite loop at wait_cycles().. */ diff --git a/drawing.cpp b/drawing.cpp index 8cdbbca2..7a17e274 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -772,12 +772,13 @@ STATIC_INLINE void fill_line2 (int startpos, int len) static void fill_line (void) { - if (hsyncstartposnative > visible_left_border + gfxvidinfo.width || hposendblank) { + int hs = coord_hw_to_window_x (hsyncstartpos * 2); + if (hs > visible_left_border + gfxvidinfo.width || hposendblank) { fill_line2 (visible_left_border, gfxvidinfo.width); } else { - fill_line2 (visible_left_border, hsyncstartposnative); + fill_line2 (visible_left_border, hs); hposendblank = 1; - fill_line2 (visible_left_border + hsyncstartposnative, gfxvidinfo.width - hsyncstartposnative); + fill_line2 (visible_left_border + hs, gfxvidinfo.width - hs); } } @@ -1918,7 +1919,6 @@ STATIC_INLINE void do_color_changes (line_draw_func worker_border, line_draw_fun int i; int lastpos = visible_left_border; int endpos = visible_left_border + gfxvidinfo.width; - int diff = 1 << lores_shift; for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++) { int regno = curr_color_changes[i].regno; diff --git a/filesys.cpp b/filesys.cpp index 6c898ab6..f8765cc9 100644 --- a/filesys.cpp +++ b/filesys.cpp @@ -332,7 +332,6 @@ static void fixcharset (TCHAR *s) TCHAR *validatevolumename (TCHAR *s) { stripsemicolon (s); - stripspace (s); fixcharset (s); striplength (s, 30); return s; diff --git a/include/blkdev.h b/include/blkdev.h index 7d390e7c..79c83aab 100644 --- a/include/blkdev.h +++ b/include/blkdev.h @@ -1,7 +1,12 @@ -#define MAX_TOTAL_DEVICES 8 #define DEVICE_SCSI_BUFSIZE (65536 - 1024) +#define SCSI_UNIT_NONE 0 +#define SCSI_UNIT_IMAGE 1 +#define SCSI_UNIT_IOCTL 2 +#define SCSI_UNIT_SPTI 3 +#define SCSI_UNIT_ASPI 4 + //#define device_debug write_log #define device_debug @@ -45,13 +50,6 @@ struct cd_toc_head struct cd_toc toc[MAX_TOC_ENTRIES]; }; -#define DEVICE_TYPE_ANY 1 -#define DEVICE_TYPE_SCSI 2 -#define DEVICE_TYPE_IOCTL 3 -#define DEVICE_TYPE_ALLOWEMU 0x10000000 -#define DEVICE_TYPE_CHECKAVAIL 0x20000000 -#define DEVICE_TYPE_USE_OLD 0x40000000 - #define SUB_ENTRY_SIZE 12 #define SUB_CHANNEL_SIZE 96 #define SUBQ_SIZE (4 + 12) @@ -63,10 +61,8 @@ struct cd_toc_head #define AUDIO_STATUS_PLAY_ERROR 0x14 #define AUDIO_STATUS_NO_STATUS 0x15 -#define DF_SCSI 0 -#define DF_IOCTL 1 - struct device_info { + bool open; int type; int media_inserted; int removable; @@ -76,17 +72,15 @@ struct device_info { int sectorspertrack; int bytespersector; int bus, target, lun; - int id; + int unitnum; TCHAR label[MAX_DPATH]; TCHAR mediapath[MAX_DPATH]; + TCHAR vendorid[10]; + TCHAR productid[18]; + TCHAR revision[6]; struct cd_toc_head toc; }; -struct device_scsi_info { - uae_u8 *buffer; - int bufsize; -}; - struct amigascsi { uae_u8 *data; @@ -105,10 +99,9 @@ struct amigascsi typedef int (*check_bus_func)(int flags); typedef int (*open_bus_func)(int flags); typedef void (*close_bus_func)(void); -typedef int (*open_device_func)(int); +typedef int (*open_device_func)(int, const TCHAR*); typedef void (*close_device_func)(int); typedef struct device_info* (*info_device_func)(int, struct device_info*, int); -typedef struct device_scsi_info* (*scsiinfo_func)(int, struct device_scsi_info*); typedef uae_u8* (*execscsicmd_out_func)(int, uae_u8*, int); typedef uae_u8* (*execscsicmd_in_func)(int, uae_u8*, int, int*); typedef int (*execscsicmd_direct_func)(int, struct amigascsi*); @@ -118,68 +111,64 @@ typedef void (*play_subchannel_callback)(uae_u8*, int); typedef int (*pause_func)(int, int); typedef int (*stop_func)(int); typedef int (*play_func)(int, int, int, int, play_subchannel_callback); -typedef void (*volume_func)(int, uae_u16); +typedef uae_u32 (*volume_func)(int, uae_u16, uae_u16); typedef int (*qcode_func)(int, uae_u8*, int); -typedef struct cd_toc_head* (*toc_func)(int); -typedef uae_u8* (*read_func)(int, uae_u8*, int, int); -typedef uae_u8* (*rawread_func)(int, uae_u8*, int, int, int); +typedef int (*toc_func)(int, struct cd_toc_head*); +typedef int (*read_func)(int, uae_u8*, int, int); +typedef int (*rawread_func)(int, uae_u8*, int, int, int, uae_u16); typedef int (*write_func)(int, uae_u8*, int, int); typedef int (*isatapi_func)(int); typedef int (*ismedia_func)(int, int); struct device_functions { - check_bus_func checkbus; - open_bus_func openbus; - close_bus_func closebus; - open_device_func opendev; - close_device_func closedev; - info_device_func info; - execscsicmd_out_func exec_out; - execscsicmd_in_func exec_in; - execscsicmd_direct_func exec_direct; - - pause_func pause; - stop_func stop; - play_func play; + const TCHAR *name; + open_bus_func openbus; + close_bus_func closebus; + open_device_func opendev; + close_device_func closedev; + info_device_func info; + execscsicmd_out_func exec_out; + execscsicmd_in_func exec_in; + execscsicmd_direct_func exec_direct; + + pause_func pause; + stop_func stop; + play_func play; volume_func volume; - qcode_func qcode; - toc_func toc; - read_func read; - rawread_func rawread; - write_func write; + qcode_func qcode; + toc_func toc; + read_func read; + rawread_func rawread; + write_func write; - isatapi_func isatapi; - - scsiinfo_func scsiinfo; - - ismedia_func ismedia; + isatapi_func isatapi; + ismedia_func ismedia; }; -extern struct device_functions *device_func[2]; +extern struct device_functions *device_func[MAX_TOTAL_SCSI_DEVICES]; extern int device_func_init(int flags); extern void device_func_reset(void); -extern int sys_command_open (int mode, int unitnum); -extern void sys_command_close (int mode, int unitnum); +extern int sys_command_open (int unitnum); +extern void sys_command_close (int unitnum); extern int sys_command_isopen (int unitnum); -extern void sys_command_setunit (int unitnum); -extern struct device_info *sys_command_info (int mode, int unitnum, struct device_info *di, int); -extern struct device_scsi_info *sys_command_scsi_info (int mode, int unitnum, struct device_scsi_info *di); -extern void sys_command_cd_pause (int mode, int unitnum, int paused); -extern void sys_command_cd_stop (int mode, int unitnum); -extern int sys_command_cd_play (int mode, int unitnum, int startlsn, int endlsn, int); -extern int sys_command_cd_play (int mode, int unitnum, int startlsn, int endlsn, int scan, play_subchannel_callback subfunc); -extern void sys_command_cd_volume (int mode, int unitnum, uae_u16 volume); -extern int sys_command_cd_qcode (int mode, int unitnum, uae_u8*); -extern struct cd_toc_head *sys_command_cd_toc (int mode, int unitnum); -extern uae_u8 *sys_command_cd_read (int mode, int unitnum, uae_u8 *data, int block, int size); -extern uae_u8 *sys_command_cd_rawread (int mode, int unitnum, uae_u8 *data, int sector, int size, int sectorsize); -extern uae_u8 *sys_command_read (int mode, int unitnum, uae_u8 *data, int block, int size); -extern int sys_command_write (int mode, int unitnum, uae_u8 *data, int block, int size); -extern int sys_command_scsi_direct_native(int unitnum, struct amigascsi *as); +extern struct device_info *sys_command_info (int unitnum, struct device_info *di, int); +extern int sys_command_cd_pause (int unitnum, int paused); +extern void sys_command_cd_stop (int unitnum); +extern int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int); +extern int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan, play_subchannel_callback subfunc); +extern uae_u32 sys_command_cd_volume (int unitnum, uae_u16 volume_left, uae_u16 volume_right); +extern int sys_command_cd_qcode (int unitnum, uae_u8*); +extern int sys_command_cd_toc (int unitnum, struct cd_toc_head*); +extern int sys_command_cd_read (int unitnum, uae_u8 *data, int block, int size); +extern int sys_command_cd_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize); +extern int sys_command_cd_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize, uae_u8 scsicmd9, uae_u8 subs); +extern int sys_command_read (int unitnum, uae_u8 *data, int block, int size); +extern int sys_command_write (int unitnum, uae_u8 *data, int block, int size); +extern int sys_command_scsi_direct_native (int unitnum, struct amigascsi *as); extern int sys_command_scsi_direct (int unitnum, uaecptr request); -extern int sys_command_ismedia (int mode, int unitnum, int quick); +extern int sys_command_ismedia (int unitnum, int quick); extern void scsi_atapi_fixup_pre (uae_u8 *scsi_cmd, int *len, uae_u8 **data, int *datalen, int *parm); extern void scsi_atapi_fixup_post (uae_u8 *scsi_cmd, int len, uae_u8 *olddata, uae_u8 *data, int *datalen, int parm); @@ -187,11 +176,17 @@ extern void scsi_atapi_fixup_post (uae_u8 *scsi_cmd, int len, uae_u8 *olddata, u extern void scsi_log_before (uae_u8 *cdb, int cdblen, uae_u8 *data, int datalen); extern void scsi_log_after (uae_u8 *data, int datalen, uae_u8 *sense, int senselen); -extern void cdimage_vsync (void); +extern void blkdev_vsync (void); extern int msf2lsn (int msf); extern int lsn2msf (int lsn); extern uae_u8 frombcd (uae_u8 v); extern uae_u8 tobcd (uae_u8 v); extern int fromlongbcd (uae_u8 *p); -extern void tolongbcd (uae_u8 *p, int v); \ No newline at end of file +extern void tolongbcd (uae_u8 *p, int v); + +extern void blkdev_default_prefs (struct uae_prefs *p); +extern void blkdev_fix_prefs (struct uae_prefs *p); +extern int isaudiotrack (struct cd_toc_head*, int block); +extern int isdatatrack (struct cd_toc_head*, int block); + diff --git a/include/custom.h b/include/custom.h index 1fe32c9f..61d77941 100644 --- a/include/custom.h +++ b/include/custom.h @@ -110,7 +110,7 @@ extern uae_u16 INTREQR (void); extern int maxhpos, maxhpos_short; extern int maxvpos, maxvpos_nom; -extern int hsyncstartposnative; +extern int hsyncstartpos; extern int minfirstline, vblank_endline, numscrlines; extern int vblank_hz, fake_vblank_hz, vblank_skip, doublescan; extern frame_time_t syncbase; diff --git a/include/execio.h b/include/execio.h index fa7f77c3..8e5f3854 100644 --- a/include/execio.h +++ b/include/execio.h @@ -7,6 +7,29 @@ #define IOERR_UNITBUSY -6 #define IOERR_SELFTEST -7 +#define CDERR_NotSpecified 20 /* general catchall */ +#define CDERR_NoSecHdr 21 /* couldn't even find a sector */ +#define CDERR_BadSecPreamble 22 /* sector looked wrong */ +#define CDERR_BadSecID 23 /* ditto */ +#define CDERR_BadHdrSum 24 /* header had incorrect checksum */ +#define CDERR_BadSecSum 25 /* data had incorrect checksum */ +#define CDERR_TooFewSecs 26 /* couldn't find enough sectors */ +#define CDERR_BadSecHdr 27 /* another "sector looked wrong" */ +#define CDERR_WriteProt 28 /* can't write to a protected disk */ +#define CDERR_NoDisk 29 /* no disk in the drive */ +#define CDERR_SeekError 30 /* couldn't find track 0 */ +#define CDERR_NoMem 31 /* ran out of memory */ +#define CDERR_BadUnitNum 32 /* asked for a unit > NUMUNITS */ +#define CDERR_BadDriveType 33 /* not a drive cd.device understands */ +#define CDERR_DriveInUse 34 /* someone else allocated the drive */ +#define CDERR_PostReset 35 /* user hit reset; awaiting doom */ +#define CDERR_BadDataType 36 /* data on disk is wrong type */ +#define CDERR_InvalidState 37 /* invalid cmd under current conditions */ + +#define CDERR_Phase 42 /* illegal or unexpected SCSI phase */ +#define CDERR_NoBoard 50 /* open failed for non-existant board */ + + #define TDERR_DiskChanged 29 #define CMD_INVALID 0 @@ -34,44 +57,58 @@ #define TAG_SKIP 3 #define TAG_USER (1 << 31) -#define NSDEVTYPE_UNKNOWN 0 -#define NSDEVTYPE_GAMEPORT 1 -#define NSDEVTYPE_TIMER 2 -#define NSDEVTYPE_KEYBOARD 3 -#define NSDEVTYPE_INPUT 4 -#define NSDEVTYPE_TRACKDISK 5 -#define NSDEVTYPE_CONSOLE 6 -#define NSDEVTYPE_SANA2 7 -#define NSDEVTYPE_AUDIO 8 -#define NSDEVTYPE_CLIPBOARD 9 -#define NSDEVTYPE_PRINTER 10 -#define NSDEVTYPE_SERIAL 11 -#define NSDEVTYPE_PARALLEL 12 - -#define CMD_MOTOR 9 -#define CMD_SEEK 10 -#define CMD_FORMAT 11 -#define CMD_REMOVE 12 -#define CMD_CHANGENUM 13 -#define CMD_CHANGESTATE 14 -#define CMD_PROTSTATUS 15 -#define CMD_GETDRIVETYPE 18 -#define CMD_GETNUMTRACKS 19 -#define CMD_ADDCHANGEINT 20 -#define CMD_REMCHANGEINT 21 -#define CMD_GETGEOMETRY 22 -#define CMD_GETDRIVETYPE 18 -#define CMD_GETNUMTRACKS 19 -#define CMD_ADDCHANGEINT 20 -#define CMD_REMCHANGEINT 21 -#define CMD_GETGEOMETRY 22 -#define HD_SCSICMD 28 +#define NSDEVTYPE_UNKNOWN 0 +#define NSDEVTYPE_GAMEPORT 1 +#define NSDEVTYPE_TIMER 2 +#define NSDEVTYPE_KEYBOARD 3 +#define NSDEVTYPE_INPUT 4 +#define NSDEVTYPE_TRACKDISK 5 +#define NSDEVTYPE_CONSOLE 6 +#define NSDEVTYPE_SANA2 7 +#define NSDEVTYPE_AUDIO 8 +#define NSDEVTYPE_CLIPBOARD 9 +#define NSDEVTYPE_PRINTER 10 +#define NSDEVTYPE_SERIAL 11 +#define NSDEVTYPE_PARALLEL 12 -/* Trackdisk64 support */ -#define TD_READ64 24 -#define TD_WRITE64 25 -#define TD_SEEK64 26 -#define TD_FORMAT64 27 +#define CMD_MOTOR 9 +#define CMD_SEEK 10 +#define CMD_FORMAT 11 +#define CMD_REMOVE 12 +#define CMD_CHANGENUM 13 +#define CMD_CHANGESTATE 14 +#define CMD_PROTSTATUS 15 +#define CMD_GETDRIVETYPE 18 +#define CMD_GETNUMTRACKS 19 +#define CMD_ADDCHANGEINT 20 +#define CMD_REMCHANGEINT 21 +#define CMD_GETGEOMETRY 22 +#define CMD_GETDRIVETYPE 18 +#define CMD_GETNUMTRACKS 19 +#define CMD_ADDCHANGEINT 20 +#define CMD_REMCHANGEINT 21 +#define CMD_GETGEOMETRY 22 +#define CD_EJECT 23 +#define TD_READ64 24 +#define TD_WRITE64 25 +#define TD_SEEK64 26 +#define TD_FORMAT64 27 +#define HD_SCSICMD 28 +#define CD_INFO 32 +#define CD_CONFIG 33 +#define CD_TOCMSF 34 +#define CD_TOCLSN 35 +#define CD_READXL 36 +#define CD_PLAYTRACK 37 +#define CD_PLAYMSF 38 +#define CD_PLAYLSN 39 +#define CD_PAUSE 40 +#define CD_SEARCH 41 +#define CD_QCODEMSF 42 +#define CD_QCODELSN 43 +#define CD_ATTENUATE 44 +#define CD_ADDFRAMEINT 45 +#define CD_REMFRAMEINT 46 /* New Style Devices (NSD) support */ #define NSCMD_TD_READ64 0xc000 diff --git a/include/options.h b/include/options.h index 7c106f0e..80479399 100644 --- a/include/options.h +++ b/include/options.h @@ -21,6 +21,8 @@ struct strlist { int unknown; }; +#define MAX_TOTAL_SCSI_DEVICES 8 + /* maximum number native input devices supported (single type) */ #define MAX_INPUT_DEVICES 8 /* maximum number of native input device's buttons and axles supported */ @@ -282,8 +284,9 @@ struct uae_prefs { TCHAR sername[256]; TCHAR amaxromfile[MAX_DPATH]; TCHAR a2065name[MAX_DPATH]; - TCHAR cdimagefile[MAX_DPATH]; - bool cdimagefileuse; + TCHAR cdimagefile[MAX_TOTAL_SCSI_DEVICES][MAX_DPATH]; + bool cdimagefileuse[MAX_TOTAL_SCSI_DEVICES]; + int cdscsidevicetype[MAX_TOTAL_SCSI_DEVICES]; TCHAR quitstatefile[MAX_DPATH]; TCHAR path_floppy[256]; diff --git a/include/scsidev.h b/include/scsidev.h index f35bbf5d..ddd14cb2 100644 --- a/include/scsidev.h +++ b/include/scsidev.h @@ -12,7 +12,7 @@ uaecptr scsidev_startup (uaecptr resaddr); void scsidev_install (void); void scsidev_reset (void); void scsidev_start_threads (void); -int scsi_do_disk_change (int device_id, int insert, int *pollmode); +int scsi_do_disk_change (int unitnum, int insert, int *pollmode); int scsi_do_disk_device_change (void); extern int log_scsi; diff --git a/main.cpp b/main.cpp index 2d021c3b..1917238e 100644 --- a/main.cpp +++ b/main.cpp @@ -390,6 +390,7 @@ void fixup_prefs (struct uae_prefs *p) p->maprom = 0x0f000000; if (p->tod_hack && p->cs_ciaatod == 0) p->cs_ciaatod = p->ntscmode ? 2 : 1; + blkdev_fix_prefs (p); target_fixup_options (p); } diff --git a/od-win32/blkdev_win32_aspi.cpp b/od-win32/blkdev_win32_aspi.cpp index e4899ba0..7d267ce7 100644 --- a/od-win32/blkdev_win32_aspi.cpp +++ b/od-win32/blkdev_win32_aspi.cpp @@ -44,7 +44,7 @@ struct scsi_info { int isatapi; int removable; }; -static struct scsi_info si[MAX_TOTAL_DEVICES]; +static struct scsi_info si[MAX_TOTAL_SCSI_DEVICES]; static int unitcnt; static int getversion(const TCHAR *name, VS_FIXEDFILEINFO *ver) @@ -710,7 +710,7 @@ static void scan_scsi_bus (SCSI *scgp, int flags) write_log (L"ASPI: %d:%d:%d '%s' '%s' '%s' ", scgp->addr.scsibus,scgp->addr.target,scgp->addr.lun, vend, prod, rev); - if (unitcnt < MAX_TOTAL_DEVICES) { + if (unitcnt < MAX_TOTAL_SCSI_DEVICES) { struct scsi_info *cis = &si[unitcnt]; int use = 0; write_log (L"["); @@ -820,15 +820,6 @@ static uae_u8 *execscsicmd_in (int unitnum, uae_u8 *data, int len, int *outlen) static SCSI *scsi_handle; -static int check_scsi_bus (int flags) -{ - if (open_driver (NULL)) { - close_driver (); - return 1; - } - return 0; -} - static int open_scsi_bus (int flags) { SCSI *scgp = openscsi (-1, -1, -1); @@ -885,7 +876,7 @@ static int mediacheck_full (int unitnum, struct device_info *di) return 1; } -static int open_scsi_device (int unitnum) +static int open_scsi_device (int unitnum, const TCHAR *ident) { if (unitnum >= unitcnt) return 0; @@ -982,13 +973,14 @@ static struct device_info *info_device (int unitnum, struct device_info *di, int struct scsi_info *sif = &si[unitnum]; if (unitnum >= unitcnt) return 0; + di->open = sif->handle != 0; di->bus = sif->scsibus; di->target = sif->target; di->lun = sif->lun; di->media_inserted = mediacheck (unitnum); di->type = sif->type; mediacheck_full (unitnum, di); - di->id = unitnum + 1; + di->unitnum = unitnum + 1; di->removable = sif->removable; _tcscpy (di->label, sif->label); if (log_scsi) { @@ -1019,15 +1011,9 @@ static int check_isatapi (int unitnum) return si[unitnum].isatapi; } -static struct device_scsi_info *scsi_info (int unitnum, struct device_scsi_info *dsi) -{ - dsi->buffer = si[unitnum].buf; - dsi->bufsize = DEVICE_SCSI_BUFSIZE; - return dsi; -} - struct device_functions devicefunc_win32_aspi = { - check_scsi_bus, open_scsi_bus, close_scsi_bus, open_scsi_device, close_scsi_device, info_device, + L"ASPI", + open_scsi_bus, close_scsi_bus, open_scsi_device, close_scsi_device, info_device, execscsicmd_out, execscsicmd_in, execscsicmd_direct, - 0, 0, 0, 0, 0, 0, 0, 0, 0, check_isatapi, scsi_info, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, check_isatapi, 0 }; diff --git a/od-win32/blkdev_win32_ioctl.cpp b/od-win32/blkdev_win32_ioctl.cpp index 52c5364a..177da530 100644 --- a/od-win32/blkdev_win32_ioctl.cpp +++ b/od-win32/blkdev_win32_ioctl.cpp @@ -42,17 +42,16 @@ struct dev_info_ioctl { TCHAR drvletter; TCHAR drvlettername[10]; TCHAR devname[30]; - int mediainserted; int type; - int blocksize; - CDROM_TOC toc; + CDROM_TOC cdromtoc; UINT errormode; int playend; int fullaccess; int cdda_play_finished; int cdda_play; int cdda_paused; - int cdda_volume; + int cdda_volume[2]; + int cdda_scan; int cdda_volume_main; uae_u32 cd_last_pos; HWAVEOUT cdda_wavehandle; @@ -63,43 +62,57 @@ struct dev_info_ioctl { play_subchannel_callback cdda_subfunc; struct device_info di; uae_sem_t sub_sem, sub_sem2; + bool open; }; -static int MCICDA; +static struct dev_info_ioctl ciw32[MAX_TOTAL_SCSI_DEVICES]; +static int unittable[MAX_TOTAL_SCSI_DEVICES]; +static int bus_open; -static struct dev_info_ioctl ciw32[MAX_TOTAL_DEVICES]; - -static void seterrormode (int unitnum) +static void seterrormode (struct dev_info_ioctl *ciw) { - ciw32[unitnum].errormode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); + ciw->errormode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); } -static void reseterrormode (int unitnum) +static void reseterrormode (struct dev_info_ioctl *ciw) { - SetErrorMode (ciw32[unitnum].errormode); + SetErrorMode (ciw->errormode); } -static void close_device (int unitnum); -static int open_device (int unitnum); +static int sys_cddev_open (struct dev_info_ioctl *ciw, int unitnum); +static void sys_cddev_close (struct dev_info_ioctl *ciw, int unitnum); -static int unitcheck (int unitnum) +static int getunitnum (struct dev_info_ioctl *ciw) { - if (unitnum >= MAX_TOTAL_DEVICES) { - if (unitnum < 'A' || unitnum > 'Z') - return 0; - return 1; + if (!ciw) + return -1; + int idx = ciw - &ciw32[0]; + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + if (unittable[i] - 1 == idx) + return i; } + return -1; +} + +static struct dev_info_ioctl *unitcheck (int unitnum) +{ + if (unitnum < 0 || unitnum >= MAX_TOTAL_SCSI_DEVICES) + return NULL; + if (unittable[unitnum] <= 0) + return NULL; + unitnum = unittable[unitnum] - 1; if (ciw32[unitnum].drvletter == 0) - return 0; - return 1; + return NULL; + return &ciw32[unitnum]; } -static bool unitisopen (int unitnum) +static struct dev_info_ioctl *unitisopen (int unitnum) { - if (!unitcheck (unitnum)) - return false; - if (ciw32[unitnum].tempbuffer == NULL) - return false; - return true; + struct dev_info_ioctl *di = unitcheck (unitnum); + if (!di) + return NULL; + if (di->open == false) + return NULL; + return di; } static int mcierr (TCHAR *str, DWORD err) @@ -112,7 +125,7 @@ static int mcierr (TCHAR *str, DWORD err) return err; } -static int win32_error (int unitnum, const TCHAR *format,...) +static int win32_error (struct dev_info_ioctl *ciw, int unitnum, const TCHAR *format,...) { LPVOID lpMsgBuf; va_list arglist; @@ -121,8 +134,8 @@ static int win32_error (int unitnum, const TCHAR *format,...) if (err == ERROR_WRONG_DISK) { write_log (L"IOCTL: media change, re-opening device\n"); - close_device (unitnum); - if (!open_device (unitnum)) + sys_cddev_close (ciw, unitnum); + if (!sys_cddev_open (ciw, unitnum)) write_log (L"IOCTL: re-opening failed!\n"); return -1; } @@ -132,15 +145,13 @@ static int win32_error (int unitnum, const TCHAR *format,...) NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); if (log_scsi) - write_log (L"IOCTL: unit=%d %s,%d: %s\n", unitnum, buf, err, (TCHAR*)lpMsgBuf); + write_log (L"IOCTL: unit=%d,%s,%d: %s\n", unitnum, buf, err, (TCHAR*)lpMsgBuf); va_end (arglist); return err; } -static int close_createfile (int unitnum) +static int close_createfile (struct dev_info_ioctl *ciw) { - struct dev_info_ioctl *ciw = &ciw32[unitnum]; - ciw->fullaccess = 0; if (ciw->h != INVALID_HANDLE_VALUE) { if (log_scsi) @@ -154,15 +165,14 @@ static int close_createfile (int unitnum) return 0; } -static int open_createfile (int unitnum, int fullaccess) +static int open_createfile (struct dev_info_ioctl *ciw, int fullaccess) { - struct dev_info_ioctl *ciw = &ciw32[unitnum]; int cnt = 50; DWORD len; if (ciw->h != INVALID_HANDLE_VALUE) { if (fullaccess && ciw->fullaccess == 0) { - close_createfile (unitnum); + close_createfile (ciw); } else { return 1; } @@ -231,7 +241,6 @@ static void *cdda_play (void *v) { DWORD len; struct dev_info_ioctl *ciw = (struct dev_info_ioctl*)v; - int unitnum = ciw32 - ciw; int cdda_pos; int num_sectors = CDDA_BUFFERS; int bufnum; @@ -241,7 +250,7 @@ static void *cdda_play (void *v) int i; WAVEHDR whdr[2]; MMRESULT mmr; - int volume, volume_main; + int volume[2], volume_main; int oldplay; int firstloops; @@ -260,7 +269,7 @@ static void *cdda_play (void *v) bufon[0] = bufon[1] = 0; bufnum = 0; buffered = 0; - volume = -1; + volume[0] = volume[1] = -1; volume_main = -1; if (cdda_openwav (ciw)) { @@ -292,12 +301,17 @@ static void *cdda_play (void *v) firstloops = 25; write_log (L"CDDA: playing from %d to %d\n", ciw->cdda_start, ciw->cdda_end); ciw->subcodevalid = false; + while (ciw->cdda_paused && ciw->cdda_play > 0) + Sleep (10); } if ((cdda_pos < ciw->cdda_end || ciw->cdda_end == 0xffffffff) && !ciw->cdda_paused && ciw->cdda_play) { RAW_READ_INFO rri; int sectors = num_sectors; + if (!isaudiotrack (&ciw->di.toc, cdda_pos)) + goto end; // data track? + uae_sem_wait (&ciw->sub_sem); ciw->subcodevalid = false; memset (ciw->subcode, 0, sizeof ciw->subcode); @@ -312,7 +326,7 @@ static void *cdda_play (void *v) } else { firstloops = -1; - seterrormode (unitnum); + seterrormode (ciw); rri.DiskOffset.QuadPart = 2048 * (cdda_pos + 0); rri.SectorCount = sectors; rri.TrackMode = RawWithSubCode; @@ -332,7 +346,7 @@ static void *cdda_play (void *v) } ciw->subcodevalid = true; } - reseterrormode (unitnum); + reseterrormode (ciw); } uae_sem_post (&ciw->sub_sem); @@ -342,18 +356,20 @@ static void *cdda_play (void *v) uae_sem_post (&ciw->sub_sem2); } - - volume = ciw->cdda_volume; volume_main = currprefs.sound_volume; - int vol_mult = (100 - volume_main) * volume / 100; - if (vol_mult) - vol_mult++; - if (vol_mult >= 65536) - vol_mult = 65536; + int vol_mult[2]; + for (int j = 0; j < 2; j++) { + volume[j] = ciw->cdda_volume[j]; + vol_mult[j] = (100 - volume_main) * volume[j] / 100; + if (vol_mult[j]) + vol_mult[j]++; + if (vol_mult[j] >= 32768) + vol_mult[j] = 32768; + } uae_s16 *p = (uae_s16*)(px[bufnum]); for (i = 0; i < num_sectors * 2352 / 4; i++) { - p[i * 2 + 0] = p[i * 2 + 0] * vol_mult / 65536; - p[i * 2 + 1] = p[i * 2 + 1] * vol_mult / 65536; + p[i * 2 + 0] = p[i * 2 + 0] * vol_mult[0] / 32768; + p[i * 2 + 1] = p[i * 2 + 1] * vol_mult[1] / 32768; } bufon[bufnum] = 1; @@ -364,7 +380,13 @@ static void *cdda_play (void *v) } if (firstloops < 0) { - cdda_pos += num_sectors; + if (ciw->cdda_scan) { + cdda_pos += ciw->cdda_scan * num_sectors; + if (cdda_pos < 0) + cdda_pos = 0; + } else { + cdda_pos += num_sectors; + } if (cdda_pos - num_sectors < ciw->cdda_end && cdda_pos >= ciw->cdda_end) { ciw->cdda_play_finished = 1; ciw->cdda_play = -1; @@ -403,10 +425,8 @@ end: return NULL; } -static void cdda_stop (int unitnum) +static void cdda_stop (struct dev_info_ioctl *ciw) { - struct dev_info_ioctl *ciw = &ciw32[unitnum]; - if (ciw->cdda_play > 0) { ciw->cdda_play = -1; while (ciw->cdda_play) { @@ -421,48 +441,52 @@ static void cdda_stop (int unitnum) /* pause/unpause CD audio */ static int ioctl_command_pause (int unitnum, int paused) { - struct dev_info_ioctl *ciw = &ciw32[unitnum]; - - if (!unitisopen (unitnum)) - return 0; + struct dev_info_ioctl *ciw = unitisopen (unitnum); + if (!ciw) + return -1; + int old = ciw->cdda_paused; ciw->cdda_paused = paused; - return 1; + return old; } /* stop CD audio */ static int ioctl_command_stop (int unitnum) { - struct dev_info_ioctl *ciw = &ciw32[unitnum]; - - if (!unitisopen (unitnum)) + struct dev_info_ioctl *ciw = unitisopen (unitnum); + if (!ciw) return 0; - cdda_stop (unitnum); + cdda_stop (ciw); return 1; } -static void ioctl_command_volume (int unitnum, uae_u16 volume) +static uae_u32 ioctl_command_volume (int unitnum, uae_u16 volume_left, uae_u16 volume_right) { - struct dev_info_ioctl *ciw = &ciw32[unitnum]; - - ciw->cdda_volume = volume; + struct dev_info_ioctl *ciw = unitisopen (unitnum); + if (!ciw) + return -1; + uae_u32 old = (ciw->cdda_volume[1] << 16) | (ciw->cdda_volume[0] << 0); + ciw->cdda_volume[0] = volume_left; + ciw->cdda_volume[1] = volume_right; + return old; } /* play CD audio */ static int ioctl_command_play (int unitnum, int startlsn, int endlsn, int scan, play_subchannel_callback subfunc) { - struct dev_info_ioctl *ciw = &ciw32[unitnum]; - - if (!unitisopen (unitnum)) + struct dev_info_ioctl *ciw = unitisopen (unitnum); + if (!ciw) return 0; - if (!open_createfile (unitnum, 0)) + if (!open_createfile (ciw, 0)) + return 0; + if (!isaudiotrack (&ciw->di.toc, startlsn)) return 0; - ciw->cdda_paused = 0; ciw->cdda_play_finished = 0; ciw->cdda_subfunc = subfunc; + ciw->cdda_scan = scan > 0 ? 10 : (scan < 0 ? 10 : 0); if (!ciw->cdda_play) { uae_start_thread (L"cdda_play", cdda_play, ciw, NULL); } @@ -491,22 +515,19 @@ static void sub_deinterleave (uae_u8 *s, uae_u8 *d) /* read qcode */ static int ioctl_command_qcode (int unitnum, uae_u8 *buf, int sector) { - struct dev_info_ioctl *ciw = &ciw32[unitnum]; - - if (!unitisopen (unitnum)) { - write_log (L"qcode: %d no unit\n", unitnum); + struct dev_info_ioctl *ciw = unitisopen (unitnum); + if (!ciw) return 0; - } uae_u8 *p; int trk; - CDROM_TOC *toc = &ciw->toc; + CDROM_TOC *toc = &ciw->cdromtoc; int pos; int msf; int start, end; int status; bool valid = false; - bool regenerate = false; + bool regenerate = true; memset (buf, 0, SUBQ_SIZE); p = buf; @@ -542,7 +563,7 @@ static int ioctl_command_qcode (int unitnum, uae_u8 *buf, int sector) if (!valid && sector >= 0) { DWORD len; uae_sem_wait (&ciw->sub_sem); - seterrormode (unitnum); + seterrormode (ciw); RAW_READ_INFO rri; rri.DiskOffset.QuadPart = 2048 * (pos + 0); rri.SectorCount = 1; @@ -552,7 +573,7 @@ static int ioctl_command_qcode (int unitnum, uae_u8 *buf, int sector) DWORD err = GetLastError (); write_log (L"IOCTL_CDROM_RAW_READ SUBQ CDDA sector %d returned %d\n", pos, err); } - reseterrormode (unitnum); + reseterrormode (ciw); uae_u8 subbuf[SUB_CHANNEL_SIZE]; sub_deinterleave (ciw->tempbuffer + 2352, subbuf); uae_sem_post (&ciw->sub_sem); @@ -593,35 +614,17 @@ typedef struct _SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER { UCHAR SenseBuf[32]; } SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER; -static uae_u8 *spti_read (int unitnum, int sector, int sectorsize) +static int do_raw_scsi (struct dev_info_ioctl *ciw, int unitnum, uae_u8 *cmd, int cmdlen, uae_u8 *data, int datalen) { DWORD status, returned; SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb; - uae_u8 *p = ciw32[unitnum].tempbuffer; - /* number of bytes returned depends on type of track: - * CDDA = 2352 - * Mode1 = 2048 - * Mode2 = 2336 - * Mode2 Form 1 = 2048 - * Mode2 Form 2 = 2328 - */ - uae_u8 cmd[12] = { 0xbe, 0, 0, 0, 0, 0, 0, 0, 1, 0x10, 0, 0 }; - int len = sizeof cmd; - - if (!unitisopen (unitnum)) + uae_u8 *p = ciw->tempbuffer; + if (!open_createfile (ciw, 1)) return 0; - - if (!open_createfile (unitnum, 1)) - return 0; - ciw32[unitnum].cd_last_pos = sector; - cmd[3] = (uae_u8)(sector >> 16); - cmd[4] = (uae_u8)(sector >> 8); - cmd[5] = (uae_u8)(sector >> 0); - gui_flicker_led (LED_CD, unitnum, 1); memset (&swb, 0, sizeof (swb)); - memcpy (swb.spt.Cdb, cmd, len); + memcpy (swb.spt.Cdb, cmd, cmdlen); swb.spt.Length = sizeof (SCSI_PASS_THROUGH); - swb.spt.CdbLength = len; + swb.spt.CdbLength = cmdlen; swb.spt.DataIn = SCSI_IOCTL_DATA_IN; swb.spt.DataTransferLength = IOCTL_DATA_BUFFER; swb.spt.DataBuffer = p; @@ -629,131 +632,237 @@ static uae_u8 *spti_read (int unitnum, int sector, int sectorsize) swb.spt.TimeOutValue = 80 * 60; swb.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, SenseBuf); swb.spt.SenseInfoLength = 32; - - seterrormode (unitnum); - status = DeviceIoControl (ciw32[unitnum].h, IOCTL_SCSI_PASS_THROUGH_DIRECT, + seterrormode (ciw); + status = DeviceIoControl (ciw->h, IOCTL_SCSI_PASS_THROUGH_DIRECT, &swb, sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), &swb, sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), &returned, NULL); - reseterrormode (unitnum); + reseterrormode (ciw); if (!status) { DWORD err = GetLastError (); - write_log (L"IOCTL_RAW_SCSI unit %d, ERR=%d ", unitnum, err); + write_log (L"IOCTL_RAW_SCSI unit %d, CMD=%d, ERR=%d ", unitnum, cmd[0], err); return 0; } - return p; + memcpy (data, p, swb.spt.DataTransferLength > datalen ? datalen : swb.spt.DataTransferLength); + return 1; +} + +static int spti_inquiry (struct dev_info_ioctl *ciw, int unitnum, uae_u8 *data) +{ + uae_u8 cmd[6] = { 0x12,0,0,0,36,0 }; /* INQUIRY */ + int len = sizeof cmd; + + do_raw_scsi (ciw, unitnum, cmd, len, data, 256); + return 1; +} + +static int spti_read (struct dev_info_ioctl *ciw, int unitnum, uae_u8 *data, int sector, int sectorsize) +{ + /* number of bytes returned depends on type of track: + * CDDA = 2352 + * Mode1 = 2048 + * Mode2 = 2336 + * Mode2 Form 1 = 2048 + * Mode2 Form 2 = 2328 + */ + uae_u8 cmd[12] = { 0xbe, 0, 0, 0, 0, 0, 0, 0, 1, 0x10, 0, 0 }; + ciw->cd_last_pos = sector; + cmd[3] = (uae_u8)(sector >> 16); + cmd[4] = (uae_u8)(sector >> 8); + cmd[5] = (uae_u8)(sector >> 0); + gui_flicker_led (LED_CD, unitnum, 1); + int len = sizeof cmd; + return do_raw_scsi (ciw, unitnum, cmd, len, data, sectorsize); } -uae_u8 *ioctl_command_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize) +static void sub_to_deinterleaved (const uae_u8 *s, uae_u8 *d) { + for (int i = 0; i < 8 * 12; i ++) { + int dmask = 0x80; + int smask = 1 << (7 - (i / 12)); + (*d) = 0; + for (int j = 0; j < 8; j++) { + (*d) |= (s[(i % 12) * 8 + j] & smask) ? dmask : 0; + dmask >>= 1; + } + d++; + } +} + +static int ioctl_command_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize, uae_u16 extra) +{ + struct dev_info_ioctl *ciw = unitisopen (unitnum); + if (!ciw) + return 0; + RAW_READ_INFO rri; DWORD len; - uae_u8 *p = ciw32[unitnum].tempbuffer; + uae_u8 *p = ciw->tempbuffer; + int ret = 0; if (log_scsi) write_log (L"IOCTL rawread unit=%d sector=%d blocksize=%d\n", unitnum, sector, sectorsize); if (!os_vista) - return spti_read (unitnum, sector, sectorsize); - if (!open_createfile (unitnum, 1)) + return spti_read (ciw, unitnum, data, sector, sectorsize); + if (!open_createfile (ciw, 1)) return 0; - cdda_stop (unitnum); - if (sectorsize != 2336 && sectorsize != 2352 && sectorsize != 2048) - return 0; - while (size-- > 0) { - gui_flicker_led (LED_CD, unitnum, 1); - seterrormode (unitnum); + cdda_stop (ciw); + gui_flicker_led (LED_CD, unitnum, 1); + if (sectorsize > 0) { + if (sectorsize != 2336 && sectorsize != 2352 && sectorsize != 2048) + return 0; + seterrormode (ciw); rri.DiskOffset.QuadPart = sector * 2048; rri.SectorCount = 1; rri.TrackMode = RawWithSubCode; len = sectorsize; memset (p, 0, sectorsize); - if (!DeviceIoControl (ciw32[unitnum].h, IOCTL_CDROM_RAW_READ, &rri, sizeof rri, + if (!DeviceIoControl (ciw->h, IOCTL_CDROM_RAW_READ, &rri, sizeof rri, p, IOCTL_DATA_BUFFER, &len, NULL)) { DWORD err = GetLastError (); write_log (L"IOCTL rawread unit=%d sector=%d blocksize=%d, ERR=%d\n", unitnum, sector, sectorsize, err); } - reseterrormode (unitnum); + reseterrormode (ciw); if (data) { - memcpy (data, p, sectorsize); + if (sectorsize == 2352) + memcpy (data, p, sectorsize); + else + memcpy (data, p + 16, sectorsize); data += sectorsize; + ret += sectorsize; } - ciw32[unitnum].cd_last_pos = sector; - break; + ciw->cd_last_pos = sector; + } else { + uae_u8 cmd9 = extra >> 8; + int sync = (cmd9 >> 7) & 1; + int headercodes = (cmd9 >> 5) & 3; + int userdata = (cmd9 >> 4) & 1; + int edcecc = (cmd9 >> 3) & 1; + int errorfield = (cmd9 >> 1) & 3; + uae_u8 subs = extra & 7; + if (subs != 0 && subs != 1 && subs != 2 && subs != 4) + return -1; + if (errorfield >= 3) + return -1; + uae_u8 *d = data; + + if (isaudiotrack (&ciw->di.toc, sector)) { + + for (int i = 0; i < size; i++) { + uae_u8 *odata = data; + int blocksize = errorfield == 0 ? 2352 : (errorfield == 1 ? 2352 + 294 : 2352 + 296); + int readblocksize = errorfield == 0 ? 2352 : 2352 + 296; + seterrormode (ciw); + rri.DiskOffset.QuadPart = sector * 2048; + rri.SectorCount = 1; + rri.TrackMode = errorfield > 0 ? RawWithC2AndSubCode : RawWithSubCode; + len = sectorsize; + memset (p, 0, blocksize); + if (!DeviceIoControl (ciw->h, IOCTL_CDROM_RAW_READ, &rri, sizeof rri, p, IOCTL_DATA_BUFFER, &len, NULL)) { + DWORD err = GetLastError (); + write_log (L"IOCTL rawread unit=%d sector=%d blocksize=%d, ERR=%d\n", unitnum, sector, sectorsize, err); + if (err) { + reseterrormode (ciw); + return ret; + } + } + reseterrormode (ciw); + if (subs == 0) { + memcpy (data, p, blocksize); + data += blocksize; + } else if (subs == 4) { // all, de-interleaved + memcpy (data, p, blocksize); + data += blocksize; + sub_to_deinterleaved (p + readblocksize, data); + data += SUB_CHANNEL_SIZE; + } else if (subs == 2) { // q-only + memcpy (data, p, blocksize); + data += blocksize; + uae_u8 subdata[SUB_CHANNEL_SIZE]; + sub_to_deinterleaved (p + readblocksize, subdata); + memcpy (data, subdata + SUB_ENTRY_SIZE, SUB_ENTRY_SIZE); + p += SUB_ENTRY_SIZE; + } else if (subs == 1) { // all, interleaved + memcpy (data, p, blocksize); + memcpy (data + blocksize, p + readblocksize, SUB_CHANNEL_SIZE); + data += blocksize + SUB_CHANNEL_SIZE; + } + ret += data - odata; + sector++; + } + } + + } - if (sectorsize == 2352) - return p; - return p + 16; + return ret; } -static int ioctl_command_readwrite (int unitnum, int sector, int size, int write, int blocksize, uae_u8 *data, uae_u8 **ptr) +static int ioctl_command_readwrite (int unitnum, int sector, int size, int write, uae_u8 *data) { + struct dev_info_ioctl *ciw = unitisopen (unitnum); + if (!ciw) + return 0; + DWORD dtotal; int cnt = 3; - uae_u8 *p = ciw32[unitnum].tempbuffer; + uae_u8 *p = ciw->tempbuffer; + int blocksize = ciw->di.bytespersector; - *ptr = NULL; - - if (!unitisopen (unitnum)) + if (!open_createfile (ciw, 0)) return 0; - - if (!open_createfile (unitnum, 0)) - return 0; - cdda_stop (unitnum); - ciw32[unitnum].cd_last_pos = sector; + cdda_stop (ciw); + ciw->cd_last_pos = sector; while (cnt-- > 0) { gui_flicker_led (LED_CD, unitnum, 1); - seterrormode (unitnum); - if (SetFilePointer (ciw32[unitnum].h, sector * ciw32[unitnum].blocksize, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { - reseterrormode (unitnum); - if (win32_error (unitnum, L"SetFilePointer") < 0) + seterrormode (ciw); + if (SetFilePointer (ciw->h, sector * ciw->di.bytespersector, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { + reseterrormode (ciw); + if (win32_error (ciw, unitnum, L"SetFilePointer") < 0) continue; return 0; } - reseterrormode (unitnum); + reseterrormode (ciw); break; } while (size-- > 0) { gui_flicker_led (LED_CD, unitnum, 1); - seterrormode (unitnum); + seterrormode (ciw); if (write) { if (data) { memcpy (p, data, blocksize); data += blocksize; } - if (!WriteFile (ciw32[unitnum].h, p, blocksize, &dtotal, 0)) { + if (!WriteFile (ciw->h, p, blocksize, &dtotal, 0)) { int err; - reseterrormode (unitnum); - err = win32_error (unitnum, L"WriteFile"); + reseterrormode (ciw); + err = win32_error (ciw, unitnum, L"WriteFile"); if (err < 0) continue; if (err == ERROR_WRITE_PROTECT) return -1; return 0; } - *ptr = p; } else { dtotal = 0; - if (!ReadFile (ciw32[unitnum].h, p, blocksize, &dtotal, 0)) { - reseterrormode (unitnum); - if (win32_error (unitnum, L"ReadFile") < 0) + if (!ReadFile (ciw->h, p, blocksize, &dtotal, 0)) { + reseterrormode (ciw); + if (win32_error (ciw, unitnum, L"ReadFile") < 0) continue; return 0; } if (dtotal == 0) { /* ESS Mega (CDTV) "fake" data area returns zero bytes and no error.. */ - *ptr = spti_read (unitnum, sector, 2048); + spti_read (ciw, unitnum, data, sector, 2048); if (log_scsi) - write_log (L"IOCTL unit %d, sector %d: ReadFile()==0. SPTI=%d\n", unitnum, sector, *ptr == 0 ? GetLastError () : 0); + write_log (L"IOCTL unit %d, sector %d: ReadFile()==0. SPTI=%d\n", unitnum, sector, GetLastError ()); return 1; - } else { - *ptr = p; } if (data) { memcpy (data, p, blocksize); data += blocksize; } } - reseterrormode (unitnum); + reseterrormode (ciw); gui_flicker_led (LED_CD, unitnum, 1); } return 1; @@ -761,39 +870,36 @@ static int ioctl_command_readwrite (int unitnum, int sector, int size, int write static int ioctl_command_write (int unitnum, uae_u8 *data, int sector, int size) { - uae_u8 *ptr; - return ioctl_command_readwrite (unitnum, sector, size, 1, ciw32[unitnum].blocksize, data, &ptr); + return ioctl_command_readwrite (unitnum, sector, size, 1, data); } -static uae_u8 *ioctl_command_read (int unitnum, uae_u8 *data, int sector, int size) +static int ioctl_command_read (int unitnum, uae_u8 *data, int sector, int size) { - uae_u8 *ptr; - if (ioctl_command_readwrite (unitnum, sector, size, 0, ciw32[unitnum].blocksize, data, &ptr) > 0) - return ptr; - return NULL; + return ioctl_command_readwrite (unitnum, sector, size, 0, data); } -static int fetch_geometry (int unitnum, struct device_info *di) +static int fetch_geometry (struct dev_info_ioctl *ciw, int unitnum, struct device_info *di) { DISK_GEOMETRY geom; DWORD len; int cnt = 3; - if (!open_createfile (unitnum, 0)) + if (!open_createfile (ciw, 0)) return 0; - uae_sem_wait (&ciw32[unitnum].sub_sem); - seterrormode (unitnum); + uae_sem_wait (&ciw->sub_sem); + seterrormode (ciw); while (cnt-- > 0) { - if (!DeviceIoControl (ciw32[unitnum].h, IOCTL_CDROM_GET_DRIVE_GEOMETRY, NULL, 0, &geom, sizeof (geom), &len, NULL)) { - if (win32_error (unitnum, L"IOCTL_CDROM_GET_DRIVE_GEOMETRY") < 0) + if (!DeviceIoControl (ciw->h, IOCTL_CDROM_GET_DRIVE_GEOMETRY, NULL, 0, &geom, sizeof (geom), &len, NULL)) { + if (win32_error (ciw, unitnum, L"IOCTL_CDROM_GET_DRIVE_GEOMETRY") < 0) continue; - reseterrormode (unitnum); - uae_sem_post (&ciw32[unitnum].sub_sem); + reseterrormode (ciw); + uae_sem_post (&ciw->sub_sem); return 0; } + break; } - reseterrormode (unitnum); - uae_sem_post (&ciw32[unitnum].sub_sem); + reseterrormode (ciw); + uae_sem_post (&ciw->sub_sem); if (di) { di->cylinders = geom.Cylinders.LowPart; di->sectorspertrack = geom.SectorsPerTrack; @@ -803,40 +909,40 @@ static int fetch_geometry (int unitnum, struct device_info *di) return 1; } -static int ismedia (int unitnum) +static int ismedia (struct dev_info_ioctl *ciw, int unitnum) { - struct dev_info_ioctl *ciw = &ciw32[unitnum]; - return fetch_geometry (unitnum, &ciw->di); + return fetch_geometry (ciw, unitnum, &ciw->di); } /* read toc */ -static struct cd_toc_head *ioctl_command_toc (int unitnum) +static int ioctl_command_toc (int unitnum, struct cd_toc_head *tocout) { - struct dev_info_ioctl *ciw = &ciw32[unitnum]; + struct dev_info_ioctl *ciw = unitisopen (unitnum); + if (!ciw) + return 0; + DWORD len; int i; - struct cd_toc_head *th = (struct cd_toc_head*)ciw->tempbuffer; + struct cd_toc_head *th = &ciw->di.toc; struct cd_toc *t = th->toc; int cnt = 3; - CDROM_TOC *toc = &ciw->toc; + CDROM_TOC *toc = &ciw->cdromtoc; if (!unitisopen (unitnum)) - return NULL; + return 0; - if (!open_createfile (unitnum, 0)) + if (!open_createfile (ciw, 0)) return 0; - cdda_stop (unitnum); - ciw32[unitnum].cd_last_pos = 0; gui_flicker_led (LED_CD, unitnum, 1); while (cnt-- > 0) { - seterrormode (unitnum); - if (!DeviceIoControl (ciw32[unitnum].h, IOCTL_CDROM_READ_TOC, NULL, 0, toc, sizeof (CDROM_TOC), &len, NULL)) { - reseterrormode (unitnum); - if (win32_error (unitnum, L"IOCTL_CDROM_READ_TOC") < 0) + seterrormode (ciw); + if (!DeviceIoControl (ciw->h, IOCTL_CDROM_READ_TOC, NULL, 0, toc, sizeof (CDROM_TOC), &len, NULL)) { + reseterrormode (ciw); + if (win32_error (ciw, unitnum, L"IOCTL_CDROM_READ_TOC") < 0) continue; return 0; } - reseterrormode (unitnum); + reseterrormode (ciw); break; } @@ -875,37 +981,39 @@ static struct cd_toc_head *ioctl_command_toc (int unitnum) t++; gui_flicker_led (LED_CD, unitnum, 1); - return th; + memcpy (tocout, th, sizeof (struct cd_toc_head)); + return 1; } static void update_device_info (int unitnum) { - if (!unitcheck (unitnum)) + struct dev_info_ioctl *ciw = unitcheck (unitnum); + if (!ciw) return; - struct device_info *di = &ciw32[unitnum].di; + struct device_info *di = &ciw->di; di->bus = unitnum; di->target = 0; di->lun = 0; di->media_inserted = 0; di->bytespersector = 2048; - _stprintf (di->mediapath, L"\\\\.\\%c:", ciw32[unitnum].drvletter); - if (fetch_geometry (unitnum, di)) { // || ioctl_command_toc (unitnum)) + _stprintf (di->mediapath, L"\\\\.\\%c:", ciw->drvletter); + if (fetch_geometry (ciw, unitnum, di)) { // || ioctl_command_toc (unitnum)) di->media_inserted = 1; - ciw32[unitnum].blocksize = di->bytespersector; } - di->write_protected = ciw32[unitnum].type == DRIVE_CDROM ? 1 : 0; - di->type = ciw32[unitnum].type == DRIVE_CDROM ? INQ_ROMD : INQ_DASD; - di->id = ciw32[unitnum].drvletter; - _tcscpy (di->label, ciw32[unitnum].drvlettername); - memcpy (&di->toc, &ciw32[unitnum].toc, sizeof (struct cd_toc_head)); + ioctl_command_toc (unitnum, &di->toc); + di->removable = ciw->type == DRIVE_CDROM ? 1 : 0; + di->write_protected = ciw->type == DRIVE_CDROM ? 1 : 0; + di->type = ciw->type == DRIVE_CDROM ? INQ_ROMD : INQ_DASD; + di->unitnum = unitnum + 1; + _tcscpy (di->label, ciw->drvlettername); } /* open device level access to cd rom drive */ -static int sys_cddev_open (int unitnum) +static int sys_cddev_open (struct dev_info_ioctl *ciw, int unitnum) { - struct dev_info_ioctl *ciw = &ciw32[unitnum]; - - ciw->cdda_volume = 0xffff; + uae_u8 inquiry[256]; + ciw->cdda_volume[0] = 0x7fff; + ciw->cdda_volume[1] = 0x7fff; ciw->cdda_volume_main = currprefs.sound_volume; /* buffer must be page aligned for device access */ ciw->tempbuffer = (uae_u8*)VirtualAlloc (NULL, IOCTL_DATA_BUFFER, MEM_COMMIT, PAGE_READWRITE); @@ -913,19 +1021,44 @@ static int sys_cddev_open (int unitnum) write_log (L"IOCTL: failed to allocate buffer"); return 1; } - if (!open_createfile (unitnum, 0)) { + _tcscpy (ciw->di.vendorid, L"UAE"); + _stprintf (ciw->di.productid, L"SCSI CD%d IMG", unitnum); + _tcscpy (ciw->di.revision, L"0.1"); + if (spti_inquiry (ciw, unitnum, inquiry)) { + char tmp[20]; + TCHAR *s; + memcpy (tmp, inquiry + 8, 8); + tmp[8] = 0; + s = au (tmp); + _tcscpy (ciw->di.vendorid, s); + xfree (s); + memcpy (tmp, inquiry + 16, 16); + tmp[16] = 0; + s = au (tmp); + _tcscpy (ciw->di.productid, s); + xfree (s); + memcpy (tmp, inquiry + 32, 4); + tmp[4] = 0; + s = au (tmp); + _tcscpy (ciw->di.revision, s); + xfree (s); + close_createfile (ciw); + } + if (!open_createfile (ciw, 0)) { write_log (L"IOCTL: failed to open '%s', err=%d\n", ciw->devname, GetLastError ()); goto error; } uae_sem_init (&ciw->sub_sem, 0, 1); uae_sem_init (&ciw->sub_sem2, 0, 1); - ciw->mediainserted = ioctl_command_toc (unitnum) ? 1 : 0; - update_device_info (unitnum); - write_log (L"IOCTL: device '%s' opened succesfully (unit number=%d,media=%d)\n", ciw->devname, unitnum, ciw->mediainserted); ioctl_command_stop (unitnum); + update_device_info (unitnum); + ciw->open = true; + write_log (L"IOCTL: device '%s' (%s/%s/%s) opened succesfully (unit=%d,media=%d)\n", + ciw->devname, ciw->di.vendorid, ciw->di.productid, ciw->di.revision, + unitnum, ciw->di.media_inserted); return 0; error: - win32_error (unitnum, L"CreateFile"); + win32_error (ciw, unitnum, L"CreateFile"); VirtualFree (ciw->tempbuffer, 0, MEM_RELEASE); ciw->tempbuffer = NULL; CloseHandle (ciw->h); @@ -934,139 +1067,170 @@ error: } /* close device handle */ -void sys_cddev_close (int unitnum) +static void sys_cddev_close (struct dev_info_ioctl *ciw, int unitnum) { - struct dev_info_ioctl *ciw = &ciw32[unitnum]; - - if (!unitcheck (unitnum)) + if (ciw->open == false) return; - cdda_stop (unitnum); - close_createfile (unitnum); + cdda_stop (ciw); + close_createfile (ciw); VirtualFree (ciw->tempbuffer, 0, MEM_RELEASE); ciw->tempbuffer = NULL; uae_sem_destroy (&ciw->sub_sem); uae_sem_destroy (&ciw->sub_sem2); + ciw->open = false; + write_log (L"IOCTL: device '%s' closed\n", ciw->devname, unitnum); } -static int open_device (int unitnum) +static int open_device (int unitnum, const TCHAR *ident) { - if (!unitcheck (unitnum)) + struct dev_info_ioctl *ciw = NULL; + if (ident) { + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + ciw = &ciw32[i]; + if (unittable[i] == 0 && ciw->drvletter != 0) { + if (!_tcsicmp (ciw->drvlettername, ident)) { + unittable[unitnum] = i + 1; + if (sys_cddev_open (ciw, unitnum) == 0) + return 1; + unittable[unitnum] = 0; + return 0; + } + } + } return 0; - if (sys_cddev_open (unitnum) == 0) + } + ciw = &ciw32[unitnum]; + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + if (unittable[i] == unitnum + 1) + return 0; + } + if (ciw->drvletter == 0) + return 0; + unittable[unitnum] = unitnum + 1; + if (sys_cddev_open (ciw, unitnum) == 0) return 1; + unittable[unitnum] = 0; return 0; } static void close_device (int unitnum) { - sys_cddev_close (unitnum); -} - -static void close_bus (void) -{ + struct dev_info_ioctl *ciw = unitcheck (unitnum); + if (!ciw) + return; + sys_cddev_close (ciw, unitnum); + unittable[unitnum] = 0; } static int total_devices; -static int check_bus (int flags) +static void close_bus (void) { - return 1; + if (!bus_open) { + write_log (L"IOCTL close_bus() when already closed!\n"); + return; + } + total_devices = 0; + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + sys_cddev_close (&ciw32[i], i); + memset (&ciw32[i], 0, sizeof (struct dev_info_ioctl)); + ciw32[i].h = INVALID_HANDLE_VALUE; + unittable[i] = 0; + } + bus_open = 0; + write_log (L"IOCTL driver closed.\n"); } static int open_bus (int flags) { int dwDriveMask; - int drive, i; - TCHAR tmp[10]; + int drive; - for (i = 0; i < MAX_TOTAL_DEVICES; i++) { - memset (&ciw32[i], 0, sizeof (struct dev_info_ioctl)); - ciw32[i].h = INVALID_HANDLE_VALUE; + if (bus_open) { + write_log (L"IOCTL open_bus() more than once!\n"); + return 1; } - MCICDA = 1;//os_vista ? 1 : 0; total_devices = 0; dwDriveMask = GetLogicalDrives (); if (log_scsi) write_log (L"IOCTL: drive mask = %08X\n", dwDriveMask); dwDriveMask >>= 2; // Skip A and B drives... - for (drive = 'C'; drive <= 'Z' && total_devices < MAX_TOTAL_DEVICES; drive++) { + for (drive = 'C'; drive <= 'Z' && total_devices < MAX_TOTAL_SCSI_DEVICES; drive++) { if (dwDriveMask & 1) { int dt; + TCHAR tmp[10]; _stprintf (tmp, L"%c:\\", drive); dt = GetDriveType (tmp); if (log_scsi) write_log (L"IOCTL: drive %c type %d\n", drive, dt); - if (((flags & (1 << INQ_ROMD)) && dt == DRIVE_CDROM) || ((flags & (1 << INQ_DASD)) && dt == DRIVE_FIXED)) { + if (dt == DRIVE_CDROM) { if (log_scsi) write_log (L"IOCTL: drive %c: = unit %d\n", drive, total_devices); ciw32[total_devices].drvletter = drive; _tcscpy (ciw32[total_devices].drvlettername, tmp); ciw32[total_devices].type = dt; - ciw32[total_devices].blocksize = 2048; + ciw32[total_devices].di.bytespersector = 2048; _stprintf (ciw32[total_devices].devname, L"\\\\.\\%c:", drive); + ciw32[total_devices].h = INVALID_HANDLE_VALUE; total_devices++; } } dwDriveMask >>= 1; } + bus_open = 1; + write_log (L"IOCTL driver open, %d devices.\n", total_devices); return total_devices; } static int ioctl_ismedia (int unitnum, int quick) { - if (!unitcheck (unitnum)) - return -1; - if (!unitisopen (unitnum)) + struct dev_info_ioctl *ciw = unitisopen (unitnum); + if (!ciw) return -1; if (quick) { - struct dev_info_ioctl *ciw = &ciw32[unitnum]; - return ciw->mediainserted; + return ciw->di.media_inserted; } update_device_info (unitnum); - return ismedia (unitnum); + return ismedia (ciw, unitnum); } static struct device_info *info_device (int unitnum, struct device_info *di, int quick) { - if (!unitcheck (unitnum)) + struct dev_info_ioctl *ciw = unitcheck (unitnum); + if (!ciw) return 0; if (!quick) update_device_info (unitnum); - memcpy (di, &ciw32[unitnum].di, sizeof (struct device_info)); + ciw->di.open = di->open; + memcpy (di, &ciw->di, sizeof (struct device_info)); return di; } void win32_ioctl_media_change (TCHAR driveletter, int insert) { - int i; - - for (i = 0; i < MAX_TOTAL_DEVICES; i++) { - if (ciw32[i].drvletter == driveletter && ciw32[i].mediainserted != insert) { - write_log (L"IOCTL: media change %s %d\n", ciw32[i].drvlettername, insert); - ciw32[i].mediainserted = insert; - update_device_info (i); - scsi_do_disk_change (driveletter, insert, NULL); + for (int i = 0; i < total_devices; i++) { + struct dev_info_ioctl *ciw = &ciw32[i]; + if (ciw->drvletter == driveletter && ciw->di.media_inserted != insert) { + write_log (L"IOCTL: media change %s %d\n", ciw->drvlettername, insert); + ciw->di.media_inserted = insert; + int unitnum = getunitnum (ciw); + if (unitnum >= 0) { + update_device_info (unitnum); + scsi_do_disk_change (unitnum, insert, NULL); #ifdef RETROPLATFORM - rp_cd_image_change (i, ciw32[i].drvlettername); + rp_cd_image_change (unitnum, ciw->drvlettername); #endif + } } } } -static struct device_scsi_info *ioctl_scsi_info (int unitnum, struct device_scsi_info *dsi) -{ - if (!unitcheck (unitnum)) - return 0; - dsi->buffer = ciw32[unitnum].tempbuffer; - dsi->bufsize = IOCTL_DATA_BUFFER; - return dsi; -} - struct device_functions devicefunc_win32_ioctl = { - check_bus, open_bus, close_bus, open_device, close_device, info_device, + L"IOCTL", + open_bus, close_bus, open_device, close_device, info_device, 0, 0, 0, ioctl_command_pause, ioctl_command_stop, ioctl_command_play, ioctl_command_volume, ioctl_command_qcode, ioctl_command_toc, ioctl_command_read, ioctl_command_rawread, ioctl_command_write, - 0, ioctl_scsi_info, ioctl_ismedia + 0, ioctl_ismedia }; #endif diff --git a/od-win32/blkdev_win32_spti.cpp b/od-win32/blkdev_win32_spti.cpp index e06a8813..d18999b4 100644 --- a/od-win32/blkdev_win32_spti.cpp +++ b/od-win32/blkdev_win32_spti.cpp @@ -45,8 +45,6 @@ typedef struct _SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER { UCHAR SenseBuf[32]; } SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER; -static int unitcnt = 0; - struct dev_info_spti { TCHAR *drvpath; TCHAR *name; @@ -62,15 +60,54 @@ struct dev_info_spti { int bus, path, target, lun; int scanmode; uae_u8 *scsibuf; + bool open; + bool enabled; + struct device_info di; }; static uae_sem_t scgp_sem; -static struct dev_info_spti dev_info[MAX_TOTAL_DEVICES]; +static struct dev_info_spti dev_info[MAX_TOTAL_SCSI_DEVICES]; +static int unittable[MAX_TOTAL_SCSI_DEVICES]; +static int total_devices; +static int bus_open; + +static int getunitnum (struct dev_info_spti *di) +{ + if (!di) + return -1; + int idx = di - &dev_info[0]; + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + if (unittable[i] - 1 == idx) + return i; + } + return -1; +} + +static struct dev_info_spti *unitcheck (int unitnum) +{ + if (unitnum < 0 || unitnum >= MAX_TOTAL_SCSI_DEVICES) + return NULL; + if (unittable[unitnum] <= 0) + return NULL; + unitnum = unittable[unitnum] - 1; + if (dev_info[unitnum].drvletter == 0) + return NULL; + return &dev_info[unitnum]; +} + +static struct dev_info_spti *unitisopen (int unitnum) +{ + struct dev_info_spti *di = unitcheck (unitnum); + if (!di) + return NULL; + if (di->open == false) + return NULL; + return di; +} -static int doscsi (int unitnum, SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER *swb, int *err) +static int doscsi (struct dev_info_spti *di, int unitnum, SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER *swb, int *err) { DWORD status, returned; - struct dev_info_spti *di = &dev_info[unitnum]; *err = 0; if (log_scsi) { @@ -114,7 +151,7 @@ static int doscsi (int unitnum, SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER *swb, int * #define MODE_SELECT_10 0x55 #define MODE_SENSE_10 0x5A -static int execscsicmd (int unitnum, uae_u8 *data, int len, uae_u8 *inbuf, int inlen) +static int execscsicmd (struct dev_info_spti *di, int unitnum, uae_u8 *data, int len, uae_u8 *inbuf, int inlen) { SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb; DWORD status; @@ -136,7 +173,7 @@ static int execscsicmd (int unitnum, uae_u8 *data, int len, uae_u8 *inbuf, int i swb.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, SenseBuf); swb.spt.SenseInfoLength = 32; memcpy (swb.spt.Cdb, data, len); - status = doscsi (unitnum, &swb, &err); + status = doscsi (di, unitnum, &swb, &err); uae_sem_post (&scgp_sem); dolen = swb.spt.DataTransferLength; if (!status) @@ -146,6 +183,10 @@ static int execscsicmd (int unitnum, uae_u8 *data, int len, uae_u8 *inbuf, int i static int execscsicmd_direct (int unitnum, struct amigascsi *as) { + struct dev_info_spti *di = unitisopen (unitnum); + if (!di) + return -1; + SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb; DWORD status; int sactual = 0, i; @@ -176,7 +217,7 @@ static int execscsicmd_direct (int unitnum, struct amigascsi *as) swb.spt.DataTransferLength = as->len; swb.spt.DataBuffer = scsi_datap; - status = doscsi (unitnum, &swb, &err); + status = doscsi (di, unitnum, &swb, &err); as->cmdactual = status == 0 ? 0 : scsi_cmd_len_orig; /* fake scsi_CmdActual */ as->status = swb.spt.ScsiStatus; /* scsi_Status */ @@ -213,7 +254,10 @@ static int execscsicmd_direct (int unitnum, struct amigascsi *as) static uae_u8 *execscsicmd_out (int unitnum, uae_u8 *data, int len) { - int v = execscsicmd (unitnum, data, len, 0, 0); + struct dev_info_spti *di = unitisopen (unitnum); + if (!di) + return 0; + int v = execscsicmd (di, unitnum, data, len, 0, 0); if (v < 0) return 0; return data; @@ -221,73 +265,162 @@ static uae_u8 *execscsicmd_out (int unitnum, uae_u8 *data, int len) static uae_u8 *execscsicmd_in (int unitnum, uae_u8 *data, int len, int *outlen) { - int v = execscsicmd (unitnum, data, len, dev_info[unitnum].scsibuf, DEVICE_SCSI_BUFSIZE); + struct dev_info_spti *di = unitisopen (unitnum); + if (!di) + return 0; + int v = execscsicmd (di, unitnum, data, len, di->scsibuf, DEVICE_SCSI_BUFSIZE); if (v < 0) return 0; if (v == 0) return 0; if (outlen) *outlen = v; - return dev_info[unitnum].scsibuf; + return di->scsibuf; } -static int total_devices; +static uae_u8 *execscsicmd_in_internal (struct dev_info_spti *di, int unitnum, uae_u8 *data, int len, int *outlen) +{ + int v = execscsicmd (di, unitnum, data, len, di->scsibuf, DEVICE_SCSI_BUFSIZE); + if (v < 0) + return 0; + if (v == 0) + return 0; + if (outlen) + *outlen = v; + return di->scsibuf; +} +static void close_scsi_device2 (struct dev_info_spti *di) +{ + if (di->open == false) + return; + if (di->handle != INVALID_HANDLE_VALUE) + CloseHandle (di->handle); + di->handle = INVALID_HANDLE_VALUE; + di->open = false; +} static void close_scsi_device (int unitnum) { - if (dev_info[unitnum].handle != INVALID_HANDLE_VALUE) { - write_log (L"SPTI: unit %d closed\n", unitnum); - CloseHandle (dev_info[unitnum].handle); - } - dev_info[unitnum].handle = INVALID_HANDLE_VALUE; + struct dev_info_spti *di = unitisopen (unitnum); + if (!di) + return; + close_scsi_device2 (di); + unittable[unitnum] = 0; } -static void free_scsi_device(int dev) +static void free_scsi_device (struct dev_info_spti *di) { - close_scsi_device (dev); - xfree(dev_info[dev].name); - xfree(dev_info[dev].drvpath); - xfree(dev_info[dev].inquirydata); - VirtualFree (dev_info[dev].scsibuf, 0, MEM_RELEASE); - dev_info[dev].name = NULL; - dev_info[dev].drvpath = NULL; - dev_info[dev].inquirydata = NULL; - dev_info[dev].scsibuf = NULL; - memset(&dev_info[dev], 0, sizeof (struct dev_info_spti)); + close_scsi_device2 (di); + xfree (di->name); + xfree (di->drvpath); + xfree (di->inquirydata); + VirtualFree (di->scsibuf, 0, MEM_RELEASE); + di->name = NULL; + di->drvpath = NULL; + di->inquirydata = NULL; + di->scsibuf = NULL; + memset (di, 0, sizeof (struct dev_info_spti)); } static int rescan (void); -static int check_scsi_bus (int flags) +static void close_scsi_bus (void) { - return 1; + if (!bus_open) { + write_log (L"SPTI close_bus() when already closed!\n"); + return; + } + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + free_scsi_device (&dev_info[i]); + unittable[i] = 0; + } + total_devices = 0; + bus_open = 0; + write_log (L"SPTI driver closed.\n"); } static int open_scsi_bus (int flags) { - int i; - + if (bus_open) { + write_log (L"SPTI open_bus() more than once!\n"); + return 1; + } total_devices = 0; uae_sem_init (&scgp_sem, 0, 1); - for (i = 0; i < MAX_TOTAL_DEVICES; i++) { - memset (&dev_info[i], 0, sizeof (struct dev_info_spti)); - dev_info[i].handle = INVALID_HANDLE_VALUE; - } rescan (); + bus_open = 1; + write_log (L"SPTI driver open, %d devices.\n", total_devices); return total_devices; } -static void close_scsi_bus (void) +static int mediacheck (struct dev_info_spti *di, int unitnum) +{ + uae_u8 cmd [6] = { 0,0,0,0,0,0 }; /* TEST UNIT READY */ + if (di->open == false) + return -1; + int v = execscsicmd (di, unitnum, cmd, sizeof cmd, 0, 0); + return v >= 0 ? 1 : 0; +} + +static int mediacheck_full (struct dev_info_spti *di, int unitnum, struct device_info *dinfo) { - int i; - for (i = 0; i < total_devices; i++) - free_scsi_device (i); + uae_u8 cmd1[10] = { 0x25,0,0,0,0,0,0,0,0,0 }; /* READ CAPACITY */ + uae_u8 *p; + int outlen; + + dinfo->sectorspertrack = 0; + dinfo->trackspercylinder = 0; + dinfo->bytespersector = 0; + dinfo->cylinders = 0; + dinfo->write_protected = 1; + if (di->open == false) + return 0; + outlen = 32; + p = execscsicmd_in_internal (di, unitnum, cmd1, sizeof cmd1, &outlen); + if (p && outlen >= 8) { + dinfo->bytespersector = (p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7]; + dinfo->sectorspertrack = ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]) + 1; + dinfo->trackspercylinder = 1; + dinfo->cylinders = 1; + } + if (di->type == INQ_DASD) { + uae_u8 cmd2[10] = { 0x5a,0x08,0,0,0,0,0,0,0xf0,0 }; /* MODE SENSE */ + outlen = 32; + p = execscsicmd_in_internal (di, unitnum, cmd2, sizeof cmd2, &outlen); + if (p && outlen >= 4) { + dinfo->write_protected = (p[3] & 0x80) ? 1 : 0; + } + } + // write_log (L"mediacheck_full(%d,%d,%d,%d,%d)\n", + // di->bytespersector, di->sectorspertrack, di->trackspercylinder, di->cylinders, di->write_protected); + return 1; +} + +static void update_device_info (int unitnum) +{ + struct dev_info_spti *dispti = unitisopen (unitnum); + if (!dispti) + return; + struct device_info *di = &dispti->di; + _tcscpy (di->label, dispti->drvletter ? dispti->drvlettername : dispti->name); + _tcscpy (di->mediapath, dispti->drvpath); + di->bus = 0; + di->target = unitnum; + di->lun = 0; + di->media_inserted = mediacheck (dispti, unitnum); + di->removable = dispti->removable; + mediacheck_full (dispti, unitnum, di); + di->type = dispti->type; + di->unitnum = unitnum + 1; + if (log_scsi) { + write_log (L"MI=%d TP=%d WP=%d CY=%d BK=%d RMB=%d '%s'\n", + di->media_inserted, di->type, di->write_protected, di->cylinders, di->bytespersector, di->removable, di->label); + } } -static void checkcapabilities (int unitnum) +static void checkcapabilities (struct dev_info_spti *di) { - struct dev_info_spti *di = &dev_info[unitnum]; STORAGE_ADAPTER_DESCRIPTOR desc; STORAGE_PROPERTY_QUERY query; DWORD ret, status; @@ -304,12 +437,12 @@ static void checkcapabilities (int unitnum) } } -static int inquiry (int unitnum, struct dev_info_spti *di, uae_u8 *inquirydata) +static int inquiry (struct dev_info_spti *di, int unitnum, uae_u8 *inquirydata) { uae_u8 cmd[6] = { 0x12,0,0,0,36,0 }; /* INQUIRY */ uae_u8 out[INQUIRY_SIZE] = { 0 }; int outlen = sizeof (out); - uae_u8 *p = execscsicmd_in (unitnum, cmd, sizeof (cmd), &outlen); + uae_u8 *p = execscsicmd_in_internal (di, unitnum, cmd, sizeof (cmd), &outlen); int inqlen = 0; di->isatapi = 0; @@ -348,61 +481,11 @@ static int inquiry (int unitnum, struct dev_info_spti *di, uae_u8 *inquirydata) return inqlen; } -static int mediacheck (int unitnum) -{ - uae_u8 cmd [6] = { 0,0,0,0,0,0 }; /* TEST UNIT READY */ - int v; - if (dev_info[unitnum].handle == INVALID_HANDLE_VALUE) - return 0; - v = execscsicmd (unitnum, cmd, sizeof (cmd), 0, 0); - return v >= 0 ? 1 : 0; -} - -static int mediacheck_full (int unitnum, struct device_info *di) -{ - uae_u8 cmd1[10] = { 0x25,0,0,0,0,0,0,0,0,0 }; /* READ CAPACITY */ - uae_u8 *p; - int outlen; - - di->sectorspertrack = 0; - di->trackspercylinder = 0; - di->bytespersector = 0; - di->cylinders = 0; - di->write_protected = 1; - if (dev_info[unitnum].handle == INVALID_HANDLE_VALUE) - return 0; - outlen = 32; - p = execscsicmd_in (unitnum, cmd1, sizeof cmd1, &outlen); - if (p && outlen >= 8) { - di->bytespersector = (p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7]; - di->sectorspertrack = ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]) + 1; - di->trackspercylinder = 1; - di->cylinders = 1; - } - if (di->type == INQ_DASD) { - uae_u8 cmd2[10] = { 0x5a,0x08,0,0,0,0,0,0,0xf0,0 }; /* MODE SENSE */ - outlen = 32; - p = execscsicmd_in (unitnum, cmd2, sizeof cmd2, &outlen); - if (p && outlen >= 4) { - di->write_protected = (p[3] & 0x80) ? 1 : 0; - } - } - // write_log (L"mediacheck_full(%d,%d,%d,%d,%d)\n", - // di->bytespersector, di->sectorspertrack, di->trackspercylinder, di->cylinders, di->write_protected); - return 1; -} - -int open_scsi_device (int unitnum) +static int open_scsi_device2 (struct dev_info_spti *di, int unitnum) { HANDLE h; TCHAR *dev; - struct dev_info_spti *di; - di = &dev_info[unitnum]; - if (unitnum >= total_devices) - return 0; - if (!di) - return 0; if (di->bus >= 0) { dev = xmalloc (TCHAR, 100); _stprintf (dev, L"\\\\.\\Scsi%d:", di->bus); @@ -417,18 +500,18 @@ int open_scsi_device (int unitnum) write_log (L"SPTI: failed to open unit %d err=%d ('%s')\n", unitnum, GetLastError (), dev); } else { uae_u8 inqdata[INQUIRY_SIZE + 1] = { 0 }; - checkcapabilities (unitnum); - if (!inquiry (unitnum, di, inqdata)) { + checkcapabilities (di); + if (!inquiry (di, unitnum, inqdata)) { write_log (L"SPTI: inquiry failed unit %d ('%s':%d:%d:%d:%d)\n", unitnum, dev, di->bus, di->path, di->target, di->lun); - close_scsi_device (unitnum); + close_scsi_device2 (di); xfree (dev); return 0; } inqdata[INQUIRY_SIZE] = 0; di->name = my_strdup_ansi ((char*)inqdata + 8); if (di->type == INQ_ROMD) { - dev_info[unitnum].mediainserted = mediacheck (unitnum); + di->mediainserted = mediacheck (di, unitnum); write_log (L"SPTI: unit %d (%c:\\) opened [%s], %s, '%s'\n", unitnum, di->drvletter ? di->drvletter : '*', di->isatapi ? L"ATAPI" : L"SCSI", @@ -441,19 +524,52 @@ int open_scsi_device (int unitnum) di->inquirydata = xmalloc (uae_u8, INQUIRY_SIZE); memcpy (di->inquirydata, inqdata, INQUIRY_SIZE); xfree (dev); + update_device_info (unitnum); + di->open = true; return 1; } xfree (dev); return 0; } +int open_scsi_device (int unitnum, const TCHAR *ident) +{ + struct dev_info_spti *di = NULL; + if (ident) { + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + di = &dev_info[i]; + if (unittable[i] == 0 && di->drvletter != 0) { + if (!_tcsicmp (di->drvlettername, ident)) { + unittable[unitnum] = i + 1; + if (open_scsi_device2 (di, unitnum)) + return 1; + unittable[unitnum] = 0; + return 0; + } + } + } + return 0; + } + di = &dev_info[unitnum]; + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + if (unittable[i] == unitnum + 1) + return 0; + } + if (di->enabled == 0) + return 0; + unittable[unitnum] = unitnum + 1; + if (open_scsi_device2 (di, unitnum)) + return 1; + unittable[unitnum] = 0; + return 0; +} -static int adddrive (TCHAR *drvpath, int bus, int pathid, int targetid, int lunid, int scanmode) +static int adddrive (const TCHAR *drvpath, int bus, int pathid, int targetid, int lunid, int scanmode) { struct dev_info_spti *di; int cnt = total_devices, i; int freeit = 1; - if (cnt >= MAX_TOTAL_DEVICES) + if (cnt >= MAX_TOTAL_SCSI_DEVICES) return 0; for (i = 0; i < total_devices; i++) { di = &dev_info[i]; @@ -470,6 +586,7 @@ static int adddrive (TCHAR *drvpath, int bus, int pathid, int targetid, int luni di->lun = lunid; di->scanmode = scanmode; di->drvletter = 0; + di->enabled = true; for (TCHAR drvletter = 'C'; drvletter <= 'Z'; drvletter++) { TCHAR drvname[10]; @@ -490,7 +607,8 @@ static int adddrive (TCHAR *drvpath, int bus, int pathid, int targetid, int luni total_devices++; - if (open_scsi_device (cnt)) { + unittable[cnt] = cnt + 1; + if (open_scsi_device2 (&dev_info[cnt], cnt)) { for (i = 0; i < cnt; i++) { if (!memcmp (di->inquirydata, dev_info[i].inquirydata, INQUIRY_SIZE) && di->scanmode != dev_info[i].scanmode) { write_log (L"duplicate device, skipped..\n"); @@ -499,57 +617,42 @@ static int adddrive (TCHAR *drvpath, int bus, int pathid, int targetid, int luni } if (i == cnt) { freeit = 0; - close_scsi_device (cnt); + close_scsi_device2 (&dev_info[cnt]); } } if (freeit) { - free_scsi_device (cnt); + free_scsi_device (&dev_info[cnt]); total_devices--; } + unittable[cnt] = 0; return 1; } -static int getid (int unitnum) -{ - return dev_info[unitnum].drvletter ? dev_info[unitnum].drvletter : unitnum + 1; -} - static struct device_info *info_device (int unitnum, struct device_info *di, int quick) { - struct dev_info_spti *dispti; - if (unitnum >= MAX_TOTAL_DEVICES || dev_info[unitnum].handle == INVALID_HANDLE_VALUE) + struct dev_info_spti *dispti = unitcheck (unitnum); + if (!dispti) return NULL; - dispti = &dev_info[unitnum]; - _tcscpy (di->label, dispti->drvletter ? dispti->drvlettername : dispti->name); - _tcscpy (di->mediapath, dispti->drvpath); - di->bus = 0; - di->target = unitnum; - di->lun = 0; - di->media_inserted = mediacheck (unitnum); - di->removable = dispti->removable; - mediacheck_full (unitnum, di); - di->type = dispti->type; - di->id = getid (unitnum); - if (log_scsi) { - write_log (L"MI=%d TP=%d WP=%d CY=%d BK=%d RMB=%d '%s'\n", - di->media_inserted, di->type, di->write_protected, di->cylinders, di->bytespersector, di->removable, di->label); - } + if (!quick) + update_device_info (unitnum); + dispti->di.open = di->open; + memcpy (di, &dispti->di, sizeof (struct device_info)); return di; } void win32_spti_media_change (TCHAR driveletter, int insert) { - int i, now; - - for (i = 0; i < total_devices; i++) { - if (dev_info[i].type == INQ_ROMD) { - now = mediacheck (i); - if (now != dev_info[i].mediainserted) { - write_log (L"SPTI: media change %c %d\n", dev_info[i].drvletter, insert); - dev_info[i].mediainserted = now; - scsi_do_disk_change (getid (i), insert, NULL); + for (int i = 0; i < total_devices; i++) { + struct dev_info_spti *di = &dev_info[i]; + if (di->drvletter == driveletter && di->mediainserted != insert) { + write_log (L"SPTI: media change %c %d\n", dev_info[i].drvletter, insert); + di->mediainserted = insert; + int unitnum = getunitnum (di); + if (unitnum >= 0) { + update_device_info (unitnum); + scsi_do_disk_change (unitnum, insert, NULL); #ifdef RETROPLATFORM - rp_cd_image_change (i, dev_info[i].drvletter ? dev_info[i].drvlettername : dev_info[i].name); + rp_cd_image_change (unitnum, di->drvletter ? di->drvlettername : di->name); #endif } } @@ -558,22 +661,12 @@ void win32_spti_media_change (TCHAR driveletter, int insert) static int check_isatapi (int unitnum) { - return dev_info[unitnum].isatapi; -} - -static struct device_scsi_info *scsi_info (int unitnum, struct device_scsi_info *dsi) -{ - dsi->buffer = dev_info[unitnum].scsibuf; - dsi->bufsize = DEVICE_SCSI_BUFSIZE; - return dsi; + struct dev_info_spti *di = unitcheck (unitnum); + if (!di) + return 0; + return di->isatapi; } -struct device_functions devicefunc_win32_spti = { - check_scsi_bus, open_scsi_bus, close_scsi_bus, open_scsi_device, close_scsi_device, info_device, - execscsicmd_out, execscsicmd_in, execscsicmd_direct, - 0, 0, 0, 0, 0, 0, 0, 0, 0, check_isatapi, scsi_info, 0 -}; - static int getCDROMProperty (int idx, HDEVINFO DevInfo, const GUID *guid) { SP_DEVICE_INTERFACE_DATA interfaceData; @@ -769,3 +862,11 @@ static int rescan (void) #endif + + +struct device_functions devicefunc_win32_spti = { + L"SPTI", + open_scsi_bus, close_scsi_bus, open_scsi_device, close_scsi_device, info_device, + execscsicmd_out, execscsicmd_in, execscsicmd_direct, + 0, 0, 0, 0, 0, 0, 0, 0, 0, check_isatapi, 0 +}; diff --git a/od-win32/dinput.cpp b/od-win32/dinput.cpp index 7cbe44a8..fac2e5d8 100644 --- a/od-win32/dinput.cpp +++ b/od-win32/dinput.cpp @@ -908,8 +908,6 @@ static int initialize_rawinput (void) } else if (did == di_keyboard) { if (rdpdevice (buf)) continue; - if (rnum_kb < 2) - continue; if (num_keyboard >= MAX_INPUT_DEVICES) continue; did += num_keyboard; @@ -985,7 +983,7 @@ static int initialize_rawinput (void) if (rnum_kb && num_keyboard < MAX_INPUT_DEVICES - 1) { struct didata *did = di_keyboard + num_keyboard; num_keyboard++; - rkb++; + rnum_kb++; did->name = my_strdup (L"WinUAE null keyboard"); did->rawinput = NULL; did->connection = DIDC_RAW; @@ -1196,9 +1194,15 @@ static void handle_rawinput_2 (RAWINPUT *raw) } } if (num == num_keyboard) { - if (!istest && scancode == DIK_F12 && pressed && isfocus ()) - inputdevice_add_inputcode (AKS_ENTERGUI, 1); - return; + for (num = 0; num < num_keyboard; num++) { + if (did->connection == DIDC_RAW && did->acquired && did->rawinput == NULL) + break; + } + if (num == num_keyboard) { + if (!istest && scancode == DIK_F12 && pressed && isfocus ()) + inputdevice_add_inputcode (AKS_ENTERGUI, 1); + return; + } } if (rawkeystate[scancode] == pressed) { diff --git a/od-win32/fsdb_mywin32.cpp b/od-win32/fsdb_mywin32.cpp index be2c8e65..20f3e390 100644 --- a/od-win32/fsdb_mywin32.cpp +++ b/od-win32/fsdb_mywin32.cpp @@ -394,7 +394,7 @@ int my_getvolumeinfo (const TCHAR *root) DWORD comlen; DWORD flags; if (GetVolumeInformation (volume, NULL, 0, NULL, &comlen, &flags, fsname, sizeof (fsname))) { - write_log (L"Volume %s FS=%s maxlen=%d flags=%08X\n", volume, fsname, comlen, flags); + //write_log (L"Volume %s FS=%s maxlen=%d flags=%08X\n", volume, fsname, comlen, flags); if (flags & FILE_NAMED_STREAMS) ret |= MYVOLUMEINFO_STREAMS; } diff --git a/od-win32/posixemu.cpp b/od-win32/posixemu.cpp index f56d3553..12601e68 100644 --- a/od-win32/posixemu.cpp +++ b/od-win32/posixemu.cpp @@ -281,7 +281,7 @@ int uae_start_thread (TCHAR *name, void *(*f)(void *), void *arg, uae_thread_id hThread = (HANDLE)_beginthreadex (NULL, 0, thread_init, thp, 0, &foo); if (hThread) { if (name) { - write_log (L"Thread '%s' started (%d)\n", name, hThread); + //write_log (L"Thread '%s' started (%d)\n", name, hThread); SetThreadPriority (hThread, THREAD_PRIORITY_HIGHEST); } } else { diff --git a/od-win32/rp.cpp b/od-win32/rp.cpp index 9c5aa3bb..1457b0f0 100644 --- a/od-win32/rp.cpp +++ b/od-win32/rp.cpp @@ -196,7 +196,7 @@ static int cd_insert (int num, const TCHAR *name) { if (num != 0) return 0; - _tcscpy (changed_prefs.cdimagefile, name); + _tcscpy (changed_prefs.cdimagefile[0], name); config_changed = 1; return 1; } @@ -834,17 +834,17 @@ void rp_fixup_options (struct uae_prefs *p) } } - for (i = 0; i < MAX_TOTAL_DEVICES; i++) { - int v = sys_command_ismedia (DF_IOCTL, i, 1); + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + int v = sys_command_ismedia (i, 1); if (v >= 0) cd_mask |= 1 << i; } RPSendMessagex (RPIPCGM_DEVICES, RP_DEVICE_CD, cd_mask, NULL, 0, &guestinfo, NULL); if (cd_mask) { - for (i = 0; i < MAX_TOTAL_DEVICES; i++) { + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { if ((1 << i) & cd_mask) { struct device_info di = { 0 }; - if (sys_command_info (DF_IOCTL, i, &di, 0)) + if (sys_command_info (i, &di, 0)) rp_cd_image_change (i, di.mediapath); } } diff --git a/od-win32/win32.cpp b/od-win32/win32.cpp index acef1a91..11b16e85 100644 --- a/od-win32/win32.cpp +++ b/od-win32/win32.cpp @@ -2139,17 +2139,13 @@ extern const TCHAR *get_aspi_path (int); static int get_aspi (int old) { - if ((old == UAESCSI_SPTI || old == UAESCSI_SPTISCAN) && os_winnt_admin) - return old; if (old == UAESCSI_NEROASPI && get_aspi_path (1)) return old; if (old == UAESCSI_FROGASPI && get_aspi_path (2)) return old; if (old == UAESCSI_ADAPTECASPI && get_aspi_path (0)) return old; - if (os_winnt_admin) - return UAESCSI_SPTI; - else if (get_aspi_path (1)) + if (get_aspi_path (1)) return UAESCSI_NEROASPI; else if (get_aspi_path (2)) return UAESCSI_FROGASPI; @@ -2508,7 +2504,7 @@ void target_default_options (struct uae_prefs *p, int type) p->win32_automount_cddrives = 0; p->win32_automount_netdrives = 0; p->win32_kbledmode = 0; - p->win32_uaescsimode = get_aspi (p->win32_uaescsimode); + p->win32_uaescsimode = UAESCSI_CDEMU; p->win32_borderless = 0; p->win32_powersavedisabled = 1; p->sana2 = 0; @@ -2521,7 +2517,7 @@ void target_default_options (struct uae_prefs *p, int type) p->win32_commandpathend[0] = 0; } if (type == 1 || type == 0) { - p->win32_uaescsimode = get_aspi (p->win32_uaescsimode); + p->win32_uaescsimode = UAESCSI_CDEMU; p->win32_midioutdev = -2; p->win32_midiindev = 0; p->win32_automount_removable = 0; @@ -2726,7 +2722,7 @@ int target_parse_option (struct uae_prefs *p, TCHAR *option, TCHAR *value) } if (cfgfile_yesno (option, value, L"aspi", &vb)) { - p->win32_uaescsimode = false; + p->win32_uaescsimode = 0; if (vb) p->win32_uaescsimode = get_aspi (0); if (p->win32_uaescsimode < UAESCSI_ASPI_FIRST) @@ -2770,8 +2766,11 @@ int target_parse_option (struct uae_prefs *p, TCHAR *option, TCHAR *value) return 1; } - if (cfgfile_strval (option, value, L"uaescsimode", &p->win32_uaescsimode, scsimode, 0)) + if (cfgfile_strval (option, value, L"uaescsimode", &p->win32_uaescsimode, scsimode, 0)) { + // do not forget me! + p->win32_uaescsimode = UAESCSI_CDEMU; return 1; + } if (cfgfile_intval (option, value, L"active_priority", &v, 1)) { p->win32_active_priority = fetchpri (v, 1); diff --git a/od-win32/win32.h b/od-win32/win32.h index 360b149d..a999f036 100644 --- a/od-win32/win32.h +++ b/od-win32/win32.h @@ -18,8 +18,8 @@ #define WINUAEPUBLICBETA 1 #define LANG_DLL 1 -#define WINUAEBETA L"3" -#define WINUAEDATE MAKEBD(2010, 7, 16) +#define WINUAEBETA L"4" +#define WINUAEDATE MAKEBD(2010, 7, 18) #define WINUAEEXTRA L"" #define WINUAEREV L"" diff --git a/od-win32/win32gui.cpp b/od-win32/win32gui.cpp index 9d29c058..8b7b0b5c 100644 --- a/od-win32/win32gui.cpp +++ b/od-win32/win32gui.cpp @@ -1922,15 +1922,15 @@ static UINT_PTR CALLBACK ofnhook (HWND hDlg, UINT message, WPARAM wParam, LPARAM static void eject_cd (void) { - workprefs.cdimagefile[0] = 0; + workprefs.cdimagefile[0][0] = 0; quickstart_cddrive[0] = 0; - workprefs.cdimagefileuse = false; + workprefs.cdimagefileuse[0] = false; if (full_property_sheet) { quickstart_cdtype = 0; } else { if (quickstart_cdtype > 0) { quickstart_cdtype = 1; - workprefs.cdimagefileuse = true; + workprefs.cdimagefileuse[0] = true; } } } @@ -1949,7 +1949,7 @@ static void selectcd (struct uae_prefs *prefs, HWND hDlg, int num, int id, TCHAR SetDlgItemText (hDlg, id, full_path); if (quickstart_cddrive[0]) eject_cd (); - _tcscpy (prefs->cdimagefile, full_path); + _tcscpy (prefs->cdimagefile[0], full_path); DISK_history_add (full_path, -1, HISTORY_CD, 0); } @@ -4810,8 +4810,8 @@ static void init_quickstartdlg (HWND hDlg) workprefs.df[1][0] = 0; workprefs.df[2][0] = 0; workprefs.df[3][0] = 0; - workprefs.cdimagefile[0] = 0; - workprefs.cdimagefileuse = quickstart_cdtype > 0; + workprefs.cdimagefile[0][0] = 0; + workprefs.cdimagefileuse[0] = quickstart_cdtype > 0; load_quickstart (hDlg, 1); quickstarthost (hDlg, hostconf); } @@ -5054,11 +5054,12 @@ static INT_PTR CALLBACK QuickstartDlgProc (HWND hDlg, UINT msg, WPARAM wParam, L int len = sizeof quickstart_cddrive / sizeof (TCHAR); quickstart_cdtype = 2; SendDlgItemMessage (hDlg, IDC_CD0Q_TYPE, WM_GETTEXT, (WPARAM)len, (LPARAM)quickstart_cddrive); - _tcscpy (workprefs.cdimagefile, quickstart_cddrive); + _tcscpy (workprefs.cdimagefile[0], quickstart_cddrive); } else { eject_cd (); quickstart_cdtype = val; } + workprefs.cdimagefileuse[0] = quickstart_cdtype > 0; addfloppytype (hDlg, 1); addfloppyhistory (hDlg); } @@ -7210,8 +7211,8 @@ extern const TCHAR *get_aspi_path (int); static void misc_scsi (HWND hDlg) { SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_RESETCONTENT, 0, 0); - SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_ADDSTRING, 0, (LPARAM)L"SCSI Emulation"); - SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_ADDSTRING, 0, (LPARAM)L"SPTI *"); + SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_ADDSTRING, 0, (LPARAM)L"SCSI Emulation *"); + SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_ADDSTRING, 0, (LPARAM)L"SPTI"); SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_ADDSTRING, 0, (LPARAM)L"SPTI + SCSI SCAN"); SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_ADDSTRING, 0, (LPARAM)((get_aspi_path (0)) ? L"AdaptecASPI" : L"(AdaptecASPI)")); SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_ADDSTRING, 0, (LPARAM)((get_aspi_path (1)) ? L"NeroASPI" : L"(NeroASPI)")); @@ -8382,7 +8383,6 @@ static struct fsvdlg_vals current_fsvdlg; struct hfdlg_vals { - TCHAR volumename[MAX_DPATH]; TCHAR devicename[MAX_DPATH]; TCHAR filename[MAX_DPATH]; TCHAR fsfilename[MAX_DPATH]; @@ -8400,7 +8400,7 @@ struct hfdlg_vals bool original; }; -static struct hfdlg_vals empty_hfdlg = { L"", L"", L"", L"", 32, 2, 1, 0, 512, 1, 0, 0, 0, 1, 0, 1 }; +static struct hfdlg_vals empty_hfdlg = { L"", L"", L"", 32, 2, 1, 0, 512, 1, 0, 0, 0, 1, 0, 1 }; static struct hfdlg_vals current_hfdlg; static int archivehd; @@ -9102,7 +9102,7 @@ static void harddiskdlg_button (HWND hDlg, WPARAM wParam) case IDC_CD_SELECT: DiskSelection (hDlg, wParam, 17, &workprefs, NULL); quickstart_cdtype = 1; - workprefs.cdimagefileuse = true; + workprefs.cdimagefileuse[0] = true; addcdtype (hDlg, IDC_CD_TYPE); break; case IDC_CD_EJECT: @@ -9278,7 +9278,7 @@ static INT_PTR CALLBACK HarddiskDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPA case IDC_CD_TEXT: getfloppyname (hDlg, 0, 1, IDC_CD_TEXT); quickstart_cdtype = 1; - workprefs.cdimagefileuse = true; + workprefs.cdimagefileuse[0] = true; addcdtype (hDlg, IDC_CD_TYPE); addfloppyhistory_2 (hDlg, 0, IDC_CD_TEXT, HISTORY_CD); break; @@ -9289,14 +9289,14 @@ static INT_PTR CALLBACK HarddiskDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPA if (quickstart_cdtype >= 2) { int len = sizeof quickstart_cddrive / sizeof (TCHAR); quickstart_cdtype = 2; - workprefs.cdimagefileuse = true; + workprefs.cdimagefileuse[0] = true; SendDlgItemMessage (hDlg, IDC_CD_TYPE, WM_GETTEXT, (WPARAM)len, (LPARAM)quickstart_cddrive); - _tcscpy (workprefs.cdimagefile, quickstart_cddrive); + _tcscpy (workprefs.cdimagefile[0], quickstart_cddrive); } else { eject_cd (); quickstart_cdtype = val; if (val > 0) - workprefs.cdimagefileuse = true; + workprefs.cdimagefileuse[0] = true; } addcdtype (hDlg, IDC_CD_TYPE); @@ -9401,7 +9401,7 @@ static void addfloppyhistory_2 (HWND hDlg, int n, int f_text, int type) SendDlgItemMessage (hDlg, f_text, CB_RESETCONTENT, 0, 0); if (type == HISTORY_CD) { nn = 1; - text = workprefs.cdimagefile; + text = workprefs.cdimagefile[0]; } else { nn = workprefs.dfxtype[n] + 1; text = workprefs.df[n]; @@ -9483,7 +9483,7 @@ static void addcdtype (HWND hDlg, int id) SendDlgItemMessage (hDlg, id, CB_ADDSTRING, 0, (LPARAM)tmp); int cdtype = quickstart_cdtype; if (currentpage != QUICKSTART_ID) { - if (full_property_sheet && !workprefs.cdimagefileuse && !workprefs.cdimagefile[0]) + if (full_property_sheet && !workprefs.cdimagefileuse[0] && !workprefs.cdimagefile[0][0]) cdtype = 0; } int cnt = 2; @@ -9495,7 +9495,7 @@ static void addcdtype (HWND hDlg, int id) SendDlgItemMessage (hDlg, id, CB_ADDSTRING, 0, (LPARAM)vol); if (!_tcsicmp (vol, quickstart_cddrive)) { cdtype = quickstart_cdtype = cnt; - _tcscpy (workprefs.cdimagefile, vol); + _tcscpy (workprefs.cdimagefile[0], vol); } cnt++; } @@ -9541,7 +9541,7 @@ static void addfloppytype (HWND hDlg, int n) SetWindowText (GetDlgItem (hDlg, f_enable), tmp); addcdtype (hDlg, IDC_CD0Q_TYPE); hide (hDlg, IDC_CD0Q_TYPE, 0); - text = workprefs.cdimagefile; + text = workprefs.cdimagefile[0]; regsetstr (NULL, L"QuickStartCDDrive", quickstart_cdtype >= 2 ? quickstart_cddrive : L""); regsetint (NULL, L"QuickStartCDType", quickstart_cdtype >= 2 ? 2 : quickstart_cdtype); } else { @@ -9671,7 +9671,7 @@ static void getfloppyname (HWND hDlg, int n, int cd, int f_text) } else { if (quickstart_cddrive[0]) eject_cd (); - _tcscpy (workprefs.cdimagefile, tmp); + _tcscpy (workprefs.cdimagefile[0], tmp); } } } @@ -13623,7 +13623,7 @@ int dragdrop (HWND hDlg, HDROP hd, struct uae_prefs *prefs, int currentpage) ret = 1; break; case ZFILE_CDIMAGE: - _tcscpy (workprefs.cdimagefile, file); + _tcscpy (workprefs.cdimagefile[0], file); break; default: if (currentpage < 0 && !full_property_sheet) { diff --git a/od-win32/winuaechangelog.txt b/od-win32/winuaechangelog.txt index d079ec5d..25b9d139 100644 --- a/od-win32/winuaechangelog.txt +++ b/od-win32/winuaechangelog.txt @@ -1,4 +1,52 @@ +Beta 4: + +- rawinput was disabled if only one keyboard device was detected, input didn't work at all + in b3 because of null keyboard (detected only one rawinput keyboard = it was ignore but null + keyboard was still added later -> more than one keyboard -> do not fallback to directinput..) +- redirect unknown rawinput messages to null keyboard (shouldn't happen but you never know..) +- spaces not allowed in directory filesystem volume name (wrong validation routine used) +- bottom border was half-blanked in some doublescanned modes + +Another major CD update. CD configuration unified, now any CD unit "slot" can point to different +CD backend (image mounter + scsi emulation, IOCTL drive + scsi emulation, SPTI drive + scsi +passthrough) On the fly changes fully supported. CD mess is nearly gone, code is finally structured +logically without special cases. (this finally made SCSI emulation quite easy to implement) + +- SCSI emulation is now the default SCSI mode (CDFS and audio tracks always work, switch to + SPTI if you need advanced stuff like cd writing) Some audio CD players work for the first time + now because some SCSI commands have been obsoleted long time ago like PLAY TRACK/INDEX +- CD audio DAE emulation does not attempt to play data tracks anymore +- added most common CD audio SCSI commands to SCSI emulator, OS3.5+ PlayCD confirmed working. + Following new SCSI command added: + START/STOP, STOP PLAY/SCAN, SCAN, PLAY AUDIO MSF, PLAY AUDIO, PLAY CD, PLAY TRACK/INDEX, + PAUSE/RESUME, READ SUB-CHANNEL, READ TOC, MODE SENSE/MODE SELECT (cd audio volume page only), + READ CD and READ CF MSF (only audio extraction supported + subchannel options) +- added CD audio io commands to uaescsi.device (most programs use HD_SCSICMD) +- emulated INQUIRY vendor, product and revision fetched from real device if possible + +Testing: + +Load your normal WB3.x configuration (that uses uaescsi.device CDROMs), start emulation +normally. (This and following betas force SCSI Emulation mode!) Report all changes, +including logs, SCSI emulation logging is enabled. + +Notes: + +GUI selection overrides slot 0, for example if you normally have D:\ = uaescsi.device unit 0 +and E:\ = uaescsi.device unit 1, mounting a cd image "ejects" whatever is in unit 0 and +replaces it with image file. + +If CD32 or CDTV is started in "autodetect" mode and it chose unit 1 or later (CD32/CDTV or +Audio CD inserted), unit 0 changes are ignored until original drive becomes empty. This +needs to be more intelligent. + +Configuration file accepts cdimage0 to cdimage7. Full syntax: +cdimagex=image path or device name,cd backend(:reserved for future) +Cd backend not mandatory. Supported CD backend names are: +image, ioctl, spti and aspi. (this is autoselected when using GUI) + +Beta 3: - most debugger options now accept .b, .w and .l size extension (+special .3 if 3-byte word), old style separate size values (1, 2, 3 or 4) not supported anymore diff --git a/scsi.cpp b/scsi.cpp index d0d6804e..366fbbe9 100644 --- a/scsi.cpp +++ b/scsi.cpp @@ -98,7 +98,7 @@ struct scsi_data *scsi_alloc(int id, struct hd_hardfiledata *hfd) struct scsi_data *scsi_alloc_native(int id, int nativeunit) { struct scsi_data *sd; - if (!sys_command_open (DF_SCSI, nativeunit)) { + if (!sys_command_open (nativeunit)) { write_log (L"SCSI: native scsi unit %d failed to open\n", nativeunit); return NULL; } @@ -118,7 +118,7 @@ void scsi_free(struct scsi_data *sd) if (!sd) return; if (sd->nativescsiunit >= 0) { - sys_command_close (DF_SCSI, sd->nativescsiunit); + sys_command_close (sd->nativescsiunit); } xfree(sd); } diff --git a/scsiemul.cpp b/scsiemul.cpp index 188463cd..9938a0a5 100644 --- a/scsiemul.cpp +++ b/scsiemul.cpp @@ -41,13 +41,12 @@ #define ASYNC_REQUEST_NONE 0 #define ASYNC_REQUEST_TEMP 1 #define ASYNC_REQUEST_CHANGEINT 10 +#define ASYNC_REQUEST_FRAMEINT 11 struct devstruct { int unitnum, aunit; int opencnt; int changenum; - int allow_scsi; - int allow_ioctl; int drivetype; int iscd; volatile uaecptr d_request[MAX_ASYNC_REQUESTS]; @@ -55,6 +54,13 @@ struct devstruct { volatile uae_u32 d_request_data[MAX_ASYNC_REQUESTS]; struct device_info di; uaecptr changeint; + int changeint_mediastate; + + int configblocksize; + int volumelevel; + int fadeframes; + int fadetarget; + int fadecounter; smp_comm_pipe requests; int thread_running; @@ -65,21 +71,23 @@ struct priv_devstruct { int inuse; int unit; int mode; - int scsi; - int ioctl; - int noscsi; int type; int flags; /* OpenDevice() */ }; -static struct devstruct devst[MAX_TOTAL_DEVICES]; +static struct devstruct devst[MAX_TOTAL_SCSI_DEVICES]; static struct priv_devstruct pdevst[MAX_OPEN_DEVICES]; static uae_u32 nscmd_cmd; static uae_sem_t change_sem; -static struct device_info *devinfo (int mode, int unitnum, struct device_info *di) +static struct device_info *devinfo (struct devstruct *devst, struct device_info *di) { - return sys_command_info (mode, unitnum, di, 0); + struct device_info *dio = sys_command_info (devst->unitnum, di, 0); + if (dio) { + if (!devst->configblocksize) + devst->configblocksize = dio->bytespersector; + } + return dio; } static void io_log (const TCHAR *msg, uaecptr request) @@ -94,8 +102,9 @@ static void io_log (const TCHAR *msg, uaecptr request) static struct devstruct *getdevstruct (int unit) { int i; - for (i = 0; i < MAX_TOTAL_DEVICES; i++) { - if (unit >= 0 && devst[i].aunit == unit) return &devst[i]; + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + if (unit >= 0 && devst[i].aunit == unit) + return &devst[i]; } return 0; } @@ -139,10 +148,7 @@ static void dev_close_3 (struct devstruct *dev, struct priv_devstruct *pdev) if (!dev->opencnt) return; dev->opencnt--; if (!dev->opencnt) { - if (pdev->scsi) - sys_command_close (DF_SCSI, dev->unitnum); - if (pdev->ioctl) - sys_command_close (DF_IOCTL, dev->unitnum); + sys_command_close (dev->unitnum); pdev->inuse = 0; write_comm_pipe_u32 (&dev->requests, 0, 1); } @@ -183,13 +189,6 @@ static int openfail (uaecptr ioreq, int error) return (uae_u32)-1; } -static void setpdev (struct priv_devstruct *pdev, struct devstruct *dev) -{ - pdev->scsi = dev->allow_scsi ? 1 : 0; - pdev->ioctl = dev->allow_scsi ? 0 : 1; - pdev->mode = dev->allow_scsi ? DF_SCSI : DF_IOCTL; -} - static uae_u32 REGPARAM2 dev_open_2 (TrapContext *context, int type) { uaecptr ioreq = m68k_areg (regs, 1); @@ -201,23 +200,17 @@ static uae_u32 REGPARAM2 dev_open_2 (TrapContext *context, int type) if (log_scsi) write_log (L"opening %s:%d ioreq=%08X\n", getdevname (type), unit, ioreq); - if (get_word (ioreq + 0x12) < IOSTDREQ_SIZE) + if (get_word (ioreq + 0x12) < IOSTDREQ_SIZE && get_word (ioreq + 0x12) > 0) return openfail (ioreq, IOERR_BADLENGTH); if (!dev) return openfail (ioreq, 32); /* badunitnum */ if (!dev->opencnt) { for (i = 0; i < MAX_OPEN_DEVICES; i++) { pdev = &pdevst[i]; - if (pdev->inuse == 0) break; - } - if (type == UAEDEV_SCSI_ID && sys_command_open (dev->allow_scsi ? DF_SCSI : DF_IOCTL, dev->unitnum)) { - setpdev (pdev, dev); - } - if (type == UAEDEV_DISK_ID && sys_command_open (DF_IOCTL, dev->unitnum)) { - pdev->ioctl = 1; - pdev->mode = DF_IOCTL; + if (pdev->inuse == 0) + break; } - if (!pdev->scsi && !pdev->ioctl) + if (!sys_command_open (dev->unitnum)) return openfail (ioreq, IOERR_OPENFAIL); pdev->type = type; pdev->unit = unit; @@ -270,53 +263,39 @@ static int is_async_request (struct devstruct *dev, uaecptr request) return 0; } - +#if 0 static int scsiemul_switchscsi (const TCHAR *name) { struct devstruct *dev = NULL; struct device_info *discsi, discsi2; - int i, j, opened[MAX_TOTAL_DEVICES]; + int i, opened[MAX_TOTAL_SCSI_DEVICES]; bool wasopen = false; - for (i = 0; i < MAX_TOTAL_DEVICES; i++) + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) opened[i] = sys_command_isopen (i); dev = &devst[0]; - if ((dev->allow_ioctl || dev->allow_scsi) && dev->opencnt) + if (dev->opencnt) wasopen = true; - if (dev->allow_scsi) - sys_command_close (DF_SCSI, dev->unitnum); - if (dev->allow_ioctl) - sys_command_close (DF_IOCTL, dev->unitnum); - dev->allow_ioctl = 0; - dev->allow_scsi = 0; + sys_command_close (dev->unitnum); dev = NULL; - for (j = 0; j < 2; j++) { - int mode = j == 0 ? DF_SCSI : DF_IOCTL; - if (!(device_func_init (j == 0 ? DEVICE_TYPE_SCSI : DEVICE_TYPE_ANY) & (1 << mode))) - continue; + if (device_func_init (DEVICE_TYPE_ANY)) { if (devst[0].di.media_inserted < 0) devst[0].di.media_inserted = 0; i = 0; - while (i < MAX_TOTAL_DEVICES && dev == NULL) { + while (i < MAX_TOTAL_SCSI_DEVICES && dev == NULL) { discsi = 0; - if (sys_command_open (mode, i)) { - discsi = sys_command_info (mode, i, &discsi2, 0); + if (sys_command_open ( i)) { + discsi = sys_command_info (i, &discsi2, 0); if (discsi && discsi->type == INQ_ROMD) { - if (!_tcsicmp (currprefs.cdimagefile, discsi->label)) { + if (!_tcsicmp (currprefs.cdimagefile[0], discsi->label)) { dev = &devst[0]; dev->unitnum = i; - dev->allow_scsi = j == 0 ? 1 : 0; - dev->allow_ioctl = j != 0 ? 1 : 0; dev->drivetype = discsi->type; memcpy (&dev->di, discsi, sizeof (struct device_info)); dev->iscd = 1; - write_log (L"%s mounted as uaescsi.device:0 (SCSI=%d IOCTL=%d)\n", discsi->label, dev->allow_scsi, dev->allow_ioctl); - if (dev->aunit >= 0) { - struct priv_devstruct *pdev = &pdevst[dev->aunit]; - setpdev (pdev, dev); - } + write_log (L"%s mounted as uaescsi.device:0\n", discsi->label); if (dev->di.media_inserted) { dev->di.media_inserted = 0; scsi_do_disk_change (dev->di.id, 1, NULL); @@ -324,7 +303,7 @@ static int scsiemul_switchscsi (const TCHAR *name) } } if (opened[i] == 0 && !wasopen) - sys_command_close (mode, i); + sys_command_close ( i); } i++; } @@ -333,49 +312,10 @@ static int scsiemul_switchscsi (const TCHAR *name) } return -1; } -static int scsiemul_switchemu (const TCHAR *name) -{ - struct devstruct *dev = NULL; - struct device_info *discsi, discsi2; - - if (!device_func_init (DEVICE_TYPE_ANY | DEVICE_TYPE_ALLOWEMU)) - return -1; - int opened = sys_command_isopen (0); - if (sys_command_open (DF_IOCTL, 0)) { - if (discsi = sys_command_info (DF_IOCTL, 0, &discsi2, 0)) { - dev = &devst[0]; - dev->unitnum = 0; - dev->allow_scsi = 1; - dev->allow_ioctl = 1; - dev->drivetype = discsi->type; - memcpy (&dev->di, discsi, sizeof (struct device_info)); - dev->iscd = 1; - write_log (L"IMG_EMU (%s) mounted as uaescsi.device:0\n", name); - if (dev->aunit >= 0) { - struct priv_devstruct *pdev = &pdevst[dev->aunit]; - setpdev (pdev, dev); - } - dev->di.media_inserted = 0; - } - if (!opened) - sys_command_close (DF_IOCTL, 0); - return 0; - } - return -1; -} - -int scsi_do_disk_device_change (void) -{ - int ret = scsiemul_switchscsi (currprefs.cdimagefile); - if (ret < 0) { - scsiemul_switchemu (currprefs.cdimagefile); - } - return ret; -} +#endif -// device_id = -1 and insert==0 -> all medias going away // pollmode is 1 if no change interrupts found -> increase time of media change -int scsi_do_disk_change (int device_id, int insert, int *pollmode) +int scsi_do_disk_change (int unitnum, int insert, int *pollmode) { int i, j, ret; @@ -383,19 +323,18 @@ int scsi_do_disk_change (int device_id, int insert, int *pollmode) if (!change_sem) return ret; uae_sem_wait (&change_sem); - for (i = 0; i < MAX_TOTAL_DEVICES; i++) { + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { struct devstruct *dev = &devst[i]; - if (dev->di.id == device_id || (device_id < 0 && i == 0)) { + if (dev->di.unitnum == unitnum + 1) { ret = i; - if ((dev->di.media_inserted > 0 && insert == 0) || (dev->di.media_inserted <= 0 && insert)) { + if ((dev->changeint_mediastate > 0 && insert == 0) || (dev->changeint_mediastate <= 0 && insert)) { + dev->changeint_mediastate = insert; if (pollmode) *pollmode = 1; if (dev->aunit >= 0) { struct priv_devstruct *pdev = &pdevst[dev->aunit]; - devinfo (pdev->mode, dev->unitnum, &dev->di); + devinfo (dev, &dev->di); } - if (device_id < 0 && insert == 0) - dev->di.media_inserted = -1; // stay away! dev->changenum++; j = 0; while (j < MAX_ASYNC_REQUESTS) { @@ -483,18 +422,17 @@ static void abort_async (struct devstruct *dev, uaecptr request, int errcode, in write_log (L"asyncronous request=%08X aborted, error=%d\n", request, errcode); } -static int command_read (int mode, struct devstruct *dev, uaecptr data, uae_u64 offset, uae_u32 length, uae_u32 *io_actual) +static int command_read (struct devstruct *dev, uaecptr data, uae_u64 offset, uae_u32 length, uae_u32 *io_actual) { int blocksize = dev->di.bytespersector; - uae_u8 *temp; length /= blocksize; offset /= blocksize; while (length > 0) { - temp = sys_command_read (mode, dev->unitnum, NULL, offset, 1); - if (!temp) + uae_u8 buffer[4096]; + if (!sys_command_read (dev->unitnum, buffer, offset, 1)) return 20; - memcpyha_safe (data, temp, blocksize); + memcpyha_safe (data, buffer, blocksize); data += blocksize; offset++; length--; @@ -502,19 +440,16 @@ static int command_read (int mode, struct devstruct *dev, uaecptr data, uae_u64 return 0; } -static int command_write (int mode, struct devstruct *dev, uaecptr data, uae_u64 offset, uae_u32 length, uae_u32 *io_actual) +static int command_write (struct devstruct *dev, uaecptr data, uae_u64 offset, uae_u32 length, uae_u32 *io_actual) { uae_u32 blocksize = dev->di.bytespersector; - struct device_scsi_info dsi; - - if (!sys_command_scsi_info (mode, dev->unitnum, &dsi)) - return 20; length /= blocksize; offset /= blocksize; while (length > 0) { + uae_u8 buffer[4096]; int err; - memcpyah_safe (dsi.buffer, data, blocksize); - err = sys_command_write (mode, dev->unitnum, NULL, offset, 1); + memcpyah_safe (buffer, data, blocksize); + err = sys_command_write (dev->unitnum, buffer, offset, 1); if (!err) return 20; if (err < 0) @@ -526,31 +461,35 @@ static int command_write (int mode, struct devstruct *dev, uaecptr data, uae_u64 return 0; } -static int command_cd_read (int mode, struct devstruct *dev, uaecptr data, uae_u64 offset, uae_u32 length, uae_u32 *io_actual) +static int command_cd_read (struct devstruct *dev, uaecptr data, uae_u64 offset, uae_u32 length, uae_u32 *io_actual) { - uae_u8 *temp; uae_u32 len, sector, startoffset; + int blocksize; + blocksize = dev->configblocksize; *io_actual = 0; - if (dev->di.bytespersector == 0) - dev->di.bytespersector = 2048; - startoffset = offset % dev->di.bytespersector; + startoffset = offset % blocksize; offset -= startoffset; - sector = offset / dev->di.bytespersector; + sector = offset / blocksize; while (length > 0) { - temp = sys_command_cd_read (mode, dev->unitnum, NULL, sector, 1); - if (!temp) - return 20; + uae_u8 temp[4096]; + if (blocksize != 2048) { + if (!sys_command_cd_rawread (dev->unitnum, temp, sector, 1, blocksize)) + return 20; + } else { + if (!sys_command_cd_read (dev->unitnum, temp, sector, 1)) + return 20; + } if (startoffset > 0) { - len = dev->di.bytespersector - startoffset; + len = blocksize - startoffset; if (len > length) len = length; memcpyha_safe (data, temp + startoffset, len); length -= len; data += len; startoffset = 0; *io_actual += len; - } else if (length >= dev->di.bytespersector) { - len = dev->di.bytespersector; + } else if (length >= blocksize) { + len = blocksize; memcpyha_safe (data, temp, len); length -= len; data += len; @@ -582,6 +521,9 @@ static int dev_do_io (struct devstruct *dev, uaecptr request) return 0; command = get_word (request + 28); +// write_log (L"%d: CMD=%04X DATA=%08X LEN=%08X OFFSET=%08X ACTUAL=%08X\n", +// command, io_data, io_length, io_offset, io_actual); + switch (command) { case CMD_READ: @@ -589,13 +531,13 @@ static int dev_do_io (struct devstruct *dev, uaecptr request) if (dev->di.media_inserted <= 0) goto no_media; if (dev->drivetype == INQ_ROMD) { - io_error = command_cd_read (pdev->mode, dev, io_data, io_offset, io_length, &io_actual); + io_error = command_cd_read (dev, io_data, io_offset, io_length, &io_actual); } else { if ((io_offset & bmask) || bmask == 0 || io_data == 0) goto bad_command; if ((io_length & bmask) || io_length == 0) goto bad_len; - io_error = command_read (pdev->mode, dev, io_data, io_offset, io_length, &io_actual); + io_error = command_read (dev, io_data, io_offset, io_length, &io_actual); } break; case TD_READ64: @@ -608,9 +550,9 @@ static int dev_do_io (struct devstruct *dev, uaecptr request) if ((io_length & bmask) || io_length == 0) goto bad_len; if (dev->drivetype == INQ_ROMD) - io_error = command_cd_read (pdev->mode, dev, io_data, io_offset64, io_length, &io_actual); + io_error = command_cd_read (dev, io_data, io_offset64, io_length, &io_actual); else - io_error = command_read (pdev->mode, dev, io_data, io_offset64, io_length, &io_actual); + io_error = command_read (dev, io_data, io_offset64, io_length, &io_actual); break; case CMD_WRITE: @@ -623,7 +565,7 @@ static int dev_do_io (struct devstruct *dev, uaecptr request) } else if ((io_length & bmask) || io_length == 0) { goto bad_len; } else { - io_error = command_write (pdev->mode, dev, io_data, io_offset, io_length, &io_actual); + io_error = command_write (dev, io_data, io_offset, io_length, &io_actual); } break; case TD_WRITE64: @@ -638,7 +580,7 @@ static int dev_do_io (struct devstruct *dev, uaecptr request) } else if ((io_length & bmask) || io_length == 0) { goto bad_len; } else { - io_error = command_write (pdev->mode, dev, io_data, io_offset64, io_length, &io_actual); + io_error = command_write (dev, io_data, io_offset64, io_length, &io_actual); } break; @@ -652,7 +594,7 @@ static int dev_do_io (struct devstruct *dev, uaecptr request) } else if ((io_length & bmask) || io_length == 0) { goto bad_len; } else { - io_error = command_write (pdev->mode, dev, io_data, io_offset, io_length, &io_actual); + io_error = command_write (dev, io_data, io_offset, io_length, &io_actual); } break; case TD_FORMAT64: @@ -667,7 +609,7 @@ static int dev_do_io (struct devstruct *dev, uaecptr request) } else if ((io_length & bmask) || io_length == 0) { goto bad_len; } else { - io_error = command_write (pdev->mode, dev, io_data, io_offset64, io_length, &io_actual); + io_error = command_write (dev, io_data, io_offset64, io_length, &io_actual); } break; @@ -681,19 +623,20 @@ static int dev_do_io (struct devstruct *dev, uaecptr request) case CMD_REMOVE: io_actual = dev->changeint; dev->changeint = io_data; + dev->changeint_mediastate = dev->di.media_inserted; break; case CMD_CHANGENUM: io_actual = dev->changenum; break; case CMD_CHANGESTATE: if (dev->di.media_inserted >= 0) { - io_actual = devinfo (pdev->mode, dev->unitnum, &dev->di)->media_inserted > 0 ? 0 : 1; + io_actual = devinfo (dev, &dev->di)->media_inserted > 0 ? 0 : 1; } else { io_actual = 1; } break; case CMD_PROTSTATUS: - io_actual = devinfo (pdev->mode, dev->unitnum, &dev->di)->write_protected ? -1 : 0; + io_actual = devinfo (dev, &dev->di)->write_protected ? -1 : 0; break; case CMD_GETDRIVETYPE: io_actual = dev->drivetype; @@ -706,7 +649,7 @@ static int dev_do_io (struct devstruct *dev, uaecptr request) case CMD_GETGEOMETRY: { struct device_info *di; - di = devinfo (pdev->mode, dev->unitnum, &dev->di); + di = devinfo (dev, &dev->di); if (di->media_inserted <= 0) goto no_media; put_long (io_data + 0, di->bytespersector); @@ -722,6 +665,7 @@ static int dev_do_io (struct devstruct *dev, uaecptr request) } break; case CMD_ADDCHANGEINT: + dev->changeint_mediastate = dev->di.media_inserted; io_error = add_async_request (dev, request, ASYNC_REQUEST_CHANGEINT, io_data); if (!io_error) async = 1; @@ -729,14 +673,193 @@ static int dev_do_io (struct devstruct *dev, uaecptr request) case CMD_REMCHANGEINT: release_async_request (dev, request); break; + + case CD_TOCLSN: + case CD_TOCMSF: + { + int msf = command == CD_TOCMSF; + struct cd_toc_head toc; + if (sys_command_cd_toc (dev->di.unitnum, &toc)) { + if (io_offset == 0 && io_length > 0) { + int pos = toc.lastaddress; + put_byte (io_data, toc.first_track); + put_byte (io_data + 1, toc.last_track); + if (msf) + pos = lsn2msf (pos); + put_long (io_data + 2, pos); + io_offset++; + io_length--; + io_data += 6; + io_actual++; + } + for (int i = toc.first_track_offset; i < toc.last_track_offset && io_length > 0; i++) { + if (io_offset == toc.toc[i].point) { + int pos = toc.toc[i].paddress; + put_byte (io_data, (toc.toc[i].control << 4) | toc.toc[i].adr); + put_byte (io_data + 1, toc.toc[i].point); + if (msf) + pos = lsn2msf (pos); + put_long (io_data + 2, pos); + io_offset++; + io_length--; + io_data += 6; + io_actual++; + } + } + } else { + io_error = CDERR_NotSpecified; + } + } + break; + case CD_ADDFRAMEINT: + io_error = add_async_request (dev, request, ASYNC_REQUEST_FRAMEINT, io_data); + if (!io_error) + async = 1; + break; + case CD_REMFRAMEINT: + release_async_request (dev, request); + break; + case CD_ATTENUATE: + { + if (io_offset != -1) { + dev->fadeframes = io_length & 0x7fff; + dev->fadetarget = io_offset & 0x7fff; + } + io_actual = dev->volumelevel; + } + break; + case CD_INFO: + { + uae_u16 status = 0; + struct cd_toc_head toc; + uae_u8 subq[SUBQ_SIZE] = { 0 }; + sys_command_cd_qcode (dev->di.unitnum, subq); + status |= 1 << 0; // door closed + if (dev->di.media_inserted) { + status |= 1 << 1; + status |= 1 << 2; // motor on + if (sys_command_cd_toc (dev->di.unitnum, &toc)) { + status |= 1 << 3; // toc + if (subq[1] == AUDIO_STATUS_IN_PROGRESS || subq[1] == AUDIO_STATUS_PAUSED) + status |= 1 << 5; // audio play + if (subq[1] == AUDIO_STATUS_PAUSED) + status |= 1 << 6; // paused + if (isdatatrack (&toc, 0)) + status |= 1 << 4; // data track + } + } + put_word (io_data + 0, 75); // PlaySpeed + put_word (io_data + 2, 1200); // ReadSpeed (randomly chose 16x) + put_word (io_data + 4, 1200); // ReadXLSpeed + put_word (io_data + 6, dev->configblocksize); // SectorSize + put_word (io_data + 8, -1); // XLECC + put_word (io_data + 10, 0); // EjectReset + put_word (io_data + 12, 0); // Reserved * 4 + put_word (io_data + 14, 0); + put_word (io_data + 16, 0); + put_word (io_data + 18, 0); + put_word (io_data + 20, 1200); // MaxSpeed + put_word (io_data + 22, 0xffff); // AudioPrecision (volume) + put_word (io_data + 24, status); // Status + put_word (io_data + 26, 0); // Reserved2 * 4 + put_word (io_data + 28, 0); + put_word (io_data + 30, 0); + put_word (io_data + 32, 0); + io_actual = 34; + } + break; + case CD_CONFIG: + { + while (get_long (io_data) != TAG_DONE) { + uae_u32 tag = get_long (io_data); + uae_u32 data = get_long (io_data + 4); + if (tag == 4) { + // TAGCD_SECTORSIZE + if (data == 2048 || data == 2336 || data == 2352) + dev->configblocksize = data; + else + io_error = IOERR_BADADDRESS; + + } + io_data += 8; + } + break; + } + case CD_PAUSE: + { + int old = sys_command_cd_pause (dev->di.unitnum, io_length); + if (old >= 0) + io_actual = old; + else + io_error = IOERR_BADADDRESS; + break; + } + case CD_PLAYLSN: + { + int start = io_offset; + int end = io_length + start; + if (!sys_command_cd_play (dev->di.unitnum, start, end, 0, NULL)) + io_error = IOERR_BADADDRESS; + } + break; + case CD_PLAYMSF: + { + int start = msf2lsn (io_offset); + int end = msf2lsn (io_length) + start; + if (!sys_command_cd_play (dev->di.unitnum, start, end, 0, NULL)) + io_error = IOERR_BADADDRESS; + } + break; + case CD_PLAYTRACK: + { + struct cd_toc_head toc; + int ok = 0; + if (sys_command_cd_toc (dev->di.unitnum, &toc)) { + for (int i = toc.first_track_offset; i < toc.last_track_offset; i++) { + if (i == io_offset && i + io_length <= toc.last_track_offset) { + ok = sys_command_cd_play (dev->di.unitnum, toc.toc[i].address, toc.toc[i + io_length].address, 0, NULL); + break; + } + } + } + if (!ok) + io_error = IOERR_BADADDRESS; + } + break; + case CD_QCODEMSF: + case CD_QCODELSN: + { + uae_u8 subq[SUBQ_SIZE]; + if (sys_command_cd_qcode (dev->di.unitnum, subq)) { + if (subq[1] == AUDIO_STATUS_IN_PROGRESS || subq[1] == AUDIO_STATUS_PAUSED) { + put_byte (io_data + 0, subq[4 + 0]); + put_byte (io_data + 1, frombcd (subq[4 + 1])); + put_byte (io_data + 2, frombcd (subq[4 + 2])); + put_byte (io_data + 3, subq[4 + 6]); + int trackpos = fromlongbcd (subq + 4 + 3); + int diskpos = fromlongbcd (subq + 4 + 7); + if (command == CD_QCODELSN) { + trackpos = msf2lsn (trackpos); + diskpos = msf2lsn (diskpos); + } + put_long (io_data + 4, trackpos); + put_long (io_data + 8, diskpos); + io_actual = 12; + } else { + io_error = CDERR_InvalidState; + } + } else { + io_error = IOERR_BADADDRESS; + } + } + break; + case HD_SCSICMD: - if (dev->allow_scsi && pdev->scsi) { + { uae_u32 sdd = get_long (request + 40); io_error = sys_command_scsi_direct (dev->unitnum, sdd); if (log_scsi) write_log (L"scsidev: did io: sdd %p request %p error %d\n", sdd, request, get_byte (request + 31)); - } else { - io_error = IOERR_NOCMD; } break; case NSCMD_DEVICEQUERY: @@ -892,10 +1015,9 @@ static void dev_reset (void) { int i, j; struct devstruct *dev; - struct device_info *discsi, discsi2; int unitnum = 0; - for (i = 0; i < MAX_TOTAL_DEVICES; i++) { + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { dev = &devst[i]; if (dev->opencnt > 0) { for (j = 0; j < MAX_ASYNC_REQUESTS; j++) { @@ -904,10 +1026,7 @@ static void dev_reset (void) abort_async (dev, request, 0, 0); } dev->opencnt = 1; - if (dev->allow_scsi) - sys_command_close (DF_SCSI, dev->unitnum); - if (dev->allow_ioctl) - sys_command_close (DF_IOCTL, dev->unitnum); + sys_command_close (dev->unitnum); } memset (dev, 0, sizeof (struct devstruct)); dev->unitnum = dev->aunit = -1; @@ -915,52 +1034,39 @@ static void dev_reset (void) for (i = 0; i < MAX_OPEN_DEVICES; i++) memset (&pdevst[i], 0, sizeof (struct priv_devstruct)); - int didswitch = -1; - if (currprefs.cdimagefile[0] || currprefs.cdimagefileuse) - didswitch = scsiemul_switchscsi (currprefs.cdimagefile); - if (didswitch < 0) { - device_func_init (DEVICE_TYPE_SCSI); - i = j = 0; - while (i < MAX_TOTAL_DEVICES) { - int mode = -1; - dev = &devst[i]; - discsi = 0; - if (sys_command_open (DF_SCSI, j)) { - dev->allow_scsi = 1; - mode = DF_SCSI; - } - if (!dev->allow_scsi) { - if (sys_command_open (DF_IOCTL, j)) { - dev->allow_ioctl = 1; - mode = DF_IOCTL; - } - } - if (mode >= 0) { - discsi = sys_command_info (mode, j, &discsi2, 0); - sys_command_close (mode, j); - } + device_func_init (0); + i = 0; + while (i < MAX_TOTAL_SCSI_DEVICES) { + dev = &devst[i]; + struct device_info *discsi, discsi2; + if (sys_command_open (i)) { + discsi = sys_command_info (i, &discsi2, 0); if (discsi) { - dev->unitnum = j; + dev->unitnum = i; dev->drivetype = discsi->type; memcpy (&dev->di, discsi, sizeof (struct device_info)); + dev->changeint_mediastate = discsi->media_inserted; + dev->configblocksize = discsi->bytespersector; if (discsi->type == INQ_ROMD) dev->iscd = 1; } - i++; - j++; } + i++; } unitnum = 0; - for (i = 0; i < MAX_TOTAL_DEVICES; i++) { + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { dev = &devst[i]; + if (dev->unitnum >= 0) + sys_command_close (dev->unitnum); if (dev->unitnum >= 0 && dev->iscd) { dev->aunit = unitnum; + dev->volumelevel = 0x7fff; unitnum++; } } if (unitnum == 0) unitnum = 1; - for (i = 0; i < MAX_TOTAL_DEVICES; i++) { + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { dev = &devst[i]; if (dev->unitnum >= 0) { if (!dev->iscd) { diff --git a/zfile_archive.cpp b/zfile_archive.cpp index 6a45aac6..0d9c3336 100644 --- a/zfile_archive.cpp +++ b/zfile_archive.cpp @@ -196,6 +196,8 @@ struct zfile *archive_access_select (struct znode *parent, struct zfile *zf, uns if ((mask & ZFD_CD) && ft) { if (ext && !_tcsicmp (ext, L".iso")) whf = 2; + if (ext && !_tcsicmp (ext, L".ccd")) + whf = 9; if (ext && !_tcsicmp (ext, L".cue")) whf = 10; }