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)
* - NVRAM
* - CDROM
*
-* Copyright 2001-2009 Toni Wilen
+* Copyright 2001-2010 Toni Wilen
*
*/
#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
#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;
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;
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;
static smp_comm_pipe requests;
static volatile int akiko_thread_running;
+static uae_sem_t akiko_sem, sub_sem;
static void checkint (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);
{
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;
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));
}
/* 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;
}
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]");
}
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);
}
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;
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;
}
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;
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) {
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 ())
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;
}
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 ();
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;
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;
}
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;
cdrom_sector_counter++;
}
-static uae_sem_t akiko_sem;
static int lastmediastate = 0;
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--;
}
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;
}
framecounter--;
if (framecounter <= 0) {
- int i;
if (cdrom_led) {
if (cdrom_playing)
cdrom_led |= LED_CD_AUDIO;
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)
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 ();
}
}
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");
}
}
}
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;
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;
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;
{
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;
}
}
}
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;
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;
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 ();
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
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
}
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;
}
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
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);
#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"
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])
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);
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;
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};
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);
#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 */
}
/* 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);
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)
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 {
}
}
-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)
}
}
-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;
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;
+}
#include "fsdb.h"
#include "threaddep/thread.h"
#include "scsidev.h"
+#include <mp3decoder.h>
+#include <memory.h>
#ifdef RETROPLATFORM
#include "rp.h"
#endif
+#define scsi_log write_log
+
#define USE 1
#define CDDA_BUFFERS 6
{
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;
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 <windows.h>
-#include <mmreg.h>
-#include <msacm.h>
-
-#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)
cdda_wavehandle = NULL;
}
-// DAE CDDA based on Larry Osterman's "Playing Audio CDs" blog series
-
static int cdda_openwav (void)
{
WAVEFORMATEX wav = { 0 };
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;
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;
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)
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;
}
}
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);
}
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)
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)
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;
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;
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);
}
index0 = -1;
tracknum = _tstoi (nextstring (&p));
tracktype = nextstring (&p);
+ if (!tracktype)
+ break;
size = 2352;
if (!_tcsicmp (tracktype, L"AUDIO")) {
ctrl &= ~4;
}
}
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) {
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);
}
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;
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;
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"<EMPTY>");
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);
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 <drive letter:>\?
+ if (mountme (cdu, false) < 0) // is it supported <drive letter:>\?
return 0;
}
if (currprefs.cdimagefileuse) {
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);
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,
*
* CDTV DMAC/CDROM controller emulation
*
-* Copyright 2004/2007 Toni Wilen
+* Copyright 2004/2007-2010 Toni Wilen
*
* Thanks to Mark Knibbs <markk@clara.co.uk> for CDTV Technical information
*
//#define ROMHACK
//#define ROMHACK2
+//#define CDTV_SUB_DEBUG
//#define CDTV_DEBUG
//#define CDTV_DEBUG_CMD
//#define CDTV_DEBUG_6525
#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;
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
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;
}
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)
{
}
cd_paused = pause;
cd_audio_status = pause ? AUDIO_STATUS_PAUSED : AUDIO_STATUS_IN_PROGRESS;
+ subreset ();
return 1;
}
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 {
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++;
}
}
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;
}
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;
}
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;
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;
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;
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;
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;
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;
}
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)
trackcnt++;
sector -= lsn - prevlsn;
prevlsn = lsn;
- s += 11;
+ t++;
}
if (track != trackcnt) {
_stprintf (fname, L"track%d.bin", trackcnt);
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)
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;
{
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 ();
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;
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)
{
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;
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;
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;
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;
}
}
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;
}
}
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;
}
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 ();
}
{
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
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)
}
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:
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;
}
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");
}
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())
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;
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
#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;
}
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);
}
}
- if (p->cdimagefile[0])
+ if (p->cdimagefile[0] || p->cdimagefileuse)
cfgfile_write_str (f, L"cdimage0", p->cdimagefile);
if (p->quitstatefile[0])
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;
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;
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;
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",
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 ();
}
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);
}
static TCHAR help[] = {
L" HELP for UAE Debugger\n"
L" -----------------------\n\n"
- L" g [<address>] Start execution at the current address or <address>\n"
- L" c Dump state of the CIA, disk drives and custom registers\n"
- L" r Dump state of the CPU\n"
- L" r <reg> <value> Modify CPU registers (Dx,Ax,USP,ISP,VBR,...)\n"
- L" m <address> [<lines>] Memory dump starting at <address>\n"
- L" d <address> [<lines>] Disassembly starting at <address>\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 <address> Add/remove breakpoint\n"
+ L" g [<address>] Start execution at the current address or <address>.\n"
+ L" c Dump state of the CIA, disk drives and custom registers.\n"
+ L" r Dump state of the CPU.\n"
+ L" r <reg> <value> Modify CPU registers (Dx,Ax,USP,ISP,VBR,...).\n"
+ L" m <address> [<lines>] Memory dump starting at <address>.\n"
+ L" d <address> [<lines>] Disassembly starting at <address>.\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 <address> Add/remove breakpoint.\n"
L" fa <address> [<start>] [<end>]\n"
- L" Find effective address <address>\n"
- L" fi Step forward until PC points to RTS, RTD or RTE\n"
- L" fi <opcode> Step forward until PC points to <opcode>\n"
- L" fp \"<name>\"/<addr> Step forward until process <name> or <addr> is active\n"
- L" fl List breakpoints\n"
- L" fd Remove all breakpoints\n"
- L" fs <val> <mask> Break when (SR & mask) = val\n"
- L" f <addr1> <addr2> Step forward until <addr1> <= PC <= <addr2>\n"
- L" e Dump contents of all custom registers, ea = AGA colors\n"
- L" i [<addr>] Dump contents of interrupt and trap vectors\n"
- L" il [<mask>] Exception breakpoint\n"
- L" o <0-2|addr> [<lines>]View memory as Copper instructions\n"
- L" od Enable/disable Copper vpos/hpos tracing\n"
- L" ot Copper single step trace\n"
- L" ob <addr> Copper breakpoint\n"
- L" H[H] <cnt> Show PC history (HH=full CPU info) <cnt> instructions\n"
- L" C <value> Search for values like energy or lifes in games\n"
- L" Cl List currently found trainer addresses\n"
+ L" Find effective address <address>.\n"
+ L" fi Step forward until PC points to RTS, RTD or RTE.\n"
+ L" fi <opcode> Step forward until PC points to <opcode>.\n"
+ L" fp \"<name>\"/<addr> Step forward until process <name> or <addr> is active.\n"
+ L" fl List breakpoints.\n"
+ L" fd Remove all breakpoints.\n"
+ L" fs <val> <mask> Break when (SR & mask) = val.\n"
+ L" f <addr1> <addr2> Step forward until <addr1> <= PC <= <addr2>.\n"
+ L" e Dump contents of all custom registers, ea = AGA colors.\n"
+ L" i [<addr>] Dump contents of interrupt and trap vectors.\n"
+ L" il [<mask>] Exception breakpoint.\n"
+ L" o <0-2|addr> [<lines>]View memory as Copper instructions.\n"
+ L" od Enable/disable Copper vpos/hpos tracing.\n"
+ L" ot Copper single step trace.\n"
+ L" ob <addr> Copper breakpoint.\n"
+ L" H[H] <cnt> Show PC history (HH=full CPU info) <cnt> instructions.\n"
+ L" C <value> 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 <address> <value> Write into Amiga memory\n"
- L" w <num> <address> <length> <R/W/I/F/C> [<value>] (read/write/opcode/freeze/mustchange)\n"
- L" Add/remove memory watchpoints\n"
+ L" W <address> <value[.x]> Write into Amiga memory.\n"
+ L" w <num> <address> <length> <R/W/I/F/C> [<value>[.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 <file> <addr> <n> Save a block of Amiga memory\n"
+ L" S <file> <addr> <n> Save a block of Amiga memory.\n"
L" s \"<string>\"/<values> [<addr>] [<length>]\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<a/b/s> <val> Enable or disable audio channels, bitplanes or sprites\n"
- L" sp <addr> [<addr2][<size>] Dump sprite information\n"
- L" di <mode> [<track>] Break on disk access. R=DMA read,W=write,RW=both,P=PIO\n"
- L" Also enables level 1 disk logging\n"
- L" did <log level> Enable disk logging\n"
- L" dj [<level bitmask>] 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<a/b/s> <val> Enable or disable audio channels, bitplanes or sprites.\n"
+ L" sp <addr> [<addr2][<size>] Dump sprite information.\n"
+ L" di <mode> [<track>] Break on disk access. R=DMA read,W=write,RW=both,P=PIO.\n"
+ L" Also enables level 1 disk logging.\n"
+ L" did <log level> Enable disk logging.\n"
+ L" dj [<level bitmask>] 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 <vpos> [<hpos>] Show DMA data (accurate only in cycle-exact mode)\n"
- L" v [-1 to -4] = enable visual DMA debugger\n"
- L" ?<value> Hex/Bin/Dec converter\n"
+ L" dm Dump current address space map.\n"
+ L" v <vpos> [<hpos>] Show DMA data (accurate only in cycle-exact mode).\n"
+ L" v [-1 to -4] = enable visual DMA debugger.\n"
+ L" ?<value> Hex/Bin/Dec converter.\n"
#ifdef _WIN32
L" x Close debugger.\n"
L" xx Switch between console and GUI debugger.\n"
- L" mg <address> Memory dump starting at <address> in GUI\n"
- L" dg <address> Disassembly starting at <address> in GUI\n"
+ L" mg <address> Memory dump starting at <address> in GUI.\n"
+ L" dg <address> Disassembly starting at <address> in GUI.\n"
#endif
L" q Quit the emulator. You don't want to use this command.\n\n"
};
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;
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;
uaecptr prev, prevx;
int size, sizex;
- if (addr >= lastaddr()) {
+ if (addr >= lastaddr ()) {
*next = -1;
return 0xffffffff;
}
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;
}
if (end)
next = *end;
- addr = nextaddr2(addr + 1, &next);
+ addr = nextaddr2 (addr + 1, &next);
if (end)
*end = next;
#if 0
(*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;
}
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;
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;
} 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;
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)
memsize = 0;
addr = 0xffffffff;
- while ((addr = nextaddr (addr, &end)) != 0xffffffff) {
+ while ((addr = nextaddr (addr, 0, &end)) != 0xffffffff) {
memsize += end - addr;
addr = end - 1;
}
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;
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;
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 {
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;
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;
}
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;
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)
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);
} else if (_totupper (**c) == 'C') {
mwn->mustchange = 1;
} else {
- mwn->val = readhex (c);
+ mwn->val = readhex (c, &mwn->val_size);
mwn->val_enabled = 1;
}
}
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';
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++) {
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)
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;
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);
* 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]
*
*/
#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;
bitoffset &= 15;
floppybits -= drv->trackspeed;
}
-#if 0
- dma_tab[j] = 0xffffffff;
-#endif
}
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)
{
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 */
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;
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)
{
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;
}
}
}
-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;
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) {
}
}
-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);
}
}
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)
{
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;
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;
}
}
}
}
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);
break;
}
}
-
enum double_how {
dh_buf,
dh_line,
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];
fill_line ();
linestate[line] = LINE_UNDECIDED;
do_flush_line (where2);
- colors_for_drawing.acolors[0] = tmp;
}
if (currprefs.leds_on_screen) {
#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
int id;
TCHAR label[MAX_DPATH];
TCHAR mediapath[MAX_DPATH];
+ struct cd_toc_head toc;
};
struct device_scsi_info {
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);
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
extern void cdtv_scsi_int (void);
extern void cdtv_scsi_clear_int (void);
+extern bool cdtv_front_panel (int);
+
#endif
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;
#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];
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
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;
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);
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
#include "autoconf.h"
#include "rp.h"
#include "dongle.h"
+#include "cdtv.h"
extern int bootrom_header, bootrom_items;
#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];
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;
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
}
}
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,
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++) {
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)
+
key = keybuf[kpb_last];
if (++kpb_last == 256)
kpb_last = 0;
+ //write_log (L"%02x:%d\n", key >> 1, key & 1);
return key;
}
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)
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);
}
}
}
*
* WIN32 CDROM/HD low level access code (IOCTL)
*
-* Copyright 2002 Toni Wilen
+* Copyright 2002-2010 Toni Wilen
*
*/
int mediainserted;
int type;
int blocksize;
- int mciid;
- int cdda;
CDROM_TOC toc;
UINT errormode;
int playend;
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;
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)
{
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];
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;
return 1;
}
}
- closed = close_mci (unitnum);
if (log_scsi)
write_log (L"IOCTL: opening IOCTL %s\n", ciw->devname);
for (;;) {
}
}
}
- 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 ());
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)
MMRESULT mmr;
int volume, volume_main;
int oldplay;
-
+ int firstloops;
for (i = 0; i < 2; i++) {
memset (&whdr[i], 0, sizeof (WAVEHDR));
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)
}
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;
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;
}
}
end:
+ ciw->subcodevalid = false;
while (!(whdr[0].dwFlags & WHDR_DONE) || !(whdr[1].dwFlags & WHDR_DONE))
Sleep (10);
for (i = 0; i < 2; i++)
}
ciw->cdda_play_finished = 0;
ciw->cdda_paused = 0;
+ ciw->subcodevalid = 0;
}
/* pause/unpause CD audio */
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;
}
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;
}
}
/* 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];
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 {
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);
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;
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;
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)
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;
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);
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);
return -1;
return 0;
}
+ *ptr = p;
} else {
dtotal = 0;
if (!ReadFile (ciw32[unitnum].h, p, blocksize, &dtotal, 0)) {
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;
}
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;
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;
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 */
{
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 */
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;
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)
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;
}
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
*
* WIN32 CDROM/HD low level access code (SPTI)
*
-* Copyright 2002-2005 Toni Wilen
+* Copyright 2002-2010 Toni Wilen
*
*/
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)
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
#ifdef WINDDK
#include <winioctl.h>
#include <ntddkbd.h>
+#include <ntddpar.h>
#endif
#include <setupapi.h>
#include <devguid.h>
#define DIDC_RAW 2
#define DIDC_WIN 3
#define DIDC_CAT 4
+#define DIDC_PARJOY 5
struct didata {
int type;
int catweasel;
int coop;
+ HANDLE parjoy;
+ PAR_QUERY_INFORMATION oldparjoystatus;
+
int axles;
int buttons, buttons_real;
int axismappings[MAX_MAPPINGS];
int axisparentdir[MAX_MAPPINGS];
};
+#define MAX_PARJOYPORTS 2
+
#define DI_BUFFER 30
#define DI_KBBUFFER 50
#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;
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");
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;
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++;
}
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);
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
} 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;
// 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 ())
{
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)
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");
}
}
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)
DWORD CreationDisposition = OPEN_EXISTING;
DWORD FlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
DWORD attr;
- wstring fname;
mos = xmalloc (struct my_openfile_s, 1);
if (!mos)
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)) {
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);
#include <io.h>
#include <setupapi.h>
+#include <Ntddpar.h>
#include "sysdeps.h"
#include "options.h"
#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.
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
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)};
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 {
return cnt;
}
+static struct serparportinfo parports[MAX_SERPAR_PORTS];
+
int enumserialports (void)
{
int cnt, i, j;
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)))
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);
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;
}
{
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;
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;
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
#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
#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
CONTROL "DF3:",IDC_DF3ENABLE,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,3,111,34,15\r
END\r
\r
-IDD_HARDDISK DIALOGEX 0, 0, 300, 237\r
+IDD_HARDDISK DIALOGEX 0, 0, 300, 243\r
STYLE DS_LOCALEDIT | DS_SETFONT | DS_3DLOOK | DS_CONTROL | WS_CHILD\r
EXSTYLE WS_EX_CONTEXTHELP\r
FONT 8, "MS Sans Serif", 0, 0, 0x1\r
BEGIN\r
- CONTROL "List1",IDC_VOLUMELIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,5,0,290,167\r
- PUSHBUTTON "Add &Directory or Archive...",IDC_NEW_FS,10,171,103,15\r
- PUSHBUTTON "Add &Hardfile...",IDC_NEW_HF,130,171,74,15\r
- PUSHBUTTON "Add Ha&rd Drive...",IDC_NEW_HD,220,171,75,15\r
- PUSHBUTTON "Remove",IDC_REMOVE,235,193,60,15\r
- PUSHBUTTON "&Properties",IDC_EDIT,235,210,60,15\r
- CONTROL "Add PC drives at startup",IDC_MAPDRIVES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,192,100,10\r
- CONTROL "Disable UAEFSDB-support",IDC_NOUAEFSDB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,192,119,10\r
- CONTROL "Don't use Windows Recycle Bin",IDC_NORECYCLEBIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,203,121,10\r
- CONTROL "Include network drives..",IDC_MAPDRIVES_NET,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,226,101,10\r
- CONTROL "Include CD/DVD drives..",IDC_MAPDRIVES_CD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,215,100,10\r
- CONTROL "Automount removable drives",IDC_MAPDRIVES_AUTO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,215,115,10\r
+ CONTROL "List1",IDC_VOLUMELIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,5,0,290,130\r
+ PUSHBUTTON "Add &Directory or Archive...",IDC_NEW_FS,10,135,103,15\r
+ PUSHBUTTON "Add &Hardfile...",IDC_NEW_HF,130,135,74,15\r
+ PUSHBUTTON "Add Ha&rd Drive...",IDC_NEW_HD,220,135,75,15\r
+ PUSHBUTTON "Remove",IDC_REMOVE,235,155,60,15\r
+ PUSHBUTTON "&Properties",IDC_EDIT,235,172,60,15\r
+ CONTROL "Add PC drives at startup",IDC_MAPDRIVES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,154,100,10\r
+ CONTROL "Disable UAEFSDB-support",IDC_NOUAEFSDB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,154,119,10\r
+ CONTROL "Don't use Windows Recycle Bin",IDC_NORECYCLEBIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,165,121,10\r
+ CONTROL "Include network drives..",IDC_MAPDRIVES_NET,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,188,101,10\r
+ CONTROL "Include CD/DVD drives..",IDC_MAPDRIVES_CD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,177,100,10\r
+ CONTROL "Automount removable drives",IDC_MAPDRIVES_AUTO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,177,115,10\r
CONTROL "Include removable drives..",IDC_MAPDRIVES_REMOVABLE,\r
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,203,100,10\r
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,165,100,10\r
+ COMBOBOX IDC_CD_TEXT,5,224,289,75,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP\r
+ PUSHBUTTON "Eject",IDC_CD_EJECT,265,204,30,15\r
+ PUSHBUTTON "Select image file",IDC_CD_SELECT,90,204,98,15\r
+ COMBOBOX IDC_CD_TYPE,194,205,63,50,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
+ LTEXT "CD drive/image",IDC_STATIC,5,206,70,10,SS_CENTERIMAGE\r
END\r
\r
IDD_SOUND DIALOGEX 0, 0, 300, 237\r
BEGIN\r
END\r
\r
+ IDD_HARDDISK, DIALOG\r
+ BEGIN\r
+ END\r
+\r
IDD_SOUND, DIALOG\r
BEGIN\r
END\r
BEGIN\r
END\r
\r
+ IDD_HARDFILE, DIALOG\r
+ BEGIN\r
+ END\r
+\r
IDD_CHIPSET, DIALOG\r
BEGIN\r
END\r
BOTTOMMARGIN, 237\r
END\r
\r
+ IDD_HARDDRIVE, DIALOG\r
+ BEGIN\r
+ END\r
+\r
IDD_MISC2, DIALOG\r
BEGIN\r
END\r
BEGIN\r
END\r
\r
+ IDD_EXPANSION, DIALOG\r
+ BEGIN\r
+ END\r
+\r
IDD_INPUTMAP, DIALOG\r
BEGIN\r
TOPMARGIN, 1\r
IDS_NETDISCONNECTED "Cable disconnected"\r
IDS_QS_CD "CD"\r
IDS_QS_CD_AUTO "Autodetect"\r
- IDS_QS_CD_IMAGE "Image file"\r
+ IDS_QS_CD_IMAGE "Image mode"\r
IDS_REMAPTITLE "Input captured. F12 = Exit. F11 = Skip current event in Remap mode."\r
IDS_FILTER_NOOVERLAYS "No overlays available"\r
END\r
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);
}
}
}
}
-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)
{
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);
}
|| 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)
#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""
#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"
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
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);
}
}
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);
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);
}
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;
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);
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)
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;
}
}
{ 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;
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;
}
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;
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);
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)
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"");
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)) {
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)
{
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];
} 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;
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);
}
<ClCompile Include="..\lcd.cpp" />
<ClCompile Include="..\midi.cpp" />
<ClCompile Include="..\mman.cpp" />
+ <ClCompile Include="..\mp3decoder.cpp" />
<ClCompile Include="..\parser.cpp" />
<ClCompile Include="..\picasso96_win.cpp" />
<ClCompile Include="..\posixemu.cpp" />
<ClCompile Include="..\..\cpuemu_21.cpp">
<Filter>common</Filter>
</ClCompile>
+ <ClCompile Include="..\mp3decoder.cpp">
+ <Filter>win32</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\resources\35floppy.ico">
+- 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
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)
#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);
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);
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)
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];
}
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);
}
}
}
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));
}
// 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;
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);
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;
+ }
}
}
}
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);
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)
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) {
}
}
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) {
nzf->zipname = my_strdup (zf->zipname);
nzf->zfdmask = zf->zfdmask;
nzf->mode = my_strdup (zf->mode);
+ nzf->size = zf->size;
return nzf;
}