From: Toni Wilen Date: Fri, 16 Jul 2010 12:30:20 +0000 (+0300) Subject: 2210b3 X-Git-Tag: 2300~22 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=b4b32cac752eeb60bf4b1af98491b029bd950648;p=francis%2Fwinuae.git 2210b3 --- diff --git a/a2091.cpp b/a2091.cpp index 32237438..fe1b4816 100644 --- a/a2091.cpp +++ b/a2091.cpp @@ -1235,7 +1235,7 @@ static void addnativescsi (void) types[i] = -1; devices[i] = -1; if (sys_command_open (DF_SCSI, i)) { - if (sys_command_info (DF_SCSI, i, &dis[i])) { + if (sys_command_info (DF_SCSI, i, &dis[i], 0)) { devices[i] = i; types[i] = 100 - i; if (dis[i].type == INQ_ROMD) diff --git a/akiko.cpp b/akiko.cpp index c4229fb7..c3a7396d 100644 --- a/akiko.cpp +++ b/akiko.cpp @@ -7,7 +7,7 @@ * - NVRAM * - CDROM * -* Copyright 2001-2009 Toni Wilen +* Copyright 2001-2010 Toni Wilen * */ @@ -355,13 +355,7 @@ static uae_u32 akiko_c2p_read (int offset) #define CDS_ERROR 0x80 #define CDS_PLAYING 0x08 - -#define AUDIO_STATUS_NOT_SUPPORTED 0x00 -#define AUDIO_STATUS_IN_PROGRESS 0x11 -#define AUDIO_STATUS_PAUSED 0x12 -#define AUDIO_STATUS_PLAY_COMPLETE 0x13 -#define AUDIO_STATUS_PLAY_ERROR 0x14 -#define AUDIO_STATUS_NO_STATUS 0x15 +#define CDS_PLAYEND 0x00 #define CH_ERR_BADCOMMAND 0x80 // %10000000 #define CH_ERR_CHECKSUM 0x88 // %10001000 @@ -377,6 +371,13 @@ static uae_u32 akiko_c2p_read (int offset) #define CH_ERR_ABNORMALSEEK 0xf0 // %11110000 #define CH_ERR_NODISK 0xf8 // %11111000 +static int framecounter, subcodecounter; + +#define MAX_SUBCODEBUFFER 20 +static volatile int subcodebufferoffset, subcodebufferoffsetw; +static uae_u8 subcodebufferinuse[MAX_SUBCODEBUFFER]; +static uae_u8 subcodebuffer[MAX_SUBCODEBUFFER * SUB_CHANNEL_SIZE]; + static uae_u32 cdrom_intreq, cdrom_intena; static uae_u8 cdrom_subcodeoffset; static uae_u32 cdrom_addressdata, cdrom_addressmisc; @@ -391,13 +392,11 @@ static uae_u8 cdrom_result_buffer[32]; static uae_u8 cdrom_command_buffer[32]; static uae_u8 cdrom_command; -#define MAX_TOC_ENTRIES 103 /* tracks 1-99, A0, A1 and A2 */ -static int cdrom_toc_entries; static int cdrom_toc_counter; static uae_u32 cdrom_toc_crc; static uae_u8 cdrom_toc_buffer[MAX_TOC_ENTRIES * 13]; -static uae_u8 cdrom_toc_cd_buffer[4 + MAX_TOC_ENTRIES * 11]; -static uae_u8 qcode_buf[12]; +static struct cd_toc_head cdrom_toc_cd_buffer; +static uae_u8 qcode_buf[SUBQ_SIZE]; static int qcode_valid; static int cdrom_disk, cdrom_paused, cdrom_playing; @@ -406,7 +405,7 @@ static int cdrom_command_length; static int cdrom_checksum_error, cdrom_unknown_command; static int cdrom_data_offset, cdrom_speed, cdrom_sector_counter; static int cdrom_current_sector, cdrom_seek_delay; -static int cdrom_data_end, cdrom_leadout; +static int cdrom_data_end; static int cdrom_audiotimeout; static int cdrom_led; static int cdrom_dosomething; @@ -428,6 +427,7 @@ static volatile int frame2counter; static smp_comm_pipe requests; static volatile int akiko_thread_running; +static uae_sem_t akiko_sem, sub_sem; static void checkint (void) { @@ -447,45 +447,11 @@ void rethink_akiko (void) checkint (); } - -static uae_u8 frombcd (uae_u8 v) -{ - return (v >> 4) * 10 + (v & 15); -} - -static uae_u8 tobcd (uae_u8 v) -{ - return ((v / 10) << 4) | (v % 10); -} - -static int fromlongbcd (uae_u8 *p) -{ - return (frombcd (p[0]) << 16) | (frombcd (p[1]) << 8) | (frombcd (p[2]) << 0); -} - -/* convert minutes, seconds and frames -> logical sector number */ -static int msf2lsn (int msf) -{ - int sector = (((msf >> 16) & 0xff) * 60 * 75 + ((msf >> 8) & 0xff) * 75 + ((msf >> 0) & 0xff)) - 150; - if (sector < 0) - sector = 0; - return sector; -} - -/* convert logical sector number -> minutes, seconds and frames */ -static int lsn2msf (int sectors) -{ - int msf; - sectors += 150; - msf = (sectors / (75 * 60)) << 16; - msf |= ((sectors / 75) % 60) << 8; - msf |= (sectors % 75) << 0; - return msf; -} - static void cdaudiostop_do (void) { qcode_valid = 0; + cdrom_playing = 0; + cdrom_paused = 0; if (unitnum < 0) return; sys_command_cd_pause (DF_IOCTL, unitnum, 0); @@ -497,81 +463,116 @@ static void cdaudiostop (void) { cdrom_playing = 0; cdrom_paused = 0; - cdrom_audiotimeout = 0; write_comm_pipe_u32 (&requests, 0x104, 1); } +static void subfunc (uae_u8 *data, int cnt) +{ + if (!(cdrom_flags & CDFLAG_SUBCODE)) + return; + uae_sem_wait (&sub_sem); +#if 0 + int total = 0; + for (int i = 0; i < MAX_SUBCODEBUFFER; i++) { + if (subcodebufferinuse[i]) + total++; + } + write_log (L"%d ", total); +#endif + if (subcodebufferinuse[subcodebufferoffsetw]) { + memset (subcodebufferinuse, 0,sizeof (subcodebufferinuse)); + subcodebufferoffsetw = subcodebufferoffset = 0; + uae_sem_post (&sub_sem); + write_log (L"CD32: subcode buffer overflow 1\n"); + return; + } + int offset = subcodebufferoffsetw; + while (cnt > 0) { + if (subcodebufferinuse[offset]) { + write_log (L"CD32: subcode buffer overflow 2\n"); + break; + } + subcodebufferinuse[offset] = 1; + memcpy (&subcodebuffer[offset * SUB_CHANNEL_SIZE], data, SUB_CHANNEL_SIZE); + data += SUB_CHANNEL_SIZE; + offset++; + if (offset >= MAX_SUBCODEBUFFER) + offset = 0; + cnt--; + } + subcodebufferoffsetw = offset; + uae_sem_post (&sub_sem); +} + static void cdaudioplay_do (void) { - uae_u32 startmsf = read_comm_pipe_u32_blocking (&requests); - uae_u32 endmsf = read_comm_pipe_u32_blocking (&requests); + uae_u32 startlsn = read_comm_pipe_u32_blocking (&requests); + uae_u32 endlsn = read_comm_pipe_u32_blocking (&requests); uae_u32 scan = read_comm_pipe_u32_blocking (&requests); qcode_valid = 0; if (unitnum < 0) return; - sys_command_cd_play (DF_IOCTL, unitnum, startmsf, endmsf, scan); + sys_command_cd_play (DF_IOCTL, unitnum, startlsn, endlsn, scan, subfunc); } -static bool isaudiotrack (uae_u32 startmsf) +static bool isaudiotrack (int startlsn) { - uae_u8 *buf = cdrom_toc_cd_buffer; - uae_u8 *s = NULL; + struct cd_toc *s = NULL; uae_u32 addr; int i; - if (!cdrom_toc_entries) + if (!cdrom_toc_cd_buffer.points) return false; - for (i = 0; i < cdrom_toc_entries; i++) { - s = buf + 4 + i * 11; - addr = (s[8] << 16) | (s[9] << 8) | (s[10] << 0); - if (s[3] > 0 && s[3] < 100 && addr >= startmsf) + for (i = 0; i < cdrom_toc_cd_buffer.points; i++) { + s = &cdrom_toc_cd_buffer.toc[i]; + addr = s->paddress; + if (s->track > 0 && s->track < 100 && addr >= startlsn) break; + s++; } - if (s && (s[1] & 0x0c) == 0x04) { - write_log (L"tried to play data track %d!\n", s[3]); + if (s && (s->control & 0x0c) == 0x04) { + write_log (L"tried to play data track %d!\n", s->track); return false; } return true; } -static uae_u32 last_play_end; -static int cd_play_audio (uae_u32 startmsf, uae_u32 endmsf, int scan) +static int last_play_end; +static int cd_play_audio (int startlsn, int endlsn, int scan) { - uae_u8 *buf = cdrom_toc_cd_buffer; - uae_u8 *s = NULL; + struct cd_toc *s = NULL; uae_u32 addr; int i; - if (!cdrom_toc_entries) + if (!cdrom_toc_cd_buffer.points) return 0; - for (i = 0; i < cdrom_toc_entries; i++) { - s = buf + 4 + i * 11; - addr = (s[8] << 16) | (s[9] << 8) | (s[10] << 0); - if (s[3] > 0 && s[3] < 100 && addr >= startmsf) + for (i = 0; i < cdrom_toc_cd_buffer.points; i++) { + s = &cdrom_toc_cd_buffer.toc[i]; + addr = s->paddress; + if (s->track > 0 && s->track < 100 && addr >= startlsn) break; } - if (s && (s[1] & 0x0c) == 0x04) { - write_log (L"tried to play data track %d!\n", s[3]); - s += 11; - startmsf = (s[8] << 16) | (s[9] << 8) | (s[10] << 0); - s += 11; - endmsf = (s[8] << 16) | (s[9] << 8) | (s[10] << 0); - //cdrom_audiotimeout = 312; + if (s && (s->control & 0x0c) == 0x04) { + write_log (L"tried to play data track %d!\n", s->track); + s++; + startlsn = s->paddress; + s++; + endlsn = s->paddress; return 0; } - last_play_end = endmsf; + last_play_end = endlsn; cdrom_audiotimeout = 0; write_comm_pipe_u32 (&requests, 0x0110, 0); - write_comm_pipe_u32 (&requests, startmsf, 0); - write_comm_pipe_u32 (&requests, endmsf, 0); + write_comm_pipe_u32 (&requests, startlsn, 0); + write_comm_pipe_u32 (&requests, endlsn, 0); write_comm_pipe_u32 (&requests, scan, 1); return 1; } /* read qcode */ -static uae_u32 last_play_pos; +static int last_play_pos; static int cd_qcode (uae_u8 *d) { uae_u8 *buf, *s, as; @@ -579,39 +580,36 @@ static int cd_qcode (uae_u8 *d) if (d) memset (d, 0, 11); last_play_pos = 0; - if (!qcode_valid) - return 0; buf = qcode_buf; as = buf[1]; - if (as != 0x11 && as != 0x12 && as != 0x13 && as != 0x15) /* audio status ok? */ + if (as != AUDIO_STATUS_IN_PROGRESS && as != AUDIO_STATUS_PAUSED && as != AUDIO_STATUS_PLAY_COMPLETE && as != AUDIO_STATUS_NO_STATUS) /* audio status ok? */ return 0; s = buf + 4; - last_play_pos = (s[5] << 16) | (s[6] << 8) | (s[7] << 0); + last_play_pos = msf2lsn (fromlongbcd (s + 7)); if (!d) return 0; /* ??? */ d[0] = 0; /* CtlAdr */ - d[1] = (s[1] >> 4) | (s[1] << 4); + d[1] = s[0]; /* Track */ - d[2] = tobcd (s[2]); + d[2] = s[1]; /* Index */ - d[3] = tobcd (s[3]); + d[3] = s[2]; /* TrackPos */ - d[4] = tobcd (s[9]); - d[5] = tobcd (s[10]); - d[6] = tobcd (s[11]); + d[4] = s[3]; + d[5] = s[4]; + d[6] = s[5]; /* DiskPos */ d[7] = 0; - d[8] = tobcd (s[5]); - d[9] = tobcd (s[6]); - d[10] = tobcd (s[7]); - if (as == 0x15) { + d[8] = s[7]; + d[9] = s[8]; + d[10] = s[9]; + if (as == AUDIO_STATUS_IN_PROGRESS) { /* Make sure end of disc position is not missed. */ - int lsn = msf2lsn ((s[5] << 16) | (s[6] << 8) | (s[7] << 0)); - int msf = lsn2msf (cdrom_leadout); - if (lsn >= cdrom_leadout || cdrom_leadout - lsn < 10) { + if (last_play_pos >= cdrom_toc_cd_buffer.lastaddress || cdrom_toc_cd_buffer.lastaddress - last_play_pos < 10) { + int msf = lsn2msf (cdrom_toc_cd_buffer.lastaddress); d[8] = tobcd ((uae_u8)(msf >> 16)); d[9] = tobcd ((uae_u8)(msf >> 8)); d[10] = tobcd ((uae_u8)(msf >> 0)); @@ -621,49 +619,42 @@ static int cd_qcode (uae_u8 *d) } /* read toc */ -static int cdrom_toc (void) +static int get_cdrom_toc (void) { - int i, j; + int j; int datatrack = 0, secondtrack = 0; - uae_u8 *s, *d, *buf; + struct cd_toc_head *th; cdrom_toc_counter = -1; - cdrom_toc_entries = 0; - buf = sys_command_cd_toc (DF_IOCTL, unitnum); - if (!buf) + th = sys_command_cd_toc (DF_IOCTL, unitnum); + if (!th) return 1; - i = (buf[0] << 8) | (buf[1] << 0); - i -= 2; - i /= 11; - if (i > MAX_TOC_ENTRIES) - return -1; - cdrom_toc_entries = i; + memcpy (&cdrom_toc_cd_buffer, th, sizeof cdrom_toc_cd_buffer); memset (cdrom_toc_buffer, 0, MAX_TOC_ENTRIES * 13); - memcpy (cdrom_toc_cd_buffer, buf, 4 + cdrom_toc_entries * 11); cdrom_data_end = -1; - for (j = 0; j < cdrom_toc_entries; j++) { - uae_u32 addr; - s = buf + 4 + j * 11; - d = &cdrom_toc_buffer[j * 13]; - addr = msf2lsn ((s[8] << 16) | (s[9] << 8) | (s[10] << 0)); - d[1] = (s[1] >> 4) | (s[1] << 4); - d[3] = s[3] < 100 ? tobcd(s[3]) : s[3]; - d[8] = tobcd (s[8]); - d[9] = tobcd (s[9]); - d[10] = tobcd (s[10]); - if (s[3] == 1 && (s[1] & 0x0c) == 0x04) + for (j = 0; j < th->points; j++) { + struct cd_toc *s = &th->toc[j]; + uae_u8 *d = &cdrom_toc_buffer[j * 13]; + int addr = s->paddress; + int msf = lsn2msf (addr); + if (s->point == 0xa0 || s->point == 0xa1) + msf = s->track << 16; + d[1] = (s->adr << 0) | (s->control << 4); + d[3] = s->point < 100 ? tobcd (s->point) : s->point; + d[8] = tobcd ((msf >> 16) & 0xff); + d[9] = tobcd ((msf >> 8) & 0xff); + d[10] = tobcd ((msf >> 0) & 0xff); + if (s->point == 1 && (s->control & 0x0c) == 0x04) datatrack = 1; - if (s[3] == 2) + if (s->point == 2) secondtrack = addr; - if (s[3] == 0xa2) - cdrom_leadout = addr; } - cdrom_toc_crc = get_crc32(cdrom_toc_buffer, cdrom_toc_entries * 13); + cdrom_toc_crc = get_crc32 (cdrom_toc_buffer, cdrom_toc_cd_buffer.points * 13); if (datatrack) { if (secondtrack) cdrom_data_end = secondtrack; else - cdrom_data_end = cdrom_leadout; + cdrom_data_end = cdrom_toc_cd_buffer.lastaddress; } return 0; } @@ -682,21 +673,21 @@ static int sys_cddev_open (void) opened[unitnum] = 0; if (sys_command_open (DF_IOCTL, unitnum)) { opened[unitnum] = 1; - di2 = sys_command_info (DF_IOCTL, unitnum, &di1); + di2 = sys_command_info (DF_IOCTL, unitnum, &di1, 0); if (di2 && di2->type == INQ_ROMD) { write_log (L"%s: ", di2->label); if (first < 0) first = unitnum; - if (!cdrom_toc ()) { + if (!get_cdrom_toc ()) { if (cdrom_data_end > 0) { - uae_u8 *p = sys_command_cd_read (DF_IOCTL, unitnum, 16); + uae_u8 *p = sys_command_cd_read (DF_IOCTL, unitnum, NULL, 16, 1); if (p) { 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, 21); + p = sys_command_cd_read (DF_IOCTL, unitnum, NULL, 21, 1); crc = get_crc32 (p, 2048); if (crc == 0xe56c340f) write_log (L" [CD32.TM]"); @@ -731,7 +722,7 @@ static int sys_cddev_open (void) } if (unitnum < 0) return 1; - di2 = sys_command_info (DF_IOCTL, unitnum, &di1); + di2 = sys_command_info (DF_IOCTL, unitnum, &di1, 0); if (!di2) { write_log (L"unit %d info failed\n", unitnum); sys_command_close (DF_IOCTL, unitnum); @@ -785,7 +776,7 @@ static void cdrom_return_data (void) } put_byte (cmd_buf + ((cdcomrxinx + len) & 0xff), checksum); #if AKIKO_DEBUG_IO_CMD - write_log (L"%02X\n", checksum); + write_log (L"(%02X)\n", checksum); #endif cdcomrxinx += len + 1; cdcomrxinx &= 0xff; @@ -812,7 +803,11 @@ static int cdrom_command_led (void) static int cdrom_command_media_status (void) { cdrom_result_buffer[0] = 0x0a; - cdrom_result_buffer[1] = sys_command_ismedia (DF_IOCTL, unitnum, 0) > 0 ? 0x83: 0x80; + if (cd_hunt) { + cdrom_result_buffer[1] = 0x80; + } else { + cdrom_result_buffer[1] = sys_command_ismedia (DF_IOCTL, unitnum, 0) > 0 ? 0x83: 0x80; + } return 2; } @@ -822,7 +817,7 @@ static int cdrom_command_status (void) cdrom_result_buffer[1] = 0x01; //cdrom_result_buffer[1] = 0x80; door open if (unitnum >= 0) - cdrom_toc (); + get_cdrom_toc (); /* firmware info */ memcpy (cdrom_result_buffer + 2, FIRMWAREVERSION, sizeof FIRMWAREVERSION); cdrom_result_buffer[0] = cdrom_command; @@ -834,17 +829,18 @@ static int cdrom_command_status (void) static int cdrom_return_toc_entry (void) { cdrom_result_buffer[0] = 6; - if (cdrom_toc_entries == 0) { + if (cdrom_toc_cd_buffer.points == 0) { cdrom_result_buffer[1] = CDS_ERROR; return 15; } cdrom_result_buffer[1] = 0; memcpy (cdrom_result_buffer + 2, cdrom_toc_buffer + cdrom_toc_counter * 13, 13); cdrom_toc_counter++; - if (cdrom_toc_counter >= cdrom_toc_entries) + if (cdrom_toc_counter >= cdrom_toc_cd_buffer.points) cdrom_toc_counter = -1; return 15; } + static int checkerr (void) { if (!cdrom_disk) { @@ -854,9 +850,21 @@ static int checkerr (void) return 0; } +static int cdrom_command_stop (void) +{ + cdrom_audiotimeout = 0; + cdrom_result_buffer[0] = cdrom_command; + if (checkerr ()) + return 2; + cdrom_result_buffer[1] = 0; + write_comm_pipe_u32 (&requests, 0x0104, 1); + return 2; +} + /* pause CD audio */ static int cdrom_command_pause (void) { + cdrom_audiotimeout = 0; cdrom_toc_counter = -1; cdrom_result_buffer[0] = cdrom_command; if (checkerr ()) @@ -866,8 +874,7 @@ static int cdrom_command_pause (void) return 2; if (cdrom_paused) return 2; - cdrom_audiotimeout = 0; - write_comm_pipe_u32 (&requests, 0x102, 1); + write_comm_pipe_u32 (&requests, 0x0102, 1); cdrom_paused = 1; return 2; } @@ -884,15 +891,15 @@ static int cdrom_command_unpause (void) if (!cdrom_playing) return 2; cdrom_paused = 0; - write_comm_pipe_u32 (&requests, 0x103, 1); + write_comm_pipe_u32 (&requests, 0x0103, 1); return 2; } /* seek head/play CD audio/read data sectors */ static int cdrom_command_multi (void) { - int seekpos = fromlongbcd (cdrom_command_buffer + 1); - int endpos = fromlongbcd (cdrom_command_buffer + 4); + int seekpos = msf2lsn (fromlongbcd (cdrom_command_buffer + 1)); + int endpos = msf2lsn (fromlongbcd (cdrom_command_buffer + 4)); if (cdrom_playing) cdaudiostop (); @@ -904,9 +911,9 @@ static int cdrom_command_multi (void) return 2; } - if (cdrom_command_buffer[7] == 0x80) { /* data read */ - int cdrom_data_offset_end = msf2lsn (endpos); - cdrom_data_offset = msf2lsn (seekpos); + if (cdrom_command_buffer[7] == 0x80) { /* data read */ + int cdrom_data_offset_end = endpos; + cdrom_data_offset = seekpos; cdrom_seek_delay = abs (cdrom_current_sector - cdrom_data_offset); if (cdrom_seek_delay < 100) { cdrom_seek_delay = 1; @@ -949,13 +956,19 @@ static int cdrom_command_multi (void) return 2; } +static int cdrom_playend_notify (void) +{ + cdrom_result_buffer[0] = 4; + cdrom_result_buffer[1] = 0x80; + return 2; +} + /* return subq entry */ static int cdrom_command_subq (void) { cdrom_result_buffer[0] = cdrom_command; cdrom_result_buffer[1] = 0; - if (cd_qcode (cdrom_result_buffer + 2)) - cdrom_result_buffer[1] = CDS_ERROR; + cd_qcode (cdrom_result_buffer + 2); return 15; } @@ -1027,6 +1040,9 @@ static void cdrom_run_command_run (void) memset (cdrom_result_buffer, 0, sizeof (cdrom_result_buffer)); switch (cdrom_command & 0x0f) { + case 1: + len = cdrom_command_stop (); + break; case 2: len = cdrom_command_pause (); break; @@ -1120,7 +1136,6 @@ static void cdrom_run_read (void) cdrom_sector_counter++; } -static uae_sem_t akiko_sem; static int lastmediastate = 0; static void akiko_handler (void) @@ -1129,24 +1144,28 @@ static void akiko_handler (void) return; if (!cd_initialized || cdrom_receive_started) return; -#if 0 - if (cdrom_result_complete > cdcomrxcmp && cdrom_result_complete - cdcomrxcmp < 100) { - //set_status (CDINTERRUPT_RXDMADONE); - return; - } - if (cdcomrxcmp < cdrom_result_complete) - return; -#endif + if (mediachanged) { mediachanged = 0; cdrom_start_return_data (cdrom_command_media_status ()); - if (!lastmediastate) - cd_hunt = 1; - cdrom_toc (); + get_cdrom_toc (); /* do not remove! first try may fail */ - cdrom_toc (); + get_cdrom_toc (); return; } + if (cdrom_audiotimeout == -1) { // play finished (or disk end) + if (cdrom_playing) { + write_comm_pipe_u32 (&requests, 0x0104, 1); + cdrom_audiotimeout = -2; + } else { + cdrom_audiotimeout = 0; + } + } + if (cdrom_audiotimeout == -2 && qcode_buf[1] != AUDIO_STATUS_IN_PROGRESS) { + cdrom_start_return_data (cdrom_playend_notify ()); + cdrom_audiotimeout = 0; + } + if (cdrom_toc_counter >= 0 && !cdrom_command_active && cdrom_dosomething) { cdrom_start_return_data (cdrom_return_toc_entry ()); cdrom_dosomething--; @@ -1191,23 +1210,22 @@ static void do_hunt (void) } if (sys_command_open (DF_IOCTL, i) > 0) { struct device_info di = { 0 }; - sys_command_info (DF_IOCTL, i, &di); + sys_command_info (DF_IOCTL, i, &di, 0); unitnum = i; cd_hunt = 0; + lastmediastate = -1; write_log (L"CD32: autodetected unit %d ('%s')\n", unitnum, di.label); } } void AKIKO_hsync_handler (void) { - static int framecounter; - if (!currprefs.cs_cd32cd || !akiko_inited) return; if (cd_hunt) { static int huntcnt; - if (huntcnt <= 0) { + if (huntcnt <= 0 && !mediachanged) { do_hunt (); huntcnt = 312 * 50 * 2; } @@ -1216,7 +1234,6 @@ void AKIKO_hsync_handler (void) framecounter--; if (framecounter <= 0) { - int i; if (cdrom_led) { if (cdrom_playing) cdrom_led |= LED_CD_AUDIO; @@ -1230,17 +1247,31 @@ void AKIKO_hsync_handler (void) cdrom_seek_delay--; } framecounter = 1000000 / (63 * 75 * cdrom_speed); - if (cdrom_flags & CDFLAG_SUBCODE) { - set_status (CDINTERRUPT_SUBCODE); - if (cdrom_subcodeoffset >= 128) - cdrom_subcodeoffset = 0; - else - cdrom_subcodeoffset = 128; - for (i = 0; i < 100; i += 4) { - put_long (subcode_address + cdrom_subcodeoffset, 0); - cdrom_subcodeoffset += 4; + } + + subcodecounter--; + if (subcodecounter <= 0) { + if ((cdrom_flags & CDFLAG_SUBCODE) && subcodebufferoffset != subcodebufferoffsetw) { + uae_sem_wait (&sub_sem); + if (subcodebufferinuse[subcodebufferoffset]) { + if (cdrom_subcodeoffset >= 128) + cdrom_subcodeoffset = 0; + else + cdrom_subcodeoffset = 128; + // 96 byte subchannel data + for (int i = 0; i < SUB_CHANNEL_SIZE; i++) + put_byte (subcode_address + cdrom_subcodeoffset + i, subcodebuffer[subcodebufferoffset * SUB_CHANNEL_SIZE + i]); + put_long (subcode_address + cdrom_subcodeoffset + SUB_CHANNEL_SIZE, 0xffffffff); + subcodebufferinuse[subcodebufferoffset] = 0; + cdrom_subcodeoffset += 100; + subcodebufferoffset++; + if (subcodebufferoffset >= MAX_SUBCODEBUFFER) + subcodebufferoffset -= MAX_SUBCODEBUFFER; + set_status (CDINTERRUPT_SUBCODE); } + uae_sem_post (&sub_sem); } + subcodecounter = 1000000 / (70 * 75 * cdrom_speed); } if (frame2counter > 0) @@ -1248,17 +1279,12 @@ void AKIKO_hsync_handler (void) if (mediacheckcounter > 0) mediacheckcounter--; - if (cdrom_playing) { - if (cdrom_audiotimeout > 0) { - cdrom_audiotimeout--; - if (cdrom_audiotimeout == 0) { - set_status (CDINTERRUPT_RXDMADONE); - cdrom_playing = 0; - cdrom_result_buffer[1] = 0; - cdrom_start_return_data (2); - } - } + if (cdrom_audiotimeout > 0) { + cdrom_audiotimeout--; + if (cdrom_audiotimeout == 0) + cdrom_audiotimeout = -1; } + akiko_internal (); akiko_handler (); } @@ -1300,20 +1326,16 @@ static void *akiko_thread (void *null) } if (frame2counter <= 0) { - uae_u8 *s; frame2counter = 312 * 50 / 2; - s = sys_command_cd_qcode (DF_IOCTL, unitnum); - if (s) { - uae_u8 as = s[1]; - memcpy (qcode_buf, s, sizeof qcode_buf); + if (sys_command_cd_qcode (DF_IOCTL, unitnum, qcode_buf)) { + uae_u8 as = qcode_buf[1]; qcode_valid = 1; if (as == AUDIO_STATUS_IN_PROGRESS) { - int lsn = msf2lsn ((s[5 + 4] << 16) | (s[6 + 4] << 8) | (s[7 + 4] << 0)); - //write_log("%d %d (%d %d)\n", lsn, msf2lsn (last_play_end) - lsn, cdrom_leadout, msf2lsn (last_play_end)); + frame2counter /= 4; + int lsn = msf2lsn (fromlongbcd (qcode_buf + 4 + 7)); // make sure audio play really ends because not all drives report position accurately - if ((lsn >= cdrom_leadout - 3 * 75 || lsn >= msf2lsn(last_play_end) - 3 * 75) && !cdrom_audiotimeout) { + if ((lsn >= cdrom_toc_cd_buffer.lastaddress - 3 * 75 || lsn >= last_play_end - 3 * 75) && cdrom_audiotimeout == 0) { cdrom_audiotimeout = 3 * 312; - //write_log("audiotimeout starts\n"); } } } @@ -1323,11 +1345,13 @@ static void *akiko_thread (void *null) mediacheckcounter = 312 * 50 * 2; int media = sys_command_ismedia (DF_IOCTL, unitnum, 1); if (media < 0) { - cd_hunt = 1; - write_log (L"CD32: device unit %d lost\n", unitnum); - media = lastmediastate = cdrom_disk = 0; - mediachanged = 1; - cdaudiostop_do (); + 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 (); + } } else if (media != lastmediastate) { write_log (L"CD32: media changed = %d (hunt=%d)\n", media, cd_hunt); lastmediastate = cdrom_disk = media; @@ -1353,7 +1377,7 @@ static void *akiko_thread (void *null) while (offset < SECTOR_BUFFER_SIZE) { p = 0; if (sector < cdrom_data_end) - p = sys_command_cd_read (DF_IOCTL, unitnum, sector); + 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; @@ -1626,6 +1650,12 @@ static void akiko_bput2 (uaecptr addr, uae_u32 v, int msg) cdrom_sector_counter = 0; if (!(cdrom_flags & CDFLAG_PBX) && (tmp & CDFLAG_PBX)) cdrom_pbx = 0; + if ((cdrom_flags & CDFLAG_SUBCODE) && !(tmp & CDFLAG_SUBCODE)) { + uae_sem_wait (&sub_sem); + memset (subcodebufferinuse, 0, sizeof subcodebufferinuse); + subcodebufferoffset = subcodebufferoffsetw = 0; + uae_sem_post (&sub_sem); + } break; } else if (addr < 0x30) { break; @@ -1737,7 +1767,7 @@ int akiko_init (void) { if (currprefs.cs_cd32cd && cdromok == 0) { unitnum = -1; - if (!device_func_init (DEVICE_TYPE_ANY)) { + if (!device_func_init (DEVICE_TYPE_IOCTL)) { write_log (L"no CDROM support\n"); return 0; } @@ -1752,6 +1782,7 @@ int akiko_init (void) } } uae_sem_init (&akiko_sem, 0, 1); + uae_sem_init (&sub_sem, 0, 1); if (!savestate_state) { cdrom_playing = cdrom_paused = 0; cdrom_data_offset = -1; @@ -1808,16 +1839,16 @@ uae_u8 *save_akiko (int *len) save_u32 ((cdrom_playing ? 1 : 0) | (cdrom_paused ? 2 : 0) | (cdrom_disk ? 4 : 0)); if (cdrom_playing) cd_qcode (0); - save_u32 (last_play_pos); - save_u32 (last_play_end); + save_u32 (lsn2msf (last_play_pos)); + save_u32 (lsn2msf (last_play_end)); save_u8 ((uae_u8)cdrom_toc_counter); save_u8 (cdrom_speed); save_u8 (cdrom_current_sector); save_u32 (cdrom_toc_crc); - save_u8 (cdrom_toc_entries); - save_u32 (cdrom_leadout); + save_u8 (cdrom_toc_cd_buffer.points); + save_u32 (cdrom_toc_cd_buffer.lastaddress); *len = dst - dstbak; return dstbak; @@ -1876,8 +1907,8 @@ uae_u8 *restore_akiko (uae_u8 *src) if (v & 2) cdrom_paused = 1; - last_play_pos = restore_u32 (); - last_play_end = restore_u32 (); + last_play_pos = msf2lsn (restore_u32 ()); + last_play_end = msf2lsn (restore_u32 ()); cdrom_toc_counter = (uae_s8)restore_u8 (); cdrom_speed = restore_u8 (); cdrom_current_sector = (uae_s8)restore_u8 (); @@ -1895,7 +1926,7 @@ void restore_akiko_finish (void) return; akiko_init (); akiko_c2p_do (); - cdrom_toc (); + get_cdrom_toc (); write_comm_pipe_u32 (&requests, 0x0102, 1); // pause write_comm_pipe_u32 (&requests, 0x0104, 1); // stop write_comm_pipe_u32 (&requests, 0x0103, 1); // unpause diff --git a/audio.cpp b/audio.cpp index d5ed42bc..3179ba03 100644 --- a/audio.cpp +++ b/audio.cpp @@ -64,7 +64,7 @@ static bool debugchannel (int ch) STATIC_INLINE bool usehacks (void) { - return currprefs.cpu_model >= 68020 && !currprefs.cpu_cycle_exact; + return currprefs.cpu_model >= 68020 || currprefs.m68k_speed != -1; } #define SINC_QUEUE_MAX_AGE 2048 @@ -1237,12 +1237,15 @@ static void audio_state_channel2 (int nr, bool perfin) } audio_activate (); - if ((cdp->state == 2 || cdp->state == 3) && (currprefs.cpu_model >= 68020 || currprefs.m68k_speed != 0) && !chan_ena && old_dma) { + if ((cdp->state == 2 || cdp->state == 3) && usehacks () && !chan_ena && old_dma) { // DMA switched off, state=2/3 and "too fast CPU": kill DMA instantly // or CPU timed DMA wait routines in common tracker players will lose notes #ifdef DEBUG_AUDIO write_log (L"%d: INSTADMAOFF\n", nr, M68K_GETPC); #endif + newsample (nr, (cdp->dat2 >> 0) & 0xff); + if (napnav) + setirq (nr, 91); zerostate (nr); return; } @@ -1258,10 +1261,18 @@ static void audio_state_channel2 (int nr, bool perfin) if (chan_ena) { cdp->evtime = MAX_EV; cdp->state = 1; - cdp->dsr = true; cdp->dr = true; cdp->drhpos = hpos; cdp->wlen = cdp->len; + // too fast CPU and some tracker players: enable DMA, CPU delay, update AUDxPT with loop position + if (usehacks ()) { + // copy AUDxPT - 2 to internal latch instantly + cdp->pt = cdp->lc - 2; + cdp->dsr = false; + } else { + // normal hardware behavior: latch it after first DMA fetch comes + cdp->dsr = true; + } #ifdef TEST_AUDIO cdp->have_dat = false; #endif @@ -1273,7 +1284,7 @@ static void audio_state_channel2 (int nr, bool perfin) cdp->state = 2; setirq (nr, 0); loaddat (nr); - if (currprefs.cpu_model >= 68020 && !currprefs.cpu_cycle_exact && cdp->per < 10 * CYCLE_UNIT) { + if (usehacks () && cdp->per < 10 * CYCLE_UNIT) { // make sure audio.device AUDxDAT startup returns to idle state before DMA is enabled newsample (nr, (cdp->dat2 >> 0) & 0xff); zerostate (nr); diff --git a/blkdev.cpp b/blkdev.cpp index a4bd8b6d..5369750e 100644 --- a/blkdev.cpp +++ b/blkdev.cpp @@ -14,11 +14,51 @@ #include "scsidev.h" #include "savestate.h" +static int scsiemu; + static struct device_functions *device_func[2]; static int have_ioctl; static int openlist[MAX_TOTAL_DEVICES]; static int forcedunit = -1; +/* convert minutes, seconds and frames -> logical sector number */ +int msf2lsn (int msf) +{ + int sector = (((msf >> 16) & 0xff) * 60 * 75 + ((msf >> 8) & 0xff) * 75 + ((msf >> 0) & 0xff)); + sector -= 150; + return sector; +} + +/* convert logical sector number -> minutes, seconds and frames */ +int lsn2msf (int sectors) +{ + int msf; + sectors += 150; + msf = (sectors / (75 * 60)) << 16; + msf |= ((sectors / 75) % 60) << 8; + msf |= (sectors % 75) << 0; + return msf; +} + +uae_u8 frombcd (uae_u8 v) +{ + return (v >> 4) * 10 + (v & 15); +} +uae_u8 tobcd (uae_u8 v) +{ + return ((v / 10) << 4) | (v % 10); +} +int fromlongbcd (uae_u8 *p) +{ + return (frombcd (p[0]) << 16) | (frombcd (p[1]) << 8) | (frombcd (p[2]) << 0); +} +void tolongbcd (uae_u8 *p, int v) +{ + p[0] = tobcd ((v >> 16) & 0xff); + p[1] = tobcd ((v >> 8) & 0xff); + p[2] = tobcd ((v >> 0) & 0xff); +} + #ifdef _WIN32 #include "od-win32/win32.h" @@ -30,26 +70,29 @@ extern struct device_functions devicefunc_cdimage; static void install_driver (int flags) { - int installed = 0; - + scsiemu = 0; device_func[DF_IOCTL] = NULL; - device_func[DF_SCSI] = &devicefunc_win32_aspi; + device_func[DF_SCSI] = NULL; if (devicefunc_cdimage.checkbus (flags | DEVICE_TYPE_CHECKAVAIL)) { device_func[DF_IOCTL] = &devicefunc_cdimage; - device_func[DF_SCSI] = NULL; + device_func[DF_SCSI] = &devicefunc_cdimage; + scsiemu = 1; return; } #ifdef WINDDK if (!device_func[DF_IOCTL]) device_func[DF_IOCTL] = &devicefunc_win32_ioctl; - device_func[DF_SCSI] = &devicefunc_win32_spti; - installed = 1; - if (currprefs.win32_uaescsimode == UAESCSI_ADAPTECASPI || - currprefs.win32_uaescsimode == UAESCSI_NEROASPI || - currprefs.win32_uaescsimode == UAESCSI_FROGASPI || - !installed) { - device_func[DF_SCSI] = &devicefunc_win32_aspi; - device_func[DF_IOCTL] = 0; + 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; + } } #endif if (device_func[DF_SCSI]) @@ -108,8 +151,20 @@ void device_func_reset (void) int device_func_init (int flags) { + static int old_flags = -1; int support_scsi = 0, support_ioctl = 0; - int oflags = (flags & DEVICE_TYPE_SCSI) ? 0 : (1 << INQ_ROMD); + int oflags; + + if (flags & DEVICE_TYPE_USE_OLD) { + if (old_flags >= 0) + flags = old_flags; + else + flags &= ~DEVICE_TYPE_USE_OLD; + } + + old_flags = flags; + + oflags = (flags & DEVICE_TYPE_SCSI) ? 0 : (1 << INQ_ROMD); forcedunit = -1; install_driver (flags); @@ -119,8 +174,12 @@ int device_func_init (int flags) have_ioctl = 0; if (flags & DEVICE_TYPE_ALLOWEMU) oflags |= DEVICE_TYPE_ALLOWEMU; - if (device_func[DF_SCSI]) - support_scsi = device_func[DF_SCSI]->openbus (oflags) ? 1 : 0; + 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; @@ -165,8 +224,36 @@ void sys_command_cd_stop (int mode, int unitnum) device_func[DF_IOCTL]->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)) + 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)) + break; + int track = frombcd (q[4 + 1]); + int idx = frombcd (q[4 + 2]); + //write_log (L"%d %d\n", track, idx); + if (idx != 0 || otrack != track) + break; + startlsn--; + } + if (lsn != startlsn) + write_log (L"CD play adjust %d -> %d\n", lsn, startlsn); + startlsn -= 10; + if (startlsn < 0) + startlsn = 0; + return startlsn; +} +#endif + /* play CD audio */ -int sys_command_cd_play (int mode, int unitnum,uae_u32 startmsf, uae_u32 endmsf, int scan) +int sys_command_cd_play (int mode, int unitnum, int startlsn, int endlsn, int scan) { if (mode == DF_SCSI || !have_ioctl) { uae_u8 cmd[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; @@ -180,6 +267,8 @@ int sys_command_cd_play (int mode, int unitnum,uae_u32 startmsf, uae_u32 endmsf, 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); @@ -192,7 +281,17 @@ int sys_command_cd_play (int mode, int unitnum,uae_u32 startmsf, uae_u32 endmsf, #endif return device_func[DF_SCSI]->exec_out (unitnum, cmd, sizeof (cmd)) == 0 ? 0 : 1; } - return device_func[DF_IOCTL]->play (unitnum, startmsf, endmsf, scan); + //startlsn = adjustplaypos (unitnum, startlsn); + return device_func[DF_IOCTL]->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) +{ + if (mode == DF_SCSI || !have_ioctl) + return 0; + //startlsn = adjustplaypos (unitnum, startlsn); + return device_func[DF_IOCTL]->play (unitnum, startlsn, endlsn, scan, subfunc); } /* set CD audio volume */ @@ -204,68 +303,83 @@ void sys_command_cd_volume (int mode, int unitnum, uae_u16 volume) } /* read qcode */ -uae_u8 *sys_command_cd_qcode (int mode, int unitnum) +int sys_command_cd_qcode (int mode, 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}; - return device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof (cmd), 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; } - return device_func[DF_IOCTL]->qcode (unitnum); + return device_func[DF_IOCTL]->qcode (unitnum, buf, -1); }; /* read table of contents */ -uae_u8 *sys_command_cd_toc (int mode, int unitnum) +struct cd_toc_head *sys_command_cd_toc (int mode, int unitnum) { 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 device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof(cmd), 0); + return NULL; +// return device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof(cmd), 0); } return device_func[DF_IOCTL]->toc (unitnum); } /* read one cd sector */ -uae_u8 *sys_command_cd_read (int mode, int unitnum, int offset) +uae_u8 *sys_command_cd_read (int mode, 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)(offset >> 16); - cmd[4] = (uae_u8)(offset >> 8); - cmd[5] = (uae_u8)(offset >> 0); - return device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof (cmd), 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; } - return device_func[DF_IOCTL]->read (unitnum, offset); + return device_func[DF_IOCTL]->read (unitnum, data, block, size); } -uae_u8 *sys_command_cd_rawread (int mode, int unitnum, int offset, int size) +uae_u8 *sys_command_cd_rawread (int mode, int unitnum, uae_u8 *data, int sector, int size, int sectorsize) { 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)(offset >> 16); - cmd[4] = (uae_u8)(offset >> 8); - cmd[5] = (uae_u8)(offset >> 0); - return device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof (cmd), 0); + 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; } - return device_func[DF_IOCTL]->rawread (unitnum, offset, size); + return device_func[DF_IOCTL]->rawread (unitnum, data, sector, size, sectorsize); } /* read block */ -uae_u8 *sys_command_read (int mode, int unitnum, int offset) +uae_u8 *sys_command_read (int mode, 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 }; - cmd[2] = (uae_u8)(offset >> 24); - cmd[3] = (uae_u8)(offset >> 16); - cmd[4] = (uae_u8)(offset >> 8); - cmd[5] = (uae_u8)(offset >> 0); - return device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof (cmd), 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 device_func[DF_IOCTL]->read (unitnum, offset); + return device_func[DF_IOCTL]->read (unitnum, data, block, size); } /* write block */ -int sys_command_write (int mode, int unitnum, int offset) +int sys_command_write (int mode, 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, 1, 0 }; + 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); @@ -274,7 +388,7 @@ int sys_command_write (int mode, int unitnum, int offset) return -1; return 0; } - return device_func[DF_IOCTL]->write (unitnum, offset); + return device_func[DF_IOCTL]->write (unitnum, data, offset, size); } int sys_command_ismedia (int mode, int unitnum, int quick) @@ -290,7 +404,7 @@ int sys_command_ismedia (int mode, int unitnum, int quick) if (quick) return -1; memset(&di, 0, sizeof di); - if (device_func[DF_SCSI]->info (unitnum, &di) == NULL) + if (device_func[DF_SCSI]->info (unitnum, &di, quick) == NULL, quick) return -1; return di.media_inserted; } else { @@ -298,12 +412,12 @@ int sys_command_ismedia (int mode, int unitnum, int quick) } } -struct device_info *sys_command_info (int mode, int unitnum, struct device_info *di) +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); + return device_func[DF_SCSI]->info (unitnum, di, quick); else - return device_func[DF_IOCTL]->info (unitnum, di); + 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) @@ -403,50 +517,6 @@ static void scsi_atapi_fixup_inquiry (struct amigascsi *as) } } -int sys_command_scsi_direct_native(int unitnum, struct amigascsi *as) -{ - int ret = device_func[DF_SCSI]->exec_direct (unitnum, as); - if (!ret && device_func[DF_SCSI]->isatapi(unitnum)) - scsi_atapi_fixup_inquiry (as); - return ret; -} - -int sys_command_scsi_direct (int unitnum, uaecptr acmd) -{ - int ret, i; - struct amigascsi as; - uaecptr ap; - addrbank *bank; - - ap = get_long (acmd + 0); - as.len = get_long (acmd + 4); - - bank = &get_mem_bank (ap); - if (!bank || !bank->check(ap, as.len)) - return -5; - as.data = bank->xlateaddr (ap); - - ap = get_long (acmd + 12); - as.cmd_len = get_word (acmd + 16); - for (i = 0; i < as.cmd_len; i++) - as.cmd[i] = get_byte (ap++); - as.flags = get_byte (acmd + 20); - as.sense_len = get_word (acmd + 26); - - ret = sys_command_scsi_direct_native (unitnum, &as); - - put_long (acmd + 8, as.actual); - put_word (acmd + 18, as.cmdactual); - put_byte (acmd + 21, as.status); - put_word (acmd + 28, as.sactual); - - ap = get_long (acmd + 22); - for (i = 0; i < as.sactual; i++) - put_byte (ap, as.sensedata[i]); - - return ret; -} - void scsi_log_before (uae_u8 *cdb, int cdblen, uae_u8 *data, int datalen) { int i; @@ -510,3 +580,457 @@ uae_u8 *restore_cd (int unit, uae_u8 *src) return src; } +static bool nodisk (struct device_info *di) +{ + return di->media_inserted == 0; +} +static uae_u64 cmd_readx (int unitnum, uae_u8 *dataptr, int offset, int len) +{ + if (device_func[DF_IOCTL]->read (unitnum, dataptr, offset, len)) + return len; + else + return 0; +} + +static void wl (uae_u8 *p, int v) +{ + p[0] = v >> 24; + p[1] = v >> 16; + p[2] = v >> 8; + p[3] = v; +} +static void ww (uae_u8 *p, int v) +{ + p[0] = v >> 8; + p[1] = v; +} +static int rl (uae_u8 *p) +{ + return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); +} + +static struct cd_toc *gettoc (struct device_info *di, int block) +{ + 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; + } + } + return &di->toc.toc[di->toc.last_track_offset]; +} + +static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, + uae_u8 *scsi_data, int *data_len, uae_u8 *r, int *reply_len, uae_u8 *s, int *sense_len) +{ + uae_u64 len, offset; + 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); + + if (cmdbuf[0] == 0) { /* TEST UNIT READY */ + if (nodisk (&di)) + goto nodisk; + scsi_len = 0; + goto end; + } + + switch (cmdbuf[0]) + { + case 0x12: /* INQUIRY */ + if ((cmdbuf[1] & 1) || cmdbuf[2] != 0) + goto err; + len = cmdbuf[4]; + if (cmdbuf[1] >> 5) + goto err; + r[0] = 5; // CDROM + r[1] |= 0x80; // removable + r[2] = 2; /* supports SCSI-2 */ + r[3] = 2; /* response data format */ + r[4] = 32; /* additional length */ + r[7] = 0x20; /* 16 bit bus */ + 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++; + } + break; + 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; + 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; + case 0x1d: /* SEND DIAGNOSTICS */ + scsi_len = 0; + break; + case 0x25: /* READ_CAPACITY */ + { + int pmi = cmdbuf[8] & 1; + uae_u32 lba = (cmdbuf[2] << 24) | (cmdbuf[3] << 16) | (cmdbuf[4] << 8) | cmdbuf[5]; + int cyl, cylsec, head, tracksec; + if (nodisk (&di)) + goto nodisk; + uae_u32 blocks = di.sectorspertrack * di.cylinders * di.trackspercylinder; + cyl = di.cylinders; + head = 1; + cylsec = tracksec = di.trackspercylinder; + if (pmi == 0 && lba != 0) + goto errreq; + if (pmi) { + lba += tracksec * head; + lba /= tracksec * head; + lba *= tracksec * head; + if (lba > blocks) + lba = blocks; + blocks = lba; + } + wl (r, blocks); + wl (r + 4, di.bytespersector); + scsi_len = lr = 8; + } + break; + case 0x08: /* READ (6) */ + { + if (nodisk (&di)) + goto nodisk; + offset = ((cmdbuf[1] & 31) << 16) | (cmdbuf[2] << 8) | cmdbuf[3]; + struct cd_toc *t = gettoc (&di, offset); + if ((t->control & 0x0c) == 0x04) { + len = cmdbuf[4]; + if (!len) + len = 256; + scsi_len = (uae_u32)cmd_readx (unitnum, scsi_data, offset, len) * di.bytespersector;; + } else { + goto notdatatrack; + } + } + break; + case 0x0a: /* WRITE (6) */ + goto readprot; + case 0x28: /* READ (10) */ + { + if (nodisk (&di)) + goto nodisk; + offset = rl (cmdbuf + 2); + struct cd_toc *t = gettoc (&di, offset); + if ((t->control & 0x0c) == 0x04) { + len = rl (cmdbuf + 7 - 2) & 0xffff; + scsi_len = cmd_readx (unitnum, scsi_data, offset, len) * di.bytespersector; + } else { + goto notdatatrack; + } + } + break; + case 0x2a: /* WRITE (10) */ + goto readprot; + case 0xa8: /* READ (12) */ + { + if (nodisk (&di)) + goto nodisk; + offset = rl (cmdbuf + 2); + struct cd_toc *t = gettoc (&di, offset); + if ((t->control & 0x0c) == 0x04) { + len = rl (cmdbuf + 6); + scsi_len = (uae_u32)cmd_readx (unitnum, scsi_data, offset, len) * di.bytespersector;; + } else { + goto notdatatrack; + } + } + break; + case 0xaa: /* WRITE (12) */ + goto readprot; + case 0x43: // READ TOC + { + uae_u8 *p = scsi_data; + int strack = cmdbuf[6]; + int msf = cmdbuf[1] & 2; + int maxlen = (cmdbuf[7] << 8) | cmdbuf[8]; + struct cd_toc_head *toc = sys_command_cd_toc (DF_IOCTL, unitnum); + if (!toc) + goto readerr; + 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) + 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; + } + } + int tlen = p2 - (p + 4); + p[0] = tlen >> 8; + p[1] = tlen >> 0; + scsi_len = tlen + 4; + } + break; +readprot: + status = 2; /* CHECK CONDITION */ + s[0] = 0x70; + s[2] = 7; /* DATA PROTECT */ + s[12] = 0x27; /* WRITE PROTECTED */ + ls = 12; + break; +nodisk: + status = 2; /* CHECK CONDITION */ + s[0] = 0x70; + s[2] = 2; /* NOT READY */ + s[12] = 0x3A; /* MEDIUM NOT PRESENT */ + ls = 12; + break; +readerr: + status = 2; /* CHECK CONDITION */ + s[0] = 0x70; + s[2] = 2; /* NOT READY */ + s[12] = 0x11; /* UNRECOVERED READ ERROR */ + ls = 12; + break; +notdatatrack: + status = 2; + s[0] = 0x70; + s[2] = 5; + s[12] = 0x64; /* ILLEGAL MODE FOR THIS TRACK */ + ls = 12; + break; + + default: +err: + write_log (L"CDEMU: unsupported scsi command 0x%02X\n", cmdbuf[0]); +errreq: + lr = -1; + status = 2; /* CHECK CONDITION */ + s[0] = 0x70; + s[2] = 5; /* ILLEGAL REQUEST */ + s[12] = 0x24; /* ILLEGAL FIELD IN CDB */ + ls = 12; + break; + } +end: + *data_len = scsi_len; + *reply_len = lr; + *sense_len = ls; + return status; +} + +static int execscsicmd_direct (int unitnum, struct amigascsi *as) +{ + int sactual = 0; + 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 replydata[256]; + int datalen = as->len; + int senselen = as->sense_len; + int replylen = 0; + + memcpy (cmd, as->cmd, as->cmd_len); + scsi_datap = scsi_datap_org = as->len ? as->data : 0; + if (as->sense_len > 32) + as->sense_len = 32; + + as->status = scsi_emulate (unitnum, cmd, as->cmd_len, scsi_datap, &datalen, replydata, &replylen, as->sensedata, &senselen); + + as->cmdactual = as->status == 0 ? 0 : as->cmd_len; /* fake scsi_CmdActual */ + if (as->status) { + io_error = 45; /* HFERR_BadStatus */ + as->sense_len = senselen; + as->actual = 0; /* scsi_Actual */ + } else { + int i; + if (replylen > 0) { + for (i = 0; i < replylen; i++) + scsi_datap[i] = replydata[i]; + datalen = replylen; + } + for (i = 0; i < as->sense_len; i++) + as->sensedata[i] = 0; + sactual = 0; + if (datalen < 0) { + io_error = 20; /* io_Error, but not specified */ + as->actual = 0; /* scsi_Actual */ + } else { + as->len = datalen; + io_error = 0; + as->actual = as->len; /* scsi_Actual */ + } + } + as->sactual = sactual; + + return io_error; +} + +int sys_command_scsi_direct_native (int unitnum, struct amigascsi *as) +{ + if (scsiemu) { + return execscsicmd_direct (unitnum, as); + } else { + if (!device_func[DF_SCSI] || !device_func[DF_SCSI]->exec_direct) + return -1; + } + int ret = device_func[DF_SCSI]->exec_direct (unitnum, as); + if (!ret && device_func[DF_SCSI]->isatapi(unitnum)) + scsi_atapi_fixup_inquiry (as); + return ret; +} + +int sys_command_scsi_direct (int unitnum, uaecptr acmd) +{ + int ret, i; + struct amigascsi as; + uaecptr ap; + addrbank *bank; + + ap = get_long (acmd + 0); + as.len = get_long (acmd + 4); + + bank = &get_mem_bank (ap); + if (!bank || !bank->check(ap, as.len)) + return -5; + as.data = bank->xlateaddr (ap); + + ap = get_long (acmd + 12); + as.cmd_len = get_word (acmd + 16); + for (i = 0; i < as.cmd_len; i++) + as.cmd[i] = get_byte (ap++); + as.flags = get_byte (acmd + 20); + as.sense_len = get_word (acmd + 26); + + ret = sys_command_scsi_direct_native (unitnum, &as); + + put_long (acmd + 8, as.actual); + put_word (acmd + 18, as.cmdactual); + put_byte (acmd + 21, as.status); + put_word (acmd + 28, as.sactual); + + ap = get_long (acmd + 22); + for (i = 0; i < as.sactual; i++) + put_byte (ap, as.sensedata[i]); + + return ret; +} diff --git a/blkdev_cdimage.cpp b/blkdev_cdimage.cpp index afe857a9..1d0396a0 100644 --- a/blkdev_cdimage.cpp +++ b/blkdev_cdimage.cpp @@ -16,10 +16,14 @@ #include "fsdb.h" #include "threaddep/thread.h" #include "scsidev.h" +#include +#include #ifdef RETROPLATFORM #include "rp.h" #endif +#define scsi_log write_log + #define USE 1 #define CDDA_BUFFERS 6 @@ -35,63 +39,59 @@ struct cdtoc { struct zfile *handle; int offset; - int filesize; uae_u8 *data; + struct zfile *subhandle; + int suboffset; + uae_u8 *subdata; + + int filesize; TCHAR *fname; int address; uae_u8 adr, ctrl; int track; int size; int mp3; + int subcode; }; -static uae_u8 buffer[2352]; -static struct cdtoc toc[102]; -static int tracks; -static uae_u64 cdsize; - -static int cdda_play_finished; -static int cdda_play; -static int cdda_paused; -static int cdda_volume; -static int cdda_volume_main; -static uae_u32 cd_last_pos; -static int cdda_start, cdda_end; - -static int imagechange; -static int donotmountme; -static TCHAR newfile[MAX_DPATH]; - -/* convert minutes, seconds and frames -> logical sector number */ -static int msf2lsn (int msf) -{ - int sector = (((msf >> 16) & 0xff) * 60 * 75 + ((msf >> 8) & 0xff) * 75 + ((msf >> 0) & 0xff)); - sector -= 150; - return sector; -} +struct cdunit { + bool enabled; + uae_u8 buffer[2352]; + struct cdtoc toc[102]; + int tracks; + uae_u64 cdsize; + int blocksize; + + int cdda_play_finished; + int cdda_play; + int cdda_paused; + int cdda_volume; + int cdda_volume_main; + int cd_last_pos; + int cdda_start, cdda_end; + play_subchannel_callback cdda_subfunc; + + int imagechange; + int donotmountme; + TCHAR newfile[MAX_DPATH]; + uae_sem_t sub_sem; +}; -/* convert logical sector number -> minutes, seconds and frames */ -static int lsn2msf (int sectors) -{ - int msf; - sectors += 150; - msf = (sectors / (75 * 60)) << 16; - msf |= ((sectors / 75) % 60) << 8; - msf |= (sectors % 75) << 0; - return msf; -} +static struct cdunit cdunits[MAX_TOTAL_DEVICES]; -static struct cdtoc *findtoc (int *sectorp) +static struct cdtoc *findtoc (struct cdunit *cdu, int *sectorp) { int i; int sector; sector = *sectorp; - for (i = 0; i <= tracks; i++) { - struct cdtoc *t = &toc[i]; + for (i = 0; i <= cdu->tracks; i++) { + struct cdtoc *t = &cdu->toc[i]; if (t->address > sector) { - if (i == 0) - return NULL; + if (i == 0) { + *sectorp = 0; + return t; + } t--; sector -= t->address; *sectorp = sector; @@ -101,216 +101,8 @@ static struct cdtoc *findtoc (int *sectorp) return NULL; } - -static int mp3_bitrates[] = { - 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1, - 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, -1, - 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1, - 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -1, - 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 -}; -static int mp3_frequencies[] = { - 44100, 48000, 32000, 0, - 22050, 24000, 16000, 0, - 11025, 12000, 8000, 0 -}; -static int mp3_samplesperframe[] = { - 384, 384, 384, - 1152, 1152, 1152, - 1152, 576, 576 -}; - -static uae_u32 mp3decoder_getsize (struct zfile *zf) -{ - uae_u32 size; - int frames; - - frames = 0; - size = 0; - for (;;) { - int ver, layer, bitrate, freq, padding, bitindex, iscrc; - int samplerate, framelen, bitrateidx, channelmode; - int isstereo; - uae_u8 header[4]; - - if (zfile_fread (header, sizeof header, 1, zf) != 1) - return size; - if (header[0] != 0xff || ((header[1] & (0x80 | 0x40 | 0x20)) != (0x80 | 0x40 | 0x20))) { - zfile_fseek (zf, -3, SEEK_CUR); - continue; - } - ver = (header[1] >> 3) & 3; - if (ver == 1) - return 0; - if (ver == 0) - ver = 2; - else if (ver == 2) - ver = 1; - else if (ver == 3) - ver = 0; - layer = 4 - ((header[1] >> 1) & 3); - if (layer == 4) - return 0; - iscrc = ((header[1] >> 0) & 1) ? 0 : 2; - bitrateidx = (header[2] >> 4) & 15; - freq = mp3_frequencies[(header[2] >> 2) & 3]; - if (!freq) - return 0; - channelmode = (header[3] >> 6) & 3; - isstereo = channelmode != 3; - if (ver == 0) { - bitindex = layer - 1; - } else { - if (layer == 1) - bitindex = 3; - else - bitindex = 4; - } - bitrate = mp3_bitrates[bitindex * 16 + bitrateidx] * 1000; - if (bitrate <= 0) - return 0; - padding = (header[2] >> 1) & 1; - samplerate = mp3_samplesperframe[(layer - 1) * 3 + ver]; - framelen = ((samplerate / 8 * bitrate) / freq) + padding; - if (framelen <= 4) - return 0; - zfile_fseek (zf, framelen + iscrc - 4, SEEK_CUR); - frames++; - size += samplerate * 2 * (isstereo ? 2 : 1); - } - return size; -} - #ifdef _WIN32 -#include -#include -#include - -#define MP3_BLOCK_SIZE 522 - -static HACMSTREAM g_mp3stream = NULL; - -static void mp3decoder_close (void) -{ - if (g_mp3stream) - acmStreamClose (g_mp3stream, 0); - g_mp3stream = NULL; -} - -static int mp3decoder_open (void) -{ - MMRESULT mmr; - LPWAVEFORMATEX waveFormat; - LPMPEGLAYER3WAVEFORMAT mp3format; - DWORD maxFormatSize; - - if (g_mp3stream) - return 1; - - // find the biggest format size - maxFormatSize = 0; - mmr = acmMetrics (NULL, ACM_METRIC_MAX_SIZE_FORMAT, &maxFormatSize); - - // define desired output format - waveFormat = (LPWAVEFORMATEX) LocalAlloc( LPTR, maxFormatSize ); - waveFormat->wFormatTag = WAVE_FORMAT_PCM; - waveFormat->nChannels = 2; // stereo - waveFormat->nSamplesPerSec = 44100; // 44.1kHz - waveFormat->wBitsPerSample = 16; // 16 bits - waveFormat->nBlockAlign = 4; // 4 bytes of data at a time are useful (1 sample) - waveFormat->nAvgBytesPerSec = 4 * 44100; // byte-rate - waveFormat->cbSize = 0; // no more data to follow - - // define MP3 input format - mp3format = (LPMPEGLAYER3WAVEFORMAT) LocalAlloc( LPTR, maxFormatSize ); - mp3format->wfx.cbSize = MPEGLAYER3_WFX_EXTRA_BYTES; - mp3format->wfx.wFormatTag = WAVE_FORMAT_MPEGLAYER3; - mp3format->wfx.nChannels = 2; - mp3format->wfx.nAvgBytesPerSec = 128 * (1024 / 8); // not really used but must be one of 64, 96, 112, 128, 160kbps - mp3format->wfx.wBitsPerSample = 0; // MUST BE ZERO - mp3format->wfx.nBlockAlign = 1; // MUST BE ONE - mp3format->wfx.nSamplesPerSec = 44100; // 44.1kHz - mp3format->fdwFlags = MPEGLAYER3_FLAG_PADDING_OFF; - mp3format->nBlockSize = MP3_BLOCK_SIZE; // voodoo value #1 - mp3format->nFramesPerBlock = 1; // MUST BE ONE - mp3format->nCodecDelay = 1393; // voodoo value #2 - mp3format->wID = MPEGLAYER3_ID_MPEG; - - mmr = acmStreamOpen( &g_mp3stream, // open an ACM conversion stream - NULL, // querying all ACM drivers - (LPWAVEFORMATEX) mp3format, // converting from MP3 - waveFormat, // to WAV - NULL, // with no filter - 0, // or async callbacks - 0, // (and no data for the callback) - 0 // and no flags - ); - - LocalFree (mp3format); - LocalFree (waveFormat); - if (mmr == MMSYSERR_NOERROR) - return 1; - write_log (L"CUEMP3: couldn't open ACM mp3 decoder, %d\n", mmr); - return 0; -} - -static uae_u8 *mp3decoder_get (struct zfile *zf, int maxsize) -{ - MMRESULT mmr; - unsigned long rawbufsize = 0; - LPBYTE mp3buf; - LPBYTE rawbuf; - uae_u8 *outbuf = NULL; - int outoffset = 0; - ACMSTREAMHEADER mp3streamHead; - - write_log (L"CUEMP3: decoding '%s'..\n", zfile_getname (zf)); - mmr = acmStreamSize (g_mp3stream, MP3_BLOCK_SIZE, &rawbufsize, ACM_STREAMSIZEF_SOURCE); - if (mmr != MMSYSERR_NOERROR) { - write_log (L"CUEMP3: acmStreamSize, %d\n", mmr); - return NULL; - } - // allocate our I/O buffers - mp3buf = (LPBYTE) LocalAlloc (LPTR, MP3_BLOCK_SIZE); - rawbuf = (LPBYTE) LocalAlloc (LPTR, rawbufsize); - - // prepare the decoder - ZeroMemory (&mp3streamHead, sizeof (ACMSTREAMHEADER)); - mp3streamHead.cbStruct = sizeof (ACMSTREAMHEADER); - mp3streamHead.pbSrc = mp3buf; - mp3streamHead.cbSrcLength = MP3_BLOCK_SIZE; - mp3streamHead.pbDst = rawbuf; - mp3streamHead.cbDstLength = rawbufsize; - mmr = acmStreamPrepareHeader (g_mp3stream, &mp3streamHead, 0); - if (mmr != MMSYSERR_NOERROR) { - write_log (L"CUEMP3: acmStreamPrepareHeader, %d\n", mmr); - return NULL; - } - zfile_fseek (zf, 0, SEEK_SET); - outbuf = xcalloc (uae_u8, maxsize); - for (;;) { - int count = zfile_fread (mp3buf, 1, MP3_BLOCK_SIZE, zf); - if (count != MP3_BLOCK_SIZE) - break; - // convert the data - mmr = acmStreamConvert (g_mp3stream, &mp3streamHead, ACM_STREAMCONVERTF_BLOCKALIGN); - if (mmr != MMSYSERR_NOERROR) { - write_log (L"CUEMP3: acmStreamConvert, %d\n", mmr); - return NULL; - } - if (outoffset + mp3streamHead.cbDstLengthUsed > maxsize) - break; - memcpy (outbuf + outoffset, rawbuf, mp3streamHead.cbDstLengthUsed); - outoffset += mp3streamHead.cbDstLengthUsed; - } - acmStreamUnprepareHeader (g_mp3stream, &mp3streamHead, 0); - LocalFree (rawbuf); - LocalFree (mp3buf); - write_log (L"CUEMP3: unpacked size %d bytes\n", outoffset); - return outbuf; -} - static HWAVEOUT cdda_wavehandle; static void cdda_closewav (void) @@ -320,8 +112,6 @@ static void cdda_closewav (void) cdda_wavehandle = NULL; } -// DAE CDDA based on Larry Osterman's "Playing Audio CDs" blog series - static int cdda_openwav (void) { WAVEFORMATEX wav = { 0 }; @@ -343,6 +133,90 @@ static int cdda_openwav (void) return 1; } +static int getsub (uae_u8 *dst, struct cdunit *cdu, struct cdtoc *t, int sector) +{ + int ret = 0; + uae_sem_wait (&cdu->sub_sem); + if (t->subcode) { + if (t->subhandle) { + zfile_fseek (t->subhandle, sector * SUB_CHANNEL_SIZE + t->suboffset, SEEK_SET); + if (zfile_fread (dst, SUB_CHANNEL_SIZE, 1, t->subhandle) > 0) + ret = t->subcode; + } else { + memcpy (dst, t->subdata + sector * SUB_CHANNEL_SIZE + t->suboffset, SUB_CHANNEL_SIZE); + ret = t->subcode; + } + } + if (!ret) { + memset (dst, 0, SUB_CHANNEL_SIZE); + // regenerate Q-subchannel + uae_u8 *s = dst + 12; + s[0] = (t->ctrl << 4) | (t->adr << 0); + s[1] = tobcd (t - &cdu->toc[0] + 1); + s[2] = tobcd (1); + int msf = lsn2msf (sector); + tolongbcd (s + 7, msf); + msf = lsn2msf (sector - t->address - 150); + tolongbcd (s + 3, msf); + ret = 2; + } + uae_sem_post (&cdu->sub_sem); + return ret; +} + +static void dosub (struct cdunit *cdu, struct cdtoc *t, int sector) +{ + uae_u8 *s, *d; + uae_u8 subbuf[SUB_CHANNEL_SIZE]; + uae_u8 subbuf2[SUB_CHANNEL_SIZE]; + + if (!cdu->cdda_subfunc) + return; + + if (!t) { + memset (subbuf, 0, sizeof subbuf); + cdu->cdda_subfunc (subbuf, 1); + return; + } + 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 + d = subbuf2; + + + } else { + d = subbuf; + } + cdu->cdda_subfunc (d, 1); +} + static void *cdda_play_func (void *v) { int cdda_pos; @@ -357,13 +231,16 @@ static void *cdda_play_func (void *v) MMRESULT mmr; int volume, volume_main; int oldplay; + mp3decoder *mp3dec = NULL; + struct cdunit *cdu = &cdunits[0]; + int firstloops; for (i = 0; i < 2; i++) { memset (&whdr[i], 0, sizeof (WAVEHDR)); whdr[i].dwFlags = WHDR_DONE; } - while (cdda_play == 0) + while (cdu->cdda_play == 0) Sleep (10); oldplay = -1; @@ -390,68 +267,84 @@ static void *cdda_play_func (void *v) whdr[i].dwFlags |= WHDR_DONE; } - while (cdda_play > 0) { + while (cdu->cdda_play > 0) { - if (oldplay != cdda_play) { + if (oldplay != cdu->cdda_play) { struct cdtoc *t; int sector; - cdda_pos = cdda_start; - oldplay = cdda_play; - - sector = cdda_start; - t = findtoc (§or); + cdda_pos = cdu->cdda_start; + oldplay = cdu->cdda_play; + cdu->cd_last_pos = cdda_pos; + sector = cdu->cdda_start; + t = findtoc (cdu, §or); if (!t) { - write_log (L"CDDA: illegal sector number %d\n", cdda_start); + write_log (L"CDDA: illegal sector number %d\n", cdu->cdda_start); } else { - write_log (L"CDDA: playing track %d (file '%s', offset %d, secoffset %d)\n", - t->track, t->fname, t->offset, sector); + write_log (L"CDDA: playing from %d to %d, track %d ('%s', offset %d, secoffset %d)\n", + cdu->cdda_start, cdu->cdda_end, t->track, t->fname, t->offset, sector); if (t->mp3 && !t->data) { - if (mp3decoder_open ()) { - t->data = mp3decoder_get (t->handle, t->filesize); + if (!mp3dec) { + try { + mp3dec = new mp3decoder(); + } catch (exception) { }; } + if (mp3dec) + t->data = mp3dec->get (t->handle, t->filesize); } } + firstloops = 25; } while (!(whdr[bufnum].dwFlags & WHDR_DONE)) { Sleep (10); - if (!cdda_play) + if (!cdu->cdda_play) goto end; } bufon[bufnum] = 0; - if ((cdda_pos < cdda_end || cdda_end == 0xffffffff) && !cdda_paused && cdda_play > 0) { + if ((cdda_pos < cdu->cdda_end || cdu->cdda_end == 0xffffffff) && !cdu->cdda_paused && cdu->cdda_play > 0) { struct cdtoc *t; int sector, cnt; int dofinish = 0; memset (px[bufnum], 0, num_sectors * 2352); - for (cnt = 0; cnt < num_sectors; cnt++) { - sector = cdda_pos; - - cdda_pos++; - if (cdda_pos - num_sectors < cdda_end && cdda_pos >= cdda_end) - dofinish = 1; - cd_last_pos = cdda_pos; - - t = findtoc (§or); - if (t) { - if (t->handle && !(t->ctrl & 4)) { - uae_u8 *dst = px[bufnum] + cnt * t->size; - if (t->mp3 && t->data) { - memcpy (dst, t->data + sector * t->size + t->offset, t->size); - } else if (!t->mp3) { - if (sector * t->size + t->offset + t->size < t->filesize) { - zfile_fseek (t->handle, sector * t->size + t->offset, SEEK_SET); - zfile_fread (dst, t->size, 1, t->handle); + + if (firstloops > 0) { + + firstloops--; + for (cnt = 0; cnt < num_sectors; cnt++) + dosub (cdu, NULL, -1); + + } else { + + for (cnt = 0; cnt < num_sectors; cnt++) { + sector = cdda_pos; + + cdda_pos++; + if (cdda_pos - num_sectors < cdu->cdda_end && cdda_pos >= cdu->cdda_end) + dofinish = 1; + + t = findtoc (cdu, §or); + if (t) { + if (t->handle && !(t->ctrl & 4)) { + uae_u8 *dst = px[bufnum] + cnt * t->size; + if (t->mp3 && t->data) { + memcpy (dst, t->data + sector * t->size + t->offset, t->size); + } else if (!t->mp3) { + if (sector * t->size + t->offset + t->size < t->filesize) { + zfile_fseek (t->handle, sector * t->size + t->offset, SEEK_SET); + zfile_fread (dst, t->size, 1, t->handle); + } } } + dosub (cdu, t, cdda_pos); } } + } - volume = cdda_volume; + volume = cdu->cdda_volume; volume_main = currprefs.sound_volume; int vol_mult = (100 - volume_main) * volume / 100; if (vol_mult) @@ -472,10 +365,12 @@ static void *cdda_play_func (void *v) break; } + cdu->cd_last_pos = cdda_pos; + if (dofinish) { - cdda_play_finished = 1; - cdda_play = -1; - cdda_pos = cdda_end + 1; + cdu->cdda_play_finished = 1; + cdu->cdda_play = -1; + cdda_pos = cdu->cdda_end + 1; } } @@ -484,7 +379,7 @@ static void *cdda_play_func (void *v) if (bufon[0] == 0 && bufon[1] == 0) { while (!(whdr[0].dwFlags & WHDR_DONE) || !(whdr[1].dwFlags & WHDR_DONE)) Sleep (10); - while (cdda_paused && cdda_play > 0) + while (cdu->cdda_paused && cdu->cdda_play > 0) Sleep (10); } @@ -501,124 +396,126 @@ end: cdda_closewav (); xfree (p); - cdda_play = 0; + delete mp3dec; + cdu->cdda_play = 0; write_log (L"CDDA: thread killed\n"); return NULL; } #endif -static void cdda_stop (void) +static void cdda_stop (struct cdunit *cdu) { - if (cdda_play > 0) { - cdda_play = -1; - while (cdda_play) { + if (cdu->cdda_play > 0) { + cdu->cdda_play = -1; + while (cdu->cdda_play) { Sleep (10); } } - cdda_play_finished = 0; - cdda_paused = 0; + cdu->cdda_play_finished = 0; + cdu->cdda_paused = 0; } static int command_pause (int unitnum, int paused) { + struct cdunit *cdu = &cdunits[unitnum]; if (unitnum) return 0; - cdda_paused = paused; + cdu->cdda_paused = paused; return 1; } static int command_stop (int unitnum) { + struct cdunit *cdu = &cdunits[unitnum]; if (unitnum) return 0; - cdda_stop (); + cdda_stop (cdu); return 1; } -static int command_play (int unitnum, uae_u32 start, uae_u32 end, int scan) +static int command_play (int unitnum, int startlsn, int endlsn, int scan, play_subchannel_callback subfunc) { + struct cdunit *cdu = &cdunits[unitnum]; if (unitnum) return 0; - cdda_paused = 0; - cdda_play_finished = 0; - cdda_start = msf2lsn (start); - cdda_end = msf2lsn (end); - if (!cdda_play) + 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; + if (!cdu->cdda_play) uae_start_thread (L"cdda_play", cdda_play_func, NULL, NULL); - cdda_play++; + cdu->cdda_play++; return 1; } -static uae_u8 *command_qcode (int unitnum) +static int command_qcode (int unitnum, uae_u8 *buf, int sector) { - static uae_u8 buf[4 + 12]; + struct cdunit *cdu = &cdunits[unitnum]; + uae_u8 subbuf[SUB_CHANNEL_SIZE]; uae_u8 *p; int trk; int pos; - int msf; - int start, end; int status; if (unitnum) return NULL; - memset (buf, 0, sizeof buf); + memset (buf, 0, SUBQ_SIZE); p = buf; status = AUDIO_STATUS_NO_STATUS; - if (cdda_play > 0) { + if (cdu->cdda_play > 0) { status = AUDIO_STATUS_IN_PROGRESS; - if (cdda_paused) + if (cdu->cdda_paused) status = AUDIO_STATUS_PAUSED; - } else if (cdda_play_finished) { + } else if (cdu->cdda_play_finished) { status = AUDIO_STATUS_PLAY_COMPLETE; } - pos = cd_last_pos; + if (sector < 0) + pos = cdu->cd_last_pos; + else + pos = sector; p[1] = status; p[3] = 12; p = buf + 4; - start = end = 0; - for (trk = 0; trk <= tracks; trk++) { - struct cdtoc *td = &toc[trk]; - if (pos < td->address) - break; - if (pos >= td->address && pos < td[1].address) { - start = td->address; + struct cdtoc *td = NULL; + for (trk = 0; trk <= cdu->tracks; trk++) { + td = &cdu->toc[trk]; + if (pos < td->address) { + if (trk > 0) + td--; break; } + if (pos >= td->address && pos < td[1].address) + break; } - p[1] = (toc[trk].ctrl << 0) | (toc[trk].adr << 4); - p[2] = trk + 1; - p[3] = 1; - msf = lsn2msf (pos); - p[5] = (msf >> 16) & 0xff; - p[6] = (msf >> 8) & 0xff; - p[7] = (msf >> 0) & 0xff; - pos -= start; - if (pos < 0) - pos = 0; - msf = lsn2msf (pos - 150); - p[9] = (msf >> 16) & 0xff; - p[10] = (msf >> 8) & 0xff; - p[11] = (msf >> 0) & 0xff; - - return buf; + if (!td) + return 0; + getsub (subbuf, cdu, td, pos); + memcpy (p, subbuf + 12, 12); +// write_log (L"%6d %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x\n", +// pos, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11]); + return 1; } static void command_volume (int unitnum, uae_u16 volume) { - cdda_volume = volume; + struct cdunit *cdu = &cdunits[unitnum]; + cdu->cdda_volume = volume; } -uae_u8 *command_rawread (int unitnum, int sector, int sectorsize) +uae_u8 *command_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize) { - struct cdtoc *t = findtoc (§or); + struct cdunit *cdu = &cdunits[unitnum]; + struct cdtoc *t = findtoc (cdu, §or); int offset; if (unitnum) @@ -626,87 +523,92 @@ uae_u8 *command_rawread (int unitnum, int sector, int sectorsize) if (!t || t->handle == NULL) return NULL; - cdda_stop (); + 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); - zfile_fread (buffer, sectorsize, 1, t->handle); - return buffer; + if (data) + zfile_fread (data, sectorsize, size, t->handle); + else + zfile_fread (cdu->buffer, sectorsize, 1, t->handle); + cdu->cd_last_pos = sector; + return cdu->buffer; } -static uae_u8 *command_read (int unitnum, int sector) +static uae_u8 *command_read (int unitnum, uae_u8 *data, int sector, int size) { - struct cdtoc *t = findtoc (§or); + struct cdunit *cdu = &cdunits[unitnum]; + struct cdtoc *t = findtoc (cdu, §or); int offset; if (unitnum) return NULL; if (!t || t->handle == NULL) return NULL; - cdda_stop (); + cdda_stop (cdu); offset = 0; if (t->size > 2048) offset = 16; zfile_fseek (t->handle, t->offset + sector * t->size + offset, SEEK_SET); - zfile_fread (buffer, 2048, 1, t->handle); - return buffer; + if (data) + zfile_fread (data, size, 2048, t->handle); + else + zfile_fread (cdu->buffer, 2048, 1, t->handle); + cdu->cd_last_pos = sector; + return cdu->buffer; } -static uae_u8 *command_toc (int unitnum) +static struct cd_toc_head *command_toc (int unitnum) { - static uae_u8 statictoc[11 * 102]; - uae_u8 *p = statictoc; + struct cdunit *cdu = &cdunits[unitnum]; + static struct cd_toc_head statictoc; + struct cd_toc *toc = &statictoc.toc[0]; int i; - uae_u32 msf; if (unitnum) return NULL; - cdda_stop (); - if (!tracks) + cdda_stop (cdu); + if (!cdu->tracks) return NULL; - p[0] = ((tracks + 4) * 11) >> 8; - p[1] = ((tracks + 4) * 11) & 0xff; - p[2] = 1; - p[3] = tracks; - p += 4; - memset (p, 0, 11); - p[0] = 1; - p[1] = (toc[0].ctrl << 0) | (toc[0].adr << 4); - p[3] = 0xa0; - p[8] = 1; - p += 11; - memset (p, 0, 11); - p[0] = 1; - p[1] = 0x10; - p[3] = 0xa1; - p[8] = tracks; - p += 11; - memset (p, 0, 11); - p[0] = 1; - p[1] = 0x10; - p[3] = 0xa2; - msf = lsn2msf (toc[tracks].address); - p[8] = msf >> 16; - p[9] = msf >> 8; - p[10] = msf >> 0; - p += 11; - for (i = 0; i < tracks; i++) { - memset (p, 0, 11); - p[0] = 1; - p[1] = (toc[i].ctrl << 0) | (toc[i].adr << 4); - p[2] = 0; - p[3] = i + 1; - msf = lsn2msf (toc[i].address); - p[8] = msf >> 16; - p[9] = msf >> 8; - p[10] = msf >> 0; - p += 11; + + 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; + + toc->adr = 1; + toc->point = 0xa0; + toc->track = statictoc.first_track; + toc++; + + statictoc.first_track_offset = 1; + for (i = 0; i < cdu->tracks; i++) { + toc->adr = cdu->toc[i].adr; + toc->control = cdu->toc[i].ctrl; + toc->track = i + 1; + toc->point = i + 1; + toc->paddress = cdu->toc[i].address; + toc++; } + + statictoc.last_track_offset = cdu->tracks; + toc->adr = 1; + toc->point = 0xa1; + toc->track = statictoc.last_track; + toc++; + + toc->adr = 1; + toc->point = 0xa2; + toc->paddress = statictoc.lastaddress; + toc++; + gui_flicker_led (LED_CD, unitnum, 1); - return statictoc; + return &statictoc; } static void skipspace (TCHAR **s) @@ -742,26 +644,152 @@ static TCHAR *nextstring (TCHAR **sp) return out; } -static int parse_image (void) +static int readval (const TCHAR *s) +{ + int base = 10; + TCHAR *endptr; + if (s[0] == '0' && _totupper (s[1]) == 'X') + s += 2, base = 16; + return _tcstol (s, &endptr, base); +} + +static int parseccd (struct cdunit *cdu, struct zfile *zcue, TCHAR *img) +{ + int mode; + int num, tracknum, trackmode; + int adr, control, lba; + bool gotlba; + struct cdtoc *t; + struct zfile *zimg, *zsub; + TCHAR fname[MAX_DPATH]; + + write_log (L"CCD TOC: '%s'\n", img); + _tcscpy (fname, img); + TCHAR *ext = _tcsrchr (fname, '.'); + if (ext) + *ext = 0; + _tcscat (fname, L".img"); + zimg = zfile_fopen (fname, L"rb", ZFD_NORMAL); + if (!zimg) { + write_log (L"CCD: can't open '%s'\n", fname); + //return 0; + } + ext = _tcsrchr (fname, '.'); + if (ext) + *ext = 0; + _tcscat (fname, L".sub"); + zsub = zfile_fopen (fname, L"rb", ZFD_NORMAL); + if (zsub) + write_log (L"CCD: '%s' detected\n", fname); + + num = -1; + mode = -1; + for (;;) { + TCHAR buf[MAX_DPATH], *p; + if (!zfile_fgets (buf, sizeof buf / sizeof (TCHAR), zcue)) + break; + p = buf; + skipspace (&p); + if (!_tcsnicmp (p, L"[DISC]", 6)) { + mode = 1; + } else if (!_tcsnicmp (p, L"[ENTRY ", 7)) { + t = NULL; + mode = 2; + num = readval (p + 7); + if (num < 0) + break; + adr = control = -1; + gotlba = false; + } else if (!_tcsnicmp (p, L"[TRACK ", 7)) { + mode = 3; + tracknum = readval (p + 7); + trackmode = -1; + if (tracknum <= 0 || tracknum > 99) + break; + t = &cdu->toc[tracknum - 1]; + } + if (mode < 0) + continue; + if (mode == 1) { + if (!_tcsnicmp (p, L"TocEntries=", 11)) { + cdu->tracks = readval (p + 11) - 3; + if (cdu->tracks <= 0 || cdu->tracks > 99) + break; + } + continue; + } + if (cdu->tracks <= 0) + break; + + if (mode == 2) { + + if (!_tcsnicmp (p, L"SESSION=", 8)) { + if (readval (p + 8) != 1) + mode = -1; + continue; + } else if (!_tcsnicmp (p, L"POINT=", 6)) { + tracknum = readval (p + 6); + if (tracknum <= 0) + break; + if (tracknum >= 0xa0 && tracknum != 0xa2) { + mode = -1; + continue; + } + if (tracknum == 0xa2) + tracknum = cdu->tracks + 1; + t = &cdu->toc[tracknum - 1]; + continue; + } + if (!_tcsnicmp (p, L"ADR=", 4)) + adr = readval (p + 4); + if (!_tcsnicmp (p, L"CONTROL=", 8)) + control = readval (p + 8); + if (!_tcsnicmp (p, L"PLBA=", 5)) { + lba = readval (p + 5); + gotlba = true; + } + if (gotlba && adr >= 0 && control >= 0) { + t->adr = adr; + t->ctrl = control; + t->address = lba; + t->offset = 0; + t->size = 2352; + t->offset = lba * t->size; + t->track = tracknum; + if (zsub) { + t->subcode = 2; + t->subhandle = zfile_dup (zsub); + t->suboffset = 0; + } + if (zimg) { + t->handle = zfile_dup (zimg); + t->fname = my_strdup (zfile_getname (zimg)); + t->filesize = zfile_size (t->handle); + } + mode = -1; + } + + } else if (mode == 3) { + + if (!_tcsnicmp (p, L"MODE=", 5)) + trackmode = _tstol (p + 5); + if (trackmode < 0 || trackmode > 2) + continue; + + } + + } + return cdu->tracks; +} + +static int parsecue (struct cdunit *cdu, struct zfile *zcue, TCHAR *img) { - struct zfile *zcue; - TCHAR *fname, *fnametype; int tracknum, index0, pregap; int offset, secoffset, newfile; - int i; - TCHAR *p; - TCHAR curdir[MAX_DPATH], oldcurdir[MAX_DPATH]; - uae_u64 siz; - TCHAR *img = currprefs.cdimagefile; + TCHAR *fname, *fnametype; int ctrl; + mp3decoder *mp3dec = NULL; - if (!img) - return 0; - zcue = zfile_fopen (img, L"rb", ZFD_ARCHIVE | ZFD_CD); - if (!zcue) - return 0; - - oldcurdir[0] = 0; fname = NULL; fnametype = NULL; tracknum = 0; @@ -772,39 +800,9 @@ static int parse_image (void) index0 = -1; pregap = 0; - siz = zfile_size (zcue); - if (siz >= 16384) { - if ((siz % 2048) == 0 || (siz % 2352) == 0) { - struct cdtoc *t = &toc[0]; - tracks = 1; - t->ctrl = 4; - t->adr = 1; - t->fname = my_strdup (img); - t->handle = zcue; - t->size = (siz % 2048) == 0 ? 2048 : 2352; - t->filesize = siz; - write_log (L"CUE: plain CD image mounted!\n"); - zcue = NULL; - goto isodone; - } - zfile_fclose (zcue); - return 0; - } - write_log (L"CUE TOC: '%s'\n", img); - _tcscpy (curdir, img); - oldcurdir[0] = 0; - p = curdir + _tcslen (curdir); - while (p > curdir) { - if (*p == '/' || *p == '\\') - break; - p--; - } - *p = 0; - if (p > curdir) - my_setcurrentdir (curdir, oldcurdir); for (;;) { - TCHAR buf[MAX_DPATH]; + TCHAR buf[MAX_DPATH], *p; if (!zfile_fgets (buf, sizeof buf / sizeof (TCHAR), zcue)) break; @@ -816,6 +814,8 @@ static int parse_image (void) xfree (fname); fname = my_strdup (nextstring (&p)); fnametype = nextstring (&p); + if (!fnametype) + break; if (_tcsicmp (fnametype, L"BINARY") && _tcsicmp (fnametype, L"WAVE") && _tcsicmp (fnametype, L"MP3")) { write_log (L"CUE: unknown file type '%s' ('%s')\n", fnametype, fname); } @@ -844,6 +844,8 @@ static int parse_image (void) index0 = -1; tracknum = _tstoi (nextstring (&p)); tracktype = nextstring (&p); + if (!tracktype) + break; size = 2352; if (!_tcsicmp (tracktype, L"AUDIO")) { ctrl &= ~4; @@ -862,7 +864,7 @@ static int parse_image (void) } } if (tracknum >= 1 && tracknum <= 99) { - struct cdtoc *t = &toc[tracknum - 1]; + struct cdtoc *t = &cdu->toc[tracknum - 1]; struct zfile *ztrack; if (tracknum > 1 && newfile) { @@ -909,8 +911,8 @@ static int parse_image (void) t->handle = ztrack; t->size = size; t->fname = my_strdup (fname); - if (tracknum > tracks) - tracks = tracknum; + if (tracknum > cdu->tracks) + cdu->tracks = tracknum; if (t->handle) t->filesize = zfile_size (t->handle); } @@ -936,7 +938,7 @@ static int parse_image (void) if (idxnum == 0) { index0 = tn; } else if (idxnum == 1 && tracknum >= 1 && tracknum <= 99) { - struct cdtoc *t = &toc[tracknum - 1]; + struct cdtoc *t = &cdu->toc[tracknum - 1]; if (!t->address) { t->address = tn + secoffset; t->address += pregap; @@ -968,109 +970,189 @@ static int parse_image (void) t->filesize = size; } } else if (!_tcsicmp (fnametype, L"MP3") && t->handle) { - t->offset = 0; - t->filesize = mp3decoder_getsize (t->handle); - if (t->filesize) - t->mp3 = 1; + if (!mp3dec) { + try { + mp3dec = new mp3decoder(); + } catch (exception) { } + } + if (mp3dec) { + t->offset = 0; + t->filesize = mp3dec->getsize (t->handle); + if (t->filesize) + t->mp3 = 1; + } } } } } } -isodone: - if (tracks && toc[tracks - 1].handle) { - struct cdtoc *t = &toc[tracks - 1]; - int size = t->filesize; - if (!secoffset) - size -= offset * t->size; - if (size < 0) - size = 0; - toc[tracks].address = t->address + size / t->size; - cdsize = toc[tracks].address * t->size; - } + + struct cdtoc *t = &cdu->toc[cdu->tracks - 1]; + int size = t->filesize; + if (!secoffset) + size -= offset * t->size; + if (size < 0) + size = 0; + cdu->toc[cdu->tracks].address = t->address + size / t->size; + xfree (fname); - if (oldcurdir[0]) - my_setcurrentdir (oldcurdir, NULL); - for (i = 0; i <= tracks; i++) { - struct cdtoc *t = &toc[i]; + + delete mp3dec; + + return cdu->tracks; +} + +static int parse_image (struct cdunit *cdu) +{ + struct zfile *zcue; + int i; + TCHAR *img = currprefs.cdimagefile; + TCHAR *ext; + int secoffset; + + secoffset = 0; + cdu->tracks = 0; + if (!img) + return 0; + zcue = zfile_fopen (img, L"rb", ZFD_ARCHIVE | ZFD_CD); + if (!zcue) + return 0; + + ext = _tcsrchr (img, '.'); + if (ext) { + TCHAR curdir[MAX_DPATH]; + TCHAR oldcurdir[MAX_DPATH], *p; + + ext++; + oldcurdir[0] = 0; + _tcscpy (curdir, img); + p = curdir + _tcslen (curdir); + while (p > curdir) { + if (*p == '/' || *p == '\\') + break; + p--; + } + *p = 0; + if (p > curdir) + my_setcurrentdir (curdir, oldcurdir); + + if (!_tcsicmp (ext, L"cue")) + parsecue (cdu, zcue, img); + else if (!_tcsicmp (ext, L"ccd")) + parseccd (cdu, zcue, img); + + if (oldcurdir[0]) + my_setcurrentdir (oldcurdir, NULL); + } + if (!cdu->tracks) { + uae_u64 siz = zfile_size (zcue); + if (siz >= 16384 && (siz % 2048) == 0 || (siz % 2352) == 0) { + struct cdtoc *t = &cdu->toc[0]; + cdu->tracks = 1; + t->ctrl = 4; + t->adr = 1; + t->fname = my_strdup (img); + t->handle = zcue; + t->size = (siz % 2048) == 0 ? 2048 : 2352; + t->filesize = siz; + write_log (L"CUE: plain CD image mounted!\n"); + cdu->toc[1].address = t->address + t->filesize / t->size; + zcue = NULL; + } + } + + for (i = 0; i <= cdu->tracks; i++) { + struct cdtoc *t = &cdu->toc[i]; uae_u32 msf = lsn2msf (t->address); - if (i < tracks) + if (i < cdu->tracks) write_log (L"%2d: ", i + 1); else write_log (L" "); write_log (L"%7d %02d:%02d:%02d", t->address, (msf >> 16) & 0xff, (msf >> 8) & 0xff, (msf >> 0) & 0xff); - if (i < tracks) - write_log (L" %s %x %10d %s", (t->ctrl & 4) ? L"DATA" : L"CDA ", t->ctrl, t->offset, t->handle == NULL ? L"[FILE ERROR]" : L""); + if (i < cdu->tracks) + write_log (L" %s %x %10d %s", (t->ctrl & 4) ? L"DATA " : (t->subcode ? L"CDA+SUB" : L"CDA "), + t->ctrl, t->offset, t->handle == NULL ? L"[FILE ERROR]" : L""); write_log (L"\n"); - if (i < tracks) + if (i < cdu->tracks) write_log (L" - %s\n", t->fname); } + + cdu->blocksize = 2048; + cdu->cdsize = cdu->toc[cdu->tracks].address * cdu->blocksize; + zfile_fclose (zcue); - mp3decoder_close (); return 1; } -static void unload_image (void) +static void unload_image (struct cdunit *cdu) { int i; - for (i = 0; i < tracks; i++) { - struct cdtoc *t = &toc[i]; + for (i = 0; i < cdu->tracks; i++) { + struct cdtoc *t = &cdu->toc[i]; zfile_fclose (t->handle); + if (t->handle != t->subhandle) + zfile_fclose (t->subhandle); xfree (t->fname); xfree (t->data); + xfree (t->subdata); } - memset (toc, 0, sizeof toc); - tracks = 0; - cdsize = 0; + memset (cdu->toc, 0, sizeof cdu->toc); + cdu->tracks = 0; + cdu->cdsize = 0; } + static int open_device (int unitnum) { - if (unitnum) + struct cdunit *cdu = &cdunits[unitnum]; + if (!cdu->enabled) return 0; - if (!tracks) - parse_image (); + uae_sem_init (&cdu->sub_sem, 0, 1); + if (!cdu->tracks) + parse_image (cdu); return 1; } static void close_device (int unitnum) { - unload_image (); + struct cdunit *cdu = &cdunits[unitnum]; + unload_image (cdu); + uae_sem_destroy (&cdu->sub_sem); } -static int mountme (bool checkparse) +static int mountme (struct cdunit *cdu, bool checkparse) { sys_command_setunit (-1); bool sel = false; - donotmountme = 1; - device_func_init (DEVICE_TYPE_ANY); + 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); + 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); - donotmountme = false; + cdu->donotmountme = false; return -1; } } } } - donotmountme = -1; - device_func_init (DEVICE_TYPE_ANY); // activate us again - donotmountme = 0; + 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 (); - int media = tracks > 0; - write_log (L"IMG_EMU (%s) selected (media=%d)\n", currprefs.cdimagefile, media); + parse_image (cdu); + int media = cdu->tracks > 0; + write_log (L"CDEMU (%s) selected (media=%d)\n", currprefs.cdimagefile, media); return 1; } return 0; @@ -1078,39 +1160,44 @@ static int mountme (bool checkparse) void cdimage_vsync (void) { + struct cdunit *cdu = &cdunits[0]; + if (_tcscmp (changed_prefs.cdimagefile, currprefs.cdimagefile)) { - _tcscpy (newfile, changed_prefs.cdimagefile); + _tcscpy (cdu->newfile, changed_prefs.cdimagefile); changed_prefs.cdimagefile[0] = currprefs.cdimagefile[0] = 0; - imagechange = 3 * 50; - write_log (L"CD: eject\n"); - unload_image (); - scsi_do_disk_change (-1, 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 (imagechange == 0) + if (cdu->imagechange == 0) return; - imagechange--; - if (imagechange > 0) + cdu->imagechange--; + if (cdu->imagechange > 0) return; - _tcscpy (currprefs.cdimagefile, newfile); - _tcscpy (changed_prefs.cdimagefile, newfile); - newfile[0] = 0; + _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) { - donotmountme = 1; + cdu->donotmountme = 1; int un = scsi_do_disk_device_change (); - donotmountme = 0; + cdu->donotmountme = 0; if (un < 0) { - donotmountme = -1; + cdu->donotmountme = -1; device_func_init (DEVICE_TYPE_ANY); // activate us again - donotmountme = 0; - parse_image (); - scsi_do_disk_change (255, 1); + cdu->donotmountme = 0; + parse_image (cdu); + scsi_do_disk_change (255, 1, NULL); } } else { - mountme (true); + mountme (cdu, true); } #ifdef RETROPLATFORM rp_cd_image_change (0, currprefs.cdimagefile); @@ -1120,24 +1207,57 @@ void cdimage_vsync (void) static int ismedia (int unitnum, int quick) { - if (unitnum) + struct cdunit *cdu = &cdunits[unitnum]; + if (!cdu->enabled) return -1; - return tracks > 0 ? 1 : 0; + return cdu->tracks > 0 ? 1 : 0; +} + +static struct device_info *info_device (int unitnum, struct device_info *di, int quick) +{ + struct cdunit *cdu = &cdunits[unitnum]; + if (!cdu->enabled) + return 0; + di->removable = 1; + di->bus = unitnum; + di->target = 0; + di->lun = 0; + di->media_inserted = 0; + di->bytespersector = 2048; + di->mediapath[0] = 0; + di->cylinders = 1; + di->trackspercylinder = 1; + di->sectorspertrack = cdu->cdsize / di->bytespersector; + if (ismedia (unitnum, 1)) { + di->media_inserted = 1; + _tcscpy (di->mediapath, currprefs.cdimagefile); + } + 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)); + di->write_protected = 1; + di->type = INQ_ROMD; + di->id = 255; + _tcscpy (di->label, L"CDEMU"); + return di; } static int check_bus (int flags) { + struct cdunit *cdu = &cdunits[0]; + cdu->enabled = true; if (!(flags & DEVICE_TYPE_CHECKAVAIL)) return 1; - if (donotmountme > 0) - return 0; - if (donotmountme < 0) + if (cdu->donotmountme < 0 || (flags & DEVICE_TYPE_ALLOWEMU)) return 1; - if (imagechange) + if (cdu->donotmountme > 0) + return 0; + if (cdu->imagechange) return 1; int v = currprefs.cdimagefile[0] ? 1 : 0; if (v) { - if (mountme (false) < 0) // is it supported \? + if (mountme (cdu, false) < 0) // is it supported \? return 0; } if (currprefs.cdimagefileuse) { @@ -1148,14 +1268,15 @@ static int check_bus (int flags) static int open_bus (int flags) { + struct cdunit *cdu = &cdunits[0]; if (!(flags & DEVICE_TYPE_CHECKAVAIL)) return 1; - if (donotmountme > 0) - return 0; - if (donotmountme < 0) + if (cdu->donotmountme < 0 || (flags & DEVICE_TYPE_ALLOWEMU)) return 1; + if (cdu->donotmountme > 0) + return 0; - mountme (true); + mountme (cdu, true); #ifdef RETROPLATFORM rp_cd_change (0, 0); rp_cd_image_change (0, currprefs.cdimagefile); @@ -1165,37 +1286,11 @@ static int open_bus (int flags) static void close_bus (void) { - mp3decoder_close (); #ifdef RETROPLATFORM rp_cd_change (0, 1); #endif } -static struct device_info *info_device (int unitnum, struct device_info *di) -{ - if (unitnum) - return 0; - di->removable = 1; - di->bus = unitnum; - di->target = 0; - di->lun = 0; - di->media_inserted = 0; - di->bytespersector = 2048; - di->mediapath[0] = 0; - di->cylinders = 1; - di->trackspercylinder = 1; - di->sectorspertrack = cdsize / di->bytespersector; - if (ismedia (unitnum, 1)) { - di->media_inserted = 1; - _tcscpy (di->mediapath, currprefs.cdimagefile); - } - di->write_protected = 1; - di->type = INQ_ROMD; - di->id = 255; - _tcscpy (di->label, L"IMG_EMU"); - return di; -} - struct device_functions devicefunc_cdimage = { check_bus, open_bus, close_bus, open_device, close_device, info_device, 0, 0, 0, diff --git a/cdtv.cpp b/cdtv.cpp index 0f09c162..eda5756f 100644 --- a/cdtv.cpp +++ b/cdtv.cpp @@ -3,7 +3,7 @@ * * CDTV DMAC/CDROM controller emulation * -* Copyright 2004/2007 Toni Wilen +* Copyright 2004/2007-2010 Toni Wilen * * Thanks to Mark Knibbs for CDTV Technical information * @@ -11,6 +11,7 @@ //#define ROMHACK //#define ROMHACK2 +//#define CDTV_SUB_DEBUG //#define CDTV_DEBUG //#define CDTV_DEBUG_CMD //#define CDTV_DEBUG_6525 @@ -49,37 +50,33 @@ #define ISTR_FF_FLG (1<<1) #define ISTR_FE_FLG (1<<0) -#define AUDIO_STATUS_NOT_SUPPORTED 0x00 -#define AUDIO_STATUS_IN_PROGRESS 0x11 -#define AUDIO_STATUS_PAUSED 0x12 -#define AUDIO_STATUS_PLAY_COMPLETE 0x13 -#define AUDIO_STATUS_PLAY_ERROR 0x14 -#define AUDIO_STATUS_NO_STATUS 0x15 - #define MODEL_NAME "MATSHITA0.96" /* also MATSHITA0.97 exists but is apparently rare */ +#define MAX_SUBCODEBUFFER 16 +static volatile int subcodebufferoffset, subcodebufferoffsetw, subcodeoffset; +static uae_u8 subcodebufferinuse[MAX_SUBCODEBUFFER]; +static uae_u8 subcodebuffer[MAX_SUBCODEBUFFER * SUB_CHANNEL_SIZE]; +static uae_sem_t sub_sem; + static smp_comm_pipe requests; static volatile int thread_alive; static int configured; static uae_u8 dmacmemory[100]; -#define MAX_TOC_ENTRIES 103 -static uae_u8 cdrom_toc[MAX_TOC_ENTRIES * 13]; +static struct cd_toc_head toc; static uae_u32 last_cd_position, play_start, play_end; -static uae_u8 cdrom_qcode[16], cd_audio_status; +static uae_u8 cdrom_qcode[4 + 12], cd_audio_status; static int datatrack; -static volatile int cdtv_command_len; -static volatile uae_u8 cdtv_command_buf[6]; static volatile uae_u8 dmac_istr, dmac_cntr; static volatile uae_u16 dmac_dawr; static volatile uae_u32 dmac_acr; static volatile int dmac_wtc; static volatile int dmac_dma; -static volatile int activate_stch, cdrom_command_done, play_state, play_state_cmd, play_statewait; +static volatile int activate_stch, cdrom_command_done, play_state, play_statewait; static volatile int cdrom_sector, cdrom_sectors, cdrom_length, cdrom_offset; static volatile int cd_playing, cd_paused, cd_motor, cd_media, cd_error, cd_finished, cd_isready, cd_hunt; static uae_u32 last_play_pos, last_play_end; @@ -87,8 +84,15 @@ 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; +static int cd_volume, cd_volume_stored; static int cd_led; +static int frontpanel; + +static uae_u8 cdrom_command_input[16]; +static int cdrom_command_cnt_in; + +static uae_u8 tp_a, tp_b, tp_c, tp_ad, tp_bd, tp_cd; +static uae_u8 tp_imask, tp_cr, tp_air, tp_ilatch, tp_ilatch2; #ifdef ROMHACK #define ROM_VECTOR 0x2000 @@ -115,39 +119,26 @@ static volatile int cmd, enable, xaen, dten; static int unitnum = -1; -/* convert minutes, seconds and frames -> logical sector number */ -static int msf2lsn (int msf) +static void subreset (void) { - int sector = ((msf >> 16) & 0xff) * 60 * 75 + ((msf >> 8) & 0xff) * 75 + ((msf >> 0) & 0xff); - if (sector < 0) - sector = 0; - return sector; -} - -/* convert logical sector number -> minutes, seconds and frames */ -static int lsn2msf (int sectors) -{ - int msf; - msf = (sectors / (75 * 60)) << 16; - msf |= ((sectors / 75) % 60) << 8; - msf |= (sectors % 75) << 0; - return msf; + uae_sem_wait (&sub_sem); + memset (subcodebufferinuse, 0, sizeof subcodebufferinuse); + subcodebufferoffsetw = subcodebufferoffset = 0; + subcodeoffset = -1; + sbcp = 0; + scor = 0; + uae_sem_post (&sub_sem); } static int get_toc (void) { - uae_u8 *buf; - int i; - datatrack = 0; - buf = sys_command_cd_toc (DF_IOCTL, unitnum); - if (!buf) + struct cd_toc_head *t = sys_command_cd_toc (DF_IOCTL, unitnum); + if (!t) return 0; - i = (buf[0] << 8) | (buf[1] << 0); - memcpy (cdrom_toc, buf, i); - last_cd_position = (buf[4 + 2 * 11 + 8] << 16) | (buf[4 + 2 * 11 + 9] << 8) | (buf[4 + 2 * 11 + 10] << 0); - last_cd_position = lsn2msf (msf2lsn (last_cd_position) - 1); - if (buf[4 + 3 * 11 + 3] == 1 && (buf[4 + 3 * 11 + 1] & 0x0c) == 0x04) + 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; return 1; } @@ -163,41 +154,43 @@ static void finished_cdplay (void) static int get_qcode (void) { - uae_u8 *s; - static uae_u8 subq0; - - memset (cdrom_qcode, 0, 16); - s = sys_command_cd_qcode (DF_IOCTL, unitnum); - if (!s) + if (!sys_command_cd_qcode (DF_IOCTL, unitnum, cdrom_qcode)) return 0; - memcpy (cdrom_qcode, s, 16); if (cd_playing) { - if (s[1] == AUDIO_STATUS_IN_PROGRESS) { - int end = msf2lsn ((s[5 + 4] << 16) | (s[6 + 4] << 8) | (s[7 + 4])); + if (cdrom_qcode[1] == AUDIO_STATUS_IN_PROGRESS) { + int end = msf2lsn (fromlongbcd (cdrom_qcode + 4 + 7)); if (end >= play_end - 75) finished_cdplay (); - } else if (s[1] == AUDIO_STATUS_PLAY_COMPLETE) { + } else if (cdrom_qcode[1] == AUDIO_STATUS_PLAY_COMPLETE) { finished_cdplay (); } } - s[1] = cd_audio_status; + cdrom_qcode[1] = cd_audio_status; return 1; } static void cdaudiostop (void) { cd_finished = 0; - if (cd_playing) + cd_audio_status = AUDIO_STATUS_NO_STATUS; + if (cd_playing) { + cd_audio_status = AUDIO_STATUS_PLAY_COMPLETE; cd_finished = 1; + } cd_playing = 0; cd_paused = 0; cd_motor = 0; - cd_audio_status = AUDIO_STATUS_NO_STATUS; if (unitnum < 0) return; sys_command_cd_pause (DF_IOCTL, unitnum, 0); sys_command_cd_stop (DF_IOCTL, unitnum); } +static void cdaudiostopfp (void) +{ + cdaudiostop (); + cd_error = 1; + cd_audio_status = AUDIO_STATUS_PLAY_ERROR; +} static int pause_audio (int pause) { @@ -209,6 +202,7 @@ static int pause_audio (int pause) } cd_paused = pause; cd_audio_status = pause ? AUDIO_STATUS_PAUSED : AUDIO_STATUS_IN_PROGRESS; + subreset (); return 1; } @@ -235,11 +229,65 @@ static int ismedia (void) return sys_command_ismedia (DF_IOCTL, unitnum, 0); } +static int issub (void) +{ + return 1; +} + +static void subfunc (uae_u8 *data, int cnt) +{ + if (!issub ()) + return; + uae_sem_wait (&sub_sem); +#ifdef CDTV_SUB_DEBUG + int total = 0; + for (int i = 0; i < MAX_SUBCODEBUFFER; i++) { + if (subcodebufferinuse[i]) + total++; + } + write_log (L"%d ", total); +#endif + if (subcodebufferinuse[subcodebufferoffsetw]) { + memset (subcodebufferinuse, 0, sizeof subcodebufferinuse); + subcodebufferoffsetw = subcodebufferoffset = 0; + subcodeoffset = -1; + uae_sem_post (&sub_sem); +#ifdef CDTV_SUB_DEBUG + write_log (L"CDTV: subcode buffer overflow 1\n"); +#endif + return; + } + int offset = subcodebufferoffsetw; + while (cnt > 0) { + if (subcodebufferinuse[offset]) { +#ifdef CDTV_SUB_DEBUG + write_log (L"CDTV: subcode buffer overflow 2\n"); +#endif + break; + } + subcodebufferinuse[offset] = 1; + memcpy (&subcodebuffer[offset * SUB_CHANNEL_SIZE], data, SUB_CHANNEL_SIZE); + data += SUB_CHANNEL_SIZE; + offset++; + if (offset >= MAX_SUBCODEBUFFER) + offset = 0; + cnt--; + } + subcodebufferoffsetw = offset; + uae_sem_post (&sub_sem); +} + + static void do_play (void) { + uae_u32 start = read_comm_pipe_u32_blocking (&requests); + 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); cd_audio_status = AUDIO_STATUS_PLAY_ERROR; - if (sys_command_cd_play (DF_IOCTL, unitnum, lsn2msf (play_start), lsn2msf (play_end), 0)) { + 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)) { cd_audio_status = AUDIO_STATUS_IN_PROGRESS; cd_playing = 1; } else { @@ -256,21 +304,21 @@ static int play_cdtrack (uae_u8 *p) int index_end = p[4]; int start_found, end_found; uae_u32 start, end; - int i, j; + int j; + + if (track_start == 0 && track_end == 0) + return 0; - i = (cdrom_toc[0] << 8) | (cdrom_toc[1] << 0); - i -= 2; - i /= 11; end = last_cd_position; start_found = end_found = 0; - for (j = 0; j < i; j++) { - uae_u8 *s = cdrom_toc + 4 + j * 11; - if (track_start == s[3]) { + for (j = 0; j < toc.points; j++) { + struct cd_toc *s = &toc.toc[j]; + if (track_start == s->track) { start_found++; - start = (s[8] << 16) | (s[9] << 8) | s[10]; + start = s->paddress; } - if (track_end == s[3]) { - end = (s[8] << 16) | (s[9] << 8) | s[10]; + if (track_end == s->track) { + end = s->paddress; end_found++; } } @@ -281,17 +329,15 @@ static int play_cdtrack (uae_u8 *p) write_log (L"PLAY CD AUDIO: illegal start track %d\n", track_start); return 0; } - play_end = msf2lsn (end); - play_start = msf2lsn (start); - last_play_end = start; + play_end = end; + play_start = start; + 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, - start, msf2lsn (start), end, msf2lsn (end)); + track_start, track_end, start, start, end, end); #endif play_state = 1; - play_state_cmd = 1; return 0; } @@ -318,21 +364,20 @@ static int play_cd (uae_u8 *p) cd_error = 1; return 0; } - if (p[0] == 0x09) { /* lsn */ - start = lsn2msf (start); + if (p[0] != 0x09) { /* msf */ + start = msf2lsn (start); if (end < 0x00ffffff) - end = lsn2msf (end); + end = msf2lsn (end); } - if (end == 0x00ffffff || end > last_cd_position) + if (end >= 0x00ffffff || end > last_cd_position) end = last_cd_position; - play_end = msf2lsn (end); - play_start = msf2lsn (start); + play_end = end; + play_start = start; #ifdef CDTV_DEBUG write_log (L"PLAY CD AUDIO from %06X (%d) to %06X (%d)\n", - start, msf2lsn (start), end, msf2lsn (end)); + lsn2msf (start), start, lsn2msf (end), end); #endif play_state = 1; - play_state_cmd = 1; return 0; } @@ -342,14 +387,13 @@ static int cdrom_subq (uae_u8 *out, int msflsn) uae_u32 trackposlsn, trackposmsf; uae_u32 diskposlsn, diskposmsf; - get_qcode (); out[0] = cd_audio_status; s += 4; - out[1] = s[1]; - out[2] = s[2]; - out[3] = s[3]; - trackposmsf = (s[9] << 16) | (s[10] << 8) | s[11]; - diskposmsf = (s[5] << 16) | (s[6] << 8) | s[7]; + out[1] = (s[0] >> 4) | (s[0] << 4); + out[2] = frombcd (s[1]); // track + out[3] = frombcd (s[2]); // index + trackposmsf = fromlongbcd (s + 3); + diskposmsf = fromlongbcd (s + 7); trackposlsn = msf2lsn (trackposmsf); diskposlsn = msf2lsn (diskposmsf); out[4] = 0; @@ -366,21 +410,14 @@ static int cdrom_subq (uae_u8 *out, int msflsn) static int cdrom_info (uae_u8 *out) { - uae_u8 *p; uae_u32 size; - int i; if (ismedia () <= 0) return -1; cd_motor = 1; - out[0] = cdrom_toc[2]; - i = (cdrom_toc[0] << 8) | (cdrom_toc[1] << 0); - i -= 2 + 11; - i /= 11; - p = cdrom_toc + 4 + i * 11; - out[1] = p[3]; - p = cdrom_toc + 4 + 2 * 11; - size = ((p[8] << 16) | (p[9] << 8) | p[10]); + out[0] = toc.first_track; + out[1] = toc.last_track; + size = lsn2msf (toc.lastaddress); out[2] = size >> 16; out[3] = size >> 8; out[4] = size >> 0; @@ -390,26 +427,21 @@ static int cdrom_info (uae_u8 *out) static int read_toc (int track, int msflsn, uae_u8 *out) { - uae_u8 *buf = cdrom_toc, *s; - int i, j; + int j; if (ismedia () <= 0) return -1; if (!out) return 0; cd_motor = 1; - i = (buf[0] << 8) | (buf[1] << 0); - i -= 2; - i /= 11; - for (j = 0; j < i; j++) { - s = buf + 4 + j * 11; - if (track == s[3]) { - uae_u32 msf = (s[8] << 16) | (s[9] << 8) | s[10]; - uae_u32 lsn = msf2lsn (msf); + for (j = 0; j < toc.points; j++) { + if (track == toc.toc[j].point) { + int lsn = toc.toc[j].paddress; + int msf = lsn2msf (lsn); out[0] = 0; - out[1] = s[1]; - out[2] = s[3]; - out[3] = buf[3]; + out[1] = (toc.toc[j].adr << 4) | (toc.toc[j].control << 0); + out[2] = toc.toc[j].point; + out[3] = toc.tracks; out[4] = 0; out[5] = (msflsn ? msf : lsn) >> 16; out[6] = (msflsn ? msf : lsn) >> 8; @@ -457,8 +489,6 @@ static void cdrom_command_accepted (int size, uae_u8 *cdrom_command_input, int * static void cdrom_command_thread (uae_u8 b) { - static uae_u8 cdrom_command_input[16]; - static int cdrom_command_cnt_in; uae_u8 *s; cdrom_command_input[cdrom_command_cnt_in] = b; @@ -509,17 +539,17 @@ static void cdrom_command_thread (uae_u8 b) if (cdrom_command_cnt_in == 1) { uae_u8 flag = 0; if (!cd_isready) - flag |= 1 << 0; + flag |= 1 << 0; // 01 if (cd_playing) - flag |= 1 << 2; + flag |= 1 << 2; // 04 if (cd_finished) - flag |= 1 << 3; + flag |= 1 << 3; // 08 if (cd_error) - flag |= 1 << 4; + flag |= 1 << 4; // 10 if (cd_motor) - flag |= 1 << 5; + flag |= 1 << 5; // 20 if (cd_media) - flag |= 1 << 6; + flag |= 1 << 6; // 40 cdrom_command_output[0] = flag; cdrom_command_accepted (1, s, &cdrom_command_cnt_in); cd_finished = 0; @@ -573,6 +603,7 @@ static void cdrom_command_thread (uae_u8 b) break; case 0xa3: /* front panel */ if (cdrom_command_cnt_in == 7) { + frontpanel = s[1] ? 1 : 0; cdrom_command_accepted (0, s, &cdrom_command_cnt_in); cd_finished = 1; } @@ -594,15 +625,14 @@ static uae_u8 *read_raw (int sector, int size) TCHAR fname[MAX_DPATH]; static uae_u8 buf[4096]; uae_u32 prevlsn = 0; - uae_u8 *s = cdrom_toc + 4; + struct cd_toc *t = &toc.toc[0]; memset (buf, 0, sizeof buf); trackcnt = 0; for (;;) { - uae_u32 msf = (s[8] << 16) | (s[9] << 8) | s[10]; - uae_u32 lsn = msf2lsn (msf); - if (s[3] >= 0xa0) { - s += 11; + int lsn = t->paddress; + if (t->point >= 0xa0) { + t++; continue; } if (sector < lsn - prevlsn) @@ -610,7 +640,7 @@ static uae_u8 *read_raw (int sector, int size) trackcnt++; sector -= lsn - prevlsn; prevlsn = lsn; - s += 11; + t++; } if (track != trackcnt) { _stprintf (fname, L"track%d.bin", trackcnt); @@ -626,7 +656,7 @@ static uae_u8 *read_raw (int sector, int size) zfile_fread (buf, size, 1, f); return buf; } - return sys_command_cd_rawread (DF_IOCTL, unitnum, osector, size); + return sys_command_cd_rawread (DF_IOCTL, unitnum, NULL, osector, size, 1); } static void dma_do_thread (void) @@ -652,7 +682,7 @@ static void dma_do_thread (void) if (cdtv_sectorsize == 2336) p = read_raw (readsector, cdtv_sectorsize); else - p = sys_command_cd_read (DF_IOCTL, unitnum, readsector); + p = sys_command_cd_read (DF_IOCTL, unitnum, NULL, readsector, 1); if (!p) { cd_error = 1; activate_stch = 1; @@ -697,10 +727,12 @@ static void *dev_thread (void *p) { int m = ismedia (); if (m < 0) { - write_log (L"CDTV: device lost\n"); - activate_stch = 1; - cd_hunt = 1; - cd_media = 0; + if (!cd_hunt) { + write_log (L"CDTV: device %d lost\n", unitnum); + activate_stch = 1; + cd_hunt = 1; + cd_media = 0; + } } else if (m != cd_media) { cd_media = m; get_toc (); @@ -723,6 +755,15 @@ static void *dev_thread (void *p) case 0x0104: // stop cdaudiostop (); break; + case 0x0105: // pause + pause_audio (1); + break; + case 0x0106: // unpause + pause_audio (0); + break; + case 0x0107: // frontpanel stop + cdaudiostopfp (); + break; case 0x0110: // do_play! do_play (); break; @@ -739,30 +780,116 @@ static void cdrom_command (uae_u8 b) write_comm_pipe_u32 (&requests, b, 1); } -static uae_u8 tp_a, tp_b, tp_c, tp_ad, tp_bd, tp_cd; -static uae_u8 tp_imr, tp_cr, tp_air; +static void init_play (int start, int end) +{ + play_end = end; + play_start = start; + 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); +#endif + play_state = 1; + subreset (); +} + +bool cdtv_front_panel (int button) +{ + if (!frontpanel || !configured) + return false; + if (button < 0) + return true; + switch (button) + { + case 0: // stop + if (cd_paused) + write_comm_pipe_u32 (&requests, 0x0106, 1); + write_comm_pipe_u32 (&requests, 0x0107, 1); + break; + case 1: // playpause + if (cd_playing) { + write_comm_pipe_u32 (&requests, cd_paused ? 0x0106 : 0x0105, 1); + } else if (cd_media) { + init_play (0, last_cd_position); + } + break; + case 2: // prev + case 3: // next + if (!cd_playing) + return true; + uae_u8 *sq = cdrom_qcode + 4; + int track = frombcd (sq[1]); + int pos = 0; + for (int j = 0; j < toc.points; j++) { + int t = toc.toc[j].track; + pos = toc.toc[j].paddress; + if (t == 1 && track == 1 && button == 2) + break; + else if (j == toc.points - 1 && t == track && button == 3) + break; + else if (t == track - 1 && track > 1 && button == 2) + break; + else if (t == track + 1 && track < 99 && button == 3) + break; + } + init_play (pos - 150, last_cd_position); + break; + } + return true; +} + +static uae_u8 get_tp_c (void) +{ + uae_u8 v = (sbcp ? 0 : (1 << 0)) | (scor ? 0 : (1 << 1)) | + (stch ? 0 : (1 << 2)) | (sten ? 0 : (1 << 3) | (1 << 4)); + return v; +} +static uae_u8 get_tp_c_level (void) +{ + uae_u8 v = (sbcp == 1 ? 0 : (1 << 0)) | (scor == 1 ? 0 : (1 << 1)) | + (stch == 1 ? 0 : (1 << 2)) | (sten == 1 ? 0 : (1 << 3)) | (1 << 4); + if (sten == 1) + sten = -1; + if (scor == 1) + scor = -1; + if (sbcp == 1) + sbcp = -1; + return v; +} static void tp_check_interrupts (void) { /* MC = 1 ? */ - if ((tp_cr & 1) != 1) + if ((tp_cr & 1) != 1) { + get_tp_c_level (); return; + } - if (sten == 1) { - sten = -1; - if (tp_cd & (1 << 3)) - tp_air |= 1 << 3; + tp_ilatch |= get_tp_c_level () ^ 0x1f; + stch = 0; + if (!(tp_ilatch & (1 << 5)) && (tp_ilatch & tp_imask)) { + tp_air = 0; + int mask = 0x10; + while (((tp_ilatch & tp_imask) & mask) == 0) + mask >>= 1; + tp_air |= tp_ilatch & mask; + tp_ilatch |= 1 << 5; // IRQ + tp_ilatch2 = tp_ilatch & mask; + tp_ilatch &= ~mask; } - if ((tp_air & tp_cd) & 0x1f) + if (tp_ilatch & (1 << 5)) INT2 (); } +// MC=1, C lines 0-4 = input irq lines, 5 = irq out, 6-7 IO static void tp_bput (int addr, uae_u8 v) { static int volstrobe1, volstrobe2; #ifdef CDTV_DEBUG_6525 - write_log (L"6525 write %x=%02X PC=%x\n", addr, v, M68K_GETPC); + if (addr != 1) + write_log (L"6525 write %x=%02X PC=%x %d\n", addr, v, M68K_GETPC, regs.s); #endif switch (addr) { @@ -773,8 +900,15 @@ static void tp_bput (int addr, uae_u8 v) tp_b = v; break; case 2: - if (!(tp_cr & 1)) - tp_c = v; + if (tp_cr & 1) { + // 0 = clear, 1 = ignored + tp_ilatch &= 0xe0 | v; + } else { + tp_c = get_tp_c () & ~tp_cd; + tp_c |= v & tp_cd; + if (tp_c & (1 << 5)) + INT2 (); + } break; case 3: tp_ad = v; @@ -783,7 +917,12 @@ static void tp_bput (int addr, uae_u8 v) tp_bd = v; break; case 5: - tp_cd = v; + // data direction (mode=0), interrupt mask (mode=1) + if (tp_cr & 1) { + tp_imask = v & 0x1f; + } else { + tp_cd = v; + } break; case 6: tp_cr = v; @@ -812,35 +951,56 @@ static void tp_bput (int addr, uae_u8 v) cd_volume = 1023; if (unitnum >= 0) sys_command_cd_volume (DF_IOCTL, unitnum, (cd_volume << 6) | (cd_volume >> 4)); + cd_volume_stored = cd_volume; cd_volume = 0; volstrobe2 = 1; } else if (volstrobe2 && !((tp_b >> 7) & 1)) { volstrobe2 = 0; } + tp_check_interrupts (); } +static uae_u8 subtransferbuf[SUB_CHANNEL_SIZE]; + static uae_u8 tp_bget (int addr) { uae_u8 v = 0; switch (addr) { case 0: - v = tp_a; - write_log (L"TPA read!\n"); + // A = subchannel byte input from serial to parallel converter + if (subcodeoffset < 0 || subcodeoffset >= SUB_CHANNEL_SIZE) { +#ifdef CDTV_SUB_DEBUG + write_log (L"CDTV: requested non-existing subchannel data!? %d\n", subcodeoffset); +#endif + v = 0; + } else { + v = subtransferbuf[subcodeoffset]; + tp_a = 0; + tp_a |= (v >> 7) & 1; + tp_a |= (v >> 5) & 2; + tp_a |= (v >> 3) & 4; + tp_a |= (v >> 1) & 8; + tp_a |= (v << 1) & 16; + tp_a |= (v << 3) & 32; + tp_a |= (v << 5) & 64; + tp_a |= (v << 7) & 128; + v = tp_a; + subcodeoffset++; + sbcp = 0; + if (subcodeoffset >= SUB_CHANNEL_SIZE) + subcodeoffset = -2; + } break; case 1: v = tp_b; break; case 2: - v = (sbcp << 0) | ((scor ^ 1) << 1) | ((stch ^ 1) << 2) | (sten << 3); if (tp_cr & 1) { - if (!v) - v |= 1 << 5; // /IRQ + v = tp_ilatch | tp_ilatch2; } else { - v |= tp_c & ~(0x80 | 0x40); + v = get_tp_c (); } - v |= tp_c & (0x80 | 0x40); - sbcp = 0; break; case 3: v = tp_ad; @@ -849,20 +1009,30 @@ static uae_u8 tp_bget (int addr) v = tp_bd; break; case 5: - v = tp_cd; + // data direction (mode=0), interrupt mask (mode=1) + if (tp_cr & 1) + v = tp_imask; + else + v = tp_cd; break; case 6: v = tp_cr; break; case 7: v = tp_air; + if (tp_cr & 1) { + tp_ilatch &= ~(1 << 5); + tp_ilatch2 = 0; + } tp_air = 0; break; } + tp_check_interrupts (); + #ifdef CDTV_DEBUG_6525 - if (addr < 7) - write_log (L"6525 read %x=%02X PC=%x\n", addr, v, M68K_GETPC); + if (addr < 7 && addr != 1) + write_log (L"6525 read %x=%02X PC=%x %d\n", addr, v, M68K_GETPC, regs.s); #endif return v; } @@ -905,16 +1075,16 @@ static void do_hunt (void) } if (unitnum >= 0) { cdaudiostop (); - sys_command_close (DF_IOCTL, unitnum); + int ou = unitnum; + unitnum = -1; + sys_command_close (DF_IOCTL, ou); } if (sys_command_open (DF_IOCTL, i) > 0) { struct device_info di = { 0 }; - sys_command_info (DF_IOCTL, i, &di); + sys_command_info (DF_IOCTL, i, &di, 0); unitnum = i; cd_hunt = 0; write_log (L"CDTV: autodetected unit %d ('%s')\n", unitnum, di.label); - } else { - unitnum = -1; } } @@ -970,34 +1140,82 @@ void CDTV_hsync_handler (void) dma_finished = 0; cdtv_hsync = -1; } - checkint(); + checkint (); if (cdrom_command_done) { cdrom_command_done = 0; sten = 1; + stch = 0; tp_check_interrupts (); } - if (cdtv_hsync < 312 * 50 / 75 && cdtv_hsync >= 0) - return; - cdtv_hsync = 0; + if (sbcp == 0 && subcodeoffset > 0) { + sbcp = 1; + tp_check_interrupts (); + } - if (first > 0) { - first--; - if (first == 0) - do_stch (); + if (sten < 0) { + sten--; + if (sten < -3) + sten = 0; } + if (scor < 0) { + scor--; + if (scor <= -2) { + if (issub ()) { + subcodeoffset = 0; + sbcp = 1; + } + scor = 0; + tp_check_interrupts (); + } + } + + static int subchannelcounter; + if (subchannelcounter > 0) + subchannelcounter--; + if (subchannelcounter <= 0) { + if (cd_playing || cd_media) { + if (subcodebufferoffset != subcodebufferoffsetw) { + uae_sem_wait (&sub_sem); +#ifdef CDTV_SUB_DEBUG + if (subcodeoffset >= 0) + write_log (L"CDTV: frame interrupt, subchannel not empty! %d\n", subcodeoffset); +#endif + subcodeoffset = -1; + if (subcodebufferinuse[subcodebufferoffset]) { + subcodebufferinuse[subcodebufferoffset] = 0; + memcpy (subtransferbuf, subcodebuffer + subcodebufferoffset * SUB_CHANNEL_SIZE, SUB_CHANNEL_SIZE); + subcodebufferoffset++; + if (subcodebufferoffset >= MAX_SUBCODEBUFFER) + subcodebufferoffset -= MAX_SUBCODEBUFFER; + sbcp = 0; + scor = 1; + tp_check_interrupts (); + } + uae_sem_post (&sub_sem); + subchannelcounter = 200; + } + } + } + + if (cdtv_hsync < 200 && cdtv_hsync >= 0) + return; + cdtv_hsync = 0; if (play_state == 1) { play_state = 2; cd_playing = 1; cd_motor = 1; activate_stch = 1; - play_statewait = 5; + play_statewait = 2; } else if (play_statewait > 0) { play_statewait--; } else if (play_state == 2) { - write_comm_pipe_u32 (&requests, 0x0110, 1); + write_comm_pipe_u32 (&requests, 0x0110, 0); + write_comm_pipe_u32 (&requests, play_start, 0); + write_comm_pipe_u32 (&requests, play_end, 0); + write_comm_pipe_u32 (&requests, 0, 1); play_state = 0; } @@ -1017,18 +1235,17 @@ void CDTV_hsync_handler (void) if (cd_led) gui_flicker_led (LED_CD, 0, cd_led); - if (cd_media && (tp_cr & 1)) { - tp_air |= 1 << 1; - INT2 (); - } - subqcnt--; if (subqcnt < 0) { write_comm_pipe_u32 (&requests, 0x0101, 1); - subqcnt = 75; + if (cd_playing && !cd_hunt) + subqcnt = 10; + else + subqcnt = 75; if (cd_hunt) do_hunt (); } + if (activate_stch) do_stch (); } @@ -1037,10 +1254,10 @@ static void do_stch (void) { static int stch_cnt; - if ((tp_cr & 1) && !(tp_air & (1 << 2)) && (tp_cd & (1 << 2))) { + if ((tp_cr & 1) && !(tp_air & (1 << 2))) { + stch = 1; activate_stch = 0; - tp_air |= 1 << 2; - INT2 (); + tp_check_interrupts (); #ifdef CDTV_DEBUG write_log (L"STCH %d\n", stch_cnt++); #endif @@ -1067,12 +1284,13 @@ static void cdtv_reset (void) cd_error = 0; cd_finished = 0; cd_led = 0; - stch = 0; + stch = 1; first = -1; } static uae_u32 dmac_bget2 (uaecptr addr) { + static uae_u8 last_out; uae_u8 v = 0; if (addr < 0x40) @@ -1113,18 +1331,22 @@ static uae_u32 dmac_bget2 (uaecptr addr) } break; case 0xa1: + sten = 0; if (cdrom_command_cnt_out >= 0) { - v = cdrom_command_output[cdrom_command_cnt_out]; + v = last_out = cdrom_command_output[cdrom_command_cnt_out]; cdrom_command_output[cdrom_command_cnt_out++] = 0; if (cdrom_command_cnt_out >= cdrom_command_size_out) { - stch = 1; - sten = 0; cdrom_command_size_out = 0; cdrom_command_cnt_out = -1; + sten = 0; + tp_check_interrupts (); } else { sten = 1; tp_check_interrupts (); } + } else { + write_log (L"CDTV: command register read while empty\n"); + v = last_out; } break; case 0xe8: @@ -1353,7 +1575,7 @@ static void open_unit (void) sys_command_close (DF_IOCTL, unitnum); unitnum = -1; cdtv_reset (); - if (!device_func_init (DEVICE_TYPE_ANY)) { + if (!device_func_init (DEVICE_TYPE_IOCTL)) { write_log (L"no CDROM support\n"); return; } @@ -1361,14 +1583,14 @@ static void open_unit (void) opened[unitnum] = 0; if (sys_command_open (DF_IOCTL, unitnum)) { opened[unitnum] = 1; - di2 = sys_command_info (DF_IOCTL, unitnum, &di1); + di2 = sys_command_info (DF_IOCTL, 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, 16); + uae_u8 *p = sys_command_cd_read (DF_IOCTL, unitnum, NULL, 16, 1); if (p) { if (!memcmp (p + 8, "CDTV", 4)) { write_log (L"CDTV\n"); @@ -1400,7 +1622,7 @@ static void open_unit (void) } cd_media = 0; if (unitnum >= 0) { - cd_media = ismedia () ? -1 : 0; + cd_media = ismedia () > 0 ? -1 : 0; if (!cd_media) cd_hunt = 1; if (!get_toc()) @@ -1616,10 +1838,10 @@ void cdtv_init (void) configured = 0; tp_a = tp_b = tp_c = tp_ad = tp_bd = tp_cd = 0; - tp_imr = tp_cr = tp_air = 0; - stch = 1; - sten = 1; - scor = 1; + tp_imask = tp_cr = tp_air = tp_ilatch = 0; + stch = 0; + sten = 0; + scor = 0; sbcp = 0; cdrom_command_cnt_out = -1; cmd = enable = xaen = dten = 0; @@ -1635,6 +1857,8 @@ void cdtv_init (void) ew (0x20, 0x00); /* ser.no. Byte 2 */ ew (0x24, 0x00); /* ser.no. Byte 3 */ + uae_sem_init (&sub_sem, 0, 1); + #ifdef ROMHACK2 romhack(); #endif @@ -1647,30 +1871,128 @@ void cdtv_init (void) #ifdef SAVESTATE +uae_u8 *save_dmac (int *len) +{ + uae_u8 *dstbak, *dst; + + dstbak = dst = xmalloc (uae_u8, 1000); + + // model (0=original,1=rev2,2=superdmac) + save_u32 (1); + save_u32 (0); // reserved flags + save_u8 (dmac_istr); + save_u8 (dmac_cntr); + save_u32 (dmac_wtc); + save_u32 (dmac_acr); + save_u16 (dmac_dawr); + save_u32 (dmac_dma ? 1 : 0); + *len = dst - dstbak; + return dstbak; + +} + +uae_u8 *restore_dmac (uae_u8 *src) +{ + restore_u32 (); + restore_u32 (); + dmac_istr = restore_u8 (); + dmac_cntr = restore_u8 (); + dmac_wtc = restore_u32 (); + dmac_acr = restore_u32 (); + dmac_dawr = restore_u16 (); + restore_u32 (); + return src; +} + uae_u8 *save_cdtv (int *len) { uae_u8 *dstbak, *dst; - int i; - if (!currprefs.cs_cd32cd) + if (!currprefs.cs_cdtvcd) return NULL; - return NULL; dstbak = dst = xmalloc (uae_u8, 1000); + + save_u32 (1); + + // tri-port + save_u8 (tp_a); + save_u8 (tp_b); + save_u8 (tp_c); + save_u8 (tp_ad); + save_u8 (tp_bd); + save_u8 (tp_cd); + save_u8 (tp_cr); + save_u8 (tp_air); + save_u8 (tp_imask); + save_u8 (tp_ilatch); + save_u8 (tp_ilatch2); + save_u8 (0); + // misc cd stuff + save_u32 ((cd_playing ? 1 : 0) | (cd_paused ? 2 : 0) | (cd_media ? 4 : 0) | + (cd_motor ? 8 : 0) | (cd_error ? 16 : 0) | (cd_finished ? 32 : 0) | (cdrom_command_done ? 64 : 0) | + (activate_stch ? 128 : 0) | (sten ? 256 : 0) | (stch ? 512 : 0) | (frontpanel ? 1024 : 0)); + save_u8 (cd_isready); + save_u8 (play_state); + save_u16 (cd_volume_stored); + if (cd_playing) + get_qcode (); + save_u32 (last_play_pos); + save_u32 (last_play_end); + save_u64 (dma_wait); + for (int i = 0; i < sizeof cdrom_command_input; i++) + save_u8 (cdrom_command_input[i]); + save_u8 (cdrom_command_cnt_in); + *len = dst - dstbak; return dstbak; } uae_u8 *restore_cdtv (uae_u8 *src) { - uae_u32 v; - int i; - cdtv_free (); if (!currprefs.cs_cdtvcd) { changed_prefs.cs_cdtvcd = changed_prefs.cs_cdtvram = true; currprefs.cs_cdtvcd = currprefs.cs_cdtvram = true; cdtv_init (); } + restore_u32 (); + + // tri-port + tp_a = restore_u8 (); + tp_b = restore_u8 (); + tp_c = restore_u8 (); + tp_ad = restore_u8 (); + tp_bd = restore_u8 (); + tp_cd = restore_u8 (); + tp_cr = restore_u8 (); + tp_air = restore_u8 (); + tp_imask = restore_u8 (); + tp_ilatch = restore_u8 (); + tp_ilatch2 = restore_u8 (); + restore_u8 (); + // misc cd stuff + uae_u32 v = restore_u32 (); + cd_playing = (v & 1) ? 1 : 0; + cd_paused = (v & 2) ? 1 : 0; + cd_media = (v & 4) ? 1 : 0; + cd_motor = (v & 8) ? 1 : 0; + cd_error = (v & 16) ? 1 : 0; + cd_finished = (v & 32) ? 1 : 0; + cdrom_command_done = (v & 64) ? 1 : 0; + activate_stch = (v & 128) ? 1 : 0; + sten = (v & 256) ? 1 : 0; + stch = (v & 512) ? 1 : 0; + frontpanel = (v & 1024) ? 1 : 0; + cd_isready = restore_u8 (); + play_state = restore_u8 (); + cd_volume_stored = restore_u16 (); + last_play_pos = restore_u32 (); + last_play_end = restore_u32 (); + dma_wait = restore_u64 (); + for (int i = 0; i < sizeof cdrom_command_input; i++) + cdrom_command_input[i] = restore_u8 (); + cdrom_command_cnt_in = restore_u8 (); + return src; } diff --git a/cfgfile.cpp b/cfgfile.cpp index 4c63a935..5267e70f 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -487,8 +487,10 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) cfgfile_write_str (f, L"config_host_path", p->config_host_path); for (sl = p->all_lines; sl; sl = sl->next) { - if (sl->unknown) - cfgfile_write_str (f, sl->option, sl->value); + if (sl->unknown) { + if (sl->option) + cfgfile_write_str (f, sl->option, sl->value); + } } _stprintf (tmp, L"%s.rom_path", TARGET_NAME); @@ -552,7 +554,7 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) } } - if (p->cdimagefile[0]) + if (p->cdimagefile[0] || p->cdimagefileuse) cfgfile_write_str (f, L"cdimage0", p->cdimagefile); if (p->quitstatefile[0]) @@ -917,7 +919,7 @@ int cfgfile_intval (const TCHAR *option, const TCHAR *value, const TCHAR *name, if (_tcscmp (option, name) != 0) return 0; /* I guess octal isn't popular enough to worry about here... */ - if (value[0] == '0' && value[1] == 'x') + if (value[0] == '0' && _totupper (value[1]) == 'X') value += 2, base = 16; *location = _tcstol (value, &endptr, base) * scale; @@ -2430,8 +2432,17 @@ static int cfgfile_load_2 (struct uae_prefs *p, const TCHAR *filename, bool real while (cfg_fgets (linea, sizeof (linea), fh) != 0) { trimwsa (linea); if (strlen (linea) > 0) { - if (linea[0] == '#' || linea[0] == ';') + if (linea[0] == '#' || linea[0] == ';') { + struct strlist *u = xcalloc (struct strlist, 1); + u->option = NULL; + TCHAR *com = au (linea); + u->value = my_strdup (com); + xfree (com); + u->unknown = 1; + u->next = p->all_lines; + p->all_lines = u; continue; + } if (!cfgfile_separate_linea (linea, line1b, line2b)) continue; type1 = type2 = 0; diff --git a/custom.cpp b/custom.cpp index cc742de4..35f6effb 100644 --- a/custom.cpp +++ b/custom.cpp @@ -174,7 +174,8 @@ 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) -int hsyncstartpos; +static int hsyncstartpos; +int hsyncstartposnative; static int maxvpos_total = 511; int minfirstline = VBLANK_ENDLINE_PAL; int equ_vblank_endline = EQU_ENDLINE_PAL; @@ -2496,6 +2497,7 @@ static void finish_decisions (void) decide_line (hpos); decide_fetch (hpos); + record_color_change2 (hsyncstartpos, 0xffff, 0); if (thisline_decision.plfleft != -1 && thisline_decision.plflinelen == -1) { if (fetch_state != fetch_not_started) { write_log (L"fetch_state=%d plfleft=%d,len=%d,vpos=%d,hpos=%d\n", @@ -2803,8 +2805,9 @@ void init_hz (void) else hsyncstartpos = maxhpos + hbstrt; } else { - hsyncstartpos = maxhpos_short + 7; + 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 (); @@ -5344,6 +5347,8 @@ static void events_dmal (int hp) } event2_newevent2 (hp, dmal_hpos + ((dmal & 2) ? 1 : 0), dmal_func); dmal &= ~3; + } else if (currprefs.cachesize) { + dmal_func2 (0); } else { event2_newevent2 (hp, 17, dmal_func2); } diff --git a/debug.cpp b/debug.cpp index ea1b487d..6365e3d1 100644 --- a/debug.cpp +++ b/debug.cpp @@ -88,63 +88,63 @@ static struct regstruct history[MAX_HIST]; static TCHAR help[] = { L" HELP for UAE Debugger\n" L" -----------------------\n\n" - L" g [
] Start execution at the current address or
\n" - L" c Dump state of the CIA, disk drives and custom registers\n" - L" r Dump state of the CPU\n" - L" r Modify CPU registers (Dx,Ax,USP,ISP,VBR,...)\n" - L" m
[] Memory dump starting at
\n" - L" d
[] Disassembly starting at
\n" - L" t [instructions] Step one or more instructions\n" - L" z Step through one instruction - useful for JSR, DBRA etc\n" - L" f Step forward until PC in RAM (\"boot block finder\")\n" - L" f
Add/remove breakpoint\n" + L" g [
] Start execution at the current address or
.\n" + L" c Dump state of the CIA, disk drives and custom registers.\n" + L" r Dump state of the CPU.\n" + L" r Modify CPU registers (Dx,Ax,USP,ISP,VBR,...).\n" + L" m
[] Memory dump starting at
.\n" + L" d
[] Disassembly starting at
.\n" + L" t [instructions] Step one or more instructions.\n" + L" z Step through one instruction - useful for JSR, DBRA etc.\n" + L" f Step forward until PC in RAM (\"boot block finder\").\n" + L" f
Add/remove breakpoint.\n" L" fa
[] []\n" - L" Find effective address
\n" - L" fi Step forward until PC points to RTS, RTD or RTE\n" - L" fi Step forward until PC points to \n" - L" fp \"\"/ Step forward until process or is active\n" - L" fl List breakpoints\n" - L" fd Remove all breakpoints\n" - L" fs Break when (SR & mask) = val\n" - L" f Step forward until <= PC <= \n" - L" e Dump contents of all custom registers, ea = AGA colors\n" - L" i [] Dump contents of interrupt and trap vectors\n" - L" il [] Exception breakpoint\n" - L" o <0-2|addr> []View memory as Copper instructions\n" - L" od Enable/disable Copper vpos/hpos tracing\n" - L" ot Copper single step trace\n" - L" ob Copper breakpoint\n" - L" H[H] Show PC history (HH=full CPU info) instructions\n" - L" C Search for values like energy or lifes in games\n" - L" Cl List currently found trainer addresses\n" + L" Find effective address
.\n" + L" fi Step forward until PC points to RTS, RTD or RTE.\n" + L" fi Step forward until PC points to .\n" + L" fp \"\"/ Step forward until process or is active.\n" + L" fl List breakpoints.\n" + L" fd Remove all breakpoints.\n" + L" fs Break when (SR & mask) = val.\n" + L" f Step forward until <= PC <= .\n" + L" e Dump contents of all custom registers, ea = AGA colors.\n" + L" i [] Dump contents of interrupt and trap vectors.\n" + L" il [] Exception breakpoint.\n" + L" o <0-2|addr> []View memory as Copper instructions.\n" + L" od Enable/disable Copper vpos/hpos tracing.\n" + L" ot Copper single step trace.\n" + L" ob Copper breakpoint.\n" + L" H[H] Show PC history (HH=full CPU info) instructions.\n" + L" C Search for values like energy or lifes in games.\n" + L" Cl List currently found trainer addresses.\n" L" D[idxzs <[max diff]>] Deep trainer. i=new value must be larger, d=smaller,\n" L" x = must be same, z = must be different, s = restart.\n" - L" W
Write into Amiga memory\n" - L" w
[] (read/write/opcode/freeze/mustchange)\n" - L" Add/remove memory watchpoints\n" + L" W
Write into Amiga memory.\n" + L" w
[[.x]] (read/write/opcode/freeze/mustchange).\n" + L" Add/remove memory watchpoints.\n" L" wd [<0-1>] Enable illegal access logger. 1 = enable break.\n" - L" S Save a block of Amiga memory\n" + L" S Save a block of Amiga memory.\n" L" s \"\"/ [] []\n" - L" Search for string/bytes\n" - L" T or Tt Show exec tasks and their PCs\n" - L" Td,Tl,Tr Show devices, libraries or resources\n" - L" b Step to previous state capture position\n" - L" M Enable or disable audio channels, bitplanes or sprites\n" - L" sp [] Dump sprite information\n" - L" di [] Break on disk access. R=DMA read,W=write,RW=both,P=PIO\n" - L" Also enables level 1 disk logging\n" - L" did Enable disk logging\n" - L" dj [] Enable joystick/mouse input debugging\n" + L" Search for string/bytes.\n" + L" T or Tt Show exec tasks and their PCs.\n" + L" Td,Tl,Tr Show devices, libraries or resources.\n" + L" b Step to previous state capture position.\n" + L" M Enable or disable audio channels, bitplanes or sprites.\n" + L" sp [] Dump sprite information.\n" + L" di [] Break on disk access. R=DMA read,W=write,RW=both,P=PIO.\n" + L" Also enables level 1 disk logging.\n" + L" did Enable disk logging.\n" + L" dj [] Enable joystick/mouse input debugging.\n" L" smc [<0-1>] Enable self-modifying code detector. 1 = enable break.\n" - L" dm Dump current address space map\n" - L" v [] Show DMA data (accurate only in cycle-exact mode)\n" - L" v [-1 to -4] = enable visual DMA debugger\n" - L" ? Hex/Bin/Dec converter\n" + L" dm Dump current address space map.\n" + L" v [] Show DMA data (accurate only in cycle-exact mode).\n" + L" v [-1 to -4] = enable visual DMA debugger.\n" + L" ? Hex/Bin/Dec converter.\n" #ifdef _WIN32 L" x Close debugger.\n" L" xx Switch between console and GUI debugger.\n" - L" mg
Memory dump starting at
in GUI\n" - L" dg
Disassembly starting at
in GUI\n" + L" mg
Memory dump starting at
in GUI.\n" + L" dg
Disassembly starting at
in GUI.\n" #endif L" q Quit the emulator. You don't want to use this command.\n\n" }; @@ -324,6 +324,28 @@ static int checkvaltype (TCHAR **c, uae_u32 *val) return 0; } +static int readsize (int val, TCHAR **c) +{ + if ((*c)[0] == '.') { + (*c)++; + TCHAR cc = _totupper ((*c)[0]); + (*c)++; + if (cc == 'B') + return 1; + if (cc == 'W') + return 2; + if (cc == '3') + return 3; + if (cc == 'L') + return 4; + } + if (val > 255 || val < -127) + return 2; + if (val > 65535 || val < -32767) + return 4; + return 1; +} + static uae_u32 readint (TCHAR **c) { uae_u32 val; @@ -338,6 +360,18 @@ static uae_u32 readhex (TCHAR **c) return val; return readhexx (c); } +static uae_u32 readint (TCHAR **c, int *size) +{ + uae_u32 val = readint (c); + *size = readsize (val, c); + return val; +} +static uae_u32 readhex (TCHAR **c, int *size) +{ + uae_u32 val = readhex (c); + *size = readsize (val, c); + return val; +} static uae_u32 readbin (TCHAR **c) { uae_u32 val; @@ -433,7 +467,7 @@ static uaecptr nextaddr2 (uaecptr addr, int *next) uaecptr prev, prevx; int size, sizex; - if (addr >= lastaddr()) { + if (addr >= lastaddr ()) { *next = -1; return 0xffffffff; } @@ -492,10 +526,15 @@ static uaecptr nextaddr2 (uaecptr addr, int *next) return addr; } -static uaecptr nextaddr (uaecptr addr, uaecptr *end) +static uaecptr nextaddr (uaecptr addr, uaecptr last, uaecptr *end) { uaecptr paddr = addr; int next; + if (last && 0) { + if (addr >= last) + return 0xffffffff; + return addr + 1; + } if (addr == 0xffffffff) { if (end) *end = currprefs.chipmem_size; @@ -503,7 +542,7 @@ static uaecptr nextaddr (uaecptr addr, uaecptr *end) } if (end) next = *end; - addr = nextaddr2(addr + 1, &next); + addr = nextaddr2 (addr + 1, &next); if (end) *end = next; #if 0 @@ -1183,14 +1222,14 @@ static void deepcheatsearch (TCHAR **c) (*c)++; } if (more_params (c)) - maxdiff = readint(c); + maxdiff = readint (c); if (!memtmp || v == 'S') { first = 1; xfree (memtmp); memsize = 0; addr = 0xffffffff; - while ((addr = nextaddr (addr, &end)) != 0xffffffff) { + while ((addr = nextaddr (addr, 0, &end)) != 0xffffffff) { memsize += end - addr; addr = end - 1; } @@ -1201,7 +1240,7 @@ static void deepcheatsearch (TCHAR **c) memset (memtmp + memsize, 0xff, memsize2); p1 = memtmp; addr = 0xffffffff; - while ((addr = nextaddr (addr, &end)) != 0xffffffff) { + while ((addr = nextaddr (addr, 0, &end)) != 0xffffffff) { for (i = addr; i < end; i++) *p1++ = get_byte (i); addr = end - 1; @@ -1221,7 +1260,7 @@ static void deepcheatsearch (TCHAR **c) addrcnt = 0; cnt = 0; addr = 0xffffffff; - while ((addr = nextaddr (addr, NULL)) != 0xffffffff) { + while ((addr = nextaddr (addr, 0, NULL)) != 0xffffffff) { uae_s32 b, b2; int doremove = 0; int addroff = addrcnt >> 3; @@ -1264,7 +1303,7 @@ static void deepcheatsearch (TCHAR **c) } else { p1[addrcnt] = b >> 8; p1[addrcnt + 1] = b >> 0; - addr = nextaddr (addr, NULL); + addr = nextaddr (addr, 0, NULL); if (addr == 0xffffffff) break; addrcnt += 2; @@ -1277,7 +1316,7 @@ static void deepcheatsearch (TCHAR **c) cnt = 0; addrcnt = 0; addr = 0xffffffff; - while ((addr = nextaddr(addr, NULL)) != 0xffffffff) { + while ((addr = nextaddr(addr, 0, NULL)) != 0xffffffff) { int addroff = addrcnt >> 3; int addrmask = (size == 1 ? 1 : 3) << (addrcnt & 7); if (p2[addroff] & addrmask) @@ -1306,7 +1345,7 @@ static void cheatsearch (TCHAR **c) memsize = 0; addr = 0xffffffff; - while ((addr = nextaddr (addr, &end)) != 0xffffffff) { + while ((addr = nextaddr (addr, 0, &end)) != 0xffffffff) { memsize += end - addr; addr = end - 1; } @@ -1324,22 +1363,10 @@ static void cheatsearch (TCHAR **c) vlist = xcalloc (uae_u8, listsize >> 3); return; } - val = readint (c); - if (first) { - if (val > 255) - size = 2; - if (val > 65535) - size = 3; - if (val > 16777215) - size = 4; - } - ignore_ws (c); - if (more_params (c)) - size = readint (c); - if (size > 4) - size = 4; - if (size < 1) - size = 1; + if (first) + val = readint (c, &size); + else + val = readint (c); if (vlist == NULL) { listsize = memsize; @@ -1352,7 +1379,7 @@ static void cheatsearch (TCHAR **c) clearcheater (); addr = 0xffffffff; prevmemcnt = memcnt = 0; - while ((addr = nextaddr (addr, &end)) != 0xffffffff) { + while ((addr = nextaddr (addr, 0, &end)) != 0xffffffff) { if (addr + size < end) { for (i = 0; i < size; i++) { int shift = (size - i - 1) * 8; @@ -1425,7 +1452,7 @@ static void illg_init (void) return; } addr = 0xffffffff; - while ((addr = nextaddr (addr, &end)) != 0xffffffff) { + while ((addr = nextaddr (addr, 0, &end)) != 0xffffffff) { if (end < 0x01000000) { memset (illgdebug + addr, c, end - addr); } else { @@ -1663,7 +1690,7 @@ static int memwatch_func (uaecptr addr, int rwi, int size, uae_u32 *valp) uae_u32 mask = (1 << (m->size * 8)) - 1; int scnt = size; for (;;) { - if (((m->val & mask) & m->valmask) == ((val & mask) & m->valmask)) + if (((m->val & mask) & m->val_mask) == ((val & mask) & m->val_mask)) trigger = 1; if (mask & 0x80000000) break; @@ -1701,12 +1728,15 @@ static int memwatch_func (uaecptr addr, int rwi, int size, uae_u32 *valp) if (m->val_enabled) { int shift = addr - m->addr; int max = 0; - if (m->val > 256) + if (m->val_size == 2) { max = 1; - if (m->val > 65536) + shift = 1 - ((addr - m->addr) & 1); + } else if (m->val_size == 4) { max = 3; - shift &= max; + shift = 3 - ((addr - m->addr) & 3); + } *valp = m->val >> ((max - shift) * 8); + return 1; } return 0; } @@ -2001,6 +2031,19 @@ int debug_bankchange (int mode) return -1; } +static TCHAR *getsizechar (int size) +{ + if (size == 4) + return L".l"; + if (size == 3) + return L".3"; + if (size == 2) + return L".w"; + if (size == 1) + return L".b"; + return L""; +} + void memwatch_dump2 (TCHAR *buf, int bufsize, int num) { int i; @@ -2019,7 +2062,7 @@ void memwatch_dump2 (TCHAR *buf, int bufsize, int num) if (mwn->frozen) buf = buf_out (buf, &bufsize, L"F"); if (mwn->val_enabled) - buf = buf_out (buf, &bufsize, L" =%X", mwn->val); + buf = buf_out (buf, &bufsize, L" =%X%s", mwn->val, getsizechar (mwn->val_size)); if (mwn->modval_written) buf = buf_out (buf, &bufsize, L" =M"); if (mwn->mustchange) @@ -2107,7 +2150,7 @@ static void memwatch (TCHAR **c) mwn->size = 1; mwn->rwi = 7; mwn->val_enabled = 0; - mwn->valmask = 0xffffffff; + mwn->val_mask = 0xffffffff; mwn->frozen = 0; mwn->modval_written = 0; ignore_ws (c); @@ -2140,7 +2183,7 @@ static void memwatch (TCHAR **c) } else if (_totupper (**c) == 'C') { mwn->mustchange = 1; } else { - mwn->val = readhex (c); + mwn->val = readhex (c, &mwn->val_size); mwn->val_enabled = 1; } } @@ -2161,17 +2204,8 @@ static void writeintomem (TCHAR **c) ignore_ws(c); addr = readhex (c); ignore_ws(c); - val = readhex (c); - if (val > 0xffff) - len = 4; - else if (val > 0xff) - len = 2; - else - len = 1; - if (more_params (c)) { - ignore_ws (c); - len = readint (c); - } + val = readhex (c, &len); + if (len == 4) { put_long (addr, val); cc = 'L'; @@ -2587,7 +2621,7 @@ static void searchmem (TCHAR **cc) endaddr = readhex (cc); } console_out_f (L"Searching from %08X to %08X..\n", addr, endaddr); - while ((addr = nextaddr (addr, NULL)) != 0xffffffff) { + while ((addr = nextaddr (addr, endaddr, NULL)) != 0xffffffff) { if (addr == endaddr) break; for (i = 0; i < sslen; i++) { @@ -2852,7 +2886,7 @@ static void disk_debug (TCHAR **inptr) disk_debug_mode |= DISK_DEBUG_PIO; } if (more_params(inptr)) - disk_debug_track = readint(inptr); + disk_debug_track = readint (inptr); if (disk_debug_track < 0 || disk_debug_track > 2 * 83) disk_debug_track = -1; if (disk_debug_logging == 0) @@ -2880,7 +2914,7 @@ static void find_ea (TCHAR **inptr) end = readhex (inptr); } console_out_f (L"Searching from %08X to %08X\n", addr, end); - while((addr = nextaddr(addr, &end)) != 0xffffffff) { + while((addr = nextaddr(addr, end, &end)) != 0xffffffff) { if ((addr & 1) == 0 && addr + 6 <= end) { sea = 0xffffffff; dea = 0xffffffff; @@ -3037,7 +3071,7 @@ static void debug_1 (void) inptr++; inputdevice_logging = 1 | 2; if (more_params (&inptr)) - inputdevice_logging = readint(&inptr); + inputdevice_logging = readint (&inptr); console_out_f (L"Input logging level %d\n", inputdevice_logging); } else if (*inptr == 'm') { memory_map_dump_2 (0); diff --git a/disk.cpp b/disk.cpp index f5616ad4..f7adccba 100644 --- a/disk.cpp +++ b/disk.cpp @@ -7,7 +7,7 @@ * Copyright 1995-2001 Bernd Schmidt * Copyright 2000-2003 Toni Wilen * -* High Density Drive Handling by Dr. Adil Temel (C) 2001 [atemel1@hotmail.com] +* Original High Density Drive Handling by Dr. Adil Temel (C) 2001 [atemel1@hotmail.com] * */ @@ -91,10 +91,6 @@ static uae_u8 writebuffer[544 * MAX_SECTORS]; #define DSKREADY_TIME 4 #define DSKREADY_DOWN_TIME 10 -#if 0 -#define MAX_DISK_WORDS_PER_LINE 50 /* depends on floppy_speed */ -static uae_u32 dma_tab[MAX_DISK_WORDS_PER_LINE + 1]; -#endif static int dskdmaen, dsklength, dsklength2, dsklen; static uae_u16 dskbytr_val; static uae_u32 dskpt; @@ -2886,9 +2882,6 @@ static void disk_doupdate_read (drive * drv, int floppybits) bitoffset &= 15; floppybits -= drv->trackspeed; } -#if 0 - dma_tab[j] = 0xffffffff; -#endif } static void disk_dma_debugmsg (void) @@ -2897,24 +2890,6 @@ static void disk_dma_debugmsg (void) dsklength, dsklength, (adkcon & 0x400) ? dsksync : 0xffff, dskpt, adkcon, M68K_GETPC); } -#if 0 -/* disk DMA fetch happens on real Amiga at the beginning of next horizontal line -(cycles 9, 11 and 13 according to hardware manual) We transfer all DMA'd -data at cycle 0. I don't think any program cares about this small difference. -*/ -static void dodmafetch (void) -{ - int i; - - i = 0; - while (dma_tab[i] != 0xffffffff && dskdmaen != 3 && (dmacon & 0x210) == 0x210) { - put_word (dskpt, dma_tab[i++]); - dskpt += 2; - } - dma_tab[0] = 0xffffffff; -} -#endif - /* this is very unoptimized. DSKBYTR is used very rarely, so it should not matter. */ uae_u16 DSKBYTR (int hpos) @@ -3360,9 +3335,6 @@ void DISK_init (void) { int dr; -#if 0 - dma_tab[0] = 0xffffffff; -#endif for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) { drive *drv = &floppy[dr]; /* reset all drive types to 3.5 DD */ diff --git a/drawing.cpp b/drawing.cpp index 8aa77b39..8cdbbca2 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -212,7 +212,7 @@ static int bplres; static int plf1pri, plf2pri, bplxor; static uae_u32 plf_sprite_mask; static int sbasecol[2] = { 16, 16 }; -static int brdsprt, brdblank, brdblank_changed; +static int brdsprt, brdblank, brdblank_changed, hposendblank; bool picasso_requested_on; bool picasso_on; @@ -674,12 +674,21 @@ STATIC_INLINE uae_u32 merge_2pixel32 (uae_u32 p1, uae_u32 p2) return v; } +STATIC_INLINE xcolnr getbgc (void) +{ +#if 0 + if (hposendblank) + return xcolors[0xf00]; +#endif + return (brdblank || hposendblank) ? 0 : colors_for_drawing.acolors[0]; +} + static void fill_line_16 (uae_u8 *buf, unsigned int start, unsigned int stop) { uae_u16 *b = (uae_u16 *)buf; unsigned int i; unsigned int rem = 0; - xcolnr col = brdblank ? 0 : colors_for_drawing.acolors[0]; + xcolnr col = getbgc (); if (((long)&b[start]) & 1) b[start++] = (uae_u16) col; if (start >= stop) @@ -700,7 +709,7 @@ static void fill_line_32 (uae_u8 *buf, unsigned int start, unsigned int stop) { uae_u32 *b = (uae_u32 *)buf; unsigned int i; - xcolnr col = brdblank ? 0 : colors_for_drawing.acolors[0]; + xcolnr col = getbgc (); for (i = start; i < stop; i++) b[i] = col; } @@ -714,7 +723,7 @@ static void pfield_do_fill_line (int start, int stop) } } -STATIC_INLINE void fill_line_2 (int startpos, int len, int blank) +STATIC_INLINE void fill_line2 (int startpos, int len) { int shift; int nints, nrem; @@ -731,16 +740,16 @@ STATIC_INLINE void fill_line_2 (int startpos, int len, int blank) nrem = nints & 7; nints &= ~7; start = (int *)(((uae_u8*)xlinebuffer) + (startpos << shift)); - val = blank ? 0 : colors_for_drawing.acolors[0]; + val = getbgc (); for (; nints > 0; nints -= 8, start += 8) { *start = val; - *(start + 1) = val; - *(start + 2) = val; - *(start + 3) = val; - *(start + 4) = val; - *(start + 5) = val; - *(start + 6) = val; - *(start + 7) = val; + *(start+1) = val; + *(start+2) = val; + *(start+3) = val; + *(start+4) = val; + *(start+5) = val; + *(start+6) = val; + *(start+7) = val; } switch (nrem) { @@ -761,15 +770,14 @@ STATIC_INLINE void fill_line_2 (int startpos, int len, int blank) } } -STATIC_INLINE void fill_line (void) +static void fill_line (void) { - int endpos = visible_left_border + gfxvidinfo.width; - int endposh = coord_hw_to_window_x (hsyncstartpos * 2); - if (endpos < endposh) { - fill_line_2 (visible_left_border, gfxvidinfo.width, brdblank); + if (hsyncstartposnative > visible_left_border + gfxvidinfo.width || hposendblank) { + fill_line2 (visible_left_border, gfxvidinfo.width); } else { - fill_line_2 (visible_left_border, endposh - visible_left_border, brdblank); - fill_line_2 (endposh, gfxvidinfo.width - endposh, 1); + fill_line2 (visible_left_border, hsyncstartposnative); + hposendblank = 1; + fill_line2 (visible_left_border + hsyncstartposnative, gfxvidinfo.width - hsyncstartposnative); } } @@ -1849,8 +1857,12 @@ static bool isham (uae_u16 bplcon0) return 0; } -static void pfield_expand_dp_bplcon2 (int regno, int v) +static void pfield_expand_dp_bplconx (int regno, int v) { + if (regno == 0xffff) { + hposendblank = 1; + return; + } regno -= 0x1000; switch (regno) { @@ -1907,7 +1919,6 @@ STATIC_INLINE void do_color_changes (line_draw_func worker_border, line_draw_fun int lastpos = visible_left_border; int endpos = visible_left_border + gfxvidinfo.width; int diff = 1 << lores_shift; - int endposh = coord_hw_to_window_x (hsyncstartpos * 2); for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++) { int regno = curr_color_changes[i].regno; @@ -1926,17 +1937,7 @@ STATIC_INLINE void do_color_changes (line_draw_func worker_border, line_draw_fun if (nextpos_in_range > lastpos) { if (lastpos < playfield_start) { int t = nextpos_in_range <= playfield_start ? nextpos_in_range : playfield_start; - if (t == endpos) { - if (lastpos < endposh) - (*worker_border) (lastpos, endposh); - // start of hsync, blank the rest of display - int blank = brdblank; - brdblank = 1; - (*worker_border) (endposh, endpos); - brdblank = blank; - } else { - (*worker_border) (lastpos, t); - } + (*worker_border) (lastpos, t); lastpos = t; } } @@ -1948,23 +1949,13 @@ STATIC_INLINE void do_color_changes (line_draw_func worker_border, line_draw_fun } } if (nextpos_in_range > lastpos) { - if (lastpos >= playfield_end) { - if (nextpos_in_range > endposh) { - (*worker_border) (lastpos, endposh); - // start of hsync, blank the rest of display - int blank = brdblank; - brdblank = 1; - (*worker_border) (endposh, nextpos_in_range); - brdblank = blank; - } else { - (*worker_border) (lastpos, nextpos_in_range); - } - } + if (lastpos >= playfield_end) + (*worker_border) (lastpos, nextpos_in_range); lastpos = nextpos_in_range; } if (i != dip_for_drawing->last_color_change) { if (regno >= 0x1000) { - pfield_expand_dp_bplcon2 (regno, value); + pfield_expand_dp_bplconx (regno, value); } else { color_reg_set (&colors_for_drawing, regno, value); colors_for_drawing.acolors[regno] = getxcolor (value); @@ -1974,7 +1965,6 @@ STATIC_INLINE void do_color_changes (line_draw_func worker_border, line_draw_fun break; } } - enum double_how { dh_buf, dh_line, @@ -2748,22 +2738,24 @@ void finish_drawing_frame (void) if (where2 < 0) continue; + hposendblank = 0; pfield_draw_line (line, where2, amiga2aspect_line_map[i1 + 1]); } + /* clear possible old garbage at the bottom if emulated area become smaller */ for (i = last_max_ypos; i < gfxvidinfo.height; i++) { int i1 = i + min_ypos_for_screen; int line = i + thisframe_y_adjust_real; int where2 = amiga2aspect_line_map[i1]; - xcolnr tmp; if (where2 >= gfxvidinfo.height) break; if (where2 < 0) continue; - tmp = colors_for_drawing.acolors[0]; - colors_for_drawing.acolors[0] = getxcolor (0); + + hposendblank = i >= last_max_ypos + 16; + xlinebuffer = gfxvidinfo.linemem; if (xlinebuffer == 0) xlinebuffer = row_map[where2]; @@ -2771,7 +2763,6 @@ void finish_drawing_frame (void) fill_line (); linestate[line] = LINE_UNDECIDED; do_flush_line (where2); - colors_for_drawing.acolors[0] = tmp; } if (currprefs.leds_on_screen) { diff --git a/include/blkdev.h b/include/blkdev.h index 7cd2f764..7d390e7c 100644 --- a/include/blkdev.h +++ b/include/blkdev.h @@ -23,10 +23,45 @@ #define INQ_NODEV 0x1F /* Unknown or no device */ #define INQ_NOTPR 0x1F /* Logical unit not present (SCSI-1) */ +#define MAX_TOC_ENTRIES 103 +struct cd_toc +{ + uae_u8 adr, control; + uae_u8 tno; + uae_u8 point; + uae_u8 track; + int address; // LSN + int paddress; // LSN + uae_u8 zero; + uae_u8 crc[2]; +}; +struct cd_toc_head +{ + int first_track, first_track_offset; + int last_track, last_track_offset; + int lastaddress; // LSN + int tracks; + int points; + 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) + +#define AUDIO_STATUS_NOT_SUPPORTED 0x00 +#define AUDIO_STATUS_IN_PROGRESS 0x11 +#define AUDIO_STATUS_PAUSED 0x12 +#define AUDIO_STATUS_PLAY_COMPLETE 0x13 +#define AUDIO_STATUS_PLAY_ERROR 0x14 +#define AUDIO_STATUS_NO_STATUS 0x15 #define DF_SCSI 0 #define DF_IOCTL 1 @@ -44,6 +79,7 @@ struct device_info { int id; TCHAR label[MAX_DPATH]; TCHAR mediapath[MAX_DPATH]; + struct cd_toc_head toc; }; struct device_scsi_info { @@ -71,21 +107,23 @@ typedef int (*open_bus_func)(int flags); typedef void (*close_bus_func)(void); typedef int (*open_device_func)(int); typedef void (*close_device_func)(int); -typedef struct device_info* (*info_device_func)(int, struct device_info*); +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*); +typedef void (*play_subchannel_callback)(uae_u8*, int); + typedef int (*pause_func)(int, int); typedef int (*stop_func)(int); -typedef int (*play_func)(int, uae_u32, uae_u32, int); +typedef int (*play_func)(int, int, int, int, play_subchannel_callback); typedef void (*volume_func)(int, uae_u16); -typedef uae_u8* (*qcode_func)(int); -typedef uae_u8* (*toc_func)(int); -typedef uae_u8* (*read_func)(int, int); -typedef uae_u8* (*rawread_func)(int, int, int); -typedef int (*write_func)(int, int); +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 (*write_func)(int, uae_u8*, int, int); typedef int (*isatapi_func)(int); typedef int (*ismedia_func)(int, int); @@ -126,26 +164,34 @@ extern int sys_command_open (int mode, int unitnum); extern void sys_command_close (int mode, 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); +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, uae_u32 startmsf, uae_u32 endmsf, int); +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 uae_u8 *sys_command_cd_qcode (int mode, int unitnum); -extern uae_u8 *sys_command_cd_toc (int mode, int unitnum); -extern uae_u8 *sys_command_cd_read (int mode, int unitnum, int offset); -extern uae_u8 *sys_command_cd_rawread (int mode, int unitnum, int offset, int size); -extern uae_u8 *sys_command_read (int mode, int unitnum, int offset); -extern int sys_command_write (int mode, int unitnum, int offset); +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 int sys_command_scsi_direct (int unitnum, uaecptr request); extern int sys_command_ismedia (int mode, int unitnum, int quick); -void scsi_atapi_fixup_pre (uae_u8 *scsi_cmd, int *len, uae_u8 **data, int *datalen, int *parm); -void scsi_atapi_fixup_post (uae_u8 *scsi_cmd, int len, uae_u8 *olddata, uae_u8 *data, int *datalen, int parm); +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); + +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); -void scsi_log_before (uae_u8 *cdb, int cdblen, uae_u8 *data, int datalen); -void scsi_log_after (uae_u8 *data, int datalen, uae_u8 *sense, int senselen); +extern void cdimage_vsync (void); -extern void cdimage_vsync (void); \ No newline at end of file +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 diff --git a/include/cdtv.h b/include/cdtv.h index b632d94a..c51b2120 100644 --- a/include/cdtv.h +++ b/include/cdtv.h @@ -26,5 +26,7 @@ extern void rethink_cdtv (void); extern void cdtv_scsi_int (void); extern void cdtv_scsi_clear_int (void); +extern bool cdtv_front_panel (int); + #endif diff --git a/include/custom.h b/include/custom.h index 61d77941..1fe32c9f 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 hsyncstartpos; +extern int hsyncstartposnative; 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/debug.h b/include/debug.h index c9dd6d59..8f49ac7b 100644 --- a/include/debug.h +++ b/include/debug.h @@ -49,16 +49,16 @@ extern struct breakpoint_node bpnodes[BREAKPOINT_TOTAL]; #define MEMWATCH_TOTAL 8 struct memwatch_node { - uaecptr addr; - int size; - int rwi; - uae_u32 val, valmask; - int mustchange; - int val_enabled; - uae_u32 modval; - int modval_written; - int frozen; - uaecptr pc; + uaecptr addr; + int size; + int rwi; + uae_u32 val, val_mask; + int val_size, val_enabled; + int mustchange; + uae_u32 modval; + int modval_written; + int frozen; + uaecptr pc; }; extern struct memwatch_node mwnodes[MEMWATCH_TOTAL]; diff --git a/include/keyboard.h b/include/keyboard.h index d61c333b..fd45a90c 100644 --- a/include/keyboard.h +++ b/include/keyboard.h @@ -158,7 +158,9 @@ enum aks { AKS_ENTERGUI = 0x200, AKS_SCREENSHOT_FILE, AKS_SCREENSHOT_CLIPBOARD, AKS_DISKSWAPPER_NEXT,AKS_DISKSWAPPER_PREV, AKS_DISKSWAPPER_INSERT0,AKS_DISKSWAPPER_INSERT1,AKS_DISKSWAPPER_INSERT2,AKS_DISKSWAPPER_INSERT3, AKS_DISK_PREV0, AKS_DISK_PREV1, AKS_DISK_PREV2, AKS_DISK_PREV3, - AKS_DISK_NEXT0, AKS_DISK_NEXT1, AKS_DISK_NEXT2, AKS_DISK_NEXT3 + AKS_DISK_NEXT0, AKS_DISK_NEXT1, AKS_DISK_NEXT2, AKS_DISK_NEXT3, + AKS_CDTV_FRONT_PANEL_STOP, AKS_CDTV_FRONT_PANEL_PLAYPAUSE, AKS_CDTV_FRONT_PANEL_PREV, + AKS_CDTV_FRONT_PANEL_NEXT, AKS_CDTV_FRONT_PANEL_REW, AKS_CDTV_FRONT_PANEL_FF }; extern int target_checkcapslock (int, int *); \ No newline at end of file diff --git a/include/options.h b/include/options.h index 95ced228..7c106f0e 100644 --- a/include/options.h +++ b/include/options.h @@ -371,6 +371,8 @@ struct uae_prefs { int win32_kbledmode; TCHAR win32_commandpathstart[MAX_DPATH]; TCHAR win32_commandpathend[MAX_DPATH]; + TCHAR win32_parjoyport0[MAX_DPATH]; + TCHAR win32_parjoyport1[MAX_DPATH]; bool statecapture; int statecapturerate, statecapturebuffersize; diff --git a/include/savestate.h b/include/savestate.h index 4433446e..d60b67f3 100644 --- a/include/savestate.h +++ b/include/savestate.h @@ -97,6 +97,9 @@ extern uae_u8 *restore_cdtv (uae_u8 *src); extern uae_u8 *save_cdtv (int *len); extern void restore_cdtv_finish (void); +extern uae_u8 *restore_dmac (uae_u8 *src); +extern uae_u8 *save_dmac (int *len); + extern uae_u8 *restore_filesys (uae_u8 *src); extern uae_u8 *save_filesys (int num, int *len); extern uae_u8 *restore_filesys_common (uae_u8 *src); diff --git a/include/scsidev.h b/include/scsidev.h index b76904b6..f35bbf5d 100644 --- a/include/scsidev.h +++ b/include/scsidev.h @@ -12,12 +12,13 @@ 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 scsi_do_disk_change (int device_id, int insert, int *pollmode); int scsi_do_disk_device_change (void); extern int log_scsi; #ifdef _WIN32 +#define UAESCSI_CDEMU 0 #define UAESCSI_SPTI 1 #define UAESCSI_SPTISCAN 2 #define UAESCSI_ASPI_FIRST 3 diff --git a/inputdevice.cpp b/inputdevice.cpp index 18f7dba4..4b0a4bca 100644 --- a/inputdevice.cpp +++ b/inputdevice.cpp @@ -47,6 +47,7 @@ #include "autoconf.h" #include "rp.h" #include "dongle.h" +#include "cdtv.h" extern int bootrom_header, bootrom_items; @@ -412,6 +413,7 @@ static struct uae_input_device_kbr_default *keyboard_default; #define KBR_DEFAULT_MAP_XA2 7 #define KBR_DEFAULT_MAP_ARCADIA 8 #define KBR_DEFAULT_MAP_ARCADIA_XA 9 +#define KBR_DEFAULT_MAP_CDTV 10 static int **keyboard_default_kbmaps; static int mouse_axis[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS]; @@ -2478,6 +2480,15 @@ void inputdevice_add_inputcode (int code, int state) void inputdevice_do_keyboard (int code, int state) { + if (code >= 0x72 && code <= 0x77) { // CDTV keys + if (cdtv_front_panel (-1)) { + // front panel active + if (!state) + return; + cdtv_front_panel (code - 0x72); + return; + } + } if (code < 0x80) { uae_u8 key = code | (state ? 0x00 : 0x80); keybuf[key & 0x7f] = (key & 0x80) ? 0 : 1; @@ -2727,6 +2738,16 @@ void inputdevice_handle_inputcode (void) case AKS_DISK_NEXT3: disk_prevnext (code - AKS_DISK_NEXT0, 1); break; +#ifdef CDTV + case AKS_CDTV_FRONT_PANEL_STOP: + case AKS_CDTV_FRONT_PANEL_PLAYPAUSE: + case AKS_CDTV_FRONT_PANEL_PREV: + case AKS_CDTV_FRONT_PANEL_NEXT: + case AKS_CDTV_FRONT_PANEL_REW: + case AKS_CDTV_FRONT_PANEL_FF: + cdtv_front_panel (code - AKS_CDTV_FRONT_PANEL_STOP); + break; +#endif } } @@ -3559,6 +3580,11 @@ static int ip_mousecdtv[] = INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_2ND_BUTTON, -1 }; +static int ip_mediacdtv[] = +{ + INPUTEVENT_KEY_CDTV_PLAYPAUSE, INPUTEVENT_KEY_CDTV_STOP, INPUTEVENT_KEY_CDTV_PREV, INPUTEVENT_KEY_CDTV_NEXT, + -1 +}; static int ip_arcadia[] = { INPUTEVENT_SPC_ARCADIA_DIAGNOSTICS, INPUTEVENT_SPC_ARCADIA_PLAYER1, INPUTEVENT_SPC_ARCADIA_PLAYER2, INPUTEVENT_SPC_ARCADIA_COIN1, INPUTEVENT_SPC_ARCADIA_COIN2, @@ -4220,6 +4246,9 @@ static void compatibility_copy (struct uae_prefs *prefs, bool gameports) if (JSEM_ISXARCADE1 (i, prefs) || JSEM_ISXARCADE2 (i, prefs)) setcompakb (keyboard_default_kbmaps[KBR_DEFAULT_MAP_ARCADIA_XA], ip_arcadiaxa, JSEM_ISXARCADE2 (i, prefs) ? 1 : 0, prefs->jports[i].autofire); } + if (0 && currprefs.cs_cdtvcd) { + setcompakb (keyboard_default_kbmaps[KBR_DEFAULT_MAP_CDTV], ip_mediacdtv, 0, 0); + } // parport for (i = 2; i < MAX_JPORTS; i++) { diff --git a/inputevents.def b/inputevents.def index be7f1577..e7ae6a7f 100644 --- a/inputevents.def +++ b/inputevents.def @@ -363,3 +363,11 @@ DEFEVENT(SPC_ARCADIA_PLAYER1,L"Arcadia player 1",AM_K,0,0,AKS_ARCADIAPLY1) DEFEVENT(SPC_ARCADIA_PLAYER2,L"Arcadia player 2",AM_K,0,0,AKS_ARCADIAPLY2) DEFEVENT(SPC_ARCADIA_COIN1,L"Arcadia coin player 1",AM_K,0,0,AKS_ARCADIACOIN1) DEFEVENT(SPC_ARCADIA_COIN2,L"Arcadia coin player 2",AM_K,0,0,AKS_ARCADIACOIN2) + +DEFEVENT(SPC_CDTV_FRONT_PANEL_STOP,L"CDTV Front Panel Stop",AM_K,0,0,AKS_CDTV_FRONT_PANEL_STOP) +DEFEVENT(SPC_CDTV_FRONT_PANEL_PLAYPAUSE,L"CDTV Front Panel Play/Pause",AM_K,0,0,AKS_CDTV_FRONT_PANEL_PLAYPAUSE) +DEFEVENT(SPC_CDTV_FRONT_PANEL_PREV,L"CDTV Front Panel Previous",AM_K,0,0,AKS_CDTV_FRONT_PANEL_PREV) +DEFEVENT(SPC_CDTV_FRONT_PANEL_NEXT,L"CDTV Front Panel Next",AM_K,0,0,AKS_CDTV_FRONT_PANEL_NEXT) +DEFEVENT(SPC_CDTV_FRONT_PANEL_REW,L"CDTV Front Panel Rewind",AM_K,0,0,AKS_CDTV_FRONT_PANEL_REW) +DEFEVENT(SPC_CDTV_FRONT_PANEL_FF,L"CDTV Front Panel Fast Forward",AM_K,0,0,AKS_CDTV_FRONT_PANEL_FF) + diff --git a/keybuf.cpp b/keybuf.cpp index 1ea097f4..d3edb3f3 100644 --- a/keybuf.cpp +++ b/keybuf.cpp @@ -42,6 +42,7 @@ int get_next_key (void) key = keybuf[kpb_last]; if (++kpb_last == 256) kpb_last = 0; + //write_log (L"%02x:%d\n", key >> 1, key & 1); return key; } diff --git a/od-win32/blkdev_win32_aspi.cpp b/od-win32/blkdev_win32_aspi.cpp index 7d67b3af..e4899ba0 100644 --- a/od-win32/blkdev_win32_aspi.cpp +++ b/od-win32/blkdev_win32_aspi.cpp @@ -977,7 +977,7 @@ static int execscsicmd_direct (int unitnum, struct amigascsi *as) return io_error; } -static struct device_info *info_device (int unitnum, struct device_info *di) +static struct device_info *info_device (int unitnum, struct device_info *di, int quick) { struct scsi_info *sif = &si[unitnum]; if (unitnum >= unitcnt) @@ -1008,7 +1008,7 @@ void win32_aspi_media_change (TCHAR driveletter, int insert) if (now != si[i].mediainserted) { write_log (L"ASPI: media change %c %d\n", driveletter, insert); si[i].mediainserted = now; - scsi_do_disk_change (i + 1, insert); + scsi_do_disk_change (i + 1, insert, NULL); } } } diff --git a/od-win32/blkdev_win32_ioctl.cpp b/od-win32/blkdev_win32_ioctl.cpp index bb247111..52c5364a 100644 --- a/od-win32/blkdev_win32_ioctl.cpp +++ b/od-win32/blkdev_win32_ioctl.cpp @@ -3,7 +3,7 @@ * * WIN32 CDROM/HD low level access code (IOCTL) * -* Copyright 2002 Toni Wilen +* Copyright 2002-2010 Toni Wilen * */ @@ -45,8 +45,6 @@ struct dev_info_ioctl { int mediainserted; int type; int blocksize; - int mciid; - int cdda; CDROM_TOC toc; UINT errormode; int playend; @@ -59,7 +57,12 @@ struct dev_info_ioctl { uae_u32 cd_last_pos; HWAVEOUT cdda_wavehandle; int cdda_start, cdda_end; - uae_u8 subcode[96 * CDDA_BUFFERS]; + uae_u8 subcode[SUB_CHANNEL_SIZE * CDDA_BUFFERS]; + uae_u8 subcodebuf[SUB_CHANNEL_SIZE]; + bool subcodevalid; + play_subchannel_callback cdda_subfunc; + struct device_info di; + uae_sem_t sub_sem, sub_sem2; }; static int MCICDA; @@ -68,7 +71,7 @@ static struct dev_info_ioctl ciw32[MAX_TOTAL_DEVICES]; static void seterrormode (int unitnum) { - ciw32[unitnum].errormode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); + ciw32[unitnum].errormode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); } static void reseterrormode (int unitnum) { @@ -134,23 +137,6 @@ static int win32_error (int unitnum, const TCHAR *format,...) return err; } -/* convert minutes, seconds and frames -> logical sector number */ -static int msf2lsn (int msf) -{ - int sector = (((msf >> 16) & 0xff) * 60 * 75 + ((msf >> 8) & 0xff) * 75 + ((msf >> 0) & 0xff)); - return sector; -} - -/* convert logical sector number -> minutes, seconds and frames */ -static int lsn2msf (int sectors) -{ - int msf; - msf = (sectors / (75 * 60)) << 16; - msf |= ((sectors / 75) % 60) << 8; - msf |= (sectors % 75) << 0; - return msf; -} - static int close_createfile (int unitnum) { struct dev_info_ioctl *ciw = &ciw32[unitnum]; @@ -168,29 +154,9 @@ static int close_createfile (int unitnum) return 0; } -static int close_mci (int unitnum) -{ - struct dev_info_ioctl *ciw = &ciw32[unitnum]; - MCI_GENERIC_PARMS gp = { 0 }; - - ciw->playend = -1; - if (ciw->mciid > 0) { - if (log_scsi) - write_log (L"IOCTL: MCI close\n"); - mcierr (L"MCI_STOP", mciSendCommand (ciw->mciid, MCI_STOP, MCI_WAIT, (DWORD_PTR)&gp)); - mcierr (L"MCI_CLOSE", mciSendCommand (ciw->mciid, MCI_CLOSE, MCI_WAIT, (DWORD_PTR)&gp)); - if (log_scsi) - write_log (L"IOCTL: MCI close completed\n"); - ciw->mciid = 0; - return 1; - } - return 0; -} - static int open_createfile (int unitnum, int fullaccess) { struct dev_info_ioctl *ciw = &ciw32[unitnum]; - int closed = 0; int cnt = 50; DWORD len; @@ -201,7 +167,6 @@ static int open_createfile (int unitnum, int fullaccess) return 1; } } - closed = close_mci (unitnum); if (log_scsi) write_log (L"IOCTL: opening IOCTL %s\n", ciw->devname); for (;;) { @@ -220,20 +185,10 @@ static int open_createfile (int unitnum, int fullaccess) } } } - if (ciw->h == INVALID_HANDLE_VALUE) { - DWORD err = GetLastError (); - if (err == ERROR_SHARING_VIOLATION) { - if (closed && cnt > 0) { - cnt--; - Sleep (10); - continue; - } - } - if (closed) - write_log (L"IOCTL: failed to re-open '%s', err=%d\n", ciw->devname, GetLastError ()); - return 0; - } - break; + if (ciw->h != INVALID_HANDLE_VALUE) + break; + write_log (L"IOCTL: failed to open '%s', err=%d\n", ciw->devname, GetLastError ()); + return 0; } if (!DeviceIoControl (ciw->h, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &len, NULL)) write_log (L"IOCTL: FSCTL_ALLOW_EXTENDED_DASD_IO returned %d\n", GetLastError ()); @@ -242,40 +197,6 @@ static int open_createfile (int unitnum, int fullaccess) return 1; } -static int open_mci (int unitnum) -{ - struct dev_info_ioctl *ciw = &ciw32[unitnum]; - TCHAR elname[10]; - TCHAR alname[100]; - MCI_OPEN_PARMS mciOpen; - DWORD err, flags; - int closed = 0; - - if (ciw->mciid > 0 || MCICDA == 0) - return 1; - ciw->playend = -1; - closed = close_createfile (unitnum); - if (log_scsi) - write_log (L"IOCTL: MCI opening %s\n", ciw->drvlettername); - memset (&mciOpen, 0, sizeof (mciOpen)); - mciOpen.lpstrDeviceType = (LPWSTR)MCI_DEVTYPE_CD_AUDIO; - _stprintf (elname, L"%c:", ciw->drvletter); - _stprintf (alname, L"CD%u:", GetCurrentTime ()); - mciOpen.lpstrElementName = elname; - mciOpen.lpstrAlias = alname; - flags = MCI_OPEN_ELEMENT | MCI_OPEN_SHAREABLE | MCI_OPEN_ALIAS | MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID | MCI_WAIT; - err = mciSendCommand (0, MCI_OPEN, flags, (DWORD_PTR)(LPVOID)&mciOpen); - ciw->mciid = mciOpen.wDeviceID; - if (err != MMSYSERR_NOERROR) { - if (closed) - mcierr (L"MCI_OPEN", err); - return 0; - } - if (log_scsi) - write_log (L"IOCTL: MCI open completed\n"); - return 1; -} - static void cdda_closewav (struct dev_info_ioctl *ciw) { if (ciw->cdda_wavehandle != NULL) @@ -322,7 +243,7 @@ static void *cdda_play (void *v) MMRESULT mmr; int volume, volume_main; int oldplay; - + int firstloops; for (i = 0; i < 2; i++) { memset (&whdr[i], 0, sizeof (WAVEHDR)); @@ -358,11 +279,6 @@ static void *cdda_play (void *v) while (ciw->cdda_play > 0) { - if (oldplay != ciw->cdda_play) { - cdda_pos = ciw->cdda_start; - oldplay = ciw->cdda_play; - } - while (!(whdr[bufnum].dwFlags & WHDR_DONE)) { Sleep (10); if (!ciw->cdda_play) @@ -370,30 +286,62 @@ static void *cdda_play (void *v) } bufon[bufnum] = 0; + if (oldplay != ciw->cdda_play) { + cdda_pos = ciw->cdda_start; + oldplay = ciw->cdda_play; + firstloops = 25; + write_log (L"CDDA: playing from %d to %d\n", ciw->cdda_start, ciw->cdda_end); + ciw->subcodevalid = false; + } + if ((cdda_pos < ciw->cdda_end || ciw->cdda_end == 0xffffffff) && !ciw->cdda_paused && ciw->cdda_play) { RAW_READ_INFO rri; + int sectors = num_sectors; + + uae_sem_wait (&ciw->sub_sem); + ciw->subcodevalid = false; + memset (ciw->subcode, 0, sizeof ciw->subcode); + + if (firstloops > 0) { + + firstloops--; + if (ciw->cdda_subfunc) + ciw->cdda_subfunc (ciw->subcode, sectors); + memset (px[bufnum], 0, sectors * 2352); - seterrormode (unitnum); - rri.DiskOffset.QuadPart = 2048 * (cdda_pos - 150); - rri.SectorCount = num_sectors; - rri.TrackMode = RawWithSubCode; - if (!DeviceIoControl (ciw->h, IOCTL_CDROM_RAW_READ, &rri, sizeof rri, px[bufnum], num_sectors * CD_RAW_SECTOR_WITH_SUBCODE_SIZE, &len, NULL)) { - rri.TrackMode = CDDA; - if (!DeviceIoControl (ciw->h, IOCTL_CDROM_RAW_READ, &rri, sizeof rri, px[bufnum], num_sectors * 2352, &len, NULL)) { - DWORD err = GetLastError (); - write_log (L"IOCTL_CDROM_RAW_READ CDDA sector %d returned %d\n", cdda_pos - 150, err); - //ciw->cdda_play_finished = 1; - //ciw->cdda_play = -1; - } } else { - for (i = 0; i < num_sectors; i++) { - memcpy (ciw->subcode + i * 96, px[bufnum] + CD_RAW_SECTOR_WITH_SUBCODE_SIZE * i + 2352, 96); - } - for (i = 1; i < num_sectors; i++) { - memmove (px[bufnum] + 2352 * i, px[bufnum] + CD_RAW_SECTOR_WITH_SUBCODE_SIZE * i, 2352); + + firstloops = -1; + seterrormode (unitnum); + rri.DiskOffset.QuadPart = 2048 * (cdda_pos + 0); + rri.SectorCount = sectors; + rri.TrackMode = RawWithSubCode; + if (!DeviceIoControl (ciw->h, IOCTL_CDROM_RAW_READ, &rri, sizeof rri, px[bufnum], sectors * CD_RAW_SECTOR_WITH_SUBCODE_SIZE, &len, NULL)) { + DWORD err = GetLastError (); + write_log (L"IOCTL_CDROM_RAW_READ CDDA sector %d returned %d\n", cdda_pos, err); + if (ciw->cdda_subfunc) + ciw->cdda_subfunc (ciw->subcode, sectors); + } else { + for (i = 0; i < sectors; i++) { + memcpy (ciw->subcode + i * SUB_CHANNEL_SIZE, px[bufnum] + CD_RAW_SECTOR_WITH_SUBCODE_SIZE * i + 2352, SUB_CHANNEL_SIZE); + } + if (ciw->cdda_subfunc) + ciw->cdda_subfunc (ciw->subcode, sectors); + for (i = 1; i < sectors; i++) { + memmove (px[bufnum] + 2352 * i, px[bufnum] + CD_RAW_SECTOR_WITH_SUBCODE_SIZE * i, 2352); + } + ciw->subcodevalid = true; } + reseterrormode (unitnum); } - reseterrormode (unitnum); + + uae_sem_post (&ciw->sub_sem); + if (ciw->subcodevalid) { + uae_sem_wait (&ciw->sub_sem2); + memcpy (ciw->subcodebuf, ciw->subcode + (sectors - 1) * SUB_CHANNEL_SIZE, SUB_CHANNEL_SIZE); + uae_sem_post (&ciw->sub_sem2); + } + volume = ciw->cdda_volume; volume_main = currprefs.sound_volume; @@ -415,12 +363,15 @@ static void *cdda_play (void *v) break; } - 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; - cdda_pos = ciw->cdda_end; + if (firstloops < 0) { + 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; + cdda_pos = ciw->cdda_end; + } } + ciw->cd_last_pos = cdda_pos; } @@ -439,6 +390,7 @@ static void *cdda_play (void *v) } end: + ciw->subcodevalid = false; while (!(whdr[0].dwFlags & WHDR_DONE) || !(whdr[1].dwFlags & WHDR_DONE)) Sleep (10); for (i = 0; i < 2; i++) @@ -463,6 +415,7 @@ static void cdda_stop (int unitnum) } ciw->cdda_play_finished = 0; ciw->cdda_paused = 0; + ciw->subcodevalid = 0; } /* pause/unpause CD audio */ @@ -472,37 +425,7 @@ static int ioctl_command_pause (int unitnum, int paused) if (!unitisopen (unitnum)) return 0; - - if (ciw->mciid > 0) { - - MCI_GENERIC_PARMS gp = { 0 }; - if (paused) - mcierr(L"MCI_PAUSE", mciSendCommand (ciw->mciid, MCI_PAUSE, MCI_WAIT, (DWORD_PTR)&gp)); - else - mcierr(L"MCI_RESUME", mciSendCommand (ciw->mciid, MCI_RESUME, MCI_WAIT, (DWORD_PTR)&gp)); - - } else if (ciw->cdda) { - - ciw->cdda_paused = paused; - - } else { - - DWORD len; - int command = paused ? IOCTL_CDROM_PAUSE_AUDIO : IOCTL_CDROM_RESUME_AUDIO; - int cnt = 3; - - while (cnt-- > 0) { - seterrormode (unitnum); - if (!DeviceIoControl(ciw32[unitnum].h, command, NULL, 0, NULL, 0, &len, NULL)) { - reseterrormode (unitnum); - if (win32_error (unitnum, paused ? L"IOCTL_CDROM_PAUSE_AUDIO" : L"IOCTL_CDROM_RESUME_AUDIO") < 0) - continue; - return 0; - } - reseterrormode (unitnum); - break; - } - } + ciw->cdda_paused = paused; return 1; } @@ -515,33 +438,8 @@ static int ioctl_command_stop (int unitnum) if (!unitisopen (unitnum)) return 0; - if (ciw->mciid > 0) { - - MCI_GENERIC_PARMS gp = { 0 }; - mcierr (L"MCI_STOP", mciSendCommand (ciw->mciid, MCI_STOP, MCI_WAIT, (DWORD_PTR)&gp)); - ciw->playend = -1; - - } else if (ciw->cdda) { - - cdda_stop (unitnum); + cdda_stop (unitnum); - } else { - - DWORD len; - int cnt = 3; - - while (cnt-- > 0) { - seterrormode (unitnum); - if(!DeviceIoControl (ciw32[unitnum].h, IOCTL_CDROM_STOP_AUDIO, NULL, 0, NULL, 0, &len, NULL)) { - reseterrormode (unitnum); - if (win32_error (unitnum, L"IOCTL_CDROM_STOP_AUDIO") < 0) - continue; - return 0; - } - reseterrormode (unitnum); - break; - } - } return 1; } @@ -553,190 +451,117 @@ static void ioctl_command_volume (int unitnum, uae_u16 volume) } /* play CD audio */ -static int ioctl_command_play (int unitnum, uae_u32 start, uae_u32 end, int scan) +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)) return 0; - if (!ciw->cdda) - open_mci (unitnum); - - if (ciw->mciid > 0) { - - MCI_SET_PARMS setParms = {0}; - MCI_PLAY_PARMS playParms = {0}; - - setParms.dwTimeFormat = MCI_FORMAT_MSF; - mcierr (L"MCI_SET", mciSendCommand (ciw->mciid, MCI_SET, MCI_SET_TIME_FORMAT | MCI_WAIT, (DWORD_PTR)&setParms)); - playParms.dwFrom = MCI_MAKE_MSF((start >> 16) & 0xff, (start >> 8) & 0xff, start & 0xff); - playParms.dwTo = MCI_MAKE_MSF((end >> 16) & 0xff, (end >> 8) & 0xff, end & 0xff); - mcierr (L"MCI_PLAY", mciSendCommand (ciw->mciid, MCI_PLAY, MCI_FROM | MCI_TO, (DWORD_PTR)&playParms)); - ciw->playend = end; - - } else if (ciw->cdda) { + if (!open_createfile (unitnum, 0)) + return 0; + ciw->cdda_paused = 0; + ciw->cdda_play_finished = 0; + ciw->cdda_subfunc = subfunc; + if (!ciw->cdda_play) { + uae_start_thread (L"cdda_play", cdda_play, ciw, NULL); + } + ciw->cdda_start = startlsn; + ciw->cdda_end = endlsn; + ciw->cd_last_pos = ciw->cdda_start; + ciw->cdda_play++; - if (!open_createfile (unitnum, 0)) - return 0; - ciw->cdda_paused = 0; - ciw->cdda_play_finished = 0; - if (!ciw->cdda_play) { - uae_start_thread (L"cdda_play", cdda_play, ciw, NULL); - } - ciw->cdda_start = msf2lsn (start); - ciw->cdda_end = msf2lsn (end); - ciw->cd_last_pos = ciw->cdda_start; - ciw->cdda_play++; - - } else { - - DWORD len; - CDROM_PLAY_AUDIO_MSF pa; - int cnt = 3; - -#if 0 - { - VOLUME_CONTROL vc; - if (!DeviceIoControl(ciw32[unitnum].h, IOCTL_CDROM_GET_VOLUME, NULL, 0, &vc, sizeof(vc), &len, NULL)) - write_log (L"IOCTL_CDROM_GET_VOLUME %d\n", GetLastError()); - vc.PortVolume[0] = 0xff; - vc.PortVolume[1] = 0xff; - vc.PortVolume[2] = 0xff; - vc.PortVolume[3] = 0xff; - if (!DeviceIoControl(ciw32[unitnum].h, IOCTL_CDROM_SET_VOLUME, &vc, sizeof(vc), NULL, 0, &len, NULL)) - write_log (L"IOCTL_CDROM_SET_VOLUME %d\n", GetLastError()); - } -#endif + return 1; +} - while (cnt-- > 0) { - pa.StartingM = start >> 16; - pa.StartingS = start >> 8; - pa.StartingF = start >> 0; - pa.EndingM = end >> 16; - pa.EndingS = end >> 8; - pa.EndingF = end >> 0; - seterrormode (unitnum); - if (!DeviceIoControl (ciw32[unitnum].h, IOCTL_CDROM_PLAY_AUDIO_MSF, &pa, sizeof(pa), NULL, 0, &len, NULL)) { - reseterrormode (unitnum); - if (win32_error (unitnum, L"IOCTL_CDROM_PLAY_AUDIO_MSF %02.%02.%02-%02.%02.%02", - pa.StartingM, pa.StartingS, pa.StartingF, pa.EndingM, pa.EndingS, pa.EndingF ) < 0) continue; - return 0; - } - reseterrormode (unitnum); - break; +static void sub_deinterleave (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++; } - - return 1; } /* read qcode */ -static uae_u8 *ioctl_command_qcode (int unitnum) +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); - return NULL; + return 0; } - if (ciw->mciid > 0) { + uae_u8 *p; + int trk; + CDROM_TOC *toc = &ciw->toc; + int pos; + int msf; + int start, end; + int status; + bool valid = false; + bool regenerate = false; + + memset (buf, 0, SUBQ_SIZE); + p = buf; + + status = AUDIO_STATUS_NO_STATUS; + if (ciw->cdda_play) { + status = AUDIO_STATUS_IN_PROGRESS; + if (ciw->cdda_paused) + status = AUDIO_STATUS_PAUSED; + } else if (ciw->cdda_play_finished) { + status = AUDIO_STATUS_PLAY_COMPLETE; + } - static uae_u8 buf[4 + 12]; - MCI_STATUS_PARMS mciStatusParms; - DWORD err, mode; - uae_u8 *p; - uae_u32 pos, pos2; - int trk; + p[1] = status; + p[3] = 12; - memset (buf, 0, sizeof buf); - memset (&mciStatusParms, 0, sizeof mciStatusParms); - mciStatusParms.dwItem = MCI_STATUS_MODE; - err = mciSendCommand (ciw->mciid, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD_PTR)&mciStatusParms); - if (err != MMSYSERR_NOERROR) - return 0; - mode = mciStatusParms.dwReturn; - mciStatusParms.dwItem = MCI_STATUS_CURRENT_TRACK; - err = mciSendCommand (ciw->mciid, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD_PTR)&mciStatusParms); - if (err != MMSYSERR_NOERROR) - return 0; - trk = mciStatusParms.dwReturn - 1; - if (trk < 0) - trk = 0; - mciStatusParms.dwItem = MCI_STATUS_POSITION; - err = mciSendCommand (ciw->mciid, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD_PTR)&mciStatusParms); - if (err != MMSYSERR_NOERROR) - return 0; - pos = (((mciStatusParms.dwReturn >> 16) & 0xff) << 0) | (((mciStatusParms.dwReturn >> 8) & 0xff) << 8) | (((mciStatusParms.dwReturn >> 0) & 0xff) << 16); - - p = buf; - p[1] = AUDIO_STATUS_NO_STATUS; - if (mode == MCI_MODE_PLAY) - p[1] = AUDIO_STATUS_IN_PROGRESS; - else if (mode == MCI_MODE_PAUSE) - p[1] = AUDIO_STATUS_PAUSED; - p[3] = 12; - - p = buf + 4; - p[1] = (ciw->toc.TrackData[trk].Control << 0) | (ciw->toc.TrackData[trk].Adr << 4); - p[2] = trk + 1; - p[3] = 1; - - p[5] = (pos >> 16) & 0xff; - p[6] = (pos >> 8) & 0xff; - p[7] = (pos >> 0) & 0xff; - - pos = msf2lsn (pos); - pos2 = (ciw->toc.TrackData[trk].Address[1] << 16) | (ciw->toc.TrackData[trk].Address[2] << 8) | (ciw->toc.TrackData[trk].Address[3] << 0); - pos -= msf2lsn (pos2); - if (pos < 0) - pos = 0; - pos = lsn2msf (pos); - - p[9] = (pos >> 16) & 0xff; - p[10] = (pos >> 8) & 0xff; - p[11] = (pos >> 0) & 0xff; - - return buf; - - } else if (ciw->cdda) { - - static uae_u8 buf[4 + 12]; - uae_u8 *p; - int trk; - CDROM_TOC *toc = &ciw->toc; - int pos; - int msf; - int start, end; - int status; - - memset (buf, 0, sizeof buf); - p = buf; - - status = AUDIO_STATUS_NO_STATUS; - if (ciw->cdda_play) { - status = AUDIO_STATUS_IN_PROGRESS; - if (ciw->cdda_paused) - status = AUDIO_STATUS_PAUSED; - } else if (ciw->cdda_play_finished) { - status = AUDIO_STATUS_PLAY_COMPLETE; - } + p = buf + 4; + + if (sector < 0) pos = ciw->cd_last_pos; -#if 0 - pos -= CDDA_BUFFERS * 2; - if (ciw->cdda_play && pos < ciw->cdda_start) { - pos = ciw->cdda_start; - status = AUDIO_STATUS_NO_STATUS; + else + pos = sector; + + if (!regenerate) { + if (sector < 0 && ciw->subcodevalid && ciw->cdda_play) { + uae_sem_wait (&ciw->sub_sem2); + uae_u8 subbuf[SUB_CHANNEL_SIZE]; + sub_deinterleave (ciw->subcodebuf, subbuf); + memcpy (p, subbuf + 12, 12); + uae_sem_post (&ciw->sub_sem2); + valid = true; } -#endif - p[1] = status; - p[3] = 12; - - p = buf + 4; + if (!valid && sector >= 0) { + DWORD len; + uae_sem_wait (&ciw->sub_sem); + seterrormode (unitnum); + RAW_READ_INFO rri; + rri.DiskOffset.QuadPart = 2048 * (pos + 0); + rri.SectorCount = 1; + rri.TrackMode = RawWithSubCode; + memset (ciw->tempbuffer, 0, CD_RAW_SECTOR_WITH_SUBCODE_SIZE); + if (!DeviceIoControl (ciw->h, IOCTL_CDROM_RAW_READ, &rri, sizeof rri, ciw->tempbuffer, CD_RAW_SECTOR_WITH_SUBCODE_SIZE, &len, NULL)) { + DWORD err = GetLastError (); + write_log (L"IOCTL_CDROM_RAW_READ SUBQ CDDA sector %d returned %d\n", pos, err); + } + reseterrormode (unitnum); + uae_u8 subbuf[SUB_CHANNEL_SIZE]; + sub_deinterleave (ciw->tempbuffer + 2352, subbuf); + uae_sem_post (&ciw->sub_sem); + memcpy (p, subbuf + 12, 12); + valid = true; + } + } - if (pos >= 150) - trk = 0; + if (!valid) { start = end = 0; for (trk = 0; trk <= toc->LastTrack; trk++) { TRACK_DATA *td = &toc->TrackData[trk]; @@ -747,58 +572,19 @@ static uae_u8 *ioctl_command_qcode (int unitnum) if (pos >= start && pos < end) break; } - p[1] = (toc->TrackData[trk].Control << 0) | (toc->TrackData[trk].Adr << 4); - p[2] = trk + 1; - p[3] = 1; + p[0] = (toc->TrackData[trk].Control << 4) | (toc->TrackData[trk].Adr << 0); + p[1] = tobcd (trk + 1); + p[2] = tobcd (1); msf = lsn2msf (pos); - p[5] = (msf >> 16) & 0xff; - p[6] = (msf >> 8) & 0xff; - p[7] = (msf >> 0) & 0xff; - pos -= start; - if (pos < 0) - pos = 0; - msf = lsn2msf (pos); - p[9] = (msf >> 16) & 0xff; - p[10] = (msf >> 8) & 0xff; - p[11] = (msf >> 0) & 0xff; - - return buf; - - } else { + tolongbcd (p + 7, msf); + msf = lsn2msf (pos - start - 150); + tolongbcd (p + 3, msf); + } - SUB_Q_CHANNEL_DATA qcd; - DWORD len; - ULONG in = 1; - uae_u8 *p = ciw->tempbuffer; - int cnt = 3; +// write_log (L"%6d %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x\n", +// pos, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11]); + return 1; - memset (p, 0, 4 + 12); - p[1] = 0x15; - p[3] = 12; - while (cnt-- > 0) { - reseterrormode (unitnum); - if(!DeviceIoControl (ciw->h, IOCTL_CDROM_READ_Q_CHANNEL, &in, sizeof in, &qcd, sizeof qcd, &len, NULL)) { - reseterrormode (unitnum); - if (win32_error (unitnum, L"IOCTL_CDROM_READ_Q_CHANNEL") < 0) - continue; - return 0; - } - break; - } - reseterrormode (unitnum); - p[1] = qcd.CurrentPosition.Header.AudioStatus; - p += 4; - p[1] = (qcd.CurrentPosition.Control << 0) | (qcd.CurrentPosition.ADR << 4); - p[2] = qcd.CurrentPosition.TrackNumber; - p[3] = qcd.CurrentPosition.IndexNumber; - p[5] = qcd.CurrentPosition.AbsoluteAddress[1]; - p[6] = qcd.CurrentPosition.AbsoluteAddress[2]; - p[7] = qcd.CurrentPosition.AbsoluteAddress[3]; - p[9] = qcd.CurrentPosition.TrackRelativeAddress[1]; - p[10] = qcd.CurrentPosition.TrackRelativeAddress[2]; - p[11] = qcd.CurrentPosition.TrackRelativeAddress[3]; - return ciw->tempbuffer; - } } typedef struct _SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER { @@ -827,7 +613,7 @@ static uae_u8 *spti_read (int unitnum, int sector, int sectorsize) if (!open_createfile (unitnum, 1)) return 0; - ciw32[unitnum].cd_last_pos = sector + sectorsize; + ciw32[unitnum].cd_last_pos = sector; cmd[3] = (uae_u8)(sector >> 16); cmd[4] = (uae_u8)(sector >> 8); cmd[5] = (uae_u8)(sector >> 0); @@ -858,9 +644,8 @@ static uae_u8 *spti_read (int unitnum, int sector, int sectorsize) return p; } -uae_u8 *ioctl_command_rawread (int unitnum, int sector, int sectorsize) +uae_u8 *ioctl_command_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize) { - int cnt = 3; RAW_READ_INFO rri; DWORD len; uae_u8 *p = ciw32[unitnum].tempbuffer; @@ -874,7 +659,7 @@ uae_u8 *ioctl_command_rawread (int unitnum, int sector, int sectorsize) cdda_stop (unitnum); if (sectorsize != 2336 && sectorsize != 2352 && sectorsize != 2048) return 0; - while (cnt-- > 0) { + while (size-- > 0) { gui_flicker_led (LED_CD, unitnum, 1); seterrormode (unitnum); rri.DiskOffset.QuadPart = sector * 2048; @@ -888,7 +673,11 @@ uae_u8 *ioctl_command_rawread (int unitnum, int sector, int sectorsize) write_log (L"IOCTL rawread unit=%d sector=%d blocksize=%d, ERR=%d\n", unitnum, sector, sectorsize, err); } reseterrormode (unitnum); - ciw32[unitnum].cd_last_pos = sector + sectorsize; + if (data) { + memcpy (data, p, sectorsize); + data += sectorsize; + } + ciw32[unitnum].cd_last_pos = sector; break; } if (sectorsize == 2352) @@ -896,7 +685,7 @@ uae_u8 *ioctl_command_rawread (int unitnum, int sector, int sectorsize) return p + 16; } -static int ioctl_command_readwrite (int unitnum, int sector, int write, int blocksize, uae_u8 **ptr) +static int ioctl_command_readwrite (int unitnum, int sector, int size, int write, int blocksize, uae_u8 *data, uae_u8 **ptr) { DWORD dtotal; int cnt = 3; @@ -910,6 +699,7 @@ static int ioctl_command_readwrite (int unitnum, int sector, int write, int bloc if (!open_createfile (unitnum, 0)) return 0; cdda_stop (unitnum); + ciw32[unitnum].cd_last_pos = sector; while (cnt-- > 0) { gui_flicker_led (LED_CD, unitnum, 1); seterrormode (unitnum); @@ -922,11 +712,14 @@ static int ioctl_command_readwrite (int unitnum, int sector, int write, int bloc reseterrormode (unitnum); break; } - cnt = 3; - while (cnt-- > 0) { + while (size-- > 0) { gui_flicker_led (LED_CD, unitnum, 1); seterrormode (unitnum); if (write) { + if (data) { + memcpy (p, data, blocksize); + data += blocksize; + } if (!WriteFile (ciw32[unitnum].h, p, blocksize, &dtotal, 0)) { int err; reseterrormode (unitnum); @@ -937,6 +730,7 @@ static int ioctl_command_readwrite (int unitnum, int sector, int write, int bloc return -1; return 0; } + *ptr = p; } else { dtotal = 0; if (!ReadFile (ciw32[unitnum].h, p, blocksize, &dtotal, 0)) { @@ -951,41 +745,30 @@ static int ioctl_command_readwrite (int unitnum, int sector, int write, int bloc if (log_scsi) write_log (L"IOCTL unit %d, sector %d: ReadFile()==0. SPTI=%d\n", unitnum, sector, *ptr == 0 ? GetLastError () : 0); return 1; -#if 0 - DWORD len = CD_RAW_SECTOR_WITH_SUBCODE_SIZE, err = -1; - RAW_READ_INFO rri = { 0 }; - rri.DiskOffset.QuadPart = sector * 2048; - rri.SectorCount = 1; - rri.TrackMode = RawWithSubCode; - memset (p, 0, blocksize); - if (!DeviceIoControl(ciw32[unitnum].h, IOCTL_CDROM_RAW_READ, &rri, sizeof rri, - p, len, &len, NULL)) { - err = GetLastError (); /* returns ERROR_IO_DEVICE and still succeeds?! */ - } - p += 16; /* skip raw header */ - write_log (L"ioctl_command_read(%d,%d)==0, IOCTL_CDROM_RAW_READ = d\n", - sector, blocksize, err); -#endif + } else { + *ptr = p; + } + if (data) { + memcpy (data, p, blocksize); + data += blocksize; } } reseterrormode (unitnum); gui_flicker_led (LED_CD, unitnum, 1); - break; } - *ptr = p; return 1; } -static int ioctl_command_write (int unitnum, int sector) +static int ioctl_command_write (int unitnum, uae_u8 *data, int sector, int size) { uae_u8 *ptr; - return ioctl_command_readwrite (unitnum, sector, 1, ciw32[unitnum].blocksize, &ptr); + return ioctl_command_readwrite (unitnum, sector, size, 1, ciw32[unitnum].blocksize, data, &ptr); } -static uae_u8 *ioctl_command_read (int unitnum, int sector) +static uae_u8 *ioctl_command_read (int unitnum, uae_u8 *data, int sector, int size) { uae_u8 *ptr; - if (ioctl_command_readwrite (unitnum, sector, 0, ciw32[unitnum].blocksize, &ptr) > 0) + if (ioctl_command_readwrite (unitnum, sector, size, 0, ciw32[unitnum].blocksize, data, &ptr) > 0) return ptr; return NULL; } @@ -998,17 +781,19 @@ static int fetch_geometry (int unitnum, struct device_info *di) if (!open_createfile (unitnum, 0)) return 0; + uae_sem_wait (&ciw32[unitnum].sub_sem); + seterrormode (unitnum); while (cnt-- > 0) { - seterrormode (unitnum); - if (!DeviceIoControl (ciw32[unitnum].h, IOCTL_CDROM_GET_DRIVE_GEOMETRY, NULL, 0, &geom, sizeof(geom), &len, NULL)) { - reseterrormode (unitnum); + 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) continue; + reseterrormode (unitnum); + uae_sem_post (&ciw32[unitnum].sub_sem); return 0; } - reseterrormode (unitnum); - break; } + reseterrormode (unitnum); + uae_sem_post (&ciw32[unitnum].sub_sem); if (di) { di->cylinders = geom.Cylinders.LowPart; di->sectorspertrack = geom.SectorsPerTrack; @@ -1021,37 +806,17 @@ static int fetch_geometry (int unitnum, struct device_info *di) static int ismedia (int unitnum) { struct dev_info_ioctl *ciw = &ciw32[unitnum]; - - if (ciw->mciid > 0) { - - DWORD err; - MCI_STATUS_PARMS mciStatusParms; - - memset (&mciStatusParms, 0, sizeof mciStatusParms); - mciStatusParms.dwItem = MCI_STATUS_MEDIA_PRESENT; - err = mciSendCommand (ciw->mciid, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD_PTR)&mciStatusParms); - if (err != MMSYSERR_NOERROR) - return 0; - if (mciStatusParms.dwReturn) - return 1; - return 0; - - } else { - - struct device_info di; - memset (&di, 0, sizeof di); - return fetch_geometry (unitnum, &di); - - } + return fetch_geometry (unitnum, &ciw->di); } /* read toc */ -static uae_u8 *ioctl_command_toc (int unitnum) +static struct cd_toc_head *ioctl_command_toc (int unitnum) { struct dev_info_ioctl *ciw = &ciw32[unitnum]; DWORD len; int i; - uae_u8 *p = ciw->tempbuffer; + struct cd_toc_head *th = (struct cd_toc_head*)ciw->tempbuffer; + struct cd_toc *t = th->toc; int cnt = 3; CDROM_TOC *toc = &ciw->toc; @@ -1075,44 +840,64 @@ static uae_u8 *ioctl_command_toc (int unitnum) break; } - p[0] = ((toc->LastTrack + 4) * 11) >> 8; - p[1] = ((toc->LastTrack + 4) * 11) & 0xff; - p[2] = 1; - p[3] = toc->LastTrack; - p += 4; - memset (p, 0, 11); - p[0] = 1; - p[1] = (toc->TrackData[0].Control << 0) | (toc->TrackData[0].Adr << 4); - p[3] = 0xa0; - p[8] = 1; - p += 11; - memset (p, 0, 11); - p[0] = 1; - p[1] = 0x10; - p[3] = 0xa1; - p[8] = toc->LastTrack; - p += 11; - memset (p, 0, 11); - p[0] = 1; - p[1] = 0x10; - p[3] = 0xa2; - p[8] = toc->TrackData[toc->LastTrack].Address[1]; - p[9] = toc->TrackData[toc->LastTrack].Address[2]; - p[10] = toc->TrackData[toc->LastTrack].Address[3]; - p += 11; + memset (th, 0, sizeof (struct cd_toc_head)); + th->first_track = toc->FirstTrack; + th->last_track = toc->LastTrack; + th->tracks = th->last_track - th->first_track + 1; + th->points = th->tracks + 3; + th->lastaddress = msf2lsn ((toc->TrackData[toc->LastTrack].Address[1] << 16) | (toc->TrackData[toc->LastTrack].Address[2] << 8) | + (toc->TrackData[toc->LastTrack].Address[3] << 0)); + + t->adr = 1; + t->point = 0xa0; + t->track = th->first_track; + t++; + + th->first_track_offset = 1; for (i = 0; i < toc->LastTrack; i++) { - memset (p, 0, 11); - p[0] = 1; - p[1] = (toc->TrackData[i].Control << 0) | (toc->TrackData[i].Adr << 4); - p[2] = 0; - p[3] = i + 1; - p[8] = toc->TrackData[i].Address[1]; - p[9] = toc->TrackData[i].Address[2]; - p[10] = toc->TrackData[i].Address[3]; - p += 11; + t->adr = toc->TrackData[i].Adr; + t->control = toc->TrackData[i].Control; + t->paddress = msf2lsn ((toc->TrackData[i].Address[1] << 16) | (toc->TrackData[i].Address[2] << 8) | + (toc->TrackData[i].Address[3] << 0)); + t->point = t->track = i + 1; + t++; } + + th->last_track_offset = toc->LastTrack; + t->adr = 1; + t->point = 0xa1; + t->track = th->last_track; + t++; + + t->adr = 1; + t->point = 0xa2; + t->paddress = th->lastaddress; + t++; + gui_flicker_led (LED_CD, unitnum, 1); - return ciw32[unitnum].tempbuffer; + return th; +} + +static void update_device_info (int unitnum) +{ + if (!unitcheck (unitnum)) + return; + struct device_info *di = &ciw32[unitnum].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)) + 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)); } /* open device level access to cd rom drive */ @@ -1120,7 +905,6 @@ static int sys_cddev_open (int unitnum) { struct dev_info_ioctl *ciw = &ciw32[unitnum]; - ciw->cdda = 1; ciw->cdda_volume = 0xffff; ciw->cdda_volume_main = currprefs.sound_volume; /* buffer must be page aligned for device access */ @@ -1133,7 +917,10 @@ static int sys_cddev_open (int unitnum) 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); return 0; @@ -1155,9 +942,10 @@ void sys_cddev_close (int unitnum) return; cdda_stop (unitnum); close_createfile (unitnum); - close_mci (unitnum); VirtualFree (ciw->tempbuffer, 0, MEM_RELEASE); ciw->tempbuffer = NULL; + uae_sem_destroy (&ciw->sub_sem); + uae_sem_destroy (&ciw->sub_sem2); } static int open_device (int unitnum) @@ -1233,27 +1021,17 @@ static int ioctl_ismedia (int unitnum, int quick) struct dev_info_ioctl *ciw = &ciw32[unitnum]; return ciw->mediainserted; } + update_device_info (unitnum); return ismedia (unitnum); } -static struct device_info *info_device (int unitnum, struct device_info *di) +static struct device_info *info_device (int unitnum, struct device_info *di, int quick) { if (!unitcheck (unitnum)) return 0; - 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)) - 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); + if (!quick) + update_device_info (unitnum); + memcpy (di, &ciw32[unitnum].di, sizeof (struct device_info)); return di; } @@ -1265,7 +1043,8 @@ void win32_ioctl_media_change (TCHAR driveletter, int insert) 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; - scsi_do_disk_change (driveletter, insert); + update_device_info (i); + scsi_do_disk_change (driveletter, insert, NULL); #ifdef RETROPLATFORM rp_cd_image_change (i, ciw32[i].drvlettername); #endif diff --git a/od-win32/blkdev_win32_spti.cpp b/od-win32/blkdev_win32_spti.cpp index be6832d6..e06a8813 100644 --- a/od-win32/blkdev_win32_spti.cpp +++ b/od-win32/blkdev_win32_spti.cpp @@ -3,7 +3,7 @@ * * WIN32 CDROM/HD low level access code (SPTI) * -* Copyright 2002-2005 Toni Wilen +* Copyright 2002-2010 Toni Wilen * */ @@ -514,7 +514,7 @@ 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) +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) @@ -547,7 +547,7 @@ void win32_spti_media_change (TCHAR driveletter, int insert) 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); + scsi_do_disk_change (getid (i), insert, NULL); #ifdef RETROPLATFORM rp_cd_image_change (i, dev_info[i].drvletter ? dev_info[i].drvlettername : dev_info[i].name); #endif diff --git a/od-win32/dinput.cpp b/od-win32/dinput.cpp index bd09f2d7..7cbe44a8 100644 --- a/od-win32/dinput.cpp +++ b/od-win32/dinput.cpp @@ -38,6 +38,7 @@ #ifdef WINDDK #include #include +#include #endif #include #include @@ -57,6 +58,7 @@ #define DIDC_RAW 2 #define DIDC_WIN 3 #define DIDC_CAT 4 +#define DIDC_PARJOY 5 struct didata { int type; @@ -77,6 +79,9 @@ struct didata { int catweasel; int coop; + HANDLE parjoy; + PAR_QUERY_INFORMATION oldparjoystatus; + int axles; int buttons, buttons_real; int axismappings[MAX_MAPPINGS]; @@ -91,6 +96,8 @@ struct didata { int axisparentdir[MAX_MAPPINGS]; }; +#define MAX_PARJOYPORTS 2 + #define DI_BUFFER 30 #define DI_KBBUFFER 50 @@ -550,6 +557,53 @@ static int initialize_tablet (void) #endif } +#if 0 +static int initialize_parjoyport (void) +{ + for (int i = 0; i < MAX_PARJOYPORTS && num_joystick < MAX_INPUT_DEVICES; i++) { + struct didata *did; + TCHAR *p = i ? currprefs.win32_parjoyport1 : currprefs.win32_parjoyport0; + if (p[0] == 0) + continue; + HANDLE ph = CreateFile (p, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + if (ph == INVALID_HANDLE_VALUE) { + write_log (L"PARJOY: '%s' failed to open: %u\n", p, GetLastError ()); + continue; + } + write_log (L"PARJOY: '%s' open\n", p); + for (int j = 0; j < 2; j++) { + TCHAR tmp[100]; + did = di_joystick; + did += num_joystick; + cleardid(did); + did->connection = DIDC_PARJOY; + did->parjoy = ph; + _stprintf (tmp, L"Parallel joystick %d.%d", i + 1, j + 1); + did->name = my_strdup (tmp); + did->sortname = my_strdup (tmp); + _stprintf (tmp, L"PARJOY%d.%d", i, j); + did->configname = my_strdup (tmp); + did->buttons = did->buttons_real = 1; + did->axles = 2; + did->axissort[0] = 0; + did->axisname[0] = my_strdup (L"X-Axis"); + did->axissort[1] = 1; + did->axisname[1] = my_strdup (L"Y-Axis"); + for (j = 0; j < did->buttons; j++) { + did->buttonsort[j] = j; + _stprintf (tmp, L"Button %d", j + 1); + did->buttonname[j] = my_strdup (tmp); + } + did->priority = -1; + fixbuttons (did); + fixthings (did); + num_joystick++; + } + } + return 0; +} +#endif + static int initialize_catweasel (void) { int j, i; @@ -595,7 +649,7 @@ static int initialize_catweasel (void) did->sortname = my_strdup (tmp); _stprintf (tmp, L"CWJOY%d", i); did->configname = my_strdup (tmp); - did->buttons = did->buttons_real =(catweasel_isjoystick() & 0x80) ? 3 : 1; + did->buttons = did->buttons_real = (catweasel_isjoystick () & 0x80) ? 3 : 1; did->axles = 2; did->axissort[0] = 0; did->axisname[0] = my_strdup (L"X-Axis"); @@ -757,6 +811,29 @@ static void getvidpid (const TCHAR *devname, int *vid, int *pid, int *mi) getvidpid2 (devname, mi, L"MI_"); } +static void addrkblabels (struct didata *did) +{ + int j = 0; + for (int k = 0; k < 254; k++) { + TCHAR tmp[100]; + tmp[0] = 0; + if (rawkeyboardlabels[j] != NULL) { + if (rawkeyboardlabels[j][0]) { + _tcscpy (tmp, rawkeyboardlabels[j]); + j++; + } + } else { + j++; + } + if (!tmp[0]) + _stprintf (tmp, L"KEY_%02X", k + 1); + did->buttonname[k] = my_strdup (tmp); + did->buttonmappings[k] = k + 1; + did->buttonsort[k] = k + 1; + did->buttons++; + } +} + static int initialize_rawinput (void) { RAWINPUTDEVICELIST *ridl = 0; @@ -833,7 +910,7 @@ static int initialize_rawinput (void) continue; if (rnum_kb < 2) continue; - if (num_keyboard >= MAX_INPUT_DEVICES - 1) + if (num_keyboard >= MAX_INPUT_DEVICES) continue; did += num_keyboard; num_keyboard++; @@ -896,34 +973,28 @@ static int initialize_rawinput (void) } did->priority = -1; } else { - int j; PRID_DEVICE_INFO_KEYBOARD rdik = &rdi->keyboard; write_log (L"type=%d sub=%d mode=%d fkeys=%d indicators=%d tkeys=%d\n", rdik->dwType, rdik->dwSubType, rdik->dwKeyboardMode, rdik->dwNumberOfFunctionKeys, rdik->dwNumberOfIndicators, rdik->dwNumberOfKeysTotal); - j = 0; - for (int k = 0; k < 254; k++) { - TCHAR tmp[100]; - tmp[0] = 0; - if (rawkeyboardlabels[j] != NULL) { - if (rawkeyboardlabels[j][0]) { - _tcscpy (tmp, rawkeyboardlabels[j]); - j++; - } - } else { - j++; - } - if (!tmp[0]) - _stprintf (tmp, L"KEY_%02X", k + 1); - did->buttonname[k] = my_strdup (tmp); - did->buttonmappings[k] = k + 1; - did->buttonsort[k] = k + 1; - did->buttons++; - } + addrkblabels (did); } } } + if (rnum_kb && num_keyboard < MAX_INPUT_DEVICES - 1) { + struct didata *did = di_keyboard + num_keyboard; + num_keyboard++; + rkb++; + did->name = my_strdup (L"WinUAE null keyboard"); + did->rawinput = NULL; + did->connection = DIDC_RAW; + did->sortname = my_strdup (L"NULLKEYBOARD"); + did->priority = -2; + did->configname = my_strdup (L"NULLKEYBOARD"); + addrkblabels (did); + } + rawinputfriendlynames (); xfree (ridl); @@ -997,10 +1068,11 @@ static void handle_rawinput_2 (RAWINPUT *raw) if (raw->header.dwType == RIM_TYPEMOUSE) { PRAWMOUSE rm = &raw->data.mouse; + HANDLE h = raw->header.hDevice; for (num = 0; num < num_mouse; num++) { did = &di_mouse[num]; - if (did->rawinput == raw->header.hDevice) + if (did->rawinput == h) break; } #ifdef DI_DEBUG_RAWINPUT @@ -1082,6 +1154,7 @@ static void handle_rawinput_2 (RAWINPUT *raw) } else if (raw->header.dwType == RIM_TYPEKEYBOARD) { PRAWKEYBOARD rk = &raw->data.keyboard; + HANDLE h = raw->header.hDevice; int scancode = rk->MakeCode & 0x7f; int pressed = (rk->Flags & RI_KEY_BREAK) ? 0 : 1; @@ -1098,17 +1171,29 @@ static void handle_rawinput_2 (RAWINPUT *raw) // eat E1 extended keys if (rk->Flags & (RI_KEY_E1)) return; + if (scancode == 0) { + scancode = MapVirtualKey (rk->VKey, MAPVK_VK_TO_VSC); +#ifdef DI_DEBUG_RAWINPUT + write_log (L"VK->CODE: %x\n", scancode); +#endif + } if (rk->VKey == 0xff || (rk->Flags & RI_KEY_E0)) scancode |= 0x80; if (rk->MakeCode == KEYBOARD_OVERRUN_MAKE_CODE) return; - if (scancode == 0xaa) + if (scancode == 0xaa || scancode == 0) return; for (num = 0; num < num_keyboard; num++) { did = &di_keyboard[num]; - if (did->acquired && did->rawinput == raw->header.hDevice) - break; + if (did->connection != DIDC_RAW) + continue; + if (did->acquired) { + if (did->rawinput == h) + break; + if (h == NULL && num_keyboard == 1) + break; + } } if (num == num_keyboard) { if (!istest && scancode == DIK_F12 && pressed && isfocus ()) @@ -1484,10 +1569,13 @@ static void di_dev_free (struct didata *did) { if (did->lpdi) IDirectInputDevice8_Release (did->lpdi); + if (did->parjoy != INVALID_HANDLE_VALUE) + CloseHandle (did->parjoy); xfree (did->name); xfree (did->sortname); xfree (did->configname); memset (did, 0, sizeof (struct didata)); + did->parjoy = INVALID_HANDLE_VALUE; } static int di_do_init (void) @@ -1534,6 +1622,8 @@ static int di_do_init (void) initialize_windowsmouse (); write_log (L"Catweasel joymouse initialization..\n"); initialize_catweasel (); +// write_log (L"Parallel joystick port initialization..\n"); +// initialize_parjoyport (); write_log (L"wintab tablet initialization..\n"); initialize_tablet (); write_log (L"end\n"); @@ -2397,6 +2487,19 @@ static void read_joystick (void) } } continue; + } else if (did->connection == DIDC_PARJOY) { + DWORD ret; + PAR_QUERY_INFORMATION inf; + ret = 0; + if (DeviceIoControl (did->parjoy, IOCTL_PAR_QUERY_INFORMATION, NULL, 0, &inf, sizeof inf, &ret, NULL)) { + write_log (L"PARJOY: IOCTL_PAR_QUERY_INFORMATION = %u\n", GetLastError ()); + } else { + if (inf.Status != did->oldparjoystatus.Status) { + write_log (L"PARJOY: %08x\n", inf.Status); + did->oldparjoystatus.Status = inf.Status; + } + } + continue; } lpdi = did->lpdi; if (!lpdi || did->connection != DIDC_DX) diff --git a/od-win32/fsdb_mywin32.cpp b/od-win32/fsdb_mywin32.cpp index 1f560756..be2c8e65 100644 --- a/od-win32/fsdb_mywin32.cpp +++ b/od-win32/fsdb_mywin32.cpp @@ -246,7 +246,6 @@ struct my_openfile_s *my_open (const TCHAR *name, int flags) DWORD CreationDisposition = OPEN_EXISTING; DWORD FlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; DWORD attr; - wstring fname; mos = xmalloc (struct my_openfile_s, 1); if (!mos) @@ -267,9 +266,7 @@ struct my_openfile_s *my_open (const TCHAR *name, int flags) if (CreationDisposition == CREATE_ALWAYS && attr != INVALID_FILE_ATTRIBUTES && (attr & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN))) SetFileAttributes (name, FILE_ATTRIBUTE_NORMAL); - fname = L"\\\\?\\"; - fname += name; - h = CreateFile (fname.c_str(), DesiredAccess, ShareMode, NULL, CreationDisposition, FlagsAndAttributes, NULL); + h = CreateFile (name, DesiredAccess, ShareMode, NULL, CreationDisposition, FlagsAndAttributes, NULL); if (h == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); if (err == ERROR_ACCESS_DENIED && (DesiredAccess & GENERIC_WRITE)) { diff --git a/od-win32/keyboard_win32.cpp b/od-win32/keyboard_win32.cpp index cd85b75b..be2282ce 100644 --- a/od-win32/keyboard_win32.cpp +++ b/od-win32/keyboard_win32.cpp @@ -185,12 +185,14 @@ static int kb_cd32_np[] = { DIK_NUMPAD4, -1, DIK_NUMPAD6, -1, DIK_NUMPAD8, -1, D static int kb_cd32_ck[] = { DIK_LEFT, -1, DIK_RIGHT, -1, DIK_UP, -1, DIK_DOWN, -1, DIK_RCONTROL, -1, DIK_RMENU, -1, DIK_NUMPAD7, -1, DIK_NUMPAD9, -1, DIK_DIVIDE, -1, DIK_SUBTRACT, -1, DIK_MULTIPLY, -1, -1 }; static int kb_cd32_se[] = { DIK_A, -1, DIK_D, -1, DIK_W, -1, DIK_S, -1, -1, DIK_LMENU, -1, DIK_LSHIFT, -1, DIK_NUMPAD7, -1, DIK_NUMPAD9, -1, DIK_DIVIDE, -1, DIK_SUBTRACT, -1, DIK_MULTIPLY, -1, -1 }; +static int kb_cdtv[] = { DIK_NUMPAD1, -1, DIK_NUMPAD3, -1, DIK_NUMPAD7, -1, DIK_NUMPAD9, -1, -1 }; + static int kb_xa1[] = { DIK_NUMPAD4, -1, DIK_NUMPAD6, -1, DIK_NUMPAD8, -1, DIK_NUMPAD2, DIK_NUMPAD5, -1, DIK_LCONTROL, -1, DIK_LMENU, -1, DIK_SPACE, -1, -1 }; static int kb_xa2[] = { DIK_D, -1, DIK_G, -1, DIK_R, -1, DIK_F, -1, DIK_A, -1, DIK_S, -1, DIK_Q, -1 }; static int kb_arcadia[] = { DIK_F2, -1, DIK_1, -1, DIK_2, -1, DIK_5, -1, DIK_6, -1, -1 }; static int kb_arcadiaxa[] = { DIK_1, -1, DIK_2, -1, DIK_3, -1, DIK_4, -1, DIK_6, -1, DIK_LBRACKET, DIK_LSHIFT, -1, DIK_RBRACKET, -1, DIK_C, -1, DIK_5, -1, DIK_Z, -1, DIK_X, -1, -1 }; -static int *kbmaps[] = { kb_np, kb_ck, kb_se, kb_cd32_np, kb_cd32_ck, kb_cd32_se, kb_xa1, kb_xa2, kb_arcadia, kb_arcadiaxa }; +static int *kbmaps[] = { kb_np, kb_ck, kb_se, kb_cd32_np, kb_cd32_ck, kb_cd32_se, kb_xa1, kb_xa2, kb_arcadia, kb_arcadiaxa, kb_cdtv }; extern int ispressed (int key); diff --git a/od-win32/parser.cpp b/od-win32/parser.cpp index fb9efe69..799efbb0 100644 --- a/od-win32/parser.cpp +++ b/od-win32/parser.cpp @@ -25,6 +25,7 @@ #include #include +#include #include "sysdeps.h" #include "options.h" @@ -1197,7 +1198,10 @@ void hsyncstuff (void) #endif } -static int enumserialports_2 (int cnt) +const static GUID GUID_DEVINTERFACE_PARALLEL = {0x97F76EF0,0xF883,0x11D0, +{0xAF,0x1F,0x00,0x00,0xF8,0x00,0x84,0x5C}}; + +static int enumports_2 (struct serparportinfo *pi, int cnt, bool parport) { // Create a device information set that will be the container for // the device interfaces. @@ -1208,7 +1212,7 @@ static int enumserialports_2 (int cnt) DWORD dwDetDataSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA) + 256 * sizeof (TCHAR); DWORD ii; - hDevInfo = SetupDiGetClassDevs (&GUID_CLASS_COMPORT, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + hDevInfo = SetupDiGetClassDevs (parport ? &GUID_DEVINTERFACE_PARALLEL : &GUID_DEVINTERFACE_COMPORT, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if(hDevInfo == INVALID_HANDLE_VALUE) return 0; // Enumerate the serial ports @@ -1218,7 +1222,7 @@ static int enumserialports_2 (int cnt) ifcData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA); pDetData->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA); for (ii = 0; bOk; ii++) { - bOk = SetupDiEnumDeviceInterfaces (hDevInfo, NULL, &GUID_CLASS_COMPORT, ii, &ifcData); + bOk = SetupDiEnumDeviceInterfaces (hDevInfo, NULL, parport ? &GUID_DEVINTERFACE_PARALLEL : &GUID_DEVINTERFACE_COMPORT, ii, &ifcData); if (bOk) { // Got a device. Get the details. SP_DEVINFO_DATA devdata = { sizeof (SP_DEVINFO_DATA)}; @@ -1234,21 +1238,21 @@ static int enumserialports_2 (int cnt) bSuccess = bSuccess && SetupDiGetDeviceRegistryProperty ( hDevInfo, &devdata, SPDRP_DEVICEDESC, NULL, (PBYTE)desc, sizeof (desc), NULL); - if (bSuccess && cnt < MAX_SERIAL_PORTS) { + if (bSuccess && cnt < MAX_SERPAR_PORTS) { TCHAR *p; - comports[cnt].dev = my_strdup (pDetData->DevicePath); - comports[cnt].name = my_strdup (fname); - p = _tcsstr (fname, L"(COM"); + pi[cnt].dev = my_strdup (pDetData->DevicePath); + pi[cnt].name = my_strdup (fname); + p = _tcsstr (fname, parport ? L"(LPT" : L"(COM"); if (p && (p[5] == ')' || p[6] == ')')) { - comports[cnt].cfgname = xmalloc (TCHAR, 100); + pi[cnt].cfgname = xmalloc (TCHAR, 100); if (isdigit(p[5])) - _stprintf (comports[cnt].cfgname, L"COM%c%c", p[4], p[5]); + _stprintf (pi[cnt].cfgname, parport ? L"LPT%c%c" : L"COM%c%c", p[4], p[5]); else - _stprintf (comports[cnt].cfgname, L"COM%c", p[4]); + _stprintf (pi[cnt].cfgname, parport ? L"LPT%c" : L"COM%c", p[4]); } else { - comports[cnt].cfgname = my_strdup (pDetData->DevicePath); + pi[cnt].cfgname = my_strdup (pDetData->DevicePath); } - write_log (L"SERPORT: '%s' = '%s' = '%s'\n", comports[cnt].name, comports[cnt].cfgname, comports[cnt].dev); + write_log (L"%s: '%s' = '%s' = '%s'\n", parport ? L"PARPORT" : L"SERPORT", pi[cnt].name, pi[cnt].cfgname, pi[cnt].dev); cnt++; } } else { @@ -1270,6 +1274,8 @@ end: return cnt; } +static struct serparportinfo parports[MAX_SERPAR_PORTS]; + int enumserialports (void) { int cnt, i, j; @@ -1291,7 +1297,7 @@ int enumserialports (void) cnt++; #endif - cnt = enumserialports_2 (cnt); + cnt = enumports_2 (comports, cnt, false); for (i = 0; i < 10; i++) { _stprintf (name, L"COM%d", i); if (!QueryDosDevice (name, devname, sizeof devname / sizeof (TCHAR))) @@ -1301,7 +1307,7 @@ int enumserialports (void) break; } if (j == cnt) { - if (cnt >= MAX_SERIAL_PORTS) + if (cnt >= MAX_SERPAR_PORTS) break; comports[j].dev = xmalloc (TCHAR, 100); _stprintf (comports[cnt].dev, L"\\.\\\\%s", name); @@ -1311,7 +1317,9 @@ int enumserialports (void) cnt++; } } - write_log (L"Serial port enumeration end\n"); + write_log (L"Parallel port enumeration..\n"); + enumports_2 (parports, 0, true); + write_log (L"Port enumeration end\n"); return cnt; } @@ -1319,7 +1327,7 @@ void sernametodev (TCHAR *sername) { int i; - for (i = 0; i < MAX_SERIAL_PORTS && comports[i].name; i++) { + for (i = 0; i < MAX_SERPAR_PORTS && comports[i].name; i++) { if (!_tcscmp(sername, comports[i].cfgname)) { _tcscpy (sername, comports[i].dev); return; @@ -1331,7 +1339,7 @@ void sernametodev (TCHAR *sername) void serdevtoname (TCHAR *sername) { int i; - for (i = 0; i < MAX_SERIAL_PORTS && comports[i].name; i++) { + for (i = 0; i < MAX_SERPAR_PORTS && comports[i].name; i++) { if (!_tcscmp(sername, comports[i].dev)) { _tcscpy (sername, comports[i].cfgname); return; diff --git a/od-win32/parser.h b/od-win32/parser.h index 5cae6d2e..cc6f56b7 100644 --- a/od-win32/parser.h +++ b/od-win32/parser.h @@ -33,22 +33,23 @@ void serialuartbreak (int); extern void unload_ghostscript (void); extern int load_ghostscript (void); -#define MAX_SERIAL_PORTS 32 -struct serialportinfo +#define MAX_SERPAR_PORTS 32 +struct serparportinfo { TCHAR *dev; TCHAR *cfgname; TCHAR *name; }; -extern struct serialportinfo comports[MAX_SERIAL_PORTS]; +extern struct serparportinfo comports[MAX_SERPAR_PORTS]; +extern struct serparportinfo parports[MAX_SERPAR_PORTS]; extern int enumserialports (void); extern void sernametodev (TCHAR*); extern void serdevtoname (TCHAR*); -extern void epson_printchar(uae_u8 c); -extern int epson_init(const TCHAR *printername, int pins); -extern void epson_close(void); +extern void epson_printchar (uae_u8 c); +extern int epson_init (const TCHAR *printername, int pins); +extern void epson_close (void); #define PARALLEL_MATRIX_TEXT 1 #define PARALLEL_MATRIX_EPSON 2 diff --git a/od-win32/resources/resource b/od-win32/resources/resource index 15ab7126..f85fbfb7 100644 --- a/od-win32/resources/resource +++ b/od-win32/resources/resource @@ -1043,6 +1043,10 @@ #define IDC_INFOBOX_TEXT2 1802 #define IDC_INFOBOX_TEXT1 1803 #define IDC_INFOBOX_TEXT3 1804 +#define IDC_CD_EJECT 1804 +#define IDC_CD_TEXT 1805 +#define IDC_CD_TYPE 1806 +#define IDC_CD_SELECT 1807 #define ID__FLOPPYDRIVES 40004 #define ID_FLOPPYDRIVES_DF0 40005 #define ID_ST_CONFIGURATION 40010 @@ -1088,7 +1092,7 @@ #define _APS_3D_CONTROLS 1 #define _APS_NEXT_RESOURCE_VALUE 356 #define _APS_NEXT_COMMAND_VALUE 40045 -#define _APS_NEXT_CONTROL_VALUE 1803 +#define _APS_NEXT_CONTROL_VALUE 1808 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/od-win32/resources/winuae.rc b/od-win32/resources/winuae.rc index bcda2335..2f2b7896 100644 --- a/od-win32/resources/winuae.rc +++ b/od-win32/resources/winuae.rc @@ -282,25 +282,30 @@ BEGIN CONTROL "DF3:",IDC_DF3ENABLE,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,3,111,34,15 END -IDD_HARDDISK DIALOGEX 0, 0, 300, 237 +IDD_HARDDISK DIALOGEX 0, 0, 300, 243 STYLE DS_LOCALEDIT | DS_SETFONT | DS_3DLOOK | DS_CONTROL | WS_CHILD EXSTYLE WS_EX_CONTEXTHELP FONT 8, "MS Sans Serif", 0, 0, 0x1 BEGIN - CONTROL "List1",IDC_VOLUMELIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,5,0,290,167 - PUSHBUTTON "Add &Directory or Archive...",IDC_NEW_FS,10,171,103,15 - PUSHBUTTON "Add &Hardfile...",IDC_NEW_HF,130,171,74,15 - PUSHBUTTON "Add Ha&rd Drive...",IDC_NEW_HD,220,171,75,15 - PUSHBUTTON "Remove",IDC_REMOVE,235,193,60,15 - PUSHBUTTON "&Properties",IDC_EDIT,235,210,60,15 - CONTROL "Add PC drives at startup",IDC_MAPDRIVES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,192,100,10 - CONTROL "Disable UAEFSDB-support",IDC_NOUAEFSDB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,192,119,10 - CONTROL "Don't use Windows Recycle Bin",IDC_NORECYCLEBIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,203,121,10 - CONTROL "Include network drives..",IDC_MAPDRIVES_NET,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,226,101,10 - CONTROL "Include CD/DVD drives..",IDC_MAPDRIVES_CD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,215,100,10 - CONTROL "Automount removable drives",IDC_MAPDRIVES_AUTO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,215,115,10 + CONTROL "List1",IDC_VOLUMELIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,5,0,290,130 + PUSHBUTTON "Add &Directory or Archive...",IDC_NEW_FS,10,135,103,15 + PUSHBUTTON "Add &Hardfile...",IDC_NEW_HF,130,135,74,15 + PUSHBUTTON "Add Ha&rd Drive...",IDC_NEW_HD,220,135,75,15 + PUSHBUTTON "Remove",IDC_REMOVE,235,155,60,15 + PUSHBUTTON "&Properties",IDC_EDIT,235,172,60,15 + CONTROL "Add PC drives at startup",IDC_MAPDRIVES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,154,100,10 + CONTROL "Disable UAEFSDB-support",IDC_NOUAEFSDB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,154,119,10 + CONTROL "Don't use Windows Recycle Bin",IDC_NORECYCLEBIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,165,121,10 + CONTROL "Include network drives..",IDC_MAPDRIVES_NET,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,188,101,10 + CONTROL "Include CD/DVD drives..",IDC_MAPDRIVES_CD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,177,100,10 + CONTROL "Automount removable drives",IDC_MAPDRIVES_AUTO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,177,115,10 CONTROL "Include removable drives..",IDC_MAPDRIVES_REMOVABLE, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,203,100,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,165,100,10 + COMBOBOX IDC_CD_TEXT,5,224,289,75,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Eject",IDC_CD_EJECT,265,204,30,15 + PUSHBUTTON "Select image file",IDC_CD_SELECT,90,204,98,15 + COMBOBOX IDC_CD_TYPE,194,205,63,50,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "CD drive/image",IDC_STATIC,5,206,70,10,SS_CENTERIMAGE END IDD_SOUND DIALOGEX 0, 0, 300, 237 @@ -1200,6 +1205,10 @@ BEGIN BEGIN END + IDD_HARDDISK, DIALOG + BEGIN + END + IDD_SOUND, DIALOG BEGIN END @@ -1224,6 +1233,10 @@ BEGIN BEGIN END + IDD_HARDFILE, DIALOG + BEGIN + END + IDD_CHIPSET, DIALOG BEGIN END @@ -1237,6 +1250,10 @@ BEGIN BOTTOMMARGIN, 237 END + IDD_HARDDRIVE, DIALOG + BEGIN + END + IDD_MISC2, DIALOG BEGIN END @@ -1269,6 +1286,10 @@ BEGIN BEGIN END + IDD_EXPANSION, DIALOG + BEGIN + END + IDD_INPUTMAP, DIALOG BEGIN TOPMARGIN, 1 @@ -1418,7 +1439,7 @@ BEGIN IDS_NETDISCONNECTED "Cable disconnected" IDS_QS_CD "CD" IDS_QS_CD_AUTO "Autodetect" - IDS_QS_CD_IMAGE "Image file" + IDS_QS_CD_IMAGE "Image mode" IDS_REMAPTITLE "Input captured. F12 = Exit. F11 = Skip current event in Remap mode." IDS_FILTER_NOOVERLAYS "No overlays available" END diff --git a/od-win32/rp.cpp b/od-win32/rp.cpp index 8257dd56..9c5aa3bb 100644 --- a/od-win32/rp.cpp +++ b/od-win32/rp.cpp @@ -844,7 +844,7 @@ void rp_fixup_options (struct uae_prefs *p) for (i = 0; i < MAX_TOTAL_DEVICES; i++) { if ((1 << i) & cd_mask) { struct device_info di = { 0 }; - if (sys_command_info (DF_IOCTL, i, &di)) + if (sys_command_info (DF_IOCTL, i, &di, 0)) rp_cd_image_change (i, di.mediapath); } } diff --git a/od-win32/win32.cpp b/od-win32/win32.cpp index 84927a84..acef1a91 100644 --- a/od-win32/win32.cpp +++ b/od-win32/win32.cpp @@ -2533,7 +2533,7 @@ void target_default_options (struct uae_prefs *p, int type) } } -static const TCHAR *scsimode[] = { L"none", L"SPTI", L"SPTI+SCSISCAN", L"AdaptecASPI", L"NeroASPI", L"FrogASPI", 0 }; +static const TCHAR *scsimode[] = { L"SCSIEMU", L"SPTI", L"SPTI+SCSISCAN", L"AdaptecASPI", L"NeroASPI", L"FrogASPI", 0 }; void target_save_options (struct zfile *f, struct uae_prefs *p) { @@ -2594,6 +2594,8 @@ void target_save_options (struct zfile *f, struct uae_prefs *p) cfgfile_target_dwrite_bool (f, L"powersavedisabled", p->win32_powersavedisabled); cfgfile_target_dwrite_str (f, L"exec_before", p->win32_commandpathstart); cfgfile_target_dwrite_str (f, L"exec_after", p->win32_commandpathend); + cfgfile_target_dwrite_str (f, L"parjoyport0", p->win32_parjoyport0); + cfgfile_target_dwrite_str (f, L"parjoyport1", p->win32_parjoyport1); } @@ -2660,6 +2662,8 @@ int target_parse_option (struct uae_prefs *p, TCHAR *option, TCHAR *value) || cfgfile_yesno (option, value, L"powersavedisabled", &p->win32_powersavedisabled) || cfgfile_string (option, value, L"exec_before", p->win32_commandpathstart, sizeof p->win32_commandpathstart / sizeof (TCHAR)) || cfgfile_string (option, value, L"exec_after", p->win32_commandpathend, sizeof p->win32_commandpathend / sizeof (TCHAR)) + || cfgfile_string (option, value, L"parjoyport0", p->win32_parjoyport0, sizeof p->win32_parjoyport0 / sizeof (TCHAR)) + || cfgfile_string (option, value, L"parjoyport1", p->win32_parjoyport1, sizeof p->win32_parjoyport1 / sizeof (TCHAR)) || cfgfile_intval (option, value, L"specialkey", &p->win32_specialkey, 1) || cfgfile_intval (option, value, L"guikey", &p->win32_guikey, 1) || cfgfile_intval (option, value, L"kbledmode", &p->win32_kbledmode, 1) diff --git a/od-win32/win32.h b/od-win32/win32.h index 620bebd6..360b149d 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"2" -#define WINUAEDATE MAKEBD(2010, 7, 8) +#define WINUAEBETA L"3" +#define WINUAEDATE MAKEBD(2010, 7, 16) #define WINUAEEXTRA L"" #define WINUAEREV L"" diff --git a/od-win32/win32gui.cpp b/od-win32/win32gui.cpp index 03ff29e5..9d29c058 100644 --- a/od-win32/win32gui.cpp +++ b/od-win32/win32gui.cpp @@ -95,7 +95,7 @@ #define USS_FORMAT_STRING_SAVE L"(*.uss)\0*.uss\0" #define HDF_FORMAT_STRING L"(*.hdf;*.vhd;*.rdf;*.hdz;*.rdz)\0*.hdf;*.vhd;*.rdf;*.hdz;*.rdz\0" #define INP_FORMAT_STRING L"(*.inp)\0*.inp\0" -#define CD_FORMAT_STRING L"(*.cue;*.iso)\0*.cue;*.iso;" ARCHIVE_STRING L"\0" +#define CD_FORMAT_STRING L"(*.cue;*.ccd;*.iso)\0*.cue;*.ccd;*.iso;" ARCHIVE_STRING L"\0" #define CONFIG_HOST L"Host" #define CONFIG_HARDWARE L"Hardware" @@ -151,6 +151,9 @@ static TCHAR quickstart_cddrive[16]; static int quickstart_ok, quickstart_ok_floppy; static void addfloppytype (HWND hDlg, int n); static void addfloppyhistory (HWND hDlg); +static void addfloppyhistory_2 (HWND hDlg, int n, int f_text, int type); +static void addcdtype (HWND hDlg, int id); +static void getfloppyname (HWND hDlg, int n, int cd, int f_text); static int C_PAGES; #define MAX_C_PAGES 30 @@ -1917,20 +1920,48 @@ static UINT_PTR CALLBACK ofnhook (HWND hDlg, UINT message, WPARAM wParam, LPARAM return FALSE; } -static void selectdisk (struct uae_prefs *prefs, HWND hDlg, int num, int id, TCHAR *full_path) +static void eject_cd (void) { - SetDlgItemText (hDlg, id, full_path); - if (iscd (num)) { - if (quickstart_cddrive[0]) { - quickstart_cdtype = 0; - quickstart_cddrive[0] = 0; + workprefs.cdimagefile[0] = 0; + quickstart_cddrive[0] = 0; + workprefs.cdimagefileuse = false; + if (full_property_sheet) { + quickstart_cdtype = 0; + } else { + if (quickstart_cdtype > 0) { + quickstart_cdtype = 1; + workprefs.cdimagefileuse = true; } - _tcscpy (prefs->cdimagefile, full_path); - DISK_history_add (full_path, -1, HISTORY_CD, 0); + } +} + +static void ejectfloppy (int n) +{ + if (iscd (n)) { + eject_cd (); } else { - _tcscpy(prefs->df[num], full_path); - DISK_history_add (full_path, -1, HISTORY_FLOPPY, 0); + workprefs.df[n][0] = 0; + } +} + +static void selectcd (struct uae_prefs *prefs, HWND hDlg, int num, int id, TCHAR *full_path) +{ + SetDlgItemText (hDlg, id, full_path); + if (quickstart_cddrive[0]) + eject_cd (); + _tcscpy (prefs->cdimagefile, full_path); + DISK_history_add (full_path, -1, HISTORY_CD, 0); +} + +static void selectdisk (struct uae_prefs *prefs, HWND hDlg, int num, int id, TCHAR *full_path) +{ + if (iscd (num)) { + selectcd (prefs, hDlg, num, id, full_path); + return; } + SetDlgItemText (hDlg, id, full_path); + _tcscpy(prefs->df[num], full_path); + DISK_history_add (full_path, -1, HISTORY_FLOPPY, 0); } @@ -2249,6 +2280,9 @@ int DiskSelection_2 (HWND hDlg, WPARAM wParam, int flag, struct uae_prefs *prefs } SetDlgItemText (hDlg, wParam, full_path); break; + case IDC_CD_SELECT: + selectcd (prefs, hDlg, 0, IDC_CD_TEXT, full_path); + break; case IDC_DF0: case IDC_DF0QQ: selectdisk (prefs, hDlg, 0, IDC_DF0TEXT, full_path); @@ -4777,6 +4811,7 @@ static void init_quickstartdlg (HWND hDlg) workprefs.df[2][0] = 0; workprefs.df[3][0] = 0; workprefs.cdimagefile[0] = 0; + workprefs.cdimagefileuse = quickstart_cdtype > 0; load_quickstart (hDlg, 1); quickstarthost (hDlg, hostconf); } @@ -4907,7 +4942,7 @@ static void testimage (HWND hDlg, int num) break; case 11: quickstart_ok_floppy = 1; - if (quickstart_model != 1 && quickstart_model != 2 && quickstart_model != 4) { + if (quickstart_model != 1 && quickstart_model != 2 && quickstart_model != 4 && quickstart_model != 5 && quickstart_model != 6 && quickstart_model != 8) { quickstart_model = 4; messageid = IDS_IMGCHK_KS2; reload = 1; @@ -5021,8 +5056,8 @@ static INT_PTR CALLBACK QuickstartDlgProc (HWND hDlg, UINT msg, WPARAM wParam, L SendDlgItemMessage (hDlg, IDC_CD0Q_TYPE, WM_GETTEXT, (WPARAM)len, (LPARAM)quickstart_cddrive); _tcscpy (workprefs.cdimagefile, quickstart_cddrive); } else { - workprefs.cdimagefile[0] = 0; - quickstart_cddrive[0] = 0; + eject_cd (); + quickstart_cdtype = val; } addfloppytype (hDlg, 1); addfloppyhistory (hDlg); @@ -7175,12 +7210,13 @@ 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"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)")); SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_ADDSTRING, 0, (LPARAM)((get_aspi_path (2)) ? L"FrogASPI" : L"(FrogASPI)")); - SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_SETCURSEL, workprefs.win32_uaescsimode - 1, 0); + SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_SETCURSEL, workprefs.win32_uaescsimode, 0); } static void misc_lang (HWND hDlg) @@ -7409,7 +7445,7 @@ static INT_PTR MiscDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) case IDC_SCSIMODE: v = SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_GETCURSEL, 0, 0L); if (v != CB_ERR) - workprefs.win32_uaescsimode = v + 1; + workprefs.win32_uaescsimode = v; break; } } @@ -9059,9 +9095,21 @@ static ACCEL HarddiskAccel[] = { { 0, 0, 0 } }; -static void harddiskdlg_button (HWND hDlg, int button) +static void harddiskdlg_button (HWND hDlg, WPARAM wParam) { + int button = LOWORD (wParam); switch (button) { + case IDC_CD_SELECT: + DiskSelection (hDlg, wParam, 17, &workprefs, NULL); + quickstart_cdtype = 1; + workprefs.cdimagefileuse = true; + addcdtype (hDlg, IDC_CD_TYPE); + break; + case IDC_CD_EJECT: + eject_cd (); + SetDlgItemText (hDlg, IDC_CD_TEXT, L""); + addcdtype (hDlg, IDC_CD_TYPE); + break; case IDC_NEW_FS: current_fsvdlg = empty_fsvdlg; archivehd = 0; @@ -9200,6 +9248,8 @@ static INT_PTR CALLBACK HarddiskDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPA CheckDlgButton (hDlg, IDC_MAPDRIVES_REMOVABLE, workprefs.win32_automount_removabledrives); CheckDlgButton (hDlg, IDC_NOUAEFSDB, workprefs.filesys_no_uaefsdb); CheckDlgButton (hDlg, IDC_NORECYCLEBIN, workprefs.win32_norecyclebin); + addfloppyhistory_2 (hDlg, 0, IDC_CD_TEXT, HISTORY_CD); + addcdtype (hDlg, IDC_CD_TYPE); InitializeListView (hDlg); hilitehd (); break; @@ -9222,21 +9272,55 @@ static INT_PTR CALLBACK HarddiskDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPA } case WM_COMMAND: - switch (LOWORD(wParam)) - { - case 10001: - clicked_entry--; - hilitehd (); - break; - case 10002: - clicked_entry++; - hilitehd (); - break; - default: - harddiskdlg_button (hDlg, LOWORD (wParam)); - InitializeListView (hDlg); - hilitehd (); + if (HIWORD (wParam) == CBN_SELCHANGE || HIWORD (wParam) == CBN_KILLFOCUS) { + switch (LOWORD (wParam)) + { + case IDC_CD_TEXT: + getfloppyname (hDlg, 0, 1, IDC_CD_TEXT); + quickstart_cdtype = 1; + workprefs.cdimagefileuse = true; + addcdtype (hDlg, IDC_CD_TYPE); + addfloppyhistory_2 (hDlg, 0, IDC_CD_TEXT, HISTORY_CD); + break; + case IDC_CD_TYPE: + int val = SendDlgItemMessage (hDlg, IDC_CD_TYPE, CB_GETCURSEL, 0, 0); + if (val != CB_ERR) { + quickstart_cdtype = val; + if (quickstart_cdtype >= 2) { + int len = sizeof quickstart_cddrive / sizeof (TCHAR); + quickstart_cdtype = 2; + workprefs.cdimagefileuse = true; + SendDlgItemMessage (hDlg, IDC_CD_TYPE, WM_GETTEXT, (WPARAM)len, (LPARAM)quickstart_cddrive); + _tcscpy (workprefs.cdimagefile, quickstart_cddrive); + } else { + eject_cd (); + quickstart_cdtype = val; + if (val > 0) + workprefs.cdimagefileuse = true; + + } + addcdtype (hDlg, IDC_CD_TYPE); + addfloppyhistory_2 (hDlg, 0, IDC_CD_TEXT, HISTORY_CD); + } break; + } + } else { + switch (LOWORD(wParam)) + { + case 10001: + clicked_entry--; + hilitehd (); + break; + case 10002: + clicked_entry++; + hilitehd (); + break; + default: + harddiskdlg_button (hDlg, wParam); + InitializeListView (hDlg); + hilitehd (); + break; + } } break; @@ -9305,23 +9389,21 @@ static void floppytooltip (HWND hDlg, int num, uae_u32 crc32) SendMessage (ToolTipHWND, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti); } -static void addfloppyhistory_2 (HWND hDlg, int n, int f_text) +static void addfloppyhistory_2 (HWND hDlg, int n, int f_text, int type) { int i, j; TCHAR *s, *text; UAEREG *fkey; - int nn, type, curidx; + int nn, curidx; if (f_text < 0) return; SendDlgItemMessage (hDlg, f_text, CB_RESETCONTENT, 0, 0); - if (iscd (n)) { + if (type == HISTORY_CD) { nn = 1; - type = HISTORY_CD; text = workprefs.cdimagefile; } else { nn = workprefs.dfxtype[n] + 1; - type = HISTORY_FLOPPY; text = workprefs.df[n]; } SendDlgItemMessage (hDlg, f_text, WM_SETTEXT, 0, (LPARAM)text); @@ -9387,18 +9469,38 @@ static void addfloppyhistory (HWND hDlg) f_text = floppybuttons[n][0]; else f_text = IDC_DISKTEXT; - addfloppyhistory_2 (hDlg, n, f_text); + addfloppyhistory_2 (hDlg, n, f_text, iscd (n) ? HISTORY_CD : HISTORY_FLOPPY); } } -static void ejectfloppy (int n) +static void addcdtype (HWND hDlg, int id) { - if (iscd (n)) { - workprefs.cdimagefile[0] = 0; - quickstart_cdtype = 0; - } else { - workprefs.df[n][0] = 0; + TCHAR tmp[MAX_DPATH]; + SendDlgItemMessage (hDlg, id, CB_RESETCONTENT, 0, 0L); + WIN32GUI_LoadUIString (IDS_QS_CD_AUTO, tmp, sizeof tmp / sizeof (TCHAR)); + SendDlgItemMessage (hDlg, id, CB_ADDSTRING, 0, (LPARAM)tmp); + WIN32GUI_LoadUIString (IDS_QS_CD_IMAGE, tmp, sizeof tmp / sizeof (TCHAR)); + 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]) + cdtype = 0; + } + int cnt = 2; + for (int drive = 'C'; drive <= 'Z'; ++drive) { + TCHAR vol[100]; + _stprintf (vol, L"%c:\\", drive); + int drivetype = GetDriveType (vol); + if (drivetype == DRIVE_CDROM) { + SendDlgItemMessage (hDlg, id, CB_ADDSTRING, 0, (LPARAM)vol); + if (!_tcsicmp (vol, quickstart_cddrive)) { + cdtype = quickstart_cdtype = cnt; + _tcscpy (workprefs.cdimagefile, vol); + } + cnt++; + } } + SendDlgItemMessage (hDlg, id, CB_SETCURSEL, cdtype, 0); } static void addfloppytype (HWND hDlg, int n) @@ -9437,29 +9539,7 @@ static void addfloppytype (HWND hDlg, int n) ew (hDlg, f_enable, FALSE); WIN32GUI_LoadUIString (IDS_QS_CD, tmp, sizeof tmp / sizeof (TCHAR)); SetWindowText (GetDlgItem (hDlg, f_enable), tmp); - SendDlgItemMessage (hDlg, IDC_CD0Q_TYPE, CB_RESETCONTENT, 0, 0L); - WIN32GUI_LoadUIString (IDS_QS_CD_AUTO, tmp, sizeof tmp / sizeof (TCHAR)); - SendDlgItemMessage (hDlg, IDC_CD0Q_TYPE, CB_ADDSTRING, 0, (LPARAM)tmp); - WIN32GUI_LoadUIString (IDS_QS_CD_IMAGE, tmp, sizeof tmp / sizeof (TCHAR)); - SendDlgItemMessage (hDlg, IDC_CD0Q_TYPE, CB_ADDSTRING, 0, (LPARAM)tmp); - quickstart_cdtype = 0; - if (workprefs.cdimagefile[0]) - quickstart_cdtype = 1; - int cnt = 2; - for (int drive = 'C'; drive <= 'Z'; ++drive) { - TCHAR vol[100]; - _stprintf (vol, L"%c:\\", drive); - int drivetype = GetDriveType (vol); - if (drivetype == DRIVE_CDROM) { - SendDlgItemMessage (hDlg, IDC_CD0Q_TYPE, CB_ADDSTRING, 0, (LPARAM)vol); - if (!_tcsicmp (vol, quickstart_cddrive)) { - quickstart_cdtype = cnt; - _tcscpy (workprefs.cdimagefile, vol); - } - cnt++; - } - } - SendDlgItemMessage (hDlg, IDC_CD0Q_TYPE, CB_SETCURSEL, quickstart_cdtype, 0); + addcdtype (hDlg, IDC_CD0Q_TYPE); hide (hDlg, IDC_CD0Q_TYPE, 0); text = workprefs.cdimagefile; regsetstr (NULL, L"QuickStartCDDrive", quickstart_cdtype >= 2 ? quickstart_cddrive : L""); @@ -9580,10 +9660,8 @@ static int getfloppybox (HWND hDlg, int f_text, TCHAR *out, int maxlen, int type return out[0] ? 1 : 0; } -static void getfloppyname (HWND hDlg, int n) +static void getfloppyname (HWND hDlg, int n, int cd, int f_text) { - int f_text = currentpage == QUICKSTART_ID ? floppybuttonsq[n][0] : floppybuttons[n][0]; - int cd = iscd (n); TCHAR tmp[MAX_DPATH]; if (getfloppybox (hDlg, f_text, tmp, sizeof (tmp) / sizeof (TCHAR), cd ? HISTORY_CD : HISTORY_FLOPPY)) { @@ -9591,14 +9669,18 @@ static void getfloppyname (HWND hDlg, int n) disk_insert (n, tmp); _tcscpy (workprefs.df[n], tmp); } else { - if (quickstart_cddrive[0]) { - quickstart_cdtype = 0; - quickstart_cddrive[0] = 0; - } + if (quickstart_cddrive[0]) + eject_cd (); _tcscpy (workprefs.cdimagefile, tmp); } } } +static void getfloppyname (HWND hDlg, int n) +{ + int cd = iscd (n); + int f_text = currentpage == QUICKSTART_ID ? floppybuttonsq[n][0] : floppybuttons[n][0]; + getfloppyname (hDlg, n, cd, f_text); +} static void addallfloppies (HWND hDlg) { @@ -10165,7 +10247,7 @@ static INT_PTR CALLBACK SwapperDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPAR static PRINTER_INFO_1 *pInfo = NULL; static DWORD dwEnumeratedPrinters = 0; #define MAX_PRINTERS 10 -struct serialportinfo comports[MAX_SERIAL_PORTS]; +struct serparportinfo comports[MAX_SERPAR_PORTS]; static int ghostscript_available; static int joyxprevious[4]; @@ -10549,7 +10631,7 @@ static void values_to_portsdlg (HWND hDlg) } else { int i; LRESULT result = -1; - for (i = 0; i < MAX_SERIAL_PORTS && comports[i].name; i++) { + for (i = 0; i < MAX_SERPAR_PORTS && comports[i].name; i++) { if (!_tcscmp (comports[i].dev, workprefs.sername)) { result = SendDlgItemMessage (hDlg, IDC_SERIAL, CB_SETCURSEL, i + 1, 0L); break; @@ -10605,7 +10687,7 @@ static void init_portsdlg (HWND hDlg) SendDlgItemMessage (hDlg, IDC_SERIAL, CB_RESETCONTENT, 0, 0L); SendDlgItemMessage (hDlg, IDC_SERIAL, CB_ADDSTRING, 0, (LPARAM)szNone.c_str()); - for (port = 0; port < MAX_SERIAL_PORTS && comports[port].name; port++) { + for (port = 0; port < MAX_SERPAR_PORTS && comports[port].name; port++) { SendDlgItemMessage (hDlg, IDC_SERIAL, CB_ADDSTRING, 0, (LPARAM)comports[port].name); } diff --git a/od-win32/winuae_msvc10/winuae_msvc.vcxproj b/od-win32/winuae_msvc10/winuae_msvc.vcxproj index ce36832f..7674f44e 100644 --- a/od-win32/winuae_msvc10/winuae_msvc.vcxproj +++ b/od-win32/winuae_msvc10/winuae_msvc.vcxproj @@ -574,6 +574,7 @@ + diff --git a/od-win32/winuae_msvc10/winuae_msvc.vcxproj.filters b/od-win32/winuae_msvc10/winuae_msvc.vcxproj.filters index a7858e1f..60909705 100644 --- a/od-win32/winuae_msvc10/winuae_msvc.vcxproj.filters +++ b/od-win32/winuae_msvc10/winuae_msvc.vcxproj.filters @@ -481,6 +481,9 @@ common + + win32 + diff --git a/od-win32/winuaechangelog.txt b/od-win32/winuaechangelog.txt index a3e256bb..d079ec5d 100644 --- a/od-win32/winuaechangelog.txt +++ b/od-win32/winuaechangelog.txt @@ -1,5 +1,69 @@ +- 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 +- debugger 'w' memory freeze mode improved, now also works with copper writes, + word and long size freeze values work properly +- fixed right border corruption when horizontal centering enabled +- filesystem access problems fixed (b2, forgotten test code..) +- another "too fast CPU" hack re-added to audio code +- quickstart "disk image requires ks2.0+" message ignored A3000/A4000/CD32 configurations +- skip DMAL emulation in JIT modes +- rawinput supports rawinput packets that have zero scancode but virtual keycode set or + null device handle (for example some software injected keys and some keyboard media keys), + packets with null device handle are redirected to new "winuae null keyboard" + +Major updates in CD related options, IOCTL access, built-in image mounter, CD32, CDTV, +uaescsi.device: + +- cd rom image and IOCTL handling rewritten, unified toc and subchannel data structures +- cd drive/image selection added to harddrives panel (quickstart duplicate, temporary + location until real CD selection panel is done.. if ever..) Use this to switch images + and drives on the fly, report if switching causes crashes or weird behavior. + NOTE: only unit 0 supported in uaescsi.device mode, other units are immediately put + to "no disk" state when this option is used for the first time. +- quickstart/harddrives CD "image mode" selected with blank select box: enable image + drive without media +- always use IOCTL in CD32/CDTV modes +- only enumarate SPTI devices when uaescsi.device is enabled +- subchannel support added to IOCTL CDROM handling (CD+G) +- CloneCD (.ccd) CD image file support added, including subchannel files +- CD32 CD subchannel DMA channel emulated, CD+G audio CDs supported +- CD32 CD end of play notification only worked if play command was last packet sent +- many CD32 and CDTV on the fly drive/image/media change updates again +- CDTV statefile support added +- CDTV 6525 (CIA-like 3-port IO chip/interrupt controller) emulation rewritten +- CDTV CD subchannel hardware emulated (CD+G, see notes below) +- added CDTV front panel CD player buttons to input event list (they directly control + CD mechanism and they are the only buttons that work in CD+G mode) +- "regular" CDTV remote Play/Stop/etc.. input events emulate front panel buttons when CD drive + receives enable front panel command, sends "normal" keycodes when frontpanel is disabled +- simple SCSI emulation added to image mounter in uaescsi.device mode (no CD audio support yet) + simple means: CDFS in SCSI mode should work with mounted images now, nothing more. + (TEST UNIT READY, READ [6,10,12], READ TOC, INQUIRY, READ CAPACITY emulated. Audio CD commands + will be implemented in later betas) +- added SCSI emulation option to SCSI GUI panel, enables SCSI emulation when using real drives +- uaescsi.device mounted image file changed without CMD_ADDCHANGEINT or CMD_REMOVE media change + interrups: use long 8 second media change delay (CDFS default poll time is ~5s) + +CD+G notes: + +Some subchannel packets will be lost if emulation slows down too much. +CD+G confirmed working, CD+MIDI should also work but not tested. + +CD32 CD+G mode starts automatically, button also in main audio CD screen. + +CDTV needs extra steps: In audio CD player screen select "TV/Keyboard" icon in bottom +right corner, then press front panel Play-button, only front panel buttons are accepted +at this point. NOTE: CDTV CD+G does not (yet) work in cycle-exact mode. + +CD32 and CDTV do not correctly handle all CD+G discs, it seems both miss first few subchannel +packets at the beginning.. Confirmed on real CD32 and CDTV. They do work in emulation +if playback start position is about 1s earlier than asked but this hack is disabled +because it can cause cd audio sync issues in games. + +Beta 2: + - CD32/CDTV image mounting broke in b1 (can still be broken in some situations) - new audio state machine emulation froze in some situations - re-added "too fast CPU" hack that fixes missing sounds with sound routines that use CPU loops diff --git a/sana2.cpp b/sana2.cpp index 26f3e4f7..be8f1d54 100644 --- a/sana2.cpp +++ b/sana2.cpp @@ -229,11 +229,6 @@ static struct priv_devstruct pdevst[MAX_OPEN_DEVICES]; static uae_u32 nscmd_cmd; static uae_sem_t change_sem, async_sem; -static struct device_info *devinfo (int mode, int unitnum, struct device_info *di) -{ - return sys_command_info (mode, unitnum, di); -} - static struct devstruct *getdevstruct (int unit) { if (unit >= MAX_TOTAL_NET_DEVICES || unit < 0) diff --git a/savestate.cpp b/savestate.cpp index 04b9e66c..89133fec 100644 --- a/savestate.cpp +++ b/savestate.cpp @@ -573,6 +573,8 @@ void restore_state (const TCHAR *filename) #ifdef CDTV else if (!_tcscmp (name, L"CDTV")) end = restore_cdtv (chunk); + else if (!_tcscmp (name, L"DMAC")) + end = restore_dmac (chunk); #endif else if (!_tcscmp (name, L"GAYL")) end = restore_gayle (chunk); @@ -832,6 +834,9 @@ int save_state (const TCHAR *filename, const TCHAR *description) xfree (dst); #endif #ifdef CDTV + dst = save_dmac (&len); + save_chunk (f, dst, len, L"DMAC", 0); + xfree (dst); dst = save_cdtv (&len); save_chunk (f, dst, len, L"CDTV", 0); xfree (dst); diff --git a/scsiemul.cpp b/scsiemul.cpp index 35c73013..188463cd 100644 --- a/scsiemul.cpp +++ b/scsiemul.cpp @@ -79,7 +79,7 @@ static uae_sem_t change_sem; static struct device_info *devinfo (int mode, int unitnum, struct device_info *di) { - return sys_command_info (mode, unitnum, di); + return sys_command_info (mode, unitnum, di, 0); } static void io_log (const TCHAR *msg, uaecptr request) @@ -302,7 +302,7 @@ static int scsiemul_switchscsi (const TCHAR *name) while (i < MAX_TOTAL_DEVICES && dev == NULL) { discsi = 0; if (sys_command_open (mode, i)) { - discsi = sys_command_info (mode, i, &discsi2); + discsi = sys_command_info (mode, i, &discsi2, 0); if (discsi && discsi->type == INQ_ROMD) { if (!_tcsicmp (currprefs.cdimagefile, discsi->label)) { dev = &devst[0]; @@ -319,7 +319,7 @@ static int scsiemul_switchscsi (const TCHAR *name) } if (dev->di.media_inserted) { dev->di.media_inserted = 0; - scsi_do_disk_change (dev->di.id, 1); + scsi_do_disk_change (dev->di.id, 1, NULL); } } } @@ -342,10 +342,10 @@ static int scsiemul_switchemu (const TCHAR *name) return -1; int opened = sys_command_isopen (0); if (sys_command_open (DF_IOCTL, 0)) { - if (discsi = sys_command_info (DF_IOCTL, 0, &discsi2)) { + if (discsi = sys_command_info (DF_IOCTL, 0, &discsi2, 0)) { dev = &devst[0]; dev->unitnum = 0; - dev->allow_scsi = 0; + dev->allow_scsi = 1; dev->allow_ioctl = 1; dev->drivetype = discsi->type; memcpy (&dev->di, discsi, sizeof (struct device_info)); @@ -374,7 +374,8 @@ int scsi_do_disk_device_change (void) } // device_id = -1 and insert==0 -> all medias going away -int scsi_do_disk_change (int device_id, int insert) +// 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 i, j, ret; @@ -387,6 +388,8 @@ int scsi_do_disk_change (int device_id, int insert) if (dev->di.id == device_id || (device_id < 0 && i == 0)) { ret = i; if ((dev->di.media_inserted > 0 && insert == 0) || (dev->di.media_inserted <= 0 && insert)) { + if (pollmode) + *pollmode = 1; if (dev->aunit >= 0) { struct priv_devstruct *pdev = &pdevst[dev->aunit]; devinfo (pdev->mode, dev->unitnum, &dev->di); @@ -398,11 +401,16 @@ int scsi_do_disk_change (int device_id, int insert) while (j < MAX_ASYNC_REQUESTS) { if (dev->d_request_type[j] == ASYNC_REQUEST_CHANGEINT) { uae_Cause (dev->d_request_data[j]); + if (pollmode) + *pollmode = 0; } j++; } - if (dev->changeint) + if (dev->changeint) { uae_Cause (dev->changeint); + if (pollmode) + *pollmode = 0; + } } } } @@ -483,7 +491,7 @@ static int command_read (int mode, struct devstruct *dev, uaecptr data, uae_u64 length /= blocksize; offset /= blocksize; while (length > 0) { - temp = sys_command_read (mode, dev->unitnum, offset); + temp = sys_command_read (mode, dev->unitnum, NULL, offset, 1); if (!temp) return 20; memcpyha_safe (data, temp, blocksize); @@ -499,14 +507,14 @@ static int command_write (int mode, struct devstruct *dev, uaecptr data, uae_u64 uae_u32 blocksize = dev->di.bytespersector; struct device_scsi_info dsi; - if (!sys_command_scsi_info(mode, dev->unitnum, &dsi)) + if (!sys_command_scsi_info (mode, dev->unitnum, &dsi)) return 20; length /= blocksize; offset /= blocksize; while (length > 0) { int err; memcpyah_safe (dsi.buffer, data, blocksize); - err = sys_command_write (mode, dev->unitnum, offset); + err = sys_command_write (mode, dev->unitnum, NULL, offset, 1); if (!err) return 20; if (err < 0) @@ -530,7 +538,7 @@ static int command_cd_read (int mode, struct devstruct *dev, uaecptr data, uae_u offset -= startoffset; sector = offset / dev->di.bytespersector; while (length > 0) { - temp = sys_command_cd_read (mode, dev->unitnum, sector); + temp = sys_command_cd_read (mode, dev->unitnum, NULL, sector, 1); if (!temp) return 20; if (startoffset > 0) { @@ -928,7 +936,7 @@ static void dev_reset (void) } } if (mode >= 0) { - discsi = sys_command_info (mode, j, &discsi2); + discsi = sys_command_info (mode, j, &discsi2, 0); sys_command_close (mode, j); } if (discsi) { diff --git a/zfile.cpp b/zfile.cpp index 2d3f8914..53d754f2 100644 --- a/zfile.cpp +++ b/zfile.cpp @@ -1860,6 +1860,7 @@ struct zfile *zfile_dup (struct zfile *zf) nzf->zipname = my_strdup (zf->zipname); nzf->zfdmask = zf->zfdmask; nzf->mode = my_strdup (zf->mode); + nzf->size = zf->size; return nzf; }