From 8e73308b0cd7ec82d61eff17f41222b2210b5db7 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 16 Jan 2010 12:21:18 +0200 Subject: [PATCH] imported winuaesrc2020b4.zip --- akiko.c | 39 +- blitter.c | 44 +- blkdev.c | 15 +- blkdev_cdimage.c | 901 ++++++++++++++++++++++++ cdtv.c | 16 +- cfgfile.c | 18 +- cia.c | 6 +- custom.c | 209 +++--- disk.c | 2 +- filesys.c | 9 +- gencpu.c | 94 ++- hardfile.c | 52 +- include/akiko.h | 1 + include/blkdev.h | 3 + include/cpu_prefetch.h | 10 + include/newcpu.h | 4 +- include/options.h | 1 + main.c | 4 + newcpu.c | 80 ++- od-win32/blkdev_win32_aspi.c | 2 +- od-win32/blkdev_win32_ioctl.c | 341 ++++++++- od-win32/blkdev_win32_spti.c | 2 +- od-win32/win32.c | 12 +- od-win32/win32.h | 6 +- od-win32/win32gfx.c | 2 + od-win32/win32gui.c | 6 +- od-win32/winuae_msvc/winuae_msvc.vcproj | 16 +- od-win32/winuaechangelog.txt | 38 + zfile.c | 4 +- 29 files changed, 1663 insertions(+), 274 deletions(-) create mode 100644 blkdev_cdimage.c diff --git a/akiko.c b/akiko.c index 5e780193..77d55337 100644 --- a/akiko.c +++ b/akiko.c @@ -411,6 +411,7 @@ static int cdrom_audiotimeout; 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; @@ -650,9 +651,13 @@ static int sys_cddev_open (void) 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); @@ -687,7 +692,6 @@ static int sys_cddev_open (void) write_log (L"can't read TOC\n"); } } - sys_command_close (DF_IOCTL, unitnum); } } unitnum = audiounit; @@ -695,10 +699,14 @@ static int sys_cddev_open (void) 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); @@ -1238,7 +1246,11 @@ static void *akiko_thread (void *null) 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; } @@ -1829,12 +1841,12 @@ void restore_akiko_finish (void) 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); @@ -1846,11 +1858,18 @@ void restore_akiko_finish (void) 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); } diff --git a/blitter.c b/blitter.c index 6749e338..ebfac686 100644 --- a/blitter.c +++ b/blitter.c @@ -824,7 +824,7 @@ STATIC_INLINE uae_u16 blitter_doblit (void) } -STATIC_INLINE int blitter_doddma (int hpos) +STATIC_INLINE void blitter_doddma (int hpos) { int wd; uae_u16 d; @@ -841,25 +841,25 @@ STATIC_INLINE int blitter_doddma (int hpos) 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) @@ -1045,10 +1045,9 @@ void decide_blitter (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); @@ -1169,6 +1168,7 @@ static void blit_bltset (int con) 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); diff --git a/blkdev.c b/blkdev.c index f0e284bd..1c6fe487 100644 --- a/blkdev.c +++ b/blkdev.c @@ -25,14 +25,19 @@ static int initialized; 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 || @@ -155,6 +160,14 @@ int sys_command_cd_play (int mode, int unitnum,uae_u32 startmsf, uae_u32 endmsf, 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) { diff --git a/blkdev_cdimage.c b/blkdev_cdimage.c new file mode 100644 index 00000000..7be044e4 --- /dev/null +++ b/blkdev_cdimage.c @@ -0,0 +1,901 @@ +/* +* 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 +#include +#include + +#define MP3_BLOCK_SIZE 522 + +static HACMSTREAM g_mp3stream = NULL; + +static void mp3decoder_close (void) +{ + if (g_mp3stream) + acmStreamClose (g_mp3stream, 0); + g_mp3stream = NULL; +} + +static int mp3decoder_open (void) +{ + MMRESULT mmr; + LPWAVEFORMATEX waveFormat; + LPMPEGLAYER3WAVEFORMAT mp3format; + DWORD maxFormatSize; + + if (g_mp3stream) + return 1; + + // find the biggest format size + maxFormatSize = 0; + mmr = acmMetrics (NULL, ACM_METRIC_MAX_SIZE_FORMAT, &maxFormatSize); + + // define desired output format + waveFormat = (LPWAVEFORMATEX) LocalAlloc( LPTR, maxFormatSize ); + waveFormat->wFormatTag = WAVE_FORMAT_PCM; + waveFormat->nChannels = 2; // stereo + waveFormat->nSamplesPerSec = 44100; // 44.1kHz + waveFormat->wBitsPerSample = 16; // 16 bits + waveFormat->nBlockAlign = 4; // 4 bytes of data at a time are useful (1 sample) + waveFormat->nAvgBytesPerSec = 4 * 44100; // byte-rate + waveFormat->cbSize = 0; // no more data to follow + + // define MP3 input format + mp3format = (LPMPEGLAYER3WAVEFORMAT) LocalAlloc( LPTR, maxFormatSize ); + mp3format->wfx.cbSize = MPEGLAYER3_WFX_EXTRA_BYTES; + mp3format->wfx.wFormatTag = WAVE_FORMAT_MPEGLAYER3; + mp3format->wfx.nChannels = 2; + mp3format->wfx.nAvgBytesPerSec = 128 * (1024 / 8); // not really used but must be one of 64, 96, 112, 128, 160kbps + mp3format->wfx.wBitsPerSample = 0; // MUST BE ZERO + mp3format->wfx.nBlockAlign = 1; // MUST BE ONE + mp3format->wfx.nSamplesPerSec = 44100; // 44.1kHz + mp3format->fdwFlags = MPEGLAYER3_FLAG_PADDING_OFF; + mp3format->nBlockSize = MP3_BLOCK_SIZE; // voodoo value #1 + mp3format->nFramesPerBlock = 1; // MUST BE ONE + mp3format->nCodecDelay = 1393; // voodoo value #2 + mp3format->wID = MPEGLAYER3_ID_MPEG; + + mmr = acmStreamOpen( &g_mp3stream, // open an ACM conversion stream + NULL, // querying all ACM drivers + (LPWAVEFORMATEX) mp3format, // converting from MP3 + waveFormat, // to WAV + NULL, // with no filter + 0, // or async callbacks + 0, // (and no data for the callback) + 0 // and no flags + ); + + LocalFree (mp3format); + LocalFree (waveFormat); + if (mmr == MMSYSERR_NOERROR) + return 1; + write_log (L"CUEMP3: couldn't open ACM mp3 decoder, %d\n", mmr); + return 0; +} + +static uae_u8 *mp3decoder_get (struct zfile *zf, int *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 +}; diff --git a/cdtv.c b/cdtv.c index e5154205..887620cc 100644 --- a/cdtv.c +++ b/cdtv.c @@ -786,6 +786,10 @@ static void tp_bput (int addr, uae_u8 v) #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)) { @@ -1310,6 +1314,8 @@ static void open_unit (void) 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); @@ -1320,7 +1326,9 @@ static void open_unit (void) 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); @@ -1345,7 +1353,6 @@ static void open_unit (void) write_log (L"TOC read failed\n"); } } - sys_command_close (DF_IOCTL, unitnum); } } unitnum = audiounit; @@ -1353,9 +1360,14 @@ static void open_unit (void) 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; diff --git a/cfgfile.c b/cfgfile.c index 64cf1d09..42fa6bb5 100644 --- a/cfgfile.c +++ b/cfgfile.c @@ -525,6 +525,9 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) } } + 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); @@ -993,6 +996,9 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value) } } + 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; @@ -3475,7 +3481,7 @@ static void buildin_default_prefs (struct uae_prefs *p) 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; @@ -3485,15 +3491,11 @@ static void set_68020_compa (struct uae_prefs *p, int compa) 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 @@ -3701,7 +3703,7 @@ static int bip_cd32 (struct uae_prefs *p, int config, int compa, int romcheck) 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)); @@ -3723,7 +3725,7 @@ static int bip_a1200 (struct uae_prefs *p, int config, int compa, int romcheck) 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); diff --git a/cia.c b/cia.c index 24c8e558..f7476ac8 100644 --- a/cia.c +++ b/cia.c @@ -58,7 +58,7 @@ static unsigned long ciaata_passed, ciaatb_passed, ciabta_passed, ciabtb_passed; 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; @@ -593,6 +593,9 @@ static void bfe001_change (void) //activate_debugger (); map_overlay (0); } + } else if (currprefs.cs_cd32cd && (v & 1) != oldcd32mute) { + oldcd32mute = v & 1; + akiko_mute (oldcd32mute ? 0 : 1); } } @@ -1150,6 +1153,7 @@ void CIA_reset (void) ciaasdr_unread = 0; serbits = 0; oldovl = 1; + oldcd32mute = 1; oldled = -1; resetwarning_phase = resetwarning_timer = 0; diff --git a/custom.c b/custom.c index 2ee9ac65..c2f53498 100644 --- a/custom.c +++ b/custom.c @@ -3265,6 +3265,91 @@ static void DMACON (int hpos, uae_u16 v) 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) @@ -3301,6 +3386,15 @@ STATIC_INLINE int use_eventmode (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); @@ -3308,9 +3402,9 @@ STATIC_INLINE void INTENA (uae_u16 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 (); } } @@ -3321,21 +3415,21 @@ void INTREQ_0 (uae_u16 v) 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) @@ -5499,90 +5593,6 @@ static void hsync_handler (void) #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; @@ -6319,10 +6329,14 @@ static void REGPARAM2 custom_bput (uaecptr addr, uae_u32 value) 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 @@ -6979,6 +6993,7 @@ void wait_cpu_cycle_write (uaecptr addr, int mode, uae_u32 v) 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) diff --git a/disk.c b/disk.c index 8728930a..f3e1318a 100644 --- a/disk.c +++ b/disk.c @@ -2766,7 +2766,7 @@ static void disk_doupdate_predict (drive * drv, int startcycle) 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); } } diff --git a/filesys.c b/filesys.c index 3d0541f7..25343605 100644 --- a/filesys.c +++ b/filesys.c @@ -5327,11 +5327,16 @@ static void dump_partinfo (uae_char *name, int num, uaecptr pp, int partblock) { 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); diff --git a/gencpu.c b/gencpu.c index 55548cf3..76e77f9a 100644 --- a/gencpu.c +++ b/gencpu.c @@ -404,6 +404,20 @@ static void fill_prefetch_0 (void) 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 (); @@ -1046,8 +1060,8 @@ static void genmovemel (uae_u16 opcode) printf ("\tm68k_areg (regs, dstreg) = srca;\n"); count_read++; } - fill_prefetch_next (); count_ncycles++; + fill_prefetch_next (); } static void genmovemel_ce (uae_u16 opcode) @@ -1075,8 +1089,8 @@ 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) @@ -1123,11 +1137,8 @@ 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) @@ -1171,8 +1182,8 @@ static void genmovemle_ce (uae_u16 opcode) size); } } - fill_prefetch_next (); count_ncycles++; + fill_prefetch_next (); } static void duplicate_carry (int n) @@ -1568,14 +1579,16 @@ static void gen_opcode (unsigned long int opcode) 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"); @@ -1583,10 +1596,11 @@ static void gen_opcode (unsigned long int opcode) 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"); @@ -1632,14 +1646,14 @@ static void gen_opcode (unsigned long int opcode) 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"); @@ -1647,6 +1661,8 @@ static void gen_opcode (unsigned long int opcode) 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); @@ -1670,7 +1686,8 @@ static void gen_opcode (unsigned long int opcode) 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: @@ -1714,14 +1731,14 @@ static void gen_opcode (unsigned long int opcode) 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"); @@ -1729,6 +1746,8 @@ static void gen_opcode (unsigned long int opcode) 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); @@ -1754,23 +1773,24 @@ static void gen_opcode (unsigned long int opcode) 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"); @@ -1806,17 +1826,17 @@ static void gen_opcode (unsigned long int opcode) 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", "", ""); @@ -1839,10 +1859,11 @@ static void gen_opcode (unsigned long int opcode) 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"); @@ -1856,6 +1877,7 @@ static void gen_opcode (unsigned long int opcode) 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); @@ -1919,13 +1941,12 @@ static void gen_opcode (unsigned long int opcode) * * - 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"); @@ -1945,11 +1966,11 @@ static void gen_opcode (unsigned long int opcode) 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"); @@ -1959,14 +1980,18 @@ static void gen_opcode (unsigned long int opcode) 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); @@ -1977,14 +2002,16 @@ static void gen_opcode (unsigned long int opcode) 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 (); @@ -2000,12 +2027,14 @@ static void gen_opcode (unsigned long int opcode) 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 @@ -2106,6 +2135,7 @@ static void gen_opcode (unsigned long int opcode) 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); @@ -2124,6 +2154,7 @@ static void gen_opcode (unsigned long int opcode) } 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); @@ -2208,6 +2239,7 @@ static void gen_opcode (unsigned long int opcode) 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"); @@ -2233,6 +2265,7 @@ static void gen_opcode (unsigned long int opcode) 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); @@ -2346,6 +2379,7 @@ static void gen_opcode (unsigned long int opcode) 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(); diff --git a/hardfile.c b/hardfile.c index 37ff6417..516fc9da 100644 --- a/hardfile.c +++ b/hardfile.c @@ -28,13 +28,13 @@ #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 @@ -137,7 +137,7 @@ static void getchs2 (struct hardfiledata *hfd, int *cyl, int *cylsec, int *head, 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); } @@ -904,7 +904,7 @@ int hdf_write (struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len) 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); } @@ -918,7 +918,7 @@ static uae_u64 cmd_read (struct hardfiledata *hfd, uaecptr dataptr, uae_u64 offs 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); } @@ -1288,28 +1288,28 @@ static int handle_scsi (uaecptr request, struct hardfiledata *hfd) 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) { @@ -1371,7 +1371,7 @@ static int add_async_request (struct hardfileprivdata *hfpd, uaecptr request, in 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++; @@ -1382,12 +1382,12 @@ static int add_async_request (struct hardfileprivdata *hfpd, uaecptr request, in 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; } @@ -1401,19 +1401,19 @@ static int release_async_request (struct hardfileprivdata *hfpd, uaecptr request 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) { @@ -1426,7 +1426,7 @@ static void abort_async (struct hardfileprivdata *hfpd, uaecptr request, int err } 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); @@ -1731,7 +1731,7 @@ no_disk: 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; @@ -1744,15 +1744,15 @@ static uae_u32 REGPARAM2 hardfile_abortio (TrapContext *context) 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; } @@ -1799,12 +1799,12 @@ static uae_u32 REGPARAM2 hardfile_beginio (TrapContext *context) } 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); @@ -1832,7 +1832,7 @@ static void *hardfile_thread (void *devs) 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); } diff --git a/include/akiko.h b/include/akiko.h index a4a6d78c..06ae5447 100644 --- a/include/akiko.h +++ b/include/akiko.h @@ -10,6 +10,7 @@ extern void akiko_free (void); 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; diff --git a/include/blkdev.h b/include/blkdev.h index 0c9c05fa..e91f5880 100644 --- a/include/blkdev.h +++ b/include/blkdev.h @@ -76,6 +76,7 @@ typedef int (*execscsicmd_direct_func)(int, struct amigascsi*); 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); @@ -97,6 +98,7 @@ struct device_functions { pause_func pause; stop_func stop; play_func play; + volume_func volume; qcode_func qcode; toc_func toc; read_func read; @@ -122,6 +124,7 @@ extern struct device_scsi_info *sys_command_scsi_info (int mode, int unitnum, st 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); diff --git a/include/cpu_prefetch.h b/include/cpu_prefetch.h index cd402ee1..d378bc41 100644 --- a/include/cpu_prefetch.h +++ b/include/cpu_prefetch.h @@ -12,6 +12,11 @@ STATIC_INLINE uae_u32 get_long_prefetch (int o) return v; } +STATIC_INLINE void prefetch_common_ce000 (void) +{ + regs.lastfetch = get_cycles () + CYCLE_UNIT; +} + #ifdef CPUEMU_20 STATIC_INLINE void checkcycles_ce020 (void) @@ -271,6 +276,7 @@ STATIC_INLINE uae_u32 next_ilong_020ce (void) STATIC_INLINE uae_u32 mem_access_delay_word_read (uaecptr addr) { + prefetch_common_ce000 (); switch (ce_banktype[addr >> 16]) { case CE_MEMBANK_CHIP: @@ -284,6 +290,7 @@ STATIC_INLINE uae_u32 mem_access_delay_word_read (uaecptr addr) } STATIC_INLINE uae_u32 mem_access_delay_wordi_read (uaecptr addr) { + prefetch_common_ce000 (); switch (ce_banktype[addr >> 16]) { case CE_MEMBANK_CHIP: @@ -297,6 +304,7 @@ STATIC_INLINE uae_u32 mem_access_delay_wordi_read (uaecptr addr) STATIC_INLINE uae_u32 mem_access_delay_byte_read (uaecptr addr) { + prefetch_common_ce000 (); switch (ce_banktype[addr >> 16]) { case CE_MEMBANK_CHIP: @@ -310,6 +318,7 @@ STATIC_INLINE uae_u32 mem_access_delay_byte_read (uaecptr addr) } 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: @@ -323,6 +332,7 @@ STATIC_INLINE void mem_access_delay_byte_write (uaecptr addr, uae_u32 v) } 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: diff --git a/include/newcpu.h b/include/newcpu.h index 3f250d08..e0cab404 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -133,6 +133,7 @@ extern struct regstruct flagtype x; flagtype stopped; int intmask; + int ipl; uae_u32 vbr, sfc, dfc; @@ -165,6 +166,7 @@ extern struct regstruct uae_u32 prefetch020data; uae_u32 prefetch020addr; int ce020memcycles; + evt lastfetch; } regs, lastint_regs, mmu_backup_regs; @@ -316,7 +318,7 @@ extern void REGPARAM3 MakeFromSR (void) REGPARAM; 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 *); diff --git a/include/options.h b/include/options.h index a9930616..31dc91d4 100644 --- a/include/options.h +++ b/include/options.h @@ -267,6 +267,7 @@ struct uae_prefs { TCHAR sername[256]; TCHAR amaxromfile[MAX_DPATH]; TCHAR a2065name[MAX_DPATH]; + TCHAR cdimagefile[MAX_DPATH]; TCHAR path_floppy[256]; TCHAR path_hardfile[256]; diff --git a/main.c b/main.c index ca850bd6..7cb3bcd6 100644 --- a/main.c +++ b/main.c @@ -532,6 +532,10 @@ static void parse_cmdline (int argc, TCHAR **argv) } 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; diff --git a/newcpu.c b/newcpu.c index ee27ae39..f4ff92c2 100644 --- a/newcpu.c +++ b/newcpu.c @@ -2569,19 +2569,49 @@ static void do_trace (void) 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) @@ -2654,14 +2684,22 @@ 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 @@ -2694,14 +2732,21 @@ STATIC_INLINE int do_specialties (int cycles) 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); @@ -2714,21 +2759,6 @@ STATIC_INLINE int do_specialties (int cycles) 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 diff --git a/od-win32/blkdev_win32_aspi.c b/od-win32/blkdev_win32_aspi.c index 20d526b2..210e54ce 100644 --- a/od-win32/blkdev_win32_aspi.c +++ b/od-win32/blkdev_win32_aspi.c @@ -1017,5 +1017,5 @@ static struct device_scsi_info *scsi_info (int unitnum, struct device_scsi_info 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 }; diff --git a/od-win32/blkdev_win32_ioctl.c b/od-win32/blkdev_win32_ioctl.c index ec69e798..1a6593da 100644 --- a/od-win32/blkdev_win32_ioctl.c +++ b/od-win32/blkdev_win32_ioctl.c @@ -12,6 +12,7 @@ #ifdef WINDDK +#include "options.h" #include "uae.h" #include "threaddep/thread.h" #include "blkdev.h" @@ -38,13 +39,23 @@ struct dev_info_ioctl { 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; @@ -97,6 +108,23 @@ static int win32_error (int unitnum, const TCHAR *format,...) return err; } +/* convert minutes, seconds and frames -> logical sector number */ +static int msf2lsn (int msf) +{ + int sector = (((msf >> 16) & 0xff) * 60 * 75 + ((msf >> 8) & 0xff) * 75 + ((msf >> 0) & 0xff)); + return sector; +} + +/* convert logical sector number -> minutes, seconds and frames */ +static int lsn2msf (int sectors) +{ + int msf; + msf = (sectors / (75 * 60)) << 16; + msf |= ((sectors / 75) % 60) << 8; + msf |= (sectors % 75) << 0; + return msf; +} + static int close_createfile (int unitnum) { struct dev_info_ioctl *ciw = &ciw32[unitnum]; @@ -222,6 +250,180 @@ static int open_mci (int 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) { @@ -235,6 +437,10 @@ 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; @@ -256,6 +462,7 @@ static int ioctl_command_pause (int unitnum, int paused) return 1; } + /* stop CD audio */ static int ioctl_command_stop (int unitnum) { @@ -267,6 +474,10 @@ 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; @@ -287,12 +498,20 @@ static int ioctl_command_stop (int unitnum) 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) { @@ -306,6 +525,20 @@ static int ioctl_command_play (int unitnum, uae_u32 start, uae_u32 end, int scan 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; @@ -348,23 +581,6 @@ static int ioctl_command_play (int unitnum, uae_u32 start, uae_u32 end, int scan 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) { @@ -429,12 +645,76 @@ 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); @@ -442,7 +722,7 @@ static uae_u8 *ioctl_command_qcode (int unitnum) 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; @@ -462,7 +742,7 @@ static uae_u8 *ioctl_command_qcode (int unitnum) 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; } } @@ -489,6 +769,7 @@ static uae_u8 *spti_read (int unitnum, int sector, int sectorsize) if (!open_createfile (unitnum, 1)) return 0; + ciw32[unitnum].cd_last_pos = sector + sectorsize; cmd[3] = (uae_u8)(sector >> 16); cmd[4] = (uae_u8)(sector >> 8); cmd[5] = (uae_u8)(sector >> 0); @@ -532,6 +813,7 @@ uae_u8 *ioctl_command_rawread (int unitnum, int sector, int sectorsize) 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) { @@ -547,6 +829,7 @@ uae_u8 *ioctl_command_rawread (int unitnum, int sector, int sectorsize) DWORD err = GetLastError (); } reseterrormode (unitnum); + ciw32[unitnum].cd_last_pos = sector + sectorsize; break; } if (sectorsize == 2352) @@ -563,6 +846,7 @@ static int ioctl_command_readwrite (int unitnum, int sector, int write, int bloc *ptr = NULL; if (!open_createfile (unitnum, 0)) return 0; + cdda_stop (unitnum); while (cnt-- > 0) { gui_flicker_led (LED_CD, unitnum, 1); seterrormode (unitnum); @@ -701,14 +985,17 @@ static int ismedia (int 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); @@ -767,6 +1054,9 @@ static int sys_cddev_open (int unitnum) { struct dev_info_ioctl *ciw = &ciw32[unitnum]; + ciw->cdda = 1; + ciw->cdda_volume = 0xffff; + ciw->cdda_volume_main = currprefs.sound_volume; /* buffer must be page aligned for device access */ ciw->tempbuffer = VirtualAlloc (NULL, IOCTL_DATA_BUFFER, MEM_COMMIT, PAGE_READWRITE); if (!ciw->tempbuffer) { @@ -809,6 +1099,7 @@ void sys_cddev_close (int unitnum) if (!unitcheck (unitnum)) return; + cdda_stop (unitnum); close_createfile (unitnum); close_mci (unitnum); VirtualFree (ciw->tempbuffer, 0, MEM_RELEASE); @@ -928,7 +1219,7 @@ static struct device_scsi_info *ioctl_scsi_info (int unitnum, struct device_scsi 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 }; diff --git a/od-win32/blkdev_win32_spti.c b/od-win32/blkdev_win32_spti.c index 193d63ab..eb2a20c8 100644 --- a/od-win32/blkdev_win32_spti.c +++ b/od-win32/blkdev_win32_spti.c @@ -528,7 +528,7 @@ static struct device_scsi_info *scsi_info (int unitnum, struct device_scsi_info 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) diff --git a/od-win32/win32.c b/od-win32/win32.c index 7754e1bc..3ac8ca17 100644 --- a/od-win32/win32.c +++ b/od-win32/win32.c @@ -112,7 +112,7 @@ HINSTANCE hInst = NULL; 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; @@ -1322,6 +1322,7 @@ static int canstretch (void) static LRESULT CALLBACK MainWindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + static RECT myrect; PAINTSTRUCT ps; RECT rc; HDC hDC; @@ -1417,24 +1418,21 @@ static LRESULT CALLBACK MainWindowProc (HWND hWnd, UINT message, WPARAM wParam, 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; diff --git a/od-win32/win32.h b/od-win32/win32.h index 69bac1fc..47aeea34 100644 --- a/od-win32/win32.h +++ b/od-win32/win32.h @@ -18,8 +18,8 @@ #define WINUAEPUBLICBETA 1 #define LANG_DLL 1 -#define WINUAEBETA L"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"" @@ -29,7 +29,7 @@ #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; diff --git a/od-win32/win32gfx.c b/od-win32/win32gfx.c index 20c3b1c2..7bbe33b9 100644 --- a/od-win32/win32gfx.c +++ b/od-win32/win32gfx.c @@ -2153,6 +2153,7 @@ static int create_windows_2 (void) 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"); @@ -2288,6 +2289,7 @@ WS_EX_TOPMOST : 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); diff --git a/od-win32/win32gui.c b/od-win32/win32gui.c index d3de097d..97b02be8 100644 --- a/od-win32/win32gui.c +++ b/od-win32/win32gui.c @@ -1521,8 +1521,6 @@ static UINT_PTR CALLBACK ofnhook (HWND hDlg, UINT message, WPARAM wParam, LPARAM nmhdr = (LPNMHDR)lParam; if (nmhdr->code == CDN_INITDONE) doit = TRUE; - } else if (message == WM_INITDIALOG) { - doit = TRUE; } if (!doit) return FALSE; @@ -1540,14 +1538,16 @@ static UINT_PTR CALLBACK ofnhook (HWND hDlg, UINT message, WPARAM wParam, LPARAM 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; } diff --git a/od-win32/winuae_msvc/winuae_msvc.vcproj b/od-win32/winuae_msvc/winuae_msvc.vcproj index b343ca3e..177d12f3 100644 --- a/od-win32/winuae_msvc/winuae_msvc.vcproj +++ b/od-win32/winuae_msvc/winuae_msvc.vcproj @@ -1446,11 +1446,11 @@ > + + diff --git a/od-win32/winuaechangelog.txt b/od-win32/winuaechangelog.txt index 18007c58..b18f7e49 100644 --- a/od-win32/winuaechangelog.txt +++ b/od-win32/winuaechangelog.txt @@ -1,4 +1,42 @@ +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= in config file, command line parameter + -cdimage= can also be used. + No GUI support yet. + Beta 3: - Shadow Fighter AGA graphics priority issue really fixed now diff --git a/zfile.c b/zfile.c index 52c174f6..ac4d3fd8 100644 --- a/zfile.c +++ b/zfile.c @@ -2044,8 +2044,8 @@ int zfile_zuncompress (void *dst, int dstsize, struct zfile *src, int srcsize) 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; -- 2.47.3