static int cdrom_led;
static int cdrom_dosomething;
static int cdrom_receive_started;
+static int cdrom_muted;
static int cd_initialized;
static uae_u8 *sector_buffer_1, *sector_buffer_2;
struct device_info di1, *di2;
int cd32unit = -1;
int audiounit = -1;
+ int opened[MAX_TOTAL_DEVICES];
+ int i;
for (unitnum = 0; unitnum < MAX_TOTAL_DEVICES; unitnum++) {
+ opened[unitnum] = 0;
if (sys_command_open (DF_IOCTL, unitnum)) {
+ opened[unitnum] = 1;
di2 = sys_command_info (DF_IOCTL, unitnum, &di1);
if (di2 && di2->type == INQ_ROMD) {
write_log (L"%s: ", di2->label);
write_log (L"can't read TOC\n");
}
}
- sys_command_close (DF_IOCTL, unitnum);
}
}
unitnum = audiounit;
unitnum = cd32unit;
if (unitnum < 0)
unitnum = first;
+ if (unitnum >= 0)
+ opened[unitnum] = 0;
+ for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
+ if (opened[i])
+ sys_command_close (DF_IOCTL, i);
+ }
if (unitnum < 0)
return 1;
- if (!sys_command_open (DF_IOCTL, unitnum))
- write_log (L"re-opening unit %d failed!\n", unitnum);
di2 = sys_command_info (DF_IOCTL, unitnum, &di1);
if (!di2) {
write_log (L"unit %d info failed\n", unitnum);
case 0x0104: // stop
cdaudiostop_do ();
break;
+ case 0x0105: // mute change
+ sys_command_cd_volume (DF_IOCTL, unitnum, cdrom_muted ? 0 : 0xffff);
+ break;
case 0x0110: // do_play!
+ sys_command_cd_volume (DF_IOCTL, unitnum, cdrom_muted ? 0 : 0xffff);
cdaudioplay_do ();
break;
}
if (!currprefs.cs_cd32cd)
return;
akiko_c2p_do ();
- write_comm_pipe_u32 (&requests, 0x102, 1); // pause
- write_comm_pipe_u32 (&requests, 0x104, 1); // stop
- write_comm_pipe_u32 (&requests, 0x103, 1); // unpause
+ write_comm_pipe_u32 (&requests, 0x0102, 1); // pause
+ write_comm_pipe_u32 (&requests, 0x0104, 1); // stop
+ write_comm_pipe_u32 (&requests, 0x0103, 1); // unpause
if (cdrom_playing) {
- write_comm_pipe_u32 (&requests, 0x103, 1); // unpause
- write_comm_pipe_u32 (&requests, 0x110, 0); // play
+ write_comm_pipe_u32 (&requests, 0x0103, 1); // unpause
+ write_comm_pipe_u32 (&requests, 0x0110, 0); // play
write_comm_pipe_u32 (&requests, last_play_pos, 0);
write_comm_pipe_u32 (&requests, last_play_end, 0);
write_comm_pipe_u32 (&requests, 0, 1);
void akiko_entergui (void)
{
if (cdrom_playing)
- write_comm_pipe_u32 (&requests, 0x102, 1);
+ write_comm_pipe_u32 (&requests, 0x0102, 1);
}
void akiko_exitgui (void)
{
if (cdrom_playing)
- write_comm_pipe_u32 (&requests, 0x103, 1);
+ write_comm_pipe_u32 (&requests, 0x0103, 1);
+}
+
+void akiko_mute (int muted)
+{
+ cdrom_muted = muted;
+ if (unitnum >= 0)
+ write_comm_pipe_u32 (&requests, 0x0105, 1);
}
}
-STATIC_INLINE int blitter_doddma (int hpos)
+STATIC_INLINE void blitter_doddma (int hpos)
{
int wd;
uae_u16 d;
d = ddat1;
ddat1use = 0;
wd = 1;
+ } else {
+ write_log (L"BLITTER: D-channel without nothing to do?\n");
+ return;
}
- if (wd) {
- alloc_cycle_ext (hpos, CYCLE_BLITTER);
- record_dma_blit (0x00, d, bltdpt, hpos);
- last_custom_value1 = d;
- chipmem_agnus_wput2 (bltdpt, d);
- bltdpt += blit_add;
- blitter_hcounter2++;
- if (blitter_hcounter2 == hblitsize) {
- blitter_hcounter2 = 0;
- bltdpt += blit_modaddd;
- blitter_vcounter2++;
- if (blitter_vcounter2 > blitter_vcounter1)
- blitter_vcounter1 = blitter_vcounter2;
- }
- if (blit_ch == 1)
- blitter_hcounter1 = blitter_hcounter2;
+ alloc_cycle_ext (hpos, CYCLE_BLITTER);
+ record_dma_blit (0x00, d, bltdpt, hpos);
+ last_custom_value1 = d;
+ chipmem_agnus_wput2 (bltdpt, d);
+ bltdpt += blit_add;
+ blitter_hcounter2++;
+ if (blitter_hcounter2 == hblitsize) {
+ blitter_hcounter2 = 0;
+ bltdpt += blit_modaddd;
+ blitter_vcounter2++;
+ if (blitter_vcounter2 > blitter_vcounter1)
+ blitter_vcounter1 = blitter_vcounter2;
}
- return wd;
+ if (blit_ch == 1)
+ blitter_hcounter1 = blitter_hcounter2;
}
STATIC_INLINE void blitter_dodma (int ch, int hpos)
blt_info.got_cycle = 1;
if (c == 4) {
- if (blitter_doddma (last_blitter_hpos)) {
- blit_cyclecounter++;
- blit_totalcyclecounter++;
- }
+ blitter_doddma (last_blitter_hpos);
+ blit_cyclecounter++;
+ blit_totalcyclecounter++;
} else {
if (blitter_vcounter1 < vblitsize) {
blitter_dodma (c, last_blitter_hpos);
blit_frozen = 0; // switched back to original fill mode? unfreeze
} else if (iseo && !isen) {
blit_frozen = 1;
+ write_log (L"BLITTER: frozen! %d (%d) -> %d (%d) %08X\n", original_ch, iseo, blit_ch, isen, M68K_GETPC);
} else if (!iseo && isen) {
#ifdef BLITTER_DEBUG_NOWAIT
write_log (L"BLITTER: on the fly %d (%d) -> %d (%d) switch\n", original_ch, iseo, blit_ch, isen);
extern struct device_functions devicefunc_win32_aspi;
extern struct device_functions devicefunc_win32_spti;
extern struct device_functions devicefunc_win32_ioctl;
+extern struct device_functions devicefunc_cdimage;
static void install_driver (int flags)
{
int installed = 0;
device_func[DF_SCSI] = &devicefunc_win32_aspi;
+ if (devicefunc_cdimage.openbus (0)) {
+ device_func[DF_IOCTL] = &devicefunc_cdimage;
+ }
#ifdef WINDDK
- device_func[DF_IOCTL] = &devicefunc_win32_ioctl;
+ 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 ||
return device_func[DF_IOCTL]->play (unitnum, startmsf, endmsf, scan);
}
+/* set CD audio volume */
+void sys_command_cd_volume (int mode, int unitnum, uae_u16 volume)
+{
+ if (mode == DF_SCSI || !have_ioctl)
+ return;
+ device_func[DF_IOCTL]->volume (unitnum, volume);
+}
+
/* read qcode */
uae_u8 *sys_command_cd_qcode (int mode, int unitnum)
{
--- /dev/null
+/*
+* UAE
+*
+* CD32/CDTV image file support
+*
+* Copyright 2010 Toni Wilen
+*
+*/
+#include "sysconfig.h"
+#include "sysdeps.h"
+
+#include "options.h"
+#include "blkdev.h"
+#include "zfile.h"
+#include "gui.h"
+#include "fsdb.h"
+#include "threaddep/thread.h"
+
+#define USE 1
+
+#define CDDA_BUFFERS 6
+
+#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
+
+struct cdtoc
+{
+ struct zfile *handle;
+ int offset;
+ int filesize;
+ uae_u8 *data;
+ TCHAR *fname;
+ int address;
+ uae_u8 adr, ctrl;
+ int track;
+ int size;
+};
+
+static uae_u8 buffer[2352];
+static struct cdtoc toc[102];
+static int tracks;
+
+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;
+
+/* 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 - 150;
+}
+
+/* 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 cdtoc *findtoc (int *sectorp)
+{
+ int i;
+ int sector;
+
+ sector = *sectorp;
+ for (i = 0; i <= tracks; i++) {
+ struct cdtoc *t = &toc[i];
+ if (t->address > sector) {
+ if (i == 0)
+ return NULL;
+ t--;
+ sector -= t->address;
+ *sectorp = sector;
+ return t;
+ }
+ }
+ return NULL;
+}
+
+#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 *size)
+{
+ MMRESULT mmr;
+ unsigned long rawbufsize = 0;
+ LPBYTE mp3buf;
+ LPBYTE rawbuf;
+ uae_u8 *outbuf = NULL;
+ int outsize = 0;
+ int outsizer = 10000000;
+ 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;
+ }
+ 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 > outsize) {
+ outsize += outsizer;
+ outbuf = realloc (outbuf, outsize);
+ if (!outbuf)
+ break;
+ }
+ memcpy (outbuf + outoffset, rawbuf, mp3streamHead.cbDstLengthUsed);
+ outoffset += mp3streamHead.cbDstLengthUsed;
+ }
+ acmStreamUnprepareHeader (g_mp3stream, &mp3streamHead, 0);
+ LocalFree (rawbuf);
+ LocalFree (mp3buf);
+ write_log (L"CUEMP3: destination size %d bytes\n", outoffset);
+ *size = outoffset;
+ return outbuf;
+}
+
+static HWAVEOUT cdda_wavehandle;
+
+static void cdda_closewav (void)
+{
+ if (cdda_wavehandle != NULL)
+ waveOutClose (cdda_wavehandle);
+ cdda_wavehandle = NULL;
+}
+
+// DAE CDDA based on Larry Osterman's "Playing Audio CDs" blog series
+
+static int cdda_openwav (void)
+{
+ WAVEFORMATEX wav = { 0 };
+ MMRESULT mmr;
+
+ wav.cbSize = 0;
+ wav.nChannels = 2;
+ wav.nSamplesPerSec = 44100;
+ wav.wBitsPerSample = 16;
+ wav.nBlockAlign = wav.wBitsPerSample / 8 * wav.nChannels;
+ wav.nAvgBytesPerSec = wav.nBlockAlign * wav.nSamplesPerSec;
+ wav.wFormatTag = WAVE_FORMAT_PCM;
+ mmr = waveOutOpen (&cdda_wavehandle, WAVE_MAPPER, &wav, 0, 0, WAVE_ALLOWSYNC | WAVE_FORMAT_DIRECT);
+ if (mmr != MMSYSERR_NOERROR) {
+ write_log (L"CDDA: wave open %d\n", mmr);
+ cdda_closewav ();
+ return 0;
+ }
+ return 1;
+}
+
+static void *cdda_play_func (void *v)
+{
+ int cdda_pos;
+ int num_sectors = CDDA_BUFFERS;
+ int quit = 0;
+ int bufnum;
+ int buffered;
+ uae_u8 *px[2], *p;
+ int bufon[2];
+ int i;
+ WAVEHDR whdr[2];
+ MMRESULT mmr;
+ int volume, volume_main;
+ int oldplay;
+
+ for (i = 0; i < 2; i++) {
+ memset (&whdr[i], 0, sizeof (WAVEHDR));
+ whdr[i].dwFlags = WHDR_DONE;
+ }
+
+ while (cdda_play == 0)
+ Sleep (10);
+ oldplay = -1;
+
+ p = xmalloc (2 * num_sectors * 4096);
+ px[0] = p;
+ px[1] = p + num_sectors * 4096;
+ bufon[0] = bufon[1] = 0;
+ bufnum = 0;
+ buffered = 0;
+ volume = -1;
+ volume_main = -1;
+
+ if (cdda_openwav ()) {
+
+ for (i = 0; i < 2; i++) {
+ memset (&whdr[i], 0, sizeof (WAVEHDR));
+ whdr[i].dwBufferLength = 2352 * num_sectors;
+ whdr[i].lpData = px[i];
+ mmr = waveOutPrepareHeader (cdda_wavehandle, &whdr[i], sizeof (WAVEHDR));
+ if (mmr != MMSYSERR_NOERROR) {
+ write_log (L"CDDA: waveOutPrepareHeader %d:%d\n", i, mmr);
+ goto end;
+ }
+ whdr[i].dwFlags |= WHDR_DONE;
+ }
+
+ while (cdda_play > 0) {
+
+ if (oldplay != cdda_play) {
+ struct cdtoc *t;
+ int sector;
+ sector = cdda_start;
+ t = findtoc (§or);
+ if (!t)
+ write_log (L"CDDA: illegal sector number %d\n", cdda_start);
+ else
+ write_log (L"CDDA: playing track %d (file '%s', offset %d, secoffset %d)\n",
+ t->track, t->fname, t->offset, sector);
+ cdda_pos = cdda_start;
+ oldplay = cdda_play;
+ }
+
+ while (!(whdr[bufnum].dwFlags & WHDR_DONE)) {
+ Sleep (10);
+ if (!cdda_play)
+ goto end;
+ }
+ bufon[bufnum] = 0;
+
+ if ((cdda_pos < cdda_end || cdda_end == 0xffffffff) && !cdda_paused && cdda_play) {
+ struct cdtoc *t;
+ int sector;
+
+ sector = cdda_pos;
+ t = findtoc (§or);
+ if (t && t->handle) {
+ if (t->data) {
+ memcpy (px[bufnum], t->data + sector * t->size + t->offset, t->size * num_sectors);
+ } else {
+ zfile_fseek (t->handle, sector * t->size + t->offset, SEEK_SET);
+ if (zfile_fread (px[bufnum], t->size, num_sectors, t->handle) < num_sectors) {
+ int i = num_sectors - 1;
+ memset (px[bufnum], 0, t->size * num_sectors);
+ while (i > 0) {
+ if (zfile_fread (px[bufnum], t->size, i, t->handle) == i)
+ break;
+ i--;
+ }
+ if (i == 0)
+ write_log (L"CDDA: read error, track %d (file '%s' offset %d secoffset %d)\n",
+ t->track, t->fname, t->offset, sector);
+ }
+ }
+ }
+
+ bufon[bufnum] = 1;
+ if (volume != cdda_volume || volume_main != currprefs.sound_volume) {
+ int vol;
+ volume = cdda_volume;
+ volume_main = currprefs.sound_volume;
+ vol = (100 - volume_main) * volume / 100;
+ if (vol >= 0xffff)
+ vol = 0xffff;
+ waveOutSetVolume (cdda_wavehandle, vol | (vol << 16));
+ }
+ mmr = waveOutWrite (cdda_wavehandle, &whdr[bufnum], sizeof (WAVEHDR));
+ if (mmr != MMSYSERR_NOERROR) {
+ write_log (L"CDDA: waveOutWrite %d\n", mmr);
+ break;
+ }
+
+ cdda_pos += num_sectors;
+ if (cdda_pos >= cdda_end)
+ cdda_play_finished = 1;
+ cd_last_pos = cdda_pos;
+
+ }
+
+
+ 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)
+ Sleep (10);
+ }
+
+ bufnum = 1 - bufnum;
+
+ }
+ }
+
+end:
+ while (!(whdr[0].dwFlags & WHDR_DONE) || !(whdr[1].dwFlags & WHDR_DONE))
+ Sleep (10);
+ for (i = 0; i < 2; i++)
+ waveOutUnprepareHeader (cdda_wavehandle, &whdr[i], sizeof (WAVEHDR));
+
+ cdda_closewav ();
+ xfree (p);
+ cdda_play = 0;
+ write_log (L"CDDA: thread killed\n");
+ return NULL;
+}
+
+#endif
+
+static void cdda_stop (void)
+{
+ if (cdda_play > 0) {
+ cdda_play = -1;
+ while (cdda_play) {
+ Sleep (10);
+ }
+ }
+ cdda_play_finished = 0;
+ cdda_paused = 0;
+}
+
+
+static int command_pause (int unitnum, int paused)
+{
+ cdda_paused = paused;
+ return 1;
+}
+
+static int command_stop (int unitnum)
+{
+ cdda_stop ();
+ return 1;
+}
+
+static int command_play (int unitnum, uae_u32 start, uae_u32 end, int scan)
+{
+ cdda_paused = 0;
+ cdda_play_finished = 0;
+ cdda_start = msf2lsn (start);
+ cdda_end = msf2lsn (end);
+ if (!cdda_play)
+ uae_start_thread (L"cdda_play", cdda_play_func, NULL, NULL);
+ cdda_play++;
+ return 1;
+}
+
+static uae_u8 *command_qcode (int unitnum)
+{
+ static uae_u8 buf[4 + 12];
+ uae_u8 *p;
+ int trk;
+ int pos;
+ int msf;
+ int start, end;
+ int status;
+
+ memset (buf, 0, sizeof buf);
+ p = buf;
+
+ status = AUDIO_STATUS_NO_STATUS;
+ if (cdda_play) {
+ status = AUDIO_STATUS_IN_PROGRESS;
+ if (cdda_paused)
+ status = AUDIO_STATUS_PAUSED;
+ } else if (cdda_play_finished) {
+ status = AUDIO_STATUS_PLAY_COMPLETE;
+ }
+ pos = cd_last_pos;
+
+ p[1] = status;
+ p[3] = 12;
+
+ p = buf + 4;
+
+ if (pos >= 150)
+ trk = 0;
+ 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;
+ 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);
+ p[9] = (pos >> 16) & 0xff;
+ p[10] = (pos >> 8) & 0xff;
+ p[11] = (pos >> 0) & 0xff;
+
+ return buf;
+}
+
+static void command_volume (int unitnum, uae_u16 volume)
+{
+ cdda_volume = volume;
+}
+
+uae_u8 *command_rawread (int unitnum, int sector, int sectorsize)
+{
+ cdda_stop ();
+ return NULL;
+}
+static uae_u8 *command_read (int unitnum, int sector)
+{
+ struct cdtoc *t = findtoc (§or);
+ int offset;
+ if (!t || t->handle == NULL)
+ return NULL;
+ cdda_stop ();
+ 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;
+}
+
+static uae_u8 *command_toc (int unitnum)
+{
+ static uae_u8 statictoc[11 * 102];
+ uae_u8 *p = statictoc;
+ int i;
+ uae_u32 msf;
+
+ cdda_stop ();
+ if (!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;
+ }
+ gui_flicker_led (LED_CD, unitnum, 1);
+ return statictoc;
+}
+
+static void skipspace (TCHAR **s)
+{
+ while (_istspace (**s))
+ (*s)++;
+}
+static void skipnspace (TCHAR **s)
+{
+ while (!_istspace (**s))
+ (*s)++;
+}
+
+static TCHAR *nextstring (TCHAR **sp)
+{
+ TCHAR *s;
+ TCHAR *out = NULL;
+
+ skipspace (sp);
+ s = *sp;
+ if (*s == '\"') {
+ s++;
+ out = s;
+ while (*s && *s != '\"')
+ s++;
+ *s++ = 0;
+ } else if (*s) {
+ out = s;
+ skipnspace (&s);
+ *s++ = 0;
+ }
+ *sp = s;
+ return out;
+}
+
+static int open_device (int unitnum)
+{
+ struct zfile *zcue;
+ TCHAR *fname, *fnametype;
+ int tracknum;
+ int offset, secoffset, newfile;
+ int i;
+ TCHAR *p;
+ TCHAR curdir[MAX_DPATH], oldcurdir[MAX_DPATH];
+ uae_u64 siz;
+ TCHAR *img = currprefs.cdimagefile;
+ int ctrl;
+
+ if (unitnum || !img)
+ return 0;
+ zcue = zfile_fopen (img, L"rb", 0);
+ if (!zcue)
+ return 0;
+
+ fname = NULL;
+ fnametype = NULL;
+ tracknum = 0;
+ offset = 0;
+ secoffset = 0;
+ newfile = 0;
+ ctrl = 0;
+
+ zfile_fseek (zcue, 0, SEEK_END);
+ siz = zfile_ftell (zcue);
+ zfile_fseek (zcue, 0, SEEK_SET);
+ 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;
+ 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];
+ if (!zfile_fgets (buf, sizeof buf / sizeof (TCHAR), zcue))
+ break;
+
+ p = buf;
+ skipspace (&p);
+
+ if (!_tcsnicmp (p, L"FILE", 4)) {
+ p += 4;
+ xfree (fname);
+ fname = my_strdup (nextstring (&p));
+ fnametype = nextstring (&p);
+ 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);
+ }
+ offset = 0;
+ newfile = 1;
+ ctrl = 0;
+ } else if (!_tcsnicmp (p, L"FLAGS", 5)) {
+ ctrl &= ~(1 | 2 | 8);
+ for (;;) {
+ TCHAR *f = nextstring (&p);
+ if (!f)
+ break;
+ if (!_tcsicmp (f, L"PRE"))
+ ctrl |= 1;
+ if (!_tcsicmp (f, L"DCP"))
+ ctrl |= 2;
+ if (!_tcsicmp (f, L"4CH"))
+ ctrl |= 8;
+ }
+ } else if (!_tcsnicmp (p, L"TRACK", 5)) {
+ int size;
+ TCHAR *tracktype;
+
+ p += 5;
+ tracknum = _tstoi (nextstring (&p));
+ tracktype = nextstring (&p);
+ size = 2352;
+ if (!_tcsicmp (tracktype, L"AUDIO")) {
+ ctrl &= ~4;
+ } else {
+ ctrl |= 4;
+ if (!_tcsicmp (tracktype, L"MODE1/2048"))
+ size = 2048;
+ else if (!_tcsicmp (tracktype, L"MODE1/2352"))
+ size = 2352;
+ else if (!_tcsicmp (tracktype, L"MODE2/2336"))
+ size = 2336;
+ else if (!_tcsicmp (tracktype, L"MODE2/2352"))
+ size = 2352;
+ else {
+ write_log (L"CUE: unknown tracktype '%s' ('%s')\n", tracktype, fname);
+ }
+ }
+ if (tracknum >= 1 && tracknum <= 99) {
+ struct cdtoc *t = &toc[tracknum - 1];
+ struct zfile *ztrack;
+
+ if (tracknum > 1 && newfile) {
+ t--;
+ secoffset += t->filesize / t->size;
+ t++;
+ }
+
+ newfile = 0;
+ ztrack = zfile_fopen (fname, L"rb", 0);
+ if (!ztrack) {
+ TCHAR tmp[MAX_DPATH];
+ _tcscpy (tmp, fname);
+ p = tmp + _tcslen (tmp);
+ while (p > tmp) {
+ if (*p == '/' || *p == '\\') {
+ ztrack = zfile_fopen (p + 1, L"rb", 0);
+ if (ztrack) {
+ xfree (fname);
+ fname = my_strdup (p + 1);
+ }
+ break;
+ }
+ p--;
+ }
+ }
+ t->track = tracknum;
+ t->ctrl = ctrl;
+ t->adr = 1;
+ t->handle = ztrack;
+ t->size = size;
+ t->fname = my_strdup (fname);
+ if (tracknum > tracks)
+ tracks = tracknum;
+ zfile_fseek (t->handle, 0, SEEK_END);
+ t->filesize = zfile_ftell (t->handle);
+ zfile_fseek (t->handle, 0, SEEK_SET);
+ }
+ } else if (!_tcsnicmp (p, L"INDEX", 5)) {
+ int idxnum;
+ int tn = 0;
+ TCHAR *tt;
+ p += 5;
+ idxnum = _tstoi (nextstring (&p));
+ tt = nextstring (&p);
+ tn = _tstoi (tt) * 60 * 75;
+ tn += _tstoi (tt + 3) * 75;
+ tn += _tstoi (tt + 6);
+ if (tracknum >= 1 && tracknum <= 99) {
+ struct cdtoc *t = &toc[tracknum - 1];
+ if (!t->address) {
+ t->address = tn + secoffset;
+ if (tracknum > 1) {
+ offset += t->address - t[-1].address;
+ } else {
+ offset += t->address;
+ }
+ if (!secoffset)
+ t->offset = offset * t->size;
+ if (!_tcsicmp (fnametype, L"WAVE") && t->handle) {
+ struct zfile *zf = t->handle;
+ uae_u8 buf[16] = { 0 };
+ zfile_fread (buf, 12, 1, zf);
+ if (!memcmp (buf, "RIFF", 4) && !memcmp (buf + 8, "WAVE", 4)) {
+ int size;
+ for (;;) {
+ memset (buf, 0, sizeof buf);
+ if (zfile_fread (buf, 8, 1, zf) != 1)
+ break;
+ size = (buf[4] << 0) | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24);
+ if (!memcmp (buf, "data", 4))
+ break;
+ if (size <= 0)
+ break;
+ zfile_fseek (zf, size, SEEK_CUR);
+ }
+ t->offset += zfile_ftell (zf);
+ t->filesize = size;
+ }
+ } else if (!_tcsicmp (fnametype, L"MP3") && t->handle) {
+ t->offset = 0;
+ // bleh
+ if (mp3decoder_open ()) {
+ t->data = mp3decoder_get (t->handle, &t->filesize);
+ }
+ }
+ }
+ }
+ }
+ }
+isodone:
+ if (tracks && toc[tracks - 1].handle) {
+ struct cdtoc *t = &toc[tracks - 1];
+ int size = t->filesize - offset * t->size;
+ if (size < 0)
+ size = 0;
+ toc[tracks].address = toc[tracks - 1].address + size / t->size;
+ }
+ xfree (fname);
+ if (oldcurdir[0])
+ my_setcurrentdir (oldcurdir, NULL);
+ for (i = 0; i <= tracks; i++) {
+ struct cdtoc *t = &toc[i];
+ uae_u32 msf = lsn2msf (t->address);
+ if (i < 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"");
+ write_log (L"\n");
+ if (i < tracks)
+ write_log (L" - %s\n", t->fname);
+ }
+ zfile_fclose (zcue);
+ mp3decoder_close ();
+ return 1;
+}
+static void close_device (int unitnum)
+{
+ int i;
+
+ for (i = 0; i < tracks; i++) {
+ struct cdtoc *t = &toc[i];
+ zfile_fclose (t->handle);
+ xfree (t->fname);
+ xfree (t->data);
+ }
+ memset (toc, 0, sizeof toc);
+ tracks = 0;
+}
+
+static int ismedia (int unitnum, int quick)
+{
+ return currprefs.cdimagefile[0] ? 1 : 0;
+}
+
+static int open_bus (int flags)
+{
+ return ismedia (0, 1);
+}
+
+static void close_bus (void)
+{
+}
+
+static struct device_info *info_device (int unitnum, struct device_info *di)
+{
+ if (unitnum)
+ return 0;
+ di->bus = unitnum;
+ di->target = 0;
+ di->lun = 0;
+ di->media_inserted = 0;
+ di->bytespersector = 2048;
+ if (ismedia (unitnum, 1))
+ di->media_inserted = 1;
+ di->write_protected = 1;
+ di->type = INQ_ROMD;
+ di->id = 1;
+ _tcscpy (di->label, L"IMG");
+ return di;
+}
+
+struct device_functions devicefunc_cdimage = {
+ open_bus, close_bus, open_device, close_device, info_device,
+ 0, 0, 0,
+ command_pause, command_stop, command_play, command_volume, command_qcode,
+ command_toc, command_read, command_rawread, 0,
+ 0, 0, ismedia
+};
#ifdef CDTV_DEBUG_CMD
write_log (L"CDTV CD volume = %d\n", cd_volume);
#endif
+ if (cd_volume > 1023)
+ cd_volume = 1023;
+ if (unitnum >= 0)
+ sys_command_cd_volume (DF_IOCTL, unitnum, (cd_volume << 6) | (cd_volume >> 4));
cd_volume = 0;
volstrobe2 = 1;
} else if (volstrobe2 && !((tp_b >> 7) & 1)) {
struct device_info di1, *di2;
int first = -1;
int cdtvunit = -1, audiounit = -1;
+ int opened[MAX_TOTAL_DEVICES];
+ int i;
if (unitnum >= 0)
sys_command_close (DF_IOCTL, unitnum);
return;
}
for (unitnum = 0; unitnum < MAX_TOTAL_DEVICES; unitnum++) {
+ opened[unitnum] = 0;
if (sys_command_open (DF_IOCTL, unitnum)) {
+ opened[unitnum] = 1;
di2 = sys_command_info (DF_IOCTL, unitnum, &di1);
if (di2 && di2->type == INQ_ROMD) {
write_log (L"%s: ", di2->label);
write_log (L"TOC read failed\n");
}
}
- sys_command_close (DF_IOCTL, unitnum);
}
}
unitnum = audiounit;
unitnum = cdtvunit;
if (unitnum < 0)
unitnum = first;
+ if (unitnum >= 0)
+ opened[unitnum] = 0;
+ for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
+ if (opened[i])
+ sys_command_close (DF_IOCTL, i);
+ }
cd_media = 0;
if (unitnum >= 0) {
- sys_command_open (DF_IOCTL, unitnum);
cd_media = ismedia () ? -1 : 0;
if (!cd_media)
cd_hunt = 1;
}
}
+ if (p->cdimagefile[0])
+ cfgfile_write_str (f, L"cdimage0", p->cdimagefile);
+
cfgfile_write (f, L"nr_floppies", L"%d", p->nr_floppies);
cfgfile_write (f, L"floppy_speed", L"%d", p->floppy_speed);
cfgfile_write (f, L"floppy_volume", L"%d", p->dfxclickvolume);
}
}
+ if (cfgfile_string (option, value, L"cdimage0", p->cdimagefile, sizeof p->cdimagefile / sizeof (TCHAR)))
+ return 1;
+
if (cfgfile_intval (option, value, L"sound_frequency", &p->sound_freq, 1)) {
/* backwards compatibility */
p->sound_latency = 1000 * (p->sound_maxbsiz >> 1) / p->sound_freq;
target_default_options (p, 1);
}
-static void set_68020_compa (struct uae_prefs *p, int compa)
+static void set_68020_compa (struct uae_prefs *p, int compa, int cd32)
{
if (compa == 0) {
p->blitter_cycle_exact = 1;
p->cpu_clock_multiplier = 4 << 8;
}
}
- if (compa > 0) {
+ if (compa > 1) {
p->cpu_compatible = 0;
p->address_space_24 = 0;
p->cachesize = 8192;
}
- if (compa > 1) {
- p->immediate_blits = 1;
- p->produce_sound = 2;
- }
}
/* 0: cycle-exact
p->nr_floppies = 0;
p->dfxtype[0] = DRV_NONE;
p->dfxtype[1] = DRV_NONE;
- set_68020_compa (p, compa);
+ set_68020_compa (p, compa, 1);
p->cs_compatible = CP_CD32;
built_in_chipset_prefs (p);
fetch_datapath (p->flashfile, sizeof (p->flashfile) / sizeof (TCHAR));
p->fastmem_size = 0x400000;
p->cs_rtc = 2;
}
- set_68020_compa (p, compa);
+ set_68020_compa (p, compa, 0);
p->cs_compatible = CP_A1200;
built_in_chipset_prefs (p);
return configure_rom (p, roms, romcheck);
static unsigned long ciaatod, ciabtod, ciaatol, ciabtol, ciaaalarm, ciabalarm;
static int ciaatlatch, ciabtlatch;
-static int oldled, oldovl, led_changed;
+static int oldled, oldovl, oldcd32mute, led_changed;
unsigned int ciabpra;
//activate_debugger ();
map_overlay (0);
}
+ } else if (currprefs.cs_cd32cd && (v & 1) != oldcd32mute) {
+ oldcd32mute = v & 1;
+ akiko_mute (oldcd32mute ? 0 : 1);
}
}
ciaasdr_unread = 0;
serbits = 0;
oldovl = 1;
+ oldcd32mute = 1;
oldled = -1;
resetwarning_phase = resetwarning_timer = 0;
events_schedule();
}
+
+static void MISC_handler (void)
+{
+ int i, recheck;
+ evt mintime;
+ evt ct = get_cycles ();
+ static int recursive;
+
+ if (recursive)
+ return;
+ recursive++;
+ eventtab[ev_misc].active = 0;
+ recheck = 1;
+ while (recheck) {
+ recheck = 0;
+ mintime = ~0L;
+ for (i = 0; i < ev2_max; i++) {
+ if (eventtab2[i].active) {
+ if (eventtab2[i].evtime == ct) {
+ eventtab2[i].active = 0;
+ eventtab2[i].handler (eventtab2[i].data);
+ if (eventtab2[i].active)
+ recheck = 1;
+ } else {
+ evt eventtime = eventtab2[i].evtime - ct;
+ if (eventtime < mintime)
+ mintime = eventtime;
+ }
+ }
+ }
+ }
+ if (mintime != ~0L) {
+ eventtab[ev_misc].active = 1;
+ eventtab[ev_misc].oldcycles = ct;
+ eventtab[ev_misc].evtime = ct + mintime;
+ events_schedule ();
+ }
+ recursive--;
+}
+
+STATIC_INLINE void event2_newevent_xx (int no, evt t, uae_u32 data, evfunc2 func)
+{
+ evt et;
+
+ et = t + get_cycles ();
+ if (no < 0) {
+ for (no = ev2_misc; no < ev2_max; no++) {
+ if (!eventtab2[no].active)
+ break;
+ if (eventtab2[no].evtime == et && eventtab2[no].handler == func) {
+ eventtab2[no].handler (eventtab2[no].data);
+ break;
+ }
+ }
+ if (no == ev2_max) {
+ write_log (L"out of event2's! PC=%x\n", M68K_GETPC);
+ return;
+ }
+ }
+ eventtab2[no].active = 1;
+ eventtab2[no].evtime = et;
+ eventtab2[no].handler = func;
+ eventtab2[no].data = data;
+ MISC_handler ();
+}
+
+STATIC_INLINE void event2_newevent_x (int no, evt t, uae_u32 data, evfunc2 func)
+{
+ if (((int)t) <= 0) {
+ func (data);
+ return;
+ }
+
+ event2_newevent_xx (no, t * CYCLE_UNIT, data, func);
+}
+
+void event2_newevent (int no, evt t)
+{
+ event2_newevent_x (no, t, 0, eventtab2[no].handler);
+}
+void event2_newevent2 (evt t, uae_u32 data, evfunc2 func)
+{
+ event2_newevent_x (-1, t, data, func);
+}
+
static int irq_nmi;
void NMI_delayed (void)
return currprefs.cpu_cycle_exact != 0;
}
+static void send_interrupt (void)
+{
+ int lev = intlev ();
+ if (lev < 0)
+ lev = 0;
+ if (lev != regs.ipl)
+ event2_newevent_xx (-1, 5 * CYCLE_UNIT, lev, prepare_interrupt);
+}
+
STATIC_INLINE void INTENA (uae_u16 v)
{
setclr (&intena,v);
if (v & 0x40)
write_log (L"INTENA %04X (%04X) %p\n", intena, v, M68K_GETPC);
#endif
- if (v & 0x8000) {
- if (use_eventmode ())
- prepare_interrupt ();
+ if (use_eventmode ()) {
+ send_interrupt ();
+ } else if (v & 0x8000) {
doint ();
}
}
intreqr = intreq;
/* data in intreq is immediately available (vsync only currently because there is something unknown..) */
setclr (&intreqr, v & (0x8000 | 0x20));
- setclr (&tmp, v);
+ setclr (&intreq, v);
+ if (v & (0x80 | 0x100 | 0x200 | 0x400))
+ audio_update_irq (v);
+ intreqr = intreq;
if (use_eventmode ()) {
if (tmp != intreq)
- prepare_interrupt ();
+ send_interrupt ();
if (tmp > intreq) {
if (debug_dma)
record_dma_event (DMA_EVENT_INTREQ, current_hpos (), vpos);
}
+ } else {
+ doint ();
}
- if (v & (0x80 | 0x100 | 0x200 | 0x400))
- audio_update_irq (v);
- intreq = tmp;
- intreqr = intreq;
- doint ();
}
void INTREQ (uae_u16 data)
#endif
}
-static void MISC_handler (void)
-{
- int i, recheck;
- evt mintime;
- evt ct = get_cycles ();
- static int recursive;
-
- if (recursive)
- return;
- recursive++;
- eventtab[ev_misc].active = 0;
- recheck = 1;
- while (recheck) {
- recheck = 0;
- mintime = ~0L;
- for (i = 0; i < ev2_max; i++) {
- if (eventtab2[i].active) {
- if (eventtab2[i].evtime == ct) {
- eventtab2[i].active = 0;
- eventtab2[i].handler (eventtab2[i].data);
- if (eventtab2[i].active)
- recheck = 1;
- } else {
- evt eventtime = eventtab2[i].evtime - ct;
- if (eventtime < mintime)
- mintime = eventtime;
- }
- }
- }
- }
- if (mintime != ~0L) {
- eventtab[ev_misc].active = 1;
- eventtab[ev_misc].oldcycles = ct;
- eventtab[ev_misc].evtime = ct + mintime;
- events_schedule ();
- }
- recursive--;
-}
-
-STATIC_INLINE void event2_newevent_xx (int no, evt t, uae_u32 data, evfunc2 func)
-{
- evt et;
-
- et = t + get_cycles ();
- if (no < 0) {
- for (no = ev2_misc; no < ev2_max; no++) {
- if (!eventtab2[no].active)
- break;
- if (eventtab2[no].evtime == et && eventtab2[no].handler == func) {
- eventtab2[no].handler (eventtab2[no].data);
- break;
- }
- }
- if (no == ev2_max) {
- write_log (L"out of event2's! PC=%x\n", M68K_GETPC);
- return;
- }
- }
- eventtab2[no].active = 1;
- eventtab2[no].evtime = et;
- eventtab2[no].handler = func;
- eventtab2[no].data = data;
- MISC_handler ();
-}
-
-STATIC_INLINE void event2_newevent_x (int no, evt t, uae_u32 data, evfunc2 func)
-{
- if (((int)t) <= 0) {
- func (data);
- return;
- }
-
- event2_newevent_xx (no, t * CYCLE_UNIT, data, func);
-}
-
-void event2_newevent (int no, evt t)
-{
- event2_newevent_x (no, t, 0, eventtab2[no].handler);
-}
-void event2_newevent2 (evt t, uae_u32 data, evfunc2 func)
-{
- event2_newevent_x (-1, t, data, func);
-}
-
void event2_remevent (int no)
{
eventtab2[no].active = 0;
static int warned;
uae_u16 rval;
- if (addr & 1) {
- rval = value & 0xff;
+ if (currprefs.chipset_mask & CSMASK_AGA) {
+ if (addr & 1) {
+ rval = value & 0xff;
+ } else {
+ rval = (value << 8) | (value & 0xFF);
+ }
} else {
- rval = (value << 8) | (value & 0xFF);
+ rval = (value << 8) | (value & 0xff);
}
#ifdef JIT
else if (mode == 0)
put_byte (addr, v);
do_cycles_ce (CYCLE_UNIT);
+
}
void wait_cpu_cycle_write_ce020 (uaecptr addr, int mode, uae_u32 v)
updatetrackspeed (drv, drv->mfmpos);
if (diskevent_flag) {
disk_sync_cycle = startcycle >> 8;
- event2_newevent(ev2_disk, (startcycle - firstcycle) / CYCLE_UNIT);
+ event2_newevent (ev2_disk, (startcycle - firstcycle) / CYCLE_UNIT);
}
}
{
TCHAR *s = au (name);
uae_u32 dostype = get_long (pp + 80);
+ uae_u64 size;
+
+ size = ((uae_u64)get_long (pp + 20)) * 4 * get_long (pp + 28) * get_long (pp + 36) * (get_long (pp + 56) - get_long (pp + 52) + 1);
+
write_log (L"RDB: '%s' dostype=%08X. PartBlock=%d\n", s, dostype, partblock);
write_log (L"BlockSize: %d, Surfaces: %d, SectorsPerBlock %d\n",
get_long (pp + 20) * 4, get_long (pp + 28), get_long (pp + 32));
- write_log (L"SectorsPerTrack: %d, Reserved: %d, LowCyl %d, HighCyl %d\n",
- get_long (pp + 36), get_long (pp + 40), get_long (pp + 52), get_long (pp + 56));
+ write_log (L"SectorsPerTrack: %d, Reserved: %d, LowCyl %d, HighCyl %d, Size %dM\n",
+ get_long (pp + 36), get_long (pp + 40), get_long (pp + 52), get_long (pp + 56), (uae_u32)(size >> 20));
+
write_log (L"Buffers: %d, BufMemType: %08x, MaxTransfer: %08x, BootPri: %d\n",
get_long (pp + 60), get_long (pp + 64), get_long (pp + 68), get_long (pp + 76));
xfree (s);
insn_n_cycles += 4;
}
+static void dummy_prefetch (void)
+{
+ int o = m68k_pc_offset + 2;
+ if (!using_prefetch)
+ return;
+ if (using_ce) {
+ printf ("\tget_wordi_ce (m68k_getpc () + %d);\n", o);
+ } else {
+ printf ("\tget_wordi (m68k_getpc () + %d);\n", o);
+ }
+ count_read++;
+ insn_n_cycles += 4;
+}
+
static void fill_prefetch_next_1 (void)
{
irc2ir ();
printf ("\tm68k_areg (regs, dstreg) = srca;\n");
count_read++;
}
- fill_prefetch_next ();
count_ncycles++;
+ fill_prefetch_next ();
}
static void genmovemel_ce (uae_u16 opcode)
count_read++;
if (table68k[opcode].dmode == Aipi)
printf ("\tm68k_areg (regs, dstreg) = srca;\n");
- fill_prefetch_next ();
count_ncycles++;
+ fill_prefetch_next ();
}
static void genmovemle (uae_u16 opcode)
printf ("\twhile (amask) { %s, m68k_areg (regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n",
putcode, size);
}
- if (using_prefetch) {
- sync_m68k_pc ();
- fill_prefetch_next ();
- }
count_ncycles++;
+ fill_prefetch_next ();
}
static void genmovemle_ce (uae_u16 opcode)
size);
}
}
- fill_prefetch_next ();
count_ncycles++;
+ fill_prefetch_next ();
}
static void duplicate_carry (int n)
genastore_rev ("src", curi->dmode, "dstreg", curi->size, "dst");
break;
}
+ // all SR/CCR modifications have dummy read access
case i_ORSR:
case i_EORSR:
printf ("\tMakeSR ();\n");
genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
+ dummy_prefetch ();
if (curi->size == sz_byte) {
printf ("\tsrc &= 0xFF;\n");
}
- addcycles000 (4);
+ addcycles000 (8);
fill_prefetch_next ();
printf ("\tregs.sr %c= src;\n", curi->mnemo == i_EORSR ? '^' : '|');
printf ("\tMakeFromSR ();\n");
case i_ANDSR:
printf ("\tMakeSR ();\n");
genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
+ dummy_prefetch ();
if (curi->size == sz_byte) {
printf ("\tsrc |= 0xFF00;\n");
}
- addcycles000 (4);
+ addcycles000 (8);
fill_prefetch_next ();
printf ("\tregs.sr &= src;\n");
printf ("\tMakeFromSR ();\n");
break;
}
case i_SUBX:
+ if (!isreg (curi->smode))
+ addcycles000 (2);
genamode_pre (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA);
genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_AA);
genamode_post (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA);
+ fill_prefetch_next ();
if (curi->size == sz_long && isreg (curi->smode))
addcycles000 (4);
- if (!isreg (curi->smode))
- addcycles000 (2);
- fill_prefetch_next ();
start_brace ();
printf ("\tuae_u32 newv = dst - src - (GET_XFLG () ? 1 : 0);\n");
genflags (flag_subx, curi->size, "newv", "src", "dst");
genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
break;
case i_SBCD:
+ if (!isreg (curi->smode))
+ addcycles000 (2);
genamode_pre (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA);
genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_AA);
genamode_post (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA);
genflags (flag_zn, curi->size, "newv", "", "");
printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n");
}
- addcycles000 (2);
+ if (isreg (curi->smode))
+ addcycles000 (2);
genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
break;
case i_ADD:
break;
}
case i_ADDX:
+ if (!isreg (curi->smode))
+ addcycles000 (2);
genamode_pre (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA);
genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_AA);
genamode_post (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA);
+ fill_prefetch_next ();
if (curi->size == sz_long && isreg (curi->smode))
addcycles000 (4);
- if (!isreg (curi->smode))
- addcycles000 (2);
- fill_prefetch_next ();
start_brace ();
printf ("\tuae_u32 newv = dst + src + (GET_XFLG () ? 1 : 0);\n");
genflags (flag_addx, curi->size, "newv", "src", "dst");
genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
break;
case i_ABCD:
+ if (!isreg (curi->smode))
+ addcycles000 (2);
genamode_pre (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA);
genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_AA);
genamode_post (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA);
genflags (flag_zn, curi->size, "newv", "", "");
printf ("\tSET_VFLG ((tmp_newv & 0x80) == 0 && (newv & 0x80) != 0);\n");
}
- addcycles000 (2);
+ if (isreg (curi->smode))
+ addcycles000 (2);
genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
break;
case i_NEG:
genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
+ fill_prefetch_next ();
if (isreg (curi->smode) && curi->size == sz_long)
addcycles000 (2);
- fill_prefetch_next ();
start_brace ();
genflags (flag_sub, curi->size, "dst", "src", "0");
genastore_rev ("dst", curi->smode, "srcreg", curi->size, "src");
break;
case i_NEGX:
genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
+ fill_prefetch_next ();
if (isreg (curi->smode) && curi->size == sz_long)
addcycles000 (2);
- fill_prefetch_next ();
start_brace ();
printf ("\tuae_u32 newv = 0 - src - (GET_XFLG () ? 1 : 0);\n");
genflags (flag_subx, curi->size, "newv", "src", "0");
break;
case i_CLR:
genamode (curi->smode, "srcreg", curi->size, "src", cpu_level == 0 ? 1 : 2, 0, 0);
+ fill_prefetch_next ();
if (isreg (curi->smode) && curi->size == sz_long)
addcycles000 (2);
- fill_prefetch_next ();
genflags (flag_logical, curi->size, "0", "", "");
genastore_rev ("0", curi->smode, "srcreg", curi->size, "src");
break;
case i_NOT:
genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
+ fill_prefetch_next ();
if (isreg (curi->smode) && curi->size == sz_long)
addcycles000 (2);
- fill_prefetch_next ();
start_brace ();
printf ("\tuae_u32 dst = ~src;\n");
genflags (flag_logical, curi->size, "dst", "", "");
case i_BSET:
genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0);
+ fill_prefetch_next ();
bsetcycles (curi);
+ // bclr needs 1 extra cycle
if (curi->mnemo == i_BCLR && curi->dmode == Dreg)
addcycles000 (2);
- fill_prefetch_next ();
if (curi->mnemo == i_BCHG) {
printf ("\tdst ^= (1 << src);\n");
printf ("\tSET_ZFLG (((uae_u32)dst & (1 << src)) >> src);\n");
genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
break;
case i_CMPM:
+ // confirmed
genamode_pre (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA);
genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_AA);
genamode_post (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA);
*
* - move.x xxx,[at least 1 extension word here] = fetch 1 extension word before (xxx)
*
- * - current theory: moves are build from 3 separate microcode subroutines, fetch, move and write
*/
int prefetch_done = 0, flags;
int dualprefetch = curi->dmode == absl && (curi->smode != Dreg && curi->smode != Areg && curi->smode != imm);
genamode_pre (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_MOVE);
flags = 1 | (dualprefetch ? GF_NOREFILL : 0);
- genamode2 (curi->dmode, "dstreg", curi->size, "dst", 2, 0, flags, 0);
+ genamode2 (curi->dmode, "dstreg", curi->size, "dst", 2, 0, flags | GF_MOVE, 0);
genamode_post (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
if (curi->mnemo == i_MOVEA && curi->size == sz_word)
printf ("\tsrc = (uae_s32)(uae_s16)src;\n");
fill_prefetch_next ();
}
break;
- case i_MVSR2: // MOVE FROM SR (like CLR, does dummy read first on 68000)
- genamode (curi->smode, "srcreg", sz_word, "src", cpu_level == 0 ? 1 : 2, 0, 0);
+ case i_MVSR2: // MOVE FROM SR
+ genamode (curi->smode, "srcreg", sz_word, "src", 2, 0, 0);
+ fill_prefetch_next ();
if (isreg (curi->smode))
addcycles000 (2);
- fill_prefetch_next ();
printf ("\tMakeSR ();\n");
if (curi->size == sz_byte)
genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src");
case i_MV2SR: // MOVE TO SR
genamode (curi->smode, "srcreg", sz_word, "src", 1, 0, 0);
if (curi->size == sz_byte) {
- addcycles000 (8);
+ // MOVE TO CCR
+ dummy_prefetch ();
+ addcycles000 (4);
printf ("\tMakeSR ();\n\tregs.sr &= 0xFF00;\n\tregs.sr |= src & 0xFF;\n");
} else {
+ // MOVE TO SR
+ dummy_prefetch ();
addcycles000 (4);
printf ("\tregs.sr = src;\n");
}
- fill_prefetch_next ();
printf ("\tMakeFromSR ();\n");
+ fill_prefetch_next ();
break;
case i_SWAP:
genamode (curi->smode, "srcreg", sz_long, "src", 1, 0, 0);
genastore ("dst", curi->smode, "srcreg", sz_long, "src");
break;
case i_EXG:
+ // confirmed
genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0);
- addcycles000 (2);
fill_prefetch_next ();
+ addcycles000 (2);
genastore ("dst", curi->smode, "srcreg", curi->size, "src");
genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
break;
case i_EXT:
+ // confirmed
genamode (curi->smode, "srcreg", sz_long, "src", 1, 0, 0);
fill_prefetch_next ();
start_brace ();
curi->size == sz_word ? sz_word : sz_long, "src");
break;
case i_MVMEL:
+ // confirmed
if (using_ce)
genmovemel_ce (opcode);
else
genmovemel (opcode);
break;
case i_MVMLE:
+ // confirmed
if (using_ce)
genmovemle_ce (opcode);
else
fill_prefetch_full ();
break;
case i_LINK:
+ // ce confirmed
if (using_mmu) {
genamode (curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, 0);
genamode (Apdi, "7", sz_long, "old", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, 0);
}
break;
case i_UNLK:
+ // ce confirmed
genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
printf ("\tm68k_areg (regs, 7) = src;\n");
genamode (Aipi, "7", sz_long, "old", 1, 0, 0);
fill_prefetch_full ();
break;
case i_BSR:
+ // .b and .w confirmed
printf ("\tuae_s32 s;\n");
genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA|GF_NOREFILL);
printf ("\ts = (uae_s32)src + 2;\n");
fill_prefetch_full ();
break;
case i_Bcc:
+ // bcc.s and bcc.w cycles confirmed
if (curi->size == sz_long) {
if (cpu_level < 2) {
addcycles000 (2);
need_endlabel = 1;
break;
case i_Scc:
+ // confirmed
genamode (curi->smode, "srcreg", curi->size, "src", cpu_level == 0 ? 1 : 2, 0, 0);
start_brace ();
fill_prefetch_next();
#include "execio.h"
#include "zfile.h"
-#undef DEBUGME
+//#undef DEBUGME
#define hf_log
#define hf_log2
#define scsi_log
#define hf_log3
-//#define DEBUGME
+#define DEBUGME
#ifdef DEBUGME
#undef hf_log
#define hf_log write_log
static void getchs (struct hardfiledata *hfd, int *cyl, int *cylsec, int *head, int *tracksec)
{
getchs2 (hfd, cyl, cylsec, head, tracksec);
- hf_log ("CHS: %08X-%08X %d %d %d %d %d\n",
+ hf_log (L"CHS: %08X-%08X %d %d %d %d %d\n",
(uae_u32)(hfd->virtsize >> 32),(uae_u32)hfd->virtsize,
*cyl, *cylsec, *head, *tracksec);
}
static uae_u64 cmd_readx (struct hardfiledata *hfd, uae_u8 *dataptr, uae_u64 offset, uae_u64 len)
{
gui_flicker_led (LED_HD, hfd->unitnum, 1);
- hf_log3 ("cmd_read: %p %04x-%08x (%d) %08x (%d)\n",
+ hf_log3 (L"cmd_read: %p %04x-%08x (%d) %08x (%d)\n",
dataptr, (uae_u32)(offset >> 32), (uae_u32)offset, (uae_u32)(offset / hfd->blocksize), (uae_u32)len, (uae_u32)(len / hfd->blocksize));
return hdf_read (hfd, dataptr, offset, len);
}
static uae_u64 cmd_writex (struct hardfiledata *hfd, uae_u8 *dataptr, uae_u64 offset, uae_u64 len)
{
gui_flicker_led (LED_HD, hfd->unitnum, 2);
- hf_log3 ("cmd_write: %p %04x-%08x (%d) %08x (%d)\n",
+ hf_log3 (L"cmd_write: %p %04x-%08x (%d) %08x (%d)\n",
dataptr, (uae_u32)(offset >> 32), (uae_u32)offset, (uae_u32)(offset / hfd->blocksize), (uae_u32)len, (uae_u32)(len / hfd->blocksize));
return hdf_write (hfd, dataptr, offset, len);
}
status = 0;
memset (reply, 0, sizeof reply);
reply_len = 0; sense_len = 0;
- scsi_log ("hdf scsiemu: cmd=%02X,%d flags=%02X sense=%p,%d data=%p,%d\n",
+ scsi_log (L"hdf scsiemu: cmd=%02X,%d flags=%02X sense=%p,%d data=%p,%d\n",
cmd, scsi_cmd_len, scsi_flags, scsi_sense, scsi_sense_len, scsi_data, scsi_len);
for (i = 0; i < scsi_cmd_len; i++) {
cmdbuf[i] = get_byte (scsi_cmd + i);
- scsi_log ("%02X%c", get_byte (scsi_cmd + i), i < scsi_cmd_len - 1 ? '.' : ' ');
+ scsi_log (L"%02X%c", get_byte (scsi_cmd + i), i < scsi_cmd_len - 1 ? '.' : ' ');
}
- scsi_log ("\n");
+ scsi_log (L"\n");
status = scsi_emulate (hfd, NULL, cmdbuf, scsi_cmd_len, scsi_data_ptr, &scsi_len, reply, &reply_len, sense, &sense_len);
put_word (acmd + 18, status != 0 ? 0 : scsi_cmd_len); /* fake scsi_CmdActual */
put_byte (acmd + 21, status); /* scsi_Status */
if (reply_len > 0) {
- scsi_log ("RD:");
+ scsi_log (L"RD:");
i = 0;
while (i < reply_len) {
if (i < 24)
- scsi_log ("%02X%c", reply[i], i < reply_len - 1 ? '.' : ' ');
+ scsi_log (L"%02X%c", reply[i], i < reply_len - 1 ? '.' : ' ');
put_byte (scsi_data + i, reply[i]);
i++;
}
- scsi_log ("\n");
+ scsi_log (L"\n");
}
i = 0;
if (scsi_sense) {
if (hfpd->d_request[i] == request) {
hfpd->d_request_type[i] = type;
hfpd->d_request_data[i] = data;
- hf_log ("old async request %p (%d) added\n", request, type);
+ hf_log (L"old async request %p (%d) added\n", request, type);
return 0;
}
i++;
hfpd->d_request[i] = request;
hfpd->d_request_type[i] = type;
hfpd->d_request_data[i] = data;
- hf_log ("async request %p (%d) added (total=%d)\n", request, type, i);
+ hf_log (L"async request %p (%d) added (total=%d)\n", request, type, i);
return 0;
}
i++;
}
- hf_log ("async request overflow %p!\n", request);
+ hf_log (L"async request overflow %p!\n", request);
return -1;
}
hfpd->d_request[i] = 0;
hfpd->d_request_data[i] = 0;
hfpd->d_request_type[i] = 0;
- hf_log ("async request %p removed\n", request);
+ hf_log (L"async request %p removed\n", request);
return type;
}
i++;
}
- hf_log ("tried to remove non-existing request %p\n", request);
+ hf_log (L"tried to remove non-existing request %p\n", request);
return -1;
}
static void abort_async (struct hardfileprivdata *hfpd, uaecptr request, int errcode, int type)
{
int i;
- hf_log ("aborting async request %p\n", request);
+ hf_log (L"aborting async request %p\n", request);
i = 0;
while (i < MAX_ASYNC_REQUESTS) {
if (hfpd->d_request[i] == request && hfpd->d_request_type[i] == ASYNC_REQUEST_TEMP) {
}
i = release_async_request (hfpd, request);
if (i >= 0)
- hf_log ("asyncronous request=%08X aborted, error=%d\n", request, errcode);
+ hf_log (L"asyncronous request=%08X aborted, error=%d\n", request, errcode);
}
static void *hardfile_thread (void *devs);
put_long (request + 32, actual);
put_byte (request + 31, error);
- hf_log2 ("hf: unit=%d, request=%p, cmd=%d offset=%u len=%d, actual=%d error%=%d\n", unit, request,
+ hf_log2 (L"hf: unit=%d, request=%p, cmd=%d offset=%u len=%d, actual=%d error%=%d\n", unit, request,
get_word (request + 28), get_long (request + 44), get_long (request + 36), actual, error);
return async;
struct hardfiledata *hfd = get_hardfile_data (unit);
struct hardfileprivdata *hfpd = &hardfpd[unit];
- hf_log2 ("uaehf.device abortio ");
+ hf_log2 (L"uaehf.device abortio ");
start_thread (context, unit);
if (!hfd || !hfpd || !hfpd->thread_running) {
put_byte (request + 31, 32);
- hf_log2 ("error\n");
+ hf_log2 (L"error\n");
return get_byte (request + 31);
}
put_byte (request + 31, -2);
- hf_log2 ("unit=%d, request=%08X\n", unit, request);
+ hf_log2 (L"unit=%d, request=%08X\n", unit, request);
abort_async (hfpd, request, -2, 0);
return 0;
}
}
put_byte (request + 31, 0);
if ((flags & 1) && hardfile_canquick (hfd, request)) {
- hf_log ("hf quickio unit=%d request=%p cmd=%d\n", unit, request, cmd);
+ hf_log (L"hf quickio unit=%d request=%p cmd=%d\n", unit, request, cmd);
if (hardfile_do_io (hfd, hfpd, request))
- hf_log2 ("uaehf.device cmd %d bug with IO_QUICK\n", cmd);
+ hf_log2 (L"uaehf.device cmd %d bug with IO_QUICK\n", cmd);
return get_byte (request + 31);
} else {
- hf_log2 ("hf asyncio unit=%d request=%p cmd=%d\n", unit, request, cmd);
+ hf_log2 (L"hf asyncio unit=%d request=%p cmd=%d\n", unit, request, cmd);
add_async_request (hfpd, request, ASYNC_REQUEST_TEMP, 0);
put_byte (request + 30, get_byte (request + 30) & ~1);
write_comm_pipe_u32 (&hfpd->requests, request, 1);
release_async_request (hfpd, request);
uae_ReplyMsg (request);
} else {
- hf_log2 ("async request %08X\n", request);
+ hf_log2 (L"async request %08X\n", request);
}
uae_sem_post (&change_sem);
}
extern void akiko_entergui (void);
extern void akiko_exitgui (void);
extern void AKIKO_hsync_handler (void);
+extern void akiko_mute (int);
extern uae_u8 *extendedkickmemory;
typedef int (*pause_func)(int, int);
typedef int (*stop_func)(int);
typedef int (*play_func)(int, uae_u32, uae_u32, int);
+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);
pause_func pause;
stop_func stop;
play_func play;
+ volume_func volume;
qcode_func qcode;
toc_func toc;
read_func read;
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 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);
return v;
}
+STATIC_INLINE void prefetch_common_ce000 (void)
+{
+ regs.lastfetch = get_cycles () + CYCLE_UNIT;
+}
+
#ifdef CPUEMU_20
STATIC_INLINE void checkcycles_ce020 (void)
STATIC_INLINE uae_u32 mem_access_delay_word_read (uaecptr addr)
{
+ prefetch_common_ce000 ();
switch (ce_banktype[addr >> 16])
{
case CE_MEMBANK_CHIP:
}
STATIC_INLINE uae_u32 mem_access_delay_wordi_read (uaecptr addr)
{
+ prefetch_common_ce000 ();
switch (ce_banktype[addr >> 16])
{
case CE_MEMBANK_CHIP:
STATIC_INLINE uae_u32 mem_access_delay_byte_read (uaecptr addr)
{
+ prefetch_common_ce000 ();
switch (ce_banktype[addr >> 16])
{
case CE_MEMBANK_CHIP:
}
STATIC_INLINE void mem_access_delay_byte_write (uaecptr addr, uae_u32 v)
{
+ prefetch_common_ce000 ();
switch (ce_banktype[addr >> 16])
{
case CE_MEMBANK_CHIP:
}
STATIC_INLINE void mem_access_delay_word_write (uaecptr addr, uae_u32 v)
{
+ prefetch_common_ce000 ();
switch (ce_banktype[addr >> 16])
{
case CE_MEMBANK_CHIP:
flagtype x;
flagtype stopped;
int intmask;
+ int ipl;
uae_u32 vbr, sfc, dfc;
uae_u32 prefetch020data;
uae_u32 prefetch020addr;
int ce020memcycles;
+ evt lastfetch;
} regs, lastint_regs, mmu_backup_regs;
extern void REGPARAM3 Exception (int, uaecptr) REGPARAM;
extern void NMI (void);
extern void NMI_delayed (void);
-extern void prepare_interrupt (void);
+extern void prepare_interrupt (uae_u32);
extern void doint (void);
extern void dump_counts (void);
extern int m68k_move2c (int, uae_u32 *);
TCHAR sername[256];
TCHAR amaxromfile[MAX_DPATH];
TCHAR a2065name[MAX_DPATH];
+ TCHAR cdimagefile[MAX_DPATH];
TCHAR path_floppy[256];
TCHAR path_hardfile[256];
} else if (_tcscmp (argv[i], L"-h") == 0 || _tcscmp (argv[i], L"-help") == 0) {
usage ();
exit (0);
+ } else if (_tcsncmp (argv[i], L"-cdimage=", 9) == 0) {
+ TCHAR *txt = parsetext (argv[i] + 9);
+ cfgfile_parse_option (&currprefs, L"cdimage0", txt, 0);
+ xfree (txt);
} else {
if (argv[i][0] == '-' && argv[i][1] != '\0') {
const TCHAR *arg = argv[i] + 2;
static int interrupt_cycles_active;
-static unsigned long interrupt_cycles;
+static evt interrupt_cycle;
// handle interrupt delay (few cycles)
STATIC_INLINE int time_for_interrupt (void)
{
- if (!interrupt_cycles_active)
- return 1;
- if ((int)get_cycles () - (int)interrupt_cycles < 0)
- return 0;
- interrupt_cycles_active = 0;
+ if (interrupt_cycles_active) {
+ if (interrupt_cycle != regs.lastfetch) {
+ interrupt_cycles_active = 0;
+ return 1;
+ } else {
+ return 0;
+ }
+ }
return 1;
}
+void prepare_interrupt (uae_u32 lev)
+{
+ // CPU IPLx lines change state now
+ // but we may need to wait for next S4 state
+ // before CPU sees it
+ regs.ipl = lev;
+ if (currprefs.cpu_model == 68000) {
+ interrupt_cycle = get_cycles ();
+ if ((regs.lastfetch - interrupt_cycle) >= 0) {
+ // interrupt arrived too late
+ // wait for next memory cycle
+ interrupt_cycles_active = 1;
+ }
+ }
+ set_special (SPCFLAG_INT);
+}
+
+void doint (void)
+{
+ if (currprefs.cpu_cycle_exact)
+ return;
+ if (currprefs.cpu_compatible)
+ set_special (SPCFLAG_INT);
+ else
+ set_special (SPCFLAG_DOINT);
+}
+
#define IDLETIME (currprefs.cpu_idle * sleep_resolution / 700)
STATIC_INLINE int do_specialties (int cycles)
do_cycles (4 * CYCLE_UNIT);
if (regs.spcflags & SPCFLAG_COPPER)
do_copper ();
- if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
+
+ if (currprefs.cpu_cycle_exact) {
if (time_for_interrupt ()) {
+ int intr = regs.ipl;
+ if (intr > 0 && intr > regs.intmask)
+ do_interrupt (intr);
+ }
+ } else {
+ if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
int intr = intlev ();
unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
- if (intr != -1 && intr > regs.intmask)
+ if (intr > 0 && intr > regs.intmask)
do_interrupt (intr);
}
}
+
if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) {
unset_special (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
// SPCFLAG_BRK breaks STOP condition, need to prefetch
if (regs.spcflags & SPCFLAG_TRACE)
do_trace ();
- if (regs.spcflags & SPCFLAG_INT) {
+ if (currprefs.cpu_cycle_exact) {
if (time_for_interrupt ()) {
+ int intr = regs.ipl;
+ if (intr > 0 && intr > regs.intmask)
+ do_interrupt (intr);
+ }
+ } else {
+ if (regs.spcflags & SPCFLAG_INT) {
int intr = intlev ();
unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
- if (intr != -1 && (intr > regs.intmask || intr == 7))
+ if (intr > 0 && (intr > regs.intmask || intr == 7))
do_interrupt (intr);
}
}
+
if (regs.spcflags & SPCFLAG_DOINT) {
unset_special (SPCFLAG_DOINT);
set_special (SPCFLAG_INT);
return 0;
}
-void prepare_interrupt (void)
-{
- interrupt_cycles = get_cycles () + 5 * CYCLE_UNIT + CYCLE_UNIT / 2;
- if (vpos == 0 && current_hpos () == 0)
- interrupt_cycles -= CYCLE_UNIT; // vblank int hpos=-1
- interrupt_cycles_active = 1;
-}
-
-void doint (void)
-{
- if (currprefs.cpu_compatible)
- set_special (SPCFLAG_INT);
- else
- set_special (SPCFLAG_DOINT);
-}
//static uae_u32 pcs[1000];
//#define DEBUG_CD32IO
struct device_functions devicefunc_win32_aspi = {
open_scsi_bus, close_scsi_bus, open_scsi_device, close_scsi_device, info_device,
execscsicmd_out, execscsicmd_in, execscsicmd_direct,
- 0, 0, 0, 0, 0, 0, 0, 0, check_isatapi, scsi_info, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, check_isatapi, scsi_info, 0
};
#ifdef WINDDK
+#include "options.h"
#include "uae.h"
#include "threaddep/thread.h"
#include "blkdev.h"
int type;
int blocksize;
int mciid;
+ int cdda;
CDROM_TOC toc;
UINT errormode;
int playend;
int fullaccess;
+ int cdda_play_finished;
+ int cdda_play;
+ int cdda_paused;
+ int cdda_volume;
+ int cdda_volume_main;
+ uae_u32 cd_last_pos;
+ HWAVEOUT cdda_wavehandle;
+ int cdda_start, cdda_end;
};
-#define IOCTL_DATA_BUFFER 4096
+#define IOCTL_DATA_BUFFER 8192
+#define CDDA_BUFFERS 6
static int MCICDA;
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 1;
}
+static void cdda_closewav (struct dev_info_ioctl *ciw)
+{
+ if (ciw->cdda_wavehandle != NULL)
+ waveOutClose (ciw->cdda_wavehandle);
+ ciw->cdda_wavehandle = NULL;
+}
+
+// DAE CDDA based on Larry Osterman's "Playing Audio CDs" blog series
+
+static int cdda_openwav (struct dev_info_ioctl *ciw)
+{
+ WAVEFORMATEX wav = { 0 };
+ MMRESULT mmr;
+
+ wav.cbSize = 0;
+ wav.nChannels = 2;
+ wav.nSamplesPerSec = 44100;
+ wav.wBitsPerSample = 16;
+ wav.nBlockAlign = wav.wBitsPerSample / 8 * wav.nChannels;
+ wav.nAvgBytesPerSec = wav.nBlockAlign * wav.nSamplesPerSec;
+ wav.wFormatTag = WAVE_FORMAT_PCM;
+ mmr = waveOutOpen (&ciw->cdda_wavehandle, WAVE_MAPPER, &wav, 0, 0, WAVE_ALLOWSYNC | WAVE_FORMAT_DIRECT);
+ if (mmr != MMSYSERR_NOERROR) {
+ write_log (L"CDDA: wave open %d\n", mmr);
+ cdda_closewav (ciw);
+ return 0;
+ }
+ return 1;
+}
+
+static void *cdda_play (void *v)
+{
+ DWORD len;
+ struct dev_info_ioctl *ciw = v;
+ int unitnum = ciw32 - ciw;
+ int cdda_pos;
+ int num_sectors = CDDA_BUFFERS;
+ int quit = 0;
+ int bufnum;
+ int buffered;
+ uae_u8 *px[2], *p;
+ int bufon[2];
+ int i;
+ WAVEHDR whdr[2];
+ MMRESULT mmr;
+ int volume, volume_main;
+ int oldplay;
+
+
+ for (i = 0; i < 2; i++) {
+ memset (&whdr[i], 0, sizeof (WAVEHDR));
+ whdr[i].dwFlags = WHDR_DONE;
+ }
+
+ while (ciw->cdda_play == 0)
+ Sleep (10);
+ oldplay = -1;
+
+ p = VirtualAlloc (NULL, 2 * num_sectors * 4096, MEM_COMMIT, PAGE_READWRITE);
+ px[0] = p;
+ px[1] = p + num_sectors * 4096;
+ bufon[0] = bufon[1] = 0;
+ bufnum = 0;
+ buffered = 0;
+ volume = -1;
+ volume_main = -1;
+
+ if (cdda_openwav (ciw)) {
+
+ for (i = 0; i < 2; i++) {
+ memset (&whdr[i], 0, sizeof (WAVEHDR));
+ whdr[i].dwBufferLength = 2352 * num_sectors;
+ whdr[i].lpData = px[i];
+ mmr = waveOutPrepareHeader (ciw->cdda_wavehandle, &whdr[i], sizeof (WAVEHDR));
+ if (mmr != MMSYSERR_NOERROR) {
+ write_log (L"CDDA: waveOutPrepareHeader %d:%d\n", i, mmr);
+ goto end;
+ }
+ whdr[i].dwFlags |= WHDR_DONE;
+ }
+
+ 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)
+ goto end;
+ }
+ bufon[bufnum] = 0;
+
+ if ((cdda_pos < ciw->cdda_end || ciw->cdda_end == 0xffffffff) && !ciw->cdda_paused && ciw->cdda_play) {
+ RAW_READ_INFO rri;
+
+ seterrormode (unitnum);
+ rri.DiskOffset.QuadPart = 2048 * (cdda_pos - 150);
+ rri.SectorCount = num_sectors;
+ 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 returned %d\n", err);
+ quit = 1;
+ }
+ reseterrormode (unitnum);
+ if (quit)
+ break;
+
+ bufon[bufnum] = 1;
+ if (volume != ciw->cdda_volume || volume_main != currprefs.sound_volume) {
+ int vol;
+ volume = ciw->cdda_volume;
+ volume_main = currprefs.sound_volume;
+ vol = (100 - volume_main) * volume / 100;
+ if (vol >= 0xffff)
+ vol = 0xffff;
+ waveOutSetVolume (ciw->cdda_wavehandle, vol | (vol << 16));
+ }
+ mmr = waveOutWrite (ciw->cdda_wavehandle, &whdr[bufnum], sizeof (WAVEHDR));
+ if (mmr != MMSYSERR_NOERROR) {
+ write_log (L"CDDA: waveOutWrite %d\n", mmr);
+ break;
+ }
+
+ cdda_pos += num_sectors;
+ if (cdda_pos >= ciw->cdda_end)
+ ciw->cdda_play_finished = 1;
+ ciw->cd_last_pos = cdda_pos;
+
+ }
+
+
+ if (bufon[0] == 0 && bufon[1] == 0) {
+ while (!(whdr[0].dwFlags & WHDR_DONE) || !(whdr[1].dwFlags & WHDR_DONE))
+ Sleep (10);
+ while (ciw->cdda_paused && ciw->cdda_play > 0)
+ Sleep (10);
+ }
+
+ bufnum = 1 - bufnum;
+
+ }
+ }
+
+end:
+ while (!(whdr[0].dwFlags & WHDR_DONE) || !(whdr[1].dwFlags & WHDR_DONE))
+ Sleep (10);
+ for (i = 0; i < 2; i++)
+ waveOutUnprepareHeader (ciw->cdda_wavehandle, &whdr[i], sizeof (WAVEHDR));
+
+ cdda_closewav (ciw);
+ VirtualFree (p, 0, MEM_RELEASE);
+ ciw->cdda_play = 0;
+ write_log (L"CDDA: thread killed\n");
+ return NULL;
+}
+
+static void cdda_stop (int unitnum)
+{
+ struct dev_info_ioctl *ciw = &ciw32[unitnum];
+
+ if (ciw->cdda_play > 0) {
+ ciw->cdda_play = -1;
+ while (ciw->cdda_play) {
+ Sleep (10);
+ }
+ }
+ ciw->cdda_play_finished = 0;
+ ciw->cdda_paused = 0;
+}
+
/* pause/unpause CD audio */
static int ioctl_command_pause (int unitnum, int paused)
{
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;
return 1;
}
+
/* stop CD audio */
static int ioctl_command_stop (int unitnum)
{
mcierr (L"MCI_STOP", mciSendCommand (ciw->mciid, MCI_STOP, MCI_WAIT, (DWORD_PTR)&gp));
ciw->playend = -1;
+ } else if (ciw->cdda) {
+
+ cdda_stop (unitnum);
+
} else {
DWORD len;
return 1;
}
+static void ioctl_command_volume (int unitnum, uae_u16 volume)
+{
+ struct dev_info_ioctl *ciw = &ciw32[unitnum];
+
+ ciw->cdda_volume = volume;
+}
+
/* play CD audio */
static int ioctl_command_play (int unitnum, uae_u32 start, uae_u32 end, int scan)
{
struct dev_info_ioctl *ciw = &ciw32[unitnum];
- open_mci (unitnum);
+ if (!ciw->cdda)
+ open_mci (unitnum);
if (ciw->mciid > 0) {
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, 1))
+ 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;
return 1;
}
-/* 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;
-}
-
/* read qcode */
static uae_u8 *ioctl_command_qcode (int unitnum)
{
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;
+ }
+ 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;
+ }
+#endif
+ p[1] = status;
+ p[3] = 12;
+
+ p = buf + 4;
+
+ if (pos >= 150)
+ trk = 0;
+ start = end = 0;
+ for (trk = 0; trk <= toc->LastTrack; trk++) {
+ TRACK_DATA *td = &toc->TrackData[trk];
+ start = msf2lsn ((td->Address[1] << 16) | (td->Address[2] << 8) | td->Address[3]);
+ end = msf2lsn ((td[1].Address[1] << 16) | (td[1].Address[2] << 8) | td[1].Address[3]);
+ if (pos < start)
+ break;
+ 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;
+ 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] = (pos >> 16) & 0xff;
+ p[10] = (pos >> 8) & 0xff;
+ p[11] = (pos >> 0) & 0xff;
+
+ return buf;
+
} else {
SUB_Q_CHANNEL_DATA qcd;
DWORD len;
ULONG in = 1;
- uae_u8 *p = ciw32[unitnum].tempbuffer;
+ uae_u8 *p = ciw->tempbuffer;
int cnt = 3;
memset (p, 0, 4 + 12);
p[3] = 12;
while (cnt-- > 0) {
reseterrormode (unitnum);
- if(!DeviceIoControl (ciw32[unitnum].h, IOCTL_CDROM_READ_Q_CHANNEL, &in, sizeof(in), &qcd, sizeof (qcd), &len, NULL)) {
+ 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;
p[9] = qcd.CurrentPosition.TrackRelativeAddress[1];
p[10] = qcd.CurrentPosition.TrackRelativeAddress[2];
p[11] = qcd.CurrentPosition.TrackRelativeAddress[3];
- return ciw32[unitnum].tempbuffer;
+ return ciw->tempbuffer;
}
}
if (!open_createfile (unitnum, 1))
return 0;
+ ciw32[unitnum].cd_last_pos = sector + sectorsize;
cmd[3] = (uae_u8)(sector >> 16);
cmd[4] = (uae_u8)(sector >> 8);
cmd[5] = (uae_u8)(sector >> 0);
return spti_read (unitnum, sector, sectorsize);
if (!open_createfile (unitnum, 1))
return 0;
+ cdda_stop (unitnum);
if (sectorsize != 2336 && sectorsize != 2352 && sectorsize != 2048)
return 0;
while (cnt-- > 0) {
DWORD err = GetLastError ();
}
reseterrormode (unitnum);
+ ciw32[unitnum].cd_last_pos = sector + sectorsize;
break;
}
if (sectorsize == 2352)
*ptr = NULL;
if (!open_createfile (unitnum, 0))
return 0;
+ cdda_stop (unitnum);
while (cnt-- > 0) {
gui_flicker_led (LED_CD, unitnum, 1);
seterrormode (unitnum);
/* read toc */
static uae_u8 *ioctl_command_toc (int unitnum)
{
+ struct dev_info_ioctl *ciw = &ciw32[unitnum];
DWORD len;
int i;
- uae_u8 *p = ciw32[unitnum].tempbuffer;
+ uae_u8 *p = ciw->tempbuffer;
int cnt = 3;
- CDROM_TOC *toc = &ciw32[unitnum].toc;
+ CDROM_TOC *toc = &ciw->toc;
if (!open_createfile (unitnum, 0))
return 0;
+ cdda_stop (unitnum);
+ ciw32[unitnum].cd_last_pos = 0;
gui_flicker_led (LED_CD, unitnum, 1);
while (cnt-- > 0) {
seterrormode (unitnum);
{
struct dev_info_ioctl *ciw = &ciw32[unitnum];
+ ciw->cdda = 1;
+ ciw->cdda_volume = 0xffff;
+ ciw->cdda_volume_main = currprefs.sound_volume;
/* buffer must be page aligned for device access */
ciw->tempbuffer = VirtualAlloc (NULL, IOCTL_DATA_BUFFER, MEM_COMMIT, PAGE_READWRITE);
if (!ciw->tempbuffer) {
if (!unitcheck (unitnum))
return;
+ cdda_stop (unitnum);
close_createfile (unitnum);
close_mci (unitnum);
VirtualFree (ciw->tempbuffer, 0, MEM_RELEASE);
struct device_functions devicefunc_win32_ioctl = {
open_bus, close_bus, open_device, close_device, info_device,
0, 0, 0,
- ioctl_command_pause, ioctl_command_stop, ioctl_command_play, ioctl_command_qcode,
+ ioctl_command_pause, ioctl_command_stop, ioctl_command_play, ioctl_command_volume, ioctl_command_qcode,
ioctl_command_toc, ioctl_command_read, ioctl_command_rawread, ioctl_command_write,
0, ioctl_scsi_info, ioctl_ismedia
};
struct device_functions devicefunc_win32_spti = {
open_scsi_bus, close_scsi_bus, open_scsi_device, close_scsi_device, info_device,
execscsicmd_out, execscsicmd_in, execscsicmd_direct,
- 0, 0, 0, 0, 0, 0, 0, 0, check_isatapi, scsi_info, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, check_isatapi, scsi_info, 0
};
static int getCDROMProperty (int idx, HDEVINFO DevInfo, const GUID *guid)
HMODULE hUIDLL = NULL;
HWND (WINAPI *pHtmlHelp)(HWND, LPCWSTR, UINT, LPDWORD) = NULL;
HWND hAmigaWnd, hMainWnd, hHiddenWnd, hGUIWnd;
-RECT amigawin_rect;
+RECT amigawin_rect, mainwin_rect;
static int mouseposx, mouseposy;
static UINT TaskbarRestart;
static HWND TaskbarRestartHWND;
static LRESULT CALLBACK MainWindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
+ static RECT myrect;
PAINTSTRUCT ps;
RECT rc;
HDC hDC;
DWORD top = rc2.top - win_y_diff;
DWORD width = rc2.right - rc2.left;
DWORD height = rc2.bottom - rc2.top;
- if (amigawin_rect.left & 3) {
- MoveWindow (hMainWnd, rc2.left + 4 - amigawin_rect.left % 4, rc2.top,
- rc2.right - rc2.left, rc2.bottom - rc2.top, TRUE);
-
- }
if (store_xy++) {
regsetint (NULL, L"MainPosX", left);
regsetint (NULL, L"MainPosY", top);
}
changed_prefs.gfx_size_win.x = left;
changed_prefs.gfx_size_win.y = top;
- if (canstretch ()) {
+ if (canstretch () && mainwin_rect.right - mainwin_rect.left != width && mainwin_rect.bottom - mainwin_rect.top != height) {
changed_prefs.gfx_size_win.width = width - window_extra_width;
changed_prefs.gfx_size_win.height = height - window_extra_height;
}
}
+ GetWindowRect (hMainWnd, &mainwin_rect);
return 0;
}
+ GetWindowRect (hMainWnd, &mainwin_rect);
}
break;
#define WINUAEPUBLICBETA 1
#define LANG_DLL 1
-#define WINUAEBETA L"Beta 3"
-#define WINUAEDATE MAKEBD(2010, 1, 10)
+#define WINUAEBETA L"Beta 4"
+#define WINUAEDATE MAKEBD(2010, 1, 16)
#define WINUAEEXTRA L""
#define WINUAEREV L""
#define WINUAEAPPNAME L"Arabuusimiehet.WinUAE"
extern HMODULE hUIDLL;
extern HWND hAmigaWnd, hMainWnd, hHiddenWnd, hGUIWnd;
-extern RECT amigawin_rect;
+extern RECT amigawin_rect, mainwin_rect;
extern int in_sizemove;
extern int manual_painting_needed;
extern int manual_palette_refresh_needed;
y = ny;
}
GetWindowRect (hAmigaWnd, &amigawin_rect);
+ GetWindowRect (hMainWnd, &mainwin_rect);
if (d3dfs || dxfs)
SetCursorPos (x + w / 2, y + h / 2);
write_log (L"window already open\n");
if (hMainWnd == NULL)
hMainWnd = hAmigaWnd;
GetWindowRect (hAmigaWnd, &amigawin_rect);
+ GetWindowRect (hMainWnd, &mainwin_rect);
if (dxfs || d3dfs)
SetCursorPos (x + w / 2, y + h / 2);
addnotifications (hAmigaWnd, FALSE, FALSE);
nmhdr = (LPNMHDR)lParam;
if (nmhdr->code == CDN_INITDONE)
doit = TRUE;
- } else if (message == WM_INITDIALOG) {
- doit = TRUE;
}
if (!doit)
return FALSE;
prevheight = h2;
write_log (L"MOVEWINDOW %dx%d %dx%d (%dx%d)\n", md->rect.left, md->rect.top, md->rect.right, md->rect.bottom, w2, h2);
hWnd = GetParent (hDlg);
+ windowRect.left = windowRect.right = windowRect.top = windowRect.bottom = -1;
GetWindowRect (hWnd, &windowRect);
width = windowRect.right - windowRect.left;
height = windowRect.bottom - windowRect.top;
+ write_log (L"%dx%d %dx%d\n", windowRect.left, windowRect.top, windowRect.right, windowRect.bottom);
if (width > w2)
width = w2;
if (height > h2)
height = h2;
- MoveWindow (hWnd, md->rect.left + (w2 - width) / 2, md->rect.top + (h2 - height) / 2, width, height, FALSE);
+ SetWindowPos (hWnd, NULL, md->rect.left + (w2 - width) / 2, md->rect.top + (h2 - height) / 2, width, height, SWP_NOZORDER | SWP_NOACTIVATE);
return FALSE;
}
>
</File>
<File
- RelativePath=".\configfile.ico"
+ RelativePath="..\resources\configfile.ico"
>
</File>
<File
- RelativePath="..\resources\configfile.ico"
+ RelativePath=".\configfile.ico"
>
</File>
<File
>
</File>
<File
- RelativePath=".\expansion.ico"
+ RelativePath="..\resources\expansion.ico"
>
</File>
<File
- RelativePath="..\resources\expansion.ico"
+ RelativePath=".\expansion.ico"
>
</File>
<File
- RelativePath=".\file.ico"
+ RelativePath="..\resources\file.ico"
>
</File>
<File
- RelativePath="..\resources\file.ico"
+ RelativePath=".\file.ico"
>
</File>
<File
RelativePath="..\..\blkdev.c"
>
</File>
+ <File
+ RelativePath="..\..\blkdev_cdimage.c"
+ >
+ </File>
<File
RelativePath="..\..\bsdsocket.c"
>
+Beta 4:
+
+- ADDX and SUBX timing updates
+- ABCD and SBCD idle cycle position in -(An),-(An) mode fixed
+- EXG idle cycle and prefetch swapped
+- BCLR/BSET/BCHG/BTST idle cycle and prefetch swapped
+- writing to blitter registers while active could have confused
+ blitter emulation logic, stopping the blitter mid blit (stopping
+ because emulation got confused, not because emulation detected
+ situation when it should really stop)
+- plain A500 OCS/ECS byte writes to custom registers fixed (I think
+ this was using 68020/AGA behavior for all modes accidentally)
+- interrupt delay and 68000 IPL sampling timing improved
+- windowed mode window was sometimes incorrectly detected as resized
+ when it only lost focus (native mode size was changed to current
+ window size)
+
+ Big CD32/CDTV CD handling update:
+
+- stupid MCI CD32/CDTV CD audio replaced with simple "audio ripper"
+ that reads the digital CD audio data and sends it to audio device
+ NOTE: no jitter correction yet (possibly bad sound if your drive
+ is old enough to not have accurate streaming support)
+- CDTV CD hardware volume control now supported
+- CD32 CD mute on/off "volume" control supported (no real volume..)
+- Sound-panel volume also adjusts CD32/CDTV CD audio volume
+- CD32/CDTV Q sub channel data virtualized (does not need real drive
+ anymore, makes new things possible, see below)
+- Built-in CUE CD image support, including CD audio track support!
+ .CUE + single big .BIN and .CUE + .BIN + .WAVs supported (MP3 audio
+ is also supported if you have mp3 codec installed but all tracks will
+ be decoded before emulation starts..) Most common data tracks
+ supported. Plain iso images also supported.
+ Problems = logs AND .cue file required.
+ cdimage0=<path to .cue/.iso> in config file, command line parameter
+ -cdimage=<path to .cue/.iso> can also be used.
+ No GUI support yet.
+
Beta 3:
- Shadow Fighter AGA graphics priority issue really fixed now
uae_u8 inbuf[4096];
int incnt;
- memset (&zs, 0, sizeof(zs));
- if (inflateInit_ (&zs, ZLIB_VERSION, sizeof(z_stream)) != Z_OK)
+ memset (&zs, 0, sizeof (zs));
+ if (inflateInit_ (&zs, ZLIB_VERSION, sizeof (z_stream)) != Z_OK)
return 0;
zs.next_out = (Bytef*)dst;
zs.avail_out = dstsize;