#define CH_ERR_ABNORMALSEEK 0xf0 // %11110000
#define CH_ERR_NODISK 0xf8 // %11111000
-static int framecounter, subcodecounter;
+static int subcodecounter;
#define MAX_SUBCODEBUFFER 20
static volatile int subcodebufferoffset, subcodebufferoffsetw;
static uae_u8 qcode_buf[SUBQ_SIZE];
static int qcode_valid;
-static int cdrom_disk, cdrom_paused, cdrom_playing;
+static int cdrom_disk, cdrom_paused, cdrom_playing, cdrom_audiostatus;
static int cdrom_command_active;
static int cdrom_command_length;
static int cdrom_checksum_error, cdrom_unknown_command;
static void cdaudiostop (void)
{
+ cdrom_audiostatus = 0;
cdrom_audiotimeout = 0;
cdrom_paused = 0;
cdrom_playing = 0;
uae_sem_post (&sub_sem);
}
+static int statusfunc (int status)
+{
+ if (status < 0)
+ return 1000;
+ if (cdrom_audiostatus != status) {
+ if (status == AUDIO_STATUS_IN_PROGRESS) {
+ cdrom_playing = 1;
+ cdrom_audiotimeout = 1;
+ }
+ if (cdrom_playing && status != AUDIO_STATUS_IN_PROGRESS && status != AUDIO_STATUS_PAUSED) {
+ cdrom_audiotimeout = -1;
+ }
+ }
+ cdrom_audiostatus = status;
+ return 0;
+}
+
static void cdaudioplay_do (void)
{
uae_u32 startlsn = read_comm_pipe_u32_blocking (&requests);
if (unitnum < 0)
return;
sys_command_cd_pause (unitnum, 0);
- sys_command_cd_play (unitnum, startlsn, endlsn, scan, subfunc);
+ sys_command_cd_play (unitnum, startlsn, endlsn, scan, statusfunc, subfunc);
}
static bool isaudiotrack (int startlsn)
buf[2] = 0x80;
if (!qcode_valid)
return 0;
- if (cdrom_playing) // fake it!
- as = AUDIO_STATUS_IN_PROGRESS;
- if (as != AUDIO_STATUS_IN_PROGRESS && as != AUDIO_STATUS_PAUSED && as != AUDIO_STATUS_PLAY_COMPLETE && as != AUDIO_STATUS_NO_STATUS) /* audio status ok? */
+ if (cdrom_audiostatus != AUDIO_STATUS_IN_PROGRESS && cdrom_audiostatus != AUDIO_STATUS_PAUSED)
return 0;
s = buf + 4;
last_play_pos = msf2lsn (fromlongbcd (s + 7));
seekpos, msf2lsn (seekpos), endpos, msf2lsn (endpos), scan);
#endif
cdrom_playing = 1;
- cdrom_result_buffer[1] |= CDS_PLAYING;
if (!cd_play_audio (seekpos, endpos, 0)) {
- // play didn't start, report it in next status packet
+ // play didn't start, report it in next status packet
cdrom_audiotimeout = -3;
}
+ cdrom_result_buffer[1] |= CDS_PLAYING;
} else {
#if AKIKO_DEBUG_IO_CMD
write_log (L"SEEKTO %06X\n",seekpos);
return 2;
}
-static int cdrom_playend_notify (int err)
+static int cdrom_playend_notify (int status)
{
cdrom_result_buffer[0] = 4;
- cdrom_result_buffer[1] = err ? 0x80 : 0x00;
+ if (status < 0)
+ cdrom_result_buffer[1] = 0x80; // error
+ else if (status == 0)
+ cdrom_result_buffer[1] = 0x08; // play started
+ else
+ cdrom_result_buffer[1] = 0x00; // play ended
return 2;
}
get_cdrom_toc ();
return;
}
+ if (cdrom_audiotimeout == 1) { // play start
+ cdrom_start_return_data (cdrom_playend_notify (0));
+ cdrom_audiotimeout = 0;
+ }
if (cdrom_audiotimeout == -1) { // play finished (or disk end)
if (cdrom_playing) {
cdaudiostop ();
cdrom_audiotimeout = 0;
}
}
- if (cdrom_audiotimeout == -2 && qcode_buf[1] != AUDIO_STATUS_IN_PROGRESS) {
- cdrom_start_return_data (cdrom_playend_notify (0));
+ if (cdrom_audiotimeout == -2) { // play end notification
+ cdrom_start_return_data (cdrom_playend_notify (1));
cdrom_audiotimeout = 0;
}
- if (cdrom_audiotimeout == -3) {
- cdrom_start_return_data (cdrom_playend_notify (1));
+ // play didn't start notification (illegal address)
+ if (cdrom_audiotimeout == -3) { // return error status
+ cdrom_start_return_data (cdrom_playend_notify (-1));
cdrom_audiotimeout = 0;
}
if (!currprefs.cs_cd32cd || !akiko_inited)
return;
+ static float framecounter;
framecounter--;
if (framecounter <= 0) {
if (cdrom_seek_delay <= 0) {
} else {
cdrom_seek_delay--;
}
- framecounter = 1000000 / (63 * 75 * cdrom_speed);
+ framecounter += (float)maxvpos * vblank_hz / (75.0 * cdrom_speed);
}
subcodecounter--;
if (subcodecounter <= 0) {
- if ((cdrom_flags & CDFLAG_SUBCODE) && subcodebufferoffset != subcodebufferoffsetw) {
+ if ((cdrom_flags & CDFLAG_SUBCODE) && cdrom_playing && subcodebufferoffset != subcodebufferoffsetw) {
uae_sem_wait (&sub_sem);
if (subcodebufferinuse[subcodebufferoffset]) {
if (cdrom_subcodeoffset >= 128)
}
uae_sem_post (&sub_sem);
}
- subcodecounter = 1000000 / (70 * 75 * cdrom_speed);
+ subcodecounter = maxvpos * vblank_hz / (75 * cdrom_speed) - 5;
}
if (frame2counter > 0)
if (mediacheckcounter > 0)
mediacheckcounter--;
- if (cdrom_audiotimeout > 0) {
- cdrom_audiotimeout--;
- if (cdrom_audiotimeout == 0)
- cdrom_audiotimeout = -1;
- }
-
akiko_internal ();
akiko_handler ();
}
if (unitnum >= 0 && sys_command_cd_qcode (unitnum, qcode_buf)) {
uae_u8 as = qcode_buf[1];
qcode_valid = 1;
- if (as == AUDIO_STATUS_IN_PROGRESS) {
- frame2counter /= 4;
- if (cdrom_audiotimeout == 0) {
- int lsn = msf2lsn (fromlongbcd (qcode_buf + 4 + 7));
- // make sure audio play really ends because not all drives report position accurately
- if ((lsn >= cdrom_toc_cd_buffer.lastaddress - 3 * 75 || lsn >= last_play_end - 3 * 75)) {
- cdrom_audiotimeout = 3 * 312;
- }
- }
- }
}
}
static struct device_functions *device_func[MAX_TOTAL_SCSI_DEVICES];
static int openlist[MAX_TOTAL_SCSI_DEVICES];
-static int waspaused[MAX_TOTAL_SCSI_DEVICES], wasslow[MAX_TOTAL_SCSI_DEVICES];
+static int waspaused[MAX_TOTAL_SCSI_DEVICES];
static int delayed[MAX_TOTAL_SCSI_DEVICES];
/* convert minutes, seconds and frames -> logical sector number */
struct device_info di;
device_func[unitnum]->info (unitnum, &di, 0);
wasopen[unitnum] = di.open;
- wasslow[unitnum] = di.slow_unit;
if (wasopen[unitnum]) {
device_func[unitnum]->closedev (unitnum);
if (currprefs.scsi) {
write_log (L"CD: delayed insert '%s'\n", currprefs.cdslots[unitnum].name[0] ? currprefs.cdslots[unitnum].name : L"<EMPTY>");
device_func_init (0);
if (wasopen[unitnum]) {
- if (!device_func[unitnum]->opendev (unitnum, currprefs.cdslots[unitnum].name, wasslow[unitnum])) {
+ if (!device_func[unitnum]->opendev (unitnum, currprefs.cdslots[unitnum].name, 0)) {
write_log (L"-> device open failed\n");
}
}
return do_scsi (unitnum, cmd, sizeof cmd) ? 0 : 1;
}
//startlsn = adjustplaypos (unitnum, startlsn);
- return device_func[unitnum]->play (unitnum, startlsn, endlsn, scan, NULL);
+ return device_func[unitnum]->play (unitnum, startlsn, endlsn, scan, NULL, NULL);
}
/* play CD audio with subchannels */
-int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan, play_subchannel_callback subfunc)
+int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan, play_status_callback statusfunc, play_subchannel_callback subfunc)
{
if (failunit (unitnum))
return 0;
if (device_func[unitnum]->play == NULL)
return sys_command_cd_play (unitnum, startlsn, endlsn, scan);
//startlsn = adjustplaypos (unitnum, startlsn);
- return device_func[unitnum]->play (unitnum, startlsn, endlsn, scan, subfunc);
+ return device_func[unitnum]->play (unitnum, startlsn, endlsn, scan, statusfunc, subfunc);
}
/* set CD audio volume */
goto errreq;
start = toc->toc[toc->first_track_offset + start].paddress;
}
- sys_command_cd_play (unitnum, start, end, scan, NULL);
+ sys_command_cd_play (unitnum, start, end, scan);
scsi_len = 0;
}
break;
goto errreq;
int start = toc->toc[toc->first_track_offset + strack - 1].paddress;
int end = etrack == toc->last_track ? toc->lastaddress : toc->toc[toc->first_track_offset + etrack - 1 + 1].paddress;
- if (!sys_command_cd_play (unitnum, start, end, 0, NULL))
+ if (!sys_command_cd_play (unitnum, start, end, 0))
goto notdatatrack;
scsi_len = 0;
}
if (end > di.toc.lastaddress)
end = di.toc.lastaddress;
if (len > 0) {
- if (!sys_command_cd_play (unitnum, start, start + len, 0, NULL))
+ if (!sys_command_cd_play (unitnum, start, start + len, 0))
goto notdatatrack;
}
scsi_len = 0;
if (start > end)
goto errreq;
if (start < end)
- if (!sys_command_cd_play (unitnum, start, end, 0, NULL))
+ if (!sys_command_cd_play (unitnum, start, end, 0))
goto notdatatrack;
scsi_len = 0;
}
int end = start + len;
if (end > di.toc.lastaddress)
end = di.toc.lastaddress;
- if (!sys_command_cd_play (unitnum, start, end, 0, NULL))
+ if (!sys_command_cd_play (unitnum, start, end, 0))
goto notdatatrack;
}
scsi_len = 0;
if (start > end)
goto errreq;
if (start < end) {
- if (!sys_command_cd_play (unitnum, start, end, 0, NULL))
+ if (!sys_command_cd_play (unitnum, start, end, 0))
goto notdatatrack;
}
}
uae_u64 cdsize;
int blocksize;
- int cdda_play_finished;
+ int cdda_play_state;
int cdda_play;
int cdda_paused;
int cdda_volume[2];
int cd_last_pos;
int cdda_start, cdda_end;
play_subchannel_callback cdda_subfunc;
- bool slowunit;
+ play_status_callback cdda_statusfunc;
+ int cdda_delay;
int imagechange;
TCHAR newfile[MAX_DPATH];
cdu->cdda_subfunc (d, 1);
}
+static int setstate (struct cdunit *cdu, int state)
+{
+ cdu->cdda_play_state = state;
+ if (cdu->cdda_statusfunc)
+ return cdu->cdda_statusfunc (cdu->cdda_play_state);
+ return 0;
+}
static void *cdda_unpack_func (void *v)
{
int volume[2], volume_main;
int oldplay;
struct cdunit *cdu = (struct cdunit*)v;
- int firstloops;
for (i = 0; i < 2; i++) {
memset (&whdr[i], 0, sizeof (WAVEHDR));
if (oldplay != cdu->cdda_play) {
struct cdtoc *t;
- int sector;
- struct _timeb tb;
+ int sector, diff;
+ struct _timeb tb1, tb2;
- _ftime (&tb);
+ _ftime (&tb1);
cdda_pos = cdu->cdda_start;
oldplay = cdu->cdda_play;
cdu->cd_last_pos = cdda_pos;
t = findtoc (cdu, §or);
if (!t) {
write_log (L"IMAGE CDDA: illegal sector number %d\n", cdu->cdda_start);
+ setstate (cdu, AUDIO_STATUS_PLAY_ERROR);
} else {
write_log (L"IMAGE 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);
while (cdimage_unpack_active == 0)
Sleep (10);
}
- firstloops = cdu->slowunit ? 150 : 30;
- while (cdu->cdda_paused && cdu->cdda_play > 0) {
- Sleep (10);
- firstloops = -1;
- }
- if (firstloops > 0)
- firstloops /= num_sectors;
+ _ftime (&tb2);
+ diff = (tb2.time * (uae_s64)1000 + tb2.millitm) - (tb1.time * (uae_s64)1000 + tb1.millitm);
+ diff -= cdu->cdda_delay;
+ if (diff < 0 && cdu->cdda_play > 0)
+ Sleep (-diff);
+ setstate (cdu, AUDIO_STATUS_IN_PROGRESS);
}
while (!(whdr[bufnum].dwFlags & WHDR_DONE)) {
}
bufon[bufnum] = 0;
- if (!isaudiotrack (&cdu->di.toc, cdda_pos))
+ if (!isaudiotrack (&cdu->di.toc, cdda_pos)) {
+ setstate (cdu, AUDIO_STATUS_PLAY_ERROR);
goto end; // data track?
+ }
if ((cdda_pos < cdu->cdda_end || cdu->cdda_end == 0xffffffff) && !cdu->cdda_paused && cdu->cdda_play > 0) {
struct cdtoc *t;
memset (px[bufnum], 0, num_sectors * 2352);
- 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;
+ for (cnt = 0; cnt < num_sectors; cnt++) {
+ sector = cdda_pos;
- if (cdu->cdda_scan) {
- cdda_pos += cdu->cdda_scan;
- if (cdda_pos < 0)
- cdda_pos = 0;
- } else {
- cdda_pos++;
- }
- if (cdda_pos - num_sectors < cdu->cdda_end && cdda_pos >= cdu->cdda_end)
- dofinish = 1;
-
- t = findtoc (cdu, §or);
- if (t) {
- if (t->handle && !(t->ctrl & 4)) {
- uae_u8 *dst = px[bufnum] + cnt * t->size;
- int totalsize = t->size + t->skipsize;
- if ((t->enctype == AUDENC_MP3 || t->enctype == AUDENC_FLAC) && t->data) {
- if (t->filesize >= sector * totalsize + t->offset + t->size)
- memcpy (dst, t->data + sector * totalsize + t->offset, t->size);
- } else if (t->enctype == AUDENC_PCM) {
- if (sector * totalsize + t->offset + totalsize < t->filesize) {
- zfile_fseek (t->handle, sector * totalsize + t->offset, SEEK_SET);
- zfile_fread (dst, t->size, 1, t->handle);
- }
+ if (cdu->cdda_scan) {
+ cdda_pos += cdu->cdda_scan;
+ if (cdda_pos < 0)
+ cdda_pos = 0;
+ } else {
+ cdda_pos++;
+ }
+ if (cdda_pos - num_sectors < cdu->cdda_end && cdda_pos >= cdu->cdda_end)
+ dofinish = 1;
+
+ t = findtoc (cdu, §or);
+ if (t) {
+ if (t->handle && !(t->ctrl & 4)) {
+ uae_u8 *dst = px[bufnum] + cnt * t->size;
+ int totalsize = t->size + t->skipsize;
+ if ((t->enctype == AUDENC_MP3 || t->enctype == AUDENC_FLAC) && t->data) {
+ if (t->filesize >= sector * totalsize + t->offset + t->size)
+ memcpy (dst, t->data + sector * totalsize + t->offset, t->size);
+ } else if (t->enctype == AUDENC_PCM) {
+ if (sector * totalsize + t->offset + totalsize < t->filesize) {
+ zfile_fseek (t->handle, sector * totalsize + t->offset, SEEK_SET);
+ zfile_fread (dst, t->size, 1, t->handle);
}
}
- dosub (cdu, t, cdda_pos);
}
+ dosub (cdu, t, cdda_pos);
}
-
}
volume_main = currprefs.sound_volume;
cdu->cd_last_pos = cdda_pos;
if (dofinish) {
- cdu->cdda_play_finished = 1;
+ setstate (cdu, AUDIO_STATUS_PLAY_COMPLETE);
cdu->cdda_play = -1;
cdda_pos = cdu->cdda_end + 1;
}
Sleep (10);
}
}
- cdu->cdda_play_finished = 0;
cdu->cdda_paused = 0;
}
return 1;
}
-static int command_play (int unitnum, int startlsn, int endlsn, int scan, play_subchannel_callback subfunc)
+static int command_play (int unitnum, int startlsn, int endlsn, int scan, play_status_callback statusfunc, play_subchannel_callback subfunc)
{
struct cdunit *cdu = unitisopen (unitnum);
if (!cdu)
return 0;
- if (!isaudiotrack (&cdu->di.toc, startlsn))
- return 0;
- cdu->cdda_play_finished = 0;
cdu->cd_last_pos = startlsn;
cdu->cdda_start = startlsn;
cdu->cdda_end = endlsn;
cdu->cdda_subfunc = subfunc;
+ cdu->cdda_statusfunc = statusfunc;
cdu->cdda_scan = scan > 0 ? 10 : (scan < 0 ? 10 : 0);
+ cdu->cdda_delay = setstate (cdu, -1);
+ setstate (cdu, AUDIO_STATUS_NOT_SUPPORTED);
+ if (!isaudiotrack (&cdu->di.toc, startlsn)) {
+ setstate (cdu, AUDIO_STATUS_PLAY_ERROR);
+ return 0;
+ }
if (!cdu->cdda_play)
uae_start_thread (L"cdimage_cdda_play", cdda_play_func, cdu, NULL);
cdu->cdda_play++;
memset (buf, 0, SUBQ_SIZE);
p = buf;
- status = AUDIO_STATUS_NO_STATUS;
- if (cdu->cdda_play > 0) {
- status = AUDIO_STATUS_IN_PROGRESS;
- if (cdu->cdda_paused)
- status = AUDIO_STATUS_PAUSED;
- } else if (cdu->cdda_play_finished) {
- status = AUDIO_STATUS_PLAY_COMPLETE;
- }
+ status = cdu->cdda_play_state;
+ if (cdu->cdda_play > 0 && cdu->cdda_paused)
+ status = AUDIO_STATUS_PAUSED;
+
if (sector < 0)
pos = cdu->cd_last_pos;
else
if (!cdu->enabled)
return NULL;
di->open = cdu->open;
- di->slow_unit = cdu->slowunit;
di->removable = 1;
di->bus = unitnum;
di->target = 0;
cdu->enabled = true;
cdu->cdda_volume[0] = 0x7fff;
cdu->cdda_volume[1] = 0x7fff;
- cdu->slowunit = (flags & 1) != 0;
blkdev_cd_change (unitnum, currprefs.cdslots[unitnum].name);
if (cdimage_unpack_thread == 0) {
init_comm_pipe (&unpack_pipe, 10, 1);
static volatile int dmac_wtc;
static volatile int dmac_dma;
-static volatile int activate_stch, cdrom_command_done, play_state, play_statewait;
+static volatile int activate_stch, cdrom_command_done;
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;
+static volatile int cd_playing, cd_paused, cd_motor, cd_media, cd_error, cd_finished, cd_isready, cd_audio_finished;
static uae_u32 last_play_pos, last_play_end;
static volatile int cdtv_hsync, dma_finished, cdtv_sectorsize;
return 1;
}
-static void finished_cdplay (void)
-{
- cd_audio_status = AUDIO_STATUS_PLAY_COMPLETE;
- cd_playing = 0;
- cd_finished = 1;
- cd_paused = 0;
- do_stch ();
-}
-
static int get_qcode (void)
{
if (!sys_command_cd_qcode (unitnum, cdrom_qcode))
return 0;
- if (cd_playing) {
- 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 (cdrom_qcode[1] == AUDIO_STATUS_PLAY_COMPLETE) {
- finished_cdplay ();
- }
- }
cdrom_qcode[1] = cd_audio_status;
return 1;
}
cd_playing = 0;
cd_paused = 0;
cd_motor = 0;
+ cd_audio_finished = 0;
write_comm_pipe_u32 (&requests, 0x0104, 1);
}
subcodebufferoffsetw = offset;
uae_sem_post (&sub_sem);
}
-
+static int statusfunc (int status)
+{
+ if (status < 0)
+ return 500;
+ if (cd_audio_status != status) {
+ if (status == AUDIO_STATUS_PLAY_COMPLETE || status == AUDIO_STATUS_PLAY_ERROR) {
+ cd_audio_finished = 1;
+ } else {
+ if (status == AUDIO_STATUS_IN_PROGRESS)
+ cd_playing = 1;
+ activate_stch = 1;
+ }
+ }
+ cd_audio_status = status;
+ return 0;
+}
static void do_play (void)
{
uae_u32 scan = read_comm_pipe_u32_blocking (&requests);
subreset ();
sys_command_cd_pause (unitnum, 0);
- cd_audio_status = AUDIO_STATUS_PLAY_ERROR;
sys_command_cd_volume (unitnum, (cd_volume_stored << 5) | (cd_volume_stored >> 5), (cd_volume_stored << 5) | (cd_volume_stored >> 5));
- if (sys_command_cd_play (unitnum, start, end, 0, subfunc)) {
- cd_audio_status = AUDIO_STATUS_IN_PROGRESS;
- cd_playing = 1;
- } else {
- cd_error = 1;
+ sys_command_cd_play (unitnum, start, end, 0, statusfunc, subfunc);
+}
+
+static void startplay (void)
+{
+ subreset ();
+ 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);
+ if (!cd_motor) {
+ cd_motor = 1;
+ activate_stch = 1;
}
- activate_stch = 1;
}
static int play_cdtrack (uae_u8 *p)
write_log (L"PLAY CD AUDIO from %d-%d, %06X (%d) to %06X (%d)\n",
track_start, track_end, start, start, end, end);
#endif
- play_state = 1;
+ startplay ();
return 0;
}
cd_playing = 0;
cd_paused = 0;
cd_motor = 0;
- cd_audio_status = AUDIO_STATUS_PLAY_COMPLETE;
- sys_command_cd_pause (unitnum, 0);
- sys_command_cd_stop (unitnum);
- cd_isready = 50;
+ write_comm_pipe_u32 (&requests, 0x0104, 1);
+ cd_audio_status = AUDIO_STATUS_NO_STATUS;
cd_error = 1;
+ activate_stch = 1;
return 0;
}
if (p[0] != 0x09) { /* msf */
write_log (L"PLAY CD AUDIO from %06X (%d) to %06X (%d)\n",
lsn2msf (start), start, lsn2msf (end), end);
#endif
- play_state = 1;
+ startplay ();
return 0;
}
{
case 0x01: /* seek */
if (cdrom_command_cnt_in == 7) {
- sleep_millis (500);
cdrom_command_accepted (0, s, &cdrom_command_cnt_in);
cd_finished = 1;
}
write_log (L"PLAY CD AUDIO from %06X (%d) to %06X (%d)\n",
lsn2msf (start), start, lsn2msf (end), end);
#endif
- play_state = 1;
- subreset ();
+ startplay ();
}
bool cdtv_front_panel (int button)
sten = 0;
}
+ if (cd_audio_finished) {
+ cd_audio_finished = 0;
+ cd_playing = 0;
+ cd_finished = 1;
+ cd_paused = 0;
+ //cd_error = 1;
+ activate_stch = 1;
+ }
+
static int subchannelcounter;
+ int cntmax = maxvpos * vblank_hz / 75 - 6;
if (subchannelcounter > 0)
subchannelcounter--;
if (subchannelcounter <= 0) {
tp_check_interrupts ();
}
uae_sem_post (&sub_sem);
- subchannelcounter = 200;
+ subchannelcounter = cntmax;
}
}
if (!scor && !cd_playing) {
scor = 1;
tp_check_interrupts ();
scor = 0;
- subchannelcounter = 200;
+ subchannelcounter = cntmax;
}
}
- if (cdtv_hsync < 200 && cdtv_hsync >= 0)
+ if (cdtv_hsync < cntmax && 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 = 2;
- } else if (play_statewait > 0) {
- play_statewait--;
- } else if (play_state == 2) {
- 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 0
if (cd_isready > 0) {
cd_isready--;
if (!cd_isready)
do_stch ();
}
+#endif
if (dmac_dma || dma_finished)
cd_led |= LED_CD_ACTIVE;
else
(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_u8 (0);
save_u16 (cd_volume_stored);
if (cd_playing)
get_qcode ();
stch = (v & 512) ? 1 : 0;
frontpanel = (v & 1024) ? 1 : 0;
cd_isready = restore_u8 ();
- play_state = restore_u8 ();
+ restore_u8 ();
cd_volume_stored = restore_u16 ();
last_play_pos = restore_u32 ();
last_play_end = restore_u32 ();
(*worker_border) (lastpos, nextpos_in_range);
lastpos = nextpos_in_range;
}
- if (i != dip_for_drawing->last_color_change) {
- if (regno >= 0x1000) {
- pfield_expand_dp_bplconx (regno, value);
- } else {
- color_reg_set (&colors_for_drawing, regno, value);
- colors_for_drawing.acolors[regno] = getxcolor (value);
- }
+ if (regno >= 0x1000) {
+ pfield_expand_dp_bplconx (regno, value);
+ } else if (regno >= 0) {
+ color_reg_set (&colors_for_drawing, regno, value);
+ colors_for_drawing.acolors[regno] = getxcolor (value);
}
if (lastpos >= endpos)
break;
TCHAR productid[18];
TCHAR revision[6];
TCHAR *backend;
- int slow_unit;
struct cd_toc_head toc;
};
typedef int (*execscsicmd_direct_func)(int, struct amigascsi*);
typedef void (*play_subchannel_callback)(uae_u8*, int);
+typedef int (*play_status_callback)(int);
typedef int (*pause_func)(int, int);
typedef int (*stop_func)(int);
-typedef int (*play_func)(int, int, int, int, play_subchannel_callback);
+typedef int (*play_func)(int, int, int, int, play_status_callback, play_subchannel_callback);
typedef uae_u32 (*volume_func)(int, uae_u16, uae_u16);
typedef int (*qcode_func)(int, uae_u8*, int);
typedef int (*toc_func)(int, struct cd_toc_head*);
extern int sys_command_cd_pause (int unitnum, int paused);
extern void sys_command_cd_stop (int unitnum);
extern int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int);
-extern int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan, play_subchannel_callback subfunc);
+extern int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan, play_status_callback statusfunc, play_subchannel_callback subfunc);
extern uae_u32 sys_command_cd_volume (int unitnum, uae_u16 volume_left, uae_u16 volume_right);
extern int sys_command_cd_qcode (int unitnum, uae_u8*);
extern int sys_command_cd_toc (int unitnum, struct cd_toc_head*);
extern int next_sprite_entry;
extern struct decision line_decisions[2 * (MAXVPOS + 2) + 1];
-extern struct draw_info line_drawinfo[2][2 * (MAXVPOS + 2) + 1];
extern uae_u8 line_data[(MAXVPOS + 2) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2];
#define MOVEC_DEBUG 0
#define MMUOP_DEBUG 2
+#define DEBUG_CD32CDTVIO 0
#include "sysconfig.h"
#include "sysdeps.h"
//static uae_u32 pcs[1000];
-//#define DEBUG_CD32CDTVIO
-#ifdef DEBUG_CD32CDTVIO
+#if DEBUG_CD32CDTVIO
static uae_u32 cd32nextpc, cd32request;
count_instr (opcode);
-#ifdef DEBUG_CD32CDTVIO
+#if DEBUG_CD32CDTVIO
out_cd32io (m68k_getpc ());
#endif
ipl_fetch ();
for (;;) {
uae_u32 opcode = r->ir;
-#ifdef DEBUG_CD32CDTVIO
+#if DEBUG_CD32CDTVIO
out_cd32io (m68k_getpc ());
#endif
(*cpufunctbl[opcode])(opcode);
uae_u32 opcode;
uae_u32 pc = m68k_getpc ();
-#ifdef DEBUG_CD32CDTVIO
+#if DEBUG_CD32CDTVIO
out_cd32io (m68k_getpc ());
#endif
#ifdef WINDDK
+#include <sys/timeb.h>
+
#include "options.h"
#include "uae.h"
#include "threaddep/thread.h"
uae_u8 subcodebuf[SUB_CHANNEL_SIZE];
bool subcodevalid;
play_subchannel_callback cdda_subfunc;
+ play_status_callback cdda_statusfunc;
+ int cdda_play_state;
+ int cdda_delay;
struct device_info di;
uae_sem_t sub_sem, sub_sem2;
bool open;
bool usesptiread;
- bool slowunit;
};
static struct dev_info_ioctl ciw32[MAX_TOTAL_SCSI_DEVICES];
return 1;
}
+static int setstate (struct dev_info_ioctl *ciw, int state)
+{
+ ciw->cdda_play_state = state;
+ if (ciw->cdda_statusfunc)
+ return ciw->cdda_statusfunc (ciw->cdda_play_state);
+ return 0;
+}
+
static void *cdda_play (void *v)
{
struct dev_info_ioctl *ciw = (struct dev_info_ioctl*)v;
MMRESULT mmr;
int volume[2], volume_main;
int oldplay;
- int firstloops;
int readblocksize = 2352 + 96;
+ int current_sector = -1;
for (i = 0; i < 2; i++) {
memset (&whdr[i], 0, sizeof (WAVEHDR));
bufon[bufnum] = 0;
if (oldplay != ciw->cdda_play) {
+ struct _timeb tb1, tb2;
+ current_sector = -1;
+ _ftime (&tb1);
cdda_pos = ciw->cdda_start;
oldplay = ciw->cdda_play;
- firstloops = ciw->slowunit ? 25 : 5;
write_log (L"IOCTL%s CDDA: playing from %d to %d\n",
ciw->usesptiread ? L"(SPTI)" : L"", ciw->cdda_start, ciw->cdda_end);
ciw->subcodevalid = false;
- while (ciw->cdda_paused && ciw->cdda_play > 0) {
- firstloops = -1;
+ while (ciw->cdda_paused && ciw->cdda_play > 0)
Sleep (10);
- }
+ // pre-load first sectors
+ if (read_block (ciw, -1, px[bufnum], cdda_pos, num_sectors, readblocksize))
+ current_sector = cdda_pos;
+ _ftime (&tb2);
+ int diff = (tb2.time * (uae_s64)1000 + tb2.millitm) - (tb1.time * (uae_s64)1000 + tb1.millitm);
+ diff -= ciw->cdda_delay;
+ if (diff < 0 && ciw->cdda_play > 0)
+ Sleep (-diff);
+ setstate (ciw, AUDIO_STATUS_IN_PROGRESS);
}
if ((cdda_pos < ciw->cdda_end || ciw->cdda_end == 0xffffffff) && !ciw->cdda_paused && ciw->cdda_play) {
- int sectors = num_sectors;
- if (!isaudiotrack (&ciw->di.toc, cdda_pos))
+ if (!isaudiotrack (&ciw->di.toc, cdda_pos)) {
+ setstate (ciw, AUDIO_STATUS_PLAY_ERROR);
goto end; // data track?
+ }
gui_flicker_led (LED_CD, ciw->di.unitnum - 1, LED_CD_AUDIO);
ciw->subcodevalid = false;
memset (ciw->subcode, 0, sizeof ciw->subcode);
- memset (px[bufnum], 0, sectors * readblocksize);
-
- if (firstloops > 0) {
-
- firstloops--;
+ bool readerr = false;
+ if (current_sector != cdda_pos) {
+ current_sector = -1;
+ memset (px[bufnum], 0, num_sectors * readblocksize);
+ readerr = read_block (ciw, -1, px[bufnum], cdda_pos, num_sectors, readblocksize) == 0;
+ if (!readerr)
+ current_sector = cdda_pos;
+ }
+ if (readerr) {
if (ciw->cdda_subfunc)
- ciw->cdda_subfunc (ciw->subcode, sectors);
-
+ ciw->cdda_subfunc (ciw->subcode, num_sectors);
} else {
-
- firstloops = -1;
- if (!read_block (ciw, -1, px[bufnum], cdda_pos, sectors, readblocksize)) {
- 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] + readblocksize * 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] + readblocksize * i, 2352);
- }
- ciw->subcodevalid = true;
+ for (i = 0; i < num_sectors; i++) {
+ memcpy (ciw->subcode + i * SUB_CHANNEL_SIZE, px[bufnum] + readblocksize * i + 2352, SUB_CHANNEL_SIZE);
}
- reseterrormode (ciw);
+ if (ciw->cdda_subfunc)
+ ciw->cdda_subfunc (ciw->subcode, num_sectors);
+ for (i = 1; i < num_sectors; i++) {
+ memmove (px[bufnum] + 2352 * i, px[bufnum] + readblocksize * i, 2352);
+ }
+ ciw->subcodevalid = true;
}
+ reseterrormode (ciw);
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);
+ memcpy (ciw->subcodebuf, ciw->subcode + (num_sectors - 1) * SUB_CHANNEL_SIZE, SUB_CHANNEL_SIZE);
uae_sem_post (&ciw->sub_sem2);
}
break;
}
- if (firstloops < 0) {
- if (ciw->cdda_scan) {
- cdda_pos += ciw->cdda_scan * num_sectors;
- if (cdda_pos < 0)
- cdda_pos = 0;
- } else {
- cdda_pos += num_sectors;
- }
- if (cdda_pos - num_sectors < ciw->cdda_end && cdda_pos >= ciw->cdda_end) {
- ciw->cdda_play_finished = 1;
- ciw->cdda_play = -1;
- cdda_pos = ciw->cdda_end;
- }
+ if (ciw->cdda_scan) {
+ cdda_pos += ciw->cdda_scan * num_sectors;
+ if (cdda_pos < 0)
+ cdda_pos = 0;
+ } else {
+ cdda_pos += num_sectors;
+ }
+ if (cdda_pos - num_sectors < ciw->cdda_end && cdda_pos >= ciw->cdda_end) {
+ setstate (ciw, AUDIO_STATUS_PLAY_COMPLETE);
+ ciw->cdda_play_finished = 1;
+ ciw->cdda_play = -1;
+ cdda_pos = ciw->cdda_end;
}
-
ciw->cd_last_pos = cdda_pos;
}
}
/* play CD audio */
-static int ioctl_command_play (int unitnum, int startlsn, int endlsn, int scan, play_subchannel_callback subfunc)
+static int ioctl_command_play (int unitnum, int startlsn, int endlsn, int scan, play_status_callback statusfunc, play_subchannel_callback subfunc)
{
struct dev_info_ioctl *ciw = unitisopen (unitnum);
if (!ciw)
return 0;
- if (!open_createfile (ciw, 0))
- return 0;
- if (!isaudiotrack (&ciw->di.toc, startlsn))
- return 0;
ciw->cdda_play_finished = 0;
ciw->cdda_subfunc = subfunc;
+ ciw->cdda_statusfunc = statusfunc;
ciw->cdda_scan = scan > 0 ? 10 : (scan < 0 ? 10 : 0);
+ ciw->cdda_delay = setstate (ciw, -1);
+ setstate (ciw, AUDIO_STATUS_NOT_SUPPORTED);
+
+ if (!open_createfile (ciw, 0)) {
+ setstate (ciw, AUDIO_STATUS_PLAY_ERROR);
+ return 0;
+ }
+ if (!isaudiotrack (&ciw->di.toc, startlsn)) {
+ setstate (ciw, AUDIO_STATUS_PLAY_ERROR);
+ return 0;
+ }
if (!ciw->cdda_play) {
uae_start_thread (L"ioctl_cdda_play", cdda_play, ciw, NULL);
}
di->type = ciw->type == DRIVE_CDROM ? INQ_ROMD : INQ_DASD;
di->unitnum = unitnum + 1;
_tcscpy (di->label, ciw->drvlettername);
- di->slow_unit = ciw->slowunit;
di->backend = L"IOCTL";
}
if (ciw->drvletter == 0)
return 0;
unittable[unitnum] = unitnum + 1;
- ciw->slowunit = (flags & 1) != 0;
if (sys_cddev_open (ciw, unitnum) == 0)
return 1;
unittable[unitnum] = 0;
#define LANG_DLL 1
#define WINUAEBETA L"10"
-#define WINUAEDATE MAKEBD(2010, 8, 10)
+#define WINUAEDATE MAKEBD(2010, 8, 11)
#define WINUAEEXTRA L""
#define WINUAEREV L""
{
int start = io_offset;
int end = io_length + start;
- if (!sys_command_cd_play (dev->di.unitnum, start, end, 0, NULL))
+ if (!sys_command_cd_play (dev->di.unitnum, start, end, 0))
io_error = IOERR_BADADDRESS;
}
break;
{
int start = msf2lsn (io_offset);
int end = msf2lsn (io_length) + start;
- if (!sys_command_cd_play (dev->di.unitnum, start, end, 0, NULL))
+ if (!sys_command_cd_play (dev->di.unitnum, start, end, 0))
io_error = IOERR_BADADDRESS;
}
break;
if (sys_command_cd_toc (dev->di.unitnum, &toc)) {
for (int i = toc.first_track_offset; i < toc.last_track_offset; i++) {
if (i == io_offset && i + io_length <= toc.last_track_offset) {
- ok = sys_command_cd_play (dev->di.unitnum, toc.toc[i].address, toc.toc[i + io_length].address, 0, NULL);
+ ok = sys_command_cd_play (dev->di.unitnum, toc.toc[i].address, toc.toc[i + io_length].address, 0);
break;
}
}